1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
//! Context Switching Operations
//! Low-level assembly for switching between Kata execution contexts
const kata_mod = @import("../kata/kata.zig");
/// Switch to a Kata's execution context
/// This function never returns - it jumps to userspace via iretq
pub fn switch_to_context(ctx: *const kata_mod.Context, page_table: u64, kernel_stack: u64) noreturn {
const ctx_addr = @intFromPtr(ctx);
asm volatile (
// Load context address and page table into registers
\\mov %[ctx_addr], %%rdi
\\mov %[pt], %%rsi
\\
// Switch to kata's higher-half kernel stack
\\mov %[kstack], %%rsp
\\
// Read iretq frame values from context struct
// Offsets based on Context struct layout:
// rsp=56, rip=128, rflags=136, cs=144, ss=152
\\mov 152(%%rdi), %%r12
\\mov 56(%%rdi), %%r13
\\mov 136(%%rdi), %%r14
\\mov 144(%%rdi), %%r15
\\mov 128(%%rdi), %%rax
\\
// Build iretq frame (ss, rsp, rflags, cs, rip)
\\pushq %%r12
\\pushq %%r13
\\pushq %%r14
\\pushq %%r15
\\pushq %%rax
\\
// Switch to user page table
\\mov %%rsi, %%cr3
\\
// Restore registers from context (offsets from Context struct)
// rax=0, rbx=8, rcx=16, rdx=24, rsi=32, rdi=40, rbp=48
// r8=64, r9=72, r10=80, r11=88, r12=96, r13=104, r14=112, r15=120
\\mov 8(%%rdi), %%rbx
\\mov 16(%%rdi), %%rcx
\\mov 24(%%rdi), %%rdx
\\mov 32(%%rdi), %%rsi
\\mov 48(%%rdi), %%rbp
\\mov 64(%%rdi), %%r8
\\mov 72(%%rdi), %%r9
\\mov 80(%%rdi), %%r10
\\mov 88(%%rdi), %%r11
\\mov 96(%%rdi), %%r12
\\mov 104(%%rdi), %%r13
\\mov 112(%%rdi), %%r14
\\mov 120(%%rdi), %%r15
\\mov 0(%%rdi), %%rax
\\mov 40(%%rdi), %%rdi
\\
// Jump to userspace
\\iretq
:
: [ctx_addr] "r" (ctx_addr),
[pt] "r" (page_table),
[kstack] "r" (kernel_stack),
: .{ .memory = true });
unreachable;
}
|