Support TLS for MIPS.

master
Yuhao Zhou 6 years ago
parent 657395784d
commit bfa4c9d47e

@ -7,22 +7,23 @@
.globl switch_context
.extern _root_page_table_ptr
.extern _cur_kstack_ptr
.extern _cur_tls
switch_context:
// save from's registers
addi sp, sp, (-4*14)
sw sp, 0(a0)
sw ra, 0(sp)
sw s0, 2*4(sp)
sw s1, 3*4(sp)
sw s2, 4*4(sp)
sw s3, 5*4(sp)
sw s4, 6*4(sp)
sw s5, 7*4(sp)
sw s6, 8*4(sp)
sw s7, 9*4(sp)
sw s8, 10*4(sp)
sw gp, 11*4(sp)
sw s0, 4*4(sp)
sw s1, 5*4(sp)
sw s2, 6*4(sp)
sw s3, 7*4(sp)
sw s4, 8*4(sp)
sw s5, 9*4(sp)
sw s6, 10*4(sp)
sw s7, 11*4(sp)
sw s8, 12*4(sp)
sw gp, 13*4(sp)
// sw ra, 12*4(sp)
// sw sp, 13*4(sp)
@ -31,27 +32,34 @@ switch_context:
lw s1, 0(s0)
sw s1, 4(sp)
// save TLS
la s2, _cur_tls
lw s1, 0(s2)
sw s1, 2*4(sp)
// restore to's registers
lw sp, 0(a1)
// restore page table address
lw s1, 4(sp)
sw s1, 0(s0)
// restore kstack ptr
// la s0, _cur_kstack_ptr
// addi s1, sp, 4 * 14
// sw s1, 0(s0)
// restore TLS
lw s1, 2*4(sp)
sw s1, 0(s2)
mtc0 s1, $4, 2 // cp0.user_local
lw ra, 0(sp)
lw s0, 2*4(sp)
lw s1, 3*4(sp)
lw s2, 4*4(sp)
lw s3, 5*4(sp)
lw s4, 6*4(sp)
lw s5, 7*4(sp)
lw s6, 8*4(sp)
lw s7, 9*4(sp)
lw s8, 10*4(sp)
lw gp, 11*4(sp)
lw s0, 4*4(sp)
lw s1, 5*4(sp)
lw s2, 6*4(sp)
lw s3, 7*4(sp)
lw s4, 8*4(sp)
lw s5, 9*4(sp)
lw s6, 10*4(sp)
lw s7, 11*4(sp)
lw s8, 12*4(sp)
lw gp, 13*4(sp)
addi sp, sp, (4*14)
sw zero, 0(a1)

@ -177,3 +177,6 @@ _root_page_table_ptr:
.global _cur_kstack_ptr
_cur_kstack_ptr:
.space 4 # 4bytes
.global _cur_tls
_cur_tls:
.space 4 # 4bytes

