2 * Fiasco Interrupt Descriptor Table (IDT) Code
9 #include "mem_layout.h"
17 friend class Jdb_kern_info_bench;
19 // idt entries for 0x20 CPU exceptions, 0x10 IRQs, 7 syscalls,
20 // 0x3e/0x3f for APIC exceptions
21 static const unsigned _idt_max = 0xa0;
23 static const Address _idt = Mem_layout::Idt;
35 #include "vmem_alloc.h"
38 * IDT write-protect/write-unprotect function.
39 * @param writable true if IDT should be made writable, false otherwise
43 Idt::set_writable(bool writable)
45 Pdir::Iter e = Kmem::dir()->walk(Virt_addr(_idt));
47 // Make sure page directory entry is valid and not a 4MB page
48 assert (e.e->valid() && e.shift() < Config::SUPERPAGE_SHIFT);
51 e.e->add_attr(Pt_entry::Writable); // Make read-write
53 e.e->del_attr(Pt_entry::Writable); // Make read-only
55 Mem_unit::tlb_flush (_idt);
58 PUBLIC static FIASCO_INIT
60 Idt::init_table(Idt_init_entry *src)
62 Idt_entry *entries = (Idt_entry*)_idt;
66 entries[src->vector] =
67 ((src->type & 0x1f) == 0x05) // task gate?
68 ? Idt_entry(src->entry, src->type)
69 : Idt_entry(src->entry, Gdt::gdt_code_kernel, src->type);
75 * IDT initialization function. Sets up initial interrupt vectors.
76 * It also write-protects the IDT because of the infamous Pentium F00F bug.
78 PUBLIC static FIASCO_INIT
82 if (!Vmem_alloc::page_alloc((void *) _idt, Vmem_alloc::ZERO_FILL))
83 panic("IDT allocation failure");
85 init_table((Idt_init_entry*)&idt_init_table);
96 Pseudo_descriptor desc(_idt, _idt_max*sizeof(Idt_entry)-1);
102 Idt::set_entry(unsigned vector, Idt_entry entry)
104 assert (vector < _idt_max);
108 Idt_entry *entries = (Idt_entry*)_idt;
109 entries[vector] = entry;
115 Idt::get(unsigned vector)
117 assert (vector < _idt_max);
119 return ((Idt_entry*)_idt)[vector];
123 * IDT patching function.
124 * Allows to change interrupt gate vectors at runtime.
125 * It makes the IDT writable for the duration of this operation.
126 * @param vector interrupt vector to be modified
127 * @param func new handler function for this interrupt vector
128 * @param user true if user mode can use this vector, false otherwise
132 Idt::set_entry(unsigned vector, Address entry, bool user)
134 assert (vector < _idt_max);
138 Idt_entry *entries = (Idt_entry*)_idt;
140 entries[vector] = Idt_entry(entry, Gdt::gdt_code_kernel,
141 Idt_entry::Access_intr_gate |
142 (user ? Idt_entry::Access_user
143 : Idt_entry::Access_kernel));
145 entries[vector].clear();
152 Idt::get_entry(unsigned vector)
154 assert (vector < _idt_max);
155 Idt_entry *entries = (Idt_entry*)_idt;
156 return entries[vector].offset();
167 //---------------------------------------------------------------------------
168 IMPLEMENTATION[ia32 | amd64]:
173 * IDT loading function.
174 * Loads IDT base and limit into the CPU.
175 * @param desc IDT descriptor (base address, limit)
179 Idt::set(Pseudo_descriptor *desc)
181 asm volatile ("lidt %0" : : "m" (*desc));
186 Idt::get(Pseudo_descriptor *desc)
188 asm volatile ("sidt %0" : "=m" (*desc) : : "memory");
191 extern "C" void entry_int_timer();
192 extern "C" void entry_int_timer_slow();
193 extern "C" void entry_int7();
194 extern "C" void entry_intf();
195 extern "C" void entry_int_pic_ignore();
198 * Set IDT vector to the normal timer interrupt handler.
202 Idt::set_vectors_run()
204 Address func = (Config::esc_hack || Config::watchdog ||
205 Config::serial_esc==Config::SERIAL_ESC_NOIRQ)
206 ? (Address)entry_int_timer_slow // slower for debugging
207 : (Address)entry_int_timer; // non-debugging
209 set_entry(Config::scheduler_irq_vector, func, false);
211 if (!Irq_chip::hw_chip->is_free(0x7))
212 Irq_chip::hw_chip->reset(0x07);
214 if (!Irq_chip::hw_chip->is_free(0xf))
215 Irq_chip::hw_chip->reset(0x0f);
220 //---------------------------------------------------------------------------
223 #include "emulation.h"
227 Idt::set(Pseudo_descriptor *desc)
229 Emulation::lidt(desc);
234 Idt::get(Pseudo_descriptor *desc)
236 Emulation::sidt(desc);