• Sricharan R's avatar
    ARM: mm: Correct virt_to_phys patching for 64 bit physical addresses · f52bb722
    Sricharan R authored
    The current phys_to_virt patching mechanism works only for 32 bit
    physical addresses and this patch extends the idea for 64bit physical
    addresses.
    
    The 64bit v2p patching mechanism patches the higher 8 bits of physical
    address with a constant using 'mov' instruction and lower 32bits are patched
    using 'add'. 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
        1) PA = 0x80000000; VA = 0xC0000000
           __pv_offset = PA - VA = 0xC0000000 (2's complement)
    
        2) PA = 0x2 80000000; VA = 0xC000000
           __pv_offset = PA - VA = 0x1 C0000000
    
    So adding __pv_offset + VA should never result in a true overflow for (1).
    So in order to differentiate between a true carry, a __pv_offset is extended
    to 64bit and the upper 32bits will have 0xffffffff if __pv_offset is
    2's complement. So 'mvn #0' is inserted instead of 'mov' while patching
    for the same reason. Since mov, add, sub instruction are to patched
    with different constants inside the same stub, the rotation field
    of the opcode is using to differentiate between them.
    
    So the above examples for v2p translation becomes for VA=0xC0000000,
        1) PA[63:32] = 0xffffffff
           PA[31:0] = VA + 0xC0000000 --> results in a carry
           PA[63:32] = PA[63:32] + carry
    
           PA[63:0] = 0x0 80000000
    
        2) PA[63:32] = 0x1
           PA[31:0] = VA + 0xC0000000 --> results in a carry
           PA[63:32] = PA[63:32] + carry
    
           PA[63:0] = 0x2 80000000
    
    The above ideas were suggested by Nicolas Pitre <nico@linaro.org> as
    part of the review of first and second versions of the subject patch.
    
    There is no corresponding change on the phys_to_virt() side, because
    computations on the upper 32-bits would be discarded anyway.
    
    Cc: Russell King <linux@arm.linux.org.uk>
    Reviewed-by: default avatarNicolas Pitre <nico@linaro.org>
    Signed-off-by: default avatarSricharan R <r.sricharan@ti.com>
    Signed-off-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
    f52bb722
head.S 16.8 KB