1/* $OpenBSD: ghcb.h,v 1.7 2026/02/16 15:06:03 hshoexer Exp $ */
2
3/*
4 * Copyright (c) 2024, 2025 Hans-Joerg Hoexer <hshoexer@genua.de>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#ifndef _MACHINE_GHCB_H_
20#define _MACHINE_GHCB_H_
21
22#ifndef _LOCORE
23
24#include <sys/systm.h>
25
26#include <machine/frame.h>
27
28#define GHCB_OFFSET(m) ((m) / 8)
29#define GHCB_IDX(m) (GHCB_OFFSET((m)) / 8)
30#define GHCB_BIT(m) (GHCB_OFFSET((m)) % 8)
31
32#define GHCB_XSS 0x140
33#define GHCB_RAX 0x1F8
34#define GHCB_RBX 0x318
35#define GHCB_RCX 0x308
36#define GHCB_RDX 0x310
37#define GHCB_SW_EXITCODE 0x390
38#define GHCB_SW_EXITINFO1 0x398
39#define GHCB_SW_EXITINFO2 0x3A0
40#define GHCB_SW_SCRATCH 0x3A8
41#define GHCB_XCR0 0x3E8
42
43#define GHCB_MAX 0xFFF
44
45struct ghcb_sa {
46 uint8_t v_pad0[0xcb]; /* 000h-0CAh */
47 uint8_t v_cpl; /* 0CBh */
48 uint8_t v_pad1[0x74]; /* 0CCh-13Fh */
49 uint64_t v_xss; /* 140h */
50 uint8_t v_pad2[0x18]; /* 148h-15Fh */
51 uint64_t v_dr7; /* 160h */
52 uint8_t v_pad3[0x10]; /* 168h-177h */
53 uint64_t v_rip; /* 178h */
54 uint8_t v_pad4[0x58]; /* 180h-1D7h */
55 uint64_t v_rsp; /* 1D8h */
56 uint8_t v_pad5[0x18]; /* 1E0h-1F7h */
57 uint64_t v_rax; /* 1F8h */
58 uint8_t v_pad6[0x108]; /* 200h-307h */
59 uint64_t v_rcx; /* 308h */
60 uint64_t v_rdx; /* 310h */
61 uint64_t v_rbx; /* 318h */
62 uint8_t v_pad7[0x8]; /* 320h-327h */
63 uint64_t v_rbp; /* 328h */
64 uint64_t v_rsi; /* 330h */
65 uint64_t v_rdi; /* 338h */
66 uint64_t v_r8; /* 340h */
67 uint64_t v_r9; /* 348h */
68 uint64_t v_r10; /* 350h */
69 uint64_t v_r11; /* 358h */
70 uint64_t v_r12; /* 360h */
71 uint64_t v_r13; /* 368h */
72 uint64_t v_r14; /* 370h */
73 uint64_t v_r15; /* 378h */
74 uint8_t v_pad8[0x10]; /* 380h-38Fh */
75 uint64_t v_sw_exitcode; /* 390h */
76 uint64_t v_sw_exitinfo1; /* 398h */
77 uint64_t v_sw_exitinfo2; /* 3a0h */
78 uint64_t v_sw_scratch; /* 3a8h */
79 uint8_t v_pad9[0x38]; /* 3B0h-3E7h */
80 uint64_t v_xcr0; /* 3E8h */
81#define GHCB_VB_SZ 0x10
82 uint8_t valid_bitmap[GHCB_VB_SZ];
83 /* 3F0h-3FFh */
84 uint64_t v_x87_state_gpa; /* 400h */
85 uint8_t v_pad10[0x3f8]; /* 408h-7FFh */
86 uint8_t v_sharedbuf[0x7f0]; /* 800h-FEFh */
87 uint8_t v_pad11[0xa]; /* FF0h-FF9h */
88 uint16_t v_ghcb_proto_version; /* FFAh-FFBh */
89 uint32_t v_ghcb_usage; /* FFCh-FFFh */
90};
91
92#define GHCB_SZ8 0
93#define GHCB_SZ16 1
94#define GHCB_SZ32 2
95#define GHCB_SZ64 3
96
97struct ghcb_sync {
98 uint8_t valid_bitmap[GHCB_VB_SZ];
99
100 int sz_a;
101 int sz_b;
102 int sz_c;
103 int sz_d;
104};
105#endif /* !_LOCORE */
106
107/* Definitions used with the MSR protocol */
108#define MSR_PROTO_CPUID_REQ 0x4
109#define MSR_PROTO_CPUID_RESP 0x5
110#define MSR_PROTO_TERMINATE 0x100
111
112#ifndef _LOCORE
113
114extern vaddr_t ghcb_vaddr;
115extern paddr_t ghcb_paddr;
116
117struct ghcb_extra_regs {
118 uint64_t exitcode;
119 uint64_t exitinfo1;
120 uint64_t exitinfo2;
121 uint64_t scratch;
122 void *data;
123 size_t data_sz;
124};
125
126void ghcb_clear(struct ghcb_sa *);
127int ghcb_valbm_set(uint8_t *, int);
128int ghcb_valbm_isset(uint8_t *, int);
129int ghcb_verify_bm(uint8_t *, uint8_t *);
130int ghcb_valid(struct ghcb_sa *);
131int ghcb_empty(struct ghcb_sa *);
132
133void ghcb_sync_val(int, int, struct ghcb_sync *);
134void ghcb_sync_out(struct trapframe *, const struct ghcb_extra_regs *,
135 struct ghcb_sa *, struct ghcb_sync *);
136void ghcb_sync_in(struct trapframe *, struct ghcb_extra_regs *,
137 struct ghcb_sa *, struct ghcb_sync *);
138void _ghcb_mem_rw(vaddr_t, int, void *, bool);
139void _ghcb_io_rw(uint16_t, int, uint32_t *, bool);
140
141static inline uint8_t
142ghcb_mem_read_1(vaddr_t addr)
143{
144 uint8_t val;
145
146 _ghcb_mem_rw(addr, GHCB_SZ8, &val, true);
147 return val;
148}
149
150static inline uint16_t
151ghcb_mem_read_2(vaddr_t addr)
152{
153 uint16_t val;
154
155 _ghcb_mem_rw(addr, GHCB_SZ16, &val, true);
156 return val;
157}
158
159static inline uint32_t
160ghcb_mem_read_4(vaddr_t addr)
161{
162 uint32_t val;
163
164 _ghcb_mem_rw(addr, GHCB_SZ32, &val, true);
165 return val;
166}
167
168static inline uint64_t
169ghcb_mem_read_8(vaddr_t addr)
170{
171 uint64_t val;
172
173 _ghcb_mem_rw(addr, GHCB_SZ64, &val, true);
174 return val;
175}
176
177static inline void
178ghcb_mem_write_1(vaddr_t addr, uint8_t v)
179{
180 _ghcb_mem_rw(addr, GHCB_SZ8, &v, false);
181}
182
183static inline void
184ghcb_mem_write_2(vaddr_t addr, uint16_t v)
185{
186 _ghcb_mem_rw(addr, GHCB_SZ16, &v, false);
187}
188
189static inline void
190ghcb_mem_write_4(vaddr_t addr, uint32_t v)
191{
192 _ghcb_mem_rw(addr, GHCB_SZ32, &v, false);
193}
194
195static inline void
196ghcb_mem_write_8(vaddr_t addr, uint64_t v)
197{
198 _ghcb_mem_rw(addr, GHCB_SZ64, &v, false);
199}
200
201static inline uint8_t
202ghcb_io_read_1(uint16_t port)
203{
204 uint32_t val;
205
206 _ghcb_io_rw(port, GHCB_SZ8, &val, true);
207 return val;
208}
209
210static inline uint16_t
211ghcb_io_read_2(uint16_t port)
212{
213 uint32_t val;
214
215 _ghcb_io_rw(port, GHCB_SZ16, &val, true);
216 return val;
217}
218
219static inline uint32_t
220ghcb_io_read_4(uint16_t port)
221{
222 uint32_t val;
223
224 _ghcb_io_rw(port, GHCB_SZ32, &val, true);
225 return val;
226}
227
228static inline void
229ghcb_io_write_1(uint16_t port, uint8_t v)
230{
231 uint32_t val = v;
232
233 _ghcb_io_rw(port, GHCB_SZ8, &val, false);
234}
235
236static inline void
237ghcb_io_write_2(uint16_t port, uint16_t v)
238{
239 uint32_t val = v;
240
241 _ghcb_io_rw(port, GHCB_SZ16, &val, false);
242}
243
244static inline void
245ghcb_io_write_4(uint16_t port, uint32_t v)
246{
247 _ghcb_io_rw(port, GHCB_SZ32, &v, false);
248}
249
250#endif /* !_LOCORE */
251
252#endif /* !_MACHINE_GHCB_H_ */