[Android-virt] [PATCH 6/8] ARM: KVM: table-driven coprocessor emulation.

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

 



On Sun, 11 Mar 2012 19:33:10 -0400, Christoffer Dall <c.dall at virtualopensystems.com> wrote:
>  On Fri, Mar 9, 2012 at 10:44 PM, Rusty Russell <rusty at rustcorp.com.au> wrote:
> > + ? ? ? /* The CP15 c15 register is architecturally implementation
> > + ? ? ? ?* defined, but some guest kernels attempt to read/write a
> > + ? ? ? ?* diagnostics register here. We always return 0 and ignore
> > + ? ? ? ?* writes and hope for the best. */
> 
> this is technically not kernel style comments is it...

Indeed, a bad habit of mine.

> > + ? ? ? { .is_64 = false, .is_w = true, .f = ignore_write, .arg = 1,
> > + ? ? ? ? .param = { .CRn = 15, .CRm = ANY, .Op1 = ANY, .Op2 = ANY } },
> > + ? ? ? { .is_64 = false, .is_w = false, .f = read_zero, .arg = 1,
> > + ? ? ? ? .param = { .CRn = 15, .CRm = ANY, .Op1 = ANY, .Op2 = ANY } },
> > +};
> 
> The overall idea is good, but I personally find this table quite messy
> looking. It's really hard to peak into it and see exactly what's going
> on. Perhaps it helps with the right syntax coloring, but not everyone
> uses that.
> 
> I tried a few things, but nothing really works great. Perhaps using a
> macro that makes the 64,w,f,a arguments shorter and indenting the
> setting of those so .param values like CRn does not have interfering
> lines between them would help. I'll give this is a try...

Yes, it's pretty messy... how's this, instead, which makes it read like
the asm does.   I can add extra param checks, too.  I reverted the
print_cp_instr() change too.

(compile tested only).

diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index bd2c3dc..cb838d0 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -167,17 +167,14 @@ struct coproc_params {
 
 static void print_cp_instr(const struct coproc_params *p)
 {
-	/* Look, we even formatted it for you to paste into the table! */
 	if (p->is_64bit) {
-		kvm_debug("{ .is_64bit = true, .is_write = %s, .param ="
-			  " { .CRm = %lu, .Op1 = %lu } }",
-			  p->is_write ? "true" : "false", p->CRm, p->Op1);
+		kvm_debug("%s\tp15, %lu, r%lu, r%lu, c%lu",
+			  (p->is_write) ? "mcrr" : "mrrc",
+			  p->Op1, p->Rt1, p->Rt2, p->CRm);
 	} else {
-		kvm_debug("{ .is_64bit = false, .is_write = %s, .param ="
-			  " { .CRn = %lu, .CRm = %lu,"
-			  " .Op1 = %lu, .Op2 = %lu } }",
-			  p->is_write ? "true" : "false",
-			  p->CRn, p->CRm, p->Op1, p->Op2);
+		kvm_debug("%s\tp15, %lu, r%lu, c%lu, c%lu, %lu",
+			  (p->is_write) ? "mcr" : "mrc",
+			  p->Op1, p->Rt1, p->CRn, p->CRm, p->Op2);
 	}
 }
 
@@ -237,17 +234,21 @@ static bool read_l2ctlr(struct kvm_vcpu *vcpu,
 	return true;
 }
 
-static bool access_cp15_reg(struct kvm_vcpu *vcpu,
-			    const struct coproc_params *p,
-			    unsigned long cp15_reg)
+static bool read_cp15_reg(struct kvm_vcpu *vcpu,
+			  const struct coproc_params *p,
+			  unsigned long cp15_reg)
 {
-	if (p->is_write)
-		vcpu->arch.cp15[cp15_reg] = *vcpu_reg(vcpu, p->Rt1);
-	else
-		*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[cp15_reg];
+	*vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[cp15_reg];
 	return true;
 }
 
+static bool write_cp15_reg(struct kvm_vcpu *vcpu,
+			   const struct coproc_params *p,
+			   unsigned long cp15_reg)
+{
+	vcpu->arch.cp15[cp15_reg] = *vcpu_reg(vcpu, p->Rt1);
+	return true;
+}
 
 /* Any field which is 0xFFFFFFFF == any. */
 #define ANY (-1UL)
@@ -267,42 +268,54 @@ struct coproc_emulate {
 	unsigned long arg;
 };
 
+#define MRC(p15, _Op1, Rt1, _CRn, _CRm, _Op2, fn, _arg)			\
+	{ .is_64 = false, .is_w = false, .f = (fn), .arg = (_arg),	\
+			.param = { .CRn = _CRn,				\
+				   .CRm = _CRm,				\
+				   .Op1 = _Op1,				\
+				   .Op2 = _Op2 } }
+#define MCR(p15, _Op1, Rt1, _CRn, _CRm, _Op2, fn, _arg)			\
+	{ .is_64 = false, .is_w = true, .f = (fn), .arg = (_arg),	\
+			.param = { .CRn = _CRn,				\
+				   .CRm = _CRm,				\
+				   .Op1 = _Op1,				\
+				   .Op2 = _Op2 } }
 
 static const struct coproc_emulate coproc_emulate[] = {
 	/* Ignore writes to L2CTLR access */
-	{ .is_64 = false, .is_w = true, .f = ignore_write,
-	  .param = { .CRn = 9, .CRm = 0, .Op1 = 1, .Op2 = 2 } },
-	{ .is_64 = false, .is_w = false, .f = read_l2ctlr,
-	  .param = { .CRn = 9, .CRm = 0, .Op1 = 1, .Op2 = 2 } },
+	MCR(p15, 1, ANY, 9, 0, 2, ignore_write, 0),
+	MRC(p15, 1, ANY, 9, 0, 2, read_l2ctlr, 0),
+
 	/* Hack alert!!! */
-	{ .is_64 = false, .is_w = true, .f = ignore_write,
-	  .param = { .CRn = 9, .CRm = ANY, .Op1 = ANY, .Op2 = ANY } },
-	{ .is_64 = false, .is_w = false, .f = read_zero,
-	  .param = { .CRn = 9, .CRm = ANY, .Op1 = ANY, .Op2 = ANY } },
+	MCR(p15, ANY, ANY, 9, ANY, ANY, ignore_write, 0),
+	MRC(p15, ANY, ANY, 9, ANY, ANY, read_zero, 0),
 
-	/* These CRn == 10 entries may not need to exist - if we can
+	/* 
+	 * These CRn == 10 entries may not need to exist - if we can
 	 * ignore guest attempts to tamper with TLB lockdowns then it
 	 * should be enough to store/restore the host/guest PRRR and
 	 * NMRR memory remap registers and allow guest direct access
-	 * to these registers. */
+	 * to these registers.
+	 */
 	/* TLB Lockdown operations - ignored */
-	{ .is_64 = false, .is_w = true, .f = ignore_write,
-	  .param = { .CRn = 10, .CRm = 0, .Op1 = ANY, .Op2 = ANY } },
-	{ .is_64 = false, .is_w = ANY, .f = access_cp15_reg,
-	  .arg = c10_PRRR,
-	  .param = { .CRn = 10, .CRm = 2, .Op1 = 0, .Op2 = 0 } },
-	{ .is_64 = false, .is_w = ANY, .f = access_cp15_reg,
-	  .arg = c10_NMRR,
-	  .param = { .CRn = 10, .CRm = 2, .Op1 = 0, .Op2 = 1 } },
-
-	/* The CP15 c15 register is architecturally implementation
+	MRC(p15, 0, ANY, 10, 0, ANY, ignore_write, 0),
+	MRC(p15, 0, ANY, 10, 1, ANY, ignore_write, 0),
+	MRC(p15, 0, ANY, 10, 4, ANY, ignore_write, 0),
+	MRC(p15, 0, ANY, 10, 8, ANY, ignore_write, 0),
+
+	MCR(p15, 0, ANY, 10, 2, 0, read_cp15_reg, c10_PRRR),
+	MRC(p15, 0, ANY, 10, 2, 0, write_cp15_reg, c10_PRRR),
+	MCR(p15, 0, ANY, 10, 2, 1, read_cp15_reg, c10_NMRR),
+	MRC(p15, 0, ANY, 10, 2, 1, write_cp15_reg, c10_NMRR),
+
+	/* 
+	 * The CP15 c15 register is architecturally implementation
 	 * defined, but some guest kernels attempt to read/write a
 	 * diagnostics register here. We always return 0 and ignore
-	 * writes and hope for the best. */
-	{ .is_64 = false, .is_w = true, .f = ignore_write, .arg = 1,
-	  .param = { .CRn = 15, .CRm = ANY, .Op1 = ANY, .Op2 = ANY } },
-	{ .is_64 = false, .is_w = false, .f = read_zero, .arg = 1,
-	  .param = { .CRn = 15, .CRm = ANY, .Op1 = ANY, .Op2 = ANY } },
+	 * writes and hope for the best.
+	 */
+	MCR(p15, ANY, ANY, 15, ANY, ANY, ignore_write, 1),
+	MRC(p15, ANY, ANY, 15, ANY, ANY, read_zero, 1),
 };
 
 static inline bool match(unsigned long val, unsigned long param)


> > + ? ? ? for (i = 0; i < ARRAY_SIZE(coproc_emulate); i++) {
> > + ? ? ? ? ? ? ? const struct coproc_emulate *e = &coproc_emulate[i];
> 
> e: entry, emulate? hmmm.

Yes :)

> > +
> > + ? ? ? ? ? ? ? if (!match(params->is_64bit, e->is_64))
> > + ? ? ? ? ? ? ? ? ? ? ? continue;
> > + ? ? ? ? ? ? ? if (!match(params->is_write, e->is_w))
> > + ? ? ? ? ? ? ? ? ? ? ? continue;
> > + ? ? ? ? ? ? ? if (!match(params->CRn, e->param.CRn))
> > + ? ? ? ? ? ? ? ? ? ? ? continue;
> > + ? ? ? ? ? ? ? if (!match(params->CRm, e->param.CRm))
> > + ? ? ? ? ? ? ? ? ? ? ? continue;
> > + ? ? ? ? ? ? ? if (!match(params->Op1, e->param.Op1))
> > + ? ? ? ? ? ? ? ? ? ? ? continue;
> > + ? ? ? ? ? ? ? if (!match(params->Op2, e->param.Op2))
> > + ? ? ? ? ? ? ? ? ? ? ? continue;
> 
> are you at all worried about a performance hit here?

Maybe, but there are many options.  One is to cache the hsr value in
kvm_handle_cp15_32, for example.  Another is binary search.  Another is
to reorder the table staticly, and a final one is to do so dynamically
(with something like RCU).

> > +
> > + ? ? ? ? ? ? ? /* If function fails, it should complain. */
> 
> questionable comment

s/complain/print its own diagnostic/?

> I'll merge this for the next patch series and we can think about
> refining it from there.

Please never hesitate to mangle my patches beyond recognition.  It's
more efficient to assume we agree, and if I really hate something, I can
counter-patch :)

Thanks!
Rusty.
-- 
  How could I marry someone with more hair than me?  http://baldalex.org



[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