xref: /qemu/target/i386/tcg/misc_helper.c (revision 8825587b)
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) == 0 ) &&
226         ((env->hflags & HF_CPL_MASK) != 0)) {
227         raise_exception_ra(env, EXCP0D_GPF, GETPC());
228     }
229     cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
230 
231     /* currently unimplemented */
232     qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
233     raise_exception_err(env, EXCP06_ILLOP, 0);
234 }
235 
236 #if defined(CONFIG_USER_ONLY)
237 void helper_wrmsr(CPUX86State *env)
238 {
239 }
240 
241 void helper_rdmsr(CPUX86State *env)
242 {
243 }
244 #else
245 void helper_wrmsr(CPUX86State *env)
246 {
247     uint64_t val;
248     CPUState *cs = env_cpu(env);
249 
250     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
251 
252     val = ((uint32_t)env->regs[R_EAX]) |
253         ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
254 
255     switch ((uint32_t)env->regs[R_ECX]) {
256     case MSR_IA32_SYSENTER_CS:
257         env->sysenter_cs = val & 0xffff;
258         break;
259     case MSR_IA32_SYSENTER_ESP:
260         env->sysenter_esp = val;
261         break;
262     case MSR_IA32_SYSENTER_EIP:
263         env->sysenter_eip = val;
264         break;
265     case MSR_IA32_APICBASE:
266         cpu_set_apic_base(env_archcpu(env)->apic_state, val);
267         break;
268     case MSR_EFER:
269         {
270             uint64_t update_mask;
271 
272             update_mask = 0;
273             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
274                 update_mask |= MSR_EFER_SCE;
275             }
276             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
277                 update_mask |= MSR_EFER_LME;
278             }
279             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
280                 update_mask |= MSR_EFER_FFXSR;
281             }
282             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
283                 update_mask |= MSR_EFER_NXE;
284             }
285             if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
286                 update_mask |= MSR_EFER_SVME;
287             }
288             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
289                 update_mask |= MSR_EFER_FFXSR;
290             }
291             cpu_load_efer(env, (env->efer & ~update_mask) |
292                           (val & update_mask));
293         }
294         break;
295     case MSR_STAR:
296         env->star = val;
297         break;
298     case MSR_PAT:
299         env->pat = val;
300         break;
301     case MSR_IA32_PKRS:
302         if (val & 0xFFFFFFFF00000000ull) {
303             goto error;
304         }
305         env->pkrs = val;
306         tlb_flush(cs);
307         break;
308     case MSR_VM_HSAVE_PA:
309         env->vm_hsave = val;
310         break;
311 #ifdef TARGET_X86_64
312     case MSR_LSTAR:
313         env->lstar = val;
314         break;
315     case MSR_CSTAR:
316         env->cstar = val;
317         break;
318     case MSR_FMASK:
319         env->fmask = val;
320         break;
321     case MSR_FSBASE:
322         env->segs[R_FS].base = val;
323         break;
324     case MSR_GSBASE:
325         env->segs[R_GS].base = val;
326         break;
327     case MSR_KERNELGSBASE:
328         env->kernelgsbase = val;
329         break;
330 #endif
331     case MSR_MTRRphysBase(0):
332     case MSR_MTRRphysBase(1):
333     case MSR_MTRRphysBase(2):
334     case MSR_MTRRphysBase(3):
335     case MSR_MTRRphysBase(4):
336     case MSR_MTRRphysBase(5):
337     case MSR_MTRRphysBase(6):
338     case MSR_MTRRphysBase(7):
339         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
340                        MSR_MTRRphysBase(0)) / 2].base = val;
341         break;
342     case MSR_MTRRphysMask(0):
343     case MSR_MTRRphysMask(1):
344     case MSR_MTRRphysMask(2):
345     case MSR_MTRRphysMask(3):
346     case MSR_MTRRphysMask(4):
347     case MSR_MTRRphysMask(5):
348     case MSR_MTRRphysMask(6):
349     case MSR_MTRRphysMask(7):
350         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
351                        MSR_MTRRphysMask(0)) / 2].mask = val;
352         break;
353     case MSR_MTRRfix64K_00000:
354         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
355                         MSR_MTRRfix64K_00000] = val;
356         break;
357     case MSR_MTRRfix16K_80000:
358     case MSR_MTRRfix16K_A0000:
359         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
360                         MSR_MTRRfix16K_80000 + 1] = val;
361         break;
362     case MSR_MTRRfix4K_C0000:
363     case MSR_MTRRfix4K_C8000:
364     case MSR_MTRRfix4K_D0000:
365     case MSR_MTRRfix4K_D8000:
366     case MSR_MTRRfix4K_E0000:
367     case MSR_MTRRfix4K_E8000:
368     case MSR_MTRRfix4K_F0000:
369     case MSR_MTRRfix4K_F8000:
370         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
371                         MSR_MTRRfix4K_C0000 + 3] = val;
372         break;
373     case MSR_MTRRdefType:
374         env->mtrr_deftype = val;
375         break;
376     case MSR_MCG_STATUS:
377         env->mcg_status = val;
378         break;
379     case MSR_MCG_CTL:
380         if ((env->mcg_cap & MCG_CTL_P)
381             && (val == 0 || val == ~(uint64_t)0)) {
382             env->mcg_ctl = val;
383         }
384         break;
385     case MSR_TSC_AUX:
386         env->tsc_aux = val;
387         break;
388     case MSR_IA32_MISC_ENABLE:
389         env->msr_ia32_misc_enable = val;
390         break;
391     case MSR_IA32_BNDCFGS:
392         /* FIXME: #GP if reserved bits are set.  */
393         /* FIXME: Extend highest implemented bit of linear address.  */
394         env->msr_bndcfgs = val;
395         cpu_sync_bndcs_hflags(env);
396         break;
397     default:
398         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
399             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
400             (4 * env->mcg_cap & 0xff)) {
401             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
402             if ((offset & 0x3) != 0
403                 || (val == 0 || val == ~(uint64_t)0)) {
404                 env->mce_banks[offset] = val;
405             }
406             break;
407         }
408         /* XXX: exception? */
409         break;
410     }
411     return;
412 error:
413     raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
414 }
415 
416 void helper_rdmsr(CPUX86State *env)
417 {
418     X86CPU *x86_cpu = env_archcpu(env);
419     uint64_t val;
420 
421     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
422 
423     switch ((uint32_t)env->regs[R_ECX]) {
424     case MSR_IA32_SYSENTER_CS:
425         val = env->sysenter_cs;
426         break;
427     case MSR_IA32_SYSENTER_ESP:
428         val = env->sysenter_esp;
429         break;
430     case MSR_IA32_SYSENTER_EIP:
431         val = env->sysenter_eip;
432         break;
433     case MSR_IA32_APICBASE:
434         val = cpu_get_apic_base(env_archcpu(env)->apic_state);
435         break;
436     case MSR_EFER:
437         val = env->efer;
438         break;
439     case MSR_STAR:
440         val = env->star;
441         break;
442     case MSR_PAT:
443         val = env->pat;
444         break;
445     case MSR_IA32_PKRS:
446         val = env->pkrs;
447         break;
448     case MSR_VM_HSAVE_PA:
449         val = env->vm_hsave;
450         break;
451     case MSR_IA32_PERF_STATUS:
452         /* tsc_increment_by_tick */
453         val = 1000ULL;
454         /* CPU multiplier */
455         val |= (((uint64_t)4ULL) << 40);
456         break;
457 #ifdef TARGET_X86_64
458     case MSR_LSTAR:
459         val = env->lstar;
460         break;
461     case MSR_CSTAR:
462         val = env->cstar;
463         break;
464     case MSR_FMASK:
465         val = env->fmask;
466         break;
467     case MSR_FSBASE:
468         val = env->segs[R_FS].base;
469         break;
470     case MSR_GSBASE:
471         val = env->segs[R_GS].base;
472         break;
473     case MSR_KERNELGSBASE:
474         val = env->kernelgsbase;
475         break;
476     case MSR_TSC_AUX:
477         val = env->tsc_aux;
478         break;
479 #endif
480     case MSR_SMI_COUNT:
481         val = env->msr_smi_count;
482         break;
483     case MSR_MTRRphysBase(0):
484     case MSR_MTRRphysBase(1):
485     case MSR_MTRRphysBase(2):
486     case MSR_MTRRphysBase(3):
487     case MSR_MTRRphysBase(4):
488     case MSR_MTRRphysBase(5):
489     case MSR_MTRRphysBase(6):
490     case MSR_MTRRphysBase(7):
491         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
492                              MSR_MTRRphysBase(0)) / 2].base;
493         break;
494     case MSR_MTRRphysMask(0):
495     case MSR_MTRRphysMask(1):
496     case MSR_MTRRphysMask(2):
497     case MSR_MTRRphysMask(3):
498     case MSR_MTRRphysMask(4):
499     case MSR_MTRRphysMask(5):
500     case MSR_MTRRphysMask(6):
501     case MSR_MTRRphysMask(7):
502         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
503                              MSR_MTRRphysMask(0)) / 2].mask;
504         break;
505     case MSR_MTRRfix64K_00000:
506         val = env->mtrr_fixed[0];
507         break;
508     case MSR_MTRRfix16K_80000:
509     case MSR_MTRRfix16K_A0000:
510         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
511                               MSR_MTRRfix16K_80000 + 1];
512         break;
513     case MSR_MTRRfix4K_C0000:
514     case MSR_MTRRfix4K_C8000:
515     case MSR_MTRRfix4K_D0000:
516     case MSR_MTRRfix4K_D8000:
517     case MSR_MTRRfix4K_E0000:
518     case MSR_MTRRfix4K_E8000:
519     case MSR_MTRRfix4K_F0000:
520     case MSR_MTRRfix4K_F8000:
521         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
522                               MSR_MTRRfix4K_C0000 + 3];
523         break;
524     case MSR_MTRRdefType:
525         val = env->mtrr_deftype;
526         break;
527     case MSR_MTRRcap:
528         if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
529             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
530                 MSR_MTRRcap_WC_SUPPORTED;
531         } else {
532             /* XXX: exception? */
533             val = 0;
534         }
535         break;
536     case MSR_MCG_CAP:
537         val = env->mcg_cap;
538         break;
539     case MSR_MCG_CTL:
540         if (env->mcg_cap & MCG_CTL_P) {
541             val = env->mcg_ctl;
542         } else {
543             val = 0;
544         }
545         break;
546     case MSR_MCG_STATUS:
547         val = env->mcg_status;
548         break;
549     case MSR_IA32_MISC_ENABLE:
550         val = env->msr_ia32_misc_enable;
551         break;
552     case MSR_IA32_BNDCFGS:
553         val = env->msr_bndcfgs;
554         break;
555      case MSR_IA32_UCODE_REV:
556         val = x86_cpu->ucode_rev;
557         break;
558     default:
559         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
560             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
561             (4 * env->mcg_cap & 0xff)) {
562             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
563             val = env->mce_banks[offset];
564             break;
565         }
566         /* XXX: exception? */
567         val = 0;
568         break;
569     }
570     env->regs[R_EAX] = (uint32_t)(val);
571     env->regs[R_EDX] = (uint32_t)(val >> 32);
572 }
573 #endif
574 
575 static void do_pause(X86CPU *cpu)
576 {
577     CPUState *cs = CPU(cpu);
578 
579     /* Just let another CPU run.  */
580     cs->exception_index = EXCP_INTERRUPT;
581     cpu_loop_exit(cs);
582 }
583 
584 static void do_hlt(X86CPU *cpu)
585 {
586     CPUState *cs = CPU(cpu);
587     CPUX86State *env = &cpu->env;
588 
589     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
590     cs->halted = 1;
591     cs->exception_index = EXCP_HLT;
592     cpu_loop_exit(cs);
593 }
594 
595 void helper_hlt(CPUX86State *env, int next_eip_addend)
596 {
597     X86CPU *cpu = env_archcpu(env);
598 
599     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
600     env->eip += next_eip_addend;
601 
602     do_hlt(cpu);
603 }
604 
605 void helper_monitor(CPUX86State *env, target_ulong ptr)
606 {
607     if ((uint32_t)env->regs[R_ECX] != 0) {
608         raise_exception_ra(env, EXCP0D_GPF, GETPC());
609     }
610     /* XXX: store address? */
611     cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
612 }
613 
614 void helper_mwait(CPUX86State *env, int next_eip_addend)
615 {
616     CPUState *cs = env_cpu(env);
617     X86CPU *cpu = env_archcpu(env);
618 
619     if ((uint32_t)env->regs[R_ECX] != 0) {
620         raise_exception_ra(env, EXCP0D_GPF, GETPC());
621     }
622     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
623     env->eip += next_eip_addend;
624 
625     /* XXX: not complete but not completely erroneous */
626     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
627         do_pause(cpu);
628     } else {
629         do_hlt(cpu);
630     }
631 }
632 
633 void helper_pause(CPUX86State *env, int next_eip_addend)
634 {
635     X86CPU *cpu = env_archcpu(env);
636 
637     cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
638     env->eip += next_eip_addend;
639 
640     do_pause(cpu);
641 }
642 
643 void helper_debug(CPUX86State *env)
644 {
645     CPUState *cs = env_cpu(env);
646 
647     cs->exception_index = EXCP_DEBUG;
648     cpu_loop_exit(cs);
649 }
650 
651 uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
652 {
653     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
654         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
655     }
656     if (ecx != 0) {
657         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
658     }
659 
660     return env->pkru;
661 }
662 
663 void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
664 {
665     CPUState *cs = env_cpu(env);
666 
667     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
668         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
669     }
670     if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
671         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
672     }
673 
674     env->pkru = val;
675     tlb_flush(cs);
676 }
677