Vystem 0.2

This commit is contained in:
2026-05-27 19:34:54 +02:00
parent a43c08b893
commit d238606b75
372 changed files with 51320 additions and 83217 deletions

View 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

View 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

View 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

View 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

View 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