iPXE
librm_mgmt.c
Go to the documentation of this file.
1 /*
2  * librm: a library for interfacing to real-mode code
3  *
4  * Michael Brown <mbrown@fensystems.co.uk>
5  *
6  */
7 
8 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
9 
10 #include <stdint.h>
11 #include <strings.h>
12 #include <assert.h>
13 #include <ipxe/profile.h>
14 #include <realmode.h>
15 #include <pic8259.h>
16 #include <ipxe/shell.h>
17 
18 /*
19  * This file provides functions for managing librm.
20  *
21  */
22 
23 /** The interrupt wrapper */
24 extern char interrupt_wrapper[];
25 
26 /** The interrupt vectors */
28 
29 /** The 32-bit interrupt descriptor table */
31 idt32[NUM_INT] __attribute__ (( aligned ( 16 ) ));
32 
33 /** The 32-bit interrupt descriptor table register */
34 struct idtr32 idtr32 = {
35  .limit = ( sizeof ( idt32 ) - 1 ),
36 };
37 
38 /** The 64-bit interrupt descriptor table */
40 idt64[NUM_INT] __attribute__ (( aligned ( 16 ) ));
41 
42 /** The interrupt descriptor table register */
43 struct idtr64 idtr64 = {
44  .limit = ( sizeof ( idt64 ) - 1 ),
45 };
46 
47 /** Length of stack dump */
48 #define STACK_DUMP_LEN 128
49 
50 /** Timer interrupt profiler */
51 static struct profiler timer_irq_profiler __profiler = { .name = "irq.timer" };
52 
53 /** Other interrupt profiler */
54 static struct profiler other_irq_profiler __profiler = { .name = "irq.other" };
55 
56 /**
57  * Allocate space on the real-mode stack and copy data there from a
58  * user buffer
59  *
60  * @v data User buffer
61  * @v size Size of stack data
62  * @ret sp New value of real-mode stack pointer
63  */
65  userptr_t rm_stack;
66  rm_sp -= size;
67  rm_stack = real_to_user ( rm_ss, rm_sp );
68  memcpy_user ( rm_stack, 0, data, 0, size );
69  return rm_sp;
70 };
71 
72 /**
73  * Deallocate space on the real-mode stack, optionally copying back
74  * data to a user buffer.
75  *
76  * @v data User buffer
77  * @v size Size of stack data
78  */
80  if ( data ) {
81  userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
82  memcpy_user ( rm_stack, 0, data, 0, size );
83  }
84  rm_sp += size;
85 };
86 
87 /**
88  * Set interrupt vector
89  *
90  * @v intr Interrupt number
91  * @v vector Interrupt vector, or NULL to disable
92  */
93 void set_interrupt_vector ( unsigned int intr, void *vector ) {
94  struct interrupt32_descriptor *idte32;
95  struct interrupt64_descriptor *idte64;
96  intptr_t addr = ( ( intptr_t ) vector );
97 
98  /* Populate 32-bit interrupt descriptor */
99  idte32 = &idt32[intr];
100  idte32->segment = VIRTUAL_CS;
101  idte32->attr = ( vector ? ( IDTE_PRESENT | IDTE_TYPE_IRQ32 ) : 0 );
102  idte32->low = ( addr >> 0 );
103  idte32->high = ( addr >> 16 );
104 
105  /* Populate 64-bit interrupt descriptor, if applicable */
106  if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
107  idte64 = &idt64[intr];
108  idte64->segment = LONG_CS;
109  idte64->attr = ( vector ?
110  ( IDTE_PRESENT | IDTE_TYPE_IRQ64 ) : 0 );
111  idte64->low = ( addr >> 0 );
112  idte64->mid = ( addr >> 16 );
113  idte64->high = ( ( ( uint64_t ) addr ) >> 32 );
114  }
115 }
116 
117 /**
118  * Initialise interrupt descriptor table
119  *
120  */
121 void init_idt ( void ) {
122  struct interrupt_vector *vec;
123  unsigned int intr;
124 
125  /* Initialise the interrupt descriptor table and interrupt vectors */
126  for ( intr = 0 ; intr < NUM_INT ; intr++ ) {
127  vec = &intr_vec[intr];
128  vec->push = PUSH_INSN;
129  vec->movb = MOVB_INSN;
130  vec->intr = intr;
131  vec->jmp = JMP_INSN;
132  vec->offset = ( ( intptr_t ) interrupt_wrapper -
133  ( intptr_t ) vec->next );
134  set_interrupt_vector ( intr, vec );
135  }
136  DBGC ( &intr_vec[0], "INTn vector at %p+%zxn (phys %#lx+%zxn)\n",
137  intr_vec, sizeof ( intr_vec[0] ),
138  virt_to_phys ( intr_vec ), sizeof ( intr_vec[0] ) );
139 
140  /* Initialise the 32-bit interrupt descriptor table register */
142 
143  /* Initialise the 64-bit interrupt descriptor table register,
144  * if applicable.
145  */
146  if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
148 }
149 
150 /**
151  * Determine interrupt profiler (for debugging)
152  *
153  * @v intr Interrupt number
154  * @ret profiler Profiler
155  */
156 static struct profiler * interrupt_profiler ( int intr ) {
157 
158  switch ( intr ) {
159  case IRQ_INT ( 0 ) :
160  return &timer_irq_profiler;
161  default:
162  return &other_irq_profiler;
163  }
164 }
165 
166 /**
167  * Display interrupt stack dump (for debugging)
168  *
169  * @v intr Interrupt number
170  * @v frame32 32-bit interrupt wrapper stack frame (or NULL)
171  * @v frame64 64-bit interrupt wrapper stack frame (or NULL)
172  */
173 static __attribute__ (( unused )) void
174 interrupt_dump ( int intr, struct interrupt_frame32 *frame32,
175  struct interrupt_frame64 *frame64 ) {
176  unsigned long sp;
177  void *stack;
178 
179  /* Do nothing unless debugging is enabled */
180  if ( ! DBG_LOG )
181  return;
182 
183  /* Print register dump */
184  if ( ( sizeof ( physaddr_t ) <= sizeof ( uint32_t ) ) || frame32 ) {
185  sp = ( frame32->esp + sizeof ( *frame32 ) -
186  offsetof ( typeof ( *frame32 ), esp ) );
187  DBGC ( &intr, "INT%d at %04x:%08x (stack %04x:%08lx):\n",
188  intr, frame32->cs, frame32->eip, frame32->ss, sp );
189  DBGC ( &intr, "cs = %04x ds = %04x es = %04x fs = %04x "
190  "gs = %04x ss = %04x\n", frame32->cs, frame32->ds,
191  frame32->es, frame32->fs, frame32->gs, frame32->ss );
192  DBGC ( &intr, "eax = %08x ebx = %08x ecx = %08x "
193  "edx = %08x flg = %08x\n", frame32->eax, frame32->ebx,
194  frame32->ecx, frame32->edx, frame32->eflags );
195  DBGC ( &intr, "esi = %08x edi = %08x ebp = %08x "
196  "esp = %08lx eip = %08x\n", frame32->esi, frame32->edi,
197  frame32->ebp, sp, frame32->eip );
198  stack = ( ( ( void * ) frame32 ) + sizeof ( *frame32 ) );
199  } else {
200  DBGC ( &intr, "INT%d at %04llx:%016llx (stack "
201  "%04llx:%016llx):\n", intr,
202  ( ( unsigned long long ) frame64->cs ),
203  ( ( unsigned long long ) frame64->rip ),
204  ( ( unsigned long long ) frame64->ss ),
205  ( ( unsigned long long ) frame64->rsp ) );
206  DBGC ( &intr, "rax = %016llx rbx = %016llx rcx = %016llx\n",
207  ( ( unsigned long long ) frame64->rax ),
208  ( ( unsigned long long ) frame64->rbx ),
209  ( ( unsigned long long ) frame64->rcx ) );
210  DBGC ( &intr, "rdx = %016llx rsi = %016llx rdi = %016llx\n",
211  ( ( unsigned long long ) frame64->rdx ),
212  ( ( unsigned long long ) frame64->rsi ),
213  ( ( unsigned long long ) frame64->rdi ) );
214  DBGC ( &intr, "rbp = %016llx rsp = %016llx flg = %016llx\n",
215  ( ( unsigned long long ) frame64->rbp ),
216  ( ( unsigned long long ) frame64->rsp ),
217  ( ( unsigned long long ) frame64->rflags ) );
218  DBGC ( &intr, "r8 = %016llx r9 = %016llx r10 = %016llx\n",
219  ( ( unsigned long long ) frame64->r8 ),
220  ( ( unsigned long long ) frame64->r9 ),
221  ( ( unsigned long long ) frame64->r10 ) );
222  DBGC ( &intr, "r11 = %016llx r12 = %016llx r13 = %016llx\n",
223  ( ( unsigned long long ) frame64->r11 ),
224  ( ( unsigned long long ) frame64->r12 ),
225  ( ( unsigned long long ) frame64->r13 ) );
226  DBGC ( &intr, "r14 = %016llx r15 = %016llx\n",
227  ( ( unsigned long long ) frame64->r14 ),
228  ( ( unsigned long long ) frame64->r15 ) );
229  sp = frame64->rsp;
230  stack = phys_to_virt ( sp );
231  }
232 
233  /* Print stack dump */
234  DBGC_HDA ( &intr, sp, stack, STACK_DUMP_LEN );
235 }
236 
237 /**
238  * Interrupt handler
239  *
240  * @v intr Interrupt number
241  * @v frame32 32-bit interrupt wrapper stack frame (or NULL)
242  * @v frame64 64-bit interrupt wrapper stack frame (or NULL)
243  * @v frame Interrupt wrapper stack frame
244  */
245 void __attribute__ (( regparm ( 3 ) ))
246 interrupt ( int intr, struct interrupt_frame32 *frame32,
247  struct interrupt_frame64 *frame64 ) {
249  uint32_t discard_eax;
250 
251  /* Trap CPU exceptions if debugging is enabled. Note that we
252  * cannot treat INT8+ as exceptions, since we are not
253  * permitted to rebase the PIC.
254  */
255  if ( DBG_LOG && ( intr < IRQ_INT ( 0 ) ) ) {
256  interrupt_dump ( intr, frame32, frame64 );
257  DBG ( "CPU exception: dropping to emergency shell\n" );
258  shell();
259  }
260 
261  /* Reissue interrupt in real mode */
263  __asm__ __volatile__ ( REAL_CODE ( "movb %%al, %%cs:(1f + 1)\n\t"
264  "\n1:\n\t"
265  "int $0x00\n\t" )
266  : "=a" ( discard_eax ) : "0" ( intr ) );
269 }
270 
271 /**
272  * Map pages for I/O
273  *
274  * @v bus_addr Bus address
275  * @v len Length of region
276  * @ret io_addr I/O address
277  */
278 static void * ioremap_pages ( unsigned long bus_addr, size_t len ) {
279  unsigned long start;
280  unsigned int count;
281  unsigned int stride;
282  unsigned int first;
283  unsigned int i;
284  size_t offset;
285  void *io_addr;
286 
287  DBGC ( &io_pages, "IO mapping %08lx+%zx\n", bus_addr, len );
288 
289  /* Sanity check */
290  if ( ! len )
291  return NULL;
292 
293  /* Round down start address to a page boundary */
294  start = ( bus_addr & ~( IO_PAGE_SIZE - 1 ) );
295  offset = ( bus_addr - start );
296  assert ( offset < IO_PAGE_SIZE );
297 
298  /* Calculate number of pages required */
299  count = ( ( offset + len + IO_PAGE_SIZE - 1 ) / IO_PAGE_SIZE );
300  assert ( count != 0 );
301  assert ( count < ( sizeof ( io_pages.page ) /
302  sizeof ( io_pages.page[0] ) ) );
303 
304  /* Round up number of pages to a power of two */
305  stride = ( 1 << ( fls ( count ) - 1 ) );
306  assert ( count <= stride );
307 
308  /* Allocate pages */
309  for ( first = 0 ; first < ( sizeof ( io_pages.page ) /
310  sizeof ( io_pages.page[0] ) ) ;
311  first += stride ) {
312 
313  /* Calculate I/O address */
314  io_addr = ( IO_BASE + ( first * IO_PAGE_SIZE ) + offset );
315 
316  /* Check that page table entries are available */
317  for ( i = first ; i < ( first + count ) ; i++ ) {
318  if ( io_pages.page[i] & PAGE_P ) {
319  io_addr = NULL;
320  break;
321  }
322  }
323  if ( ! io_addr )
324  continue;
325 
326  /* Create page table entries */
327  for ( i = first ; i < ( first + count ) ; i++ ) {
328  io_pages.page[i] = ( start | PAGE_P | PAGE_RW |
330  PAGE_PS );
331  start += IO_PAGE_SIZE;
332  }
333 
334  /* Mark last page as being the last in this allocation */
335  io_pages.page[ i - 1 ] |= PAGE_LAST;
336 
337  /* Return I/O address */
338  DBGC ( &io_pages, "IO mapped %08lx+%zx to %p using PTEs "
339  "[%d-%d]\n", bus_addr, len, io_addr, first,
340  ( first + count - 1 ) );
341  return io_addr;
342  }
343 
344  DBGC ( &io_pages, "IO could not map %08lx+%zx\n", bus_addr, len );
345  return NULL;
346 }
347 
348 /**
349  * Unmap pages for I/O
350  *
351  * @v io_addr I/O address
352  */
353 static void iounmap_pages ( volatile const void *io_addr ) {
354  volatile const void *invalidate = io_addr;
355  unsigned int first;
356  unsigned int i;
357  int is_last;
358 
359  DBGC ( &io_pages, "IO unmapping %p\n", io_addr );
360 
361  /* Calculate first page table entry */
362  first = ( ( io_addr - IO_BASE ) / IO_PAGE_SIZE );
363 
364  /* Clear page table entries */
365  for ( i = first ; ; i++ ) {
366 
367  /* Sanity check */
368  assert ( io_pages.page[i] & PAGE_P );
369 
370  /* Check if this is the last page in this allocation */
371  is_last = ( io_pages.page[i] & PAGE_LAST );
372 
373  /* Clear page table entry */
374  io_pages.page[i] = 0;
375 
376  /* Invalidate TLB for this page */
377  __asm__ __volatile__ ( "invlpg (%0)" : : "r" ( invalidate ) );
378  invalidate += IO_PAGE_SIZE;
379 
380  /* Terminate if this was the last page */
381  if ( is_last )
382  break;
383  }
384 
385  DBGC ( &io_pages, "IO unmapped %p using PTEs [%d-%d]\n",
386  io_addr, first, i );
387 }
388 
#define IO_PAGE_SIZE
I/O page size.
Definition: librm.h:466
uint32_t cs
Definition: librm.h:400
#define __attribute__(x)
Definition: compiler.h:10
uint64_t rsp
Definition: librm.h:424
unsigned short uint16_t
Definition: stdint.h:11
Minimal command shell.
uint32_t esp
Definition: librm.h:249
uint64_t r14
Definition: librm.h:407
uint16_t mid
Middle 16 bits of address.
Definition: librm.h:336
uint8_t next[0]
Next instruction after jump.
Definition: librm.h:372
uint64_t r12
Definition: librm.h:409
uint32_t vector
MSI-X vector.
Definition: ena.h:20
uint8_t intr
Interrupt number.
Definition: librm.h:366
off_t memchr_user(userptr_t userptr, off_t offset, int c, size_t len)
Find character in user buffer.
#define IDTE_TYPE_IRQ32
Interrupt descriptor 32-bit interrupt gate type.
Definition: librm.h:347
PROVIDE_UACCESS_INLINE(librm, phys_to_user)
uint32_t es
Definition: librm.h:390
uint64_t rsi
Definition: librm.h:416
uint16_t high
High 16 bits of address.
Definition: librm.h:322
Page-level write-through.
Definition: librm.h:445
void init_idt(void)
Initialise interrupt descriptor table.
Definition: librm_mgmt.c:121
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
PROVIDE_IOMAP(pages, ioremap, ioremap_pages)
#define DBGC(...)
Definition: compiler.h:505
#define LONG_CS
Definition: librm.h:17
uint8_t attr
Type and attributes.
Definition: librm.h:320
unsigned long long uint64_t
Definition: stdint.h:13
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
int shell(void)
Start command shell.
Definition: shell.c:84
uint64_t r10
Definition: librm.h:411
uint32_t eax
Definition: librm.h:398
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
A data structure for storing profiling information.
Definition: profile.h:26
unsigned long io_to_bus(volatile const void *io_addr)
Convert I/O address to bus address (for debug only)
unsigned long intptr_t
Definition: stdint.h:21
static void iounmap_pages(volatile const void *io_addr)
Unmap pages for I/O.
Definition: librm_mgmt.c:353
static void interrupt_dump(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Display interrupt stack dump (for debugging)
Definition: librm_mgmt.c:174
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
uint32_t high
High 32 bits of address.
Definition: librm.h:338
Page-level cache disable.
Definition: librm.h:447
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
uint64_t r13
Definition: librm.h:408
uint64_t ss
Definition: librm.h:425
uint32_t start
Starting offset.
Definition: netvsc.h:12
#define IDTE_TYPE_IRQ64
Interrupt descriptor 64-bit interrupt gate type.
Definition: librm.h:350
uint64_t rcx
Definition: librm.h:418
uint32_t ds
Definition: librm.h:391
static __always_inline void * phys_to_virt(unsigned long phys_addr)
Convert physical address to a virtual address.
Definition: uaccess.h:299
uint64_t r8
Definition: librm.h:413
A 32-bit interrupt descriptor table entry.
Definition: librm.h:312
void memset_user(userptr_t userptr, off_t offset, int c, size_t len)
Fill user buffer with a constant byte.
userptr_t userptr_add(userptr_t userptr, off_t offset)
Add offset to user pointer.
const char * name
Name.
Definition: profile.h:28
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:64
uint32_t edx
Definition: librm.h:395
uint64_t rax
Definition: librm.h:420
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
uint8_t intr
Interrupts enabled.
Definition: ena.h:14
#define IO_BASE
I/O page base address.
Definition: librm.h:473
#define DBGC_HDA(...)
Definition: compiler.h:506
uint32_t fs
Definition: librm.h:389
uint64_t r9
Definition: librm.h:412
A 16-bit general register.
Definition: registers.h:24
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
uint8_t movb
"movb" instruction
Definition: librm.h:364
Page is the last page in an allocation.
Definition: librm.h:455
uint32_t ecx
Definition: librm.h:396
static struct interrupt_vector intr_vec[NUM_INT]
The interrupt vectors.
Definition: librm_mgmt.c:27
uint32_t eip
Definition: librm.h:399
Page is a large page.
Definition: librm.h:449
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
Profiling.
uint32_t edi
Definition: librm.h:393
#define PUSH_INSN
"push %eax" instruction
Definition: librm.h:376
uint16_t low
Low 16 bits of address.
Definition: librm.h:314
uint32_t esp
Definition: librm.h:386
uint64_t rdx
Definition: librm.h:417
uint64_t r15
Definition: librm.h:406
uint16_t limit
Limit.
Definition: librm.h:298
uint16_t rm_ss
An interrupt vector.
Definition: librm.h:360
uint32_t ebp
Definition: librm.h:392
uint32_t eflags
Definition: librm.h:401
#define IRQ_INT(irq)
Definition: pic8259.h:60
#define VIRTUAL_CS
Definition: librm.h:10
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
A 32-bit interrupt descriptor table register.
Definition: librm.h:296
u32 addr
Definition: sky2.h:8
uint8_t push
"push" instruction
Definition: librm.h:362
uint16_t low
Low 16 bits of address.
Definition: librm.h:328
static struct profiler timer_irq_profiler __profiler
Timer interrupt profiler.
Definition: librm_mgmt.c:51
unsigned int uint32_t
Definition: stdint.h:12
#define STACK_DUMP_LEN
Length of stack dump.
Definition: librm_mgmt.c:48
A 64-bit interrupt descriptor table entry.
Definition: librm.h:326
uint64_t rbp
Definition: librm.h:414
__asm__ __volatile__("\n1:\n\t" "movb -1(%2,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %3, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
#define MOVB_INSN
"movb" instruction
Definition: librm.h:379
uint32_t ss
Definition: librm.h:387
unsigned long physaddr_t
Definition: stdint.h:20
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:423
32-bit interrupt wrapper stack frame
Definition: librm.h:385
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
#define IDTE_PRESENT
Interrupt descriptor is present.
Definition: librm.h:344
uint32_t esi
Definition: librm.h:394
uint32_t len
Length.
Definition: ena.h:14
uint64_t base
Base.
Definition: librm.h:308
uint8_t unused[32]
Unused.
Definition: eltorito.h:15
void set_interrupt_vector(unsigned int intr, void *vector)
Set interrupt vector.
Definition: librm_mgmt.c:93
uint32_t gs
Definition: librm.h:388
uint32_t ebx
Definition: librm.h:397
uint16_t count
Number of entries.
Definition: ena.h:22
uint64_t cs
Definition: librm.h:422
uint16_t segment
Code segment.
Definition: librm.h:330
uint16_t limit
Limit.
Definition: librm.h:306
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
Page is writable.
Definition: librm.h:441
struct page_table io_pages
The I/O space page table.
void * user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
uint64_t rbx
Definition: librm.h:419
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
void iounmap(volatile const void *io_addr)
Unmap I/O address.
#define JMP_INSN
"jmp" instruction
Definition: librm.h:382
uint32_t base
Base.
Definition: librm.h:300
uint16_t rm_sp
char interrupt_wrapper[]
The interrupt wrapper.
uint32_t offset
Interrupt wrapper address offset.
Definition: librm.h:370
static void * ioremap_pages(unsigned long bus_addr, size_t len)
Map pages for I/O.
Definition: librm_mgmt.c:278
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.
static __always_inline userptr_t real_to_user(unsigned int segment, unsigned int offset)
Convert segment:offset address to user buffer.
Definition: realmode.h:75
Page is accessible by user code.
Definition: librm.h:443
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:79
static struct profiler * interrupt_profiler(int intr)
Determine interrupt profiler (for debugging)
Definition: librm_mgmt.c:156
#define NUM_INT
Number of interrupts.
Definition: librm.h:293
uint64_t page[512]
Page address and flags.
Definition: librm.h:433
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
static void profile_exclude(struct profiler *profiler)
Exclude time from other ongoing profiling results.
Definition: profile.h:184
uint64_t rip
Definition: librm.h:421
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint8_t jmp
"jmp" instruction
Definition: librm.h:368
void * ioremap(unsigned long bus_addr, size_t len)
Map bus address as an I/O address.
static struct interrupt64_descriptor idt64[NUM_INT]
The 64-bit interrupt descriptor table.
Definition: librm_mgmt.c:39
#define fls(x)
Find last (i.e.
Definition: strings.h:166
#define DBG_LOG
Definition: compiler.h:317
uint64_t r11
Definition: librm.h:410
#define REAL_CODE(asm_code_str)
Definition: libkir.h:226
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
void interrupt(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Interrupt handler.
Definition: librm_mgmt.c:246
uint8_t attr
Type and attributes.
Definition: librm.h:334
64-bit interrupt wrapper stack frame
Definition: librm.h:405
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23
A 64-bit interrupt descriptor table register.
Definition: librm.h:304
PROVIDE_IOMAP_INLINE(pages, io_to_bus)
uint16_t sp
Definition: registers.h:27
uint64_t rdi
Definition: librm.h:415
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:316
String functions.
static struct interrupt32_descriptor idt32[NUM_INT]
The 32-bit interrupt descriptor table.
Definition: librm_mgmt.c:30
Page is present.
Definition: librm.h:439