* [PATCH v5 1/7] arm64: tlb: Refactor the core flush algorithm of __flush_tlb_range
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 2/7] KVM: arm64: Implement __kvm_tlb_flush_vmid_range() Raghavendra Rao Ananta
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm, Catalin Marinas
Currently, the core TLB flush functionality of __flush_tlb_range()
hardcodes vae1is (and variants) for the flush operation. In the
upcoming patches, the KVM code reuses this core algorithm with
ipas2e1is for range based TLB invalidations based on the IPA.
Hence, extract the core flush functionality of __flush_tlb_range()
into its own macro that accepts an 'op' argument to pass any
TLBI operation, such that other callers (KVM) can benefit.
No functional changes intended.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 108 +++++++++++++++---------------
1 file changed, 55 insertions(+), 53 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 412a3b9a3c25d..4775378b6da1b 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -278,14 +278,61 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
*/
#define MAX_TLBI_OPS PTRS_PER_PTE
+/* When the CPU does not support TLB range operations, flush the TLB
+ * entries one by one at the granularity of 'stride'. If the TLB
+ * range ops are supported, then:
+ *
+ * 1. If 'pages' is odd, flush the first page through non-range
+ * operations;
+ *
+ * 2. For remaining pages: the minimum range granularity is decided
+ * by 'scale', so multiple range TLBI operations may be required.
+ * Start from scale = 0, flush the corresponding number of pages
+ * ((num+1)*2^(5*scale+1) starting from 'addr'), then increase it
+ * until no pages left.
+ *
+ * Note that certain ranges can be represented by either num = 31 and
+ * scale or num = 0 and scale + 1. The loop below favours the latter
+ * since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
+ */
+#define __flush_tlb_range_op(op, start, pages, stride, \
+ asid, tlb_level, tlbi_user) do { \
+ int num = 0; \
+ int scale = 0; \
+ unsigned long addr; \
+ \
+ while (pages > 0) { \
+ if (!system_supports_tlb_range() || \
+ pages % 2 == 1) { \
+ addr = __TLBI_VADDR(start, asid); \
+ __tlbi_level(op, addr, tlb_level); \
+ if (tlbi_user) \
+ __tlbi_user_level(op, addr, tlb_level); \
+ start += stride; \
+ pages -= stride >> PAGE_SHIFT; \
+ continue; \
+ } \
+ \
+ num = __TLBI_RANGE_NUM(pages, scale); \
+ if (num >= 0) { \
+ addr = __TLBI_VADDR_RANGE(start, asid, scale, \
+ num, tlb_level); \
+ __tlbi(r##op, addr); \
+ if (tlbi_user) \
+ __tlbi_user(r##op, addr); \
+ start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
+ pages -= __TLBI_RANGE_PAGES(num, scale); \
+ } \
+ scale++; \
+ } \
+} while (0)
+
static inline void __flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end,
unsigned long stride, bool last_level,
int tlb_level)
{
- int num = 0;
- int scale = 0;
- unsigned long asid, addr, pages;
+ unsigned long asid, pages;
start = round_down(start, stride);
end = round_up(end, stride);
@@ -307,56 +354,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
dsb(ishst);
asid = ASID(vma->vm_mm);
- /*
- * When the CPU does not support TLB range operations, flush the TLB
- * entries one by one at the granularity of 'stride'. If the TLB
- * range ops are supported, then:
- *
- * 1. If 'pages' is odd, flush the first page through non-range
- * operations;
- *
- * 2. For remaining pages: the minimum range granularity is decided
- * by 'scale', so multiple range TLBI operations may be required.
- * Start from scale = 0, flush the corresponding number of pages
- * ((num+1)*2^(5*scale+1) starting from 'addr'), then increase it
- * until no pages left.
- *
- * Note that certain ranges can be represented by either num = 31 and
- * scale or num = 0 and scale + 1. The loop below favours the latter
- * since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
- */
- while (pages > 0) {
- if (!system_supports_tlb_range() ||
- pages % 2 == 1) {
- addr = __TLBI_VADDR(start, asid);
- if (last_level) {
- __tlbi_level(vale1is, addr, tlb_level);
- __tlbi_user_level(vale1is, addr, tlb_level);
- } else {
- __tlbi_level(vae1is, addr, tlb_level);
- __tlbi_user_level(vae1is, addr, tlb_level);
- }
- start += stride;
- pages -= stride >> PAGE_SHIFT;
- continue;
- }
-
- num = __TLBI_RANGE_NUM(pages, scale);
- if (num >= 0) {
- addr = __TLBI_VADDR_RANGE(start, asid, scale,
- num, tlb_level);
- if (last_level) {
- __tlbi(rvale1is, addr);
- __tlbi_user(rvale1is, addr);
- } else {
- __tlbi(rvae1is, addr);
- __tlbi_user(rvae1is, addr);
- }
- start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT;
- pages -= __TLBI_RANGE_PAGES(num, scale);
- }
- scale++;
- }
+ if (last_level)
+ __flush_tlb_range_op(vale1is, start, pages, stride, asid, tlb_level, true);
+ else
+ __flush_tlb_range_op(vae1is, start, pages, stride, asid, tlb_level, true);
+
dsb(ish);
}
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 2/7] KVM: arm64: Implement __kvm_tlb_flush_vmid_range()
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 1/7] arm64: tlb: Refactor the core flush algorithm of __flush_tlb_range Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 3/7] KVM: arm64: Define kvm_tlb_flush_vmid_range() Raghavendra Rao Ananta
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm
Define __kvm_tlb_flush_vmid_range() (for VHE and nVHE)
to flush a range of stage-2 page-tables using IPA in one go.
If the system supports FEAT_TLBIRANGE, the following patches
would conviniently replace global TLBI such as vmalls12e1is
in the map, unmap, and dirty-logging paths with ripas2e1is
instead.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
---
arch/arm64/include/asm/kvm_asm.h | 3 +++
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 11 +++++++++++
arch/arm64/kvm/hyp/nvhe/tlb.c | 30 ++++++++++++++++++++++++++++++
arch/arm64/kvm/hyp/vhe/tlb.c | 28 ++++++++++++++++++++++++++++
4 files changed, 72 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 43c3bc0f9544d..60ed0880cc9d6 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -69,6 +69,7 @@ enum __kvm_host_smccc_func {
__KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context,
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa,
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid,
+ __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_range,
__KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context,
__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
__KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr,
@@ -225,6 +226,8 @@ extern void __kvm_flush_vm_context(void);
extern void __kvm_flush_cpu_context(struct kvm_s2_mmu *mmu);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa,
int level);
+extern void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ phys_addr_t start, unsigned long pages);
extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu);
extern void __kvm_timer_set_cntvoff(u64 cntvoff);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 728e01d4536b0..a19a9299c8362 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -125,6 +125,16 @@ static void handle___kvm_tlb_flush_vmid_ipa(struct kvm_cpu_context *host_ctxt)
__kvm_tlb_flush_vmid_ipa(kern_hyp_va(mmu), ipa, level);
}
+static void
+handle___kvm_tlb_flush_vmid_range(struct kvm_cpu_context *host_ctxt)
+{
+ DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1);
+ DECLARE_REG(phys_addr_t, start, host_ctxt, 2);
+ DECLARE_REG(unsigned long, pages, host_ctxt, 3);
+
+ __kvm_tlb_flush_vmid_range(kern_hyp_va(mmu), start, pages);
+}
+
static void handle___kvm_tlb_flush_vmid(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1);
@@ -316,6 +326,7 @@ static const hcall_t host_hcall[] = {
HANDLE_FUNC(__kvm_flush_vm_context),
HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa),
HANDLE_FUNC(__kvm_tlb_flush_vmid),
+ HANDLE_FUNC(__kvm_tlb_flush_vmid_range),
HANDLE_FUNC(__kvm_flush_cpu_context),
HANDLE_FUNC(__kvm_timer_set_cntvoff),
HANDLE_FUNC(__vgic_v3_read_vmcr),
diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c
index 978179133f4b9..213b11952f641 100644
--- a/arch/arm64/kvm/hyp/nvhe/tlb.c
+++ b/arch/arm64/kvm/hyp/nvhe/tlb.c
@@ -130,6 +130,36 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
__tlb_switch_to_host(&cxt);
}
+void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ phys_addr_t start, unsigned long pages)
+{
+ struct tlb_inv_context cxt;
+ unsigned long stride;
+
+ /*
+ * Since the range of addresses may not be mapped at
+ * the same level, assume the worst case as PAGE_SIZE
+ */
+ stride = PAGE_SIZE;
+ start = round_down(start, stride);
+
+ /* Switch to requested VMID */
+ __tlb_switch_to_guest(mmu, &cxt, false);
+
+ __flush_tlb_range_op(ipas2e1is, start, pages, stride, 0, 0, false);
+
+ dsb(ish);
+ __tlbi(vmalle1is);
+ dsb(ish);
+ isb();
+
+ /* See the comment below in __kvm_tlb_flush_vmid_ipa() */
+ if (icache_is_vpipt())
+ icache_inval_all_pou();
+
+ __tlb_switch_to_host(&cxt);
+}
+
void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
{
struct tlb_inv_context cxt;
diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c
index 24cef9b87f9e9..3ca3d38b7eb23 100644
--- a/arch/arm64/kvm/hyp/vhe/tlb.c
+++ b/arch/arm64/kvm/hyp/vhe/tlb.c
@@ -111,6 +111,34 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
__tlb_switch_to_host(&cxt);
}
+void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ phys_addr_t start, unsigned long pages)
+{
+ struct tlb_inv_context cxt;
+ unsigned long stride;
+
+ /*
+ * Since the range of addresses may not be mapped at
+ * the same level, assume the worst case as PAGE_SIZE
+ */
+ stride = PAGE_SIZE;
+ start = round_down(start, stride);
+
+ dsb(ishst);
+
+ /* Switch to requested VMID */
+ __tlb_switch_to_guest(mmu, &cxt);
+
+ __flush_tlb_range_op(ipas2e1is, start, pages, stride, 0, 0, false);
+
+ dsb(ish);
+ __tlbi(vmalle1is);
+ dsb(ish);
+ isb();
+
+ __tlb_switch_to_host(&cxt);
+}
+
void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
{
struct tlb_inv_context cxt;
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 3/7] KVM: arm64: Define kvm_tlb_flush_vmid_range()
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 1/7] arm64: tlb: Refactor the core flush algorithm of __flush_tlb_range Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 2/7] KVM: arm64: Implement __kvm_tlb_flush_vmid_range() Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 4/7] KVM: arm64: Implement kvm_arch_flush_remote_tlbs_range() Raghavendra Rao Ananta
` (4 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm
Implement the helper kvm_tlb_flush_vmid_range() that acts
as a wrapper for range-based TLB invalidations. For the
given VMID, use the range-based TLBI instructions to do
the job or fallback to invalidating all the TLB entries.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
---
arch/arm64/include/asm/kvm_pgtable.h | 10 ++++++++++
arch/arm64/kvm/hyp/pgtable.c | 20 ++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 4cd6762bda805..1b12295a83595 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -682,4 +682,14 @@ enum kvm_pgtable_prot kvm_pgtable_stage2_pte_prot(kvm_pte_t pte);
* kvm_pgtable_prot format.
*/
enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte);
+
+/**
+ * kvm_tlb_flush_vmid_range() - Invalidate/flush a range of TLB entries
+ *
+ * @mmu: Stage-2 KVM MMU struct
+ * @addr: The base Intermediate physical address from which to invalidate
+ * @size: Size of the range from the base to invalidate
+ */
+void kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ phys_addr_t addr, size_t size);
#endif /* __ARM64_KVM_PGTABLE_H__ */
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 3d61bd3e591d2..df8ac14d9d3d4 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -631,6 +631,26 @@ static bool stage2_has_fwb(struct kvm_pgtable *pgt)
return !(pgt->flags & KVM_PGTABLE_S2_NOFWB);
}
+void kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ phys_addr_t addr, size_t size)
+{
+ unsigned long pages, inval_pages;
+
+ if (!system_supports_tlb_range()) {
+ kvm_call_hyp(__kvm_tlb_flush_vmid, mmu);
+ return;
+ }
+
+ pages = size >> PAGE_SHIFT;
+ while (pages > 0) {
+ inval_pages = min(pages, MAX_TLBI_RANGE_PAGES);
+ kvm_call_hyp(__kvm_tlb_flush_vmid_range, mmu, addr, inval_pages);
+
+ addr += inval_pages << PAGE_SHIFT;
+ pages -= inval_pages;
+ }
+}
+
#define KVM_S2_MEMATTR(pgt, attr) PAGE_S2_MEMATTR(attr, stage2_has_fwb(pgt))
static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot prot,
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 4/7] KVM: arm64: Implement kvm_arch_flush_remote_tlbs_range()
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
` (2 preceding siblings ...)
2023-06-06 19:28 ` [PATCH v5 3/7] KVM: arm64: Define kvm_tlb_flush_vmid_range() Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 5/7] KVM: arm64: Flush only the memslot after write-protect Raghavendra Rao Ananta
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm
Implement kvm_arch_flush_remote_tlbs_range() for arm64
to invalidate the given range in the TLB.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
---
arch/arm64/include/asm/kvm_host.h | 3 +++
arch/arm64/kvm/mmu.c | 7 +++++++
2 files changed, 10 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 81ab41b84f436..343fb530eea9c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1081,6 +1081,9 @@ struct kvm *kvm_arch_alloc_vm(void);
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS
int kvm_arch_flush_remote_tlbs(struct kvm *kvm);
+#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE
+int kvm_arch_flush_remote_tlbs_range(struct kvm *kvm, gfn_t start_gfn, u64 pages);
+
static inline bool kvm_vm_is_protected(struct kvm *kvm)
{
return false;
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index d0a0d3dca9316..c3ec2141c3284 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -92,6 +92,13 @@ int kvm_arch_flush_remote_tlbs(struct kvm *kvm)
return 0;
}
+int kvm_arch_flush_remote_tlbs_range(struct kvm *kvm, gfn_t start_gfn, u64 pages)
+{
+ kvm_tlb_flush_vmid_range(&kvm->arch.mmu,
+ start_gfn << PAGE_SHIFT, pages << PAGE_SHIFT);
+ return 0;
+}
+
static bool kvm_is_device_pfn(unsigned long pfn)
{
return !pfn_is_map_memory(pfn);
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 5/7] KVM: arm64: Flush only the memslot after write-protect
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
` (3 preceding siblings ...)
2023-06-06 19:28 ` [PATCH v5 4/7] KVM: arm64: Implement kvm_arch_flush_remote_tlbs_range() Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 6/7] KVM: arm64: Invalidate the table entries upon a range Raghavendra Rao Ananta
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm
After write-protecting the region, currently KVM invalidates
the entire TLB entries using kvm_flush_remote_tlbs(). Instead,
scope the invalidation only to the targeted memslot. If
supported, the architecture would use the range-based TLBI
instructions to flush the memslot or else fallback to flushing
all of the TLBs.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
---
arch/arm64/kvm/mmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index c3ec2141c3284..94f10e670c100 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -992,7 +992,7 @@ static void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot)
write_lock(&kvm->mmu_lock);
stage2_wp_range(&kvm->arch.mmu, start, end);
write_unlock(&kvm->mmu_lock);
- kvm_flush_remote_tlbs(kvm);
+ kvm_flush_remote_tlbs_memslot(kvm, memslot);
}
/**
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 6/7] KVM: arm64: Invalidate the table entries upon a range
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
` (4 preceding siblings ...)
2023-06-06 19:28 ` [PATCH v5 5/7] KVM: arm64: Flush only the memslot after write-protect Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-06 19:28 ` [PATCH v5 7/7] KVM: arm64: Use TLBI range-based intructions for unmap Raghavendra Rao Ananta
2023-06-14 12:19 ` [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Oliver Upton
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm
Currently, during the operations such as a hugepage collapse,
KVM would flush the entire VM's context using 'vmalls12e1is'
TLBI operation. Specifically, if the VM is faulting on many
hugepages (say after dirty-logging), it creates a performance
penalty for the guest whose pages have already been faulted
earlier as they would have to refill their TLBs again.
Instead, leverage kvm_tlb_flush_vmid_range() for table entries.
If the system supports it, only the required range will be
flushed. Else, it'll fallback to the previous mechanism.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
---
arch/arm64/kvm/hyp/pgtable.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index df8ac14d9d3d4..50ef7623c54db 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -766,7 +766,8 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
* value (if any).
*/
if (kvm_pte_table(ctx->old, ctx->level))
- kvm_call_hyp(__kvm_tlb_flush_vmid, mmu);
+ kvm_tlb_flush_vmid_range(mmu, ctx->addr,
+ kvm_granule_size(ctx->level));
else if (kvm_pte_valid(ctx->old))
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ctx->level);
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 7/7] KVM: arm64: Use TLBI range-based intructions for unmap
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
` (5 preceding siblings ...)
2023-06-06 19:28 ` [PATCH v5 6/7] KVM: arm64: Invalidate the table entries upon a range Raghavendra Rao Ananta
@ 2023-06-06 19:28 ` Raghavendra Rao Ananta
2023-06-14 12:19 ` [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Oliver Upton
7 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-06 19:28 UTC (permalink / raw)
To: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose
Cc: Paolo Bonzini, Jing Zhang, Colton Lewis, Raghavendra Rao Anata,
linux-arm-kernel, kvmarm, linux-kernel, kvm
The current implementation of the stage-2 unmap walker traverses
the given range and, as a part of break-before-make, performs
TLB invalidations with a DSB for every PTE. A multitude of this
combination could cause a performance bottleneck on some systems.
Hence, if the system supports FEAT_TLBIRANGE, defer the TLB
invalidations until the entire walk is finished, and then
use range-based instructions to invalidate the TLBs in one go.
Condition deferred TLB invalidation on the system supporting FWB,
as the optimization is entirely pointless when the unmap walker
needs to perform CMOs.
Rename stage2_put_pte() to stage2_unmap_put_pte() as the function
now serves the stage-2 unmap walker specifically, rather than
acting generic.
Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
---
arch/arm64/kvm/hyp/pgtable.c | 67 +++++++++++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 50ef7623c54db..c6e080867919d 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -789,16 +789,54 @@ static void stage2_make_pte(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_t n
smp_store_release(ctx->ptep, new);
}
-static void stage2_put_pte(const struct kvm_pgtable_visit_ctx *ctx, struct kvm_s2_mmu *mmu,
- struct kvm_pgtable_mm_ops *mm_ops)
+struct stage2_unmap_data {
+ struct kvm_pgtable *pgt;
+ bool defer_tlb_flush_init;
+};
+
+static bool __stage2_unmap_defer_tlb_flush(struct kvm_pgtable *pgt)
+{
+ /*
+ * If FEAT_TLBIRANGE is implemented, defer the individual
+ * TLB invalidations until the entire walk is finished, and
+ * then use the range-based TLBI instructions to do the
+ * invalidations. Condition deferred TLB invalidation on the
+ * system supporting FWB, as the optimization is entirely
+ * pointless when the unmap walker needs to perform CMOs.
+ */
+ return system_supports_tlb_range() && stage2_has_fwb(pgt);
+}
+
+static bool stage2_unmap_defer_tlb_flush(struct stage2_unmap_data *unmap_data)
+{
+ bool defer_tlb_flush = __stage2_unmap_defer_tlb_flush(unmap_data->pgt);
+
+ /*
+ * Since __stage2_unmap_defer_tlb_flush() is based on alternative
+ * patching and the TLBIs' operations behavior depend on this,
+ * track if there's any change in the state during the unmap sequence.
+ */
+ WARN_ON(unmap_data->defer_tlb_flush_init != defer_tlb_flush);
+ return defer_tlb_flush;
+}
+
+static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx,
+ struct kvm_s2_mmu *mmu,
+ struct kvm_pgtable_mm_ops *mm_ops)
{
+ struct stage2_unmap_data *unmap_data = ctx->arg;
+
/*
- * Clear the existing PTE, and perform break-before-make with
- * TLB maintenance if it was valid.
+ * Clear the existing PTE, and perform break-before-make if it was
+ * valid. Depending on the system support, the TLB maintenance for
+ * the same can be deferred until the entire unmap is completed.
*/
if (kvm_pte_valid(ctx->old)) {
kvm_clear_pte(ctx->ptep);
- kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ctx->level);
+
+ if (!stage2_unmap_defer_tlb_flush(unmap_data))
+ kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
+ ctx->addr, ctx->level);
}
mm_ops->put_page(ctx->ptep);
@@ -1005,7 +1043,8 @@ int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
enum kvm_pgtable_walk_flags visit)
{
- struct kvm_pgtable *pgt = ctx->arg;
+ struct stage2_unmap_data *unmap_data = ctx->arg;
+ struct kvm_pgtable *pgt = unmap_data->pgt;
struct kvm_s2_mmu *mmu = pgt->mmu;
struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops;
kvm_pte_t *childp = NULL;
@@ -1033,7 +1072,7 @@ static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
* block entry and rely on the remaining portions being faulted
* back lazily.
*/
- stage2_put_pte(ctx, mmu, mm_ops);
+ stage2_unmap_put_pte(ctx, mmu, mm_ops);
if (need_flush && mm_ops->dcache_clean_inval_poc)
mm_ops->dcache_clean_inval_poc(kvm_pte_follow(ctx->old, mm_ops),
@@ -1047,13 +1086,23 @@ static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
int kvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
{
+ int ret;
+ struct stage2_unmap_data unmap_data = {
+ .pgt = pgt,
+ .defer_tlb_flush_init = __stage2_unmap_defer_tlb_flush(pgt),
+ };
struct kvm_pgtable_walker walker = {
.cb = stage2_unmap_walker,
- .arg = pgt,
+ .arg = &unmap_data,
.flags = KVM_PGTABLE_WALK_LEAF | KVM_PGTABLE_WALK_TABLE_POST,
};
- return kvm_pgtable_walk(pgt, addr, size, &walker);
+ ret = kvm_pgtable_walk(pgt, addr, size, &walker);
+ if (stage2_unmap_defer_tlb_flush(&unmap_data))
+ /* Perform the deferred TLB invalidations */
+ kvm_tlb_flush_vmid_range(pgt->mmu, addr, size);
+
+ return ret;
}
struct stage2_attr_data {
--
2.41.0.rc0.172.g3f132b7071-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE
2023-06-06 19:28 [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Raghavendra Rao Ananta
` (6 preceding siblings ...)
2023-06-06 19:28 ` [PATCH v5 7/7] KVM: arm64: Use TLBI range-based intructions for unmap Raghavendra Rao Ananta
@ 2023-06-14 12:19 ` Oliver Upton
2023-06-15 1:57 ` Raghavendra Rao Ananta
7 siblings, 1 reply; 13+ messages in thread
From: Oliver Upton @ 2023-06-14 12:19 UTC (permalink / raw)
To: Raghavendra Rao Ananta
Cc: Marc Zyngier, James Morse, Suzuki K Poulose, Paolo Bonzini,
Jing Zhang, Colton Lewis, linux-arm-kernel, kvmarm, linux-kernel,
kvm
Hi Raghavendra,
On Tue, Jun 06, 2023 at 07:28:51PM +0000, Raghavendra Rao Ananta wrote:
> The series is based off of upstream v6.4-rc2, and applied David
> Matlack's common API for TLB invalidations[1] on top.
Sorry I didn't spot the dependency earlier, but this isn't helpful TBH.
David's series was partially applied, and what remains no longer cleanly
applies to the base you suggest. Independent of that, my *strong*
preference is that you just send out a series containing your patches as
well as David's. Coordinating dependent efforts is the only sane thing
to do. Also, those patches are 5 months old at this point which is
ancient history.
> [1]:
> https://lore.kernel.org/linux-arm-kernel/20230126184025.2294823-1-dmatlack@google.com/
--
Thanks,
Oliver
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE
2023-06-14 12:19 ` [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE Oliver Upton
@ 2023-06-15 1:57 ` Raghavendra Rao Ananta
2023-06-15 8:39 ` Oliver Upton
0 siblings, 1 reply; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-15 1:57 UTC (permalink / raw)
To: Oliver Upton
Cc: Marc Zyngier, James Morse, Suzuki K Poulose, Paolo Bonzini,
Jing Zhang, Colton Lewis, linux-arm-kernel, kvmarm, linux-kernel,
kvm
On Wed, Jun 14, 2023 at 5:19 AM Oliver Upton <oliver.upton@linux.dev> wrote:
>
> Hi Raghavendra,
>
> On Tue, Jun 06, 2023 at 07:28:51PM +0000, Raghavendra Rao Ananta wrote:
> > The series is based off of upstream v6.4-rc2, and applied David
> > Matlack's common API for TLB invalidations[1] on top.
>
> Sorry I didn't spot the dependency earlier, but this isn't helpful TBH.
>
> David's series was partially applied, and what remains no longer cleanly
> applies to the base you suggest. Independent of that, my *strong*
> preference is that you just send out a series containing your patches as
> well as David's. Coordinating dependent efforts is the only sane thing
> to do. Also, those patches are 5 months old at this point which is
> ancient history.
>
Would you rather prefer I detach this series from David's as I'm not
sure what his plans are for future versions?
On the other hand, the patches seem simple enough to rebase and give
another shot at review, but may end up delaying this series.
WDYT?
Thank you.
Raghavendra
> > [1]:
> > https://lore.kernel.org/linux-arm-kernel/20230126184025.2294823-1-dmatlack@google.com/
>
> --
> Thanks,
> Oliver
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE
2023-06-15 1:57 ` Raghavendra Rao Ananta
@ 2023-06-15 8:39 ` Oliver Upton
2023-06-15 14:14 ` Sean Christopherson
0 siblings, 1 reply; 13+ messages in thread
From: Oliver Upton @ 2023-06-15 8:39 UTC (permalink / raw)
To: Raghavendra Rao Ananta
Cc: Marc Zyngier, James Morse, Suzuki K Poulose, Paolo Bonzini,
Jing Zhang, Colton Lewis, linux-arm-kernel, kvmarm, linux-kernel,
kvm, seanjc
+cc Sean
On Wed, Jun 14, 2023 at 06:57:01PM -0700, Raghavendra Rao Ananta wrote:
> On Wed, Jun 14, 2023 at 5:19 AM Oliver Upton <oliver.upton@linux.dev> wrote:
> >
> > Hi Raghavendra,
> >
> > On Tue, Jun 06, 2023 at 07:28:51PM +0000, Raghavendra Rao Ananta wrote:
> > > The series is based off of upstream v6.4-rc2, and applied David
> > > Matlack's common API for TLB invalidations[1] on top.
> >
> > Sorry I didn't spot the dependency earlier, but this isn't helpful TBH.
> >
> > David's series was partially applied, and what remains no longer cleanly
> > applies to the base you suggest. Independent of that, my *strong*
> > preference is that you just send out a series containing your patches as
> > well as David's. Coordinating dependent efforts is the only sane thing
> > to do. Also, those patches are 5 months old at this point which is
> > ancient history.
> >
> Would you rather prefer I detach this series from David's as I'm not
> sure what his plans are for future versions?
> On the other hand, the patches seem simple enough to rebase and give
> another shot at review, but may end up delaying this series.
> WDYT?
In cases such as this you'd typically coordinate with the other
developer to pick up their changes as part of your series. Especially
for this case -- David's refactoring is _pointless_ without another
user for that code (i.e. arm64). As fun as it might be to antagonize
Sean, that series pokes x86 and I'd like an ack from on it.
So, please post a combined series that applies cleanly to an early 6.4
rc of your choosing, and cc all affected reviewers/maintainers.
--
Thanks,
Oliver
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE
2023-06-15 8:39 ` Oliver Upton
@ 2023-06-15 14:14 ` Sean Christopherson
2023-06-15 17:26 ` Raghavendra Rao Ananta
0 siblings, 1 reply; 13+ messages in thread
From: Sean Christopherson @ 2023-06-15 14:14 UTC (permalink / raw)
To: Oliver Upton
Cc: Raghavendra Rao Ananta, Marc Zyngier, James Morse,
Suzuki K Poulose, Paolo Bonzini, Jing Zhang, Colton Lewis,
linux-arm-kernel, kvmarm, linux-kernel, kvm
On Thu, Jun 15, 2023, Oliver Upton wrote:
> +cc Sean
>
> On Wed, Jun 14, 2023 at 06:57:01PM -0700, Raghavendra Rao Ananta wrote:
> > On Wed, Jun 14, 2023 at 5:19 AM Oliver Upton <oliver.upton@linux.dev> wrote:
> > >
> > > Hi Raghavendra,
> > >
> > > On Tue, Jun 06, 2023 at 07:28:51PM +0000, Raghavendra Rao Ananta wrote:
> > > > The series is based off of upstream v6.4-rc2, and applied David
> > > > Matlack's common API for TLB invalidations[1] on top.
> > >
> > > Sorry I didn't spot the dependency earlier, but this isn't helpful TBH.
> > >
> > > David's series was partially applied, and what remains no longer cleanly
> > > applies to the base you suggest. Independent of that, my *strong*
> > > preference is that you just send out a series containing your patches as
> > > well as David's. Coordinating dependent efforts is the only sane thing
> > > to do. Also, those patches are 5 months old at this point which is
> > > ancient history.
> > >
> > Would you rather prefer I detach this series from David's as I'm not
> > sure what his plans are for future versions?
> > On the other hand, the patches seem simple enough to rebase and give
> > another shot at review, but may end up delaying this series.
> > WDYT?
>
> In cases such as this you'd typically coordinate with the other
> developer to pick up their changes as part of your series. Especially
> for this case -- David's refactoring is _pointless_ without another
> user for that code (i.e. arm64). As fun as it might be to antagonize
> Sean, that series pokes x86 and I'd like an ack from on it.
>
> So, please post a combined series that applies cleanly to an early 6.4
> rc of your choosing, and cc all affected reviewers/maintainers.
+1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 0/7] KVM: arm64: Add support for FEAT_TLBIRANGE
2023-06-15 14:14 ` Sean Christopherson
@ 2023-06-15 17:26 ` Raghavendra Rao Ananta
0 siblings, 0 replies; 13+ messages in thread
From: Raghavendra Rao Ananta @ 2023-06-15 17:26 UTC (permalink / raw)
To: Sean Christopherson
Cc: Oliver Upton, Marc Zyngier, James Morse, Suzuki K Poulose,
Paolo Bonzini, Jing Zhang, Colton Lewis, linux-arm-kernel, kvmarm,
linux-kernel, kvm
Allright, I'll resend the series along with David's patches.
Thank you.
Raghavendra
On Thu, Jun 15, 2023 at 7:14 AM Sean Christopherson <seanjc@google.com> wrote:
>
> On Thu, Jun 15, 2023, Oliver Upton wrote:
> > +cc Sean
> >
> > On Wed, Jun 14, 2023 at 06:57:01PM -0700, Raghavendra Rao Ananta wrote:
> > > On Wed, Jun 14, 2023 at 5:19 AM Oliver Upton <oliver.upton@linux.dev> wrote:
> > > >
> > > > Hi Raghavendra,
> > > >
> > > > On Tue, Jun 06, 2023 at 07:28:51PM +0000, Raghavendra Rao Ananta wrote:
> > > > > The series is based off of upstream v6.4-rc2, and applied David
> > > > > Matlack's common API for TLB invalidations[1] on top.
> > > >
> > > > Sorry I didn't spot the dependency earlier, but this isn't helpful TBH.
> > > >
> > > > David's series was partially applied, and what remains no longer cleanly
> > > > applies to the base you suggest. Independent of that, my *strong*
> > > > preference is that you just send out a series containing your patches as
> > > > well as David's. Coordinating dependent efforts is the only sane thing
> > > > to do. Also, those patches are 5 months old at this point which is
> > > > ancient history.
> > > >
> > > Would you rather prefer I detach this series from David's as I'm not
> > > sure what his plans are for future versions?
> > > On the other hand, the patches seem simple enough to rebase and give
> > > another shot at review, but may end up delaying this series.
> > > WDYT?
> >
> > In cases such as this you'd typically coordinate with the other
> > developer to pick up their changes as part of your series. Especially
> > for this case -- David's refactoring is _pointless_ without another
> > user for that code (i.e. arm64). As fun as it might be to antagonize
> > Sean, that series pokes x86 and I'd like an ack from on it.
> >
> > So, please post a combined series that applies cleanly to an early 6.4
> > rc of your choosing, and cc all affected reviewers/maintainers.
>
> +1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 13+ messages in thread