52 #define STACK_DUMP_LEN 128 140 DBGC ( &
intr_vec[0],
"INTn vector at %p+%zxn (phys %#lx+%zxn)\n",
164 return &timer_irq_profiler;
166 return &other_irq_profiler;
189 sp = ( frame32->
esp +
sizeof ( *frame32 ) -
191 DBGC ( &
intr,
"INT%d at %04x:%08x (stack %04x:%08lx):\n",
193 DBGC ( &
intr,
"cs = %04x ds = %04x es = %04x fs = %04x " 194 "gs = %04x ss = %04x\n", frame32->
cs, frame32->
ds,
195 frame32->
es, frame32->
fs, frame32->
gs, frame32->
ss );
196 DBGC ( &
intr,
"eax = %08x ebx = %08x ecx = %08x " 197 "edx = %08x flg = %08x\n", frame32->
eax, frame32->
ebx,
199 DBGC ( &
intr,
"esi = %08x edi = %08x ebp = %08x " 200 "esp = %08lx eip = %08x\n", frame32->
esi, frame32->
edi,
202 stack = ( ( (
void * ) frame32 ) +
sizeof ( *frame32 ) );
204 DBGC ( &
intr,
"INT%d at %04llx:%016llx (stack " 205 "%04llx:%016llx):\n",
intr,
206 ( (
unsigned long long ) frame64->
cs ),
207 ( (
unsigned long long ) frame64->
rip ),
208 ( (
unsigned long long ) frame64->
ss ),
209 ( (
unsigned long long ) frame64->
rsp ) );
210 DBGC ( &
intr,
"rax = %016llx rbx = %016llx rcx = %016llx\n",
211 ( (
unsigned long long ) frame64->
rax ),
212 ( (
unsigned long long ) frame64->
rbx ),
213 ( (
unsigned long long ) frame64->
rcx ) );
214 DBGC ( &
intr,
"rdx = %016llx rsi = %016llx rdi = %016llx\n",
215 ( (
unsigned long long ) frame64->
rdx ),
216 ( (
unsigned long long ) frame64->
rsi ),
217 ( (
unsigned long long ) frame64->
rdi ) );
218 DBGC ( &
intr,
"rbp = %016llx rsp = %016llx flg = %016llx\n",
219 ( (
unsigned long long ) frame64->
rbp ),
220 ( (
unsigned long long ) frame64->
rsp ),
221 ( (
unsigned long long ) frame64->
rflags ) );
222 DBGC ( &
intr,
"r8 = %016llx r9 = %016llx r10 = %016llx\n",
223 ( (
unsigned long long ) frame64->
r8 ),
224 ( (
unsigned long long ) frame64->
r9 ),
225 ( (
unsigned long long ) frame64->
r10 ) );
226 DBGC ( &
intr,
"r11 = %016llx r12 = %016llx r13 = %016llx\n",
227 ( (
unsigned long long ) frame64->
r11 ),
228 ( (
unsigned long long ) frame64->
r12 ),
229 ( (
unsigned long long ) frame64->
r13 ) );
230 DBGC ( &
intr,
"r14 = %016llx r15 = %016llx\n",
231 ( (
unsigned long long ) frame64->
r14 ),
232 ( (
unsigned long long ) frame64->
r15 ) );
261 DBG (
"CPU exception: dropping to emergency shell\n" );
270 :
"=a" ( discard_eax ) :
"0" (
intr ) );
309 stride = ( 1 << (
fls (
count ) - 1 ) );
342 DBGC ( &
io_pages,
"IO mapped %08lx+%zx to %p using PTEs " 358 volatile const void *invalidate = io_addr;
369 for ( i =
first ; ; i++ ) {
389 DBGC ( &
io_pages,
"IO unmapped %p using PTEs [%d-%d]\n",
405 ( (
regs->flags &
CF ) ?
" not" :
"" ) );
#define IO_PAGE_SIZE
I/O page size.
uint16_t mid
Middle 16 bits of address.
uint8_t next[0]
Next instruction after jump.
uint32_t first
First block in range.
uint32_t vector
MSI-X vector.
uint8_t intr
Interrupt number.
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.
uint32_t sipi_handler
Startup IPI protected-mode handler (physical address)
struct i386_regs sipi_regs
Startup IPI register state.
PROVIDE_UACCESS_INLINE(librm, phys_to_user)
uint16_t high
High 16 bits of address.
Page-level write-through.
uint8_t size
Entry size (in 32-bit words)
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
PROVIDE_IOMAP(pages, ioremap, ioremap_pages)
uint8_t attr
Type and attributes.
unsigned long long uint64_t
void x86_features(struct x86_features *features)
Get x86 CPU features.
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
int shell(void)
Start command shell.
#define offsetof(type, field)
Get offset of a field within a structure.
A data structure for storing profiling information.
unsigned long io_to_bus(volatile const void *io_addr)
Convert I/O address to bus address (for debug only)
static void iounmap_pages(volatile const void *io_addr)
Unmap pages for I/O.
static void interrupt_dump(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Display interrupt stack dump (for debugging)
static void profile_stop(struct profiler *profiler)
Stop profiling.
uint32_t high
High 32 bits of address.
Page-level cache disable.
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
static __always_inline void unsigned long bus_addr
uint32_t start
Starting offset.
#define IDTE_TYPE_IRQ64
Interrupt descriptor 64-bit interrupt gate type.
static __always_inline void * phys_to_virt(unsigned long phys_addr)
Convert physical address to a virtual address.
A 32-bit interrupt descriptor table entry.
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.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
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.
#define __asmcall
Declare a function with standard calling conventions.
uint32_t userptr_t
A pointer to a user buffer.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
uint8_t intr
Interrupts enabled.
#define IO_BASE
I/O page base address.
A 16-bit general register.
uint16_t count
Number of entries.
uint8_t movb
"movb" instruction
Page is the last page in an allocation.
static struct interrupt_vector intr_vec[NUM_INT]
The interrupt vectors.
static void profile_start(struct profiler *profiler)
Start profiling.
__asmcall void init_idt(void)
Initialise interrupt descriptor table.
#define CPUID_FEATURES_INTEL_EDX_FXSR
FXSAVE and FXRSTOR are supported.
#define PUSH_INSN
"push %eax" instruction
uint16_t low
Low 16 bits of address.
x86 CPU feature detection
uint32_t features
Supported features.
__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.
uint8_t push
"push" instruction
uint16_t low
Low 16 bits of address.
static struct profiler timer_irq_profiler __profiler
Timer interrupt profiler.
char sipi_len[]
Length of startup IPI real-mode handler.
#define STACK_DUMP_LEN
Length of stack dump.
A 64-bit interrupt descriptor table entry.
void setup_sipi(unsigned int vector, uint32_t handler, struct i386_regs *regs)
Set up startup IPI handler.
#define MOVB_INSN
"movb" instruction
A 32-bit general register dump.
size_t strlen_user(userptr_t userptr, off_t offset)
Find length of NUL-terminated string in user buffer.
32-bit interrupt wrapper stack frame
__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.
void set_interrupt_vector(unsigned int intr, void *vector)
Set interrupt vector.
uint16_t segment
Code segment.
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
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.
void iounmap(volatile const void *io_addr)
Unmap I/O address.
#define JMP_INSN
"jmp" instruction
uint8_t data[48]
Additional event data.
char interrupt_wrapper[]
The interrupt wrapper.
uint32_t offset
Interrupt wrapper address offset.
static void * ioremap_pages(unsigned long bus_addr, size_t len)
Map pages for I/O.
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.
Page is accessible by user code.
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.
uint16_t offset
Offset to command line.
static struct profiler * interrupt_profiler(int intr)
Determine interrupt profiler (for debugging)
typeof(acpi_finder=acpi_find)
ACPI table finder.
#define NUM_INT
Number of interrupts.
uint64_t page[512]
Page address and flags.
static void profile_exclude(struct profiler *profiler)
Exclude time from other ongoing profiling results.
#define DBG(...)
Print a debugging message.
uint8_t jmp
"jmp" instruction
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.
#define fls(x)
Find last (i.e.
__asmcall void check_fxsr(struct i386_all_regs *regs)
Check for FXSAVE/FXRSTOR instruction support.
#define REAL_CODE(asm_code_str)
#define NULL
NULL pointer (VOID *)
void interrupt(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Interrupt handler.
uint8_t attr
Type and attributes.
64-bit interrupt wrapper stack frame
A 64-bit interrupt descriptor table register.
PROVIDE_IOMAP_INLINE(pages, io_to_bus)
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.
uint16_t segment
Code segment.
static struct interrupt32_descriptor idt32[NUM_INT]
The 32-bit interrupt descriptor table.