refactor: tasks code cleanup
This commit is contained in:
+192
-60
@@ -8,12 +8,16 @@ mod boot;
|
||||
mod debug;
|
||||
mod memory;
|
||||
mod platform;
|
||||
mod syscall;
|
||||
mod task;
|
||||
|
||||
use core::arch::global_asm;
|
||||
|
||||
use crate::{
|
||||
debug::serial,
|
||||
memory::{
|
||||
AddressSpace, KernelStackPool, MemoryRegionKind, PagePermissions, UserStack, VirtualAddr,
|
||||
AddressSpace, DirectMap, FrameAllocator, KernelStackPool, MemoryRegionKind,
|
||||
PagePermissions, UserStack, VirtualAddr,
|
||||
},
|
||||
task::tcb::Tcb,
|
||||
};
|
||||
@@ -88,6 +92,112 @@ pub extern "C" fn _start() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
static task_a_start: u8;
|
||||
static task_a_end: u8;
|
||||
static task_b_start: u8;
|
||||
static task_b_end: u8;
|
||||
static task_c_start: u8;
|
||||
static task_c_end: u8;
|
||||
}
|
||||
|
||||
unsafe fn embedded_code(start: *const u8, end: *const u8) -> &'static [u8] {
|
||||
let length = unsafe { end.offset_from(start) as usize };
|
||||
unsafe { core::slice::from_raw_parts(start, length) }
|
||||
}
|
||||
|
||||
global_asm!(
|
||||
r#"
|
||||
.global task_a_start
|
||||
task_a_start:
|
||||
mov r12d, 100
|
||||
|
||||
.Ltask_a_loop:
|
||||
mov eax, 3
|
||||
mov edi, 1
|
||||
lea rsi, [rip + .Ltask_a_message]
|
||||
mov edx, 7
|
||||
xor r10d, r10d
|
||||
syscall
|
||||
|
||||
mov eax, 1
|
||||
syscall
|
||||
|
||||
dec r12d
|
||||
jnz .Ltask_a_loop
|
||||
|
||||
.Ltask_a_done:
|
||||
mov eax, 2
|
||||
syscall
|
||||
jmp .Ltask_a_done
|
||||
|
||||
.Ltask_a_message:
|
||||
.ascii "task A\n"
|
||||
|
||||
.global task_a_end
|
||||
task_a_end:
|
||||
|
||||
|
||||
.global task_b_start
|
||||
task_b_start:
|
||||
mov r12d, 100
|
||||
|
||||
.Ltask_b_loop:
|
||||
mov eax, 3
|
||||
mov edi, 1
|
||||
lea rsi, [rip + .Ltask_b_message]
|
||||
mov edx, 7
|
||||
xor r10d, r10d
|
||||
syscall
|
||||
|
||||
mov eax, 1
|
||||
syscall
|
||||
|
||||
dec r12d
|
||||
jnz .Ltask_b_loop
|
||||
|
||||
.Ltask_b_done:
|
||||
mov eax, 2
|
||||
syscall
|
||||
jmp .Ltask_b_done
|
||||
|
||||
.Ltask_b_message:
|
||||
.ascii "task B\n"
|
||||
|
||||
.global task_b_end
|
||||
task_b_end:
|
||||
|
||||
.global task_c_start
|
||||
task_c_start:
|
||||
mov r12d, 100
|
||||
|
||||
.Ltask_c_loop:
|
||||
mov eax, 3
|
||||
mov edi, 1
|
||||
lea rsi, [rip + .Ltask_c_message]
|
||||
mov edx, 7
|
||||
xor r10d, r10d
|
||||
syscall
|
||||
|
||||
mov eax, 1
|
||||
syscall
|
||||
|
||||
dec r12d
|
||||
jnz .Ltask_c_loop
|
||||
|
||||
.Ltask_c_done:
|
||||
mov eax, 2
|
||||
syscall
|
||||
jmp .Ltask_c_done
|
||||
|
||||
.Ltask_c_message:
|
||||
.ascii "task C\n"
|
||||
|
||||
.global task_c_end
|
||||
task_c_end:
|
||||
"#
|
||||
);
|
||||
|
||||
pub unsafe extern "C" fn kernel_main(handoff: *mut KernelHandoff) -> ! {
|
||||
let (
|
||||
mut allocator,
|
||||
@@ -134,73 +244,95 @@ pub unsafe extern "C" fn kernel_main(handoff: *mut KernelHandoff) -> ! {
|
||||
arch::init_interrupt_controller(&madt, &mut allocator, &mut address_space)
|
||||
.expect("failed to initialize interrupt controller");
|
||||
|
||||
println!("Creating user address space...");
|
||||
let task_a_code = unsafe { embedded_code(&task_a_start, &task_a_end) };
|
||||
let task_b_code = unsafe { embedded_code(&task_b_start, &task_b_end) };
|
||||
let task_c_code = unsafe { embedded_code(&task_c_start, &task_c_end) };
|
||||
|
||||
let task_kernel_stack = kernel_stack_pool
|
||||
.allocate(&mut address_space, &mut allocator)
|
||||
.expect("failed to allocate user task stack");
|
||||
let task_a = create_test_task(
|
||||
task_a_code,
|
||||
&mut address_space,
|
||||
&mut kernel_stack_pool,
|
||||
&mut allocator,
|
||||
direct_map,
|
||||
);
|
||||
|
||||
let mut user_addr_space = address_space
|
||||
.new_user(&mut allocator)
|
||||
.expect("failed to create user address space");
|
||||
let task_b = create_test_task(
|
||||
task_b_code,
|
||||
&mut address_space,
|
||||
&mut kernel_stack_pool,
|
||||
&mut allocator,
|
||||
direct_map,
|
||||
);
|
||||
|
||||
println!("Allocating user stack...");
|
||||
let task_c = create_test_task(
|
||||
task_c_code,
|
||||
&mut address_space,
|
||||
&mut kernel_stack_pool,
|
||||
&mut allocator,
|
||||
direct_map,
|
||||
);
|
||||
|
||||
let user_stack = UserStack::allocate(&mut user_addr_space, &mut allocator)
|
||||
.expect("failed to allocate user stack");
|
||||
|
||||
let user_instruction_pointer = VirtualAddr::new(0x8000);
|
||||
let user_code_page = allocator
|
||||
.alloc()
|
||||
.expect("failed to allocate user code page")
|
||||
.frame_address();
|
||||
user_addr_space
|
||||
.map(
|
||||
user_code_page.start_address(),
|
||||
user_instruction_pointer,
|
||||
PagePermissions::new(true, true, true),
|
||||
&mut allocator,
|
||||
memory::CachePolicy::WriteBack,
|
||||
)
|
||||
.expect("failed to map user code page");
|
||||
|
||||
unsafe {
|
||||
let user_code: &[u8] = &[
|
||||
0xCC, // INT3
|
||||
0x0F, 0x05, // SYSCALL
|
||||
0xEB, 0xFE, // JMP -2 (loop forever if exit returns)
|
||||
];
|
||||
|
||||
let user_code_virtual = direct_map
|
||||
.translate(user_code_page.start_address())
|
||||
.unwrap();
|
||||
|
||||
println!("Copying user code to {:#X}", user_code_virtual.as_usize());
|
||||
|
||||
core::ptr::copy_nonoverlapping(
|
||||
user_code.as_ptr(),
|
||||
user_code_virtual.as_mut_ptr::<u8>(),
|
||||
user_code.len(),
|
||||
);
|
||||
|
||||
println!("Activating user address space...");
|
||||
|
||||
let user_tcb = Tcb::new_user(
|
||||
0,
|
||||
user_addr_space,
|
||||
task_kernel_stack,
|
||||
user_instruction_pointer,
|
||||
user_stack.top(),
|
||||
);
|
||||
|
||||
println!("Running first user task {user_tcb:?}...");
|
||||
|
||||
task::tcb::run_first_user(&user_tcb);
|
||||
}
|
||||
task::scheduler::add_task(task_a).expect("scheduler is full");
|
||||
task::scheduler::add_task(task_b).expect("scheduler is full");
|
||||
task::scheduler::add_task(task_c).expect("scheduler is full");
|
||||
task::scheduler::start();
|
||||
|
||||
hcf();
|
||||
}
|
||||
|
||||
fn create_test_task(
|
||||
code: &[u8],
|
||||
kernel_address_space: &mut AddressSpace,
|
||||
kernel_stack_pool: &mut KernelStackPool,
|
||||
allocator: &mut FrameAllocator,
|
||||
direct_map: DirectMap,
|
||||
) -> Tcb {
|
||||
assert!(code.len() <= memory::FRAME_SIZE);
|
||||
|
||||
let kernel_stack = kernel_stack_pool
|
||||
.allocate(kernel_address_space, allocator)
|
||||
.expect("failed to allocate task kernel stack");
|
||||
|
||||
let mut user_address_space = kernel_address_space
|
||||
.new_user(allocator)
|
||||
.expect("failed to create user address space");
|
||||
|
||||
let user_stack = UserStack::allocate(&mut user_address_space, allocator)
|
||||
.expect("failed to allocate user stack");
|
||||
|
||||
let entry = VirtualAddr::new(0x8000);
|
||||
let code_frame = allocator
|
||||
.alloc()
|
||||
.expect("failed to allocate code frame")
|
||||
.into_raw();
|
||||
|
||||
user_address_space
|
||||
.map(
|
||||
code_frame.start_address(),
|
||||
entry,
|
||||
PagePermissions::new(false, true, true),
|
||||
allocator,
|
||||
memory::CachePolicy::WriteBack,
|
||||
)
|
||||
.expect("failed to map user code");
|
||||
|
||||
let destination = direct_map
|
||||
.translate(code_frame.start_address())
|
||||
.expect("code frame outside direct map");
|
||||
|
||||
unsafe {
|
||||
core::ptr::copy_nonoverlapping(code.as_ptr(), destination.as_mut_ptr(), code.len());
|
||||
}
|
||||
|
||||
Tcb::new_user(
|
||||
0, // overwritten by add_task for now
|
||||
user_address_space,
|
||||
kernel_stack,
|
||||
entry,
|
||||
user_stack.top(),
|
||||
)
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||
println!("Uh oh, something went wrong!");
|
||||
|
||||
Reference in New Issue
Block a user