• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz>
4  *
5  * x86-specific KVM helper functions and structures
6  */
7 
8 #ifndef KVM_X86_H_
9 #define KVM_X86_H_
10 
11 #include "kvm_test.h"
12 
13 /* Interrupts */
14 #define X86_INTR_COUNT 256
15 
16 #define INTR_ZERODIV 0
17 #define INTR_DEBUG 1
18 #define INTR_NMI 2
19 #define INTR_BREAKPOINT 3
20 #define INTR_OVERFLOW 4
21 #define INTR_BOUND_RANGE_EXC 5
22 #define INTR_BAD_OPCODE 6
23 #define INTR_DEVICE_ERROR 7
24 #define INTR_DOUBLE_FAULT 8
25 #define INTR_INVALID_TSS 10
26 #define INTR_SEGFAULT 11
27 #define INTR_STACK_FAULT 12
28 #define INTR_GPF 13
29 #define INTR_PAGE_FAULT 14
30 #define INTR_FPU_ERROR 16
31 #define INTR_ALIGNMENT_ERROR 17
32 #define INTR_MACHINE_CHECK 18
33 #define INTR_SIMD_ERROR 19
34 #define INTR_VIRT_ERROR 20
35 #define INTR_CPE 21
36 #define INTR_HV_INJECTION 28
37 #define INTR_VMM_COMM 29
38 #define INTR_SECURITY_ERROR 30
39 
40 
41 /* CPUID constants */
42 #define CPUID_GET_INPUT_RANGE 0x80000000
43 #define CPUID_GET_EXT_FEATURES 0x80000001
44 
45 
46 /* Model-specific CPU register constants */
47 #define MSR_EFER 0xc0000080
48 
49 #define EFER_SCE (1 << 0)	/* SYSCALL/SYSRET instructions enabled */
50 #define EFER_LME (1 << 8)	/* CPU is running in 64bit mode */
51 #define EFER_LMA (1 << 10)	/* CPU uses 64bit memory paging (read-only) */
52 #define EFER_NXE (1 << 11)	/* Execute disable bit active */
53 
54 
55 /* Control register constants */
56 #define CR4_VME (1 << 0)
57 #define CR4_PVI (1 << 1)
58 #define CR4_TSD (1 << 2)
59 #define CR4_DE (1 << 3)
60 #define CR4_PSE (1 << 4)
61 #define CR4_PAE (1 << 5)
62 #define CR4_MCE (1 << 6)
63 #define CR4_PGE (1 << 7)
64 #define CR4_PCE (1 << 8)
65 #define CR4_OSFXSR (1 << 9)
66 #define CR4_OSXMMEXCPT (1 << 10)
67 #define CR4_UMIP (1 << 11)
68 #define CR4_LA57 (1 << 12)
69 #define CR4_VMXE (1 << 13)
70 #define CR4_SMXE (1 << 14)
71 #define CR4_FSGSBASE (1 << 16)
72 #define CR4_PCIDE (1 << 17)
73 #define CR4_OSXSAVE (1 << 18)
74 #define CR4_KL (1 << 19)
75 #define CR4_SMEP (1 << 20)
76 #define CR4_SMAP (1 << 21)
77 #define CR4_PKE (1 << 22)
78 #define CR4_CET (1 << 23)
79 #define CR4_PKS (1 << 24)
80 
81 struct intr_descriptor {
82 	uint16_t offset_lo;
83 	uint16_t selector;
84 	uint8_t ist;
85 	uint8_t flags;
86 #if defined(__x86_64__)
87 	uint64_t offset_hi; /* top 16 bits must be set to 0 */
88 	uint16_t padding;
89 #else /* defined(__x86_64__) */
90 	uint16_t offset_hi;
91 #endif /* defined(__x86_64__) */
92 } __attribute__((__packed__));
93 
94 struct page_table_entry_pae {
95 	unsigned int present: 1;
96 	unsigned int writable: 1;
97 	unsigned int user_access: 1;
98 	unsigned int write_through: 1;
99 	unsigned int disable_cache: 1;
100 	unsigned int accessed: 1;
101 	unsigned int dirty: 1;
102 	unsigned int page_type: 1;
103 	unsigned int global: 1;
104 	unsigned int padding: 3;
105 	uint64_t address: 40;
106 	unsigned int padding2: 7;
107 	unsigned int prot_key: 4;
108 	unsigned int noexec: 1;
109 } __attribute__((__packed__));
110 
111 struct kvm_cpuid {
112 	unsigned int eax, ebx, ecx, edx;
113 };
114 
115 struct kvm_cregs {
116 	unsigned long cr0, cr2, cr3, cr4;
117 };
118 
119 extern struct page_table_entry_pae kvm_pagetable[];
120 extern struct intr_descriptor kvm_idt[X86_INTR_COUNT];
121 
122 /* Page table helper functions */
123 uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry);
124 
125 /* Functions for querying CPU info and status */
126 void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf);
127 void kvm_read_cregs(struct kvm_cregs *buf);
128 uint64_t kvm_rdmsr(unsigned int msr);
129 void kvm_wrmsr(unsigned int msr, uint64_t value);
130 
131 /* Low-level interrupt handlers, DO NOT call directly */
132 void kvm_handle_bad_exception(void);
133 void kvm_handle_zerodiv(void);
134 void kvm_handle_debug(void);
135 void kvm_handle_nmi(void);
136 void kvm_handle_breakpoint(void);
137 void kvm_handle_overflow(void);
138 void kvm_handle_bound_range_exc(void);
139 void kvm_handle_bad_opcode(void);
140 void kvm_handle_device_error(void);
141 void kvm_handle_double_fault(void);
142 void kvm_handle_invalid_tss(void);
143 void kvm_handle_segfault(void);
144 void kvm_handle_stack_fault(void);
145 void kvm_handle_gpf(void);
146 void kvm_handle_page_fault(void);
147 void kvm_handle_fpu_error(void);
148 void kvm_handle_alignment_error(void);
149 void kvm_handle_machine_check(void);
150 void kvm_handle_simd_error(void);
151 void kvm_handle_virt_error(void);
152 void kvm_handle_cpe(void);
153 void kvm_handle_hv_injection(void);
154 void kvm_handle_vmm_comm(void);
155 void kvm_handle_security_error(void);
156 
157 #endif /* KVM_X86_H_ */
158