1// Copyright 2017 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include "constants_priv.h" 8 9#define IA32_GS_BASE 0xc0000101 10#define X86_MSR_IA32_STAR 0xc0000081 11#define X86_MSR_IA32_LSTAR 0xc0000082 12#define X86_MSR_IA32_SYSENTER_CS 0x00000174 13#define X86_MSR_IA32_SYSENTER_ESP 0x00000175 14#define X86_MSR_IA32_SYSENTER_EIP 0x00000176 15#define X86_MSR_IA32_EFER 0xc0000080 16#define ABSOLUTE_ADDR(base, x) (x - base + GUEST_ENTRY) 17#define CODE_32_SELECTOR (1<<3) 18#define CODE_64_SELECTOR (2<<3) 19#define DATA_SELECTOR (3<<3) 20#define USER_CODE_32_SELECTOR (4<<3) 21#define USER_DATA_SELECTOR (5<<3) 22#define USER_CODE_64_SELECTOR (6<<3) 23#define CODE_16_SELECTOR (8<<3) 24#define INVALID_HYPERCALL 0xffffffff 25 26.text 27 28// Define new function 'name'. 29// Local label '1:' used by other macros to compute offsets. 30.macro FUNCTION name 31 .global \name 32 .type \name, STT_FUNC 33 \name: 34 1: 35.endm 36 37.macro init_gdt start 38 lgdt ABSOLUTE_ADDR(\start, gdtr_for_\start) 39 mov $GUEST_ENTRY + 0x1000, %rsp 40 jmp end_of_init_gdt_for_\start 41 42.align 8 43gdt_for_\start: 44 // Null entry. 45 .8byte 0 46 // CODE_32_SELECTOR 47 .2byte 0xffff // Limit 15:00 48 .2byte 0x0000 // Base 15:00 49 .byte 0x00 // Base 23:16 50 .byte 0b10011010 // P(1) DPL(00) S(1) 1 C(0) R(1) A(0) 51 .byte 0b11001111 // G(1) D(1) L(0) AVL(0) Limit 19:16 52 .byte 0x0 // Base 31:24 53 // CODE_64_SELECTOR 54 .2byte 0xffff // Limit 15:00 55 .2byte 0x0000 // Base 15:00 56 .byte 0x00 // Base 23:16 57 .byte 0b10011010 // P(1) DPL(00) S(1) 1 C(0) R(1) A(0) 58 .byte 0b10101111 // G(1) D(0) L(1) AVL(0) Limit 19:16 59 .byte 0x0 // Base 31:24 60 // DATA_SELECTOR 61 .2byte 0xffff // Limit 15:00 62 .2byte 0x0000 // Base 15:00 63 .byte 0x00 // Base 23:16 64 .byte 0b10010010 // P(1) DPL(00) S(1) 0 E(0) W(1) A(0) 65 .byte 0b11001111 // G(1) B(1) L(0) AVL(0) Limit 19:16 66 .byte 0x0 // Base 31:24 67 // USER_CODE_32_SELECTOR 68 .2byte 0xffff // Limit 15:00 69 .2byte 0x0000 // Base 15:00 70 .byte 0x00 // Base 23:16 71 .byte 0b11111010 // P(1) DPL(11) S(1) 1 C(0) R(1) A(0) 72 .byte 0b11001111 // G(1) D(1) L(0) AVL(0) Limit 19:16 73 .byte 0x0 // Base 31:24 74 // USER_DATA_SELECTOR 75 .2byte 0xffff // Limit 15:00 76 .2byte 0x0000 // Base 15:00 77 .byte 0x00 // Base 23:16 78 .byte 0b11110010 // P(1) DPL(11) S(1) 0 E(0) W(1) A(0) 79 .byte 0b11001111 // G(1) B(1) 0 0 limit 19:16 80 .byte 0x0 // Base 31:24 81 // USER_CODE_64_SELECTOR 82 .2byte 0xffff // Limit 15:00 83 .2byte 0x0000 // Base 15:00 84 .byte 0x00 // Base 23:16 85 .byte 0b11111010 // P(1) DPL(11) S(1) 1 C(0) R(1) A(0) 86 .byte 0b10101111 // G(1) D(0) L(1) AVL(0) Limit 19:16 87 .byte 0x0 // Base 31:24 88 // USER_DATA_SELECTOR duplicate for sysexit 89 .2byte 0xffff // Limit 15:00 90 .2byte 0x0000 // Base 15:00 91 .byte 0x00 // Base 23:16 92 .byte 0b11110010 // P(1) DPL(11) S(1) 0 E(0) W(1) A(0) 93 .byte 0b11001111 // G(1) B(1) 0 0 limit 19:16 94 .byte 0x0 // Base 31:24 95 // CODE_16_SELECTOR 96 .2byte 0xffff // Limit 15:00 97 .2byte 0x0000 // Base 15:00 98 .byte 0x00 // Base 23:16 99 .byte 0b10011010 // P(1) DPL(00) S(1) 1 C(0) R(1) A(0) 100 .byte 0b10001111 // G(1) D(0) L(0) AVL(0) Limit 19:16 101 .byte 0x0 // Base 31:24 102gdtr_for_\start: 103 .2byte gdtr_for_\start - gdt_for_\start - 1 104 .8byte ABSOLUTE_ADDR(\start, gdt_for_\start) 105end_of_init_gdt_for_\start: 106.endm 107 108.macro debug_isr start, n 109int_\n\()_for_\start: 110 mov $\n, %rax 111 popq %rbx // Error code 112 popq %rcx // RIP 113 movq $-1, (EXIT_TEST_ADDR) 114.endm 115 116.macro debug_idt start, n 117 .2byte ABSOLUTE_ADDR(\start, \ 118 int_\n\()_for_\start) // Offset 15:00 119 .2byte CODE_64_SELECTOR // Segment selector 120 .byte 0 // IST(000) 121 .byte 0b10001110 // P(1) DPL(00) 0 Type(1110) 122 .2byte 0 // Offset 31:16 123 .4byte 0 // Offset 63:32 124 .4byte 0 // Reserved 125.endm 126 127.macro init_interrupt_handling start 128 init_gdt \start 129 lidt ABSOLUTE_ADDR(\start, idtr_for_\start) 130 mov $GUEST_ENTRY + 0x1000, %rsp 131 jmp end_of_\start 132 133.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ 134 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 135 debug_isr \start \n 136.endr 137 138int32_for_\start: 139 movq $0, (EXIT_TEST_ADDR) 140 141.align 8 142idt_for_\start: 143.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ 144 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 145 debug_idt \start \n 146.endr 147 148 .2byte ABSOLUTE_ADDR(\start, int32_for_\start) // Offset 15:00 149 .2byte CODE_64_SELECTOR // Segment selector 150 .byte 0 // IST(000) 151 .byte 0b10001110 // P(1) DPL(00) 0 Type(1110) 152 .2byte 0 // Offset 31:16 153 .4byte 0 // Offset 63:32 154 .4byte 0 // Reserved 155idtr_for_\start: 156 .2byte idtr_for_\start - idt_for_\start - 1 // Limit 157 .8byte ABSOLUTE_ADDR(\start, idt_for_\start) // Address 158end_of_\start: 159.endm 160 161// Test vcpu_resume. 162FUNCTION vcpu_resume_start 163 // Test that we do not exit on load/store of CR3. 164 mov %cr3, %rax 165 mov %rax, %cr3 166 167 // Test that we do not exit on store of GS_BASE. 168 xor %eax, %eax 169 xor %edx, %edx 170 mov $IA32_GS_BASE, %ecx 171 wrmsr 172 173 // Test that we handle CPUID instruction correctly. 174 xor %eax, %eax 175 cpuid 176 177 movq $0, (EXIT_TEST_ADDR) 178FUNCTION vcpu_resume_end 179 180// Test vcpu_interrupt. 181FUNCTION vcpu_interrupt_start 182 init_interrupt_handling vcpu_interrupt_start 183 sti 184 jmp . 185FUNCTION vcpu_interrupt_end 186 187// Test guest HLT instruction handling. 188FUNCTION vcpu_hlt_start 189 init_interrupt_handling vcpu_hlt_start 190 sti 191 hlt 192FUNCTION vcpu_hlt_end 193 194// Test that pause exiting works correctly. 195FUNCTION vcpu_pause_start 196 pause 197 movq $0, (EXIT_TEST_ADDR) 198FUNCTION vcpu_pause_end 199 200// Test that reading and writing cr0 works correctly. 201FUNCTION vcpu_write_cr0_start 202 // Read cr0. 203 mov %cr0, %rax 204 205 // Write cr0 and negate the NE bit. 206 and $~X86_CR0_NE, %rax 207 mov %rax, %cr0 208 209 // Test cr0 masking. NE bit should be set. 210 mov %cr0, %rax 211 212 movq $0, (EXIT_TEST_ADDR) 213FUNCTION vcpu_write_cr0_end 214 215// Test vcpu_read_state and vcpu_write_state. 216FUNCTION vcpu_read_write_state_start 217 add $1, %rax 218 add $2, %rcx 219 add $3, %rdx 220 add $4, %rbx 221 add $5, %rsp 222 add $6, %rbp 223 add $7, %rsi 224 add $8, %rdi 225 add $9, %r8 226 add $10, %r9 227 add $11, %r10 228 add $12, %r11 229 add $13, %r12 230 add $14, %r13 231 add $15, %r14 232 add $16, %r15 233 234 stc // Set carry flag (bit 0) 235 stac // Set AC flag (bit 18) 236 237 movq $0, (EXIT_TEST_ADDR) 238FUNCTION vcpu_read_write_state_end 239 240// Test 32 bit compatibility mode (long mode disabled). 241FUNCTION vcpu_compat_mode_start 242 init_gdt vcpu_compat_mode_start 243 movq $0, %rbx 244 movq $0, %rcx 245 246 // Drop into compatibility mode 247 pushq $CODE_32_SELECTOR 248 lea vcpu_compat_mode_code(%rip),%rax 249 pushq %rax 250 lretq 251 252.code32 253vcpu_compat_mode_code: 254 // Hack to check if we're x86 or x64. In x86, 0x41 is `inc %ecx` and loop 255 // falls through. In x64, 0x41 is the REX.B prefix and %ecx is not 256 // incremented so loop jmps to vcpu_compat_mode_exit. 257 xor %ecx,%ecx 258 .byte 0x41 // x86: inc %ecx; x64: rex.B prefix 259 loop vcpu_compat_mode_exit 260 261 // Write a value to ebx to check in guest.cpp 262 mov $1,%ebx 263 264 // Go back to long mode 265 pushl $CODE_64_SELECTOR 266 pushl $ABSOLUTE_ADDR(vcpu_compat_mode_start, vcpu_compat_mode_test16) 267 lret 268.code64 269 270vcpu_compat_mode_test16: 271 // Drop into compatibility mode with 16 bit default operands. 272 pushq $CODE_16_SELECTOR 273 lea vcpu_compat_mode_code16(%rip),%rax 274 pushq %rax 275 lretq 276 277.code32 278vcpu_compat_mode_code16: 279 // The default operand size should be 16 bits and push should subtract 2 280 // from the stack pointer. 281 mov %esp,%eax 282 sub $2,%eax 283 push $0 284 cmp %esp,%eax 285 pop %eax 286 jne vcpu_compat_mode_code16_done 287 288 // Write a value to ebx to check in guest.cpp 289 mov $2,%ecx 290 291 // Go back to long mode 292vcpu_compat_mode_code16_done: 293 pushl $CODE_64_SELECTOR 294 pushl $ABSOLUTE_ADDR(vcpu_compat_mode_start, vcpu_compat_mode_done) 295 lret 296.code64 297 298vcpu_compat_mode_done: 299 // Fix the data segment selectors 300 mov $DATA_SELECTOR,%rax 301 mov %rax,%ds 302 mov %rax,%es 303 mov %rax,%fs 304 mov %rax,%gs 305 mov %rax,%ss 306 307vcpu_compat_mode_exit: 308 movq $0, (EXIT_TEST_ADDR) 309FUNCTION vcpu_compat_mode_end 310 311FUNCTION vcpu_syscall_start 312 init_interrupt_handling vcpu_syscall_start 313 314 xor %eax, %eax 315 mov $((USER_CODE_32_SELECTOR << 16) | CODE_64_SELECTOR), %edx 316 mov $X86_MSR_IA32_STAR, %ecx 317 wrmsr 318 319 xor %edx, %edx 320 mov $ABSOLUTE_ADDR(vcpu_syscall_start, vcpu_syscall_done), %eax 321 mov $X86_MSR_IA32_LSTAR, %ecx 322 wrmsr 323 324 pushfq 325 pop %r11 326 mov $ABSOLUTE_ADDR(vcpu_syscall_start, vcpu_syscall_ring3), %rcx 327 sysretq 328 329vcpu_syscall_ring3: 330 syscall 331 332vcpu_syscall_done: 333 movq $0, (EXIT_TEST_ADDR) 334FUNCTION vcpu_syscall_end 335 336FUNCTION vcpu_sysenter_start 337 init_interrupt_handling vcpu_sysenter_start 338 339 xor %edx, %edx 340 mov $CODE_64_SELECTOR, %eax 341 mov $X86_MSR_IA32_SYSENTER_CS, %ecx 342 wrmsr 343 344 mov $ABSOLUTE_ADDR(vcpu_sysenter_start, vcpu_sysenter_done), %eax 345 mov $X86_MSR_IA32_SYSENTER_EIP, %ecx 346 wrmsr 347 348 mov %esp, %eax 349 mov $X86_MSR_IA32_SYSENTER_ESP, %ecx 350 wrmsr 351 352 mov %rsp, %rdx 353 mov $ABSOLUTE_ADDR(vcpu_sysenter_start, vcpu_sysenter_ring3), %rdx 354 .byte 0x48 // rex.W 355 sysexit 356 357vcpu_sysenter_ring3: 358 sysenter 359 360vcpu_sysenter_done: 361 movq $0, (EXIT_TEST_ADDR) 362FUNCTION vcpu_sysenter_end 363 364FUNCTION vcpu_sysenter_compat_start 365 init_interrupt_handling vcpu_sysenter_compat_start 366 367 xor %edx, %edx 368 mov $CODE_64_SELECTOR, %eax 369 mov $X86_MSR_IA32_SYSENTER_CS, %ecx 370 wrmsr 371 372 mov $ABSOLUTE_ADDR(vcpu_sysenter_compat_start, vcpu_sysenter_compat_done), %eax 373 mov $X86_MSR_IA32_SYSENTER_EIP, %ecx 374 wrmsr 375 376 mov %esp, %eax 377 mov $X86_MSR_IA32_SYSENTER_ESP, %ecx 378 wrmsr 379 380 mov %rsp, %rdx 381 mov $ABSOLUTE_ADDR(vcpu_sysenter_compat_start, vcpu_sysenter_compat_ring3), %rdx 382 sysexit 383 384.code32 385vcpu_sysenter_compat_ring3: 386 sysenter 387.code64 388 389vcpu_sysenter_compat_done: 390 movq $0, (EXIT_TEST_ADDR) 391FUNCTION vcpu_sysenter_compat_end 392 393// Test guest_set_trap using a memory-based trap. 394FUNCTION guest_set_trap_start 395 movq $0, (TRAP_ADDR) 396 movq $0, (EXIT_TEST_ADDR) 397FUNCTION guest_set_trap_end 398 399// Test guest_set_trap using an IO-based trap. 400FUNCTION guest_set_trap_with_io_start 401 out %al, $TRAP_PORT 402 movq $0, (EXIT_TEST_ADDR) 403FUNCTION guest_set_trap_with_io_end 404 405FUNCTION vcpu_vmcall_start 406 movq $(INVALID_HYPERCALL), %rax 407 vmcall 408 movq $0, (EXIT_TEST_ADDR) 409FUNCTION vcpu_vmcall_end 410