mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 06:47:34 +00:00
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.
This commit is contained in:
parent
63e53b8af2
commit
442f4a5f2c
@ -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);
|
||||
|
@ -86,16 +86,40 @@ SWAP_REGISTERS:
|
||||
mov %r14, (RUSTRT_R14*8)(ARG0)
|
||||
mov %r15, (RUSTRT_R15*8)(ARG0)
|
||||
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
mov %rdi, (RUSTRT_RDI*8)(ARG0)
|
||||
mov %rsi, (RUSTRT_RSI*8)(ARG0)
|
||||
|
||||
// Save stack range
|
||||
mov %gs:0x08, %r8
|
||||
mov %r8, (RUSTRT_ST1*8)(ARG0)
|
||||
mov %gs:0x10, %r9
|
||||
mov %r9, (RUSTRT_ST2*8)(ARG0)
|
||||
#endif
|
||||
|
||||
// Save 0th argument register:
|
||||
mov ARG0, (RUSTRT_ARG0*8)(ARG0)
|
||||
|
||||
// Save non-volatile XMM registers:
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
movapd %xmm6, (RUSTRT_XMM6*8)(ARG0)
|
||||
movapd %xmm7, (RUSTRT_XMM7*8)(ARG0)
|
||||
movapd %xmm8, (RUSTRT_XMM8*8)(ARG0)
|
||||
movapd %xmm9, (RUSTRT_XMM9*8)(ARG0)
|
||||
movapd %xmm10, (RUSTRT_XMM10*8)(ARG0)
|
||||
movapd %xmm11, (RUSTRT_XMM11*8)(ARG0)
|
||||
movapd %xmm12, (RUSTRT_XMM12*8)(ARG0)
|
||||
movapd %xmm13, (RUSTRT_XMM13*8)(ARG0)
|
||||
movapd %xmm14, (RUSTRT_XMM14*8)(ARG0)
|
||||
movapd %xmm15, (RUSTRT_XMM15*8)(ARG0)
|
||||
#else
|
||||
movapd %xmm0, (RUSTRT_XMM0*8)(ARG0)
|
||||
movapd %xmm1, (RUSTRT_XMM1*8)(ARG0)
|
||||
movapd %xmm2, (RUSTRT_XMM2*8)(ARG0)
|
||||
movapd %xmm3, (RUSTRT_XMM3*8)(ARG0)
|
||||
movapd %xmm4, (RUSTRT_XMM4*8)(ARG0)
|
||||
movapd %xmm5, (RUSTRT_XMM5*8)(ARG0)
|
||||
#endif
|
||||
|
||||
// Restore non-volatile integer registers:
|
||||
// (including RSP)
|
||||
@ -107,16 +131,40 @@ SWAP_REGISTERS:
|
||||
mov (RUSTRT_R14*8)(ARG1), %r14
|
||||
mov (RUSTRT_R15*8)(ARG1), %r15
|
||||
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
mov (RUSTRT_RDI*8)(ARG1), %rdi
|
||||
mov (RUSTRT_RSI*8)(ARG1), %rsi
|
||||
|
||||
// Restore stack range
|
||||
mov (RUSTRT_ST1*8)(ARG1), %r8
|
||||
mov %r8, %gs:0x08
|
||||
mov (RUSTRT_ST2*8)(ARG1), %r9
|
||||
mov %r9, %gs:0x10
|
||||
#endif
|
||||
|
||||
// Restore 0th argument register:
|
||||
mov (RUSTRT_ARG0*8)(ARG1), ARG0
|
||||
|
||||
// Restore non-volatile XMM registers:
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
movapd (RUSTRT_XMM6*8)(ARG1), %xmm6
|
||||
movapd (RUSTRT_XMM7*8)(ARG1), %xmm7
|
||||
movapd (RUSTRT_XMM8*8)(ARG1), %xmm8
|
||||
movapd (RUSTRT_XMM9*8)(ARG1), %xmm9
|
||||
movapd (RUSTRT_XMM10*8)(ARG1), %xmm10
|
||||
movapd (RUSTRT_XMM11*8)(ARG1), %xmm11
|
||||
movapd (RUSTRT_XMM12*8)(ARG1), %xmm12
|
||||
movapd (RUSTRT_XMM13*8)(ARG1), %xmm13
|
||||
movapd (RUSTRT_XMM14*8)(ARG1), %xmm14
|
||||
movapd (RUSTRT_XMM15*8)(ARG1), %xmm15
|
||||
#else
|
||||
movapd (RUSTRT_XMM0*8)(ARG1), %xmm0
|
||||
movapd (RUSTRT_XMM1*8)(ARG1), %xmm1
|
||||
movapd (RUSTRT_XMM2*8)(ARG1), %xmm2
|
||||
movapd (RUSTRT_XMM3*8)(ARG1), %xmm3
|
||||
movapd (RUSTRT_XMM4*8)(ARG1), %xmm4
|
||||
movapd (RUSTRT_XMM5*8)(ARG1), %xmm5
|
||||
#endif
|
||||
|
||||
// Jump to the instruction pointer
|
||||
// found in regs:
|
||||
|
@ -18,15 +18,33 @@
|
||||
#define RUSTRT_R14 6
|
||||
#define RUSTRT_R15 7
|
||||
#define RUSTRT_IP 8
|
||||
// Not used, just padding
|
||||
#define RUSTRT_XXX 9
|
||||
#define RUSTRT_XMM0 10
|
||||
#define RUSTRT_XMM1 12
|
||||
#define RUSTRT_XMM2 14
|
||||
#define RUSTRT_XMM3 16
|
||||
#define RUSTRT_XMM4 18
|
||||
#define RUSTRT_XMM5 20
|
||||
#define RUSTRT_MAX 22
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
#define RUSTRT_RDI 9
|
||||
#define RUSTRT_RSI 10
|
||||
#define RUSTRT_ST1 11
|
||||
#define RUSTRT_ST2 12
|
||||
#define RUSTRT_XMM6 14
|
||||
#define RUSTRT_XMM7 16
|
||||
#define RUSTRT_XMM8 18
|
||||
#define RUSTRT_XMM9 20
|
||||
#define RUSTRT_XMM10 22
|
||||
#define RUSTRT_XMM11 24
|
||||
#define RUSTRT_XMM12 26
|
||||
#define RUSTRT_XMM13 28
|
||||
#define RUSTRT_XMM14 30
|
||||
#define RUSTRT_XMM15 32
|
||||
#define RUSTRT_MAX 34
|
||||
#else
|
||||
// Not used, just padding
|
||||
#define RUSTRT_XXX 9
|
||||
#define RUSTRT_XMM0 10
|
||||
#define RUSTRT_XMM1 12
|
||||
#define RUSTRT_XMM2 14
|
||||
#define RUSTRT_XMM3 16
|
||||
#define RUSTRT_XMM4 18
|
||||
#define RUSTRT_XMM5 20
|
||||
#define RUSTRT_MAX 22
|
||||
#endif
|
||||
|
||||
// ARG0 is the register in which the first argument goes.
|
||||
// Naturally this depends on your operating system.
|
||||
|
Loading…
Reference in New Issue
Block a user