Skip to content

Commit

Permalink
wtorek
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Kościelnicki committed Jun 5, 2018
1 parent 74c578d commit 41b4dc3
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/kernel
/loader
*.o
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
all: kernel loader

OBJS := main.o
OBJS := main.o gdt.o page.o

kernel: kernel.lds kernel.o $(OBJS)
ld -Tkernel.lds kernel.o -o kernel $(OBJS)
Expand All @@ -15,4 +15,4 @@ loader.o: loader.s kernel
gcc -m32 loader.s -c -o loader.o

%.o: %.c
clang $< -o $@ -c -ffreestanding -O3 -Wall
clang $< -o $@ -c -ffreestanding -O3 -Wall --target=x86_64-unknown -mcmodel=large -mno-mmx -mno-sse
89 changes: 89 additions & 0 deletions gdt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <stdint.h>
#include "gdt.h"

extern void stack;

struct tss {
uint32_t _pad;
uint64_t rsp[3];
uint64_t _pad2;
uint64_t ist_rsp[7];
uint32_t _pad3[3];
} __attribute__((packed)) tss = {
.rsp[0] = &stack,
};

_Static_assert(sizeof tss == 0x68, "meh");

struct gdt_entry {
uint16_t limit_lo;
uint16_t base_lo;
uint8_t base_mid;
uint8_t flags_a;
uint8_t flags_b;
uint8_t base_hi;
} gdt[] = {
// 0
{ 0 },
// 8: kernel code
{ 0, 0, 0, 0x9b, 0xa0, 0 },
// 0x10: user code 32-bit
{ 0xffff, 0, 0, 0xfb, 0xcf, 0 },
// 0x18: user data
{ 0xffff, 0, 0, 0xf3, 0xcf, 0 },
// 0x20: user code 64-bit
{ 0, 0, 0, 0xfb, 0xa0, 0 },
// 0x28: TSS
{ sizeof tss - 1, 0, 0, 0x89, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
};

struct idt_entry {
uint16_t addr_lo;
uint16_t segment;
uint8_t ist;
uint8_t flags;
uint16_t addr_mid;
uint32_t addr_hi;
uint32_t _pad;
} idt[256] = {
{0},
};

void init_gdt() {
uint64_t tss_addr = (uint64_t)&tss;
gdt[5].base_lo = tss_addr;
gdt[5].base_mid = tss_addr >> 16;
gdt[5].base_hi = tss_addr >> 24;
gdt[6].limit_lo = tss_addr >> 32;
gdt[6].base_lo = tss_addr >> 48;
struct gdtr {
uint16_t _pad[3];
uint16_t limit;
void *addr;
} gdtr = {
{0, 0, 0}, sizeof gdt - 1, &gdt,
};
struct idtr {
uint16_t _pad[3];
uint16_t limit;
void *addr;
} idtr = {
{0, 0, 0}, sizeof idt - 1, &idt,
};
__asm__ volatile (
"lgdt (%0)"
:
: "r"(&gdtr.limit)
);
__asm__ volatile (
"lidt (%0)"
:
: "r"(&idtr.limit)
);
__asm__ volatile (
"ltr %0"
:
: "r"((uint16_t)0x28)
);
}
1 change: 1 addition & 0 deletions gdt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void init_gdt();
1 change: 1 addition & 0 deletions kernel.s
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ hlt
.section .bss

.skip 0x1000
.global stack
stack:
24 changes: 23 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
#include <stdint.h>
#include "gdt.h"
#include "page.h"
char hello[] = "Hello, C world!";

__asm__(
".text\n"
"go_user:\n"
"pushq $0x1b\n"
"pushq $0\n"
"pushq $0x2\n"
"pushq $0x23\n"
"pushq %rdi\n"
"iretq\n"
);

_Noreturn void go_user(void *);

void main() {
init_gdt();
init_pg();
map_page(0x31337000, phys_alloc(), 7);
uint8_t *upage = (void *)0x31337000ull;
upage[0] = 0xeb;
upage[1] = 0xfe;
go_user(upage);
for (int i = 0; i < sizeof hello; i++) {
*(uint16_t *)(0xffff8000000b8000 + i * 2) = hello[i] | 0x0f00;
*(uint16_t *)(0x31337000 + i * 2) = hello[i] | 0x0f00;
}
}
43 changes: 43 additions & 0 deletions page.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "page.h"

extern void kbss_end;
uint64_t phys_next = (uint64_t)(&kbss_end - 0xffff800000000000ull);

uint64_t phys_alloc() {
if (phys_next & 0xfff) {
phys_next |= 0xfff;
phys_next++;
}
uint64_t res = phys_next;
phys_next += 0x1000;
return res;
}

void map_page(uint64_t virt, uint64_t phys, int flags) {
uint64_t p_ptl4 = read_cr3() & ~0xfffull;
uint64_t *v_ptl4 = P2V(p_ptl4);
int idx1 = virt >> 12 & 0x1ff;
int idx2 = virt >> 21 & 0x1ff;
int idx3 = virt >> 30 & 0x1ff;
int idx4 = virt >> 39 & 0x1ff;
if (!v_ptl4[idx4])
v_ptl4[idx4] = phys_alloc() | 7;
uint64_t p_ptl3 = v_ptl4[idx4] & ~0xfffull;
uint64_t *v_ptl3 = P2V(p_ptl3);
if (!v_ptl3[idx3])
v_ptl3[idx3] = phys_alloc() | 7;
uint64_t p_ptl2 = v_ptl3[idx3] & ~0xfffull;
uint64_t *v_ptl2 = P2V(p_ptl2);
if (!v_ptl2[idx2])
v_ptl2[idx2] = phys_alloc() | 7;
uint64_t p_ptl1 = v_ptl2[idx2] & ~0xfffull;
uint64_t *v_ptl1 = P2V(p_ptl1);
v_ptl1[idx1] = phys | flags;
}

void init_pg() {
uint64_t p_ptl4 = read_cr3() & ~0xfffull;
uint64_t *v_ptl4 = P2V(p_ptl4);
v_ptl4[0] = 0;
write_cr3(read_cr3());
}
27 changes: 27 additions & 0 deletions page.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <stdint.h>

static inline void *P2V(uint64_t p) {
return (void *)(0xffff800000000000ull + p);
}

static inline uint64_t read_cr3() {
uint64_t res;
__asm__ volatile(
"movq %%cr3, %0"
: "=r"(res)
:
);
return res;
}

static inline void write_cr3(uint64_t val) {
__asm__ volatile(
"movq %0, %%cr3"
:
: "r"(val)
);
}

uint64_t phys_alloc();
void init_pg();
void map_page(uint64_t virt, uint64_t phys, int flags);

0 comments on commit 41b4dc3

Please sign in to comment.