All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers
@ 2015-12-04 10:25 Pavel Fedin
  2015-12-04 10:25 ` [PATCH v2 1/4] KVM: arm64: Correctly handle zero register during MMIO Pavel Fedin
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 10:25 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: Marc Zyngier

ARM64 CPU has zero register which is read-only, with a value of 0.
However, KVM currently incorrectly recognizes it being SP (because
Rt == 31, and in struct user_pt_regs 'regs' array is followed by SP),
resulting in invalid value being read, or even SP corruption on write.

The problem has been discovered by performing an operation

 *((volatile int *)reg) = 0;

which compiles as "str xzr, [xx]", and resulted in strange values being
written.

v1 => v2:
- Changed type of transfer value to u64 and store it directly in
  struct sys_reg_params instead of a pointer
- Use lower_32_bits()/upper_32_bits() where appropriate
- Fixed wrong usage of 'Rt' instead of 'Rt2' in kvm_handle_cp_64(),
  overlooked in v1
- Do not write value back when reading

Pavel Fedin (4):
  KVM: arm64: Correctly handle zero register during MMIO
  KVM: arm64: Remove const from struct sys_reg_params
  KVM: arm64: Correctly handle zero register in system register accesses
  KVM: arm64: Get rid of old vcpu_reg()

 arch/arm/include/asm/kvm_emulate.h   |  12 ++++
 arch/arm/kvm/mmio.c                  |   5 +-
 arch/arm/kvm/psci.c                  |  20 +++---
 arch/arm64/include/asm/kvm_emulate.h |  18 +++--
 arch/arm64/kvm/handle_exit.c         |   2 +-
 arch/arm64/kvm/sys_regs.c            | 126 +++++++++++++++++------------------
 arch/arm64/kvm/sys_regs.h            |  16 ++---
 arch/arm64/kvm/sys_regs_generic_v8.c |   4 +-
 8 files changed, 111 insertions(+), 92 deletions(-)

-- 
2.4.4


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/4] KVM: arm64: Correctly handle zero register during MMIO
  2015-12-04 10:25 [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Pavel Fedin
@ 2015-12-04 10:25 ` Pavel Fedin
  2015-12-04 10:25 ` [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params Pavel Fedin
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 10:25 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: Marc Zyngier

On ARM64 register index of 31 corresponds to both zero register and SP.
However, all memory access instructions, use ZR as transfer register. SP
is used only as a base register in indirect memory addressing, or by
register-register arithmetics, which cannot be trapped here.

Correct emulation is achieved by introducing new register accessor
functions, which can do special handling for reg_num == 31. These new
accessors intentionally do not rely on old vcpu_reg() on ARM64, because
it is to be removed. Since the affected code is shared by both ARM
flavours, implementations of these accessors are also added to ARM32 code.

This patch fixes setting MMIO register to a random value (actually SP)
instead of zero by something like:

 *((volatile int *)reg) = 0;

compilers tend to generate "str wzr, [xx]" here

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_emulate.h   | 12 ++++++++++++
 arch/arm/kvm/mmio.c                  |  5 +++--
 arch/arm64/include/asm/kvm_emulate.h | 13 +++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index a9c80a2..b7ff32e 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -28,6 +28,18 @@
 unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
 unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu);
 
+static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
+					 u8 reg_num)
+{
+	return *vcpu_reg(vcpu, reg_num);
+}
+
+static inline void vcpu_set_reg(const struct kvm_vcpu *vcpu, u8 reg_num,
+				unsigned long val)
+{
+	*vcpu_reg(vcpu, reg_num) = val;
+}
+
 bool kvm_condition_valid(struct kvm_vcpu *vcpu);
 void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr);
 void kvm_inject_undefined(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 974b1c6..3a10c9f 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -115,7 +115,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
 			       data);
 		data = vcpu_data_host_to_guest(vcpu, data, len);
-		*vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt) = data;
+		vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data);
 	}
 
 	return 0;
@@ -186,7 +186,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	rt = vcpu->arch.mmio_decode.rt;
 
 	if (is_write) {
-		data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt), len);
+		data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
+					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
 		mmio_write_buf(data_buf, len, data);
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 3ca894e..5a182af 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -109,6 +109,19 @@ static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
 	return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
 }
 
+static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
+					 u8 reg_num)
+{
+	return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num];
+}
+
+static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
+				unsigned long val)
+{
+	if (reg_num != 31)
+		vcpu_gp_regs(vcpu)->regs.regs[reg_num] = val;
+}
+
 /* Get vcpu SPSR for current mode */
 static inline unsigned long *vcpu_spsr(const struct kvm_vcpu *vcpu)
 {
-- 
2.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params
  2015-12-04 10:25 [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Pavel Fedin
  2015-12-04 10:25 ` [PATCH v2 1/4] KVM: arm64: Correctly handle zero register during MMIO Pavel Fedin
