From patchwork Thu Sep 5 06:01:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 272794 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 1E38D2C00F5 for ; Thu, 5 Sep 2013 16:02:02 +1000 (EST) Received: from localhost ([::1]:57046 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VHSdk-0003cr-25 for incoming@patchwork.ozlabs.org; Thu, 05 Sep 2013 02:02:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39192) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VHSdL-0003cM-ME for qemu-devel@nongnu.org; Thu, 05 Sep 2013 02:01:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VHSdB-0003P0-Lu for qemu-devel@nongnu.org; Thu, 05 Sep 2013 02:01:35 -0400 Received: from e23smtp09.au.ibm.com ([202.81.31.142]:60661) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VHSdB-0003Ol-21 for qemu-devel@nongnu.org; Thu, 05 Sep 2013 02:01:25 -0400 Received: from /spool/local by e23smtp09.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 6 Sep 2013 02:55:14 +1000 Received: from d23dlp01.au.ibm.com (202.81.31.203) by e23smtp09.au.ibm.com (202.81.31.206) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 6 Sep 2013 02:55:12 +1000 Received: from d23relay04.au.ibm.com (d23relay04.au.ibm.com [9.190.234.120]) by d23dlp01.au.ibm.com (Postfix) with ESMTP id 60BDC2CE8057; Thu, 5 Sep 2013 16:01:20 +1000 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r855j48w61014078; Thu, 5 Sep 2013 15:45:05 +1000 Received: from d23av04.au.ibm.com (loopback [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r8561JTx019172; Thu, 5 Sep 2013 16:01:19 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.190.163.12]) by d23av04.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id r8561J6T019167; Thu, 5 Sep 2013 16:01:19 +1000 Received: from bran.ozlabs.ibm.com (haven.au.ibm.com [9.190.164.82]) by ozlabs.au.ibm.com (Postfix) with ESMTP id 7A20BA01FC; Thu, 5 Sep 2013 16:01:19 +1000 (EST) Received: from ka1.ozlabs.ibm.com (ka1.ozlabs.ibm.com [10.61.145.11]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id DDB5C16AB01; Thu, 5 Sep 2013 16:01:18 +1000 (EST) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 5 Sep 2013 16:01:17 +1000 Message-Id: <1378360877-4455-1-git-send-email-aik@ozlabs.ru> X-Mailer: git-send-email 1.8.4.rc4 MIME-Version: 1.0 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13090516-3568-0000-0000-00000431A0A4 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 202.81.31.142 Cc: Alexey Kardashevskiy , Alexander Graf , qemu-ppc@nongnu.org, Paul Mackerras , =?UTF-8?q?Andreas=20F=C3=A4rber?= Subject: [Qemu-devel] [PATCH v6] powerpc: add PVR mask support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org IBM POWERPC processors encode PVR as a CPU family in higher 16 bits and a CPU version in lower 16 bits. Since there is no significant change in behavior between versions, there is no point to add every single CPU version in QEMU's CPU list. Also, new CPU versions of already supported CPU won't break the existing code. This adds PVR value/mask support for KVM, i.e. for -cpu host option. As CPU family class name for POWER7 is "POWER7-family", there is no need to touch aliases. Cc: Andreas Färber Signed-off-by: Alexey Kardashevskiy --- Changes: v6: * family classes are abstract again * POWER7+ moved to a separate patch as it also need a separate family * added ppc_cpu_class_by_pvr_mask() which is a copy of ppc_cpu_class_by_pvr() but compares PVRs with masks; this function is called from KVM code only to support the "-cpu host" option; unlike the original search function, the new one also includes abstract family classes. v5: * removed pvr_default * added hiding of family CPU classes (should not appear in -cpu ?) * separated POWER7+ into a class (it used to be POWER7) and added a mask for it * added mask for POWER8 * added _BASE suffix to PVR mask constants and moved them before actual CPUs v4: * removed bogus layer from hierarchy v3: * renamed macros to describe the functionality better * added default PVR value for the powerpc cpu family (what alias used to do) v2: * aliases are replaced with another level in class hierarchy --- target-ppc/cpu-models.c | 1 + target-ppc/cpu-models.h | 5 +++++ target-ppc/cpu-qom.h | 2 ++ target-ppc/kvm.c | 4 ++++ target-ppc/translate_init.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c index 8dea560..04d88c5 100644 --- a/target-ppc/cpu-models.c +++ b/target-ppc/cpu-models.c @@ -44,6 +44,7 @@ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); \ \ pcc->pvr = _pvr; \ + pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK; \ pcc->svr = _svr; \ dc->desc = _desc; \ } \ diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h index d9145d1..731ec4a 100644 --- a/target-ppc/cpu-models.h +++ b/target-ppc/cpu-models.h @@ -39,6 +39,7 @@ extern PowerPCCPUAlias ppc_cpu_aliases[]; /*****************************************************************************/ /* PVR definitions for most known PowerPC */ enum { + CPU_POWERPC_DEFAULT_MASK = 0xFFFFFFFF, /* PowerPC 401 family */ /* Generic PowerPC 401 */ #define CPU_POWERPC_401 CPU_POWERPC_401G2 @@ -552,10 +553,14 @@ enum { CPU_POWERPC_POWER6 = 0x003E0000, CPU_POWERPC_POWER6_5 = 0x0F000001, /* POWER6 in POWER5 mode */ CPU_POWERPC_POWER6A = 0x0F000002, + CPU_POWERPC_POWER7_BASE = 0x003F0000, + CPU_POWERPC_POWER7_MASK = 0xFFFF0000, CPU_POWERPC_POWER7_v20 = 0x003F0200, CPU_POWERPC_POWER7_v21 = 0x003F0201, CPU_POWERPC_POWER7_v23 = 0x003F0203, CPU_POWERPC_POWER7P_v21 = 0x004A0201, + CPU_POWERPC_POWER8_BASE = 0x004B0000, + CPU_POWERPC_POWER8_MASK = 0xFFFF0000, CPU_POWERPC_POWER8_v10 = 0x004B0100, CPU_POWERPC_970 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index f3c710a..3f82629 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -54,6 +54,7 @@ typedef struct PowerPCCPUClass { void (*parent_reset)(CPUState *cpu); uint32_t pvr; + uint32_t pvr_mask; uint32_t svr; uint64_t insns_flags; uint64_t insns_flags2; @@ -99,6 +100,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env) #define ENV_OFFSET offsetof(PowerPCCPU, env) PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr); +PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr); void ppc_cpu_do_interrupt(CPUState *cpu); void ppc_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 8a196c6..d10dba2 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1732,6 +1732,7 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); /* Now fix up the class with information we can query from the host */ + pcc->pvr = mfpvr(); if (vmx != -1) { /* Only override when we know what the host supports */ @@ -1782,6 +1783,9 @@ static int kvm_ppc_register_host_cpu_type(void) pvr_pcc = ppc_cpu_class_by_pvr(host_pvr); if (pvr_pcc == NULL) { + pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr); + } + if (pvr_pcc == NULL) { return -1; } type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 761b2e5..7e37cf2 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7216,6 +7216,8 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER7"; dc->desc = "POWER7"; + pcc->pvr = CPU_POWERPC_POWER7_BASE; + pcc->pvr_mask = CPU_POWERPC_POWER7_MASK; pcc->init_proc = init_proc_POWER7; pcc->check_pow = check_pow_nocheck; pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | @@ -7251,6 +7253,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER8"; dc->desc = "POWER8"; + pcc->pvr = CPU_POWERPC_POWER8_BASE; + pcc->pvr_mask = CPU_POWERPC_POWER8_MASK; pcc->init_proc = init_proc_POWER7; pcc->check_pow = check_pow_nocheck; pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | @@ -8164,7 +8168,6 @@ static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b) return -1; } #endif - return pcc->pvr == pvr ? 0 : -1; } @@ -8183,6 +8186,44 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr) return pcc; } +static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b) +{ + ObjectClass *oc = (ObjectClass *)a; + uint32_t pvr = *(uint32_t *)b; + PowerPCCPUClass *pcc = (PowerPCCPUClass *)a; + gint ret; + + /* -cpu host does a PVR lookup during construction */ + if (unlikely(strcmp(object_class_get_name(oc), + TYPE_HOST_POWERPC_CPU) == 0)) { + return -1; + } + +#if defined(TARGET_PPCEMB) + if (pcc->mmu_model != POWERPC_MMU_BOOKE) { + return -1; + } +#endif + ret = (((pcc->pvr & pcc->pvr_mask) == (pvr & pcc->pvr_mask)) ? 0 : -1); + + return ret; +} + +PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr) +{ + GSList *list, *item; + PowerPCCPUClass *pcc = NULL; + + list = object_class_get_list(TYPE_POWERPC_CPU, true); + item = g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr_mask); + if (item != NULL) { + pcc = POWERPC_CPU_CLASS(item->data); + } + g_slist_free(list); + + return pcc; +} + static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b) { ObjectClass *oc = (ObjectClass *)a; @@ -8557,6 +8598,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); pcc->parent_realize = dc->realize; + pcc->pvr = CPU_POWERPC_DEFAULT_MASK; + pcc->pvr_mask = 0; dc->realize = ppc_cpu_realizefn; dc->unrealize = ppc_cpu_unrealizefn;