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