From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41608) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wn3Hb-0006jH-19 for qemu-devel@nongnu.org; Wed, 21 May 2014 05:58:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Wn3HS-0002aE-Sv for qemu-devel@nongnu.org; Wed, 21 May 2014 05:57:58 -0400 Message-ID: <537C789D.8070406@suse.de> Date: Wed, 21 May 2014 11:57:49 +0200 From: Alexander Graf MIME-Version: 1.0 References: <1400660862-20455-1-git-send-email-aik@ozlabs.ru> <1400660862-20455-9-git-send-email-aik@ozlabs.ru> <537C7002.5090100@suse.de> <537C73B9.9060803@ozlabs.ru> In-Reply-To: <537C73B9.9060803@ozlabs.ru> Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Alexey Kardashevskiy , qemu-devel@nongnu.org Cc: qemu-ppc@nongnu.org On 21.05.14 11:36, Alexey Kardashevskiy wrote: > On 05/21/2014 07:21 PM, Alexander Graf wrote: >> On 21.05.14 10:27, Alexey Kardashevskiy wrote: >>> Modern Linux kernels support last POWERPC CPUs so when a kernel boots, >>> in most cases it can find a matching cpu_spec in the kernel's cpu_specs >>> list. However if the kernel is quite old, it may be missing a definition >>> of the actual CPU. To provide an ability for old kernels to work on modern >>> hardware, a Processor Compatibility Mode has been introduced >>> by the PowerISA specification. >>> >>> From the hardware prospective, it is supported by the Processor >>> Compatibility Register (PCR) which is defined in PowerISA. The register >>> enables one of the compatibility modes (2.05/2.06/2.07). >>> Since PCR is a hypervisor privileged register and cannot be >>> directly accessed from the guest, the mode selection is done via >>> ibm,client-architecture-support (CAS) RTAS call using which the guest >>> specifies what "raw" and "architected" CPU versions it supports. >>> QEMU works out the best match, changes a "cpu-version" property of >>> every CPU and notifies the guest about the change by setting these >>> properties in the buffer passed as a response on a custom H_CAS hypercall. >>> >>> This implements ibm,client-architecture-support parameters parsing >>> (now only for PVRs) and cooks the device tree diff with new values for >>> "cpu-version", "ibm,ppc-interrupt-server#s" and >>> "ibm,ppc-interrupt-server#s" properties. >>> >>> Signed-off-by: Alexey Kardashevskiy >>> --- >>> hw/ppc/spapr.c | 4 ++- >>> hw/ppc/spapr_hcall.c | 85 >>> ++++++++++++++++++++++++++++++++++++++++++++++++++++ >>> trace-events | 4 +++ >>> 3 files changed, 92 insertions(+), 1 deletion(-) >>> >>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c >>> index 14c72d9..020426a 100644 >>> --- a/hw/ppc/spapr.c >>> +++ b/hw/ppc/spapr.c >>> @@ -34,6 +34,7 @@ >>> #include "sysemu/kvm.h" >>> #include "kvm_ppc.h" >>> #include "mmu-hash64.h" >>> +#include "qom/cpu.h" >>> #include "hw/boards.h" >>> #include "hw/ppc/ppc.h" >>> @@ -601,7 +602,8 @@ int spapr_h_cas_compose_response(target_ulong addr, >>> target_ulong size) >>> _FDT((fdt_open_into(fdt_skel, fdt, size))); >>> g_free(fdt_skel); >>> - /* Place to make changes to the tree */ >>> + /* Fix skeleton up */ >>> + _FDT((spapr_fixup_cpu_dt(fdt, spapr))); >>> /* Pack resulting tree */ >>> _FDT((fdt_pack(fdt))); >>> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c >>> index 2f6aa5c..2e0a49c 100644 >>> --- a/hw/ppc/spapr_hcall.c >>> +++ b/hw/ppc/spapr_hcall.c >>> @@ -3,6 +3,9 @@ >>> #include "helper_regs.h" >>> #include "hw/ppc/spapr.h" >>> #include "mmu-hash64.h" >>> +#include "cpu-models.h" >>> +#include "trace.h" >>> +#include "kvm_ppc.h" >>> struct SPRSyncState { >>> CPUState *cs; >>> @@ -752,12 +755,94 @@ out: >>> return ret; >>> } >>> +#define get_compat_level(cpuver) ( \ >>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_05) ? 2050 : \ >>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06) ? 2060 : \ >>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \ >>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0) >>> + >>> static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, >>> sPAPREnvironment *spapr, >>> target_ulong opcode, >>> target_ulong *args) >>> { >>> target_ulong list = args[0]; >>> + PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_); >>> + CPUState *cs; >>> + bool cpu_match = false; >>> + unsigned old_cpu_version = cpu_->cpu_version; >>> + unsigned compat_lvl = 0, cpu_version = 0; >>> + unsigned max_lvl = get_compat_level(cpu_->max_compat); >>> + >>> + /* Parse PVR list */ >>> + for ( ; ; ) { >>> + uint32_t pvr, pvr_mask; >>> + >>> + pvr_mask = rtas_ld(list, 0); >>> + list += 4; >>> + pvr = rtas_ld(list, 0); >>> + list += 4; >>> + >>> + trace_spapr_cas_pvr_try(pvr); >>> + if (!max_lvl && >>> + ((cpu_->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask))) { >>> + cpu_match = true; >>> + cpu_version = 0; >>> + } else if (pvr == cpu_->cpu_version) { >>> + cpu_match = true; >>> + cpu_version = cpu_->cpu_version; >>> + } else if (!cpu_match) { >>> + /* If it is a logical PVR, try to determine the highest >>> level */ >>> + unsigned lvl = get_compat_level(pvr); >>> + if (lvl) { >>> + bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) && >>> + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05)); >>> + bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) && >>> + ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) || >>> + (lvl == >>> get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS))); >>> + >>> + if (is205 || is206) { >>> + if (!max_lvl) { >>> + /* User did not set the level, choose the >>> highest */ >>> + if (compat_lvl <= lvl) { >>> + compat_lvl = lvl; >>> + cpu_version = pvr; >>> + } >>> + } else if (max_lvl >= lvl) { >>> + /* User chose the level, don't set higher than >>> this */ >>> + compat_lvl = lvl; >>> + cpu_version = pvr; >>> + } >>> + } >>> + } >>> + } >>> + /* Terminator record */ >>> + if (~pvr_mask & pvr) { >> This loop can be used by the guest to stall QEMU for a long period of time, >> no? Better add a safety net check somewhere to allow for early abort. > Like what? No more than 64 PVRs would be enough? Yeah, choose a random (high) number. If you like make it 512 to be safe for a few generations :). Alex