Skip to content

Commit 5b091a6

Browse files
User Mode working
1 parent 0dc16ef commit 5b091a6

File tree

8 files changed

+140
-16
lines changed

8 files changed

+140
-16
lines changed

build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn main() {
2929
// Build stage 3
3030
build_subproject(
3131
Path::new("src/protected/stage_3"),
32-
&["third_stage"],
32+
&["third_stage", "iret_test"],
3333
"../i386-unknown-none.json",
3434
&target_dir,
3535
&objcopy,
@@ -55,7 +55,7 @@ fn main() {
5555
// Build stage 2
5656
build_subproject(
5757
Path::new("src/real/stage_2"),
58-
&["second_stage"],
58+
&["second_stage", "v8086_test"],
5959
"../i386-unknown-none-code16.json",
6060
&target_dir,
6161
&objcopy,

src/protected/stage_3/src/interrupts.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ lazy_static! {
99
idt.divide_error.set_handler_fn(divide_handler);
1010
idt.breakpoint.set_handler_fn(breakpoint_handler);
1111

12+
idt.general_protection_fault.set_handler_fn(general_protection_fault_handler);
1213
idt.double_fault.set_handler_fn(double_fault_handler);
1314

1415
idt
@@ -38,4 +39,11 @@ extern "x86-interrupt" fn double_fault_handler(
3839
stack_frame: &mut InterruptStackFrame, _error_code: u32) -> !
3940
{
4041
panic!("[Bootloader] [IDT] Double Fault!");
42+
}
43+
44+
extern "x86-interrupt" fn general_protection_fault_handler(
45+
stack_frame: &mut InterruptStackFrame, error_code: u32)
46+
{
47+
println!("[Bootloader] [IDT] GPF {} ({})", stack_frame.eip, error_code);
48+
loop {};
4149
}

src/protected/stage_3/src/iret.s

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.att_syntax prefix
2+
iret_asm_test:
3+
mov $0x23, %eax
4+
mov %eax, %ds
5+
mov %eax, %es
6+
mov %eax, %fs
7+
mov %eax, %gs
8+
mov %esp, %eax
9+
10+
push $0x23
11+
push %eax
12+
13+
pushf
14+
15+
push $0x1b
16+
pushl $iret_test
17+
18+
iret

src/protected/stage_3/src/lib.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
#![no_std]
2-
#![feature(abi_x86_interrupt, asm)]
2+
#![feature(abi_x86_interrupt, asm, global_asm)]
33

44
use shared::println;
55
use shared::instructions;
6+
use shared::linker_symbol;
67

78
mod interrupts;
89
mod panic;
910

11+
global_asm!(include_str!("iret.s"));
12+
13+
extern "C" {
14+
fn v8086_test();
15+
fn iret_asm_test();
16+
}
17+
1018
#[no_mangle]
1119
pub extern "C" fn third_stage() -> ! {
12-
println!("[Bootloader] [32] Stage 3");
20+
println!("[Bootloader] [32] Stage 3");
1321

14-
unsafe {
15-
let ptr = 0x110000 as *mut u32;
16-
*ptr = 0xdeadbeef;
22+
unsafe {
23+
let ptr = 0x110000 as *mut u32;
24+
*ptr = 0xdeadbeef;
1725
}
1826

1927
println!("[Bootloader] [32] > 1MB");
@@ -29,5 +37,21 @@ pub extern "C" fn third_stage() -> ! {
2937

3038
println!("[Bootloader] [32] Loaded IDT");
3139

40+
unsafe {
41+
let eflags = instructions::read_eflags() ;//| (1 << 17);
42+
let fn_addr = &iret_test as *const _ as u32;
43+
44+
println!("fn @ {}", fn_addr);
45+
46+
iret_asm_test();
47+
}
48+
49+
println!("User mode returned");
50+
3251
loop {};
52+
}
53+
54+
#[no_mangle]
55+
pub extern "C" fn iret_test() {
56+
println!("User mode");
3357
}

src/real/stage_2/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,26 @@ use lazy_static::lazy_static;
88

99
mod panic;
1010

11+
#[no_mangle]
12+
pub fn v8086_test() {
13+
loop {};
14+
println!("v8086 mode! Yayyyy");
15+
loop {};
16+
}
17+
1118
extern "C" {
1219
fn protected_mode_switch() -> !;
1320
}
1421

1522
lazy_static! {
1623
static ref TSS: TaskStateSegment = {
24+
use core::mem::size_of;
25+
1726
let mut tss = TaskStateSegment::new();
1827

1928
tss.privilege_stack_table[0].esp = linker_symbol!(_protected_mode_stack_end);
2029
tss.privilege_stack_table[0].ss = 2 * 8; // Kernel data segment is 2nd segment (null, code, data)
30+
tss.iomap_base = size_of::<TaskStateSegment>() as u16;
2131

2232
tss
2333
};

src/shared/src/instructions.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
global_asm!(include_str!("instructions.s"));
2+
13
/// Performs a retf instruction, jumping to cs:eip
24
///
35
/// # Unsafety
@@ -10,6 +12,45 @@ pub unsafe fn retf(cs: u16, eip: u32) {
1012
in(reg) cs, in(reg) eip);
1113
}
1214

15+
/// Performs an iret instruction, jumping to cs:eip (as well as setting the stack to ss:esp and setting eflags)
16+
///
17+
/// # Unsafety
18+
/// We make no guarantees that any of the parameters are valid
19+
extern "C" {
20+
pub fn iret(ss: u32, esp: u32, cs: u32, eip: u32, eflags: u32);
21+
}
22+
23+
/*
24+
#[inline(always)]
25+
pub unsafe fn iret(ss: u32, esp: u32, cs: u32, eip: u32, eflags: u32) {
26+
use crate::println;
27+
println!("ss - {} esp - {} cs - {} eip - {} eflags - {}", ss, esp, cs, eip, eflags);
28+
asm!("push {ss:e}
29+
push {esp:e}
30+
push {eflags:e}
31+
push {cs:e}
32+
push {eip:e}
33+
iret",
34+
ss = in(reg) ss, esp = in(reg) esp, cs = in(reg) cs, eip = in(reg) eip, eflags = in(reg) eflags
35+
);
36+
}*/
37+
38+
/// Reads EFlags
39+
#[inline]
40+
pub fn read_eflags() -> u32 {
41+
let mut eflags: u32;
42+
43+
unsafe {
44+
asm!(
45+
"pushfd
46+
pop {}",
47+
out(reg) eflags, options(nomem, preserves_flags)
48+
)
49+
};
50+
51+
eflags
52+
}
53+
1354
/// Loads a new value into the task state register
1455
///
1556
/// # Unsafety

src/shared/src/instructions.s

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.intel_syntax noprefix
2+
3+
iret:
4+
mov ebp, esp
5+
6+
push dword PTR [ebp+4]
7+
push dword PTR [ebp+8]
8+
push dword PTR [ebp+12]
9+
push dword PTR [ebp+16]
10+
push dword PTR [ebp+20]
11+
iret

src/shared/src/structures/gdt.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ impl GlobalDescriptorTable {
4949
limit: (self.table.len() * size_of::<u64>() - 1) as u16,
5050
};
5151

52+
use crate::println;
53+
println!("GDT -");
54+
println!(" {:#08x}", self.table[0]);
55+
println!(" {:#08x}", self.table[1]);
56+
println!(" {:#08x}", self.table[2]);
57+
println!(" {:#08x}", self.table[3]);
58+
println!(" {:#08x}", self.table[4]);
59+
println!(" {:#08x}", self.table[5]);
60+
println!(" {:#08x}", self.table[6]);
61+
println!(" {:#08x}", self.table[7]);
62+
5263
asm!("lgdt [{}]",
5364
in(reg) &ptr,
5465
options(nostack)
@@ -95,6 +106,9 @@ bitflags! {
95106
/// The DPL for this descriptor is Ring 3
96107
const DPL_RING_3 = 3 << 45;
97108

109+
/// Is this segment available for use
110+
const AVAILABLE = 1 << 52;
111+
98112
/// If set, this page is a 32 bit descriptor
99113
const SIZE = 1 << 54;
100114

@@ -116,7 +130,7 @@ impl Descriptor {
116130
use self::DescriptorFlags as Flags;
117131

118132
let flags =
119-
Flags::USER_SEGMENT | Flags::PRESENT | Flags::EXECUTABLE | Flags::READABLE_WRITABLE | Flags::SIZE;
133+
Flags::USER_SEGMENT | Flags::PRESENT | Flags::READABLE_WRITABLE | Flags::ACCESSED | Flags::SIZE | Flags::EXECUTABLE;
120134

121135
Descriptor(flags.bits()).with_flat_limit()
122136
}
@@ -126,7 +140,8 @@ impl Descriptor {
126140
pub fn kernel_data_segment() -> Descriptor {
127141
use self::DescriptorFlags as Flags;
128142

129-
let flags = Flags::USER_SEGMENT | Flags::PRESENT | Flags::READABLE_WRITABLE | Flags::SIZE;
143+
let flags =
144+
Flags::USER_SEGMENT | Flags::PRESENT | Flags::READABLE_WRITABLE | Flags::ACCESSED | Flags::SIZE;
130145
Descriptor(flags.bits()).with_flat_limit()
131146
}
132147

@@ -136,7 +151,7 @@ impl Descriptor {
136151
use self::DescriptorFlags as Flags;
137152

138153
let flags =
139-
Flags::USER_SEGMENT | Flags::PRESENT | Flags::READABLE_WRITABLE | Flags::DPL_RING_3;
154+
Flags::USER_SEGMENT | Flags::PRESENT | Flags::READABLE_WRITABLE | Flags::ACCESSED | Flags::SIZE | Flags::DPL_RING_3;
140155
Descriptor(flags.bits()).with_flat_limit()
141156
}
142157

@@ -145,11 +160,8 @@ impl Descriptor {
145160
pub fn user_code_segment() -> Descriptor {
146161
use self::DescriptorFlags as Flags;
147162

148-
let flags = Flags::USER_SEGMENT
149-
| Flags::PRESENT
150-
| Flags::EXECUTABLE
151-
| Flags::DPL_RING_3
152-
| Flags::READABLE_WRITABLE;
163+
let flags =
164+
Flags::USER_SEGMENT | Flags::PRESENT | Flags::READABLE_WRITABLE | Flags::ACCESSED | Flags::SIZE | Flags::EXECUTABLE | Flags::DPL_RING_3;
153165
Descriptor(flags.bits()).with_flat_limit()
154166
}
155167

@@ -162,7 +174,7 @@ impl Descriptor {
162174
let ptr = tss as *const _ as u64;
163175

164176

165-
let mut val: u64 = (Flags::PRESENT | Flags::EXECUTABLE | Flags::ACCESSED | Flags::SIZE).bits();
177+
let mut val: u64 = (Flags::PRESENT | Flags::EXECUTABLE | Flags::ACCESSED | Flags::SIZE | Flags::DPL_RING_3).bits();
166178

167179
// base
168180
val.set_bits(16..40, ptr.get_bits(0..24));

0 commit comments

Comments
 (0)