Vystem 0.2
This commit is contained in:
56
shelter/lib/include/cpu/ap.h
Normal file
56
shelter/lib/include/cpu/ap.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_AP_H
|
||||
#define SH_LIB_AP_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
#include "memory/memory.h"
|
||||
#include "irq/gdt.h"
|
||||
#include "irq/idt.h"
|
||||
#include "devs/apic/lapic.h"
|
||||
#define SH_AP_AP_TRAMPOLINE 0x7000
|
||||
#define SH_AP_GDT_32_PA 0x8000
|
||||
#define SH_AP_BOOTSTRAP_PA 0x9000
|
||||
#define SH_AP_TRAMPOLINE_PAYLOAD 0xA000
|
||||
#define SH_AP_STATE_PENDING 0x00
|
||||
#define SH_AP_STATE_NO_LAPIC 0x01
|
||||
#define SH_AP_STATE_OK 0x02
|
||||
// Fill the 32 bits GDT used by AP trampoline
|
||||
SH_STATUS sh_ap_load_gdt_32();
|
||||
// AP boostrap structure, shared with each AP
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_page_PHYSICAL_ADDRESS lapic_base_pa;
|
||||
sh_page_VIRTUAL_ADDRESS c_entry_point_va;
|
||||
sh_page_PHYSICAL_ADDRESS page_table_pa;
|
||||
sh_page_VIRTUAL_ADDRESS cpu_struct_base_area;
|
||||
sh_page_VIRTUAL_ADDRESS shared_gdt_64_va;
|
||||
sh_gdt_GDTR gdt_64_gdtr;
|
||||
sh_idt_IDT *idt;
|
||||
} sh_ap_AP_BOOTSTRAP;
|
||||
#pragma pack()
|
||||
// Per-CPU structure, one for each AP
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_uint64 cpu_id;
|
||||
sh_uint32 bytes_outputed;
|
||||
sh_bool timer_state;
|
||||
char *temp_buffer;
|
||||
sh_uint64 temp_buffer_size;
|
||||
} sh_ap_PER_CPU;
|
||||
#pragma pack()
|
||||
// CPU structure, one for each AP
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
sh_page_VIRTUAL_ADDRESS c_entry_point_stack_top_va;
|
||||
sh_uint32 lapic_id; // just for the tranpoline to confirm it has found his own struct
|
||||
sh_uint16 tss_selector;
|
||||
sh_ap_PER_CPU *per_cpu;
|
||||
} sh_ap_CPU_STRUCT;
|
||||
#pragma pack()
|
||||
// Allocate each sets of stacks for each TSS and each C stack, create each TSS entry, create global GDT64, create the CPU structure area, create and fill each CPU structure, create the AP bootstrap structure and place it correctly
|
||||
SH_STATUS sh_ap_prepare_for_smp_launch(sh_lapic_DEVICE **lapic_dev_array,sh_uint64 max_lapic_id,sh_uint64 expected_lapic_found,sh_conf_BOOT_CONFIG *boot_config,sh_idt_IDT *idt);
|
||||
// AP C entry point
|
||||
void sh_ap_entry_point();
|
||||
// Start AP boot procedure
|
||||
SH_STATUS sh_ap_start_ap_boot_procedure(sh_conf_BOOT_CONFIG *boot_config);
|
||||
#endif
|
||||
@@ -3,14 +3,17 @@
|
||||
#define SH_LIB_ASM_H
|
||||
#include "std/type.h"
|
||||
#include "std/status.h"
|
||||
#include "irq/gdt.h"
|
||||
#include "irq/tss.h"
|
||||
#include "irq/idt.h"
|
||||
// inb instruction wrapper
|
||||
static inline sh_uint8 sh_asm_inb(sh_uint16 port) {
|
||||
inline sh_uint8 sh_asm_inb(sh_uint16 port) {
|
||||
sh_uint8 val;
|
||||
__asm__ volatile ("inb %1, %0":"=a"(val):"Nd"(port));
|
||||
return val;
|
||||
}
|
||||
// outb instruction wrapper
|
||||
static inline void sh_asm_outb(sh_uint16 port,sh_uint8 val) {
|
||||
inline void sh_asm_outb(sh_uint16 port,sh_uint8 val) {
|
||||
__asm__ volatile ("outb %0, %1"::"a"(val),"Nd"(port));
|
||||
}
|
||||
// rdtsc instruction wrapper
|
||||
@@ -23,4 +26,44 @@ static inline sh_uint64 sh_asm_rdtsc() {
|
||||
static inline void sh_asm_invlpg(void *addr) {
|
||||
__asm__ volatile ("invlpg (%0)"::"r"(addr):"memory");
|
||||
}
|
||||
// lgdt instruction wrapper
|
||||
static inline void sh_asm_lgdt(sh_gdt_GDTR gdtr) {
|
||||
__asm__ volatile ("lgdt %0"::"m"(gdtr):"memory");
|
||||
}
|
||||
// ltr instruction wrapper
|
||||
static inline void sh_asm_ltr(sh_uint16 tss_selector) {
|
||||
__asm__ volatile ("ltr %0"::"r"(tss_selector):"memory");
|
||||
}
|
||||
// lidt instruction wrapper
|
||||
static inline void sh_asm_lidt(sh_idt_IDTR idtr) {
|
||||
__asm__ volatile ("lidt %0"::"m"(idtr):"memory");
|
||||
}
|
||||
// sidt instruction wrapper
|
||||
static inline void sh_asm_sidt(sh_idt_IDTR* idtr) {
|
||||
__asm__ volatile ("sidt %0":"=m"(*idtr)::"memory");
|
||||
}
|
||||
// sti instruction wrapper
|
||||
static inline void sh_asm_sti() {
|
||||
__asm__ volatile ("sti");
|
||||
}
|
||||
// cli instruction wrapper
|
||||
static inline void sh_asm_cli() {
|
||||
__asm__ volatile ("cli");
|
||||
}
|
||||
// cpuid instruction wrapper
|
||||
static inline void sh_asm_cpuid(sh_uint32 leaf,sh_uint32 subleaf,sh_uint32 *eax,sh_uint32 *ebx,sh_uint32 *ecx,sh_uint32 *edx){
|
||||
__asm__ volatile ("cpuid":"=a"(*eax),"=b"(*ebx),"=c"(*ecx),"=d"(*edx):"a"(leaf),"c"(subleaf));
|
||||
}
|
||||
// mfence instruction wrapper
|
||||
inline void sh_asm_mfence() {
|
||||
__asm__ volatile("mfence":::"memory");
|
||||
}
|
||||
// lfence instruction wrapper
|
||||
inline void sh_asm_lfence() {
|
||||
__asm__ volatile("lfence":::"memory");
|
||||
}
|
||||
// sfence instruction wrapper
|
||||
inline void sh_asm_sfence() {
|
||||
__asm__ volatile("sfence":::"memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
17
shelter/lib/include/cpu/pic.h
Normal file
17
shelter/lib/include/cpu/pic.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_PIC_H
|
||||
#define SH_LIB_PIC_H
|
||||
#include "std/stdlib.h"
|
||||
#define SH_PIC1_CMD 0x20
|
||||
#define SH_PIC1_DATA 0x21
|
||||
#define SH_PIC2_CMD 0xA0
|
||||
#define SH_PIC2_DATA 0xA1
|
||||
// Remap all PIC interrupts on interrupts vectors 32 to 47, leave only IRQ0 enabled
|
||||
void sh_pic_remap();
|
||||
// Unmask a PIC interrupt
|
||||
void sh_pic_unmask(sh_uint8 irq);
|
||||
// Mask a PIC interrupt
|
||||
void sh_pic_mask(sh_uint8 irq);
|
||||
// Send EOI to PIC
|
||||
void sh_pic_send_eoi(sh_uint8 irq);
|
||||
#endif
|
||||
7
shelter/lib/include/cpu/pit.h
Normal file
7
shelter/lib/include/cpu/pit.h
Normal file
@@ -0,0 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_PIT_H
|
||||
#define SH_LIB_PIT_H
|
||||
#include "std/stdlib.h"
|
||||
// Set PIT frequency
|
||||
void sh_pit_set_frequency(sh_uint64 hz);
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "std/type.h"
|
||||
#include "std/status.h"
|
||||
#include "cpu/asm.h"
|
||||
#include "devs/devs.h"
|
||||
typedef sh_uint64 sh_tsc_TSC_VALUE;
|
||||
// Reas TSC register.
|
||||
static inline sh_tsc_TSC_VALUE sh_tsc_read_tsc() {
|
||||
@@ -15,4 +16,16 @@ SH_STATUS sh_tsc_init_tsc();
|
||||
sh_tsc_TSC_VALUE sh_tsc_get_kernel_init_tsc();
|
||||
// Return kernel current tsc.
|
||||
sh_tsc_TSC_VALUE sh_tsc_get_kernel_current_tsc();
|
||||
// Estimate CPU frequency using TSC and PIT
|
||||
sh_uint64 sh_tsc_estimate_cpu_freq();
|
||||
// Load CPU frequency
|
||||
void sh_tsc_load_cpu_freq(sh_uint64 cpu_freq);
|
||||
// Detect if CPUID provide hypervisor bit
|
||||
sh_bool sh_tsc_has_hypervisor();
|
||||
// Detect if CPUID provide TSC constant bit
|
||||
sh_bool sh_tsc_is_tsc_constant();
|
||||
// Return CPUID CPU frequence if available
|
||||
SH_STATUS sh_tsc_get_cpu_freq_cpuid(sh_uint64 *freq);
|
||||
// Parse a TSC DevS query
|
||||
SH_STATUS sh_tsc_devs_query(char *sub_path,sh_devs_RESULT *result);
|
||||
#endif
|
||||
|
||||
65
shelter/lib/include/devs/acpi.h
Normal file
65
shelter/lib/include/devs/acpi.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_ACPI_H
|
||||
#define SH_LIB_ACPI_H
|
||||
#include "std/stdlib.h"
|
||||
// ACPI v1 RSDP structure
|
||||
typedef struct {
|
||||
sh_uint8 signature[8];
|
||||
sh_uint8 checksum;
|
||||
sh_uint8 oem_id[6];
|
||||
sh_uint8 revision;
|
||||
sh_uint32 rsdt_address;
|
||||
} sh_acpi_RSDP_V1;
|
||||
// ACPI v2 RSDP structure
|
||||
typedef struct {
|
||||
sh_acpi_RSDP_V1 first_part;
|
||||
sh_uint32 length;
|
||||
sh_uint64 xsdt_address;
|
||||
sh_uint8 extended_checksum;
|
||||
sh_uint8 reserved[3];
|
||||
} sh_acpi_RSDP_V2;
|
||||
// ACPI pointers root structure
|
||||
typedef struct {
|
||||
sh_uint64 rsdt;
|
||||
sh_uint64 xsdt; // set to 0 if ACPI v2 isn't supported
|
||||
} sh_apci_ACPI_POINTERS_ROOT;
|
||||
// ACPI XSDT header
|
||||
typedef struct {
|
||||
char signature[4];
|
||||
sh_uint32 length;
|
||||
sh_uint8 revision;
|
||||
sh_uint8 checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
sh_uint32 oem_revision;
|
||||
sh_uint32 creator_id;
|
||||
sh_uint32 creator_revision;
|
||||
} sh_acpi_ACPI_XSDT_HEADER;
|
||||
// ACPI XSTD body
|
||||
typedef struct {
|
||||
sh_uint64 *entries;
|
||||
sh_uint64 entry_count;
|
||||
} sh_acpi_ACPI_XSDT_BODY;
|
||||
// ACPI tables list
|
||||
typedef struct {
|
||||
sh_uint64 madt_physical_address;
|
||||
} sh_acpi_ACPI_TABLES;
|
||||
// ACPI table header
|
||||
typedef struct {
|
||||
char signature[4];
|
||||
sh_uint32 length;
|
||||
sh_uint8 revision;
|
||||
sh_uint8 checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
sh_uint32 oem_revision;
|
||||
sh_uint32 creator_id;
|
||||
sh_uint32 creator_revision;
|
||||
} sh_acpi_TABLE_HEADER;
|
||||
// Try to obtain ACPI root pointer
|
||||
SH_STATUS sh_acpi_parse_rsdp(sh_uint64 rsdp,sh_uint8 acpi_ver,sh_apci_ACPI_POINTERS_ROOT *out);
|
||||
// Parse XSDT header and ensure that all entries are mapped
|
||||
SH_STATUS sh_acpi_parse_xsdt(sh_uint64 xsdt,sh_acpi_ACPI_XSDT_BODY *xsdt_body);
|
||||
// Parse XSDT entries, ensure that all the headers of each table is mapped and sort all entries into their respectives fields inside acpi_tables. Doesn't parse each table header
|
||||
SH_STATUS sh_acpi_parse_tables(sh_acpi_ACPI_XSDT_BODY *xsdt_body,sh_acpi_ACPI_TABLES *acpi_tables);
|
||||
#endif
|
||||
53
shelter/lib/include/devs/acpi_tables/madt.h
Normal file
53
shelter/lib/include/devs/acpi_tables/madt.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_ACPI_MADT_H
|
||||
#define SH_LIB_ACPI_MADT_H
|
||||
#include "std/stdlib.h"
|
||||
// MADT header structure
|
||||
typedef struct {
|
||||
char signature[4];
|
||||
sh_uint32 length;
|
||||
sh_uint8 revision;
|
||||
sh_uint8 checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
sh_uint32 oem_revision;
|
||||
sh_uint32 creator_id;
|
||||
sh_uint32 creator_revision;
|
||||
} sh_acpi_madt_TABLE_HEADER;
|
||||
// MADT structure
|
||||
typedef struct {
|
||||
sh_acpi_madt_TABLE_HEADER header;
|
||||
sh_uint32 local_apic_address;
|
||||
sh_uint32 flags;
|
||||
} sh_acpi_madt_MADT;
|
||||
// MADT entry header structure
|
||||
typedef struct {
|
||||
sh_uint8 type;
|
||||
sh_uint8 length;
|
||||
} sh_acpi_madt_ENTRY_HEADER;
|
||||
// Local APIC structure
|
||||
typedef struct {
|
||||
sh_acpi_madt_ENTRY_HEADER header;
|
||||
sh_uint8 acpi_processor_id;
|
||||
sh_uint8 apic_id;
|
||||
sh_uint32 flags;
|
||||
} sh_acpi_madt_LAPIC;
|
||||
// IO APIC structure
|
||||
typedef struct {
|
||||
sh_acpi_madt_ENTRY_HEADER header;
|
||||
sh_uint8 ioapic_id;
|
||||
sh_uint8 reserved;
|
||||
sh_uint32 ioapic_address;
|
||||
sh_uint32 global_system_interrupt_base;
|
||||
} sh_acpi_madt_IOAPIC;
|
||||
// Interrupt source override structure
|
||||
typedef struct {
|
||||
sh_acpi_madt_ENTRY_HEADER header;
|
||||
sh_uint8 bus;
|
||||
sh_uint8 source;
|
||||
sh_uint32 gsi;
|
||||
sh_uint16 flags;
|
||||
} sh_acpi_madt_ISO;
|
||||
// Parse MADT table
|
||||
SH_STATUS sh_acpi_madt_parse(sh_uint64 madt_ptr);
|
||||
#endif
|
||||
70
shelter/lib/include/devs/apic/ioapic.h
Normal file
70
shelter/lib/include/devs/apic/ioapic.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_IOAPIC_H
|
||||
#define SH_LIB_IOAPIC_H
|
||||
#include "std/stdlib.h"
|
||||
#include "memory/page.h"
|
||||
#define SH_IOAPIC_OFFSET_IOREGSEL 0x00
|
||||
#define SH_IOAPIC_OFFSET_IOWIN 0x10
|
||||
#define SH_IOAPIC_REGISTER_IOAPICID 0x00
|
||||
#define SH_IOAPIC_REGISTER_IOAPICVER 0x01
|
||||
#define SH_IOAPIC_REGISTER_IOAPICARB 0x02
|
||||
#define SH_IOAPIC_REGISTER_IOREDTBL_BASE 0x10
|
||||
// IOAPIC device structure
|
||||
typedef struct {
|
||||
volatile sh_uint32 *base;
|
||||
sh_uint8 ioapic_id;
|
||||
sh_uint32 gsi_base;
|
||||
sh_uint32 gsi_count; // must be completed by reading the IOAPICVER register in the sh_ioapic_init call
|
||||
sh_SPIN_LOCK lock;
|
||||
} sh_ioapic_DEVICE;
|
||||
// Initialize an IOAPIC device structure, intented to initialize all IOAPIC devices structures during MADT parsing
|
||||
SH_STATUS sh_ioapic_init(sh_uint32 base,sh_uint8 ioapic_id,sh_uint32 gsi_base,sh_ioapic_DEVICE *ioapic);
|
||||
// Initialize DevS IOAPIC backend (max_ioapic_id is the max IOAPIC id, not the number of IOAPIC counted)
|
||||
SH_STATUS sh_ioapic_init_devs(sh_uint8 max_ioapic_id);
|
||||
// Bind a LAPIC device to DevS LAPIC backend
|
||||
SH_STATUS sh_ioapic_bind(sh_ioapic_DEVICE *lapic_dev);
|
||||
// Return a pointer to an IOAPIC device based on the provided IOAPIC id
|
||||
sh_ioapic_DEVICE *sh_ioapic_get_dev_ioapic_id(sh_uint64 ioapic_id);
|
||||
#define SH_IOAPIC_IOREDTBL_DELIVERY_FIXED 0b000
|
||||
#define SH_IOAPIC_IOREDTBL_DELIVERY_LOWEST_PRIORITY 0b001
|
||||
#define SH_IOAPIC_IOREDTBL_DELIVERY_NMI 0b100
|
||||
#define SH_IOAPIC_IOREDTBL_DELIVERY_INIT 0b101
|
||||
#define SH_IOAPIC_IOREDTBL_DELIVERY_EXTINT 0b111
|
||||
#define SH_IOAPIC_IOREDTBL_TRIGGER_EDGE 0b0
|
||||
#define SH_IOAPIC_IOREDTBL_TRIGGER_LEVEL 0b1
|
||||
#define SH_IOAPIC_IOREDTBL_POLARITY_HIGH 0b0
|
||||
#define SH_IOAPIC_IOREDTBL_POLARITY_LOW 0b1
|
||||
#define SH_IOAPIC_IOREDTBL_DEST_MODE_PHYSICAL 0b0
|
||||
#define SH_IOAPIC_IOREDTBL_DEST_MODE_LOGICAL 0b1
|
||||
// IOREDTBL entry structure
|
||||
typedef struct {
|
||||
sh_uint32 low;
|
||||
sh_uint32 high;
|
||||
} sh_ioapic_IOREDTBL_ENTRY;
|
||||
// Create an IOREDTBL entry
|
||||
inline sh_ioapic_IOREDTBL_ENTRY sh_ioapic_make_ioredtbl_entry(sh_uint8 vector,sh_uint8 delivery_mode,sh_uint8 destination_mode,sh_uint8 polarity,sh_uint8 trigger_mode,sh_bool mask,sh_uint8 apic_id) {
|
||||
sh_ioapic_IOREDTBL_ENTRY e={0};
|
||||
e.low=(e.low& ~0xFFU)|vector;
|
||||
e.low=(e.low& ~(0x7U<<8))|((delivery_mode&0x7U)<<8);
|
||||
e.low=(e.low& ~(1U<<11))|((destination_mode&0x1U)<<11);
|
||||
e.low=(e.low& ~(1U<<13))|((polarity&0x1U)<<13);
|
||||
e.low=(e.low& ~(1U<<15))|((trigger_mode&0x1U)<<15);
|
||||
e.low=(e.low& ~(1U<<16))|((mask&0x1U)<<16);
|
||||
e.high=(e.high& ~(0xFFU<<24))|((sh_uint32)apic_id<<24);
|
||||
return e;
|
||||
}
|
||||
// Mask an IOREDTBL entry for the provided GSI
|
||||
SH_STATUS sh_ioapic_mask_gsi(sh_ioapic_DEVICE *dev,sh_uint32 gsi);
|
||||
// Unmask an IOREDTBL entry for the provided GSI
|
||||
SH_STATUS sh_ioapic_unmask_gsi(sh_ioapic_DEVICE *dev,sh_uint32 gsi);
|
||||
// Read an IOREDTBL entry for the provided GSI
|
||||
SH_STATUS sh_ioapic_read_ioredtbl_entry(sh_ioapic_DEVICE *ioapic_dev,sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry);
|
||||
// Write an IOREDTBL entry for the provided GSI
|
||||
SH_STATUS sh_ioapic_write_ioredtbl_entry(sh_ioapic_DEVICE *ioapic_dev,sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry);
|
||||
// Mask all IOREDTBL entries for all IOAPIC
|
||||
SH_STATUS sh_ioapic_mask_all();
|
||||
// Return the IOAPIC device corresponding to the provided GSI
|
||||
sh_ioapic_DEVICE *sh_ioapic_get_dev_by_gsi(sh_uint32 gsi);
|
||||
// Parse an IOAPIC DevS query
|
||||
SH_STATUS sh_ioapic_devs_query(char *sub_path,sh_devs_RESULT *result);
|
||||
#endif
|
||||
83
shelter/lib/include/devs/apic/lapic.h
Normal file
83
shelter/lib/include/devs/apic/lapic.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_LAPIC_H
|
||||
#define SH_LIB_LAPIC_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
#include "memory/page.h"
|
||||
#include "devs/devs.h"
|
||||
#define SH_LAPIC_OFFSET_ID 0x020
|
||||
#define SH_LAPIC_OFFSET_VERSION 0x030
|
||||
#define SH_LAPIC_OFFSET_EOI 0x0B0
|
||||
#define SH_LAPIC_OFFSET_SVR 0x0F0
|
||||
#define SH_LAPIC_OFFSET_ESR 0x280
|
||||
#define SH_LAPIC_OFFSET_ICR_LOW 0x300
|
||||
#define SH_LAPIC_OFFSET_ICR_HIGH 0x310
|
||||
#define SH_LAPIC_OFFSET_LVT_TIMER 0x320
|
||||
#define SH_LAPIC_OFFSET_LVT_ERROR 0x370
|
||||
#define SH_LAPIC_OFFSET_TIMER_INIT 0x380
|
||||
#define SH_LAPIC_OFFSET_TIMER_CURR 0x390
|
||||
#define SH_LAPIC_OFFSET_TIMER_DIV 0x3E0
|
||||
#define SH_LAPIC_TIMER_DIVIDER 0x3
|
||||
// LAPIC device structure
|
||||
typedef struct {
|
||||
volatile sh_uint32 *base;
|
||||
sh_uint8 apic_id;
|
||||
sh_uint8 acpi_processor_id;
|
||||
sh_uint32 flags;
|
||||
sh_uint32 spurious_vector;
|
||||
} sh_lapic_DEVICE;
|
||||
// Initialize a LAPIC device structure, intented to initialize all LAPIC devices structures during MADT parsing
|
||||
SH_STATUS sh_lapic_init(sh_uint64 lapic_phys,sh_uint8 spurious_vector,sh_uint8 apic_id,sh_uint8 apic_processor_id,sh_uint32 flags,sh_lapic_DEVICE *lapic);
|
||||
// Initialize LAPIC for this CPU, intended to be used once by each CPU
|
||||
SH_STATUS sh_lapic_init_dev(sh_uint8 spurious_vector,sh_lapic_DEVICE *lapic);
|
||||
// Initialize DevS LAPIC backend (max_lapic_id is the max LAPIC id, not the number of LAPIC counted)
|
||||
SH_STATUS sh_lapic_init_devs(sh_uint16 max_lapic_id,sh_uint16 max_acpi_processor_id);
|
||||
// Bind a LAPIC device to DevS LAPIC backend
|
||||
SH_STATUS sh_lapic_bind(sh_lapic_DEVICE *lapic_dev);
|
||||
// Write 0 in provided LAPIC device EOI register
|
||||
void sh_lapic_eoi(sh_lapic_DEVICE *lapic);
|
||||
// Return a pointer to a LAPIC device based on the provided APIC id
|
||||
sh_lapic_DEVICE *sh_lapic_get_dev_apic_id(sh_uint64 apic_id);
|
||||
// Return a pointer to a LAPIC device based on the provided ACPI processor id
|
||||
sh_lapic_DEVICE *sh_lapic_get_dev_acpi_cpu_id(sh_uint64 acpi_processor_id);
|
||||
// Launch a LAPIC one-shot timer, independantely of the calibrated state of the LAPIC
|
||||
SH_STATUS sh_lapic_timer_one_shot(sh_lapic_DEVICE *lapic_dev,sh_uint32 initial_value);
|
||||
// Calibrate the LAPIC frequency
|
||||
SH_STATUS sh_lapic_calibrate(sh_lapic_DEVICE *lapic_dev,sh_uint64 cpu_freq);
|
||||
// Return the LAPIC frequency
|
||||
sh_uint64 sh_lapic_get_frequency();
|
||||
// Launch a LAPIC one-shot timer, LAPIC frequency need to be set
|
||||
SH_STATUS sh_lapic_timer_one_shot_us(sh_lapic_DEVICE *lapic_dev,sh_uint64 microseconds_count);
|
||||
// Return LAPIC DevS array
|
||||
sh_lapic_DEVICE **sh_lapic_get_by_apic_id_array();
|
||||
// Return max LAPIC APIC id
|
||||
sh_uint64 sh_lapic_get_max_apic_id();
|
||||
// Return max ACPI processor id
|
||||
sh_uint64 sh_lapic_get_max_acpi_processor_id();
|
||||
// Return LAPIC count
|
||||
sh_uint64 sh_lapic_get_lapic_count();
|
||||
#define SH_LAPIC_IPI_TYPE_NMI 0b100
|
||||
#define SH_LAPIC_IPI_TYPE_INIT 0b101
|
||||
#define SH_LAPIC_IPI_TYPE_STARTUP 0b110
|
||||
#define SH_LAPIC_IPI_TYPE_FIXED 0b000
|
||||
#define SH_LAPIC_IPI_DESTINATION_SPECIFIC (0b00<<18)
|
||||
#define SH_LAPIC_IPI_DESTINATION_SELF (0b01<<18)
|
||||
#define SH_LAPIC_IPI_DESTINATION_ALL (0b10<<18)
|
||||
#define SH_LAPIC_IPI_DESTINATION_ALL_EXCLUDING_SELF (0b11<<18)
|
||||
#define SH_LAPIC_IPI_NO_DESTINATION (sh_int16)(-1)
|
||||
// Return SH_TRUE if LAPIC IPI feature is busy
|
||||
sh_bool sh_lapic_ipi_is_busy(sh_lapic_DEVICE *lapic_dev);
|
||||
// Return LAPIC id of current core, return -1 if error happened
|
||||
sh_int16 sh_lapic_get_current_core();
|
||||
// Send a fixed IPI with the specified vector. lapic_dev must be the struct of the current CPU.
|
||||
// If destination_mode!=SH_LAPIC_IPI_DESTINATION_SPECIFIC, target_lapic_id must be SH_LAPIC_IPI_NO_DESTINATION
|
||||
SH_STATUS sh_lapic_send_fixed_ipi(sh_lapic_DEVICE *lapic_dev,sh_uint8 vector,sh_uint32 destination_mode,sh_int16 target_lapic_id);
|
||||
// Send any IPI other than a fixed IPI to specified destination. lapic_dev must be the struct of the current CPU.
|
||||
// ipi_type must be either SH_LAPIC_IPI_TYPE_INIT, SH_LAPIC_IPI_TYPE_STARTUP or SH_LAPIC_IPI_TYPE_NMI
|
||||
// If ipi_type is SH_LAPIC_IPI_TYPE_STARTUP, start_address must contain the starting address. Address constraint (compatible with 16 bits mode) are checked.
|
||||
// If ipi_type isn't SH_LAPIC_IPI_TYPE_STARTUP, start_address must be zero.
|
||||
// If destination_mode!=SH_LAPIC_IPI_DESTINATION_SPECIFIC, target_lapic_id must be SH_LAPIC_IPI_NO_DESTINATION
|
||||
SH_STATUS sh_lapic_send_ipi(sh_lapic_DEVICE *lapic_dev,sh_uint32 ipi_type,sh_uint32 destination_mode,sh_int16 target_lapic_id,sh_page_PHYSICAL_ADDRESS start_address);
|
||||
// Parse a LAPIC DevS query
|
||||
SH_STATUS sh_lapic_devs_query(char *sub_path,sh_devs_RESULT *result);
|
||||
#endif
|
||||
21
shelter/lib/include/devs/devs.h
Normal file
21
shelter/lib/include/devs/devs.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_DEVS_H
|
||||
#define SH_LIB_DEVS_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
#include "std/string.h"
|
||||
// DevS result type enum
|
||||
enum sh_devs_RESULT_TYPE {
|
||||
SH_DEVS_LAPIC,
|
||||
SH_DEVS_IOAPIC,
|
||||
SH_DEVS_VALUE,
|
||||
SH_DEVS_BOOL
|
||||
};
|
||||
// DevS result structure
|
||||
typedef struct {
|
||||
enum sh_devs_RESULT_TYPE type;
|
||||
sh_uint64 value;
|
||||
} sh_devs_RESULT;
|
||||
// Parse a DevS query
|
||||
SH_STATUS sh_devs_query(char *path,sh_devs_RESULT *result);
|
||||
#endif
|
||||
39
shelter/lib/include/devs/input/event.h
Normal file
39
shelter/lib/include/devs/input/event.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_EVENT_H
|
||||
#define SH_LIB_EVENT_H
|
||||
#include "std/type.h"
|
||||
// Events types
|
||||
typedef sh_uint8 sh_event_TYPE;
|
||||
#define SH_EVENT_TYPE_PS2_NORMAL 0U
|
||||
#define SH_EVENT_TYPE_PS2_E0 1U
|
||||
#define SH_EVENT_TYPE_KBD_CONTEXT 2U
|
||||
#define SH_EVENT_TYPE_KBD_PAUSE 3U
|
||||
// Keyboard events context flags
|
||||
#define SH_KBD_EVENT_SHIFT_ACTIVE (1u<<0)
|
||||
#define SH_KBD_EVENT_WIN_ACTIVE (1u<<1)
|
||||
#define SH_KBD_EVENT_LEFT_ACTIVE (1u<<1)
|
||||
#define SH_KBD_EVENT_RIGHT_ACTIVE (1u<<0)
|
||||
#define SH_KBD_EVENT_NUMLOCK_ACTIVE (1u<<0)
|
||||
#define SH_KBD_EVENT_CAPSLOCK_ACTIVE (1u<<1)
|
||||
// Keyboard contexts key scancodes
|
||||
#define SH_KBD_CONTEXT_LSHIFT 0U
|
||||
#define SH_KBD_CONTEXT_RSHIFT 1U
|
||||
#define SH_KBD_CONTEXT_LCTRL 2U
|
||||
#define SH_KBD_CONTEXT_RCTRL 3U
|
||||
#define SH_KBD_CONTEXT_LALT 4U
|
||||
#define SH_KBD_CONTEXT_RALT 5U
|
||||
#define SH_KBD_CONTEXT_WIN 6U
|
||||
#define SH_KBD_CONTEXT_NUMLOCK 7U
|
||||
#define SH_KBD_CONTEXT_CAPSLOCK 8U
|
||||
// Keyboard event structure
|
||||
typedef struct {
|
||||
sh_uint16 scancode;
|
||||
sh_bool pressed;
|
||||
sh_uint8 context_shift_win;
|
||||
sh_uint8 context_alt;
|
||||
sh_uint8 context_ctrl;
|
||||
sh_uint8 context_lock_status;
|
||||
sh_uint8 event_type;
|
||||
sh_uint64 timestamp; // tsc
|
||||
} sh_kbd_EVENT;
|
||||
#endif
|
||||
52
shelter/lib/include/devs/input/kbd.h
Normal file
52
shelter/lib/include/devs/input/kbd.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_KBD_H
|
||||
#define SH_LIB_KBD_H
|
||||
#include "std/stdlib.h"
|
||||
#include "devs/input/event.h"
|
||||
// Keyboard driver handle structure, driver handles should only be owned by keyboards drivers
|
||||
typedef struct sh_kbd_DRIVER_HANDLE sh_kbd_DRIVER_HANDLE;
|
||||
// Keyboard consumer handle structure, used for requests made by consumer
|
||||
typedef struct sh_kbd_CONSUMER_HANDLE sh_kbd_CONSUMER_HANDLE;
|
||||
// Keyboard device structure
|
||||
typedef struct {
|
||||
sh_uint8 kbd_id;
|
||||
sh_queue_KBD_EVENT *events_queue;
|
||||
sh_bool present;
|
||||
sh_bool ver_maj;
|
||||
sh_bool ver_num;
|
||||
sh_bool shift;
|
||||
sh_bool alt;
|
||||
sh_bool ctrl;
|
||||
sh_bool win;
|
||||
sh_SPIN_LOCK spinlock;
|
||||
} sh_kbd_DEVICE;
|
||||
// Initialize Keyboard input subsystem, should only be called one time
|
||||
SH_STATUS sh_kbd_init_devs();
|
||||
// Register the PS2 keyboard, completing the provided handle.
|
||||
SH_STATUS sh_kbd_register_ps2(sh_bool is_present,sh_kbd_DRIVER_HANDLE **handle);
|
||||
// Register any others keyboard, completing the provided handle, that should be used only by the keyboard driver for using the keyboard subsystem API
|
||||
SH_STATUS sh_kbd_register(sh_bool is_present,sh_kbd_DRIVER_HANDLE **handle);
|
||||
#define SH_KBD_FLAG_PRESENT 0U
|
||||
#define SH_KBD_FLAG_VER_MAJ 1U
|
||||
#define SH_KBD_FLAG_VER_NUM 2U
|
||||
#define SH_KBD_FLAG_SHIFT 3U
|
||||
#define SH_KBD_FLAG_ALT 4U
|
||||
#define SH_KBD_FLAG_CTRL 5U
|
||||
#define SH_KBD_FLAG_WIN 6U
|
||||
// Set any flag in the sh_kbd_DEVICE struct, given that a correct handle has been provided
|
||||
SH_STATUS sh_kbd_set_flag(sh_kbd_DRIVER_HANDLE *handle,sh_uint8 flag,sh_bool value);
|
||||
// Push a keyboard event on the keyboard queue, given that a correct handle has been provided
|
||||
SH_STATUS sh_kbd_push_events(sh_kbd_DRIVER_HANDLE *handle,sh_kbd_EVENT *event);
|
||||
// Keyboard device enumeration structure
|
||||
typedef struct {
|
||||
sh_uint64 bitmap[4];
|
||||
} sh_kbd_ENUMERATION;
|
||||
// Enumerate all keyboard devices id
|
||||
SH_STATUS sh_kbd_enumerate_devices(sh_kbd_ENUMERATION *enumeration);
|
||||
// Return a valid consumer handle for the provided keyboard device id
|
||||
SH_STATUS sh_kbd_get_handle(sh_uint8 kbd_id,sh_kbd_CONSUMER_HANDLE **handle);
|
||||
// Destroy the provided consumer handle and set the pointer to SH_NULLPTR
|
||||
SH_STATUS sh_kbd_destroy_handle(sh_kbd_CONSUMER_HANDLE **handle);
|
||||
// Read any flag in the sh_kbd_DEVICE struct, given that a correct handle has been provided. Accept either a driver or consumer handle, but fail if both handle are provided
|
||||
SH_STATUS sh_kbd_read_flag(sh_kbd_DRIVER_HANDLE *d_handle,sh_kbd_CONSUMER_HANDLE *c_handle,sh_uint8 flag,sh_bool *value);
|
||||
#endif
|
||||
105
shelter/lib/include/devs/input/ps2.h
Normal file
105
shelter/lib/include/devs/input/ps2.h
Normal file
@@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_PS2_H
|
||||
#define SH_LIB_PS2_H
|
||||
#include "std/stdlib.h"
|
||||
#include "devs/input/event.h"
|
||||
#include "devs/input/kbd.h"
|
||||
// Port macros
|
||||
#define SH_PS2_PORT_DATA 0x60
|
||||
#define SH_PS2_PORT_COMMAND 0x64
|
||||
// Status byte bits
|
||||
#define SH_PS2_STATUS_OBF 0b1
|
||||
#define SH_PS2_STATUS_IBF 0b10
|
||||
#define SH_PS2_STATUS_MOUSE_DATA 0b100000
|
||||
#define SH_PS2_STATUS_TIMEOUT 0b1000000
|
||||
#define SH_PS2_STATUS_PARITY 0b10000000
|
||||
// Config byte bits
|
||||
#define SH_PS2_CONFIG_PORT1_IRQ 0b1
|
||||
#define SH_PS2_CONFIG_PORT2_IRQ 0b10
|
||||
#define SH_PS2_CONFIG_PORT1_CLOCK_DISABLED 0b10000
|
||||
#define SH_PS2_CONFIG_PORT2_CLOCK_DISABLED 0b100000
|
||||
#define SH_PS2_CONFIG_TRANSLATION 0b1000000
|
||||
// PS2 controller commands macros
|
||||
#define SH_PS2_COMMAND_READ_CONFIG 0x20
|
||||
#define SH_PS2_COMMAND_WRITE_CONFIG 0x60
|
||||
#define SH_PS2_COMMAND_PS2_SELF_TEST 0xAA
|
||||
#define SH_PS2_COMMAND_PORT1_TEST 0xAB
|
||||
#define SH_PS2_COMMAND_PORT2_DISABLE 0xA7
|
||||
#define SH_PS2_COMMAND_PORT2_ENABLE 0xA8
|
||||
#define SH_PS2_COMMAND_PORT2_TEST 0xA9
|
||||
#define SH_PS2_COMMAND_PORT1_DISABLE 0xAD
|
||||
#define SH_PS2_COMMAND_PORT1_ENABLE 0xAE
|
||||
#define SH_PS2_COMMAND_READ_OUTPUT 0xD0
|
||||
#define SH_PS2_COMMAND_WRITE_OUTPUT 0xD1
|
||||
#define SH_PS2_COMMAND_WRITE_PORT2 0xD4
|
||||
// Self test results macros
|
||||
#define SH_PS2_SELF_TEST_SUCCESS 0x55
|
||||
#define SH_PS2_SELF_TEST_FAIL 0xFC
|
||||
#define SH_PS2_PORTS_SELF_TEST_SUCCESS 0x00
|
||||
// PS2 keyboard commands macros
|
||||
#define SH_PS2_KBD_COMMAND_SET_LEDS 0xED
|
||||
#define SH_PS2_KBD_COMMAND_ECHO 0xEE
|
||||
#define SH_PS2_KBD_COMMAND_SC_SET 0xF0
|
||||
#define SH_PS2_KBD_COMMAND_IDENTIFY 0xF2
|
||||
#define SH_PS2_KBD_COMMAND_ENABLE_SCANNING 0xF4
|
||||
#define SH_PS2_KBD_COMMAND_DISABLE_SCANNING 0xF5
|
||||
#define SH_PS2_KBD_COMMAND_DEFAULTS 0xF6
|
||||
#define SH_PS2_KBD_COMMAND_RESET 0xFF
|
||||
// Leds bits
|
||||
#define SH_PS2_KBD_LEDS_SCROLL_LOCK 0b1
|
||||
#define SH_PS2_KBD_LEDS_NUM_LOCK 0b10
|
||||
#define SH_PS2_KBD_LEDS_CAPS_LOCK 0b100
|
||||
// Scancodes (SC) sets
|
||||
#define SH_PS2_KBD_SC_SET_CURRENT 0
|
||||
#define SH_PS2_KBD_SC_SET_1 1
|
||||
#define SH_PS2_KBD_SC_SET_2 2
|
||||
#define SH_PS2_KBD_SC_SET_3 3
|
||||
// Keyboard response macros
|
||||
#define SH_PS2_KBD_ACK 0xFA
|
||||
#define SH_PS2_KBD_RESEND 0xFE
|
||||
#define SH_PS2_KBD_BAT_SUCCESS 0xAA
|
||||
#define SH_PS2_KBD_BAT_FAIL 0xFC
|
||||
#define SH_PS2_KBD_ECHO_REPLY 0xEE
|
||||
// Return SH_TRUE if data port contain useful datas to read
|
||||
inline sh_bool sh_ps2_output_ready() {
|
||||
return sh_asm_inb(SH_PS2_PORT_COMMAND) & SH_PS2_STATUS_OBF;
|
||||
}
|
||||
// Return SH_TRUE if controller isn't ready for any output
|
||||
inline sh_bool sh_ps2_cant_write() {
|
||||
return sh_asm_inb(SH_PS2_PORT_COMMAND) & SH_PS2_STATUS_IBF;
|
||||
}
|
||||
// Keyboard command struct
|
||||
typedef struct {
|
||||
sh_uint8 command;
|
||||
sh_uint8 data;
|
||||
sh_bool has_data;
|
||||
} sh_ps2_KBD_COMMAND;
|
||||
// Read status byte
|
||||
inline sh_uint8 sh_ps2_read_status() {
|
||||
return sh_asm_inb(SH_PS2_PORT_COMMAND);
|
||||
}
|
||||
// Read config byte
|
||||
inline sh_uint8 sh_ps2_read_config() {
|
||||
while (sh_ps2_cant_write());
|
||||
sh_asm_outb(SH_PS2_PORT_COMMAND,SH_PS2_COMMAND_READ_CONFIG);
|
||||
while (!sh_ps2_output_ready());
|
||||
return sh_asm_inb(SH_PS2_PORT_DATA);
|
||||
}
|
||||
// Write config byte
|
||||
inline void sh_ps2_write_config(sh_uint8 config) {
|
||||
while (sh_ps2_cant_write());
|
||||
sh_asm_outb(SH_PS2_PORT_COMMAND,SH_PS2_COMMAND_WRITE_CONFIG);
|
||||
while (sh_ps2_cant_write());
|
||||
sh_asm_outb(SH_PS2_PORT_DATA,config);
|
||||
}
|
||||
// PS2 IRQ1 handler
|
||||
void sh_ps2_irq1_handler();
|
||||
// Send a keyboard command and wait for it to finish
|
||||
SH_STATUS sh_ps2_send_keyboard_command_wait(sh_uint8 cmd,sh_uint8 data,sh_bool has_data);
|
||||
// Initialize the PS2 driver
|
||||
SH_STATUS sh_ps2_driver_init();
|
||||
// Disable scanning
|
||||
SH_STATUS sh_ps2_disable_scanning();
|
||||
// Enable scanning
|
||||
SH_STATUS sh_ps2_enable_scanning();
|
||||
#endif
|
||||
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
|
||||
@@ -5,7 +5,22 @@
|
||||
#include "std/status.h"
|
||||
#include "memory/page.h"
|
||||
#include "memory/vmem_layout.h"
|
||||
#include "devs/devs.h"
|
||||
#define SH_CONF_BOOT_CONFIG_VA SH_VMEM_LAYOUT_BOOT_CONFIG_VA
|
||||
// Framebuffer configuration
|
||||
typedef struct __attribute__((aligned(8))) {
|
||||
sh_bool fb_present;
|
||||
sh_page_VIRTUAL_ADDRESS fb_pa;
|
||||
sh_uint32 white_pixel_value;
|
||||
sh_uint32 gray_pixel_value;
|
||||
sh_uint64 size_in_bytes;
|
||||
sh_uint32 fb_height;
|
||||
sh_uint32 fb_width;
|
||||
sh_uint16 text_x;
|
||||
sh_uint16 text_y;
|
||||
sh_uint16 text_width;
|
||||
sh_uint16 text_height;
|
||||
} sh_conf_FB_CONFIG;
|
||||
// Boot config structure.
|
||||
typedef struct __attribute__((aligned(8))) {
|
||||
sh_uint8 sig_start[8];
|
||||
@@ -18,8 +33,14 @@ typedef struct __attribute__((aligned(8))) {
|
||||
sh_bool log_disable_serial_port;
|
||||
sh_bool disable_serial_port;
|
||||
sh_uint16 log_ring_size;
|
||||
sh_uint64 acpi_rsdp;
|
||||
sh_uint8 acpi_ver;
|
||||
sh_uint16 kbd_events_queue_capacity;
|
||||
sh_conf_FB_CONFIG fb_config;
|
||||
sh_uint8 sig_end[8];
|
||||
} sh_conf_BOOT_CONFIG;
|
||||
// Check and create boot config structure.
|
||||
SH_STATUS sh_conf_get_boot_config(sh_conf_BOOT_CONFIG **config);
|
||||
// Parse a configuration DevS query
|
||||
SH_STATUS sh_conf_devs_query(char *sub_path,sh_devs_RESULT *result);
|
||||
#endif
|
||||
|
||||
12
shelter/lib/include/kernel/efifb.h
Normal file
12
shelter/lib/include/kernel/efifb.h
Normal file
@@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_EFIFB_H
|
||||
#define SH_LIB_EFIFB_H
|
||||
#include "std/stdlib.h"
|
||||
#include "kernel/conf.h"
|
||||
// Initialize the EFI FB subsystem
|
||||
SH_STATUS sh_efifb_init_fb(sh_conf_FB_CONFIG *fb_conf,sh_page_PAGE_TABLE_POOL *ptp);
|
||||
// Initialize the boot progress bar
|
||||
SH_STATUS sh_efifb_init_bar();
|
||||
// Set the progress bar to a certain percentage
|
||||
SH_STATUS sh_efifb_set_bar(sh_uint8 percent);
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@ typedef sh_uint8 sh_log_OUTPUT_TYPE;
|
||||
#define SH_LOG_CRITICAL ((sh_log_OUTPUT_TYPE)4)
|
||||
#define SH_LOG_FATAL ((sh_log_OUTPUT_TYPE)5)
|
||||
#define SH_LOG_TEST ((sh_log_OUTPUT_TYPE)6)
|
||||
#define SH_LOG_FAULT ((sh_log_OUTPUT_TYPE)7)
|
||||
typedef sh_uint16 sh_log_OUTPUT_SOURCE;
|
||||
#define SH_LOG_SOURCE_MAIN ((sh_log_OUTPUT_SOURCE)0)
|
||||
#define SH_LOG_SOURCE_CONF ((sh_log_OUTPUT_SOURCE)1)
|
||||
@@ -22,6 +23,11 @@ typedef sh_uint16 sh_log_OUTPUT_SOURCE;
|
||||
#define SH_LOG_SOURCE_PBA ((sh_log_OUTPUT_SOURCE)6)
|
||||
#define SH_LOG_SOURCE_HEAP ((sh_log_OUTPUT_SOURCE)7)
|
||||
#define SH_LOG_SOURCE_STD ((sh_log_OUTPUT_SOURCE)8)
|
||||
#define SH_LOG_SOURCE_MEMS ((sh_log_OUTPUT_SOURCE)9)
|
||||
#define SH_LOG_SOURCE_CPUF ((sh_log_OUTPUT_SOURCE)10)
|
||||
#define SH_LOG_SOURCE_ACPI ((sh_log_OUTPUT_SOURCE)11)
|
||||
#define SH_LOG_SOURCE_TSC ((sh_log_OUTPUT_SOURCE)12)
|
||||
#define SH_LOG_SOURCE_SMP ((sh_log_OUTPUT_SOURCE)13)
|
||||
typedef struct {
|
||||
sh_log_OUTPUT_TYPE output_type;
|
||||
sh_log_OUTPUT_SOURCE output_source;
|
||||
@@ -30,11 +36,11 @@ typedef struct {
|
||||
} sh_log_OUTPUT_PAYLOAD;
|
||||
// Return SH_TRUE if provided output type is valid.
|
||||
static inline sh_bool sh_log_output_type_valid(sh_log_OUTPUT_TYPE t) {
|
||||
return t<=SH_LOG_TEST;
|
||||
return t<=SH_LOG_FAULT;
|
||||
}
|
||||
// Return SH_TRUE if provided source type is valid.
|
||||
static inline sh_bool sh_log_output_source_valid(sh_log_OUTPUT_SOURCE s) {
|
||||
return s<=SH_LOG_SOURCE_STD;
|
||||
return s<=SH_LOG_SOURCE_SMP;
|
||||
}
|
||||
// Load serial logging setting
|
||||
void sh_log_load_serial_setting(sh_bool is_disabled);
|
||||
@@ -46,6 +52,8 @@ void sh_log_load_logging_ring_size(sh_uint16 pages_count);
|
||||
sh_uint32 sh_log_get_logging_ring_size();
|
||||
// Return total bytes written to the ring buffer
|
||||
sh_uint64 sh_log_get_total_bytes_written();
|
||||
// Disable global logging ring, should only be used after SMP is enabled
|
||||
void sh_log_disable_global_logging_ring();
|
||||
// Log a byte
|
||||
void sh_log_byte(sh_uint8 byte);
|
||||
// Log a string
|
||||
@@ -103,6 +111,8 @@ SH_STATUS sh_log_error(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
SH_STATUS sh_log_critical(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
// Print a string to fatal channel, from provided source.
|
||||
SH_STATUS sh_log_fatal(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
// Print a string to fault channel, from provided source.
|
||||
SH_STATUS sh_log_fault(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
// Print a string to test channel. Doesn't include the new line caracter.
|
||||
SH_STATUS sh_log_ltest(const char* str);
|
||||
// Print a string to debug channel, from provided source. Doesn't include the new line caracter.
|
||||
@@ -117,6 +127,8 @@ SH_STATUS sh_log_lerror(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
SH_STATUS sh_log_lcritical(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
// Print a string to fatal channel, from provided source. Doesn't include the new line caracter.
|
||||
SH_STATUS sh_log_lfatal(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
// Print a string to fault channel, from provided source. Doesn't include the new line caracter.
|
||||
SH_STATUS sh_log_lfault(const char* str,sh_log_OUTPUT_SOURCE source);
|
||||
// The following functions format the output before logging it. The syntax is as follow:
|
||||
// - %s : char*
|
||||
// - %d : double
|
||||
@@ -141,6 +153,8 @@ SH_STATUS sh_log_ferror(const sh_log_OUTPUT_SOURCE source,const char* format,...
|
||||
SH_STATUS sh_log_fcritical(const sh_log_OUTPUT_SOURCE source,const char* format,...);
|
||||
// Print a string to fatal channel, from provided source. Format it before hand
|
||||
SH_STATUS sh_log_ffatal(const sh_log_OUTPUT_SOURCE source,const char* format,...);
|
||||
// Print a string to fault channel, from provided source. Format it before hand
|
||||
SH_STATUS sh_log_ffault(const sh_log_OUTPUT_SOURCE source,const char* format,...);
|
||||
// Print every information about memory statictics. Require log level to be 1 or 0
|
||||
SH_STATUS sh_log_mem_stats(sh_log_OUTPUT_SOURCE source);
|
||||
#endif
|
||||
|
||||
@@ -4,4 +4,5 @@
|
||||
#include "kernel/tests/test_radix.h"
|
||||
#include "kernel/tests/test_pez.h"
|
||||
#include "kernel/tests/test_malloc.h"
|
||||
#include "kernel/tests/test_queues.h"
|
||||
#include "kernel/tests/test_utils.h"
|
||||
|
||||
File diff suppressed because one or more lines are too long
10
shelter/lib/include/kernel/tests/payloads/test_pez_payload.h
Normal file
10
shelter/lib/include/kernel/tests/payloads/test_pez_payload.h
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
shelter/lib/include/kernel/tests/test_queues.h
Normal file
8
shelter/lib/include/kernel/tests/test_queues.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_TEST_QUEUES_H
|
||||
#define SH_LIB_TEST_QUEUES_H
|
||||
#include "std/stdlib.h"
|
||||
#include "cpu/tsc.h"
|
||||
// Test and benchmark queues from standard library
|
||||
SH_STATUS sh_test_benchmark_queues();
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "std/status.h"
|
||||
#include "cpu/tsc.h"
|
||||
// Compute and print time stats based on provided list of TSC values.
|
||||
SH_STATUS sh_test_compute_print_stats(char* benchname,sh_tsc_TSC_VALUE *tsc_value_array,sh_uint64 array_size);
|
||||
SH_STATUS sh_test_compute_print_stats(char* benchname,sh_tsc_TSC_VALUE *tsc_value_array,sh_uint64 array_size,sh_bool use_std_print);
|
||||
// Return pointer to TSC values buffer
|
||||
sh_tsc_TSC_VALUE* sh_test_get_tsc_values_buffer_ptr();
|
||||
// Load the number of iterations for benchmarks.
|
||||
|
||||
26
shelter/lib/include/memory/memory.h
Normal file
26
shelter/lib/include/memory/memory.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_MEMORY_H
|
||||
#define SH_LIB_MEMORY_H
|
||||
#include "std/type.h"
|
||||
#include "std/status.h"
|
||||
#include "kernel/conf.h"
|
||||
#include "memory/page.h"
|
||||
#include "memory/slab.h"
|
||||
#include "memory/heap.h"
|
||||
// Memory subsystem services structure
|
||||
typedef struct {
|
||||
sh_page_PAGE_TABLE_POOL kernel_ptp;
|
||||
sh_slab_reg_phys_SLAB_ALLOCATOR slab_reg_phys;
|
||||
sh_slab_reg_virt_SLAB_ALLOCATOR slab_reg_virt;
|
||||
struct sh_slab_radix_node_SLAB_ALLOCATOR slab_radix_node;
|
||||
sh_pez_PHYSICAL_PLANE physical_plane;
|
||||
sh_pez_VIRTUAL_PLANE virtual_plane_kernel_heap;
|
||||
sh_heap_KERNEL_HEAP kernel_heap;
|
||||
} sh_memory_MEMORY_SERVICES;
|
||||
// Initialize memory subsystem
|
||||
SH_STATUS sh_memory_init_subsystem(sh_conf_BOOT_CONFIG *boot_config,sh_memory_MEMORY_SERVICES *services);
|
||||
// Identity map a physical memory area
|
||||
SH_STATUS sh_memory_identity_map(sh_page_PHYSICAL_ADDRESS phys_start,sh_uint64 page_count,sh_uint64 flags);
|
||||
// Parse a memory DevS query
|
||||
SH_STATUS sh_memory_devs_query(char *sub_path,sh_devs_RESULT *result);
|
||||
#endif
|
||||
@@ -156,4 +156,6 @@ SH_STATUS sh_page_analyse_memory_map(sh_page_PAGE_TABLE_POOL *ptp);
|
||||
sh_page_VIRTUAL_ADDRESS sh_page_get_physical_bitmap_ptr();
|
||||
// Get physical memory statistics
|
||||
SH_STATUS sh_page_get_memory_stats(sh_page_MEM_STATS *mem_stats);
|
||||
// Return total installed memory in bytes
|
||||
sh_uint64 sh_page_get_installed_memory_bytes();
|
||||
#endif
|
||||
|
||||
@@ -15,4 +15,6 @@ typedef struct {
|
||||
SH_STATUS sh_ring_write_byte(sh_ring_RING_BUFFER_HEADER *ring_buffer,sh_uint8 byte);
|
||||
// Write a null terminated string into the provided ring buffer
|
||||
SH_STATUS sh_ring_write_string(sh_ring_RING_BUFFER_HEADER *ring_buffer,char *string);
|
||||
// Read bytes_count from the provided ring buffer, and put it into output. Return SH_STATUS_TOO_MUCH_DATA if bytes_count>buf.buffer_size_bytes, setting the entire buffer to 0x00
|
||||
SH_STATUS sh_ring_read_bytes(sh_ring_RING_BUFFER_HEADER *ring_buffer,sh_uint32 bytes_count,void *output);
|
||||
#endif
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
#define SH_VMEM_LAYOUT_SLAB_REG_VIRT_VA 0xFFFFFF800C600000ULL
|
||||
// The total size for the slabs for virtual regions objects
|
||||
#define SH_VMEM_LAYOUT_SLAB_REG_VIRT_SIZE_BYTES (1ULL<<29)*12ULL
|
||||
// The alignement for SH_VMEM_LAYOUT_SLAB_RADIX_NODE_VA
|
||||
// The alignment for SH_VMEM_LAYOUT_SLAB_RADIX_NODE_VA
|
||||
#define SH_VMEM_LAYOUT_PBA_RADIX_NODE_BLOCK_ALIGN (32ULL*4096ULL)
|
||||
// The base for the PBA for the slabs for radix nodes
|
||||
#define SH_VMEM_LAYOUT_SLAB_RADIX_NODE_VA ((SH_VMEM_LAYOUT_SLAB_REG_VIRT_VA+SH_VMEM_LAYOUT_SLAB_REG_VIRT_SIZE_BYTES+SH_VMEM_LAYOUT_PBA_RADIX_NODE_BLOCK_ALIGN)/SH_VMEM_LAYOUT_PBA_RADIX_NODE_BLOCK_ALIGN)*SH_VMEM_LAYOUT_PBA_RADIX_NODE_BLOCK_ALIGN
|
||||
|
||||
29
shelter/lib/include/std/print.h
Normal file
29
shelter/lib/include/std/print.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_PRINT_H
|
||||
#define SH_LIB_PRINT_H
|
||||
#include "std/status.h"
|
||||
#include "std/type.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/conf.h"
|
||||
#include "cpu/ap.h"
|
||||
#define SH_DEBUG SH_LOG_DEBUG
|
||||
#define SH_LOG SH_LOG_LOG
|
||||
#define SH_WARNING SH_LOG_WARNING
|
||||
#define SH_ERROR SH_LOG_ERROR
|
||||
#define SH_CRITICAL SH_LOG_CRITICAL
|
||||
#define SH_FATAL SH_LOG_FATAL
|
||||
#define SH_TEST SH_LOG_TEST
|
||||
#define SH_FAULT SH_LOG_FAULT
|
||||
// Setup rings buffer for APs
|
||||
SH_STATUS sh_print_setup_ring_buffers_per_ap(sh_conf_BOOT_CONFIG *boot_config);
|
||||
// Print string
|
||||
SH_STATUS sh_print(sh_log_OUTPUT_TYPE output_type,char* text);
|
||||
// Print string, format it before hand
|
||||
SH_STATUS sh_printf(sh_log_OUTPUT_TYPE output_type,char* format,...);
|
||||
// Priority print string, reserved to IRQ handler
|
||||
SH_STATUS sh_iprint(sh_log_OUTPUT_TYPE output_type,char* text);
|
||||
// Priority print string, reserved to IRQ handler, format it before hand
|
||||
SH_STATUS sh_iprintf(sh_log_OUTPUT_TYPE output_type,char* text,...);
|
||||
// Format a string and put it into the provided buffer
|
||||
SH_STATUS sh_sprintf(char* output_string,sh_uint64 output_len,char* format,...);
|
||||
#endif
|
||||
19
shelter/lib/include/std/queue.h
Normal file
19
shelter/lib/include/std/queue.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_QUEUE_H
|
||||
#define SH_LIB_QUEUE_H
|
||||
#include "std/type.h"
|
||||
#include "std/status.h"
|
||||
#include "devs/input/event.h"
|
||||
// Keyboard events queue structure
|
||||
typedef struct {
|
||||
sh_kbd_EVENT *buffer;
|
||||
sh_uint32 capacity;
|
||||
sh_uint32 write_index;
|
||||
} sh_queue_KBD_EVENT;
|
||||
// Initialize an event queue
|
||||
SH_STATUS sh_queue_event_init(sh_queue_KBD_EVENT *q,sh_uint32 capacity);
|
||||
// Push a keyboard event to the provided queue
|
||||
SH_STATUS sh_queue_event_push(sh_queue_KBD_EVENT *q,sh_kbd_EVENT ev);
|
||||
// Destroy the provided keyboard event queue
|
||||
SH_STATUS sh_queue_event_destroy(sh_queue_KBD_EVENT *q);
|
||||
#endif
|
||||
74
shelter/lib/include/std/smp.h
Normal file
74
shelter/lib/include/std/smp.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_SMP_H
|
||||
#define SH_LIB_SMP_H
|
||||
#include "std/type.h"
|
||||
#include "std/status.h"
|
||||
#include "cpu/ap.h"
|
||||
#include "cpu/serial.h"
|
||||
#include "cpu/asm.h"
|
||||
// Write GS base register
|
||||
inline void sh_smp_write_gs_base(sh_uint64 value) {
|
||||
sh_uint32 low=(sh_uint32)(value);
|
||||
sh_uint32 high=(sh_uint32)(value>>32);
|
||||
__asm__ volatile ("wrmsr"::"c"(0xC0000101),"a"(low),"d"(high));
|
||||
}
|
||||
// Return CPU struct of this CPU
|
||||
inline sh_ap_CPU_STRUCT *sh_smp_gs_base() {
|
||||
sh_uint32 low,high;
|
||||
__asm__ volatile ("rdmsr":"=a"(low),"=d"(high):"c"(0xC0000101));
|
||||
return (sh_ap_CPU_STRUCT*)(((sh_uint64)high<<32)|low);
|
||||
}
|
||||
// Lock structure, unlocked lock have lapic_id to SH_UINT32_MAX
|
||||
typedef struct {
|
||||
volatile sh_uint32 spinlock;
|
||||
sh_uint32 lapic_id;
|
||||
} sh_SPIN_LOCK;
|
||||
// Create an unlocked lock, intended for creation of global variables.
|
||||
#define SH_LOCK() {.spinlock=0,.lapic_id=SH_UINT32_MAX}
|
||||
// Create an unlocked lock, intended for creation of local variables
|
||||
#define SH_LOCK_LOCAL() ((sh_SPIN_LOCK){.spinlock=0,.lapic_id=SH_UINT32_MAX})
|
||||
// Lock a spinlock
|
||||
inline void sh_spin_lock(sh_SPIN_LOCK *lock) {
|
||||
while (__atomic_test_and_set(&lock->spinlock,__ATOMIC_ACQUIRE)) {
|
||||
while (lock->spinlock) {
|
||||
__asm__ volatile ("pause");
|
||||
}
|
||||
}
|
||||
if (sh_smp_gs_base()==SH_NULLPTR) {
|
||||
sh_serial_send_byte('!');
|
||||
while (SH_TRUE) {}
|
||||
}
|
||||
lock->lapic_id=sh_smp_gs_base()->lapic_id;
|
||||
}
|
||||
// Unlock a spinlock
|
||||
inline void sh_spin_unlock(sh_SPIN_LOCK *lock) {
|
||||
lock->lapic_id=SH_UINT32_MAX;
|
||||
__atomic_clear(&lock->spinlock,__ATOMIC_RELEASE);
|
||||
}
|
||||
// Try to lock a spinlock, doesn't wait for it to be unlocked, return SH_TRUE if lock is now owned by us
|
||||
inline sh_bool sh_spin_trylock(sh_SPIN_LOCK *lock) {
|
||||
if (__atomic_test_and_set(&lock->spinlock,__ATOMIC_ACQUIRE)) return SH_FALSE;
|
||||
lock->lapic_id=sh_smp_gs_base()->lapic_id;
|
||||
return SH_TRUE;
|
||||
}
|
||||
// Return which CPU is locking the lock
|
||||
inline sh_uint32 sh_spin_wholock(sh_SPIN_LOCK *lock) {
|
||||
return lock->lapic_id;
|
||||
}
|
||||
// Set CPU count (aka max_cpu_id+1)
|
||||
void sh_smp_set_cpu_count(sh_int16 cpu_count);
|
||||
// Return CPU count, return -1 if this value isn't initialized
|
||||
sh_int16 sh_smp_get_cpu_count();
|
||||
// Memory barrier
|
||||
inline void sh_mb() {
|
||||
sh_asm_mfence();
|
||||
}
|
||||
// Read memory barrier
|
||||
inline void sh_rmb() {
|
||||
sh_asm_lfence();
|
||||
}
|
||||
// Write memory barrier
|
||||
inline void sh_wmb() {
|
||||
sh_asm_sfence();
|
||||
}
|
||||
#endif
|
||||
@@ -36,6 +36,17 @@ typedef sh_int64 SH_STATUS;
|
||||
#define SH_STATUS_PAGE_ALREADY_FREE 25LL
|
||||
#define SH_STATUS_TOO_MUCH_DATA 26LL
|
||||
#define SH_STATUS_HEAP_NOT_INITIALIZED 27LL
|
||||
#define SH_STATUS_MEMORY_SUBSYSTEM_NOT_INITIALIZED 28LL
|
||||
#define SH_STATUS_INVALID_CHECKSUM 29LL
|
||||
#define SH_STATUS_BAD_SIZE 30LL
|
||||
#define SH_STATUS_INVALID_STATE 31LL
|
||||
#define SH_STATUS_DEVS_NOT_INITIALIZED 32LL
|
||||
#define SH_STATUS_UNAVAILABLE 33LL
|
||||
#define SH_STATUS_ALREADY_INITIALIZED 34LL
|
||||
#define SH_STATUS_AP_NO_LAPIC 35LL
|
||||
#define SH_STATUS_ISO_UNKNOW_BUS 36LL
|
||||
#define SH_STATUS_INVALID_HANDLE 37LL
|
||||
#define SH_STATUS_DEVICE_NOT_PRESENT 38LL
|
||||
// Return SH_TRUE if provided status is an error
|
||||
static inline sh_bool sh_status_error(SH_STATUS s) {
|
||||
return s>=SH_STATUS_INVALID_PARAMETER;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// This header is just here to include all standard header
|
||||
// If you are looking for printing functions, take a look at kernel/log.h
|
||||
// If you are looking for non-thread safe/more direct printing functions, take a look at kernel/log.h
|
||||
#include "std/mem.h"
|
||||
#include "std/malloc.h"
|
||||
#include "std/status.h"
|
||||
#include "std/print.h"
|
||||
#include "std/smp.h"
|
||||
#include "std/type.h"
|
||||
#include "std/status.h"
|
||||
#include "std/string.h"
|
||||
#include "std/queue.h"
|
||||
|
||||
17
shelter/lib/include/std/string.h
Normal file
17
shelter/lib/include/std/string.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#ifndef SH_LIB_STRING_H
|
||||
#define SH_LIB_STRING_H
|
||||
#include "std/type.h"
|
||||
// Return the length of a null terminated string
|
||||
sh_uint64 sh_string_len(char *str);
|
||||
// Compare two null terminated string, both strings must not exceed the provided length. Return SH_TRUE if both strings are equals on the provided length
|
||||
sh_bool sh_string_compare(char *str1,char* str2,sh_uint64 length);
|
||||
// Return the index of the first occurence of the provided character into the string, return SH_UINT64_MAX if not found or error
|
||||
sh_uint64 sh_string_find_char(char *str,char character);
|
||||
// Return the index of the start of the first occurence of the provided substring into the string, return SH_UINT64_MAX if not found or error
|
||||
sh_uint64 sh_string_find(char *str,char *substr);
|
||||
// Copy a substring from a string to another string, and return the pointer to the new string
|
||||
char *sh_string_substring(char *source_str,sh_uint64 start_index,sh_uint64 length,char *output);
|
||||
// Convert a string to a sh_uint64
|
||||
sh_uint64 sh_string_to_uint64(char *str);
|
||||
#endif
|
||||
Reference in New Issue
Block a user