From 16a6bafa2481db28131ba3368022ff3c859f3a3d Mon Sep 17 00:00:00 2001 From: brenozd Date: Mon, 4 Nov 2024 18:09:30 -0300 Subject: [PATCH] implementation of TSS --- src/kernel/CMakeLists.txt | 8 ++++ src/kernel/arch/i386/gdt.c | 53 ++++++++++++++++++++--- src/kernel/{include => arch/i386}/gdt.h | 3 +- src/kernel/arch/i386/gdt.s | 0 src/kernel/arch/i386/tss.h | 57 +++++++++++++++++++++++++ src/kernel/kernel.c | 3 +- src/kernel/kernel.h | 2 +- src/kernel/version.h | 4 +- src/libc/version.h | 4 +- 9 files changed, 119 insertions(+), 15 deletions(-) rename src/kernel/{include => arch/i386}/gdt.h (97%) create mode 100644 src/kernel/arch/i386/gdt.s create mode 100644 src/kernel/arch/i386/tss.h diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt index 90f3f1e..5fdd9d3 100644 --- a/src/kernel/CMakeLists.txt +++ b/src/kernel/CMakeLists.txt @@ -10,6 +10,14 @@ add_custom_target( COMMENT "Running versioning script") add_dependencies(${PROJECT_NAME} run_versioning_script-kernel) +add_custom_target( + generate-iso ALL + COMMAND "${PROJECT_SOURCE_DIR}/scripts/create_iso.sh" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + BYPRODUCTS "${PROJECT_SOURCE_DIR}/appa-os.iso" + COMMENT "Creating ISO") +add_dependencies(generate-iso ${PROJECT_NAME}) + # Set target name to be "${PROJECT_NAME}.bin" set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}") diff --git a/src/kernel/arch/i386/gdt.c b/src/kernel/arch/i386/gdt.c index 30c503f..eecc4a2 100644 --- a/src/kernel/arch/i386/gdt.c +++ b/src/kernel/arch/i386/gdt.c @@ -1,15 +1,31 @@ #include "gdt.h" +#include "tss.h" #include #include +#include -#define GDT_ENTRY_SIZE 5 +#define GDT_ENTRY_SIZE 6 static gdt_segment_descriptor_t gdt_descriptors[GDT_ENTRY_SIZE]; static gdt_entry_t gdt; +static tss_descriptor_t tss; + +// https://github.com/szhou42/osdev/blob/52c02f0d4327442493459253a5c6c83c5f378765/src/kernel/descriptor_tables/tss_helper.asm#L3 +void tss_flush() { + // TSS is the last entry on our gdt table + const uint32_t tss_offset = sizeof(gdt_segment_descriptor_t) * (GDT_ENTRY_SIZE - 1); + + asm volatile("mov %0, %%eax\n\t" + "ltr %%eax\n\t" // Load the Task Register with the TSS selector in AX + "ret\n\t" // Return to the caller + : + : "r"(tss_offset) + : "eax"); +} // https://forum.osdev.org/viewtopic.php?t=37245 void gdt_flush() { - uint32_t ptr = (uint32_t)&gdt; + const uint32_t ptr = (uint32_t)&gdt; asm volatile("movl %0,%%eax \n\t" "lgdt (%%eax) \n\t" @@ -25,45 +41,68 @@ void gdt_flush() { "movw %%ax, %%gs \n\t" "movw %%ax, %%ss \n\t" "ljmp $0x0008,$.gdt_flush_end%=\n\t" - ".gdt_flush_end%=:" + ".gdt_flush_end%=:\n\t" + "ret\n\t" : : "r"(ptr) : "eax"); } +void tss_init() { + const uint32_t tss_base = (uint32_t)&tss; + const uint32_t tss_limit = tss_base + sizeof(tss_descriptor_t); + + // TODO: Somehow setting TSS to 0 crashes the system, why? + // memset(&tss, 0, sizeof(tss)); + + // 0x10 corresponds to Kernel Mode Data Segment (gdt_descriptors[2]), 3rd entry on gdt table + tss.ss0 = (uint16_t)(sizeof(gdt_segment_descriptor_t) * (2)); + tss.esp0 = (uint32_t)0x00; + tss.iopb = (uint16_t)sizeof(tss_descriptor_t); + + gdt_descriptors[5] = gdt_create_segment_descriptor(tss_base, tss_limit, 0x00, GDT_ACCESS_PRESENT(1) | GDT_CODE_EXA); +} + void gdt_init() { // This is setting up 4 large seguments overlapped to use paging // https://stackoverflow.com/a/23979175 - gdt.limit = (sizeof(struct gdt_segment_descriptor) * GDT_ENTRY_SIZE) - 1; + gdt.limit = (sizeof(gdt_segment_descriptor_t) * GDT_ENTRY_SIZE) - 1; gdt.base = (uint32_t)gdt_descriptors; // Null Segment gdt_descriptors[0] = gdt_create_segment_descriptor(0, 0, 0, 0); - // Kernel Mode Code Segment with 4 megabytes + // Kernel Mode Code Segment gdt_descriptors[1] = gdt_create_segment_descriptor(0, 0xFFFFFFFF, (GDT_FLAG_GRANULARITY(1) | GDT_FLAG_SIZE(1)) << 4, GDT_ACCESS_PRESENT(1) | GDT_ACCESS_PRIVILEGE(0) | GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_CODE_EXRD); + // Kernel Mode Data Segment gdt_descriptors[2] = gdt_create_segment_descriptor(0, 0xFFFFFFFF, (GDT_FLAG_GRANULARITY(1) | GDT_FLAG_SIZE(1)) << 4, GDT_ACCESS_PRESENT(1) | GDT_ACCESS_PRIVILEGE(0) | GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_DATA_RDWR); + // User Mode Code Segment gdt_descriptors[3] = gdt_create_segment_descriptor(0, 0xFFFFFFFF, (GDT_FLAG_GRANULARITY(1) | GDT_FLAG_SIZE(1)) << 4, GDT_ACCESS_PRESENT(1) | GDT_ACCESS_PRIVILEGE(3) | GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_CODE_EXRD); + // User Mode Data Segment gdt_descriptors[4] = gdt_create_segment_descriptor(0, 0xFFFFFFFF, (GDT_FLAG_GRANULARITY(1) | GDT_FLAG_SIZE(1)) << 4, GDT_ACCESS_PRESENT(1) | GDT_ACCESS_PRIVILEGE(3) | GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_DATA_RDWR); - // TODO: add Task State Segment + tss_init(); + // Load and flush the GDT gdt_flush(); + + // Load the TSS + tss_flush(); } gdt_segment_descriptor_t gdt_create_segment_descriptor(uint32_t base, uint32_t limit, uint8_t flags, uint8_t access) { if (limit > UINT32_MAX) { - printf("GDT cannot encode limits larger than 0xFFFFF"); + printf("GDT cannot encode limits larger than %X", UINT32_MAX); abort(); } diff --git a/src/kernel/include/gdt.h b/src/kernel/arch/i386/gdt.h similarity index 97% rename from src/kernel/include/gdt.h rename to src/kernel/arch/i386/gdt.h index ceff6ac..ba03617 100644 --- a/src/kernel/include/gdt.h +++ b/src/kernel/arch/i386/gdt.h @@ -65,6 +65,7 @@ gdt_segment_descriptor_t gdt_create_segment_descriptor(uint32_t base, uint32_t l void gdt_init(); -void gdt_flush(); +extern void gdt_flush(); +extern void tts_flush(); #endif // INCLUDE_GDT_H_ diff --git a/src/kernel/arch/i386/gdt.s b/src/kernel/arch/i386/gdt.s new file mode 100644 index 0000000..e69de29 diff --git a/src/kernel/arch/i386/tss.h b/src/kernel/arch/i386/tss.h new file mode 100644 index 0000000..62f07ef --- /dev/null +++ b/src/kernel/arch/i386/tss.h @@ -0,0 +1,57 @@ +#ifndef INCLUDE_INCLUDE_TSS_H_ +#define INCLUDE_INCLUDE_TSS_H_ + +#include + +struct tss_descriptor { + uint32_t link; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldtr; + // Some places place those two below as uint16_t? // http://www.brokenthorn.com/Resources/OSDev23.html + uint16_t iopb; + uint16_t ssp; +} __attribute__((packed)); + +typedef struct tss_descriptor tss_descriptor_t; + +void tss_flush(); + +#endif // INCLUDE_INCLUDE_TSS_H_ + + + + + + + + + + + + + + + + diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 7cd5d94..9ef61db 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,4 +1,4 @@ -#include "gdt.h" +#include "arch/i386/gdt.h" #include "kernel/tty.h" #include "version.h" #include @@ -23,7 +23,6 @@ void kprintf(const char *format, ...) { } } - void __attribute__((noinline)) kernel_main(void) { tty_initialize(); kprintf("Appa-OS version %s\n", VERSION); diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index 5bda4e1..63c51b4 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -1,6 +1,6 @@ #ifndef INCLUDE_KERNEL_KERNEL_H_ #define INCLUDE_KERNEL_KERNEL_H_ -void kprintf(const char *format, ...) +void kprintf(const char *format, ...); #endif // INCLUDE_KERNEL_KERNEL_H_ diff --git a/src/kernel/version.h b/src/kernel/version.h index e1e1e8a..07e5851 100644 --- a/src/kernel/version.h +++ b/src/kernel/version.h @@ -8,9 +8,9 @@ #define APPA_OS_VERSION_MAJOR 0 #define APPA_OS_VERSION_MINOR 0 -#define APPA_OS_VERSION_PATCH 154 +#define APPA_OS_VERSION_PATCH 233 #define APPA_OS_COMMIT_HASH cd01d7d8d36862bc00ae88f7cd185c352a7b7eda -#define APPA_OS_BUILD_TIMESTAMP 1730732925 +#define APPA_OS_BUILD_TIMESTAMP 1730754533 #endif // INCLUDE_APPA_OS_VERSION_H_ diff --git a/src/libc/version.h b/src/libc/version.h index e4c6c36..db3bd68 100644 --- a/src/libc/version.h +++ b/src/libc/version.h @@ -8,9 +8,9 @@ #define LIB_C_VERSION_MAJOR 0 #define LIB_C_VERSION_MINOR 0 -#define LIB_C_VERSION_PATCH 148 +#define LIB_C_VERSION_PATCH 227 #define LIB_C_COMMIT_HASH cd01d7d8d36862bc00ae88f7cd185c352a7b7eda -#define LIB_C_BUILD_TIMESTAMP 1730732925 +#define LIB_C_BUILD_TIMESTAMP 1730754533 #endif // INCLUDE_LIB_C_VERSION_H_