Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
OBJS = entry.o vectors.o trapasm.o
OBJS = entry.o vectors.o trapasm.o swtch.o
RS = src/*.rs

# Cross-compiling (e.g., on Mac OS X)
Expand Down Expand Up @@ -82,6 +82,12 @@ bootblock: bootasm.S bootmain.c linkers/bootblock.ld
$(OBJDUMP) -S -D bootblock.o > bootblock.asm
$(OBJCOPY) -S -O binary bootblock.o bootblock

initcode: initcode.S
$(CC) $(CFLAGS) -nostdinc -I. -c initcode.S
$(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o
$(OBJCOPY) -S -O binary initcode.out initcode
$(OBJDUMP) -S initcode.o > initcode.asm

kernel.a: $(RS)
cargo +nightly rustc \
-Z build-std=core \
Expand All @@ -91,8 +97,8 @@ kernel.a: $(RS)
--lib --release \
-- -A warnings --emit link=kernel.a

kernel: kernel.a $(OBJS) ./linkers/kernel.ld
$(LD) -m elf_i386 -T ./linkers/kernel.ld -o kernel $(OBJS) kernel.a
kernel: kernel.a $(OBJS) ./linkers/kernel.ld initcode
$(LD) -m elf_i386 -T ./linkers/kernel.ld -o kernel $(OBJS) kernel.a -b binary initcode
$(OBJDUMP) -S -D kernel > kernel.asm
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym

Expand Down
10 changes: 10 additions & 0 deletions initcode.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Initial process execs /init.
# This code runs in user space.

# movl %eax, 0x10001
# movl %eax, 0x1000100
.globl start
start:
add $1, %eax
movl %eax, 0x10001
jmp start
2 changes: 1 addition & 1 deletion linkers/kernel.ld
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ENTRY(_start)
SECTIONS
{
/* Link the kernel at this address: "." means the current address */
/* Must be equal to KERNLINK */
/* Must be equal to KERNLINK */
. = 0x00100000;

