/* $NetBSD: nvmm_x86.h,v 1.15.4.2 2020/08/26 17:55:49 martin Exp $ */ /* * Copyright (c) 2018-2020 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Maxime Villard. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _NVMM_X86_H_ #define _NVMM_X86_H_ /* -------------------------------------------------------------------------- */ #ifndef ASM_NVMM struct nvmm_x86_exit_memory { int prot; gpaddr_t gpa; uint8_t inst_len; uint8_t inst_bytes[15]; }; struct nvmm_x86_exit_io { bool in; uint16_t port; int8_t seg; uint8_t address_size; uint8_t operand_size; bool rep; bool str; uint64_t npc; }; struct nvmm_x86_exit_rdmsr { uint32_t msr; uint64_t npc; }; struct nvmm_x86_exit_wrmsr { uint32_t msr; uint64_t val; uint64_t npc; }; struct nvmm_x86_exit_insn { uint64_t npc; }; struct nvmm_x86_exit_invalid { uint64_t hwcode; }; /* Generic. */ #define NVMM_VCPU_EXIT_NONE 0x0000000000000000ULL #define NVMM_VCPU_EXIT_INVALID 0xFFFFFFFFFFFFFFFFULL /* x86: operations. */ #define NVMM_VCPU_EXIT_MEMORY 0x0000000000000001ULL #define NVMM_VCPU_EXIT_IO 0x0000000000000002ULL /* x86: changes in VCPU state. */ #define NVMM_VCPU_EXIT_SHUTDOWN 0x0000000000001000ULL #define NVMM_VCPU_EXIT_INT_READY 0x0000000000001001ULL #define NVMM_VCPU_EXIT_NMI_READY 0x0000000000001002ULL #define NVMM_VCPU_EXIT_HALTED 0x0000000000001003ULL #define NVMM_VCPU_EXIT_TPR_CHANGED 0x0000000000001004ULL /* x86: instructions. */ #define NVMM_VCPU_EXIT_RDMSR 0x0000000000002000ULL #define NVMM_VCPU_EXIT_WRMSR 0x0000000000002001ULL #define NVMM_VCPU_EXIT_MONITOR 0x0000000000002002ULL #define NVMM_VCPU_EXIT_MWAIT 0x0000000000002003ULL #define NVMM_VCPU_EXIT_CPUID 0x0000000000002004ULL struct nvmm_x86_exit { uint64_t reason; union { struct nvmm_x86_exit_memory mem; struct nvmm_x86_exit_io io; struct nvmm_x86_exit_rdmsr rdmsr; struct nvmm_x86_exit_wrmsr wrmsr; struct nvmm_x86_exit_insn insn; struct nvmm_x86_exit_invalid inv; } u; struct { uint64_t rflags; uint64_t cr8; uint64_t int_shadow:1; uint64_t int_window_exiting:1; uint64_t nmi_window_exiting:1; uint64_t evt_pending:1; uint64_t rsvd:60; } exitstate; }; #define NVMM_VCPU_EVENT_EXCP 0 #define NVMM_VCPU_EVENT_INTR 1 struct nvmm_x86_event { u_int type; uint8_t vector; union { struct { uint64_t error; } excp; } u; }; struct nvmm_cap_md { uint64_t mach_conf_support; uint64_t vcpu_conf_support; #define NVMM_CAP_ARCH_VCPU_CONF_CPUID __BIT(0) #define NVMM_CAP_ARCH_VCPU_CONF_TPR __BIT(1) uint64_t xcr0_mask; uint32_t mxcsr_mask; uint32_t conf_cpuid_maxops; uint64_t rsvd[6]; }; #endif /* -------------------------------------------------------------------------- */ /* * Segment state indexes. We use X64 as naming convention, not to confuse with * X86 which originally implied 32bit. */ /* Segments. */ #define NVMM_X64_SEG_ES 0 #define NVMM_X64_SEG_CS 1 #define NVMM_X64_SEG_SS 2 #define NVMM_X64_SEG_DS 3 #define NVMM_X64_SEG_FS 4 #define NVMM_X64_SEG_GS 5 #define NVMM_X64_SEG_GDT 6 #define NVMM_X64_SEG_IDT 7 #define NVMM_X64_SEG_LDT 8 #define NVMM_X64_SEG_TR 9 #define NVMM_X64_NSEG 10 /* General Purpose Registers. */ #define NVMM_X64_GPR_RAX 0 #define NVMM_X64_GPR_RCX 1 #define NVMM_X64_GPR_RDX 2 #define NVMM_X64_GPR_RBX 3 #define NVMM_X64_GPR_RSP 4 #define NVMM_X64_GPR_RBP 5 #define NVMM_X64_GPR_RSI 6 #define NVMM_X64_GPR_RDI 7 #define NVMM_X64_GPR_R8 8 #define NVMM_X64_GPR_R9 9 #define NVMM_X64_GPR_R10 10 #define NVMM_X64_GPR_R11 11 #define NVMM_X64_GPR_R12 12 #define NVMM_X64_GPR_R13 13 #define NVMM_X64_GPR_R14 14 #define NVMM_X64_GPR_R15 15 #define NVMM_X64_GPR_RIP 16 #define NVMM_X64_GPR_RFLAGS 17 #define NVMM_X64_NGPR 18 /* Control Registers. */ #define NVMM_X64_CR_CR0 0 #define NVMM_X64_CR_CR2 1 #define NVMM_X64_CR_CR3 2 #define NVMM_X64_CR_CR4 3 #define NVMM_X64_CR_CR8 4 #define NVMM_X64_CR_XCR0 5 #define NVMM_X64_NCR 6 /* Debug Registers. */ #define NVMM_X64_DR_DR0 0 #define NVMM_X64_DR_DR1 1 #define NVMM_X64_DR_DR2 2 #define NVMM_X64_DR_DR3 3 #define NVMM_X64_DR_DR6 4 #define NVMM_X64_DR_DR7 5 #define NVMM_X64_NDR 6 /* MSRs. */ #define NVMM_X64_MSR_EFER 0 #define NVMM_X64_MSR_STAR 1 #define NVMM_X64_MSR_LSTAR 2 #define NVMM_X64_MSR_CSTAR 3 #define NVMM_X64_MSR_SFMASK 4 #define NVMM_X64_MSR_KERNELGSBASE 5 #define NVMM_X64_MSR_SYSENTER_CS 6 #define NVMM_X64_MSR_SYSENTER_ESP 7 #define NVMM_X64_MSR_SYSENTER_EIP 8 #define NVMM_X64_MSR_PAT 9 #define NVMM_X64_MSR_TSC 10 #define NVMM_X64_NMSR 11 #ifndef ASM_NVMM #include #include struct nvmm_x64_state_seg { uint16_t selector; struct { /* hidden */ uint16_t type:4; uint16_t s:1; uint16_t dpl:2; uint16_t p:1; uint16_t avl:1; uint16_t l:1; uint16_t def:1; uint16_t g:1; uint16_t rsvd:4; } attrib; uint32_t limit; /* hidden */ uint64_t base; /* hidden */ }; struct nvmm_x64_state_intr { uint64_t int_shadow:1; uint64_t int_window_exiting:1; uint64_t nmi_window_exiting:1; uint64_t evt_pending:1; uint64_t rsvd:60; }; /* Flags. */ #define NVMM_X64_STATE_SEGS 0x01 #define NVMM_X64_STATE_GPRS 0x02 #define NVMM_X64_STATE_CRS 0x04 #define NVMM_X64_STATE_DRS 0x08 #define NVMM_X64_STATE_MSRS 0x10 #define NVMM_X64_STATE_INTR 0x20 #define NVMM_X64_STATE_FPU 0x40 #define NVMM_X64_STATE_ALL \ (NVMM_X64_STATE_SEGS | NVMM_X64_STATE_GPRS | NVMM_X64_STATE_CRS | \ NVMM_X64_STATE_DRS | NVMM_X64_STATE_MSRS | NVMM_X64_STATE_INTR | \ NVMM_X64_STATE_FPU) struct nvmm_x64_state { struct nvmm_x64_state_seg segs[NVMM_X64_NSEG]; uint64_t gprs[NVMM_X64_NGPR]; uint64_t crs[NVMM_X64_NCR]; uint64_t drs[NVMM_X64_NDR]; uint64_t msrs[NVMM_X64_NMSR]; struct nvmm_x64_state_intr intr; struct fxsave fpu; }; #define NVMM_VCPU_CONF_CPUID NVMM_VCPU_CONF_MD_BEGIN #define NVMM_VCPU_CONF_TPR (NVMM_VCPU_CONF_MD_BEGIN + 1) struct nvmm_vcpu_conf_cpuid { /* The options. */ uint32_t mask:1; uint32_t exit:1; uint32_t rsvd:30; /* The leaf. */ uint32_t leaf; /* The params. */ union { struct { struct { uint32_t eax; uint32_t ebx; uint32_t ecx; uint32_t edx; } set; struct { uint32_t eax; uint32_t ebx; uint32_t ecx; uint32_t edx; } del; } mask; } u; }; struct nvmm_vcpu_conf_tpr { uint32_t exit_changed:1; uint32_t rsvd:31; }; #define nvmm_vcpu_exit nvmm_x86_exit #define nvmm_vcpu_event nvmm_x86_event #define nvmm_vcpu_state nvmm_x64_state #ifdef _KERNEL #define NVMM_X86_MACH_NCONF 0 #define NVMM_X86_VCPU_NCONF 2 struct nvmm_x86_cpuid_mask { uint32_t eax; uint32_t ebx; uint32_t ecx; uint32_t edx; }; extern const struct nvmm_x64_state nvmm_x86_reset_state; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000001; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000007; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008; bool nvmm_x86_pat_validate(uint64_t); #endif #endif /* ASM_NVMM */ #endif /* _NVMM_X86_H_ */