github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/vmexit/vmexit_task_switch.c (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #include "vmm_defs.h" 16 #include "guest_cpu.h" 17 #include "isr.h" 18 #include "vmx_vmcs.h" 19 #include "guest_cpu_vmenter_event.h" 20 #include "host_memory_manager_api.h" 21 #ifdef JLMDEBUG 22 #include "jlmdebug.h" 23 #endif 24 25 26 // This is 32-bit TSS. 27 #pragma pack(1) 28 typedef struct { 29 UINT32 prev_tr; // 0 30 UINT32 esp0; // 4 31 UINT32 ss0; // 8 32 UINT32 esp1; // 12 33 UINT32 ss1; // 16 34 UINT32 esp2; // 20 35 UINT32 ss2; // 24 36 UINT32 cr3; // 28 37 UINT32 eip; // 32 38 UINT32 eflags; // 36 39 UINT32 eax; // 40 40 UINT32 ecx; // 44 41 UINT32 edx; // 48 42 UINT32 ebx; // 52 43 UINT32 esp; // 56 44 UINT32 ebp; // 60 45 UINT32 esi; // 64 46 UINT32 edi; // 68 47 UINT32 es; // 72 48 UINT32 cs; // 76 49 UINT32 ss; // 80 50 UINT32 ds; // 84 51 UINT32 fs; // 88 52 UINT32 gs; // 92 53 UINT32 ldtr; // 96 54 UINT32 io_base_addr; // 100 55 } tss32_t; 56 #pragma pack() 57 58 59 // Only three 32-bit registers are used during task switch. They are not to 60 // be shared with VMM. VMM works with 64-bit values. 61 typedef union { 62 UINT32 value; 63 struct { 64 UINT32 carry:1; 65 UINT32 rsvd_1:1; 66 UINT32 parity:1; 67 UINT32 rsvd_3:1; 68 UINT32 adjust:1; 69 UINT32 rsvd_5:1; 70 UINT32 zero:1; 71 UINT32 sign:1; 72 UINT32 trap:1; 73 UINT32 intr_enable:1; 74 UINT32 direction:1; 75 UINT32 overflow:1; 76 UINT32 iopl:2; 77 UINT32 nested_task:1; 78 UINT32 rsvd_15:1; 79 UINT32 resume:1; 80 UINT32 v86_mode:1; 81 UINT32 align_chk:1; 82 UINT32 v_intr:1; 83 UINT32 v_intr_pend:1; 84 UINT32 ident:1; 85 UINT32 rsvd_31_22:10; 86 } bits; 87 } eflags_t; 88 89 typedef union { 90 UINT32 value; 91 struct { 92 UINT32 pe:1; // bit 0 Protection Enable 93 UINT32 mp:1; // bit 1 Monitor Coprocessor 94 UINT32 em:1; // bit 2 Emulation 95 UINT32 ts:1; // bit 3 Task Switched 96 UINT32 et:1; // bit 4 Extension Type 97 UINT32 ne:1; // bit 5 Numeric Error 98 UINT32 rsvd_15_6:10; // bits 15:6 Reserved 99 UINT32 wp:1; // bit 16 Write Protect 100 UINT32 rsvd_17:1; // bit 17 Reserved 101 UINT32 am:1; // bit 18 Alignment Mask 102 UINT32 rsvd_28_19:10; // bits 28:19 Reserved 103 UINT32 nw:1; // bit 29 Not Write-through 104 UINT32 cd:1; // bit 30 Cache Disable 105 UINT32 pg:1; // bit 31 Paging 106 } bits; 107 } cr0_t; 108 109 typedef union { 110 UINT32 value; 111 struct { 112 UINT32 l0:1; // bit 0 local b.p. enable 113 UINT32 g0:1; // bit 1 global b.p. enable 114 UINT32 l1:1; // bit 2 local b.p. enable 115 UINT32 g1:1; // bit 3 global b.p. enable 116 UINT32 l2:1; // bit 4 local b.p. enable 117 UINT32 g2:1; // bit 5 global b.p. enable 118 UINT32 l3:1; // bit 6 local b.p. enable 119 UINT32 g3:1; // bit 7 global b.p. enable 120 UINT32 le:1; // bit 8 local exact b.p. enable 121 UINT32 ge:1; // bit 9 global exact b.p. enable 122 UINT32 rsvd_12_10:3; // bits 12:10 Reserved 123 UINT32 gd:1; // bit 13 general detect enable 124 UINT32 rsvd_15_14:2; // bits 15:14 Reserved 125 UINT32 rw0:2; // bits 17:16 126 UINT32 len0:2; // bits 19:18 127 UINT32 rw1:2; // bits 21:20 128 UINT32 len1:2; // bits 23:22 129 UINT32 rw2:2; // bits 25:24 130 UINT32 len2:2; // bits 27:26 131 UINT32 rw3:2; // bits 29:28 132 UINT32 len3:2; // bits 31:30 133 } bits; 134 } dr7_t; 135 136 137 // This is 32-bit selector and descriptor. 138 typedef union { 139 UINT32 value; 140 struct { 141 UINT32 type:4; // bits 3:0 142 UINT32 s_bit:1; // bit 4 143 UINT32 dpl:2; // bit2 6:5 144 UINT32 p_bit:1; // bit 7 145 UINT32 rsvd_11_8:4; // bits 11:8 146 UINT32 avl_bit:1; // bit 12 147 UINT32 l_bit:1; // bit 13 148 UINT32 db_bit:1; // bit 14 149 UINT32 g_bit:1; // bit 15 150 UINT32 null_bit:1; // bit 16 151 UINT32 rsvd_31_17:15; // bits 31:17 152 } bits; 153 } ar_t; 154 155 #pragma warning(push) 156 #pragma warning(disable: 4820) 157 // Two-byte padding after selector is ok. 158 typedef struct { 159 UINT16 selector; 160 UINT32 base; 161 UINT32 limit; 162 ar_t ar; 163 } seg_reg_t; 164 #pragma warning(pop) 165 166 typedef union { 167 UINT64 value; 168 struct { 169 UINT32 limit_15_00:16; // bits 15:0 170 UINT32 base_15_00:16; // bits 31:16 171 UINT32 base_23_16:8; // bits 39:32 172 UINT32 type:4; // bits 43:40 173 UINT32 s_bit:1; // bit 44 174 UINT32 dpl:2; // bit2 46:45 175 UINT32 p_bit:1; // bit 47 176 UINT32 limit_19_16:4; // bits 51:48 177 UINT32 avl_bit:1; // bit 52 178 UINT32 l_bit:1; // bit 53 179 UINT32 db_bit:1; // bit 54 180 UINT32 g_bit:1; // bit 55 181 UINT32 base_31_24:8; // bits 63:56 182 } bits; 183 } desc_t; 184 185 // Types for (s_bit == 0). 186 #define Tss32Aval (0x9) 187 #define Tss32Busy (0xb) 188 #define IsLdt(type) ((type) == 0x2) 189 #define IsTss32Aval(type) ((type) == Tss32Aval) 190 #define IsTss32Busy(type) ((type) == Tss32Busy) 191 #define IsTss32(type) (IsTss32Aval(type) || IsTss32Busy(type)) 192 193 // Types for (s_bit == 1). 194 #define SetAssessed(type) type |= 0x1 195 #define IsAssessed(type) (((type) & 0x1) != 0) 196 #define IsDataRW(type) (((type) & 0xa) == 0x2) 197 #define IsCode(type) (((type) & 0x8) != 0) 198 #define IsCodeR(type) (((type) & 0xa) == 0xa) 199 #define IsCodeConform(type) (((type) & 0xc) == 0xc) 200 201 // Selector fields. 202 #define SelectorIdx(sel) ((sel) & 0xfff8) 203 #define SelectorGdt(sel) (((sel) & 0x0004) == 0) 204 #define SelectorRpl(sel) ((sel) & 0x0003) 205 206 207 int copy_from_gva(GUEST_CPU_HANDLE gcpu, UINT64 gva, UINT32 size, UINT64 hva) 208 { 209 UINT64 dst_hva = 0; 210 UINT64 src_gva = gva; 211 UINT8 *local_ptr = (UINT8*)hva; 212 UINT32 size_remaining = size; 213 UINT32 size_copied = 0; 214 215 while (size_remaining) { 216 if (!gcpu_gva_to_hva(gcpu, (GVA)src_gva, (HVA *)&dst_hva)) { 217 VMM_LOG(mask_uvmm, level_error,"%s: Invalid Parameter Struct Address %P\n", __FUNCTION__, src_gva); 218 return -1; 219 } 220 /* Copy until end */ 221 if(src_gva >(UINT64_ALL_ONES-size_remaining)) { 222 VMM_LOG(mask_uvmm,level_error,"Error: Size bounds exceeded\n"); 223 return -1; 224 } 225 if ((src_gva + size_remaining) <= (src_gva | PAGE_4KB_MASK)) { 226 vmm_memcpy((void*)local_ptr, (void*)dst_hva, size_remaining); 227 return 0; 228 } else { 229 /* Copy until end of page */ 230 size_copied = (UINT32) 231 (((src_gva + PAGE_4KB_SIZE) & ~PAGE_4KB_MASK) - src_gva); 232 233 vmm_memcpy((void*)local_ptr, (void*)dst_hva, size_copied); 234 235 /* Adjust size and pointers for next copy */ 236 size_remaining -= size_copied; 237 local_ptr += size_copied; 238 src_gva += size_copied; 239 } 240 } 241 return 0; 242 } 243 244 245 static int copy_to_gva(GUEST_CPU_HANDLE gcpu, UINT64 gva, UINT32 size, UINT64 hva) 246 { 247 UINT64 dst_gva = gva; 248 UINT64 src_hva = 0; 249 UINT8 *local_ptr = (UINT8*)hva; 250 UINT32 size_remaining = size; 251 UINT32 size_copied = 0; 252 253 while (size_remaining) { 254 if (!gcpu_gva_to_hva(gcpu, dst_gva, &src_hva)) { 255 VMM_LOG(mask_uvmm, level_error,"%s: Invalid guest pointer Address %P\n", __FUNCTION__, gva); 256 return -1; 257 } 258 /* Copy until end */ 259 if(dst_gva >(UINT64_ALL_ONES-size_remaining)) { 260 VMM_LOG(mask_uvmm,level_error,"Error: Size bounds exceeded\n"); 261 return -1; 262 } 263 if ((dst_gva + size_remaining) <= (dst_gva | PAGE_4KB_MASK)) { 264 vmm_memcpy((void*)src_hva, (void*)local_ptr, size_remaining); 265 return 0; 266 } else { 267 /* Copy until end of page */ 268 size_copied = (UINT32) 269 (((dst_gva + PAGE_4KB_SIZE) & ~PAGE_4KB_MASK) - dst_gva); 270 271 vmm_memcpy((void*)src_hva, (void*)local_ptr, size_copied); 272 273 /* Adjust size and pointers for next copy */ 274 size_remaining -= size_copied; 275 local_ptr += size_copied; 276 dst_gva += size_copied; 277 } 278 } 279 280 return 0; 281 } 282 283 284 static void parse_desc(desc_t *dsc, seg_reg_t *seg) 285 { 286 seg->base = (dsc->bits.base_15_00) | 287 (dsc->bits.base_23_16 << 16) | (dsc->bits.base_31_24 << 24); 288 seg->limit = (dsc->bits.limit_15_00) | (dsc->bits.limit_19_16 << 16); 289 seg->ar.value = 0; 290 seg->ar.bits.type = dsc->bits.type; 291 seg->ar.bits.s_bit = dsc->bits.s_bit; 292 seg->ar.bits.dpl = dsc->bits.dpl; 293 seg->ar.bits.p_bit = dsc->bits.p_bit; 294 seg->ar.bits.avl_bit = dsc->bits.avl_bit; 295 seg->ar.bits.l_bit = dsc->bits.l_bit; 296 seg->ar.bits.db_bit = dsc->bits.db_bit; 297 seg->ar.bits.g_bit = dsc->bits.g_bit; 298 } 299 300 301 static void get_task_info(GUEST_CPU_HANDLE gcpu, UINT32 *type, UINT16 *sel, 302 IA32_VMX_VMCS_VM_EXIT_INFO_IDT_VECTORING vect) 303 { 304 VMCS_OBJECT *vmcs = gcpu_get_vmcs(gcpu); 305 IA32_VMX_EXIT_QUALIFICATION qual; 306 307 qual.Uint64 = vmcs_read(vmcs, VMCS_EXIT_INFO_QUALIFICATION); 308 *type = (UINT32)(qual.TaskSwitch.Source); 309 *sel = (UINT16)(qual.TaskSwitch.TssSelector); 310 if ((*type == TASK_SWITCH_TYPE_IDT) && IsSoftwareVector(vect)) 311 *type = TASK_SWITCH_TYPE_CALL; 312 } 313 314 315 static void force_ring3_ss(GUEST_CPU_HANDLE gcpu) 316 { 317 seg_reg_t ss; 318 cr0_t cr0; 319 eflags_t flags; 320 321 cr0.value = 322 (UINT32)gcpu_get_guest_visible_control_reg(gcpu, IA32_CTRL_CR0); 323 flags.value = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RFLAGS); 324 if ((cr0.bits.pe == 0) || (flags.bits.v86_mode == 1)) 325 return; 326 gcpu_get_segment_reg( gcpu, IA32_SEG_TR, (UINT16 *)&(ss.selector), 327 (UINT64 *)&(ss.base), (UINT32 *)&(ss.limit), (UINT32 *)&(ss.ar)); 328 ss.ar.bits.dpl = 3; 329 gcpu_set_segment_reg( gcpu, IA32_SEG_SS, ss.selector, 330 ss.base, ss.limit, ss.ar.value); 331 return; 332 } 333 334 // Set guest LDTR according to new tss. 335 static int set_guest_ldtr(GUEST_CPU_HANDLE gcpu, seg_reg_t *gdtr, seg_reg_t *ldtr, tss32_t *tss) 336 { 337 desc_t desc; 338 int r; 339 340 vmm_memset(ldtr, 0, sizeof(seg_reg_t)); 341 ldtr->selector = (UINT16)tss->ldtr; 342 343 if (SelectorIdx(ldtr->selector) == 0) { 344 ldtr->ar.bits.null_bit = 1; 345 return 0; 346 } 347 if (!SelectorGdt(ldtr->selector)) { // must be in gdt 348 force_ring3_ss(gcpu); 349 gcpu_inject_ts(gcpu, ldtr->selector); 350 return -1; 351 } 352 r = copy_from_gva(gcpu, (UINT64)(gdtr->base + SelectorIdx(ldtr->selector)), 353 sizeof(desc), (UINT64)(&desc)); 354 if (r != 0) { 355 force_ring3_ss(gcpu); 356 gcpu_inject_ts(gcpu, ldtr->selector); 357 return -1; 358 } 359 parse_desc(&desc, ldtr); 360 if ((ldtr->ar.bits.s_bit != 0) || // must be sys desc 361 !IsLdt(ldtr->ar.bits.type) || // must be ldt 362 (ldtr->ar.bits.p_bit != 1)) { // must be present 363 force_ring3_ss(gcpu); 364 gcpu_inject_ts(gcpu, ldtr->selector); 365 return -1; 366 } 367 gcpu_set_segment_reg( gcpu, IA32_SEG_LDTR, ldtr->selector, ldtr->base, 368 ldtr->limit, ldtr->ar.value); 369 return 0; 370 } 371 372 373 // Set guest SS according to new tss. 374 static int set_guest_ss(GUEST_CPU_HANDLE gcpu, seg_reg_t *gdtr, seg_reg_t *ldtr, tss32_t *tss) 375 { 376 desc_t desc; 377 seg_reg_t ss; 378 seg_reg_t *dtr; 379 UINT32 cpl; 380 int r; 381 382 vmm_memset(&ss, 0, sizeof(ss)); 383 ss.selector = (UINT16)tss->ss; 384 cpl = SelectorRpl(tss->cs); 385 if (SelectorIdx(ss.selector) == 0) { // must not be null 386 force_ring3_ss(gcpu); 387 gcpu_inject_ts(gcpu, ss.selector); 388 return -1; 389 } 390 dtr = SelectorGdt(ss.selector)? gdtr:ldtr; 391 r = copy_from_gva(gcpu, (UINT64)(dtr->base + SelectorIdx(ss.selector)), 392 sizeof(desc), (UINT64)(&desc)); 393 if (r != 0) { 394 force_ring3_ss(gcpu); 395 gcpu_inject_ts(gcpu, ss.selector); 396 return -1; 397 } 398 parse_desc(&desc, &ss); 399 if (ss.ar.bits.p_bit == 0) { // must be present 400 force_ring3_ss(gcpu); 401 gcpu_inject_ss(gcpu, ss.selector); 402 return -1; 403 } 404 if ((ss.ar.bits.s_bit == 0) || // must be non-sys desc 405 IsCode(ss.ar.bits.type) || // must not be code 406 !IsDataRW(ss.ar.bits.type) || // must be data with r/w 407 (ss.ar.bits.dpl != cpl) || 408 ((UINT32)SelectorRpl(ss.selector) != cpl)) { 409 force_ring3_ss(gcpu); 410 gcpu_inject_ts(gcpu, ss.selector); 411 return -1; 412 } 413 414 // If g_bit is set, the unit is 4 KB. 415 if (ss.ar.bits.g_bit == 1) 416 ss.limit = (ss.limit << 12) | 0xfff; 417 if (!IsAssessed(ss.ar.bits.type)) { 418 SetAssessed(ss.ar.bits.type); 419 SetAssessed(desc.bits.type); 420 r = copy_to_gva(gcpu, 421 (UINT64)(dtr->base + SelectorIdx(ss.selector)), 422 sizeof(desc), 423 (UINT64)(&desc) 424 ); 425 if (r != 0) { 426 force_ring3_ss(gcpu); 427 gcpu_inject_ts(gcpu, ss.selector); 428 return -1; 429 } 430 } 431 gcpu_set_segment_reg( gcpu, IA32_SEG_SS, ss.selector, ss.base, 432 ss.limit, ss.ar.value); 433 return 0; 434 } 435 436 437 // Set guest CS according to new tss. 438 static int set_guest_cs(GUEST_CPU_HANDLE gcpu, seg_reg_t *gdtr, seg_reg_t *ldtr, tss32_t *tss) 439 { 440 desc_t desc; 441 seg_reg_t cs; 442 seg_reg_t *dtr; 443 UINT32 cpl; 444 int r; 445 446 vmm_memset(&cs, 0, sizeof(cs)); 447 cs.selector = (UINT16)tss->cs; 448 cpl = SelectorRpl(tss->cs); 449 if (SelectorIdx(cs.selector) == 0) { // must not be null 450 gcpu_inject_ts(gcpu, cs.selector); 451 return -1; 452 } 453 dtr = SelectorGdt(cs.selector)? gdtr:ldtr; 454 r = copy_from_gva(gcpu, (UINT64)(dtr->base + SelectorIdx(cs.selector)), 455 sizeof(desc), (UINT64)(&desc)); 456 if (r != 0) { 457 gcpu_inject_ts(gcpu, cs.selector); 458 return -1; 459 } 460 parse_desc(&desc, &cs); 461 if (cs.ar.bits.p_bit != 1) { // must be present 462 gcpu_inject_np(gcpu, cs.selector); 463 return -1; 464 } 465 if ((cs.ar.bits.s_bit == 0) || // must be non-sys desc 466 !IsCode(cs.ar.bits.type)) { // must be code 467 gcpu_inject_ts(gcpu, cs.selector); 468 return -1; 469 } 470 // Priv checks 471 if (IsCodeConform(cs.ar.bits.type)) { 472 if (cs.ar.bits.dpl > cpl) { 473 gcpu_inject_ts(gcpu, cs.selector); 474 return -1; 475 } 476 } 477 else { 478 if (cs.ar.bits.dpl != cpl) { 479 gcpu_inject_ts(gcpu, cs.selector); 480 return -1; 481 } 482 } 483 484 // If g_bit is set, the unit is 4 KB. 485 if (cs.ar.bits.g_bit == 1) 486 cs.limit = (cs.limit << 12) | 0xfff; 487 if (!IsAssessed(cs.ar.bits.type)) { 488 SetAssessed(cs.ar.bits.type); 489 SetAssessed(desc.bits.type); 490 r = copy_to_gva(gcpu, (UINT64)(dtr->base + (cs.selector & 0xfff8)), 491 sizeof(desc), (UINT64)(&desc)); 492 if (r != 0) { 493 gcpu_inject_ts(gcpu, cs.selector); 494 return -1; 495 } 496 } 497 cs.ar.bits.null_bit = 0; 498 gcpu_set_segment_reg( gcpu, IA32_SEG_CS, cs.selector, cs.base, 499 cs.limit, cs.ar.value); 500 if (tss->eip > cs.limit) { 501 gcpu_inject_ts(gcpu, cs.selector); 502 return -1; 503 } 504 return 0; 505 } 506 507 508 // Set guest ES, DS, FS, or GS, based on register name and new tss. 509 static int set_guest_seg( GUEST_CPU_HANDLE gcpu, seg_reg_t *gdtr, seg_reg_t *ldtr, tss32_t *tss, 510 VMM_IA32_SEGMENT_REGISTERS name) 511 { 512 desc_t desc; 513 seg_reg_t seg; 514 seg_reg_t *dtr; 515 UINT32 cpl; 516 int r; 517 518 vmm_memset(&seg, 0, sizeof(seg)); 519 520 if (name == IA32_SEG_ES) 521 seg.selector = (UINT16)tss->es; 522 else if (name == IA32_SEG_DS) 523 seg.selector = (UINT16)tss->ds; 524 else if (name == IA32_SEG_FS) 525 seg.selector = (UINT16)tss->fs; 526 else if (name == IA32_SEG_GS) 527 seg.selector = (UINT16)tss->gs; 528 else 529 return -1; 530 531 cpl = SelectorRpl(tss->cs); 532 dtr = SelectorGdt(seg.selector)? gdtr:ldtr; 533 if (SelectorIdx(seg.selector) == 0) { 534 seg.selector = 0; 535 seg.ar.bits.null_bit = 1; 536 goto set_seg_reg; 537 } 538 r = copy_from_gva(gcpu, (UINT64)(dtr->base + SelectorIdx(seg.selector)), 539 sizeof(desc), (UINT64)(&desc)); 540 if (r != 0) { 541 force_ring3_ss(gcpu); 542 gcpu_inject_ts(gcpu, seg.selector); 543 return -1; 544 } 545 parse_desc(&desc, &seg); 546 if ((seg.ar.bits.s_bit == 0) || // must be non-sys desc 547 (IsCode(seg.ar.bits.type) && !IsCodeR(seg.ar.bits.type))) { 548 force_ring3_ss(gcpu); 549 gcpu_inject_ts(gcpu, seg.selector); 550 return -1; 551 } 552 553 // Must be present. 554 if (seg.ar.bits.p_bit != 1) { 555 force_ring3_ss(gcpu); 556 gcpu_inject_np(gcpu, seg.selector); 557 return -1; 558 } 559 560 // If g_bit is set, the unit is 4 KB. 561 if (seg.ar.bits.g_bit == 1) 562 seg.limit = (seg.limit << 12) | 0xfff; 563 564 // Priv checks. 565 if (IsCode(seg.ar.bits.type) && !IsCodeConform(seg.ar.bits.type)) { 566 UINT32 rpl = (UINT32)SelectorRpl(seg.selector); 567 568 if ((seg.ar.bits.dpl < cpl) || (seg.ar.bits.dpl < rpl)) { 569 force_ring3_ss(gcpu); 570 gcpu_inject_ts(gcpu, seg.selector); 571 return -1; 572 } 573 } 574 575 set_seg_reg: 576 gcpu_set_segment_reg( gcpu, name, seg.selector, seg.base, 577 seg.limit, seg.ar.value); 578 return 0; 579 } 580 581 582 // Copy guest status from VMCS to tss buffer. 583 static void copy_vmcs_to_tss32(GUEST_CPU_HANDLE gcpu, tss32_t *tss) 584 { 585 VMCS_OBJECT *vmcs = gcpu_get_vmcs(gcpu); 586 587 tss->eip = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RIP); 588 tss->eflags = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RFLAGS); 589 tss->eax = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RAX); 590 tss->ecx = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RCX); 591 tss->edx = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RDX); 592 tss->ebx = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RBX); 593 tss->esp = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RSP); 594 tss->ebp = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RBP); 595 tss->esi = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RSI); 596 tss->edi = (UINT32)gcpu_get_gp_reg(gcpu, IA32_REG_RDI); 597 598 tss->es = (UINT32)vmcs_read(vmcs, VMCS_GUEST_ES_SELECTOR); 599 tss->cs = (UINT32)vmcs_read(vmcs, VMCS_GUEST_CS_SELECTOR); 600 tss->ss = (UINT32)vmcs_read(vmcs, VMCS_GUEST_SS_SELECTOR); 601 tss->ds = (UINT32)vmcs_read(vmcs, VMCS_GUEST_DS_SELECTOR); 602 tss->fs = (UINT32)vmcs_read(vmcs, VMCS_GUEST_FS_SELECTOR); 603 tss->gs = (UINT32)vmcs_read(vmcs, VMCS_GUEST_GS_SELECTOR); 604 } 605 606 607 // This function does task switch for 32-bit VMM guest. 608 int task_switch_for_guest(GUEST_CPU_HANDLE gcpu, IA32_VMX_VMCS_VM_EXIT_INFO_IDT_VECTORING vec_info) 609 { 610 int ret; 611 UINT32 inst_type; 612 tss32_t tss; 613 614 cr0_t cr0; 615 dr7_t dr7; 616 seg_reg_t gdtr; 617 seg_reg_t old_ldtr; 618 seg_reg_t new_ldtr; 619 seg_reg_t new_tr; 620 seg_reg_t old_tr; 621 desc_t new_tss_desc; 622 desc_t old_tss_desc; 623 gcpu_get_gdt_reg(gcpu, (UINT64 *)&(gdtr.base), (UINT32 *)&(gdtr.limit)); 624 gdtr.ar.value = 0x000080; 625 cr0.value = (UINT32) gcpu_get_guest_visible_control_reg(gcpu, IA32_CTRL_CR0); 626 627 // Find new tr & tss. 628 get_task_info(gcpu, &inst_type, &(new_tr.selector), vec_info); 629 ret = copy_from_gva(gcpu, (UINT64)(gdtr.base + SelectorIdx(new_tr.selector)), 630 sizeof(new_tss_desc), (UINT64)(&new_tss_desc)); 631 if (ret != 0) { 632 gcpu_inject_ts(gcpu, new_tr.selector); 633 return -1; 634 } 635 parse_desc(&new_tss_desc, &new_tr); 636 if (!IsTss32(new_tr.ar.bits.type)) { 637 gcpu_inject_ts(gcpu, new_tr.selector); 638 return -1; 639 } 640 641 // Find old ldtr. 642 gcpu_get_segment_reg( gcpu, IA32_SEG_LDTR, (UINT16 *)&(old_ldtr.selector), 643 (UINT64 *)&(old_ldtr.base), (UINT32 *)&(old_ldtr.limit), (UINT32 *)&(old_ldtr.ar) 644 ); 645 646 // Find old tr. 647 gcpu_get_segment_reg( gcpu, IA32_SEG_TR, (UINT16 *)&(old_tr.selector), 648 (UINT64 *)&(old_tr.base), (UINT32 *)&(old_tr.limit), (UINT32 *)&(old_tr.ar)); 649 650 if (!IsTss32Busy(old_tr.ar.bits.type)) { 651 gcpu_inject_ts(gcpu, old_tr.selector); 652 return -1; 653 } 654 655 // Save guest status to old tss. 656 if (inst_type != TASK_SWITCH_TYPE_IDT) // call, jmp or iret 657 gcpu_skip_guest_instruction(gcpu); 658 659 vmm_memset(&tss, 0, sizeof(tss)); 660 copy_vmcs_to_tss32(gcpu, &tss); 661 if (inst_type == TASK_SWITCH_TYPE_IRET) { 662 ((eflags_t *)&(tss.eflags))->bits.nested_task = 0; 663 } 664 ret = copy_to_gva(gcpu, 665 (UINT64)(old_tr.base + 32), // gva of old_tss.eip 666 64, // from eip to gs: total 64 bytes 667 (UINT64)&(tss.eip)); // hva of old_tss.eip 668 669 if (ret != 0) { 670 gcpu_inject_ts(gcpu, old_tr.selector); 671 return -1; 672 } 673 // Read new tss from memory. 674 vmm_memset(&tss, 0, sizeof(tss)); 675 ret = copy_from_gva(gcpu, (UINT64)(new_tr.base), sizeof(tss), (UINT64)&(tss)); 676 if (ret != 0) { 677 gcpu_inject_ts(gcpu, new_tr.selector); 678 return -1; 679 } 680 681 // Clear busy bit in old tss descriptor. 682 if ((inst_type == TASK_SWITCH_TYPE_JMP) || (inst_type == TASK_SWITCH_TYPE_IRET)) { 683 ret = copy_from_gva(gcpu, (UINT64)(gdtr.base + SelectorIdx(old_tr.selector)), 684 sizeof(old_tss_desc), (UINT64)(&old_tss_desc)); 685 if (ret != 0) { 686 gcpu_inject_ts(gcpu, old_tr.selector); 687 return -1; 688 } 689 // Clear the B bit, and write it back. 690 old_tss_desc.bits.type = Tss32Aval; 691 ret = copy_to_gva(gcpu, (UINT64)(gdtr.base + SelectorIdx(old_tr.selector)), 692 sizeof(old_tss_desc), (UINT64)(&old_tss_desc)); 693 if (ret != 0) { 694 gcpu_inject_ts(gcpu, old_tr.selector); 695 return -1; 696 } 697 } 698 699 // Set busy bit in new tss descriptor. 700 if (inst_type != TASK_SWITCH_TYPE_IRET) { 701 new_tss_desc.bits.type = Tss32Busy; 702 new_tr.ar.bits.type = Tss32Busy; 703 704 ret = copy_to_gva(gcpu, (UINT64)(gdtr.base + SelectorIdx(new_tr.selector)), 705 sizeof(new_tss_desc), (UINT64)(&new_tss_desc)); 706 if (ret != 0) { 707 gcpu_inject_ts(gcpu, new_tr.selector); 708 return -1; 709 } 710 } 711 712 // Save old tr in new tss. 713 if ((inst_type == TASK_SWITCH_TYPE_CALL) || (inst_type == TASK_SWITCH_TYPE_IDT)) { 714 ret = copy_to_gva(gcpu, (UINT64)(new_tr.base + 0), // gva of new_tss.prev_tr 715 sizeof(old_tr.selector), // two bytes 716 (UINT64)(&(old_tr.selector))); // hva 717 718 if (ret != 0) { 719 new_tss_desc.bits.type = Tss32Aval; 720 copy_to_gva(gcpu, (UINT64)(gdtr.base + SelectorIdx(new_tr.selector)), 721 sizeof(new_tss_desc), (UINT64)(&new_tss_desc)); 722 gcpu_inject_ts(gcpu, new_tr.selector); 723 return -1; 724 } 725 } 726 727 // Load new tr. 728 gcpu_set_segment_reg( gcpu, IA32_SEG_TR, new_tr.selector, new_tr.base, 729 new_tr.limit, new_tr.ar.value); 730 731 // Load new cr3. 732 if (cr0.bits.pg) { 733 gcpu_set_guest_visible_control_reg(gcpu, IA32_CTRL_CR3, tss.cr3); 734 gcpu_set_control_reg(gcpu, IA32_CTRL_CR3, tss.cr3); 735 } 736 737 // Load new flags. 738 if ((inst_type == TASK_SWITCH_TYPE_CALL) || (inst_type == TASK_SWITCH_TYPE_IDT)) { 739 ((eflags_t *)&(tss.eflags))->bits.nested_task = 1; 740 } 741 ((eflags_t *)&(tss.eflags))->bits.rsvd_1 = 1; 742 743 // Load general regs. 744 gcpu_set_gp_reg(gcpu, IA32_REG_RIP, (UINT64)tss.eip); 745 gcpu_set_gp_reg(gcpu, IA32_REG_RFLAGS, (UINT64)tss.eflags); 746 gcpu_set_gp_reg(gcpu, IA32_REG_RAX, (UINT64)tss.eax); 747 gcpu_set_gp_reg(gcpu, IA32_REG_RCX, (UINT64)tss.ecx); 748 gcpu_set_gp_reg(gcpu, IA32_REG_RDX, (UINT64)tss.edx); 749 gcpu_set_gp_reg(gcpu, IA32_REG_RBX, (UINT64)tss.ebx); 750 gcpu_set_gp_reg(gcpu, IA32_REG_RBP, (UINT64)tss.ebp); 751 gcpu_set_gp_reg(gcpu, IA32_REG_RSP, (UINT64)tss.esp); 752 gcpu_set_gp_reg(gcpu, IA32_REG_RSI, (UINT64)tss.esi); 753 gcpu_set_gp_reg(gcpu, IA32_REG_RDI, (UINT64)tss.edi); 754 755 // Set the TS bit in CR0. 756 cr0.bits.ts = 1; 757 gcpu_set_guest_visible_control_reg(gcpu, IA32_CTRL_CR0, cr0.value); 758 gcpu_set_control_reg(gcpu, IA32_CTRL_CR0, cr0.value); 759 760 // Load new ldtr. 761 if (tss.ldtr != old_ldtr.selector) { 762 if (set_guest_ldtr(gcpu, &gdtr, &new_ldtr, &tss) != 0) 763 return -1; 764 } 765 766 // Load new seg regs. 767 if (((eflags_t *)&(tss.eflags))->bits.v86_mode == 1) { 768 UINT16 es = (UINT16)tss.es; 769 UINT16 cs = (UINT16)tss.cs; 770 UINT16 ss = (UINT16)tss.ss; 771 UINT16 ds = (UINT16)tss.ds; 772 UINT16 fs = (UINT16)tss.fs; 773 UINT16 gs = (UINT16)tss.gs; 774 775 // Set v86 selector, base, limit, ar, in real-mode style. 776 gcpu_set_segment_reg(gcpu, IA32_SEG_ES, es, es << 4, 0xffff, 0xf3); 777 gcpu_set_segment_reg(gcpu, IA32_SEG_CS, cs, cs << 4, 0xffff, 0xf3); 778 gcpu_set_segment_reg(gcpu, IA32_SEG_SS, ss, ss << 4, 0xffff, 0xf3); 779 gcpu_set_segment_reg(gcpu, IA32_SEG_DS, ds, ds << 4, 0xffff, 0xf3); 780 gcpu_set_segment_reg(gcpu, IA32_SEG_FS, fs, fs << 4, 0xffff, 0xf3); 781 gcpu_set_segment_reg(gcpu, IA32_SEG_GS, gs, gs << 4, 0xffff, 0xf3); 782 783 goto all_done; 784 } 785 786 // Load new ss. 787 if (set_guest_ss(gcpu, &gdtr, &new_ldtr, &tss) != 0) 788 return -1; 789 // Load new es, ds, fs, gs. 790 if ((set_guest_seg(gcpu, &gdtr, &new_ldtr, &tss, IA32_SEG_ES) != 0) || 791 (set_guest_seg(gcpu, &gdtr, &new_ldtr, &tss, IA32_SEG_DS) != 0) || 792 (set_guest_seg(gcpu, &gdtr, &new_ldtr, &tss, IA32_SEG_FS) != 0) || 793 (set_guest_seg(gcpu, &gdtr, &new_ldtr, &tss, IA32_SEG_GS) != 0)) { 794 return -1; 795 } 796 // Load new cs. 797 if (set_guest_cs(gcpu, &gdtr, &new_ldtr, &tss) != 0) 798 return -1; 799 800 all_done: 801 802 // Clear the LE bits in DR7. 803 dr7.value = (UINT32)gcpu_get_debug_reg(gcpu, IA32_REG_DR7); 804 dr7.bits.l0 = 0; 805 dr7.bits.l1 = 0; 806 dr7.bits.l2 = 0; 807 dr7.bits.l3 = 0; 808 dr7.bits.le = 0; 809 gcpu_set_debug_reg(gcpu, IA32_REG_DR7, (UINT64)dr7.value); 810 811 // Debug trap in new task? 812 if ((tss.io_base_addr & 0x00000001) != 0) { 813 gcpu_inject_db(gcpu); 814 return -1; 815 } 816 return 0; 817 } 818 819 820 VMEXIT_HANDLING_STATUS vmexit_task_switch(GUEST_CPU_HANDLE gcpu) 821 { 822 VMCS_OBJECT* vmcs = gcpu_get_vmcs(gcpu); 823 IA32_VMX_VMCS_VM_EXIT_INFO_IDT_VECTORING idt_vectoring_info; 824 IA32_VMX_EXIT_QUALIFICATION qualification; 825 826 idt_vectoring_info.Uint32 = (UINT32) vmcs_read(vmcs, VMCS_EXIT_INFO_IDT_VECTORING); 827 qualification.Uint64 = vmcs_read(vmcs, VMCS_EXIT_INFO_QUALIFICATION); 828 829 #ifdef DEBUG 830 { 831 #define TS_NMI_VECOTR 0x02 832 #define TS_DOUBLE_FAULT_VECTOR 0x08 833 #define TS_MC_VECOR 0x12 834 835 char *task_switch_name[]={"NMI", "Double Fault", "Machine Check", "Others"}; 836 char *task_switch_type[]={"Call", "IRET", "Jmp", "Task Gate"}; 837 838 UINT32 name_id = 3; // default Double fault 839 UINT32 vector = (UINT32)-1; 840 841 if(idt_vectoring_info.Bits.Valid) { 842 vector = idt_vectoring_info.Bits.Vector; 843 } 844 845 if ( qualification.TaskSwitch.Source == TASK_SWITCH_TYPE_IDT) { 846 if (qualification.TaskSwitch.TssSelector == 0x50) 847 name_id = 1; 848 else if (qualification.TaskSwitch.TssSelector == 0x58) 849 name_id = 0; 850 else if (qualification.TaskSwitch.TssSelector == 0xa0) 851 name_id = 2; 852 else 853 name_id = 3; 854 } 855 856 VMM_LOG(mask_anonymous, level_trace,"Task Switch on CPU#%d src:%s type:%s tss:0x%x Qual:0x%x Vec:0x%x \n", 857 guest_vcpu(gcpu)->guest_cpu_id, 858 task_switch_name[name_id], 859 task_switch_type[qualification.TaskSwitch.Source], 860 (qualification.Uint64 & 0xffff), 861 qualification.Uint64, 862 vector); 863 864 } 865 #endif //DEBUG 866 867 if(idt_vectoring_info.Bits.Valid && qualification.TaskSwitch.Source == TASK_SWITCH_TYPE_IDT){ 868 // clear IDT if valid, so that 869 // we can inject the event when needed (see event injections in task_switch_for_guest() below) 870 // or 871 // avoid re-inject unwanted exception, e.g NMI. 872 vmcs_write(vmcs, VMCS_EXIT_INFO_IDT_VECTORING, 0); 873 } 874 875 // pass idt_vectoring_info on to the following function calling since 876 // the value in VMCS_EXIT_INFO_IDT_VECTORING VMCS may be cleared above 877 task_switch_for_guest(gcpu, idt_vectoring_info); 878 return VMEXIT_HANDLED; 879 } 880 881 882