1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 00:16:17 +04:00

aarch64: context switch is runnable!

This commit is contained in:
equation314 2018-11-07 22:07:48 +08:00
parent 67b920cc16
commit 5610d0bdb0
11 changed files with 109 additions and 82 deletions

View File

@ -5,8 +5,7 @@ use super::bcm2837::interrupt::{Controller, Interrupt};
pub fn handle_irq(tf: &mut TrapFrame) {
let controller = Timer::new();
if controller.is_pending() {
println!("Timer tick {}...", super::timer::get_cycle());
super::timer::set_next();
// ::trap::timer();
::trap::timer();
}
}

View File

@ -12,6 +12,6 @@ pub fn get_cycle() -> u64 {
}
pub fn set_next() {
// 1000 ms
timer::tick_in(1000 * 1000);
// 10 ms
timer::tick_in(10 * 1000);
}

View File

@ -18,6 +18,9 @@ setup:
# store the desired EL1 stack pointer in x1
adr x1, _start
# use SP_ELx for Exception level ELx
msr SPsel, #1
# read the current exception level into x0 (ref: C5.2.1)
mrs x0, CurrentEL
and x0, x0, #0b1100

View File

@ -116,6 +116,8 @@ impl Context {
tlbi vmalle1is // invalidate the TLB entry for the entry that changes
dsb ish // ensure TLB invalidation is complete
isb // synchronize context on this processor
str xzr, [x1]
ret"
: : : : "volatile" );
}

View File

