implementation of TSS
This commit is contained in:
@@ -10,6 +10,14 @@ add_custom_target(
|
|||||||
COMMENT "Running versioning script")
|
COMMENT "Running versioning script")
|
||||||
add_dependencies(${PROJECT_NAME} run_versioning_script-kernel)
|
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 name to be "${PROJECT_NAME}.bin"
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}")
|
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}")
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
#include "tss.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define GDT_ENTRY_SIZE 5
|
#define GDT_ENTRY_SIZE 6
|
||||||
|
|
||||||
static gdt_segment_descriptor_t gdt_descriptors[GDT_ENTRY_SIZE];
|
static gdt_segment_descriptor_t gdt_descriptors[GDT_ENTRY_SIZE];
|
||||||
static gdt_entry_t gdt;
|
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
|
// https://forum.osdev.org/viewtopic.php?t=37245
|
||||||
void gdt_flush() {
|
void gdt_flush() {
|
||||||
uint32_t ptr = (uint32_t)&gdt;
|
const uint32_t ptr = (uint32_t)&gdt;
|
||||||
|
|
||||||
asm volatile("movl %0,%%eax \n\t"
|
asm volatile("movl %0,%%eax \n\t"
|
||||||
"lgdt (%%eax) \n\t"
|
"lgdt (%%eax) \n\t"
|
||||||
@@ -25,45 +41,68 @@ void gdt_flush() {
|
|||||||
"movw %%ax, %%gs \n\t"
|
"movw %%ax, %%gs \n\t"
|
||||||
"movw %%ax, %%ss \n\t"
|
"movw %%ax, %%ss \n\t"
|
||||||
"ljmp $0x0008,$.gdt_flush_end%=\n\t"
|
"ljmp $0x0008,$.gdt_flush_end%=\n\t"
|
||||||
".gdt_flush_end%=:"
|
".gdt_flush_end%=:\n\t"
|
||||||
|
"ret\n\t"
|
||||||
:
|
:
|
||||||
: "r"(ptr)
|
: "r"(ptr)
|
||||||
: "eax");
|
: "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() {
|
void gdt_init() {
|
||||||
// This is setting up 4 large seguments overlapped to use paging
|
// This is setting up 4 large seguments overlapped to use paging
|
||||||
// https://stackoverflow.com/a/23979175
|
// 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;
|
gdt.base = (uint32_t)gdt_descriptors;
|
||||||
|
|
||||||
// Null Segment
|
// Null Segment
|
||||||
gdt_descriptors[0] = gdt_create_segment_descriptor(0, 0, 0, 0);
|
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_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_PRESENT(1) | GDT_ACCESS_PRIVILEGE(0) |
|
||||||
GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_CODE_EXRD);
|
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_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_PRESENT(1) | GDT_ACCESS_PRIVILEGE(0) |
|
||||||
GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_DATA_RDWR);
|
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_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_PRESENT(1) | GDT_ACCESS_PRIVILEGE(3) |
|
||||||
GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_CODE_EXRD);
|
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_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_PRESENT(1) | GDT_ACCESS_PRIVILEGE(3) |
|
||||||
GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_DATA_RDWR);
|
GDT_ACCESS_DESCRIPTOR_TYPE(1) | GDT_DATA_RDWR);
|
||||||
// TODO: add Task State Segment
|
tss_init();
|
||||||
|
|
||||||
// Load and flush the GDT
|
// Load and flush the GDT
|
||||||
gdt_flush();
|
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) {
|
gdt_segment_descriptor_t gdt_create_segment_descriptor(uint32_t base, uint32_t limit, uint8_t flags, uint8_t access) {
|
||||||
if (limit > UINT32_MAX) {
|
if (limit > UINT32_MAX) {
|
||||||
printf("GDT cannot encode limits larger than 0xFFFFF");
|
printf("GDT cannot encode limits larger than %X", UINT32_MAX);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ gdt_segment_descriptor_t gdt_create_segment_descriptor(uint32_t base, uint32_t l
|
|||||||
|
|
||||||
void gdt_init();
|
void gdt_init();
|
||||||
|
|
||||||
void gdt_flush();
|
extern void gdt_flush();
|
||||||
|
extern void tts_flush();
|
||||||
|
|
||||||
#endif // INCLUDE_GDT_H_
|
#endif // INCLUDE_GDT_H_
|
||||||
0
src/kernel/arch/i386/gdt.s
Normal file
0
src/kernel/arch/i386/gdt.s
Normal file
57
src/kernel/arch/i386/tss.h
Normal file
57
src/kernel/arch/i386/tss.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#ifndef INCLUDE_INCLUDE_TSS_H_
|
||||||
|
#define INCLUDE_INCLUDE_TSS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "gdt.h"
|
#include "arch/i386/gdt.h"
|
||||||
#include "kernel/tty.h"
|
#include "kernel/tty.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -23,7 +23,6 @@ void kprintf(const char *format, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void __attribute__((noinline)) kernel_main(void) {
|
void __attribute__((noinline)) kernel_main(void) {
|
||||||
tty_initialize();
|
tty_initialize();
|
||||||
kprintf("Appa-OS version %s\n", VERSION);
|
kprintf("Appa-OS version %s\n", VERSION);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifndef INCLUDE_KERNEL_KERNEL_H_
|
#ifndef INCLUDE_KERNEL_KERNEL_H_
|
||||||
#define INCLUDE_KERNEL_KERNEL_H_
|
#define INCLUDE_KERNEL_KERNEL_H_
|
||||||
|
|
||||||
void kprintf(const char *format, ...)
|
void kprintf(const char *format, ...);
|
||||||
|
|
||||||
#endif // INCLUDE_KERNEL_KERNEL_H_
|
#endif // INCLUDE_KERNEL_KERNEL_H_
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#define APPA_OS_VERSION_MAJOR 0
|
#define APPA_OS_VERSION_MAJOR 0
|
||||||
#define APPA_OS_VERSION_MINOR 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_COMMIT_HASH cd01d7d8d36862bc00ae88f7cd185c352a7b7eda
|
||||||
#define APPA_OS_BUILD_TIMESTAMP 1730732925
|
#define APPA_OS_BUILD_TIMESTAMP 1730754533
|
||||||
|
|
||||||
#endif // INCLUDE_APPA_OS_VERSION_H_
|
#endif // INCLUDE_APPA_OS_VERSION_H_
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#define LIB_C_VERSION_MAJOR 0
|
#define LIB_C_VERSION_MAJOR 0
|
||||||
#define LIB_C_VERSION_MINOR 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_COMMIT_HASH cd01d7d8d36862bc00ae88f7cd185c352a7b7eda
|
||||||
#define LIB_C_BUILD_TIMESTAMP 1730732925
|
#define LIB_C_BUILD_TIMESTAMP 1730754533
|
||||||
|
|
||||||
#endif // INCLUDE_LIB_C_VERSION_H_
|
#endif // INCLUDE_LIB_C_VERSION_H_
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user