[PATCH 6/8] ARM: mm: LPAE: Correct virt_to_phys patching for 64 bit physical addresses
Nicolas Pitre
nicolas.pitre at linaro.org
Tue Jul 23 22:49:03 EDT 2013
On Tue, 23 Jul 2013, Santosh Shilimkar wrote:
> On Tuesday 23 July 2013 09:10 PM, Nicolas Pitre wrote:
> > On Fri, 21 Jun 2013, Santosh Shilimkar wrote:
> >
> >> From: Sricharan R <r.sricharan at ti.com>
> >>
> >> The current phys_to_virt patching mechanism does not work
> >> for 64 bit physical addressesp. Note that constant used in add/sub
> >> instructions is encoded in to the last 8 bits of the opcode. So shift
> >> the _pv_offset constant by 24 to get it in to the correct place.
> >>
> >> The v2p patching mechanism patches the higher 32bits of physical
> >> address with a constant. While this is correct, in those platforms
> >> where the lowmem addressable physical memory spawns across 4GB boundary,
> >> a carry bit can be produced as a result of addition of lower 32bits.
> >> This has to be taken in to account and added in to the upper. The patched
> >> __pv_offset and va are added in lower 32bits, where __pv_offset can be
> >> in two's complement form when PA_START < VA_START and that can result
> >> in a false carry bit.
> >>
> >> e.g PA = 0x80000000 VA = 0xC0000000
> >> __pv_offset = PA - VA = 0xC0000000 (2's complement)
> >>
> >> So adding __pv_offset + VA should never result in a true overflow. So in
> >> order to differentiate between a true carry, a extra flag __pv_sign_flag
> >> is introduced.
> >
> First of all thanks for the review.
>
> > I'm still wondering if this is worth bothering about.
> >
> > If PA = 0x80000000 and VA = 0xC0000000 there will never be a real carry
> > to propagate to the high word of the physical address as the VA space
> > cannot be larger than 0x40000000.
> >
> Agreed.
>
> > So is there really a case where:
> >
> > 1) physical memory is crossing the 4GB mark, and ...
> >
> > 2) physical memory start address is higher than virtual memory start
> > address needing a carry due to the 32-bit add overflow?
> >
> Consider below two cases of memory layout apart from one mentioned
> above where the carry is bit irrelevant as you rightly said.
>
> 1) PA = 0x8_0000_0000, VA= 0xC000_0000, absolute pv_offset = 0x7_4000_0000
This can be patched as:
mov phys_hi, #0x8
add phys_lo, virt, #0x40000000 @ carry ignored
> 2) PA = 0x2_8000_0000, VA= 0xC000_000, absolute pv_offset = 0x1_C000_0000
mov phys_hi, #0x2
add phys_lo, virt, #0xc0000000 @ carry ignored
> In both of these cases there a true carry which needs to be
> considered.
Well, not really. However, if you have:
3) PA = 0x2_8000_0000, VA = 0x4000-0000, pv_offset = 0x2-4000-0000
... then you need:
mov phys_hi, #0x2
adds phys_lo, virt, #0x40000000
adc phys_hi, phys_hi, #0
My question is: how likely is this?
What is your actual physical memory start address?
If we really need to cope with the carry, then the __pv_sign_flag should
instead be represented in pv_offset directly:
Taking example #2 above, that would be:
mov phys_hi, #0x1
adds phys_lo, virt, #0xc0000000
adc phys_hi, phys_hi, #0
If PA = 0x8000-0000 and VA = 0xc000-0000 then pv_offset is
0xffff-ffff-c000-0000, meaning:
mvn phys_hi, #0
add phys_lo, virt, #0xc0000000
adc phys_hi, phys_hi, #0
So that would require a special case in the patching code where a mvn
with 0 is used if the high part of pv_offset is 0xffffffff.
Nicolas
More information about the linux-arm-kernel
mailing list