Does it compile? no. Do I know what Im doing? maybe. Am I making progress? Yes.
This commit is contained in:
parent
983c5d6e27
commit
e48c3fc680
12 changed files with 192 additions and 49 deletions
|
|
@ -1,2 +0,0 @@
|
|||
set arch i386
|
||||
file build/bluesnow-x86.bin
|
||||
|
|
@ -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)'
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, {});
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
27
kernel-rs/src/process/fifo.rs
Normal file
27
kernel-rs/src/process/fifo.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
64
kernel-rs/src/process/mod.rs
Normal file
64
kernel-rs/src/process/mod.rs
Normal 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 {}
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in a new issue