@ 2015-12-04 10:25 ` Pavel Fedin
  2015-12-04 11:15   ` Marc Zyngier
  2015-12-04 10:25 ` [PATCH v2 3/4] KVM: arm64: Correctly handle zero register in system register accesses Pavel Fedin
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 10:25 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: Marc Zyngier

Further rework is going to introduce a dedicated storage for transfer
register value in struct sys_reg_params. Before doing this we have to
remove all 'const' modifiers from it.

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
 arch/arm64/kvm/sys_regs.c            | 38 ++++++++++++++++++------------------
 arch/arm64/kvm/sys_regs.h            | 12 ++++++------
 arch/arm64/kvm/sys_regs_generic_v8.c |  2 +-
 3 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 87a64e8..e5f024e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -78,7 +78,7 @@ static u32 get_ccsidr(u32 csselr)
  * See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized).
  */
 static bool access_dcsw(struct kvm_vcpu *vcpu,
-			const struct sys_reg_params *p,
+			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
 {
 	if (!p->is_write)
@@ -94,7 +94,7 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
  * sys_regs and leave it in complete control of the caches.
  */
 static bool access_vm_reg(struct kvm_vcpu *vcpu,
-			  const struct sys_reg_params *p,
+			  struct sys_reg_params *p,
 			  const struct sys_reg_desc *r)
 {
 	unsigned long val;
@@ -122,7 +122,7 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
  * for both AArch64 and AArch32 accesses.
  */
 static bool access_gic_sgi(struct kvm_vcpu *vcpu,
-			   const struct sys_reg_params *p,
+			   struct sys_reg_params *p,
 			   const struct sys_reg_desc *r)
 {
 	u64 val;
@@ -137,7 +137,7 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
 }
 
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
-			const struct sys_reg_params *p,
+			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
 {
 	if (p->is_write)
@@ -147,7 +147,7 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
 }
 
 static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
-			   const struct sys_reg_params *p,
+			   struct sys_reg_params *p,
 			   const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
@@ -159,7 +159,7 @@ static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
 }
 
 static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
-				   const struct sys_reg_params *p,
+				   struct sys_reg_params *p,
 				   const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
@@ -200,7 +200,7 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
  *   now use the debug registers.
  */
 static bool trap_debug_regs(struct kvm_vcpu *vcpu,
-			    const struct sys_reg_params *p,
+			    struct sys_reg_params *p,
 			    const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
@@ -225,7 +225,7 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
  * hyp.S code switches between host and guest values in future.
  */
 static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
-			      const struct sys_reg_params *p,
+			      struct sys_reg_params *p,
 			      u64 *dbg_reg)
 {
 	u64 val = *vcpu_reg(vcpu, p->Rt);
@@ -240,7 +240,7 @@ static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
 }
 
 static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
-			      const struct sys_reg_params *p,
+			      struct sys_reg_params *p,
 			      u64 *dbg_reg)
 {
 	u64 val = *dbg_reg;
@@ -252,7 +252,7 @@ static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
 }
 
 static inline bool trap_bvr(struct kvm_vcpu *vcpu,
-			    const struct sys_reg_params *p,
+			    struct sys_reg_params *p,
 			    const struct sys_reg_desc *rd)
 {
 	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
@@ -294,7 +294,7 @@ static inline void reset_bvr(struct kvm_vcpu *vcpu,
 }
 
 static inline bool trap_bcr(struct kvm_vcpu *vcpu,
-			    const struct sys_reg_params *p,
+			    struct sys_reg_params *p,
 			    const struct sys_reg_desc *rd)
 {
 	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
@@ -337,7 +337,7 @@ static inline void reset_bcr(struct kvm_vcpu *vcpu,
 }
 
 static inline bool trap_wvr(struct kvm_vcpu *vcpu,
-			    const struct sys_reg_params *p,
+			    struct sys_reg_params *p,
 			    const struct sys_reg_desc *rd)
 {
 	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
@@ -380,7 +380,7 @@ static inline void reset_wvr(struct kvm_vcpu *vcpu,
 }
 
 static inline bool trap_wcr(struct kvm_vcpu *vcpu,
-			    const struct sys_reg_params *p,
+			    struct sys_reg_params *p,
 			    const struct sys_reg_desc *rd)
 {
 	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
@@ -687,7 +687,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 };
 
 static bool trap_dbgidr(struct kvm_vcpu *vcpu,
-			const struct sys_reg_params *p,
+			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
@@ -706,7 +706,7 @@ static bool trap_dbgidr(struct kvm_vcpu *vcpu,
 }
 
 static bool trap_debug32(struct kvm_vcpu *vcpu,
-			 const struct sys_reg_params *p,
+			 struct sys_reg_params *p,
 			 const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
@@ -731,7 +731,7 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
  */
 
 static inline bool trap_xvr(struct kvm_vcpu *vcpu,
-			    const struct sys_reg_params *p,
+			    struct sys_reg_params *p,
 			    const struct sys_reg_desc *rd)
 {
 	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
@@ -949,7 +949,7 @@ static const struct sys_reg_desc *get_target_table(unsigned target,
 	}
 }
 
-static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
+static const struct sys_reg_desc *find_reg(struct sys_reg_params *params,
 					 const struct sys_reg_desc table[],
 					 unsigned int num)
 {
@@ -991,7 +991,7 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
  * Return 0 if the access has been handled, and -1 if not.
  */
 static int emulate_cp(struct kvm_vcpu *vcpu,
-		      const struct sys_reg_params *params,
+		      struct sys_reg_params *params,
 		      const struct sys_reg_desc *table,
 		      size_t num)
 {
@@ -1175,7 +1175,7 @@ int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
 }
 
 static int emulate_sys_reg(struct kvm_vcpu *vcpu,
-			   const struct sys_reg_params *params)
+			   struct sys_reg_params *params)
 {
 	size_t num;
 	const struct sys_reg_desc *table, *r;
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index eaa324e..6c251ab 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -44,7 +44,7 @@ struct sys_reg_desc {
 
 	/* Trapped access from guest, if non-NULL. */
 	bool (*access)(struct kvm_vcpu *,
-		       const struct sys_reg_params *,
+		       struct sys_reg_params *,
 		       const struct sys_reg_desc *);
 
 	/* Initialization for vcpu. */
@@ -63,7 +63,7 @@ struct sys_reg_desc {
 			const struct kvm_one_reg *reg, void __user *uaddr);
 };
 
-static inline void print_sys_reg_instr(const struct sys_reg_params *p)
+static inline void print_sys_reg_instr(struct sys_reg_params *p)
 {
 	/* Look, we even formatted it for you to paste into the table! */
 	kvm_pr_unimpl(" { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
@@ -71,20 +71,20 @@ static inline void print_sys_reg_instr(const struct sys_reg_params *p)
 }
 
 static inline bool ignore_write(struct kvm_vcpu *vcpu,
-				const struct sys_reg_params *p)
+				struct sys_reg_params *p)
 {
 	return true;
 }
 
 static inline bool read_zero(struct kvm_vcpu *vcpu,
-			     const struct sys_reg_params *p)
+			     struct sys_reg_params *p)
 {
 	*vcpu_reg(vcpu, p->Rt) = 0;
 	return true;
 }
 
 static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
-				      const struct sys_reg_params *params)
+				      struct sys_reg_params *params)
 {
 	kvm_debug("sys_reg write to read-only register at: %lx\n",
 		  *vcpu_pc(vcpu));
@@ -93,7 +93,7 @@ static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
 }
 
 static inline bool read_from_write_only(struct kvm_vcpu *vcpu,
-					const struct sys_reg_params *params)
+					struct sys_reg_params *params)
 {
 	kvm_debug("sys_reg read to write-only register at: %lx\n",
 		  *vcpu_pc(vcpu));
diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c
index 1e45768..ccd3e35 100644
--- a/arch/arm64/kvm/sys_regs_generic_v8.c
+++ b/arch/arm64/kvm/sys_regs_generic_v8.c
@@ -31,7 +31,7 @@
 #include "sys_regs.h"
 
 static bool access_actlr(struct kvm_vcpu *vcpu,
-			 const struct sys_reg_params *p,
+			 struct sys_reg_params *p,
 			 const struct sys_reg_desc *r)
 {
 	if (p->is_write)
-- 
2.4.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 3/4] KVM: arm64: Correctly handle zero register in system register accesses
  2015-12-04 10:25 [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Pavel Fedin
  2015-12-04 10:25 ` [PATCH v2 1/4] KVM: arm64: Correctly handle zero register during MMIO Pavel Fedin
  2015-12-04 10:25 ` [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params Pavel Fedin
@ 2015-12-04 10:25 ` Pavel Fedin
  2015-12-04 11:21   ` Marc Zyngier
  2015-12-04 10:26 ` [PATCH v2 4/4] KVM: arm64: Get rid of old vcpu_reg() Pavel Fedin
  2015-12-04 11:28 ` [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Marc Zyngier
  4 siblings, 1 reply; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 10:25 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: Marc Zyngier

System register accesses also use zero register for Rt == 31, and
therefore using it will also result in getting SP value instead. This
patch makes them also using new accessors, introduced by the previous
patch. Since register value is no longer directly associated with storage
inside vCPU context structure, we introduce a dedicated storage for it in
struct sys_reg_params.

This refactor also gets rid of "massive hack" in kvm_handle_cp_64().

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
 arch/arm64/kvm/sys_regs.c            | 88 ++++++++++++++++++------------------
 arch/arm64/kvm/sys_regs.h            |  4 +-
 arch/arm64/kvm/sys_regs_generic_v8.c |  2 +-
 3 files changed, 46 insertions(+), 48 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e5f024e..7c9cd64 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -97,18 +97,17 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
 			  struct sys_reg_params *p,
 			  const struct sys_reg_desc *r)
 {
-	unsigned long val;
 	bool was_enabled = vcpu_has_cache_enabled(vcpu);
 
 	BUG_ON(!p->is_write);
 
-	val = *vcpu_reg(vcpu, p->Rt);
 	if (!p->is_aarch32) {
-		vcpu_sys_reg(vcpu, r->reg) = val;
+		vcpu_sys_reg(vcpu, r->reg) = p->regval;
 	} else {
 		if (!p->is_32bit)
-			vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
-		vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
+			vcpu_cp15_64_high(vcpu, r->reg) =
+				upper_32_bits(p->regval);
+		vcpu_cp15_64_low(vcpu, r->reg) = lower_32_bits(p->regval);
 	}
 
 	kvm_toggle_cache(vcpu, was_enabled);
@@ -125,13 +124,10 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
 			   struct sys_reg_params *p,
 			   const struct sys_reg_desc *r)
 {
-	u64 val;
-
 	if (!p->is_write)
 		return read_from_write_only(vcpu, p);
 
-	val = *vcpu_reg(vcpu, p->Rt);
-	vgic_v3_dispatch_sgi(vcpu, val);
+	vgic_v3_dispatch_sgi(vcpu, p->regval);
 
 	return true;
 }
@@ -153,7 +149,7 @@ static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
 	if (p->is_write) {
 		return ignore_write(vcpu, p);
 	} else {
-		*vcpu_reg(vcpu, p->Rt) = (1 << 3);
+		p->regval = (1 << 3);
 		return true;
 	}
 }
@@ -167,7 +163,7 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
 	} else {
 		u32 val;
 		asm volatile("mrs %0, dbgauthstatus_el1" : "=r" (val));
-		*vcpu_reg(vcpu, p->Rt) = val;
+		p->regval = val;
 		return true;
 	}
 }
@@ -204,13 +200,13 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
 			    const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
-		vcpu_sys_reg(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
+		vcpu_sys_reg(vcpu, r->reg) = p->regval;
 		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
 	} else {
-		*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, r->reg);
+		p->regval = vcpu_sys_reg(vcpu, r->reg);
 	}
 
-	trace_trap_reg(__func__, r->reg, p->is_write, *vcpu_reg(vcpu, p->Rt));
+	trace_trap_reg(__func__, r->reg, p->is_write, p->regval);
 
 	return true;
 }
@@ -228,7 +224,7 @@ static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      u64 *dbg_reg)
 {
-	u64 val = *vcpu_reg(vcpu, p->Rt);
+	u64 val = p->regval;
 
 	if (p->is_32bit) {
 		val &= 0xffffffffUL;
@@ -243,12 +239,9 @@ static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
 			      struct sys_reg_params *p,
 			      u64 *dbg_reg)
 {
-	u64 val = *dbg_reg;
-
+	p->regval = *dbg_reg;
 	if (p->is_32bit)
-		val &= 0xffffffffUL;
-
-	*vcpu_reg(vcpu, p->Rt) = val;
+		p->regval &= 0xffffffffUL;
 }
 
 static inline bool trap_bvr(struct kvm_vcpu *vcpu,
@@ -697,10 +690,10 @@ static bool trap_dbgidr(struct kvm_vcpu *vcpu,
 		u64 pfr = read_system_reg(SYS_ID_AA64PFR0_EL1);
 		u32 el3 = !!cpuid_feature_extract_field(pfr, ID_AA64PFR0_EL3_SHIFT);
 
-		*vcpu_reg(vcpu, p->Rt) = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
-					  (((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
-					  (((dfr >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) << 20) |
-					  (6 << 16) | (el3 << 14) | (el3 << 12));
+		p->regval = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
+			     (((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
+			     (((dfr >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) << 20)
+			     | (6 << 16) | (el3 << 14) | (el3 << 12));
 		return true;
 	}
 }
@@ -710,10 +703,10 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
 			 const struct sys_reg_desc *r)
 {
 	if (p->is_write) {
-		vcpu_cp14(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
+		vcpu_cp14(vcpu, r->reg) = p->regval;
 		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
 	} else {
-		*vcpu_reg(vcpu, p->Rt) = vcpu_cp14(vcpu, r->reg);
+		p->regval = vcpu_cp14(vcpu, r->reg);
 	}
 
 	return true;
@@ -740,12 +733,12 @@ static inline bool trap_xvr(struct kvm_vcpu *vcpu,
 		u64 val = *dbg_reg;
 
 		val &= 0xffffffffUL;
-		val |= *vcpu_reg(vcpu, p->Rt) << 32;
+		val |= p->regval << 32;
 		*dbg_reg = val;
 
 		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
 	} else {
-		*vcpu_reg(vcpu, p->Rt) = *dbg_reg >> 32;
+		p->regval = *dbg_reg >> 32;
 	}
 
 	trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
@@ -1062,12 +1055,12 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
+	int Rt = (hsr >> 5) & 0xf;
 	int Rt2 = (hsr >> 10) & 0xf;
 
 	params.is_aarch32 = true;
 	params.is_32bit = false;
 	params.CRm = (hsr >> 1) & 0xf;
-	params.Rt = (hsr >> 5) & 0xf;
 	params.is_write = ((hsr & 1) == 0);
 
 	params.Op0 = 0;
@@ -1076,15 +1069,12 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 	params.CRn = 0;
 
 	/*
-	 * Massive hack here. Store Rt2 in the top 32bits so we only
-	 * have one register to deal with. As we use the same trap
+	 * Make a 64-bit value out of Rt and Rt2. As we use the same trap
 	 * backends between AArch32 and AArch64, we get away with it.
 	 */
 	if (params.is_write) {
-		u64 val = *vcpu_reg(vcpu, params.Rt);
-		val &= 0xffffffff;
-		val |= *vcpu_reg(vcpu, Rt2) << 32;
-		*vcpu_reg(vcpu, params.Rt) = val;
+		params.regval = vcpu_get_reg(vcpu, Rt) & 0xffffffff;
+		params.regval |= vcpu_get_reg(vcpu, Rt2) << 32;
 	}
 
 	if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
@@ -1095,11 +1085,10 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 	unhandled_cp_access(vcpu, &params);
 
 out:
-	/* Do the opposite hack for the read side */
+	/* Split up the value between registers for the read side */
 	if (!params.is_write) {
-		u64 val = *vcpu_reg(vcpu, params.Rt);
-		val >>= 32;
-		*vcpu_reg(vcpu, Rt2) = val;
+		vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval));
+		vcpu_set_reg(vcpu, Rt2, upper_32_bits(params.regval));
 	}
 
 	return 1;
@@ -1118,21 +1107,24 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
+	int Rt  = (hsr >> 5) & 0xf;
 
 	params.is_aarch32 = true;
 	params.is_32bit = true;
 	params.CRm = (hsr >> 1) & 0xf;
-	params.Rt  = (hsr >> 5) & 0xf;
+	params.regval = vcpu_get_reg(vcpu, Rt);
 	params.is_write = ((hsr & 1) == 0);
 	params.CRn = (hsr >> 10) & 0xf;
 	params.Op0 = 0;
 	params.Op1 = (hsr >> 14) & 0x7;
 	params.Op2 = (hsr >> 17) & 0x7;
 
-	if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
-		return 1;
-	if (!emulate_cp(vcpu, &params, global, nr_global))
+	if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
+	    !emulate_cp(vcpu, &params, global, nr_global)) {
+		if (!params.is_write)
+			vcpu_set_reg(vcpu, Rt, params.regval);
 		return 1;
+	}
 
 	unhandled_cp_access(vcpu, &params);
 	return 1;
@@ -1230,6 +1222,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	struct sys_reg_params params;
 	unsigned long esr = kvm_vcpu_get_hsr(vcpu);
+	int Rt = (esr >> 5) & 0x1f;
+	int ret;
 
 	trace_kvm_handle_sys_reg(esr);
 
@@ -1240,10 +1234,14 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	params.CRn = (esr >> 10) & 0xf;
 	params.CRm = (esr >> 1) & 0xf;
 	params.Op2 = (esr >> 17) & 0x7;
-	params.Rt = (esr >> 5) & 0x1f;
+	params.regval = vcpu_get_reg(vcpu, Rt);
 	params.is_write = !(esr & 1);
 
-	return emulate_sys_reg(vcpu, &params);
+	ret = emulate_sys_reg(vcpu, &params);
+
+	if (!params.is_write)
+		vcpu_set_reg(vcpu, Rt, params.regval);
+	return ret;
 }
 
 /******************************************************************************
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 6c251ab..86ed945 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -28,7 +28,7 @@ struct sys_reg_params {
 	u8	CRn;
 	u8	CRm;
 	u8	Op2;
-	u8	Rt;
+	u64	regval;
 	bool	is_write;
 	bool	is_aarch32;
 	bool	is_32bit;	/* Only valid if is_aarch32 is true */
@@ -79,7 +79,7 @@ static inline bool ignore_write(struct kvm_vcpu *vcpu,
 static inline bool read_zero(struct kvm_vcpu *vcpu,
 			     struct sys_reg_params *p)
 {
-	*vcpu_reg(vcpu, p->Rt) = 0;
+	p->regval = 0;
 	return true;
 }
 
diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c
index ccd3e35..ed90578 100644
--- a/arch/arm64/kvm/sys_regs_generic_v8.c
+++ b/arch/arm64/kvm/sys_regs_generic_v8.c
@@ -37,7 +37,7 @@ static bool access_actlr(struct kvm_vcpu *vcpu,
 	if (p->is_write)
 		return ignore_write(vcpu, p);
 
-	*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, ACTLR_EL1);
+	p->regval = vcpu_sys_reg(vcpu, ACTLR_EL1);
 	return true;
 }
 
-- 
2.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 4/4] KVM: arm64: Get rid of old vcpu_reg()
  2015-12-04 10:25 [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Pavel Fedin
                   ` (2 preceding siblings ...)
  2015-12-04 10:25 ` [PATCH v2 3/4] KVM: arm64: Correctly handle zero register in system register accesses Pavel Fedin
@ 2015-12-04 10:26 ` Pavel Fedin
  2015-12-04 11:23   ` Marc Zyngier
  2015-12-04 11:28 ` [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Marc Zyngier
  4 siblings, 1 reply; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 10:26 UTC (permalink / raw)
  To: kvmarm, kvm; +Cc: Marc Zyngier

Using oldstyle vcpu_reg() accessor is proven to be inappropriate and
unsafe on ARM64. This patch converts the rest of use cases to new
accessors and completely removes vcpu_reg() on ARM64.

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
 arch/arm/kvm/psci.c                  | 20 ++++++++++----------
 arch/arm64/include/asm/kvm_emulate.h | 11 +++--------
 arch/arm64/kvm/handle_exit.c         |  2 +-
 3 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 0b55696..a9b3b90 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -75,7 +75,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	unsigned long context_id;
 	phys_addr_t target_pc;
 
-	cpu_id = *vcpu_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
+	cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
 	if (vcpu_mode_is_32bit(source_vcpu))
 		cpu_id &= ~((u32) 0);
 
@@ -94,8 +94,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 			return PSCI_RET_INVALID_PARAMS;
 	}
 
