iPXE
librm.h
Go to the documentation of this file.
1 #ifndef LIBRM_H
2 #define LIBRM_H
3 
4 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
5 
6 /* Segment selectors as used in our protected-mode GDTs.
7  *
8  * Don't change these unless you really know what you're doing.
9  */
10 #define VIRTUAL_CS 0x08
11 #define VIRTUAL_DS 0x10
12 #define PHYSICAL_CS 0x18
13 #define PHYSICAL_DS 0x20
14 #define REAL_CS 0x28
15 #define REAL_DS 0x30
16 #define P2R_DS 0x38
17 #define LONG_CS 0x40
18 
19 /* Calculate symbol address within VIRTUAL_CS or VIRTUAL_DS
20  *
21  * In a 64-bit build, we set the bases of VIRTUAL_CS and VIRTUAL_DS
22  * such that truncating a .textdata symbol value to 32 bits gives a
23  * valid 32-bit virtual address.
24  *
25  * The C code is compiled with -mcmodel=kernel and so we must place
26  * all .textdata symbols within the negative 2GB of the 64-bit address
27  * space. Consequently, all .textdata symbols will have the MSB set
28  * after truncation to 32 bits. This means that a straightforward
29  * R_X86_64_32 relocation record for the symbol will fail, since the
30  * truncated symbol value will not correctly zero-extend to the
31  * original 64-bit value.
32  *
33  * Using an R_X86_64_32S relocation record would work, but there is no
34  * (sensible) way to generate these relocation records within 32-bit
35  * or 16-bit code.
36  *
37  * The simplest solution is to generate an R_X86_64_32 relocation
38  * record with an addend of (-0xffffffff00000000). Since all
39  * .textdata symbols are within the negative 2GB of the 64-bit address
40  * space, this addend acts to effectively truncate the symbol to 32
41  * bits, thereby matching the semantics of the R_X86_64_32 relocation
42  * records generated for 32-bit and 16-bit code.
43  *
44  * In a 32-bit build, this problem does not exist, and we can just use
45  * the .textdata symbol values directly.
46  */
47 #ifdef __x86_64__
48 #define VIRTUAL(address) ( (address) - 0xffffffff00000000 )
49 #else
50 #define VIRTUAL(address) (address)
51 #endif
52 
53 #ifdef ASSEMBLY
54 
55 /**
56  * Call C function from real-mode code
57  *
58  * @v function C function
59  */
60 .macro virtcall function
61  pushl $VIRTUAL(\function)
62  call virt_call
63 .endm
64 
65 #else /* ASSEMBLY */
66 
67 #ifdef UACCESS_LIBRM
68 #define UACCESS_PREFIX_librm
69 #else
70 #define UACCESS_PREFIX_librm __librm_
71 #endif
72 
73 /**
74  * Call C function from real-mode code
75  *
76  * @v function C function
77  */
78 #define VIRT_CALL( function ) \
79  "pushl $( " _S2 ( VIRTUAL ( function ) ) " )\n\t" \
80  "call virt_call\n\t"
81 
82 /* Variables in librm.S */
83 extern const unsigned long virt_offset;
84 
85 /**
86  * Convert physical address to user pointer
87  *
88  * @v phys_addr Physical address
89  * @ret userptr User pointer
90  */
91 static inline __always_inline userptr_t
92 UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
93 
94  /* In a 64-bit build, any valid physical address is directly
95  * usable as a virtual address, since the low 4GB is
96  * identity-mapped.
97  */
98  if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
99  return phys_addr;
100 
101  /* In a 32-bit build, subtract virt_offset */
102  return ( phys_addr - virt_offset );
103 }
104 
105 /**
106  * Convert user buffer to physical address
107  *
108  * @v userptr User pointer
109  * @v offset Offset from user pointer
110  * @ret phys_addr Physical address
111  */
112 static inline __always_inline unsigned long
114  unsigned long addr = ( userptr + offset );
115 
116  /* In a 64-bit build, any virtual address in the low 4GB is
117  * directly usable as a physical address, since the low 4GB is
118  * identity-mapped.
119  */
120  if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
121  ( addr <= 0xffffffffUL ) )
122  return addr;
123 
124  /* In a 32-bit build or in a 64-bit build with a virtual
125  * address above 4GB: add virt_offset
126  */
127  return ( addr + virt_offset );
128 }
129 
130 static inline __always_inline userptr_t
131 UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
132  return trivial_virt_to_user ( addr );
133 }
134 
135 static inline __always_inline void *
136 UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
137  return trivial_user_to_virt ( userptr, offset );
138 }
139 
140 static inline __always_inline userptr_t
141 UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
142  return trivial_userptr_add ( userptr, offset );
143 }
144 
145 static inline __always_inline off_t
146 UACCESS_INLINE ( librm, userptr_sub ) ( userptr_t userptr,
148  return trivial_userptr_sub ( userptr, subtrahend );
149 }
150 
151 static inline __always_inline void
154  size_t len ) {
156 }
157 
158 static inline __always_inline void
161  size_t len ) {
163 }
164 
165 static inline __always_inline int
168  size_t len ) {
170 }
171 
172 static inline __always_inline void
174  int c, size_t len ) {
176 }
177 
178 static inline __always_inline size_t
180  return trivial_strlen_user ( buffer, offset );
181 }
182 
183 static inline __always_inline off_t
185  int c, size_t len ) {
186  return trivial_memchr_user ( buffer, offset, c, len );
187 }
188 
189 
190 /******************************************************************************
191  *
192  * Access to variables in .data16 and .text16
193  *
194  */
195 
196 extern char * const data16;
197 extern char * const text16;
198 
199 #define __data16( variable ) \
200  __attribute__ (( section ( ".data16" ) )) \
201  _data16_ ## variable __asm__ ( #variable )
202 
203 #define __data16_array( variable, array ) \
204  __attribute__ (( section ( ".data16" ) )) \
205  _data16_ ## variable array __asm__ ( #variable )
206 
207 #define __bss16( variable ) \
208  __attribute__ (( section ( ".bss16" ) )) \
209  _data16_ ## variable __asm__ ( #variable )
210 
211 #define __bss16_array( variable, array ) \
212  __attribute__ (( section ( ".bss16" ) )) \
213  _data16_ ## variable array __asm__ ( #variable )
214 
215 #define __text16( variable ) \
216  __attribute__ (( section ( ".text16.data" ) )) \
217  _text16_ ## variable __asm__ ( #variable )
218 
219 #define __text16_array( variable, array ) \
220  __attribute__ (( section ( ".text16.data" ) )) \
221  _text16_ ## variable array __asm__ ( #variable )
222 
223 #define __use_data16( variable ) \
224  ( * ( ( typeof ( _data16_ ## variable ) * ) \
225  & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
226 
227 #define __use_text16( variable ) \
228  ( * ( ( typeof ( _text16_ ## variable ) * ) \
229  & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
230 
231 #define __from_data16( pointer ) \
232  ( ( unsigned int ) \
233  ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) )
234 
235 #define __from_text16( pointer ) \
236  ( ( unsigned int ) \
237  ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) )
238 
239 /* Variables in librm.S, present in the normal data segment */
240 extern uint16_t rm_sp;
241 extern uint16_t rm_ss;
242 extern const uint16_t __text16 ( rm_cs );
243 #define rm_cs __use_text16 ( rm_cs )
244 extern const uint16_t __text16 ( rm_ds );
245 #define rm_ds __use_text16 ( rm_ds )
246 
248 extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
250 /* CODE_DEFAULT: restore default .code32/.code64 directive */
251 #ifdef __x86_64__
252 #define CODE_DEFAULT ".code64"
253 #define STACK_DEFAULT "q"
254 #else
255 #define CODE_DEFAULT ".code32"
256 #define STACK_DEFAULT "l"
257 #endif
259 /* LINE_SYMBOL: declare a symbol for the current source code line */
260 #define LINE_SYMBOL _S2 ( OBJECT ) "__line_" _S2 ( __LINE__ ) "__%=:"
262 /* TEXT16_CODE: declare a fragment of code that resides in .text16 */
263 #define TEXT16_CODE( asm_code_str ) \
264  ".section \".text16\", \"ax\", @progbits\n\t" \
265  "\n" LINE_SYMBOL "\n\t" \
266  ".code16\n\t" \
267  asm_code_str "\n\t" \
268  CODE_DEFAULT "\n\t" \
269  ".previous\n\t"
270 
271 /* REAL_CODE: declare a fragment of code that executes in real mode */
272 #define REAL_CODE( asm_code_str ) \
273  "push" STACK_DEFAULT " $1f\n\t" \
274  "call real_call\n\t" \
275  TEXT16_CODE ( "\n1:\n\t" \
276  asm_code_str \
277  "\n\t" \
278  "ret\n\t" )
279 
280 /* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
281 #define PHYS_CODE( asm_code_str ) \
282  "push" STACK_DEFAULT " $1f\n\t" \
283  "call phys_call\n\t" \
284  ".section \".text.phys\", \"ax\", @progbits\n\t"\
285  "\n" LINE_SYMBOL "\n\t" \
286  ".code32\n\t" \
287  "\n1:\n\t" \
288  asm_code_str \
289  "\n\t" \
290  "ret\n\t" \
291  CODE_DEFAULT "\n\t" \
292  ".previous\n\t"
293 
294 /** Number of interrupts */
295 #define NUM_INT 256
296 
297 /** A 32-bit interrupt descriptor table register */
298 struct idtr32 {
299  /** Limit */
301  /** Base */
303 } __attribute__ (( packed ));
304 
305 /** A 64-bit interrupt descriptor table register */
306 struct idtr64 {
307  /** Limit */
309  /** Base */
311 } __attribute__ (( packed ));
312 
313 /** A 32-bit interrupt descriptor table entry */
315  /** Low 16 bits of address */
317  /** Code segment */
319  /** Unused */
321  /** Type and attributes */
323  /** High 16 bits of address */
325 } __attribute__ (( packed ));
326 
327 /** A 64-bit interrupt descriptor table entry */
329  /** Low 16 bits of address */
331  /** Code segment */
333  /** Unused */
335  /** Type and attributes */
337  /** Middle 16 bits of address */
339  /** High 32 bits of address */
341  /** Reserved */
343 } __attribute__ (( packed ));
344 
345 /** Interrupt descriptor is present */
346 #define IDTE_PRESENT 0x80
347 
348 /** Interrupt descriptor 32-bit interrupt gate type */
349 #define IDTE_TYPE_IRQ32 0x0e
350 
351 /** Interrupt descriptor 64-bit interrupt gate type */
352 #define IDTE_TYPE_IRQ64 0x0e
353 
354 /** An interrupt vector
355  *
356  * Each interrupt vector comprises an eight-byte fragment of code:
357  *
358  * 50 pushl %eax (or pushq %rax in long mode)
359  * b0 xx movb $INT, %al
360  * e9 xx xx xx xx jmp interrupt_wrapper
361  */
363  /** "push" instruction */
365  /** "movb" instruction */
367  /** Interrupt number */
369  /** "jmp" instruction */
371  /** Interrupt wrapper address offset */
373  /** Next instruction after jump */
375 } __attribute__ (( packed ));
376 
377 /** "push %eax" instruction */
378 #define PUSH_INSN 0x50
379 
380 /** "movb" instruction */
381 #define MOVB_INSN 0xb0
382 
383 /** "jmp" instruction */
384 #define JMP_INSN 0xe9
385 
386 /** 32-bit interrupt wrapper stack frame */
404 } __attribute__ (( packed ));
405 
406 /** 64-bit interrupt wrapper stack frame */
428 } __attribute__ (( packed ));
429 
430 extern void set_interrupt_vector ( unsigned int intr, void *vector );
431 
432 /** A page table */
433 struct page_table {
434  /** Page address and flags */
436 };
437 
438 /** Page flags */
440  /** Page is present */
441  PAGE_P = 0x01,
442  /** Page is writable */
443  PAGE_RW = 0x02,
444  /** Page is accessible by user code */
445  PAGE_US = 0x04,
446  /** Page-level write-through */
447  PAGE_PWT = 0x08,
448  /** Page-level cache disable */
449  PAGE_PCD = 0x10,
450  /** Page is a large page */
451  PAGE_PS = 0x80,
452  /** Page is the last page in an allocation
453  *
454  * This bit is ignored by the hardware. We use it to track
455  * the size of allocations made by ioremap().
456  */
457  PAGE_LAST = 0x800,
458 };
459 
460 /** The I/O space page table */
461 extern struct page_table io_pages;
462 
463 /** I/O page size
464  *
465  * We choose to use 2MB pages for I/O space, to minimise the number of
466  * page table entries required.
467  */
468 #define IO_PAGE_SIZE 0x200000UL
469 
470 /** I/O page base address
471  *
472  * We choose to place I/O space immediately above the identity-mapped
473  * 32-bit address space.
474  */
475 #define IO_BASE ( ( void * ) 0x100000000ULL )
476 
477 /** Startup IPI real-mode handler */
478 extern char __text16_array ( sipi, [] );
479 #define sipi __use_text16 ( sipi )
480 
481 /** Length of startup IPI real-mode handler */
482 extern char sipi_len[];
483 
484 /** Startup IPI real-mode handler copy of real-mode data segment */
485 extern uint16_t __text16 ( sipi_ds );
486 #define sipi_ds __use_text16 ( sipi_ds )
487 
488 /** Startup IPI protected-mode handler (physical address) */
489 extern uint32_t sipi_handler;
490 
491 /** Startup IPI register state */
492 extern struct i386_regs sipi_regs;
493 
494 extern void setup_sipi ( unsigned int vector, uint32_t handler,
495  struct i386_regs *regs );
496 
497 #endif /* ASSEMBLY */
498 
499 #endif /* LIBRM_H */
uint32_t cs
Definition: librm.h:402
static __always_inline int off_t userptr_t off_t second_off
Definition: librm.h:166
uint64_t rsp
Definition: librm.h:426
unsigned short uint16_t
Definition: stdint.h:11
static __always_inline size_t trivial_strlen_user(userptr_t buffer, off_t offset)
Find length of NUL-terminated string in user buffer.
Definition: uaccess.h:167
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define __text16_array(variable, array)
Definition: librm.h:219
uint64_t r14
Definition: librm.h:409
uint16_t mid
Middle 16 bits of address.
Definition: librm.h:338
static __always_inline int trivial_memcmp_user(userptr_t first, off_t first_off, userptr_t second, off_t second_off, size_t len)
Compare data between user buffers.
Definition: uaccess.h:140
uint8_t next[0]
Next instruction after jump.
Definition: librm.h:374
char *const data16
Definition: ib_mad.h:19
uint64_t r12
Definition: librm.h:411
uint32_t vector
MSI-X vector.
Definition: ena.h:20
static __always_inline void * trivial_user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
Definition: uaccess.h:69
uint8_t intr
Interrupt number.
Definition: librm.h:368
off_t memchr_user(userptr_t userptr, off_t offset, int c, size_t len)
Find character in user buffer.
uint32_t sipi_handler
Startup IPI protected-mode handler (physical address)
uint32_t es
Definition: librm.h:392
uint64_t rsi
Definition: librm.h:418
uint16_t high
High 16 bits of address.
Definition: librm.h:324
Page-level write-through.
Definition: librm.h:447
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define sipi_ds
Definition: librm.h:486
static __always_inline int off_t first_off
Definition: librm.h:166
static __always_inline void off_t dest_off
Definition: librm.h:152
uint8_t attr
Type and attributes.
Definition: librm.h:322
static __always_inline userptr_t trivial_userptr_add(userptr_t userptr, off_t offset)
Add offset to user pointer.
Definition: uaccess.h:81
unsigned long long uint64_t
Definition: stdint.h:13
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
static __always_inline void trivial_memmove_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers, allowing for overlap.
Definition: uaccess.h:123
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
uint64_t r10
Definition: librm.h:413
uint32_t eax
Definition: librm.h:400
static __always_inline userptr_t UACCESS_INLINE(librm, phys_to_user)(unsigned long phys_addr)
Convert physical address to user pointer.
Definition: librm.h:92
uint32_t high
High 32 bits of address.
Definition: librm.h:340
Page-level cache disable.
Definition: librm.h:449
static __always_inline off_t trivial_memchr_user(userptr_t buffer, off_t offset, int c, size_t len)
Find character in user buffer.
Definition: uaccess.h:181
page_flags
Page flags.
Definition: librm.h:439
uint64_t r13
Definition: librm.h:410
uint64_t ss
Definition: librm.h:427
off_t userptr_sub(userptr_t userptr, userptr_t subtrahend)
Subtract user pointers.
uint64_t rcx
Definition: librm.h:420
char *const text16
uint32_t ds
Definition: librm.h:393
struct i386_regs sipi_regs
Startup IPI register state.
Definition: librm_mgmt.c:49
uint64_t r8
Definition: librm.h:415
A 32-bit interrupt descriptor table entry.
Definition: librm.h:314
void memset_user(userptr_t userptr, off_t offset, int c, size_t len)
Fill user buffer with a constant byte.
static __always_inline void off_t userptr_t off_t size_t len
Definition: librm.h:154
userptr_t userptr_add(userptr_t userptr, off_t offset)
Add offset to user pointer.
uint32_t edx
Definition: librm.h:397
uint8_t intr
Interrupt number.
Definition: librm.h:254
uint64_t rax
Definition: librm.h:422
uint8_t unused
Unused.
Definition: librm.h:320
uint32_t fs
Definition: librm.h:391
#define rm_ds
Definition: librm.h:245
uint64_t r9
Definition: librm.h:414
static __always_inline void off_t userptr_t off_t src_off
Definition: librm.h:152
uint8_t movb
"movb" instruction
Definition: librm.h:366
Page is the last page in an allocation.
Definition: librm.h:457
uint32_t ecx
Definition: librm.h:398
uint32_t eip
Definition: librm.h:401
Page is a large page.
Definition: librm.h:451
uint32_t edi
Definition: librm.h:395
static void * dest
Definition: strings.h:176
uint8_t unused
Unused.
Definition: librm.h:334
uint16_t low
Low 16 bits of address.
Definition: librm.h:316
uint32_t esp
Definition: librm.h:388
uint64_t rdx
Definition: librm.h:419
uint64_t r15
Definition: librm.h:408
struct page_table __attribute__
uint16_t limit
Limit.
Definition: librm.h:300
uint16_t rm_ss
#define __always_inline
Declare a function to be always inline.
Definition: compiler.h:611
An interrupt vector.
Definition: librm.h:362
uint32_t ebp
Definition: librm.h:394
uint32_t eflags
Definition: librm.h:403
A 32-bit interrupt descriptor table register.
Definition: librm.h:298
u32 addr
Definition: sky2.h:8
unsigned char uint8_t
Definition: stdint.h:10
static __always_inline void off_t userptr_t src
Definition: librm.h:152
uint8_t push
"push" instruction
Definition: librm.h:364
uint16_t low
Low 16 bits of address.
Definition: librm.h:330
uint16_t copy_user_to_rm_stack(userptr_t data, size_t size)
Allocate space on the real-mode stack and copy data there from a user buffer.
Definition: librm_mgmt.c:68
void set_interrupt_vector(unsigned int intr, void *vector)
Set interrupt vector.
Definition: librm_mgmt.c:97
unsigned int uint32_t
Definition: stdint.h:12
char sipi_len[]
Length of startup IPI real-mode handler.
A 64-bit interrupt descriptor table entry.
Definition: librm.h:328
struct i386_regs regs
Definition: registers.h:15
uint64_t rbp
Definition: librm.h:416
A 32-bit general register dump.
Definition: registers.h:62
uint32_t ss
Definition: librm.h:389
unsigned long physaddr_t
Definition: stdint.h:20
void setup_sipi(unsigned int vector, uint32_t handler, struct i386_regs *regs)
Set up startup IPI handler.
Definition: librm_mgmt.c:415
static __always_inline off_t trivial_userptr_sub(userptr_t userptr, userptr_t subtrahend)
Subtract user pointers.
Definition: uaccess.h:93
size_t strlen_user(userptr_t userptr, off_t offset)
Find length of NUL-terminated string in user buffer.
uint64_t rflags
Definition: librm.h:425
signed long off_t
Definition: stdint.h:8
A page table.
Definition: librm.h:433
32-bit interrupt wrapper stack frame
Definition: librm.h:387
uint32_t esi
Definition: librm.h:396
uint64_t base
Base.
Definition: librm.h:310
uint32_t reserved
Reserved.
Definition: librm.h:342
uint32_t gs
Definition: librm.h:390
uint32_t ebx
Definition: librm.h:399
int memcmp_user(userptr_t first, off_t first_off, userptr_t second, off_t second_off, size_t len)
Compare data between user buffers.
uint64_t cs
Definition: librm.h:424
uint16_t segment
Code segment.
Definition: librm.h:332
uint16_t limit
Limit.
Definition: librm.h:308
static __always_inline void trivial_memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.
Definition: uaccess.h:107
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
#define __text16(variable)
Definition: librm.h:215
struct page_table io_pages
The I/O space page table.
Page is writable.
Definition: librm.h:443
void * user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
uint64_t rbx
Definition: librm.h:421
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint32_t base
Base.
Definition: librm.h:302
uint16_t rm_sp
const unsigned long virt_offset
uint32_t offset
Interrupt wrapper address offset.
Definition: librm.h:372
void memmove_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers, allowing for overlap.
void remove_user_from_rm_stack(userptr_t data, size_t size)
Deallocate space on the real-mode stack, optionally copying back data to a user buffer.
Definition: librm_mgmt.c:83
Page is accessible by user code.
Definition: librm.h:445
#define sipi
Definition: librm.h:479
uint64_t page[512]
Page address and flags.
Definition: librm.h:435
uint64_t rip
Definition: librm.h:423
static __always_inline off_t userptr_t subtrahend
Definition: librm.h:147
uint8_t jmp
"jmp" instruction
Definition: librm.h:370
static __always_inline unsigned long off_t offset
Interrupt wrapper address offset.
Definition: librm.h:113
static __always_inline userptr_t trivial_virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
Definition: uaccess.h:55
uint64_t r11
Definition: librm.h:412
static __always_inline int off_t userptr_t second
Definition: librm.h:166
uint8_t attr
Type and attributes.
Definition: librm.h:336
64-bit interrupt wrapper stack frame
Definition: librm.h:407
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23
A 64-bit interrupt descriptor table register.
Definition: librm.h:306
static __always_inline void off_t int c
Definition: librm.h:173
uint64_t rdi
Definition: librm.h:417
void memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
uint16_t segment
Code segment.
Definition: librm.h:318
static __always_inline void trivial_memset_user(userptr_t buffer, off_t offset, int c, size_t len)
Fill user buffer with a constant byte.
Definition: uaccess.h:155
#define rm_cs
Definition: librm.h:243
Page is present.
Definition: librm.h:441