Message ID | 1470194119.12584.43.camel@kernel.crashing.org |
---|---|
State | New |
Headers | show |
On 3 August 2016 at 04:15, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote: > The current constructs ends up cropping the host address to 32-bit > which crashes for me running 32-bit ppc programs on an x86_64. > > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> > --- > > Not sure who to CC for this... > > include/exec/cpu_ldst.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h > index 6eb5fe8..0164535 100644 > --- a/include/exec/cpu_ldst.h > +++ b/include/exec/cpu_ldst.h > @@ -49,7 +49,7 @@ > > #if defined(CONFIG_USER_ONLY) > /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ > -#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + guest_base)) > +#define g2h(x) ((void *)(guest_base + (unsigned long)(target_ulong)(x))) I'm confused. Is this just swapping the order of the operands to '+'? I wouldn't expect that to make any difference because typecast has higher precedence than '+'... I run 32-bit (ARM) programs on x86-64 a lot so I would be surprised if g2h() was broken like this. thanks -- PMM
On Wed, 2016-08-03 at 09:40 +0100, Peter Maydell wrote: > > index 6eb5fe8..0164535 100644 > > --- a/include/exec/cpu_ldst.h > > +++ b/include/exec/cpu_ldst.h > > @@ -49,7 +49,7 @@ > > > > #if defined(CONFIG_USER_ONLY) > > /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ > > -#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + guest_base)) > > +#define g2h(x) ((void *)(guest_base + (unsigned long)(target_ulong)(x))) > > I'm confused. Is this just swapping the order of the operands to '+'? > I wouldn't expect that to make any difference because typecast has > higher precedence than '+'... The typecast to target_ulong which is 32-bits :-) > > I run 32-bit (ARM) programs on x86-64 a lot so I would be surprised > if g2h() was broken like this. I had a pretty clear breakage case, and this along with patch 1 fixed it. Cheers, Ben.
On Wed, 2016-08-03 at 19:50 +1000, Benjamin Herrenschmidt wrote: > > > I'm confused. Is this just swapping the order of the operands to > > '+'? > > I wouldn't expect that to make any difference because typecast has > > higher precedence than '+'... > > The typecast to target_ulong which is 32-bits :-) But you are right, this isn't the breakage. Patch 1/2 is sufficient to fix it, though I didn't realize it at first. "vaddr" is actually a typedef, so the whole tlb_vaddr_to_host() turned into a cast of guest_base to vaddr... The g2h part was just me being tired. It's true though that target_ulong is going to be 32-bits which I don't like but type promotion makes it work. So drop that patch and stick to patch 1/2 which is the real fix. As to why you don't hit the bug on ARM, well, maybe you don't many helpers using tlb_vaddr_to_host ? Also address randomization makes things hit or miss here ... Cheers, Ben.
On 3 August 2016 at 11:18, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote: > On Wed, 2016-08-03 at 19:50 +1000, Benjamin Herrenschmidt wrote: >> >> > I'm confused. Is this just swapping the order of the operands to >> > '+'? >> > I wouldn't expect that to make any difference because typecast has >> > higher precedence than '+'... >> >> The typecast to target_ulong which is 32-bits :-) > > But you are right, this isn't the breakage. Patch 1/2 is sufficient > to fix it, though I didn't realize it at first. > > "vaddr" is actually a typedef, so the whole tlb_vaddr_to_host() turned > into a cast of guest_base to vaddr... > > The g2h part was just me being tired. It's true though that > target_ulong is going to be 32-bits which I don't like but > type promotion makes it work. The cast to target_ulong is deliberate -- guest addresses should be that size and type, which is why we cast to it. Then we cast to unsigned long to zero-extend them to the size of a host address, before adding the guest_base. See commit 8d9dde9429d2b5b5 which added that cast to fix a problem where there was otherwise accidental sign extension in some uses of 32-bit-guest-on-64-bit-host. > So drop that patch and stick to patch 1/2 which is the real fix. > > As to why you don't hit the bug on ARM, well, maybe you don't > many helpers using tlb_vaddr_to_host ? Also address randomization makes > things hit or miss here ... The only uses of tlb_vaddr_to_host in the tree are (a) in a not-CONFIG_USER_ONLY codepath on target-arm (b) in target-s390x, which is a 64-bit guest thanks -- PMM
On Wed, 2016-08-03 at 11:48 +0100, Peter Maydell wrote: > > As to why you don't hit the bug on ARM, well, maybe you don't > > many helpers using tlb_vaddr_to_host ? Also address randomization makes > > things hit or miss here ... > > The only uses of tlb_vaddr_to_host in the tree are > (a) in a not-CONFIG_USER_ONLY codepath on target-arm > (b) in target-s390x, which is a 64-bit guest (c) a few new helpers using it on ppc that are in David's ppc-for-2.8 branch :-) Now we can put the fix in his branch if you prefer but it's a pretty trivial one so I would suggest just sticking it in. Cheers, Ben
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h index 6eb5fe8..0164535 100644 --- a/include/exec/cpu_ldst.h +++ b/include/exec/cpu_ldst.h @@ -49,7 +49,7 @@ #if defined(CONFIG_USER_ONLY) /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ -#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + guest_base)) +#define g2h(x) ((void *)(guest_base + (unsigned long)(target_ulong)(x))) #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS #define h2g_valid(x) 1
The current constructs ends up cropping the host address to 32-bit which crashes for me running 32-bit ppc programs on an x86_64. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- Not sure who to CC for this... include/exec/cpu_ldst.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)