.text : AT(0x100000) {
Expand Down
26 changes: 25 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,39 @@ pub const SEG_TSS: u16 = 5; // this process's task state
// cpu->gdt[NSEGS] holds the above segments.
pub const NSEGS: usize = 6;

// Privilege level
pub const DPL_USER: u8 = 0x3; // User DPL

// Application segment type bits
pub const STA_X: u8 = 0x8; // Executable segment
pub const STA_W: u8 = 0x2; // Writeable (non-executable segments)
pub const STA_R: u8 = 0x2; // Readable (executable segments)

// Memory layout
pub const EXTMEM: u32 = 0x100000; // Start of extended memory
pub const PHYSTOP: u32 = 0xE000000; // Top physical memory
pub const DEVSPACE: u32 = 0xFE000000; // Other devices are at high addresses

// Key addresses for address space layout
pub const KERNBASE: u32 = 0x0; // First kernel virtual address
pub const KERNLINK: u32 = KERNBASE + EXTMEM; // Address where kernel is linked

// We assume that kernel.asm can fit in first 2MB
pub const STARTPROC: u32 = 0x200000; // Start allocating process from here (2MB)
pub const PROCSIZE: u32 = 0x100000; // Size of each process (1MB)
pub const PROCSIZE: u32 = 0x100; // 1MB is the size of each process (in multiple of 4KB)

// Page table constants
pub const PGSIZE: u32 = 4096; // bytes mapped by a page
pub const NPDENTRIES: usize = 1024; // # directory entries per page directory
pub const NPTENTRIES: usize = 1024; // # PTEs per page table
pub const PTXSHIFT: u32 = 12; // offset of PTX in a linear address
pub const PDXSHIFT: u32 = 22; // offset of PDX in a linear address

// Page table/directory entry flags
pub const PTE_P: u32 = 0x001; // Present
pub const PTE_W: u32 = 0x002; // Writeable
pub const PTE_U: u32 = 0x004; // User
pub const PTE_PS: u32 = 0x080; // Page Size

// System segment type bits
pub const STS_T32A: u8 = 0x9; // Available 32-bit TSS
Expand Down
9 changes: 5 additions & 4 deletions src/lapic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::ptr::{read_volatile, write_volatile};
use crate::mp::MP_ONCE;
use crate::constants::{IRQ_ERROR, IRQ_SPURIOUS, IRQ_TIMER, T_IRQ0};
use crate::constants::{IRQ_ERROR, IRQ_SPURIOUS, T_IRQ0};

const ID: isize = 0x0020 / 4;
const VER: isize = 0x0030 / 4;
Expand Down Expand Up @@ -68,9 +68,10 @@ pub fn lapicinit() {
// from lapic[TICR] and then issues an interrupt.
// If xv6 cared more about precise timekeeping,
// TICR would be calibrated using an external time source.
lapicw(TDCR, X1);
lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
lapicw(TICR, 10000000);
// Timer disabled for p15 - will be re-enabled later
// lapicw(TDCR, X1);
// lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
// lapicw(TICR, 10000000);


// Disable logical interrupt lines.
Expand Down
37 changes: 31 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod file;
mod log;
mod mmu;
mod vm;
mod spinlock;
use crate::traps::*;

fn halt() -> ! {
Expand Down Expand Up @@ -82,18 +83,42 @@ pub extern "C" fn entryofrust() -> ! {
x86::sti();
fs::iinit(param::ROOTDEV);
log::initlog(param::ROOTDEV);
// cli(); // disable interrupts
file::mknod("/console", param::CONSOLE as i16, param::CONSOLE as i16);
vm::seginit(); // segment descriptors
welcome();

loop {
x86::wfi();
}
proc::pinit(); // first process
proc::scheduler(); // start running processes (never returns)
}

static mut PANICKED: bool = false;

#[cfg(not(test))]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
println!("Kernel Panic: {:?}", info);
halt()
use core::fmt::Write;

// Disable interrupts to prevent interrupt handlers from interfering
cli();

// Print panic message with LAPIC ID to identify which CPU panicked
let mut console = console::Console {};
let _ = write!(&mut console, "lapicid {}: panic: ", lapicid());
let _ = writeln!(&mut console, "{}", info);

// Print stack trace
let mut pcs = [0u32; 10];
let stack_ptr = &info as *const _ as *const u32;
spinlock::getcallerpcs(stack_ptr, &mut pcs);

for &pc in &pcs {
if pc != 0 {
let _ = writeln!(&mut console, " {:#x}", pc);
}
}

unsafe { PANICKED = true; }

// Halt the system
halt();
}
32 changes: 31 additions & 1 deletion src/mmu.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#![allow(unused_parens)] // False positive from bitfield macro

use modular_bitfield::prelude::*;
use crate::constants::{PDXSHIFT, PTXSHIFT}; // Page table/directory helper functions

// Segment Descriptor

#[bitfield]
#[repr(C, packed)]
#[derive(Clone, Copy, Default, Debug)]
Expand Down Expand Up @@ -44,3 +44,33 @@ impl SegDesc {
seg
}
}

// Extract page directory index from virtual address
#[inline]
pub fn pdx(va: u32) -> usize {
((va >> PDXSHIFT) & 0x3FF) as usize
}

// Extract page table index from virtual address
#[inline]
pub fn ptx(va: u32) -> usize {
((va >> PTXSHIFT) & 0x3FF) as usize
}

// Construct virtual address from page directory index, page table index, and offset
#[inline]
pub fn pgaddr(d: u32, t: u32, o: u32) -> u32 {
(d << PDXSHIFT) | (t << PTXSHIFT) | o
}

// Extract address from page table entry
#[inline]
pub fn pte_addr(pte: u32) -> u32 {
pte & !0xFFF
}

// Extract flags from page table entry
#[inline]
pub fn pte_flags(pte: u32) -> u32 {
pte & 0xFFF
}
2 changes: 2 additions & 0 deletions src/param.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub const NPROC: usize = 64; // maximum number of processes
pub const KSTACKSIZE: usize = 4096; // size of per-process kernel stack (unused in p3)
pub const NCPU: usize = 8; // maximum number of CPUs
pub const MAXOPBLOCKS: usize = 10; // max # of blocks any FS op writes
pub const NOFILE: usize = 16; // open files per process
pub const NFILE: usize = 100; // open files per system
pub const NINODE: usize = 50; // maximum number of active i-nodes
pub const NDEV: usize = 10; // maximum major device number
Expand Down
Loading