On Fri, Jul 13, 2012 at 3:43 AM, Rusty Russell <rusty.russell at linaro.org> wrote: > Recent kernels use this to set the CP15 registers, rather than putting > them in 'struct kvm_regs'. The changed size of that struct changes the > ioctl number, so we have a temporary hack to try both. > > Signed-off-by: Rusty Russell <rusty.russell at linaro.org> > > diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h > index 988890a..4842e85 100644 > --- a/linux-headers/asm-arm/kvm.h > +++ b/linux-headers/asm-arm/kvm.h > @@ -75,6 +75,37 @@ struct kvm_sregs { > __u32 features[14]; > }; > > +/* Exactly like x86. */ > +struct kvm_msr_entry { > + __u32 index; > + __u32 reserved; > + __u64 data; > +}; > + > +/* for KVM_GET_MSRS and KVM_SET_MSRS */ > +struct kvm_msrs { > + __u32 nmsrs; /* number of msrs in entries */ > + __u32 pad; > + > + struct kvm_msr_entry entries[0]; > +}; > + > +/* for KVM_GET_MSR_INDEX_LIST */ > +struct kvm_msr_list { > + __u32 nmsrs; /* number of msrs in entries */ > + __u32 indices[0]; > +}; > + > +/* If you need to interpret the index values, here's the key. */ > +#define KVM_ARM_MSR_COPROC_MASK 0xFFFF0000 > +#define KVM_ARM_MSR_64_BIT_MASK 0x00008000 > +#define KVM_ARM_MSR_64_OPC1_MASK 0x000000F0 > +#define KVM_ARM_MSR_64_CRM_MASK 0x0000000F > +#define KVM_ARM_MSR_32_CRM_MASK 0x0000000F > +#define KVM_ARM_MSR_32_OPC2_MASK 0x00000070 > +#define KVM_ARM_MSR_32_CRN_MASK 0x00000780 > +#define KVM_ARM_MSR_32_OPC1_MASK 0x00003800 > + > struct kvm_fpu { > }; > > diff --git a/target-arm/kvm.c b/target-arm/kvm.c > index 67d005f..2c149bd 100644 > --- a/target-arm/kvm.c > +++ b/target-arm/kvm.c > @@ -43,15 +43,28 @@ int kvm_arch_init_vcpu(CPUARMState *env) > return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs) ? 0 : 0; > } > > +#define MSR32_INDEX_OF(coproc, crn, opc1, crm, opc2) \ > + (((coproc)<<16) | ((opc1)<<11) | ((crn)<<7) | ((opc2)<<4) | (crm)) > + > +/* A modern kernel has a smaller struct kvm_regs, so ioctls differ: */ > +#define KVM_GET_REGS_MODERN 2157227649U > +#define KVM_SET_REGS_MODERN 1083485826U > + > int kvm_arch_put_registers(CPUARMState *env, int level) > { > struct kvm_regs regs; > int mode, bn; > + struct cp15 { > + struct kvm_msrs hdr; > + struct kvm_msr_entry e[2]; > + } cp15; > int ret; > > ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); > if (ret < 0) > - return ret; > + ret = kvm_vcpu_ioctl(env, KVM_GET_REGS_MODERN, ®s); > + if (ret < 0) > + return ret; Braces. > > /* We make sure the banked regs are properly set */ > mode = env->uncached_cpsr & CPSR_M; > @@ -91,8 +104,18 @@ int kvm_arch_put_registers(CPUARMState *env, int level) > regs.cp15.c0_midr = env->cp15.c0_cpuid; > regs.cp15.c1_sys = env->cp15.c1_sys; > > - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); > + cp15.hdr.nmsrs = ARRAY_SIZE(cp15.e); > + cp15.e[0].index = MSR32_INDEX_OF(15, 0, 0, 0, 0); /* MIDR */ > + cp15.e[0].data = env->cp15.c0_cpuid; > + cp15.e[1].index = MSR32_INDEX_OF(15, 1, 0, 0, 0); /* SCTLR */ > + cp15.e[1].data = env->cp15.c1_sys; > > + ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); > + if (ret < 0) { > + ret = kvm_vcpu_ioctl(env, KVM_SET_REGS_MODERN, ®s); > + if (ret == 0) > + ret = kvm_vcpu_ioctl(env, KVM_SET_MSRS, &cp15); Again. Please use checkpatch.pl to avoid these issues. > + } > return ret; > } > > @@ -101,11 +124,27 @@ int kvm_arch_get_registers(CPUARMState *env) > struct kvm_regs regs; > int mode, bn; > int32_t ret; > + struct cp15 { > + struct kvm_msrs hdr; > + struct kvm_msr_entry e[6]; > + } cp15; > > ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); > if (ret < 0) > + ret = kvm_vcpu_ioctl(env, KVM_GET_REGS_MODERN, ®s); > + if (ret < 0) Ditto. > return ret; > > + cp15.hdr.nmsrs = ARRAY_SIZE(cp15.e); > + cp15.e[0].index = MSR32_INDEX_OF(15, 0, 0, 0, 0); /* MIDR */ > + cp15.e[1].index = MSR32_INDEX_OF(15, 1, 0, 0, 0); /* SCTLR */ > + cp15.e[2].index = MSR32_INDEX_OF(15, 2, 0, 0, 0); /* TTBR0 */ > + cp15.e[3].index = MSR32_INDEX_OF(15, 2, 0, 0, 1); /* TTBR1 */ > + cp15.e[4].index = MSR32_INDEX_OF(15, 2, 0, 0, 2); /* TTBCR */ > + cp15.e[5].index = MSR32_INDEX_OF(15, 3, 0, 0, 0); /* DACR */ > + > + ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &cp15); > + > /* First, let's transfer the banked state */ > cpsr_write(env, regs.cpsr, 0xFFFFFFFF); > memcpy(env->regs, regs.regs0_7, sizeof(uint32_t) * 8); > @@ -142,18 +181,33 @@ int kvm_arch_get_registers(CPUARMState *env) > env->regs[14] = env->banked_r14[bn]; > env->spsr = env->banked_spsr[bn]; > > - //env->cp15.c0_cpuid = regs.cp15.c0_midr; > - env->cp15.c1_sys = regs.cp15.c1_sys; > - env->cp15.c2_base0 = regs.cp15.c2_base0; > - env->cp15.c2_base1 = regs.cp15.c2_base1; > + /* Old KVM version. */ > + if (ret != 0) { > + //env->cp15.c0_cpuid = regs.cp15.c0_midr; I see that this is code movement, but please change the C99 comment to C89. > + env->cp15.c1_sys = regs.cp15.c1_sys; > + env->cp15.c2_base0 = regs.cp15.c2_base0; > + env->cp15.c2_base1 = regs.cp15.c2_base1; > > - /* This is ugly, but necessary for GDB compatibility */ > - env->cp15.c2_control = regs.cp15.c2_control; > - env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> regs.cp15.c2_control); > - env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> regs.cp15.c2_control); > + /* This is ugly, but necessary for GDB compatibility */ > + env->cp15.c2_control = regs.cp15.c2_control; > + env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> regs.cp15.c2_control); > + env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> regs.cp15.c2_control); > > - env->cp15.c3 = regs.cp15.c3_dacr; > + env->cp15.c3 = regs.cp15.c3_dacr; > + return 0; > + } > + > + //env->cp15.c0_cpuid = cp15.e[0].data; Ditto. > + env->cp15.c1_sys = cp15.e[1].data; > + env->cp15.c2_base0 = cp15.e[2].data; > + env->cp15.c2_base1 = cp15.e[3].data; > + > + /* This is ugly, but necessary for GDB compatibility */ > + env->cp15.c2_control = cp15.e[4].data; > + env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> cp15.e[4].data); > + env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> cp15.e[4].data); > > + env->cp15.c3 = cp15.e[5].data; > return 0; > } > >