Thunking to real mode for interrupts

This commit is contained in:
Jeremy Soller
2022-02-01 22:14:50 -07:00
parent c9ec8f7a07
commit f6582168c6
4 changed files with 200 additions and 9 deletions
+59 -2
View File
@@ -1,8 +1,12 @@
#![no_std]
#![feature(asm)]
#![feature(lang_items)]
#![feature(llvm_asm)]
use core::slice;
use core::{
ptr,
slice,
};
mod panic;
@@ -32,8 +36,61 @@ pub enum VgaTextColor {
White = 15,
}
#[derive(Clone, Copy)]
#[repr(packed)]
pub struct ThunkData {
di: u16,
si: u16,
bp: u16,
sp: u16,
bx: u16,
dx: u16,
cx: u16,
ax: u16,
}
impl ThunkData {
pub const STACK: usize = 0x7C00;
pub fn new() -> Self {
Self {
di: 0,
si: 0,
bp: 0,
sp: Self::STACK as u16,
bx: 0,
dx: 0,
cx: 0,
ax: 0,
}
}
pub unsafe fn save(&self) {
ptr::write((Self::STACK - 16) as *mut ThunkData, *self);
}
pub unsafe fn load(&mut self) {
*self = ptr::read((Self::STACK - 16) as *const ThunkData);
}
pub unsafe fn with(&mut self, f: extern "C" fn()) {
self.save();
f();
self.load();
}
}
#[no_mangle]
pub unsafe extern "C" fn kstart() -> ! {
pub unsafe extern "C" fn kstart(
thunk10: extern "C" fn(),
thunk13: extern "C" fn(),
) -> ! {
{
let mut data = ThunkData::new();
data.ax = 0x03;
data.with(thunk10);
}
let vga = slice::from_raw_parts_mut(
0xb8000 as *mut VgaTextBlock,
80 * 25
+32 -6
View File
@@ -10,12 +10,12 @@ startup_arch:
mov cr0, eax
; far jump to load CS with 32 bit segment
jmp gdt.kernel_code:protected_mode
jmp gdt.pm32_code:protected_mode
USE32
protected_mode:
; load all the other segments with 32 bit data segments
mov eax, gdt.kernel_data
mov eax, gdt.pm32_data
mov ds, eax
mov es, eax
mov fs, eax
@@ -25,6 +25,10 @@ protected_mode:
mov esp, 0x800000 - 128
; entry point
mov eax, thunk.int13
push eax
mov eax, thunk.int10
push eax
mov eax, [args.kernel_base]
call [eax + 0x18]
.halt:
@@ -32,6 +36,8 @@ protected_mode:
hlt
jmp .halt
%include "thunk.asm"
gdtr:
dw gdt.end + 1 ; size
dd gdt ; offset
@@ -40,23 +46,43 @@ gdt:
.null equ $ - gdt
dq 0
.kernel_code equ $ - gdt
.pm32_code equ $ - gdt
istruc GDTEntry
at GDTEntry.limitl, dw 0xFFFF
at GDTEntry.basel, dw 0
at GDTEntry.basem, db 0
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code | attrib.readable
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
at GDTEntry.flags__limith, db 0xF | flags.granularity | flags.default_operand_size
at GDTEntry.baseh, db 0
iend
.kernel_data equ $ - gdt
.pm32_data equ $ - gdt
istruc GDTEntry
at GDTEntry.limitl, dw 0xFFFF
at GDTEntry.basel, dw 0
at GDTEntry.basem, db 0
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
at GDTEntry.flags__limith, db 0xF | flags.granularity | flags.default_operand_size
at GDTEntry.baseh, db 0
iend
.pm16_code equ $ - gdt
istruc GDTEntry
at GDTEntry.limitl, dw 0xFFFF
at GDTEntry.basel, dw 0
at GDTEntry.basem, db 0
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code | attrib.readable
at GDTEntry.flags__limith, db 0xF
at GDTEntry.baseh, db 0
iend
.pm16_data equ $ - gdt
istruc GDTEntry
at GDTEntry.limitl, dw 0xFFFF
at GDTEntry.basel, dw 0
at GDTEntry.basem, db 0
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
at GDTEntry.flags__limith, db 0xF
at GDTEntry.baseh, db 0
iend
+108
View File
@@ -0,0 +1,108 @@
USE32
thunk:
.int10:
mov dword [.func], .int10_real
jmp .enter
.int13:
mov dword [.func], .int13_real
jmp .enter
.func: dd 0
.esp: dd 0
.cr0: dd 0
.enter:
; save flags
pushfd
; save registers
pushad
; save esp
mov [.esp], esp
; far jump to protected mode 16-bit
jmp gdt.pm16_code:.pm16
.exit:
; set segment selectors to 32-bit protected mode
mov eax, gdt.pm32_data
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ss, eax
; restore esp
mov esp, [.esp]
; restore registers
popad
; restore flags
popfd
; return
ret
USE16
.int10_real:
sti
int 0x10
cli
; ret
.int13_real:
sti
int 0x13
cli
ret
.pm16:
; set segment selectors to protected mode 16-bit
mov eax, gdt.pm16_data
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ss, eax
; save cr0
mov eax, cr0
mov [.cr0], eax
; disable paging and protected mode
and eax, 0x7FFFFFFE
mov cr0, eax
; far jump to real mode
jmp 0:.real
.real:
; set segment selectors to real mode
mov eax, 0
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ss, eax
; set stack
mov esp, 0x7C00 - 16
; load registers
popa
; call real mode function
call [.func]
; save registers
pusha
; restore cr0, will enable protected mode
mov eax, [.cr0]
mov cr0, eax
; far jump to protected mode 32-bit
jmp gdt.pm32_code:.exit
+1 -1
View File
@@ -48,7 +48,7 @@ unreal_gdt:
at GDTEntry.basel, dw 0x0
at GDTEntry.basem, db 0x0
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
at GDTEntry.flags__limith, db 0xF | flags.granularity | flags.default_operand_size
at GDTEntry.baseh, db 0x0
iend
.end equ $ - unreal_gdt