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

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

 



On Mon, Mar 12, 2012 at 8:18 PM, Rusty Russell <rusty at rustcorp.com.au> wrote:
> 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.
>

looks definitely better. Take a look at my attempt to mangle it in the
v7 series as well and let me know which you prefer. I am undecided at
this point.

> (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 :)
>

awesome

>> > +
>> > + ? ? ? ? ? ? ? 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).
>

ok, well, let's do it this way and see if it's a bottle-neck when we
have hardware.

>> > +
>> > + ? ? ? ? ? ? ? /* If function fails, it should complain. */
>>
>> questionable comment
>
> s/complain/print its own diagnostic/?
>

yeah, now I see why you had the comment in the first place

>> 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 :)
>

hehe, ok, I will mangle:)

-Christoffer



[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