Rewrite pit_sleep_and_quit_on_keypress() to be fully in real mode to avoid issues with switching back and forth
This commit is contained in:
parent
8ef1e28e9d
commit
2fd36507a1
4
Makefile
4
Makefile
@ -17,7 +17,7 @@ echfs-test: all
|
||||
echfs-utils -g -p1 test.img import test/test.elf boot/test.elf
|
||||
echfs-utils -g -p1 test.img import test/qloader2.cfg qloader2.cfg
|
||||
./qloader2-install src/qloader2.bin test.img 2048
|
||||
qemu-system-x86_64 -hda test.img -monitor stdio
|
||||
qemu-system-x86_64 -hda test.img -debugcon stdio
|
||||
|
||||
ext2-test: all
|
||||
$(MAKE) -C test
|
||||
@ -38,4 +38,4 @@ ext2-test: all
|
||||
sudo losetup -d `cat loopback_dev`
|
||||
rm -rf test_image loopback_dev
|
||||
./qloader2-install src/qloader2.bin test.img 2048
|
||||
qemu-system-x86_64 -hda test.img -monitor stdio
|
||||
qemu-system-x86_64 -hda test.img -debugcon stdio
|
||||
|
BIN
qloader2.bin
BIN
qloader2.bin
Binary file not shown.
124
src/lib/blib.c
124
src/lib/blib.c
@ -5,7 +5,6 @@
|
||||
#include <lib/libc.h>
|
||||
#include <drivers/vga_textmode.h>
|
||||
#include <lib/real.h>
|
||||
#include <sys/interrupt.h>
|
||||
#include <lib/cio.h>
|
||||
|
||||
void panic(const char *str) {
|
||||
@ -50,26 +49,113 @@ void *balloc_aligned(size_t count, size_t alignment) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pit_sleep(uint64_t pit_ticks) {
|
||||
uint64_t target = global_pit_tick + pit_ticks;
|
||||
while (global_pit_tick < target) {
|
||||
asm volatile ("hlt");
|
||||
}
|
||||
__attribute__((used)) static uint32_t int_1c_ticks_counter;
|
||||
|
||||
__attribute__((used)) __attribute__((naked)) static void ivt_timer_isr(void) {
|
||||
asm (
|
||||
".code16\n\t"
|
||||
"pushf\n\t"
|
||||
"push bx\n\t"
|
||||
"mov ebx, dword ptr ds:[1f]\n\t"
|
||||
"inc dword ptr ds:[ebx]\n\t"
|
||||
"pop bx\n\t"
|
||||
"popf\n\t"
|
||||
"iret\n\t"
|
||||
".code32\n\t"
|
||||
"1: .long int_1c_ticks_counter\n\t"
|
||||
);
|
||||
}
|
||||
|
||||
int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks) {
|
||||
uint64_t target = global_pit_tick + pit_ticks;
|
||||
while (global_pit_tick < target) {
|
||||
struct rm_regs r = {0};
|
||||
r.eax = 0x0100;
|
||||
rm_int(0x16, &r, &r);
|
||||
if (!(r.eflags & EFLAGS_ZF)) {
|
||||
r.eax = 0x0000;
|
||||
rm_int(0x16, &r, &r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
// This is a dirty hack but we need to execute this full function in real mode
|
||||
__attribute__((naked)) int pit_sleep_and_quit_on_keypress(uint32_t ticks) {
|
||||
asm (
|
||||
// pit_ticks in edx
|
||||
"mov edx, dword ptr ss:[esp+4]\n\t"
|
||||
|
||||
"lea ecx, int_1c_ticks_counter\n\t"
|
||||
|
||||
// Make sure the ISR for int 0x1c is hooked
|
||||
"lea eax, ivt_timer_isr\n\t"
|
||||
"mov word ptr ds:[0x1c * 4], ax\n\t"
|
||||
"mov word ptr ds:[0x1c * 4 + 2], 0\n\t"
|
||||
|
||||
"mov dword ptr ds:[ecx], 0\n\t"
|
||||
|
||||
// Save non-scratch GPRs
|
||||
"push ebx\n\t"
|
||||
"push esi\n\t"
|
||||
"push edi\n\t"
|
||||
"push ebp\n\t"
|
||||
|
||||
// Jump to real mode
|
||||
"jmp 0x08:1f\n\t"
|
||||
"1: .code16\n\t"
|
||||
"mov ax, 0x10\n\t"
|
||||
"mov ds, ax\n\t"
|
||||
"mov es, ax\n\t"
|
||||
"mov fs, ax\n\t"
|
||||
"mov gs, ax\n\t"
|
||||
"mov ss, ax\n\t"
|
||||
"mov eax, cr0\n\t"
|
||||
"and al, 0xfe\n\t"
|
||||
"mov cr0, eax\n\t"
|
||||
"jmp 0:2f\n\t"
|
||||
"2:\n\t"
|
||||
"mov ax, 0\n\t"
|
||||
"mov ds, ax\n\t"
|
||||
"mov es, ax\n\t"
|
||||
"mov fs, ax\n\t"
|
||||
"mov gs, ax\n\t"
|
||||
"mov ss, ax\n\t"
|
||||
|
||||
"sti\n\t"
|
||||
|
||||
"10:\n\t"
|
||||
|
||||
"cmp dword ptr ds:[ecx], edx\n\t"
|
||||
"je 30f\n\t" // out on timeout
|
||||
|
||||
"mov ah, 0x01\n\t"
|
||||
"xor al, al\n\t"
|
||||
"int 0x16\n\t"
|
||||
|
||||
"jz 10b\n\t" // loop
|
||||
|
||||
// on keypress
|
||||
"xor ax, ax\n\t"
|
||||
"int 0x16\n\t"
|
||||
"mov eax, 1\n\t"
|
||||
"jmp 20f\n\t" // out
|
||||
|
||||
"30:\n\t" // out on timeout
|
||||
"xor eax, eax\n\t"
|
||||
|
||||
"20:\n\t"
|
||||
|
||||
"cli\n\t"
|
||||
|
||||
// Jump back to pmode
|
||||
"mov ebx, cr0\n\t"
|
||||
"or bl, 1\n\t"
|
||||
"mov cr0, ebx\n\t"
|
||||
"jmp 0x18:4f\n\t"
|
||||
"4: .code32\n\t"
|
||||
"mov bx, 0x20\n\t"
|
||||
"mov ds, bx\n\t"
|
||||
"mov es, bx\n\t"
|
||||
"mov fs, bx\n\t"
|
||||
"mov gs, bx\n\t"
|
||||
"mov ss, bx\n\t"
|
||||
|
||||
// Restore non-scratch GPRs
|
||||
"pop ebp\n\t"
|
||||
"pop edi\n\t"
|
||||
"pop esi\n\t"
|
||||
"pop ebx\n\t"
|
||||
|
||||
// Exit
|
||||
"ret\n\t"
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t strtoui(const char *s) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
void panic(const char *str);
|
||||
|
||||
void pit_sleep(uint64_t pit_ticks);
|
||||
int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks);
|
||||
int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks);
|
||||
|
||||
void brewind(size_t count);
|
||||
void *balloc(size_t count);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdint.h>
|
||||
#include <lib/real.h>
|
||||
|
||||
__attribute__((naked))
|
||||
@ -23,19 +24,6 @@ void rm_int(
|
||||
"push esi\n\t"
|
||||
"push edi\n\t"
|
||||
"push ebp\n\t"
|
||||
"pushf\n\t"
|
||||
|
||||
"cli\n\t"
|
||||
|
||||
"mov dx, 0x21\n\t"
|
||||
"mov al, byte ptr ds:[rm_pic0_mask]\n\t"
|
||||
"out dx, al\n\t"
|
||||
"mov dx, 0xa1\n\t"
|
||||
"mov al, byte ptr ds:[rm_pic1_mask]\n\t"
|
||||
"out dx, al\n\t"
|
||||
|
||||
"sidt [8f]\n\t"
|
||||
"lidt [9f]\n\t"
|
||||
|
||||
// Jump to real mode
|
||||
"jmp 0x08:1f\n\t"
|
||||
@ -106,17 +94,7 @@ void rm_int(
|
||||
"mov gs, ax\n\t"
|
||||
"mov ss, ax\n\t"
|
||||
|
||||
"mov dx, 0x21\n\t"
|
||||
"mov al, byte ptr ds:[pm_pic0_mask]\n\t"
|
||||
"out dx, al\n\t"
|
||||
"mov dx, 0xa1\n\t"
|
||||
"mov al, byte ptr ds:[pm_pic1_mask]\n\t"
|
||||
"out dx, al\n\t"
|
||||
|
||||
"lidt [8f]\n\t"
|
||||
|
||||
// Restore non-scratch GPRs
|
||||
"popf\n\t"
|
||||
"pop ebp\n\t"
|
||||
"pop edi\n\t"
|
||||
"pop esi\n\t"
|
||||
@ -131,11 +109,5 @@ void rm_int(
|
||||
"6: .long 0\n\t"
|
||||
// in_regs
|
||||
"7: .long 0\n\t"
|
||||
// pmode IDT
|
||||
"8: .short 0\n\t"
|
||||
" .long 0\n\t"
|
||||
// rmode IDT
|
||||
"9: .short 0x3ff\n\t"
|
||||
" .long 0\n\t"
|
||||
);
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ asm (
|
||||
#include <lib/part.h>
|
||||
#include <lib/config.h>
|
||||
#include <fs/file.h>
|
||||
#include <sys/interrupt.h>
|
||||
#include <lib/elf.h>
|
||||
#include <protos/stivale.h>
|
||||
#include <protos/linux.h>
|
||||
@ -93,8 +92,6 @@ void main(int boot_drive) {
|
||||
// Initial prompt.
|
||||
init_vga_textmode();
|
||||
|
||||
init_idt();
|
||||
|
||||
print("qloader2\n\n");
|
||||
|
||||
print("Boot drive: %x\n", boot_drive);
|
||||
@ -166,7 +163,9 @@ got_entry:
|
||||
panic("KERNEL_PROTO not specified");
|
||||
}
|
||||
|
||||
fopen(&f, drive, part, path);
|
||||
if (fopen(&f, drive, part, path)) {
|
||||
panic("Could not open kernel file");
|
||||
}
|
||||
|
||||
if (!strcmp(proto, "stivale")) {
|
||||
stivale_load(&f, cmdline);
|
||||
|
@ -103,15 +103,6 @@ void linux_load(struct file_handle *fd, char *cmdline) {
|
||||
"cli\n\t"
|
||||
"cld\n\t"
|
||||
|
||||
"mov dx, 0x21\n\t"
|
||||
"mov al, byte ptr ds:[rm_pic0_mask]\n\t"
|
||||
"out dx, al\n\t"
|
||||
"mov dx, 0xa1\n\t"
|
||||
"mov al, byte ptr ds:[rm_pic1_mask]\n\t"
|
||||
"out dx, al\n\t"
|
||||
|
||||
"lidt [3f]\n\t"
|
||||
|
||||
"jmp 0x08:1f\n\t"
|
||||
"1: .code16\n\t"
|
||||
"mov ax, 0x10\n\t"
|
||||
@ -136,10 +127,6 @@ void linux_load(struct file_handle *fd, char *cmdline) {
|
||||
"push cx\n\t"
|
||||
"push 0\n\t"
|
||||
"retf\n\t"
|
||||
|
||||
// rmode IDT
|
||||
"3: .short 0x3ff\n\t"
|
||||
" .long 0\n\t"
|
||||
:
|
||||
: "b" (real_mode_code_seg), "c" (kernel_entry_seg)
|
||||
);
|
||||
|
@ -1,102 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/interrupt.h>
|
||||
#include <lib/cio.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/real.h>
|
||||
|
||||
__attribute__((interrupt)) static void unhandled_int(void *r) {
|
||||
(void)r;
|
||||
panic("Unhandled interrupt");
|
||||
}
|
||||
|
||||
volatile uint64_t global_pit_tick = 0;
|
||||
|
||||
__attribute__((interrupt)) static void pit_irq(void *r) {
|
||||
(void)r;
|
||||
global_pit_tick++;
|
||||
port_out_b(0x20, 0x20);
|
||||
}
|
||||
|
||||
__attribute__((naked)) static void ivt_timer_isr(void) {
|
||||
asm (
|
||||
".code16\n\t"
|
||||
"pushf\n\t"
|
||||
"push bx\n\t"
|
||||
"mov ebx, dword ptr ds:[1f]\n\t"
|
||||
"inc dword ptr ds:[ebx]\n\t"
|
||||
"pop bx\n\t"
|
||||
"popf\n\t"
|
||||
"iret\n\t"
|
||||
".code32\n\t"
|
||||
"1: .long global_pit_tick\n\t"
|
||||
);
|
||||
}
|
||||
|
||||
uint8_t rm_pic0_mask = 0xff;
|
||||
uint8_t rm_pic1_mask = 0xff;
|
||||
uint8_t pm_pic0_mask = 0xff;
|
||||
uint8_t pm_pic1_mask = 0xff;
|
||||
|
||||
struct idt_entry_t {
|
||||
uint16_t offset_lo;
|
||||
uint16_t selector;
|
||||
uint8_t unused;
|
||||
uint8_t type_attr;
|
||||
uint16_t offset_hi;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct idt_ptr_t {
|
||||
uint16_t size;
|
||||
uint32_t address;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define IDT_MAX_ENTRIES 16
|
||||
|
||||
static struct idt_entry_t idt[IDT_MAX_ENTRIES];
|
||||
|
||||
void init_idt(void) {
|
||||
rm_pic0_mask = port_in_b(0x21);
|
||||
rm_pic1_mask = port_in_b(0xa1);
|
||||
|
||||
for (int i = 0; i < IDT_MAX_ENTRIES; i++) {
|
||||
register_interrupt_handler(i, unhandled_int, 0x8e);
|
||||
}
|
||||
|
||||
register_interrupt_handler(0x08, pit_irq, 0x8e);
|
||||
|
||||
ivt_register_handler(0x1c, ivt_timer_isr);
|
||||
|
||||
struct idt_ptr_t idt_ptr = {
|
||||
sizeof(idt) - 1,
|
||||
(uint32_t)idt
|
||||
};
|
||||
|
||||
asm volatile (
|
||||
"lidt %0"
|
||||
:
|
||||
: "m" (idt_ptr)
|
||||
);
|
||||
|
||||
pm_pic0_mask = 0xfe;
|
||||
pm_pic1_mask = 0xff;
|
||||
port_out_b(0x21, pm_pic0_mask);
|
||||
port_out_b(0xa1, pm_pic1_mask);
|
||||
|
||||
asm volatile ("sti");
|
||||
}
|
||||
|
||||
void register_interrupt_handler(size_t vec, void *handler, uint8_t type) {
|
||||
uint32_t p = (uint32_t)handler;
|
||||
|
||||
idt[vec].offset_lo = (uint16_t)p;
|
||||
idt[vec].selector = 0x18;
|
||||
idt[vec].unused = 0;
|
||||
idt[vec].type_attr = type;
|
||||
idt[vec].offset_hi = (uint16_t)(p >> 16);
|
||||
}
|
||||
|
||||
void ivt_register_handler(int vect, void *isr) {
|
||||
volatile uint32_t *ivt = (volatile void *)0;
|
||||
ivt[vect] = rm_seg(isr) << 16 | rm_off(isr);
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#ifndef __SYS__INTERRUPT_H__
|
||||
#define __SYS__INTERRUPT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern volatile uint64_t global_pit_tick;
|
||||
|
||||
extern uint8_t rm_pic0_mask;
|
||||
extern uint8_t rm_pic1_mask;
|
||||
extern uint8_t pm_pic0_mask;
|
||||
extern uint8_t pm_pic1_mask;
|
||||
|
||||
void init_idt(void);
|
||||
void register_interrupt_handler(size_t, void *, uint8_t);
|
||||
void ivt_register_handler(int vect, void *isr);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user