os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 3004d69ec284a47f85170027284c5efada78839f
parent cc8fe1a7405f48e3ca08f6559c01b4b305cc7db5
Author: erai <erai@omiltem.net>
Date:   Tue,  2 Apr 2024 01:18:39 -0400

task switching

Diffstat:
Mas.c | 16+++++++++-------
Mcc1.c | 337+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mkernel.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 442 insertions(+), 9 deletions(-)

diff --git a/as.c b/as.c @@ -69,7 +69,8 @@ enum { OP_LLDM = 0x020f00, OP_LTRM = 0x030f00, - OP_MOVSRM = 0x8e, + OP_WRSR = 0x8e, + OP_RDSR = 0x8c, OP_RET = 0xc3, OP_CALL = 0xe8, @@ -78,6 +79,7 @@ enum { OP_SETCC = 0x0f90, OP_PUSHF = 0x9c, + OP_POPF = 0x9d, OP_IRET = 0xcf, OP_IRETQ = 0x48cf, OP_WRMSR = 0x0f30, @@ -369,7 +371,7 @@ emit_kstart(c: *assembler) { as_jmp(c, OP_JCC + CC_NE, hang); // Setup an early stack - as_modri(c, OP_MOVI, R_RSP, 0x00200000); + as_modri(c, OP_MOVI, R_RSP, 0x00200000); // FIXME bss // Align stack to page as_modri(c, OP_ANDI, R_RSP, -0x1000); @@ -471,11 +473,11 @@ emit_kstart(c: *assembler) { // Reload segments as_modri(c, OP_MOVI, R_RAX, 16); - as_modrr(c, OP_MOVSRM, R_ES, R_RAX); - as_modrr(c, OP_MOVSRM, R_DS, R_RAX); - as_modrr(c, OP_MOVSRM, R_FS, R_RAX); - as_modrr(c, OP_MOVSRM, R_GS, R_RAX); - as_modrr(c, OP_MOVSRM, R_SS, R_RAX); + as_modrr(c, OP_WRSR, R_ES, R_RAX); + as_modrr(c, OP_WRSR, R_DS, R_RAX); + as_modrr(c, OP_WRSR, R_FS, R_RAX); + as_modrr(c, OP_WRSR, R_GS, R_RAX); + as_modrr(c, OP_WRSR, R_SS, R_RAX); as_modrr(c, OP_MOVE, R_RSP, R_RSP); // Reload stack in the top half diff --git a/cc1.c b/cc1.c @@ -1343,6 +1343,343 @@ main(argc: int, argv: **byte, envp: **byte) { emit_ret(c.as); } + d = find(c, "ud2", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_op(c.as, OP_UD2); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "cpuid", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 16); + as_modrm(c.as, OP_LOAD, R_RAX, R_RDI, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 24); + as_modrm(c.as, OP_LOAD, R_RCX, R_RDI, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 32); + as_modrm(c.as, OP_LOAD, R_RDX, R_RDI, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 40); + as_modrm(c.as, OP_LOAD, R_RBX, R_RDI, 0, 0, 0); + as_op(c.as, OP_CPUID); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 16); + as_modrm(c.as, OP_STORE, R_RAX, R_RDI, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 24); + as_modrm(c.as, OP_STORE, R_RCX, R_RDI, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 32); + as_modrm(c.as, OP_STORE, R_RDX, R_RDI, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 40); + as_modrm(c.as, OP_STORE, R_RBX, R_RDI, 0, 0, 0); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "inb", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); + as_op(c.as, OP_IN); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "outb", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); + as_op(c.as, OP_OUT); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "rdmsr", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); + as_op(c.as, OP_RDMSR); + as_modri(c.as, OP_MOVI, R_RCX, 32); + as_modr(c.as, OP_SHLM, R_RDX); + as_modrr(c.as, OP_ORRM, R_RAX, R_RDX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "wrmsr", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); + as_modrr(c.as, OP_MOVE, R_RDX, R_RAX); + as_modri(c.as, OP_MOVI, R_RCX, 32); + as_modr(c.as, OP_SHRM, R_RDX); + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); + as_op(c.as, OP_WRMSR); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "rdcr0", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrr(c.as, OP_RDCRR, R_CR0, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "wrcr0", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); + as_modrr(c.as, OP_WRCRR, R_CR0, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "rdcr2", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrr(c.as, OP_RDCRR, R_CR2, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "wrcr2", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); + as_modrr(c.as, OP_WRCRR, R_CR2, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "rdcr3", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrr(c.as, OP_RDCRR, R_CR3, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "wrcr3", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); + as_modrr(c.as, OP_WRCRR, R_CR3, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "rdcr4", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrr(c.as, OP_RDCRR, R_CR4, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "wrcr4", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); + as_modrr(c.as, OP_WRCRR, R_CR4, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "lgdt", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_modm(c.as, OP_LGDTM, R_RAX, 0, 0, 0); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "lidt", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_modm(c.as, OP_LIDTM, R_RAX, 0, 0, 0); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "lldt", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_modr(c.as, OP_LLDTM, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "ltr", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_modr(c.as, OP_LTRM, R_RAX); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "hlt", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_op(c.as, OP_HLT); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "rdflags", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_op(c.as, OP_PUSHF); + emit_ret(c.as); + } + + d = find(c, "wrflags", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_op(c.as, OP_PUSHF); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_opr(c.as, OP_PUSHR, R_RAX); + as_op(c.as, OP_POPF); + emit_ret(c.as); + } + + d = find(c, "wbinvld", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_modm(c.as, OP_WBINVD, R_RAX, 0, 0, 0); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "invlpg", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); + as_modm(c.as, OP_INVLPGM, R_RAX, 0, 0, 0); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + + d = find(c, "taskswitch", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + + as_opr(c.as, OP_PUSHR, R_RBP); + as_op(c.as, OP_PUSHF); + + as_modrm(c.as, OP_LOAD, R_RBP, R_RSP, 0, 0, 24); + + // save + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 0); + as_modrm(c.as, OP_STORE, R_RCX, R_RBP, 0, 0, 8); + as_modrm(c.as, OP_STORE, R_RDX, R_RBP, 0, 0, 16); + as_modrm(c.as, OP_STORE, R_RBX, R_RBP, 0, 0, 24); + + // rsp + as_modrm(c.as, OP_LEA, R_RAX, R_RSP, 0, 0, 24); + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 32); + + // rbp + as_modrm(c.as, OP_LOAD, R_RAX, R_RSP, 0, 0, 8); + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 40); + + as_modrm(c.as, OP_STORE, R_RSI, R_RBP, 0, 0, 48); + as_modrm(c.as, OP_STORE, R_RDI, R_RBP, 0, 0, 56); + as_modrm(c.as, OP_STORE, R_R8, R_RBP, 0, 0, 64); + as_modrm(c.as, OP_STORE, R_R9, R_RBP, 0, 0, 72); + as_modrm(c.as, OP_STORE, R_R10, R_RBP, 0, 0, 80); + as_modrm(c.as, OP_STORE, R_R11, R_RBP, 0, 0, 88); + as_modrm(c.as, OP_STORE, R_R12, R_RBP, 0, 0, 96); + as_modrm(c.as, OP_STORE, R_R13, R_RBP, 0, 0, 104); + as_modrm(c.as, OP_STORE, R_R14, R_RBP, 0, 0, 112); + as_modrm(c.as, OP_STORE, R_R15, R_RBP, 0, 0, 120); + + // rip + as_modrm(c.as, OP_LOAD, R_RAX, R_RSP, 0, 0, 16); + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 128); + + // flags + as_modrm(c.as, OP_LOAD, R_RAX, R_RSP, 0, 0, 0); + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 136); + + // cs + as_modrr(c.as, OP_RDSR, R_CS, R_RAX); + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 144); + + // ss + as_modrr(c.as, OP_RDSR, R_SS, R_RAX); + as_modrm(c.as, OP_STORE, R_RAX, R_RBP, 0, 0, 152); + + as_modrm(c.as, OP_LOAD, R_RBP, R_RSP, 0, 0, 32); + + // restore + as_modrm(c.as, OP_LOAD, R_RCX, R_RBP, 0, 0, 8); + as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); + as_modrm(c.as, OP_LOAD, R_RBX, R_RBP, 0, 0, 24); + as_modrm(c.as, OP_LOAD, R_RSI, R_RBP, 0, 0, 48); + as_modrm(c.as, OP_LOAD, R_RDI, R_RBP, 0, 0, 56); + as_modrm(c.as, OP_LOAD, R_R8, R_RBP, 0, 0, 64); + as_modrm(c.as, OP_LOAD, R_R9, R_RBP, 0, 0, 72); + as_modrm(c.as, OP_LOAD, R_R10, R_RBP, 0, 0, 80); + as_modrm(c.as, OP_LOAD, R_R11, R_RBP, 0, 0, 88); + as_modrm(c.as, OP_LOAD, R_R12, R_RBP, 0, 0, 96); + as_modrm(c.as, OP_LOAD, R_R13, R_RBP, 0, 0, 104); + as_modrm(c.as, OP_LOAD, R_R14, R_RBP, 0, 0, 112); + as_modrm(c.as, OP_LOAD, R_R15, R_RBP, 0, 0, 120); + + // ss + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 152); + as_opr(c.as, OP_PUSHR, R_RAX); + // rsp + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 32); + as_opr(c.as, OP_PUSHR, R_RAX); + // flags + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 136); + as_opr(c.as, OP_PUSHR, R_RAX); + // cs + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 144); + as_opr(c.as, OP_PUSHR, R_RAX); + // rip + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 128); + as_opr(c.as, OP_PUSHR, R_RAX); + + // finish up restore + as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 0); + as_modrm(c.as, OP_LOAD, R_RBP, R_RBP, 0, 0, 40); + + // iretq + as_op(c.as, OP_IRETQ); + } + start = 0: *label; d = find(c, "_start", 0:*byte, 0); if (d && d.func_defined) { diff --git a/kernel.c b/kernel.c @@ -1,12 +1,106 @@ -// in out iretq rdmsr wrmsr wrcr rdcr lgdt lldt lidt ltr hlt cli sti syscall sysret wbinvld invlpg +ud2(); + +cpuid(a: *int, c: *int, d: *int, b: *int); + +inb(a: int): int; +outb(a: int, x: int); + +rdmsr(r: int): int; +wrmsr(r: int, x: int); + +rdcr0(): int; +wrcr0(x: int); +rdcr2(): int; +wrcr2(x: int); +rdcr3(): int; +wrcr3(x: int); +rdcr4(): int; +wrcr4(x: int); + +lgdt(gdtp: int); +lidt(idtp: int); +lldt(s: int); +ltr(s: int); + +hlt(); + +rdflags(): int; +wrflags(x: int); + +wbinvld(x: int); +invlpg(x: int); + +struct regs { + rax: int; // 0 + rcx: int; // 8 + rdx: int; // 16 + rbx: int; // 24 + rsp: int; // 32 + rbp: int; // 40 + rsi: int; // 48 + rdi: int; // 56 + r8: int; // 64 + r9: int; // 72 + r10: int; // 80 + r11: int; // 88 + r12: int; // 96 + r13: int; // 104 + r14: int; // 112 + r15: int; // 120 + rip: int; // 128 + rflags: int; // 136 + cs: int; // 144 + ss: int; // 152 +} + +taskswitch(save_regs: *regs, load_regs: *regs); _start() { + loop { + ud2(); + } } ru32(p: *byte): int { return p[0]:int + (p[1]:int << 8) + (p[2]:int << 16) + (p[3]:int << 24); } +bootstrap(a: *regs, b: *regs) { + a.r15 = 15; + taskswitch(b, a); + ud2(); +} + _kstart(mb: *byte) { - loop { } + var a: regs; + var b: regs; + + b.rax = 1; + b.rcx = 2; + b.rdx = 3; + b.rbx = 4; + b.rsp = (-0x8000 << 16) + 1024 * 1024 * 2 - 1024 * 32 - 24; + b.rbp = 0; + b.rsi = 7; + b.rdi = 8; + b.r8 = 9; + b.r9 = 10; + b.r10 = 11; + b.r11 = 12; + b.r12 = 13; + b.r13 = 14; + b.r14 = 15; + b.r15 = 16; + b.rip = bootstrap:int; + b.rflags = 0; + b.cs = 8; + b.ss = 16; + + (b.rsp:**regs)[1] = &a; + (b.rsp:**regs)[2] = &b; + + taskswitch(&a, &b); + loop { + hlt(); + } }