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)
PORT := 4242
PORTG := 4244
PORT_MONIT := 4242
PORT_GDB := 4244
else
PORT := 4342
PORTG := 4344
PORT_MONIT := 4342
PORT_GDB := 4344
endif
QEMU := qemu-system-i386\
-gdb tcp::$(PORTG)\
-cdrom build/bluesnow-x86.iso\
-S\
-enable-kvm\
-monitor telnet:127.0.0.1:$(PORT),server,nowait\
-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;\
telnet 127.0.0.1 $(PORT);\
GDB := gdb -q\
-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 2 \`
GDB := gdb -q\
-ex \"target remote :$(PORTG)\"
monitor:
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 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
bits 32
start:
; our stack, located in bss, linker.ld puts bss at the end of the binary
mov esp, stack_top

View file

@ -5,5 +5,5 @@ pub mod cpu;
pub unsafe fn init(active_table: &mut ActivePageTable) {
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 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_DATA: u16 = 2;
pub static GDT_USER_CODE: u16 = 3;
pub static GDT_USER_DATA: u16 = 4;
// tss takes 2 spots;
pub static GDT_TSS: u16 = 5;
pub static GDT_KERNEL_CODE: SegmentSelector = SegmentSelector::new(1, Ring0);
pub static GDT_KERNEL_DATA: SegmentSelector = SegmentSelector::new(2, Ring0);
pub static GDT_USER_CODE: SegmentSelector = SegmentSelector::new(3, Ring3);
pub static GDT_USER_DATA: SegmentSelector = SegmentSelector::new(4, Ring3);
pub static GDT_TSS: SegmentSelector = SegmentSelector::new(5, Ring3);
pub static GDT_TASK_TSS: SegmentSelector = SegmentSelector::new(7, Ring3);
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
let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment());
let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment());
let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment());
let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment());
//I read that the tss should be twice as long
//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));
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!(
// "tr({:#x}):\n {:#?}",
// tss_selector.0,
@ -45,3 +57,8 @@ pub unsafe fn init() {
load_tss(tss_selector);
// 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!(stack_segment, {});
exception_err!(general_protection, {
panic!("general protection fault (#GP) can not recover");
panic!("cannot recover from #GP");
});
pub extern "x86-interrupt" fn page_fault(
stack_frame: &mut ExceptionStackFrame,
code: PageFaultErrorCode,
) {
use x86::registers::control::Cr2;
println!("Exception: page_fault");
println!("Error code: {:?}", code);
println!("PFLA: {:?}", Cr2::read());
println!("{:#?}", stack_frame);
flush!();
panic!("cannot recover from #PF")
}
exception!(x87_fpu, {});

View file

@ -45,6 +45,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
// set up heap
::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
device::init(&mut active_table);
@ -52,7 +58,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
::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::instructions::segmentation::*;
use x86::PrivilegeLevel::{Ring0, Ring3};
@ -62,12 +73,26 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! {
// println!("sp: {:#x}", sp);
// println!("ip: {:#x}", ip);
let udata_selector = SegmentSelector::new(gdt::GDT_USER_DATA, Ring0);
let ucode_selector = SegmentSelector::new(gdt::GDT_USER_CODE, Ring3);
load_ds(udata_selector);
load_es(udata_selector);
load_fs(udata_selector);
load_gs(udata_selector);
// load_ds(udata_selector);
// asm!("mov $0, %ds" :: "r"(gdt::GDT_USER_DATA << 3 | 3));
// loop {}
// 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!("
push $0; \
@ -76,15 +101,17 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! {
push $3; \
push $4"
: //no output
: "r"(udata_selector),
: "r"(gdt::GDT_USER_DATA.0),
"r"(sp),
"r"(1 << 9) // interrupt enable flag
"r"(ucode_selector),
"r"(gdt::GDT_USER_CODE.0),
"r"(ip)
: //no clobbers
: "intel", "volatile"
);
// loop {}
asm!("iret");
unreachable!();

View file

@ -45,6 +45,8 @@ pub mod memory;
/// arch specific entry points
pub mod arch;
pub use arch::x86::consts::*;
/// process scheduling
pub mod process;
/// kernel entry point. arch module is responsible for
/// calling this once the core has loaded
@ -69,24 +71,20 @@ pub fn kmain() -> ! {
// println!("flags: {:?}", x86::registers::flags::flags());
// flush!();
let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32();
// let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32();
// let sp: u32;
// unsafe {
// asm!("mov %ebp, $0" : "=r" (sp));
// }
let ip = self::init as *const () as u32;
// unsafe {
// arch::x86::usermode(ip, sp, 0);
// }
// unreachable!()
loop {}
}
pub fn init() {
println!("inside init function!!!!!");
flush!();
loop {}
process::ploop();
unreachable!();
}
#[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 {
() => (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 =
$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 =
$crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} );
}
@ -63,7 +63,7 @@ impl Writer {
pub const fn new() -> Writer {
Writer {
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],
command: [b'\0'; 10],
command_len: 0,
@ -100,7 +100,7 @@ impl Writer {
b'\n' => {
self.write_byte(b'\n');
if let Err(msg) = console::exec(&self) {
set_color!(Red, Black);
set_color!(Red, Yellow);
println!("Something wrong: {}", msg);
set_color!();
}
@ -180,7 +180,7 @@ impl Writer {
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 + 1)] =
ColorCode::new(Color::White, Color::Black).0;
ColorCode::new(Color::Black, Color::Yellow).0;
}
self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS;

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