Re: [PATCH v2 6/6] ARM: KVM: move away from VCPU_*_MODE in register manipulation code

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

 



On Mon, Oct 15, 2012 at 11:19 AM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote:
> The use of VCPU_*_MODE in register manipulation code is not really
> necessary, and possibly costly (table lookup doesn't come for free).

the reason why the table is there is that previous reviewers felt the
series of branches with a lot of room for misprediction wold be
harmfully slow and therefore suggested the lookup table. I'm curious,
do you feel otherwise?

>
> Just use the normal *_MODE defines and some case statements. Also,
> merge USR and SYS registers, which are architecturally indentical.

otherwise this looks ok.

I will find time to apply and test this probably at the end of the week.

(note the subject of this patch is unreasonably long)

-Christoffer

>
> Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
> ---
>  arch/arm/include/asm/kvm_emulate.h |  17 +-----
>  arch/arm/kvm/emulate.c             | 114 ++++++++++++++-----------------------
>  2 files changed, 47 insertions(+), 84 deletions(-)
>
> diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
> index 1a7f3dd..6a82fcc 100644
> --- a/arch/arm/include/asm/kvm_emulate.h
> +++ b/arch/arm/include/asm/kvm_emulate.h
> @@ -22,8 +22,6 @@
>  #include <linux/kvm_host.h>
>  #include <asm/kvm_asm.h>
>
> -u32 *vcpu_reg_mode(struct kvm_vcpu *vcpu, u8 reg_num, u32 cpsr);
> -u32 *vcpu_spsr_mode(struct kvm_vcpu *vcpu, u32 cpsr);
>  /*
>   * The in-kernel MMIO emulation code wants to use a copy of run->mmio,
>   * which is an anonymous type. Use our own type instead.
> @@ -45,6 +43,9 @@ static inline void kvm_prepare_mmio(struct kvm_run *run,
>         run->exit_reason        = KVM_EXIT_MMIO;
>  }
>
> +u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
> +u32 *vcpu_spsr(struct kvm_vcpu *vcpu);
> +
>  int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run);
>  int kvm_emulate_mmio_ls(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>                         unsigned long instr, struct kvm_exit_mmio *mmio);
> @@ -53,12 +54,6 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu);
>  void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
>  void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
>
> -/* Get vcpu register for current mode */
> -static inline u32 *vcpu_reg(struct kvm_vcpu *vcpu, unsigned long reg_num)
> -{
> -       return vcpu_reg_mode(vcpu, reg_num, vcpu->arch.regs.usr_regs.ARM_cpsr);
> -}
> -
>  static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
>  {
>         return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
> @@ -69,12 +64,6 @@ static inline u32 *vcpu_cpsr(struct kvm_vcpu *vcpu)
>         return (u32 *)&vcpu->arch.regs.usr_regs.ARM_cpsr;
>  }
>
> -/* Get vcpu SPSR for current mode */
> -static inline u32 *vcpu_spsr(struct kvm_vcpu *vcpu)
> -{
> -       return vcpu_spsr_mode(vcpu, vcpu->arch.regs.usr_regs.ARM_cpsr);
> -}
> -
>  static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
>  {
>         unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
> diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
> index de6189e..995c59f 100644
> --- a/arch/arm/kvm/emulate.c
> +++ b/arch/arm/kvm/emulate.c
> @@ -24,13 +24,23 @@
>
>  #include "trace.h"
>
> -#define VCPU_NR_MODES 7
> +#define VCPU_NR_MODES 6
>  #define REG_OFFSET(_reg) \
>         (offsetof(struct kvm_regs, _reg) / sizeof(u32))
>
>  #define USR_REG_OFFSET(_num) REG_OFFSET(usr_regs.uregs[_num])
>
>  static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][16] = {
> +       /* USR/SYS Registers */
> +       {
> +               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
> +               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
> +               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
> +               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
> +               USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14),
> +               REG_OFFSET(usr_regs.ARM_pc)
> +       },
> +
>         /* FIQ Registers */
>         {
>                 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
> @@ -93,93 +103,57 @@ static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][16] = {
>                 REG_OFFSET(und_regs[1]), /* r14 */
>                 REG_OFFSET(usr_regs.ARM_pc)
>         },
> -
> -       /* USR Registers */
> -       {
> -               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
> -               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
> -               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
> -               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
> -               USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14),
> -               REG_OFFSET(usr_regs.ARM_pc)
> -       },
> -
> -       /* SYS Registers */
> -       {
> -               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
> -               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
> -               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
> -               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
> -               USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14),
> -               REG_OFFSET(usr_regs.ARM_pc)
> -       },
> -};
> -
> -/*
> - * Modes used for short-hand mode determinition in the world-switch code and
> - * in emulation code.
> - *
> - * Note: These indices do NOT correspond to the value of the CPSR mode bits!
> - */
> -enum vcpu_mode {
> -       VCPU_FIQ_MODE = 0,
> -       VCPU_IRQ_MODE,
> -       VCPU_SVC_MODE,
> -       VCPU_ABT_MODE,
> -       VCPU_UND_MODE,
> -       VCPU_USR_MODE,
> -       VCPU_SYS_MODE
> -};
> -
> -static const u8 modes_table[32] = {
> -       0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
> -       0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
> -       VCPU_USR_MODE,  /* 0x0 */
> -       VCPU_FIQ_MODE,  /* 0x1 */
> -       VCPU_IRQ_MODE,  /* 0x2 */
> -       VCPU_SVC_MODE,  /* 0x3 */
> -       0xf, 0xf, 0xf,
> -       VCPU_ABT_MODE,  /* 0x7 */
> -       0xf, 0xf, 0xf,
> -       VCPU_UND_MODE,  /* 0xb */
> -       0xf, 0xf, 0xf,
> -       VCPU_SYS_MODE   /* 0xf */
> -};
> -
> -static enum vcpu_mode vcpu_mode(u32 cpsr)
> -{
> -       u8 mode = modes_table[cpsr & 0x1f];
> -       BUG_ON(mode == 0xf);
> -       return mode;
>  };
>
>  /*
> - * Return a pointer to the register number valid in the specified mode of
> + * Return a pointer to the register number valid in the current mode of
>   * the virtual CPU.
>   */
> -u32 *vcpu_reg_mode(struct kvm_vcpu *vcpu, u8 reg_num, u32 cpsr)
> +u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
>  {
> -       unsigned long mode = vcpu_mode(cpsr);
>         u32 *reg_array = (u32 *)&vcpu->arch.regs;
> +       u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
> +
> +       switch (mode) {
> +       case USR_MODE...SVC_MODE:
> +               mode &= ~MODE32_BIT; /* 0 ... 3 */
> +               break;
> +
> +       case ABT_MODE:
> +               mode = 4;
> +               break;
> +
> +       case UND_MODE:
> +               mode = 5;
> +               break;
> +
> +       case SYSTEM_MODE:
> +               mode = 0;
> +               break;
> +
> +       default:
> +               BUG();
> +       }
>
>         return reg_array + vcpu_reg_offsets[mode][reg_num];
>  }
>
>  /*
> - * Return the SPSR for the specified mode of the virtual CPU.
> + * Return the SPSR for the current mode of the virtual CPU.
>   */
> -u32 *vcpu_spsr_mode(struct kvm_vcpu *vcpu, u32 cpsr)
> +u32 *vcpu_spsr(struct kvm_vcpu *vcpu)
>  {
> -       switch (vcpu_mode(cpsr)) {
> -       case VCPU_SVC_MODE:
> +       u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
> +       switch (mode) {
> +       case SVC_MODE:
>                 return &vcpu->arch.regs.svc_regs[2];
> -       case VCPU_ABT_MODE:
> +       case ABT_MODE:
>                 return &vcpu->arch.regs.abt_regs[2];
> -       case VCPU_UND_MODE:
> +       case UND_MODE:
>                 return &vcpu->arch.regs.und_regs[2];
> -       case VCPU_IRQ_MODE:
> +       case IRQ_MODE:
>                 return &vcpu->arch.regs.irq_regs[2];
> -       case VCPU_FIQ_MODE:
> +       case FIQ_MODE:
>                 return &vcpu->arch.regs.fiq_regs[7];
>         default:
>                 BUG();
> --
> 1.7.12
>
>
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@xxxxxxxxxxxxxxxxxxxxx
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux