From edf7958d501fd9bce1f61bfa940cd52dfe1e9904 Mon Sep 17 00:00:00 2001 From: Izik Eidus Date: Tue, 16 Oct 2007 14:42:30 +0200 Subject: [PATCH] --- yaml --- r: 80667 b: refs/heads/master c: 98348e9507ace5fda95432ff8ca23f13e7f66176 h: refs/heads/master i: 80665: 54e91739832c8a51e26b1a197329f95f3a4f1f5e 80663: a40ee00989679411dfe6d7695a549582ae380fbf v: v3 --- [refs] | 2 +- trunk/drivers/kvm/mmu.c | 45 ++++++++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index 0a2a7bab9ac8..fbdf8b421a4f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b284be576471b1521dd04c0845beedb790cbb9d7 +refs/heads/master: 98348e9507ace5fda95432ff8ca23f13e7f66176 diff --git a/trunk/drivers/kvm/mmu.c b/trunk/drivers/kvm/mmu.c index f52604a7f9e8..14e54e331f50 100644 --- a/trunk/drivers/kvm/mmu.c +++ b/trunk/drivers/kvm/mmu.c @@ -456,28 +456,53 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) } } -static void rmap_write_protect(struct kvm *kvm, u64 gfn) +static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte) { struct kvm_rmap_desc *desc; + struct kvm_rmap_desc *prev_desc; + u64 *prev_spte; + int i; + + if (!*rmapp) + return NULL; + else if (!(*rmapp & 1)) { + if (!spte) + return (u64 *)*rmapp; + return NULL; + } + desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul); + prev_desc = NULL; + prev_spte = NULL; + while (desc) { + for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i) { + if (prev_spte == spte) + return desc->shadow_ptes[i]; + prev_spte = desc->shadow_ptes[i]; + } + desc = desc->more; + } + return NULL; +} + +static void rmap_write_protect(struct kvm *kvm, u64 gfn) +{ unsigned long *rmapp; u64 *spte; + u64 *prev_spte; gfn = unalias_gfn(kvm, gfn); rmapp = gfn_to_rmap(kvm, gfn); - while (*rmapp) { - if (!(*rmapp & 1)) - spte = (u64 *)*rmapp; - else { - desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul); - spte = desc->shadow_ptes[0]; - } + spte = rmap_next(kvm, rmapp, NULL); + while (spte) { BUG_ON(!spte); BUG_ON(!(*spte & PT_PRESENT_MASK)); BUG_ON(!(*spte & PT_WRITABLE_MASK)); rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte); - rmap_remove(kvm, spte); - set_shadow_pte(spte, *spte & ~PT_WRITABLE_MASK); + prev_spte = spte; + spte = rmap_next(kvm, rmapp, spte); + rmap_remove(kvm, prev_spte); + set_shadow_pte(prev_spte, *prev_spte & ~PT_WRITABLE_MASK); kvm_flush_remote_tlbs(kvm); } }