]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[librm] Support userptr_t in 64-bit builds
authorMichael Brown <mcb30@ipxe.org>
Sun, 21 Feb 2016 11:37:37 +0000 (11:37 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sun, 21 Feb 2016 11:37:37 +0000 (11:37 +0000)
In a 64-bit build, the entirety of the 32-bit address space is
identity-mapped and so any valid physical address may immediately be
used as a virtual address.  Conversely, a virtual address that is
already within the 32-bit address space may immediately be used as a
physical address.

A valid virtual address that lies outside the 32-bit address space
must be an address within .textdata, and so can be converted to a
physical address by adding virt_offset.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/include/librm.h

index efc8b114af5b7eaa22d28e053b69fbfa2898547d..d6214ac809fcb372dbc119a28abc9f8c921dfc19 100644 (file)
@@ -89,6 +89,15 @@ extern const unsigned long virt_offset;
  */
 static inline __always_inline userptr_t
 UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
+
+       /* In a 64-bit build, any valid physical address is directly
+        * usable as a virtual address, since the low 4GB is
+        * identity-mapped.
+        */
+       if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
+               return phys_addr;
+
+       /* In a 32-bit build, subtract virt_offset */
        return ( phys_addr - virt_offset );
 }
 
@@ -101,7 +110,20 @@ UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
  */
 static inline __always_inline unsigned long
 UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
-       return ( userptr + offset + virt_offset );
+       unsigned long addr = ( userptr + offset );
+
+       /* In a 64-bit build, any virtual address in the low 4GB is
+        * directly usable as a physical address, since the low 4GB is
+        * identity-mapped.
+        */
+       if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
+            ( addr <= 0xffffffffUL ) )
+               return addr;
+
+       /* In a 32-bit build or in a 64-bit build with a virtual
+        * address above 4GB: add virt_offset
+        */
+       return ( addr + virt_offset );
 }
 
 static inline __always_inline userptr_t