qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

x86_descr.c (4179B)


      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 
     32 static 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 
     48 uint32_t vmx_read_segment_limit(CPUState *cpu, X86Seg seg)
     49 {
     50     return (uint32_t)rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].limit);
     51 }
     52 
     53 uint32_t vmx_read_segment_ar(CPUState *cpu, X86Seg seg)
     54 {
     55     return (uint32_t)rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].ar_bytes);
     56 }
     57 
     58 uint64_t vmx_read_segment_base(CPUState *cpu, X86Seg seg)
     59 {
     60     return rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].base);
     61 }
     62 
     63 x68_segment_selector vmx_read_segment_selector(CPUState *cpu, X86Seg seg)
     64 {
     65     x68_segment_selector sel;
     66     sel.sel = rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].selector);
     67     return sel;
     68 }
     69 
     70 void vmx_write_segment_selector(struct CPUState *cpu, x68_segment_selector selector, X86Seg seg)
     71 {
     72     wvmcs(cpu->hvf->fd, vmx_segment_fields[seg].selector, selector.sel);
     73 }
     74 
     75 void vmx_read_segment_descriptor(struct CPUState *cpu, struct vmx_segment *desc, X86Seg seg)
     76 {
     77     desc->sel = rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].selector);
     78     desc->base = rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].base);
     79     desc->limit = rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].limit);
     80     desc->ar = rvmcs(cpu->hvf->fd, vmx_segment_fields[seg].ar_bytes);
     81 }
     82 
     83 void 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->hvf->fd, sf->base, desc->base);
     88     wvmcs(cpu->hvf->fd, sf->limit, desc->limit);
     89     wvmcs(cpu->hvf->fd, sf->selector, desc->sel);
     90     wvmcs(cpu->hvf->fd, sf->ar_bytes, desc->ar);
     91 }
     92 
     93 void x86_segment_descriptor_to_vmx(struct CPUState *cpu, x68_segment_selector selector, struct x86_segment_descriptor *desc, struct vmx_segment *vmx_desc)
     94 {
     95     vmx_desc->sel = selector.sel;
     96     vmx_desc->base = x86_segment_base(desc);
     97     vmx_desc->limit = x86_segment_limit(desc);
     98 
     99     vmx_desc->ar = (selector.sel ? 0 : 1) << 16 |
    100                     desc->g << 15 |
    101                     desc->db << 14 |
    102                     desc->l << 13 |
    103                     desc->avl << 12 |
    104                     desc->p << 7 |
    105                     desc->dpl << 5 |
    106                     desc->s << 4 |
    107                     desc->type;
    108 }
    109 
    110 void vmx_segment_to_x86_descriptor(struct CPUState *cpu, struct vmx_segment *vmx_desc, struct x86_segment_descriptor *desc)
    111 {
    112     x86_set_segment_limit(desc, vmx_desc->limit);
    113     x86_set_segment_base(desc, vmx_desc->base);
    114     
    115     desc->type = vmx_desc->ar & 15;
    116     desc->s = (vmx_desc->ar >> 4) & 1;
    117     desc->dpl = (vmx_desc->ar >> 5) & 3;
    118     desc->p = (vmx_desc->ar >> 7) & 1;
    119     desc->avl = (vmx_desc->ar >> 12) & 1;
    120     desc->l = (vmx_desc->ar >> 13) & 1;
    121     desc->db = (vmx_desc->ar >> 14) & 1;
    122     desc->g = (vmx_desc->ar >> 15) & 1;
    123 }
    124