[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture
From: |
Alexander Graf |
Subject: |
Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support |
Date: |
Wed, 4 Sep 2013 12:42:28 +0200 |
On 04.09.2013, at 12:19, Alexey Kardashevskiy wrote:
> This is an RFC patch.
>
> The modern Linux kernel supports every known POWERPC CPU so when
> it boots, it can always find a matching cpu_spec from the cpu_specs array.
> However if the kernel is quite old, it may be missing the definition of
> the actual CPU. To provide ability for old kernels to work on modern
> hardware, a Logical Processor Version concept was introduced in PowerISA.
> From the hardware prospective, it is supported by PCR (Processor
> Compatibility Register) which is defined in PowerISA. The register
> enables compatibility mode which can be set to PowerISA 2.05 or 2.06.
>
> PAPR+ specification defines a Logical Processor Version per every
> version of PowerISA specification. PAPR+ also defines
> a ibm,client-architecture-support rtas call which purpose is to provide
> a negotiation mechanism for the guest and the hypervisor to work out
> the best Logical Processor Version to continue with.
>
> At the moment, the Linux kernel calls the ibm,client-architecture-support
> method and only then reads the device. The current RTAS's handler checks
> the capabilities from the array supplied by the guest kernel, analyses
> if QEMU can or cannot provide with the requested features.
> If QEMU supports everything the guest has requested, it returns from rtas
> call and the guest continues booting.
> If some parameter changes, QEMU fixes the device tree and reboots
> the guest with a new tree.
>
> In this version, the ibm,client-architecture-support handler checks
> if the current CPU is in the list from the guest and if it is not, QEMU
> adds a "cpu-version" property to a cpu node with the best of logical PVRs
> supported by the guest.
>
> Technically QEMU reboots and as a part of reboot, it fixes the tree and
> this is when the cpu-version property is actually added.
>
> Although it seems possible to add a custom interface between SLOF and QEMU
> and implement device tree update on the fly to avoid a guest reboot,
> there still may be cases when device tree change would not be enough.
> As an example, the guest may ask for a bigger RMA area than QEMU allocates
> by default.
>
> The patch depends on "[PATCH v5] powerpc: add PVR mask support".
>
> Cc: Nikunj A Dadhania <address@hidden>
> Cc: Andreas Färber <address@hidden>
> Signed-off-by: Alexey Kardashevskiy <address@hidden>
> ---
> hw/ppc/spapr.c | 10 ++++++
> hw/ppc/spapr_hcall.c | 76 +++++++++++++++++++++++++++++++++++++++++++++
> include/hw/ppc/spapr.h | 7 ++++-
> target-ppc/cpu-models.h | 13 ++++++++
> target-ppc/cpu-qom.h | 1 +
> target-ppc/translate_init.c | 3 ++
> 6 files changed, 109 insertions(+), 1 deletion(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 13574bf..5adf53c 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -238,6 +238,16 @@ static int spapr_fixup_cpu_dt(void *fdt,
> sPAPREnvironment *spapr)
> if (ret < 0) {
> return ret;
> }
> +
> + if (spapr->pvr_new) {
> + ret = fdt_setprop(fdt, offset, "cpu-version",
> + &spapr->pvr_new, sizeof(spapr->pvr_new));
> + if (ret < 0) {
> + return ret;
> + }
> + /* Reset as the guest after reboot may give other PVR set */
> + spapr->pvr_new = 0;
> + }
> }
> return ret;
> }
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 9f6e7b8..509de89 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -3,6 +3,7 @@
> #include "helper_regs.h"
> #include "hw/ppc/spapr.h"
> #include "mmu-hash64.h"
> +#include "cpu-models.h"
>
> static target_ulong h_random(PowerPCCPU *cpu, sPAPREnvironment *spapr,
> target_ulong opcode, target_ulong *args)
> @@ -792,6 +793,78 @@ out:
> return ret;
> }
>
> +static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> + sPAPREnvironment *spapr,
> + target_ulong opcode,
> + target_ulong *args)
> +{
> + target_ulong list = args[0];
> + int i, number_of_option_vectors;
> + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> + bool cpu_match = false;
> + unsigned compat_cpu_level = 0, pvr_new;
> +
> + /* Parse PVR list */
> + for ( ; ; ) {
> + uint32_t pvr, pvr_mask;
> +
> + pvr_mask = ldl_phys(list);
> + list += 4;
> + pvr = ldl_phys(list);
> + list += 4;
> +
> + if ((cpu->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask)) {
> + cpu_match = true;
> + pvr_new = cpu->env.spr[SPR_PVR];
> + }
> +
> + /* Is it a logical PVR? */
> + if ((pvr & CPU_POWERPC_LOGICAL_MASK) == CPU_POWERPC_LOGICAL_MASK) {
> + switch (pvr) {
> + case CPU_POWERPC_LOGICAL_2_05:
> + if ((pcc->pcr & POWERPC_ISA_COMPAT_2_05) &&
> + (compat_cpu_level < 2050)) {
> + compat_cpu_level = 2050;
> + pvr_new = pvr;
> + }
> + break;
> + case CPU_POWERPC_LOGICAL_2_06:
> + if ((pcc->pcr & POWERPC_ISA_COMPAT_2_06) &&
> + (compat_cpu_level < 2060)) {
> + compat_cpu_level = 2060;
> + pvr_new = pvr;
> + }
> + break;
> + case CPU_POWERPC_LOGICAL_2_06_PLUS:
> + if ((pcc->pcr & POWERPC_ISA_COMPAT_2_06) &&
> + (compat_cpu_level < 2061)) {
> + compat_cpu_level = 2061;
> + pvr_new = pvr;
> + }
> + break;
> + }
> + }
> +
> + if (~pvr_mask & pvr) {
> + break;
> + }
> + }
> +
> + /* Parsing finished. Making decision whether to reboot or not */
> + if (cpu_match) {
> + return H_SUCCESS;
> + }
> + if (pvr_new == cpu->env.spr[SPR_PVR]) {
> + return H_SUCCESS;
> + }
> +
> + cpu->env.spr[SPR_PVR] = pvr_new;
This would change the SPR value the guest sees. IIUC this is not what is
happening with this call.
> + spapr->pvr_new = pvr_new;
> + qemu_system_reset_request();
I think there should be a way to define the compat mode from the beginning
without the need to reboot the machine from itself. That way management tools
can straight on create POWER6 compat machines without jumping through reboot
hoops.
Alex
> +
> + return H_FUNCTION;
> +}
> +
> static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
> static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX -
> KVMPPC_HCALL_BASE + 1];
>
> @@ -879,6 +952,9 @@ static void hypercall_register_types(void)
> spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
>
> spapr_register_hypercall(H_SET_MODE, h_set_mode);
> +
> + /* ibm,client-architecture-support support */
> + spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support);
> }
>
> type_init(hypercall_register_types)
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 995ddcf..e2158ff 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -44,6 +44,9 @@ typedef struct sPAPREnvironment {
> uint64_t middle_iterations, middle_chunks, middle_valid,
> middle_invalid;
> uint64_t final_chunks, final_valid, final_invalid;
> } migstats;
> +
> + uint32_t pvr_new;
> +
> } sPAPREnvironment;
>
> #define H_SUCCESS 0
> @@ -304,7 +307,9 @@ typedef struct sPAPREnvironment {
> #define KVMPPC_HCALL_BASE 0xf000
> #define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0)
> #define KVMPPC_H_LOGICAL_MEMOP (KVMPPC_HCALL_BASE + 0x1)
> -#define KVMPPC_HCALL_MAX KVMPPC_H_LOGICAL_MEMOP
> +/* Client Architecture support */
> +#define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2)
> +#define KVMPPC_HCALL_MAX KVMPPC_H_CAS
>
> extern sPAPREnvironment *spapr;
>
> diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
> index 49ba4a4..a4e8763 100644
> --- a/target-ppc/cpu-models.h
> +++ b/target-ppc/cpu-models.h
> @@ -583,6 +583,13 @@ enum {
> CPU_POWERPC_RS64II = 0x00340000,
> CPU_POWERPC_RS64III = 0x00360000,
> CPU_POWERPC_RS64IV = 0x00370000,
> +
> + /* Logical CPUs */
> + CPU_POWERPC_LOGICAL_MASK = 0x0F000000,
> + CPU_POWERPC_LOGICAL_2_05 = 0x0F000002,
> + CPU_POWERPC_LOGICAL_2_06 = 0x0F000003,
> + CPU_POWERPC_LOGICAL_2_06_PLUS = 0x0F100003,
> +
> #endif /* defined(TARGET_PPC64) */
> /* Original POWER */
> /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
> @@ -745,4 +752,10 @@ enum {
> POWERPC_SVR_8641D = 0x80900121,
> };
>
> +/* Processor Compatibility Register (PCR) */
> +enum {
> + POWERPC_ISA_COMPAT_2_05 = 1ULL << 62,
> + POWERPC_ISA_COMPAT_2_06 = 1ULL << 61,
> +};
> +
> #endif
> diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
> index 0ae8b09..702ae96 100644
> --- a/target-ppc/cpu-qom.h
> +++ b/target-ppc/cpu-qom.h
> @@ -55,6 +55,7 @@ typedef struct PowerPCCPUClass {
>
> uint32_t pvr;
> uint32_t pvr_mask;
> + uint64_t pcr;
> uint32_t svr;
> uint64_t insns_flags;
> uint64_t insns_flags2;
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index e8cc3c8..645f54d 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -7249,6 +7249,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
> dc->desc = "POWER7";
> pcc->pvr = CPU_POWERPC_POWER7_BASE;
> pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
> + pcc->pcr = POWERPC_ISA_COMPAT_2_05 | POWERPC_ISA_COMPAT_2_06;
> pcc->init_proc = init_proc_POWER7;
> pcc->check_pow = check_pow_nocheck;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
> @@ -7286,6 +7287,7 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
> dc->desc = "POWER7+";
> pcc->pvr = CPU_POWERPC_POWER7P_BASE;
> pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
> + pcc->pcr = POWERPC_ISA_COMPAT_2_05 | POWERPC_ISA_COMPAT_2_06;
> pcc->init_proc = init_proc_POWER7;
> pcc->check_pow = check_pow_nocheck;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
> @@ -7323,6 +7325,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
> dc->desc = "POWER8";
> pcc->pvr = CPU_POWERPC_POWER8_BASE;
> pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
> + pcc->pcr = POWERPC_ISA_COMPAT_2_05 | POWERPC_ISA_COMPAT_2_06;
> pcc->init_proc = init_proc_POWER7;
> pcc->check_pow = check_pow_nocheck;
> pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
> --
> 1.8.4.rc4
>
- [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Alexey Kardashevskiy, 2013/09/04
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support,
Alexander Graf <=
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Alexey Kardashevskiy, 2013/09/04
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Alexander Graf, 2013/09/04
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Alexey Kardashevskiy, 2013/09/04
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Alexander Graf, 2013/09/04
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Anthony Liguori, 2013/09/04
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Paul Mackerras, 2013/09/05
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Alexander Graf, 2013/09/05
- Re: [Qemu-devel] [RFC PATCH] spapr: add initial ibm, client-architecture-support rtas call support, Paul Mackerras, 2013/09/05