qemu/target/i386/hvf/x86_descr.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2016 Veertu Inc,
   3 * Copyright (C) 2017 Google Inc,
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU Lesser General Public
   7 * License as published by the Free Software Foundation; either
   8 * version 2.1 of the License, or (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * Lesser General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU Lesser General Public
  16 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19#include "qemu/osdep.h"
  20
  21#include "vmx.h"
  22#include "x86_descr.h"
  23
  24#define VMX_SEGMENT_FIELD(seg)                        \
  25    [R_##seg] = {                                     \
  26        .selector = VMCS_GUEST_##seg##_SELECTOR,      \
  27        .base = VMCS_GUEST_##seg##_BASE,              \
  28        .limit = VMCS_GUEST_##seg##_LIMIT,            \
  29        .ar_bytes = VMCS_GUEST_##seg##_ACCESS_RIGHTS, \
  30}
  31
  32static const struct vmx_segment_field {
  33    int selector;
  34    int base;
  35    int limit;
  36    int ar_bytes;
  37} vmx_segment_fields[] = {
  38    VMX_SEGMENT_FIELD(ES),
  39    VMX_SEGMENT_FIELD(CS),
  40    VMX_SEGMENT_FIELD(SS),
  41    VMX_SEGMENT_FIELD(DS),
  42    VMX_SEGMENT_FIELD(FS),
  43    VMX_SEGMENT_FIELD(GS),
  44    VMX_SEGMENT_FIELD(LDTR),
  45    VMX_SEGMENT_FIELD(TR),
  46};
  47
  48uint32_t vmx_read_segment_limit(CPUState *cpu, X86Seg seg)
  49{
  50    return (uint32_t)rvmcs(cpu->accel->fd, vmx_segment_fields[seg].limit);
  51}
  52
  53uint32_t vmx_read_segment_ar(CPUState *cpu, X86Seg seg)
  54{
  55    return (uint32_t)rvmcs(cpu->accel->fd, vmx_segment_fields[seg].ar_bytes);
  56}
  57
  58uint64_t vmx_read_segment_base(CPUState *cpu, X86Seg seg)
  59{
  60    return rvmcs(cpu->accel->fd, vmx_segment_fields[seg].base);
  61}
  62
  63x86_segment_selector vmx_read_segment_selector(CPUState *cpu, X86Seg seg)
  64{
  65    x86_segment_selector sel;
  66    sel.sel = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].selector);
  67    return sel;
  68}
  69
  70void vmx_write_segment_selector(CPUState *cpu, x86_segment_selector selector, X86Seg seg)
  71{
  72    wvmcs(cpu->accel->fd, vmx_segment_fields[seg].selector, selector.sel);
  73}
  74
  75void vmx_read_segment_descriptor(CPUState *cpu, struct vmx_segment *desc, X86Seg seg)
  76{
  77    desc->sel = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].selector);
  78    desc->base = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].base);
  79    desc->limit = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].limit);
  80    desc->ar = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].ar_bytes);
  81}
  82
  83void vmx_write_segment_descriptor(CPUState *cpu, struct vmx_segment *desc, X86Seg seg)
  84{
  85    const struct vmx_segment_field *sf = &vmx_segment_fields[seg];
  86
  87    wvmcs(cpu->accel->fd, sf->base, desc->base);
  88    wvmcs(cpu->accel->fd, sf->limit, desc->limit);
  89    wvmcs(cpu->accel->fd, sf->selector, desc->sel);
  90    wvmcs(cpu->accel->fd, sf->ar_bytes, desc->ar);
  91}
  92
  93void x86_segment_descriptor_to_vmx(CPUState *cpu, x86_segment_selector selector,
  94                                   struct x86_segment_descriptor *desc,
  95                                   struct vmx_segment *vmx_desc)
  96{
  97    vmx_desc->sel = selector.sel;
  98    vmx_desc->base = x86_segment_base(desc);
  99    vmx_desc->limit = x86_segment_limit(desc);
 100
 101    vmx_desc->ar = (selector.sel ? 0 : 1) << 16 |
 102                    desc->g << 15 |
 103                    desc->db << 14 |
 104                    desc->l << 13 |
 105                    desc->avl << 12 |
 106                    desc->p << 7 |
 107                    desc->dpl << 5 |
 108                    desc->s << 4 |
 109                    desc->type;
 110}
 111
 112void vmx_segment_to_x86_descriptor(CPUState *cpu, struct vmx_segment *vmx_desc,
 113                                   struct x86_segment_descriptor *desc)
 114{
 115    x86_set_segment_limit(desc, vmx_desc->limit);
 116    x86_set_segment_base(desc, vmx_desc->base);
 117    
 118    desc->type = vmx_desc->ar & 15;
 119    desc->s = (vmx_desc->ar >> 4) & 1;
 120    desc->dpl = (vmx_desc->ar >> 5) & 3;
 121    desc->p = (vmx_desc->ar >> 7) & 1;
 122    desc->avl = (vmx_desc->ar >> 12) & 1;
 123    desc->l = (vmx_desc->ar >> 13) & 1;
 124    desc->db = (vmx_desc->ar >> 14) & 1;
 125    desc->g = (vmx_desc->ar >> 15) & 1;
 126}
 127
 128