Skip to content

Commit

Permalink
[PATCH] KVM: MMU: Support emulated writes into RAM
Browse files Browse the repository at this point in the history
As the mmu write protects guest page table, we emulate those writes.  Since
they are not mmio, there is no need to go to userspace to perform them.

So, perform the writes in the kernel if possible, and notify the mmu about
them so it can take the approriate action.

Signed-off-by: Avi Kivity <avi@qumranet.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Avi Kivity authored and Linus Torvalds committed Jan 6, 2007
1 parent 815af8d commit da4a00f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/kvm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ int kvm_write_guest(struct kvm_vcpu *vcpu,

unsigned long segment_base(u16 selector);

void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);

static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn)
{
struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
Expand Down
24 changes: 24 additions & 0 deletions drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,27 @@ static int emulator_read_emulated(unsigned long addr,
}
}

static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
unsigned long val, int bytes)
{
struct kvm_memory_slot *m;
struct page *page;
void *virt;

if (((gpa + bytes - 1) >> PAGE_SHIFT) != (gpa >> PAGE_SHIFT))
return 0;
m = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
if (!m)
return 0;
page = gfn_to_page(m, gpa >> PAGE_SHIFT);
kvm_mmu_pre_write(vcpu, gpa, bytes);
virt = kmap_atomic(page, KM_USER0);
memcpy(virt + offset_in_page(gpa), &val, bytes);
kunmap_atomic(virt, KM_USER0);
kvm_mmu_post_write(vcpu, gpa, bytes);
return 1;
}

static int emulator_write_emulated(unsigned long addr,
unsigned long val,
unsigned int bytes,
Expand All @@ -888,6 +909,9 @@ static int emulator_write_emulated(unsigned long addr,
if (gpa == UNMAPPED_GVA)
return X86EMUL_PROPAGATE_FAULT;

if (emulator_write_phys(vcpu, gpa, val, bytes))
return X86EMUL_CONTINUE;

vcpu->mmio_needed = 1;
vcpu->mmio_phys_addr = gpa;
vcpu->mmio_size = bytes;
Expand Down
9 changes: 9 additions & 0 deletions drivers/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,15 @@ int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
return init_kvm_mmu(vcpu);
}

void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
{
pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
}

void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
{
}

static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
while (!list_empty(&vcpu->free_pages)) {
Expand Down

0 comments on commit da4a00f

Please sign in to comment.