enter user mode

main
Clyne 3 weeks ago
parent c7066d2950
commit 6da213d840
Signed by: clyne
GPG Key ID: 1B74EE6C49C96795

@ -39,5 +39,5 @@ clean:
run: myos.iso
@echo " QEMU"
@qemu-system-i386 -drive file=$<,index=2,media=cdrom -monitor stdio -no-reboot #-s -S #-d int
@qemu-system-i386 -drive file=$<,index=2,media=cdrom -monitor stdio -no-reboot -s -S #-d int

@ -19,7 +19,21 @@ struct gdt_entry_bits {
std::uint32_t base_high : 8;
} __attribute__((packed));
constinit static const std::array<gdt_entry_bits, 3> gdt {{
struct TSSEntry
{
std::uint32_t prevTSS;
std::uint32_t esp0;
std::uint32_t ss0;
std::uint32_t unused[23];
} __attribute__((packed));
static TSSEntry tss = {
.prevTSS = 0,
.esp0 = 0,
.ss0 = 0x10
};
static const std::array<gdt_entry_bits, 6> gdt {{
{},
/* kernel_code = */ {
.limit_low = 0xFFFF,
@ -54,6 +68,57 @@ constinit static const std::array<gdt_entry_bits, 3> gdt {{
.big = 1,
.gran = 1,
.base_high = 0x00
},
/* user_code = */ {
.limit_low = 0xFFFF,
.base_low = 0x0000,
.accessed = 0,
.read_write = 1,
.conforming_expand_down = 0,
.code = 1,
.code_data_segment = 1,
.DPL = 3,
.present = 1,
.limit_high = 0xF,
.available = 0,
.long_mode = 0,
.big = 1,
.gran = 1,
.base_high = 0x00
},
/* user_data = */ {
.limit_low = 0xFFFF,
.base_low = 0x0000,
.accessed = 0,
.read_write = 1,
.conforming_expand_down = 0,
.code = 0,
.code_data_segment = 1,
.DPL = 3,
.present = 1,
.limit_high = 0xF,
.available = 0,
.long_mode = 0,
.big = 1,
.gran = 1,
.base_high = 0x00
},
/* tss = */ {
.limit_low = sizeof(TSSEntry),
.base_low = (std::uint32_t)&tss & 0xFFFFFF,
.accessed = 1,
.read_write = 0,
.conforming_expand_down = 0,
.code = 1,
.code_data_segment = 0,
.DPL = 0,
.present = 1,
.limit_high = 0,
.available = 0,
.long_mode = 0,
.big = 0,
.gran = 0,
.base_high = (std::uint32_t)&tss >> 24
}
}};
@ -76,6 +141,29 @@ void gdt_initialize()
mov %%eax, %%fs
mov %%eax, %%gs
mov %%eax, %%ss
mov $0x28, %%ax
ltr %%ax
)" :: "m"(gdtr));
}
void enter_user_mode(void (*func)())
{
asm volatile("mov %%esp, %0" : "=r" (tss.esp0));
asm volatile(R"(
mov $0x23, %%ax
mov %%ax, %%ds
mov %%ax, %%es
mov %%ax, %%fs
mov %%ax, %%gs
mov %%esp, %%eax
push $0x23
push %%esp
pushf
push $0x1b
push %0
iret
)" :: "b"(func));
}

@ -2,6 +2,7 @@
#define GDT_HPP
void gdt_initialize();
void enter_user_mode(void (*func)());
#endif // GDT_HPP

@ -8,6 +8,8 @@
extern TextOutput& term;
static constexpr unsigned InterruptCount = 49;
static constexpr std::uint8_t TaskGate = 0x5;
static constexpr std::uint8_t IntrGate16 = 0x6;
static constexpr std::uint8_t TrapGate16 = 0x7;
@ -25,7 +27,7 @@ struct idt_entry_bits {
std::uint32_t offset_high : 16;
} __attribute__((packed));
static std::array<Callback, 48> callbacks;
static std::array<Callback, InterruptCount> callbacks;
extern "C"
void interruptGeneralHandler(Registers regs)
@ -91,10 +93,12 @@ struct StubEntry
static auto idt =
[]<std::size_t... ints>(std::index_sequence<ints...>) {
return std::array<idt_entry_bits, 256> { StubEntry<ints>()... };
}(std::make_index_sequence<48>{});
}(std::make_index_sequence<InterruptCount>{});
void idt_initialize()
{
idt[0x28].dpl = 3;
auto idtr = reinterpret_cast<std::uint64_t>(idt.data());
idtr <<= 16;
idtr |= idt.size() * sizeof(idt[0]);

@ -67,6 +67,16 @@ void kernel_main(void)
ata_probe(bus1, ATA::Master, "1:0");
ata_probe(bus1, ATA::Slave, "1:1");
idt_register_callback(0x28, [](auto& regs) {
term.write(static_cast<char>(regs.eax));
});
term.write("Entering user mode...\n");
enter_user_mode([] {
asm volatile("int $0x28" :: "a" ('Z'));
for (;;);
});
for (;;) {
const auto ch = keyboard_read();
if (ch)

@ -8,7 +8,7 @@ struct PageDirectory
static constexpr std::uint32_t NotPresent = 0x2;
PageDirectory(): value(NotPresent) {}
PageDirectory(void *addr): value(reinterpret_cast<std::uint32_t>(addr) | 3) {}
PageDirectory(void *addr): value(reinterpret_cast<std::uint32_t>(addr) | 7) {}
std::uint32_t value;
};
@ -39,7 +39,7 @@ void memory_initialize()
std::uint32_t addr = 0;
for (auto& p : pageTable) {
p = addr | 3; // supervisor, r/w, present
p = addr | 7; // supervisor, r/w, present
addr += 0x1000;
}

Loading…
Cancel
Save