Re: [PATCH v3 26/32] arm64: KVM: 32bit handling of coprocessor traps

2013-04-23 Thread Christoffer Dall
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

2013-04-24 Thread Marc Zyngier
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

2013-04-24 Thread Christoffer Dall
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)