Re: [PATCH v3 26/32] arm64: KVM: 32bit handling of coprocessor traps
On Mon, Apr 08, 2013 at 05:17:28PM +0100, Marc Zyngier wrote: > Provide the necessary infrastructure to trap coprocessor accesses that > occur when running 32bit guests. > > Also wire SMC and HVC trapped in 32bit mode while were at it. > > Reviewed-by: Christopher Covington > Signed-off-by: Marc Zyngier > --- > arch/arm64/include/asm/kvm_coproc.h | 5 + > arch/arm64/kvm/handle_exit.c| 7 ++ > arch/arm64/kvm/sys_regs.c | 178 > ++-- > 3 files changed, 183 insertions(+), 7 deletions(-) > > diff --git a/arch/arm64/include/asm/kvm_coproc.h > b/arch/arm64/include/asm/kvm_coproc.h > index 9b4477a..9a59301 100644 > --- a/arch/arm64/include/asm/kvm_coproc.h > +++ b/arch/arm64/include/asm/kvm_coproc.h > @@ -32,11 +32,16 @@ struct kvm_sys_reg_table { > > struct kvm_sys_reg_target_table { > struct kvm_sys_reg_table table64; > + struct kvm_sys_reg_table table32; > }; > > void kvm_register_target_sys_reg_table(unsigned int target, > struct kvm_sys_reg_target_table *table); > > +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); > +int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); > +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); > +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); > int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run); > > #define kvm_coproc_table_init kvm_sys_reg_table_init > diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c > index 4766b7f..9beaca03 100644 > --- a/arch/arm64/kvm/handle_exit.c > +++ b/arch/arm64/kvm/handle_exit.c > @@ -62,6 +62,13 @@ static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct > kvm_run *run) > > static exit_handle_fn arm_exit_handlers[] = { > [ESR_EL2_EC_WFI]= kvm_handle_wfi, > + [ESR_EL2_EC_CP15_32]= kvm_handle_cp15_32, > + [ESR_EL2_EC_CP15_64]= kvm_handle_cp15_64, > + [ESR_EL2_EC_CP14_MR]= kvm_handle_cp14_access, > + [ESR_EL2_EC_CP14_LS]= kvm_handle_cp14_load_store, > + [ESR_EL2_EC_CP14_64]= kvm_handle_cp14_access, > + [ESR_EL2_EC_HVC32] = handle_hvc, > + [ESR_EL2_EC_SMC32] = handle_smc, > [ESR_EL2_EC_HVC64] = handle_hvc, > [ESR_EL2_EC_SMC64] = handle_smc, > [ESR_EL2_EC_SYS64] = kvm_handle_sys_reg, > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c > index 9df3b32..0303218 100644 > --- a/arch/arm64/kvm/sys_regs.c > +++ b/arch/arm64/kvm/sys_regs.c > @@ -38,6 +38,10 @@ > * types are different. My gut feeling is that it should be pretty > * easy to merge, but that would be an ABI breakage -- again. VFP > * would also need to be abstracted. > + * > + * For AArch32, we only take care of what is being trapped. Anything > + * that has to do with init and userspace access has to go via the > + * 64bit interface. > */ > > /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */ > @@ -163,6 +167,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { > { Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010), > access_dcsw }, > > + /* TEECR32_EL1 */ > + { Op0(0b10), Op1(0b010), CRn(0b), CRm(0b), Op2(0b000), > + NULL, reset_val, TEECR32_EL1, 0 }, > + /* TEEHBR32_EL1 */ > + { Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b), Op2(0b000), > + NULL, reset_val, TEEHBR32_EL1, 0 }, > + /* DBGVCR32_EL2 */ > + { Op0(0b10), Op1(0b100), CRn(0b), CRm(0b0111), Op2(0b000), > + NULL, reset_val, DBGVCR32_EL2, 0 }, > + > /* MPIDR_EL1 */ > { Op0(0b11), Op1(0b000), CRn(0b), CRm(0b), Op2(0b101), > NULL, reset_mpidr, MPIDR_EL1 }, > @@ -273,6 +287,39 @@ static const struct sys_reg_desc sys_reg_descs[] = { > /* TPIDRRO_EL0 */ > { Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b), Op2(0b011), > NULL, reset_unknown, TPIDRRO_EL0 }, > + > + /* DACR32_EL2 */ > + { Op0(0b11), Op1(0b100), CRn(0b0011), CRm(0b), Op2(0b000), > + NULL, reset_unknown, DACR32_EL2 }, > + /* IFSR32_EL2 */ > + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b), Op2(0b001), > + NULL, reset_unknown, IFSR32_EL2 }, > + /* FPEXC32_EL2 */ > + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b0011), Op2(0b000), > + NULL, reset_val, FPEXC32_EL2, 0x70 }, > +}; > + > +/* Trapped cp15 registers */ > +static const struct sys_reg_desc cp15_regs[] = { > + /* > + * DC{C,I,CI}SW operations: > + */ > + { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw }, > + { Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw }, > + { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw }, > + { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake }, > + { Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake }, > + { Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake }, > + { Op1( 0), CRn( 9), CRm(12), Op
Re: [PATCH v3 26/32] arm64: KVM: 32bit handling of coprocessor traps
On 24/04/13 00:01, Christoffer Dall wrote: > On Mon, Apr 08, 2013 at 05:17:28PM +0100, Marc Zyngier wrote: >> Provide the necessary infrastructure to trap coprocessor accesses that >> occur when running 32bit guests. >> >> Also wire SMC and HVC trapped in 32bit mode while were at it. >> >> Reviewed-by: Christopher Covington >> Signed-off-by: Marc Zyngier >> --- >> arch/arm64/include/asm/kvm_coproc.h | 5 + >> arch/arm64/kvm/handle_exit.c| 7 ++ >> arch/arm64/kvm/sys_regs.c | 178 >> ++-- >> 3 files changed, 183 insertions(+), 7 deletions(-) >> >> diff --git a/arch/arm64/include/asm/kvm_coproc.h >> b/arch/arm64/include/asm/kvm_coproc.h >> index 9b4477a..9a59301 100644 >> --- a/arch/arm64/include/asm/kvm_coproc.h >> +++ b/arch/arm64/include/asm/kvm_coproc.h >> @@ -32,11 +32,16 @@ struct kvm_sys_reg_table { >> >> struct kvm_sys_reg_target_table { >> struct kvm_sys_reg_table table64; >> + struct kvm_sys_reg_table table32; >> }; >> >> void kvm_register_target_sys_reg_table(unsigned int target, >> struct kvm_sys_reg_target_table *table); >> >> +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); >> +int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); >> +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); >> +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); >> int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run); >> >> #define kvm_coproc_table_init kvm_sys_reg_table_init >> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c >> index 4766b7f..9beaca03 100644 >> --- a/arch/arm64/kvm/handle_exit.c >> +++ b/arch/arm64/kvm/handle_exit.c >> @@ -62,6 +62,13 @@ static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct >> kvm_run *run) >> >> static exit_handle_fn arm_exit_handlers[] = { >> [ESR_EL2_EC_WFI]= kvm_handle_wfi, >> + [ESR_EL2_EC_CP15_32]= kvm_handle_cp15_32, >> + [ESR_EL2_EC_CP15_64]= kvm_handle_cp15_64, >> + [ESR_EL2_EC_CP14_MR]= kvm_handle_cp14_access, >> + [ESR_EL2_EC_CP14_LS]= kvm_handle_cp14_load_store, >> + [ESR_EL2_EC_CP14_64]= kvm_handle_cp14_access, >> + [ESR_EL2_EC_HVC32] = handle_hvc, >> + [ESR_EL2_EC_SMC32] = handle_smc, >> [ESR_EL2_EC_HVC64] = handle_hvc, >> [ESR_EL2_EC_SMC64] = handle_smc, >> [ESR_EL2_EC_SYS64] = kvm_handle_sys_reg, >> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c >> index 9df3b32..0303218 100644 >> --- a/arch/arm64/kvm/sys_regs.c >> +++ b/arch/arm64/kvm/sys_regs.c >> @@ -38,6 +38,10 @@ >> * types are different. My gut feeling is that it should be pretty >> * easy to merge, but that would be an ABI breakage -- again. VFP >> * would also need to be abstracted. >> + * >> + * For AArch32, we only take care of what is being trapped. Anything >> + * that has to do with init and userspace access has to go via the >> + * 64bit interface. >> */ >> >> /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */ >> @@ -163,6 +167,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { >> { Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010), >> access_dcsw }, >> >> + /* TEECR32_EL1 */ >> + { Op0(0b10), Op1(0b010), CRn(0b), CRm(0b), Op2(0b000), >> + NULL, reset_val, TEECR32_EL1, 0 }, >> + /* TEEHBR32_EL1 */ >> + { Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b), Op2(0b000), >> + NULL, reset_val, TEEHBR32_EL1, 0 }, >> + /* DBGVCR32_EL2 */ >> + { Op0(0b10), Op1(0b100), CRn(0b), CRm(0b0111), Op2(0b000), >> + NULL, reset_val, DBGVCR32_EL2, 0 }, >> + >> /* MPIDR_EL1 */ >> { Op0(0b11), Op1(0b000), CRn(0b), CRm(0b), Op2(0b101), >> NULL, reset_mpidr, MPIDR_EL1 }, >> @@ -273,6 +287,39 @@ static const struct sys_reg_desc sys_reg_descs[] = { >> /* TPIDRRO_EL0 */ >> { Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b), Op2(0b011), >> NULL, reset_unknown, TPIDRRO_EL0 }, >> + >> + /* DACR32_EL2 */ >> + { Op0(0b11), Op1(0b100), CRn(0b0011), CRm(0b), Op2(0b000), >> + NULL, reset_unknown, DACR32_EL2 }, >> + /* IFSR32_EL2 */ >> + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b), Op2(0b001), >> + NULL, reset_unknown, IFSR32_EL2 }, >> + /* FPEXC32_EL2 */ >> + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b0011), Op2(0b000), >> + NULL, reset_val, FPEXC32_EL2, 0x70 }, >> +}; >> + >> +/* Trapped cp15 registers */ >> +static const struct sys_reg_desc cp15_regs[] = { >> + /* >> + * DC{C,I,CI}SW operations: >> + */ >> + { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw }, >> + { Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw }, >> + { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw }, >> + { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake }, >> + { Op
Re: [PATCH v3 26/32] arm64: KVM: 32bit handling of coprocessor traps
On Wed, Apr 24, 2013 at 6:42 AM, Marc Zyngier wrote: > On 24/04/13 00:01, Christoffer Dall wrote: >> On Mon, Apr 08, 2013 at 05:17:28PM +0100, Marc Zyngier wrote: >>> Provide the necessary infrastructure to trap coprocessor accesses that >>> occur when running 32bit guests. >>> >>> Also wire SMC and HVC trapped in 32bit mode while were at it. >>> >>> Reviewed-by: Christopher Covington >>> Signed-off-by: Marc Zyngier >>> --- >>> arch/arm64/include/asm/kvm_coproc.h | 5 + >>> arch/arm64/kvm/handle_exit.c| 7 ++ >>> arch/arm64/kvm/sys_regs.c | 178 >>> ++-- >>> 3 files changed, 183 insertions(+), 7 deletions(-) >>> >>> diff --git a/arch/arm64/include/asm/kvm_coproc.h >>> b/arch/arm64/include/asm/kvm_coproc.h >>> index 9b4477a..9a59301 100644 >>> --- a/arch/arm64/include/asm/kvm_coproc.h >>> +++ b/arch/arm64/include/asm/kvm_coproc.h >>> @@ -32,11 +32,16 @@ struct kvm_sys_reg_table { >>> >>> struct kvm_sys_reg_target_table { >>> struct kvm_sys_reg_table table64; >>> + struct kvm_sys_reg_table table32; >>> }; >>> >>> void kvm_register_target_sys_reg_table(unsigned int target, >>> struct kvm_sys_reg_target_table >>> *table); >>> >>> +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); >>> +int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); >>> +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); >>> +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); >>> int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run); >>> >>> #define kvm_coproc_table_init kvm_sys_reg_table_init >>> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c >>> index 4766b7f..9beaca03 100644 >>> --- a/arch/arm64/kvm/handle_exit.c >>> +++ b/arch/arm64/kvm/handle_exit.c >>> @@ -62,6 +62,13 @@ static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct >>> kvm_run *run) >>> >>> static exit_handle_fn arm_exit_handlers[] = { >>> [ESR_EL2_EC_WFI]= kvm_handle_wfi, >>> + [ESR_EL2_EC_CP15_32]= kvm_handle_cp15_32, >>> + [ESR_EL2_EC_CP15_64]= kvm_handle_cp15_64, >>> + [ESR_EL2_EC_CP14_MR]= kvm_handle_cp14_access, >>> + [ESR_EL2_EC_CP14_LS]= kvm_handle_cp14_load_store, >>> + [ESR_EL2_EC_CP14_64]= kvm_handle_cp14_access, >>> + [ESR_EL2_EC_HVC32] = handle_hvc, >>> + [ESR_EL2_EC_SMC32] = handle_smc, >>> [ESR_EL2_EC_HVC64] = handle_hvc, >>> [ESR_EL2_EC_SMC64] = handle_smc, >>> [ESR_EL2_EC_SYS64] = kvm_handle_sys_reg, >>> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c >>> index 9df3b32..0303218 100644 >>> --- a/arch/arm64/kvm/sys_regs.c >>> +++ b/arch/arm64/kvm/sys_regs.c >>> @@ -38,6 +38,10 @@ >>> * types are different. My gut feeling is that it should be pretty >>> * easy to merge, but that would be an ABI breakage -- again. VFP >>> * would also need to be abstracted. >>> + * >>> + * For AArch32, we only take care of what is being trapped. Anything >>> + * that has to do with init and userspace access has to go via the >>> + * 64bit interface. >>> */ >>> >>> /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 >>> */ >>> @@ -163,6 +167,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { >>> { Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010), >>> access_dcsw }, >>> >>> + /* TEECR32_EL1 */ >>> + { Op0(0b10), Op1(0b010), CRn(0b), CRm(0b), Op2(0b000), >>> + NULL, reset_val, TEECR32_EL1, 0 }, >>> + /* TEEHBR32_EL1 */ >>> + { Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b), Op2(0b000), >>> + NULL, reset_val, TEEHBR32_EL1, 0 }, >>> + /* DBGVCR32_EL2 */ >>> + { Op0(0b10), Op1(0b100), CRn(0b), CRm(0b0111), Op2(0b000), >>> + NULL, reset_val, DBGVCR32_EL2, 0 }, >>> + >>> /* MPIDR_EL1 */ >>> { Op0(0b11), Op1(0b000), CRn(0b), CRm(0b), Op2(0b101), >>> NULL, reset_mpidr, MPIDR_EL1 }, >>> @@ -273,6 +287,39 @@ static const struct sys_reg_desc sys_reg_descs[] = { >>> /* TPIDRRO_EL0 */ >>> { Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b), Op2(0b011), >>> NULL, reset_unknown, TPIDRRO_EL0 }, >>> + >>> + /* DACR32_EL2 */ >>> + { Op0(0b11), Op1(0b100), CRn(0b0011), CRm(0b), Op2(0b000), >>> + NULL, reset_unknown, DACR32_EL2 }, >>> + /* IFSR32_EL2 */ >>> + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b), Op2(0b001), >>> + NULL, reset_unknown, IFSR32_EL2 }, >>> + /* FPEXC32_EL2 */ >>> + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b0011), Op2(0b000), >>> + NULL, reset_val, FPEXC32_EL2, 0x70 }, >>> +}; >>> + >>> +/* Trapped cp15 registers */ >>> +static const struct sys_reg_desc cp15_regs[] = { >>> + /* >>> + * DC{C,I,CI}SW operations: >>> + */ >>> + { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw }, >>> + { Op1( 0)