Merge branch 'master' of github.com:redox-os/kernel
This commit is contained in:
commit
1c9b6361c9
|
@ -3,8 +3,12 @@ name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
path = "kernel/lib.rs"
|
||||||
crate-type = ["staticlib"]
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
|
arch = { path = "arch/x86_64" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "*"
|
bitflags = "*"
|
||||||
|
|
||||||
|
|
6
arch/x86_64/Cargo.toml
Normal file
6
arch/x86_64/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "arch"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bitflags = "*"
|
19
arch/x86_64/src/interrupt.rs
Normal file
19
arch/x86_64/src/interrupt.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//! Interrupt instructions
|
||||||
|
|
||||||
|
/// Clear interrupts
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn clear_interrupts() {
|
||||||
|
asm!("cli" : : : : "intel", "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set interrupts
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn set_interrupts() {
|
||||||
|
asm!("sti" : : : : "intel", "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Halt instruction
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn halt() {
|
||||||
|
asm!("hlt" : : : : "intel", "volatile");
|
||||||
|
}
|
94
arch/x86_64/src/lib.rs
Normal file
94
arch/x86_64/src/lib.rs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
//! Architecture support for x86_64
|
||||||
|
|
||||||
|
#![feature(asm)]
|
||||||
|
#![feature(concat_idents)]
|
||||||
|
#![feature(const_fn)]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(naked_functions)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
|
|
||||||
|
/// Print to console
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! print {
|
||||||
|
($($arg:tt)*) => ({
|
||||||
|
use core::fmt::Write;
|
||||||
|
let _ = write!($crate::serial::SerialConsole::new(), $($arg)*);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)*));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an interrupt function that can safely run rust code
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! interrupt {
|
||||||
|
($name:ident, $func:block) => {
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern fn $name () {
|
||||||
|
unsafe fn inner() {
|
||||||
|
$func
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push scratch registers
|
||||||
|
asm!("push rax
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
push r11"
|
||||||
|
: : : : "intel", "volatile");
|
||||||
|
|
||||||
|
// Call inner rust function
|
||||||
|
inner();
|
||||||
|
|
||||||
|
// Pop scratch registers and return
|
||||||
|
asm!("pop r11
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rsi
|
||||||
|
pop rdi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
|
pop rax
|
||||||
|
iretq"
|
||||||
|
: : : : "intel", "volatile");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Global descriptor table
|
||||||
|
pub mod gdt;
|
||||||
|
|
||||||
|
/// Interrupt descriptor table
|
||||||
|
pub mod idt;
|
||||||
|
|
||||||
|
/// IO Handling
|
||||||
|
pub mod io;
|
||||||
|
|
||||||
|
/// Interrupt instructions
|
||||||
|
pub mod interrupt;
|
||||||
|
|
||||||
|
/// Initialization and main function
|
||||||
|
pub mod main;
|
||||||
|
|
||||||
|
/// Memcpy, memmove, etc.
|
||||||
|
pub mod mem;
|
||||||
|
|
||||||
|
/// Serial driver and print! support
|
||||||
|
pub mod serial;
|
||||||
|
|
||||||
|
/// Task state segment
|
||||||
|
pub mod tss;
|
||||||
|
|
||||||
|
pub mod physical;
|
|
@ -30,8 +30,12 @@ static BSS_TEST_ZERO: usize = 0;
|
||||||
/// Test of non-zero values in BSS.
|
/// Test of non-zero values in BSS.
|
||||||
static BSS_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF;
|
static BSS_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF;
|
||||||
|
|
||||||
|
extern {
|
||||||
|
fn kmain() -> !;
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn kmain() {
|
pub unsafe extern fn kstart() -> ! {
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
||||||
|
|
||||||
// Zero BSS, this initializes statics that are set to 0
|
// Zero BSS, this initializes statics that are set to 0
|
||||||
|
@ -44,8 +48,8 @@ pub unsafe extern "C" fn kmain() {
|
||||||
memset(start_ptr, 0, size);
|
memset(start_ptr, 0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//debug_assert_eq!(BSS_TEST_ZERO, 0);
|
debug_assert_eq!(BSS_TEST_ZERO, 0);
|
||||||
//debug_assert_eq!(BSS_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
|
debug_assert_eq!(BSS_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
||||||
|
@ -64,15 +68,9 @@ pub unsafe extern "C" fn kmain() {
|
||||||
|
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
||||||
|
|
||||||
print!("TEST\n");
|
kmain();
|
||||||
|
|
||||||
loop{
|
|
||||||
asm!("hlt" : : : : "intel", "volatile");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
interrupt!(blank, {
|
||||||
pub unsafe extern "C" fn blank() {
|
println!("INTERRUPT");
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
});
|
||||||
asm!("iretq" : : : : "intel", "volatile");
|
|
||||||
}
|
|
|
@ -1,8 +1,9 @@
|
||||||
/// Copy memory.
|
/// Memcpy
|
||||||
///
|
///
|
||||||
/// Copy N bytes of memory from one location to another.
|
/// Copy N bytes of memory from one location to another.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
|
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
|
||||||
|
n: usize) -> *mut u8 {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < n {
|
while i < n {
|
||||||
*dest.offset(i as isize) = *src.offset(i as isize);
|
*dest.offset(i as isize) = *src.offset(i as isize);
|
||||||
|
@ -12,7 +13,7 @@ pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8
|
||||||
dest
|
dest
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy (possibly overlapping) memory.
|
/// Memmove
|
||||||
///
|
///
|
||||||
/// Copy N bytes of memory from src to dest. The memory areas may overlap.
|
/// Copy N bytes of memory from src to dest. The memory areas may overlap.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -35,7 +36,7 @@ pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
|
||||||
dest
|
dest
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set memory.
|
/// Memset
|
||||||
///
|
///
|
||||||
/// Fill a block of memory with a specified value.
|
/// Fill a block of memory with a specified value.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -49,7 +50,7 @@ pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare memory.
|
/// Memcmp
|
||||||
///
|
///
|
||||||
/// Compare two blocks of memory.
|
/// Compare two blocks of memory.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
20
arch/x86_64/src/tss.rs
Normal file
20
arch/x86_64/src/tss.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#[repr(packed)]
|
||||||
|
pub struct Tss {
|
||||||
|
pub reserved1: u32,
|
||||||
|
pub sp0: u64,
|
||||||
|
pub sp1: u64,
|
||||||
|
pub sp2: u64,
|
||||||
|
pub reserved2: u32,
|
||||||
|
pub reserved3: u32,
|
||||||
|
pub ist1: u64,
|
||||||
|
pub ist2: u64,
|
||||||
|
pub ist3: u64,
|
||||||
|
pub ist4: u64,
|
||||||
|
pub ist5: u64,
|
||||||
|
pub ist6: u64,
|
||||||
|
pub ist7: u64,
|
||||||
|
pub reserved4: u32,
|
||||||
|
pub reserved5: u32,
|
||||||
|
pub reserved6: u16,
|
||||||
|
pub iomap_base: u16,
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
ENTRY(kmain)
|
ENTRY(kstart)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
kernel_base = 0x101000;
|
kernel_base = 0x101000;
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
//! Architecture specific items
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pub use self::x86_64::*;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pub mod x86_64;
|
|
|
@ -1,10 +0,0 @@
|
||||||
//! # IRQ handling
|
|
||||||
//!
|
|
||||||
//! This module defines IRQ handling functions. These functions should all be #[naked],
|
|
||||||
//! unsafe, extern, and end in `iretq`
|
|
||||||
|
|
||||||
/// Interupt Request handler.
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern fn irq() {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
//! X86_64 architecture primitives.
|
|
||||||
|
|
||||||
/// Global descriptor table.
|
|
||||||
pub mod gdt;
|
|
||||||
|
|
||||||
/// Interrupt descriptor table.
|
|
||||||
pub mod idt;
|
|
||||||
|
|
||||||
/// IO handling.
|
|
||||||
pub mod io;
|
|
||||||
|
|
||||||
/// IRQ handling.
|
|
||||||
pub mod irq;
|
|
||||||
|
|
||||||
/// Initialization and main function.
|
|
||||||
pub mod main;
|
|
||||||
|
|
||||||
/// Core memory routines.
|
|
||||||
pub mod mem;
|
|
||||||
|
|
||||||
/// Serial driver and `print!` support.
|
|
||||||
pub mod serial;
|
|
||||||
|
|
||||||
/// Task state segment.
|
|
||||||
pub mod tss;
|
|
||||||
|
|
||||||
pub mod physical;
|
|
|
@ -1,22 +0,0 @@
|
||||||
/// The Task State Segment.
|
|
||||||
#[repr(C, packed)]
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct Tss {
|
|
||||||
/// Reserved.
|
|
||||||
pub _reserved1: u32,
|
|
||||||
/// The stack-pointers (reg RSP) for the IO privilege level 0 through 2.
|
|
||||||
pub rsp: [u64; 3],
|
|
||||||
/// Reserved.
|
|
||||||
pub _reserved2: u32,
|
|
||||||
/// Reserved.
|
|
||||||
pub _reserved3: u32,
|
|
||||||
pub ist: [u64; 7],
|
|
||||||
/// Reserved.
|
|
||||||
pub _reserved4: u32,
|
|
||||||
/// Reserved.
|
|
||||||
pub _reserved5: u32,
|
|
||||||
// Reserved.
|
|
||||||
pub reserved6: u16,
|
|
||||||
/// The offset to the IOPB.
|
|
||||||
pub iomap_base: u16,
|
|
||||||
}
|
|
|
@ -64,45 +64,27 @@
|
||||||
//! An error will be returned, `ENOBUFS`, if the buffer is not long enough for the name.
|
//! An error will be returned, `ENOBUFS`, if the buffer is not long enough for the name.
|
||||||
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
|
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
|
||||||
|
|
||||||
#![feature(asm)]
|
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(core_intrinsics)]
|
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(naked_functions)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
|
||||||
/// Print to console
|
use arch::interrupt::{set_interrupts, halt};
|
||||||
macro_rules! print {
|
|
||||||
($($arg:tt)*) => ({
|
|
||||||
use $crate::core::fmt::Write;
|
|
||||||
let _ = write!($crate::arch::serial::SerialConsole::new(), $($arg)*);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Print with new line to console
|
|
||||||
macro_rules! println {
|
|
||||||
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
|
||||||
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Architecture specific items
|
/// Architecture specific items
|
||||||
pub mod arch;
|
#[macro_use]
|
||||||
|
extern crate arch;
|
||||||
|
|
||||||
#[cfg(not(test))]
|
/// Intrinsics for panic handling
|
||||||
#[lang = "eh_personality"]
|
pub mod panic;
|
||||||
extern "C" fn eh_personality() {}
|
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
/// Required to handle panics
|
|
||||||
#[lang = "panic_fmt"]
|
|
||||||
extern "C" fn panic_fmt() -> ! {loop{}}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
/// Required to handle panics
|
pub extern fn kmain() {
|
||||||
pub extern "C" fn _Unwind_Resume() -> ! {
|
println!("TEST");
|
||||||
loop {}
|
|
||||||
|
unsafe { set_interrupts() };
|
||||||
|
loop {
|
||||||
|
unsafe { halt() };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
25
kernel/panic.rs
Normal file
25
kernel/panic.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//! Intrinsics for panic handling
|
||||||
|
|
||||||
|
use arch::interrupt::halt;
|
||||||
|
|
||||||
|
#[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() -> ! {
|
||||||
|
loop {
|
||||||
|
unsafe { halt() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Required to handle panics
|
||||||
|
pub extern "C" fn _Unwind_Resume() -> ! {
|
||||||
|
loop {
|
||||||
|
unsafe { halt() }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue