2011-10-03 05:56:20 -07:00
|
|
|
/*
|
2015-07-20 14:35:22 +02:00
|
|
|
* cpu_ppc64.c: CPU driver for 64-bit PowerPC CPUs
|
2011-10-03 05:56:20 -07:00
|
|
|
*
|
maint: avoid 'const fooPtr' in cpu files
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can). But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).
Fix up offenders in src/cpu.
* src/cpu/cpu.h (cpuArchDecode, cpuArchEncode, cpuArchUpdate)
(cpuArchHasFeature, cpuDecode, cpuEncode, cpuUpdate)
(cpuHasFeature): Use intended type.
* src/conf/cpu_conf.h (virCPUDefCopyModel, virCPUDefCopy):
Likewise.
(virCPUDefParseXML): Drop const.
* src/cpu/cpu.c (cpuDecode, cpuEncode, cpuUpdate, cpuHasFeature):
Fix fallout.
* src/cpu/cpu_x86.c (x86ModelFromCPU, x86ModelSubtractCPU)
(x86DecodeCPUData, x86EncodePolicy, x86Encode, x86UpdateCustom)
(x86UpdateHostModel, x86Update, x86HasFeature): Likewise.
* src/cpu/cpu_s390.c (s390Decode): Likewise.
* src/cpu/cpu_arm.c (ArmDecode): Likewise.
* src/cpu/cpu_powerpc.c (ppcModelFromCPU, ppcCompute, ppcDecode)
(ppcUpdate): Likewise.
* src/conf/cpu_conf.c (virCPUDefCopyModel, virCPUDefCopy)
(virCPUDefParseXML): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-05 14:01:02 -06:00
|
|
|
* Copyright (C) 2013 Red Hat, Inc.
|
2012-10-15 17:07:51 +08:00
|
|
|
* Copyright (C) IBM Corporation, 2010
|
2011-10-03 05:56:20 -07:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 16:30:55 -06:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 18:06:23 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-10-03 05:56:20 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2011-10-03 05:56:20 -07:00
|
|
|
#include "cpu.h"
|
2013-05-03 14:41:23 +02:00
|
|
|
#include "virstring.h"
|
2012-10-15 17:07:50 +08:00
|
|
|
#include "cpu_map.h"
|
2012-12-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2011-10-03 05:56:20 -07:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_CPU
|
|
|
|
|
2015-07-20 14:35:22 +02:00
|
|
|
VIR_LOG_INIT("cpu.cpu_ppc64");
|
2014-02-28 12:16:17 +00:00
|
|
|
|
2014-11-04 22:51:26 +05:30
|
|
|
static const virArch archs[] = { VIR_ARCH_PPC64, VIR_ARCH_PPC64LE };
|
2011-10-03 05:56:20 -07:00
|
|
|
|
2020-09-02 17:25:35 -03:00
|
|
|
typedef struct _ppc64_vendor virCPUppc64Vendor;
|
|
|
|
typedef struct _ppc64_vendor *virCPUppc64VendorPtr;
|
|
|
|
struct _ppc64_vendor {
|
2012-10-15 17:07:50 +08:00
|
|
|
char *name;
|
|
|
|
};
|
|
|
|
|
2020-09-02 17:25:38 -03:00
|
|
|
typedef struct _ppc64_model virCPUppc64Model;
|
|
|
|
typedef struct _ppc64_model *virCPUppc64ModelPtr;
|
|
|
|
struct _ppc64_model {
|
2012-10-15 17:07:50 +08:00
|
|
|
char *name;
|
2020-09-02 17:25:35 -03:00
|
|
|
const virCPUppc64Vendor *vendor;
|
2016-06-07 12:04:13 +02:00
|
|
|
virCPUppc64Data data;
|
2012-10-15 17:07:50 +08:00
|
|
|
};
|
|
|
|
|
2020-09-02 17:25:41 -03:00
|
|
|
typedef struct _ppc64_map virCPUppc64Map;
|
|
|
|
typedef struct _ppc64_map *virCPUppc64MapPtr;
|
|
|
|
struct _ppc64_map {
|
2016-05-17 15:56:53 +02:00
|
|
|
size_t nvendors;
|
2020-09-02 17:25:35 -03:00
|
|
|
virCPUppc64VendorPtr *vendors;
|
2016-05-18 15:23:54 +02:00
|
|
|
size_t nmodels;
|
2020-09-02 17:25:38 -03:00
|
|
|
virCPUppc64ModelPtr *models;
|
2012-10-15 17:07:50 +08:00
|
|
|
};
|
|
|
|
|
2015-08-07 17:39:18 +02:00
|
|
|
/* Convert a legacy CPU definition by transforming
|
|
|
|
* model names to generation names:
|
|
|
|
* POWER7_v2.1 => POWER7
|
|
|
|
* POWER7_v2.3 => POWER7
|
|
|
|
* POWER7+_v2.1 => POWER7
|
|
|
|
* POWER8_v1.0 => POWER8 */
|
2016-11-09 17:09:48 +01:00
|
|
|
static int
|
|
|
|
virCPUppc64ConvertLegacy(virCPUDefPtr cpu)
|
2015-08-07 17:39:18 +02:00
|
|
|
{
|
2016-11-09 17:09:48 +01:00
|
|
|
if (cpu->model &&
|
|
|
|
(STREQ(cpu->model, "POWER7_v2.1") ||
|
|
|
|
STREQ(cpu->model, "POWER7_v2.3") ||
|
|
|
|
STREQ(cpu->model, "POWER7+_v2.1") ||
|
|
|
|
STREQ(cpu->model, "POWER8_v1.0"))) {
|
|
|
|
cpu->model[strlen("POWERx")] = 0;
|
2015-08-07 17:39:18 +02:00
|
|
|
}
|
|
|
|
|
2016-11-09 17:09:48 +01:00
|
|
|
return 0;
|
2015-08-07 17:39:18 +02:00
|
|
|
}
|
|
|
|
|
2015-08-13 17:50:37 +02:00
|
|
|
/* Some hosts can run guests in compatibility mode, but not all
|
|
|
|
* host CPUs support this and not all combinations are valid.
|
|
|
|
* This function performs the necessary checks */
|
|
|
|
static virCPUCompareResult
|
|
|
|
ppc64CheckCompatibilityMode(const char *host_model,
|
|
|
|
const char *compat_mode)
|
|
|
|
{
|
|
|
|
int host;
|
|
|
|
int compat;
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
if (!compat_mode)
|
|
|
|
return VIR_CPU_COMPARE_IDENTICAL;
|
|
|
|
|
2017-05-17 16:39:16 +02:00
|
|
|
/* Valid host CPUs: POWER6, POWER7, POWER8, POWER9 */
|
2015-08-13 17:50:37 +02:00
|
|
|
if (!STRPREFIX(host_model, "POWER") ||
|
|
|
|
!(tmp = (char *) host_model + strlen("POWER")) ||
|
|
|
|
virStrToLong_i(tmp, NULL, 10, &host) < 0 ||
|
2017-05-17 16:39:16 +02:00
|
|
|
host < 6 || host > 9) {
|
2015-08-13 17:50:37 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",
|
|
|
|
_("Host CPU does not support compatibility modes"));
|
2020-01-06 18:57:35 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2015-08-13 17:50:37 +02:00
|
|
|
}
|
|
|
|
|
2017-05-17 16:39:16 +02:00
|
|
|
/* Valid compatibility modes: power6, power7, power8, power9 */
|
2015-08-13 17:50:37 +02:00
|
|
|
if (!STRPREFIX(compat_mode, "power") ||
|
|
|
|
!(tmp = (char *) compat_mode + strlen("power")) ||
|
|
|
|
virStrToLong_i(tmp, NULL, 10, &compat) < 0 ||
|
2017-05-17 16:39:16 +02:00
|
|
|
compat < 6 || compat > 9) {
|
2015-08-13 17:50:37 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown compatibility mode %s"),
|
|
|
|
compat_mode);
|
2020-01-06 18:57:35 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2015-08-13 17:50:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Version check */
|
|
|
|
if (compat > host)
|
2020-01-06 18:57:35 -03:00
|
|
|
return VIR_CPU_COMPARE_INCOMPATIBLE;
|
2015-08-13 17:50:37 +02:00
|
|
|
|
2020-01-06 18:57:35 -03:00
|
|
|
return VIR_CPU_COMPARE_IDENTICAL;
|
2015-08-13 17:50:37 +02:00
|
|
|
}
|
|
|
|
|
2015-08-07 17:39:13 +02:00
|
|
|
static void
|
2016-06-07 12:04:13 +02:00
|
|
|
ppc64DataClear(virCPUppc64Data *data)
|
2015-08-07 17:39:13 +02:00
|
|
|
{
|
2015-08-07 17:39:14 +02:00
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(data->pvr);
|
2015-08-07 17:39:13 +02:00
|
|
|
}
|
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
static int
|
|
|
|
ppc64DataCopy(virCPUppc64Data *dst, const virCPUppc64Data *src)
|
2015-08-07 17:39:13 +02:00
|
|
|
{
|
2015-08-07 17:39:14 +02:00
|
|
|
size_t i;
|
2015-08-07 17:39:13 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
if (VIR_ALLOC_N(dst->pvr, src->len) < 0)
|
|
|
|
return -1;
|
2015-08-07 17:39:13 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
dst->len = src->len;
|
2015-08-07 17:39:14 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
for (i = 0; i < src->len; i++) {
|
|
|
|
dst->pvr[i].value = src->pvr[i].value;
|
|
|
|
dst->pvr[i].mask = src->pvr[i].mask;
|
2015-08-07 17:39:16 +02:00
|
|
|
}
|
2015-08-07 17:39:13 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
return 0;
|
2015-08-07 17:39:13 +02:00
|
|
|
}
|
|
|
|
|
2015-08-07 17:39:05 +02:00
|
|
|
static void
|
2020-09-02 17:25:35 -03:00
|
|
|
ppc64VendorFree(virCPUppc64VendorPtr vendor)
|
2015-08-07 17:39:05 +02:00
|
|
|
{
|
|
|
|
if (!vendor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(vendor->name);
|
|
|
|
VIR_FREE(vendor);
|
|
|
|
}
|
2020-09-02 17:25:36 -03:00
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUppc64Vendor, ppc64VendorFree);
|
2015-08-07 17:39:05 +02:00
|
|
|
|
2020-09-02 17:25:35 -03:00
|
|
|
static virCPUppc64VendorPtr
|
2020-09-02 17:25:41 -03:00
|
|
|
ppc64VendorFind(const virCPUppc64Map *map,
|
2015-08-07 17:39:05 +02:00
|
|
|
const char *name)
|
|
|
|
{
|
2016-05-17 15:56:53 +02:00
|
|
|
size_t i;
|
2015-08-07 17:39:05 +02:00
|
|
|
|
2016-05-17 15:56:53 +02:00
|
|
|
for (i = 0; i < map->nvendors; i++) {
|
|
|
|
if (STREQ(map->vendors[i]->name, name))
|
|
|
|
return map->vendors[i];
|
2015-08-07 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-10-15 17:07:50 +08:00
|
|
|
|
|
|
|
static void
|
2020-09-02 17:25:38 -03:00
|
|
|
ppc64ModelFree(virCPUppc64ModelPtr model)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2015-08-07 17:39:03 +02:00
|
|
|
if (!model)
|
2012-10-15 17:07:50 +08:00
|
|
|
return;
|
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
ppc64DataClear(&model->data);
|
2012-10-15 17:07:50 +08:00
|
|
|
VIR_FREE(model->name);
|
|
|
|
VIR_FREE(model);
|
|
|
|
}
|
2020-09-02 17:25:39 -03:00
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUppc64Model, ppc64ModelFree);
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2020-09-02 17:25:38 -03:00
|
|
|
static virCPUppc64ModelPtr
|
|
|
|
ppc64ModelCopy(const virCPUppc64Model *model)
|
2015-08-07 17:39:05 +02:00
|
|
|
{
|
2020-09-02 17:25:40 -03:00
|
|
|
g_autoptr(virCPUppc64Model) copy = NULL;
|
2015-08-07 17:39:05 +02:00
|
|
|
|
2015-08-07 17:39:13 +02:00
|
|
|
if (VIR_ALLOC(copy) < 0)
|
2020-09-02 17:25:40 -03:00
|
|
|
return NULL;
|
2015-08-07 17:39:13 +02:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
copy->name = g_strdup(model->name);
|
2015-08-07 17:39:13 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
if (ppc64DataCopy(©->data, &model->data) < 0)
|
2020-09-02 17:25:40 -03:00
|
|
|
return NULL;
|
2015-08-07 17:39:05 +02:00
|
|
|
|
|
|
|
copy->vendor = model->vendor;
|
|
|
|
|
2020-09-02 17:25:40 -03:00
|
|
|
return g_steal_pointer(©);
|
2015-08-07 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
2020-09-02 17:25:38 -03:00
|
|
|
static virCPUppc64ModelPtr
|
2020-09-02 17:25:41 -03:00
|
|
|
ppc64ModelFind(const virCPUppc64Map *map,
|
2015-07-20 15:13:02 +02:00
|
|
|
const char *name)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2016-05-18 15:23:54 +02:00
|
|
|
size_t i;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2016-05-18 15:23:54 +02:00
|
|
|
for (i = 0; i < map->nmodels; i++) {
|
|
|
|
if (STREQ(map->models[i]->name, name))
|
|
|
|
return map->models[i];
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-09-02 17:25:38 -03:00
|
|
|
static virCPUppc64ModelPtr
|
2020-09-02 17:25:41 -03:00
|
|
|
ppc64ModelFindPVR(const virCPUppc64Map *map,
|
2015-07-20 15:13:02 +02:00
|
|
|
uint32_t pvr)
|
2012-12-19 01:35:51 +01:00
|
|
|
{
|
2015-08-07 17:39:14 +02:00
|
|
|
size_t i;
|
2016-05-18 15:23:54 +02:00
|
|
|
size_t j;
|
2012-12-19 01:35:51 +01:00
|
|
|
|
2016-05-18 15:23:54 +02:00
|
|
|
for (i = 0; i < map->nmodels; i++) {
|
2020-09-02 17:25:38 -03:00
|
|
|
virCPUppc64ModelPtr model = map->models[i];
|
2016-06-07 12:04:13 +02:00
|
|
|
for (j = 0; j < model->data.len; j++) {
|
|
|
|
if ((pvr & model->data.pvr[j].mask) == model->data.pvr[j].value)
|
2015-08-07 17:39:14 +02:00
|
|
|
return model;
|
|
|
|
}
|
2012-12-19 01:35:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-09-02 17:25:38 -03:00
|
|
|
static virCPUppc64ModelPtr
|
2015-08-07 17:39:05 +02:00
|
|
|
ppc64ModelFromCPU(const virCPUDef *cpu,
|
2020-09-02 17:25:41 -03:00
|
|
|
const virCPUppc64Map *map)
|
2013-09-03 14:28:24 +08:00
|
|
|
{
|
2020-09-02 17:25:38 -03:00
|
|
|
virCPUppc64ModelPtr model;
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2017-09-18 22:27:52 +05:30
|
|
|
if (!cpu->model) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("no CPU model specified"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-07 17:39:05 +02:00
|
|
|
if (!(model = ppc64ModelFind(map, cpu->model))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown CPU model %s"), cpu->model);
|
2013-09-03 14:28:24 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-07 17:39:05 +02:00
|
|
|
return ppc64ModelCopy(model);
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-09-02 17:25:41 -03:00
|
|
|
ppc64MapFree(virCPUppc64MapPtr map)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2016-05-17 15:56:53 +02:00
|
|
|
size_t i;
|
|
|
|
|
2015-08-07 17:39:05 +02:00
|
|
|
if (!map)
|
2012-10-15 17:07:50 +08:00
|
|
|
return;
|
|
|
|
|
2016-05-18 15:23:54 +02:00
|
|
|
for (i = 0; i < map->nmodels; i++)
|
|
|
|
ppc64ModelFree(map->models[i]);
|
|
|
|
VIR_FREE(map->models);
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2016-05-17 15:56:53 +02:00
|
|
|
for (i = 0; i < map->nvendors; i++)
|
|
|
|
ppc64VendorFree(map->vendors[i]);
|
|
|
|
VIR_FREE(map->vendors);
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2015-08-07 17:39:05 +02:00
|
|
|
VIR_FREE(map);
|
2013-09-03 14:28:24 +08:00
|
|
|
}
|
2020-09-02 17:25:42 -03:00
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUppc64Map, ppc64MapFree);
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2018-07-30 17:08:38 +01:00
|
|
|
static int
|
2019-10-14 14:45:33 +02:00
|
|
|
ppc64VendorParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED,
|
2018-07-30 17:08:38 +01:00
|
|
|
const char *name,
|
|
|
|
void *data)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2020-09-02 17:25:41 -03:00
|
|
|
virCPUppc64MapPtr map = data;
|
2020-09-02 17:25:37 -03:00
|
|
|
g_autoptr(virCPUppc64Vendor) vendor = NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2013-07-04 12:03:29 +02:00
|
|
|
if (VIR_ALLOC(vendor) < 0)
|
2018-07-30 17:08:38 +01:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
vendor->name = g_strdup(name);
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (ppc64VendorFind(map, vendor->name)) {
|
2012-10-15 17:07:50 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("CPU vendor %s already defined"), vendor->name);
|
2020-09-02 17:25:37 -03:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2018-07-30 17:08:38 +01:00
|
|
|
if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
|
2020-09-02 17:25:37 -03:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2020-09-02 17:25:37 -03:00
|
|
|
return 0;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2016-05-17 10:59:28 +02:00
|
|
|
|
2012-10-15 17:07:50 +08:00
|
|
|
static int
|
2016-05-17 10:59:28 +02:00
|
|
|
ppc64ModelParse(xmlXPathContextPtr ctxt,
|
2018-07-30 17:08:38 +01:00
|
|
|
const char *name,
|
|
|
|
void *data)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2020-09-02 17:25:41 -03:00
|
|
|
virCPUppc64MapPtr map = data;
|
2020-09-02 17:25:40 -03:00
|
|
|
g_autoptr(virCPUppc64Model) model = NULL;
|
2020-09-02 17:25:45 -03:00
|
|
|
g_autofree xmlNodePtr *nodes = NULL;
|
|
|
|
g_autofree char *vendor = NULL;
|
2012-12-19 01:35:51 +01:00
|
|
|
unsigned long pvr;
|
2015-08-07 17:39:14 +02:00
|
|
|
size_t i;
|
|
|
|
int n;
|
|
|
|
|
2013-07-04 12:03:29 +02:00
|
|
|
if (VIR_ALLOC(model) < 0)
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
model->name = g_strdup(name);
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (ppc64ModelFind(map, model->name)) {
|
2012-12-19 01:35:51 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("CPU model %s already defined"), model->name);
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2012-12-19 01:35:51 +01:00
|
|
|
}
|
2012-10-15 17:07:50 +08:00
|
|
|
|
|
|
|
if (virXPathBoolean("boolean(./vendor)", ctxt)) {
|
|
|
|
vendor = virXPathString("string(./vendor/@name)", ctxt);
|
|
|
|
if (!vendor) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Invalid vendor element in CPU model %s"),
|
|
|
|
model->name);
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (!(model->vendor = ppc64VendorFind(map, vendor))) {
|
2012-10-15 17:07:50 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown vendor %s referenced by CPU model %s"),
|
|
|
|
vendor, model->name);
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-07 17:39:14 +02:00
|
|
|
if ((n = virXPathNodeSet("./pvr", ctxt, &nodes)) <= 0) {
|
2012-12-19 01:35:51 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2015-08-07 17:39:14 +02:00
|
|
|
_("Missing PVR information for CPU model %s"),
|
2012-12-19 01:35:51 +01:00
|
|
|
model->name);
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2012-12-19 01:35:51 +01:00
|
|
|
}
|
2015-08-07 17:39:14 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
if (VIR_ALLOC_N(model->data.pvr, n) < 0)
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2015-08-07 17:39:14 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
model->data.len = n;
|
2015-08-07 17:39:14 +02:00
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
ctxt->node = nodes[i];
|
|
|
|
|
|
|
|
if (virXPathULongHex("string(./@value)", ctxt, &pvr) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Missing or invalid PVR value in CPU model %s"),
|
|
|
|
model->name);
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2015-08-07 17:39:14 +02:00
|
|
|
}
|
2016-06-07 12:04:13 +02:00
|
|
|
model->data.pvr[i].value = pvr;
|
2015-08-07 17:39:16 +02:00
|
|
|
|
|
|
|
if (virXPathULongHex("string(./@mask)", ctxt, &pvr) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Missing or invalid PVR mask in CPU model %s"),
|
|
|
|
model->name);
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2015-08-07 17:39:16 +02:00
|
|
|
}
|
2016-06-07 12:04:13 +02:00
|
|
|
model->data.pvr[i].mask = pvr;
|
2015-08-07 17:39:14 +02:00
|
|
|
}
|
2012-12-19 01:35:51 +01:00
|
|
|
|
2018-07-30 17:08:38 +01:00
|
|
|
if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
|
2020-09-02 17:25:45 -03:00
|
|
|
return -1;
|
2018-07-30 17:08:38 +01:00
|
|
|
|
2020-09-02 17:25:45 -03:00
|
|
|
return 0;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2016-05-17 10:59:28 +02:00
|
|
|
|
2020-09-02 17:25:41 -03:00
|
|
|
static virCPUppc64MapPtr
|
2015-07-20 15:13:02 +02:00
|
|
|
ppc64LoadMap(void)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2020-09-02 17:25:43 -03:00
|
|
|
g_autoptr(virCPUppc64Map) map = NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2013-07-04 12:03:29 +02:00
|
|
|
if (VIR_ALLOC(map) < 0)
|
2020-09-02 17:25:43 -03:00
|
|
|
return NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2018-07-30 17:08:38 +01:00
|
|
|
if (cpuMapLoad("ppc64", ppc64VendorParse, NULL, ppc64ModelParse, map) < 0)
|
2020-09-02 17:25:43 -03:00
|
|
|
return NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2020-09-02 17:25:43 -03:00
|
|
|
return g_steal_pointer(&map);
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2013-09-03 14:28:24 +08:00
|
|
|
static virCPUDataPtr
|
2015-07-20 15:20:20 +02:00
|
|
|
ppc64MakeCPUData(virArch arch,
|
2015-08-07 17:39:13 +02:00
|
|
|
virCPUppc64Data *data)
|
2013-09-03 14:28:24 +08:00
|
|
|
{
|
2020-09-11 15:22:42 +02:00
|
|
|
g_autoptr(virCPUData) cpuData = NULL;
|
2013-09-03 14:28:24 +08:00
|
|
|
|
|
|
|
if (VIR_ALLOC(cpuData) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
cpuData->arch = arch;
|
2015-08-07 17:39:13 +02:00
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
if (ppc64DataCopy(&cpuData->data.ppc64, data) < 0)
|
2020-09-11 15:22:42 +02:00
|
|
|
return NULL;
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2020-09-11 15:22:42 +02:00
|
|
|
return g_steal_pointer(&cpuData);
|
2013-09-03 14:28:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static virCPUCompareResult
|
2015-07-20 15:13:02 +02:00
|
|
|
ppc64Compute(virCPUDefPtr host,
|
2015-08-07 17:39:18 +02:00
|
|
|
const virCPUDef *other,
|
2015-07-20 15:13:02 +02:00
|
|
|
virCPUDataPtr *guestData,
|
|
|
|
char **message)
|
2013-09-03 14:28:24 +08:00
|
|
|
{
|
2020-09-02 17:25:43 -03:00
|
|
|
g_autoptr(virCPUppc64Map) map = NULL;
|
2020-09-02 17:25:40 -03:00
|
|
|
g_autoptr(virCPUppc64Model) host_model = NULL;
|
|
|
|
g_autoptr(virCPUppc64Model) guest_model = NULL;
|
2020-09-02 17:25:46 -03:00
|
|
|
g_autoptr(virCPUDef) cpu = NULL;
|
2013-09-03 14:28:24 +08:00
|
|
|
virArch arch;
|
|
|
|
size_t i;
|
|
|
|
|
2015-08-07 17:39:18 +02:00
|
|
|
/* Ensure existing configurations are handled correctly */
|
2016-11-09 17:09:48 +01:00
|
|
|
if (!(cpu = virCPUDefCopy(other)) ||
|
|
|
|
virCPUppc64ConvertLegacy(cpu) < 0)
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2015-08-07 17:39:18 +02:00
|
|
|
|
2013-09-03 14:28:24 +08:00
|
|
|
if (cpu->arch != VIR_ARCH_NONE) {
|
|
|
|
bool found = false;
|
|
|
|
|
2019-10-15 13:55:26 +02:00
|
|
|
for (i = 0; i < G_N_ELEMENTS(archs); i++) {
|
2013-09-03 14:28:24 +08:00
|
|
|
if (archs[i] == cpu->arch) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
VIR_DEBUG("CPU arch %s does not match host arch",
|
|
|
|
virArchToString(cpu->arch));
|
2019-10-22 15:26:14 +02:00
|
|
|
if (message)
|
|
|
|
*message = g_strdup_printf(_("CPU arch %s does not match host arch"),
|
|
|
|
virArchToString(cpu->arch));
|
2013-09-09 13:56:33 +08:00
|
|
|
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_INCOMPATIBLE;
|
2013-09-03 14:28:24 +08:00
|
|
|
}
|
|
|
|
arch = cpu->arch;
|
|
|
|
} else {
|
|
|
|
arch = host->arch;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->vendor &&
|
|
|
|
(!host->vendor || STRNEQ(cpu->vendor, host->vendor))) {
|
|
|
|
VIR_DEBUG("host CPU vendor does not match required CPU vendor %s",
|
|
|
|
cpu->vendor);
|
2019-10-22 15:26:14 +02:00
|
|
|
if (message) {
|
|
|
|
*message = g_strdup_printf(_("host CPU vendor does not match required "
|
|
|
|
"CPU vendor %s"),
|
|
|
|
cpu->vendor);
|
|
|
|
}
|
2013-09-09 13:56:33 +08:00
|
|
|
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_INCOMPATIBLE;
|
2013-09-03 14:28:24 +08:00
|
|
|
}
|
|
|
|
|
2015-08-13 17:50:37 +02:00
|
|
|
if (!(map = ppc64LoadMap()))
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2015-08-13 17:50:37 +02:00
|
|
|
|
|
|
|
/* Host CPU information */
|
|
|
|
if (!(host_model = ppc64ModelFromCPU(host, map)))
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2015-08-13 17:50:37 +02:00
|
|
|
if (cpu->type == VIR_CPU_TYPE_GUEST) {
|
|
|
|
/* Guest CPU information */
|
|
|
|
virCPUCompareResult tmp;
|
|
|
|
switch (cpu->mode) {
|
|
|
|
case VIR_CPU_MODE_HOST_MODEL:
|
|
|
|
/* host-model only:
|
|
|
|
* we need to take compatibility modes into account */
|
|
|
|
tmp = ppc64CheckCompatibilityMode(host->model, cpu->model);
|
2020-09-02 17:25:46 -03:00
|
|
|
if (tmp != VIR_CPU_COMPARE_IDENTICAL)
|
|
|
|
return tmp;
|
2019-10-15 13:38:21 +02:00
|
|
|
G_GNUC_FALLTHROUGH;
|
2015-08-13 17:50:37 +02:00
|
|
|
|
|
|
|
case VIR_CPU_MODE_HOST_PASSTHROUGH:
|
|
|
|
/* host-model and host-passthrough:
|
|
|
|
* the guest CPU is the same as the host */
|
2016-06-02 11:47:11 +02:00
|
|
|
guest_model = ppc64ModelCopy(host_model);
|
2015-08-13 17:50:37 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_CPU_MODE_CUSTOM:
|
|
|
|
/* custom:
|
|
|
|
* look up guest CPU information */
|
2016-06-02 11:47:11 +02:00
|
|
|
guest_model = ppc64ModelFromCPU(cpu, map);
|
2015-08-13 17:50:37 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Other host CPU information */
|
2016-06-02 11:47:11 +02:00
|
|
|
guest_model = ppc64ModelFromCPU(cpu, map);
|
2015-08-13 17:50:37 +02:00
|
|
|
}
|
|
|
|
|
2016-06-02 11:47:11 +02:00
|
|
|
if (!guest_model)
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2016-06-02 11:47:11 +02:00
|
|
|
|
2015-08-07 17:39:10 +02:00
|
|
|
if (STRNEQ(guest_model->name, host_model->name)) {
|
2015-08-07 17:39:09 +02:00
|
|
|
VIR_DEBUG("host CPU model does not match required CPU model %s",
|
|
|
|
guest_model->name);
|
2019-10-22 15:26:14 +02:00
|
|
|
if (message) {
|
|
|
|
*message = g_strdup_printf(_("host CPU model does not match required "
|
|
|
|
"CPU model %s"),
|
|
|
|
guest_model->name);
|
|
|
|
}
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_INCOMPATIBLE;
|
2015-08-07 17:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (guestData)
|
2016-06-07 12:04:13 +02:00
|
|
|
if (!(*guestData = ppc64MakeCPUData(arch, &guest_model->data)))
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_ERROR;
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2020-09-02 17:25:46 -03:00
|
|
|
return VIR_CPU_COMPARE_IDENTICAL;
|
2013-09-03 14:28:24 +08:00
|
|
|
}
|
|
|
|
|
2012-10-15 17:07:50 +08:00
|
|
|
static virCPUCompareResult
|
2016-08-09 13:26:53 +02:00
|
|
|
virCPUppc64Compare(virCPUDefPtr host,
|
2015-08-07 17:39:02 +02:00
|
|
|
virCPUDefPtr cpu,
|
|
|
|
bool failIncompatible)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2015-08-07 17:39:11 +02:00
|
|
|
virCPUCompareResult ret;
|
2020-09-02 17:25:45 -03:00
|
|
|
g_autofree char *message = NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2016-08-09 13:26:53 +02:00
|
|
|
if (!host || !host->model) {
|
|
|
|
if (failIncompatible) {
|
|
|
|
virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s",
|
|
|
|
_("unknown host CPU"));
|
|
|
|
} else {
|
|
|
|
VIR_WARN("unknown host CPU");
|
|
|
|
ret = VIR_CPU_COMPARE_INCOMPATIBLE;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-08-07 17:39:11 +02:00
|
|
|
ret = ppc64Compute(host, cpu, NULL, &message);
|
|
|
|
|
|
|
|
if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) {
|
|
|
|
ret = VIR_CPU_COMPARE_ERROR;
|
|
|
|
if (message) {
|
|
|
|
virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", message);
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
|
|
|
|
}
|
2014-05-28 15:11:57 +02:00
|
|
|
}
|
2015-08-07 17:39:11 +02:00
|
|
|
|
|
|
|
return ret;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-08-07 17:39:02 +02:00
|
|
|
ppc64DriverDecode(virCPUDefPtr cpu,
|
|
|
|
const virCPUData *data,
|
2017-09-26 10:24:05 +02:00
|
|
|
virDomainCapsCPUModelsPtr models)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2020-09-02 17:25:43 -03:00
|
|
|
g_autoptr(virCPUppc64Map) map = NULL;
|
2020-09-02 17:25:38 -03:00
|
|
|
const virCPUppc64Model *model;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2015-08-07 17:39:03 +02:00
|
|
|
if (!data || !(map = ppc64LoadMap()))
|
2012-10-15 17:07:50 +08:00
|
|
|
return -1;
|
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
if (!(model = ppc64ModelFindPVR(map, data->data.ppc64.pvr[0].value))) {
|
2012-12-19 01:35:51 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("Cannot find CPU model with PVR 0x%08x"),
|
2016-06-07 12:04:13 +02:00
|
|
|
data->data.ppc64.pvr[0].value);
|
2020-09-02 17:25:43 -03:00
|
|
|
return -1;
|
2012-12-19 01:35:51 +01:00
|
|
|
}
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2017-09-22 15:51:33 +02:00
|
|
|
if (!virCPUModelIsAllowed(model->name, models)) {
|
2012-12-19 01:53:25 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("CPU model %s is not supported by hypervisor"),
|
2012-12-19 01:35:51 +01:00
|
|
|
model->name);
|
2020-09-02 17:25:43 -03:00
|
|
|
return -1;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
cpu->model = g_strdup(model->name);
|
|
|
|
if (model->vendor)
|
|
|
|
cpu->vendor = g_strdup(model->vendor->name);
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2020-09-02 17:25:43 -03:00
|
|
|
return 0;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-02-02 15:37:40 +01:00
|
|
|
virCPUppc64DataFree(virCPUDataPtr data)
|
2012-10-15 17:07:50 +08:00
|
|
|
{
|
2015-08-07 17:39:03 +02:00
|
|
|
if (!data)
|
2012-10-15 17:07:50 +08:00
|
|
|
return;
|
|
|
|
|
2016-06-07 12:04:13 +02:00
|
|
|
ppc64DataClear(&data->data.ppc64);
|
2012-10-15 17:07:50 +08:00
|
|
|
VIR_FREE(data);
|
|
|
|
}
|
|
|
|
|
2017-03-06 21:35:49 +01:00
|
|
|
|
|
|
|
static int
|
2017-03-07 12:20:01 +01:00
|
|
|
virCPUppc64GetHost(virCPUDefPtr cpu,
|
2017-09-22 15:51:33 +02:00
|
|
|
virDomainCapsCPUModelsPtr models)
|
2011-10-03 05:56:20 -07:00
|
|
|
{
|
2020-09-02 17:25:44 -03:00
|
|
|
g_autoptr(virCPUData) cpuData = NULL;
|
2015-08-07 17:39:13 +02:00
|
|
|
virCPUppc64Data *data;
|
2011-10-03 05:56:20 -07:00
|
|
|
|
2017-03-06 21:35:49 +01:00
|
|
|
if (!(cpuData = virCPUDataNew(archs[0])))
|
2020-09-02 17:25:44 -03:00
|
|
|
return -1;
|
2011-10-03 05:56:20 -07:00
|
|
|
|
2017-03-06 21:35:49 +01:00
|
|
|
data = &cpuData->data.ppc64;
|
Ensure 'arch' is always set in cpuArchNodeData
The s390, ppc and arm CPU drivers never set the 'arch' field
in their impl of cpuArchNodeData. This leads to error messages
being reported from cpuDataFree later, due to trying to use
VIR_ARCH_NONE.
#0 virRaiseErrorFull (filename=filename@entry=0x76f94434 "cpu/cpu.c", funcname=funcname@entry=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58,
domain=domain@entry=31, code=code@entry=1, level=level@entry=VIR_ERR_ERROR, str1=0x76f70e18 "internal error: %s",
str2=str2@entry=0x7155f2ec "undefined hardware architecture", str3=str3@entry=0x0, int1=int1@entry=-1, int2=int2@entry=-1, fmt=0x76f70e18 "internal error: %s")
at util/virerror.c:646
#1 0x76e682ea in virReportErrorHelper (domcode=domcode@entry=31, errorcode=errorcode@entry=1, filename=0x76f94434 "cpu/cpu.c",
funcname=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58, fmt=0x76f7e7e4 "%s") at util/virerror.c:1292
#2 0x76ed82d4 in cpuGetSubDriver (arch=<optimized out>) at cpu/cpu.c:57
#3 cpuGetSubDriver (arch=VIR_ARCH_NONE) at cpu/cpu.c:51
#4 0x76ed8818 in cpuDataFree (data=data@entry=0x70c22d78) at cpu/cpu.c:216
#5 0x716aaec0 in virQEMUCapsInitCPU (arch=VIR_ARCH_ARMV7L, caps=0x70c29a08) at qemu/qemu_capabilities.c:867
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-09-04 17:41:55 +01:00
|
|
|
|
2015-08-07 17:39:14 +02:00
|
|
|
if (VIR_ALLOC_N(data->pvr, 1) < 0)
|
2020-09-02 17:25:44 -03:00
|
|
|
return -1;
|
2015-08-07 17:39:14 +02:00
|
|
|
|
|
|
|
data->len = 1;
|
|
|
|
|
Ensure 'arch' is always set in cpuArchNodeData
The s390, ppc and arm CPU drivers never set the 'arch' field
in their impl of cpuArchNodeData. This leads to error messages
being reported from cpuDataFree later, due to trying to use
VIR_ARCH_NONE.
#0 virRaiseErrorFull (filename=filename@entry=0x76f94434 "cpu/cpu.c", funcname=funcname@entry=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58,
domain=domain@entry=31, code=code@entry=1, level=level@entry=VIR_ERR_ERROR, str1=0x76f70e18 "internal error: %s",
str2=str2@entry=0x7155f2ec "undefined hardware architecture", str3=str3@entry=0x0, int1=int1@entry=-1, int2=int2@entry=-1, fmt=0x76f70e18 "internal error: %s")
at util/virerror.c:646
#1 0x76e682ea in virReportErrorHelper (domcode=domcode@entry=31, errorcode=errorcode@entry=1, filename=0x76f94434 "cpu/cpu.c",
funcname=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58, fmt=0x76f7e7e4 "%s") at util/virerror.c:1292
#2 0x76ed82d4 in cpuGetSubDriver (arch=<optimized out>) at cpu/cpu.c:57
#3 cpuGetSubDriver (arch=VIR_ARCH_NONE) at cpu/cpu.c:51
#4 0x76ed8818 in cpuDataFree (data=data@entry=0x70c22d78) at cpu/cpu.c:216
#5 0x716aaec0 in virQEMUCapsInitCPU (arch=VIR_ARCH_ARMV7L, caps=0x70c29a08) at qemu/qemu_capabilities.c:867
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-09-04 17:41:55 +01:00
|
|
|
#if defined(__powerpc__) || defined(__powerpc64__)
|
2012-12-18 23:42:34 +01:00
|
|
|
asm("mfpvr %0"
|
2015-08-07 17:39:14 +02:00
|
|
|
: "=r" (data->pvr[0].value));
|
Ensure 'arch' is always set in cpuArchNodeData
The s390, ppc and arm CPU drivers never set the 'arch' field
in their impl of cpuArchNodeData. This leads to error messages
being reported from cpuDataFree later, due to trying to use
VIR_ARCH_NONE.
#0 virRaiseErrorFull (filename=filename@entry=0x76f94434 "cpu/cpu.c", funcname=funcname@entry=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58,
domain=domain@entry=31, code=code@entry=1, level=level@entry=VIR_ERR_ERROR, str1=0x76f70e18 "internal error: %s",
str2=str2@entry=0x7155f2ec "undefined hardware architecture", str3=str3@entry=0x0, int1=int1@entry=-1, int2=int2@entry=-1, fmt=0x76f70e18 "internal error: %s")
at util/virerror.c:646
#1 0x76e682ea in virReportErrorHelper (domcode=domcode@entry=31, errorcode=errorcode@entry=1, filename=0x76f94434 "cpu/cpu.c",
funcname=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58, fmt=0x76f7e7e4 "%s") at util/virerror.c:1292
#2 0x76ed82d4 in cpuGetSubDriver (arch=<optimized out>) at cpu/cpu.c:57
#3 cpuGetSubDriver (arch=VIR_ARCH_NONE) at cpu/cpu.c:51
#4 0x76ed8818 in cpuDataFree (data=data@entry=0x70c22d78) at cpu/cpu.c:216
#5 0x716aaec0 in virQEMUCapsInitCPU (arch=VIR_ARCH_ARMV7L, caps=0x70c29a08) at qemu/qemu_capabilities.c:867
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-09-04 17:41:55 +01:00
|
|
|
#endif
|
2015-08-07 17:39:16 +02:00
|
|
|
data->pvr[0].mask = 0xfffffffful;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2020-09-02 17:25:44 -03:00
|
|
|
return ppc64DriverDecode(cpu, cpuData, models);
|
2011-10-03 05:56:20 -07:00
|
|
|
}
|
|
|
|
|
2013-09-03 14:28:24 +08:00
|
|
|
|
2011-10-03 05:56:20 -07:00
|
|
|
static int
|
2016-06-23 15:27:07 +02:00
|
|
|
virCPUppc64Update(virCPUDefPtr guest,
|
2019-10-14 14:45:33 +02:00
|
|
|
const virCPUDef *host G_GNUC_UNUSED)
|
2011-10-03 05:56:20 -07:00
|
|
|
{
|
2016-06-23 15:27:07 +02:00
|
|
|
/*
|
|
|
|
* - host-passthrough doesn't even get here
|
|
|
|
* - host-model is used for host CPU running in a compatibility mode and
|
|
|
|
* it needs to remain unchanged
|
|
|
|
* - custom doesn't support any optional features, there's nothing to
|
|
|
|
* update
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (guest->mode == VIR_CPU_MODE_CUSTOM)
|
2013-09-03 14:28:24 +08:00
|
|
|
guest->match = VIR_CPU_MATCH_EXACT;
|
|
|
|
|
2016-06-23 15:27:07 +02:00
|
|
|
return 0;
|
2011-10-03 05:56:20 -07:00
|
|
|
}
|
2012-12-20 12:38:25 +01:00
|
|
|
|
2012-10-15 17:07:50 +08:00
|
|
|
static virCPUDefPtr
|
2018-05-15 10:50:32 +02:00
|
|
|
virCPUppc64Baseline(virCPUDefPtr *cpus,
|
2015-08-07 17:39:02 +02:00
|
|
|
unsigned int ncpus,
|
2019-10-14 14:45:33 +02:00
|
|
|
virDomainCapsCPUModelsPtr models G_GNUC_UNUSED,
|
|
|
|
const char **features G_GNUC_UNUSED,
|
|
|
|
bool migratable G_GNUC_UNUSED)
|
2011-10-03 05:56:20 -07:00
|
|
|
{
|
2020-09-02 17:25:43 -03:00
|
|
|
g_autoptr(virCPUppc64Map) map = NULL;
|
2020-09-02 17:25:38 -03:00
|
|
|
const virCPUppc64Model *model;
|
2020-09-02 17:25:35 -03:00
|
|
|
const virCPUppc64Vendor *vendor = NULL;
|
2020-09-02 17:25:46 -03:00
|
|
|
g_autoptr(virCPUDef) cpu = NULL;
|
Convert 'int i' to 'size_t i' in src/cpu/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 15:09:33 +01:00
|
|
|
size_t i;
|
2012-12-19 01:33:01 +01:00
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (!(map = ppc64LoadMap()))
|
2020-09-02 17:25:46 -03:00
|
|
|
return NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (!(model = ppc64ModelFind(map, cpus[0]->model))) {
|
2012-12-19 01:33:01 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown CPU model %s"), cpus[0]->model);
|
2020-09-02 17:25:46 -03:00
|
|
|
return NULL;
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2012-12-19 01:33:01 +01:00
|
|
|
for (i = 0; i < ncpus; i++) {
|
2020-09-02 17:25:35 -03:00
|
|
|
const virCPUppc64Vendor *vnd;
|
2012-12-11 12:58:54 +00:00
|
|
|
|
2015-08-07 17:39:18 +02:00
|
|
|
/* Hosts running old (<= 1.2.18) versions of libvirt will report
|
|
|
|
* strings like 'power7+' or 'power8e' instead of proper CPU model
|
|
|
|
* names in the capabilities XML; moreover, they lack information
|
|
|
|
* about some proper CPU models like 'POWER8'.
|
|
|
|
* This implies two things:
|
|
|
|
* 1) baseline among such hosts never worked
|
|
|
|
* 2) while a few models, eg. 'POWER8_v1.0', could work on both
|
|
|
|
* old and new versions of libvirt, the information we have
|
|
|
|
* here is not enough to pick such a model
|
|
|
|
* Hence we just compare models by name to decide whether or not
|
|
|
|
* two hosts are compatible */
|
2012-12-19 01:33:01 +01:00
|
|
|
if (STRNEQ(cpus[i]->model, model->name)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("CPUs are incompatible"));
|
2020-09-02 17:25:46 -03:00
|
|
|
return NULL;
|
2012-12-19 01:33:01 +01:00
|
|
|
}
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2012-12-19 01:33:01 +01:00
|
|
|
if (!cpus[i]->vendor)
|
|
|
|
continue;
|
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (!(vnd = ppc64VendorFind(map, cpus[i]->vendor))) {
|
2012-12-19 01:33:01 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("Unknown CPU vendor %s"), cpus[i]->vendor);
|
2020-09-02 17:25:46 -03:00
|
|
|
return NULL;
|
2012-12-19 01:33:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (model->vendor) {
|
|
|
|
if (model->vendor != vnd) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("CPU vendor %s of model %s differs from "
|
|
|
|
"vendor %s"),
|
|
|
|
model->vendor->name, model->name,
|
|
|
|
vnd->name);
|
2020-09-02 17:25:46 -03:00
|
|
|
return NULL;
|
2012-12-19 01:33:01 +01:00
|
|
|
}
|
|
|
|
} else if (vendor) {
|
|
|
|
if (vendor != vnd) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("CPU vendors do not match"));
|
2020-09-02 17:25:46 -03:00
|
|
|
return NULL;
|
2012-12-19 01:33:01 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vendor = vnd;
|
|
|
|
}
|
2012-10-15 17:07:50 +08:00
|
|
|
}
|
|
|
|
|
2019-11-29 11:00:26 +00:00
|
|
|
cpu = virCPUDefNew();
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
cpu->model = g_strdup(model->name);
|
|
|
|
|
|
|
|
if (vendor)
|
|
|
|
cpu->vendor = g_strdup(vendor->name);
|
2012-12-19 01:33:01 +01:00
|
|
|
|
|
|
|
cpu->type = VIR_CPU_TYPE_GUEST;
|
|
|
|
cpu->match = VIR_CPU_MATCH_EXACT;
|
2015-08-07 17:39:19 +02:00
|
|
|
cpu->fallback = VIR_CPU_FALLBACK_FORBID;
|
2012-10-15 17:07:50 +08:00
|
|
|
|
2020-09-02 17:25:46 -03:00
|
|
|
return g_steal_pointer(&cpu);
|
2011-10-03 05:56:20 -07:00
|
|
|
}
|
|
|
|
|
2014-11-20 11:08:21 +01:00
|
|
|
static int
|
2016-11-04 14:20:39 +01:00
|
|
|
virCPUppc64DriverGetModels(char ***models)
|
2014-11-20 11:08:21 +01:00
|
|
|
{
|
2020-09-02 17:25:43 -03:00
|
|
|
g_autoptr(virCPUppc64Map) map = NULL;
|
2016-05-18 15:23:54 +02:00
|
|
|
size_t i;
|
2014-11-20 11:08:21 +01:00
|
|
|
|
2015-07-20 15:13:02 +02:00
|
|
|
if (!(map = ppc64LoadMap()))
|
2020-09-09 08:37:51 +02:00
|
|
|
return -1;
|
2014-11-20 11:08:21 +01:00
|
|
|
|
2016-05-18 15:23:54 +02:00
|
|
|
if (models) {
|
|
|
|
if (VIR_ALLOC_N(*models, map->nmodels + 1) < 0)
|
2020-09-09 08:37:51 +02:00
|
|
|
return -1;
|
2014-11-20 11:08:21 +01:00
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
for (i = 0; i < map->nmodels; i++)
|
|
|
|
(*models)[i] = g_strdup(map->models[i]->name);
|
2014-11-20 11:08:21 +01:00
|
|
|
}
|
|
|
|
|
2020-09-02 17:25:43 -03:00
|
|
|
return map->nmodels;
|
2014-11-20 11:08:21 +01:00
|
|
|
}
|
|
|
|
|
2015-07-20 14:35:22 +02:00
|
|
|
struct cpuArchDriver cpuDriverPPC64 = {
|
2015-07-20 15:20:20 +02:00
|
|
|
.name = "ppc64",
|
|
|
|
.arch = archs,
|
2019-10-15 13:55:26 +02:00
|
|
|
.narch = G_N_ELEMENTS(archs),
|
2016-08-09 13:26:53 +02:00
|
|
|
.compare = virCPUppc64Compare,
|
2015-08-07 17:39:02 +02:00
|
|
|
.decode = ppc64DriverDecode,
|
2011-10-03 05:56:20 -07:00
|
|
|
.encode = NULL,
|
2017-02-02 15:37:40 +01:00
|
|
|
.dataFree = virCPUppc64DataFree,
|
2017-03-06 21:35:49 +01:00
|
|
|
.getHost = virCPUppc64GetHost,
|
2018-05-15 10:50:32 +02:00
|
|
|
.baseline = virCPUppc64Baseline,
|
2016-06-23 15:27:07 +02:00
|
|
|
.update = virCPUppc64Update,
|
2016-11-04 14:20:39 +01:00
|
|
|
.getModels = virCPUppc64DriverGetModels,
|
2016-11-09 17:09:48 +01:00
|
|
|
.convertLegacy = virCPUppc64ConvertLegacy,
|
2011-10-03 05:56:20 -07:00
|
|
|
};
|