2 * Copyright (C) 2016 Veertu Inc,
3 * Copyright (C) 2017 Google Inc,
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 of the License, or (at your option) any later version.
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.
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/>.
19 #include "qemu/osdep.h"
22 #include "qemu-common.h"
23 #include "x86_decode.h"
28 #include "x86_descr.h"
30 /* static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var)
40 ar |= (var->s & 1) << 4;
41 ar |= (var->dpl & 3) << 5;
42 ar |= (var->p & 1) << 7;
43 ar |= (var->avl & 1) << 12;
44 ar |= (var->l & 1) << 13;
45 ar |= (var->db & 1) << 14;
46 ar |= (var->g & 1) << 15;
50 bool x86_read_segment_descriptor(struct CPUState
*cpu
,
51 struct x86_segment_descriptor
*desc
,
52 x68_segment_selector sel
)
57 memset(desc
, 0, sizeof(*desc
));
59 /* valid gdt descriptors start from index 1 */
60 if (!sel
.index
&& GDT_SEL
== sel
.ti
) {
64 if (GDT_SEL
== sel
.ti
) {
65 base
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_GDTR_BASE
);
66 limit
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_GDTR_LIMIT
);
68 base
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_LDTR_BASE
);
69 limit
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_LDTR_LIMIT
);
72 if (sel
.index
* 8 >= limit
) {
76 vmx_read_mem(cpu
, desc
, base
+ sel
.index
* 8, sizeof(*desc
));
80 bool x86_write_segment_descriptor(struct CPUState
*cpu
,
81 struct x86_segment_descriptor
*desc
,
82 x68_segment_selector sel
)
87 if (GDT_SEL
== sel
.ti
) {
88 base
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_GDTR_BASE
);
89 limit
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_GDTR_LIMIT
);
91 base
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_LDTR_BASE
);
92 limit
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_LDTR_LIMIT
);
95 if (sel
.index
* 8 >= limit
) {
96 printf("%s: gdt limit\n", __func__
);
99 vmx_write_mem(cpu
, base
+ sel
.index
* 8, desc
, sizeof(*desc
));
103 bool x86_read_call_gate(struct CPUState
*cpu
, struct x86_call_gate
*idt_desc
,
106 target_ulong base
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_IDTR_BASE
);
107 uint32_t limit
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_IDTR_LIMIT
);
109 memset(idt_desc
, 0, sizeof(*idt_desc
));
110 if (gate
* 8 >= limit
) {
111 printf("%s: idt limit\n", __func__
);
115 vmx_read_mem(cpu
, idt_desc
, base
+ gate
* 8, sizeof(*idt_desc
));
119 bool x86_is_protected(struct CPUState
*cpu
)
121 uint64_t cr0
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_CR0
);
125 bool x86_is_real(struct CPUState
*cpu
)
127 return !x86_is_protected(cpu
);
130 bool x86_is_v8086(struct CPUState
*cpu
)
132 X86CPU
*x86_cpu
= X86_CPU(cpu
);
133 CPUX86State
*env
= &x86_cpu
->env
;
134 return x86_is_protected(cpu
) && (RFLAGS(env
) & RFLAGS_VM
);
137 bool x86_is_long_mode(struct CPUState
*cpu
)
139 return rvmcs(cpu
->hvf_fd
, VMCS_GUEST_IA32_EFER
) & MSR_EFER_LMA
;
142 bool x86_is_long64_mode(struct CPUState
*cpu
)
144 struct vmx_segment desc
;
145 vmx_read_segment_descriptor(cpu
, &desc
, R_CS
);
147 return x86_is_long_mode(cpu
) && ((desc
.ar
>> 13) & 1);
150 bool x86_is_paging_mode(struct CPUState
*cpu
)
152 uint64_t cr0
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_CR0
);
156 bool x86_is_pae_enabled(struct CPUState
*cpu
)
158 uint64_t cr4
= rvmcs(cpu
->hvf_fd
, VMCS_GUEST_CR4
);
159 return cr4
& CR4_PAE
;
162 target_ulong
linear_addr(struct CPUState
*cpu
, target_ulong addr
, X86Seg seg
)
164 return vmx_read_segment_base(cpu
, seg
) + addr
;
167 target_ulong
linear_addr_size(struct CPUState
*cpu
, target_ulong addr
, int size
,
172 addr
= (uint16_t)addr
;
175 addr
= (uint32_t)addr
;
180 return linear_addr(cpu
, addr
, seg
);
183 target_ulong
linear_rip(struct CPUState
*cpu
, target_ulong rip
)
185 return linear_addr(cpu
, rip
, R_CS
);