xref: /illumos-gate/usr/src/uts/intel/sys/hma.h (revision 7c8c0b82)
1a32a1f37SRobert Mustacchi /*
2a32a1f37SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3a32a1f37SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4a32a1f37SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5a32a1f37SRobert Mustacchi  * 1.0 of the CDDL.
6a32a1f37SRobert Mustacchi  *
7a32a1f37SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8a32a1f37SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9a32a1f37SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10a32a1f37SRobert Mustacchi  */
11a32a1f37SRobert Mustacchi 
12a32a1f37SRobert Mustacchi /*
13761dea5eSPatrick Mooney  * Copyright 2019 Joyent, Inc.
14957246c9SPatrick Mooney  * Copyright 2022 Oxide Computer Company
15a32a1f37SRobert Mustacchi  */
16a32a1f37SRobert Mustacchi 
17a32a1f37SRobert Mustacchi #ifndef _SYS_HMA_H
18a32a1f37SRobert Mustacchi #define	_SYS_HMA_H
19a32a1f37SRobert Mustacchi 
20a32a1f37SRobert Mustacchi /*
21a32a1f37SRobert Mustacchi  * Hypervisor Multiplexor API
22a32a1f37SRobert Mustacchi  *
23a32a1f37SRobert Mustacchi  * This provides a set of APIs that are usable by hypervisor implementations
24a32a1f37SRobert Mustacchi  * that allows them to coexist and to make sure that they are all in a
25a32a1f37SRobert Mustacchi  * consistent state.
26a32a1f37SRobert Mustacchi  */
27a32a1f37SRobert Mustacchi 
28a32a1f37SRobert Mustacchi #include <sys/fp.h>
29a32a1f37SRobert Mustacchi 
30a32a1f37SRobert Mustacchi #ifdef __cplusplus
31a32a1f37SRobert Mustacchi extern "C" {
32a32a1f37SRobert Mustacchi #endif
33a32a1f37SRobert Mustacchi 
34761dea5eSPatrick Mooney 
35761dea5eSPatrick Mooney /*
36761dea5eSPatrick Mooney  * Register a hypervisor with HMA.  On success, a pointer to the opaque
37761dea5eSPatrick Mooney  * registration token will be returned, indicating that proper host setup has
38761dea5eSPatrick Mooney  * occurred for further hypervisor actions.
39761dea5eSPatrick Mooney  */
40761dea5eSPatrick Mooney typedef struct hma_reg hma_reg_t;
41761dea5eSPatrick Mooney extern hma_reg_t *hma_register(const char *);
42454f0c49SAndy Fiddaman extern hma_reg_t *hma_register_exclusive(const char *);
43761dea5eSPatrick Mooney extern void hma_unregister(hma_reg_t *);
44761dea5eSPatrick Mooney 
45761dea5eSPatrick Mooney /*
46761dea5eSPatrick Mooney  * Allocate or free a VPID for use with VMX.
47761dea5eSPatrick Mooney  *
48761dea5eSPatrick Mooney  * This must not be performed by a hypervisor until it has successfully
49761dea5eSPatrick Mooney  * registered via hma_register().
50761dea5eSPatrick Mooney  */
51761dea5eSPatrick Mooney extern uint16_t hma_vmx_vpid_alloc(void);
52761dea5eSPatrick Mooney extern void hma_vmx_vpid_free(uint16_t);
53761dea5eSPatrick Mooney 
54761dea5eSPatrick Mooney /*
55761dea5eSPatrick Mooney  * On all active CPUs, perform a single-context INVEPT on the given EPTP.
56761dea5eSPatrick Mooney  */
57761dea5eSPatrick Mooney extern void hma_vmx_invept_allcpus(uintptr_t);
58761dea5eSPatrick Mooney 
59761dea5eSPatrick Mooney struct hma_svm_asid {
60761dea5eSPatrick Mooney 	uint64_t hsa_gen;
61761dea5eSPatrick Mooney 	uint32_t hsa_asid;
62761dea5eSPatrick Mooney };
63761dea5eSPatrick Mooney typedef struct hma_svm_asid hma_svm_asid_t;
64761dea5eSPatrick Mooney 
65761dea5eSPatrick Mooney extern void hma_svm_asid_init(hma_svm_asid_t *);
66761dea5eSPatrick Mooney extern uint8_t hma_svm_asid_update(hma_svm_asid_t *, boolean_t, boolean_t);
67761dea5eSPatrick Mooney 
68a32a1f37SRobert Mustacchi /*
69a32a1f37SRobert Mustacchi  * FPU related management. These functions provide a set of APIs to manage the
70a32a1f37SRobert Mustacchi  * FPU state and switch between host and guest management of this state.
71a32a1f37SRobert Mustacchi  */
72a32a1f37SRobert Mustacchi 
73a32a1f37SRobert Mustacchi typedef struct hma_fpu hma_fpu_t;
74a32a1f37SRobert Mustacchi 
75a32a1f37SRobert Mustacchi /*
76a32a1f37SRobert Mustacchi  * Allocate and free FPU state management structures.
77a32a1f37SRobert Mustacchi  */
78a32a1f37SRobert Mustacchi extern hma_fpu_t *hma_fpu_alloc(int);
79a32a1f37SRobert Mustacchi extern void hma_fpu_free(hma_fpu_t *);
80a32a1f37SRobert Mustacchi 
81a32a1f37SRobert Mustacchi /*
82a32a1f37SRobert Mustacchi  * Resets the FPU to the standard x86 default state. This should be called after
83a32a1f37SRobert Mustacchi  * allocation and whenever the guest needs to logically reset the state (when
84a32a1f37SRobert Mustacchi  * the CPU is reset, etc.). If the system supports xsave, then the xbv state
85a32a1f37SRobert Mustacchi  * will be set to have the x87 and SSE portions as valid and the rest will be
86a32a1f37SRobert Mustacchi  * set to their initial states (regardless of whether or not they will be
87a32a1f37SRobert Mustacchi  * advertised in the host).
88a32a1f37SRobert Mustacchi  */
89a32a1f37SRobert Mustacchi extern int hma_fpu_init(hma_fpu_t *);
90a32a1f37SRobert Mustacchi 
91a32a1f37SRobert Mustacchi /*
92a32a1f37SRobert Mustacchi  * Save the current host's FPU state and restore the guest's state in the FPU.
93a32a1f37SRobert Mustacchi  * At this point, CR0.TS will not be set. The caller must not use the FPU in any
94a32a1f37SRobert Mustacchi  * way before entering the guest.
95a32a1f37SRobert Mustacchi  *
96a32a1f37SRobert Mustacchi  * This should be used in normal operation before entering the guest. It should
97a32a1f37SRobert Mustacchi  * also be used in a thread context operation when the thread is being scheduled
98a32a1f37SRobert Mustacchi  * again. This interface has an implicit assumption that a given guest state
99a32a1f37SRobert Mustacchi  * will be mapped to only one specific OS thread at any given time.
100a32a1f37SRobert Mustacchi  *
101a32a1f37SRobert Mustacchi  * This must be called with preemption disabled.
102a32a1f37SRobert Mustacchi  */
103a32a1f37SRobert Mustacchi extern void hma_fpu_start_guest(hma_fpu_t *);
104a32a1f37SRobert Mustacchi 
105a32a1f37SRobert Mustacchi /*
106a32a1f37SRobert Mustacchi  * Save the current guest's FPU state and restore the host's state in the FPU.
107a32a1f37SRobert Mustacchi  * By the time the thread returns to userland, the FPU will be in a usable
108a32a1f37SRobert Mustacchi  * state; however, the FPU will not be usable while inside the kernel (CR0.TS
109a32a1f37SRobert Mustacchi  * will be set).
110a32a1f37SRobert Mustacchi  *
111a32a1f37SRobert Mustacchi  * This should be used in normal operation after leaving the guest and returning
112a32a1f37SRobert Mustacchi  * to user land. It should also be used in a thread context operation when the
113a32a1f37SRobert Mustacchi  * thread is being descheduled. Like the hma_fpu_start_guest() interface, this
114a32a1f37SRobert Mustacchi  * interface has an implicit assumption that a given guest state will be mapped
115a32a1f37SRobert Mustacchi  * to only a single OS thread at any given time.
116a32a1f37SRobert Mustacchi  *
117a32a1f37SRobert Mustacchi  * This must be called with preemption disabled.
118a32a1f37SRobert Mustacchi  */
119a32a1f37SRobert Mustacchi extern void hma_fpu_stop_guest(hma_fpu_t *);
120a32a1f37SRobert Mustacchi 
121957246c9SPatrick Mooney typedef enum {
122957246c9SPatrick Mooney 	HFXR_OK = 0,
123957246c9SPatrick Mooney 	HFXR_NO_SPACE,		/* buffer is not large enough */
124957246c9SPatrick Mooney 	HFXR_BAD_ALIGN,		/* buffer is not properly (64-byte) aligned */
125957246c9SPatrick Mooney 	HFXR_UNSUP_FMT,		/* data using unsupported (compressed) format */
126957246c9SPatrick Mooney 	HFXR_UNSUP_FEAT,	/* data has unsupported features set */
127957246c9SPatrick Mooney 	HFXR_INVALID_DATA,	/* CPU determined xsave data is invalid */
128957246c9SPatrick Mooney } hma_fpu_xsave_result_t;
129957246c9SPatrick Mooney 
130957246c9SPatrick Mooney /*
131957246c9SPatrick Mooney  * Get and set the contents of the FPU save area, formatted as XSAVE-style
132957246c9SPatrick Mooney  * information.  If XSAVE is not supported by the host, the input and output
133957246c9SPatrick Mooney  * values will be translated to and from the FXSAVE format.  Attempts to set
134957246c9SPatrick Mooney  * XSAVE values not supported by the host will result in an error.
135957246c9SPatrick Mooney  *
136957246c9SPatrick Mooney  * These functions cannot be called while the FPU is in use by the guest. It is
137957246c9SPatrick Mooney  * up to callers to guarantee this invariant.
138957246c9SPatrick Mooney  */
139957246c9SPatrick Mooney extern hma_fpu_xsave_result_t hma_fpu_get_xsave_state(const hma_fpu_t *, void *,
140957246c9SPatrick Mooney     size_t);
141957246c9SPatrick Mooney extern hma_fpu_xsave_result_t hma_fpu_set_xsave_state(hma_fpu_t *, void *,
142957246c9SPatrick Mooney     size_t);
143957246c9SPatrick Mooney 
144957246c9SPatrick Mooney typedef struct hma_xsave_state_desc {
145957246c9SPatrick Mooney 	uint64_t	hxsd_bit;
146957246c9SPatrick Mooney 	uint32_t	hxsd_size;
147957246c9SPatrick Mooney 	uint32_t	hxsd_off;
148957246c9SPatrick Mooney } hma_xsave_state_desc_t;
149957246c9SPatrick Mooney 
150957246c9SPatrick Mooney /*
151957246c9SPatrick Mooney  * Get a description of the data fields supported by the host via the XSAVE APIs
152957246c9SPatrick Mooney  * for getting/setting guest FPU data.  See the function definition for more
153957246c9SPatrick Mooney  * detailed parameter usage.
154957246c9SPatrick Mooney  */
155957246c9SPatrick Mooney extern uint_t hma_fpu_describe_xsave_state(hma_xsave_state_desc_t *, uint_t,
156957246c9SPatrick Mooney     size_t *);
157957246c9SPatrick Mooney 
158a32a1f37SRobert Mustacchi /*
159a32a1f37SRobert Mustacchi  * Get and set the contents of the FPU save area. This sets the fxsave style
160a32a1f37SRobert Mustacchi  * information. In all cases when this is in use, if an XSAVE state is actually
161a32a1f37SRobert Mustacchi  * used by the host, then this will end up zeroing all of the non-fxsave state
162a32a1f37SRobert Mustacchi  * and it will reset the xbv to indicate that the legacy x87 and SSE portions
163a32a1f37SRobert Mustacchi  * are valid.
164a32a1f37SRobert Mustacchi  *
165a32a1f37SRobert Mustacchi  * These functions cannot be called while the FPU is in use by the guest. It is
166a32a1f37SRobert Mustacchi  * up to callers to guarantee this fact.
167a32a1f37SRobert Mustacchi  */
168a32a1f37SRobert Mustacchi extern void hma_fpu_get_fxsave_state(const hma_fpu_t *, struct fxsave_state *);
169a32a1f37SRobert Mustacchi extern int hma_fpu_set_fxsave_state(hma_fpu_t *, const struct fxsave_state *);
170a32a1f37SRobert Mustacchi 
171761dea5eSPatrick Mooney /* Perform HMA initialization steps during boot-up. */
172761dea5eSPatrick Mooney extern void hma_init(void);
173761dea5eSPatrick Mooney 
174a32a1f37SRobert Mustacchi #ifdef __cplusplus
175a32a1f37SRobert Mustacchi }
176a32a1f37SRobert Mustacchi #endif
177a32a1f37SRobert Mustacchi 
178a32a1f37SRobert Mustacchi #endif /* _SYS_HMA_H */
179