@ -4,6 +4,7 @@ mod handler;
mod context;
mod syndrome;
use super::cortex_a::regs::*;
pub use self::context::*;
pub use self::handler::*;
@ -34,8 +35,9 @@ pub unsafe fn disable() {
/// return: status(usize)
#[inline(always)]
pub unsafe fn disable_and_store() -> usize {
// TODO
0
let daif = DAIF.get() as usize;
disable();
daif
}
/// Use the original status to restore the process
@ -44,5 +46,5 @@ pub unsafe fn disable_and_store() -> usize {
/// * flags: original status(usize)
#[inline(always)]
pub unsafe fn restore(flags: usize) {
// TODO
DAIF.set(flags as u32);
}

View File

@ -1,6 +1,7 @@
//! Entrance and initialization for aarch64.
extern crate atags;
extern crate cortex_a;
pub mod io;
pub mod paging;
@ -13,72 +14,16 @@ pub mod board;
pub use self::board::timer;
/// TODO
/// The entry point of kernel
#[no_mangle] // don't mangle the name of this function
pub extern "C" fn rust_main() -> ! {
// Init board to enable serial port.
board::init();
// First init log mod, so that we can print log info.
// FIXME
::logging::init();
let (start, end) = memory::memory_map().expect("failed to find memory map");
println!("The value of start is: {:#x?}, end is {:#x?}", start, end);
::logging::init(); // FIXME
interrupt::init();
memory::init();
timer::init();
//let mut v = vec![];
//for i in 0..1000 {
// v.push(i);
// println!("{:?}", v);
//}
::process::init();
unsafe { interrupt::enable(); }
super::fs::show_logo();
loop {
print!(">> ");
loop {
let c = io::getchar();
match c {
'\u{7f}' => {
print!("\u{7f}");
}
'b' => unsafe {
println!("brk 233");
asm!("brk 233");
},
'c' => unsafe {
println!("sys_putc");
asm!(
"mov x8, #30
mov x0, #65
svc 0"
);
},
't' => unsafe {
println!("{}", timer::get_cycle());
},
' '...'\u{7e}' => {
print!("{}", c);
}
'\n' | '\r' => {
print!("\n");
break;
}
_ => {}
}
}
}
// ::kmain();
::kmain();
}
global_asm!(include_str!("boot/boot.S"));

View File

@ -26,6 +26,62 @@ pub fn show_logo() {
println!("{}", LOGO);
}
#[inline(always)]
fn sys_call(id: usize, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 {
let ret: i32;
unsafe {
#[cfg(target_arch = "riscv32")]
asm!("ecall"
: "={x10}" (ret)
: "{x10}" (id), "{x11}" (arg0), "{x12}" (arg1), "{x13}" (arg2), "{x14}" (arg3), "{x15}" (arg4), "{x16}" (arg5)
: "memory"
: "volatile");
#[cfg(target_arch = "x86_64")]
asm!("int 0x40"
: "={rax}" (ret)
: "{rax}" (id), "{rdi}" (arg0), "{rsi}" (arg1), "{rdx}" (arg2), "{rcx}" (arg3), "{r8}" (arg4), "{r9}" (arg5)
: "memory"
: "intel" "volatile");
#[cfg(target_arch = "aarch64")]
asm!("svc 0"
: "={x0}" (ret)
: "{x8}" (id), "{x0}" (arg0), "{x1}" (arg1), "{x2}" (arg2), "{x3}" (arg3), "{x4}" (arg4), "{x5}" (arg5)
: "memory"
: "volatile");
}
ret
}
pub fn test_shell(prefix: &str) -> ! {
show_logo();
loop {
print!("{}", prefix);
loop {
let c = super::arch::io::getchar();
match c {
'\u{7f}' => {
print!("\u{7f}");
}
'c' => unsafe {
print!("sys_putc: ");
sys_call(30, 'A' as usize, 0, 0, 0, 0, 0);
},
't' => unsafe {
println!("sys_get_time: {}", sys_call(17, 0, 0, 0, 0, 0, 0));
},
' '...'\u{7e}' => {
print!("{}", c);
}
'\n' | '\r' => {
print!("\n");
break;
}
_ => {}
}
}
}
}
pub fn shell() {
show_logo();

View File

@ -66,9 +66,14 @@ pub mod arch;
pub fn kmain() -> ! {
process::init();
use process::*;
processor().add(Context::new_kernel(kernel_proc2, 2333));
processor().add(Context::new_user_test(kernel_proc3));
unsafe { arch::interrupt::enable(); }
fs::shell();
// fs::shell();
// thread::test::local_key();
// thread::test::unpack();
@ -86,3 +91,12 @@ pub fn kmain() -> ! {
/// It should be defined in memory mod, but in Rust `global_allocator` must be in root mod.
#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap = LockedHeap::empty();
pub extern "C" fn kernel_proc2(arg: usize) -> ! {
fs::test_shell(&format!("proc2-{}>> ", arg));
}
pub extern "C" fn kernel_proc3(arg: usize) -> ! {
fs::test_shell(&format!("proc3-{}$ ", arg));
}

View File

@ -33,6 +33,15 @@ impl Context {
}
}
pub fn new_user_test(entry: extern fn(usize) -> !) -> Self {
let ms = MemorySet::new();
let user_stack = ::memory::alloc_stack();
Context {
arch: unsafe { ArchContext::new_user_thread(entry as usize, user_stack.top - 8, ms.kstack_top(), false, ms.token()) },
memory_set: ms,
}
}
/// Make a new user thread from ELF data
pub fn new_user(data: &[u8]) -> Self {
// Parse elf
@ -143,4 +152,4 @@ fn memory_attr_from(elf_flags: Flags) -> MemoryAttr {
// TODO: handle readonly
if elf_flags.is_execute() { flags = flags.execute(); }
flags
}
}

View File

@ -1,39 +1,32 @@
use spin::Once;
use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq};
use sync::{Mutex, MutexGuard, SpinNoIrq, SpinNoIrqLock};
pub use self::context::Context;
pub use ucore_process::processor::{*, Context as _whatever};
pub use ucore_process::scheduler::*;
pub use ucore_process::thread::*;
use arch::timer;
mod context;
type Processor = Processor_<Context, StrideScheduler>;
pub fn init() {
PROCESSOR.call_once(||
PROCESSOR.call_once(|| {
SpinNoIrqLock::new({
let mut processor = Processor::new(
unsafe { Context::new_init() },
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass
StrideScheduler::new(5),
);
extern fn idle1(arg: usize) -> ! {
extern "C" fn idle(arg: usize) -> ! {
loop {
println!("idle 1 {}", timer::get_cycle());
#[cfg(target_arch = "aarch64")]
unsafe { asm!("wfi" :::: "volatile") }
}
}
extern fn idle2(arg: usize) -> ! {
loop {
println!("idle 2 {}", timer::get_cycle());
}
}
processor.add(Context::new_kernel(idle1, 0));
processor.add(Context::new_kernel(idle2, 0));
processor.add(Context::new_kernel(idle, 0));
processor
})
);
});
info!("process init end");
}

View File

@ -217,6 +217,8 @@ impl MutexSupport for Spin {
asm!("pause" :::: "volatile");
#[cfg(target_arch = "riscv32")]
asm!("nop" :::: "volatile");
#[cfg(target_arch = "aarch64")]
asm!("yield" :::: "volatile");
}
}
fn before_lock() -> Self::GuardData {}
@ -247,6 +249,8 @@ impl MutexSupport for SpinNoIrq {
asm!("pause" :::: "volatile");
#[cfg(target_arch = "riscv32")]
asm!("nop" :::: "volatile");
#[cfg(target_arch = "aarch64")]
asm!("yield" :::: "volatile");
}
}
fn before_lock() -> Self::GuardData {
@ -267,4 +271,4 @@ impl MutexSupport for Condvar {
fn after_unlock(&self) {
self.notify_one();
}
}
}