From 6715d5c5348184ab8a4e36c5667d354b09d27eb3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 25 Aug 2016 17:03:01 -0600 Subject: [PATCH] Arm! --- Cargo.toml | 4 ++ Makefile | 53 ++++++++------ arch/arm/Cargo.toml | 8 +++ arch/arm/src/context.rs | 9 +++ arch/arm/src/externs.rs | 70 +++++++++++++++++++ arch/arm/src/interrupt.rs | 30 ++++++++ arch/arm/src/lib.rs | 39 +++++++++++ arch/arm/src/linker.ld | 60 ++++++++++++++++ arch/arm/src/panic.rs | 38 ++++++++++ arch/arm/src/start.rs | 27 +++++++ .../kernel.ld => arch/x86_64/src/linker.ld | 0 arm-unknown-none.json | 25 +++++++ bootloader/arm/start.s | 17 +++++ bootloader/{x86 => x86_64}/bootsector.asm | 0 .../{x86 => x86_64}/descriptor_flags.inc | 0 bootloader/{x86 => x86_64}/gdt_entry.inc | 0 bootloader/{x86 => x86_64}/harddrive.asm | 0 bootloader/{x86 => x86_64}/initialize.asm | 0 bootloader/{x86 => x86_64}/memory_map.asm | 0 bootloader/{x86 => x86_64}/print16.asm | 0 bootloader/{x86 => x86_64}/startup-common.asm | 0 bootloader/{x86 => x86_64}/startup-i386.asm | 0 bootloader/{x86 => x86_64}/startup-x86_64.asm | 0 bootloader/{x86 => x86_64}/unreal.asm | 0 bootloader/{x86 => x86_64}/vesa.asm | 0 bootloader/{x86 => x86_64}/vesa.inc | 0 kernel/console.rs | 15 ++++ kernel/lib.rs | 10 +++ kernel/scheme/debug.rs | 1 + 29 files changed, 385 insertions(+), 21 deletions(-) create mode 100644 arch/arm/Cargo.toml create mode 100644 arch/arm/src/context.rs create mode 100644 arch/arm/src/externs.rs create mode 100644 arch/arm/src/interrupt.rs create mode 100644 arch/arm/src/lib.rs create mode 100644 arch/arm/src/linker.ld create mode 100644 arch/arm/src/panic.rs create mode 100644 arch/arm/src/start.rs rename bootloader/x86/kernel.ld => arch/x86_64/src/linker.ld (100%) create mode 100644 arm-unknown-none.json create mode 100644 bootloader/arm/start.s rename bootloader/{x86 => x86_64}/bootsector.asm (100%) rename bootloader/{x86 => x86_64}/descriptor_flags.inc (100%) rename bootloader/{x86 => x86_64}/gdt_entry.inc (100%) rename bootloader/{x86 => x86_64}/harddrive.asm (100%) rename bootloader/{x86 => x86_64}/initialize.asm (100%) rename bootloader/{x86 => x86_64}/memory_map.asm (100%) rename bootloader/{x86 => x86_64}/print16.asm (100%) rename bootloader/{x86 => x86_64}/startup-common.asm (100%) rename bootloader/{x86 => x86_64}/startup-i386.asm (100%) rename bootloader/{x86 => x86_64}/startup-x86_64.asm (100%) rename bootloader/{x86 => x86_64}/unreal.asm (100%) rename bootloader/{x86 => x86_64}/vesa.asm (100%) rename bootloader/{x86 => x86_64}/vesa.inc (100%) create mode 100644 kernel/console.rs diff --git a/Cargo.toml b/Cargo.toml index 1dafca6..661a78f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["staticlib"] [dependencies] bitflags = "*" +ransid = "*" spin = "*" [dependencies.goblin] @@ -19,6 +20,9 @@ features = ["no_mach", "no_mach32", "no_pe", "no_pe32", "no_endian_fd", "pure"] [dev-dependencies] arch_test = { path = "arch/test" } +[target.'cfg(target_arch = "arm")'.dependencies] +arch_arm = { path = "arch/arm" } + [target.'cfg(target_arch = "x86_64")'.dependencies] arch_x86_64 = { path = "arch/x86_64" } diff --git a/Makefile b/Makefile index 0e0057c..82e97b1 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,27 @@ -ARCH?=x86_64 +ARCH?=arm -LD=ld QEMU=qemu-system-$(ARCH) -QEMUFLAGS=-enable-kvm -cpu host +QEMUFLAGS=-serial mon:stdio -d guest_errors -UNAME := $(shell uname) -ifeq ($(UNAME),Darwin) - LD=$(ARCH)-elf-ld - QEMUFLAGS= +ifeq ($(ARCH),arm) + LD=$(ARCH)-none-eabi-ld + QEMUFLAGS+=-cpu arm1176 -machine integratorcp + QEMUFLAGS+=-nographic +else + LD=ld + QEMUFLAGS+=-enable-kvm -cpu host -machine q35 -smp 4 + #,int,pcall + #-nographic + #-device intel-iommu + + UNAME := $(shell uname) + ifeq ($(UNAME),Darwin) + LD=$(ARCH)-elf-ld + QEMUFLAGS= + endif endif -QEMUFLAGS+=-smp 4 -machine q35 -QEMUFLAGS+=-serial mon:stdio -QEMUFLAGS+=-d guest_errors -#,int,pcall -#-nographic -#-device intel-iommu - - -all: build/harddrive.bin +all: build/kernel.bin list: build/kernel.list @@ -27,9 +30,6 @@ run: bochs bochs: build/harddrive.bin bochs -f bochs.$(ARCH) -qemu: build/harddrive.bin - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw,index=0,media=disk - FORCE: build/libcore.rlib: rust/src/libcore/lib.rs @@ -53,13 +53,24 @@ build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.r RUSTC="./rustc.sh" cargo rustc --target $(ARCH)-unknown-none.json -- -C soft-float -o $@ build/kernel.bin: build/libkernel.a - $(LD) --gc-sections -z max-page-size=0x1000 -T bootloader/x86/kernel.ld -o $@ $< + $(LD) --gc-sections -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $< +ifeq ($(ARCH),arm) +build/kernel.list: build/kernel.bin + $(ARCH)-none-eabi-objdump -C -D $< > $@ + +qemu: build/kernel.bin + $(QEMU) $(QEMUFLAGS) -kernel $< +else build/kernel.list: build/kernel.bin objdump -C -M intel -D $< > $@ build/harddrive.bin: build/kernel.bin - nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/x86/ -ibuild/ bootloader/x86/harddrive.asm + nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ -ibuild/ bootloader/$(ARCH)/harddrive.asm + +qemu: build/harddrive.bin + $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw,index=0,media=disk +endif clean: rm -rf build/* target/* diff --git a/arch/arm/Cargo.toml b/arch/arm/Cargo.toml new file mode 100644 index 0000000..b01e511 --- /dev/null +++ b/arch/arm/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "arch_arm" +version = "0.1.0" + +[dependencies] +bitflags = "*" +hole_list_allocator = { path = "../../alloc/hole_list_allocator"} +spin = "*" diff --git a/arch/arm/src/context.rs b/arch/arm/src/context.rs new file mode 100644 index 0000000..db711c3 --- /dev/null +++ b/arch/arm/src/context.rs @@ -0,0 +1,9 @@ +#[derive(Debug)] +pub struct Context; + +impl Context { + pub fn new() -> Self { + Context + } +} + diff --git a/arch/arm/src/externs.rs b/arch/arm/src/externs.rs new file mode 100644 index 0000000..3b87427 --- /dev/null +++ b/arch/arm/src/externs.rs @@ -0,0 +1,70 @@ +/// Memcpy +/// +/// Copy N bytes of memory from one location to another. +#[no_mangle] +pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *dest.offset(i as isize) = *src.offset(i as isize); + i += 1; + } + + dest +} + +/// Memmove +/// +/// Copy N bytes of memory from src to dest. The memory areas may overlap. +#[no_mangle] +pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + if src < dest as *const u8 { + let mut i = n; + while i != 0 { + i -= 1; + *dest.offset(i as isize) = *src.offset(i as isize); + } + } else { + let mut i = 0; + while i < n { + *dest.offset(i as isize) = *src.offset(i as isize); + i += 1; + } + } + + dest +} + +/// Memset +/// +/// Fill a block of memory with a specified value. +#[no_mangle] +pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *s.offset(i as isize) = c as u8; + i += 1; + } + + s +} + +/// Memcmp +/// +/// Compare two blocks of memory. +#[no_mangle] +pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + let mut i = 0; + + while i < n { + let a = *s1.offset(i as isize); + let b = *s2.offset(i as isize); + if a != b { + return a as i32 - b as i32 + } + i += 1; + } + + 0 +} diff --git a/arch/arm/src/interrupt.rs b/arch/arm/src/interrupt.rs new file mode 100644 index 0000000..6d7d460 --- /dev/null +++ b/arch/arm/src/interrupt.rs @@ -0,0 +1,30 @@ +//! Interrupt instructions + +/// Clear interrupts +#[inline(always)] +pub unsafe fn disable() { +} + +/// Set interrupts +#[inline(always)] +pub unsafe fn enable() { +} + +/// Set interrupts and halt +#[inline(always)] +pub unsafe fn enable_and_halt() { + halt(); +} + +/// Halt instruction +#[inline(always)] +pub unsafe fn halt() { + //asm!("wfi" : : : : "volatile"); + asm!("nop" : : : : "volatile"); +} + +/// Get a stack trace +//TODO: Check for stack being mapped before dereferencing +#[inline(never)] +pub unsafe fn stack_trace() { +} diff --git a/arch/arm/src/lib.rs b/arch/arm/src/lib.rs new file mode 100644 index 0000000..77b0e9c --- /dev/null +++ b/arch/arm/src/lib.rs @@ -0,0 +1,39 @@ +//! Architecture support for ARM + +#![feature(asm)] +#![feature(lang_items)] +#![feature(naked_functions)] +#![no_std] + +extern crate hole_list_allocator as allocator; +#[macro_use] +extern crate bitflags; +extern crate spin; + +/// Print to console +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ({}); +} + +/// Print with new line to console +#[macro_export] +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +/// Context switching +pub mod context; + +/// Memset, memcpy, etc. +pub mod externs; + +/// Interrupt handling +pub mod interrupt; + +/// Panic support +pub mod panic; + +/// Initialization function +pub mod start; diff --git a/arch/arm/src/linker.ld b/arch/arm/src/linker.ld new file mode 100644 index 0000000..71fd23e --- /dev/null +++ b/arch/arm/src/linker.ld @@ -0,0 +1,60 @@ +ENTRY(kstart) +OUTPUT_ARCH(arm) +OUTPUT_FORMAT(elf32-littlearm) + +KERNEL_OFFSET = 0; + +SECTIONS { + . = KERNEL_OFFSET; + + .text : AT(ADDR(.text) - KERNEL_OFFSET) { + __text_start = .; + *(.text*) + . = ALIGN(4096); + __text_end = .; + } + + .rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) { + __rodata_start = .; + *(.rodata*) + . = ALIGN(4096); + __rodata_end = .; + } + + .data : AT(ADDR(.data) - KERNEL_OFFSET) { + __data_start = .; + *(.data*) + . = ALIGN(4096); + __data_end = .; + } + + .tdata : AT(ADDR(.tdata) - KERNEL_OFFSET) { + __tdata_start = .; + *(.tdata*) + . = ALIGN(4096); + __tdata_end = .; + __tbss_start = .; + *(.tbss*) + . += 8; + . = ALIGN(4096); + __tbss_end = .; + } + + .bss : AT(ADDR(.bss) - KERNEL_OFFSET) { + __bss_start = .; + *(.bss*) + . = ALIGN(4096); + __bss_end = .; + } + + __end = .; + + /DISCARD/ : { + *(.comment*) + *(.debug*) + *(.eh_frame*) + *(.gcc_except_table*) + *(.note*) + *(.rel.eh_frame*) + } +} diff --git a/arch/arm/src/panic.rs b/arch/arm/src/panic.rs new file mode 100644 index 0000000..2acb38e --- /dev/null +++ b/arch/arm/src/panic.rs @@ -0,0 +1,38 @@ +//! Intrinsics for panic handling + +use interrupt; + +#[cfg(not(test))] +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[cfg(not(test))] +/// Required to handle panics +#[lang = "panic_fmt"] +extern "C" fn panic_fmt(fmt: ::core::fmt::Arguments, file: &str, line: u32) -> ! { + println!("PANIC: {}", fmt); + println!("FILE: {}", file); + println!("LINE: {}", line); + + unsafe { interrupt::stack_trace(); } + + println!("HALT"); + loop { + unsafe { interrupt::halt(); } + } +} + +#[allow(non_snake_case)] +#[no_mangle] +/// Required to handle panics +pub extern "C" fn _Unwind_Resume() -> ! { + loop { + unsafe { interrupt::halt(); } + } +} + +/// Required for linker +#[no_mangle] +pub extern "C" fn __aeabi_unwind_cpp_pr0() { + loop {} +} diff --git a/arch/arm/src/start.rs b/arch/arm/src/start.rs new file mode 100644 index 0000000..b9abbe6 --- /dev/null +++ b/arch/arm/src/start.rs @@ -0,0 +1,27 @@ +const SERIAL_BASE: *mut u8 = 0x16000000 as *mut u8; +const SERIAL_FLAG_REGISTER: *const u8 = 0x16000018 as *const u8; +const SERIAL_BUFFER_FULL: u8 = (1 << 5); + +unsafe fn putc (c: u8) +{ + /* Wait until the serial buffer is empty */ + while *SERIAL_FLAG_REGISTER & SERIAL_BUFFER_FULL == SERIAL_BUFFER_FULL {} + + /* Put our character, c, into the serial buffer */ + *SERIAL_BASE = c; +} + +unsafe fn puts(string: &str) +{ + for b in string.bytes() { + putc(b); + } +} + +#[no_mangle] +#[naked] +pub unsafe extern fn kstart() -> ! { + asm!("mov sp, 0x18000" : : : : "volatile"); + puts("TEST\r\n"); + loop {} +} diff --git a/bootloader/x86/kernel.ld b/arch/x86_64/src/linker.ld similarity index 100% rename from bootloader/x86/kernel.ld rename to arch/x86_64/src/linker.ld diff --git a/arm-unknown-none.json b/arm-unknown-none.json new file mode 100644 index 0000000..bf1f6bd --- /dev/null +++ b/arm-unknown-none.json @@ -0,0 +1,25 @@ +{ + "llvm-target": "arm-unknown-none", + "target-endian": "little", + "target-pointer-width": "32", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "arch": "arm", + "os": "none", + "env": "", + "vendor": "unknown", + "target-family": "redox", + "pre-link-args": ["-m32", "-nostdlib", "-static"], + "features": "+soft-float", + "dynamic-linking": false, + "executables": false, + "relocation-model": "static", + "code-model": "kernel", + "disable-redzone": true, + "eliminate-frame-pointer": false, + "exe-suffix": "", + "has-rpath": false, + "no-compiler-rt": true, + "no-default-libraries": true, + "position-independent-executables": false, + "has-elf-tls": true +} diff --git a/bootloader/arm/start.s b/bootloader/arm/start.s new file mode 100644 index 0000000..8495600 --- /dev/null +++ b/bootloader/arm/start.s @@ -0,0 +1,17 @@ +interrupt_vector_table: + b . @ Reset + b . + b . @ SWI instruction + b . + b . + b . + b . + b . + +.comm stack, 0x10000 @ Reserve 64k stack in the BSS +_start: + .globl _start + ldr sp, =stack+0x10000 @ Set up the stack + bl kstart @ Jump to the main function +1: + b 1b @ Halt diff --git a/bootloader/x86/bootsector.asm b/bootloader/x86_64/bootsector.asm similarity index 100% rename from bootloader/x86/bootsector.asm rename to bootloader/x86_64/bootsector.asm diff --git a/bootloader/x86/descriptor_flags.inc b/bootloader/x86_64/descriptor_flags.inc similarity index 100% rename from bootloader/x86/descriptor_flags.inc rename to bootloader/x86_64/descriptor_flags.inc diff --git a/bootloader/x86/gdt_entry.inc b/bootloader/x86_64/gdt_entry.inc similarity index 100% rename from bootloader/x86/gdt_entry.inc rename to bootloader/x86_64/gdt_entry.inc diff --git a/bootloader/x86/harddrive.asm b/bootloader/x86_64/harddrive.asm similarity index 100% rename from bootloader/x86/harddrive.asm rename to bootloader/x86_64/harddrive.asm diff --git a/bootloader/x86/initialize.asm b/bootloader/x86_64/initialize.asm similarity index 100% rename from bootloader/x86/initialize.asm rename to bootloader/x86_64/initialize.asm diff --git a/bootloader/x86/memory_map.asm b/bootloader/x86_64/memory_map.asm similarity index 100% rename from bootloader/x86/memory_map.asm rename to bootloader/x86_64/memory_map.asm diff --git a/bootloader/x86/print16.asm b/bootloader/x86_64/print16.asm similarity index 100% rename from bootloader/x86/print16.asm rename to bootloader/x86_64/print16.asm diff --git a/bootloader/x86/startup-common.asm b/bootloader/x86_64/startup-common.asm similarity index 100% rename from bootloader/x86/startup-common.asm rename to bootloader/x86_64/startup-common.asm diff --git a/bootloader/x86/startup-i386.asm b/bootloader/x86_64/startup-i386.asm similarity index 100% rename from bootloader/x86/startup-i386.asm rename to bootloader/x86_64/startup-i386.asm diff --git a/bootloader/x86/startup-x86_64.asm b/bootloader/x86_64/startup-x86_64.asm similarity index 100% rename from bootloader/x86/startup-x86_64.asm rename to bootloader/x86_64/startup-x86_64.asm diff --git a/bootloader/x86/unreal.asm b/bootloader/x86_64/unreal.asm similarity index 100% rename from bootloader/x86/unreal.asm rename to bootloader/x86_64/unreal.asm diff --git a/bootloader/x86/vesa.asm b/bootloader/x86_64/vesa.asm similarity index 100% rename from bootloader/x86/vesa.asm rename to bootloader/x86_64/vesa.asm diff --git a/bootloader/x86/vesa.inc b/bootloader/x86_64/vesa.inc similarity index 100% rename from bootloader/x86/vesa.inc rename to bootloader/x86_64/vesa.inc diff --git a/kernel/console.rs b/kernel/console.rs new file mode 100644 index 0000000..d2dfeca --- /dev/null +++ b/kernel/console.rs @@ -0,0 +1,15 @@ +use ransid::Console; +use spin::{Once, Mutex, MutexGuard}; + +/// Console +static CONSOLE: Once> = Once::new(); + +/// Initialize console, called if needed +fn init_console() -> Mutex { + Mutex::new(Console::new(0, 0)) +} + +/// Get the global console +pub fn console() -> MutexGuard<'static, Console> { + CONSOLE.call_once(init_console).lock() +} diff --git a/kernel/lib.rs b/kernel/lib.rs index f4c85f0..3b1d6eb 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -80,6 +80,11 @@ use arch::interrupt; #[macro_use] extern crate arch_test as arch; +/// Architecture specific items (ARM) +#[cfg(all(not(test), target_arch = "arm"))] +#[macro_use] +extern crate arch_arm as arch; + /// Architecture specific items (x86_64) #[cfg(all(not(test), target_arch = "x86_64"))] #[macro_use] @@ -92,12 +97,17 @@ extern crate collections; #[macro_use] extern crate bitflags; extern crate goblin; +extern crate ransid; extern crate spin; +/// Console +pub mod console; + /// Context management pub mod context; /// ELF file parsing +#[cfg(all(not(test), target_arch = "x86_64"))] pub mod elf; /// Schemes, filesystem handlers diff --git a/kernel/scheme/debug.rs b/kernel/scheme/debug.rs index 43882ae..0555b09 100644 --- a/kernel/scheme/debug.rs +++ b/kernel/scheme/debug.rs @@ -1,4 +1,5 @@ use core::str; + use syscall::Result; use super::Scheme;