Skip to content

Commit 7cf4d8c

Browse files
committed
- Have pagefault avaliable in riscv
- Add fork spawning process in riscv - Add program loading function in riscv - Solve global pointer bug in riscv
1 parent c5650c9 commit 7cf4d8c

16 files changed

Lines changed: 272 additions & 34 deletions

File tree

api/ruxos_posix_api/src/imp/execve/mod.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod load_elf;
33
mod stack;
44

55
use alloc::vec;
6-
use core::ffi::c_char;
6+
use core::{arch::asm, ffi::c_char, ptr::null};
77
use ruxtask::current;
88

99
use crate::{
@@ -107,11 +107,13 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! {
107107

108108
let mut argv = argv as *const usize;
109109
unsafe {
110-
while *argv != 0 {
111-
arg_vec.push(*argv);
112-
argv = argv.add(1);
110+
if argv != null() {
111+
while *argv != 0 {
112+
arg_vec.push(*argv);
113+
argv = argv.add(1);
114+
}
115+
arg_vec.push(0);
113116
}
114-
arg_vec.push(0);
115117
}
116118

117119
// push
@@ -167,6 +169,17 @@ fn set_sp_and_jmp(sp: usize, entry: usize) -> ! {
167169
in(reg)entry,
168170
);
169171
}
172+
#[cfg(target_arch = "riscv64")]
173+
unsafe {
174+
core::arch::asm!(
175+
"
176+
mv sp, {0}
177+
jalr {1}
178+
",
179+
in(reg) sp,
180+
in(reg) entry,
181+
);
182+
}
170183
unreachable!("sys_execve: unknown arch, sp 0x{sp:x}, entry 0x{entry:x}");
171184
}
172185

api/ruxos_posix_api/src/imp/mmap/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
cfg_if::cfg_if! {
1111
// for X86_64 with SMP, it must flush TLB via IPI
12-
if #[cfg( all(feature = "paging", any(target_arch = "aarch64", any( all(target_arch = "x86_64", feature = "irq", feature = "smp"), all(target_arch = "x86_64", not(feature = "smp")) ) ) ))] {
12+
if #[cfg( all(feature = "paging", any(target_arch = "aarch64",target_arch="riscv64",any( all(target_arch = "x86_64", feature = "irq", feature = "smp"), all(target_arch = "x86_64", not(feature = "smp")) ) ) ))] {
1313
#[macro_use]
1414
mod utils;
1515
mod api;

api/ruxos_posix_api/src/imp/pthread/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,24 @@ pub unsafe fn sys_clone(
374374
ruxtask::put_task(task_inner);
375375

376376
return Ok(tid);
377+
} else if (flags as u32 & ctypes::SIGCHLD) != 0 {
378+
let pid = if let Some(task_ref) = ruxtask::fork_task() {
379+
task_ref.id().as_u64()
380+
} else {
381+
let children_ref = ruxtask::current();
382+
let tid = children_ref.id().as_u64();
383+
let thread = Pthread {
384+
inner: children_ref.clone_as_taskref(),
385+
retval: Arc::new(Packet {
386+
result: UnsafeCell::new(core::ptr::null_mut()),
387+
}),
388+
};
389+
let ptr = Box::into_raw(Box::new(thread)) as *mut c_void;
390+
TID_TO_PTHREAD.write().insert(tid, ForceSendSync(ptr));
391+
0
392+
};
393+
debug!("will sys_clone <= pid: {}", pid);
394+
return Ok(pid);
377395
} else {
378396
debug!("ONLY support CLONE_THREAD and SIGCHLD");
379397
return Err(LinuxError::EINVAL);

modules/ruxhal/src/arch/riscv/context.rs

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
* See the Mulan PSL v2 for more details.
88
*/
99

10+
use core::arch::asm;
1011
use core::arch::naked_asm;
12+
use memory_addr::PhysAddr;
1113
use memory_addr::VirtAddr;
1214

15+
use super::reg_satp::RegSatp;
16+
1317
include_asm_marcos!();
1418

1519
/// General registers of RISC-V.
@@ -60,6 +64,7 @@ pub struct TrapFrame {
6064
pub sepc: usize,
6165
/// Supervisor Status Register.
6266
pub sstatus: usize,
67+
pub sscratch: usize,
6368
}
6469

6570
/// Saved hardware states of a task.
@@ -95,6 +100,7 @@ pub struct TaskContext {
95100
pub s11: usize,
96101

97102
pub tp: usize,
103+
pub gp: usize,
98104
// TODO: FP states
99105
}
100106

@@ -116,21 +122,96 @@ impl TaskContext {
116122
///
117123
/// It first saves the current task's context from CPU to this place, and then
118124
/// restores the next task's context from `next_ctx` to CPU.
119-
pub fn switch_to(&mut self, next_ctx: &Self) {
125+
pub fn switch_to(&mut self, next_ctx: &Self, page_table_addr: PhysAddr) {
120126
#[cfg(feature = "tls")]
121127
{
122128
self.tp = super::read_thread_pointer();
123129
unsafe { super::write_thread_pointer(next_ctx.tp) };
124130
}
131+
132+
let satp = RegSatp::gen_satp(riscv::register::satp::Mode::Sv39, 0, page_table_addr.into());
125133
unsafe {
126134
// TODO: switch FP states
127-
context_switch(self, next_ctx)
135+
context_switch(self, next_ctx, satp);
128136
}
129137
}
138+
139+
/// This function copy the content from src to dst,the content size is given by parameter "size"
140+
/// It's only supposed to use this function for processes stack's copying
141+
/// Not only the content of the src process's stack would be copied into dst's
142+
/// It would also save the current context of the process to src's stack
143+
///
144+
/// # Argument
145+
/// - src: The raw pointer of the src process stack
146+
/// - dst: The raw pointer of the dst process stack
147+
/// - size: The size of the stack
148+
///
149+
/// # Safety
150+
/// This function assumes that the parameter "size" indicate exactly the size of both stacks.
151+
/// The caller must ensure this to make safe function call.
152+
pub unsafe fn save_current_content(&mut self, src: *const u8, dst: *mut u8, size: usize) {
153+
unsafe {
154+
save_stack(src, dst, size);
155+
save_current_context(self);
156+
}
157+
}
158+
}
159+
160+
#[unsafe(naked)]
161+
#[allow(named_asm_labels)]
162+
unsafe extern "C" fn save_current_context(_current_task: &mut TaskContext) {
163+
naked_asm!(
164+
"
165+
sd ra,0(a0)
166+
sd sp,8(a0)
167+
sd s0,16(a0)
168+
sd s1,24(a0)
169+
sd s2,32(a0)
170+
sd s3,40(a0)
171+
sd s4,48(a0)
172+
sd s5,56(a0)
173+
sd s6,64(a0)
174+
sd s7,72(a0)
175+
sd s8,80(a0)
176+
sd s9,88(a0)
177+
sd s10,96(a0)
178+
sd s11,104(a0)
179+
sd tp,112(a0)
180+
ret
181+
"
182+
)
183+
}
184+
185+
#[unsafe(naked)]
186+
#[no_mangle]
187+
#[allow(named_asm_labels)]
188+
// TODO: consider using SIMD instructions to copy the stack in parallel.
189+
unsafe extern "C" fn save_stack(src: *const u8, dst: *mut u8, size: usize) {
190+
// a0:src ; a1:dst ; a2:size
191+
naked_asm!(
192+
"
193+
xor a4,a4,a4
194+
add a4,a4,a2
195+
start_copy:
196+
ld a5,0(a0)
197+
sd a5,0(a1)
198+
addi a0,a0,8
199+
addi a1,a1,8
200+
addi a4,a4,-8
201+
bnez a4,start_copy
202+
ret
203+
204+
"
205+
)
130206
}
131207

132208
#[unsafe(naked)]
133-
unsafe extern "C" fn context_switch(_current_task: &mut TaskContext, _next_task: &TaskContext) {
209+
#[allow(named_asm_labels)]
210+
unsafe extern "C" fn context_switch(
211+
_current_task: &mut TaskContext,
212+
_next_task: &TaskContext,
213+
_page_table_addr: usize,
214+
) {
134215
naked_asm!(
135216
"
136217
// save old context (callee-saved registers)
@@ -149,6 +230,12 @@ unsafe extern "C" fn context_switch(_current_task: &mut TaskContext, _next_task:
149230
sd s10, 96(a0)
150231
sd s11, 104(a0)
151232
233+
csrr a3,satp
234+
csrw satp,a2
235+
xor a3,a3,a2
236+
beqz a3,set_satp_done
237+
sfence.vma
238+
set_satp_done:
152239
// restore new context
153240
ld s11, 104(a1)
154241
ld s10, 96(a1)

modules/ruxhal/src/arch/riscv/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
mod macros;
1212

1313
mod context;
14+
mod reg_satp;
1415
mod trap;
15-
1616
use memory_addr::{PhysAddr, VirtAddr};
1717
use riscv::asm;
1818
use riscv::register::{satp, sstatus, stvec};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use riscv::register::satp;
2+
3+
type PhysAddr = usize;
4+
5+
#[allow(clippy::upper_case_acronyms)]
6+
pub struct PPN(usize);
7+
8+
impl From<PhysAddr> for PPN {
9+
fn from(value: PhysAddr) -> Self {
10+
let num = value;
11+
let page_frame_num = num >> 12;
12+
Self(page_frame_num)
13+
}
14+
}
15+
16+
impl From<PPN> for usize {
17+
fn from(value: PPN) -> Self {
18+
value.0
19+
}
20+
}
21+
pub struct AddressSpaceID(usize);
22+
23+
impl From<u16> for AddressSpaceID {
24+
fn from(value: u16) -> Self {
25+
let value = usize::from(value);
26+
AddressSpaceID(value << 44)
27+
}
28+
}
29+
30+
impl From<AddressSpaceID> for usize {
31+
fn from(value: AddressSpaceID) -> Self {
32+
value.0
33+
}
34+
}
35+
36+
pub struct RegSatp;
37+
38+
impl RegSatp {
39+
pub fn gen_satp(mode: satp::Mode, asid: u16, page_table_addr: PhysAddr) -> usize {
40+
let mode = (mode as usize) << 60;
41+
let asid: AddressSpaceID = asid.into();
42+
let physical_page_num: PPN = page_table_addr.into();
43+
mode | usize::from(asid) | usize::from(physical_page_num)
44+
}
45+
}

modules/ruxhal/src/arch/riscv/trap.S

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,35 @@
11
.macro SAVE_REGS, from_user
22
addi sp, sp, -{trapframe_size}
33
PUSH_GENERAL_REGS
4-
4+
addi t2, sp, {trapframe_size}
55
csrr t0, sepc
66
csrr t1, sstatus
7-
csrrw t2, sscratch, zero // save sscratch (sp) and zero it
87
STR t0, sp, 31 // tf.sepc
98
STR t1, sp, 32 // tf.sstatus
9+
STR gp, sp, 2
1010
STR t2, sp, 1 // tf.regs.sp
11-
11+
csrr gp, sscratch
1212
.if \from_user == 1
1313
LDR t0, sp, 3 // load supervisor tp
14-
STR gp, sp, 2 // save user gp and tp
1514
STR tp, sp, 3
1615
mv tp, t0
1716
.endif
1817
.endm
1918

2019
.macro RESTORE_REGS, from_user
20+
// LDR gp, sp, 2
2121
.if \from_user == 1
22-
LDR gp, sp, 2 // load user gp and tp
2322
LDR t0, sp, 3
2423
STR tp, sp, 3 // save supervisor tp
2524
mv tp, t0
2625
addi t0, sp, {trapframe_size} // put supervisor sp to scratch
27-
csrw sscratch, t0
2826
.endif
29-
27+
LDR gp, sp, 2
3028
LDR t0, sp, 31
3129
LDR t1, sp, 32
3230
csrw sepc, t0
3331
csrw sstatus, t1
34-
32+
//csrw sscratch, t2
3533
POP_GENERAL_REGS
3634
LDR sp, sp, 1 // load sp from tf.regs.sp
3735
.endm
@@ -42,10 +40,9 @@
4240
trap_vector_base:
4341
// sscratch == 0: trap from S mode
4442
// sscratch != 0: trap from U mode
45-
csrrw sp, sscratch, sp // switch sscratch and sp
46-
bnez sp, .Ltrap_entry_u
47-
48-
csrr sp, sscratch // put supervisor sp back
43+
//csrrw sp, sscratch, sp // switch sscratch and sp
44+
//bnez sp, .Ltrap_entry_u
45+
//csrr sp, sscratch // put supervisor sp back
4946
j .Ltrap_entry_s
5047

5148
.Ltrap_entry_s:

modules/ruxhal/src/arch/riscv/trap.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
use riscv::register::scause::{self, Exception as E, Trap};
1111

12-
use super::TrapFrame;
12+
use super::{disable_irqs, enable_irqs, TrapFrame};
1313

1414
include_asm_marcos!();
1515

@@ -31,6 +31,8 @@ fn riscv_trap_handler(tf: &mut TrapFrame, _from_user: bool) {
3131
Trap::Interrupt(_) => crate::trap::handle_irq_extern(scause.bits()),
3232
#[cfg(feature = "musl")]
3333
Trap::Exception(E::UserEnvCall) => {
34+
#[cfg(feature = "irq")]
35+
enable_irqs();
3436
let ret = crate::trap::handle_syscall(
3537
tf.regs.a7,
3638
[
@@ -43,6 +45,23 @@ fn riscv_trap_handler(tf: &mut TrapFrame, _from_user: bool) {
4345
],
4446
);
4547
tf.regs.a0 = ret as _;
48+
#[cfg(feature = "irq")]
49+
disable_irqs();
50+
}
51+
#[cfg(feature = "paging")]
52+
Trap::Exception(E::LoadPageFault) => {
53+
let vaddr = riscv::register::stval::read();
54+
crate::trap::handle_page_fault(vaddr, crate::trap::PageFaultCause::READ);
55+
}
56+
#[cfg(feature = "paging")]
57+
Trap::Exception(E::StorePageFault) => {
58+
let vaddr = riscv::register::stval::read();
59+
crate::trap::handle_page_fault(vaddr, crate::trap::PageFaultCause::WRITE);
60+
}
61+
#[cfg(feature = "paging")]
62+
Trap::Exception(E::InstructionPageFault) => {
63+
let vaddr = riscv::register::stval::read();
64+
crate::trap::handle_page_fault(vaddr, crate::trap::PageFaultCause::INSTRUCTION);
4665
}
4766
_ => {
4867
panic!(

0 commit comments

Comments
 (0)