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

Re: [Xen-devel] [PATCH 12/14] xen: arm: handle hypercalls from 64-bit guests



On Tue, 12 Mar 2013, Ian Campbell wrote:
> From: Ian Campbell <ian.campbell@xxxxxxxxxx>
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>

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


>  xen/arch/arm/traps.c            |   67 
> ++++++++++++++++++++++++++++-----------
>  xen/include/asm-arm/processor.h |    7 ++--
>  2 files changed, 54 insertions(+), 20 deletions(-)
> 
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index f1dd557..190d1e8 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -726,8 +726,8 @@ unsigned long do_arch_0(unsigned int cmd, unsigned long 
> long value)
>          return 0;
>  }
>  
> -typedef unsigned long (*arm_hypercall_fn_t)(
> -    unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
> +typedef register_t (*arm_hypercall_fn_t)(
> +    register_t, register_t, register_t, register_t, register_t);
>  
>  typedef struct {
>      arm_hypercall_fn_t fn;
> @@ -783,30 +783,49 @@ static void do_debug_trap(struct cpu_user_regs *regs, 
> unsigned int code)
>      }
>  }
>  
> -static void do_trap_hypercall(struct cpu_user_regs *regs, unsigned long iss)
> +#ifdef CONFIG_ARM_64
> +#define HYPERCALL_RESULT_REG(r) (r)->x0
> +#define HYPERCALL_ARG1(r) (r)->x0
> +#define HYPERCALL_ARG2(r) (r)->x1
> +#define HYPERCALL_ARG3(r) (r)->x2
> +#define HYPERCALL_ARG4(r) (r)->x3
> +#define HYPERCALL_ARG5(r) (r)->x4
> +#define HYPERCALL_ARGS(r) (r)->x0, (r)->x1, (r)->x2, (r)->x3, (r)->x4
> +#else
> +#define HYPERCALL_RESULT_REG(r) (r)->r0
> +#define HYPERCALL_ARG1(r) (r)->r0
> +#define HYPERCALL_ARG2(r) (r)->r1
> +#define HYPERCALL_ARG3(r) (r)->r2
> +#define HYPERCALL_ARG4(r) (r)->r3
> +#define HYPERCALL_ARG5(r) (r)->r4
> +#define HYPERCALL_ARGS(r) (r)->r0, (r)->r1, (r)->r2, (r)->r3, (r)->r4
> +#endif
> +
> +static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
> +                              unsigned long iss)
>  {
>      arm_hypercall_fn_t call = NULL;
>  #ifndef NDEBUG
> -    uint32_t orig_pc = regs->pc;
> +    register_t orig_pc = regs->pc;
>  #endif
>  
>      if ( iss != XEN_HYPERCALL_TAG )
>          domain_crash_synchronous();
>  
> -    if ( regs->r12 >= ARRAY_SIZE(arm_hypercall_table) )
> +    if ( *nr >= ARRAY_SIZE(arm_hypercall_table) )
>      {
> -        regs->r0 = -ENOSYS;
> +        HYPERCALL_RESULT_REG(regs) = -ENOSYS;
>          return;
>      }
>  
> -    call = arm_hypercall_table[regs->r12].fn;
> +    call = arm_hypercall_table[*nr].fn;
>      if ( call == NULL )
>      {
> -        regs->r0 = -ENOSYS;
> +        HYPERCALL_RESULT_REG(regs) = -ENOSYS;
>          return;
>      }
>  
> -    regs->r0 = call(regs->r0, regs->r1, regs->r2, regs->r3, regs->r4);
> +    HYPERCALL_RESULT_REG(regs) = call(HYPERCALL_ARGS(regs));
>  
>  #ifndef NDEBUG
>      /*
> @@ -815,16 +834,16 @@ static void do_trap_hypercall(struct cpu_user_regs 
> *regs, unsigned long iss)
>       */
>      if ( orig_pc == regs->pc )
>      {
> -        switch ( arm_hypercall_table[regs->r12].nr_args ) {
> -        case 5: regs->r4 = 0xDEADBEEF;
> -        case 4: regs->r3 = 0xDEADBEEF;
> -        case 3: regs->r2 = 0xDEADBEEF;
> -        case 2: regs->r1 = 0xDEADBEEF;
> -        case 1: /* Don't clobber r0 -- it's the return value */
> +        switch ( arm_hypercall_table[*nr].nr_args ) {
> +        case 5: HYPERCALL_ARG5(regs) = 0xDEADBEEF;
> +        case 4: HYPERCALL_ARG4(regs) = 0xDEADBEEF;
> +        case 3: HYPERCALL_ARG3(regs) = 0xDEADBEEF;
> +        case 2: HYPERCALL_ARG2(regs) = 0xDEADBEEF;
> +        case 1: /* Don't clobber x0/r0 -- it's the return value */
>              break;
>          default: BUG();
>          }
> -        regs->r12 = 0xDEADBEEF;
> +        *nr = 0xDEADBEEF;
>      }
>  #endif
>  }
> @@ -1079,11 +1098,23 @@ asmlinkage void do_trap_hypervisor(struct 
> cpu_user_regs *regs)
>              goto bad_trap;
>          do_cp15_64(regs, hsr);
>          break;
> -    case HSR_EC_HVC:
> +    case HSR_EC_HVC32:
> +#ifndef NDEBUG
> +        if ( (hsr.iss & 0xff00) == 0xff00 )
> +            return do_debug_trap(regs, hsr.iss & 0x00ff);
> +#endif
> +        do_trap_hypercall(regs, (register_t *)&regs->r12, hsr.iss);
> +        break;
> +
> +#ifdef CONFIG_ARM_64
> +    case HSR_EC_HVC64:
> +#ifndef NDEBUG
>          if ( (hsr.iss & 0xff00) == 0xff00 )
>              return do_debug_trap(regs, hsr.iss & 0x00ff);
> -        do_trap_hypercall(regs, hsr.iss);
> +#endif
> +        do_trap_hypercall(regs, &regs->x16, hsr.iss);
>          break;
> +#endif
>      case HSR_EC_DATA_ABORT_GUEST:
>          do_trap_data_abort_guest(regs, hsr.dabt);
>          break;
> diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
> index 32c441b..17f5465 100644
> --- a/xen/include/asm-arm/processor.h
> +++ b/xen/include/asm-arm/processor.h
> @@ -86,8 +86,11 @@
>  #define HSR_EC_JAZELLE              0x09
>  #define HSR_EC_BXJ                  0x0a
>  #define HSR_EC_CP14_64              0x0c
> -#define HSR_EC_SVC                  0x11
> -#define HSR_EC_HVC                  0x12
> +#define HSR_EC_SVC32                0x11
> +#define HSR_EC_HVC32                0x12
> +#ifdef CONFIG_ARM_64
> +#define HSR_EC_HVC64                0x16
> +#endif
>  #define HSR_EC_INSTR_ABORT_GUEST    0x20
>  #define HSR_EC_INSTR_ABORT_HYP      0x21
>  #define HSR_EC_DATA_ABORT_GUEST     0x24
> -- 
> 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®.