|
48 | 48 |
|
49 | 49 | static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
|
50 | 50 |
|
| 51 | +enum kvm_wfx_trap_policy { |
| 52 | + KVM_WFX_NOTRAP_SINGLE_TASK, /* Default option */ |
| 53 | + KVM_WFX_NOTRAP, |
| 54 | + KVM_WFX_TRAP, |
| 55 | +}; |
| 56 | + |
| 57 | +static enum kvm_wfx_trap_policy kvm_wfi_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK; |
| 58 | +static enum kvm_wfx_trap_policy kvm_wfe_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK; |
| 59 | + |
51 | 60 | DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
|
52 | 61 |
|
53 | 62 | DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
|
@@ -546,6 +555,24 @@ static void vcpu_set_pauth_traps(struct kvm_vcpu *vcpu)
|
546 | 555 | }
|
547 | 556 | }
|
548 | 557 |
|
| 558 | +static bool kvm_vcpu_should_clear_twi(struct kvm_vcpu *vcpu) |
| 559 | +{ |
| 560 | + if (unlikely(kvm_wfi_trap_policy != KVM_WFX_NOTRAP_SINGLE_TASK)) |
| 561 | + return kvm_wfi_trap_policy == KVM_WFX_NOTRAP; |
| 562 | + |
| 563 | + return single_task_running() && |
| 564 | + (atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) || |
| 565 | + vcpu->kvm->arch.vgic.nassgireq); |
| 566 | +} |
| 567 | + |
| 568 | +static bool kvm_vcpu_should_clear_twe(struct kvm_vcpu *vcpu) |
| 569 | +{ |
| 570 | + if (unlikely(kvm_wfe_trap_policy != KVM_WFX_NOTRAP_SINGLE_TASK)) |
| 571 | + return kvm_wfe_trap_policy == KVM_WFX_NOTRAP; |
| 572 | + |
| 573 | + return single_task_running(); |
| 574 | +} |
| 575 | + |
549 | 576 | void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
550 | 577 | {
|
551 | 578 | struct kvm_s2_mmu *mmu;
|
@@ -579,10 +606,15 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
579 | 606 | if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
|
580 | 607 | kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
|
581 | 608 |
|
582 |
| - if (single_task_running()) |
583 |
| - vcpu_clear_wfx_traps(vcpu); |
| 609 | + if (kvm_vcpu_should_clear_twe(vcpu)) |
| 610 | + vcpu->arch.hcr_el2 &= ~HCR_TWE; |
| 611 | + else |
| 612 | + vcpu->arch.hcr_el2 |= HCR_TWE; |
| 613 | + |
| 614 | + if (kvm_vcpu_should_clear_twi(vcpu)) |
| 615 | + vcpu->arch.hcr_el2 &= ~HCR_TWI; |
584 | 616 | else
|
585 |
| - vcpu_set_wfx_traps(vcpu); |
| 617 | + vcpu->arch.hcr_el2 |= HCR_TWI; |
586 | 618 |
|
587 | 619 | vcpu_set_pauth_traps(vcpu);
|
588 | 620 |
|
@@ -2858,6 +2890,36 @@ static int __init early_kvm_mode_cfg(char *arg)
|
2858 | 2890 | }
|
2859 | 2891 | early_param("kvm-arm.mode", early_kvm_mode_cfg);
|
2860 | 2892 |
|
| 2893 | +static int __init early_kvm_wfx_trap_policy_cfg(char *arg, enum kvm_wfx_trap_policy *p) |
| 2894 | +{ |
| 2895 | + if (!arg) |
| 2896 | + return -EINVAL; |
| 2897 | + |
| 2898 | + if (strcmp(arg, "trap") == 0) { |
| 2899 | + *p = KVM_WFX_TRAP; |
| 2900 | + return 0; |
| 2901 | + } |
| 2902 | + |
| 2903 | + if (strcmp(arg, "notrap") == 0) { |
| 2904 | + *p = KVM_WFX_NOTRAP; |
| 2905 | + return 0; |
| 2906 | + } |
| 2907 | + |
| 2908 | + return -EINVAL; |
| 2909 | +} |
| 2910 | + |
| 2911 | +static int __init early_kvm_wfi_trap_policy_cfg(char *arg) |
| 2912 | +{ |
| 2913 | + return early_kvm_wfx_trap_policy_cfg(arg, &kvm_wfi_trap_policy); |
| 2914 | +} |
| 2915 | +early_param("kvm-arm.wfi_trap_policy", early_kvm_wfi_trap_policy_cfg); |
| 2916 | + |
| 2917 | +static int __init early_kvm_wfe_trap_policy_cfg(char *arg) |
| 2918 | +{ |
| 2919 | + return early_kvm_wfx_trap_policy_cfg(arg, &kvm_wfe_trap_policy); |
| 2920 | +} |
| 2921 | +early_param("kvm-arm.wfe_trap_policy", early_kvm_wfe_trap_policy_cfg); |
| 2922 | + |
2861 | 2923 | enum kvm_mode kvm_get_mode(void)
|
2862 | 2924 | {
|
2863 | 2925 | return kvm_mode;
|
|
0 commit comments