diff options
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/kvm_arm.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 3 | ||||
-rw-r--r-- | arch/arm/kvm/handle_exit.c | 19 | ||||
-rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 3 | ||||
-rw-r--r-- | arch/arm64/kvm/handle_exit.c | 19 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/tlb.c | 64 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 30 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic-v3.h | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 109 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio.c | 32 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-v3.c | 5 |
13 files changed, 191 insertions, 101 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 069450938b79..3c248f772ae6 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -951,6 +951,10 @@ This ioctl allows the user to create or modify a guest physical memory | |||
951 | slot. When changing an existing slot, it may be moved in the guest | 951 | slot. When changing an existing slot, it may be moved in the guest |
952 | physical memory space, or its flags may be modified. It may not be | 952 | physical memory space, or its flags may be modified. It may not be |
953 | resized. Slots may not overlap in guest physical address space. | 953 | resized. Slots may not overlap in guest physical address space. |
954 | Bits 0-15 of "slot" specifies the slot id and this value should be | ||
955 | less than the maximum number of user memory slots supported per VM. | ||
956 | The maximum allowed slots can be queried using KVM_CAP_NR_MEMSLOTS, | ||
957 | if this capability is supported by the architecture. | ||
954 | 958 | ||
955 | If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 of "slot" | 959 | If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 of "slot" |
956 | specifies the address space which is being modified. They must be | 960 | specifies the address space which is being modified. They must be |
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h index e22089fb44dc..a3f0b3d50089 100644 --- a/arch/arm/include/asm/kvm_arm.h +++ b/arch/arm/include/asm/kvm_arm.h | |||
@@ -209,6 +209,7 @@ | |||
209 | #define HSR_EC_IABT_HYP (0x21) | 209 | #define HSR_EC_IABT_HYP (0x21) |
210 | #define HSR_EC_DABT (0x24) | 210 | #define HSR_EC_DABT (0x24) |
211 | #define HSR_EC_DABT_HYP (0x25) | 211 | #define HSR_EC_DABT_HYP (0x25) |
212 | #define HSR_EC_MAX (0x3f) | ||
212 | 213 | ||
213 | #define HSR_WFI_IS_WFE (_AC(1, UL) << 0) | 214 | #define HSR_WFI_IS_WFE (_AC(1, UL) << 0) |
214 | 215 | ||
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index cc495d799c67..31ee468ce667 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h | |||
@@ -30,7 +30,6 @@ | |||
30 | #define __KVM_HAVE_ARCH_INTC_INITIALIZED | 30 | #define __KVM_HAVE_ARCH_INTC_INITIALIZED |
31 | 31 | ||
32 | #define KVM_USER_MEM_SLOTS 32 | 32 | #define KVM_USER_MEM_SLOTS 32 |
33 | #define KVM_PRIVATE_MEM_SLOTS 4 | ||
34 | #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 | 33 | #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 |
35 | #define KVM_HAVE_ONE_REG | 34 | #define KVM_HAVE_ONE_REG |
36 | #define KVM_HALT_POLL_NS_DEFAULT 500000 | 35 | #define KVM_HALT_POLL_NS_DEFAULT 500000 |
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index c9a2103faeb9..96dba7cd8be7 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -221,6 +221,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) | |||
221 | case KVM_CAP_MAX_VCPUS: | 221 | case KVM_CAP_MAX_VCPUS: |
222 | r = KVM_MAX_VCPUS; | 222 | r = KVM_MAX_VCPUS; |
223 | break; | 223 | break; |
224 | case KVM_CAP_NR_MEMSLOTS: | ||
225 | r = KVM_USER_MEM_SLOTS; | ||
226 | break; | ||
224 | case KVM_CAP_MSI_DEVID: | 227 | case KVM_CAP_MSI_DEVID: |
225 | if (!kvm) | 228 | if (!kvm) |
226 | r = -EINVAL; | 229 | r = -EINVAL; |
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 4e40d1955e35..96af65a30d78 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c | |||
@@ -79,7 +79,19 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
79 | return 1; | 79 | return 1; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
83 | { | ||
84 | u32 hsr = kvm_vcpu_get_hsr(vcpu); | ||
85 | |||
86 | kvm_pr_unimpl("Unknown exception class: hsr: %#08x\n", | ||
87 | hsr); | ||
88 | |||
89 | kvm_inject_undefined(vcpu); | ||
90 | return 1; | ||
91 | } | ||
92 | |||
82 | static exit_handle_fn arm_exit_handlers[] = { | 93 | static exit_handle_fn arm_exit_handlers[] = { |
94 | [0 ... HSR_EC_MAX] = kvm_handle_unknown_ec, | ||
83 | [HSR_EC_WFI] = kvm_handle_wfx, | 95 | [HSR_EC_WFI] = kvm_handle_wfx, |
84 | [HSR_EC_CP15_32] = kvm_handle_cp15_32, | 96 | [HSR_EC_CP15_32] = kvm_handle_cp15_32, |
85 | [HSR_EC_CP15_64] = kvm_handle_cp15_64, | 97 | [HSR_EC_CP15_64] = kvm_handle_cp15_64, |
@@ -98,13 +110,6 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) | |||
98 | { | 110 | { |
99 | u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu); | 111 | u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu); |
100 | 112 | ||
101 | if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || | ||
102 | !arm_exit_handlers[hsr_ec]) { | ||
103 | kvm_err("Unknown exception class: hsr: %#08x\n", | ||
104 | (unsigned int)kvm_vcpu_get_hsr(vcpu)); | ||
105 | BUG(); | ||
106 | } | ||
107 | |||
108 | return arm_exit_handlers[hsr_ec]; | 113 | return arm_exit_handlers[hsr_ec]; |
109 | } | 114 | } |
110 | 115 | ||
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index f21fd3894370..e7705e7bb07b 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h | |||
@@ -30,8 +30,7 @@ | |||
30 | 30 | ||
31 | #define __KVM_HAVE_ARCH_INTC_INITIALIZED | 31 | #define __KVM_HAVE_ARCH_INTC_INITIALIZED |
32 | 32 | ||
33 | #define KVM_USER_MEM_SLOTS 32 | 33 | #define KVM_USER_MEM_SLOTS 512 |
34 | #define KVM_PRIVATE_MEM_SLOTS 4 | ||
35 | #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 | 34 | #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 |
36 | #define KVM_HALT_POLL_NS_DEFAULT 500000 | 35 | #define KVM_HALT_POLL_NS_DEFAULT 500000 |
37 | 36 | ||
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 1bfe30dfbfe7..fa1b18e364fc 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c | |||
@@ -135,7 +135,19 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
135 | return ret; | 135 | return ret; |
136 | } | 136 | } |
137 | 137 | ||
138 | static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
139 | { | ||
140 | u32 hsr = kvm_vcpu_get_hsr(vcpu); | ||
141 | |||
142 | kvm_pr_unimpl("Unknown exception class: hsr: %#08x -- %s\n", | ||
143 | hsr, esr_get_class_string(hsr)); | ||
144 | |||
145 | kvm_inject_undefined(vcpu); | ||
146 | return 1; | ||
147 | } | ||
148 | |||
138 | static exit_handle_fn arm_exit_handlers[] = { | 149 | static exit_handle_fn arm_exit_handlers[] = { |
150 | [0 ... ESR_ELx_EC_MAX] = kvm_handle_unknown_ec, | ||
139 | [ESR_ELx_EC_WFx] = kvm_handle_wfx, | 151 | [ESR_ELx_EC_WFx] = kvm_handle_wfx, |
140 | [ESR_ELx_EC_CP15_32] = kvm_handle_cp15_32, | 152 | [ESR_ELx_EC_CP15_32] = kvm_handle_cp15_32, |
141 | [ESR_ELx_EC_CP15_64] = kvm_handle_cp15_64, | 153 | [ESR_ELx_EC_CP15_64] = kvm_handle_cp15_64, |
@@ -162,13 +174,6 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) | |||
162 | u32 hsr = kvm_vcpu_get_hsr(vcpu); | 174 | u32 hsr = kvm_vcpu_get_hsr(vcpu); |
163 | u8 hsr_ec = ESR_ELx_EC(hsr); | 175 | u8 hsr_ec = ESR_ELx_EC(hsr); |
164 | 176 | ||
165 | if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || | ||
166 | !arm_exit_handlers[hsr_ec]) { | ||
167 | kvm_err("Unknown exception class: hsr: %#08x -- %s\n", | ||
168 | hsr, esr_get_class_string(hsr)); | ||
169 | BUG(); | ||
170 | } | ||
171 | |||
172 | return arm_exit_handlers[hsr_ec]; | 177 | return arm_exit_handlers[hsr_ec]; |
173 | } | 178 | } |
174 | 179 | ||
diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c index e8e7ba2bc11f..9e1d2b75eecd 100644 --- a/arch/arm64/kvm/hyp/tlb.c +++ b/arch/arm64/kvm/hyp/tlb.c | |||
@@ -18,14 +18,62 @@ | |||
18 | #include <asm/kvm_hyp.h> | 18 | #include <asm/kvm_hyp.h> |
19 | #include <asm/tlbflush.h> | 19 | #include <asm/tlbflush.h> |
20 | 20 | ||
21 | static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm) | ||
22 | { | ||
23 | u64 val; | ||
24 | |||
25 | /* | ||
26 | * With VHE enabled, we have HCR_EL2.{E2H,TGE} = {1,1}, and | ||
27 | * most TLB operations target EL2/EL0. In order to affect the | ||
28 | * guest TLBs (EL1/EL0), we need to change one of these two | ||
29 | * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so | ||
30 | * let's flip TGE before executing the TLB operation. | ||
31 | */ | ||
32 | write_sysreg(kvm->arch.vttbr, vttbr_el2); | ||
33 | val = read_sysreg(hcr_el2); | ||
34 | val &= ~HCR_TGE; | ||
35 | write_sysreg(val, hcr_el2); | ||
36 | isb(); | ||
37 | } | ||
38 | |||
39 | static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm) | ||
40 | { | ||
41 | write_sysreg(kvm->arch.vttbr, vttbr_el2); | ||
42 | isb(); | ||
43 | } | ||
44 | |||
45 | static hyp_alternate_select(__tlb_switch_to_guest, | ||
46 | __tlb_switch_to_guest_nvhe, | ||
47 | __tlb_switch_to_guest_vhe, | ||
48 | ARM64_HAS_VIRT_HOST_EXTN); | ||
49 | |||
50 | static void __hyp_text __tlb_switch_to_host_vhe(struct kvm *kvm) | ||
51 | { | ||
52 | /* | ||
53 | * We're done with the TLB operation, let's restore the host's | ||
54 | * view of HCR_EL2. | ||
55 | */ | ||
56 | write_sysreg(0, vttbr_el2); | ||
57 | write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); | ||
58 | } | ||
59 | |||
60 | static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm) | ||
61 | { | ||
62 | write_sysreg(0, vttbr_el2); | ||
63 | } | ||
64 | |||
65 | static hyp_alternate_select(__tlb_switch_to_host, | ||
66 | __tlb_switch_to_host_nvhe, | ||
67 | __tlb_switch_to_host_vhe, | ||
68 | ARM64_HAS_VIRT_HOST_EXTN); | ||
69 | |||
21 | void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) | 70 | void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) |
22 | { | 71 | { |
23 | dsb(ishst); | 72 | dsb(ishst); |
24 | 73 | ||
25 | /* Switch to requested VMID */ | 74 | /* Switch to requested VMID */ |
26 | kvm = kern_hyp_va(kvm); | 75 | kvm = kern_hyp_va(kvm); |
27 | write_sysreg(kvm->arch.vttbr, vttbr_el2); | 76 | __tlb_switch_to_guest()(kvm); |
28 | isb(); | ||
29 | 77 | ||
30 | /* | 78 | /* |
31 | * We could do so much better if we had the VA as well. | 79 | * We could do so much better if we had the VA as well. |
@@ -46,7 +94,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) | |||
46 | dsb(ish); | 94 | dsb(ish); |
47 | isb(); | 95 | isb(); |
48 | 96 | ||
49 | write_sysreg(0, vttbr_el2); | 97 | __tlb_switch_to_host()(kvm); |
50 | } | 98 | } |
51 | 99 | ||
52 | void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) | 100 | void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) |
@@ -55,14 +103,13 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) | |||
55 | 103 | ||
56 | /* Switch to requested VMID */ | 104 | /* Switch to requested VMID */ |
57 | kvm = kern_hyp_va(kvm); | 105 | kvm = kern_hyp_va(kvm); |
58 | write_sysreg(kvm->arch.vttbr, vttbr_el2); | 106 | __tlb_switch_to_guest()(kvm); |
59 | isb(); | ||
60 | 107 | ||
61 | __tlbi(vmalls12e1is); | 108 | __tlbi(vmalls12e1is); |
62 | dsb(ish); | 109 | dsb(ish); |
63 | isb(); | 110 | isb(); |
64 | 111 | ||
65 | write_sysreg(0, vttbr_el2); | 112 | __tlb_switch_to_host()(kvm); |
66 | } | 113 | } |
67 | 114 | ||
68 | void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) | 115 | void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) |
@@ -70,14 +117,13 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) | |||
70 | struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm); | 117 | struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm); |
71 | 118 | ||
72 | /* Switch to requested VMID */ | 119 | /* Switch to requested VMID */ |
73 | write_sysreg(kvm->arch.vttbr, vttbr_el2); | 120 | __tlb_switch_to_guest()(kvm); |
74 | isb(); | ||
75 | 121 | ||
76 | __tlbi(vmalle1); | 122 | __tlbi(vmalle1); |
77 | dsb(nsh); | 123 | dsb(nsh); |
78 | isb(); | 124 | isb(); |
79 | 125 | ||
80 | write_sysreg(0, vttbr_el2); | 126 | __tlb_switch_to_host()(kvm); |
81 | } | 127 | } |
82 | 128 | ||
83 | void __hyp_text __kvm_flush_vm_context(void) | 129 | void __hyp_text __kvm_flush_vm_context(void) |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 283aa8601833..98e82ee1e699 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -7258,9 +7258,8 @@ static int handle_vmoff(struct kvm_vcpu *vcpu) | |||
7258 | static int handle_vmclear(struct kvm_vcpu *vcpu) | 7258 | static int handle_vmclear(struct kvm_vcpu *vcpu) |
7259 | { | 7259 | { |
7260 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 7260 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
7261 | u32 zero = 0; | ||
7261 | gpa_t vmptr; | 7262 | gpa_t vmptr; |
7262 | struct vmcs12 *vmcs12; | ||
7263 | struct page *page; | ||
7264 | 7263 | ||
7265 | if (!nested_vmx_check_permission(vcpu)) | 7264 | if (!nested_vmx_check_permission(vcpu)) |
7266 | return 1; | 7265 | return 1; |
@@ -7271,22 +7270,9 @@ static int handle_vmclear(struct kvm_vcpu *vcpu) | |||
7271 | if (vmptr == vmx->nested.current_vmptr) | 7270 | if (vmptr == vmx->nested.current_vmptr) |
7272 | nested_release_vmcs12(vmx); | 7271 | nested_release_vmcs12(vmx); |
7273 | 7272 | ||
7274 | page = nested_get_page(vcpu, vmptr); | 7273 | kvm_vcpu_write_guest(vcpu, |
7275 | if (page == NULL) { | 7274 | vmptr + offsetof(struct vmcs12, launch_state), |
7276 | /* | 7275 | &zero, sizeof(zero)); |
7277 | * For accurate processor emulation, VMCLEAR beyond available | ||
7278 | * physical memory should do nothing at all. However, it is | ||
7279 | * possible that a nested vmx bug, not a guest hypervisor bug, | ||
7280 | * resulted in this case, so let's shut down before doing any | ||
7281 | * more damage: | ||
7282 | */ | ||
7283 | kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); | ||
7284 | return 1; | ||
7285 | } | ||
7286 | vmcs12 = kmap(page); | ||
7287 | vmcs12->launch_state = 0; | ||
7288 | kunmap(page); | ||
7289 | nested_release_page(page); | ||
7290 | 7276 | ||
7291 | nested_free_vmcs02(vmx, vmptr); | 7277 | nested_free_vmcs02(vmx, vmptr); |
7292 | 7278 | ||
@@ -9694,10 +9680,8 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu, | |||
9694 | return false; | 9680 | return false; |
9695 | 9681 | ||
9696 | page = nested_get_page(vcpu, vmcs12->msr_bitmap); | 9682 | page = nested_get_page(vcpu, vmcs12->msr_bitmap); |
9697 | if (!page) { | 9683 | if (!page) |
9698 | WARN_ON(1); | ||
9699 | return false; | 9684 | return false; |
9700 | } | ||
9701 | msr_bitmap_l1 = (unsigned long *)kmap(page); | 9685 | msr_bitmap_l1 = (unsigned long *)kmap(page); |
9702 | 9686 | ||
9703 | memset(msr_bitmap_l0, 0xff, PAGE_SIZE); | 9687 | memset(msr_bitmap_l0, 0xff, PAGE_SIZE); |
@@ -11121,8 +11105,10 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, | |||
11121 | */ | 11105 | */ |
11122 | static void vmx_leave_nested(struct kvm_vcpu *vcpu) | 11106 | static void vmx_leave_nested(struct kvm_vcpu *vcpu) |
11123 | { | 11107 | { |
11124 | if (is_guest_mode(vcpu)) | 11108 | if (is_guest_mode(vcpu)) { |
11109 | to_vmx(vcpu)->nested.nested_run_pending = 0; | ||
11125 | nested_vmx_vmexit(vcpu, -1, 0, 0); | 11110 | nested_vmx_vmexit(vcpu, -1, 0, 0); |
11111 | } | ||
11126 | free_nested(to_vmx(vcpu)); | 11112 | free_nested(to_vmx(vcpu)); |
11127 | } | 11113 | } |
11128 | 11114 | ||
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 672cfef72fc8..97cbca19430d 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h | |||
@@ -373,6 +373,8 @@ | |||
373 | #define ICC_IGRPEN0_EL1_MASK (1 << ICC_IGRPEN0_EL1_SHIFT) | 373 | #define ICC_IGRPEN0_EL1_MASK (1 << ICC_IGRPEN0_EL1_SHIFT) |
374 | #define ICC_IGRPEN1_EL1_SHIFT 0 | 374 | #define ICC_IGRPEN1_EL1_SHIFT 0 |
375 | #define ICC_IGRPEN1_EL1_MASK (1 << ICC_IGRPEN1_EL1_SHIFT) | 375 | #define ICC_IGRPEN1_EL1_MASK (1 << ICC_IGRPEN1_EL1_SHIFT) |
376 | #define ICC_SRE_EL1_DIB (1U << 2) | ||
377 | #define ICC_SRE_EL1_DFB (1U << 1) | ||
376 | #define ICC_SRE_EL1_SRE (1U << 0) | 378 | #define ICC_SRE_EL1_SRE (1U << 0) |
377 | 379 | ||
378 | /* | 380 | /* |
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 571b64a01c50..8d1da1af4b09 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
@@ -360,29 +360,6 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) | |||
360 | return ret; | 360 | return ret; |
361 | } | 361 | } |
362 | 362 | ||
363 | static unsigned long vgic_mmio_read_its_ctlr(struct kvm *vcpu, | ||
364 | struct vgic_its *its, | ||
365 | gpa_t addr, unsigned int len) | ||
366 | { | ||
367 | u32 reg = 0; | ||
368 | |||
369 | mutex_lock(&its->cmd_lock); | ||
370 | if (its->creadr == its->cwriter) | ||
371 | reg |= GITS_CTLR_QUIESCENT; | ||
372 | if (its->enabled) | ||
373 | reg |= GITS_CTLR_ENABLE; | ||
374 | mutex_unlock(&its->cmd_lock); | ||
375 | |||
376 | return reg; | ||
377 | } | ||
378 | |||
379 | static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its, | ||
380 | gpa_t addr, unsigned int len, | ||
381 | unsigned long val) | ||
382 | { | ||
383 | its->enabled = !!(val & GITS_CTLR_ENABLE); | ||
384 | } | ||
385 | |||
386 | static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm, | 363 | static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm, |
387 | struct vgic_its *its, | 364 | struct vgic_its *its, |
388 | gpa_t addr, unsigned int len) | 365 | gpa_t addr, unsigned int len) |
@@ -1161,33 +1138,16 @@ static void vgic_mmio_write_its_cbaser(struct kvm *kvm, struct vgic_its *its, | |||
1161 | #define ITS_CMD_SIZE 32 | 1138 | #define ITS_CMD_SIZE 32 |
1162 | #define ITS_CMD_OFFSET(reg) ((reg) & GENMASK(19, 5)) | 1139 | #define ITS_CMD_OFFSET(reg) ((reg) & GENMASK(19, 5)) |
1163 | 1140 | ||
1164 | /* | 1141 | /* Must be called with the cmd_lock held. */ |
1165 | * By writing to CWRITER the guest announces new commands to be processed. | 1142 | static void vgic_its_process_commands(struct kvm *kvm, struct vgic_its *its) |
1166 | * To avoid any races in the first place, we take the its_cmd lock, which | ||
1167 | * protects our ring buffer variables, so that there is only one user | ||
1168 | * per ITS handling commands at a given time. | ||
1169 | */ | ||
1170 | static void vgic_mmio_write_its_cwriter(struct kvm *kvm, struct vgic_its *its, | ||
1171 | gpa_t addr, unsigned int len, | ||
1172 | unsigned long val) | ||
1173 | { | 1143 | { |
1174 | gpa_t cbaser; | 1144 | gpa_t cbaser; |
1175 | u64 cmd_buf[4]; | 1145 | u64 cmd_buf[4]; |
1176 | u32 reg; | ||
1177 | 1146 | ||
1178 | if (!its) | 1147 | /* Commands are only processed when the ITS is enabled. */ |
1179 | return; | 1148 | if (!its->enabled) |
1180 | |||
1181 | mutex_lock(&its->cmd_lock); | ||
1182 | |||
1183 | reg = update_64bit_reg(its->cwriter, addr & 7, len, val); | ||
1184 | reg = ITS_CMD_OFFSET(reg); | ||
1185 | if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser)) { | ||
1186 | mutex_unlock(&its->cmd_lock); | ||
1187 | return; | 1149 | return; |
1188 | } | ||
1189 | 1150 | ||
1190 | its->cwriter = reg; | ||
1191 | cbaser = CBASER_ADDRESS(its->cbaser); | 1151 | cbaser = CBASER_ADDRESS(its->cbaser); |
1192 | 1152 | ||
1193 | while (its->cwriter != its->creadr) { | 1153 | while (its->cwriter != its->creadr) { |
@@ -1207,6 +1167,34 @@ static void vgic_mmio_write_its_cwriter(struct kvm *kvm, struct vgic_its *its, | |||
1207 | if (its->creadr == ITS_CMD_BUFFER_SIZE(its->cbaser)) | 1167 | if (its->creadr == ITS_CMD_BUFFER_SIZE(its->cbaser)) |
1208 | its->creadr = 0; | 1168 | its->creadr = 0; |
1209 | } | 1169 | } |
1170 | } | ||
1171 | |||
1172 | /* | ||
1173 | * By writing to CWRITER the guest announces new commands to be processed. | ||
1174 | * To avoid any races in the first place, we take the its_cmd lock, which | ||
1175 | * protects our ring buffer variables, so that there is only one user | ||
1176 | * per ITS handling commands at a given time. | ||
1177 | */ | ||
1178 | static void vgic_mmio_write_its_cwriter(struct kvm *kvm, struct vgic_its *its, | ||
1179 | gpa_t addr, unsigned int len, | ||
1180 | unsigned long val) | ||
1181 | { | ||
1182 | u64 reg; | ||
1183 | |||
1184 | if (!its) | ||
1185 | return; | ||
1186 | |||
1187 | mutex_lock(&its->cmd_lock); | ||
1188 | |||
1189 | reg = update_64bit_reg(its->cwriter, addr & 7, len, val); | ||
1190 | reg = ITS_CMD_OFFSET(reg); | ||
1191 | if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser)) { | ||
1192 | mutex_unlock(&its->cmd_lock); | ||
1193 | return; | ||
1194 | } | ||
1195 | its->cwriter = reg; | ||
1196 | |||
1197 | vgic_its_process_commands(kvm, its); | ||
1210 | 1198 | ||
1211 | mutex_unlock(&its->cmd_lock); | 1199 | mutex_unlock(&its->cmd_lock); |
1212 | } | 1200 | } |
@@ -1287,6 +1275,39 @@ static void vgic_mmio_write_its_baser(struct kvm *kvm, | |||
1287 | *regptr = reg; | 1275 | *regptr = reg; |
1288 | } | 1276 | } |
1289 | 1277 | ||
1278 | static unsigned long vgic_mmio_read_its_ctlr(struct kvm *vcpu, | ||
1279 | struct vgic_its *its, | ||
1280 | gpa_t addr, unsigned int len) | ||
1281 | { | ||
1282 | u32 reg = 0; | ||
1283 | |||
1284 | mutex_lock(&its->cmd_lock); | ||
1285 | if (its->creadr == its->cwriter) | ||
1286 | reg |= GITS_CTLR_QUIESCENT; | ||
1287 | if (its->enabled) | ||
1288 | reg |= GITS_CTLR_ENABLE; | ||
1289 | mutex_unlock(&its->cmd_lock); | ||
1290 | |||
1291 | return reg; | ||
1292 | } | ||
1293 | |||
1294 | static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its, | ||
1295 | gpa_t addr, unsigned int len, | ||
1296 | unsigned long val) | ||
1297 | { | ||
1298 | mutex_lock(&its->cmd_lock); | ||
1299 | |||
1300 | its->enabled = !!(val & GITS_CTLR_ENABLE); | ||
1301 | |||
1302 | /* | ||
1303 | * Try to process any pending commands. This function bails out early | ||
1304 | * if the ITS is disabled or no commands have been queued. | ||
1305 | */ | ||
1306 | vgic_its_process_commands(kvm, its); | ||
1307 | |||
1308 | mutex_unlock(&its->cmd_lock); | ||
1309 | } | ||
1310 | |||
1290 | #define REGISTER_ITS_DESC(off, rd, wr, length, acc) \ | 1311 | #define REGISTER_ITS_DESC(off, rd, wr, length, acc) \ |
1291 | { \ | 1312 | { \ |
1292 | .reg_offset = off, \ | 1313 | .reg_offset = off, \ |
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c index 3654b4c835ef..2a5db1352722 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.c +++ b/virt/kvm/arm/vgic/vgic-mmio.c | |||
@@ -180,21 +180,37 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu, | |||
180 | static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq, | 180 | static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq, |
181 | bool new_active_state) | 181 | bool new_active_state) |
182 | { | 182 | { |
183 | struct kvm_vcpu *requester_vcpu; | ||
183 | spin_lock(&irq->irq_lock); | 184 | spin_lock(&irq->irq_lock); |
185 | |||
186 | /* | ||
187 | * The vcpu parameter here can mean multiple things depending on how | ||
188 | * this function is called; when handling a trap from the kernel it | ||
189 | * depends on the GIC version, and these functions are also called as | ||
190 | * part of save/restore from userspace. | ||
191 | * | ||
192 | * Therefore, we have to figure out the requester in a reliable way. | ||
193 | * | ||
194 | * When accessing VGIC state from user space, the requester_vcpu is | ||
195 | * NULL, which is fine, because we guarantee that no VCPUs are running | ||
196 | * when accessing VGIC state from user space so irq->vcpu->cpu is | ||
197 | * always -1. | ||
198 | */ | ||
199 | requester_vcpu = kvm_arm_get_running_vcpu(); | ||
200 | |||
184 | /* | 201 | /* |
185 | * If this virtual IRQ was written into a list register, we | 202 | * If this virtual IRQ was written into a list register, we |
186 | * have to make sure the CPU that runs the VCPU thread has | 203 | * have to make sure the CPU that runs the VCPU thread has |
187 | * synced back LR state to the struct vgic_irq. We can only | 204 | * synced back the LR state to the struct vgic_irq. |
188 | * know this for sure, when either this irq is not assigned to | ||
189 | * anyone's AP list anymore, or the VCPU thread is not | ||
190 | * running on any CPUs. | ||
191 | * | 205 | * |
192 | * In the opposite case, we know the VCPU thread may be on its | 206 | * As long as the conditions below are true, we know the VCPU thread |
193 | * way back from the guest and still has to sync back this | 207 | * may be on its way back from the guest (we kicked the VCPU thread in |
194 | * IRQ, so we release and re-acquire the spin_lock to let the | 208 | * vgic_change_active_prepare) and still has to sync back this IRQ, |
195 | * other thread sync back the IRQ. | 209 | * so we release and re-acquire the spin_lock to let the other thread |
210 | * sync back the IRQ. | ||
196 | */ | 211 | */ |
197 | while (irq->vcpu && /* IRQ may have state in an LR somewhere */ | 212 | while (irq->vcpu && /* IRQ may have state in an LR somewhere */ |
213 | irq->vcpu != requester_vcpu && /* Current thread is not the VCPU thread */ | ||
198 | irq->vcpu->cpu != -1) /* VCPU thread is running */ | 214 | irq->vcpu->cpu != -1) /* VCPU thread is running */ |
199 | cond_resched_lock(&irq->irq_lock); | 215 | cond_resched_lock(&irq->irq_lock); |
200 | 216 | ||
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index edc6ee2dc852..be0f4c3e0142 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c | |||
@@ -229,10 +229,13 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu) | |||
229 | /* | 229 | /* |
230 | * If we are emulating a GICv3, we do it in an non-GICv2-compatible | 230 | * If we are emulating a GICv3, we do it in an non-GICv2-compatible |
231 | * way, so we force SRE to 1 to demonstrate this to the guest. | 231 | * way, so we force SRE to 1 to demonstrate this to the guest. |
232 | * Also, we don't support any form of IRQ/FIQ bypass. | ||
232 | * This goes with the spec allowing the value to be RAO/WI. | 233 | * This goes with the spec allowing the value to be RAO/WI. |
233 | */ | 234 | */ |
234 | if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { | 235 | if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { |
235 | vgic_v3->vgic_sre = ICC_SRE_EL1_SRE; | 236 | vgic_v3->vgic_sre = (ICC_SRE_EL1_DIB | |
237 | ICC_SRE_EL1_DFB | | ||
238 | ICC_SRE_EL1_SRE); | ||
236 | vcpu->arch.vgic_cpu.pendbaser = INITIAL_PENDBASER_VALUE; | 239 | vcpu->arch.vgic_cpu.pendbaser = INITIAL_PENDBASER_VALUE; |
237 | } else { | 240 | } else { |
238 | vgic_v3->vgic_sre = 0; | 241 | vgic_v3->vgic_sre = 0; |