Thread (22 messages) 22 messages, 3 authors, 2013-07-25
STALE4714d

[PATCH 6/8] ARM: mm: LPAE: Correct virt_to_phys patching for 64 bit physical addresses

From: Nicolas Pitre <hidden>
Date: 2013-07-24 02:49:03

On Tue, 23 Jul 2013, Santosh Shilimkar wrote:
On Tuesday 23 July 2013 09:10 PM, Nicolas Pitre wrote:
quoted
On Fri, 21 Jun 2013, Santosh Shilimkar wrote:
quoted
From: Sricharan R <redacted>

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.
 
quoted
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.
quoted
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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help