The use of VCPU_*_MODE in register manipulation code is not really necessary, and possibly costly (table lookup doesn't come for free). Just use the normal *_MODE defines and some case statements. Also, merge USR and SYS registers, which are architecturally indentical. 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