root / target-i386 / misc_helper.c @ 5b50e790
History | View | Annotate | Download (15.9 kB)
1 | f7b2429f | Blue Swirl | /*
|
---|---|---|---|
2 | f7b2429f | Blue Swirl | * x86 misc helpers
|
3 | f7b2429f | Blue Swirl | *
|
4 | f7b2429f | Blue Swirl | * Copyright (c) 2003 Fabrice Bellard
|
5 | f7b2429f | Blue Swirl | *
|
6 | f7b2429f | Blue Swirl | * This library is free software; you can redistribute it and/or
|
7 | f7b2429f | Blue Swirl | * modify it under the terms of the GNU Lesser General Public
|
8 | f7b2429f | Blue Swirl | * License as published by the Free Software Foundation; either
|
9 | f7b2429f | Blue Swirl | * version 2 of the License, or (at your option) any later version.
|
10 | f7b2429f | Blue Swirl | *
|
11 | f7b2429f | Blue Swirl | * This library is distributed in the hope that it will be useful,
|
12 | f7b2429f | Blue Swirl | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | f7b2429f | Blue Swirl | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | f7b2429f | Blue Swirl | * Lesser General Public License for more details.
|
15 | f7b2429f | Blue Swirl | *
|
16 | f7b2429f | Blue Swirl | * You should have received a copy of the GNU Lesser General Public
|
17 | f7b2429f | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | f7b2429f | Blue Swirl | */
|
19 | f7b2429f | Blue Swirl | |
20 | f7b2429f | Blue Swirl | #include "cpu.h" |
21 | 022c62cb | Paolo Bonzini | #include "exec/ioport.h" |
22 | f7b2429f | Blue Swirl | #include "helper.h" |
23 | f7b2429f | Blue Swirl | |
24 | 92fc4b58 | Blue Swirl | #if !defined(CONFIG_USER_ONLY)
|
25 | 022c62cb | Paolo Bonzini | #include "exec/softmmu_exec.h" |
26 | 92fc4b58 | Blue Swirl | #endif /* !defined(CONFIG_USER_ONLY) */ |
27 | 92fc4b58 | Blue Swirl | |
28 | f7b2429f | Blue Swirl | /* check if Port I/O is allowed in TSS */
|
29 | 4a7443be | Blue Swirl | static inline void check_io(CPUX86State *env, int addr, int size) |
30 | f7b2429f | Blue Swirl | { |
31 | f7b2429f | Blue Swirl | int io_offset, val, mask;
|
32 | f7b2429f | Blue Swirl | |
33 | f7b2429f | Blue Swirl | /* TSS must be a valid 32 bit one */
|
34 | f7b2429f | Blue Swirl | if (!(env->tr.flags & DESC_P_MASK) ||
|
35 | f7b2429f | Blue Swirl | ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 || |
36 | f7b2429f | Blue Swirl | env->tr.limit < 103) {
|
37 | f7b2429f | Blue Swirl | goto fail;
|
38 | f7b2429f | Blue Swirl | } |
39 | 4a7443be | Blue Swirl | io_offset = cpu_lduw_kernel(env, env->tr.base + 0x66);
|
40 | f7b2429f | Blue Swirl | io_offset += (addr >> 3);
|
41 | f7b2429f | Blue Swirl | /* Note: the check needs two bytes */
|
42 | f7b2429f | Blue Swirl | if ((io_offset + 1) > env->tr.limit) { |
43 | f7b2429f | Blue Swirl | goto fail;
|
44 | f7b2429f | Blue Swirl | } |
45 | 4a7443be | Blue Swirl | val = cpu_lduw_kernel(env, env->tr.base + io_offset); |
46 | f7b2429f | Blue Swirl | val >>= (addr & 7);
|
47 | f7b2429f | Blue Swirl | mask = (1 << size) - 1; |
48 | f7b2429f | Blue Swirl | /* all bits must be zero to allow the I/O */
|
49 | f7b2429f | Blue Swirl | if ((val & mask) != 0) { |
50 | f7b2429f | Blue Swirl | fail:
|
51 | f7b2429f | Blue Swirl | raise_exception_err(env, EXCP0D_GPF, 0);
|
52 | f7b2429f | Blue Swirl | } |
53 | f7b2429f | Blue Swirl | } |
54 | f7b2429f | Blue Swirl | |
55 | 4a7443be | Blue Swirl | void helper_check_iob(CPUX86State *env, uint32_t t0)
|
56 | f7b2429f | Blue Swirl | { |
57 | 4a7443be | Blue Swirl | check_io(env, t0, 1);
|
58 | f7b2429f | Blue Swirl | } |
59 | f7b2429f | Blue Swirl | |
60 | 4a7443be | Blue Swirl | void helper_check_iow(CPUX86State *env, uint32_t t0)
|
61 | f7b2429f | Blue Swirl | { |
62 | 4a7443be | Blue Swirl | check_io(env, t0, 2);
|
63 | f7b2429f | Blue Swirl | } |
64 | f7b2429f | Blue Swirl | |
65 | 4a7443be | Blue Swirl | void helper_check_iol(CPUX86State *env, uint32_t t0)
|
66 | f7b2429f | Blue Swirl | { |
67 | 4a7443be | Blue Swirl | check_io(env, t0, 4);
|
68 | f7b2429f | Blue Swirl | } |
69 | f7b2429f | Blue Swirl | |
70 | f7b2429f | Blue Swirl | void helper_outb(uint32_t port, uint32_t data)
|
71 | f7b2429f | Blue Swirl | { |
72 | f7b2429f | Blue Swirl | cpu_outb(port, data & 0xff);
|
73 | f7b2429f | Blue Swirl | } |
74 | f7b2429f | Blue Swirl | |
75 | f7b2429f | Blue Swirl | target_ulong helper_inb(uint32_t port) |
76 | f7b2429f | Blue Swirl | { |
77 | f7b2429f | Blue Swirl | return cpu_inb(port);
|
78 | f7b2429f | Blue Swirl | } |
79 | f7b2429f | Blue Swirl | |
80 | f7b2429f | Blue Swirl | void helper_outw(uint32_t port, uint32_t data)
|
81 | f7b2429f | Blue Swirl | { |
82 | f7b2429f | Blue Swirl | cpu_outw(port, data & 0xffff);
|
83 | f7b2429f | Blue Swirl | } |
84 | f7b2429f | Blue Swirl | |
85 | f7b2429f | Blue Swirl | target_ulong helper_inw(uint32_t port) |
86 | f7b2429f | Blue Swirl | { |
87 | f7b2429f | Blue Swirl | return cpu_inw(port);
|
88 | f7b2429f | Blue Swirl | } |
89 | f7b2429f | Blue Swirl | |
90 | f7b2429f | Blue Swirl | void helper_outl(uint32_t port, uint32_t data)
|
91 | f7b2429f | Blue Swirl | { |
92 | f7b2429f | Blue Swirl | cpu_outl(port, data); |
93 | f7b2429f | Blue Swirl | } |
94 | f7b2429f | Blue Swirl | |
95 | f7b2429f | Blue Swirl | target_ulong helper_inl(uint32_t port) |
96 | f7b2429f | Blue Swirl | { |
97 | f7b2429f | Blue Swirl | return cpu_inl(port);
|
98 | f7b2429f | Blue Swirl | } |
99 | f7b2429f | Blue Swirl | |
100 | 4a7443be | Blue Swirl | void helper_into(CPUX86State *env, int next_eip_addend) |
101 | f7b2429f | Blue Swirl | { |
102 | f7b2429f | Blue Swirl | int eflags;
|
103 | f7b2429f | Blue Swirl | |
104 | f0967a1a | Blue Swirl | eflags = cpu_cc_compute_all(env, CC_OP); |
105 | f7b2429f | Blue Swirl | if (eflags & CC_O) {
|
106 | f7b2429f | Blue Swirl | raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend); |
107 | f7b2429f | Blue Swirl | } |
108 | f7b2429f | Blue Swirl | } |
109 | f7b2429f | Blue Swirl | |
110 | 4a7443be | Blue Swirl | void helper_single_step(CPUX86State *env)
|
111 | f7b2429f | Blue Swirl | { |
112 | f7b2429f | Blue Swirl | #ifndef CONFIG_USER_ONLY
|
113 | e175bce5 | liguang | check_hw_breakpoints(env, true);
|
114 | f7b2429f | Blue Swirl | env->dr[6] |= DR6_BS;
|
115 | f7b2429f | Blue Swirl | #endif
|
116 | f7b2429f | Blue Swirl | raise_exception(env, EXCP01_DB); |
117 | f7b2429f | Blue Swirl | } |
118 | f7b2429f | Blue Swirl | |
119 | 4a7443be | Blue Swirl | void helper_cpuid(CPUX86State *env)
|
120 | f7b2429f | Blue Swirl | { |
121 | f7b2429f | Blue Swirl | uint32_t eax, ebx, ecx, edx; |
122 | f7b2429f | Blue Swirl | |
123 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0);
|
124 | f7b2429f | Blue Swirl | |
125 | 90a2541b | liguang | cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX], |
126 | 90a2541b | liguang | &eax, &ebx, &ecx, &edx); |
127 | 4b34e3ad | liguang | env->regs[R_EAX] = eax; |
128 | 70b51365 | liguang | env->regs[R_EBX] = ebx; |
129 | a4165610 | liguang | env->regs[R_ECX] = ecx; |
130 | 00f5e6f2 | liguang | env->regs[R_EDX] = edx; |
131 | f7b2429f | Blue Swirl | } |
132 | f7b2429f | Blue Swirl | |
133 | f7b2429f | Blue Swirl | #if defined(CONFIG_USER_ONLY)
|
134 | 4a7443be | Blue Swirl | target_ulong helper_read_crN(CPUX86State *env, int reg)
|
135 | f7b2429f | Blue Swirl | { |
136 | f7b2429f | Blue Swirl | return 0; |
137 | f7b2429f | Blue Swirl | } |
138 | f7b2429f | Blue Swirl | |
139 | 4a7443be | Blue Swirl | void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) |
140 | f7b2429f | Blue Swirl | { |
141 | f7b2429f | Blue Swirl | } |
142 | f7b2429f | Blue Swirl | |
143 | 4a7443be | Blue Swirl | void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) |
144 | f7b2429f | Blue Swirl | { |
145 | f7b2429f | Blue Swirl | } |
146 | f7b2429f | Blue Swirl | #else
|
147 | 4a7443be | Blue Swirl | target_ulong helper_read_crN(CPUX86State *env, int reg)
|
148 | f7b2429f | Blue Swirl | { |
149 | f7b2429f | Blue Swirl | target_ulong val; |
150 | f7b2429f | Blue Swirl | |
151 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0);
|
152 | f7b2429f | Blue Swirl | switch (reg) {
|
153 | f7b2429f | Blue Swirl | default:
|
154 | f7b2429f | Blue Swirl | val = env->cr[reg]; |
155 | f7b2429f | Blue Swirl | break;
|
156 | f7b2429f | Blue Swirl | case 8: |
157 | f7b2429f | Blue Swirl | if (!(env->hflags2 & HF2_VINTR_MASK)) {
|
158 | f7b2429f | Blue Swirl | val = cpu_get_apic_tpr(env->apic_state); |
159 | f7b2429f | Blue Swirl | } else {
|
160 | f7b2429f | Blue Swirl | val = env->v_tpr; |
161 | f7b2429f | Blue Swirl | } |
162 | f7b2429f | Blue Swirl | break;
|
163 | f7b2429f | Blue Swirl | } |
164 | f7b2429f | Blue Swirl | return val;
|
165 | f7b2429f | Blue Swirl | } |
166 | f7b2429f | Blue Swirl | |
167 | 4a7443be | Blue Swirl | void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) |
168 | f7b2429f | Blue Swirl | { |
169 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0);
|
170 | f7b2429f | Blue Swirl | switch (reg) {
|
171 | f7b2429f | Blue Swirl | case 0: |
172 | f7b2429f | Blue Swirl | cpu_x86_update_cr0(env, t0); |
173 | f7b2429f | Blue Swirl | break;
|
174 | f7b2429f | Blue Swirl | case 3: |
175 | f7b2429f | Blue Swirl | cpu_x86_update_cr3(env, t0); |
176 | f7b2429f | Blue Swirl | break;
|
177 | f7b2429f | Blue Swirl | case 4: |
178 | f7b2429f | Blue Swirl | cpu_x86_update_cr4(env, t0); |
179 | f7b2429f | Blue Swirl | break;
|
180 | f7b2429f | Blue Swirl | case 8: |
181 | f7b2429f | Blue Swirl | if (!(env->hflags2 & HF2_VINTR_MASK)) {
|
182 | f7b2429f | Blue Swirl | cpu_set_apic_tpr(env->apic_state, t0); |
183 | f7b2429f | Blue Swirl | } |
184 | f7b2429f | Blue Swirl | env->v_tpr = t0 & 0x0f;
|
185 | f7b2429f | Blue Swirl | break;
|
186 | f7b2429f | Blue Swirl | default:
|
187 | f7b2429f | Blue Swirl | env->cr[reg] = t0; |
188 | f7b2429f | Blue Swirl | break;
|
189 | f7b2429f | Blue Swirl | } |
190 | f7b2429f | Blue Swirl | } |
191 | f7b2429f | Blue Swirl | |
192 | 4a7443be | Blue Swirl | void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0) |
193 | f7b2429f | Blue Swirl | { |
194 | f7b2429f | Blue Swirl | int i;
|
195 | f7b2429f | Blue Swirl | |
196 | f7b2429f | Blue Swirl | if (reg < 4) { |
197 | f7b2429f | Blue Swirl | hw_breakpoint_remove(env, reg); |
198 | f7b2429f | Blue Swirl | env->dr[reg] = t0; |
199 | f7b2429f | Blue Swirl | hw_breakpoint_insert(env, reg); |
200 | f7b2429f | Blue Swirl | } else if (reg == 7) { |
201 | 428065ce | liguang | for (i = 0; i < DR7_MAX_BP; i++) { |
202 | f7b2429f | Blue Swirl | hw_breakpoint_remove(env, i); |
203 | f7b2429f | Blue Swirl | } |
204 | f7b2429f | Blue Swirl | env->dr[7] = t0;
|
205 | 428065ce | liguang | for (i = 0; i < DR7_MAX_BP; i++) { |
206 | f7b2429f | Blue Swirl | hw_breakpoint_insert(env, i); |
207 | f7b2429f | Blue Swirl | } |
208 | f7b2429f | Blue Swirl | } else {
|
209 | f7b2429f | Blue Swirl | env->dr[reg] = t0; |
210 | f7b2429f | Blue Swirl | } |
211 | f7b2429f | Blue Swirl | } |
212 | f7b2429f | Blue Swirl | #endif
|
213 | f7b2429f | Blue Swirl | |
214 | 4a7443be | Blue Swirl | void helper_lmsw(CPUX86State *env, target_ulong t0)
|
215 | f7b2429f | Blue Swirl | { |
216 | f7b2429f | Blue Swirl | /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
|
217 | f7b2429f | Blue Swirl | if already set to one. */
|
218 | f7b2429f | Blue Swirl | t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); |
219 | 4a7443be | Blue Swirl | helper_write_crN(env, 0, t0);
|
220 | f7b2429f | Blue Swirl | } |
221 | f7b2429f | Blue Swirl | |
222 | 4a7443be | Blue Swirl | void helper_invlpg(CPUX86State *env, target_ulong addr)
|
223 | f7b2429f | Blue Swirl | { |
224 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
|
225 | f7b2429f | Blue Swirl | tlb_flush_page(env, addr); |
226 | f7b2429f | Blue Swirl | } |
227 | f7b2429f | Blue Swirl | |
228 | 4a7443be | Blue Swirl | void helper_rdtsc(CPUX86State *env)
|
229 | f7b2429f | Blue Swirl | { |
230 | f7b2429f | Blue Swirl | uint64_t val; |
231 | f7b2429f | Blue Swirl | |
232 | f7b2429f | Blue Swirl | if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { |
233 | f7b2429f | Blue Swirl | raise_exception(env, EXCP0D_GPF); |
234 | f7b2429f | Blue Swirl | } |
235 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0);
|
236 | f7b2429f | Blue Swirl | |
237 | f7b2429f | Blue Swirl | val = cpu_get_tsc(env) + env->tsc_offset; |
238 | 4b34e3ad | liguang | env->regs[R_EAX] = (uint32_t)(val); |
239 | 00f5e6f2 | liguang | env->regs[R_EDX] = (uint32_t)(val >> 32);
|
240 | f7b2429f | Blue Swirl | } |
241 | f7b2429f | Blue Swirl | |
242 | 4a7443be | Blue Swirl | void helper_rdtscp(CPUX86State *env)
|
243 | f7b2429f | Blue Swirl | { |
244 | 4a7443be | Blue Swirl | helper_rdtsc(env); |
245 | a4165610 | liguang | env->regs[R_ECX] = (uint32_t)(env->tsc_aux); |
246 | f7b2429f | Blue Swirl | } |
247 | f7b2429f | Blue Swirl | |
248 | 4a7443be | Blue Swirl | void helper_rdpmc(CPUX86State *env)
|
249 | f7b2429f | Blue Swirl | { |
250 | f7b2429f | Blue Swirl | if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { |
251 | f7b2429f | Blue Swirl | raise_exception(env, EXCP0D_GPF); |
252 | f7b2429f | Blue Swirl | } |
253 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0);
|
254 | f7b2429f | Blue Swirl | |
255 | f7b2429f | Blue Swirl | /* currently unimplemented */
|
256 | f7b2429f | Blue Swirl | qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
|
257 | f7b2429f | Blue Swirl | raise_exception_err(env, EXCP06_ILLOP, 0);
|
258 | f7b2429f | Blue Swirl | } |
259 | f7b2429f | Blue Swirl | |
260 | f7b2429f | Blue Swirl | #if defined(CONFIG_USER_ONLY)
|
261 | 4a7443be | Blue Swirl | void helper_wrmsr(CPUX86State *env)
|
262 | f7b2429f | Blue Swirl | { |
263 | f7b2429f | Blue Swirl | } |
264 | f7b2429f | Blue Swirl | |
265 | 4a7443be | Blue Swirl | void helper_rdmsr(CPUX86State *env)
|
266 | f7b2429f | Blue Swirl | { |
267 | f7b2429f | Blue Swirl | } |
268 | f7b2429f | Blue Swirl | #else
|
269 | 4a7443be | Blue Swirl | void helper_wrmsr(CPUX86State *env)
|
270 | f7b2429f | Blue Swirl | { |
271 | f7b2429f | Blue Swirl | uint64_t val; |
272 | f7b2429f | Blue Swirl | |
273 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1);
|
274 | f7b2429f | Blue Swirl | |
275 | 90a2541b | liguang | val = ((uint32_t)env->regs[R_EAX]) | |
276 | 90a2541b | liguang | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
|
277 | f7b2429f | Blue Swirl | |
278 | a4165610 | liguang | switch ((uint32_t)env->regs[R_ECX]) {
|
279 | f7b2429f | Blue Swirl | case MSR_IA32_SYSENTER_CS:
|
280 | f7b2429f | Blue Swirl | env->sysenter_cs = val & 0xffff;
|
281 | f7b2429f | Blue Swirl | break;
|
282 | f7b2429f | Blue Swirl | case MSR_IA32_SYSENTER_ESP:
|
283 | f7b2429f | Blue Swirl | env->sysenter_esp = val; |
284 | f7b2429f | Blue Swirl | break;
|
285 | f7b2429f | Blue Swirl | case MSR_IA32_SYSENTER_EIP:
|
286 | f7b2429f | Blue Swirl | env->sysenter_eip = val; |
287 | f7b2429f | Blue Swirl | break;
|
288 | f7b2429f | Blue Swirl | case MSR_IA32_APICBASE:
|
289 | f7b2429f | Blue Swirl | cpu_set_apic_base(env->apic_state, val); |
290 | f7b2429f | Blue Swirl | break;
|
291 | f7b2429f | Blue Swirl | case MSR_EFER:
|
292 | f7b2429f | Blue Swirl | { |
293 | f7b2429f | Blue Swirl | uint64_t update_mask; |
294 | f7b2429f | Blue Swirl | |
295 | f7b2429f | Blue Swirl | update_mask = 0;
|
296 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
|
297 | f7b2429f | Blue Swirl | update_mask |= MSR_EFER_SCE; |
298 | f7b2429f | Blue Swirl | } |
299 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
|
300 | f7b2429f | Blue Swirl | update_mask |= MSR_EFER_LME; |
301 | f7b2429f | Blue Swirl | } |
302 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
|
303 | f7b2429f | Blue Swirl | update_mask |= MSR_EFER_FFXSR; |
304 | f7b2429f | Blue Swirl | } |
305 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
|
306 | f7b2429f | Blue Swirl | update_mask |= MSR_EFER_NXE; |
307 | f7b2429f | Blue Swirl | } |
308 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
|
309 | f7b2429f | Blue Swirl | update_mask |= MSR_EFER_SVME; |
310 | f7b2429f | Blue Swirl | } |
311 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
|
312 | f7b2429f | Blue Swirl | update_mask |= MSR_EFER_FFXSR; |
313 | f7b2429f | Blue Swirl | } |
314 | f7b2429f | Blue Swirl | cpu_load_efer(env, (env->efer & ~update_mask) | |
315 | f7b2429f | Blue Swirl | (val & update_mask)); |
316 | f7b2429f | Blue Swirl | } |
317 | f7b2429f | Blue Swirl | break;
|
318 | f7b2429f | Blue Swirl | case MSR_STAR:
|
319 | f7b2429f | Blue Swirl | env->star = val; |
320 | f7b2429f | Blue Swirl | break;
|
321 | f7b2429f | Blue Swirl | case MSR_PAT:
|
322 | f7b2429f | Blue Swirl | env->pat = val; |
323 | f7b2429f | Blue Swirl | break;
|
324 | f7b2429f | Blue Swirl | case MSR_VM_HSAVE_PA:
|
325 | f7b2429f | Blue Swirl | env->vm_hsave = val; |
326 | f7b2429f | Blue Swirl | break;
|
327 | f7b2429f | Blue Swirl | #ifdef TARGET_X86_64
|
328 | f7b2429f | Blue Swirl | case MSR_LSTAR:
|
329 | f7b2429f | Blue Swirl | env->lstar = val; |
330 | f7b2429f | Blue Swirl | break;
|
331 | f7b2429f | Blue Swirl | case MSR_CSTAR:
|
332 | f7b2429f | Blue Swirl | env->cstar = val; |
333 | f7b2429f | Blue Swirl | break;
|
334 | f7b2429f | Blue Swirl | case MSR_FMASK:
|
335 | f7b2429f | Blue Swirl | env->fmask = val; |
336 | f7b2429f | Blue Swirl | break;
|
337 | f7b2429f | Blue Swirl | case MSR_FSBASE:
|
338 | f7b2429f | Blue Swirl | env->segs[R_FS].base = val; |
339 | f7b2429f | Blue Swirl | break;
|
340 | f7b2429f | Blue Swirl | case MSR_GSBASE:
|
341 | f7b2429f | Blue Swirl | env->segs[R_GS].base = val; |
342 | f7b2429f | Blue Swirl | break;
|
343 | f7b2429f | Blue Swirl | case MSR_KERNELGSBASE:
|
344 | f7b2429f | Blue Swirl | env->kernelgsbase = val; |
345 | f7b2429f | Blue Swirl | break;
|
346 | f7b2429f | Blue Swirl | #endif
|
347 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(0): |
348 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(1): |
349 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(2): |
350 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(3): |
351 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(4): |
352 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(5): |
353 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(6): |
354 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(7): |
355 | 90a2541b | liguang | env->mtrr_var[((uint32_t)env->regs[R_ECX] - |
356 | 90a2541b | liguang | MSR_MTRRphysBase(0)) / 2].base = val; |
357 | f7b2429f | Blue Swirl | break;
|
358 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(0): |
359 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(1): |
360 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(2): |
361 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(3): |
362 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(4): |
363 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(5): |
364 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(6): |
365 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(7): |
366 | 90a2541b | liguang | env->mtrr_var[((uint32_t)env->regs[R_ECX] - |
367 | 90a2541b | liguang | MSR_MTRRphysMask(0)) / 2].mask = val; |
368 | f7b2429f | Blue Swirl | break;
|
369 | f7b2429f | Blue Swirl | case MSR_MTRRfix64K_00000:
|
370 | 90a2541b | liguang | env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - |
371 | 90a2541b | liguang | MSR_MTRRfix64K_00000] = val; |
372 | f7b2429f | Blue Swirl | break;
|
373 | f7b2429f | Blue Swirl | case MSR_MTRRfix16K_80000:
|
374 | f7b2429f | Blue Swirl | case MSR_MTRRfix16K_A0000:
|
375 | 90a2541b | liguang | env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - |
376 | 90a2541b | liguang | MSR_MTRRfix16K_80000 + 1] = val;
|
377 | f7b2429f | Blue Swirl | break;
|
378 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_C0000:
|
379 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_C8000:
|
380 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_D0000:
|
381 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_D8000:
|
382 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_E0000:
|
383 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_E8000:
|
384 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_F0000:
|
385 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_F8000:
|
386 | 90a2541b | liguang | env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - |
387 | 90a2541b | liguang | MSR_MTRRfix4K_C0000 + 3] = val;
|
388 | f7b2429f | Blue Swirl | break;
|
389 | f7b2429f | Blue Swirl | case MSR_MTRRdefType:
|
390 | f7b2429f | Blue Swirl | env->mtrr_deftype = val; |
391 | f7b2429f | Blue Swirl | break;
|
392 | f7b2429f | Blue Swirl | case MSR_MCG_STATUS:
|
393 | f7b2429f | Blue Swirl | env->mcg_status = val; |
394 | f7b2429f | Blue Swirl | break;
|
395 | f7b2429f | Blue Swirl | case MSR_MCG_CTL:
|
396 | f7b2429f | Blue Swirl | if ((env->mcg_cap & MCG_CTL_P)
|
397 | f7b2429f | Blue Swirl | && (val == 0 || val == ~(uint64_t)0)) { |
398 | f7b2429f | Blue Swirl | env->mcg_ctl = val; |
399 | f7b2429f | Blue Swirl | } |
400 | f7b2429f | Blue Swirl | break;
|
401 | f7b2429f | Blue Swirl | case MSR_TSC_AUX:
|
402 | f7b2429f | Blue Swirl | env->tsc_aux = val; |
403 | f7b2429f | Blue Swirl | break;
|
404 | f7b2429f | Blue Swirl | case MSR_IA32_MISC_ENABLE:
|
405 | f7b2429f | Blue Swirl | env->msr_ia32_misc_enable = val; |
406 | f7b2429f | Blue Swirl | break;
|
407 | f7b2429f | Blue Swirl | default:
|
408 | a4165610 | liguang | if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
|
409 | 90a2541b | liguang | && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + |
410 | 90a2541b | liguang | (4 * env->mcg_cap & 0xff)) { |
411 | a4165610 | liguang | uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; |
412 | f7b2429f | Blue Swirl | if ((offset & 0x3) != 0 |
413 | f7b2429f | Blue Swirl | || (val == 0 || val == ~(uint64_t)0)) { |
414 | f7b2429f | Blue Swirl | env->mce_banks[offset] = val; |
415 | f7b2429f | Blue Swirl | } |
416 | f7b2429f | Blue Swirl | break;
|
417 | f7b2429f | Blue Swirl | } |
418 | f7b2429f | Blue Swirl | /* XXX: exception? */
|
419 | f7b2429f | Blue Swirl | break;
|
420 | f7b2429f | Blue Swirl | } |
421 | f7b2429f | Blue Swirl | } |
422 | f7b2429f | Blue Swirl | |
423 | 4a7443be | Blue Swirl | void helper_rdmsr(CPUX86State *env)
|
424 | f7b2429f | Blue Swirl | { |
425 | f7b2429f | Blue Swirl | uint64_t val; |
426 | f7b2429f | Blue Swirl | |
427 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0);
|
428 | f7b2429f | Blue Swirl | |
429 | a4165610 | liguang | switch ((uint32_t)env->regs[R_ECX]) {
|
430 | f7b2429f | Blue Swirl | case MSR_IA32_SYSENTER_CS:
|
431 | f7b2429f | Blue Swirl | val = env->sysenter_cs; |
432 | f7b2429f | Blue Swirl | break;
|
433 | f7b2429f | Blue Swirl | case MSR_IA32_SYSENTER_ESP:
|
434 | f7b2429f | Blue Swirl | val = env->sysenter_esp; |
435 | f7b2429f | Blue Swirl | break;
|
436 | f7b2429f | Blue Swirl | case MSR_IA32_SYSENTER_EIP:
|
437 | f7b2429f | Blue Swirl | val = env->sysenter_eip; |
438 | f7b2429f | Blue Swirl | break;
|
439 | f7b2429f | Blue Swirl | case MSR_IA32_APICBASE:
|
440 | f7b2429f | Blue Swirl | val = cpu_get_apic_base(env->apic_state); |
441 | f7b2429f | Blue Swirl | break;
|
442 | f7b2429f | Blue Swirl | case MSR_EFER:
|
443 | f7b2429f | Blue Swirl | val = env->efer; |
444 | f7b2429f | Blue Swirl | break;
|
445 | f7b2429f | Blue Swirl | case MSR_STAR:
|
446 | f7b2429f | Blue Swirl | val = env->star; |
447 | f7b2429f | Blue Swirl | break;
|
448 | f7b2429f | Blue Swirl | case MSR_PAT:
|
449 | f7b2429f | Blue Swirl | val = env->pat; |
450 | f7b2429f | Blue Swirl | break;
|
451 | f7b2429f | Blue Swirl | case MSR_VM_HSAVE_PA:
|
452 | f7b2429f | Blue Swirl | val = env->vm_hsave; |
453 | f7b2429f | Blue Swirl | break;
|
454 | f7b2429f | Blue Swirl | case MSR_IA32_PERF_STATUS:
|
455 | f7b2429f | Blue Swirl | /* tsc_increment_by_tick */
|
456 | f7b2429f | Blue Swirl | val = 1000ULL;
|
457 | f7b2429f | Blue Swirl | /* CPU multiplier */
|
458 | f7b2429f | Blue Swirl | val |= (((uint64_t)4ULL) << 40); |
459 | f7b2429f | Blue Swirl | break;
|
460 | f7b2429f | Blue Swirl | #ifdef TARGET_X86_64
|
461 | f7b2429f | Blue Swirl | case MSR_LSTAR:
|
462 | f7b2429f | Blue Swirl | val = env->lstar; |
463 | f7b2429f | Blue Swirl | break;
|
464 | f7b2429f | Blue Swirl | case MSR_CSTAR:
|
465 | f7b2429f | Blue Swirl | val = env->cstar; |
466 | f7b2429f | Blue Swirl | break;
|
467 | f7b2429f | Blue Swirl | case MSR_FMASK:
|
468 | f7b2429f | Blue Swirl | val = env->fmask; |
469 | f7b2429f | Blue Swirl | break;
|
470 | f7b2429f | Blue Swirl | case MSR_FSBASE:
|
471 | f7b2429f | Blue Swirl | val = env->segs[R_FS].base; |
472 | f7b2429f | Blue Swirl | break;
|
473 | f7b2429f | Blue Swirl | case MSR_GSBASE:
|
474 | f7b2429f | Blue Swirl | val = env->segs[R_GS].base; |
475 | f7b2429f | Blue Swirl | break;
|
476 | f7b2429f | Blue Swirl | case MSR_KERNELGSBASE:
|
477 | f7b2429f | Blue Swirl | val = env->kernelgsbase; |
478 | f7b2429f | Blue Swirl | break;
|
479 | f7b2429f | Blue Swirl | case MSR_TSC_AUX:
|
480 | f7b2429f | Blue Swirl | val = env->tsc_aux; |
481 | f7b2429f | Blue Swirl | break;
|
482 | f7b2429f | Blue Swirl | #endif
|
483 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(0): |
484 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(1): |
485 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(2): |
486 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(3): |
487 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(4): |
488 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(5): |
489 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(6): |
490 | f7b2429f | Blue Swirl | case MSR_MTRRphysBase(7): |
491 | 90a2541b | liguang | val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - |
492 | 90a2541b | liguang | MSR_MTRRphysBase(0)) / 2].base; |
493 | f7b2429f | Blue Swirl | break;
|
494 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(0): |
495 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(1): |
496 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(2): |
497 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(3): |
498 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(4): |
499 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(5): |
500 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(6): |
501 | f7b2429f | Blue Swirl | case MSR_MTRRphysMask(7): |
502 | 90a2541b | liguang | val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - |
503 | 90a2541b | liguang | MSR_MTRRphysMask(0)) / 2].mask; |
504 | f7b2429f | Blue Swirl | break;
|
505 | f7b2429f | Blue Swirl | case MSR_MTRRfix64K_00000:
|
506 | f7b2429f | Blue Swirl | val = env->mtrr_fixed[0];
|
507 | f7b2429f | Blue Swirl | break;
|
508 | f7b2429f | Blue Swirl | case MSR_MTRRfix16K_80000:
|
509 | f7b2429f | Blue Swirl | case MSR_MTRRfix16K_A0000:
|
510 | 90a2541b | liguang | val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - |
511 | 90a2541b | liguang | MSR_MTRRfix16K_80000 + 1];
|
512 | f7b2429f | Blue Swirl | break;
|
513 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_C0000:
|
514 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_C8000:
|
515 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_D0000:
|
516 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_D8000:
|
517 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_E0000:
|
518 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_E8000:
|
519 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_F0000:
|
520 | f7b2429f | Blue Swirl | case MSR_MTRRfix4K_F8000:
|
521 | 90a2541b | liguang | val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - |
522 | 90a2541b | liguang | MSR_MTRRfix4K_C0000 + 3];
|
523 | f7b2429f | Blue Swirl | break;
|
524 | f7b2429f | Blue Swirl | case MSR_MTRRdefType:
|
525 | f7b2429f | Blue Swirl | val = env->mtrr_deftype; |
526 | f7b2429f | Blue Swirl | break;
|
527 | f7b2429f | Blue Swirl | case MSR_MTRRcap:
|
528 | 0514ef2f | Eduardo Habkost | if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
|
529 | f7b2429f | Blue Swirl | val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | |
530 | f7b2429f | Blue Swirl | MSR_MTRRcap_WC_SUPPORTED; |
531 | f7b2429f | Blue Swirl | } else {
|
532 | f7b2429f | Blue Swirl | /* XXX: exception? */
|
533 | f7b2429f | Blue Swirl | val = 0;
|
534 | f7b2429f | Blue Swirl | } |
535 | f7b2429f | Blue Swirl | break;
|
536 | f7b2429f | Blue Swirl | case MSR_MCG_CAP:
|
537 | f7b2429f | Blue Swirl | val = env->mcg_cap; |
538 | f7b2429f | Blue Swirl | break;
|
539 | f7b2429f | Blue Swirl | case MSR_MCG_CTL:
|
540 | f7b2429f | Blue Swirl | if (env->mcg_cap & MCG_CTL_P) {
|
541 | f7b2429f | Blue Swirl | val = env->mcg_ctl; |
542 | f7b2429f | Blue Swirl | } else {
|
543 | f7b2429f | Blue Swirl | val = 0;
|
544 | f7b2429f | Blue Swirl | } |
545 | f7b2429f | Blue Swirl | break;
|
546 | f7b2429f | Blue Swirl | case MSR_MCG_STATUS:
|
547 | f7b2429f | Blue Swirl | val = env->mcg_status; |
548 | f7b2429f | Blue Swirl | break;
|
549 | f7b2429f | Blue Swirl | case MSR_IA32_MISC_ENABLE:
|
550 | f7b2429f | Blue Swirl | val = env->msr_ia32_misc_enable; |
551 | f7b2429f | Blue Swirl | break;
|
552 | f7b2429f | Blue Swirl | default:
|
553 | a4165610 | liguang | if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
|
554 | 90a2541b | liguang | && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + |
555 | 90a2541b | liguang | (4 * env->mcg_cap & 0xff)) { |
556 | a4165610 | liguang | uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; |
557 | f7b2429f | Blue Swirl | val = env->mce_banks[offset]; |
558 | f7b2429f | Blue Swirl | break;
|
559 | f7b2429f | Blue Swirl | } |
560 | f7b2429f | Blue Swirl | /* XXX: exception? */
|
561 | f7b2429f | Blue Swirl | val = 0;
|
562 | f7b2429f | Blue Swirl | break;
|
563 | f7b2429f | Blue Swirl | } |
564 | 4b34e3ad | liguang | env->regs[R_EAX] = (uint32_t)(val); |
565 | 00f5e6f2 | liguang | env->regs[R_EDX] = (uint32_t)(val >> 32);
|
566 | f7b2429f | Blue Swirl | } |
567 | f7b2429f | Blue Swirl | #endif
|
568 | f7b2429f | Blue Swirl | |
569 | 259186a7 | Andreas Färber | static void do_hlt(X86CPU *cpu) |
570 | f7b2429f | Blue Swirl | { |
571 | 259186a7 | Andreas Färber | CPUState *cs = CPU(cpu); |
572 | 259186a7 | Andreas Färber | CPUX86State *env = &cpu->env; |
573 | 259186a7 | Andreas Färber | |
574 | f7b2429f | Blue Swirl | env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
|
575 | 259186a7 | Andreas Färber | cs->halted = 1;
|
576 | f7b2429f | Blue Swirl | env->exception_index = EXCP_HLT; |
577 | f7b2429f | Blue Swirl | cpu_loop_exit(env); |
578 | f7b2429f | Blue Swirl | } |
579 | f7b2429f | Blue Swirl | |
580 | 4a7443be | Blue Swirl | void helper_hlt(CPUX86State *env, int next_eip_addend) |
581 | f7b2429f | Blue Swirl | { |
582 | 259186a7 | Andreas Färber | X86CPU *cpu = x86_env_get_cpu(env); |
583 | 259186a7 | Andreas Färber | |
584 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
|
585 | a78d0eab | liguang | env->eip += next_eip_addend; |
586 | f7b2429f | Blue Swirl | |
587 | 259186a7 | Andreas Färber | do_hlt(cpu); |
588 | f7b2429f | Blue Swirl | } |
589 | f7b2429f | Blue Swirl | |
590 | 4a7443be | Blue Swirl | void helper_monitor(CPUX86State *env, target_ulong ptr)
|
591 | f7b2429f | Blue Swirl | { |
592 | a4165610 | liguang | if ((uint32_t)env->regs[R_ECX] != 0) { |
593 | f7b2429f | Blue Swirl | raise_exception(env, EXCP0D_GPF); |
594 | f7b2429f | Blue Swirl | } |
595 | f7b2429f | Blue Swirl | /* XXX: store address? */
|
596 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0);
|
597 | f7b2429f | Blue Swirl | } |
598 | f7b2429f | Blue Swirl | |
599 | 4a7443be | Blue Swirl | void helper_mwait(CPUX86State *env, int next_eip_addend) |
600 | f7b2429f | Blue Swirl | { |
601 | 259186a7 | Andreas Färber | CPUState *cs; |
602 | 259186a7 | Andreas Färber | X86CPU *cpu; |
603 | 55e5c285 | Andreas Färber | |
604 | a4165610 | liguang | if ((uint32_t)env->regs[R_ECX] != 0) { |
605 | f7b2429f | Blue Swirl | raise_exception(env, EXCP0D_GPF); |
606 | f7b2429f | Blue Swirl | } |
607 | f7b2429f | Blue Swirl | cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
|
608 | a78d0eab | liguang | env->eip += next_eip_addend; |
609 | f7b2429f | Blue Swirl | |
610 | 259186a7 | Andreas Färber | cpu = x86_env_get_cpu(env); |
611 | 259186a7 | Andreas Färber | cs = CPU(cpu); |
612 | f7b2429f | Blue Swirl | /* XXX: not complete but not completely erroneous */
|
613 | 182735ef | Andreas Färber | if (cs->cpu_index != 0 || cs->next_cpu != NULL) { |
614 | f7b2429f | Blue Swirl | /* more than one CPU: do not sleep because another CPU may
|
615 | f7b2429f | Blue Swirl | wake this one */
|
616 | f7b2429f | Blue Swirl | } else {
|
617 | 259186a7 | Andreas Färber | do_hlt(cpu); |
618 | f7b2429f | Blue Swirl | } |
619 | f7b2429f | Blue Swirl | } |
620 | f7b2429f | Blue Swirl | |
621 | 4a7443be | Blue Swirl | void helper_debug(CPUX86State *env)
|
622 | f7b2429f | Blue Swirl | { |
623 | f7b2429f | Blue Swirl | env->exception_index = EXCP_DEBUG; |
624 | f7b2429f | Blue Swirl | cpu_loop_exit(env); |
625 | f7b2429f | Blue Swirl | } |