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:
Andrew Boie 2016-09-22 15:59:36 -07:00
parent ba5ddc189e
commit 4dd1ca2c1a
2 changed files with 44 additions and 34 deletions

View file

@ -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
*

View file

@ -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)) {