redox/kernel/lib.rs

179 lines
4.5 KiB
Rust
Raw Normal View History

2016-08-14 00:34:27 +02:00
//! # The Redox OS Kernel, version 2
//!
2016-11-04 20:38:40 +01:00
//! The Redox OS Kernel is a hybrid kernel that supports X86_64 systems and
2016-08-14 00:34:27 +02:00
//! provides Unix-like syscalls for primarily Rust applications
2016-08-14 02:21:46 +02:00
2016-08-15 06:05:32 +02:00
#![feature(alloc)]
2016-10-07 02:46:24 +02:00
#![feature(arc_counts)]
#![feature(asm)]
2016-08-15 06:05:32 +02:00
#![feature(collections)]
2016-08-15 02:16:56 +02:00
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(drop_types_in_const)]
2016-09-23 00:14:45 +02:00
#![feature(heap_api)]
#![feature(integer_atomics)]
2016-09-12 05:04:34 +02:00
#![feature(never_type)]
#![feature(thread_local)]
2016-08-14 02:21:46 +02:00
#![no_std]
use arch::interrupt;
2016-08-14 22:59:18 +02:00
/// Architecture specific items (test)
#[cfg(test)]
2016-08-14 19:45:47 +02:00
#[macro_use]
2016-08-14 22:59:18 +02:00
extern crate arch_test as arch;
2016-08-26 01:03:01 +02:00
/// Architecture specific items (ARM)
#[cfg(all(not(test), target_arch = "arm"))]
#[macro_use]
extern crate arch_arm as arch;
2016-08-14 22:59:18 +02:00
/// Architecture specific items (x86_64)
#[cfg(all(not(test), target_arch = "x86_64"))]
#[macro_use]
extern crate arch_x86_64 as arch;
2016-08-14 02:21:46 +02:00
2016-08-15 06:05:32 +02:00
extern crate alloc;
#[macro_use]
extern crate collections;
2016-08-16 19:04:14 +02:00
#[macro_use]
extern crate bitflags;
2016-08-19 15:57:24 +02:00
extern crate goblin;
2016-08-16 19:04:14 +02:00
extern crate spin;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
2016-08-15 02:16:56 +02:00
/// Context management
pub mod context;
#[macro_use]
/// Shared data structures
pub mod common;
/// ELF file parsing
2016-08-26 01:03:01 +02:00
#[cfg(all(not(test), target_arch = "x86_64"))]
pub mod elf;
2016-08-15 05:38:32 +02:00
/// Schemes, filesystem handlers
pub mod scheme;
/// Synchronization primitives
pub mod sync;
2016-08-14 23:58:35 +02:00
/// Syscall handlers
pub mod syscall;
2016-08-14 22:59:18 +02:00
/// Tests
#[cfg(test)]
pub mod tests;
2016-11-04 03:29:19 +01:00
/// A unique number that identifies the current CPU - used for scheduling
#[thread_local]
static CPU_ID: AtomicUsize = ATOMIC_USIZE_INIT;
2016-11-04 03:29:19 +01:00
/// Get the current CPU's scheduling ID
#[inline(always)]
pub fn cpu_id() -> usize {
CPU_ID.load(Ordering::Relaxed)
}
2016-11-04 03:29:19 +01:00
/// The count of all CPUs that can have work scheduled
static CPU_COUNT : AtomicUsize = ATOMIC_USIZE_INIT;
2016-11-04 03:29:19 +01:00
/// Get the number of CPUs currently active
#[inline(always)]
pub fn cpu_count() -> usize {
CPU_COUNT.load(Ordering::Relaxed)
}
2016-11-04 03:29:19 +01:00
/// Initialize userspace by running the initfs:bin/init process
/// This function will also set the CWD to initfs:bin and open debug: as stdio
2016-09-11 06:06:09 +02:00
pub extern fn userspace_init() {
2016-09-27 01:39:58 +02:00
assert_eq!(syscall::chdir(b"initfs:bin"), Ok(0));
2016-09-11 06:06:09 +02:00
assert_eq!(syscall::open(b"debug:", 0), Ok(0));
assert_eq!(syscall::open(b"debug:", 0), Ok(1));
assert_eq!(syscall::open(b"debug:", 0), Ok(2));
2016-08-24 18:35:42 +02:00
syscall::exec(b"initfs:bin/init", &[]).expect("failed to execute initfs:init");
2016-09-11 06:06:09 +02:00
panic!("initfs:init returned")
2016-08-24 18:35:42 +02:00
}
/// Allow exception handlers to send signal to arch-independant kernel
#[no_mangle]
pub extern fn ksignal(signal: usize) {
println!("SIGNAL {}, CPU {}, PID {}", signal, cpu_id(), context::context_id());
{
let contexts = context::contexts();
if let Some(context_lock) = contexts.current() {
let context = context_lock.read();
println!("NAME {}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) });
}
}
}
2016-11-04 03:29:19 +01:00
/// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this
#[no_mangle]
pub extern fn kmain(cpus: usize) {
CPU_ID.store(0, Ordering::SeqCst);
CPU_COUNT.store(cpus, Ordering::SeqCst);
2016-08-20 22:32:45 +02:00
context::init();
2016-09-01 19:51:33 +02:00
let pid = syscall::getpid();
println!("BSP: {:?} {}", pid, cpus);
match context::contexts_mut().spawn(userspace_init) {
Ok(context_lock) => {
let mut context = context_lock.write();
context.status = context::Status::Runnable;
},
Err(err) => {
panic!("failed to spawn userspace_init: {:?}", err);
}
}
2016-08-24 18:35:42 +02:00
2016-08-14 19:45:47 +02:00
loop {
2016-09-15 16:39:20 +02:00
unsafe {
interrupt::disable();
2016-09-23 23:47:53 +02:00
if context::switch() {
interrupt::enable_and_nop();
} else {
// Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired.
2016-09-23 23:47:53 +02:00
interrupt::enable_and_halt();
}
2016-09-15 16:39:20 +02:00
}
}
}
2016-11-04 03:29:19 +01:00
/// This is the main kernel entry point for secondary CPUs
#[no_mangle]
pub extern fn kmain_ap(id: usize) {
CPU_ID.store(id, Ordering::SeqCst);
2016-08-20 22:32:45 +02:00
context::init();
2016-09-01 19:51:33 +02:00
let pid = syscall::getpid();
println!("AP {}: {:?}", id, pid);
2016-11-04 20:38:40 +01:00
// Disable APs for now
loop {
unsafe { interrupt::enable_and_halt(); }
}
loop {
unsafe {
interrupt::disable();
if context::switch() {
interrupt::enable_and_nop();
} else {
// Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired.
interrupt::enable_and_halt();
}
}
2016-08-14 19:45:47 +02:00
}
}