49 #define STACK_DUMP_LEN 128 137 DBGC ( &
intr_vec[0],
"INTn vector at %p+%zxn (phys %#lx+%zxn)\n",
161 return &timer_irq_profiler;
163 return &other_irq_profiler;
186 sp = ( frame32->
esp +
sizeof ( *frame32 ) -
188 DBGC ( &
intr,
"INT%d at %04x:%08x (stack %04x:%08lx):\n",
190 DBGC ( &
intr,
"cs = %04x ds = %04x es = %04x fs = %04x " 191 "gs = %04x ss = %04x\n", frame32->
cs, frame32->
ds,
192 frame32->
es, frame32->
fs, frame32->
gs, frame32->
ss );
193 DBGC ( &
intr,
"eax = %08x ebx = %08x ecx = %08x " 194 "edx = %08x flg = %08x\n", frame32->
eax, frame32->
ebx,
196 DBGC ( &
intr,
"esi = %08x edi = %08x ebp = %08x " 197 "esp = %08lx eip = %08x\n", frame32->
esi, frame32->
edi,
199 stack = ( ( (
void * ) frame32 ) +
sizeof ( *frame32 ) );
201 DBGC ( &
intr,
"INT%d at %04llx:%016llx (stack " 202 "%04llx:%016llx):\n",
intr,
203 ( (
unsigned long long ) frame64->
cs ),
204 ( (
unsigned long long ) frame64->
rip ),
205 ( (
unsigned long long ) frame64->
ss ),
206 ( (
unsigned long long ) frame64->
rsp ) );
207 DBGC ( &
intr,
"rax = %016llx rbx = %016llx rcx = %016llx\n",
208 ( (
unsigned long long ) frame64->
rax ),
209 ( (
unsigned long long ) frame64->
rbx ),
210 ( (
unsigned long long ) frame64->
rcx ) );
211 DBGC ( &
intr,
"rdx = %016llx rsi = %016llx rdi = %016llx\n",
212 ( (
unsigned long long ) frame64->
rdx ),
213 ( (
unsigned long long ) frame64->
rsi ),
214 ( (
unsigned long long ) frame64->
rdi ) );
215 DBGC ( &
intr,
"rbp = %016llx rsp = %016llx flg = %016llx\n",
216 ( (
unsigned long long ) frame64->
rbp ),
217 ( (
unsigned long long ) frame64->
rsp ),
218 ( (
unsigned long long ) frame64->
rflags ) );
219 DBGC ( &
intr,
"r8 = %016llx r9 = %016llx r10 = %016llx\n",
220 ( (
unsigned long long ) frame64->
r8 ),
221 ( (
unsigned long long ) frame64->
r9 ),
222 ( (
unsigned long long ) frame64->
r10 ) );
223 DBGC ( &
intr,
"r11 = %016llx r12 = %016llx r13 = %016llx\n",
224 ( (
unsigned long long ) frame64->
r11 ),
225 ( (
unsigned long long ) frame64->
r12 ),
226 ( (
unsigned long long ) frame64->
r13 ) );
227 DBGC ( &
intr,
"r14 = %016llx r15 = %016llx\n",
228 ( (
unsigned long long ) frame64->
r14 ),
229 ( (
unsigned long long ) frame64->
r15 ) );
258 DBG (
"CPU exception: dropping to emergency shell\n" );
267 :
"=a" ( discard_eax ) :
"0" (
intr ) );
306 stride = ( 1 << (
fls (
count ) - 1 ) );
339 DBGC ( &
io_pages,
"IO mapped %08lx+%zx to %p using PTEs " 355 volatile const void *invalidate = io_addr;
366 for ( i =
first ; ; i++ ) {
386 DBGC ( &
io_pages,
"IO unmapped %p using PTEs [%d-%d]\n",
402 ( (
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 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.
PROVIDE_UACCESS_INLINE(librm, phys_to_user)
uint16_t high
High 16 bits of address.
Page-level write-through.
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.
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.
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.
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.
static userptr_t size_t offset
Offset of the first segment within the content.
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.
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.
__asm__ __volatile__("\n1:\n\t" "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %4, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c), "+m"(*value) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
#define STACK_DUMP_LEN
Length of stack dump.
A 64-bit interrupt descriptor table entry.
#define MOVB_INSN
"movb" instruction
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.
uint8_t unused[32]
Unused.
void set_interrupt_vector(unsigned int intr, void *vector)
Set interrupt vector.
uint16_t count
Number of entries.
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.
uint8_t size
Entry size (in 32-bit words)
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.
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.
static __always_inline void unsigned long bus_addr
__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
uint32_t first
Length to skip in first segment.
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.
unsigned long userptr_t
A pointer to a user buffer.
uint16_t segment
Code segment.
static struct interrupt32_descriptor idt32[NUM_INT]
The 32-bit interrupt descriptor table.