From 23b671daf490acaec6fdad55f2bfa44021200a63 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 28 Apr 2014 20:17:15 +0100 Subject: [librm] Allow interrupts in protected mode When running in a virtual machine, switching to real mode may be expensive. Allow interrupts to be enabled while in protected mode and reflected down to the real-mode interrupt handlers. Signed-off-by: Michael Brown --- src/arch/i386/include/gdbmach.h | 10 +++++++ src/arch/i386/include/librm.h | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) (limited to 'src/arch/i386/include') diff --git a/src/arch/i386/include/gdbmach.h b/src/arch/i386/include/gdbmach.h index 794dab193..416ae341a 100644 --- a/src/arch/i386/include/gdbmach.h +++ b/src/arch/i386/include/gdbmach.h @@ -46,6 +46,14 @@ enum { GDBMACH_AWATCH, }; +/* Interrupt vectors */ +extern void gdbmach_nocode_sigfpe ( void ); +extern void gdbmach_nocode_sigtrap ( void ); +extern void gdbmach_nocode_sigstkflt ( void ); +extern void gdbmach_nocode_sigill ( void ); +extern void gdbmach_withcode_sigbus ( void ); +extern void gdbmach_withcode_sigsegv ( void ); + static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) { regs [ GDBMACH_EIP ] = pc; } @@ -61,4 +69,6 @@ static inline void gdbmach_breakpoint ( void ) { extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable ); +extern void gdbmach_init ( void ); + #endif /* GDBMACH_H */ diff --git a/src/arch/i386/include/librm.h b/src/arch/i386/include/librm.h index fc5598eba..4a4e61aa1 100644 --- a/src/arch/i386/include/librm.h +++ b/src/arch/i386/include/librm.h @@ -209,6 +209,71 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size ); asm_code_str \ "call _phys_to_virt\n\t" +/** Number of interrupts */ +#define NUM_INT 256 + +/** An interrupt descriptor table register */ +struct idtr { + /** Limit */ + uint16_t limit; + /** Base */ + uint32_t base; +} __attribute__ (( packed )); + +/** An interrupt descriptor table entry */ +struct interrupt_descriptor { + /** Low 16 bits of address */ + uint16_t low; + /** Code segment */ + uint16_t segment; + /** Unused */ + uint8_t unused; + /** Type and attributes */ + uint8_t attr; + /** High 16 bits of address */ + uint16_t high; +} __attribute__ (( packed )); + +/** Interrupt descriptor is present */ +#define IDTE_PRESENT 0x80 + +/** Interrupt descriptor 32-bit interrupt gate type */ +#define IDTE_TYPE_IRQ32 0x0e + +/** An interrupt vector + * + * Each interrupt vector comprises an eight-byte fragment of code: + * + * 60 pushal + * b0 xx movb $INT, %al + * e9 xx xx xx xx jmp interrupt_wrapper + */ +struct interrupt_vector { + /** "pushal" instruction */ + uint8_t pushal; + /** "movb" instruction */ + uint8_t movb; + /** Interrupt number */ + uint8_t intr; + /** "jmp" instruction */ + uint8_t jmp; + /** Interrupt wrapper address offset */ + uint32_t offset; + /** Next instruction after jump */ + uint8_t next[0]; +} __attribute__ (( packed )); + +/** "pushal" instruction */ +#define PUSHAL_INSN 0x60 + +/** "movb" instruction */ +#define MOVB_INSN 0xb0 + +/** "jmp" instruction */ +#define JMP_INSN 0xe9 + +extern void set_interrupt_vector ( unsigned int intr, void *vector ); + #endif /* ASSEMBLY */ #endif /* LIBRM_H */ -- cgit v1.2.3-55-g7522