* [PATCH for 3.3] KVM: Fix write protection race during dirty logging
@ 2012-02-05 11:42 Takuya Yoshikawa
2012-02-06 3:40 ` Xiao Guangrong
2012-02-08 16:38 ` Marcelo Tosatti
0 siblings, 2 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-02-05 11:42 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
This patch fixes a race introduced by:
commit 95d4c16ce78cb6b7549a09159c409d52ddd18dae
KVM: Optimize dirty logging by rmap_write_protect()
During protecting pages for dirty logging, other threads may also try
to protect a page in mmu_sync_children() or kvm_mmu_get_page().
In such a case, because get_dirty_log releases mmu_lock before flushing
TLB's, the following race condition can happen:
A (get_dirty_log) B (another thread)
lock(mmu_lock)
clear pte.w
unlock(mmu_lock)
lock(mmu_lock)
pte.w is already cleared
unlock(mmu_lock)
skip TLB flush
return
...
TLB flush
Though thread B assumes the page has already been protected when it
returns, the remaining TLB entry will break that assumption.
This patch fixes this problem by making get_dirty_log hold the mmu_lock
until it flushes the TLB's.
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
---
arch/x86/kvm/x86.c | 11 +++++------
1 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2bd77a3..048fe6c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3022,6 +3022,8 @@ static void write_protect_slot(struct kvm *kvm,
unsigned long *dirty_bitmap,
unsigned long nr_dirty_pages)
{
+ spin_lock(&kvm->mmu_lock);
+
/* Not many dirty pages compared to # of shadow pages. */
if (nr_dirty_pages < kvm->arch.n_used_mmu_pages) {
unsigned long gfn_offset;
@@ -3029,16 +3031,13 @@ static void write_protect_slot(struct kvm *kvm,
for_each_set_bit(gfn_offset, dirty_bitmap, memslot->npages) {
unsigned long gfn = memslot->base_gfn + gfn_offset;
- spin_lock(&kvm->mmu_lock);
kvm_mmu_rmap_write_protect(kvm, gfn, memslot);
- spin_unlock(&kvm->mmu_lock);
}
kvm_flush_remote_tlbs(kvm);
- } else {
- spin_lock(&kvm->mmu_lock);
+ } else
kvm_mmu_slot_remove_write_access(kvm, memslot->id);
- spin_unlock(&kvm->mmu_lock);
- }
+
+ spin_unlock(&kvm->mmu_lock);
}
/*
--
1.7.5.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-05 11:42 [PATCH for 3.3] KVM: Fix write protection race during dirty logging Takuya Yoshikawa
@ 2012-02-06 3:40 ` Xiao Guangrong
2012-02-06 3:46 ` Takuya Yoshikawa
2012-02-08 16:38 ` Marcelo Tosatti
1 sibling, 1 reply; 9+ messages in thread
From: Xiao Guangrong @ 2012-02-06 3:40 UTC (permalink / raw)
To: Takuya Yoshikawa; +Cc: avi, mtosatti, kvm
On 02/05/2012 07:42 PM, Takuya Yoshikawa wrote:
> From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
>
> This patch fixes a race introduced by:
>
> commit 95d4c16ce78cb6b7549a09159c409d52ddd18dae
> KVM: Optimize dirty logging by rmap_write_protect()
>
> During protecting pages for dirty logging, other threads may also try
> to protect a page in mmu_sync_children() or kvm_mmu_get_page().
>
> In such a case, because get_dirty_log releases mmu_lock before flushing
> TLB's, the following race condition can happen:
>
> A (get_dirty_log) B (another thread)
>
> lock(mmu_lock)
> clear pte.w
> unlock(mmu_lock)
> lock(mmu_lock)
> pte.w is already cleared
> unlock(mmu_lock)
> skip TLB flush
> return
> ...
> TLB flush
>
> Though thread B assumes the page has already been protected when it
> returns, the remaining TLB entry will break that assumption.
>
> This patch fixes this problem by making get_dirty_log hold the mmu_lock
> until it flushes the TLB's.
>
I do not think this is a problem since the dirty page is logged when
the writeable spte is being set, and in the end of get_dirty_log, all
TLBs are always flushed.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-06 3:40 ` Xiao Guangrong
@ 2012-02-06 3:46 ` Takuya Yoshikawa
2012-02-06 3:53 ` Xiao Guangrong
0 siblings, 1 reply; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-02-06 3:46 UTC (permalink / raw)
To: Xiao Guangrong; +Cc: Takuya Yoshikawa, avi, mtosatti, kvm
(2012/02/06 12:40), Xiao Guangrong wrote:
> On 02/05/2012 07:42 PM, Takuya Yoshikawa wrote:
>
>> From: Takuya Yoshikawa<yoshikawa.takuya@oss.ntt.co.jp>
>>
>> This patch fixes a race introduced by:
>>
>> commit 95d4c16ce78cb6b7549a09159c409d52ddd18dae
>> KVM: Optimize dirty logging by rmap_write_protect()
>>
>> During protecting pages for dirty logging, other threads may also try
>> to protect a page in mmu_sync_children() or kvm_mmu_get_page().
>>
>> In such a case, because get_dirty_log releases mmu_lock before flushing
>> TLB's, the following race condition can happen:
>>
>> A (get_dirty_log) B (another thread)
>>
>> lock(mmu_lock)
>> clear pte.w
>> unlock(mmu_lock)
>> lock(mmu_lock)
>> pte.w is already cleared
>> unlock(mmu_lock)
>> skip TLB flush
>> return
>> ...
>> TLB flush
>>
>> Though thread B assumes the page has already been protected when it
>> returns, the remaining TLB entry will break that assumption.
>>
>> This patch fixes this problem by making get_dirty_log hold the mmu_lock
>> until it flushes the TLB's.
>>
>
>
> I do not think this is a problem since the dirty page is logged when
> the writeable spte is being set, and in the end of get_dirty_log, all
> TLBs are always flushed.
>
The victim is not GET_DIRTY_LOG but thread B; it needs to assure the page
is protected before returning.
Thanks,
Takuya
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-06 3:46 ` Takuya Yoshikawa
@ 2012-02-06 3:53 ` Xiao Guangrong
2012-02-06 5:02 ` Xiao Guangrong
0 siblings, 1 reply; 9+ messages in thread
From: Xiao Guangrong @ 2012-02-06 3:53 UTC (permalink / raw)
To: Takuya Yoshikawa; +Cc: Takuya Yoshikawa, avi, mtosatti, kvm
On 02/06/2012 11:46 AM, Takuya Yoshikawa wrote:
> (2012/02/06 12:40), Xiao Guangrong wrote:
>> On 02/05/2012 07:42 PM, Takuya Yoshikawa wrote:
>>
>>> From: Takuya Yoshikawa<yoshikawa.takuya@oss.ntt.co.jp>
>>>
>>> This patch fixes a race introduced by:
>>>
>>> commit 95d4c16ce78cb6b7549a09159c409d52ddd18dae
>>> KVM: Optimize dirty logging by rmap_write_protect()
>>>
>>> During protecting pages for dirty logging, other threads may also try
>>> to protect a page in mmu_sync_children() or kvm_mmu_get_page().
>>>
>>> In such a case, because get_dirty_log releases mmu_lock before flushing
>>> TLB's, the following race condition can happen:
>>>
>>> A (get_dirty_log) B (another thread)
>>>
>>> lock(mmu_lock)
>>> clear pte.w
>>> unlock(mmu_lock)
>>> lock(mmu_lock)
>>> pte.w is already cleared
>>> unlock(mmu_lock)
>>> skip TLB flush
>>> return
>>> ...
>>> TLB flush
>>>
>>> Though thread B assumes the page has already been protected when it
>>> returns, the remaining TLB entry will break that assumption.
>>>
>>> This patch fixes this problem by making get_dirty_log hold the mmu_lock
>>> until it flushes the TLB's.
>>>
>>
>>
>> I do not think this is a problem since the dirty page is logged when
>> the writeable spte is being set, and in the end of get_dirty_log, all
>> TLBs are always flushed.
>>
>
> The victim is not GET_DIRTY_LOG but thread B; it needs to assure the page
> is protected before returning.
>
Ah, right!
Reviewed-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-06 3:53 ` Xiao Guangrong
@ 2012-02-06 5:02 ` Xiao Guangrong
2012-02-06 5:12 ` Takuya Yoshikawa
0 siblings, 1 reply; 9+ messages in thread
From: Xiao Guangrong @ 2012-02-06 5:02 UTC (permalink / raw)
To: Xiao Guangrong; +Cc: Takuya Yoshikawa, Takuya Yoshikawa, avi, mtosatti, kvm
On 02/06/2012 11:53 AM, Xiao Guangrong wrote:
> On 02/06/2012 11:46 AM, Takuya Yoshikawa wrote:
>
>> (2012/02/06 12:40), Xiao Guangrong wrote:
>>> On 02/05/2012 07:42 PM, Takuya Yoshikawa wrote:
>>>
>>>> From: Takuya Yoshikawa<yoshikawa.takuya@oss.ntt.co.jp>
>>>>
>>>> This patch fixes a race introduced by:
>>>>
>>>> commit 95d4c16ce78cb6b7549a09159c409d52ddd18dae
>>>> KVM: Optimize dirty logging by rmap_write_protect()
>>>>
>>>> During protecting pages for dirty logging, other threads may also try
>>>> to protect a page in mmu_sync_children() or kvm_mmu_get_page().
>>>>
>>>> In such a case, because get_dirty_log releases mmu_lock before flushing
>>>> TLB's, the following race condition can happen:
>>>>
>>>> A (get_dirty_log) B (another thread)
>>>>
>>>> lock(mmu_lock)
>>>> clear pte.w
>>>> unlock(mmu_lock)
>>>> lock(mmu_lock)
>>>> pte.w is already cleared
>>>> unlock(mmu_lock)
>>>> skip TLB flush
>>>> return
>>>> ...
>>>> TLB flush
>>>>
>>>> Though thread B assumes the page has already been protected when it
>>>> returns, the remaining TLB entry will break that assumption.
>>>>
>>>> This patch fixes this problem by making get_dirty_log hold the mmu_lock
>>>> until it flushes the TLB's.
>>>>
>>>
>>>
>>> I do not think this is a problem since the dirty page is logged when
>>> the writeable spte is being set, and in the end of get_dirty_log, all
>>> TLBs are always flushed.
>>>
>>
>> The victim is not GET_DIRTY_LOG but thread B; it needs to assure the page
>> is protected before returning.
>>
>
>
> Ah, right!
>
> Reviewed-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
>
I am worrying if other paths(such as like kvm_mmu_notifier_invalidate_page)
which unmap/modify writeable ptes and flush TLBs out of mmu lock have the
same problem?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-06 5:02 ` Xiao Guangrong
@ 2012-02-06 5:12 ` Takuya Yoshikawa
2012-02-06 9:48 ` Avi Kivity
0 siblings, 1 reply; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-02-06 5:12 UTC (permalink / raw)
To: Xiao Guangrong; +Cc: Takuya Yoshikawa, avi, mtosatti, kvm
(2012/02/06 14:02), Xiao Guangrong wrote:
> I am worrying if other paths(such as like kvm_mmu_notifier_invalidate_page)
> which unmap/modify writeable ptes and flush TLBs out of mmu lock have the
> same problem?
>
Yes, I think so ... (long standing bug?)
Let's ask Avi if he prefers to fix it separately then!
Takuya
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-06 5:12 ` Takuya Yoshikawa
@ 2012-02-06 9:48 ` Avi Kivity
0 siblings, 0 replies; 9+ messages in thread
From: Avi Kivity @ 2012-02-06 9:48 UTC (permalink / raw)
To: Takuya Yoshikawa; +Cc: Xiao Guangrong, Takuya Yoshikawa, mtosatti, kvm
On 02/06/2012 07:12 AM, Takuya Yoshikawa wrote:
> (2012/02/06 14:02), Xiao Guangrong wrote:
>
>> I am worrying if other paths(such as like
>> kvm_mmu_notifier_invalidate_page)
>> which unmap/modify writeable ptes and flush TLBs out of mmu lock have
>> the
>> same problem?
>>
>
> Yes, I think so ... (long standing bug?)
Ugh, I looked at arch/x86/kvm for this problem but not at virt/kvm.
>
> Let's ask Avi if he prefers to fix it separately then!
Separate fixes please.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-05 11:42 [PATCH for 3.3] KVM: Fix write protection race during dirty logging Takuya Yoshikawa
2012-02-06 3:40 ` Xiao Guangrong
@ 2012-02-08 16:38 ` Marcelo Tosatti
2012-02-09 13:54 ` Takuya Yoshikawa
1 sibling, 1 reply; 9+ messages in thread
From: Marcelo Tosatti @ 2012-02-08 16:38 UTC (permalink / raw)
To: Takuya Yoshikawa; +Cc: avi, kvm
On Sun, Feb 05, 2012 at 08:42:41PM +0900, Takuya Yoshikawa wrote:
> From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
>
> This patch fixes a race introduced by:
>
> commit 95d4c16ce78cb6b7549a09159c409d52ddd18dae
> KVM: Optimize dirty logging by rmap_write_protect()
>
> During protecting pages for dirty logging, other threads may also try
> to protect a page in mmu_sync_children() or kvm_mmu_get_page().
>
> In such a case, because get_dirty_log releases mmu_lock before flushing
> TLB's, the following race condition can happen:
>
> A (get_dirty_log) B (another thread)
>
> lock(mmu_lock)
> clear pte.w
> unlock(mmu_lock)
> lock(mmu_lock)
> pte.w is already cleared
> unlock(mmu_lock)
> skip TLB flush
> return
> ...
> TLB flush
>
> Though thread B assumes the page has already been protected when it
> returns, the remaining TLB entry will break that assumption.
>
> This patch fixes this problem by making get_dirty_log hold the mmu_lock
> until it flushes the TLB's.
>
> Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
> ---
> arch/x86/kvm/x86.c | 11 +++++------
> 1 files changed, 5 insertions(+), 6 deletions(-)
Applied, thanks.
Please don't forget the invalidate_page fix.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH for 3.3] KVM: Fix write protection race during dirty logging
2012-02-08 16:38 ` Marcelo Tosatti
@ 2012-02-09 13:54 ` Takuya Yoshikawa
0 siblings, 0 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-02-09 13:54 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: avi, kvm
On Wed, 8 Feb 2012 14:38:07 -0200
Marcelo Tosatti <mtosatti@redhat.com> wrote:
> Please don't forget the invalidate_page fix.
I will send in a few days.
Takuya
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-02-09 13:54 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-05 11:42 [PATCH for 3.3] KVM: Fix write protection race during dirty logging Takuya Yoshikawa
2012-02-06 3:40 ` Xiao Guangrong
2012-02-06 3:46 ` Takuya Yoshikawa
2012-02-06 3:53 ` Xiao Guangrong
2012-02-06 5:02 ` Xiao Guangrong
2012-02-06 5:12 ` Takuya Yoshikawa
2012-02-06 9:48 ` Avi Kivity
2012-02-08 16:38 ` Marcelo Tosatti
2012-02-09 13:54 ` Takuya Yoshikawa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).