diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-01-02 10:09:54 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2016-02-29 13:34:13 -0500 |
commit | 1d58d2cbf723704e070d560507787b9912b63839 (patch) | |
tree | f8da6533b1d7029c35a867c8881de179aca90da1 | |
parent | 3c29568768dfe6965ca51e1a78f9f31ebc0c500a (diff) |
ARM: KVM: Add TLB invalidation code
Convert the TLB invalidation code to C, hooking it into the
build system whilst we're at it.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | arch/arm/kvm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kvm/hyp/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/kvm/hyp/hyp.h | 5 | ||||
-rw-r--r-- | arch/arm/kvm/hyp/tlb.c | 70 |
4 files changed, 81 insertions, 0 deletions
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index c5eef02c52ba..eb1bf4309c13 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile | |||
@@ -17,6 +17,7 @@ AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt) | |||
17 | KVM := ../../../virt/kvm | 17 | KVM := ../../../virt/kvm |
18 | kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o | 18 | kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o |
19 | 19 | ||
20 | obj-$(CONFIG_KVM_ARM_HOST) += hyp/ | ||
20 | obj-y += kvm-arm.o init.o interrupts.o | 21 | obj-y += kvm-arm.o init.o interrupts.o |
21 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o | 22 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o |
22 | obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o | 23 | obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o |
diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile new file mode 100644 index 000000000000..36c760df2360 --- /dev/null +++ b/arch/arm/kvm/hyp/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for Kernel-based Virtual Machine module, HYP part | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_KVM_ARM_HOST) += tlb.o | ||
diff --git a/arch/arm/kvm/hyp/hyp.h b/arch/arm/kvm/hyp/hyp.h index 727089f0ddb6..5808bbd38c5f 100644 --- a/arch/arm/kvm/hyp/hyp.h +++ b/arch/arm/kvm/hyp/hyp.h | |||
@@ -42,4 +42,9 @@ | |||
42 | }) | 42 | }) |
43 | #define read_sysreg(...) __read_sysreg(__VA_ARGS__) | 43 | #define read_sysreg(...) __read_sysreg(__VA_ARGS__) |
44 | 44 | ||
45 | #define VTTBR __ACCESS_CP15_64(6, c2) | ||
46 | #define ICIALLUIS __ACCESS_CP15(c7, 0, c1, 0) | ||
47 | #define TLBIALLIS __ACCESS_CP15(c8, 0, c3, 0) | ||
48 | #define TLBIALLNSNHIS __ACCESS_CP15(c8, 4, c3, 4) | ||
49 | |||
45 | #endif /* __ARM_KVM_HYP_H__ */ | 50 | #endif /* __ARM_KVM_HYP_H__ */ |
diff --git a/arch/arm/kvm/hyp/tlb.c b/arch/arm/kvm/hyp/tlb.c new file mode 100644 index 000000000000..aaa44bbac766 --- /dev/null +++ b/arch/arm/kvm/hyp/tlb.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Original code: | ||
3 | * Copyright (C) 2012 - Virtual Open Systems and Columbia University | ||
4 | * Author: Christoffer Dall <c.dall@virtualopensystems.com> | ||
5 | * | ||
6 | * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include "hyp.h" | ||
22 | |||
23 | /** | ||
24 | * Flush per-VMID TLBs | ||
25 | * | ||
26 | * __kvm_tlb_flush_vmid(struct kvm *kvm); | ||
27 | * | ||
28 | * We rely on the hardware to broadcast the TLB invalidation to all CPUs | ||
29 | * inside the inner-shareable domain (which is the case for all v7 | ||
30 | * implementations). If we come across a non-IS SMP implementation, we'll | ||
31 | * have to use an IPI based mechanism. Until then, we stick to the simple | ||
32 | * hardware assisted version. | ||
33 | * | ||
34 | * As v7 does not support flushing per IPA, just nuke the whole TLB | ||
35 | * instead, ignoring the ipa value. | ||
36 | */ | ||
37 | static void __hyp_text __tlb_flush_vmid(struct kvm *kvm) | ||
38 | { | ||
39 | dsb(ishst); | ||
40 | |||
41 | /* Switch to requested VMID */ | ||
42 | kvm = kern_hyp_va(kvm); | ||
43 | write_sysreg(kvm->arch.vttbr, VTTBR); | ||
44 | isb(); | ||
45 | |||
46 | write_sysreg(0, TLBIALLIS); | ||
47 | dsb(ish); | ||
48 | isb(); | ||
49 | |||
50 | write_sysreg(0, VTTBR); | ||
51 | } | ||
52 | |||
53 | __alias(__tlb_flush_vmid) void __weak __kvm_tlb_flush_vmid(struct kvm *kvm); | ||
54 | |||
55 | static void __hyp_text __tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) | ||
56 | { | ||
57 | __tlb_flush_vmid(kvm); | ||
58 | } | ||
59 | |||
60 | __alias(__tlb_flush_vmid_ipa) void __weak __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, | ||
61 | phys_addr_t ipa); | ||
62 | |||
63 | static void __hyp_text __tlb_flush_vm_context(void) | ||
64 | { | ||
65 | write_sysreg(0, TLBIALLNSNHIS); | ||
66 | write_sysreg(0, ICIALLUIS); | ||
67 | dsb(ish); | ||
68 | } | ||
69 | |||
70 | __alias(__tlb_flush_vm_context) void __weak __kvm_flush_vm_context(void); | ||