forked from lolo859/vystem
Vystem 0.2
This commit is contained in:
126
shelter/lib/include/irq/gdt.h
Normal file
126
shelter/lib/include/irq/gdt.h
Normal file
@@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_GDT_H
|
||||
#define SH_LIB_GDT_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
#include "irq/tss.h"
|
||||
// Long mode GDT part
|
||||
// GDT entry 64 bits structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 limit_low;
|
||||
sh_uint16 base_low;
|
||||
sh_uint8 base_mid;
|
||||
sh_uint8 access;
|
||||
sh_uint8 flags_limit_high;
|
||||
sh_uint8 base_high;
|
||||
} sh_gdt_GDT_ENTRY_64;
|
||||
#pragma pack()
|
||||
// GDT entry 128 bits (special TSS) structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 limit_low;
|
||||
sh_uint16 base_low;
|
||||
sh_uint8 base_mid;
|
||||
sh_uint8 access;
|
||||
sh_uint8 flags_limit_high;
|
||||
sh_uint8 base_high;
|
||||
sh_uint32 base_upper;
|
||||
sh_uint32 reserved;
|
||||
} sh_gdt_GDT_ENTRY_128;
|
||||
#pragma pack()
|
||||
// GDTR structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 limit;
|
||||
sh_uint64 base;
|
||||
} sh_gdt_GDTR;
|
||||
#pragma pack()
|
||||
// GDT structure for bootstrap core
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_gdt_GDT_ENTRY_64 null;
|
||||
sh_gdt_GDT_ENTRY_64 kernel_code;
|
||||
sh_gdt_GDT_ENTRY_64 kernel_data;
|
||||
sh_gdt_GDT_ENTRY_64 user_code;
|
||||
sh_gdt_GDT_ENTRY_64 user_data;
|
||||
sh_gdt_GDT_ENTRY_128 tss;
|
||||
} sh_gdt_GDT;
|
||||
#pragma pack()
|
||||
// GDT structure for all APs
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_gdt_GDT_ENTRY_64 null;
|
||||
sh_gdt_GDT_ENTRY_64 kernel_code;
|
||||
sh_gdt_GDT_ENTRY_64 kernel_data;
|
||||
sh_gdt_GDT_ENTRY_64 user_code;
|
||||
sh_gdt_GDT_ENTRY_64 user_data;
|
||||
sh_gdt_GDT_ENTRY_128 tss[256];
|
||||
} sh_gdt_GDT_AP;
|
||||
#pragma pack()
|
||||
// Generate access byte
|
||||
inline sh_uint8 sh_gdt_fill_access_byte(sh_bool present,sh_uint8 dpl,sh_bool descriptor_type,sh_uint8 segment_type) {
|
||||
return ((present?1:0)<<7)|((dpl&0x3)<<5)|((descriptor_type?1:0)<<4)|(segment_type&0xF);
|
||||
}
|
||||
// Generate flags byte (put all 4 bits in bit 0-3 of the returned byte)
|
||||
inline sh_uint8 sh_gdt_fill_flags_byte(sh_bool g,sh_bool db,sh_bool l,sh_bool avl) {
|
||||
return ((g?1:0)<<3)|((db?1:0)<<2)|((l?1:0)<<1)|((avl?1:0)<<0);
|
||||
}
|
||||
// Fill GDT entry 64 bits, expect flags as sh_gdt_fill_flags_byte would return it
|
||||
sh_gdt_GDT_ENTRY_64 sh_gdt_fill_gdt_entry_64(sh_uint32 limit,sh_uint32 base,sh_uint8 access,sh_uint8 flags);
|
||||
// Fill GDT entry 128 bits, expect flags as sh_gdt_fill_flags_byte would return it
|
||||
sh_gdt_GDT_ENTRY_128 sh_gdt_fill_gdt_entry_128(sh_uint32 limit,sh_uint64 base,sh_uint8 access,sh_uint8 flags);
|
||||
// Fill GDT with provided TSS
|
||||
SH_STATUS sh_gdt_fill_gdt(sh_tss_TSS *tss,sh_gdt_GDT *gdt);
|
||||
// Fill APs common GDT with provided TSS array
|
||||
SH_STATUS sh_gdt_fill_gdt_ap(sh_tss_TSS *tss,sh_uint64 tss_count,sh_gdt_GDT_AP *gdt);
|
||||
// Generate GDTR for AP GDT
|
||||
sh_gdt_GDTR sh_gdt_make_gdtr_ap(sh_gdt_GDT_AP *gdt);
|
||||
// Fill and load GDTR
|
||||
SH_STATUS sh_gdt_load_gdtr(sh_gdt_GDT *gdt);
|
||||
// Reload registers
|
||||
SH_STATUS sh_gdt_reload_registers();
|
||||
// 16/32 bits mode GDT part
|
||||
// GDT entry 32 bits structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 limit_low;
|
||||
sh_uint16 base_low;
|
||||
sh_uint8 base_middle;
|
||||
sh_uint8 access;
|
||||
sh_uint8 granularity;
|
||||
sh_uint8 base_high;
|
||||
} sh_gdt_GDT_ENTRY_32;
|
||||
#pragma pack()
|
||||
// GDT 32 bits structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_gdt_GDT_ENTRY_32 null;
|
||||
sh_gdt_GDT_ENTRY_32 code_64;
|
||||
sh_gdt_GDT_ENTRY_32 code;
|
||||
sh_gdt_GDT_ENTRY_32 data;
|
||||
} sh_gdt_GDT_32;
|
||||
#pragma pack()
|
||||
// Generate access byte
|
||||
inline sh_uint8 sh_gdt_fill_access_byte_32(sh_bool present,sh_uint8 dpl,sh_bool descriptor_type,sh_uint8 segment_type) {
|
||||
sh_uint8 access=0;
|
||||
access|=(present?1:0)<<7;
|
||||
access|=(dpl&0x3)<<5;
|
||||
access|=(descriptor_type?1:0)<<4;
|
||||
access|=(segment_type&0xF);
|
||||
return access;
|
||||
}
|
||||
// Generate granularity byte
|
||||
inline sh_uint8 sh_gdt_fill_granularity_byte_32(sh_bool granularity,sh_bool db,sh_bool l,sh_bool avl) {
|
||||
sh_uint8 g=0;
|
||||
g|=(granularity?1:0)<<7;
|
||||
g|=(db?1:0)<<6;
|
||||
g|=(l?1:0)<<5;
|
||||
g|=(avl?1:0)<<4;
|
||||
return g;
|
||||
}
|
||||
// Fill GDT entry 32 bits, expect granularity as sh_gdt_fill_granularity_byte_32 would return it
|
||||
sh_gdt_GDT_ENTRY_32 sh_gdt_fill_gdt_entry_32(sh_uint32 limit,sh_uint32 base,sh_uint8 access,sh_uint8 granularity);
|
||||
// Fill GDT 32 bits
|
||||
SH_STATUS sh_gdt_fill_gdt_32(sh_gdt_GDT_32 *gdt_32);
|
||||
#endif
|
||||
62
shelter/lib/include/irq/gsi.h
Normal file
62
shelter/lib/include/irq/gsi.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_GSI_H
|
||||
#define SH_LIB_GSI_H
|
||||
#include "std/stdlib.h"
|
||||
#include "devs/apic/ioapic.h"
|
||||
// GSI polarity enum
|
||||
enum sh_gsi_POLARITY {
|
||||
SH_GSI_POLARITY_NOT_SET=0,
|
||||
SH_GSI_POLARITY_BUS_DEFAULT,
|
||||
SH_GSI_POLARITY_ACTIVE_HIGH,
|
||||
SH_GSI_POLARITY_ACTIVE_LOW
|
||||
};
|
||||
// GSI trigger mode enum
|
||||
enum sh_gsi_TRIGGER_MODE {
|
||||
SH_GSI_TRIGGER_MODE_NOT_SET=0,
|
||||
SH_GSI_TRIGGER_MODE_BUS_DEFAULT,
|
||||
SH_GSI_TRIGGER_MODE_EDGE,
|
||||
SH_GSI_TRIGGER_MODE_LEVEL
|
||||
};
|
||||
// Interrupt source override (ISO) structure
|
||||
typedef struct {
|
||||
sh_uint32 gsi;
|
||||
// must default to SH_FALSE
|
||||
sh_bool valid;
|
||||
// when ISOs array is initialized, this field must default to 0
|
||||
sh_uint8 source_irq;
|
||||
// these two fields are determined by the flags field in the MADT entry. Bus-default value are resolved when writing IOREDTBL
|
||||
enum sh_gsi_POLARITY polarity;
|
||||
enum sh_gsi_TRIGGER_MODE trigger_mode;
|
||||
// when ISOs array is initialized, this field must default to 0
|
||||
sh_uint8 bus;
|
||||
} sh_gsi_ISO;
|
||||
// Initialize a 256 elements array of sh_gsi_ISO structs
|
||||
SH_STATUS sh_gsi_iso_array_init();
|
||||
// Register an ISO, this function is supposed to be used during MADT parsing when encountering an ISO. It expect the field as they are provided into the MADT entry
|
||||
SH_STATUS sh_gsi_iso_register(sh_uint8 bus,sh_uint8 source,sh_uint32 gsi,sh_uint16 flags);
|
||||
// Return an ISO structure for the given interrupt
|
||||
sh_gsi_ISO *sh_gsi_get_iso_by_irq(sh_uint8 irq);
|
||||
// Return an ISO structure for the given GSI
|
||||
sh_gsi_ISO *sh_gsi_get_iso_by_gsi(sh_uint32 gsi);
|
||||
// These two functions provide a thread-safe and "interrupt-storm" safe way to get and set IOREDTBL entries
|
||||
// Read the IOREDTBL entry associated with the provided GSI
|
||||
SH_STATUS sh_gsi_get(sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry);
|
||||
// Set the provided GSI to the corresponding IOREDTBL entry, mask the IOOREDTBL entry and doesn't unmask it
|
||||
SH_STATUS sh_gsi_set(sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry);
|
||||
// Set the provided IRQ to IOREDTBL entry, calculate the expected GSI using sh_gsi_get_iso_by_irq
|
||||
SH_STATUS sh_gsi_irq_set(sh_uint8 irq,sh_ioapic_IOREDTBL_ENTRY *entry);
|
||||
// Mask the IOREDTBL entry corresponding to the provided GSI
|
||||
inline SH_STATUS sh_gsi_mask(sh_uint32 gsi) {
|
||||
return sh_ioapic_mask_gsi(sh_ioapic_get_dev_by_gsi(gsi),gsi);
|
||||
}
|
||||
// Unmask the IOREDTBL entry corresponding to the provided GSI
|
||||
inline SH_STATUS sh_gsi_unmask(sh_uint32 gsi) {
|
||||
return sh_ioapic_unmask_gsi(sh_ioapic_get_dev_by_gsi(gsi),gsi);
|
||||
}
|
||||
// Mask the IOREDTBL entry corresponding to the provided IRQ
|
||||
SH_STATUS sh_gsi_irq_mask(sh_uint8 irq);
|
||||
// Unmask the IOREDTBL entry corresponding to the provided IRQ
|
||||
SH_STATUS sh_gsi_irq_unmask(sh_uint8 irq);
|
||||
// Load all legacy IRQ to IOREDTBL entries, intented to be called only one time
|
||||
SH_STATUS sh_gsi_irq_switch();
|
||||
#endif
|
||||
41
shelter/lib/include/irq/idt.h
Normal file
41
shelter/lib/include/irq/idt.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_IDT_H
|
||||
#define SH_LIB_IDT_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
// IDT entry structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 offset_low;
|
||||
sh_uint16 selector;
|
||||
sh_uint8 ist;
|
||||
sh_uint8 type_attr;
|
||||
sh_uint16 offset_mid;
|
||||
sh_uint32 offset_high;
|
||||
sh_uint32 reserved;
|
||||
} sh_idt_IDT_ENTRY;
|
||||
#pragma pack()
|
||||
// IDTR structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 limit;
|
||||
sh_uint64 base;
|
||||
} sh_idt_IDTR;
|
||||
#pragma pack()
|
||||
// Full IDT structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_idt_IDT_ENTRY entries[256];
|
||||
} sh_idt_IDT;
|
||||
#pragma pack()
|
||||
// Generate type_attr byte
|
||||
inline sh_uint8 sh_idt_fill_type_attr_byte(sh_bool present,sh_uint8 dpl,sh_uint8 type) {
|
||||
return ((present?1:0)<<7)|((dpl&0x3)<<5)|(type&0x1F);
|
||||
}
|
||||
// Fill an IDT entry, expect type_attr as sh_idt_fill_type_attr_byte would return it
|
||||
sh_idt_IDT_ENTRY sh_idt_fill_idt_entry(sh_uint64 offset,sh_uint16 selector,sh_uint8 ist,sh_uint8 type_attr);
|
||||
// Fill the IDT
|
||||
SH_STATUS sh_idt_fill_idt(sh_idt_IDT *idt);
|
||||
// Fill and load IDTR
|
||||
SH_STATUS sh_idt_load_idtr(sh_idt_IDT *idt);
|
||||
#endif
|
||||
57
shelter/lib/include/irq/irq.h
Normal file
57
shelter/lib/include/irq/irq.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_IRQ_H
|
||||
#define SH_LIB_IRQ_H
|
||||
#include "std/stdlib.h"
|
||||
// Interrupt frame structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint64 r11,r10,r9,r8,rdx,rcx,rax;
|
||||
sh_uint64 vector;
|
||||
sh_uint64 error_code;
|
||||
sh_uint64 rip;
|
||||
sh_uint64 cs;
|
||||
sh_uint64 rflags;
|
||||
} sh_irq_INTERRUPT_FRAME;
|
||||
#pragma pack()
|
||||
#define SH_IRQ_DIV_BY_ZERO_FAULT_STRING "Division by Zero #DE"
|
||||
#define SH_IRQ_DEBUG_STRING "Debug #DB\nWarning: Usage of debugger in Shelter isn't supported and any #DB fault will result in a dead kernel."
|
||||
#define SH_IRQ_PAGE_FAULT_STRING "Page fault #PF"
|
||||
#define SH_IRQ_NMI_FAULT_STRING "Non maskable interrupt"
|
||||
#define SH_IRQ_BREAKPOINT_STRING "Breakpoint #BP\nWarning: Usage of debugger in Shelter isn't supported but usage of #BP fault will not block the kernel."
|
||||
#define SH_IRQ_OVERFLOW_STRING "Overflow #OF"
|
||||
#define SH_IRQ_BOUND_RANGE_STRING "Bound range Exceedeed #BR"
|
||||
#define SH_IRQ_INVALID_OPCODE_STRING "Invalid Opcode #UD"
|
||||
#define SH_IRQ_DEVICE_NOT_AVAILABLE_STRING "Device Not Available #NM"
|
||||
#define SH_IRQ_DOUBLE_FAULT_STRING "Double Fault #DF"
|
||||
#define SH_IRQ_COPROCESSOR_SEGMENT_OVRERRUN_STRING "Coprocessor segment overrun"
|
||||
#define SH_IRQ_INVALID_TSS_STRING "Invalid TSS #TS"
|
||||
#define SH_IRQ_SEGMENT_NOT_PRESENT_STRING "Segment Not Present #NP"
|
||||
#define SH_IRQ_STACK_SEGMENT_FAULT_STRING "Stack Segment Fault #SS"
|
||||
#define SH_IRQ_GENERAL_PROTECTION_FAULT_STRING "General Protection Fault #GP"
|
||||
#define SH_IRQ_X87_FLOATING_POINT_EXCEPTION_STRING "x87 Floating Point Exception #MF"
|
||||
#define SH_IRQ_ALIGNMENT_CHECK_STRING "Alignment Check #AC"
|
||||
#define SH_IRQ_MACHINE_CHECK_STRING "Machine Check #MC"
|
||||
#define SH_IRQ_SIMD_FLOATING_POINT_EXCEPTION_STRING "SIMD Floating Point Exception #XM"
|
||||
#define SH_IRQ_VIRTUALIZATION_EXCEPTION_STRING "Virtualization Exception #VE"
|
||||
#define SH_IRQ_CONTROL_PROTECTION_EXCEPTION_STRING "Control Protection Exception #CP"
|
||||
#define SH_IRQ_HYPERVISOR_INJECTION_EXCEPTION_STRING "Hypervisor Injection Exception #HV\nWarning: Shelter will never communicate with an hypervisor."
|
||||
#define SH_IRQ_VMM_COMMUNICATION_EXCEPTION_STRING "VMM Communication Exception #VC\nWarning: Shelter will never communicate with an hypervisor."
|
||||
#define SH_IRQ_SECURITY_EXCEPTION_STRING "Security Exception #SX\nWarning: Shelter will never communicate with an hypervisor."
|
||||
typedef void (*sh_irq_HANDLER_PTR)();
|
||||
// Start TSC calibration
|
||||
void sh_irq_start_tsc();
|
||||
// Return TSC delta mesured between two PIC interrupts
|
||||
sh_uint64 sh_irq_get_tsc_delta();
|
||||
// Set timer state of this CPU to SH_TRUE
|
||||
void sh_irq_start_timer();
|
||||
// Get timer state of this CPU
|
||||
sh_bool sh_irq_get_timer_state();
|
||||
// Set the irq_managed_by_ioapic to SH_TRUE
|
||||
SH_STATUS sh_irq_switch_irq_management();
|
||||
// Register a legacy IRQ handler, unmask the corresponding GSI
|
||||
SH_STATUS sh_irq_legacy_register_handler(sh_uint8 legacy_irq,sh_irq_HANDLER_PTR handler);
|
||||
// Present interrupt frame if it's a fault
|
||||
void sh_irq_present_frame(sh_irq_INTERRUPT_FRAME *frame);
|
||||
// Dispatch interrupts
|
||||
void sh_irq_dispatch(sh_irq_INTERRUPT_FRAME *frame);
|
||||
#endif
|
||||
39
shelter/lib/include/irq/tss.h
Normal file
39
shelter/lib/include/irq/tss.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_TSS_H
|
||||
#define SH_LIB_TSS_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
#include "std/malloc.h"
|
||||
#include "std/mem.h"
|
||||
// TSS structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint32 reserved0;
|
||||
sh_uint64 rsp0;
|
||||
sh_uint64 rsp1;
|
||||
sh_uint64 rsp2;
|
||||
sh_uint64 reserved1;
|
||||
sh_uint64 ist1;
|
||||
sh_uint64 ist2;
|
||||
sh_uint64 ist3;
|
||||
sh_uint64 ist4;
|
||||
sh_uint64 ist5;
|
||||
sh_uint64 ist6;
|
||||
sh_uint64 ist7;
|
||||
sh_uint64 reserved2;
|
||||
sh_uint16 reserved3;
|
||||
sh_uint16 iomap_base;
|
||||
} sh_tss_TSS;
|
||||
#pragma pack()
|
||||
// TR structure
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint16 limit;
|
||||
sh_uint64 base;
|
||||
} sh_tss_TR;
|
||||
#pragma pack()
|
||||
// Fill TSS structure for any CPU core and allocate stacks
|
||||
SH_STATUS sh_tss_fill_tss(sh_tss_TSS *tss);
|
||||
// Fill and load TR
|
||||
SH_STATUS sh_tss_load_tr(sh_tss_TSS *tss);
|
||||
#endif
|
||||
Reference in New Issue
Block a user