aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/cpufeatures.h2
-rw-r--r--arch/x86/include/asm/microcode.h1
-rw-r--r--arch/x86/include/asm/nospec-branch.h5
-rw-r--r--arch/x86/kernel/cpu/intel.c3
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c34
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c76
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c4
-rw-r--r--arch/x86/kernel/vm86_32.c3
-rw-r--r--kernel/jump_label.c3
-rw-r--r--tools/testing/selftests/x86/entry_from_vm86.c32
10 files changed, 108 insertions, 55 deletions
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index f41079da38c5..d554c11e01ff 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -316,6 +316,7 @@
316#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ 316#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */
317#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ 317#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */
318#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ 318#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */
319#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */
319#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ 320#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
320#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ 321#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */
321#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ 322#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */
@@ -328,6 +329,7 @@
328/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ 329/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
329#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ 330#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
330#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ 331#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
332#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
331#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ 333#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
332#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ 334#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
333#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ 335#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 7fb1047d61c7..6cf0e4cb7b97 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -39,6 +39,7 @@ struct device;
39 39
40enum ucode_state { 40enum ucode_state {
41 UCODE_OK = 0, 41 UCODE_OK = 0,
42 UCODE_NEW,
42 UCODE_UPDATED, 43 UCODE_UPDATED,
43 UCODE_NFOUND, 44 UCODE_NFOUND,
44 UCODE_ERROR, 45 UCODE_ERROR,
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index d0dabeae0505..f928ad9b143f 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -183,7 +183,10 @@
183 * otherwise we'll run out of registers. We don't care about CET 183 * otherwise we'll run out of registers. We don't care about CET
184 * here, anyway. 184 * here, anyway.
185 */ 185 */
186# define CALL_NOSPEC ALTERNATIVE("call *%[thunk_target]\n", \ 186# define CALL_NOSPEC \
187 ALTERNATIVE( \
188 ANNOTATE_RETPOLINE_SAFE \
189 "call *%[thunk_target]\n", \
187 " jmp 904f;\n" \ 190 " jmp 904f;\n" \
188 " .align 16\n" \ 191 " .align 16\n" \
189 "901: call 903f;\n" \ 192 "901: call 903f;\n" \
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 4aa9fd379390..c3af167d0a70 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -105,7 +105,7 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c)
105/* 105/*
106 * Early microcode releases for the Spectre v2 mitigation were broken. 106 * Early microcode releases for the Spectre v2 mitigation were broken.
107 * Information taken from; 107 * Information taken from;
108 * - https://newsroom.intel.com/wp-content/uploads/sites/11/2018/01/microcode-update-guidance.pdf 108 * - https://newsroom.intel.com/wp-content/uploads/sites/11/2018/03/microcode-update-guidance.pdf
109 * - https://kb.vmware.com/s/article/52345 109 * - https://kb.vmware.com/s/article/52345
110 * - Microcode revisions observed in the wild 110 * - Microcode revisions observed in the wild
111 * - Release note from 20180108 microcode release 111 * - Release note from 20180108 microcode release
@@ -123,7 +123,6 @@ static const struct sku_microcode spectre_bad_microcodes[] = {
123 { INTEL_FAM6_KABYLAKE_MOBILE, 0x09, 0x80 }, 123 { INTEL_FAM6_KABYLAKE_MOBILE, 0x09, 0x80 },
124 { INTEL_FAM6_SKYLAKE_X, 0x03, 0x0100013e }, 124 { INTEL_FAM6_SKYLAKE_X, 0x03, 0x0100013e },
125 { INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003c }, 125 { INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003c },
126 { INTEL_FAM6_SKYLAKE_DESKTOP, 0x03, 0xc2 },
127 { INTEL_FAM6_BROADWELL_CORE, 0x04, 0x28 }, 126 { INTEL_FAM6_BROADWELL_CORE, 0x04, 0x28 },
128 { INTEL_FAM6_BROADWELL_GT3E, 0x01, 0x1b }, 127 { INTEL_FAM6_BROADWELL_GT3E, 0x01, 0x1b },
129 { INTEL_FAM6_BROADWELL_XEON_D, 0x02, 0x14 }, 128 { INTEL_FAM6_BROADWELL_XEON_D, 0x02, 0x14 },
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index a998e1a7d46f..48179928ff38 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -339,7 +339,7 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
339 return -EINVAL; 339 return -EINVAL;
340 340
341 ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size); 341 ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size);
342 if (ret != UCODE_OK) 342 if (ret > UCODE_UPDATED)
343 return -EINVAL; 343 return -EINVAL;
344 344
345 return 0; 345 return 0;
@@ -683,27 +683,35 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
683static enum ucode_state 683static enum ucode_state
684load_microcode_amd(bool save, u8 family, const u8 *data, size_t size) 684load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
685{ 685{
686 struct ucode_patch *p;
686 enum ucode_state ret; 687 enum ucode_state ret;
687 688
688 /* free old equiv table */ 689 /* free old equiv table */
689 free_equiv_cpu_table(); 690 free_equiv_cpu_table();
690 691
691 ret = __load_microcode_amd(family, data, size); 692 ret = __load_microcode_amd(family, data, size);
692 693 if (ret != UCODE_OK) {
693 if (ret != UCODE_OK)
694 cleanup(); 694 cleanup();
695 return ret;
696 }
695 697
696#ifdef CONFIG_X86_32 698 p = find_patch(0);
697 /* save BSP's matching patch for early load */ 699 if (!p) {
698 if (save) { 700 return ret;
699 struct ucode_patch *p = find_patch(0); 701 } else {
700 if (p) { 702 if (boot_cpu_data.microcode == p->patch_id)
701 memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); 703 return ret;
702 memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), 704
703 PATCH_MAX_SIZE)); 705 ret = UCODE_NEW;
704 }
705 } 706 }
706#endif 707
708 /* save BSP's matching patch for early load */
709 if (!save)
710 return ret;
711
712 memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
713 memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), PATCH_MAX_SIZE));
714
707 return ret; 715 return ret;
708} 716}
709 717
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 70ecbc8099c9..10c4fc2c91f8 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -517,7 +517,29 @@ static int check_online_cpus(void)
517 return -EINVAL; 517 return -EINVAL;
518} 518}
519 519
520static atomic_t late_cpus; 520static atomic_t late_cpus_in;
521static atomic_t late_cpus_out;
522
523static int __wait_for_cpus(atomic_t *t, long long timeout)
524{
525 int all_cpus = num_online_cpus();
526
527 atomic_inc(t);
528
529 while (atomic_read(t) < all_cpus) {
530 if (timeout < SPINUNIT) {
531 pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
532 all_cpus - atomic_read(t));
533 return 1;
534 }
535
536 ndelay(SPINUNIT);
537 timeout -= SPINUNIT;
538
539 touch_nmi_watchdog();
540 }
541 return 0;
542}
521 543
522/* 544/*
523 * Returns: 545 * Returns:
@@ -527,30 +549,16 @@ static atomic_t late_cpus;
527 */ 549 */
528static int __reload_late(void *info) 550static int __reload_late(void *info)
529{ 551{
530 unsigned int timeout = NSEC_PER_SEC;
531 int all_cpus = num_online_cpus();
532 int cpu = smp_processor_id(); 552 int cpu = smp_processor_id();
533 enum ucode_state err; 553 enum ucode_state err;
534 int ret = 0; 554 int ret = 0;
535 555
536 atomic_dec(&late_cpus);
537
538 /* 556 /*
539 * Wait for all CPUs to arrive. A load will not be attempted unless all 557 * Wait for all CPUs to arrive. A load will not be attempted unless all
540 * CPUs show up. 558 * CPUs show up.
541 * */ 559 * */
542 while (atomic_read(&late_cpus)) { 560 if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))
543 if (timeout < SPINUNIT) { 561 return -1;
544 pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
545 atomic_read(&late_cpus));
546 return -1;
547 }
548
549 ndelay(SPINUNIT);
550 timeout -= SPINUNIT;
551
552 touch_nmi_watchdog();
553 }
554 562
555 spin_lock(&update_lock); 563 spin_lock(&update_lock);
556 apply_microcode_local(&err); 564 apply_microcode_local(&err);
@@ -558,15 +566,22 @@ static int __reload_late(void *info)
558 566
559 if (err > UCODE_NFOUND) { 567 if (err > UCODE_NFOUND) {
560 pr_warn("Error reloading microcode on CPU %d\n", cpu); 568 pr_warn("Error reloading microcode on CPU %d\n", cpu);
561 ret = -1; 569 return -1;
562 } else if (err == UCODE_UPDATED) { 570 /* siblings return UCODE_OK because their engine got updated already */
571 } else if (err == UCODE_UPDATED || err == UCODE_OK) {
563 ret = 1; 572 ret = 1;
573 } else {
574 return ret;
564 } 575 }
565 576
566 atomic_inc(&late_cpus); 577 /*
567 578 * Increase the wait timeout to a safe value here since we're
568 while (atomic_read(&late_cpus) != all_cpus) 579 * serializing the microcode update and that could take a while on a
569 cpu_relax(); 580 * large number of CPUs. And that is fine as the *actual* timeout will
581 * be determined by the last CPU finished updating and thus cut short.
582 */
583 if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC * num_online_cpus()))
584 panic("Timeout during microcode update!\n");
570 585
571 return ret; 586 return ret;
572} 587}
@@ -579,12 +594,11 @@ static int microcode_reload_late(void)
579{ 594{
580 int ret; 595 int ret;
581 596
582 atomic_set(&late_cpus, num_online_cpus()); 597 atomic_set(&late_cpus_in, 0);
598 atomic_set(&late_cpus_out, 0);
583 599
584 ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask); 600 ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
585 if (ret < 0) 601 if (ret > 0)
586 return ret;
587 else if (ret > 0)
588 microcode_check(); 602 microcode_check();
589 603
590 return ret; 604 return ret;
@@ -607,7 +621,7 @@ static ssize_t reload_store(struct device *dev,
607 return size; 621 return size;
608 622
609 tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev, true); 623 tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev, true);
610 if (tmp_ret != UCODE_OK) 624 if (tmp_ret != UCODE_NEW)
611 return size; 625 return size;
612 626
613 get_online_cpus(); 627 get_online_cpus();
@@ -691,10 +705,8 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
691 if (system_state != SYSTEM_RUNNING) 705 if (system_state != SYSTEM_RUNNING)
692 return UCODE_NFOUND; 706 return UCODE_NFOUND;
693 707
694 ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, 708 ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, refresh_fw);
695 refresh_fw); 709 if (ustate == UCODE_NEW) {
696
697 if (ustate == UCODE_OK) {
698 pr_debug("CPU%d updated upon init\n", cpu); 710 pr_debug("CPU%d updated upon init\n", cpu);
699 apply_microcode_on_target(cpu); 711 apply_microcode_on_target(cpu);
700 } 712 }
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 2aded9db1d42..32b8e5724f96 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -862,6 +862,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
862 unsigned int leftover = size; 862 unsigned int leftover = size;
863 unsigned int curr_mc_size = 0, new_mc_size = 0; 863 unsigned int curr_mc_size = 0, new_mc_size = 0;
864 unsigned int csig, cpf; 864 unsigned int csig, cpf;
865 enum ucode_state ret = UCODE_OK;
865 866
866 while (leftover) { 867 while (leftover) {
867 struct microcode_header_intel mc_header; 868 struct microcode_header_intel mc_header;
@@ -903,6 +904,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
903 new_mc = mc; 904 new_mc = mc;
904 new_mc_size = mc_size; 905 new_mc_size = mc_size;
905 mc = NULL; /* trigger new vmalloc */ 906 mc = NULL; /* trigger new vmalloc */
907 ret = UCODE_NEW;
906 } 908 }
907 909
908 ucode_ptr += mc_size; 910 ucode_ptr += mc_size;
@@ -932,7 +934,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
932 pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", 934 pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
933 cpu, new_rev, uci->cpu_sig.rev); 935 cpu, new_rev, uci->cpu_sig.rev);
934 936
935 return UCODE_OK; 937 return ret;
936} 938}
937 939
938static int get_ucode_fw(void *to, const void *from, size_t n) 940static int get_ucode_fw(void *to, const void *from, size_t n)
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 5edb27f1a2c4..9d0b5af7db91 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -727,7 +727,8 @@ void handle_vm86_fault(struct kernel_vm86_regs *regs, long error_code)
727 return; 727 return;
728 728
729check_vip: 729check_vip:
730 if (VEFLAGS & X86_EFLAGS_VIP) { 730 if ((VEFLAGS & (X86_EFLAGS_VIP | X86_EFLAGS_VIF)) ==
731 (X86_EFLAGS_VIP | X86_EFLAGS_VIF)) {
731 save_v86_state(regs, VM86_STI); 732 save_v86_state(regs, VM86_STI);
732 return; 733 return;
733 } 734 }
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 52a0a7af8640..e7214093dcd1 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -373,7 +373,8 @@ static void __jump_label_update(struct static_key *key,
373 if (kernel_text_address(entry->code)) 373 if (kernel_text_address(entry->code))
374 arch_jump_label_transform(entry, jump_label_type(entry)); 374 arch_jump_label_transform(entry, jump_label_type(entry));
375 else 375 else
376 WARN_ONCE(1, "can't patch jump_label at %pS", (void *)entry->code); 376 WARN_ONCE(1, "can't patch jump_label at %pS",
377 (void *)(unsigned long)entry->code);
377 } 378 }
378 } 379 }
379} 380}
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index 361466a2eaef..ade443a88421 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -95,6 +95,10 @@ asm (
95 "int3\n\t" 95 "int3\n\t"
96 "vmcode_int80:\n\t" 96 "vmcode_int80:\n\t"
97 "int $0x80\n\t" 97 "int $0x80\n\t"
98 "vmcode_popf_hlt:\n\t"
99 "push %ax\n\t"
100 "popf\n\t"
101 "hlt\n\t"
98 "vmcode_umip:\n\t" 102 "vmcode_umip:\n\t"
99 /* addressing via displacements */ 103 /* addressing via displacements */
100 "smsw (2052)\n\t" 104 "smsw (2052)\n\t"
@@ -124,8 +128,8 @@ asm (
124 128
125extern unsigned char vmcode[], end_vmcode[]; 129extern unsigned char vmcode[], end_vmcode[];
126extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], 130extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
127 vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[], 131 vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_popf_hlt[],
128 vmcode_umip_str[], vmcode_umip_sldt[]; 132 vmcode_umip[], vmcode_umip_str[], vmcode_umip_sldt[];
129 133
130/* Returns false if the test was skipped. */ 134/* Returns false if the test was skipped. */
131static bool do_test(struct vm86plus_struct *v86, unsigned long eip, 135static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -175,7 +179,7 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
175 (VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) { 179 (VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) {
176 printf("[OK]\tReturned correctly\n"); 180 printf("[OK]\tReturned correctly\n");
177 } else { 181 } else {
178 printf("[FAIL]\tIncorrect return reason\n"); 182 printf("[FAIL]\tIncorrect return reason (started at eip = 0x%lx, ended at eip = 0x%lx)\n", eip, v86->regs.eip);
179 nerrs++; 183 nerrs++;
180 } 184 }
181 185
@@ -264,6 +268,9 @@ int main(void)
264 v86.regs.ds = load_addr / 16; 268 v86.regs.ds = load_addr / 16;
265 v86.regs.es = load_addr / 16; 269 v86.regs.es = load_addr / 16;
266 270
271 /* Use the end of the page as our stack. */
272 v86.regs.esp = 4096;
273
267 assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ 274 assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
268 275
269 /* #BR -- should deliver SIG??? */ 276 /* #BR -- should deliver SIG??? */
@@ -295,6 +302,23 @@ int main(void)
295 v86.regs.eflags &= ~X86_EFLAGS_IF; 302 v86.regs.eflags &= ~X86_EFLAGS_IF;
296 do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set"); 303 do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set");
297 304
305 /* POPF with VIP set but IF clear: should not trap */
306 v86.regs.eflags = X86_EFLAGS_VIP;
307 v86.regs.eax = 0;
308 do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP set and IF clear");
309
310 /* POPF with VIP set and IF set: should trap */
311 v86.regs.eflags = X86_EFLAGS_VIP;
312 v86.regs.eax = X86_EFLAGS_IF;
313 do_test(&v86, vmcode_popf_hlt - vmcode, VM86_STI, 0, "POPF with VIP and IF set");
314
315 /* POPF with VIP clear and IF set: should not trap */
316 v86.regs.eflags = 0;
317 v86.regs.eax = X86_EFLAGS_IF;
318 do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP clear and IF set");
319
320 v86.regs.eflags = 0;
321
298 /* INT3 -- should cause #BP */ 322 /* INT3 -- should cause #BP */
299 do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3"); 323 do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3");
300 324
@@ -318,7 +342,7 @@ int main(void)
318 clearhandler(SIGSEGV); 342 clearhandler(SIGSEGV);
319 343
320 /* Make sure nothing explodes if we fork. */ 344 /* Make sure nothing explodes if we fork. */
321 if (fork() > 0) 345 if (fork() == 0)
322 return 0; 346 return 0;
323 347
324 return (nerrs == 0 ? 0 : 1); 348 return (nerrs == 0 ? 0 : 1);