diff options
author | Michael Brown <mcb30@ipxe.org> | 2016-02-21 11:37:37 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2016-02-21 11:37:37 +0000 |
commit | 4c1f2486e664e9c88164cfff917a99bfe6beed52 (patch) | |
tree | a87dfb2423a808d7121fe3dd1c51efa5349976b0 /src | |
parent | b6ebafe1bba5fa841c71a03f1a264e6a17ed8584 (diff) | |
download | ipxe-4c1f2486e664e9c88164cfff917a99bfe6beed52.zip ipxe-4c1f2486e664e9c88164cfff917a99bfe6beed52.tar.gz ipxe-4c1f2486e664e9c88164cfff917a99bfe6beed52.tar.bz2 |
[librm] Support userptr_t in 64-bit builds
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/x86/include/librm.h | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/arch/x86/include/librm.h b/src/arch/x86/include/librm.h index efc8b11..d6214ac 100644 --- a/src/arch/x86/include/librm.h +++ b/src/arch/x86/include/librm.h @@ -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 |