1 use alloc::sync::{Arc, Weak}; 2 use core::{ 3 arch::asm, 4 intrinsics::unlikely, 5 mem::ManuallyDrop, 6 sync::atomic::{compiler_fence, Ordering}, 7 }; 8 use kdepends::memoffset::offset_of; 9 use riscv::register::sstatus::Sstatus; 10 use system_error::SystemError; 11 12 use crate::{ 13 arch::{ 14 interrupt::entry::ret_from_exception, process::kthread::kernel_thread_bootstrap_stage1, 15 CurrentIrqArch, 16 }, 17 exception::InterruptArch, 18 kerror, 19 libs::spinlock::SpinLockGuard, 20 mm::VirtAddr, 21 process::{ 22 fork::{CloneFlags, KernelCloneArgs}, 23 switch_finish_hook, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, 24 PROCESS_SWITCH_RESULT, 25 }, 26 smp::cpu::ProcessorId, 27 }; 28 29 use super::{ 30 cpu::{local_context, LocalContext}, 31 interrupt::TrapFrame, 32 }; 33 34 pub mod idle; 35 pub mod kthread; 36 pub mod syscall; 37 38 #[allow(dead_code)] 39 #[repr(align(32768))] 40 union InitProcUnion { 41 /// 用于存放idle进程的内核栈 42 idle_stack: [u8; 32768], 43 } 44 45 #[link_section = ".data.init_proc_union"] 46 #[no_mangle] 47 static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion { 48 idle_stack: [0; 32768], 49 }; 50 51 pub unsafe fn arch_switch_to_user(trap_frame: TrapFrame) -> ! { 52 // 以下代码不能发生中断 53 CurrentIrqArch::interrupt_disable(); 54 55 let current_pcb = ProcessManager::current_pcb(); 56 let trap_frame_vaddr = VirtAddr::new( 57 current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::<TrapFrame>(), 58 ); 59 60 let new_pc = VirtAddr::new(ret_from_exception as usize); 61 62 let mut arch_guard = current_pcb.arch_info_irqsave(); 63 arch_guard.ksp = trap_frame_vaddr.data(); 64 65 drop(arch_guard); 66 67 drop(current_pcb); 68 69 compiler_fence(Ordering::SeqCst); 70 71 // 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题! 72 73 *(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame; 74 75 compiler_fence(Ordering::SeqCst); 76 ready_to_switch_to_user(trap_frame_vaddr.data(), new_pc.data()); 77 } 78 79 #[naked] 80 unsafe extern "C" fn ready_to_switch_to_user(trap_frame: usize, new_pc: usize) -> ! { 81 asm!( 82 concat!( 83 " 84 // 设置trap frame 85 mv sp, a0 86 // 设置返回地址 87 88 jr a1 89 90 " 91 ), 92 options(noreturn) 93 ); 94 } 95 96 impl ProcessManager { 97 pub fn arch_init() { 98 // do nothing 99 } 100 101 /// fork的过程中复制线程 102 /// 103 /// 由于这个过程与具体的架构相关,所以放在这里 104 pub fn copy_thread( 105 current_pcb: &Arc<ProcessControlBlock>, 106 new_pcb: &Arc<ProcessControlBlock>, 107 clone_args: KernelCloneArgs, 108 current_trapframe: &TrapFrame, 109 ) -> Result<(), SystemError> { 110 let clone_flags = clone_args.flags; 111 let mut child_trapframe = *current_trapframe; 112 113 // 子进程的返回值为0 114 child_trapframe.set_return_value(0); 115 116 // 设置子进程的栈基址(开始执行中断返回流程时的栈基址) 117 let mut new_arch_guard = unsafe { new_pcb.arch_info() }; 118 let kernel_stack_guard = new_pcb.kernel_stack(); 119 let trap_frame_vaddr: VirtAddr = 120 kernel_stack_guard.stack_max_address() - core::mem::size_of::<TrapFrame>(); 121 new_arch_guard.set_stack(trap_frame_vaddr); 122 123 // 拷贝栈帧 124 unsafe { 125 let usp = clone_args.stack; 126 if usp != 0 { 127 child_trapframe.sp = usp; 128 } 129 let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame; 130 *trap_frame_ptr = child_trapframe; 131 } 132 133 // copy arch info 134 135 let current_arch_guard = current_pcb.arch_info_irqsave(); 136 // 拷贝浮点寄存器的状态 137 new_arch_guard.fp_state = current_arch_guard.fp_state; 138 new_arch_guard.sstatus = current_arch_guard.sstatus; 139 140 drop(current_arch_guard); 141 142 // 设置返回地址(子进程开始执行的指令地址) 143 if new_pcb.flags().contains(ProcessFlags::KTHREAD) { 144 let kthread_bootstrap_stage1_func_addr = kernel_thread_bootstrap_stage1 as usize; 145 new_arch_guard.ra = kthread_bootstrap_stage1_func_addr; 146 } else { 147 new_arch_guard.ra = ret_from_exception as usize; 148 } 149 150 // 设置tls 151 if clone_flags.contains(CloneFlags::CLONE_SETTLS) { 152 drop(new_arch_guard); 153 todo!("set tls"); 154 } 155 156 return Ok(()); 157 } 158 159 /// 切换进程 160 /// 161 /// ## 参数 162 /// 163 /// - `prev`:上一个进程的pcb 164 /// - `next`:下一个进程的pcb 165 /// 166 /// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76 167 pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) { 168 assert!(!CurrentIrqArch::is_irq_enabled()); 169 // kdebug!( 170 // "riscv switch process: prev: {:?}, next: {:?}", 171 // prev.pid(), 172 // next.pid() 173 // ); 174 Self::switch_process_fpu(&prev, &next); 175 Self::switch_local_context(&prev, &next); 176 177 // 切换地址空间 178 let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone(); 179 compiler_fence(Ordering::SeqCst); 180 181 next_addr_space.read().user_mapper.utable.make_current(); 182 drop(next_addr_space); 183 compiler_fence(Ordering::SeqCst); 184 185 // kdebug!("current sum={}, prev sum={}, next_sum={}", riscv::register::sstatus::read().sum(), prev.arch_info_irqsave().sstatus.sum(), next.arch_info_irqsave().sstatus.sum()); 186 187 // 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁) 188 let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo; 189 let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo; 190 191 // 恢复当前的 preempt count*2 192 ProcessManager::current_pcb().preempt_enable(); 193 ProcessManager::current_pcb().preempt_enable(); 194 PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev); 195 PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next); 196 // kdebug!("riscv switch process: before to inner"); 197 compiler_fence(Ordering::SeqCst); 198 // 正式切换上下文 199 switch_to_inner(prev_arch, next_arch); 200 } 201 202 fn switch_process_fpu(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) { 203 let prev_regs = unsafe { Self::task_trapframe(prev) }; 204 let next_regs = unsafe { Self::task_trapframe(next) }; 205 if unlikely(prev_regs.status.sd()) { 206 prev.arch_info_irqsave().fp_state.save(prev_regs); 207 } 208 next.arch_info_irqsave().fp_state.restore(next_regs); 209 } 210 211 fn switch_local_context(prev: &Arc<ProcessControlBlock>, next: &Arc<ProcessControlBlock>) { 212 prev.arch_info_irqsave().local_context = *local_context().get(); 213 local_context() 214 .get_mut() 215 .restore(&next.arch_info_irqsave().local_context); 216 } 217 218 unsafe fn task_trapframe(task: &Arc<ProcessControlBlock>) -> &mut TrapFrame { 219 let mut sp = task.kernel_stack().stack_max_address().data(); 220 sp -= core::mem::size_of::<TrapFrame>(); 221 return (sp as *mut TrapFrame).as_mut().unwrap(); 222 } 223 } 224 225 /// 切换上下文 226 /// 227 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/entry.S#233 228 #[naked] 229 unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBInfo) { 230 core::arch::asm!(concat!( 231 " 232 sd ra, {off_ra}(a0) 233 sd sp, {off_sp}(a0) 234 sd s0, {off_s0}(a0) 235 sd s1, {off_s1}(a0) 236 sd s2, {off_s2}(a0) 237 sd s3, {off_s3}(a0) 238 sd s4, {off_s4}(a0) 239 sd s5, {off_s5}(a0) 240 sd s6, {off_s6}(a0) 241 sd s7, {off_s7}(a0) 242 sd s8, {off_s8}(a0) 243 sd s9, {off_s9}(a0) 244 sd s10, {off_s10}(a0) 245 sd s11, {off_s11}(a0) 246 247 addi sp , sp, -8 248 sd a1, 0(sp) 249 csrr a1, sstatus 250 sd a1, {off_sstatus}(a0) 251 ld a1, 0(sp) 252 addi sp, sp, 8 253 254 255 ld sp, {off_sp}(a1) 256 ld s0, {off_s0}(a1) 257 ld s1, {off_s1}(a1) 258 ld s2, {off_s2}(a1) 259 ld s3, {off_s3}(a1) 260 ld s4, {off_s4}(a1) 261 ld s5, {off_s5}(a1) 262 ld s6, {off_s6}(a1) 263 ld s7, {off_s7}(a1) 264 ld s8, {off_s8}(a1) 265 ld s9, {off_s9}(a1) 266 ld s10, {off_s10}(a1) 267 ld s11, {off_s11}(a1) 268 269 // save a1 temporarily 270 addi sp , sp, -8 271 sd a1, 0(sp) 272 273 ld a0, {off_sstatus}(a1) 274 csrw sstatus, a0 275 276 // 将ra设置为标签1,并跳转到before_switch_finish_hook 277 la ra, 1f 278 j {before_switch_finish_hook} 279 280 1: 281 282 // restore a1 283 ld a1, 0(sp) 284 addi sp, sp, 8 285 ld sp, {off_sp}(a1) 286 ld ra, {off_ra}(a1) 287 288 ret 289 290 " 291 ), 292 off_ra = const(offset_of!(ArchPCBInfo, ra)), 293 off_sstatus = const(offset_of!(ArchPCBInfo, sstatus)), 294 off_sp = const(offset_of!(ArchPCBInfo, ksp)), 295 off_s0 = const(offset_of!(ArchPCBInfo, s0)), 296 off_s1 = const(offset_of!(ArchPCBInfo, s1)), 297 off_s2 = const(offset_of!(ArchPCBInfo, s2)), 298 off_s3 = const(offset_of!(ArchPCBInfo, s3)), 299 off_s4 = const(offset_of!(ArchPCBInfo, s4)), 300 off_s5 = const(offset_of!(ArchPCBInfo, s5)), 301 off_s6 = const(offset_of!(ArchPCBInfo, s6)), 302 off_s7 = const(offset_of!(ArchPCBInfo, s7)), 303 off_s8 = const(offset_of!(ArchPCBInfo, s8)), 304 off_s9 = const(offset_of!(ArchPCBInfo, s9)), 305 off_s10 = const(offset_of!(ArchPCBInfo, s10)), 306 off_s11 = const(offset_of!(ArchPCBInfo, s11)), 307 before_switch_finish_hook = sym before_switch_finish_hook, 308 options(noreturn)); 309 } 310 311 /// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误) 312 unsafe extern "C" fn before_switch_finish_hook() { 313 switch_finish_hook(); 314 } 315 316 impl ProcessControlBlock { 317 /// 获取当前进程的pcb 318 pub fn arch_current_pcb() -> Arc<Self> { 319 // 获取栈指针 320 let mut sp: usize; 321 unsafe { asm!("mv {}, sp", lateout(reg) sp, options(nostack)) }; 322 let ptr = VirtAddr::new(sp); 323 324 let stack_base = VirtAddr::new(ptr.data() & (!(KernelStack::ALIGN - 1))); 325 326 // 从内核栈的最低地址处取出pcb的地址 327 let p = stack_base.data() as *const *const ProcessControlBlock; 328 if core::intrinsics::unlikely((unsafe { *p }).is_null()) { 329 kerror!("p={:p}", p); 330 panic!("current_pcb is null"); 331 } 332 unsafe { 333 // 为了防止内核栈的pcb weak 指针被释放,这里需要将其包装一下 334 let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> = 335 ManuallyDrop::new(Weak::from_raw(*p)); 336 337 let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade().unwrap(); 338 return new_arc; 339 } 340 } 341 } 342 343 /// PCB中与架构相关的信息 344 #[derive(Debug, Clone, Copy)] 345 #[allow(dead_code)] 346 #[repr(C)] 347 pub struct ArchPCBInfo { 348 ra: usize, 349 ksp: usize, 350 s0: usize, 351 s1: usize, 352 s2: usize, 353 s3: usize, 354 s4: usize, 355 s5: usize, 356 s6: usize, 357 s7: usize, 358 s8: usize, 359 s9: usize, 360 s10: usize, 361 s11: usize, 362 sstatus: Sstatus, 363 364 fp_state: FpDExtState, 365 local_context: LocalContext, 366 } 367 368 #[allow(dead_code)] 369 impl ArchPCBInfo { 370 /// 创建一个新的ArchPCBInfo 371 /// 372 /// ## 参数 373 /// 374 /// - `kstack`:内核栈的引用 375 /// 376 /// ## 返回值 377 /// 378 /// 返回一个新的ArchPCBInfo 379 pub fn new(kstack: &KernelStack) -> Self { 380 let mut sstatus = Sstatus::from(0); 381 sstatus.update_sum(true); 382 Self { 383 ra: 0, 384 ksp: kstack.stack_max_address().data(), 385 s0: 0, 386 s1: 0, 387 s2: 0, 388 s3: 0, 389 s4: 0, 390 s5: 0, 391 s6: 0, 392 s7: 0, 393 s8: 0, 394 s9: 0, 395 s10: 0, 396 s11: 0, 397 sstatus, 398 fp_state: FpDExtState::new(), 399 local_context: LocalContext::new(ProcessorId::new(0)), 400 } 401 } 402 // ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变 403 pub fn clone_from(&mut self, from: &Self) { 404 *self = from.clone(); 405 } 406 407 pub fn set_stack(&mut self, stack: VirtAddr) { 408 self.ksp = stack.data(); 409 } 410 } 411 412 #[repr(C)] 413 #[derive(Debug, Clone, Copy)] 414 struct FpDExtState { 415 f: [u64; 32], 416 fcsr: u32, 417 } 418 419 impl FpDExtState { 420 /// 创建一个新的FpState 421 const fn new() -> Self { 422 Self { 423 f: [0; 32], 424 fcsr: 0, 425 } 426 } 427 428 fn save(&mut self, regs: &mut TrapFrame) { 429 if regs.status.fs() == riscv::register::sstatus::FS::Dirty { 430 self.do_save(); 431 self.do_clean(regs); 432 } 433 } 434 435 fn restore(&mut self, regs: &mut TrapFrame) { 436 if regs.status.fs() != riscv::register::sstatus::FS::Off { 437 self.do_restore(); 438 self.do_clean(regs); 439 } 440 } 441 442 fn do_clean(&mut self, regs: &mut TrapFrame) { 443 regs.status.update_fs(riscv::register::sstatus::FS::Clean); 444 } 445 446 fn do_save(&mut self) { 447 compiler_fence(Ordering::SeqCst); 448 unsafe { 449 riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial); 450 asm!("frcsr {0}", lateout(reg) self.fcsr); 451 asm!(concat!( 452 " 453 // 为原来的a0寄存器的值在堆栈上分配空间 454 addi sp, sp, -8 455 sd a0, 0(sp) 456 mv a0, {0} 457 458 fsd f0, 0(a0) 459 fsd f1, 8(a0) 460 fsd f2, 16(a0) 461 fsd f3, 24(a0) 462 fsd f4, 32(a0) 463 fsd f5, 40(a0) 464 fsd f6, 48(a0) 465 fsd f7, 56(a0) 466 fsd f8, 64(a0) 467 fsd f9, 72(a0) 468 fsd f10, 80(a0) 469 fsd f11, 88(a0) 470 fsd f12, 96(a0) 471 fsd f13, 104(a0) 472 fsd f14, 112(a0) 473 fsd f15, 120(a0) 474 fsd f16, 128(a0) 475 fsd f17, 136(a0) 476 fsd f18, 144(a0) 477 fsd f19, 152(a0) 478 fsd f20, 160(a0) 479 fsd f21, 168(a0) 480 fsd f22, 176(a0) 481 fsd f23, 184(a0) 482 fsd f24, 192(a0) 483 fsd f25, 200(a0) 484 fsd f26, 208(a0) 485 fsd f27, 216(a0) 486 fsd f28, 224(a0) 487 fsd f29, 232(a0) 488 fsd f30, 240(a0) 489 fsd f31, 248(a0) 490 491 // 恢复a0寄存器的值 492 ld a0, 0(sp) 493 addi sp, sp, 8 494 " 495 ), 496 in (reg) &self.f as *const _, 497 ); 498 riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off); 499 } 500 501 compiler_fence(Ordering::SeqCst); 502 } 503 504 fn do_restore(&mut self) { 505 compiler_fence(Ordering::SeqCst); 506 let fcsr = self.fcsr; 507 unsafe { 508 riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Initial); 509 compiler_fence(Ordering::SeqCst); 510 asm!(concat!( 511 " 512 // 为原来的a0寄存器的值在堆栈上分配空间 513 addi sp, sp, -8 514 sd a0, 0(sp) 515 mv a0, {0} 516 517 fld f0, 0(a0) 518 fld f1, 8(a0) 519 fld f2, 16(a0) 520 fld f3, 24(a0) 521 fld f4, 32(a0) 522 fld f5, 40(a0) 523 fld f6, 48(a0) 524 fld f7, 56(a0) 525 fld f8, 64(a0) 526 fld f9, 72(a0) 527 fld f10, 80(a0) 528 fld f11, 88(a0) 529 fld f12, 96(a0) 530 fld f13, 104(a0) 531 fld f14, 112(a0) 532 fld f15, 120(a0) 533 fld f16, 128(a0) 534 fld f17, 136(a0) 535 fld f18, 144(a0) 536 fld f19, 152(a0) 537 fld f20, 160(a0) 538 fld f21, 168(a0) 539 fld f22, 176(a0) 540 fld f23, 184(a0) 541 fld f24, 192(a0) 542 fld f25, 200(a0) 543 fld f26, 208(a0) 544 fld f27, 216(a0) 545 fld f28, 224(a0) 546 fld f29, 232(a0) 547 fld f30, 240(a0) 548 fld f31, 248(a0) 549 550 // 恢复a0寄存器的值 551 ld a0, 0(sp) 552 addi sp, sp, 8 553 " 554 ), 555 in (reg) &self.f as *const _, 556 ); 557 compiler_fence(Ordering::SeqCst); 558 asm!("fscsr {0}", in(reg) fcsr); 559 riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off); 560 } 561 compiler_fence(Ordering::SeqCst); 562 } 563 } 564