xref: /openbmc/qemu/target/i386/tcg/misc_helper.c (revision 38e0b790)
1 /*
2  *  x86 misc helpers
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/exec-all.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/address-spaces.h"
27 #include "helper-tcg.h"
28 
29 /*
30  * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
31  * after generating a call to a helper that uses this.
32  */
33 void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask)
34 {
35     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
36     CC_OP = CC_OP_EFLAGS;
37     env->df = 1 - (2 * ((eflags >> 10) & 1));
38     env->eflags = (env->eflags & ~update_mask) |
39         (eflags & update_mask) | 0x2;
40 }
41 
42 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
43 {
44 #ifdef CONFIG_USER_ONLY
45     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data);
46 #else
47     address_space_stb(&address_space_io, port, data,
48                       cpu_get_mem_attrs(env), NULL);
49 #endif
50 }
51 
52 target_ulong helper_inb(CPUX86State *env, uint32_t port)
53 {
54 #ifdef CONFIG_USER_ONLY
55     fprintf(stderr, "inb: port=0x%04x\n", port);
56     return 0;
57 #else
58     return address_space_ldub(&address_space_io, port,
59                               cpu_get_mem_attrs(env), NULL);
60 #endif
61 }
62 
63 void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
64 {
65 #ifdef CONFIG_USER_ONLY
66     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data);
67 #else
68     address_space_stw(&address_space_io, port, data,
69                       cpu_get_mem_attrs(env), NULL);
70 #endif
71 }
72 
73 target_ulong helper_inw(CPUX86State *env, uint32_t port)
74 {
75 #ifdef CONFIG_USER_ONLY
76     fprintf(stderr, "inw: port=0x%04x\n", port);
77     return 0;
78 #else
79     return address_space_lduw(&address_space_io, port,
80                               cpu_get_mem_attrs(env), NULL);
81 #endif
82 }
83 
84 void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
85 {
86 #ifdef CONFIG_USER_ONLY
87     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data);
88 #else
89     address_space_stl(&address_space_io, port, data,
90                       cpu_get_mem_attrs(env), NULL);
91 #endif
92 }
93 
94 target_ulong helper_inl(CPUX86State *env, uint32_t port)
95 {
96 #ifdef CONFIG_USER_ONLY
97     fprintf(stderr, "inl: port=0x%04x\n", port);
98     return 0;
99 #else
100     return address_space_ldl(&address_space_io, port,
101                              cpu_get_mem_attrs(env), NULL);
102 #endif
103 }
104 
105 void helper_into(CPUX86State *env, int next_eip_addend)
106 {
107     int eflags;
108 
109     eflags = cpu_cc_compute_all(env, CC_OP);
110     if (eflags & CC_O) {
111         raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
112     }
113 }
114 
115 void helper_cpuid(CPUX86State *env)
116 {
117     uint32_t eax, ebx, ecx, edx;
118 
119     cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
120 
121     cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
122                   &eax, &ebx, &ecx, &edx);
123     env->regs[R_EAX] = eax;
124     env->regs[R_EBX] = ebx;
125     env->regs[R_ECX] = ecx;
126     env->regs[R_EDX] = edx;
127 }
128 
129 #if defined(CONFIG_USER_ONLY)
130 target_ulong helper_read_crN(CPUX86State *env, int reg)
131 {
132     return 0;
133 }
134 
135 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
136 {
137 }
138 #else
139 target_ulong helper_read_crN(CPUX86State *env, int reg)
140 {
141     target_ulong val;
142 
143     cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
144     switch (reg) {
145     default:
146         val = env->cr[reg];
147         break;
148     case 8:
149         if (!(env->hflags2 & HF2_VINTR_MASK)) {
150             val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
151         } else {
152             val = env->v_tpr;
153         }
154         break;
155     }
156     return val;
157 }
158 
159 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
160 {
161     cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
162     switch (reg) {
163     case 0:
164         cpu_x86_update_cr0(env, t0);
165         break;
166     case 3:
167         cpu_x86_update_cr3(env, t0);
168         break;
169     case 4:
170         cpu_x86_update_cr4(env, t0);
171         break;
172     case 8:
173         if (!(env->hflags2 & HF2_VINTR_MASK)) {
174             qemu_mutex_lock_iothread();
175             cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0);
176             qemu_mutex_unlock_iothread();
177         }
178         env->v_tpr = t0 & 0x0f;
179         break;
180     default:
181         env->cr[reg] = t0;
182         break;
183     }
184 }
185 #endif
186 
187 void helper_lmsw(CPUX86State *env, target_ulong t0)
188 {
189     /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
190        if already set to one. */
191     t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
192     helper_write_crN(env, 0, t0);
193 }
194 
195 void helper_invlpg(CPUX86State *env, target_ulong addr)
196 {
197     X86CPU *cpu = env_archcpu(env);
198 
199     cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
200     tlb_flush_page(CPU(cpu), addr);
201 }
202 
203 void helper_rdtsc(CPUX86State *env)
204 {
205     uint64_t val;
206 
207     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
208         raise_exception_ra(env, EXCP0D_GPF, GETPC());
209     }
210     cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
211 
212     val = cpu_get_tsc(env) + env->tsc_offset;
213     env->regs[R_EAX] = (uint32_t)(val);
214     env->regs[R_EDX] = (uint32_t)(val >> 32);
215 }
216 
217 void helper_rdtscp(CPUX86State *env)
218 {
219     helper_rdtsc(env);
220     env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
221 }
222 
223 void helper_rdpmc(CPUX86State *env)
224 {
225     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
226         raise_exception_ra(env, EXCP0D_GPF, GETPC());
227     }
228     cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
229 
230     /* currently unimplemented */
231     qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
232     raise_exception_err(env, EXCP06_ILLOP, 0);
233 }
234 
235 #if defined(CONFIG_USER_ONLY)
236 void helper_wrmsr(CPUX86State *env)
237 {
238 }
239 
240 void helper_rdmsr(CPUX86State *env)
241 {
242 }
243 #else
244 void helper_wrmsr(CPUX86State *env)
245 {
246     uint64_t val;
247     CPUState *cs = env_cpu(env);
248 
249     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
250 
251     val = ((uint32_t)env->regs[R_EAX]) |
252         ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
253 
254     switch ((uint32_t)env->regs[R_ECX]) {
255     case MSR_IA32_SYSENTER_CS:
256         env->sysenter_cs = val & 0xffff;
257         break;
258     case MSR_IA32_SYSENTER_ESP:
259         env->sysenter_esp = val;
260         break;
261     case MSR_IA32_SYSENTER_EIP:
262         env->sysenter_eip = val;
263         break;
264     case MSR_IA32_APICBASE:
265         cpu_set_apic_base(env_archcpu(env)->apic_state, val);
266         break;
267     case MSR_EFER:
268         {
269             uint64_t update_mask;
270 
271             update_mask = 0;
272             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
273                 update_mask |= MSR_EFER_SCE;
274             }
275             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
276                 update_mask |= MSR_EFER_LME;
277             }
278             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
279                 update_mask |= MSR_EFER_FFXSR;
280             }
281             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
282                 update_mask |= MSR_EFER_NXE;
283             }
284             if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
285                 update_mask |= MSR_EFER_SVME;
286             }
287             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
288                 update_mask |= MSR_EFER_FFXSR;
289             }
290             cpu_load_efer(env, (env->efer & ~update_mask) |
291                           (val & update_mask));
292         }
293         break;
294     case MSR_STAR:
295         env->star = val;
296         break;
297     case MSR_PAT:
298         env->pat = val;
299         break;
300     case MSR_IA32_PKRS:
301         if (val & 0xFFFFFFFF00000000ull) {
302             goto error;
303         }
304         env->pkrs = val;
305         tlb_flush(cs);
306         break;
307     case MSR_VM_HSAVE_PA:
308         env->vm_hsave = val;
309         break;
310 #ifdef TARGET_X86_64
311     case MSR_LSTAR:
312         env->lstar = val;
313         break;
314     case MSR_CSTAR:
315         env->cstar = val;
316         break;
317     case MSR_FMASK:
318         env->fmask = val;
319         break;
320     case MSR_FSBASE:
321         env->segs[R_FS].base = val;
322         break;
323     case MSR_GSBASE:
324         env->segs[R_GS].base = val;
325         break;
326     case MSR_KERNELGSBASE:
327         env->kernelgsbase = val;
328         break;
329 #endif
330     case MSR_MTRRphysBase(0):
331     case MSR_MTRRphysBase(1):
332     case MSR_MTRRphysBase(2):
333     case MSR_MTRRphysBase(3):
334     case MSR_MTRRphysBase(4):
335     case MSR_MTRRphysBase(5):
336     case MSR_MTRRphysBase(6):
337     case MSR_MTRRphysBase(7):
338         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
339                        MSR_MTRRphysBase(0)) / 2].base = val;
340         break;
341     case MSR_MTRRphysMask(0):
342     case MSR_MTRRphysMask(1):
343     case MSR_MTRRphysMask(2):
344     case MSR_MTRRphysMask(3):
345     case MSR_MTRRphysMask(4):
346     case MSR_MTRRphysMask(5):
347     case MSR_MTRRphysMask(6):
348     case MSR_MTRRphysMask(7):
349         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
350                        MSR_MTRRphysMask(0)) / 2].mask = val;
351         break;
352     case MSR_MTRRfix64K_00000:
353         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
354                         MSR_MTRRfix64K_00000] = val;
355         break;
356     case MSR_MTRRfix16K_80000:
357     case MSR_MTRRfix16K_A0000:
358         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
359                         MSR_MTRRfix16K_80000 + 1] = val;
360         break;
361     case MSR_MTRRfix4K_C0000:
362     case MSR_MTRRfix4K_C8000:
363     case MSR_MTRRfix4K_D0000:
364     case MSR_MTRRfix4K_D8000:
365     case MSR_MTRRfix4K_E0000:
366     case MSR_MTRRfix4K_E8000:
367     case MSR_MTRRfix4K_F0000:
368     case MSR_MTRRfix4K_F8000:
369         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
370                         MSR_MTRRfix4K_C0000 + 3] = val;
371         break;
372     case MSR_MTRRdefType:
373         env->mtrr_deftype = val;
374         break;
375     case MSR_MCG_STATUS:
376         env->mcg_status = val;
377         break;
378     case MSR_MCG_CTL:
379         if ((env->mcg_cap & MCG_CTL_P)
380             && (val == 0 || val == ~(uint64_t)0)) {
381             env->mcg_ctl = val;
382         }
383         break;
384     case MSR_TSC_AUX:
385         env->tsc_aux = val;
386         break;
387     case MSR_IA32_MISC_ENABLE:
388         env->msr_ia32_misc_enable = val;
389         break;
390     case MSR_IA32_BNDCFGS:
391         /* FIXME: #GP if reserved bits are set.  */
392         /* FIXME: Extend highest implemented bit of linear address.  */
393         env->msr_bndcfgs = val;
394         cpu_sync_bndcs_hflags(env);
395         break;
396     default:
397         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
398             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
399             (4 * env->mcg_cap & 0xff)) {
400             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
401             if ((offset & 0x3) != 0
402                 || (val == 0 || val == ~(uint64_t)0)) {
403                 env->mce_banks[offset] = val;
404             }
405             break;
406         }
407         /* XXX: exception? */
408         break;
409     }
410     return;
411 error:
412     raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
413 }
414 
415 void helper_rdmsr(CPUX86State *env)
416 {
417     X86CPU *x86_cpu = env_archcpu(env);
418     uint64_t val;
419 
420     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
421 
422     switch ((uint32_t)env->regs[R_ECX]) {
423     case MSR_IA32_SYSENTER_CS:
424         val = env->sysenter_cs;
425         break;
426     case MSR_IA32_SYSENTER_ESP:
427         val = env->sysenter_esp;
428         break;
429     case MSR_IA32_SYSENTER_EIP:
430         val = env->sysenter_eip;
431         break;
432     case MSR_IA32_APICBASE:
433         val = cpu_get_apic_base(env_archcpu(env)->apic_state);
434         break;
435     case MSR_EFER:
436         val = env->efer;
437         break;
438     case MSR_STAR:
439         val = env->star;
440         break;
441     case MSR_PAT:
442         val = env->pat;
443         break;
444     case MSR_IA32_PKRS:
445         val = env->pkrs;
446         break;
447     case MSR_VM_HSAVE_PA:
448         val = env->vm_hsave;
449         break;
450     case MSR_IA32_PERF_STATUS:
451         /* tsc_increment_by_tick */
452         val = 1000ULL;
453         /* CPU multiplier */
454         val |= (((uint64_t)4ULL) << 40);
455         break;
456 #ifdef TARGET_X86_64
457     case MSR_LSTAR:
458         val = env->lstar;
459         break;
460     case MSR_CSTAR:
461         val = env->cstar;
462         break;
463     case MSR_FMASK:
464         val = env->fmask;
465         break;
466     case MSR_FSBASE:
467         val = env->segs[R_FS].base;
468         break;
469     case MSR_GSBASE:
470         val = env->segs[R_GS].base;
471         break;
472     case MSR_KERNELGSBASE:
473         val = env->kernelgsbase;
474         break;
475     case MSR_TSC_AUX:
476         val = env->tsc_aux;
477         break;
478 #endif
479     case MSR_SMI_COUNT:
480         val = env->msr_smi_count;
481         break;
482     case MSR_MTRRphysBase(0):
483     case MSR_MTRRphysBase(1):
484     case MSR_MTRRphysBase(2):
485     case MSR_MTRRphysBase(3):
486     case MSR_MTRRphysBase(4):
487     case MSR_MTRRphysBase(5):
488     case MSR_MTRRphysBase(6):
489     case MSR_MTRRphysBase(7):
490         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
491                              MSR_MTRRphysBase(0)) / 2].base;
492         break;
493     case MSR_MTRRphysMask(0):
494     case MSR_MTRRphysMask(1):
495     case MSR_MTRRphysMask(2):
496     case MSR_MTRRphysMask(3):
497     case MSR_MTRRphysMask(4):
498     case MSR_MTRRphysMask(5):
499     case MSR_MTRRphysMask(6):
500     case MSR_MTRRphysMask(7):
501         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
502                              MSR_MTRRphysMask(0)) / 2].mask;
503         break;
504     case MSR_MTRRfix64K_00000:
505         val = env->mtrr_fixed[0];
506         break;
507     case MSR_MTRRfix16K_80000:
508     case MSR_MTRRfix16K_A0000:
509         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
510                               MSR_MTRRfix16K_80000 + 1];
511         break;
512     case MSR_MTRRfix4K_C0000:
513     case MSR_MTRRfix4K_C8000:
514     case MSR_MTRRfix4K_D0000:
515     case MSR_MTRRfix4K_D8000:
516     case MSR_MTRRfix4K_E0000:
517     case MSR_MTRRfix4K_E8000:
518     case MSR_MTRRfix4K_F0000:
519     case MSR_MTRRfix4K_F8000:
520         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
521                               MSR_MTRRfix4K_C0000 + 3];
522         break;
523     case MSR_MTRRdefType:
524         val = env->mtrr_deftype;
525         break;
526     case MSR_MTRRcap:
527         if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
528             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
529                 MSR_MTRRcap_WC_SUPPORTED;
530         } else {
531             /* XXX: exception? */
532             val = 0;
533         }
534         break;
535     case MSR_MCG_CAP:
536         val = env->mcg_cap;
537         break;
538     case MSR_MCG_CTL:
539         if (env->mcg_cap & MCG_CTL_P) {
540             val = env->mcg_ctl;
541         } else {
542             val = 0;
543         }
544         break;
545     case MSR_MCG_STATUS:
546         val = env->mcg_status;
547         break;
548     case MSR_IA32_MISC_ENABLE:
549         val = env->msr_ia32_misc_enable;
550         break;
551     case MSR_IA32_BNDCFGS:
552         val = env->msr_bndcfgs;
553         break;
554      case MSR_IA32_UCODE_REV:
555         val = x86_cpu->ucode_rev;
556         break;
557     default:
558         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
559             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
560             (4 * env->mcg_cap & 0xff)) {
561             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
562             val = env->mce_banks[offset];
563             break;
564         }
565         /* XXX: exception? */
566         val = 0;
567         break;
568     }
569     env->regs[R_EAX] = (uint32_t)(val);
570     env->regs[R_EDX] = (uint32_t)(val >> 32);
571 }
572 #endif
573 
574 static void do_pause(X86CPU *cpu)
575 {
576     CPUState *cs = CPU(cpu);
577 
578     /* Just let another CPU run.  */
579     cs->exception_index = EXCP_INTERRUPT;
580     cpu_loop_exit(cs);
581 }
582 
583 static void do_hlt(X86CPU *cpu)
584 {
585     CPUState *cs = CPU(cpu);
586     CPUX86State *env = &cpu->env;
587 
588     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
589     cs->halted = 1;
590     cs->exception_index = EXCP_HLT;
591     cpu_loop_exit(cs);
592 }
593 
594 void helper_hlt(CPUX86State *env, int next_eip_addend)
595 {
596     X86CPU *cpu = env_archcpu(env);
597 
598     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
599     env->eip += next_eip_addend;
600 
601     do_hlt(cpu);
602 }
603 
604 void helper_monitor(CPUX86State *env, target_ulong ptr)
605 {
606     if ((uint32_t)env->regs[R_ECX] != 0) {
607         raise_exception_ra(env, EXCP0D_GPF, GETPC());
608     }
609     /* XXX: store address? */
610     cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
611 }
612 
613 void helper_mwait(CPUX86State *env, int next_eip_addend)
614 {
615     CPUState *cs = env_cpu(env);
616     X86CPU *cpu = env_archcpu(env);
617 
618     if ((uint32_t)env->regs[R_ECX] != 0) {
619         raise_exception_ra(env, EXCP0D_GPF, GETPC());
620     }
621     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
622     env->eip += next_eip_addend;
623 
624     /* XXX: not complete but not completely erroneous */
625     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
626         do_pause(cpu);
627     } else {
628         do_hlt(cpu);
629     }
630 }
631 
632 void helper_pause(CPUX86State *env, int next_eip_addend)
633 {
634     X86CPU *cpu = env_archcpu(env);
635 
636     cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
637     env->eip += next_eip_addend;
638 
639     do_pause(cpu);
640 }
641 
642 void helper_debug(CPUX86State *env)
643 {
644     CPUState *cs = env_cpu(env);
645 
646     cs->exception_index = EXCP_DEBUG;
647     cpu_loop_exit(cs);
648 }
649 
650 uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
651 {
652     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
653         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
654     }
655     if (ecx != 0) {
656         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
657     }
658 
659     return env->pkru;
660 }
661 
662 void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
663 {
664     CPUState *cs = env_cpu(env);
665 
666     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
667         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
668     }
669     if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
670         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
671     }
672 
673     env->pkru = val;
674     tlb_flush(cs);
675 }
676