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