-	target_pc = *vcpu_reg(source_vcpu, 2);
-	context_id = *vcpu_reg(source_vcpu, 3);
+	target_pc = vcpu_get_reg(source_vcpu, 2);
+	context_id = vcpu_get_reg(source_vcpu, 3);
 
 	kvm_reset_vcpu(vcpu);
 
@@ -114,7 +114,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	 * NOTE: We always update r0 (or x0) because for PSCI v0.1
 	 * the general puspose registers are undefined upon CPU_ON.
 	 */
-	*vcpu_reg(vcpu, 0) = context_id;
+	vcpu_set_reg(vcpu, 0, context_id);
 	vcpu->arch.power_off = false;
 	smp_mb();		/* Make sure the above is visible */
 
@@ -134,8 +134,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 	struct kvm *kvm = vcpu->kvm;
 	struct kvm_vcpu *tmp;
 
-	target_affinity = *vcpu_reg(vcpu, 1);
-	lowest_affinity_level = *vcpu_reg(vcpu, 2);
+	target_affinity = vcpu_get_reg(vcpu, 1);
+	lowest_affinity_level = vcpu_get_reg(vcpu, 2);
 
 	/* Determine target affinity mask */
 	target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
@@ -209,7 +209,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
 	int ret = 1;
-	unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
+	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
 
 	switch (psci_fn) {
@@ -273,13 +273,13 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		break;
 	}
 