@ -130,17 +130,21 @@ struct ContextData {
ra: usize,
/// Page table token
satp: usize,
/// Callee-saved registers
/// s[0] = TLS
/// s[1] = reserved
/// s[2..11] = Callee-saved registers
s: [usize; 12],
}
impl ContextData {
fn new(satp: usize) -> Self {
ContextData {
fn new(satp: usize, tls: usize) -> Self {
let mut context = ContextData {
ra: trap_return as usize,
satp,
satp: satp,
..ContextData::default()
}
};
context.s[0] = tls;
context
}
}
@ -191,7 +195,7 @@ impl Context {
);
InitStack {
context: ContextData::new(satp),
context: ContextData::new(satp, 0),
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}
.push_at(kstack_top)
@ -215,7 +219,7 @@ impl Context {
);
InitStack {
context: ContextData::new(satp),
context: ContextData::new(satp, 0),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
}
.push_at(kstack_top)
@ -228,7 +232,7 @@ impl Context {
/// All the other registers are same as the original.
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Self {
InitStack {
context: ContextData::new(satp),
context: ContextData::new(satp, 0),
tf: {
let mut tf = tf.clone();
// fork function's ret value, the new process is 0
@ -254,11 +258,10 @@ impl Context {
tls: usize,
) -> Self {
InitStack {
context: ContextData::new(satp),
context: ContextData::new(satp, tls),
tf: {
let mut tf = tf.clone();
tf.sp = ustack_top; // sp
tf.v1 = tls;
tf.v0 = 0; // return value
tf
},

@ -70,6 +70,14 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
E::TLBModification => page_fault(tf),
E::TLBLoadMiss => page_fault(tf),
E::TLBStoreMiss => page_fault(tf),
E::ReservedInstruction => {
if !reserved_inst(tf) {
error!("Unhandled Exception @ CPU{}: {:?} ", 0, tf.cause.cause());
crate::trap::error(tf)
} else {
tf.epc = tf.epc + 4;
}
}
_ => {
error!("Unhandled Exception @ CPU{}: {:?} ", 0, tf.cause.cause());
crate::trap::error(tf)
@ -149,6 +157,78 @@ fn syscall(tf: &mut TrapFrame) {
}
}
fn set_trapframe_register(rt: usize, val: usize, tf: &mut TrapFrame) {
match rt {
1 => tf.at = val,
2 => tf.v0 = val,
3 => tf.v1 = val,
4 => tf.a0 = val,
5 => tf.a1 = val,
6 => tf.a2 = val,
7 => tf.a3 = val,
8 => tf.t0 = val,
9 => tf.t1 = val,
10 => tf.t2 = val,
11 => tf.t3 = val,
12 => tf.t4 = val,
13 => tf.t5 = val,
14 => tf.t6 = val,
15 => tf.t7 = val,
16 => tf.s0 = val,
17 => tf.s1 = val,
18 => tf.s2 = val,
19 => tf.s3 = val,
20 => tf.s4 = val,
21 => tf.s5 = val,
22 => tf.s6 = val,
23 => tf.s7 = val,
24 => tf.t8 = val,
25 => tf.t9 = val,
26 => tf.k0 = val,
27 => tf.k1 = val,
28 => tf.gp = val,
29 => tf.sp = val,
30 => tf.fp = val,
31 => tf.ra = val,
_ => {
error!("Unknown register {:?} ", rt);
crate::trap::error(tf)
}
}
}
fn reserved_inst(tf: &mut TrapFrame) -> bool {
let inst = unsafe {
*(tf.epc as *const usize)
};
let opcode = inst >> 26;
let rt = (inst >> 16) & 0b11111;
let rd = (inst >> 11) & 0b11111;
let sel = (inst >> 6) & 0b111;
let format = inst & 0b111111;
if opcode == 0b011111 && format == 0b111011 {
// RDHWR
if rd == 29 && sel == 0 {
info!("Read TLS by rdhdr");
extern "C" {
fn _cur_tls();
}
let tls = unsafe {
*(_cur_tls as *const usize)
};
set_trapframe_register(rt, tls, tf);
return true;
} else {
return false;
}
}
false
}
fn page_fault(tf: &mut TrapFrame) {
// TODO: set access/dirty bit
let addr = tf.vaddr;

@ -288,8 +288,15 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
let x86_64_ret = x86_64_syscall(id, args, tf);
#[cfg(not(target_arch = "x86_64"))]
let x86_64_ret = None;
#[cfg(target_arch = "mips")]
let mips_ret = mips_syscall(id, args, tf);
#[cfg(not(target_arch = "mips"))]
let mips_ret = None;
if let Some(ret) = x86_64_ret {
ret
} else if let Some(ret) = mips_ret {
ret
} else {
error!("unknown syscall id: {}, args: {:x?}", id, args);
crate::trap::error(tf);
@ -309,6 +316,27 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
}
}
#[cfg(target_arch = "mips")]
fn mips_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
let ret = match id {
SYS_SET_THREAD_AREA => {
extern "C" {
fn _cur_tls();
}
unsafe {
asm!("mtc0 $0, $$4, 2": :"r"(args[0]));
*(_cur_tls as *mut usize) = args[0];
}
Ok(0)
}
_ => {
return None;
}
};
Some(ret)
}
#[cfg(target_arch = "x86_64")]
fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
let ret = match id {

Loading…
Cancel
Save