From 2c6c422ad320729b91306485e43662749bce0497 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sun, 11 Apr 2010 09:28:14 +0300 Subject: [PATCH] kvm: Dump page tables at exit To make debugging more easy, dump page tables at exit as suggested by Avi Kivity. Signed-off-by: Pekka Enberg --- tools/kvm/include/kvm/kvm.h | 1 + tools/kvm/kvm.c | 32 +++++++++++++++++++++++++++++++- tools/kvm/main.c | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h index cddcad0a9f1d..61100151de37 100644 --- a/tools/kvm/include/kvm/kvm.h +++ b/tools/kvm/include/kvm/kvm.h @@ -45,6 +45,7 @@ bool kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, */ void kvm__show_code(struct kvm *self); void kvm__show_registers(struct kvm *self); +void kvm__show_page_tables(struct kvm *self); void kvm__dump_mem(struct kvm *self, unsigned long addr, unsigned long size); extern const char *kvm_exit_reasons[]; diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c index 1ecf79d86a65..64316875db87 100644 --- a/tools/kvm/kvm.c +++ b/tools/kvm/kvm.c @@ -351,6 +351,11 @@ static inline uint64_t ip_flat_to_real(struct kvm *self, uint64_t ip) return ip - (cs << 4); } +static inline bool is_in_protected_mode(struct kvm *self) +{ + return self->sregs.cr0 & 0x01; +} + static inline uint64_t ip_to_flat(struct kvm *self, uint64_t ip) { uint64_t cs; @@ -359,7 +364,7 @@ static inline uint64_t ip_to_flat(struct kvm *self, uint64_t ip) * NOTE! We should take code segment base address into account here. * Luckily it's usually zero because Linux uses flat memory model. */ - if (self->sregs.cr0 & 0x01) + if (is_in_protected_mode(self)) return ip; cs = self->sregs.cs.selector; @@ -659,6 +664,31 @@ void kvm__show_code(struct kvm *self) kvm__dump_mem(self, self->regs.rsp, 32); } +void kvm__show_page_tables(struct kvm *self) +{ + uint64_t *pte1; + uint64_t *pte2; + uint64_t *pte3; + uint64_t *pte4; + + if (!is_in_protected_mode(self)) + return; + + if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0) + die("KVM_GET_SREGS failed"); + + pte4 = guest_flat_to_host(self, self->sregs.cr3); + pte3 = guest_flat_to_host(self, (*pte4 & ~0xfff)); + pte2 = guest_flat_to_host(self, (*pte3 & ~0xfff)); + pte1 = guest_flat_to_host(self, (*pte2 & ~0xfff)); + + printf("Page Tables:\n"); + if (*pte2 & (1 << 7)) + printf(" pte4: %016lx pte3: %016lx pte2: %016lx\n", *pte4, *pte3, *pte2); + else + printf(" pte4: %016lx pte3: %016lx pte2: %016lx pte1: %016lx\n", *pte4, *pte3, *pte2, *pte1); +} + void kvm__dump_mem(struct kvm *self, unsigned long addr, unsigned long size) { unsigned char *p; diff --git a/tools/kvm/main.c b/tools/kvm/main.c index aa25bd81ebdb..5e72cf5f7816 100644 --- a/tools/kvm/main.c +++ b/tools/kvm/main.c @@ -91,6 +91,7 @@ exit_kvm: kvm__show_registers(kvm); kvm__show_code(kvm); + kvm__show_page_tables(kvm); kvm__delete(kvm); -- 2.39.5