Hi all. Patch #1 is actually Pavel Fedin's patch https://qemu-devel/2015-05/msg04495.html, which I included as a replacement to my original patch #1 "as there could be only one". I think that Pavel's needs to address all the issues in the original thread. Best regards. S.P. On Jun 4, 2015 7:18 PM, "Peter Maydell" <peter.mayd...@linaro.org> wrote:
> On 4 June 2015 at 17:40, Shlomo Pongratz <shlomopongr...@gmail.com> wrote: > > From: Pavel Fedin <p.fe...@samsung.com> > > Hi. I think this patch largely makes sense, but I have some comments > below. If you want to fix these and resend as a standalone patch > I'm happy to apply that. > > > 1. MPIDR value (minus feature bits) is now directly stored in CPU > instance. > > 2. Default assignment is based on original rule (8 CPUs per cluster). > > 3. If KVM is used, MPIDR values are overridden with those from KVM. This > is > > necessary for > > proper KVM PSCI functioning. > > 4. Some cosmetic changes which would make further expansion of this code > easier. > > 5. Added some debugging macros because CPU ID assignment is tricky part, > and if > > there are > > some problems, i think there should be a quick way to make sure they are > > correct. > > This does not have an RFC mark because it is perfectly okay to be > committed > > alone, it > > does not break anything. Commit message follows. Cc'ed to all interested > > parties because i > > really hope to get things going somewhere this time. > > This sort of commentary belongs below the '---' line, so it doesn't > end up in the final git commit message. > > > In order to support up to 128 cores with GIC-500 (GICv3 implementation) > > affinity1 must be used. GIC-500 support up to 32 clusters with up to > > 8 cores in a cluster. So for example, if one wishes to have 16 cores, > > the options are: 2 clusters of 8 cores each, 4 clusters with 4 cores each > > Currently only the first option is supported for TCG. However, KVM > expects > > to have the same clusters layout as host machine has. Therefore, if we > use > > 64-bit KVM we override CPU IDs with those provided by the KVM. For 32-bit > > systems it is OK to leave the default because so far we do not have more > > than 8 CPUs on any of them. > > This implementation has a potential to be extended with some methods > which > > would define cluster layout instead of hardcoded CPUS_PER_CLUSTER > > definition. This would allow to emulate real machines with different > > layouts. However, in case of KVM we would still have to inherit IDs from > > the host. > > I agree that we want to be using the same idea of MPIDR as KVM > when KVM is enabled, certainly. But this commit message has > a number of inaccuracies: > * KVM doesn't inherit IDs from the host > * we don't need to have the same cluster layout as the host machine > * this isn't specific to 64-bit VMs so we should fix 32 bits at the same > time > > The bug we're actually trying to fix here is just that the > kernel's mapping from VCPU ID to MPIDR value has changed > from the simplistic implementation it originally had. So in > userspace we need to read the MPIDR value back from the kernel > rather than assuming we know the mapping. (It happens that the > reason the kernel changed was to accommodate GICv3 and its > restrictions on affinity values, but that's not relevant to why > this patch is needed.) > > > Signed-off-by: Shlomo Pongratz <shlomo.pongr...@huawei.com> > > Signed-off-by: Pavel Fedin <p.fe...@samsung.com> > > --- > > hw/arm/virt.c | 6 +++++- > > target-arm/cpu-qom.h | 3 +++ > > target-arm/cpu.c | 17 +++++++++++++++++ > > target-arm/helper.c | 9 +++------ > > target-arm/kvm64.c | 25 +++++++++++++++++++++++++ > > target-arm/psci.c | 20 ++++++++++++++++++-- > > 6 files changed, 71 insertions(+), 9 deletions(-) > > > > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > > index 05db8cb..19c8c3a 100644 > > --- a/hw/arm/virt.c > > +++ b/hw/arm/virt.c > > @@ -294,7 +294,11 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo > *vbi) > > "enable-method", "psci"); > > } > > > > - qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", cpu); > > + /* > > + * If cpus node's #address-cells property is set to 1 > > + * The reg cell bits [23:0] must be set to bits [23:0] of > MPIDR_EL1. > > + */ > > This comment is either obvious or misleading depending on your > point of view. > > > + qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", armcpu->mpidr); > > g_free(nodename); > > } > > } > > diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h > > index ed5a644..a382a09 100644 > > --- a/target-arm/cpu-qom.h > > +++ b/target-arm/cpu-qom.h > > @@ -159,6 +159,7 @@ typedef struct ARMCPU { > > uint64_t id_aa64mmfr1; > > uint32_t dbgdidr; > > uint32_t clidr; > > + uint64_t mpidr; /* Without feature bits */ > > I think it would be less confusing to store the entire MPIDR > here, and then mask it out if there are places that only > want the affinity bits. > > > /* The elements of this array are the CCSIDR values for each cache, > > * in the order L1DCache, L1ICache, L2DCache, L2ICache, etc. > > */ > > @@ -171,6 +172,8 @@ typedef struct ARMCPU { > > uint64_t rvbar; > > } ARMCPU; > > > > +#define CPUS_PER_CLUSTER 8 > > Changes I suggest below will mean this #define is only > used in one place so it won't need to be in a header. > > > + > > #define TYPE_AARCH64_CPU "aarch64-cpu" > > #define AARCH64_CPU_CLASS(klass) \ > > OBJECT_CLASS_CHECK(AArch64CPUClass, (klass), TYPE_AARCH64_CPU) > > diff --git a/target-arm/cpu.c b/target-arm/cpu.c > > index 4a888ab..7272466 100644 > > --- a/target-arm/cpu.c > > +++ b/target-arm/cpu.c > > @@ -31,6 +31,12 @@ > > #include "sysemu/kvm.h" > > #include "kvm_arm.h" > > > > +#ifdef DEBUG > > +# define DPRINTF(format, ...) printf("armcpu: " format , ## __VA_ARGS__) > > +#else > > +# define DPRINTF(format, ...) do { } while (0) > > +#endif > > Drop these debug macros, please. > > > + > > static void arm_cpu_set_pc(CPUState *cs, vaddr value) > > { > > ARMCPU *cpu = ARM_CPU(cs); > > @@ -388,12 +394,23 @@ static void arm_cpu_initfn(Object *obj) > > CPUState *cs = CPU(obj); > > ARMCPU *cpu = ARM_CPU(obj); > > static bool inited; > > + uint32_t Aff1, Aff0; > > > > cs->env_ptr = &cpu->env; > > cpu_exec_init(&cpu->env); > > cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal, > > g_free, g_free); > > > > + /* > > + * We don't support setting cluster ID ([16..23]) (known as Aff2 > > + * in later ARM ARM versions), or any of the higher affinity level > fields, > > + * so these bits always RAZ. > > + */ > > + Aff1 = cs->cpu_index / CPUS_PER_CLUSTER; > > + Aff0 = cs->cpu_index % CPUS_PER_CLUSTER; > > + cpu->mpidr = (Aff1 << 8) | Aff0; > > + DPRINTF("Init(%p): index %d mpidr 0x%jX\n", cpu, cs->cpu_index, > cpu->mpidr); > > + > > #ifndef CONFIG_USER_ONLY > > /* Our inbound IRQ and FIQ lines */ > > if (kvm_enabled()) { > > diff --git a/target-arm/helper.c b/target-arm/helper.c > > index 1cc4993..99c7a30 100644 > > --- a/target-arm/helper.c > > +++ b/target-arm/helper.c > > @@ -2063,12 +2063,9 @@ static const ARMCPRegInfo strongarm_cp_reginfo[] > = { > > > > static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri) > > { > > - CPUState *cs = CPU(arm_env_get_cpu(env)); > > - uint32_t mpidr = cs->cpu_index; > > - /* We don't support setting cluster ID ([8..11]) (known as Aff1 > > - * in later ARM ARM versions), or any of the higher affinity level > fields, > > - * so these bits always RAZ. > > - */ > > + ARMCPU *cpu = ARM_CPU(arm_env_get_cpu(env)); > > + uint64_t mpidr = cpu->mpidr; > > + > > if (arm_feature(env, ARM_FEATURE_V7MP)) { > > mpidr |= (1U << 31); > > /* Cores which are uniprocessor (non-coherent) > > diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c > > index 93c1ca8..99fa34e 100644 > > --- a/target-arm/kvm64.c > > +++ b/target-arm/kvm64.c > > @@ -25,6 +25,12 @@ > > #include "internals.h" > > #include "hw/arm/arm.h" > > > > +#ifdef DEBUG > > +# define DPRINTF(format, ...) printf("arm-kvm64: " format , ## > __VA_ARGS__) > > +#else > > +# define DPRINTF(format, ...) do { } while (0) > > +#endif > > + > > static inline void set_feature(uint64_t *features, int feature) > > { > > *features |= 1ULL << feature; > > @@ -77,6 +83,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass > *ahcc) > > return true; > > } > > > > +#define ARM_MPIDR_HWID_BITMASK 0xFF00FFFFFFULL > > +#define ARM_CPU_ID 3, 0, 0, 0 > > +#define ARM_CPU_ID_MPIDR 5 > > I don't see the point in separating the op2 value from the rest. > > > + > > int kvm_arch_init_vcpu(CPUState *cs) > > { > > int ret; > > @@ -107,6 +117,21 @@ int kvm_arch_init_vcpu(CPUState *cs) > > return ret; > > } > > > > + /* > > + * When KVM is in use, psci is emulated in-kernel and not by qemu. > > PSCI and QEMU should both be all-caps. > > > + * In order for it to work correctly we should use correct MPIDR > values, > > + * which appear to be inherited from the host. > > I don't think they're inherited from the host: it's just that > different host kernels use different mappings from vcpu ID > to MPIDR (see reset_mpidr() in arch/arm64/kvm/sys_regs.c; its > implementation has changed over time). > In any case we don't need to speculate; you can just say: > > In order for it to work correctly we must use MPIDR values in > the device tree which match the MPIDR values the kernel has picked > for the vcpus, so ask KVM what those values are. > > > + * So we override our defaults by asking KVM about these values. > > + */ > > + ret = kvm_get_one_reg(cs, ARM64_SYS_REG(ARM_CPU_ID, > ARM_CPU_ID_MPIDR), > > + &cpu->mpidr); > > + if (ret) { > > + return ret; > > + } > > + cpu->mpidr &= ARM_MPIDR_HWID_BITMASK; > > + DPRINTF("Init(%p): index %d MPIDR 0x%jX\n", cpu, > > + cs->cpu_index, cpu->mpidr); > > + > > return kvm_arm_init_cpreg_list(cpu); > > } > > > > There should also be an equivalent patch to kvm32.c, because > PSCI on 32-bit systems has the same issue. > > > diff --git a/target-arm/psci.c b/target-arm/psci.c > > index d8fafab..d03896f 100644 > > --- a/target-arm/psci.c > > +++ b/target-arm/psci.c > > @@ -72,6 +72,22 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type) > > } > > } > > > > +static uint32_t mpidr_to_idx(uint64_t mpidr) > > +{ > > + uint32_t Aff1, Aff0; > > + > > + /* > > + * MPIDR_EL1 [RES0:affinity-3:RES1:U:RES0:MT:affinity-1:affinity-0] > > + * GIC 500 code currently supports 32 clusters with 8 cores each > > + * but no more than 128 cores. Future version will have flexible > > + * affinity selection > > + * GIC 400 supports 8 cores so 0x7 for Aff0 is O.K. too > > + */ > > + Aff1 = (mpidr & 0xff00) >> 8; > > + Aff0 = mpidr & 0xff; > > + return Aff1 * CPUS_PER_CLUSTER + Aff0; > > +} > > > + > > void arm_handle_psci_call(ARMCPU *cpu) > > { > > /* > > @@ -121,7 +137,7 @@ void arm_handle_psci_call(ARMCPU *cpu) > > > > switch (param[2]) { > > case 0: > > - target_cpu_state = qemu_get_cpu(mpidr & 0xff); > > + target_cpu_state = qemu_get_cpu(mpidr_to_idx(mpidr)); > > Rather than doing this, you can just have an > arm_get_cpu_by_mpidr() which does > CPU_FOREACH(cs) { > ARMCPU *cpu = ARM_CPU(cs); > > if (cpu->mpidr == mpidr) { > return cpu; > } > } > return NULL; > > ie same as qemu_get_cpu() but checking on mpidr rather than > cpu_index. Then we don't need to make assumptions about the > mpidr-to-index mapping here at all (and this code will > continue to work if in future we decide to expose the > cluster topology via CPU properties for the board to set.) > > thanks > -- PMM >