x86: add _init_irq_gate and use it in gen_idt
Change-Id: Id655e5c42ca82e48c5e6d80dcb1c7db8d207eb25 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
ba5ddc189e
commit
4dd1ca2c1a
|
@ -72,6 +72,8 @@ extern "C" {
|
|||
#define DT_CONFORM 1
|
||||
#define DT_NONCONFORM 0
|
||||
|
||||
#define DT_TYPE_SYSTEM 0
|
||||
#define DT_TYPE_CODEDATA 1
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
|
@ -397,6 +399,45 @@ struct __packed far_ptr {
|
|||
extern struct pseudo_descriptor _gdt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Properly set the segment descriptor segment and offset
|
||||
*
|
||||
* Used for call/interrupt/trap gates
|
||||
*
|
||||
* @param sd Segment descriptor
|
||||
* @param offset Offset within segment
|
||||
* @param segment_selector Segment selector
|
||||
*/
|
||||
static inline void _sd_set_seg_offset(struct segment_descriptor *sd,
|
||||
uint16_t segment_selector,
|
||||
uint32_t offset)
|
||||
{
|
||||
sd->offset_low = offset & 0xFFFF;
|
||||
sd->offset_hi = offset >> 16;
|
||||
sd->segment_selector = segment_selector;
|
||||
sd->always_0_0 = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize an segment descriptor to be a 32-bit IRQ gate
|
||||
*
|
||||
* @param sd Segment descriptor memory
|
||||
* @param seg_selector Segment selector of handler
|
||||
* @param offset offset of handler
|
||||
* @param dpl descriptor privilege level
|
||||
*/
|
||||
static inline void _init_irq_gate(struct segment_descriptor *sd,
|
||||
uint16_t seg_selector, uint32_t offset,
|
||||
uint32_t dpl)
|
||||
{
|
||||
_sd_set_seg_offset(sd, seg_selector, offset);
|
||||
sd->dpl = dpl;
|
||||
sd->descriptor_type = DT_TYPE_SYSTEM;
|
||||
sd->present = 1;
|
||||
sd->type = SEG_TYPE_IRQ_GATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an IA far jump to code within another code segment
|
||||
*
|
||||
|
|
|
@ -77,8 +77,6 @@ static void generate_idt(void);
|
|||
static void generate_interrupt_vector_bitmap(void);
|
||||
static void clean_exit(int exit_code);
|
||||
static void debug(const char *format, ...);
|
||||
static void idt_entry_create(uint64_t *pIdtEntry, uint32_t routine,
|
||||
unsigned int dpl);
|
||||
|
||||
struct genidt_header_s {
|
||||
uint32_t spurious_addr;
|
||||
|
@ -128,35 +126,6 @@ static void debug(const char *format, ...)
|
|||
va_end(vargs);
|
||||
}
|
||||
|
||||
static void idt_entry_create(uint64_t *pIdtEntry, uint32_t routine,
|
||||
unsigned int dpl)
|
||||
{
|
||||
uint32_t *pIdtEntry32 = (uint32_t *)pIdtEntry;
|
||||
|
||||
pIdtEntry32[0] = (KERNEL_CODE_SEG_SELECTOR << 16) |
|
||||
((uint16_t)routine);
|
||||
|
||||
/*
|
||||
* The constant 0x8e00 results from the following:
|
||||
*
|
||||
* Segment Present = 1
|
||||
*
|
||||
* Descriptor Privilege Level (DPL) = 0 (dpl arg will be or'ed in)
|
||||
*
|
||||
* Interrupt Gate Indicator = 0xE
|
||||
* The _IntEnt() and _ExcEnt() stubs assume that an interrupt-gate
|
||||
* descriptor is used, and thus they do not issue a 'cli' instruction
|
||||
* given that the processor automatically clears the IF flag when
|
||||
* accessing the interrupt/exception handler via an interrupt-gate.
|
||||
*
|
||||
* Size of Gate (D) = 1
|
||||
*
|
||||
* Reserved = 0
|
||||
*/
|
||||
|
||||
pIdtEntry32[1] = (routine & 0xffff0000) | (0x8e00 | (dpl << 13));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
get_exec_name(argv[0]);
|
||||
|
@ -489,11 +458,11 @@ static void generate_idt(void)
|
|||
*/
|
||||
|
||||
for (i = 0; i < num_vectors; i++) {
|
||||
uint64_t idt_entry;
|
||||
struct segment_descriptor idt_entry;
|
||||
ssize_t bytes_written;
|
||||
|
||||
idt_entry_create(&idt_entry, generated_entry[i].isr,
|
||||
generated_entry[i].dpl);
|
||||
_init_irq_gate(&idt_entry, KERNEL_CODE_SEG_SELECTOR,
|
||||
generated_entry[i].isr, generated_entry[i].dpl);
|
||||
|
||||
bytes_written = write(fds[OFILE], &idt_entry, sizeof(idt_entry));
|
||||
if (bytes_written != sizeof(idt_entry)) {
|
||||
|
|
Loading…
Reference in a new issue