aboutsummaryrefslogtreecommitdiff
path: root/mirai.old/asm/context.zig
blob: 5876b33eb1cf00a26a36421bb1f03e783351093b (plain)
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;
}