summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/i386/CPU.cpp621
-rw-r--r--Kernel/Arch/i386/CPU.h153
-rw-r--r--Kernel/Arch/i386/ISRStubs.h433
-rw-r--r--Kernel/Arch/i386/Interrupts.h12
-rw-r--r--Kernel/Arch/i386/ProcessorInfo.h4
5 files changed, 789 insertions, 434 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 307338edcd..20d2cd205c 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -49,6 +49,7 @@
//#define PAGE_FAULT_DEBUG
//#define CONTEXT_SWITCH_DEBUG
+//#define SMP_DEBUG
namespace Kernel {
@@ -153,7 +154,7 @@ void handle_crash(RegisterState& regs, const char* description, int signal, bool
auto process = Process::current();
if (!process) {
klog() << description << " with !current";
- hang();
+ Processor::halt();
}
// If a process crashed while inspecting another process,
@@ -166,7 +167,7 @@ void handle_crash(RegisterState& regs, const char* description, int signal, bool
if (process->is_ring0()) {
klog() << "Crash in ring 0 :(";
dump_backtrace();
- hang();
+ Processor::halt();
}
cli();
@@ -291,7 +292,7 @@ void debug_handler(TrapFrame* trap)
auto current_thread = Thread::current();
if (&current_thread->process() == nullptr || (regs.cs & 3) == 0) {
klog() << "Debug Exception in Ring0";
- hang();
+ Processor::halt();
return;
}
constexpr u8 REASON_SINGLESTEP = 14;
@@ -313,7 +314,7 @@ void breakpoint_handler(TrapFrame* trap)
auto current_thread = Thread::current();
if (&current_thread->process() == nullptr || (regs.cs & 3) == 0) {
klog() << "Breakpoint Trap in Ring0";
- hang();
+ Processor::halt();
return;
}
if (current_thread->tracer()) {
@@ -336,7 +337,7 @@ void breakpoint_handler(TrapFrame* trap)
asm("movl %%cr4, %%eax" \
: "=a"(cr4)); \
klog() << "CR0=" << String::format("%x", cr0) << " CR2=" << String::format("%x", cr2) << " CR3=" << String::format("%x", cr3) << " CR4=" << String::format("%x", cr4); \
- hang(); \
+ Processor::halt(); \
}
EH(2, "Unknown error")
@@ -358,7 +359,7 @@ const DescriptorTablePointer& get_idtr()
static void unimp_trap()
{
klog() << "Unhandled IRQ.";
- hang();
+ Processor::Processor::halt();
}
GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number)
@@ -374,6 +375,7 @@ static void revert_to_unused_handler(u8 interrupt_number)
void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
{
+ ASSERT(interrupt_number < GENERIC_INTERRUPT_HANDLERS_COUNT);
if (s_interrupt_handler[interrupt_number] != nullptr) {
if (s_interrupt_handler[interrupt_number]->type() == HandlerType::UnhandledInterruptHandler) {
s_interrupt_handler[interrupt_number] = &handler;
@@ -442,10 +444,7 @@ void flush_idt()
static void idt_init()
{
s_idtr.address = s_idt;
- s_idtr.limit = 0x100 * 8 - 1;
-
- for (u8 i = 0xff; i > 0x10; --i)
- register_interrupt_handler(i, unimp_trap);
+ s_idtr.limit = 256 * 8 - 1;
register_interrupt_handler(0x00, divide_error_asm_entry);
register_user_callable_interrupt_handler(0x01, debug_asm_entry);
@@ -465,134 +464,185 @@ static void idt_init()
register_interrupt_handler(0x0f, _exception15);
register_interrupt_handler(0x10, _exception16);
- register_interrupt_handler(0x50, interrupt_0_asm_entry);
- register_interrupt_handler(0x51, interrupt_1_asm_entry);
- register_interrupt_handler(0x52, interrupt_2_asm_entry);
- register_interrupt_handler(0x53, interrupt_3_asm_entry);
- register_interrupt_handler(0x54, interrupt_4_asm_entry);
- register_interrupt_handler(0x55, interrupt_5_asm_entry);
- register_interrupt_handler(0x56, interrupt_6_asm_entry);
- register_interrupt_handler(0x57, interrupt_7_asm_entry);
- register_interrupt_handler(0x58, interrupt_8_asm_entry);
- register_interrupt_handler(0x59, interrupt_9_asm_entry);
- register_interrupt_handler(0x5a, interrupt_10_asm_entry);
- register_interrupt_handler(0x5b, interrupt_11_asm_entry);
- register_interrupt_handler(0x5c, interrupt_12_asm_entry);
- register_interrupt_handler(0x5d, interrupt_13_asm_entry);
- register_interrupt_handler(0x5e, interrupt_14_asm_entry);
- register_interrupt_handler(0x5f, interrupt_15_asm_entry);
- register_interrupt_handler(0x60, interrupt_16_asm_entry);
- register_interrupt_handler(0x61, interrupt_17_asm_entry);
- register_interrupt_handler(0x62, interrupt_18_asm_entry);
- register_interrupt_handler(0x63, interrupt_19_asm_entry);
- register_interrupt_handler(0x64, interrupt_20_asm_entry);
- register_interrupt_handler(0x65, interrupt_21_asm_entry);
- register_interrupt_handler(0x66, interrupt_22_asm_entry);
- register_interrupt_handler(0x67, interrupt_23_asm_entry);
- register_interrupt_handler(0x68, interrupt_24_asm_entry);
- register_interrupt_handler(0x69, interrupt_25_asm_entry);
- register_interrupt_handler(0x6a, interrupt_26_asm_entry);
- register_interrupt_handler(0x6b, interrupt_27_asm_entry);
- register_interrupt_handler(0x6c, interrupt_28_asm_entry);
- register_interrupt_handler(0x6d, interrupt_29_asm_entry);
- register_interrupt_handler(0x6e, interrupt_30_asm_entry);
- register_interrupt_handler(0x6f, interrupt_31_asm_entry);
- register_interrupt_handler(0x70, interrupt_32_asm_entry);
- register_interrupt_handler(0x71, interrupt_33_asm_entry);
- register_interrupt_handler(0x72, interrupt_34_asm_entry);
- register_interrupt_handler(0x73, interrupt_35_asm_entry);
- register_interrupt_handler(0x74, interrupt_36_asm_entry);
- register_interrupt_handler(0x75, interrupt_37_asm_entry);
- register_interrupt_handler(0x76, interrupt_38_asm_entry);
- register_interrupt_handler(0x77, interrupt_39_asm_entry);
- register_interrupt_handler(0x78, interrupt_40_asm_entry);
- register_interrupt_handler(0x79, interrupt_41_asm_entry);
- register_interrupt_handler(0x7a, interrupt_42_asm_entry);
- register_interrupt_handler(0x7b, interrupt_43_asm_entry);
- register_interrupt_handler(0x7c, interrupt_44_asm_entry);
- register_interrupt_handler(0x7d, interrupt_45_asm_entry);
- register_interrupt_handler(0x7e, interrupt_46_asm_entry);
- register_interrupt_handler(0x7f, interrupt_47_asm_entry);
- register_interrupt_handler(0x80, interrupt_48_asm_entry);
- register_interrupt_handler(0x81, interrupt_49_asm_entry);
- register_interrupt_handler(0x82, interrupt_50_asm_entry);
- register_interrupt_handler(0x83, interrupt_51_asm_entry);
- register_interrupt_handler(0x84, interrupt_52_asm_entry);
- register_interrupt_handler(0x85, interrupt_53_asm_entry);
- register_interrupt_handler(0x86, interrupt_54_asm_entry);
- register_interrupt_handler(0x87, interrupt_55_asm_entry);
- register_interrupt_handler(0x88, interrupt_56_asm_entry);
- register_interrupt_handler(0x89, interrupt_57_asm_entry);
- register_interrupt_handler(0x8a, interrupt_58_asm_entry);
- register_interrupt_handler(0x8b, interrupt_59_asm_entry);
- register_interrupt_handler(0x8c, interrupt_60_asm_entry);
- register_interrupt_handler(0x8d, interrupt_61_asm_entry);
- register_interrupt_handler(0x8e, interrupt_62_asm_entry);
- register_interrupt_handler(0x8f, interrupt_63_asm_entry);
- register_interrupt_handler(0x90, interrupt_64_asm_entry);
- register_interrupt_handler(0x91, interrupt_65_asm_entry);
- register_interrupt_handler(0x92, interrupt_66_asm_entry);
- register_interrupt_handler(0x93, interrupt_67_asm_entry);
- register_interrupt_handler(0x94, interrupt_68_asm_entry);
- register_interrupt_handler(0x95, interrupt_69_asm_entry);
- register_interrupt_handler(0x96, interrupt_70_asm_entry);
- register_interrupt_handler(0x97, interrupt_71_asm_entry);
- register_interrupt_handler(0x98, interrupt_72_asm_entry);
- register_interrupt_handler(0x99, interrupt_73_asm_entry);
- register_interrupt_handler(0x9a, interrupt_74_asm_entry);
- register_interrupt_handler(0x9b, interrupt_75_asm_entry);
- register_interrupt_handler(0x9c, interrupt_76_asm_entry);
- register_interrupt_handler(0x9d, interrupt_77_asm_entry);
- register_interrupt_handler(0x9e, interrupt_78_asm_entry);
- register_interrupt_handler(0x9f, interrupt_79_asm_entry);
- register_interrupt_handler(0xa0, interrupt_80_asm_entry);
- register_interrupt_handler(0xa1, interrupt_81_asm_entry);
- register_interrupt_handler(0xa2, interrupt_82_asm_entry);
- register_interrupt_handler(0xa3, interrupt_83_asm_entry);
- register_interrupt_handler(0xa4, interrupt_84_asm_entry);
- register_interrupt_handler(0xa5, interrupt_85_asm_entry);
- register_interrupt_handler(0xa6, interrupt_86_asm_entry);
- register_interrupt_handler(0xa7, interrupt_87_asm_entry);
- register_interrupt_handler(0xa8, interrupt_88_asm_entry);
- register_interrupt_handler(0xa9, interrupt_89_asm_entry);
- register_interrupt_handler(0xaa, interrupt_90_asm_entry);
- register_interrupt_handler(0xab, interrupt_91_asm_entry);
- register_interrupt_handler(0xac, interrupt_92_asm_entry);
- register_interrupt_handler(0xad, interrupt_93_asm_entry);
- register_interrupt_handler(0xae, interrupt_94_asm_entry);
- register_interrupt_handler(0xaf, interrupt_95_asm_entry);
- register_interrupt_handler(0xb0, interrupt_96_asm_entry);
- register_interrupt_handler(0xb1, interrupt_97_asm_entry);
- register_interrupt_handler(0xb2, interrupt_98_asm_entry);
- register_interrupt_handler(0xb3, interrupt_99_asm_entry);
- register_interrupt_handler(0xb4, interrupt_100_asm_entry);
- register_interrupt_handler(0xb5, interrupt_101_asm_entry);
- register_interrupt_handler(0xb6, interrupt_102_asm_entry);
- register_interrupt_handler(0xb7, interrupt_103_asm_entry);
- register_interrupt_handler(0xb8, interrupt_104_asm_entry);
- register_interrupt_handler(0xb9, interrupt_105_asm_entry);
- register_interrupt_handler(0xba, interrupt_106_asm_entry);
- register_interrupt_handler(0xbb, interrupt_107_asm_entry);
- register_interrupt_handler(0xbc, interrupt_108_asm_entry);
- register_interrupt_handler(0xbd, interrupt_109_asm_entry);
- register_interrupt_handler(0xbe, interrupt_110_asm_entry);
- register_interrupt_handler(0xbf, interrupt_111_asm_entry);
- register_interrupt_handler(0xc0, interrupt_112_asm_entry);
- register_interrupt_handler(0xc1, interrupt_113_asm_entry);
- register_interrupt_handler(0xc2, interrupt_114_asm_entry);
- register_interrupt_handler(0xc3, interrupt_115_asm_entry);
- register_interrupt_handler(0xc4, interrupt_116_asm_entry);
- register_interrupt_handler(0xc5, interrupt_117_asm_entry);
- register_interrupt_handler(0xc6, interrupt_118_asm_entry);
- register_interrupt_handler(0xc7, interrupt_119_asm_entry);
- register_interrupt_handler(0xc8, interrupt_120_asm_entry);
- register_interrupt_handler(0xc9, interrupt_121_asm_entry);
- register_interrupt_handler(0xca, interrupt_122_asm_entry);
- register_interrupt_handler(0xcb, interrupt_123_asm_entry);
- register_interrupt_handler(0xcc, interrupt_124_asm_entry);
- register_interrupt_handler(0xcd, interrupt_125_asm_entry);
- register_interrupt_handler(0xce, interrupt_126_asm_entry);
- register_interrupt_handler(0xcf, interrupt_127_asm_entry);
+ for (u8 i = 0x11; i < 0x50; i++)
+ register_interrupt_handler(i, unimp_trap);
+
+ register_interrupt_handler(0x50, interrupt_80_asm_entry);
+ register_interrupt_handler(0x51, interrupt_81_asm_entry);
+ register_interrupt_handler(0x52, interrupt_82_asm_entry);
+ register_interrupt_handler(0x53, interrupt_83_asm_entry);
+ register_interrupt_handler(0x54, interrupt_84_asm_entry);
+ register_interrupt_handler(0x55, interrupt_85_asm_entry);
+ register_interrupt_handler(0x56, interrupt_86_asm_entry);
+ register_interrupt_handler(0x57, interrupt_87_asm_entry);
+ register_interrupt_handler(0x58, interrupt_88_asm_entry);
+ register_interrupt_handler(0x59, interrupt_89_asm_entry);
+ register_interrupt_handler(0x5a, interrupt_90_asm_entry);
+ register_interrupt_handler(0x5b, interrupt_91_asm_entry);
+ register_interrupt_handler(0x5c, interrupt_92_asm_entry);
+ register_interrupt_handler(0x5d, interrupt_93_asm_entry);
+ register_interrupt_handler(0x5e, interrupt_94_asm_entry);
+ register_interrupt_handler(0x5f, interrupt_95_asm_entry);
+ register_interrupt_handler(0x60, interrupt_96_asm_entry);
+ register_interrupt_handler(0x61, interrupt_97_asm_entry);
+ register_interrupt_handler(0x62, interrupt_98_asm_entry);
+ register_interrupt_handler(0x63, interrupt_99_asm_entry);
+ register_interrupt_handler(0x64, interrupt_100_asm_entry);
+ register_interrupt_handler(0x65, interrupt_101_asm_entry);
+ register_interrupt_handler(0x66, interrupt_102_asm_entry);
+ register_interrupt_handler(0x67, interrupt_103_asm_entry);
+ register_interrupt_handler(0x68, interrupt_104_asm_entry);
+ register_interrupt_handler(0x69, interrupt_105_asm_entry);
+ register_interrupt_handler(0x6a, interrupt_106_asm_entry);
+ register_interrupt_handler(0x6b, interrupt_107_asm_entry);
+ register_interrupt_handler(0x6c, interrupt_108_asm_entry);
+ register_interrupt_handler(0x6d, interrupt_109_asm_entry);
+ register_interrupt_handler(0x6e, interrupt_110_asm_entry);
+ register_interrupt_handler(0x6f, interrupt_111_asm_entry);
+ register_interrupt_handler(0x70, interrupt_112_asm_entry);
+ register_interrupt_handler(0x71, interrupt_113_asm_entry);
+ register_interrupt_handler(0x72, interrupt_114_asm_entry);
+ register_interrupt_handler(0x73, interrupt_115_asm_entry);
+ register_interrupt_handler(0x74, interrupt_116_asm_entry);
+ register_interrupt_handler(0x75, interrupt_117_asm_entry);
+ register_interrupt_handler(0x76, interrupt_118_asm_entry);
+ register_interrupt_handler(0x77, interrupt_119_asm_entry);
+ register_interrupt_handler(0x78, interrupt_120_asm_entry);
+ register_interrupt_handler(0x79, interrupt_121_asm_entry);
+ register_interrupt_handler(0x7a, interrupt_122_asm_entry);
+ register_interrupt_handler(0x7b, interrupt_123_asm_entry);
+ register_interrupt_handler(0x7c, interrupt_124_asm_entry);
+ register_interrupt_handler(0x7d, interrupt_125_asm_entry);
+ register_interrupt_handler(0x7e, interrupt_126_asm_entry);
+ register_interrupt_handler(0x7f, interrupt_127_asm_entry);
+ register_interrupt_handler(0x80, interrupt_128_asm_entry);
+ register_interrupt_handler(0x81, interrupt_129_asm_entry);
+ register_interrupt_handler(0x82, interrupt_130_asm_entry);
+ register_interrupt_handler(0x83, interrupt_131_asm_entry);
+ register_interrupt_handler(0x84, interrupt_132_asm_entry);
+ register_interrupt_handler(0x85, interrupt_133_asm_entry);
+ register_interrupt_handler(0x86, interrupt_134_asm_entry);
+ register_interrupt_handler(0x87, interrupt_135_asm_entry);
+ register_interrupt_handler(0x88, interrupt_136_asm_entry);
+ register_interrupt_handler(0x89, interrupt_137_asm_entry);
+ register_interrupt_handler(0x8a, interrupt_138_asm_entry);
+ register_interrupt_handler(0x8b, interrupt_139_asm_entry);
+ register_interrupt_handler(0x8c, interrupt_140_asm_entry);
+ register_interrupt_handler(0x8d, interrupt_141_asm_entry);
+ register_interrupt_handler(0x8e, interrupt_142_asm_entry);
+ register_interrupt_handler(0x8f, interrupt_143_asm_entry);
+ register_interrupt_handler(0x90, interrupt_144_asm_entry);
+ register_interrupt_handler(0x91, interrupt_145_asm_entry);
+ register_interrupt_handler(0x92, interrupt_146_asm_entry);
+ register_interrupt_handler(0x93, interrupt_147_asm_entry);
+ register_interrupt_handler(0x94, interrupt_148_asm_entry);
+ register_interrupt_handler(0x95, interrupt_149_asm_entry);
+ register_interrupt_handler(0x96, interrupt_150_asm_entry);
+ register_interrupt_handler(0x97, interrupt_151_asm_entry);
+ register_interrupt_handler(0x98, interrupt_152_asm_entry);
+ register_interrupt_handler(0x99, interrupt_153_asm_entry);
+ register_interrupt_handler(0x9a, interrupt_154_asm_entry);
+ register_interrupt_handler(0x9b, interrupt_155_asm_entry);
+ register_interrupt_handler(0x9c, interrupt_156_asm_entry);
+ register_interrupt_handler(0x9d, interrupt_157_asm_entry);
+ register_interrupt_handler(0x9e, interrupt_158_asm_entry);
+ register_interrupt_handler(0x9f, interrupt_159_asm_entry);
+ register_interrupt_handler(0xa0, interrupt_160_asm_entry);
+ register_interrupt_handler(0xa1, interrupt_161_asm_entry);
+ register_interrupt_handler(0xa2, interrupt_162_asm_entry);
+ register_interrupt_handler(0xa3, interrupt_163_asm_entry);
+ register_interrupt_handler(0xa4, interrupt_164_asm_entry);
+ register_interrupt_handler(0xa5, interrupt_165_asm_entry);
+ register_interrupt_handler(0xa6, interrupt_166_asm_entry);
+ register_interrupt_handler(0xa7, interrupt_167_asm_entry);
+ register_interrupt_handler(0xa8, interrupt_168_asm_entry);
+ register_interrupt_handler(0xa9, interrupt_169_asm_entry);
+ register_interrupt_handler(0xaa, interrupt_170_asm_entry);
+ register_interrupt_handler(0xab, interrupt_171_asm_entry);
+ register_interrupt_handler(0xac, interrupt_172_asm_entry);
+ register_interrupt_handler(0xad, interrupt_173_asm_entry);
+ register_interrupt_handler(0xae, interrupt_174_asm_entry);
+ register_interrupt_handler(0xaf, interrupt_175_asm_entry);
+ register_interrupt_handler(0xb0, interrupt_176_asm_entry);
+ register_interrupt_handler(0xb1, interrupt_177_asm_entry);
+ register_interrupt_handler(0xb2, interrupt_178_asm_entry);
+ register_interrupt_handler(0xb3, interrupt_179_asm_entry);
+ register_interrupt_handler(0xb4, interrupt_180_asm_entry);
+ register_interrupt_handler(0xb5, interrupt_181_asm_entry);
+ register_interrupt_handler(0xb6, interrupt_182_asm_entry);
+ register_interrupt_handler(0xb7, interrupt_183_asm_entry);
+ register_interrupt_handler(0xb8, interrupt_184_asm_entry);
+ register_interrupt_handler(0xb9, interrupt_185_asm_entry);
+ register_interrupt_handler(0xba, interrupt_186_asm_entry);
+ register_interrupt_handler(0xbb, interrupt_187_asm_entry);
+ register_interrupt_handler(0xbc, interrupt_188_asm_entry);
+ register_interrupt_handler(0xbd, interrupt_189_asm_entry);
+ register_interrupt_handler(0xbe, interrupt_190_asm_entry);
+ register_interrupt_handler(0xbf, interrupt_191_asm_entry);
+ register_interrupt_handler(0xc0, interrupt_192_asm_entry);
+ register_interrupt_handler(0xc1, interrupt_193_asm_entry);
+ register_interrupt_handler(0xc2, interrupt_194_asm_entry);
+ register_interrupt_handler(0xc3, interrupt_195_asm_entry);
+ register_interrupt_handler(0xc4, interrupt_196_asm_entry);
+ register_interrupt_handler(0xc5, interrupt_197_asm_entry);
+ register_interrupt_handler(0xc6, interrupt_198_asm_entry);
+ register_interrupt_handler(0xc7, interrupt_199_asm_entry);
+ register_interrupt_handler(0xc8, interrupt_200_asm_entry);
+ register_interrupt_handler(0xc9, interrupt_201_asm_entry);
+ register_interrupt_handler(0xca, interrupt_202_asm_entry);
+ register_interrupt_handler(0xcb, interrupt_203_asm_entry);
+ register_interrupt_handler(0xcc, interrupt_204_asm_entry);
+ register_interrupt_handler(0xcd, interrupt_205_asm_entry);
+ register_interrupt_handler(0xce, interrupt_206_asm_entry);
+ register_interrupt_handler(0xcf, interrupt_207_asm_entry);
+ register_interrupt_handler(0xd0, interrupt_208_asm_entry);
+ register_interrupt_handler(0xd1, interrupt_209_asm_entry);
+ register_interrupt_handler(0xd2, interrupt_210_asm_entry);
+ register_interrupt_handler(0xd3, interrupt_211_asm_entry);
+ register_interrupt_handler(0xd4, interrupt_212_asm_entry);
+ register_interrupt_handler(0xd5, interrupt_213_asm_entry);
+ register_interrupt_handler(0xd6, interrupt_214_asm_entry);
+ register_interrupt_handler(0xd7, interrupt_215_asm_entry);
+ register_interrupt_handler(0xd8, interrupt_216_asm_entry);
+ register_interrupt_handler(0xd9, interrupt_217_asm_entry);
+ register_interrupt_handler(0xda, interrupt_218_asm_entry);
+ register_interrupt_handler(0xdb, interrupt_219_asm_entry);
+ register_interrupt_handler(0xdc, interrupt_220_asm_entry);
+ register_interrupt_handler(0xdd, interrupt_221_asm_entry);
+ register_interrupt_handler(0xde, interrupt_222_asm_entry);
+ register_interrupt_handler(0xdf, interrupt_223_asm_entry);
+ register_interrupt_handler(0xe0, interrupt_224_asm_entry);
+ register_interrupt_handler(0xe1, interrupt_225_asm_entry);
+ register_interrupt_handler(0xe2, interrupt_226_asm_entry);
+ register_interrupt_handler(0xe3, interrupt_227_asm_entry);
+ register_interrupt_handler(0xe4, interrupt_228_asm_entry);
+ register_interrupt_handler(0xe5, interrupt_229_asm_entry);
+ register_interrupt_handler(0xe6, interrupt_230_asm_entry);
+ register_interrupt_handler(0xe7, interrupt_231_asm_entry);
+ register_interrupt_handler(0xe8, interrupt_232_asm_entry);
+ register_interrupt_handler(0xe9, interrupt_233_asm_entry);
+ register_interrupt_handler(0xea, interrupt_234_asm_entry);
+ register_interrupt_handler(0xeb, interrupt_235_asm_entry);
+ register_interrupt_handler(0xec, interrupt_236_asm_entry);
+ register_interrupt_handler(0xed, interrupt_237_asm_entry);
+ register_interrupt_handler(0xee, interrupt_238_asm_entry);
+ register_interrupt_handler(0xef, interrupt_239_asm_entry);
+ register_interrupt_handler(0xf0, interrupt_240_asm_entry);
+ register_interrupt_handler(0xf1, interrupt_241_asm_entry);
+ register_interrupt_handler(0xf2, interrupt_242_asm_entry);
+ register_interrupt_handler(0xf3, interrupt_243_asm_entry);
+ register_interrupt_handler(0xf4, interrupt_244_asm_entry);
+ register_interrupt_handler(0xf5, interrupt_245_asm_entry);
+ register_interrupt_handler(0xf6, interrupt_246_asm_entry);
+ register_interrupt_handler(0xf7, interrupt_247_asm_entry);
+ register_interrupt_handler(0xf8, interrupt_248_asm_entry);
+ register_interrupt_handler(0xf9, interrupt_249_asm_entry);
+ register_interrupt_handler(0xfa, interrupt_250_asm_entry);
+ register_interrupt_handler(0xfb, interrupt_251_asm_entry);
+ register_interrupt_handler(0xfc, interrupt_252_asm_entry);
+ register_interrupt_handler(0xfd, interrupt_253_asm_entry);
+ register_interrupt_handler(0xfe, interrupt_254_asm_entry);
+ register_interrupt_handler(0xff, interrupt_255_asm_entry);
dbg() << "Installing Unhandled Handlers";
@@ -688,6 +738,8 @@ FPUState Processor::s_clean_fpu_state;
static Vector<Processor*>* s_processors;
static SpinLock s_processor_lock;
+volatile u32 Processor::g_total_processors;
+static volatile bool s_smp_enabled;
Vector<Processor*>& Processor::processors()
{
@@ -707,6 +759,12 @@ Processor& Processor::by_id(u32 cpu)
return *procs[cpu];
}
+[[noreturn]] static inline void halt_this()
+{
+ for (;;) {
+ asm volatile("cli; hlt");
+ }
+}
void Processor::cpu_detect()
{
@@ -868,13 +926,21 @@ void Processor::early_initialize(u32 cpu)
m_invoke_scheduler_async = false;
m_scheduler_initialized = false;
+ m_message_queue = nullptr;
m_idle_thread = nullptr;
m_current_thread = nullptr;
m_mm_data = nullptr;
m_info = nullptr;
- cpu_setup();
+ m_halt_requested = false;
+ if (cpu == 0) {
+ s_smp_enabled = false;
+ atomic_store(&g_total_processors, 1u, AK::MemoryOrder::memory_order_release);
+ } else {
+ atomic_fetch_add(&g_total_processors, 1u, AK::MemoryOrder::memory_order_acq_rel);
+ }
+ cpu_setup();
gdt_init();
ASSERT(&current() == this); // sanity check
}
@@ -910,9 +976,9 @@ void Processor::initialize(u32 cpu)
if (cpu >= s_processors->size())
s_processors->resize(cpu + 1);
(*s_processors)[cpu] = this;
- }
- klog() << "CPU[" << cpu << "]: initialized Processor at " << VirtualAddress(FlatPtr(this));
+ klog() << "CPU[" << cpu << "]: initialized Processor at " << VirtualAddress(FlatPtr(this));
+ }
}
void Processor::write_raw_gdt_entry(u16 selector, u32 low, u32 high)
@@ -979,7 +1045,7 @@ bool Processor::get_context_frame_ptr(Thread& thread, u32& frame_ptr, u32& eip)
// TODO: If this is the case, the thread is currently running
// on another processor. We can't trust the kernel stack as
// it may be changing at any time. We need to probably send
- // an ICI to that processor, have it walk the stack and wait
+ // an IPI to that processor, have it walk the stack and wait
// until it returns the data back to us
dbg() << "CPU[" << proc.id() << "] getting stack for "
<< thread << " on other CPU# " << thread.cpu() << " not yet implemented!";
@@ -1288,12 +1354,16 @@ void Processor::initialize_context_switching(Thread& initial_thread)
"addl $20, %%ebx \n" // calculate pointer to TrapFrame
"pushl %%ebx \n"
"cld \n"
+ "pushl %[cpu] \n"
+ "call init_finished \n"
+ "addl $4, %%esp \n"
"call enter_trap_no_irq \n"
"addl $4, %%esp \n"
"lret \n"
:: [new_esp] "g" (tss.esp),
[new_eip] "a" (tss.eip),
- [from_to_thread] "b" (&initial_thread)
+ [from_to_thread] "b" (&initial_thread),
+ [cpu] "c" (id())
);
ASSERT_NOT_REACHED();
@@ -1312,7 +1382,9 @@ void Processor::exit_trap(TrapFrame& trap)
InterruptDisabler disabler;
ASSERT(m_in_irq >= trap.prev_irq_level);
m_in_irq = trap.prev_irq_level;
-
+
+ smp_process_pending_messages();
+
if (!m_in_irq && !m_in_critical)
check_invoke_scheduler();
}
@@ -1327,6 +1399,267 @@ void Processor::check_invoke_scheduler()
}
}
+void Processor::flush_tlb_local(VirtualAddress vaddr, size_t page_count)
+{
+ auto ptr = vaddr.as_ptr();
+ while (page_count > 0) {
+ asm volatile("invlpg %0"
+ :
+ : "m"(*(char*)vaddr.get())
+ : "memory");
+ ptr += PAGE_SIZE;
+ page_count--;
+ }
+}
+
+void Processor::flush_tlb(VirtualAddress vaddr, size_t page_count)
+{
+ flush_tlb_local(vaddr, page_count);
+ if (s_smp_enabled)
+ smp_broadcast_flush_tlb(vaddr, page_count);
+}
+
+static volatile ProcessorMessage* s_message_pool;
+
+void Processor::smp_return_to_pool(ProcessorMessage& msg)
+{
+ ProcessorMessage* next = nullptr;
+ do {
+ msg.next = next;
+ } while (!atomic_compare_exchange_strong(&s_message_pool, next, &msg, AK::MemoryOrder::memory_order_acq_rel));
+}
+
+ProcessorMessage& Processor::smp_get_from_pool()
+{
+ ProcessorMessage* msg;
+
+ // The assumption is that messages are never removed from the pool!
+ for (;;) {
+ msg = atomic_load(&s_message_pool, AK::MemoryOrder::memory_order_consume);
+ if (!msg) {
+ if (!Processor::current().smp_process_pending_messages()) {
+ // TODO: pause for a bit?
+ }
+ continue;
+ }
+ // If another processor were to use this message in the meanwhile,
+ // "msg" is still valid (because it never gets freed). We'd detect
+ // this because the expected value "msg" and pool would
+ // no longer match, and the compare_exchange will fail. But accessing
+ // "msg->next" is always safe here.
+ if (atomic_compare_exchange_strong(&s_message_pool, msg, msg->next, AK::MemoryOrder::memory_order_acq_rel)) {
+ // We successfully "popped" this available message
+ break;
+ }
+ }
+
+ ASSERT(msg != nullptr);
+ return *msg;
+}
+
+void Processor::smp_enable()
+{
+ size_t msg_pool_size = Processor::count() * 100u;
+ size_t msg_entries_cnt = Processor::count();
+
+ auto msgs = new ProcessorMessage[msg_pool_size];
+ auto msg_entries = new ProcessorMessageEntry[msg_pool_size * msg_entries_cnt];
+ size_t msg_entry_i = 0;
+ for (size_t i = 0; i < msg_pool_size; i++, msg_entry_i += msg_entries_cnt) {
+ auto& msg = msgs[i];
+ msg.next = i < msg_pool_size - 1 ? &msgs[i + 1] : nullptr;
+ msg.per_proc_entries = &msg_entries[msg_entry_i];
+ for (size_t k = 0; k < msg_entries_cnt; k++)
+ msg_entries[msg_entry_i + k].msg = &msg;
+ }
+
+ atomic_store(&s_message_pool, &msgs[0], AK::MemoryOrder::memory_order_release);
+
+ // Start sending IPI messages
+ s_smp_enabled = true;
+}
+
+void Processor::smp_cleanup_message(ProcessorMessage& msg)
+{
+ switch (msg.type) {
+ case ProcessorMessage::CallbackWithData:
+ if (msg.callback_with_data.free)
+ msg.callback_with_data.free(msg.callback_with_data.data);
+ break;
+ default:
+ break;
+ }
+}
+
+bool Processor::smp_process_pending_messages()
+{
+ bool did_process = false;
+ u32 prev_flags;
+ enter_critical(prev_flags);
+
+ if (auto pending_msgs = atomic_exchange(&m_message_queue, nullptr, AK::MemoryOrder::memory_order_acq_rel))
+ {
+ // We pulled the stack of pending messages in LIFO order, so we need to reverse the list first
+ auto reverse_list =
+ [](ProcessorMessageEntry* list) -> ProcessorMessageEntry*
+ {
+ ProcessorMessageEntry* rev_list = nullptr;
+ while (list) {
+ auto next = list->next;
+ list->next = rev_list;
+ rev_list = list;
+ list = next;
+ }
+ return rev_list;
+ };
+
+ pending_msgs = reverse_list(pending_msgs);
+
+ // now process in the right order
+ ProcessorMessageEntry* next_msg;
+ for (auto cur_msg = pending_msgs; cur_msg; cur_msg = next_msg) {
+ next_msg = cur_msg->next;
+ auto msg = cur_msg->msg;
+
+#ifdef SMP_DEBUG
+ dbg() << "SMP[" << id() << "]: Processing message " << VirtualAddress(msg);
+#endif
+
+ switch (msg->type) {
+ case ProcessorMessage::Callback:
+ msg->callback.handler();
+ break;
+ case ProcessorMessage::CallbackWithData:
+ msg->callback_with_data.handler(msg->callback_with_data.data);
+ break;
+ case ProcessorMessage::FlushTlb:
+ flush_tlb_local(VirtualAddress(msg->flush_tlb.ptr), msg->flush_tlb.page_count);
+ break;
+ }
+
+ bool is_async = msg->async; // Need to cache this value *before* dropping the ref count!
+ auto prev_refs = atomic_fetch_sub(&msg->refs, 1u, AK::MemoryOrder::memory_order_acq_rel);
+ ASSERT(prev_refs != 0);
+ if (prev_refs == 1) {
+ // All processors handled this. If this is an async message,
+ // we need to clean it up and return it to the pool
+ if (is_async) {
+ smp_cleanup_message(*msg);
+ smp_return_to_pool(*msg);
+ }
+ }
+
+ if (m_halt_requested)
+ halt_this();
+ }
+ did_process = true;
+ } else if (m_halt_requested) {
+ halt_this();
+ }
+
+ leave_critical(prev_flags);
+ return did_process;
+}
+
+bool Processor::smp_queue_message(ProcessorMessage& msg)
+{
+ // Note that it's quite possible that the other processor may pop
+ // the queue at any given time. We rely on the fact that the messages
+ // are pooled and never get freed!
+ auto& msg_entry = msg.per_proc_entries[id()];
+ ASSERT(msg_entry.msg == &msg);
+ ProcessorMessageEntry* next = nullptr;
+ do {
+ msg_entry.next = next;
+ } while (!atomic_compare_exchange_strong(&m_message_queue, next, &msg_entry, AK::MemoryOrder::memory_order_acq_rel));
+ return next == nullptr;
+}
+
+void Processor::smp_broadcast_message(ProcessorMessage& msg, bool async)
+{
+ auto& cur_proc = Processor::current();
+ msg.async = async;
+#ifdef SMP_DEBUG
+ dbg() << "SMP[" << cur_proc.id() << "]: Broadcast message " << VirtualAddress(&msg) << " to cpus: " << (count()) << " proc: " << VirtualAddress(&cur_proc);
+#endif
+ atomic_store(&msg.refs, count() - 1, AK::MemoryOrder::memory_order_release);
+ ASSERT(msg.refs > 0);
+ for_each(
+ [&](Processor& proc) -> IterationDecision
+ {
+ if (&proc != &cur_proc) {
+ if (proc.smp_queue_message(msg)) {
+ // TODO: only send IPI to that CPU if we queued the first
+ }
+ }
+ return IterationDecision::Continue;
+ });
+
+ // Now trigger an IPI on all other APs
+ APIC::the().broadcast_ipi();
+
+ if (!async) {
+ // If synchronous then we must cleanup and return the message back
+ // to the pool. Otherwise, the last processor to complete it will return it
+ while (atomic_load(&msg.refs, AK::MemoryOrder::memory_order_consume) != 0) {
+ // TODO: pause for a bit?
+ }
+
+ smp_cleanup_message(msg);
+ smp_return_to_pool(msg);
+ }
+}
+
+void Processor::smp_broadcast(void(*callback)(void*), void* data, void(*free_data)(void*), bool async)
+{
+ auto& msg = smp_get_from_pool();
+ msg.type = ProcessorMessage::CallbackWithData;
+ msg.callback_with_data.handler = callback;
+ msg.callback_with_data.data = data;
+ msg.callback_with_data.free = free_data;
+ smp_broadcast_message(msg, async);
+}
+
+void Processor::smp_broadcast(void(*callback)(), bool async)
+{
+ auto& msg = smp_get_from_pool();
+ msg.type = ProcessorMessage::CallbackWithData;
+ msg.callback.handler = callback;
+ smp_broadcast_message(msg, async);
+}
+
+void Processor::smp_broadcast_flush_tlb(VirtualAddress vaddr, size_t page_count)
+{
+ auto& msg = smp_get_from_pool();
+ msg.type = ProcessorMessage::FlushTlb;
+ msg.flush_tlb.ptr = vaddr.as_ptr();
+ msg.flush_tlb.page_count = page_count;
+ smp_broadcast_message(msg, false);
+}
+
+void Processor::smp_broadcast_halt()
+{
+ // We don't want to use a message, because this could have been triggered
+ // by being out of memory and we might not be able to get a message
+ for_each(
+ [&](Processor& proc) -> IterationDecision
+ {
+ proc.m_halt_requested = true;
+ return IterationDecision::Continue;
+ });
+
+ // Now trigger an IPI on all other APs
+ APIC::the().broadcast_ipi();
+}
+
+void Processor::Processor::halt()
+{
+ if (s_smp_enabled)
+ smp_broadcast_halt();
+
+ halt_this();
+}
+
void Processor::gdt_init()
{
m_gdt_length = 0;
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
index 1c53a48660..60f92e6786 100644
--- a/Kernel/Arch/i386/CPU.h
+++ b/Kernel/Arch/i386/CPU.h
@@ -26,6 +26,7 @@
#pragma once
+#include <AK/Atomic.h>
#include <AK/Badge.h>
#include <AK/Noncopyable.h>
#include <AK/Vector.h>
@@ -33,7 +34,7 @@
#include <Kernel/VirtualAddress.h>
#define PAGE_SIZE 4096
-#define GENERIC_INTERRUPT_HANDLERS_COUNT 128
+#define GENERIC_INTERRUPT_HANDLERS_COUNT (256 - IRQ_VECTOR_BASE)
#define PAGE_MASK ((FlatPtr)0xfffff000u)
namespace Kernel {
@@ -276,13 +277,6 @@ void flush_idt();
void load_task_register(u16 selector);
void handle_crash(RegisterState&, const char* description, int signal, bool out_of_memory = false);
-[[noreturn]] static inline void hang()
-{
- asm volatile("cli; hlt");
- for (;;) {
- }
-}
-
#define LSW(x) ((u32)(x)&0xFFFF)
#define MSW(x) (((u32)(x) >> 16) & 0xFFFF)
#define LSB(x) ((x)&0xFF)
@@ -307,20 +301,17 @@ inline u32 cpu_flags()
inline void set_fs(u32 segment)
{
asm volatile(
- "movl %%eax, %%fs" :: "a"(segment)
- : "memory"
- );
+ "movl %%eax, %%fs" ::"a"(segment)
+ : "memory");
}
inline void set_gs(u32 segment)
{
asm volatile(
- "movl %%eax, %%gs" :: "a"(segment)
- : "memory"
- );
+ "movl %%eax, %%gs" ::"a"(segment)
+ : "memory");
}
-
inline u32 get_fs()
{
u32 fs;
@@ -532,9 +523,9 @@ u32 read_dr6();
static inline bool is_kernel_mode()
{
u32 cs;
- asm volatile (
+ asm volatile(
"movl %%cs, %[cs] \n"
- : [cs] "=g" (cs));
+ : [ cs ] "=g"(cs));
return (cs & 3) == 0;
}
@@ -624,10 +615,48 @@ struct TrapFrame;
class ProcessorInfo;
struct MemoryManagerData;
+struct ProcessorMessageEntry;
+
+struct ProcessorMessage {
+ enum Type {
+ FlushTlb,
+ Callback,
+ CallbackWithData
+ };
+ Type type;
+ volatile u32 refs; // atomic
+ union {
+ ProcessorMessage* next; // only valid while in the pool
+ struct {
+ void (*handler)();
+ } callback;
+ struct {
+ void* data;
+ void (*handler)(void*);
+ void (*free)(void*);
+ } callback_with_data;
+ struct {
+ u8* ptr;
+ size_t page_count;
+ } flush_tlb;
+ };
+
+ volatile bool async;
+
+ ProcessorMessageEntry* per_proc_entries;
+};
+
+struct ProcessorMessageEntry {
+ ProcessorMessageEntry* next;
+ ProcessorMessage* msg;
+};
class Processor {
friend class ProcessorInfo;
+ AK_MAKE_NONCOPYABLE(Processor);
+ AK_MAKE_NONMOVABLE(Processor);
+
Processor* m_self; // must be first field (%fs offset 0x0)
DescriptorTablePointer m_gdtr;
@@ -641,48 +670,85 @@ class Processor {
TSS32 m_tss;
static FPUState s_clean_fpu_state;
CPUFeature m_features;
+ static volatile u32 g_total_processors; // atomic
ProcessorInfo* m_info;
MemoryManagerData* m_mm_data;
Thread* m_current_thread;
Thread* m_idle_thread;
+ volatile ProcessorMessageEntry* m_message_queue; // atomic, LIFO
+
bool m_invoke_scheduler_async;
bool m_scheduler_initialized;
+ bool m_halt_requested;
void gdt_init();
void write_raw_gdt_entry(u16 selector, u32 low, u32 high);
void write_gdt_entry(u16 selector, Descriptor& descriptor);
static Vector<Processor*>& processors();
+ static void smp_return_to_pool(ProcessorMessage& msg);
+ static ProcessorMessage& smp_get_from_pool();
+ static void smp_cleanup_message(ProcessorMessage& msg);
+ bool smp_queue_message(ProcessorMessage& msg);
+ static void smp_broadcast_message(ProcessorMessage& msg, bool async);
+ static void smp_broadcast_halt();
+
void cpu_detect();
void cpu_setup();
String features_string() const;
public:
+ Processor() = default;
+
void early_initialize(u32 cpu);
void initialize(u32 cpu);
+ static u32 count()
+ {
+ // NOTE: because this value never changes once all APs are booted,
+ // we don't really need to do an atomic_load() on this variable
+ return g_total_processors;
+ }
+
+ ALWAYS_INLINE static void wait_check()
+ {
+ Processor::current().smp_process_pending_messages();
+ // TODO: pause
+ }
+
+ [[noreturn]] static void halt();
+
+ static void flush_entire_tlb_local()
+ {
+ write_cr3(read_cr3());
+ }
+
+ static void flush_tlb_local(VirtualAddress vaddr, size_t page_count);
+ static void flush_tlb(VirtualAddress vaddr, size_t page_count);
+
Descriptor& get_gdt_entry(u16 selector);
void flush_gdt();
const DescriptorTablePointer& get_gdtr();
static Processor& by_id(u32 cpu);
- template <typename Callback>
+ template<typename Callback>
static inline IterationDecision for_each(Callback callback)
{
auto& procs = processors();
- for (auto it = procs.begin(); it != procs.end(); ++it) {
- if (callback(**it) == IterationDecision::Break)
+ size_t count = procs.size();
+ for (size_t i = 0; i < count; i++) {
+ if (callback(*procs[i]) == IterationDecision::Break)
return IterationDecision::Break;
}
return IterationDecision::Continue;
}
-
+
ALWAYS_INLINE ProcessorInfo& info() { return *m_info; }
-
+
ALWAYS_INLINE static Processor& current()
{
return *(Processor*)read_fs_u32(0);
@@ -729,19 +795,30 @@ public:
{
return m_cpu;
}
-
+
+ ALWAYS_INLINE u32 raise_irq()
+ {
+ return m_in_irq++;
+ }
+
+ ALWAYS_INLINE void restore_irq(u32 prev_irq)
+ {
+ ASSERT(prev_irq <= m_in_irq);
+ m_in_irq = prev_irq;
+ }
+
ALWAYS_INLINE u32& in_irq()
{
return m_in_irq;
}
-
+
ALWAYS_INLINE void enter_critical(u32& prev_flags)
{
m_in_critical++;
prev_flags = cpu_flags();
cli();
}
-
+
ALWAYS_INLINE void leave_critical(u32 prev_flags)
{
ASSERT(m_in_critical > 0);
@@ -754,7 +831,7 @@ public:
else
cli();
}
-
+
ALWAYS_INLINE u32 clear_critical(u32& prev_flags, bool enable_interrupts)
{
u32 prev_crit = m_in_critical;
@@ -766,7 +843,7 @@ public:
sti();
return prev_crit;
}
-
+
ALWAYS_INLINE void restore_critical(u32 prev_crit, u32 prev_flags)
{
ASSERT(m_in_critical == 0);
@@ -784,6 +861,27 @@ public:
return s_clean_fpu_state;
}
+ static void smp_enable();
+ bool smp_process_pending_messages();
+
+ template<typename Callback>
+ static void smp_broadcast(Callback callback, bool async)
+ {
+ auto* data = new Callback(move(callback));
+ smp_broadcast(
+ [](void* data) {
+ (*reinterpret_cast<Callback*>(data))();
+ },
+ data,
+ [](void* data) {
+ delete reinterpret_cast<Callback*>(data);
+ },
+ async);
+ }
+ static void smp_broadcast(void (*callback)(), bool async);
+ static void smp_broadcast(void (*callback)(void*), void* data, void (*free_data)(void*), bool async);
+ static void smp_broadcast_flush_tlb(VirtualAddress vaddr, size_t page_count);
+
ALWAYS_INLINE bool has_feature(CPUFeature f) const
{
return (static_cast<u32>(m_features) & static_cast<u32>(f)) != 0;
@@ -793,6 +891,7 @@ public:
void invoke_scheduler_async() { m_invoke_scheduler_async = true; }
void enter_trap(TrapFrame& trap, bool raise_irq);
+
void exit_trap(TrapFrame& trap);
[[noreturn]] void initialize_context_switching(Thread& initial_thread);
diff --git a/Kernel/Arch/i386/ISRStubs.h b/Kernel/Arch/i386/ISRStubs.h
index af5e6cf521..86db4644a1 100644
--- a/Kernel/Arch/i386/ISRStubs.h
+++ b/Kernel/Arch/i386/ISRStubs.h
@@ -28,260 +28,179 @@
#include <Kernel/Arch/i386/Interrupts.h>
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(0, 0x50)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(1, 0x51)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(2, 0x52)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(3, 0x53)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(4, 0x54)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(5, 0x55)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(6, 0x56)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(7, 0x57)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(8, 0x58)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(9, 0x59)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(10, 0x5a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(11, 0x5b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(12, 0x5c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(13, 0x5d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(14, 0x5e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(15, 0x5f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(16, 0x60)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(17, 0x61)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(18, 0x62)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(19, 0x63)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(20, 0x64)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(21, 0x65)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(22, 0x66)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(23, 0x67)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(24, 0x68)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(25, 0x69)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(26, 0x6a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(27, 0x6b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(28, 0x6c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(29, 0x6d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(30, 0x6e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(31, 0x6f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(32, 0x70)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(33, 0x71)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(34, 0x72)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(35, 0x73)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(36, 0x74)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(37, 0x75)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(38, 0x76)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(39, 0x77)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(40, 0x78)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(41, 0x79)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(42, 0x7a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(43, 0x7b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(44, 0x7c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(45, 0x7d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(46, 0x7e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(47, 0x7f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(48, 0x80)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(49, 0x81)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(50, 0x82)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(51, 0x83)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(52, 0x84)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(53, 0x85)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(54, 0x86)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(55, 0x87)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(56, 0x88)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(57, 0x89)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(58, 0x8a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(59, 0x8b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(60, 0x8c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(61, 0x8d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(62, 0x8e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(63, 0x8f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(64, 0x90)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(65, 0x91)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(66, 0x92)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(67, 0x93)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(68, 0x94)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(69, 0x95)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(70, 0x96)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(71, 0x97)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(72, 0x98)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(73, 0x99)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(74, 0x9a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(75, 0x9b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(76, 0x9c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(77, 0x9d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(78, 0x9e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(79, 0x9f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(80, 0xa0)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(81, 0xa1)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(82, 0xa2)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(83, 0xa3)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(84, 0xa4)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(85, 0xa5)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(86, 0xa6)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(87, 0xa7)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(88, 0xa8)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(89, 0xa9)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(90, 0xaa)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(91, 0xab)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(92, 0xac)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(93, 0xad)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(94, 0xae)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(95, 0xaf)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(96, 0xb0)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(97, 0xb1)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(98, 0xb2)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(99, 0xb3)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(100, 0xb4)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(101, 0xb5)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(102, 0xb6)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(103, 0xb7)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(104, 0xb8)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(105, 0xb9)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(106, 0xba)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(107, 0xbb)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(108, 0xbc)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(109, 0xbd)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(110, 0xbe)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(111, 0xbf)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(112, 0xc0)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(113, 0xc1)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(114, 0xc2)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(115, 0xc3)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(116, 0xc4)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(117, 0xc5)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(118, 0xc6)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(119, 0xc7)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(120, 0xc8)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(121, 0xc9)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(122, 0xca)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(123, 0xcb)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(124, 0xcc)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(125, 0xcd)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(126, 0xce)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(127, 0xcf)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(128, 0xd0)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(129, 0xd1)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(130, 0xd2)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(131, 0xd3)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(132, 0xd4)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(133, 0xd5)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(134, 0xd6)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(135, 0xd7)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(136, 0xd8)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(137, 0xd9)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(138, 0xda)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(139, 0xdb)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(140, 0xdc)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(141, 0xdd)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(142, 0xde)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(143, 0xdf)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(144, 0xe0)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(145, 0xe1)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(146, 0xe2)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(147, 0xe3)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(148, 0xe4)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(149, 0xe5)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(150, 0xe6)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(151, 0xe7)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(152, 0xe8)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(153, 0xe9)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(154, 0xea)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(155, 0xeb)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(156, 0xec)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(157, 0xed)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(158, 0xee)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(159, 0xef)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(160, 0xf0)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(161, 0xf1)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(162, 0xf2)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(163, 0xf3)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(164, 0xf4)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(165, 0xf5)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(166, 0xf6)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(167, 0xf7)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(168, 0xf8)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(169, 0xf9)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(170, 0xfa)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(171, 0xfb)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(172, 0xfc)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(173, 0xfd)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(174, 0xfe)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(175, 0xff)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(176, 0x100)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(177, 0x101)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(178, 0x102)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(179, 0x103)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(180, 0x104)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(181, 0x105)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(182, 0x106)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(183, 0x107)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(184, 0x108)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(185, 0x109)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(186, 0x10a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(187, 0x10b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(188, 0x10c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(189, 0x10d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(190, 0x10e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(191, 0x10f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(192, 0x110)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(193, 0x111)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(194, 0x112)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(195, 0x113)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(196, 0x114)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(197, 0x115)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(198, 0x116)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(199, 0x117)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(200, 0x118)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(201, 0x119)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(202, 0x11a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(203, 0x11b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(204, 0x11c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(205, 0x11d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(206, 0x11e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(207, 0x11f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(208, 0x120)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(209, 0x121)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(210, 0x122)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(211, 0x123)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(212, 0x124)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(213, 0x125)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(214, 0x126)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(215, 0x127)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(216, 0x128)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(217, 0x129)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(218, 0x12a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(219, 0x12b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(220, 0x12c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(221, 0x12d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(222, 0x12e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(223, 0x12f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(224, 0x130)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(225, 0x131)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(226, 0x132)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(227, 0x133)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(228, 0x134)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(229, 0x135)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(230, 0x136)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(231, 0x137)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(232, 0x138)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(233, 0x139)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(234, 0x13a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(235, 0x13b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(236, 0x13c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(237, 0x13d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(238, 0x13e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(239, 0x13f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(240, 0x140)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(241, 0x141)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(242, 0x142)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(243, 0x143)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(244, 0x144)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(245, 0x145)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(246, 0x146)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(247, 0x147)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(248, 0x148)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(249, 0x149)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(250, 0x14a)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(251, 0x14b)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(252, 0x14c)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(253, 0x14d)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(254, 0x14e)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(255, 0x14f)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(256, 0x150)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(80)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(81)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(82)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(83)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(84)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(85)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(86)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(87)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(88)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(89)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(90)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(91)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(92)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(93)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(94)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(95)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(96)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(97)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(98)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(99)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(100)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(101)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(102)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(103)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(104)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(105)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(106)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(107)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(108)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(109)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(110)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(111)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(112)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(113)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(114)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(115)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(116)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(117)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(118)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(119)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(120)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(121)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(122)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(123)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(124)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(125)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(126)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(127)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(128)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(129)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(130)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(131)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(132)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(133)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(134)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(135)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(136)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(137)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(138)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(139)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(140)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(141)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(142)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(143)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(144)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(145)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(146)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(147)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(148)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(149)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(150)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(151)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(152)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(153)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(154)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(155)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(156)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(157)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(158)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(159)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(160)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(161)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(162)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(163)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(164)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(165)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(166)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(167)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(168)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(169)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(170)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(171)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(172)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(173)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(174)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(175)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(176)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(177)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(178)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(179)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(180)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(181)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(182)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(183)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(184)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(185)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(186)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(187)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(188)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(189)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(190)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(191)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(192)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(193)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(194)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(195)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(196)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(197)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(198)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(199)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(200)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(201)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(202)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(203)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(204)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(205)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(206)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(207)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(208)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(209)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(210)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(211)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(212)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(213)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(214)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(215)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(216)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(217)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(218)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(219)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(220)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(221)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(222)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(223)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(224)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(225)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(226)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(227)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(228)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(229)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(230)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(231)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(232)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(233)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(234)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(235)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(236)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(237)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(238)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(239)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(240)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(241)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(242)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(243)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(244)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(245)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(246)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(247)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(248)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(249)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(250)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(251)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(252)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(253)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(254)
+GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(255)
diff --git a/Kernel/Arch/i386/Interrupts.h b/Kernel/Arch/i386/Interrupts.h
index c209f95d8f..320e26281e 100644
--- a/Kernel/Arch/i386/Interrupts.h
+++ b/Kernel/Arch/i386/Interrupts.h
@@ -32,12 +32,12 @@
extern "C" void interrupt_common_asm_entry();
-#define GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(interrupt_vector, isr_number) \
- extern "C" void interrupt_##interrupt_vector##_asm_entry(); \
- asm(".globl interrupt_" #interrupt_vector "_asm_entry\n" \
- "interrupt_" #interrupt_vector "_asm_entry:\n" \
- " pushw $" #isr_number "\n" \
- " pushw $0\n" \
+#define GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(isr_number) \
+ extern "C" void interrupt_##isr_number##_asm_entry(); \
+ asm(".globl interrupt_" #isr_number "_asm_entry\n" \
+ "interrupt_" #isr_number "_asm_entry:\n" \
+ " pushw $" #isr_number "\n" \
+ " pushw $0\n" \
" jmp interrupt_common_asm_entry\n");
asm(
diff --git a/Kernel/Arch/i386/ProcessorInfo.h b/Kernel/Arch/i386/ProcessorInfo.h
index 2ea9a19dbe..c74d74e607 100644
--- a/Kernel/Arch/i386/ProcessorInfo.h
+++ b/Kernel/Arch/i386/ProcessorInfo.h
@@ -42,6 +42,7 @@ class ProcessorInfo
u32 m_display_family;
u32 m_stepping;
u32 m_type;
+ u32 m_apic_id;
public:
ProcessorInfo(Processor& processor);
@@ -53,6 +54,9 @@ public:
u32 display_family() const { return m_display_family; }
u32 stepping() const { return m_stepping; }
u32 type() const { return m_type; }
+ u32 apic_id() const { return m_apic_id; }
+
+ void set_apic_id(u32 apic_id) { m_apic_id = apic_id; }
};
}