Browse Source

TSS and other things

master
Mathieu Serandour 1 year ago
parent
commit
d8df3c89e7
  1. 4
      Makefile
  2. 5
      kernel/acpi/acpi.c
  3. 6
      kernel/cpuid.s
  4. 5
      kernel/debug/assert.h
  5. 5
      kernel/drivers/pcie.c
  6. 9
      kernel/drivers/pcie.h
  7. 223
      kernel/entry.c
  8. 2
      kernel/int/isr.c
  9. 44
      kernel/memory/gdt.c
  10. 5
      kernel/regs.s

4
Makefile

@ -8,8 +8,8 @@ USED_LOOPBACK := /dev/loop6
LIMINE_INSTALL := ./limine-bootloader/limine-install-linux-x86_64
QEMU_PATH := "/mnt/d/Program Files/qemu/qemu-system-x86_64.exe"
QEMU_ARGS := -monitor stdio -bios "d:/Program Files/qemu/bios/OVMF.fd" -m 256 -vga std -no-reboot
QEMU_PATH := kvm
QEMU_ARGS := -monitor stdio -bios /usr/share/ovmf/OVMF.fd -m 256 -vga std -no-reboot
# -bios "d:/Program Files/qemu/bios/OVMF.fd"
run: all

5
kernel/acpi/acpi.c

