Skip to content
This repository was archived by the owner on Nov 10, 2022. It is now read-only.

Commit 7daeb70

Browse files
committed
Initial stab at a context switching tools library
0 parents  commit 7daeb70

File tree

11 files changed

+599
-0
lines changed

11 files changed

+599
-0
lines changed

.github/workflows/lint.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
on: [push, pull_request]
2+
3+
name: lint
4+
5+
jobs:
6+
fmt:
7+
name: cargo fmt
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- uses: actions-rs/toolchain@v1
12+
with:
13+
components: rustfmt
14+
toolchain: nightly
15+
profile: minimal
16+
override: true
17+
- uses: actions-rs/cargo@v1
18+
with:
19+
command: fmt
20+
args: --all -- --check
21+
22+
clippy:
23+
name: cargo clippy
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v2
27+
- uses: actions-rs/toolchain@v1
28+
with:
29+
components: clippy
30+
toolchain: nightly
31+
profile: minimal
32+
override: true
33+
- uses: actions-rs/cargo@v1
34+
with:
35+
command: clippy
36+
args: -- -D warnings

.github/workflows/test.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
on: [push, pull_request]
3+
name: test
4+
jobs:
5+
test:
6+
name: ${{ matrix.config.target }}
7+
runs-on: ${{ matrix.config.os }}-latest
8+
steps:
9+
- run: ${{ matrix.config.prep }}
10+
- uses: actions/checkout@v2
11+
- uses: actions-rs/toolchain@v1
12+
with:
13+
target: ${{ matrix.config.target }}
14+
toolchain: nightly
15+
override: true
16+
- uses: actions-rs/cargo@v1
17+
with:
18+
command: test
19+
args: --release --target=${{ matrix.config.target }}
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
config:
24+
- target: i586-pc-windows-msvc
25+
os: windows
26+
- target: i586-unknown-linux-gnu
27+
prep: sudo apt install -y gcc-multilib
28+
os: ubuntu
29+
- target: i586-unknown-linux-musl
30+
os: ubuntu
31+
- target: i686-pc-windows-msvc
32+
os: windows
33+
- target: i686-unknown-linux-gnu
34+
prep: sudo apt install -y gcc-multilib
35+
os: ubuntu
36+
- target: i686-unknown-linux-musl
37+
os: ubuntu
38+
- target: x86_64-apple-darwin
39+
os: macos
40+
- target: x86_64-pc-windows-gnu
41+
os: windows
42+
- target: x86_64-pc-windows-msvc
43+
os: windows
44+
- target: x86_64-unknown-linux-gnu
45+
os: ubuntu
46+
- target: x86_64-unknown-linux-musl
47+
os: ubuntu

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "frenetic"
3+
version = "0.1.0"
4+
authors = ["Nathaniel McCallum <[email protected]>"]
5+
edition = "2018"
6+
license = "Apache-2.0"
7+
8+
categories = ["no-std"]
9+
keywords = ["no_std"]

src/arch/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4+
mod x86;
5+
6+
#[cfg(target_arch = "x86_64")]
7+
mod x86_64;
8+
9+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
10+
pub use x86::Extended;
11+
12+
#[cfg(target_arch = "x86")]
13+
pub use x86::Basic;
14+
15+
#[cfg(target_arch = "x86_64")]
16+
pub use x86_64::Basic;

