Skip to content

Instantly share code, notes, and snippets.

@RiscInside
Created July 12, 2020 18:16
Show Gist options
  • Save RiscInside/43ec03b296922bd6f7e5f7fcc1becf4a to your computer and use it in GitHub Desktop.
Save RiscInside/43ec03b296922bd6f7e5f7fcc1becf4a to your computer and use it in GitHub Desktop.
#include <amd64/gdt.h>
#include <amd64/tss.h>
#include <memory/bdalloc.h>
#include <smp/percpu.h>
#define GDT_ENTRIES 7
struct gdt {
uint64_t entries[GDT_ENTRIES];
struct gdt_pointer {
uint16_t limit;
uint64_t base;
} PACKED pointer;
};
extern void gdt_load(struct gdt_pointer *pointer);
void gdt_init(void) {
struct gdt *gdt = bdalloc_new(sizeof(struct gdt));
assert(gdt != NULL, "[gdt] Panic: Failed to allocated GDT\n");
gdt->entries[0] = 0;
gdt->entries[1] = (1LLU << 44) | (1LLU << 47) | (1LLU << 41LLU) |
(1LLU << 43) | (1LLU << 53);
gdt->entries[2] = (1LLU << 44) | (1LLU << 47) | (1LLU << 41LLU);
gdt->entries[3] = (1LLU << 44) | (1LLU << 47) | (1LLU << 41LLU) |
(1LLU << 43) | (1LLU << 53) | (1LLU << 46) |
(1LLU << 45);
gdt->entries[4] = (1LLU << 44) | (1LLU << 47) | (1LLU << 41LLU) |
(1LLU << 46) | (1LLU << 45);
uint64_t tss_base = (uint64_t)(percpu_get()->tss);
gdt->entries[5] = ((sizeof(struct tss_layout) - 1) & 0xffff) |
((tss_base & 0xffffff) << 16) | (0b1001LLU << 40) |
(1LLU << 47) | (((tss_base >> 24) & 0xff) << 56);
gdt->entries[6] = tss_base >> 32;
gdt->pointer.base = (uint64_t)(&(gdt->entries));
gdt->pointer.limit = 8 * GDT_ENTRIES - 1;
gdt_load(&(gdt->pointer));
}
#ifndef __GDT_H_INCLUDED__
#define __GDT_H_INCLUDED__
#include <utils.h>
void gdt_init(void);
#endif
#include <amd64/idt.h>
#include <memory/bdalloc.h>
#include <smp/percpu.h>
struct idt_entry {
uint16_t addr_low;
uint16_t selector;
uint8_t ist : 3;
uint8_t zeroed1 : 5;
bool ints_enabled : 1;
uint8_t ones1 : 3;
uint8_t zeroed2 : 1;
uint8_t dpl : 2;
uint8_t present : 1;
uint16_t addr_middle;
uint32_t addr_high;
uint32_t zeroed3;
} PACKED;
struct idt_pointer {
uint16_t limit;
uint64_t base;
} PACKED;
struct idt {
struct idt_entry entries[256];
struct idt_pointer pointer;
};
extern void idt_load(struct idt_pointer *pointer);
void idt_handler(void) {
panic("Panic: Unhandled interrupt!!!");
}
void idt_init(void) {
struct idt *idt = (struct idt *)bdalloc_new(sizeof(struct idt));
assert(idt != NULL, "[idt] Panic: Failed to allocate IDT\n");
memset(&(idt->entries), sizeof(idt->entries), 0);
idt->pointer.base = (uint64_t)(&idt);
idt->pointer.limit = 0x1000;
idt_load(&(idt->pointer));
printf("IDT at %p\n", &(idt->pointer));
percpu_get()->idt = idt;
for (uint64_t i = 0; i < 256; ++i) {
idt_set_gate(i, (uint64_t)idt_handler, 0, false);
}
}
void idt_set_gate(uint8_t index, uint64_t addr, uint8_t dpl, bool enable_ints) {
struct idt *idt = percpu_get()->idt;
struct idt_entry *entries = idt->entries;
entries[index].addr_low = (uint16_t)addr;
entries[index].addr_middle = (uint16_t)(addr >> 16);
entries[index].addr_high = (uint64_t)(addr >> 32);
entries[index].zeroed1 = 0;
entries[index].zeroed2 = 0;
entries[index].zeroed3 = 0;
entries[index].ints_enabled = enable_ints;
entries[index].ist = 0;
entries[index].dpl = dpl;
entries[index].ones1 = 0b111;
entries[index].selector = 0x8;
entries[index].present = true;
}
#ifndef __IDT_H_INCLUDED__
#define __IDT_H_INLCUDED__
#include <utils.h>
void idt_init(void);
void idt_set_gate(uint8_t vec, uint64_t addr, uint8_t dpl, bool enable_ints);
#endif
#include <amd64/gdt.h>
#include <amd64/idt.h>
#include <amd64/tss.h>
#include <drivers/lapic.h>
#include <smp/percpu.h>
#include <smp/smp.h>
#include <spinlock.h>
#include <utils.h>
atomic_ulong cpu_count;
void smpmain() {
lapic_core_init();
atomic_fetch_add(&cpu_count, 1);
while (atomic_load(&cpu_count) != smp_get_cpu_count()) {
asm("pause");
}
percpu_storage_init();
idt_init();
tss_init();
gdt_init();
tss_load();
printf("Started CPU %llu\n", percpu_get()->id);
asm("int $80");
while (true)
;
}
#include <amd64/tss.h>
#include <memory/bdalloc.h>
#include <smp/percpu.h>
#include <utils.h>
void tss_init() {
struct tss_layout *tss = bdalloc_new(sizeof(struct tss_layout));
assert(tss != NULL, "[tss] Panic: Failed to allocate TSS\n");
memset(tss, sizeof(struct tss_layout), 0);
tss->iopb = sizeof(struct tss_layout);
// hack to get stack used by cpu
int val;
tss->rsp[0] = ALIGN_UP((uint64_t)(&val), 0x10000);
}
#ifndef __TSS_H_INCLUDED__
#define __TSS_H_INCLUDED__
#include <utils.h>
struct tss_layout {
uint32_t : 32;
uint64_t rsp[3];
uint64_t : 64;
uint64_t ist[7];
uint64_t : 64;
uint16_t : 16;
uint16_t iopb;
} PACKED;
void tss_init(void);
void tss_load(void);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment