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
  */
89
  */
90
 static inline __always_inline userptr_t
90
 static inline __always_inline userptr_t
91
 UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
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
 	return ( phys_addr - virt_offset );
101
 	return ( phys_addr - virt_offset );
93
 }
102
 }
94
 
103
 
101
  */
110
  */
102
 static inline __always_inline unsigned long
111
 static inline __always_inline unsigned long
103
 UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
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
 static inline __always_inline userptr_t
129
 static inline __always_inline userptr_t

Loading…
Cancel
Save