1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/x86/descriptors/descriptors.h"
4
5#include <mos/platform/platform.h>
6#include <mos/x86/x86_interrupt.h>
7#include <mos/x86/x86_platform.h>
8
9static idt_entry_t idt[IDT_ENTRY_COUNT] __aligned(16) = { 0 };
10static idtr_t idtr;
11
12#define IDT_FLAG_P (1 << 7)
13
14#define STS_IG32 0xE // 32-bit Interrupt Gate
15#define STS_TG32 0xF // 32-bit Trap Gate
16
17__attribute__((sysv_abi)) void idt_flush(idtr_t *idtr);
18
19static void idt_set_descriptor(u8 vector, void *isr, bool usermode, bool is_trap)
20{
21 idt_entry_t *descriptor = &idt[vector];
22
23 descriptor->isr_veryhigh = (uintn) isr >> 32;
24 descriptor->reserved2 = 0;
25
26 descriptor->isr_low = (uintn) isr & 0xFFFF;
27 descriptor->isr_high = (uintn) isr >> 16;
28 descriptor->segment = GDT_SEGMENT_KCODE;
29 descriptor->present = true;
30 descriptor->dpl = usermode ? 3 : 0;
31 descriptor->type = is_trap ? STS_TG32 : STS_IG32;
32 descriptor->zero = 0;
33 descriptor->reserved = 0;
34}
35
36void x86_init_percpu_idt()
37{
38 idt_flush(idtr: &idtr);
39}
40
41void x86_idt_init()
42{
43 for (u8 isr = 0; isr < ISR_MAX_COUNT; isr++)
44 idt_set_descriptor(vector: isr, isr: isr_stub_table[isr], usermode: false, is_trap: false);
45
46 for (u8 irq_n = 0; irq_n < IRQ_MAX_COUNT; irq_n++)
47 idt_set_descriptor(vector: irq_n + IRQ_BASE, isr: irq_stub_table[irq_n], usermode: false, is_trap: false);
48
49 // system calls
50 idt_set_descriptor(MOS_SYSCALL_INTR, isr: isr_stub_table[MOS_SYSCALL_INTR], usermode: true, is_trap: true);
51
52 for (u8 ipi_n = 0; ipi_n < IPI_TYPE_MAX; ipi_n++)
53 idt_set_descriptor(vector: ipi_n + IPI_BASE, isr: isr_stub_table[ipi_n + IPI_BASE], usermode: false, is_trap: false);
54
55 idtr.base = &idt[0];
56 idtr.limit = (u16) sizeof(idt_entry_t) * IDT_ENTRY_COUNT - 1;
57}
58