@ -26,7 +26,7 @@ static bool __ATTR_PURE__ checksum(const void* table, size_t size) {
static void parse_madt(const struct MADT* table);
static void parse_fadt(const struct ACPISDTHeader* table);
static void parse_pcie(const struct PCIETable* table);
void read_acpi_tables(const void* rsdp_location) {
@ -65,7 +65,7 @@ void read_acpi_tables(const void* rsdp_location) {
fadt_parsed = true;
break;
case PCIE_SIGNATURE:
parse_pcie(table);
parse_pcie((const struct PCIETable *)table);
pcie_parsed = true;
break;
default:
@ -77,6 +77,7 @@ void read_acpi_tables(const void* rsdp_location) {
asm volatile("hlt");
assert(madt_parsed);
assert(fadt_parsed);
assert(pcie_parsed);
}
static void parse_madt(const struct MADT* table) {

6
kernel/cpuid.s

@ -8,8 +8,8 @@
; void cpuid(uint32_t eax, struct cpuid_regs* out_regs);
cpuid:
push ebp
mov ebp, esp
push rbp
mov rbp, rsp
push rbx
mov eax, edi
@ -22,5 +22,5 @@ cpuid:
pop rbx
leave
leave
ret

5
kernel/debug/assert.h

@ -12,5 +12,8 @@ void __assert(const char* __restrict__ expression,
#endif
#define static_assert(EX) _Static_assert(EX, "static assert failed")
#define static_assert(EX) _Static_assert(EX, #EX)
#define static_assert_equals(EX1,EX2) _Static_assert(EX1==EX2, #EX1 " != " #EX2)

5
kernel/drivers/pcie.c

@ -1,4 +1,5 @@
#define PCIE_C
#include "pcie.h"
// @TODO
struct PCIE_Descriptor pcie_descriptor = {0, {0}};

9
kernel/drivers/pcie.h

@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
struct PCIE_config_space_descriptor {
void* address; // Base address
@ -22,8 +22,7 @@ struct PCIE_Descriptor {
};
#ifndef PCIE_C
// defined in pcie.c
extern struct PCIE_Descriptor pcie_descriptor;
#else
struct PCIE_Descriptor pcie_descriptor = {0, {0}};
#endif//PCIE_C

223
kernel/entry.c

@ -1,223 +0,0 @@
#include <stivale2.h>
#include <stddef.h>
#include <stdint.h>
#include "memory/gdt.h"
#include "video/video.h"
#include "klib/sprintf.h"
#include "klib/string.h"
#include "video/terminal.h"
#include "acpi/acpi.h"
#include "common.h"
#include "regs.h"
#include "int/apic.h"
#include "int/idt.h"
// 8K stack
static uint8_t stack[8192] __align(16);
static struct stivale2_header_tag_terminal terminal_hdr_tag = {
// All tags need to begin with an identifier and a pointer to the next tag.
.tag = {
// Identification constant defined in stivale2.h and the specification.
.identifier = STIVALE2_HEADER_TAG_TERMINAL_ID,
// If next is 0, it marks the end of the linked list of header tags.
.next = 0
},
// The terminal header tag possesses a flags field, leave it as 0 for now
// as it is unused.
.flags = 0
};
// We are now going to define a framebuffer header tag, which is mandatory when
// using the stivale2 terminal.
// This tag tells the bootloader that we want a graphical framebuffer instead
// of a CGA-compatible text mode. Omitting this tag will make the bootloader
// default to text mode, if available.
static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = {
// Same as above.
.tag = {
.identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
// Instead of 0, we now point to the previous header tag. The order in
// which header tags are linked does not matter.
.next = (uint64_t)&terminal_hdr_tag
},
// We set all the framebuffer specifics to 0 as we want the bootloader
// to pick the best it can.
.framebuffer_width = 1152,
.framebuffer_height = 864,
.framebuffer_bpp = 32
};
// The stivale2 specification says we need to define a "header structure".
// This structure needs to reside in the .stivale2hdr ELF section in order
// for the bootloader to find it. We use this __attribute__ directive to
// tell the compiler to put the following structure in said section.
__attribute__((section(".stivale2hdr"), used))
static struct stivale2_header stivale_hdr = {
// The entry_point member is used to specify an alternative entry
// point that the bootloader should jump to instead of the executable's
// ELF entry point. We do not care about that so we leave it zeroed.
.entry_point = 0,
// Let's tell the bootloader where our stack is.
// We need to add the sizeof(stack) since in x86(_64) the stack grows
// downwards.
.stack = (uintptr_t)stack + sizeof(stack),
// Bit 1, if set, causes the bootloader to return to us pointers in the
// higher half, which we likely want.
.flags = (1 << 1),
// This header structure is the root of the linked list of header tags and
// points to the first one in the linked list.
.tags = (uintptr_t)&framebuffer_hdr_tag
};
// We will now write a helper function which will allow us to scan for tags
// that we want FROM the bootloader (structure tags).
void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) {
struct stivale2_tag *current_tag = (void *)stivale2_struct->tags;
for (;;) {
// If the tag pointer is NULL (end of linked list), we did not find
// the tag. Return NULL to signal this.
if (current_tag == NULL) {
return NULL;
}
// Check whether the identifier matches. If it does, return a pointer
// to the matching tag.
if (current_tag->identifier == id) {
return current_tag;
}
// Get a pointer to the next tag in the linked list and repeat.
current_tag = (void *)current_tag->next;
}
}
#define PRINT_VAL(v) kprintf(#v "=%ld\n", (uint64_t)v);
#define PRINT_HEX(v) kprintf(#v "=%lx\n", (uint64_t)v);
// const char but represents a big string
extern const char _binary_bootmessage_txt;
// print all chars
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
static void debug_terminal() {
char buff[256];
for(int i = 0; i < 256; i++)
buff[i] = i+1;
kputs(buff);
}
static void print_fb_infos(struct stivale2_struct_tag_framebuffer* fbtag) {
PRINT_VAL(fbtag->framebuffer_width);
PRINT_VAL(fbtag->framebuffer_height);
PRINT_VAL(fbtag->framebuffer_pitch);
PRINT_VAL(fbtag->framebuffer_bpp);
PRINT_HEX(fbtag->framebuffer_addr);
}
#pragma GCC diagnostic pop
// Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling functio
// The following will be our kernel's entry point.
void _start(struct stivale2_struct *stivale2_struct) {
// Let's get the terminal structure tag from the bootloader.
struct stivale2_struct_tag_terminal *term_str_tag;
term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
// Check if the tag was actually found.
if (term_str_tag == NULL) {
// It wasn't found, just hang...
for (;;) {
asm volatile("hlt");
}
__builtin_unreachable();
}
// Let's get the address of the terminal write function.
void *term_write_ptr = (void *)term_str_tag->term_write;
set_terminal_handler(term_write_ptr);
struct stivale2_struct_tag_framebuffer fbtag;
struct stivale2_struct_tag_framebuffer* _fbtag = stivale2_get_tag(stivale2_struct,0x506461d2950408fa);
memcpy(&fbtag, _fbtag, sizeof(fbtag));
struct stivale2_struct_tag_rsdp* rsdp_tag_ptr = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_RSDP_ID);
assert(rsdp_tag_ptr != NULL);
uint64_t rsdp_location = rsdp_tag_ptr->rsdp;
Image sc = {.w = fbtag.framebuffer_width,
.h = fbtag.framebuffer_height,
.pitch= fbtag.framebuffer_pitch,
.bpp = fbtag.framebuffer_bpp,
.pix = (void*)fbtag.framebuffer_addr};
init_gdt_table();
initVideo(&sc);
setup_terminal();
setup_isr();
terminal_set_colors(0xf0f0f0, 0x007000);
terminal_clear();
kputs(&_binary_bootmessage_txt);
read_acpi_tables((void*)rsdp_location);
kputs("DONE\n");
apic_setup_clock();
for(;;) {
asm volatile("hlt");
kprintf("%lu\t", clock());
}
for(;;) {
asm volatile ("hlt");
}
__builtin_unreachable();
//*ptr = 0xfffa24821;
asm volatile ("sti");
asm volatile ("hlt");
for(size_t i = 0; i < fbtag.framebuffer_height; i++) {
uint8_t* base = (uint8_t*)fbtag.framebuffer_addr + fbtag.framebuffer_pitch*i;
for(size_t j = 0; j < fbtag.framebuffer_width; j++) {
uint32_t* px = (uint32_t*)&base[4*j];
*px = 0xffffff00;
}
}
//*(uint64_t*)(term_write_ptr) = 0xfeac;
//print_fun(buf, 2);
// kprintf("Bincows beta");
// We're done, just hang...
for (;;) {
asm ("hlt");
}
}

2
kernel/int/isr.c

@ -36,6 +36,7 @@ __attribute__((interrupt)) void ISR_general_handler(struct IFrame* interrupt_fra
}
__attribute__((interrupt)) void ISR_error_handler(struct IFrame* interrupt_frame, uint64_t error_code) {
(void) error_code;
kprintf("ERROR CODE: %lu\n", error_code);
panic_handler("ISR_error_handler", interrupt_frame);
}
__attribute__((interrupt)) void ISR_div_by_zero_handler(struct IFrame* interrupt_frame) {
@ -86,6 +87,7 @@ __attribute__((interrupt)) void ISR_stack_segment_fault_handler(struct IFrame* i
}
__attribute__((interrupt)) void ISR_general_protection_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) {
(void) error_code;
kprintf("ERROR CODE: %lu\n", error_code);
panic_handler("ISR_general_protection_fault_handler", interrupt_frame);
}
__attribute__((interrupt)) void ISR_page_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) {

44
kernel/memory/gdt.c

@ -3,9 +3,25 @@
#include "../klib/sprintf.h"
#include "../debug/assert.h"
/*
typedef GDTentryAccessByte
*/
extern void _ltr(uint16_t tss_selector);
// kernel stack
extern const uint8_t stack[];
struct TSS {
uint32_t reserved0;
uint64_t RSP[3]; // The full 64-bit canonical forms of the stack pointers (RSP) for privilege levels 0-2
uint64_t reserved1;
uint64_t IST[7]; // The full 64-bit canonical forms of the interrupt stack table (IST) pointers.
uint64_t reserved2;
uint16_t reserved3;
uint16_t IOPB_offset; // just put the size of the structure
} __attribute__((packed));
static_assert_equals(sizeof(struct TSS), 104);
const struct TSS tss = {0, {(uint64_t)stack,0,0}, 0, {0}, 0,0,sizeof(struct TSS)};
struct GDTentry {
u16 limit1; // x86_64: ignrored
@ -58,12 +74,12 @@ static struct GDTentry gdt[] = {
{0,0,0, 0,0,0,1,1,3,1, 0, 0,1,0,1, 0}, // user code segment
{0,0,0, 0,1,0,0,1,3,1, 0, 0,0,1,1, 0}, // user data segment
{0,0,0, 0,1,0,0,1,3,1, 0, 0,0,1,1, 0}, // user data segment
/// 98a0
// 92a0
// gcc is SO dumb we have to fill the struct by software
{0,0,0, 1,0,0,1,0,0,1, 0, 1,0,0,0, 0}, // TSS segment1
{0,0,0, 0,0,0,0,0,0,0, 0, 0,0,0,0, 0}, // TSS segment2
};
static_assert(sizeof(gdt) == 6 * sizeof(struct GDTentry));
static_assert(sizeof(gdt) == 7 * sizeof(struct GDTentry));
// from gdt.s
void _lgdt(void* gdt_desc_ptr);
@ -80,6 +96,20 @@ struct GDTDescriptor gdt_descriptor = {
volatile int y = 5421;
void init_gdt_table() {
// init GDT TSS entry
gdt[5].base1 = (uint64_t)&tss & 0xfffflu;
gdt[5].base2 = (uint64_t)&tss >> 16 & 0x00ffllu;
gdt[5].base3 = (uint64_t)&tss >> 24 & 0x00ffllu;
*(uint64_t *)(&gdt[6]) = (uint64_t)(&tss) >> 32;
kprintf("0x%16lx = 0x%2x %2x %4x\n", &tss, gdt[5].base3, gdt[5].base2, gdt[5].base1);
_lgdt(&gdt_descriptor);
// the TSS offset in the GDT table << 3 (the first 3 bits are DPL)
_ltr(0x28);
}

5
kernel/regs.s

@ -8,6 +8,7 @@
[global outb]
[global get_rflags]
[global set_rflags]
[global _ltr]
section .text
@ -53,6 +54,10 @@ set_rflags:
popfq
ret
; void _ltr(uint16_t tss_selector)
_ltr:
ltr di
ret
; uint8_t inb(port)
inb:

Loading…
Cancel
Save