Browse Source

[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>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
4c1f2486e6
1 changed files with 23 additions and 1 deletions
  1. 23
    1
      src/arch/x86/include/librm.h

+ 23
- 1
src/arch/x86/include/librm.h View File

@@ -89,6 +89,15 @@ extern const unsigned long virt_offset;
89 89
  */
90 90
 static inline __always_inline userptr_t
91 91
 UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
92
+
93
+	/* In a 64-bit build, any valid physical address is directly
94
+	 * usable as a virtual address, since the low 4GB is
95
+	 * identity-mapped.
96
+	 */
97
+	if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
98
+		return phys_addr;
99
+
100
+	/* In a 32-bit build, subtract virt_offset */
92 101
 	return ( phys_addr - virt_offset );
93 102
 }
94 103
 
@@ -101,7 +110,20 @@ UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
101 110
  */
102 111
 static inline __always_inline unsigned long
103 112
 UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
104
-	return ( userptr + offset + virt_offset );
113
+	unsigned long addr = ( userptr + offset );
114
+
115
+	/* In a 64-bit build, any virtual address in the low 4GB is
116
+	 * directly usable as a physical address, since the low 4GB is
117
+	 * identity-mapped.
118
+	 */
119
+	if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
120
+	     ( addr <= 0xffffffffUL ) )
121
+		return addr;
122
+
123
+	/* In a 32-bit build or in a 64-bit build with a virtual
124
+	 * address above 4GB: add virt_offset
125
+	 */
126
+	return ( addr + virt_offset );
105 127
 }
106 128
 
107 129
 static inline __always_inline userptr_t

Loading…
Cancel
Save