src/arch/x86/mod.rs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
use core::mem::size_of;
4+
5+
#[derive(Default)]
6+
#[repr(C, align(16))]
7+
#[cfg(target_arch = "x86")]
8+
pub struct Basic([usize; 6]);
9+
10+
#[cfg(target_arch = "x86")]
11+
impl Basic {
12+
#[inline(never)]
13+
pub extern "C" fn wipe() {
14+
unsafe {
15+
asm!(
16+
"xor eax, eax",
17+
"xor ecx, ecx",
18+
"xor edx, edx",
19+
"add eax, eax",
20+
"cld",
21+
out("eax") _,
22+
out("ecx") _,
23+
out("edx") _,
24+
)
25+
}
26+
}
27+
28+
#[naked]
29+
#[must_use]
30+
#[inline(never)]
31+
pub extern "fastcall" fn save(&mut self) -> bool {
32+
unsafe {
33+
asm!(
34+
"pop edx",
35+
"mov [ecx + 0x00], edi",
36+
"mov [ecx + 0x04], esi",
37+
"mov [ecx + 0x08], ebx",
38+
"mov [ecx + 0x0a], ebp",
39+
"mov [ecx + 0x10], esp",
40+
"mov [ecx + 0x14], edx",
41+
"mov eax, 1",
42+
"jmp edx",
43+
options(noreturn)
44+
)
45+
}
46+
}
47+
48+
#[naked]
49+
#[inline(never)]
50+
pub unsafe extern "fastcall" fn load(&self) -> ! {
51+
asm!(
52+
"mov eax, 0",
53+
"mov edi, [ecx + 0x00]",
54+
"mov esi, [ecx + 0x04]",
55+
"mov ebx, [ecx + 0x08]",
56+
"mov ebp, [ecx + 0x0a]",
57+
"mov esp, [ecx + 0x10]",
58+
"jmp [ecx + 0x14]",
59+
options(noreturn)
60+
)
61+
}
62+
}
63+
64+
#[derive(Copy, Clone)]
65+
#[repr(C, align(16))]
66+
struct Mm([u8; 10], [u8; 6]);
67+
68+
#[derive(Copy, Clone)]
69+
#[repr(C, align(16))]
70+
struct Xmm([u8; 16]);
71+
72+
#[derive(Copy, Clone)]
73+
#[repr(C, align(64))]
74+
struct Legacy {
75+
fcw: u16,
76+
fsw: u16,
77+
ftw: u8,
78+
reserved: u8,
79+
fop: u16,
80+
fip: u64,
81+
fdp: u64,
82+
mxcsr: u32,
83+
mxcsr_mask: u32,
84+
mm: [Mm; 8],
85+
xmm: [Xmm; 16],
86+
unused: [u64; 12],
87+
}
88+
89+
#[derive(Copy, Clone)]
90+
#[repr(C, align(64))]
91+
struct Header {
92+
xstate_bv: u64,
93+
xcomp_bv: u64,
94+
reserved: [u64; 6],
95+
}
96+
97+
#[derive(Copy, Clone)]
98+
#[repr(C, align(4096))]
99+
pub struct XSave {
100+
legacy: Legacy,
101+
header: Header,
102+
extend: [u8; XSave::fill()],
103+
}
104+
105+
impl XSave {
106+
const DEFAULT: XSave = XSave {
107+
legacy: Legacy {
108+
fcw: 0x037F,
109+
fsw: 0,
110+
ftw: 0,
111+
reserved: 0,
112+
fop: 0,
113+
fip: 0,
114+
fdp: 0,
115+
mxcsr: 0x1F80,
116+
mxcsr_mask: 0xFFFF,
117+
mm: [Mm([0; 10], [0; 6]); 8],
118+
xmm: [Xmm([0; 16]); 16],
119+
unused: [0; 12],
120+
},
121+
122+
header: Header {
123+
xstate_bv: 0,
124+
xcomp_bv: 0,
125+
reserved: [0; 6],
126+
},
127+
128+
extend: [0; XSave::fill()],
129+
};
130+
131+
const fn fill() -> usize {
132+
4096 - size_of::<Legacy>() - size_of::<Header>()
133+
}
134+
}
135+
136+
#[repr(transparent)]
137+
pub struct Extended(XSave);
138+
139+
impl Default for Extended {
140+
fn default() -> Self {
141+
Self(XSave::DEFAULT)
142+
}
143+
}
144+
145+
impl Extended {
146+
#[inline(always)]
147+
pub fn wipe() {
148+
Self(XSave::DEFAULT).load()
149+
}
150+
151+
#[inline(never)]
152+
pub extern "C" fn save(&mut self) {
153+
unsafe {
154+
asm!(
155+
"mov eax, ~0",
156+
"mov edx, ~0",
157+
"xsave [{}]",
158+
159+
in(reg) &mut self.0,
160+
out("eax") _,
161+
out("edx") _,
162+
)
163+
}
164+
}
165+
166+
#[inline(never)]
167+
pub extern "C" fn load(&self) {
168+
unsafe {
169+
asm!(
170+
"mov eax, ~0",
171+
"mov edx, ~0",
172+
"xrstor [{}]",
173+
174+
in(reg) &self.0,
175+
out("eax") _,
176+
out("edx") _,
177+
)
178+
}
179+
}
180+
}
181+
182+
#[cfg(test)]
183+
#[test]
184+
fn size() {
185+
assert_eq!(size_of::<Header>(), 64);
186+
assert_eq!(size_of::<Legacy>(), 512);
187+
assert_eq!(size_of::<XSave>(), 4096);
188+
}

