1 // Copyright 2017 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 // kvm_gen.cc generates machine code from this file and saves it into kvm.S.h. 5 6 // +build 7 8 #include "kvm.h" 9 10 .global kvm_asm64_enable_long, kvm_asm64_enable_long_end 11 kvm_asm64_enable_long: 12 .code32 13 mov %cr0, %eax 14 or $0x80000000, %eax 15 mov %eax, %cr0 16 ljmp $SEL_CS64, NEXT_INSN 17 .code64 18 mov $SEL_TSS64, %rax 19 ltr %ax 20 kvm_asm64_enable_long_end: 21 nop 22 23 .global kvm_asm32_paged, kvm_asm32_paged_end 24 kvm_asm32_paged: 25 .code32 26 mov %cr0, %eax 27 or $0x80000000, %eax 28 mov %eax, %cr0 29 kvm_asm32_paged_end: 30 nop 31 32 .global kvm_asm32_vm86, kvm_asm32_vm86_end 33 kvm_asm32_vm86: 34 .code32 35 mov $SEL_TSS32, %ax 36 ltr %ax 37 ljmp $SEL_TSS32_VM86, $0 38 kvm_asm32_vm86_end: 39 nop 40 41 .global kvm_asm32_paged_vm86, kvm_asm32_paged_vm86_end 42 kvm_asm32_paged_vm86: 43 .code32 44 mov %cr0, %eax 45 or $0x80000000, %eax 46 mov %eax, %cr0 47 mov $SEL_TSS32, %ax 48 ltr %ax 49 ljmp $SEL_TSS32_VM86, $0 50 kvm_asm32_paged_vm86_end: 51 nop 52 53 .global kvm_asm64_vm86, kvm_asm64_vm86_end 54 kvm_asm64_vm86: 55 .code32 56 mov %cr0, %eax 57 or $0x80000000, %eax 58 mov %eax, %cr0 59 mov $SEL_TSS32, %ax 60 ltr %ax 61 ljmp $SEL_TSS32_VM86, $0 62 kvm_asm64_vm86_end: 63 nop 64 65 .global kvm_asm16_cpl3, kvm_asm16_cpl3_end 66 kvm_asm16_cpl3: 67 .code16 68 mov %cr0, %eax 69 or $1, %eax 70 mov %eax, %cr0 71 mov $SEL_TSS16, %ax 72 ltr %ax 73 mov $SEL_DS16_CPL3, %ax 74 mov %ax, %ds 75 mov %ax, %es 76 mov %ax, %fs 77 mov %ax, %gs 78 mov $0x100, %sp 79 movw $PREFIX_SIZE, 0x100 80 movw $SEL_CS16_CPL3, 0x102 81 movw $0x100, 0x104 82 movw $SEL_DS16_CPL3, 0x106 83 lret 84 kvm_asm16_cpl3_end: 85 nop 86 87 .global kvm_asm64_cpl3, kvm_asm64_cpl3_end 88 kvm_asm64_cpl3: 89 .code32 90 mov %cr0, %eax 91 or $0x80000000, %eax 92 mov %eax, %cr0 93 ljmp $SEL_CS64, NEXT_INSN 94 .code64 95 mov $SEL_TSS64, %rax 96 ltr %ax 97 mov $SEL_DS64_CPL3, %rax 98 mov %ax, %ds 99 mov %ax, %es 100 mov %ax, %fs 101 mov %ax, %gs 102 mov $ADDR_STACK0, %rsp 103 movq $PREFIX_SIZE, 0(%rsp) 104 movq $SEL_CS64_CPL3, 4(%rsp) 105 movq $ADDR_STACK0, 8(%rsp) 106 movq $SEL_DS64_CPL3, 12(%rsp) 107 lret 108 kvm_asm64_cpl3_end: 109 nop 110 111 .global kvm_asm64_init_vm, kvm_asm64_init_vm_end 112 kvm_asm64_init_vm: 113 .code32 114 // CR0.PG = 1 115 mov %cr0, %eax 116 or $0x80000000, %eax 117 mov %eax, %cr0 118 ljmp $SEL_CS64, NEXT_INSN 119 .code64 120 mov $SEL_TSS64, %rax 121 ltr %ax 122 123 // Enable and lock non-SMM VM 124 mov $MSR_IA32_FEATURE_CONTROL, %rcx 125 rdmsr 126 or $0x5, %rax 127 wrmsr 128 129 // CR4.VMXE = 1 130 mov %cr4, %rax 131 or $0x2000, %rax 132 mov %rax, %cr4 133 134 // Write VMCS revision into VMXON and VMCS regions 135 mov $MSR_IA32_VMX_BASIC, %rcx 136 rdmsr 137 mov $ADDR_VAR_VMXON, %rdx 138 mov %eax, (%rdx) 139 mov $ADDR_VAR_VMCS, %rdx 140 mov %eax, (%rdx) 141 142 mov $ADDR_VAR_VMXON_PTR, %rax 143 vmxon (%rax) 144 mov $ADDR_VAR_VMCS_PTR, %rax 145 vmclear (%rax) 146 vmptrld (%rax) 147 148 #define VMSET(FIELD, VAL) \ 149 mov $FIELD, %rdx; \ 150 mov VAL, %rax; \ 151 vmwrite %rax, %rdx; \ 152 /**/ 153 154 #define VMSET_LIMITED(FIELD, VAL, MSR) \ 155 mov $MSR, %rcx; \ 156 rdmsr; \ 157 or VAL, %rax; \ 158 and %rdx, %rax; \ 159 mov $FIELD, %rdx; \ 160 vmwrite %rax, %rdx; \ 161 /**/ 162 163 VMSET_LIMITED(0x00004000, $0x3f, 0x481) // Pin-based VM-execution controls 164 //VMSET_LIMITED(0x00004002, $0x61999e84, 0x482) // Primary processor-based VM-execution controls 165 VMSET(0x00004002, $0xf3999e84) 166 VMSET(0x0000401E, $((1<<0) | (1<<7))) // Secondary processor-based VM-execution controls 167 VMSET_LIMITED(0x0000400C, $0x36fff, 0x483) // VM-exit controls (F6FFF) 168 VMSET_LIMITED(0x00004012, $0x17ff, 0x484) // VM-entry controls (51FF) 169 170 VMSET(0x00002C04, $0) // Host IA32_PERF_GLOBAL_CTR 171 VMSET(0x00002800, $0xffffffffffffffff) // VMCS link pointer 172 173 VMSET(0x00000C02, $SEL_CS64) // host CS 174 175 mov $SEL_DS64, %rax 176 mov $0x00000C00, %rdx // host ES 177 vmwrite %rax, %rdx 178 mov $0x00000C04, %rdx // host SS 179 vmwrite %rax, %rdx 180 mov $0x00000C06, %rdx // host DS 181 vmwrite %rax, %rdx 182 mov $0x00000C08, %rdx // host FS 183 vmwrite %rax, %rdx 184 mov $0x00000C0A, %rdx // host GS 185 vmwrite %rax, %rdx 186 mov $SEL_TSS64, %rax 187 mov $0x00000C0C, %rdx // host TR 188 vmwrite %rax, %rdx 189 190 VMSET(0x00002C02, $0x500) // host EFER 191 192 VMSET(0x00004C00, $SEL_CS64) // Host IA32_SYSENTER_CS 193 VMSET(0x00006C10, $0) // Host IA32_SYSENTER_ESP 194 VMSET(0x00006C12, $0) // Host IA32_SYSENTER_EIP 195 196 mov %cr0, %rax 197 VMSET(0x00006C00, %rax) // host CR0 198 mov %cr3, %rax 199 VMSET(0x00006C02, %rax) // host CR3 200 mov %cr4, %rax 201 VMSET(0x00006C04, %rax) // host CR4 202 203 VMSET(0x00006C06, $0) // host FS base 204 VMSET(0x00006C08, $0) // host GS base 205 VMSET(0x00006C0A, $ADDR_VAR_TSS64) // host TR base 206 207 VMSET(0x00006C0C, $ADDR_GDT) // host GDTR base 208 VMSET(0x00006C0E, $ADDR_VAR_IDT) // host IDTR base 209 210 VMSET(0x00006C14, $0) // host RSP 211 VMSET(0x00006C16, ADDR_VAR_VMEXIT_PTR) // host RIP 212 213 VMSET(0x00000000, $1) // VPID 214 VMSET(0x00000002, $0) // Posted-interrupt notification vector 215 //VMSET(0x00000004, $0) // EPTP index 216 217 VMSET(0x00002000, $0) // Address of I/O bitmap A 218 VMSET(0x00002002, $0) // Address of I/O bitmap B 219 VMSET(0x00002004, $0) // Address of MSR bitmaps 220 VMSET(0x00002006, $0) // VM-exit MSR-store address 221 222 mov $0x277, %rcx 223 rdmsr 224 shl $32, %rdx 225 or %rdx, %rax 226 VMSET(0x00002C00, %rax) // Host IA32_PAT 227 228 VMSET(0x00004004, $0) // Exception bitmap 229 VMSET(0x0000400A, $0) // CR3-target count 230 VMSET(0x0000400E, $0) // VM-exit MSR-store count 231 VMSET(0x00004010, $0) // VM-exit MSR-load count 232 VMSET(0x00004016, $0) // VM-entry interruption-information field 233 VMSET(0x00004014, $0) // VM-entry MSR-load count 234 235 VMSET(0x00006000, $0xffffffffffffffff) // CR0 guest/host mask 236 VMSET(0x00006002, $0xffffffffffffffff) // CR4 guest/host mask 237 238 VMSET(0x0000201C, $0) // EOI-exit bitmap 0 239 VMSET(0x0000201E, $0) // EOI-exit bitmap 1 240 VMSET(0x00002020, $0) // EOI-exit bitmap 2 241 VMSET(0x00002022, $0) // EOI-exit bitmap 3 242 243 VMSET(0x00000800, $SEL_DS64) // Guest ES selector 244 VMSET(0x00000802, $SEL_CS64) // Guest CS selector 245 VMSET(0x00000804, $SEL_DS64) // Guest SS selector 246 VMSET(0x00000806, $SEL_DS64) // Guest DS selector 247 VMSET(0x00000808, $SEL_DS64) // Guest FS selector 248 VMSET(0x0000080A, $SEL_DS64) // Guest GS selector 249 VMSET(0x0000080C, $0) // Guest LDTR selector 250 VMSET(0x0000080E, $SEL_TSS64) // Guest TR selector 251 252 VMSET(0x00006812, $0) // Guest LDTR base 253 VMSET(0x00006814, $ADDR_VAR_TSS64) // Guest TR base 254 VMSET(0x00006816, $ADDR_GDT) // Guest GDTR base 255 VMSET(0x00006818, $ADDR_VAR_IDT) // Guest IDTR base 256 257 VMSET(0x00004800, $0xfffff) // Guest ES limit 258 VMSET(0x00004802, $0xfffff) // Guest CS limit 259 VMSET(0x00004804, $0xfffff) // Guest SS limit 260 VMSET(0x00004806, $0xfffff) // Guest DS limit 261 VMSET(0x00004808, $0xfffff) // Guest FS limit 262 VMSET(0x0000480A, $0xfffff) // Guest GS limit 263 VMSET(0x0000480C, $0) // Guest LDTR limit 264 VMSET(0x0000480E, $0x1fff) // Guest TR limit 265 VMSET(0x00004810, $0x1fff) // Guest GDTR limit 266 VMSET(0x00004812, $0x1fff) // Guest IDTR limit 267 268 VMSET(0x00004814, $0x4093) // Guest ES access rights 269 VMSET(0x00004816, $0x209b) // Guest CS access rights 270 VMSET(0x00004818, $0x4093) // Guest SS access rights 271 VMSET(0x0000481A, $0x4093) // Guest DS access rights 272 VMSET(0x0000481C, $0x4093) // Guest FS access rights 273 VMSET(0x0000481E, $0x4093) // Guest GS access rights 274 VMSET(0x00004820, $0x82) // Guest LDTR access rights 275 VMSET(0x00004822, $0x8b) // Guest TR access rights 276 277 VMSET(0x0000681C, $0) // Guest RSP 278 VMSET(0x0000681E, $ADDR_VAR_USER_CODE) // Guest RIP 279 VMSET(0x00006820, $((1<<1))) // Guest RFLAGS 280 VMSET(0x00002806, $0x500) // Guest IA32_EFER 281 VMSET(0x0000280A, $0) // Guest PDPTE0 282 VMSET(0x0000280C, $0) // Guest PDPTE1 283 VMSET(0x0000280E, $0) // Guest PDPTE2 284 VMSET(0x00002810, $0) // Guest PDPTE3 285 286 mov %cr0, %rax 287 VMSET(0x00006800, %rax) // Guest CR0 288 mov %cr3, %rax 289 VMSET(0x00006802, %rax) // Guest CR3 290 mov %cr4, %rax 291 VMSET(0x00006804, %rax) // Guest CR4 292 293 // Write 1 additional random field. 294 mov $ADDR_VAR_VMWRITE_FLD, %rax 295 mov (%rax), %rdx 296 mov $ADDR_VAR_VMWRITE_VAL, %rax 297 mov (%rax), %rcx 298 xor %rax, %rax 299 vmread %rdx, %rax 300 xor %rcx, %rax 301 vmwrite %rax, %rdx 302 303 vmlaunch 304 305 mov $0x00004400, %rdx 306 vmread %rdx, %rax 307 hlt 308 kvm_asm64_init_vm_end: 309 nop 310 311 .global kvm_asm64_vm_exit, kvm_asm64_vm_exit_end 312 kvm_asm64_vm_exit: 313 .code64 314 //vmresume 315 mov $0x00004400, %rbx // VM-instruction error 316 vmread %rbx, %rdx 317 mov $0x00004402, %rbx // Exit reason 318 vmread %rbx, %rcx 319 mov $0x00006400, %rax // Exit qualification 320 vmread %rax, %rax 321 mov $0x0000681E, %rbx // Guest RIP 322 vmread %rbx, %rbx 323 hlt 324 kvm_asm64_vm_exit_end: 325 nop 326