Hi,
Major changes since v2 (Based on Will's feedback)
-Dropped adding a new static key and cpufeature for retrieving
supported VMID bits. Instead, we now make use of the
kvm_arm_vmid_bits variable (patch #2).
-Since we expect less frequent rollover in the case of VMIDs,
the TLB invalidation is now broadcasted on rollover instead
of keeping per CPU flush_pending info and issuing a local
context flush.
-Clear active_vmids on vCPU schedule out to avoid unnecessarily
reserving the VMID space(patch #3).
-I have kept the struct kvm_vmid as it is for now(instead of a
typedef as suggested), as we may soon add another variable to
it when we introduce Pinned KVM VMID support.
Sanity tested on HiSilicon D06 board.
Thanks,
Shameer
RFCv1 --> v2
- Dropped "pinned VMID" support for now.
- Dropped RFC tag.
History(from RFC v1):
-------------------
Please find the RFC series here,
https://lore.kernel.org/kvmarm/20210506165232.1969-1-shameerali.kolothum.thodi@huawei.com/
This is based on a suggestion from Will [0] to try out the asid
based kvm vmid solution as a separate VMID allocator instead of
the shared lib approach attempted in v4[1].
The idea is to compare both the approaches and see whether the
shared lib solution with callbacks make sense or not.
Though we are not yet using the pinned vmids yet, patch #2 has
code for pinned vmid support. This is just to help the comparison.
Test Setup/Results
----------------
The measurement was made with maxcpus set to 8 and with the
number of VMID limited to 4-bit. The test involves running
concurrently 40 guests with 2 vCPUs. Each guest will then
execute hackbench 5 times before exiting.
The performance difference between the current algo and the
new one are(avg. of 10 runs):
- 1.9% less entry/exit from the guest
- 0.5% faster
This is more or less comparable to v4 numbers.
For the complete series, please see,
https://github.com/hisilicon/kernel-dev/tree/private-v5.12-rc7-vmid-2nd-rfc
and for the shared asid lib v4 solution,
https://github.com/hisilicon/kernel-dev/tree/private-v5.12-rc7-asid-v4
As you can see there are ofcourse code duplication with this
approach but may be it is more easy to maintain considering
the complexity involved.
Please take a look and let me know your feedback.
Thanks,
Shameer
Julien Grall (1):
KVM: arm64: Align the VMID allocation with the arm64 ASID one
Shameer Kolothum (3):
KVM: arm64: Introduce a new VMID allocator for KVM
KVM: arm64: Make VMID bits accessible outside of allocator
KVM: arm64: Clear active_vmids on vCPU schedule out
arch/arm64/include/asm/kvm_host.h | 10 +-
arch/arm64/include/asm/kvm_mmu.h | 4 +-
arch/arm64/kernel/image-vars.h | 3 +
arch/arm64/kvm/Makefile | 2 +-
arch/arm64/kvm/arm.c | 122 +++++------------
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 3 +-
arch/arm64/kvm/mmu.c | 1 -
arch/arm64/kvm/vmid.c | 182 ++++++++++++++++++++++++++
8 files changed, 228 insertions(+), 99 deletions(-)
create mode 100644 arch/arm64/kvm/vmid.c
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
A new VMID allocator for arm64 KVM use. This is based on
arm64 ASID allocator algorithm.
One major deviation from the ASID allocator is the way we
flush the context. Unlike ASID allocator, we expect less
frequent rollover in the case of VMIDs. Hence, instead of
marking the CPU as flush_pending and issuing a local context
invalidation on the next context switch, we broadcast TLB
flush + I-cache invalidation over the inner shareable domain
on rollover.
Signed-off-by: Shameer Kolothum <redacted>
---
arch/arm64/include/asm/kvm_host.h | 4 +
arch/arm64/kvm/vmid.c | 176 ++++++++++++++++++++++++++++++
2 files changed, 180 insertions(+)
create mode 100644 arch/arm64/kvm/vmid.c
@@ -0,0 +1,176 @@+// SPDX-License-Identifier: GPL-2.0+/*+*VMIDallocator.+*+*BasedonArm64ASIDallocatoralgorithm.+*Pleasereferarch/arm64/mm/context.cfordetailed+*commentsonalgorithm.+*+*Copyright(C)2002-2003DeepBlueSolutionsLtd,allrightsreserved.+*Copyright(C)2012ARMLtd.+*/++#include<linux/bitfield.h>+#include<linux/bitops.h>++#include<asm/kvm_asm.h>+#include<asm/kvm_mmu.h>++staticunsignedintkvm_arm_vmid_bits;+staticDEFINE_RAW_SPINLOCK(cpu_vmid_lock);++staticatomic64_tvmid_generation;+staticunsignedlong*vmid_map;++staticDEFINE_PER_CPU(atomic64_t,active_vmids);+staticDEFINE_PER_CPU(u64,reserved_vmids);++#define VMID_MASK (~GENMASK(kvm_arm_vmid_bits - 1, 0))+#define VMID_FIRST_VERSION (1UL << kvm_arm_vmid_bits)++#define NUM_USER_VMIDS VMID_FIRST_VERSION+#define vmid2idx(vmid) ((vmid) & ~VMID_MASK)+#define idx2vmid(idx) vmid2idx(idx)++#define vmid_gen_match(vmid) \+(!(((vmid)^atomic64_read(&vmid_generation))>>kvm_arm_vmid_bits))++staticvoidflush_context(void)+{+intcpu;+u64vmid;++bitmap_clear(vmid_map,0,NUM_USER_VMIDS);++for_each_possible_cpu(cpu){+vmid=atomic64_xchg_relaxed(&per_cpu(active_vmids,cpu),0);++/* Preserve reserved VMID */+if(vmid==0)+vmid=per_cpu(reserved_vmids,cpu);+__set_bit(vmid2idx(vmid),vmid_map);+per_cpu(reserved_vmids,cpu)=vmid;+}++/*+*UnlikeASIDallocator,weexpectlessfrequentrolloverin+*caseofVMIDs.Hence,insteadofmarkingtheCPUas+*flush_pendingandissuingalocalcontextinvalidationon+*thenextcontext-switch,webroadcastTLBflush+I-cache+*invalidationovertheinnershareabledomainonrollover.+*/+kvm_call_hyp(__kvm_flush_vm_context);+}++staticboolcheck_update_reserved_vmid(u64vmid,u64newvmid)+{+intcpu;+boolhit=false;++/*+*IterateoverthesetofreservedVMIDslookingforamatch+*andupdatetousenewvmid(i.e.thesameVMIDinthecurrent+*generation).+*/+for_each_possible_cpu(cpu){+if(per_cpu(reserved_vmids,cpu)==vmid){+hit=true;+per_cpu(reserved_vmids,cpu)=newvmid;+}+}++returnhit;+}++staticu64new_vmid(structkvm_vmid*kvm_vmid)+{+staticu32cur_idx=1;+u64vmid=atomic64_read(&kvm_vmid->id);+u64generation=atomic64_read(&vmid_generation);++if(vmid!=0){+u64newvmid=generation|(vmid&~VMID_MASK);++if(check_update_reserved_vmid(vmid,newvmid))+returnnewvmid;++if(!__test_and_set_bit(vmid2idx(vmid),vmid_map))+returnnewvmid;+}++vmid=find_next_zero_bit(vmid_map,NUM_USER_VMIDS,cur_idx);+if(vmid!=NUM_USER_VMIDS)+gotoset_vmid;++/* We're out of VMIDs, so increment the global generation count */+generation=atomic64_add_return_relaxed(VMID_FIRST_VERSION,+&vmid_generation);+flush_context();++/* We have more VMIDs than CPUs, so this will always succeed */+vmid=find_next_zero_bit(vmid_map,NUM_USER_VMIDS,1);++set_vmid:+__set_bit(vmid,vmid_map);+cur_idx=vmid;+returnidx2vmid(vmid)|generation;+}++voidkvm_arm_vmid_update(structkvm_vmid*kvm_vmid)+{+unsignedlongflags;+unsignedintcpu;+u64vmid,old_active_vmid;++vmid=atomic64_read(&kvm_vmid->id);++/*+*Pleaserefercommentsincheck_and_switch_context()in+*arch/arm64/mm/context.c.+*/+old_active_vmid=atomic64_read(this_cpu_ptr(&active_vmids));+if(old_active_vmid&&vmid_gen_match(vmid)&&+atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),+old_active_vmid,vmid))+return;++raw_spin_lock_irqsave(&cpu_vmid_lock,flags);++/* Check that our VMID belongs to the current generation. */+vmid=atomic64_read(&kvm_vmid->id);+if(!vmid_gen_match(vmid)){+vmid=new_vmid(kvm_vmid);+atomic64_set(&kvm_vmid->id,vmid);+}++cpu=smp_processor_id();++atomic64_set(this_cpu_ptr(&active_vmids),vmid);+raw_spin_unlock_irqrestore(&cpu_vmid_lock,flags);+}++/*+*InitializetheVMIDallocator+*/+intkvm_arm_vmid_alloc_init(void)+{+kvm_arm_vmid_bits=kvm_get_vmid_bits();++/*+*Expectallocationafterrollovertofailifwedon'thave+*atleastonemoreVMIDthanCPUs.VMID#0isalwaysreserved.+*/+WARN_ON(NUM_USER_VMIDS-1<=num_possible_cpus());+atomic64_set(&vmid_generation,VMID_FIRST_VERSION);+vmid_map=kcalloc(BITS_TO_LONGS(NUM_USER_VMIDS),+sizeof(*vmid_map),GFP_KERNEL);+if(!vmid_map)+return-ENOMEM;++return0;+}++voidkvm_arm_vmid_alloc_free(void)+{+kfree(vmid_map);+}
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Since we already set the kvm_arm_vmid_bits in the VMID allocator
init function, make it accessible outside as well so that it can
be used in the subsequent patch.
Suggested-by: Will Deacon <will@kernel.org>
Signed-off-by: Shameer Kolothum <redacted>
---
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/kernel/image-vars.h | 3 +++
arch/arm64/kvm/vmid.c | 2 +-
3 files changed, 5 insertions(+), 1 deletion(-)
@@ -79,6 +79,9 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors);/* Kernel symbol used by icache_is_vpipt(). */KVM_NVHE_ALIAS(__icache_flags);+/* VMID bits set by the KVM VMID allocator */+KVM_NVHE_ALIAS(kvm_arm_vmid_bits);+/* Kernel symbols needed for cpus_have_final/const_caps checks. */KVM_NVHE_ALIAS(arm64_const_caps_ready);KVM_NVHE_ALIAS(cpu_hwcap_keys);
From: Julien Grall <redacted>
At the moment, the VMID algorithm will send an SGI to all the
CPUs to force an exit and then broadcast a full TLB flush and
I-Cache invalidation.
This patch uses the new VMID allocator. The benefits are:
- Aligns with arm64 ASID algorithm.
- CPUs are not forced to exit at roll-over. Instead,
the VMID will be marked reserved and context invalidation
is broadcasted. This will reduce the IPIs traffic.
- More flexible to add support for pinned KVM VMIDs in
the future.
With the new algo, the code is now adapted:
- The call to update_vmid() will be done with preemption
disabled as the new algo requires to store information
per-CPU.
Signed-off-by: Julien Grall <redacted>
Signed-off-by: Shameer Kolothum <redacted>
---
arch/arm64/include/asm/kvm_host.h | 4 +-
arch/arm64/include/asm/kvm_mmu.h | 4 +-
arch/arm64/kvm/Makefile | 2 +-
arch/arm64/kvm/arm.c | 121 +++++++-------------------
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 3 +-
arch/arm64/kvm/mmu.c | 1 -
6 files changed, 36 insertions(+), 99 deletions(-)
@@ -71,9 +71,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu);voidkvm_arm_vcpu_destroy(structkvm_vcpu*vcpu);structkvm_vmid{-/* The VMID generation used for the virt. memory system */-u64vmid_gen;-u32vmid;+atomic64_tid;};structkvm_s2_mmu{
@@ -55,11 +55,6 @@ static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);unsignedlongkvm_arm_hyp_percpu_base[NR_CPUS];DECLARE_KVM_NVHE_PER_CPU(structkvm_nvhe_init_params,kvm_init_params);-/* The VMID used in the VTTBR */-staticatomic64_tkvm_vmid_gen=ATOMIC64_INIT(1);-staticu32kvm_next_vmid;-staticDEFINE_SPINLOCK(kvm_vmid_lock);-staticboolvgic_present;staticDEFINE_PER_CPU(unsignedchar,kvm_arm_hardware_enabled);
@@ -500,87 +495,6 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)returnvcpu_mode_priv(vcpu);}-/* Just ensure a guest exit from a particular CPU */-staticvoidexit_vm_noop(void*info)-{-}--voidforce_vm_exit(constcpumask_t*mask)-{-preempt_disable();-smp_call_function_many(mask,exit_vm_noop,NULL,true);-preempt_enable();-}--/**-*need_new_vmid_gen-checkthattheVMIDisstillvalid-*@vmid:TheVMIDtocheck-*-*returntrueifthereisanewgenerationofVMIDsbeingused-*-*Thehardwaresupportsalimitedsetofvalueswiththevaluezeroreserved-*forthehost,sowecheckifanassignedvaluebelongstoaprevious-*generation,whichrequiresustoassignanewvalue.Ifwe'rethefirstto-*useaVMIDforthenewgeneration,wemustflushnecessarycachesandTLBs-*onallCPUs.-*/-staticboolneed_new_vmid_gen(structkvm_vmid*vmid)-{-u64current_vmid_gen=atomic64_read(&kvm_vmid_gen);-smp_rmb();/* Orders read of kvm_vmid_gen and kvm->arch.vmid */-returnunlikely(READ_ONCE(vmid->vmid_gen)!=current_vmid_gen);-}--/**-*update_vmid-UpdatethevmidwithavalidVMIDforthecurrentgeneration-*@vmid:Thestage-2VMIDinformationstruct-*/-staticvoidupdate_vmid(structkvm_vmid*vmid)-{-if(!need_new_vmid_gen(vmid))-return;--spin_lock(&kvm_vmid_lock);--/*-*Weneedtore-checkthevmid_genheretoensurethatifanothervcpu-*alreadyallocatedavalidvmidforthisvm,thenthisvcpushould-*usethesamevmid.-*/-if(!need_new_vmid_gen(vmid)){-spin_unlock(&kvm_vmid_lock);-return;-}--/* First user of a new VMID generation? */-if(unlikely(kvm_next_vmid==0)){-atomic64_inc(&kvm_vmid_gen);-kvm_next_vmid=1;--/*-*OnSMPweknownootherCPUscanusethisCPU'soreach-*other'sVMIDafterforce_vm_exitreturnssincethe-*kvm_vmid_lockblocksthemfromreentrytotheguest.-*/-force_vm_exit(cpu_all_mask);-/*-*NowbroadcastTLB+ICACHEinvalidationovertheinner-*shareabledomaintomakesurealldatastructuresare-*clean.-*/-kvm_call_hyp(__kvm_flush_vm_context);-}--vmid->vmid=kvm_next_vmid;-kvm_next_vmid++;-kvm_next_vmid&=(1<<kvm_get_vmid_bits())-1;--smp_wmb();-WRITE_ONCE(vmid->vmid_gen,atomic64_read(&kvm_vmid_gen));--spin_unlock(&kvm_vmid_lock);-}-staticintkvm_vcpu_first_run_init(structkvm_vcpu*vcpu){structkvm*kvm=vcpu->kvm;
@@ -759,8 +673,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)*/cond_resched();-update_vmid(&vcpu->arch.hw_mmu->vmid);-check_vcpu_requests(vcpu);/*
@@ -770,6 +682,15 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)*/preempt_disable();+/*+*TheVMIDallocatoronlytracksactiveVMIDsper+*physicalCPU,andthereforetheVMIDallocatedmaynotbe+*preservedonVMIDroll-overifthetaskwaspreempted,+*makingathread'sVMIDinactive.Soweneedtocall+*kvm_arm_vmid_update()innon-premptiblecontext.+*/+kvm_arm_vmid_update(&vcpu->arch.hw_mmu->vmid);+kvm_pmu_flush_hwstate(vcpu);local_irq_disable();
@@ -808,8 +729,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)*/smp_store_mb(vcpu->mode,IN_GUEST_MODE);-if(ret<=0||need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid)||-kvm_request_pending(vcpu)){+if(ret<=0||kvm_request_pending(vcpu)){vcpu->mode=OUTSIDE_GUEST_MODE;isb();/* Ensure work in x_flush_hwstate is committed */kvm_pmu_sync_hwstate(vcpu);
Like ASID allocator, we copy the active_vmids into the
reserved_vmids on a rollover. But it's unlikely that
every CPU will have a vCPU as current task and we may
end up unnecessarily reserving the VMID space.
Hence, clear active_vmids when scheduling out a vCPU.
Suggested-by: Will Deacon <will@kernel.org>
Signed-off-by: Shameer Kolothum <redacted>
---
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/kvm/arm.c | 1 +
arch/arm64/kvm/vmid.c | 6 ++++++
3 files changed, 8 insertions(+)
From: Will Deacon <will@kernel.org> Date: 2021-08-03 11:39:07
On Thu, Jul 29, 2021 at 11:40:06AM +0100, Shameer Kolothum wrote:
A new VMID allocator for arm64 KVM use. This is based on
arm64 ASID allocator algorithm.
One major deviation from the ASID allocator is the way we
flush the context. Unlike ASID allocator, we expect less
frequent rollover in the case of VMIDs. Hence, instead of
marking the CPU as flush_pending and issuing a local context
invalidation on the next context switch, we broadcast TLB
flush + I-cache invalidation over the inner shareable domain
on rollover.
Signed-off-by: Shameer Kolothum <redacted>
---
[...]
+void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
+{
+ unsigned long flags;
+ unsigned int cpu;
+ u64 vmid, old_active_vmid;
+
+ vmid = atomic64_read(&kvm_vmid->id);
+
+ /*
+ * Please refer comments in check_and_switch_context() in
+ * arch/arm64/mm/context.c.
+ */
+ old_active_vmid = atomic64_read(this_cpu_ptr(&active_vmids));
+ if (old_active_vmid && vmid_gen_match(vmid) &&
+ atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),
+ old_active_vmid, vmid))
+ return;
+
+ raw_spin_lock_irqsave(&cpu_vmid_lock, flags);
+
+ /* Check that our VMID belongs to the current generation. */
+ vmid = atomic64_read(&kvm_vmid->id);
+ if (!vmid_gen_match(vmid)) {
+ vmid = new_vmid(kvm_vmid);
+ atomic64_set(&kvm_vmid->id, vmid);
From: Will Deacon <will@kernel.org> Date: 2021-08-03 11:40:43
On Thu, Jul 29, 2021 at 11:40:09AM +0100, Shameer Kolothum wrote:
quoted hunk
Like ASID allocator, we copy the active_vmids into the
reserved_vmids on a rollover. But it's unlikely that
every CPU will have a vCPU as current task and we may
end up unnecessarily reserving the VMID space.
Hence, clear active_vmids when scheduling out a vCPU.
Suggested-by: Will Deacon <will@kernel.org>
Signed-off-by: Shameer Kolothum <redacted>
---
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/kvm/arm.c | 1 +
arch/arm64/kvm/vmid.c | 6 ++++++
3 files changed, 8 insertions(+)
I think this is very broken, as it will force everybody to take the
slow-path when they see an active_vmid of 0.
It also doesn't solve the issue I mentioned before, as an active_vmid of 0
means that the reserved vmid is preserved.
Needs more thought...
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
-----Original Message-----
From: Will Deacon [mailto:will@kernel.org]
Sent: 03 August 2021 12:39
To: Shameerali Kolothum Thodi <redacted>
Cc: linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
linux-kernel@vger.kernel.org; maz@kernel.org; catalin.marinas@arm.com;
james.morse@arm.com; julien.thierry.kdev@gmail.com;
suzuki.poulose@arm.com; jean-philippe@linaro.org;
Alexandru.Elisei@arm.com; qperret@google.com; Linuxarm
[off-list ref]
Subject: Re: [PATCH v3 1/4] KVM: arm64: Introduce a new VMID allocator for
KVM
On Thu, Jul 29, 2021 at 11:40:06AM +0100, Shameer Kolothum wrote:
quoted
A new VMID allocator for arm64 KVM use. This is based on
arm64 ASID allocator algorithm.
One major deviation from the ASID allocator is the way we
flush the context. Unlike ASID allocator, we expect less
frequent rollover in the case of VMIDs. Hence, instead of
marking the CPU as flush_pending and issuing a local context
invalidation on the next context switch, we broadcast TLB
flush + I-cache invalidation over the inner shareable domain
on rollover.
Signed-off-by: Shameer Kolothum
[off-list ref]
quoted
---
[...]
quoted
+void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
+{
+ unsigned long flags;
+ unsigned int cpu;
+ u64 vmid, old_active_vmid;
+
+ vmid = atomic64_read(&kvm_vmid->id);
+
+ /*
+ * Please refer comments in check_and_switch_context() in
+ * arch/arm64/mm/context.c.
+ */
+ old_active_vmid = atomic64_read(this_cpu_ptr(&active_vmids));
+ if (old_active_vmid && vmid_gen_match(vmid) &&
+ atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),
+ old_active_vmid, vmid))
+ return;
+
+ raw_spin_lock_irqsave(&cpu_vmid_lock, flags);
+
+ /* Check that our VMID belongs to the current generation. */
+ vmid = atomic64_read(&kvm_vmid->id);
+ if (!vmid_gen_match(vmid)) {
+ vmid = new_vmid(kvm_vmid);
+ atomic64_set(&kvm_vmid->id, vmid);
new_vmid() can just set kvm_vmid->id directly
Ok.
quoted
+ }
+
+ cpu = smp_processor_id();
Why?
Left over from previous one. Forgot to remove
as we don't have the tlb_flush_pending check anymore.
Thanks,
Shameer
-----Original Message-----
From: Will Deacon [mailto:will@kernel.org]
Sent: 03 August 2021 12:41
To: Shameerali Kolothum Thodi <redacted>
Cc: linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
linux-kernel@vger.kernel.org; maz@kernel.org; catalin.marinas@arm.com;
james.morse@arm.com; julien.thierry.kdev@gmail.com;
suzuki.poulose@arm.com; jean-philippe@linaro.org;
Alexandru.Elisei@arm.com; qperret@google.com; Linuxarm
[off-list ref]
Subject: Re: [PATCH v3 4/4] KVM: arm64: Clear active_vmids on vCPU
schedule out
On Thu, Jul 29, 2021 at 11:40:09AM +0100, Shameer Kolothum wrote:
quoted
Like ASID allocator, we copy the active_vmids into the
reserved_vmids on a rollover. But it's unlikely that
every CPU will have a vCPU as current task and we may
end up unnecessarily reserving the VMID space.
Hence, clear active_vmids when scheduling out a vCPU.
Suggested-by: Will Deacon <will@kernel.org>
Signed-off-by: Shameer Kolothum
I think this is very broken, as it will force everybody to take the
slow-path when they see an active_vmid of 0.
Yes. I have seen that happening in my test setup.
It also doesn't solve the issue I mentioned before, as an active_vmid of 0
means that the reserved vmid is preserved.
Needs more thought...
How about we clear all the active_vmids in kvm_arch_free_vm() if it
matches the kvm_vmid->id ? But we may have to hold the lock
there.
Thanks,
Shameer
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
I think this is very broken, as it will force everybody to take the
slow-path when they see an active_vmid of 0.
Yes. I have seen that happening in my test setup.
Why didn't you say so?!
quoted
It also doesn't solve the issue I mentioned before, as an active_vmid of 0
means that the reserved vmid is preserved.
Needs more thought...
How about we clear all the active_vmids in kvm_arch_free_vm() if it
matches the kvm_vmid->id ? But we may have to hold the lock
there
I think we have to be really careful not to run into the "suspended
animation" problem described in ae120d9edfe9 ("ARM: 7767/1: let the ASID
allocator handle suspended animation") if we go down this road.
Maybe something along the lines of:
ROLLOVER
* Take lock
* Inc generation
=> This will force everybody down the slow path
* Record active VMIDs
* Broadcast TLBI
=> Only active VMIDs can be dirty
=> Reserve active VMIDs and mark as allocated
VCPU SCHED IN
* Set active VMID
* Check generation
* If mismatch then:
* Take lock
* Try to match a reserved VMID
* If no reserved VMID, allocate new
VCPU SCHED OUT
* Clear active VMID
but I'm not daft enough to think I got it right first time. I think it
needs both implementing *and* modelling in TLA+ before we merge it!
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
I think this is very broken, as it will force everybody to take the
slow-path when they see an active_vmid of 0.
Yes. I have seen that happening in my test setup.
Why didn't you say so?!
Sorry. I thought of getting some performance numbers with and
without this patch and measure the impact. But didn't quite get time
to finish it yet.
quoted
quoted
It also doesn't solve the issue I mentioned before, as an active_vmid of 0
means that the reserved vmid is preserved.
Needs more thought...
How about we clear all the active_vmids in kvm_arch_free_vm() if it
matches the kvm_vmid->id ? But we may have to hold the lock
there
I think we have to be really careful not to run into the "suspended
animation" problem described in ae120d9edfe9 ("ARM: 7767/1: let the ASID
allocator handle suspended animation") if we go down this road.
Ok. I will go through that.
Maybe something along the lines of:
ROLLOVER
* Take lock
* Inc generation
=> This will force everybody down the slow path
* Record active VMIDs
* Broadcast TLBI
=> Only active VMIDs can be dirty
=> Reserve active VMIDs and mark as allocated
VCPU SCHED IN
* Set active VMID
* Check generation
* If mismatch then:
* Take lock
* Try to match a reserved VMID
* If no reserved VMID, allocate new
VCPU SCHED OUT
* Clear active VMID
but I'm not daft enough to think I got it right first time. I think it
needs both implementing *and* modelling in TLA+ before we merge it!
Ok. I need some time to digest the above first :).
On another note, how serious do you think is the problem of extra
reservation of the VMID space? Just wondering if we can skip this
patch for now or not..
Thanks,
Shameer
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
I think this is very broken, as it will force everybody to take the
slow-path when they see an active_vmid of 0.
Yes. I have seen that happening in my test setup.
Why didn't you say so?!
Sorry. I thought of getting some performance numbers with and
without this patch and measure the impact. But didn't quite get time
to finish it yet.
These are some test numbers with and without this patch, run on two
different test setups.
a)Test Setup -1
-----------------------
Platform: HiSilicon D06 with 128 CPUs, VMID bits = 16
Run 128 VMs concurrently each with 2 vCPUs. Each Guest will execute hackbench
5 times before exiting.
Measurements taken avg. of 10 Runs.
Image : 5.14-rc3
---------------------------
Time(s) 44.43813888
No. of exits 145,348,264
Image: 5.14-rc3 + vmid-v3
----------------------------------------
Time(s) 46.59789034
No. of exits 133,587,307
%diff against 5.14-rc3
Time: 4.8% more
Exits: 8% less
Image: 5.14-rc3 + vmid-v3 + Without active_asid clear
---------------------------------------------------------------------------
Time(s) 44.5031782
No. of exits 144,443,188
%diff against 5.14-rc3
Time: 0.15% more
Exits: 2.42% less
b)Test Setup -2
-----------------------
Platform: HiSilicon D06 + Kernel with maxcpus set to 8 and VMID bits set to 4.
Run 40 VMs concurrently each with 2 vCPUs. Each Guest will execute hackbench
5 times before exiting.
Measurements taken avg. of 10 Runs.
Image : 5.14-rc3-vmid4bit
------------------------------------
Time(s) 46.19963266
No. of exits 23,699,546
Image: 5.14-rc3-vmid4bit + vmid-v3
---------------------------------------------------
Time(s) 45.83307736
No. of exits 23,260,203
%diff against 5.14-rc3-vmid4bit
Time: 0.8% less
Exits: 1.85% less
Image: 5.14-rc3-vmid4bit + vmid-v3 + Without active_asid clear
-----------------------------------------------------------------------------------------
Time(s) 44.5031782
No. of exits 144,443,188
%diff against 5.14-rc3-vmid4bit
Time: 1.05% less
Exits: 2.06% less
As expected, the active_asid clear on schedule out is not helping.
But without this patch, the numbers seems to be better than the
vanilla kernel when we force the setup(cpus=8, vmd=4bits)
to perform rollover.
Please let me know your thoughts.
Thanks,
Shameer
quoted
quoted
quoted
It also doesn't solve the issue I mentioned before, as an active_vmid of 0
means that the reserved vmid is preserved.
Needs more thought...
How about we clear all the active_vmids in kvm_arch_free_vm() if it
matches the kvm_vmid->id ? But we may have to hold the lock
there
I think we have to be really careful not to run into the "suspended
animation" problem described in ae120d9edfe9 ("ARM: 7767/1: let the ASID
allocator handle suspended animation") if we go down this road.
Ok. I will go through that.
quoted
Maybe something along the lines of:
ROLLOVER
* Take lock
* Inc generation
=> This will force everybody down the slow path
* Record active VMIDs
* Broadcast TLBI
=> Only active VMIDs can be dirty
=> Reserve active VMIDs and mark as allocated
VCPU SCHED IN
* Set active VMID
* Check generation
* If mismatch then:
* Take lock
* Try to match a reserved VMID
* If no reserved VMID, allocate new
VCPU SCHED OUT
* Clear active VMID
but I'm not daft enough to think I got it right first time. I think it
needs both implementing *and* modelling in TLA+ before we merge it!
Ok. I need some time to digest the above first :).
On another note, how serious do you think is the problem of extra
reservation of the VMID space? Just wondering if we can skip this
patch for now or not..
Thanks,
Shameer
From: Will Deacon <will@kernel.org> Date: 2021-08-09 13:09:26
On Fri, Aug 06, 2021 at 12:24:36PM +0000, Shameerali Kolothum Thodi wrote:
These are some test numbers with and without this patch, run on two
different test setups.
a)Test Setup -1
-----------------------
Platform: HiSilicon D06 with 128 CPUs, VMID bits = 16
Run 128 VMs concurrently each with 2 vCPUs. Each Guest will execute hackbench
5 times before exiting.
Measurements taken avg. of 10 Runs.
Image : 5.14-rc3
---------------------------
Time(s) 44.43813888
No. of exits 145,348,264
Image: 5.14-rc3 + vmid-v3
----------------------------------------
Time(s) 46.59789034
No. of exits 133,587,307
%diff against 5.14-rc3
Time: 4.8% more
Exits: 8% less
Image: 5.14-rc3 + vmid-v3 + Without active_asid clear
---------------------------------------------------------------------------
Time(s) 44.5031782
No. of exits 144,443,188
%diff against 5.14-rc3
Time: 0.15% more
Exits: 2.42% less
b)Test Setup -2
-----------------------
Platform: HiSilicon D06 + Kernel with maxcpus set to 8 and VMID bits set to 4.
Run 40 VMs concurrently each with 2 vCPUs. Each Guest will execute hackbench
5 times before exiting.
Measurements taken avg. of 10 Runs.
Image : 5.14-rc3-vmid4bit
------------------------------------
Time(s) 46.19963266
No. of exits 23,699,546
Image: 5.14-rc3-vmid4bit + vmid-v3
---------------------------------------------------
Time(s) 45.83307736
No. of exits 23,260,203
%diff against 5.14-rc3-vmid4bit
Time: 0.8% less
Exits: 1.85% less
Image: 5.14-rc3-vmid4bit + vmid-v3 + Without active_asid clear
-----------------------------------------------------------------------------------------
Time(s) 44.5031782
No. of exits 144,443,188
Really? The *exact* same numbers as the "Image: 5.14-rc3 + vmid-v3 + Without
active_asid clear" configuration? Guessing a copy-paste error here.
%diff against 5.14-rc3-vmid4bit
Time: 1.05% less
Exits: 2.06% less
As expected, the active_asid clear on schedule out is not helping.
But without this patch, the numbers seems to be better than the
vanilla kernel when we force the setup(cpus=8, vmd=4bits)
to perform rollover.
I'm struggling a bit to understand these numbers. Are you saying that
clearing the active_asid helps in the 16-bit VMID case but not in the
4-bit case?
Why would the active_asid clear have any impact on the number of exits?
The problem I see with not having the active_asid clear is that we will
roll over more frequently as the number of reserved VMIDs increases.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
-----Original Message-----
From: Will Deacon [mailto:will@kernel.org]
Sent: 09 August 2021 14:09
To: Shameerali Kolothum Thodi <redacted>
Cc: linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
linux-kernel@vger.kernel.org; maz@kernel.org; catalin.marinas@arm.com;
james.morse@arm.com; julien.thierry.kdev@gmail.com;
suzuki.poulose@arm.com; jean-philippe@linaro.org;
Alexandru.Elisei@arm.com; qperret@google.com; Linuxarm
[off-list ref]
Subject: Re: [PATCH v3 4/4] KVM: arm64: Clear active_vmids on vCPU
schedule out
On Fri, Aug 06, 2021 at 12:24:36PM +0000, Shameerali Kolothum Thodi
wrote:
quoted
These are some test numbers with and without this patch, run on two
different test setups.
a)Test Setup -1
-----------------------
Platform: HiSilicon D06 with 128 CPUs, VMID bits = 16
Run 128 VMs concurrently each with 2 vCPUs. Each Guest will execute
hackbench
quoted
5 times before exiting.
Measurements taken avg. of 10 Runs.
Image : 5.14-rc3
---------------------------
Time(s) 44.43813888
No. of exits 145,348,264
Image: 5.14-rc3 + vmid-v3
----------------------------------------
Time(s) 46.59789034
No. of exits 133,587,307
%diff against 5.14-rc3
Time: 4.8% more
Exits: 8% less
Image: 5.14-rc3 + vmid-v3 + Without active_asid clear
---------------------------------------------------------------------------
Time(s) 44.5031782
No. of exits 144,443,188
%diff against 5.14-rc3
Time: 0.15% more
Exits: 2.42% less
b)Test Setup -2
-----------------------
Platform: HiSilicon D06 + Kernel with maxcpus set to 8 and VMID bits set to
4.
quoted
Run 40 VMs concurrently each with 2 vCPUs. Each Guest will execute
hackbench
quoted
5 times before exiting.
Measurements taken avg. of 10 Runs.
Image : 5.14-rc3-vmid4bit
------------------------------------
Time(s) 46.19963266
No. of exits 23,699,546
Image: 5.14-rc3-vmid4bit + vmid-v3
---------------------------------------------------
Time(s) 45.83307736
No. of exits 23,260,203
%diff against 5.14-rc3-vmid4bit
Time: 0.8% less
Exits: 1.85% less
Image: 5.14-rc3-vmid4bit + vmid-v3 + Without active_asid clear
-----------------------------------------------------------------------------------------
Time(s) 44.5031782
No. of exits 144,443,188
Really? The *exact* same numbers as the "Image: 5.14-rc3 + vmid-v3 +
Without
active_asid clear" configuration? Guessing a copy-paste error here.
quoted
%diff against 5.14-rc3-vmid4bit
Time: 1.05% less
Exits: 2.06% less
As expected, the active_asid clear on schedule out is not helping.
But without this patch, the numbers seems to be better than the
vanilla kernel when we force the setup(cpus=8, vmd=4bits)
to perform rollover.
I'm struggling a bit to understand these numbers. Are you saying that
clearing the active_asid helps in the 16-bit VMID case but not in the
4-bit case?
Nope, the other way around.. The point I was trying to make is that
clearing the active_vmids definitely have an impact in 16-bit vmid
case, where rollover is not happening, as it ends up taking the slow
path more frequently.
Test setup-1, case 2(with active_vmids clear): Around 4.8% more time
to finish the test compared to vanilla kernel.
Test setup-1, case 3(Without clear): 0.15% more time compared to
vanilla kernel.
For the 4-bit vmid case, the impact of clearing vmids is not that obvious
probably because we have more rollovers.
Test setup-2, case 2(with active_vmids clear):0.8% less time compared to vanilla.
Test setup-2, case 3(Without clear): 1.05% less time compared to vanilla kernel.
So between the two(with and without clearing the active_vmids), the "without"
one has better numbers for both Test setups.
Why would the active_asid clear have any impact on the number of exits?
In 16 bit vmid case, it looks like the no. of exits is considerably lower if we clear
active_vmids. . Not sure it is because of the frequent slow path or not. But anyway,
the time to finish the test is higher.
The problem I see with not having the active_asid clear is that we will
roll over more frequently as the number of reserved VMIDs increases.
Ok. The idea of running the 4-bit test setup was to capture that. It doesn't
look like it has a major impact when compared to the original kernel. May be
I should take an average of more test runs. Please let me know if there is a
better way to measure that impact.
Hope, I am clear.
Thanks,
Shameer
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
-----Original Message-----
From: Will Deacon [mailto:will@kernel.org]
Sent: 03 August 2021 16:31
To: Shameerali Kolothum Thodi <redacted>
Cc: linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
linux-kernel@vger.kernel.org; maz@kernel.org; catalin.marinas@arm.com;
james.morse@arm.com; julien.thierry.kdev@gmail.com;
suzuki.poulose@arm.com; jean-philippe@linaro.org;
Alexandru.Elisei@arm.com; qperret@google.com; Linuxarm
[off-list ref]
Subject: Re: [PATCH v3 4/4] KVM: arm64: Clear active_vmids on vCPU
schedule out
[...]
I think we have to be really careful not to run into the "suspended
animation" problem described in ae120d9edfe9 ("ARM: 7767/1: let the ASID
allocator handle suspended animation") if we go down this road.
Maybe something along the lines of:
ROLLOVER
* Take lock
* Inc generation
=> This will force everybody down the slow path
* Record active VMIDs
* Broadcast TLBI
=> Only active VMIDs can be dirty
=> Reserve active VMIDs and mark as allocated
VCPU SCHED IN
* Set active VMID
* Check generation
* If mismatch then:
* Take lock
* Try to match a reserved VMID
* If no reserved VMID, allocate new
VCPU SCHED OUT
* Clear active VMID
but I'm not daft enough to think I got it right first time. I think it
needs both implementing *and* modelling in TLA+ before we merge it!
I attempted to implement the above algo as below. It seems to be
working in both 16-bit vmid and 4-bit vmid test setup. Though I am
not quite sure this Is exactly what you had in mind above and covers
all corner cases.
Please take a look and let me know.
(The diff below is against this v3 series)
Thanks,
Shameer
--->8<----
@@ -125,32 +125,17 @@ void kvm_arm_vmid_clear_active(void)voidkvm_arm_vmid_update(structkvm_vmid*kvm_vmid){unsignedlongflags;-u64vmid,old_active_vmid;+u64vmid;vmid=atomic64_read(&kvm_vmid->id);--/*-*Pleaserefercommentsincheck_and_switch_context()in-*arch/arm64/mm/context.c.-*/-old_active_vmid=atomic64_read(this_cpu_ptr(&active_vmids));-if(old_active_vmid&&vmid_gen_match(vmid)&&-atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),-old_active_vmid,vmid))+if(vmid_gen_match(vmid)){+atomic64_set(this_cpu_ptr(&active_vmids),vmid);return;--raw_spin_lock_irqsave(&cpu_vmid_lock,flags);--/* Check that our VMID belongs to the current generation. */-vmid=atomic64_read(&kvm_vmid->id);-if(!vmid_gen_match(vmid)){-vmid=new_vmid(kvm_vmid);-atomic64_set(&kvm_vmid->id,vmid);}-+raw_spin_lock_irqsave(&cpu_vmid_lock,flags);+vmid=new_vmid(kvm_vmid);+atomic64_set(&kvm_vmid->id,vmid);atomic64_set(this_cpu_ptr(&active_vmids),vmid);raw_spin_unlock_irqrestore(&cpu_vmid_lock,flags);}--->8<----
-----Original Message-----
From: Shameerali Kolothum Thodi
Sent: 11 August 2021 09:48
To: 'Will Deacon' <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
linux-kernel@vger.kernel.org; maz@kernel.org; catalin.marinas@arm.com;
james.morse@arm.com; julien.thierry.kdev@gmail.com;
suzuki.poulose@arm.com; jean-philippe@linaro.org;
Alexandru.Elisei@arm.com; qperret@google.com; Linuxarm
[off-list ref]
Subject: RE: [PATCH v3 4/4] KVM: arm64: Clear active_vmids on vCPU
schedule out
Hi Will,
quoted
-----Original Message-----
From: Will Deacon [mailto:will@kernel.org]
Sent: 03 August 2021 16:31
To: Shameerali Kolothum Thodi <redacted>
Cc: linux-arm-kernel@lists.infradead.org; kvmarm@lists.cs.columbia.edu;
linux-kernel@vger.kernel.org; maz@kernel.org; catalin.marinas@arm.com;
james.morse@arm.com; julien.thierry.kdev@gmail.com;
suzuki.poulose@arm.com; jean-philippe@linaro.org;
Alexandru.Elisei@arm.com; qperret@google.com; Linuxarm
[off-list ref]
Subject: Re: [PATCH v3 4/4] KVM: arm64: Clear active_vmids on vCPU
schedule out
[...]
quoted
I think we have to be really careful not to run into the "suspended
animation" problem described in ae120d9edfe9 ("ARM: 7767/1: let the ASID
allocator handle suspended animation") if we go down this road.
Maybe something along the lines of:
ROLLOVER
* Take lock
* Inc generation
=> This will force everybody down the slow path
* Record active VMIDs
* Broadcast TLBI
=> Only active VMIDs can be dirty
=> Reserve active VMIDs and mark as allocated
VCPU SCHED IN
* Set active VMID
* Check generation
* If mismatch then:
* Take lock
* Try to match a reserved VMID
* If no reserved VMID, allocate new
VCPU SCHED OUT
* Clear active VMID
but I'm not daft enough to think I got it right first time. I think it
needs both implementing *and* modelling in TLA+ before we merge it!
I attempted to implement the above algo as below. It seems to be
working in both 16-bit vmid and 4-bit vmid test setup.
It is not :(. I did an extended, overnight test run and it fails.
It looks to me in my below implementation there is no synchronization
on setting the active VMID and a concurrent rollover. I will have another go.
Thanks,
Shameer
Though I am
quoted hunk
not quite sure this Is exactly what you had in mind above and covers
all corner cases.
Please take a look and let me know.
(The diff below is against this v3 series)
Thanks,
Shameer
--->8<----