On 04.09.2013, at 13:40, Alexey Kardashevskiy wrote:

> On 09/04/2013 08:42 PM, Alexander Graf wrote:
>> 
>> 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 <nik...@linux.vnet.ibm.com>
>>> Cc: Andreas Färber <afaer...@suse.de>
>>> Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
>>> ---
>>> 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.
> 
> I am always trying to avoid adding new variables but yes, this is not the
> case, I'll fix it.
> 
>> 
>>> +    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 is a different problem which I do not how to solve in a way to make
> everybody happy. Add logical CPUs to every CPU family (at least for
> POWER7/7+/8)?

I'm not sure the CPU is really the right place to put this information. After 
all, you are not changing the CPU itself, you're only changing a few bits 
inside of that CPU that make it appear closer to the legacy CPU plus a few 
device tree changes.

So IMHO this whole thing should be orthogonal to -cpu.

> 
> 
>> That way
>> management tools can straight on create POWER6 compat machines without
>> jumping through reboot hoops.
> 
> One of the examples (came from Paul) is:
> the host runs on POWER8, the guest boots a kernel which is capable of
> POWER7 only + POWER7-compat. We do this reboot tweak and boot in
> POWER7-compat mode. Then the guest does "yum update" and gets POWER8 kernel
> installed so when it reboots, it will boot in normal POWER8 mode. Everybody
> is happy.
> 
> Having POWER7-compat mode set from the very beginning will break this
> behaviour.

Why? Just because you're on POWER7 as default doesn't mean you can't bump to a 
newer compat later on, no?


Alex


Reply via email to