diff options
| author | klutzy <klutzytheklutzy@gmail.com> | 2013-08-26 22:01:55 +0900 |
|---|---|---|
| committer | klutzy <klutzytheklutzy@gmail.com> | 2013-08-26 22:16:54 +0900 |
| commit | 442f4a5f2ca6f7f4082c09968e0fd83601a50d2a (patch) | |
| tree | 9ad67e23fcc2987c6500414796a36b4c454e7499 /src/libstd/rt | |
| parent | 63e53b8af2f37f9eb8eda0087b02f8deba252c2f (diff) | |
| download | rust-442f4a5f2ca6f7f4082c09968e0fd83601a50d2a.tar.gz rust-442f4a5f2ca6f7f4082c09968e0fd83601a50d2a.zip | |
Support Win64 context switching
This patch saves and restores win64's nonvolatile registers. This patch also saves stack information of thread environment block (TEB), which is at %gs:0x08 and %gs:0x10.
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/context.rs | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs index 5aaddc68383..476554bf7f7 100644 --- a/src/libstd/rt/context.rs +++ b/src/libstd/rt/context.rs @@ -47,6 +47,7 @@ impl Context { let fp: *c_void = task_start_wrapper as *c_void; let argp: *c_void = unsafe { transmute::<&~fn(), *c_void>(&*start) }; + let stack_base: *uint = stack.start(); let sp: *uint = stack.end(); let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) }; // Save and then immediately load the current context, @@ -56,7 +57,7 @@ impl Context { swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs)); }; - initialize_call_frame(&mut *regs, fp, argp, sp); + initialize_call_frame(&mut *regs, fp, argp, sp, stack_base); return Context { start: Some(start), @@ -107,7 +108,8 @@ fn new_regs() -> ~Registers { } #[cfg(target_arch = "x86")] -fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, + sp: *mut uint, _stack_base: *uint) { let sp = align_down(sp); let sp = mut_offset(sp, -4); @@ -123,14 +125,19 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: regs.ebp = 0; } -#[cfg(target_arch = "x86_64")] +#[cfg(windows, target_arch = "x86_64")] +type Registers = [uint, ..34]; +#[cfg(not(windows), target_arch = "x86_64")] type Registers = [uint, ..22]; -#[cfg(target_arch = "x86_64")] +#[cfg(windows, target_arch = "x86_64")] +fn new_regs() -> ~Registers { ~([0, .. 34]) } +#[cfg(not(windows), target_arch = "x86_64")] fn new_regs() -> ~Registers { ~([0, .. 22]) } #[cfg(target_arch = "x86_64")] -fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, + sp: *mut uint, stack_base: *uint) { // Redefinitions from regs.h static RUSTRT_ARG0: uint = 3; @@ -138,6 +145,21 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: static RUSTRT_IP: uint = 8; static RUSTRT_RBP: uint = 2; + #[cfg(windows)] + fn initialize_tib(regs: &mut Registers, sp: *mut uint, stack_base: *uint) { + // Redefinitions from regs.h + static RUSTRT_ST1: uint = 11; // stack bottom + static RUSTRT_ST2: uint = 12; // stack top + regs[RUSTRT_ST1] = sp as uint; + regs[RUSTRT_ST2] = stack_base as uint; + } + #[cfg(not(windows))] + fn initialize_tib(_: &mut Registers, _: *mut uint, _: *uint) { + } + + // Win64 manages stack range at TIB: %gs:0x08 (top) and %gs:0x10 (bottom) + initialize_tib(regs, sp, stack_base); + let sp = align_down(sp); let sp = mut_offset(sp, -1); @@ -164,7 +186,8 @@ type Registers = [uint, ..32]; fn new_regs() -> ~Registers { ~([0, .. 32]) } #[cfg(target_arch = "arm")] -fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, + sp: *mut uint, _stack_base: *uint) { let sp = align_down(sp); // sp of arm eabi is 8-byte aligned let sp = mut_offset(sp, -2); @@ -184,7 +207,8 @@ type Registers = [uint, ..32]; fn new_regs() -> ~Registers { ~([0, .. 32]) } #[cfg(target_arch = "mips")] -fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, + sp: *mut uint, _stack_base: *uint) { let sp = align_down(sp); // sp of mips o32 is 8-byte aligned let sp = mut_offset(sp, -2); |
