From 760d88d1d0c409f1afe6f1c91539487413e8b2a9 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 8 Aug 2016 15:08:53 +0200 Subject: [PATCH 1/6] ppc64: fix compressed dump with pseries kernel If we don't provide the page size in target-ppc:cpu_get_dump_info(), the default one (TARGET_PAGE_SIZE, 4KB) is used to create the compressed dump. It works fine with Macintosh, but not with pseries as the kernel default page size is 64KB. Without this patch, if we generate a compressed dump in the QEMU monitor: (qemu) dump-guest-memory -z qemu.dump This dump cannot be read by crash: # crash vmlinux qemu.dump ... WARNING: cannot translate vmemmap kernel virtual addresses: commands requiring page structure contents will fail ... Page_size is used to determine the dumpfile's block size. The block size needs to be at least the page size, but a multiple of page size works fine too. For PPC64, linux supports either 4KB or 64KB software page size. So we define the page_size to 64KB. Signed-off-by: Laurent Vivier Reviewed-by: Andrew Jones Signed-off-by: David Gibson --- target-ppc/arch_dump.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target-ppc/arch_dump.c b/target-ppc/arch_dump.c index df1fd8c336..40282a1f50 100644 --- a/target-ppc/arch_dump.c +++ b/target-ppc/arch_dump.c @@ -220,6 +220,11 @@ int cpu_get_dump_info(ArchDumpInfo *info, } else { info->d_endian = ELFDATA2LSB; } + /* 64KB is the max page size for pseries kernel */ + if (strncmp(object_get_typename(qdev_get_machine()), + "pseries-", 8) == 0) { + info->page_size = (1U << 16); + } return 0; } From caebf37859b991c27ada22d5d7bfd929844bd20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2016 18:59:57 +0200 Subject: [PATCH 2/6] spapr: remove extra type variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sPAPR CPU core typename is already available in the upper block. Let's use it and move the check upward also. Signed-off-by: Cédric Le Goater Reviewed-by: Thomas Huth Signed-off-by: David Gibson --- hw/ppc/spapr.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 57564e5b8e..399dcc0aee 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1815,6 +1815,11 @@ static void ppc_spapr_init(MachineState *machine) if (mc->query_hotpluggable_cpus) { char *type = spapr_get_cpu_core_type(machine->cpu_model); + if (!object_class_by_name(type)) { + error_report("Unable to find sPAPR CPU Core definition"); + exit(1); + } + spapr->cores = g_new0(Object *, spapr_max_cores); for (i = 0; i < spapr_max_cores; i++) { int core_id = i * smp_threads; @@ -1826,15 +1831,7 @@ static void ppc_spapr_init(MachineState *machine) qemu_register_reset(spapr_drc_reset, drc); if (i < spapr_cores) { - char *type = spapr_get_cpu_core_type(machine->cpu_model); - Object *core; - - if (!object_class_by_name(type)) { - error_report("Unable to find sPAPR CPU Core definition"); - exit(1); - } - - core = object_new(type); + Object *core = object_new(type); object_property_set_int(core, smp_threads, "nr-threads", &error_fatal); object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, From caf6316de90301e07444de95bd540c93ce9d333a Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 9 Aug 2016 18:59:58 +0200 Subject: [PATCH 3/6] ppc: Introduce a function to look up CPU alias strings We will need this function to look up the aliases in the spapr-cpu-core code, too. Signed-off-by: Thomas Huth Signed-off-by: David Gibson --- target-ppc/cpu.h | 1 + target-ppc/translate_init.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 5fce1ffa25..786ab5cdfa 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1201,6 +1201,7 @@ extern const struct VMStateDescription vmstate_ppc_cpu; /*****************************************************************************/ PowerPCCPU *cpu_ppc_init(const char *cpu_model); void ppc_translate_init(void); +const char *ppc_cpu_lookup_alias(const char *alias); void gen_update_current_nip(void *opaque); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 5f28a36998..7a9b15e7e1 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -10012,6 +10012,19 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name) return NULL; } +const char *ppc_cpu_lookup_alias(const char *alias) +{ + int ai; + + for (ai = 0; ppc_cpu_aliases[ai].alias != NULL; ai++) { + if (strcmp(ppc_cpu_aliases[ai].alias, alias) == 0) { + return ppc_cpu_aliases[ai].model; + } + } + + return NULL; +} + PowerPCCPU *cpu_ppc_init(const char *cpu_model) { return POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model)); From 4babfaf05d020eab7d6469d12ce77cc142d22276 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 9 Aug 2016 18:59:59 +0200 Subject: [PATCH 4/6] hw/ppc/spapr: Look up CPU alias names instead of hard-coding the aliases Hard-coding the CPU alias names in the spapr_cores[] array has two big disadvantages: 1) We register a real type with the CPU alias name in spapr_cpu_core_register_types() - this prevents us from registering a CPU family name in kvm_ppc_register_host_cpu_type() with the same name (as we do it for the non-hotpluggable CPU types). 2) It's quite cumbersome to maintain the aliases here in sync with the ppc_cpu_aliases list from target-ppc/cpu-models.c. So let's simply add proper alias lookup to the spapr cpu core code, too (by checking whether the given model can be used directly, and if not by trying to look up the given model as an alias name instead). Signed-off-by: Thomas Huth Signed-off-by: David Gibson --- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_cpu_core.c | 38 +++++++++++++++++++++----------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 399dcc0aee..0787c66486 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1815,7 +1815,7 @@ static void ppc_spapr_init(MachineState *machine) if (mc->query_hotpluggable_cpus) { char *type = spapr_get_cpu_core_type(machine->cpu_model); - if (!object_class_by_name(type)) { + if (type == NULL) { error_report("Unable to find sPAPR CPU Core definition"); exit(1); } diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 716f7c44cd..bcb483dbe6 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -93,6 +93,19 @@ char *spapr_get_cpu_core_type(const char *model) core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE); g_strfreev(model_pieces); + + /* Check whether it exists or whether we have to look up an alias name */ + if (!object_class_by_name(core_type)) { + const char *realmodel; + + g_free(core_type); + realmodel = ppc_cpu_lookup_alias(model); + if (realmodel) { + return spapr_get_cpu_core_type(realmodel); + } + return NULL; + } + return core_type; } @@ -354,41 +367,32 @@ typedef struct SPAPRCoreInfo { } SPAPRCoreInfo; static const SPAPRCoreInfo spapr_cores[] = { - /* 970 and aliaes */ + /* 970 */ { .name = "970_v2.2", .initfn = spapr_cpu_core_970_initfn }, - { .name = "970", .initfn = spapr_cpu_core_970_initfn }, - /* 970MP variants and aliases */ + /* 970MP variants */ { .name = "970MP_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn }, { .name = "970mp_v1.0", .initfn = spapr_cpu_core_970MP_v10_initfn }, { .name = "970MP_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn }, { .name = "970mp_v1.1", .initfn = spapr_cpu_core_970MP_v11_initfn }, - { .name = "970mp", .initfn = spapr_cpu_core_970MP_v11_initfn }, - /* POWER5 and aliases */ + /* POWER5+ */ { .name = "POWER5+_v2.1", .initfn = spapr_cpu_core_POWER5plus_initfn }, - { .name = "POWER5+", .initfn = spapr_cpu_core_POWER5plus_initfn }, - /* POWER7 and aliases */ + /* POWER7 */ { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn }, - { .name = "POWER7", .initfn = spapr_cpu_core_POWER7_initfn }, - /* POWER7+ and aliases */ + /* POWER7+ */ { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn }, - { .name = "POWER7+", .initfn = spapr_cpu_core_POWER7plus_initfn }, - /* POWER8 and aliases */ + /* POWER8 */ { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn }, - { .name = "POWER8", .initfn = spapr_cpu_core_POWER8_initfn }, - { .name = "power8", .initfn = spapr_cpu_core_POWER8_initfn }, - /* POWER8E and aliases */ + /* POWER8E */ { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn }, - { .name = "POWER8E", .initfn = spapr_cpu_core_POWER8E_initfn }, - /* POWER8NVL and aliases */ + /* POWER8NVL */ { .name = "POWER8NVL_v1.0", .initfn = spapr_cpu_core_POWER8NVL_initfn }, - { .name = "POWER8NVL", .initfn = spapr_cpu_core_POWER8NVL_initfn }, { .name = NULL } }; From 9c83fc2e8e1630e4d0fb10055563844b6e2cf2e0 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 9 Aug 2016 19:00:00 +0200 Subject: [PATCH 5/6] ppc/kvm: Do not mess up the generic CPU family registration The code for registering the sPAPR CPU host core type has been added inbetween the generic CPU host core type and the generic CPU family type. That way the instance_init and the class_init information got lost when registering the generic CPU family type. Fix it by moving the generic family registration before the spapr cpu core registration code. Signed-off-by: Thomas Huth Signed-off-by: David Gibson --- target-ppc/kvm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 84764edeae..82b1df9bc0 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2394,6 +2394,13 @@ static int kvm_ppc_register_host_cpu_type(void) type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_register(&type_info); + /* Register generic family CPU class for a family */ + pvr_pcc = ppc_cpu_get_family_class(pvr_pcc); + dc = DEVICE_CLASS(pvr_pcc); + type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); + type_info.name = g_strdup_printf("%s-"TYPE_POWERPC_CPU, dc->desc); + type_register(&type_info); + #if defined(TARGET_PPC64) type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host"); type_info.parent = TYPE_SPAPR_CPU_CORE, @@ -2406,13 +2413,6 @@ static int kvm_ppc_register_host_cpu_type(void) type_info.instance_init = NULL; #endif - /* Register generic family CPU class for a family */ - pvr_pcc = ppc_cpu_get_family_class(pvr_pcc); - dc = DEVICE_CLASS(pvr_pcc); - type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); - type_info.name = g_strdup_printf("%s-"TYPE_POWERPC_CPU, dc->desc); - type_register(&type_info); - return 0; } From d11b268e1765e8878c1150d463b9f6dc3a8d4456 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 9 Aug 2016 19:00:01 +0200 Subject: [PATCH 6/6] ppc/kvm: Register also a generic spapr CPU core family type There is a regression with the "-cpu" parameter introduced by the spapr CPU hotplug code: We used to allow to specify a "CPU family" name with the "-cpu" parameter when running on KVM so that the user does not need to know the gory details of the exact CPU version of the host CPU. For example, it was possible to use "-cpu POWER8" on a POWER8E host CPU. This behavior does not work anymore with the new hot-pluggable spapr-cpu-core types. Since libvirt already heavily depends on the old behavior, this is quite a severe regression in the QEMU parameter interface. Let's fix it by supporting a CPU family type for the spapr-cpu-core on KVM, too. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1363812 Signed-off-by: Thomas Huth Signed-off-by: David Gibson --- target-ppc/kvm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 82b1df9bc0..dcb68b9081 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2409,8 +2409,11 @@ static int kvm_ppc_register_host_cpu_type(void) type_info.class_init = NULL; type_register(&type_info); g_free((void *)type_info.name); - type_info.instance_size = 0; - type_info.instance_init = NULL; + + /* Register generic spapr CPU family class for current host CPU type */ + type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, dc->desc); + type_register(&type_info); + g_free((void *)type_info.name); #endif return 0;