1f08c3bdfSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * x86-specific KVM helper functions and structures 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci#ifndef KVM_X86_H_ 9f08c3bdfSopenharmony_ci#define KVM_X86_H_ 10f08c3bdfSopenharmony_ci 11f08c3bdfSopenharmony_ci#include "kvm_test.h" 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci#define PAGESIZE 0x1000 14f08c3bdfSopenharmony_ci#define KVM_GDT_SIZE 32 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci/* Interrupts */ 17f08c3bdfSopenharmony_ci#define X86_INTR_COUNT 256 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#define INTR_ZERODIV 0 20f08c3bdfSopenharmony_ci#define INTR_DEBUG 1 21f08c3bdfSopenharmony_ci#define INTR_NMI 2 22f08c3bdfSopenharmony_ci#define INTR_BREAKPOINT 3 23f08c3bdfSopenharmony_ci#define INTR_OVERFLOW 4 24f08c3bdfSopenharmony_ci#define INTR_BOUND_RANGE_EXC 5 25f08c3bdfSopenharmony_ci#define INTR_BAD_OPCODE 6 26f08c3bdfSopenharmony_ci#define INTR_DEVICE_ERROR 7 27f08c3bdfSopenharmony_ci#define INTR_DOUBLE_FAULT 8 28f08c3bdfSopenharmony_ci#define INTR_INVALID_TSS 10 29f08c3bdfSopenharmony_ci#define INTR_SEGFAULT 11 30f08c3bdfSopenharmony_ci#define INTR_STACK_FAULT 12 31f08c3bdfSopenharmony_ci#define INTR_GPF 13 32f08c3bdfSopenharmony_ci#define INTR_PAGE_FAULT 14 33f08c3bdfSopenharmony_ci#define INTR_FPU_ERROR 16 34f08c3bdfSopenharmony_ci#define INTR_ALIGNMENT_ERROR 17 35f08c3bdfSopenharmony_ci#define INTR_MACHINE_CHECK 18 36f08c3bdfSopenharmony_ci#define INTR_SIMD_ERROR 19 37f08c3bdfSopenharmony_ci#define INTR_VIRT_ERROR 20 38f08c3bdfSopenharmony_ci#define INTR_CPE 21 39f08c3bdfSopenharmony_ci#define INTR_HV_INJECTION 28 40f08c3bdfSopenharmony_ci#define INTR_VMM_COMM 29 41f08c3bdfSopenharmony_ci#define INTR_SECURITY_ERROR 30 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci/* Segment descriptor flags */ 45f08c3bdfSopenharmony_ci#define SEGTYPE_LDT 0x02 46f08c3bdfSopenharmony_ci#define SEGTYPE_TSS 0x09 47f08c3bdfSopenharmony_ci#define SEGTYPE_TSS_BUSY 0x0b 48f08c3bdfSopenharmony_ci#define SEGTYPE_CALL_GATE 0x0c 49f08c3bdfSopenharmony_ci#define SEGTYPE_INTR_GATE 0x0e 50f08c3bdfSopenharmony_ci#define SEGTYPE_TRAP_GATE 0x0f 51f08c3bdfSopenharmony_ci#define SEGTYPE_RODATA 0x10 52f08c3bdfSopenharmony_ci#define SEGTYPE_RWDATA 0x12 53f08c3bdfSopenharmony_ci#define SEGTYPE_STACK 0x16 54f08c3bdfSopenharmony_ci#define SEGTYPE_CODE 0x1a 55f08c3bdfSopenharmony_ci#define SEGTYPE_MASK 0x1f 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci#define SEGFLAG_NSYSTEM 0x10 58f08c3bdfSopenharmony_ci#define SEGFLAG_PRESENT 0x80 59f08c3bdfSopenharmony_ci#define SEGFLAG_CODE64 0x200 60f08c3bdfSopenharmony_ci#define SEGFLAG_32BIT 0x400 61f08c3bdfSopenharmony_ci#define SEGFLAG_PAGE_LIMIT 0x800 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci/* CPUID constants */ 65f08c3bdfSopenharmony_ci#define CPUID_GET_INPUT_RANGE 0x80000000 66f08c3bdfSopenharmony_ci#define CPUID_GET_EXT_FEATURES 0x80000001 67f08c3bdfSopenharmony_ci#define CPUID_GET_SVM_FEATURES 0x8000000a 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci/* Model-specific CPU register constants */ 71f08c3bdfSopenharmony_ci#define MSR_EFER 0xc0000080 72f08c3bdfSopenharmony_ci#define MSR_VM_CR 0xc0010114 73f08c3bdfSopenharmony_ci#define MSR_VM_HSAVE_PA 0xc0010117 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci#define EFER_SCE (1 << 0) /* SYSCALL/SYSRET instructions enabled */ 76f08c3bdfSopenharmony_ci#define EFER_LME (1 << 8) /* CPU is running in 64bit mode */ 77f08c3bdfSopenharmony_ci#define EFER_LMA (1 << 10) /* CPU uses 64bit memory paging (read-only) */ 78f08c3bdfSopenharmony_ci#define EFER_NXE (1 << 11) /* Execute disable bit active */ 79f08c3bdfSopenharmony_ci#define EFER_SVME (1 << 12) /* AMD SVM instructions enabled */ 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci#define VM_CR_DPD (1 << 0) 82f08c3bdfSopenharmony_ci#define VM_CR_R_INIT (1 << 1) 83f08c3bdfSopenharmony_ci#define VM_CR_DIS_A20M (1 << 2) 84f08c3bdfSopenharmony_ci#define VM_CR_LOCK (1 << 3) 85f08c3bdfSopenharmony_ci#define VM_CR_SVMDIS (1 << 4) 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci/* Control register constants */ 88f08c3bdfSopenharmony_ci#define CR4_VME (1 << 0) 89f08c3bdfSopenharmony_ci#define CR4_PVI (1 << 1) 90f08c3bdfSopenharmony_ci#define CR4_TSD (1 << 2) 91f08c3bdfSopenharmony_ci#define CR4_DE (1 << 3) 92f08c3bdfSopenharmony_ci#define CR4_PSE (1 << 4) 93f08c3bdfSopenharmony_ci#define CR4_PAE (1 << 5) 94f08c3bdfSopenharmony_ci#define CR4_MCE (1 << 6) 95f08c3bdfSopenharmony_ci#define CR4_PGE (1 << 7) 96f08c3bdfSopenharmony_ci#define CR4_PCE (1 << 8) 97f08c3bdfSopenharmony_ci#define CR4_OSFXSR (1 << 9) 98f08c3bdfSopenharmony_ci#define CR4_OSXMMEXCPT (1 << 10) 99f08c3bdfSopenharmony_ci#define CR4_UMIP (1 << 11) 100f08c3bdfSopenharmony_ci#define CR4_LA57 (1 << 12) 101f08c3bdfSopenharmony_ci#define CR4_VMXE (1 << 13) 102f08c3bdfSopenharmony_ci#define CR4_SMXE (1 << 14) 103f08c3bdfSopenharmony_ci#define CR4_FSGSBASE (1 << 16) 104f08c3bdfSopenharmony_ci#define CR4_PCIDE (1 << 17) 105f08c3bdfSopenharmony_ci#define CR4_OSXSAVE (1 << 18) 106f08c3bdfSopenharmony_ci#define CR4_KL (1 << 19) 107f08c3bdfSopenharmony_ci#define CR4_SMEP (1 << 20) 108f08c3bdfSopenharmony_ci#define CR4_SMAP (1 << 21) 109f08c3bdfSopenharmony_ci#define CR4_PKE (1 << 22) 110f08c3bdfSopenharmony_ci#define CR4_CET (1 << 23) 111f08c3bdfSopenharmony_ci#define CR4_PKS (1 << 24) 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_cistruct intr_descriptor { 114f08c3bdfSopenharmony_ci uint16_t offset_lo; 115f08c3bdfSopenharmony_ci uint16_t selector; 116f08c3bdfSopenharmony_ci uint8_t ist; 117f08c3bdfSopenharmony_ci uint8_t flags; 118f08c3bdfSopenharmony_ci#if defined(__x86_64__) 119f08c3bdfSopenharmony_ci uint64_t offset_hi; /* top 16 bits must be set to 0 */ 120f08c3bdfSopenharmony_ci uint16_t padding; 121f08c3bdfSopenharmony_ci#else /* defined(__x86_64__) */ 122f08c3bdfSopenharmony_ci uint16_t offset_hi; 123f08c3bdfSopenharmony_ci#endif /* defined(__x86_64__) */ 124f08c3bdfSopenharmony_ci} __attribute__((__packed__)); 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_cistruct segment_descriptor { 127f08c3bdfSopenharmony_ci unsigned int limit_lo : 16; 128f08c3bdfSopenharmony_ci unsigned int baseaddr_lo : 24; 129f08c3bdfSopenharmony_ci unsigned int flags_lo : 8; 130f08c3bdfSopenharmony_ci unsigned int limit_hi : 4; 131f08c3bdfSopenharmony_ci unsigned int flags_hi : 4; 132f08c3bdfSopenharmony_ci unsigned int baseaddr_hi : 8; 133f08c3bdfSopenharmony_ci} __attribute__((__packed__)); 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_cistruct segment_descriptor64 { 136f08c3bdfSopenharmony_ci unsigned int limit_lo : 16; 137f08c3bdfSopenharmony_ci unsigned int baseaddr_lo : 24; 138f08c3bdfSopenharmony_ci unsigned int flags_lo : 8; 139f08c3bdfSopenharmony_ci unsigned int limit_hi : 4; 140f08c3bdfSopenharmony_ci unsigned int flags_hi : 4; 141f08c3bdfSopenharmony_ci uint64_t baseaddr_hi : 40; 142f08c3bdfSopenharmony_ci uint32_t reserved; 143f08c3bdfSopenharmony_ci} __attribute__((__packed__)); 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_cistruct page_table_entry_pae { 146f08c3bdfSopenharmony_ci unsigned int present: 1; 147f08c3bdfSopenharmony_ci unsigned int writable: 1; 148f08c3bdfSopenharmony_ci unsigned int user_access: 1; 149f08c3bdfSopenharmony_ci unsigned int write_through: 1; 150f08c3bdfSopenharmony_ci unsigned int disable_cache: 1; 151f08c3bdfSopenharmony_ci unsigned int accessed: 1; 152f08c3bdfSopenharmony_ci unsigned int dirty: 1; 153f08c3bdfSopenharmony_ci unsigned int page_type: 1; 154f08c3bdfSopenharmony_ci unsigned int global: 1; 155f08c3bdfSopenharmony_ci unsigned int padding: 3; 156f08c3bdfSopenharmony_ci uint64_t address: 40; 157f08c3bdfSopenharmony_ci unsigned int padding2: 7; 158f08c3bdfSopenharmony_ci unsigned int prot_key: 4; 159f08c3bdfSopenharmony_ci unsigned int noexec: 1; 160f08c3bdfSopenharmony_ci} __attribute__((__packed__)); 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_cistruct kvm_cpuid { 163f08c3bdfSopenharmony_ci unsigned int eax, ebx, ecx, edx; 164f08c3bdfSopenharmony_ci}; 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_cistruct kvm_cregs { 167f08c3bdfSopenharmony_ci unsigned long cr0, cr2, cr3, cr4; 168f08c3bdfSopenharmony_ci}; 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_cistruct kvm_sregs { 171f08c3bdfSopenharmony_ci uint16_t cs, ds, es, fs, gs, ss; 172f08c3bdfSopenharmony_ci}; 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_cistruct kvm_regs64 { 175f08c3bdfSopenharmony_ci uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, rsp; 176f08c3bdfSopenharmony_ci uint64_t r8, r9, r10, r11, r12, r13, r14, r15; 177f08c3bdfSopenharmony_ci}; 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ciextern struct page_table_entry_pae kvm_pagetable[]; 180f08c3bdfSopenharmony_ciextern struct intr_descriptor kvm_idt[X86_INTR_COUNT]; 181f08c3bdfSopenharmony_ciextern struct segment_descriptor kvm_gdt[KVM_GDT_SIZE]; 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci/* Page table helper functions */ 184f08c3bdfSopenharmony_ciuintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry); 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci/* Segment descriptor table functions */ 187f08c3bdfSopenharmony_civoid kvm_set_segment_descriptor(struct segment_descriptor *dst, 188f08c3bdfSopenharmony_ci uint64_t baseaddr, uint32_t limit, unsigned int flags); 189f08c3bdfSopenharmony_civoid kvm_parse_segment_descriptor(struct segment_descriptor *src, 190f08c3bdfSopenharmony_ci uint64_t *baseaddr, uint32_t *limit, unsigned int *flags); 191f08c3bdfSopenharmony_ciint kvm_find_free_descriptor(const struct segment_descriptor *table, 192f08c3bdfSopenharmony_ci size_t size); 193f08c3bdfSopenharmony_ciunsigned int kvm_create_stack_descriptor(struct segment_descriptor *table, 194f08c3bdfSopenharmony_ci size_t tabsize, void *stack_base); 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_ci/* Functions for querying CPU info and status */ 197f08c3bdfSopenharmony_civoid kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf); 198f08c3bdfSopenharmony_civoid kvm_read_cregs(struct kvm_cregs *buf); 199f08c3bdfSopenharmony_civoid kvm_read_sregs(struct kvm_sregs *buf); 200f08c3bdfSopenharmony_ciuint64_t kvm_rdmsr(unsigned int msr); 201f08c3bdfSopenharmony_civoid kvm_wrmsr(unsigned int msr, uint64_t value); 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci/* Low-level interrupt handlers, DO NOT call directly */ 204f08c3bdfSopenharmony_civoid kvm_handle_bad_exception(void); 205f08c3bdfSopenharmony_civoid kvm_handle_zerodiv(void); 206f08c3bdfSopenharmony_civoid kvm_handle_debug(void); 207f08c3bdfSopenharmony_civoid kvm_handle_nmi(void); 208f08c3bdfSopenharmony_civoid kvm_handle_breakpoint(void); 209f08c3bdfSopenharmony_civoid kvm_handle_overflow(void); 210f08c3bdfSopenharmony_civoid kvm_handle_bound_range_exc(void); 211f08c3bdfSopenharmony_civoid kvm_handle_bad_opcode(void); 212f08c3bdfSopenharmony_civoid kvm_handle_device_error(void); 213f08c3bdfSopenharmony_civoid kvm_handle_double_fault(void); 214f08c3bdfSopenharmony_civoid kvm_handle_invalid_tss(void); 215f08c3bdfSopenharmony_civoid kvm_handle_segfault(void); 216f08c3bdfSopenharmony_civoid kvm_handle_stack_fault(void); 217f08c3bdfSopenharmony_civoid kvm_handle_gpf(void); 218f08c3bdfSopenharmony_civoid kvm_handle_page_fault(void); 219f08c3bdfSopenharmony_civoid kvm_handle_fpu_error(void); 220f08c3bdfSopenharmony_civoid kvm_handle_alignment_error(void); 221f08c3bdfSopenharmony_civoid kvm_handle_machine_check(void); 222f08c3bdfSopenharmony_civoid kvm_handle_simd_error(void); 223f08c3bdfSopenharmony_civoid kvm_handle_virt_error(void); 224f08c3bdfSopenharmony_civoid kvm_handle_cpe(void); 225f08c3bdfSopenharmony_civoid kvm_handle_hv_injection(void); 226f08c3bdfSopenharmony_civoid kvm_handle_vmm_comm(void); 227f08c3bdfSopenharmony_civoid kvm_handle_security_error(void); 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci#endif /* KVM_X86_H_ */ 230