Skip to contentSkip to conversation

kvm_show_code for ROM code

PATCH Applied Jan Kiszka 2 participants 4 messages Apr 30, 2008 – May 2, 2008 KVM

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

PATCH 1/1 kvm_show_code for ROM code

Userland-located ROM memory is not available via kvm->physical_memory + guest_address. To let kvm_show_code also dump useful information when some problem in ROM (BIOS...) occurs, this patch first tries to obtain the memory content via the mmio_read callback - maybe not 100% clean, but works at least for the QEMU use case. If the callback complains about the given address, we then fall back to RAM access.

---
 libkvm/libkvm-x86.c |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
libkvm/libkvm-x86.c +10 -7
Index: b/libkvm/libkvm-x86.c
===================================================================
@@ -393,14 +393,15 @@ int kvm_set_pit(kvm_context_t kvm, struc
 
 void kvm_show_code(kvm_context_t kvm, int vcpu)
 {
+#define CODE_LEN	50
 #define CR0_PE_MASK	(1ULL<<0)
 	int fd = kvm->vcpu_fd[vcpu];
 	struct kvm_regs regs;
 	struct kvm_sregs sregs;
-	int r;
-	unsigned char code[50];
+	int r, n;
 	int back_offset;
-	char code_str[sizeof(code) * 3 + 1];
+	unsigned char code;
+	char code_str[CODE_LEN * 3 + 1];
 	unsigned long rip;
 
 	r = ioctl(fd, KVM_GET_SREGS, &sregs);
@@ -420,12 +421,14 @@ void kvm_show_code(kvm_context_t kvm, in
 	back_offset = regs.rip;
 	if (back_offset > 20)
 	    back_offset = 20;
-	memcpy(code, kvm->physical_memory + rip - back_offset, sizeof code);
 	*code_str = 0;
-	for (r = 0; r < sizeof code; ++r) {
-	    	if (r == back_offset)
+	for (n = -back_offset; n < CODE_LEN-back_offset; ++n) {
+		if (n == 0)
 			strcat(code_str, " -->");
-		sprintf(code_str + strlen(code_str), " %02x", code[r]);
+		r = kvm->callbacks->mmio_read(kvm->opaque, rip + n, &code, 1);
+		if (r < 0)
+			code = *(unsigned char *)(kvm->physical_memory + rip + n);
+		sprintf(code_str + strlen(code_str), " %02x", code);
 	}
 	fprintf(stderr, "code:%s\n", code_str);
 }

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone

#1 lore raw
Quoted 8 lines · Jan Kiszka

Userland-located ROM memory is not available via kvm->physical_memory + guest_address. To let kvm_show_code also dump useful information when some problem in ROM (BIOS...) occurs, this patch first tries to obtain the memory content via the mmio_read callback - maybe not 100% clean, but works at least for the QEMU use case. If the callback complains about the given address, we then fall back to RAM access.

kvm->physical_memory is actually broken, since nothing guarantees a 1:1 (+offset) mapping.

Why not use ->mmio_read() all the time? Sure it overloads the definition of mmio_read(), but worse things have happened.

Signature · 8 lines
Any sufficiently difficult bug is indistinguishable from a feature.


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
author
#2 lore raw
Quoted 10 lines · Avi Kivity
Quoted 8 lines · Jan Kiszka

Userland-located ROM memory is not available via kvm->physical_memory + guest_address. To let kvm_show_code also dump useful information when some problem in ROM (BIOS...) occurs, this patch first tries to obtain the memory content via the mmio_read callback - maybe not 100% clean, but works at least for the QEMU use case. If the callback complains about the given address, we then fall back to RAM access.

Quoted 5 lines

kvm->physical_memory is actually broken, since nothing guarantees a 1:1 (+offset) mapping.

Why not use ->mmio_read() all the time? Sure it overloads the definition of mmio_read(), but worse things have happened.

That was my first approach as well, but then I became unsure if such an overloading is acceptable. As it is now:

----------

Userland-located memory is not unconditionally available via kvm->physical_memory + guest_address. To let kvm_show_code also dump useful information when, e.g., some problem in ROM (BIOS...) occurs, this patch tries to obtain the memory content via the mmio_read callback. If the callback fails, the code byte is marked as invalid.

This patch also removes the check for protected mode and dumps the code in any case - I didn't find the reason for this restriction.

---
 libkvm/libkvm-x86.c |   23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
libkvm/libkvm-x86.c +12 -11
Index: b/libkvm/libkvm-x86.c
===================================================================
@@ -393,14 +393,14 @@ int kvm_set_pit(kvm_context_t kvm, struc
 
 void kvm_show_code(kvm_context_t kvm, int vcpu)
 {
-#define CR0_PE_MASK	(1ULL<<0)
+#define SHOW_CODE_LEN 50
 	int fd = kvm->vcpu_fd[vcpu];
 	struct kvm_regs regs;
 	struct kvm_sregs sregs;
-	int r;
-	unsigned char code[50];
+	int r, n;
 	int back_offset;
-	char code_str[sizeof(code) * 3 + 1];
+	unsigned char code;
+	char code_str[SHOW_CODE_LEN * 3 + 1];
 	unsigned long rip;
 
 	r = ioctl(fd, KVM_GET_SREGS, &sregs);
@@ -408,9 +408,6 @@ void kvm_show_code(kvm_context_t kvm, in
 		perror("KVM_GET_SREGS");
 		return;
 	}
-	if (sregs.cr0 & CR0_PE_MASK)
-		return;
-
 	r = ioctl(fd, KVM_GET_REGS, &regs);
 	if (r == -1) {
 		perror("KVM_GET_REGS");
@@ -420,12 +417,16 @@ void kvm_show_code(kvm_context_t kvm, in
 	back_offset = regs.rip;
 	if (back_offset > 20)
 	    back_offset = 20;
-	memcpy(code, kvm->physical_memory + rip - back_offset, sizeof code);
 	*code_str = 0;
-	for (r = 0; r < sizeof code; ++r) {
-	    	if (r == back_offset)
+	for (n = -back_offset; n < SHOW_CODE_LEN-back_offset; ++n) {
+		if (n == 0)
 			strcat(code_str, " -->");
-		sprintf(code_str + strlen(code_str), " %02x", code[r]);
+		r = kvm->callbacks->mmio_read(kvm->opaque, rip + n, &code, 1);
+		if (r < 0) {
+			strcat(code_str, " xx");
+			continue;
+		}
+		sprintf(code_str + strlen(code_str), " %02x", code);
 	}
 	fprintf(stderr, "code:%s\n", code_str);
 }

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone

Applied
#3 lore raw
Quoted 10 lines · Jan Kiszka

Userland-located memory is not unconditionally available via kvm->physical_memory + guest_address. To let kvm_show_code also dump useful information when, e.g., some problem in ROM (BIOS...) occurs, this patch tries to obtain the memory content via the mmio_read callback. If the callback fails, the code byte is marked as invalid.

This patch also removes the check for protected mode and dumps the code in any case - I didn't find the reason for this restriction.

Applied, thanks.

Signature · 9 lines
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone