[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 13/14] xen: arm: handle 64-bit system register access traps.



On Tue, 12 Mar 2013, Ian Campbell wrote:
> From: Ian Campbell <ian.campbell@xxxxxxxxxx>
> 
> Wire up the vtimer handling to it.
> 
> Use a simplified version of the 32-bit cp-register macros to have convenient
> decoding of HSR register values. (simplified because we don't need them for
> passing to the assembler on 64-bit)
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>


Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

assuming that you didn't make any mistakes in writing down thw new
SYSREG #define


>  xen/arch/arm/traps.c            |   39 +++++++++++++
>  xen/arch/arm/vtimer.c           |  119 
> ++++++++++++++++++++++++++-------------
>  xen/include/asm-arm/processor.h |   32 +++++++++++
>  xen/include/asm-arm/sysregs.h   |   56 ++++++++++++++++++
>  4 files changed, 208 insertions(+), 38 deletions(-)
>  create mode 100644 xen/include/asm-arm/sysregs.h
> 
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 190d1e8..67d9072 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -973,6 +973,39 @@ static void do_cp15_64(struct cpu_user_regs *regs,
>  
>  }
>  
> +#ifdef CONFIG_ARM_64
> +static void do_sysreg(struct cpu_user_regs *regs,
> +                      union hsr hsr)
> +{
> +    struct hsr_sysreg sysreg = hsr.sysreg;
> +
> +    switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
> +    {
> +    case CNTP_CTL_EL0:
> +    case CNTP_TVAL_EL0:
> +        if ( !vtimer_emulate(regs, hsr) )
> +        {
> +            dprintk(XENLOG_ERR,
> +                    "failed emulation of 64-bit vtimer sysreg access\n");
> +            domain_crash_synchronous();
> +        }
> +        break;
> +    default:
> +        printk("%s %d, %d, c%d, c%d, %d %s x%d @ 0x%"PRIregister"\n",
> +               sysreg.read ? "mrs" : "msr",
> +               sysreg.op0, sysreg.op1,
> +               sysreg.crn, sysreg.crm,
> +               sysreg.op2,
> +               sysreg.read ? "=>" : "<=",
> +               sysreg.reg, regs->pc);
> +        panic("unhandled 64-bit sysreg access %#x\n",
> +              hsr.bits & HSR_SYSREG_REGS_MASK);
> +    }
> +
> +    regs->pc += 4;
> +}
> +#endif
> +
>  void dump_guest_s1_walk(struct domain *d, vaddr_t addr)
>  {
>      uint32_t ttbcr = READ_SYSREG32(TCR_EL1);
> @@ -1114,7 +1147,13 @@ asmlinkage void do_trap_hypervisor(struct 
> cpu_user_regs *regs)
>  #endif
>          do_trap_hypercall(regs, &regs->x16, hsr.iss);
>          break;
> +    case HSR_EC_SYSREG:
> +        if ( is_pv32_domain(current->domain) )
> +            goto bad_trap;
> +        do_sysreg(regs, hsr);
> +        break;
>  #endif
> +
>      case HSR_EC_DATA_ABORT_GUEST:
>          do_trap_data_abort_guest(regs, hsr.dabt);
>          break;
> diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
> index a68f662..f9fc045 100644
> --- a/xen/arch/arm/vtimer.c
> +++ b/xen/arch/arm/vtimer.c
> @@ -102,51 +102,62 @@ int virt_timer_restore(struct vcpu *v)
>      return 0;
>  }
>  
> -static int vtimer_emulate_32(struct cpu_user_regs *regs, union hsr hsr)
> +static void vtimer_cntp_ctl(struct cpu_user_regs *regs, uint32_t *r, int 
> read)
>  {
>      struct vcpu *v = current;
> -    struct hsr_cp32 cp32 = hsr.cp32;
> -    uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg);
> -    s_time_t now;
> -
> -    switch ( hsr.bits & HSR_CP32_REGS_MASK )
> +    if ( read )
>      {
> -    case HSR_CPREG32(CNTP_CTL):
> -        if ( cp32.read )
> +        *r = v->arch.phys_timer.ctl;
> +    }
> +    else
> +    {
> +        v->arch.phys_timer.ctl = *r;
> +
> +        if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
>          {
> -            *r = v->arch.phys_timer.ctl;
> +            set_timer(&v->arch.phys_timer.timer,
> +                      v->arch.phys_timer.cval + v->arch.phys_timer.offset);
>          }
>          else
> +            stop_timer(&v->arch.phys_timer.timer);
> +    }
> +}
> +
> +static void vtimer_cntp_tval(struct cpu_user_regs *regs, uint32_t *r, int 
> read)
> +{
> +    struct vcpu *v = current;
> +    s_time_t now;
> +
> +    now = NOW() - v->arch.phys_timer.offset;
> +
> +    if ( read )
> +    {
> +        *r = (uint32_t)(ns_to_ticks(v->arch.phys_timer.cval - now) & 
> 0xffffffffull);
> +    }
> +    else
> +    {
> +        v->arch.phys_timer.cval = now + ticks_to_ns(*r);
> +        if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
>          {
> -            v->arch.phys_timer.ctl = *r;
> -
> -            if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
> -            {
> -                set_timer(&v->arch.phys_timer.timer,
> -                          v->arch.phys_timer.cval + 
> v->arch.phys_timer.offset);
> -            }
> -            else
> -                stop_timer(&v->arch.phys_timer.timer);
> +            set_timer(&v->arch.phys_timer.timer,
> +                      v->arch.phys_timer.cval + v->arch.phys_timer.offset);
>          }
> +    }
> +}
>  
> +static int vtimer_emulate_cp32(struct cpu_user_regs *regs, union hsr hsr)
> +{
> +    struct hsr_cp32 cp32 = hsr.cp32;
> +    uint32_t *r = (uint32_t *)select_user_reg(regs, cp32.reg);
> +
> +    switch ( hsr.bits & HSR_CP32_REGS_MASK )
> +    {
> +    case HSR_CPREG32(CNTP_CTL):
> +        vtimer_cntp_ctl(regs, r, cp32.read);
>          return 1;
>  
>      case HSR_CPREG32(CNTP_TVAL):
> -        now = NOW() - v->arch.phys_timer.offset;
> -        if ( cp32.read )
> -        {
> -            *r = (uint32_t)(ns_to_ticks(v->arch.phys_timer.cval - now) & 
> 0xffffffffull);
> -        }
> -        else
> -        {
> -            v->arch.phys_timer.cval = now + ticks_to_ns(*r);
> -            if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
> -            {
> -                set_timer(&v->arch.phys_timer.timer,
> -                          v->arch.phys_timer.cval + 
> v->arch.phys_timer.offset);
> -            }
> -        }
> -
> +        vtimer_cntp_tval(regs, r, cp32.read);
>          return 1;
>  
>      default:
> @@ -154,7 +165,7 @@ static int vtimer_emulate_32(struct cpu_user_regs *regs, 
> union hsr hsr)
>      }
>  }
>  
> -static int vtimer_emulate_64(struct cpu_user_regs *regs, union hsr hsr)
> +static int vtimer_emulate_cp64(struct cpu_user_regs *regs, union hsr hsr)
>  {
>      struct vcpu *v = current;
>      struct hsr_cp64 cp64 = hsr.cp64;
> @@ -185,16 +196,48 @@ static int vtimer_emulate_64(struct cpu_user_regs 
> *regs, union hsr hsr)
>      }
>  }
>  
> +#ifdef CONFIG_ARM_64
> +static int vtimer_emulate_sysreg(struct cpu_user_regs *regs, union hsr hsr)
> +{
> +    struct hsr_sysreg sysreg = hsr.sysreg;
> +    register_t *x = select_user_reg(regs, sysreg.reg);
> +    uint32_t r = (uint32_t)*x;
> +
> +    switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
> +    {
> +    case CNTP_CTL_EL0:
> +        vtimer_cntp_ctl(regs, &r, sysreg.read);
> +        *x = r;
> +        return 1;
> +    case CNTP_TVAL_EL0:
> +        vtimer_cntp_tval(regs, &r, sysreg.read);
> +        *x = r;
> +        return 1;
> +    default:
> +        return 0;
> +    }
> +
> +}
> +#endif
> +
>  int vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr)
>  {
> -    if ( !is_pv32_domain(current->domain) )
> -        return -EINVAL;
>  
>      switch (hsr.ec) {
>      case HSR_EC_CP15_32:
> -        return vtimer_emulate_32(regs, hsr);
> +        if ( !is_pv32_domain(current->domain) )
> +            return 0;
> +        return vtimer_emulate_cp32(regs, hsr);
>      case HSR_EC_CP15_64:
> -        return vtimer_emulate_64(regs, hsr);
> +        if ( !is_pv32_domain(current->domain) )
> +            return 0;
> +        return vtimer_emulate_cp64(regs, hsr);
> +#ifdef CONFIG_ARM_64
> +    case HSR_EC_SYSREG:
> +        if ( is_pv32_domain(current->domain) )
> +            return 0;
> +        return vtimer_emulate_sysreg(regs, hsr);
> +#endif
>      default:
>          return 0;
>      }
> diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
> index 17f5465..d75530d 100644
> --- a/xen/include/asm-arm/processor.h
> +++ b/xen/include/asm-arm/processor.h
> @@ -2,6 +2,7 @@
>  #define __ASM_ARM_PROCESSOR_H
>  
>  #include <asm/cpregs.h>
> +#include <asm/sysregs.h>
>  
>  /* MIDR Main ID Register */
>  #define MIDR_MASK    0xff0ffff0
> @@ -90,6 +91,7 @@
>  #define HSR_EC_HVC32                0x12
>  #ifdef CONFIG_ARM_64
>  #define HSR_EC_HVC64                0x16
> +#define HSR_EC_SYSREG               0x18
>  #endif
>  #define HSR_EC_INSTR_ABORT_GUEST    0x20
>  #define HSR_EC_INSTR_ABORT_HYP      0x21
> @@ -249,6 +251,21 @@ union hsr {
>          unsigned long ec:6;    /* Exception Class */
>      } cp64; /* HSR_EC_CP15_64, HSR_EC_CP14_64 */
>  
> +#ifdef CONFIG_ARM_64
> +    struct hsr_sysreg {
> +        unsigned long read:1;   /* Direction */
> +        unsigned long crm:4;    /* CRm */
> +        unsigned long reg:5;    /* Rt */
> +        unsigned long crn:4;    /* CRn */
> +        unsigned long op1:3;    /* Op1 */
> +        unsigned long op2:3;    /* Op2 */
> +        unsigned long op0:2;    /* Op0 */
> +        unsigned long res0:3;
> +        unsigned long len:1;    /* Instruction length */
> +        unsigned long ec:6;
> +    } sysreg; /* HSR_EC_SYSREG */
> +#endif
> +
>      struct hsr_dabt {
>          unsigned long dfsc:6;  /* Data Fault Status Code */
>          unsigned long write:1; /* Write / not Read */
> @@ -291,6 +308,21 @@ union hsr {
>  #define HSR_CP64_CRM_SHIFT (1)
>  #define HSR_CP64_REGS_MASK (HSR_CP64_OP1_MASK|HSR_CP64_CRM_MASK)
>  
> +/* HSR.EC == HSR_SYSREG */
> +#define HSR_SYSREG_OP0_MASK (0x00300000)
> +#define HSR_SYSREG_OP0_SHIFT (20)
> +#define HSR_SYSREG_OP1_MASK (0x0001c000)
> +#define HSR_SYSREG_OP1_SHIFT (14)
> +#define HSR_SYSREG_CRN_MASK (0x00003800)
> +#define HSR_SYSREG_CRN_SHIFT (10)
> +#define HSR_SYSREG_CRM_MASK (0x0000001e)
> +#define HSR_SYSREG_CRM_SHIFT (1)
> +#define HSR_SYSREG_OP2_MASK (0x000e0000)
> +#define HSR_SYSREG_OP2_SHIFT (17)
> +#define HSR_SYSREG_REGS_MASK (HSR_SYSREG_OP0_MASK|HSR_SYSREG_OP1_MASK|\
> +                              HSR_SYSREG_CRN_MASK|HSR_SYSREG_CRM_MASK|\
> +                              HSR_SYSREG_OP2_MASK)
> +
>  /* Physical Address Register */
>  #define PAR_F           (1<<0)
>  
> diff --git a/xen/include/asm-arm/sysregs.h b/xen/include/asm-arm/sysregs.h
> new file mode 100644
> index 0000000..9c64777
> --- /dev/null
> +++ b/xen/include/asm-arm/sysregs.h
> @@ -0,0 +1,56 @@
> +#ifndef __ASM_ARM_SYSREGS_H
> +#define __ASM_ARM_SYSREGS_H
> +
> +#ifdef CONFIG_ARM_64
> +
> +#include <xen/stringify.h>
> +
> +/* AArch 64 System Register Encodings */
> +#define __HSR_SYSREG_c0  0
> +#define __HSR_SYSREG_c1  1
> +#define __HSR_SYSREG_c2  2
> +#define __HSR_SYSREG_c3  3
> +#define __HSR_SYSREG_c4  4
> +#define __HSR_SYSREG_c5  5
> +#define __HSR_SYSREG_c6  6
> +#define __HSR_SYSREG_c7  7
> +#define __HSR_SYSREG_c8  8
> +#define __HSR_SYSREG_c9  9
> +#define __HSR_SYSREG_c10 10
> +#define __HSR_SYSREG_c11 11
> +#define __HSR_SYSREG_c12 12
> +#define __HSR_SYSREG_c13 13
> +#define __HSR_SYSREG_c14 14
> +#define __HSR_SYSREG_c15 15
> +
> +#define __HSR_SYSREG_0   0
> +#define __HSR_SYSREG_1   1
> +#define __HSR_SYSREG_2   2
> +#define __HSR_SYSREG_3   3
> +#define __HSR_SYSREG_4   4
> +#define __HSR_SYSREG_5   5
> +#define __HSR_SYSREG_6   6
> +#define __HSR_SYSREG_7   7
> +
> +/* These are used to decode traps with HSR.EC==HSR_EC_SYSREG */
> +#define HSR_SYSREG(op0,op1,crn,crm,op2) \
> +    ((__HSR_SYSREG_##op0) << HSR_SYSREG_OP0_SHIFT) | \
> +    ((__HSR_SYSREG_##op1) << HSR_SYSREG_OP1_SHIFT) | \
> +    ((__HSR_SYSREG_##crn) << HSR_SYSREG_CRN_SHIFT) | \
> +    ((__HSR_SYSREG_##crm) << HSR_SYSREG_CRM_SHIFT) | \
> +    ((__HSR_SYSREG_##op2) << HSR_SYSREG_OP2_SHIFT)
> +
> +#define CNTP_CTL_EL0  HSR_SYSREG(3,3,c14,c2,1)
> +#define CNTP_TVAL_EL0 HSR_SYSREG(3,3,c14,c2,0)
> +#endif
> +
> +#endif
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-set-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> -- 
> 1.7.10.4
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.