KVM guest: do not batch pte updates from interrupt context
Commit b8bcfe997e
made paravirt pte updates synchronous in interrupt
context.
Unfortunately the KVM pv mmu code caches the lazy/nonlazy mode
internally, so a pte update from interrupt context during a lazy mmu
operation can be batched while it should be performed synchronously.
https://bugzilla.redhat.com/show_bug.cgi?id=518022
Drop the internal mode variable and use paravirt_get_lazy_mode(), which
returns the correct state.
Cc: stable@kernel.org
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
committed by
Avi Kivity
parent
65a8221163
commit
6ba6617875
@@ -34,7 +34,6 @@
|
|||||||
struct kvm_para_state {
|
struct kvm_para_state {
|
||||||
u8 mmu_queue[MMU_QUEUE_SIZE];
|
u8 mmu_queue[MMU_QUEUE_SIZE];
|
||||||
int mmu_queue_len;
|
int mmu_queue_len;
|
||||||
enum paravirt_lazy_mode mode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct kvm_para_state, para_state);
|
static DEFINE_PER_CPU(struct kvm_para_state, para_state);
|
||||||
@@ -77,7 +76,7 @@ static void kvm_deferred_mmu_op(void *buffer, int len)
|
|||||||
{
|
{
|
||||||
struct kvm_para_state *state = kvm_para_state();
|
struct kvm_para_state *state = kvm_para_state();
|
||||||
|
|
||||||
if (state->mode != PARAVIRT_LAZY_MMU) {
|
if (paravirt_get_lazy_mode() != PARAVIRT_LAZY_MMU) {
|
||||||
kvm_mmu_op(buffer, len);
|
kvm_mmu_op(buffer, len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -185,10 +184,7 @@ static void kvm_release_pt(unsigned long pfn)
|
|||||||
|
|
||||||
static void kvm_enter_lazy_mmu(void)
|
static void kvm_enter_lazy_mmu(void)
|
||||||
{
|
{
|
||||||
struct kvm_para_state *state = kvm_para_state();
|
|
||||||
|
|
||||||
paravirt_enter_lazy_mmu();
|
paravirt_enter_lazy_mmu();
|
||||||
state->mode = paravirt_get_lazy_mode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_leave_lazy_mmu(void)
|
static void kvm_leave_lazy_mmu(void)
|
||||||
@@ -197,7 +193,6 @@ static void kvm_leave_lazy_mmu(void)
|
|||||||
|
|
||||||
mmu_queue_flush(state);
|
mmu_queue_flush(state);
|
||||||
paravirt_leave_lazy_mmu();
|
paravirt_leave_lazy_mmu();
|
||||||
state->mode = paravirt_get_lazy_mode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init paravirt_ops_setup(void)
|
static void __init paravirt_ops_setup(void)
|
||||||
|
Reference in New Issue
Block a user