Commit 9e81d29f authored by Marc Zyngier's avatar Marc Zyngier Committed by Ben Hutchings

arm/arm64: KVM: Enforce unconditional flush to PoC when mapping to stage-2

commit 8f36ebaf upstream.

When we fault in a page, we flush it to the PoC (Point of Coherency)
if the faulting vcpu has its own caches off, so that it can observe
the page we just brought it.

But if the vcpu has its caches on, we skip that step. Bad things
happen when *another* vcpu tries to access that page with its own
caches disabled. At that point, there is no garantee that the
data has made it to the PoC, and we access stale data.

The obvious fix is to always flush to PoC when a page is faulted
in, no matter what the state of the vcpu is.

Fixes: 2d58b733 ("arm64: KVM: force cache clean on page fault when caches are off")
Reviewed-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
[bwh: Backported to 3.16: conditions for flushing were simpler here]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 324b4fb1
...@@ -142,8 +142,7 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) ...@@ -142,8 +142,7 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
unsigned long size) unsigned long size)
{ {
if (!vcpu_has_cache_enabled(vcpu)) kvm_flush_dcache_to_poc((void *)hva, size);
kvm_flush_dcache_to_poc((void *)hva, size);
/* /*
* If we are going to insert an instruction page and the icache is * If we are going to insert an instruction page and the icache is
......
...@@ -141,8 +141,7 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) ...@@ -141,8 +141,7 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
unsigned long size) unsigned long size)
{ {
if (!vcpu_has_cache_enabled(vcpu)) kvm_flush_dcache_to_poc((void *)hva, size);
kvm_flush_dcache_to_poc((void *)hva, size);
if (!icache_is_aliasing()) { /* PIPT */ if (!icache_is_aliasing()) { /* PIPT */
flush_icache_range(hva, hva + size); flush_icache_range(hva, hva + size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment