qemu

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

x86.c (4915B)


      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 "cpu.h"
     22 #include "x86_decode.h"
     23 #include "x86_emu.h"
     24 #include "vmcs.h"
     25 #include "vmx.h"
     26 #include "x86_mmu.h"
     27 #include "x86_descr.h"
     28 
     29 /* static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var)
     30 {
     31    uint32_t ar;
     32 
     33    if (!var->p) {
     34        ar = 1 << 16;
     35        return ar;
     36    }
     37 
     38    ar = var->type & 15;
     39    ar |= (var->s & 1) << 4;
     40    ar |= (var->dpl & 3) << 5;
     41    ar |= (var->p & 1) << 7;
     42    ar |= (var->avl & 1) << 12;
     43    ar |= (var->l & 1) << 13;
     44    ar |= (var->db & 1) << 14;
     45    ar |= (var->g & 1) << 15;
     46    return ar;
     47 }*/
     48 
     49 bool x86_read_segment_descriptor(struct CPUState *cpu,
     50                                  struct x86_segment_descriptor *desc,
     51                                  x68_segment_selector sel)
     52 {
     53     target_ulong base;
     54     uint32_t limit;
     55 
     56     memset(desc, 0, sizeof(*desc));
     57 
     58     /* valid gdt descriptors start from index 1 */
     59     if (!sel.index && GDT_SEL == sel.ti) {
     60         return false;
     61     }
     62 
     63     if (GDT_SEL == sel.ti) {
     64         base  = rvmcs(cpu->hvf->fd, VMCS_GUEST_GDTR_BASE);
     65         limit = rvmcs(cpu->hvf->fd, VMCS_GUEST_GDTR_LIMIT);
     66     } else {
     67         base  = rvmcs(cpu->hvf->fd, VMCS_GUEST_LDTR_BASE);
     68         limit = rvmcs(cpu->hvf->fd, VMCS_GUEST_LDTR_LIMIT);
     69     }
     70 
     71     if (sel.index * 8 >= limit) {
     72         return false;
     73     }
     74 
     75     vmx_read_mem(cpu, desc, base + sel.index * 8, sizeof(*desc));
     76     return true;
     77 }
     78 
     79 bool x86_write_segment_descriptor(struct CPUState *cpu,
     80                                   struct x86_segment_descriptor *desc,
     81                                   x68_segment_selector sel)
     82 {
     83     target_ulong base;
     84     uint32_t limit;
     85     
     86     if (GDT_SEL == sel.ti) {
     87         base  = rvmcs(cpu->hvf->fd, VMCS_GUEST_GDTR_BASE);
     88         limit = rvmcs(cpu->hvf->fd, VMCS_GUEST_GDTR_LIMIT);
     89     } else {
     90         base  = rvmcs(cpu->hvf->fd, VMCS_GUEST_LDTR_BASE);
     91         limit = rvmcs(cpu->hvf->fd, VMCS_GUEST_LDTR_LIMIT);
     92     }
     93     
     94     if (sel.index * 8 >= limit) {
     95         printf("%s: gdt limit\n", __func__);
     96         return false;
     97     }
     98     vmx_write_mem(cpu, base + sel.index * 8, desc, sizeof(*desc));
     99     return true;
    100 }
    101 
    102 bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc,
    103                         int gate)
    104 {
    105     target_ulong base  = rvmcs(cpu->hvf->fd, VMCS_GUEST_IDTR_BASE);
    106     uint32_t limit = rvmcs(cpu->hvf->fd, VMCS_GUEST_IDTR_LIMIT);
    107 
    108     memset(idt_desc, 0, sizeof(*idt_desc));
    109     if (gate * 8 >= limit) {
    110         printf("%s: idt limit\n", __func__);
    111         return false;
    112     }
    113 
    114     vmx_read_mem(cpu, idt_desc, base + gate * 8, sizeof(*idt_desc));
    115     return true;
    116 }
    117 
    118 bool x86_is_protected(struct CPUState *cpu)
    119 {
    120     uint64_t cr0 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0);
    121     return cr0 & CR0_PE_MASK;
    122 }
    123 
    124 bool x86_is_real(struct CPUState *cpu)
    125 {
    126     return !x86_is_protected(cpu);
    127 }
    128 
    129 bool x86_is_v8086(struct CPUState *cpu)
    130 {
    131     X86CPU *x86_cpu = X86_CPU(cpu);
    132     CPUX86State *env = &x86_cpu->env;
    133     return x86_is_protected(cpu) && (env->eflags & VM_MASK);
    134 }
    135 
    136 bool x86_is_long_mode(struct CPUState *cpu)
    137 {
    138     return rvmcs(cpu->hvf->fd, VMCS_GUEST_IA32_EFER) & MSR_EFER_LMA;
    139 }
    140 
    141 bool x86_is_long64_mode(struct CPUState *cpu)
    142 {
    143     struct vmx_segment desc;
    144     vmx_read_segment_descriptor(cpu, &desc, R_CS);
    145 
    146     return x86_is_long_mode(cpu) && ((desc.ar >> 13) & 1);
    147 }
    148 
    149 bool x86_is_paging_mode(struct CPUState *cpu)
    150 {
    151     uint64_t cr0 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0);
    152     return cr0 & CR0_PG_MASK;
    153 }
    154 
    155 bool x86_is_pae_enabled(struct CPUState *cpu)
    156 {
    157     uint64_t cr4 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR4);
    158     return cr4 & CR4_PAE_MASK;
    159 }
    160 
    161 target_ulong linear_addr(struct CPUState *cpu, target_ulong addr, X86Seg seg)
    162 {
    163     return vmx_read_segment_base(cpu, seg) + addr;
    164 }
    165 
    166 target_ulong linear_addr_size(struct CPUState *cpu, target_ulong addr, int size,
    167                               X86Seg seg)
    168 {
    169     switch (size) {
    170     case 2:
    171         addr = (uint16_t)addr;
    172         break;
    173     case 4:
    174         addr = (uint32_t)addr;
    175         break;
    176     default:
    177         break;
    178     }
    179     return linear_addr(cpu, addr, seg);
    180 }
    181 
    182 target_ulong linear_rip(struct CPUState *cpu, target_ulong rip)
    183 {
    184     return linear_addr(cpu, rip, R_CS);
    185 }