Does it compile? no. Do I know what Im doing? maybe. Am I making progress? Yes.

This commit is contained in:
Jack Halford 2018-05-31 18:32:52 +02:00
parent 983c5d6e27
commit e48c3fc680
12 changed files with 192 additions and 49 deletions

View file

@ -1,2 +0,0 @@
set arch i386
file build/bluesnow-x86.bin

View file

@ -1,27 +1,35 @@
ifeq ($(shell whoami), jack) ifeq ($(shell whoami), jack)
PORT := 4242 PORT_MONIT := 4242
PORTG := 4244 PORT_GDB := 4244
else else
PORT := 4342 PORT_MONIT := 4342
PORTG := 4344 PORT_GDB := 4344
endif endif
QEMU := qemu-system-i386\ QEMU := qemu-system-i386\
-gdb tcp::$(PORTG)\ -cdrom build/bluesnow-x86.iso\
-S\ -S\
-enable-kvm\ -enable-kvm\
-monitor telnet:127.0.0.1:$(PORT),server,nowait\
-curses\ -curses\
-cdrom build/bluesnow-x86.iso -gdb tcp::$(PORT_GDB)\
-monitor telnet:127.0.0.1:$(PORT_MONIT),server,nowait
qemu:
$(QEMU)
MONITOR := sleep 0.5;\ GDB := gdb -q\
telnet 127.0.0.1 $(PORT);\ -symbols "$(kernel)" \
-ex "target remote :$(PORT_GDB)"\
-ex "set arch i386"
gdb:
$(GDB)
MONITOR := telnet 127.0.0.1 $(PORT_MONIT);\
kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\
kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \`
GDB := gdb -q\ monitor:
-ex \"target remote :$(PORTG)\" telnet 127.0.0.1 $(PORT_MONIT)
qemu: #not using this anymore
william:
@tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; }
@tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU)' @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU)'

View file

@ -4,6 +4,7 @@ extern x86_start
section .text section .text
bits 32 bits 32
start: start:
; our stack, located in bss, linker.ld puts bss at the end of the binary ; our stack, located in bss, linker.ld puts bss at the end of the binary
mov esp, stack_top mov esp, stack_top

View file

@ -5,5 +5,5 @@ pub mod cpu;
pub unsafe fn init(active_table: &mut ActivePageTable) { pub unsafe fn init(active_table: &mut ActivePageTable) {
pic::init(); pic::init();
local_apic::init(active_table); // local_apic::init(active_table);
} }

View file

@ -8,28 +8,40 @@ use x86::*;
pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); pub static mut GDT: gdt::Gdt = gdt::Gdt::new();
pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new();
pub static mut TASK_TSS: tss::TaskStateSegment = tss::TaskStateSegment::new();
pub static GDT_KERNEL_CODE: u16 = 1; pub static GDT_KERNEL_CODE: SegmentSelector = SegmentSelector::new(1, Ring0);
pub static GDT_KERNEL_DATA: u16 = 2; pub static GDT_KERNEL_DATA: SegmentSelector = SegmentSelector::new(2, Ring0);
pub static GDT_USER_CODE: u16 = 3; pub static GDT_USER_CODE: SegmentSelector = SegmentSelector::new(3, Ring3);
pub static GDT_USER_DATA: u16 = 4; pub static GDT_USER_DATA: SegmentSelector = SegmentSelector::new(4, Ring3);
// tss takes 2 spots; pub static GDT_TSS: SegmentSelector = SegmentSelector::new(5, Ring3);
pub static GDT_TSS: u16 = 5; pub static GDT_TASK_TSS: SegmentSelector = SegmentSelector::new(7, Ring3);
pub unsafe fn init() { pub unsafe fn init() {
TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0;
asm!("mov %esp, $0" : "=r" (TSS.esp0));
// the following *order* is important // the following *order* is important
let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment()); let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment());
let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment()); let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment());
let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment()); let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment());
let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment()); let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment());
//I read that the tss should be twice as long //I read that the tss should be twice as long
//fuck knows why... //fuck knows why...
TSS.ss0 = GDT_KERNEL_CODE.0;
asm!("mov %esp, $0" : "=r" (TSS.esp0));
let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS));
GDT.add_entry(gdt::Descriptor(0)); GDT.add_entry(gdt::Descriptor(0));
TASK_TSS.eip = self::test_task as *const () as u32;
let task_tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TASK_TSS));
GDT.add_entry(gdt::Descriptor(0));
assert_eq!(kcode_selector, GDT_KERNEL_CODE);
assert_eq!(kdata_selector, GDT_KERNEL_DATA);
assert_eq!(ucode_selector, GDT_USER_CODE);
assert_eq!(udata_selector, GDT_USER_DATA);
assert_eq!(tss_selector, GDT_TSS);
assert_eq!(task_tss_selector, GDT_TASK_TSS);
// println!( // println!(
// "tr({:#x}):\n {:#?}", // "tr({:#x}):\n {:#?}",
// tss_selector.0, // tss_selector.0,
@ -45,3 +57,8 @@ pub unsafe fn init() {
load_tss(tss_selector); load_tss(tss_selector);
// unreachable!(); // unreachable!();
} }
pub fn test_task() {
println!("inside test task omg we did it !!!");
flush!();
}

View file

@ -56,17 +56,20 @@ exception_err!(invalid_tss, {});
exception_err!(segment_not_present, {}); exception_err!(segment_not_present, {});
exception_err!(stack_segment, {}); exception_err!(stack_segment, {});
exception_err!(general_protection, { exception_err!(general_protection, {
panic!("general protection fault (#GP) can not recover"); panic!("cannot recover from #GP");
}); });
pub extern "x86-interrupt" fn page_fault( pub extern "x86-interrupt" fn page_fault(
stack_frame: &mut ExceptionStackFrame, stack_frame: &mut ExceptionStackFrame,
code: PageFaultErrorCode, code: PageFaultErrorCode,
) { ) {
use x86::registers::control::Cr2;
println!("Exception: page_fault"); println!("Exception: page_fault");
println!("Error code: {:?}", code); println!("Error code: {:?}", code);
println!("PFLA: {:?}", Cr2::read());
println!("{:#?}", stack_frame); println!("{:#?}", stack_frame);
flush!(); flush!();
panic!("cannot recover from #PF")
} }
exception!(x87_fpu, {}); exception!(x87_fpu, {});

View file

@ -45,6 +45,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
// set up heap // set up heap
::allocator::init(&mut active_table); ::allocator::init(&mut active_table);
// set up user stack
use x86::structures::paging::*;
// for page in ::USER_STACK_RANGE {
// active_table.map(page, PageTableFlags::WRITABLE);
// }
// set up pic & apic // set up pic & apic
device::init(&mut active_table); device::init(&mut active_table);
@ -52,7 +58,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
::kmain(); ::kmain();
} }
pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { pub unsafe fn switch(ip: u32) -> ! {
asm!("push $0; ret" :: "r"(ip) :: "volatile", "intel");
unreachable!();
}
pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! {
use x86::structures::gdt::{Descriptor, SegmentSelector}; use x86::structures::gdt::{Descriptor, SegmentSelector};
use x86::instructions::segmentation::*; use x86::instructions::segmentation::*;
use x86::PrivilegeLevel::{Ring0, Ring3}; use x86::PrivilegeLevel::{Ring0, Ring3};
@ -62,12 +73,26 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! {
// println!("sp: {:#x}", sp); // println!("sp: {:#x}", sp);
// println!("ip: {:#x}", ip); // println!("ip: {:#x}", ip);
let udata_selector = SegmentSelector::new(gdt::GDT_USER_DATA, Ring0); // load_ds(udata_selector);
let ucode_selector = SegmentSelector::new(gdt::GDT_USER_CODE, Ring3); // asm!("mov $0, %ds" :: "r"(gdt::GDT_USER_DATA << 3 | 3));
load_ds(udata_selector);
load_es(udata_selector); // loop {}
load_fs(udata_selector);
load_gs(udata_selector); // load_es(udata_selector);
// load_fs(udata_selector);
// load_gs(udata_selector);
use x86::registers::flags;
flags::set_flags(flags::Flags::NT);
asm!("mov %esp, $0" : "=r" (sp));
println!("{:#x}", gdt::GDT_KERNEL_DATA.0);
println!("{:#x}", sp);
println!("{:#x}", 1 << 9);
println!("{:#x}", gdt::GDT_KERNEL_CODE.0);
println!("{:#x}", ip);
flush!();
asm!(" asm!("
push $0; \ push $0; \
@ -76,15 +101,17 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! {
push $3; \ push $3; \
push $4" push $4"
: //no output : //no output
: "r"(udata_selector), : "r"(gdt::GDT_USER_DATA.0),
"r"(sp), "r"(sp),
"r"(1 << 9) // interrupt enable flag "r"(1 << 9) // interrupt enable flag
"r"(ucode_selector), "r"(gdt::GDT_USER_CODE.0),
"r"(ip) "r"(ip)
: //no clobbers : //no clobbers
: "intel", "volatile" : "intel", "volatile"
); );
// loop {}
asm!("iret"); asm!("iret");
unreachable!(); unreachable!();

View file

@ -45,6 +45,8 @@ pub mod memory;
/// arch specific entry points /// arch specific entry points
pub mod arch; pub mod arch;
pub use arch::x86::consts::*; pub use arch::x86::consts::*;
/// process scheduling
pub mod process;
/// kernel entry point. arch module is responsible for /// kernel entry point. arch module is responsible for
/// calling this once the core has loaded /// calling this once the core has loaded
@ -69,24 +71,20 @@ pub fn kmain() -> ! {
// println!("flags: {:?}", x86::registers::flags::flags()); // println!("flags: {:?}", x86::registers::flags::flags());
// flush!(); // flush!();
let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); // let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32();
// let sp: u32; // let sp: u32;
// unsafe { // unsafe {
// asm!("mov %ebp, $0" : "=r" (sp)); // asm!("mov %ebp, $0" : "=r" (sp));
// } // }
let ip = self::init as *const () as u32;
// unsafe { // unsafe {
// arch::x86::usermode(ip, sp, 0); // arch::x86::usermode(ip, sp, 0);
// } // }
// unreachable!() // unreachable!()
loop {}
}
pub fn init() { process::ploop();
println!("inside init function!!!!!");
flush!(); unreachable!();
loop {}
} }
#[lang = "eh_personality"] #[lang = "eh_personality"]

View file

@ -0,0 +1,27 @@
use spin::Mutex;
use alloc::VecDeque;
use super::*;
pub struct Fifo {
list: VecDeque<Process>,
}
impl Fifo {
pub fn new() -> Fifo {
Fifo {
list: VecDeque::new(),
}
}
}
impl Scheduler for Fifo {
fn add_process(&mut self, ip: u32) {
let p = Process::new(ip);
self.list.push_back(p);
}
fn next(&mut self) -> Option<Process> {
self.list.pop_front()
}
}

View file

@ -0,0 +1,64 @@
mod fifo;
lazy_static! {
static ref SCHEDULER: fifo::Fifo = fifo::Fifo::new();
}
// lazy_static! {
// static ref SCHEDULER: self::Scheduler = self::Scheduler {
// list: Mutex::new(VecDeque::new())
// };
// }
#[derive(Debug)]
pub struct Process {
// this is eip right now
// this will be an elf blob later
ip: u32,
}
impl Process {
pub fn new(ip: u32) -> Process {
Process { ip }
}
pub unsafe fn execute(&mut self) {
asm!("push $0; ret" :: "r"(self.ip) :: "volatile", "intel");
}
}
pub trait Scheduler {
fn add_process(&mut self, ip: u32);
fn next(&mut self) -> Option<Process>;
}
pub fn ploop() {
let ip = self::init as *const () as u32;
unsafe {
SCHEDULER.add_process(ip);
}
loop {
if let Some(mut p) = unsafe { SCHEDULER.next() } {
print!("{:?}", p);
unsafe {
p.execute();
}
}
}
}
pub fn fork() -> i32 {
let ip;
unsafe {
asm!("" : "={eip}"(ip) ::: "volatile");
SCHEDULER.add_process(ip);
}
0
}
pub fn init() -> ! {
let i = self::fork();
println!("inside fork_print() function!!!!!, fork={}", i);
flush!();
loop {}
}

View file

@ -32,9 +32,9 @@ macro_rules! flush {
macro_rules! set_color { macro_rules! set_color {
() => (unsafe { $crate::vga::VGA.color_code = () => (unsafe { $crate::vga::VGA.color_code =
$crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} ); $crate::vga::ColorCode::new($crate::vga::Color::Black, $crate::vga::Color::Yellow)} );
($fg:ident) => (unsafe { $crate::vga::VGA.color_code = ($fg:ident) => (unsafe { $crate::vga::VGA.color_code =
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} ); $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Yellow)} );
($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code = ($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code =
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} ); $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} );
} }
@ -63,7 +63,7 @@ impl Writer {
pub const fn new() -> Writer { pub const fn new() -> Writer {
Writer { Writer {
buffer_pos: 0, buffer_pos: 0,
color_code: ColorCode::new(Color::White, Color::Black), color_code: ColorCode::new(Color::Black, Color::Yellow),
buffer: [0; BUFFER_ROWS * BUFFER_COLS], buffer: [0; BUFFER_ROWS * BUFFER_COLS],
command: [b'\0'; 10], command: [b'\0'; 10],
command_len: 0, command_len: 0,
@ -100,7 +100,7 @@ impl Writer {
b'\n' => { b'\n' => {
self.write_byte(b'\n'); self.write_byte(b'\n');
if let Err(msg) = console::exec(&self) { if let Err(msg) = console::exec(&self) {
set_color!(Red, Black); set_color!(Red, Yellow);
println!("Something wrong: {}", msg); println!("Something wrong: {}", msg);
set_color!(); set_color!();
} }
@ -180,7 +180,7 @@ impl Writer {
for col in (0..BUFFER_COLS / 2).map(|x| x * 2) { for col in (0..BUFFER_COLS / 2).map(|x| x * 2) {
self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col)] = b' '; self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col)] = b' ';
self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] = self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] =
ColorCode::new(Color::White, Color::Black).0; ColorCode::new(Color::Black, Color::Yellow).0;
} }
self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS;

@ -1 +1 @@
Subproject commit 3a6ff64c5fb9a4bdeb8b6b4c83328278c551dbad Subproject commit d81e8a3690f3cd2dc64f0d6ebabceeb8e5583c97