xref: /openbmc/qemu/target/i386/tcg/sysemu/misc_helper.c (revision 9e7449901d33ed0ddc0c432b15896019e3aec4f1)
1  /*
2   *  x86 misc helpers - sysemu code
3   *
4   *  Copyright (c) 2003 Fabrice Bellard
5   *
6   * This library is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU Lesser General Public
8   * License as published by the Free Software Foundation; either
9   * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  #include "qemu/osdep.h"
21  #include "qemu/main-loop.h"
22  #include "cpu.h"
23  #include "exec/helper-proto.h"
24  #include "exec/cpu_ldst.h"
25  #include "exec/address-spaces.h"
26  #include "tcg/helper-tcg.h"
27  
28  void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
29  {
30      address_space_stb(&address_space_io, port, data,
31                        cpu_get_mem_attrs(env), NULL);
32  }
33  
34  target_ulong helper_inb(CPUX86State *env, uint32_t port)
35  {
36      return address_space_ldub(&address_space_io, port,
37                                cpu_get_mem_attrs(env), NULL);
38  }
39  
40  void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
41  {
42      address_space_stw(&address_space_io, port, data,
43                        cpu_get_mem_attrs(env), NULL);
44  }
45  
46  target_ulong helper_inw(CPUX86State *env, uint32_t port)
47  {
48      return address_space_lduw(&address_space_io, port,
49                                cpu_get_mem_attrs(env), NULL);
50  }
51  
52  void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
53  {
54      address_space_stl(&address_space_io, port, data,
55                        cpu_get_mem_attrs(env), NULL);
56  }
57  
58  target_ulong helper_inl(CPUX86State *env, uint32_t port)
59  {
60      return address_space_ldl(&address_space_io, port,
61                               cpu_get_mem_attrs(env), NULL);
62  }
63  
64  target_ulong helper_read_crN(CPUX86State *env, int reg)
65  {
66      target_ulong val;
67  
68      switch (reg) {
69      default:
70          val = env->cr[reg];
71          break;
72      case 8:
73          if (!(env->hflags2 & HF2_VINTR_MASK)) {
74              val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
75          } else {
76              val = env->v_tpr;
77          }
78          break;
79      }
80      return val;
81  }
82  
83  void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
84  {
85      switch (reg) {
86      case 0:
87          cpu_x86_update_cr0(env, t0);
88          break;
89      case 3:
90          cpu_x86_update_cr3(env, t0);
91          break;
92      case 4:
93          if (((t0 ^ env->cr[4]) & CR4_LA57_MASK) &&
94              (env->hflags & HF_CS64_MASK)) {
95              raise_exception_ra(env, EXCP0D_GPF, GETPC());
96          }
97          cpu_x86_update_cr4(env, t0);
98          break;
99      case 8:
100          if (!(env->hflags2 & HF2_VINTR_MASK)) {
101              qemu_mutex_lock_iothread();
102              cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0);
103              qemu_mutex_unlock_iothread();
104          }
105          env->v_tpr = t0 & 0x0f;
106          break;
107      default:
108          env->cr[reg] = t0;
109          break;
110      }
111  }
112  
113  void helper_wrmsr(CPUX86State *env)
114  {
115      uint64_t val;
116      CPUState *cs = env_cpu(env);
117  
118      cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
119  
120      val = ((uint32_t)env->regs[R_EAX]) |
121          ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
122  
123      switch ((uint32_t)env->regs[R_ECX]) {
124      case MSR_IA32_SYSENTER_CS:
125          env->sysenter_cs = val & 0xffff;
126          break;
127      case MSR_IA32_SYSENTER_ESP:
128          env->sysenter_esp = val;
129          break;
130      case MSR_IA32_SYSENTER_EIP:
131          env->sysenter_eip = val;
132          break;
133      case MSR_IA32_APICBASE:
134          cpu_set_apic_base(env_archcpu(env)->apic_state, val);
135          break;
136      case MSR_EFER:
137          {
138              uint64_t update_mask;
139  
140              update_mask = 0;
141              if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
142                  update_mask |= MSR_EFER_SCE;
143              }
144              if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
145                  update_mask |= MSR_EFER_LME;
146              }
147              if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
148                  update_mask |= MSR_EFER_FFXSR;
149              }
150              if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
151                  update_mask |= MSR_EFER_NXE;
152              }
153              if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
154                  update_mask |= MSR_EFER_SVME;
155              }
156              if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
157                  update_mask |= MSR_EFER_FFXSR;
158              }
159              cpu_load_efer(env, (env->efer & ~update_mask) |
160                            (val & update_mask));
161          }
162          break;
163      case MSR_STAR:
164          env->star = val;
165          break;
166      case MSR_PAT:
167          env->pat = val;
168          break;
169      case MSR_IA32_PKRS:
170          if (val & 0xFFFFFFFF00000000ull) {
171              goto error;
172          }
173          env->pkrs = val;
174          tlb_flush(cs);
175          break;
176      case MSR_VM_HSAVE_PA:
177          env->vm_hsave = val;
178          break;
179  #ifdef TARGET_X86_64
180      case MSR_LSTAR:
181          env->lstar = val;
182          break;
183      case MSR_CSTAR:
184          env->cstar = val;
185          break;
186      case MSR_FMASK:
187          env->fmask = val;
188          break;
189      case MSR_FSBASE:
190          env->segs[R_FS].base = val;
191          break;
192      case MSR_GSBASE:
193          env->segs[R_GS].base = val;
194          break;
195      case MSR_KERNELGSBASE:
196          env->kernelgsbase = val;
197          break;
198  #endif
199      case MSR_MTRRphysBase(0):
200      case MSR_MTRRphysBase(1):
201      case MSR_MTRRphysBase(2):
202      case MSR_MTRRphysBase(3):
203      case MSR_MTRRphysBase(4):
204      case MSR_MTRRphysBase(5):
205      case MSR_MTRRphysBase(6):
206      case MSR_MTRRphysBase(7):
207          env->mtrr_var[((uint32_t)env->regs[R_ECX] -
208                         MSR_MTRRphysBase(0)) / 2].base = val;
209          break;
210      case MSR_MTRRphysMask(0):
211      case MSR_MTRRphysMask(1):
212      case MSR_MTRRphysMask(2):
213      case MSR_MTRRphysMask(3):
214      case MSR_MTRRphysMask(4):
215      case MSR_MTRRphysMask(5):
216      case MSR_MTRRphysMask(6):
217      case MSR_MTRRphysMask(7):
218          env->mtrr_var[((uint32_t)env->regs[R_ECX] -
219                         MSR_MTRRphysMask(0)) / 2].mask = val;
220          break;
221      case MSR_MTRRfix64K_00000:
222          env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
223                          MSR_MTRRfix64K_00000] = val;
224          break;
225      case MSR_MTRRfix16K_80000:
226      case MSR_MTRRfix16K_A0000:
227          env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
228                          MSR_MTRRfix16K_80000 + 1] = val;
229          break;
230      case MSR_MTRRfix4K_C0000:
231      case MSR_MTRRfix4K_C8000:
232      case MSR_MTRRfix4K_D0000:
233      case MSR_MTRRfix4K_D8000:
234      case MSR_MTRRfix4K_E0000:
235      case MSR_MTRRfix4K_E8000:
236      case MSR_MTRRfix4K_F0000:
237      case MSR_MTRRfix4K_F8000:
238          env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
239                          MSR_MTRRfix4K_C0000 + 3] = val;
240          break;
241      case MSR_MTRRdefType:
242          env->mtrr_deftype = val;
243          break;
244      case MSR_MCG_STATUS:
245          env->mcg_status = val;
246          break;
247      case MSR_MCG_CTL:
248          if ((env->mcg_cap & MCG_CTL_P)
249              && (val == 0 || val == ~(uint64_t)0)) {
250              env->mcg_ctl = val;
251          }
252          break;
253      case MSR_TSC_AUX:
254          env->tsc_aux = val;
255          break;
256      case MSR_IA32_MISC_ENABLE:
257          env->msr_ia32_misc_enable = val;
258          break;
259      case MSR_IA32_BNDCFGS:
260          /* FIXME: #GP if reserved bits are set.  */
261          /* FIXME: Extend highest implemented bit of linear address.  */
262          env->msr_bndcfgs = val;
263          cpu_sync_bndcs_hflags(env);
264          break;
265      default:
266          if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
267              && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
268              (4 * env->mcg_cap & 0xff)) {
269              uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
270              if ((offset & 0x3) != 0
271                  || (val == 0 || val == ~(uint64_t)0)) {
272                  env->mce_banks[offset] = val;
273              }
274              break;
275          }
276          /* XXX: exception? */
277          break;
278      }
279      return;
280  error:
281      raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
282  }
283  
284  void helper_rdmsr(CPUX86State *env)
285  {
286      X86CPU *x86_cpu = env_archcpu(env);
287      uint64_t val;
288  
289      cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
290  
291      switch ((uint32_t)env->regs[R_ECX]) {
292      case MSR_IA32_SYSENTER_CS:
293          val = env->sysenter_cs;
294          break;
295      case MSR_IA32_SYSENTER_ESP:
296          val = env->sysenter_esp;
297          break;
298      case MSR_IA32_SYSENTER_EIP:
299          val = env->sysenter_eip;
300          break;
301      case MSR_IA32_APICBASE:
302          val = cpu_get_apic_base(env_archcpu(env)->apic_state);
303          break;
304      case MSR_EFER:
305          val = env->efer;
306          break;
307      case MSR_STAR:
308          val = env->star;
309          break;
310      case MSR_PAT:
311          val = env->pat;
312          break;
313      case MSR_IA32_PKRS:
314          val = env->pkrs;
315          break;
316      case MSR_VM_HSAVE_PA:
317          val = env->vm_hsave;
318          break;
319      case MSR_IA32_PERF_STATUS:
320          /* tsc_increment_by_tick */
321          val = 1000ULL;
322          /* CPU multiplier */
323          val |= (((uint64_t)4ULL) << 40);
324          break;
325  #ifdef TARGET_X86_64
326      case MSR_LSTAR:
327          val = env->lstar;
328          break;
329      case MSR_CSTAR:
330          val = env->cstar;
331          break;
332      case MSR_FMASK:
333          val = env->fmask;
334          break;
335      case MSR_FSBASE:
336          val = env->segs[R_FS].base;
337          break;
338      case MSR_GSBASE:
339          val = env->segs[R_GS].base;
340          break;
341      case MSR_KERNELGSBASE:
342          val = env->kernelgsbase;
343          break;
344      case MSR_TSC_AUX:
345          val = env->tsc_aux;
346          break;
347  #endif
348      case MSR_SMI_COUNT:
349          val = env->msr_smi_count;
350          break;
351      case MSR_MTRRphysBase(0):
352      case MSR_MTRRphysBase(1):
353      case MSR_MTRRphysBase(2):
354      case MSR_MTRRphysBase(3):
355      case MSR_MTRRphysBase(4):
356      case MSR_MTRRphysBase(5):
357      case MSR_MTRRphysBase(6):
358      case MSR_MTRRphysBase(7):
359          val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
360                               MSR_MTRRphysBase(0)) / 2].base;
361          break;
362      case MSR_MTRRphysMask(0):
363      case MSR_MTRRphysMask(1):
364      case MSR_MTRRphysMask(2):
365      case MSR_MTRRphysMask(3):
366      case MSR_MTRRphysMask(4):
367      case MSR_MTRRphysMask(5):
368      case MSR_MTRRphysMask(6):
369      case MSR_MTRRphysMask(7):
370          val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
371                               MSR_MTRRphysMask(0)) / 2].mask;
372          break;
373      case MSR_MTRRfix64K_00000:
374          val = env->mtrr_fixed[0];
375          break;
376      case MSR_MTRRfix16K_80000:
377      case MSR_MTRRfix16K_A0000:
378          val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
379                                MSR_MTRRfix16K_80000 + 1];
380          break;
381      case MSR_MTRRfix4K_C0000:
382      case MSR_MTRRfix4K_C8000:
383      case MSR_MTRRfix4K_D0000:
384      case MSR_MTRRfix4K_D8000:
385      case MSR_MTRRfix4K_E0000:
386      case MSR_MTRRfix4K_E8000:
387      case MSR_MTRRfix4K_F0000:
388      case MSR_MTRRfix4K_F8000:
389          val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
390                                MSR_MTRRfix4K_C0000 + 3];
391          break;
392      case MSR_MTRRdefType:
393          val = env->mtrr_deftype;
394          break;
395      case MSR_MTRRcap:
396          if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
397              val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
398                  MSR_MTRRcap_WC_SUPPORTED;
399          } else {
400              /* XXX: exception? */
401              val = 0;
402          }
403          break;
404      case MSR_MCG_CAP:
405          val = env->mcg_cap;
406          break;
407      case MSR_MCG_CTL:
408          if (env->mcg_cap & MCG_CTL_P) {
409              val = env->mcg_ctl;
410          } else {
411              val = 0;
412          }
413          break;
414      case MSR_MCG_STATUS:
415          val = env->mcg_status;
416          break;
417      case MSR_IA32_MISC_ENABLE:
418          val = env->msr_ia32_misc_enable;
419          break;
420      case MSR_IA32_BNDCFGS:
421          val = env->msr_bndcfgs;
422          break;
423       case MSR_IA32_UCODE_REV:
424          val = x86_cpu->ucode_rev;
425          break;
426      default:
427          if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
428              && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
429              (4 * env->mcg_cap & 0xff)) {
430              uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
431              val = env->mce_banks[offset];
432              break;
433          }
434          /* XXX: exception? */
435          val = 0;
436          break;
437      }
438      env->regs[R_EAX] = (uint32_t)(val);
439      env->regs[R_EDX] = (uint32_t)(val >> 32);
440  }
441  
442  void helper_flush_page(CPUX86State *env, target_ulong addr)
443  {
444      tlb_flush_page(env_cpu(env), addr);
445  }
446  
447  static void QEMU_NORETURN do_hlt(CPUX86State *env)
448  {
449      CPUState *cs = env_cpu(env);
450  
451      env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
452      cs->halted = 1;
453      cs->exception_index = EXCP_HLT;
454      cpu_loop_exit(cs);
455  }
456  
457  void QEMU_NORETURN helper_hlt(CPUX86State *env, int next_eip_addend)
458  {
459      cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
460      env->eip += next_eip_addend;
461  
462      do_hlt(env);
463  }
464  
465  void helper_monitor(CPUX86State *env, target_ulong ptr)
466  {
467      if ((uint32_t)env->regs[R_ECX] != 0) {
468          raise_exception_ra(env, EXCP0D_GPF, GETPC());
469      }
470      /* XXX: store address? */
471      cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
472  }
473  
474  void QEMU_NORETURN helper_mwait(CPUX86State *env, int next_eip_addend)
475  {
476      CPUState *cs = env_cpu(env);
477  
478      if ((uint32_t)env->regs[R_ECX] != 0) {
479          raise_exception_ra(env, EXCP0D_GPF, GETPC());
480      }
481      cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
482      env->eip += next_eip_addend;
483  
484      /* XXX: not complete but not completely erroneous */
485      if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
486          do_pause(env);
487      } else {
488          do_hlt(env);
489      }
490  }
491