some stuff

This commit is contained in:
Jack Halford 2018-05-17 13:17:39 +02:00
parent 0aae87eda3
commit e2cf54877e
16 changed files with 186 additions and 116 deletions

2
kernel-rs/.gdbinit Normal file
View file

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

View file

@ -1,7 +1,7 @@
[package] [package]
name = "bluesnow" name = "bluesnow"
version = "0.1.0" version = "0.1.0"
authors = ["Jack Halford <j@crans.org>", "William Escande <wescande@student.42.fr>"] authors = ["Jack Halford <jack@crans.org>", "William Escande <wescande@student.42.fr>"]
[lib] [lib]
crate-type = ["staticlib"] crate-type = ["staticlib"]

View file

@ -4,6 +4,11 @@ ARCH := x86
OS := bluesnow OS := bluesnow
TARGET ?= $(ARCH)-$(OS) TARGET ?= $(ARCH)-$(OS)
all:
@printf "make kernel\t# build kernel binary\n"
@printf "make iso\t# build iso cdrom with grub\n"
@printf "make qemu\t# run qemu+gdb in tmux window\n"
## COMPILE ASM (nasm) ## COMPILE ASM (nasm)
asm_source := $(wildcard src/arch/$(ARCH)/*.asm) asm_source := $(wildcard src/arch/$(ARCH)/*.asm)
asm_object := $(patsubst src/arch/$(ARCH)/%.asm, build/arch/$(ARCH)/%.o, $(asm_source)) asm_object := $(patsubst src/arch/$(ARCH)/%.asm, build/arch/$(ARCH)/%.o, $(asm_source))
@ -15,18 +20,18 @@ build/arch/$(ARCH)/%.o: src/arch/$(ARCH)/%.asm Makefile
## COMPILE RUST (xargo) ## COMPILE RUST (xargo)
rust_os := target/$(TARGET)/debug/lib$(OS).a rust_os := target/$(TARGET)/debug/lib$(OS).a
$(rust_os): $(TARGET).json Makefile $(rust_os): $(TARGET).json Makefile
@TERM=xterm RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) TERM=xterm RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET)
## LINKAGE ## LINKAGE
kernel := build/$(OS) kernel := build/$(OS)-$(ARCH).bin
linker_script := src/arch/$(ARCH)/linker.ld linker_script := src/arch/$(ARCH)/linker.ld
LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections
$(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile
$(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) $(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os)
clean: clean:
@xargo clean xargo clean
@rm -rf build rm -rf build
.PHONY: clean kernel iso $(rust_os) .PHONY: clean kernel iso $(rust_os)
@ -37,3 +42,4 @@ include mk/qemu.mk
include mk/grub.mk include mk/grub.mk
iso: $(grub-iso) iso: $(grub-iso)
kernel: $(kernel)

View file

@ -1,4 +1,4 @@
grub-iso := $(kernel).iso grub-iso := $(kernel:.bin=.iso)
grub-cfg := src/arch/$(ARCH)/grub.cfg grub-cfg := src/arch/$(ARCH)/grub.cfg
isodir := build/isofiles isodir := build/isofiles

View file

@ -1,4 +1,4 @@
ifeq ($(shell whoami), william) ifeq ($(shell whoami), jack)
PORT := 4242 PORT := 4242
PORTG := 4244 PORTG := 4244
else else
@ -6,20 +6,22 @@ else
PORTG := 4344 PORTG := 4344
endif endif
QEMU := qemu-system-x86_64 QEMU := qemu-system-x86_64\
QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom build/bluesnow.iso -gdb tcp::$(PORTG)\
-S\
-enable-kvm\
-monitor telnet:127.0.0.1:$(PORT),server,nowait\
-curses\
-cdrom build/bluesnow-x86.iso
MONITOR := sleep 0.5;\ MONITOR := sleep 0.5;\
telnet 127.0.0.1 $(PORT);\ telnet 127.0.0.1 $(PORT);\
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\ GDB := gdb -q\
-ex \"set arch i386:x86-64\"\ -ex \"target remote :$(PORTG)\"
-ex \"file $(kernel)\"\
-ex \"target remote :$(PORTG)\"\
-ex \"continue\"
qemu: qemu:
@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) $(QEMUFLAGS)' @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

@ -5,12 +5,9 @@ use x86::*;
use x86::structures::paging::*; use x86::structures::paging::*;
use arch::x86::paging::*; use arch::x86::paging::*;
fn map_heap(active_table: &mut ActivePageTable, offset: u32, size: u32) { fn map_heap(active_table: &mut ActivePageTable) {
let heap_start_page = Page::containing_address(VirtAddr::new(offset)); //zone for heap is predefines in `consts.rs`
let heap_end_page = Page::containing_address(VirtAddr::new(offset + size - 1)); for page in ::KERNEL_HEAP_RANGE {
for page in heap_start_page..heap_end_page + 1 {
//we really should only map 1 huge page instead of 1024 small pages
active_table.map(page, PageTableFlags::WRITABLE); active_table.map(page, PageTableFlags::WRITABLE);
} }
} }
@ -20,7 +17,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
let offset = ::KERNEL_HEAP_OFFSET; let offset = ::KERNEL_HEAP_OFFSET;
let size = ::KERNEL_HEAP_SIZE; let size = ::KERNEL_HEAP_SIZE;
map_heap(active_table, offset, size); map_heap(active_table);
Allocator::init(offset as usize, size as usize); //slab allocator
Allocator::init(offset.as_u32() as usize, size as usize);
} }

View file

@ -42,6 +42,10 @@ set_up_page_tables:
or eax, 0b10000011 ; huge + present + writable or eax, 0b10000011 ; huge + present + writable
mov [p2_table + 4], eax mov [p2_table + 4], eax
mov eax, 0x800000 ; 8MB -> 12Mb (second page)
or eax, 0b10000011 ; huge + present + writable
mov [p2_table + 8], eax
mov eax, p2_table mov eax, p2_table
mov cr3, eax mov cr3, eax
ret ret

View file

@ -1,31 +1,52 @@
//layout looks like this: // p2 layout looks like this:
// [kernel 0->4MiB] // [kernel 0->4MiB]
// [kernel 4->8MiB] // [kernel 4->8MiB]
// [start of no man's land]
// .
// .
// .
// [end of no man's land]
// [user stack] // [user stack]
// [start of userheap]
// .
// .
// .
// [end of userheap]
// [kernel heap] // [kernel heap]
// [recursive map] points to first entry // [recursive map] points to first entry
// //
// which makes userheap = 4GiB - 4*4MiB (~= 4GiB) // no man's land should be used in the future for mmap() I guess
macro_rules! p2 { ($i:expr) => {($i & P2_MASK) / P1_SIZE}} // the kernel right now takes up 2 pages with debug symbols,
pub const P2_MASK: u32 = 0xFFC0_0000; //top 10 bits // if it gets to 3 pages everything will crash and i'll have
pub const P1_SIZE: u32 = 0x0040_0000; //4MiB (2**22) // to hardcode the third page here and in `boot.asm` also!
//
// TODO
// kernel is mapped identically (start of memory) but in
// the future it should be higher-half mapped so that
// user memory starts at 0
pub const RECURSIVE_PAGE_OFFSET: u32 = (-(P1_SIZE as isize)) as u32; use x86::structures::paging::*;
///1023 use x86::*;
pub const RECURSIVE_PAGE_P2: u32 = p2!(RECURSIVE_PAGE_OFFSET); use core::ops::Range;
pub const KERNEL_HEAP_OFFSET: u32 = RECURSIVE_PAGE_OFFSET - P1_SIZE; // macro_rules! prange { ($i:expr, $s:expr) => {$i..$i+$s+1}}
///1022
pub const KERNEL_HEAP_P2: u32 = p2!(KERNEL_HEAP_OFFSET);
pub const KERNEL_HEAP_SIZE: u32 = 4 * 1024 * 1024; //4MiB (1 huge page)
pub const USER_OFFSET: u32 = 0x00a0_0000; //3rd page (kernel takes 2 first pages) // all of this is fucking contrived
pub const USER_P2: u32 = p2!(USER_OFFSET); // the rust compiler should be able to evaluate const expressions
// by using the impl for my structs, what i'm doing here is obvious
// to me but not to the compiler
pub const USER_STACK_OFFSET: u32 = USER_OFFSET + P1_SIZE; pub const RECURSIVE_PAGE_OFFSET: VirtAddr = VirtAddr(0xffc0_000); // first 10 bits
pub const USER_STACK_2: u32 = p2!(USER_STACK_OFFSET); pub const RECURSIVE_PAGE: Page = Page::containing_address(RECURSIVE_PAGE_OFFSET);
pub const RECURSIVE_PAGE_SIZE: u32 = 0x0040_0000; // the whole p2 entry
pub const KERNEL_HEAP_OFFSET: VirtAddr = VirtAddr(RECURSIVE_PAGE_OFFSET.0 - RECURSIVE_PAGE_SIZE);
// should be
// pub const KERNEL_HEAP_OFFSET: VirtAddr = RECURSIVE_PAGE_OFFSET - RECURSIVE_PAGE_SIZE);
pub const KERNEL_HEAP_SIZE: u32 = 0x0040_0000; //4MiB (1 huge page)
pub const KERNEL_HEAP_START: Page = Page::containing_address(KERNEL_HEAP_OFFSET);
pub const KERNEL_HEAP_END: Page =
Page::containing_address(VirtAddr(KERNEL_HEAP_OFFSET.0 + KERNEL_HEAP_SIZE));
pub const KERNEL_HEAP_RANGE: Range<Page> = KERNEL_HEAP_START..KERNEL_HEAP_END;
pub const USER_STACK_OFFSET: VirtAddr = VirtAddr(KERNEL_HEAP_OFFSET.0 - KERNEL_HEAP_SIZE);
pub const USER_STACK_START: Page = Page::containing_address(USER_STACK_OFFSET);
pub const USER_STACK_SIZE: u32 = 0x0040_0000; //4MiB (1 huge page)
pub const USER_STACK_END: Page =
Page::containing_address(VirtAddr(USER_STACK_OFFSET.0 + USER_STACK_SIZE));
pub const USER_STACK_RANGE: Range<Page> = USER_STACK_START..USER_STACK_END;

View file

@ -1,33 +1,41 @@
use x86::structures::gdt; use x86::structures::gdt;
use x86::structures::tss; use x86::structures::tss;
use x86::structures::gdt::{Descriptor, SegmentSelector};
use x86::instructions::segmentation::*; use x86::instructions::segmentation::*;
use x86::instructions::tables::load_tss; use x86::instructions::tables::load_tss;
use x86::PrivilegeLevel::{Ring0, Ring3};
use x86::*; use x86::*;
use spin::Once;
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 GDT_KERNEL_CODE: u16 = 1; pub static GDT_KERNEL_CODE: u16 = 1;
pub static GDT_KERNEL_DATA: u16 = 1; pub static GDT_KERNEL_DATA: u16 = 2;
pub static GDT_USER_CODE: u16 = 2; pub static GDT_USER_CODE: u16 = 3;
pub static GDT_USER_DATA: u16 = 3; pub static GDT_USER_DATA: u16 = 4;
// tss takes 2 spots;
pub static GDT_TSS: u16 = 5;
pub unsafe fn init() { pub unsafe fn init() {
TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0; TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0;
asm!("mov %ebp, $0" : "=r" (TSS.esp0)); 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 tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS));
//I read that the tss should be twice as long
//fuck knows why...
//also this doesnt work if the tss is after 3rd spot
//once again: fuck knows why...
GDT.add_entry(gdt::Descriptor(0));
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
//fuck knows why...
let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS));
GDT.add_entry(gdt::Descriptor(0));
// println!(
// "tr({:#x}):\n {:#?}",
// tss_selector.0,
// gdt::Descriptor(GDT.table[tss_selector.index() as usize])
// );
// flush!();
GDT.load(); GDT.load();
set_cs(kcode_selector); set_cs(kcode_selector);
@ -35,4 +43,5 @@ pub unsafe fn init() {
load_es(kdata_selector); load_es(kdata_selector);
load_ss(kdata_selector); load_ss(kdata_selector);
load_tss(tss_selector); load_tss(tss_selector);
// unreachable!();
} }

View file

@ -66,4 +66,16 @@ SECTIONS {
*(.bss .bss.*) *(.bss .bss.*)
. = ALIGN(4K); . = ALIGN(4K);
} }
.stab :
{
*(.stab)
. = ALIGN(4K);
}
.stabstr :
{
*(.stabstr)
. = ALIGN(4K);
}
} }

View file

@ -53,35 +53,39 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
} }
pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! {
asm!("push r10 use x86::structures::gdt::{Descriptor, SegmentSelector};
push r11 use x86::instructions::segmentation::*;
push r12 use x86::PrivilegeLevel::{Ring0, Ring3};
push r13
push r14 x86::instructions::interrupts::disable();
push r15
" // 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);
asm!("
push $0; \
push $1; \
push $2; \
push $3; \
push $4"
: //no output : //no output
: "{r10}"(gdt::GDT_USER_DATA << 3 | 3), : "r"(udata_selector),
"{r11}"(sp), "r"(sp),
"{r12}"(1 << 9) // interrupt enable flag "r"(1 << 9) // interrupt enable flag
"{r13}"(gdt::GDT_USER_CODE << 3 | 3), "r"(ucode_selector),
"{r14}"(ip), "r"(ip)
"{r15}"(arg)
: //no clobbers : //no clobbers
: "intel", "volatile" : "intel", "volatile"
); );
asm!("mov ds, r14d asm!("iret");
mov es, r14d
mov fs, r15d
mov gs, r14d
fninit
iret"
: //no output (never returns)
: "{r14}"(gdt::GDT_USER_DATA << 3 | 3),
"{r15}"(gdt::GDT_USER_CODE << 3 | 3)
: //no clobbers (never returns)
: "intel", "volatile"
);
unreachable!(); unreachable!();
} }

View file

@ -84,7 +84,6 @@ impl Mapper {
let frame = p1[page.p1_index()].pointed_frame().unwrap(); let frame = p1[page.p1_index()].pointed_frame().unwrap();
p1[page.p1_index()].set_unused(); p1[page.p1_index()].set_unused();
tlb::flush(page.start_address()); tlb::flush(page.start_address());
// TODO
::memory::deallocate_frames(frame, 1); ::memory::deallocate_frames(frame, 1);
} }
} }

View file

@ -188,10 +188,12 @@ pub fn regs() -> Result<(), &'static str> {
use x86::registers::control::*; use x86::registers::control::*;
use x86::instructions::tables::tr; use x86::instructions::tables::tr;
use x86::instructions::segmentation::*; use x86::instructions::segmentation::*;
use x86::registers::flags::*;
use x86::structures::gdt; use x86::structures::gdt;
println!("cr0 = {:?}", Cr0::read()); println!("cr0 = {:?}", Cr0::read());
println!("cr3 = {:?}", Cr3::read()); println!("cr3 = {:?}", Cr3::read());
println!("cr4 = {:?}", Cr4::read()); println!("cr4 = {:?}", Cr4::read());
println!("flags= {:?}", flags());
println!("tr = {:?}", tr()); println!("tr = {:?}", tr());
println!("ss = {:?}", ss()); println!("ss = {:?}", ss());
println!("cs = {:?}", cs()); println!("cs = {:?}", cs());

View file

@ -3,6 +3,7 @@
// nightly stuff we need // nightly stuff we need
#![no_std] #![no_std]
#![feature(lang_items)] #![feature(lang_items)]
#![feature(naked_functions)]
#![feature(const_fn)] #![feature(const_fn)]
#![feature(ptr_internals)] #![feature(ptr_internals)]
#![feature(asm)] #![feature(asm)]
@ -67,6 +68,26 @@ pub fn kmain() -> ! {
// x86::instructions::interrupts::int3(); // x86::instructions::interrupts::int3();
// println!("flags: {:?}", x86::registers::flags::flags());
// flush!();
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 {} loop {}
} }

View file

@ -6,7 +6,6 @@ use multiboot2;
use x86::structures::paging::*; use x86::structures::paging::*;
use arch::x86::paging::ActivePageTable; use arch::x86::paging::ActivePageTable;
use x86::*; use x86::*;
// use spin::Mutex;
use self::bump::BumpFrameAllocator; use self::bump::BumpFrameAllocator;
use self::recycle::RecycleAllocator; use self::recycle::RecycleAllocator;
@ -19,7 +18,7 @@ pub trait FrameAllocator {
pub struct MemoryControler { pub struct MemoryControler {
frame_allocator: RecycleAllocator<BumpFrameAllocator>, frame_allocator: RecycleAllocator<BumpFrameAllocator>,
stack_allocator: StackAllocator, // stack_allocator: StackAllocator,
} }
static mut MEMORY_CONTROLER: Option<MemoryControler> = None; static mut MEMORY_CONTROLER: Option<MemoryControler> = None;
@ -51,21 +50,12 @@ pub fn init(boot_info: &multiboot2::BootInformation) {
); );
let frame_allocator = RecycleAllocator::new(bump_allocator); let frame_allocator = RecycleAllocator::new(bump_allocator);
// let stack_allocator = StackAllocator::new(::USER_STACK_RANGE);
let heap_end_page =
Page::containing_address(VirtAddr::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE - 1));
let stack_allocator = {
let stack_alloc_start = heap_end_page + 1;
let stack_alloc_end = stack_alloc_start + 100;
let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1;
StackAllocator::new(stack_alloc_range)
};
unsafe { unsafe {
MEMORY_CONTROLER = Some(MemoryControler { MEMORY_CONTROLER = Some(MemoryControler {
frame_allocator, frame_allocator,
stack_allocator, // stack_allocator,
}); });
} }
} }
@ -90,17 +80,17 @@ pub fn deallocate_frames(frame: PhysFrame, count: usize) {
} }
} }
pub fn allocate_stack(mut active_table: &mut ActivePageTable) -> Option<Stack> { // pub fn allocate_stack(mut active_table: &mut ActivePageTable) -> Option<Stack> {
unsafe { // unsafe {
if let Some(ref mut controler) = MEMORY_CONTROLER { // if let Some(ref mut controler) = MEMORY_CONTROLER {
controler // controler
.stack_allocator // .stack_allocator
.allocate_stack(&mut active_table, 4) // .allocate_stack(&mut active_table, 4)
} else { // } else {
panic!("frame allocator not initialized!"); // panic!("frame allocator not initialized!");
} // }
} // }
} // }
/// Init memory module after core /// Init memory module after core
/// Must be called once, and only once, /// Must be called once, and only once,

@ -1 +1 @@
Subproject commit 73a83239073de4acb5b18bacad049553a086ce3f Subproject commit 3a6ff64c5fb9a4bdeb8b6b4c83328278c551dbad