src/arch/x86_64/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#[cfg(not(target_os = "windows"))]
4+
mod sysv;
5+
6+
#[cfg(not(target_os = "windows"))]
7+
pub use sysv::Basic;
8+
9+
#[cfg(target_os = "windows")]
10+
mod win;
11+
12+
#[cfg(target_os = "windows")]
13+
pub use win::Basic;

src/arch/x86_64/sysv.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#[derive(Default)]
4+
#[repr(C, align(16))]
5+
pub struct Basic([usize; 8]);
6+
7+
impl Basic {
8+
#[naked]
9+
#[inline(never)]
10+
pub extern "C" fn wipe() {
11+
unsafe {
12+
asm!(
13+
"xor rax, rax",
14+
"xor rcx, rcx",
15+
"xor rdx, rdx",
16+
"xor rdi, rdi",
17+
"xor rsi, rsi",
18+
"xor r8, r8",
19+
"xor r9, r9",
20+
"xor r10, r10",
21+
"xor r11, r11",
22+
"add rax, rax",
23+
"cld",
24+
"ret",
25+
options(noreturn)
26+
)
27+
}
28+
}
29+
30+
#[naked]
31+
#[must_use]
32+
#[inline(never)]
33+
pub extern "C" fn save(&mut self) -> bool {
34+
unsafe {
35+
asm!(
36+
"pop rsi",
37+
"mov [rdi + 0x00], r15",
38+
"mov [rdi + 0x08], r14",
39+
"mov [rdi + 0x10], r13",
40+
"mov [rdi + 0x18], r12",
41+
"mov [rdi + 0x20], rbx",
42+
"mov [rdi + 0x28], rbp",
43+
"mov [rdi + 0x30], rsp",
44+
"mov [rdi + 0x38], rsi",
45+
"mov rax, 1",
46+
"jmp rsi",
47+
in("rdi") self,
48+
options(noreturn)
49+
)
50+
}
51+
}
52+
53+
#[naked]
54+
#[inline(never)]
55+
pub unsafe extern "C" fn load(&self) -> ! {
56+
asm!(
57+
"mov rax, 0",
58+
"mov r15, qword ptr [rdi + 0x00]",
59+
"mov r14, qword ptr [rdi + 0x08]",
60+
"mov r13, qword ptr [rdi + 0x10]",
61+
"mov r12, qword ptr [rdi + 0x18]",
62+
"mov rbx, qword ptr [rdi + 0x20]",
63+
"mov rbp, qword ptr [rdi + 0x28]",
64+
"mov rsp, qword ptr [rdi + 0x30]",
65+
"jmp qword ptr [rdi + 0x38]",
66+
in("rdi") self,
67+
options(noreturn)
68+
)
69+
}
70+
}

0 commit comments

Comments
 (0)