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