-	*vcpu_reg(vcpu, 0) = val;
+	vcpu_set_reg(vcpu, 0, val);
 	return ret;
 }
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
-	unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
+	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
 
 	switch (psci_fn) {
@@ -295,7 +295,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 		break;
 	}
 
-	*vcpu_reg(vcpu, 0) = val;
+	vcpu_set_reg(vcpu, 0, val);
 	return 1;
 }
 
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 5a182af..25a4021 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -100,15 +100,10 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
 }
 
 /*
- * vcpu_reg should always be passed a register number coming from a
- * read of ESR_EL2. Otherwise, it may give the wrong result on AArch32
- * with banked registers.
+ * vcpu_get_reg and vcpu_set_reg should always be passed a register number
+ * coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
+ * AArch32 with banked registers.
  */
-static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
-{
-	return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
-}
-
 static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
 					 u8 reg_num)
 {
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 68a0759..15f0477 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -37,7 +37,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	int ret;
 
-	trace_kvm_hvc_arm64(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
+	trace_kvm_hvc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
 			    kvm_vcpu_hvc_get_imm(vcpu));
 
 	ret = kvm_psci_call(vcpu);
-- 
2.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params
  2015-12-04 10:25 ` [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params Pavel Fedin
@ 2015-12-04 11:15   ` Marc Zyngier
  2015-12-04 11:29     ` Pavel Fedin
  0 siblings, 1 reply; 11+ messages in thread
From: Marc Zyngier @ 2015-12-04 11:15 UTC (permalink / raw)
  To: Pavel Fedin, kvmarm, kvm

Hi Pavel,

On 04/12/15 10:25, Pavel Fedin wrote:
> Further rework is going to introduce a dedicated storage for transfer
> register value in struct sys_reg_params. Before doing this we have to
> remove all 'const' modifiers from it.

I think you are being a bit overzealous here, and a few const can
legitimately be kept, see below.

> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
>  arch/arm64/kvm/sys_regs.c            | 38 ++++++++++++++++++------------------
>  arch/arm64/kvm/sys_regs.h            | 12 ++++++------
>  arch/arm64/kvm/sys_regs_generic_v8.c |  2 +-
>  3 files changed, 26 insertions(+), 26 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 87a64e8..e5f024e 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -78,7 +78,7 @@ static u32 get_ccsidr(u32 csselr)
>   * See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized).
>   */
>  static bool access_dcsw(struct kvm_vcpu *vcpu,
> -			const struct sys_reg_params *p,
> +			struct sys_reg_params *p,
>  			const struct sys_reg_desc *r)
>  {
>  	if (!p->is_write)
> @@ -94,7 +94,7 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
>   * sys_regs and leave it in complete control of the caches.
>   */
>  static bool access_vm_reg(struct kvm_vcpu *vcpu,
> -			  const struct sys_reg_params *p,
> +			  struct sys_reg_params *p,
>  			  const struct sys_reg_desc *r)
>  {
>  	unsigned long val;
> @@ -122,7 +122,7 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
>   * for both AArch64 and AArch32 accesses.
>   */
>  static bool access_gic_sgi(struct kvm_vcpu *vcpu,
> -			   const struct sys_reg_params *p,
> +			   struct sys_reg_params *p,
>  			   const struct sys_reg_desc *r)
>  {
>  	u64 val;
> @@ -137,7 +137,7 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
>  }
>  
>  static bool trap_raz_wi(struct kvm_vcpu *vcpu,
> -			const struct sys_reg_params *p,
> +			struct sys_reg_params *p,
>  			const struct sys_reg_desc *r)
>  {
>  	if (p->is_write)
> @@ -147,7 +147,7 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
>  }
>  
>  static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
> -			   const struct sys_reg_params *p,
> +			   struct sys_reg_params *p,
>  			   const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> @@ -159,7 +159,7 @@ static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
>  }
>  
>  static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
> -				   const struct sys_reg_params *p,
> +				   struct sys_reg_params *p,
>  				   const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> @@ -200,7 +200,7 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
>   *   now use the debug registers.
>   */
>  static bool trap_debug_regs(struct kvm_vcpu *vcpu,
> -			    const struct sys_reg_params *p,
> +			    struct sys_reg_params *p,
>  			    const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> @@ -225,7 +225,7 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
>   * hyp.S code switches between host and guest values in future.
>   */
>  static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
> -			      const struct sys_reg_params *p,
> +			      struct sys_reg_params *p,
>  			      u64 *dbg_reg)
>  {
>  	u64 val = *vcpu_reg(vcpu, p->Rt);
> @@ -240,7 +240,7 @@ static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
>  }
>  
>  static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
> -			      const struct sys_reg_params *p,
> +			      struct sys_reg_params *p,
>  			      u64 *dbg_reg)
>  {
>  	u64 val = *dbg_reg;
> @@ -252,7 +252,7 @@ static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
>  }
>  
>  static inline bool trap_bvr(struct kvm_vcpu *vcpu,
> -			    const struct sys_reg_params *p,
> +			    struct sys_reg_params *p,
>  			    const struct sys_reg_desc *rd)
>  {
>  	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
> @@ -294,7 +294,7 @@ static inline void reset_bvr(struct kvm_vcpu *vcpu,
>  }
>  
>  static inline bool trap_bcr(struct kvm_vcpu *vcpu,
> -			    const struct sys_reg_params *p,
> +			    struct sys_reg_params *p,
>  			    const struct sys_reg_desc *rd)
>  {
>  	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
> @@ -337,7 +337,7 @@ static inline void reset_bcr(struct kvm_vcpu *vcpu,
>  }
>  
>  static inline bool trap_wvr(struct kvm_vcpu *vcpu,
> -			    const struct sys_reg_params *p,
> +			    struct sys_reg_params *p,
>  			    const struct sys_reg_desc *rd)
>  {
>  	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
> @@ -380,7 +380,7 @@ static inline void reset_wvr(struct kvm_vcpu *vcpu,
>  }
>  
>  static inline bool trap_wcr(struct kvm_vcpu *vcpu,
> -			    const struct sys_reg_params *p,
> +			    struct sys_reg_params *p,
>  			    const struct sys_reg_desc *rd)
>  {
>  	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
> @@ -687,7 +687,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  };
>  
>  static bool trap_dbgidr(struct kvm_vcpu *vcpu,
> -			const struct sys_reg_params *p,
> +			struct sys_reg_params *p,
>  			const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> @@ -706,7 +706,7 @@ static bool trap_dbgidr(struct kvm_vcpu *vcpu,
>  }
>  
>  static bool trap_debug32(struct kvm_vcpu *vcpu,
> -			 const struct sys_reg_params *p,
> +			 struct sys_reg_params *p,
>  			 const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> @@ -731,7 +731,7 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
>   */
>  
>  static inline bool trap_xvr(struct kvm_vcpu *vcpu,
> -			    const struct sys_reg_params *p,
> +			    struct sys_reg_params *p,
>  			    const struct sys_reg_desc *rd)
>  {
>  	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
> @@ -949,7 +949,7 @@ static const struct sys_reg_desc *get_target_table(unsigned target,
>  	}
>  }
>  
> -static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
> +static const struct sys_reg_desc *find_reg(struct sys_reg_params *params,
>  					 const struct sys_reg_desc table[],
>  					 unsigned int num)

No need to drop const here (nothing changes the structure).

>  {
> @@ -991,7 +991,7 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
>   * Return 0 if the access has been handled, and -1 if not.
>   */
>  static int emulate_cp(struct kvm_vcpu *vcpu,
> -		      const struct sys_reg_params *params,
> +		      struct sys_reg_params *params,
>  		      const struct sys_reg_desc *table,
>  		      size_t num)
>  {
> @@ -1175,7 +1175,7 @@ int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  }
>  
>  static int emulate_sys_reg(struct kvm_vcpu *vcpu,
> -			   const struct sys_reg_params *params)
> +			   struct sys_reg_params *params)
>  {
>  	size_t num;
>  	const struct sys_reg_desc *table, *r;
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index eaa324e..6c251ab 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -44,7 +44,7 @@ struct sys_reg_desc {
>  
>  	/* Trapped access from guest, if non-NULL. */
>  	bool (*access)(struct kvm_vcpu *,
> -		       const struct sys_reg_params *,
> +		       struct sys_reg_params *,
>  		       const struct sys_reg_desc *);
>  
>  	/* Initialization for vcpu. */
> @@ -63,7 +63,7 @@ struct sys_reg_desc {
>  			const struct kvm_one_reg *reg, void __user *uaddr);
>  };
>  
> -static inline void print_sys_reg_instr(const struct sys_reg_params *p)
> +static inline void print_sys_reg_instr(struct sys_reg_params *p)

No need to drop the const here.

>  {
>  	/* Look, we even formatted it for you to paste into the table! */
>  	kvm_pr_unimpl(" { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
> @@ -71,20 +71,20 @@ static inline void print_sys_reg_instr(const struct sys_reg_params *p)
>  }
>  
>  static inline bool ignore_write(struct kvm_vcpu *vcpu,
> -				const struct sys_reg_params *p)
> +				struct sys_reg_params *p)

Nor this one.

>  {
>  	return true;
>  }
>  
>  static inline bool read_zero(struct kvm_vcpu *vcpu,
> -			     const struct sys_reg_params *p)
> +			     struct sys_reg_params *p)
>  {
>  	*vcpu_reg(vcpu, p->Rt) = 0;
>  	return true;
>  }
>  
>  static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
> -				      const struct sys_reg_params *params)
> +				      struct sys_reg_params *params)

Or here.

>  {
>  	kvm_debug("sys_reg write to read-only register at: %lx\n",
>  		  *vcpu_pc(vcpu));
> @@ -93,7 +93,7 @@ static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
>  }
>  
>  static inline bool read_from_write_only(struct kvm_vcpu *vcpu,
> -					const struct sys_reg_params *params)
> +					struct sys_reg_params *params)

Or here.

>  {
>  	kvm_debug("sys_reg read to write-only register at: %lx\n",
>  		  *vcpu_pc(vcpu));
> diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c
> index 1e45768..ccd3e35 100644
> --- a/arch/arm64/kvm/sys_regs_generic_v8.c
> +++ b/arch/arm64/kvm/sys_regs_generic_v8.c
> @@ -31,7 +31,7 @@
>  #include "sys_regs.h"
>  
>  static bool access_actlr(struct kvm_vcpu *vcpu,
> -			 const struct sys_reg_params *p,
> +			 struct sys_reg_params *p,
>  			 const struct sys_reg_desc *r)
>  {
>  	if (p->is_write)
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 3/4] KVM: arm64: Correctly handle zero register in system register accesses
  2015-12-04 10:25 ` [PATCH v2 3/4] KVM: arm64: Correctly handle zero register in system register accesses Pavel Fedin
@ 2015-12-04 11:21   ` Marc Zyngier
  0 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2015-12-04 11:21 UTC (permalink / raw)
  To: Pavel Fedin, kvmarm, kvm

Hi Pavel,

On 04/12/15 10:25, Pavel Fedin wrote:
> System register accesses also use zero register for Rt == 31, and
> therefore using it will also result in getting SP value instead. This
> patch makes them also using new accessors, introduced by the previous
> patch. Since register value is no longer directly associated with storage
> inside vCPU context structure, we introduce a dedicated storage for it in
> struct sys_reg_params.
> 
> This refactor also gets rid of "massive hack" in kvm_handle_cp_64().
> 
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> ---
>  arch/arm64/kvm/sys_regs.c            | 88 ++++++++++++++++++------------------
>  arch/arm64/kvm/sys_regs.h            |  4 +-
>  arch/arm64/kvm/sys_regs_generic_v8.c |  2 +-
>  3 files changed, 46 insertions(+), 48 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index e5f024e..7c9cd64 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -97,18 +97,17 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
>  			  struct sys_reg_params *p,
>  			  const struct sys_reg_desc *r)
>  {
> -	unsigned long val;
>  	bool was_enabled = vcpu_has_cache_enabled(vcpu);
>  
>  	BUG_ON(!p->is_write);
>  
> -	val = *vcpu_reg(vcpu, p->Rt);
>  	if (!p->is_aarch32) {
> -		vcpu_sys_reg(vcpu, r->reg) = val;
> +		vcpu_sys_reg(vcpu, r->reg) = p->regval;
>  	} else {
>  		if (!p->is_32bit)
> -			vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
> -		vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
> +			vcpu_cp15_64_high(vcpu, r->reg) =
> +				upper_32_bits(p->regval);

nit: please keep the assignment on one line. My terminal expands way
beyond 80 chars, and the checkpatch police doesn't intimidate me! ;-)

> +		vcpu_cp15_64_low(vcpu, r->reg) = lower_32_bits(p->regval);
>  	}
>  
>  	kvm_toggle_cache(vcpu, was_enabled);
> @@ -125,13 +124,10 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
>  			   struct sys_reg_params *p,
>  			   const struct sys_reg_desc *r)
>  {
> -	u64 val;
> -
>  	if (!p->is_write)
>  		return read_from_write_only(vcpu, p);
>  
> -	val = *vcpu_reg(vcpu, p->Rt);
> -	vgic_v3_dispatch_sgi(vcpu, val);
> +	vgic_v3_dispatch_sgi(vcpu, p->regval);
>  
>  	return true;
>  }
> @@ -153,7 +149,7 @@ static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
>  	if (p->is_write) {
>  		return ignore_write(vcpu, p);
>  	} else {
> -		*vcpu_reg(vcpu, p->Rt) = (1 << 3);
> +		p->regval = (1 << 3);
>  		return true;
>  	}
>  }
> @@ -167,7 +163,7 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
>  	} else {
>  		u32 val;
>  		asm volatile("mrs %0, dbgauthstatus_el1" : "=r" (val));
> -		*vcpu_reg(vcpu, p->Rt) = val;
> +		p->regval = val;
>  		return true;
>  	}
>  }
> @@ -204,13 +200,13 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
>  			    const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> -		vcpu_sys_reg(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
> +		vcpu_sys_reg(vcpu, r->reg) = p->regval;
>  		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
>  	} else {
> -		*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, r->reg);
> +		p->regval = vcpu_sys_reg(vcpu, r->reg);
>  	}
>  
> -	trace_trap_reg(__func__, r->reg, p->is_write, *vcpu_reg(vcpu, p->Rt));
> +	trace_trap_reg(__func__, r->reg, p->is_write, p->regval);
>  
>  	return true;
>  }
> @@ -228,7 +224,7 @@ static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
>  			      struct sys_reg_params *p,
>  			      u64 *dbg_reg)
>  {
> -	u64 val = *vcpu_reg(vcpu, p->Rt);
> +	u64 val = p->regval;
>  
>  	if (p->is_32bit) {
>  		val &= 0xffffffffUL;
> @@ -243,12 +239,9 @@ static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
>  			      struct sys_reg_params *p,
>  			      u64 *dbg_reg)
>  {
> -	u64 val = *dbg_reg;
> -
> +	p->regval = *dbg_reg;
>  	if (p->is_32bit)
> -		val &= 0xffffffffUL;
> -
> -	*vcpu_reg(vcpu, p->Rt) = val;
> +		p->regval &= 0xffffffffUL;
>  }
>  
>  static inline bool trap_bvr(struct kvm_vcpu *vcpu,
> @@ -697,10 +690,10 @@ static bool trap_dbgidr(struct kvm_vcpu *vcpu,
>  		u64 pfr = read_system_reg(SYS_ID_AA64PFR0_EL1);
>  		u32 el3 = !!cpuid_feature_extract_field(pfr, ID_AA64PFR0_EL3_SHIFT);
>  
> -		*vcpu_reg(vcpu, p->Rt) = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
> -					  (((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
> -					  (((dfr >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) << 20) |
> -					  (6 << 16) | (el3 << 14) | (el3 << 12));
> +		p->regval = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
> +			     (((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
> +			     (((dfr >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) << 20)
> +			     | (6 << 16) | (el3 << 14) | (el3 << 12));
>  		return true;
>  	}
>  }
> @@ -710,10 +703,10 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
>  			 const struct sys_reg_desc *r)
>  {
>  	if (p->is_write) {
> -		vcpu_cp14(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
> +		vcpu_cp14(vcpu, r->reg) = p->regval;
>  		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
>  	} else {
> -		*vcpu_reg(vcpu, p->Rt) = vcpu_cp14(vcpu, r->reg);
> +		p->regval = vcpu_cp14(vcpu, r->reg);
>  	}
>  
>  	return true;
> @@ -740,12 +733,12 @@ static inline bool trap_xvr(struct kvm_vcpu *vcpu,
>  		u64 val = *dbg_reg;
>  
>  		val &= 0xffffffffUL;
> -		val |= *vcpu_reg(vcpu, p->Rt) << 32;
> +		val |= p->regval << 32;
>  		*dbg_reg = val;
>  
>  		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
>  	} else {
> -		*vcpu_reg(vcpu, p->Rt) = *dbg_reg >> 32;
> +		p->regval = *dbg_reg >> 32;
>  	}
>  
>  	trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
> @@ -1062,12 +1055,12 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
>  {
>  	struct sys_reg_params params;
>  	u32 hsr = kvm_vcpu_get_hsr(vcpu);
> +	int Rt = (hsr >> 5) & 0xf;
>  	int Rt2 = (hsr >> 10) & 0xf;
>  
>  	params.is_aarch32 = true;
>  	params.is_32bit = false;
>  	params.CRm = (hsr >> 1) & 0xf;
> -	params.Rt = (hsr >> 5) & 0xf;
>  	params.is_write = ((hsr & 1) == 0);
>  
>  	params.Op0 = 0;
> @@ -1076,15 +1069,12 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
>  	params.CRn = 0;
>  
>  	/*
> -	 * Massive hack here. Store Rt2 in the top 32bits so we only
> -	 * have one register to deal with. As we use the same trap
> +	 * Make a 64-bit value out of Rt and Rt2. As we use the same trap
>  	 * backends between AArch32 and AArch64, we get away with it.
>  	 */
>  	if (params.is_write) {
> -		u64 val = *vcpu_reg(vcpu, params.Rt);
> -		val &= 0xffffffff;
> -		val |= *vcpu_reg(vcpu, Rt2) << 32;
> -		*vcpu_reg(vcpu, params.Rt) = val;
> +		params.regval = vcpu_get_reg(vcpu, Rt) & 0xffffffff;
> +		params.regval |= vcpu_get_reg(vcpu, Rt2) << 32;
>  	}
>  
>  	if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
> @@ -1095,11 +1085,10 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
>  	unhandled_cp_access(vcpu, &params);
>  
>  out:
> -	/* Do the opposite hack for the read side */
> +	/* Split up the value between registers for the read side */
>  	if (!params.is_write) {
> -		u64 val = *vcpu_reg(vcpu, params.Rt);
> -		val >>= 32;
> -		*vcpu_reg(vcpu, Rt2) = val;
> +		vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval));
> +		vcpu_set_reg(vcpu, Rt2, upper_32_bits(params.regval));
>  	}
>  
>  	return 1;
> @@ -1118,21 +1107,24 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
>  {
>  	struct sys_reg_params params;
>  	u32 hsr = kvm_vcpu_get_hsr(vcpu);
> +	int Rt  = (hsr >> 5) & 0xf;
>  
>  	params.is_aarch32 = true;
>  	params.is_32bit = true;
>  	params.CRm = (hsr >> 1) & 0xf;
> -	params.Rt  = (hsr >> 5) & 0xf;
> +	params.regval = vcpu_get_reg(vcpu, Rt);
>  	params.is_write = ((hsr & 1) == 0);
>  	params.CRn = (hsr >> 10) & 0xf;
>  	params.Op0 = 0;
>  	params.Op1 = (hsr >> 14) & 0x7;
>  	params.Op2 = (hsr >> 17) & 0x7;
>  
> -	if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
> -		return 1;
> -	if (!emulate_cp(vcpu, &params, global, nr_global))
> +	if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
> +	    !emulate_cp(vcpu, &params, global, nr_global)) {
> +		if (!params.is_write)
> +			vcpu_set_reg(vcpu, Rt, params.regval);
>  		return 1;
> +	}
>  
>  	unhandled_cp_access(vcpu, &params);
>  	return 1;
> @@ -1230,6 +1222,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  {
>  	struct sys_reg_params params;
>  	unsigned long esr = kvm_vcpu_get_hsr(vcpu);
> +	int Rt = (esr >> 5) & 0x1f;
> +	int ret;
>  
>  	trace_kvm_handle_sys_reg(esr);
>  
> @@ -1240,10 +1234,14 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  	params.CRn = (esr >> 10) & 0xf;
>  	params.CRm = (esr >> 1) & 0xf;
>  	params.Op2 = (esr >> 17) & 0x7;
> -	params.Rt = (esr >> 5) & 0x1f;
> +	params.regval = vcpu_get_reg(vcpu, Rt);
>  	params.is_write = !(esr & 1);
>  
> -	return emulate_sys_reg(vcpu, &params);
> +	ret = emulate_sys_reg(vcpu, &params);
> +
> +	if (!params.is_write)
> +		vcpu_set_reg(vcpu, Rt, params.regval);
> +	return ret;
>  }
>  
>  /******************************************************************************
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 6c251ab..86ed945 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -28,7 +28,7 @@ struct sys_reg_params {
>  	u8	CRn;
>  	u8	CRm;
>  	u8	Op2;
> -	u8	Rt;
> +	u64	regval;
>  	bool	is_write;
>  	bool	is_aarch32;
>  	bool	is_32bit;	/* Only valid if is_aarch32 is true */
> @@ -79,7 +79,7 @@ static inline bool ignore_write(struct kvm_vcpu *vcpu,
>  static inline bool read_zero(struct kvm_vcpu *vcpu,
>  			     struct sys_reg_params *p)
>  {
> -	*vcpu_reg(vcpu, p->Rt) = 0;
> +	p->regval = 0;
>  	return true;
>  }
>  
> diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c
> index ccd3e35..ed90578 100644
> --- a/arch/arm64/kvm/sys_regs_generic_v8.c
> +++ b/arch/arm64/kvm/sys_regs_generic_v8.c
> @@ -37,7 +37,7 @@ static bool access_actlr(struct kvm_vcpu *vcpu,
>  	if (p->is_write)
>  		return ignore_write(vcpu, p);
>  
> -	*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, ACTLR_EL1);
> +	p->regval = vcpu_sys_reg(vcpu, ACTLR_EL1);
>  	return true;
>  }
>  
> 

Aside from the above nit, this looks good to me:

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 4/4] KVM: arm64: Get rid of old vcpu_reg()
  2015-12-04 10:26 ` [PATCH v2 4/4] KVM: arm64: Get rid of old vcpu_reg() Pavel Fedin
@ 2015-12-04 11:23   ` Marc Zyngier
  0 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2015-12-04 11:23 UTC (permalink / raw)
  To: Pavel Fedin, kvmarm, kvm

On 04/12/15 10:26, Pavel Fedin wrote:
> Using oldstyle vcpu_reg() accessor is proven to be inappropriate and
> unsafe on ARM64. This patch converts the rest of use cases to new
> accessors and completely removes vcpu_reg() on ARM64.
> 
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers
  2015-12-04 10:25 [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Pavel Fedin
                   ` (3 preceding siblings ...)
  2015-12-04 10:26 ` [PATCH v2 4/4] KVM: arm64: Get rid of old vcpu_reg() Pavel Fedin
@ 2015-12-04 11:28 ` Marc Zyngier
  2015-12-04 11:58   ` Pavel Fedin
  4 siblings, 1 reply; 11+ messages in thread
From: Marc Zyngier @ 2015-12-04 11:28 UTC (permalink / raw)
  To: Pavel Fedin, kvmarm, kvm

On 04/12/15 10:25, Pavel Fedin wrote:
> ARM64 CPU has zero register which is read-only, with a value of 0.
> However, KVM currently incorrectly recognizes it being SP (because
> Rt == 31, and in struct user_pt_regs 'regs' array is followed by SP),
> resulting in invalid value being read, or even SP corruption on write.
> 
> The problem has been discovered by performing an operation
> 
>  *((volatile int *)reg) = 0;
> 
> which compiles as "str xzr, [xx]", and resulted in strange values being
> written.
> 
> v1 => v2:
> - Changed type of transfer value to u64 and store it directly in
>   struct sys_reg_params instead of a pointer
> - Use lower_32_bits()/upper_32_bits() where appropriate
> - Fixed wrong usage of 'Rt' instead of 'Rt2' in kvm_handle_cp_64(),
>   overlooked in v1
> - Do not write value back when reading

[+Christoffer]

Hi Pavel,

Thanks a lot for respining this quickly. I just had a few minor
comments, so this is almost ready to go. If you can fix that (and
assuming nobody has any further objection), we'll try to get this queued
ASAP.

Cheers,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params
  2015-12-04 11:15   ` Marc Zyngier
@ 2015-12-04 11:29     ` Pavel Fedin
  0 siblings, 0 replies; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 11:29 UTC (permalink / raw)
  To: 'Marc Zyngier', kvmarm, kvm

 Hello!

> I think you are being a bit overzealous here, and a few const can
> legitimately be kept, see below.

 :) Yes, i've just commanded "search and replace" to the editor. Fixing...

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia



^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers
  2015-12-04 11:28 ` [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Marc Zyngier
@ 2015-12-04 11:58   ` Pavel Fedin
  0 siblings, 0 replies; 11+ messages in thread
From: Pavel Fedin @ 2015-12-04 11:58 UTC (permalink / raw)
  To: 'Marc Zyngier', kvmarm, kvm; +Cc: 'Christoffer Dall'

 Hello!

> Thanks a lot for respining this quickly. I just had a few minor
> comments, so this is almost ready to go. If you can fix that

 Damn, the rest of reviews got stuck somewhere and arrived later, so i've just sent v3 without wrap fix. Will correct it.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-12-04 11:58 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-04 10:25 [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Pavel Fedin
2015-12-04 10:25 ` [PATCH v2 1/4] KVM: arm64: Correctly handle zero register during MMIO Pavel Fedin
2015-12-04 10:25 ` [PATCH v2 2/4] KVM: arm64: Remove const from struct sys_reg_params Pavel Fedin
2015-12-04 11:15   ` Marc Zyngier
2015-12-04 11:29     ` Pavel Fedin
2015-12-04 10:25 ` [PATCH v2 3/4] KVM: arm64: Correctly handle zero register in system register accesses Pavel Fedin
2015-12-04 11:21   ` Marc Zyngier
2015-12-04 10:26 ` [PATCH v2 4/4] KVM: arm64: Get rid of old vcpu_reg() Pavel Fedin
2015-12-04 11:23   ` Marc Zyngier
2015-12-04 11:28 ` [PATCH v2 0/4] KVM: arm64: BUG FIX: Correctly handle zero register transfers Marc Zyngier
2015-12-04 11:58   ` Pavel Fedin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.