Re: [PATCH v3 1/3] arm/arm64: KVM: Use set/way op trapping to track the state of the caches
On Tue, Jan 27, 2015 at 01:44:05PM +, Marc Zyngier wrote: > On 27/01/15 13:17, Christoffer Dall wrote: > > On Tue, Jan 27, 2015 at 11:21:38AM +, Marc Zyngier wrote: > >> On 26/01/15 22:58, Christoffer Dall wrote: > >>> On Wed, Jan 21, 2015 at 06:39:46PM +, Marc Zyngier wrote: > Trying to emulate the behaviour of set/way cache ops is fairly > pointless, as there are too many ways we can end-up missing stuff. > Also, there is some system caches out there that simply ignore > set/way operations. > > So instead of trying to implement them, let's convert it to VA ops, > and use them as a way to re-enable the trapping of VM ops. That way, > we can detect the point when the MMU/caches are turned off, and do > a full VM flush (which is what the guest was trying to do anyway). > > This allows a 32bit zImage to boot on the APM thingy, and will > probably help bootloaders in general. > > Signed-off-by: Marc Zyngier > >>> > >>> This had some conflicts with dirty page logging. I fixed it up here, > >>> and also removed some trailing white space and mixed spaces/tabs that > >>> patch complained about: > >>> > >>> http://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git mm-fixes > >> > >> Thanks for doing so. > >> > --- > arch/arm/include/asm/kvm_emulate.h | 10 + > arch/arm/include/asm/kvm_host.h | 3 -- > arch/arm/include/asm/kvm_mmu.h | 3 +- > arch/arm/kvm/arm.c | 10 - > arch/arm/kvm/coproc.c| 64 ++ > arch/arm/kvm/coproc_a15.c| 2 +- > arch/arm/kvm/coproc_a7.c | 2 +- > arch/arm/kvm/mmu.c | 70 > - > arch/arm/kvm/trace.h | 39 +++ > arch/arm64/include/asm/kvm_emulate.h | 10 + > arch/arm64/include/asm/kvm_host.h| 3 -- > arch/arm64/include/asm/kvm_mmu.h | 3 +- > arch/arm64/kvm/sys_regs.c| 75 > +--- > 13 files changed, 155 insertions(+), 139 deletions(-) > > diff --git a/arch/arm/include/asm/kvm_emulate.h > b/arch/arm/include/asm/kvm_emulate.h > index 66ce176..7b01523 100644 > --- a/arch/arm/include/asm/kvm_emulate.h > +++ b/arch/arm/include/asm/kvm_emulate.h > @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu > *vcpu) > vcpu->arch.hcr = HCR_GUEST_MASK; > } > > +static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) > +{ > + return vcpu->arch.hcr; > +} > + > +static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long > hcr) > +{ > + vcpu->arch.hcr = hcr; > +} > + > static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) > { > return 1; > diff --git a/arch/arm/include/asm/kvm_host.h > b/arch/arm/include/asm/kvm_host.h > index 254e065..04b4ea0 100644 > --- a/arch/arm/include/asm/kvm_host.h > +++ b/arch/arm/include/asm/kvm_host.h > @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { > * Anything that is not used directly from assembly code goes > * here. > */ > - /* dcache set/way operation pending */ > - int last_pcpu; > - cpumask_t require_dcache_flush; > > /* Don't run the guest on this vcpu */ > bool pause; > diff --git a/arch/arm/include/asm/kvm_mmu.h > b/arch/arm/include/asm/kvm_mmu.h > index 63e0ecc..286644c 100644 > --- a/arch/arm/include/asm/kvm_mmu.h > +++ b/arch/arm/include/asm/kvm_mmu.h > @@ -190,7 +190,8 @@ static inline void coherent_cache_guest_page(struct > kvm_vcpu *vcpu, hva_t hva, > > #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) > > -void stage2_flush_vm(struct kvm *kvm); > +void kvm_set_way_flush(struct kvm_vcpu *vcpu); > +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); > > #endif /* !__ASSEMBLY__ */ > > diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c > index 2d6d910..0b0d58a 100644 > --- a/arch/arm/kvm/arm.c > +++ b/arch/arm/kvm/arm.c > @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int > cpu) > vcpu->cpu = cpu; > vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); > > - /* > - * Check whether this vcpu requires the cache to be flushed on > - * this physical CPU. This is a consequence of doing dcache > - * operations by set/way on this vcpu. We do it here to be in > - * a non-preemptible section. > - */ > - if (cpumask_test_and_clear_cpu(cpu, > &vcpu->arch.require_dcache_flush))
Re: [PATCH v3 1/3] arm/arm64: KVM: Use set/way op trapping to track the state of the caches
On 27/01/15 13:17, Christoffer Dall wrote: > On Tue, Jan 27, 2015 at 11:21:38AM +, Marc Zyngier wrote: >> On 26/01/15 22:58, Christoffer Dall wrote: >>> On Wed, Jan 21, 2015 at 06:39:46PM +, Marc Zyngier wrote: Trying to emulate the behaviour of set/way cache ops is fairly pointless, as there are too many ways we can end-up missing stuff. Also, there is some system caches out there that simply ignore set/way operations. So instead of trying to implement them, let's convert it to VA ops, and use them as a way to re-enable the trapping of VM ops. That way, we can detect the point when the MMU/caches are turned off, and do a full VM flush (which is what the guest was trying to do anyway). This allows a 32bit zImage to boot on the APM thingy, and will probably help bootloaders in general. Signed-off-by: Marc Zyngier >>> >>> This had some conflicts with dirty page logging. I fixed it up here, >>> and also removed some trailing white space and mixed spaces/tabs that >>> patch complained about: >>> >>> http://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git mm-fixes >> >> Thanks for doing so. >> --- arch/arm/include/asm/kvm_emulate.h | 10 + arch/arm/include/asm/kvm_host.h | 3 -- arch/arm/include/asm/kvm_mmu.h | 3 +- arch/arm/kvm/arm.c | 10 - arch/arm/kvm/coproc.c| 64 ++ arch/arm/kvm/coproc_a15.c| 2 +- arch/arm/kvm/coproc_a7.c | 2 +- arch/arm/kvm/mmu.c | 70 - arch/arm/kvm/trace.h | 39 +++ arch/arm64/include/asm/kvm_emulate.h | 10 + arch/arm64/include/asm/kvm_host.h| 3 -- arch/arm64/include/asm/kvm_mmu.h | 3 +- arch/arm64/kvm/sys_regs.c| 75 +--- 13 files changed, 155 insertions(+), 139 deletions(-) diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h index 66ce176..7b01523 100644 --- a/arch/arm/include/asm/kvm_emulate.h +++ b/arch/arm/include/asm/kvm_emulate.h @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr = HCR_GUEST_MASK; } +static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.hcr; +} + +static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) +{ + vcpu->arch.hcr = hcr; +} + static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) { return 1; diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 254e065..04b4ea0 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { * Anything that is not used directly from assembly code goes * here. */ - /* dcache set/way operation pending */ - int last_pcpu; - cpumask_t require_dcache_flush; /* Don't run the guest on this vcpu */ bool pause; diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 63e0ecc..286644c 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -190,7 +190,8 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) -void stage2_flush_vm(struct kvm *kvm); +void kvm_set_way_flush(struct kvm_vcpu *vcpu); +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 2d6d910..0b0d58a 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vcpu->cpu = cpu; vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); - /* - * Check whether this vcpu requires the cache to be flushed on - * this physical CPU. This is a consequence of doing dcache - * operations by set/way on this vcpu. We do it here to be in - * a non-preemptible section. - */ - if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) - flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ - kvm_arm_set_running_vcpu(vcpu); } @@ -541,7 +532,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) ret = kvm_call_hyp(__kvm_vcpu_run
Re: [PATCH v3 1/3] arm/arm64: KVM: Use set/way op trapping to track the state of the caches
On Tue, Jan 27, 2015 at 11:21:38AM +, Marc Zyngier wrote: > On 26/01/15 22:58, Christoffer Dall wrote: > > On Wed, Jan 21, 2015 at 06:39:46PM +, Marc Zyngier wrote: > >> Trying to emulate the behaviour of set/way cache ops is fairly > >> pointless, as there are too many ways we can end-up missing stuff. > >> Also, there is some system caches out there that simply ignore > >> set/way operations. > >> > >> So instead of trying to implement them, let's convert it to VA ops, > >> and use them as a way to re-enable the trapping of VM ops. That way, > >> we can detect the point when the MMU/caches are turned off, and do > >> a full VM flush (which is what the guest was trying to do anyway). > >> > >> This allows a 32bit zImage to boot on the APM thingy, and will > >> probably help bootloaders in general. > >> > >> Signed-off-by: Marc Zyngier > > > > This had some conflicts with dirty page logging. I fixed it up here, > > and also removed some trailing white space and mixed spaces/tabs that > > patch complained about: > > > > http://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git mm-fixes > > Thanks for doing so. > > >> --- > >> arch/arm/include/asm/kvm_emulate.h | 10 + > >> arch/arm/include/asm/kvm_host.h | 3 -- > >> arch/arm/include/asm/kvm_mmu.h | 3 +- > >> arch/arm/kvm/arm.c | 10 - > >> arch/arm/kvm/coproc.c| 64 ++ > >> arch/arm/kvm/coproc_a15.c| 2 +- > >> arch/arm/kvm/coproc_a7.c | 2 +- > >> arch/arm/kvm/mmu.c | 70 > >> - > >> arch/arm/kvm/trace.h | 39 +++ > >> arch/arm64/include/asm/kvm_emulate.h | 10 + > >> arch/arm64/include/asm/kvm_host.h| 3 -- > >> arch/arm64/include/asm/kvm_mmu.h | 3 +- > >> arch/arm64/kvm/sys_regs.c| 75 > >> +--- > >> 13 files changed, 155 insertions(+), 139 deletions(-) > >> > >> diff --git a/arch/arm/include/asm/kvm_emulate.h > >> b/arch/arm/include/asm/kvm_emulate.h > >> index 66ce176..7b01523 100644 > >> --- a/arch/arm/include/asm/kvm_emulate.h > >> +++ b/arch/arm/include/asm/kvm_emulate.h > >> @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) > >> vcpu->arch.hcr = HCR_GUEST_MASK; > >> } > >> > >> +static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) > >> +{ > >> + return vcpu->arch.hcr; > >> +} > >> + > >> +static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) > >> +{ > >> + vcpu->arch.hcr = hcr; > >> +} > >> + > >> static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) > >> { > >> return 1; > >> diff --git a/arch/arm/include/asm/kvm_host.h > >> b/arch/arm/include/asm/kvm_host.h > >> index 254e065..04b4ea0 100644 > >> --- a/arch/arm/include/asm/kvm_host.h > >> +++ b/arch/arm/include/asm/kvm_host.h > >> @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { > >>* Anything that is not used directly from assembly code goes > >>* here. > >>*/ > >> - /* dcache set/way operation pending */ > >> - int last_pcpu; > >> - cpumask_t require_dcache_flush; > >> > >> /* Don't run the guest on this vcpu */ > >> bool pause; > >> diff --git a/arch/arm/include/asm/kvm_mmu.h > >> b/arch/arm/include/asm/kvm_mmu.h > >> index 63e0ecc..286644c 100644 > >> --- a/arch/arm/include/asm/kvm_mmu.h > >> +++ b/arch/arm/include/asm/kvm_mmu.h > >> @@ -190,7 +190,8 @@ static inline void coherent_cache_guest_page(struct > >> kvm_vcpu *vcpu, hva_t hva, > >> > >> #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) > >> > >> -void stage2_flush_vm(struct kvm *kvm); > >> +void kvm_set_way_flush(struct kvm_vcpu *vcpu); > >> +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); > >> > >> #endif /* !__ASSEMBLY__ */ > >> > >> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c > >> index 2d6d910..0b0d58a 100644 > >> --- a/arch/arm/kvm/arm.c > >> +++ b/arch/arm/kvm/arm.c > >> @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int > >> cpu) > >> vcpu->cpu = cpu; > >> vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); > >> > >> - /* > >> - * Check whether this vcpu requires the cache to be flushed on > >> - * this physical CPU. This is a consequence of doing dcache > >> - * operations by set/way on this vcpu. We do it here to be in > >> - * a non-preemptible section. > >> - */ > >> - if (cpumask_test_and_clear_cpu(cpu, > >> &vcpu->arch.require_dcache_flush)) > >> - flush_cache_all(); /* We'd really want v7_flush_dcache_all() > >> */ > >> - > >> kvm_arm_set_running_vcpu(vcpu); > >> } > >> > >> @@ -541,7 +532,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, > >> struct kvm_run *run) > >> ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); > >> > >> vcpu->mode =
Re: [PATCH v3 1/3] arm/arm64: KVM: Use set/way op trapping to track the state of the caches
On 26/01/15 22:58, Christoffer Dall wrote: > On Wed, Jan 21, 2015 at 06:39:46PM +, Marc Zyngier wrote: >> Trying to emulate the behaviour of set/way cache ops is fairly >> pointless, as there are too many ways we can end-up missing stuff. >> Also, there is some system caches out there that simply ignore >> set/way operations. >> >> So instead of trying to implement them, let's convert it to VA ops, >> and use them as a way to re-enable the trapping of VM ops. That way, >> we can detect the point when the MMU/caches are turned off, and do >> a full VM flush (which is what the guest was trying to do anyway). >> >> This allows a 32bit zImage to boot on the APM thingy, and will >> probably help bootloaders in general. >> >> Signed-off-by: Marc Zyngier > > This had some conflicts with dirty page logging. I fixed it up here, > and also removed some trailing white space and mixed spaces/tabs that > patch complained about: > > http://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git mm-fixes Thanks for doing so. >> --- >> arch/arm/include/asm/kvm_emulate.h | 10 + >> arch/arm/include/asm/kvm_host.h | 3 -- >> arch/arm/include/asm/kvm_mmu.h | 3 +- >> arch/arm/kvm/arm.c | 10 - >> arch/arm/kvm/coproc.c| 64 ++ >> arch/arm/kvm/coproc_a15.c| 2 +- >> arch/arm/kvm/coproc_a7.c | 2 +- >> arch/arm/kvm/mmu.c | 70 - >> arch/arm/kvm/trace.h | 39 +++ >> arch/arm64/include/asm/kvm_emulate.h | 10 + >> arch/arm64/include/asm/kvm_host.h| 3 -- >> arch/arm64/include/asm/kvm_mmu.h | 3 +- >> arch/arm64/kvm/sys_regs.c| 75 >> +--- >> 13 files changed, 155 insertions(+), 139 deletions(-) >> >> diff --git a/arch/arm/include/asm/kvm_emulate.h >> b/arch/arm/include/asm/kvm_emulate.h >> index 66ce176..7b01523 100644 >> --- a/arch/arm/include/asm/kvm_emulate.h >> +++ b/arch/arm/include/asm/kvm_emulate.h >> @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) >> vcpu->arch.hcr = HCR_GUEST_MASK; >> } >> >> +static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) >> +{ >> + return vcpu->arch.hcr; >> +} >> + >> +static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) >> +{ >> + vcpu->arch.hcr = hcr; >> +} >> + >> static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) >> { >> return 1; >> diff --git a/arch/arm/include/asm/kvm_host.h >> b/arch/arm/include/asm/kvm_host.h >> index 254e065..04b4ea0 100644 >> --- a/arch/arm/include/asm/kvm_host.h >> +++ b/arch/arm/include/asm/kvm_host.h >> @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { >>* Anything that is not used directly from assembly code goes >>* here. >>*/ >> - /* dcache set/way operation pending */ >> - int last_pcpu; >> - cpumask_t require_dcache_flush; >> >> /* Don't run the guest on this vcpu */ >> bool pause; >> diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h >> index 63e0ecc..286644c 100644 >> --- a/arch/arm/include/asm/kvm_mmu.h >> +++ b/arch/arm/include/asm/kvm_mmu.h >> @@ -190,7 +190,8 @@ static inline void coherent_cache_guest_page(struct >> kvm_vcpu *vcpu, hva_t hva, >> >> #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) >> >> -void stage2_flush_vm(struct kvm *kvm); >> +void kvm_set_way_flush(struct kvm_vcpu *vcpu); >> +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); >> >> #endif /* !__ASSEMBLY__ */ >> >> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c >> index 2d6d910..0b0d58a 100644 >> --- a/arch/arm/kvm/arm.c >> +++ b/arch/arm/kvm/arm.c >> @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) >> vcpu->cpu = cpu; >> vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); >> >> - /* >> - * Check whether this vcpu requires the cache to be flushed on >> - * this physical CPU. This is a consequence of doing dcache >> - * operations by set/way on this vcpu. We do it here to be in >> - * a non-preemptible section. >> - */ >> - if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) >> - flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ >> - >> kvm_arm_set_running_vcpu(vcpu); >> } >> >> @@ -541,7 +532,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, >> struct kvm_run *run) >> ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); >> >> vcpu->mode = OUTSIDE_GUEST_MODE; >> - vcpu->arch.last_pcpu = smp_processor_id(); >> kvm_guest_exit(); >> trace_kvm_exit(*vcpu_pc(vcpu)); >> /* >> diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c >> index 7928dbd..0afcc00 100644 >> --- a/arch/arm/kvm/coproc.c >> +++ b/arch/arm/k
Re: [PATCH v3 1/3] arm/arm64: KVM: Use set/way op trapping to track the state of the caches
On Wed, Jan 21, 2015 at 06:39:46PM +, Marc Zyngier wrote: > Trying to emulate the behaviour of set/way cache ops is fairly > pointless, as there are too many ways we can end-up missing stuff. > Also, there is some system caches out there that simply ignore > set/way operations. > > So instead of trying to implement them, let's convert it to VA ops, > and use them as a way to re-enable the trapping of VM ops. That way, > we can detect the point when the MMU/caches are turned off, and do > a full VM flush (which is what the guest was trying to do anyway). > > This allows a 32bit zImage to boot on the APM thingy, and will > probably help bootloaders in general. > > Signed-off-by: Marc Zyngier This had some conflicts with dirty page logging. I fixed it up here, and also removed some trailing white space and mixed spaces/tabs that patch complained about: http://git.linaro.org/people/christoffer.dall/linux-kvm-arm.git mm-fixes > --- > arch/arm/include/asm/kvm_emulate.h | 10 + > arch/arm/include/asm/kvm_host.h | 3 -- > arch/arm/include/asm/kvm_mmu.h | 3 +- > arch/arm/kvm/arm.c | 10 - > arch/arm/kvm/coproc.c| 64 ++ > arch/arm/kvm/coproc_a15.c| 2 +- > arch/arm/kvm/coproc_a7.c | 2 +- > arch/arm/kvm/mmu.c | 70 - > arch/arm/kvm/trace.h | 39 +++ > arch/arm64/include/asm/kvm_emulate.h | 10 + > arch/arm64/include/asm/kvm_host.h| 3 -- > arch/arm64/include/asm/kvm_mmu.h | 3 +- > arch/arm64/kvm/sys_regs.c| 75 > +--- > 13 files changed, 155 insertions(+), 139 deletions(-) > > diff --git a/arch/arm/include/asm/kvm_emulate.h > b/arch/arm/include/asm/kvm_emulate.h > index 66ce176..7b01523 100644 > --- a/arch/arm/include/asm/kvm_emulate.h > +++ b/arch/arm/include/asm/kvm_emulate.h > @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) > vcpu->arch.hcr = HCR_GUEST_MASK; > } > > +static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) > +{ > + return vcpu->arch.hcr; > +} > + > +static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) > +{ > + vcpu->arch.hcr = hcr; > +} > + > static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) > { > return 1; > diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h > index 254e065..04b4ea0 100644 > --- a/arch/arm/include/asm/kvm_host.h > +++ b/arch/arm/include/asm/kvm_host.h > @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { >* Anything that is not used directly from assembly code goes >* here. >*/ > - /* dcache set/way operation pending */ > - int last_pcpu; > - cpumask_t require_dcache_flush; > > /* Don't run the guest on this vcpu */ > bool pause; > diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h > index 63e0ecc..286644c 100644 > --- a/arch/arm/include/asm/kvm_mmu.h > +++ b/arch/arm/include/asm/kvm_mmu.h > @@ -190,7 +190,8 @@ static inline void coherent_cache_guest_page(struct > kvm_vcpu *vcpu, hva_t hva, > > #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) > > -void stage2_flush_vm(struct kvm *kvm); > +void kvm_set_way_flush(struct kvm_vcpu *vcpu); > +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); > > #endif /* !__ASSEMBLY__ */ > > diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c > index 2d6d910..0b0d58a 100644 > --- a/arch/arm/kvm/arm.c > +++ b/arch/arm/kvm/arm.c > @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) > vcpu->cpu = cpu; > vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); > > - /* > - * Check whether this vcpu requires the cache to be flushed on > - * this physical CPU. This is a consequence of doing dcache > - * operations by set/way on this vcpu. We do it here to be in > - * a non-preemptible section. > - */ > - if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) > - flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ > - > kvm_arm_set_running_vcpu(vcpu); > } > > @@ -541,7 +532,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct > kvm_run *run) > ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); > > vcpu->mode = OUTSIDE_GUEST_MODE; > - vcpu->arch.last_pcpu = smp_processor_id(); > kvm_guest_exit(); > trace_kvm_exit(*vcpu_pc(vcpu)); > /* > diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c > index 7928dbd..0afcc00 100644 > --- a/arch/arm/kvm/coproc.c > +++ b/arch/arm/kvm/coproc.c > @@ -189,82 +189,40 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu, > return true; > } > > -/* See note at ARM ARM B1.14.4 */ > +/* > + * See note at
[PATCH v3 1/3] arm/arm64: KVM: Use set/way op trapping to track the state of the caches
Trying to emulate the behaviour of set/way cache ops is fairly pointless, as there are too many ways we can end-up missing stuff. Also, there is some system caches out there that simply ignore set/way operations. So instead of trying to implement them, let's convert it to VA ops, and use them as a way to re-enable the trapping of VM ops. That way, we can detect the point when the MMU/caches are turned off, and do a full VM flush (which is what the guest was trying to do anyway). This allows a 32bit zImage to boot on the APM thingy, and will probably help bootloaders in general. Signed-off-by: Marc Zyngier --- arch/arm/include/asm/kvm_emulate.h | 10 + arch/arm/include/asm/kvm_host.h | 3 -- arch/arm/include/asm/kvm_mmu.h | 3 +- arch/arm/kvm/arm.c | 10 - arch/arm/kvm/coproc.c| 64 ++ arch/arm/kvm/coproc_a15.c| 2 +- arch/arm/kvm/coproc_a7.c | 2 +- arch/arm/kvm/mmu.c | 70 - arch/arm/kvm/trace.h | 39 +++ arch/arm64/include/asm/kvm_emulate.h | 10 + arch/arm64/include/asm/kvm_host.h| 3 -- arch/arm64/include/asm/kvm_mmu.h | 3 +- arch/arm64/kvm/sys_regs.c| 75 +--- 13 files changed, 155 insertions(+), 139 deletions(-) diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h index 66ce176..7b01523 100644 --- a/arch/arm/include/asm/kvm_emulate.h +++ b/arch/arm/include/asm/kvm_emulate.h @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr = HCR_GUEST_MASK; } +static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.hcr; +} + +static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) +{ + vcpu->arch.hcr = hcr; +} + static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) { return 1; diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 254e065..04b4ea0 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { * Anything that is not used directly from assembly code goes * here. */ - /* dcache set/way operation pending */ - int last_pcpu; - cpumask_t require_dcache_flush; /* Don't run the guest on this vcpu */ bool pause; diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 63e0ecc..286644c 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -190,7 +190,8 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, #define kvm_virt_to_phys(x)virt_to_idmap((unsigned long)(x)) -void stage2_flush_vm(struct kvm *kvm); +void kvm_set_way_flush(struct kvm_vcpu *vcpu); +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 2d6d910..0b0d58a 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vcpu->cpu = cpu; vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); - /* -* Check whether this vcpu requires the cache to be flushed on -* this physical CPU. This is a consequence of doing dcache -* operations by set/way on this vcpu. We do it here to be in -* a non-preemptible section. -*/ - if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) - flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ - kvm_arm_set_running_vcpu(vcpu); } @@ -541,7 +532,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); vcpu->mode = OUTSIDE_GUEST_MODE; - vcpu->arch.last_pcpu = smp_processor_id(); kvm_guest_exit(); trace_kvm_exit(*vcpu_pc(vcpu)); /* diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c index 7928dbd..0afcc00 100644 --- a/arch/arm/kvm/coproc.c +++ b/arch/arm/kvm/coproc.c @@ -189,82 +189,40 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu, return true; } -/* See note at ARM ARM B1.14.4 */ +/* + * See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized). + */ static bool access_dcsw(struct kvm_vcpu *vcpu, const struct coproc_params *p, const struct coproc_reg *r) { - unsigned long val; - int cpu; - if (!p->is_write) return read_from_write_only(vcpu, p); - cpu = get_cpu(); - - cpumask_setall(&vcpu->arch.require_dcache_flush); - cpumask_clear_cpu(cpu, &vcpu->arch.require_