Skip to main content

hyperlight_guest_bin/arch/amd64/
context.rs

1/*
2Copyright 2025  The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15 */
16
17use super::machine::ExceptionInfo;
18
19#[repr(C)]
20/// Saved context, pushed onto the stack by exception entry code
21pub struct Context {
22    /// in order: ds, gs, fs, es
23    pub segments: [u64; 4],
24    pub fxsave: [u8; 512],
25    /// no `rsp`, since the processor saved it
26    /// `rax` is at the top, `r15` the bottom
27    pub gprs: [u64; 15],
28    _padding: u64,
29}
30const _: () = assert!(size_of::<Context>() == 32 + 512 + 120 + 8);
31// The combination of the ExceptionInfo (pushed by the CPU) and the
32// register Context that we save to the stack must be 16byte aligned
33// before calling the hl_exception_handler as specified in the x86-64
34// ELF System V psABI specification, Section 3.2.2:
35//
36// https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build
37const _: () = assert!((size_of::<Context>() + size_of::<ExceptionInfo>()).is_multiple_of(16));
38
39// Defines `context_save` and `context_restore`
40macro_rules! save {
41    () => {
42        concat!(
43            // Save general-purpose registers
44            "    sub rsp, 8\n",
45            "    push rax\n",
46            "    push rbx\n",
47            "    push rcx\n",
48            "    push rdx\n",
49            "    push rsi\n",
50            "    push rdi\n",
51            "    push rbp\n",
52            "    push r8\n",
53            "    push r9\n",
54            "    push r10\n",
55            "    push r11\n",
56            "    push r12\n",
57            "    push r13\n",
58            "    push r14\n",
59            "    push r15\n",
60            // Save floating-point/SSE registers
61            // TODO: Don't do this unconditionally: get the exn
62            //       handlers compiled without sse
63            // TODO: Check if we ever generate code with ymm/zmm in
64            //       the handlers and save/restore those as well
65            "    sub rsp, 512\n",
66            "    mov rax, rsp\n",
67            "    fxsave [rax]\n",
68            // Save the rest of the segment registers
69            "    mov rax, es\n",
70            "    push rax\n",
71            "    mov rax, fs\n",
72            "    push rax\n",
73            "    mov rax, gs\n",
74            "    push rax\n",
75            "    mov rax, ds\n",
76            "    push rax\n",
77        )
78    };
79}
80pub(super) use save;
81
82macro_rules! restore {
83    () => {
84        concat!(
85            // Restore most segment registers
86            "    pop rax\n",
87            "    mov ds, rax\n",
88            "    pop rax\n",
89            "    mov gs, rax\n",
90            "    pop rax\n",
91            "    mov fs, rax\n",
92            "    pop rax\n",
93            "    mov es, rax\n",
94            // Restore floating-point/SSE registers
95            "    mov rax, rsp\n",
96            "    fxrstor [rax]\n",
97            "    add rsp, 512\n",
98            // Restore general-purpose registers
99            "    pop r15\n",
100            "    pop r14\n",
101            "    pop r13\n",
102            "    pop r12\n",
103            "    pop r11\n",
104            "    pop r10\n",
105            "    pop r9\n",
106            "    pop r8\n",
107            "    pop rbp\n",
108            "    pop rdi\n",
109            "    pop rsi\n",
110            "    pop rdx\n",
111            "    pop rcx\n",
112            "    pop rbx\n",
113            "    pop rax\n",
114            "    add rsp, 8\n",
115        )
116    };
117}
118pub(super) use restore;