From: christoffer.dall@linaro.org (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH] arm/arm64: KVM: Fix BE accesses to GICv2 EISR and ELRSR regs
Date: Wed, 1 Oct 2014 19:45:52 +0200 [thread overview]
Message-ID: <20141001174552.GA12519@cbox> (raw)
In-Reply-To: <542C31FE.9080609@arm.com>
Hi Andre,
On Wed, Oct 01, 2014 at 05:55:26PM +0100, Andre Przywara wrote:
> Hi Christoffer,
>
> On 28/09/14 15:04, Christoffer Dall wrote:
> > The EIRSR and ELRSR registers are 32-bit registers on GICv2, and we
> > store these as an array of two such registers on the vgic vcpu struct.
> > However, we access them as a single 64-bit value or as a bitmap pointer
> > in the generic vgic code, which breaks BE support.
> >
> > Instead, store them as u64 values on the vgic structure and do the
> > word-swapping in the assembly code, which already handles the byte order
> > for BE systems.
>
> I am wondering if that approach isn't too involved.
> EISR and ELRSR are 32-bit registers, and AFAIK the GIC is always LE on
> the hardware side. So by claiming we have a 64bit register we introduce
> too much hassle, right?
You have to deal with this mess somehow, the question is just where.
> Wouldn't it be better to just fix the registers shortly before we
> actually use them?
if you're looking at it isolated, I agree completely, having those two
32-bit registers in the struct would be 'nicer'. However, we already
jump through a lot of hoops here to store things in a way that makes it
possible for us to share code between 32-bit and 64-bit and between
gicv2 and gicv3, so it's not completely out of line.
> With my limited endianess experience: Wouldn't this patch solve the EISR
> part (copy & pasted, so "for eyes only" ;-)
>
> @@ -92,13 +89,10 @@ static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu)
> {
> u64 val;
>
> -#if BITS_PER_LONG == 64
> - val = vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[1];
> + val = le32_to_cpu(vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[1]);
don't do this - the reverse instructions for dealing with the inner-word
endianness already takes place in the assembly code, so that's not the
problem.
> val <<= 32;
> - val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[0];
> -#else
> - val = *(u64 *)vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr;
> -#endif
> + val |= le32_to_cpu(vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[0]);
what that whole block above does, is that when an unsigned long is 64
bits, if you just convert the &eisr[0] pointer to an unsigned long *,
you'll get this on a LE system:
| 63 .................. 32 | 31 .................. 0 |
| eisr[1] | eisr[0] |
which is what you want, but on a BE system, you'll get:
| 63 .................. 32 | 31 .................. 0 |
| eisr[0] | eisr[1] |
which is obviously not what the caller expects. The current code block
(before my patch) always gives you the first one, which is what you'd
want.
> +
> return val;
> }
>
> (BTW: Wasn't that 64 bit optimization path the wrong way round here?)
Not sure I understand your question?
>
> Please bear with me if this is complete nonsense, could well twisted my
> mind once too much ;-)
>
> Still thinking about a clever solution for that strange sync_elrsr()
> thing ...
>
You have to factor that into the equation and not split up the things,
that's where I think you go wrong.
I tried to do what you asked before, but it becomes a bloody mess, with
a more convoluted patch and resulting code path than what I suggest,
IMHO.
Try to write out the whole thing yourself and be very careful that
you're getting it right.
If you can come up with a way that works with the callers using
for_each_set_bit() (open-coding that one doesn't exactly make that
twited vgic code any more pretty), then I'll be very happy to throw this
away and take yours.
Happy brain twisting :)
Thanks for looking at this stuff.
-Christoffer
WARNING: multiple messages have this Message-ID (diff)
From: Christoffer Dall <christoffer.dall@linaro.org>
To: Andre Przywara <andre.przywara@arm.com>
Cc: kvmarm@lists.cs.columbia.edu,
linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org
Subject: Re: [RFC PATCH] arm/arm64: KVM: Fix BE accesses to GICv2 EISR and ELRSR regs
Date: Wed, 1 Oct 2014 19:45:52 +0200 [thread overview]
Message-ID: <20141001174552.GA12519@cbox> (raw)
In-Reply-To: <542C31FE.9080609@arm.com>
Hi Andre,
On Wed, Oct 01, 2014 at 05:55:26PM +0100, Andre Przywara wrote:
> Hi Christoffer,
>
> On 28/09/14 15:04, Christoffer Dall wrote:
> > The EIRSR and ELRSR registers are 32-bit registers on GICv2, and we
> > store these as an array of two such registers on the vgic vcpu struct.
> > However, we access them as a single 64-bit value or as a bitmap pointer
> > in the generic vgic code, which breaks BE support.
> >
> > Instead, store them as u64 values on the vgic structure and do the
> > word-swapping in the assembly code, which already handles the byte order
> > for BE systems.
>
> I am wondering if that approach isn't too involved.
> EISR and ELRSR are 32-bit registers, and AFAIK the GIC is always LE on
> the hardware side. So by claiming we have a 64bit register we introduce
> too much hassle, right?
You have to deal with this mess somehow, the question is just where.
> Wouldn't it be better to just fix the registers shortly before we
> actually use them?
if you're looking at it isolated, I agree completely, having those two
32-bit registers in the struct would be 'nicer'. However, we already
jump through a lot of hoops here to store things in a way that makes it
possible for us to share code between 32-bit and 64-bit and between
gicv2 and gicv3, so it's not completely out of line.
> With my limited endianess experience: Wouldn't this patch solve the EISR
> part (copy & pasted, so "for eyes only" ;-)
>
> @@ -92,13 +89,10 @@ static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu)
> {
> u64 val;
>
> -#if BITS_PER_LONG == 64
> - val = vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[1];
> + val = le32_to_cpu(vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[1]);
don't do this - the reverse instructions for dealing with the inner-word
endianness already takes place in the assembly code, so that's not the
problem.
> val <<= 32;
> - val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[0];
> -#else
> - val = *(u64 *)vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr;
> -#endif
> + val |= le32_to_cpu(vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[0]);
what that whole block above does, is that when an unsigned long is 64
bits, if you just convert the &eisr[0] pointer to an unsigned long *,
you'll get this on a LE system:
| 63 .................. 32 | 31 .................. 0 |
| eisr[1] | eisr[0] |
which is what you want, but on a BE system, you'll get:
| 63 .................. 32 | 31 .................. 0 |
| eisr[0] | eisr[1] |
which is obviously not what the caller expects. The current code block
(before my patch) always gives you the first one, which is what you'd
want.
> +
> return val;
> }
>
> (BTW: Wasn't that 64 bit optimization path the wrong way round here?)
Not sure I understand your question?
>
> Please bear with me if this is complete nonsense, could well twisted my
> mind once too much ;-)
>
> Still thinking about a clever solution for that strange sync_elrsr()
> thing ...
>
You have to factor that into the equation and not split up the things,
that's where I think you go wrong.
I tried to do what you asked before, but it becomes a bloody mess, with
a more convoluted patch and resulting code path than what I suggest,
IMHO.
Try to write out the whole thing yourself and be very careful that
you're getting it right.
If you can come up with a way that works with the callers using
for_each_set_bit() (open-coding that one doesn't exactly make that
twited vgic code any more pretty), then I'll be very happy to throw this
away and take yours.
Happy brain twisting :)
Thanks for looking at this stuff.
-Christoffer
next prev parent reply other threads:[~2014-10-01 17:45 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-28 14:04 [RFC PATCH] arm/arm64: KVM: Fix BE accesses to GICv2 EISR and ELRSR regs Christoffer Dall
2014-09-28 14:04 ` Christoffer Dall
2014-10-01 16:55 ` Andre Przywara
2014-10-01 16:55 ` Andre Przywara
2014-10-01 17:45 ` Christoffer Dall [this message]
2014-10-01 17:45 ` Christoffer Dall
2014-10-14 9:47 ` Marc Zyngier
2014-10-14 9:47 ` Marc Zyngier
2014-10-14 15:21 ` Victor Kamensky
2014-10-14 15:21 ` Victor Kamensky
2014-10-15 23:54 ` Victor Kamensky
2014-10-15 23:54 ` Victor Kamensky
2014-10-16 8:48 ` Christoffer Dall
2014-10-16 8:48 ` Christoffer Dall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141001174552.GA12519@cbox \
--to=christoffer.dall@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.