[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]

 



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


[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