Skip to contentSkip to conversation

kvm tools: Only build/init i8042 on x86

PATCH In review Matt Evans 3 participants 37 messages Dec 9, 2011 – Dec 13, 2011 1 message not in the archive KVM

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Matt Evans

author
#1 lore raw

PATCH v2 1/23 kvm tools: Only build/init i8042 on x86

Not every architecture has an i8042 kbd controller, so only use this when building for x86.

---
 tools/kvm/Makefile      |    2 +-
 tools/kvm/builtin-run.c |    2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)
tools/kvm/Makefile +1 -1
index 243886e..f58a1d8 100644
@@ -77,7 +77,6 @@ OBJS	+= util/strbuf.o
 OBJS	+= virtio/9p.o
 OBJS	+= virtio/9p-pdu.o
 OBJS	+= hw/vesa.o
-OBJS	+= hw/i8042.o
 OBJS	+= hw/pci-shmem.o
 OBJS	+= kvm-ipc.o
 
@@ -153,6 +152,7 @@ ifeq ($(ARCH),x86)
 	OBJS	+= x86/kvm.o
 	OBJS	+= x86/kvm-cpu.o
 	OBJS	+= x86/mptable.o
+	OBJS	+= hw/i8042.o
 # Exclude BIOS object files from header dependencies.
 	OTHEROBJS	+= x86/bios.o
 	OTHEROBJS	+= x86/bios/bios-rom.o
tools/kvm/builtin-run.c +2 -0
index d5abeb4..e273398 100644
@@ -943,7 +943,9 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	kvm__init_ram(kvm);
 
+#ifdef CONFIG_X86
 	kbd__init(kvm);
+#endif
 
 	pci_shmem__init(kvm);
 
author
#2 lore raw

PATCH v2 2/23 kvm tools: Add Makefile parameter for kernel include path

In reply to a message not in the archive

This patch adds an 'I' parameter to override the default kernel include path of '../../include'.

---
 tools/kvm/Makefile |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
tools/kvm/Makefile +7 -2
index f58a1d8..f85a154 100644
@@ -9,7 +9,12 @@ else
 	E = @\#
 	Q =
 endif
-export E Q
+ifneq ($(I), )
+	KINCL_PATH=$(I)
+else
+	KINCL_PATH=../..
+endif
+export E Q KINCL_PATH
 
 include config/utilities.mak
 include config/feature-tests.mak
@@ -176,7 +181,7 @@ DEFINES	+= -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"'
 DEFINES	+= -DBUILD_ARCH='"$(ARCH)"'
 
 KVM_INCLUDE := include
-CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g
+CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I$(KINCL_PATH)/include -I$(KINCL_PATH)/arch/$(ARCH)/include/ -Os -g
 
 ifneq ($(WERROR),0)
 	WARNINGS += -Werror
author
#3 lore raw

PATCH v2 3/23 kvm tools: Re-arrange Makefile to heed CFLAGS before checking for optional libs

In reply to a message not in the archive

The checks for optional libraries build code to perform the tests, so should respect certain CFLAGS -- in particular, -m64 so we check for 64bit libraries if they're required.

---
 tools/kvm/Makefile |   86 ++++++++++++++++++++++++++-------------------------
 1 files changed, 44 insertions(+), 42 deletions(-)
tools/kvm/Makefile +44 -42
index f85a154..009a6ba 100644
@@ -85,48 +85,6 @@ OBJS	+= hw/vesa.o
 OBJS	+= hw/pci-shmem.o
 OBJS	+= kvm-ipc.o
 
-FLAGS_BFD := $(CFLAGS) -lbfd
-has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD))
-ifeq ($(has_bfd),y)
-	CFLAGS	+= -DCONFIG_HAS_BFD
-	OBJS	+= symbol.o
-	LIBS	+= -lbfd
-endif
-
-FLAGS_VNCSERVER := $(CFLAGS) -lvncserver
-has_vncserver := $(call try-cc,$(SOURCE_VNCSERVER),$(FLAGS_VNCSERVER))
-ifeq ($(has_vncserver),y)
-	OBJS	+= ui/vnc.o
-	CFLAGS	+= -DCONFIG_HAS_VNCSERVER
-	LIBS	+= -lvncserver
-endif
-
-FLAGS_SDL := $(CFLAGS) -lSDL
-has_SDL := $(call try-cc,$(SOURCE_SDL),$(FLAGS_SDL))
-ifeq ($(has_SDL),y)
-	OBJS	+= ui/sdl.o
-	CFLAGS	+= -DCONFIG_HAS_SDL
-	LIBS	+= -lSDL
-endif
-
-FLAGS_ZLIB := $(CFLAGS) -lz
-has_ZLIB := $(call try-cc,$(SOURCE_ZLIB),$(FLAGS_ZLIB))
-ifeq ($(has_ZLIB),y)
-	CFLAGS	+= -DCONFIG_HAS_ZLIB
-	LIBS	+= -lz
-endif
-
-FLAGS_AIO := $(CFLAGS) -laio
-has_AIO := $(call try-cc,$(SOURCE_AIO),$(FLAGS_AIO))
-ifeq ($(has_AIO),y)
-	CFLAGS	+= -DCONFIG_HAS_AIO
-	LIBS	+= -laio
-endif
-
-LIBS	+= -lrt
-LIBS	+= -lpthread
-LIBS	+= -lutil
-
 # Additional ARCH settings for x86
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                   -e s/arm.*/arm/ -e s/sa110/arm/ \
@@ -172,6 +130,50 @@ else
 	UNSUPP_ERR =
 endif
 
+
+FLAGS_BFD := $(CFLAGS) -lbfd
+has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD))
+ifeq ($(has_bfd),y)
+	CFLAGS	+= -DCONFIG_HAS_BFD
+	OBJS	+= symbol.o
+	LIBS	+= -lbfd
+endif
+
+FLAGS_VNCSERVER := $(CFLAGS) -lvncserver
+has_vncserver := $(call try-cc,$(SOURCE_VNCSERVER),$(FLAGS_VNCSERVER))
+ifeq ($(has_vncserver),y)
+	OBJS	+= ui/vnc.o
+	CFLAGS	+= -DCONFIG_HAS_VNCSERVER
+	LIBS	+= -lvncserver
+endif
+
+FLAGS_SDL := $(CFLAGS) -lSDL
+has_SDL := $(call try-cc,$(SOURCE_SDL),$(FLAGS_SDL))
+ifeq ($(has_SDL),y)
+	OBJS	+= ui/sdl.o
+	CFLAGS	+= -DCONFIG_HAS_SDL
+	LIBS	+= -lSDL
+endif
+
+FLAGS_ZLIB := $(CFLAGS) -lz
+has_ZLIB := $(call try-cc,$(SOURCE_ZLIB),$(FLAGS_ZLIB))
+ifeq ($(has_ZLIB),y)
+	CFLAGS	+= -DCONFIG_HAS_ZLIB
+	LIBS	+= -lz
+endif
+
+FLAGS_AIO := $(CFLAGS) -laio
+has_AIO := $(call try-cc,$(SOURCE_AIO),$(FLAGS_AIO))
+ifeq ($(has_AIO),y)
+	CFLAGS	+= -DCONFIG_HAS_AIO
+	LIBS	+= -laio
+endif
+
+LIBS	+= -lrt
+LIBS	+= -lpthread
+LIBS	+= -lutil
+
+
 DEPS	:= $(patsubst %.o,%.d,$(OBJS))
 OBJS	+= $(OTHEROBJS)
 
author
#4 lore raw

PATCH v2 4/23 kvm tools: Get correct 64-bit types on PPC64 and link appropriately

In reply to a message not in the archive

kvmtool's types.h includes <asm/types.h>, which by default on PPC64 brings in int-l64.h; define __SANE_USERSPACE_TYPES__ to get LL64 types.

This patch also adds CFLAGS to the final link, so that any -m64 is obeyed when linking, too.

---
 tools/kvm/Makefile              |    2 +-
 tools/kvm/include/linux/types.h |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)
tools/kvm/Makefile +1 -1
index 009a6ba..57dc521 100644
@@ -218,7 +218,7 @@ KVMTOOLS-VERSION-FILE:
 
 $(PROGRAM): $(DEPS) $(OBJS)
 	$(E) "  LINK    " $@
-	$(Q) $(CC) $(OBJS) $(LIBS) -o $@
+	$(Q) $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $@
 
 $(GUEST_INIT): guest/init.c
 	$(E) "  LINK    " $@
tools/kvm/include/linux/types.h +1 -0
index 357799c..5e20f10 100644
@@ -2,6 +2,7 @@
 #define LINUX_TYPES_H
 
 #include <kvm/compiler.h>
+#define __SANE_USERSPACE_TYPES__	/* For PPC64, to get LL64 types */
 #include <asm/types.h>
 
 typedef __u64 u64;
#5 lore raw

Re: [PATCH V2 04/23] kvm tools: Get correct 64-bit types on PPC64 and link appropriately

If you also got kernel patches that add __SANE_USERSPACE_TYPES__ to the headers, and KVM_CAP_NR_VCPUS to KVM PPC, we can carry them in the KVM tools tree as well.

Quoted 37 lines · Matt Evans

kvmtool's types.h includes <asm/types.h>, which by default on PPC64 brings in int-l64.h; define __SANE_USERSPACE_TYPES__ to get LL64 types.

This patch also adds CFLAGS to the final link, so that any -m64 is obeyed when linking, too.

---
 tools/kvm/Makefile              |    2 +-
 tools/kvm/include/linux/types.h |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)
tools/kvm/Makefile +1 -1
index 009a6ba..57dc521 100644
@@ -218,7 +218,7 @@ KVMTOOLS-VERSION-FILE:
 
 $(PROGRAM): $(DEPS) $(OBJS)
 	$(E) "  LINK    " $@
-	$(Q) $(CC) $(OBJS) $(LIBS) -o $@
+	$(Q) $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $@
 
 $(GUEST_INIT): guest/init.c
 	$(E) "  LINK    " $@
tools/kvm/include/linux/types.h +1 -0
index 357799c..5e20f10 100644
@@ -2,6 +2,7 @@
 #define LINUX_TYPES_H
 
 #include <kvm/compiler.h>
+#define __SANE_USERSPACE_TYPES__	/* For PPC64, to get LL64 types */
 #include <asm/types.h>
 
 typedef __u64 u64;
Signature · 1 line
Sasha.
#6 lore raw

Re: [PATCH V2 04/23] kvm tools: Get correct 64-bit types on PPC64 and link appropriately

Quoted 3 lines · Sasha Levin

If you also got kernel patches that add __SANE_USERSPACE_TYPES__ to the headers, and KVM_CAP_NR_VCPUS to KVM PPC, we can carry them in the KVM tools tree as well.

Yup, all we need is ACKs from PPC maintainers.

Pekka

author
#7 lore raw

Re: [PATCH V2 04/23] kvm tools: Get correct 64-bit types on PPC64 and link appropriately

Quoted 6 lines · Pekka Enberg
Quoted 3 lines · Sasha Levin

If you also got kernel patches that add __SANE_USERSPACE_TYPES__ to the headers, and KVM_CAP_NR_VCPUS to KVM PPC, we can carry them in the KVM tools tree as well.

Yup, all we need is ACKs from PPC maintainers.

Cool, I've pinged them re. __SANE_USERSPACE_TYPES__, and that would be useful to carry in your tree. But, IMHO, the patch I sent to Alex ("[PATCH] KVM: PPC: Add KVM_CAP_NR_VCPUS and KVM_CAP_MAX_VCPUS") should go in via his tree. The KVM/PPC-HV kernel folk will get it quicker in their trees (pulled from Alex) and it's not a build problem, "only" a limit of SMP CPU numbers. That is, if you're building a kernel for PPC KVM today you'll probably use something more similar to Alex's tree than mainline/kvm tools tree.

Cheers,

Matt

#8 lore raw

Re: [PATCH V2 04/23] kvm tools: Get correct 64-bit types on PPC64 and link appropriately

Quoted 8 lines · Matt Evans
Quoted 6 lines · Pekka Enberg
Quoted 3 lines · Sasha Levin

If you also got kernel patches that add __SANE_USERSPACE_TYPES__ to the headers, and KVM_CAP_NR_VCPUS to KVM PPC, we can carry them in the KVM tools tree as well.

Yup, all we need is ACKs from PPC maintainers.

Quoted 7 lines

Cool, I've pinged them re. __SANE_USERSPACE_TYPES__, and that would be useful to carry in your tree. But, IMHO, the patch I sent to Alex ("[PATCH] KVM: PPC: Add KVM_CAP_NR_VCPUS and KVM_CAP_MAX_VCPUS") should go in via his tree. The KVM/PPC-HV kernel folk will get it quicker in their trees (pulled from Alex) and it's not a build problem, "only" a limit of SMP CPU numbers. That is, if you're building a kernel for PPC KVM today you'll probably use something more similar to Alex's tree than mainline/kvm tools tree.

Definitely. The __SANE_USERSPACE_TYPES__ patch should probably go to powerpc git tree in addition to our tree.

Pekka

author
#9 lore raw

Re: [PATCH V2 04/23] kvm tools: Get correct 64-bit types on PPC64 and link appropriately

In reply to Matt Evans

Hi Pekka,

Quoted 5 lines · Matt Evans

kvmtool's types.h includes <asm/types.h>, which by default on PPC64 brings in int-l64.h; define __SANE_USERSPACE_TYPES__ to get LL64 types.

This patch also adds CFLAGS to the final link, so that any -m64 is obeyed when linking, too.

Just noticed this patch wasn't included in what you committed from this series, but is required for the PPC64 series to build.

I'm waiting on an ack on the /other/ patch (that adds SANE_USERSPACE_TYPES to PPC64 headers); I have a verbal one, but on-list is better :-) But, /this/ patch is somewhat independent from that.

If you're waiting so they can both go in together, then that's fine too. Just a reminder.

Cheers,

Matt

Quoted 36 lines
---
 tools/kvm/Makefile              |    2 +-
 tools/kvm/include/linux/types.h |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)
tools/kvm/Makefile +1 -1
index 009a6ba..57dc521 100644
@@ -218,7 +218,7 @@ KVMTOOLS-VERSION-FILE:
 
 $(PROGRAM): $(DEPS) $(OBJS)
 	$(E) "  LINK    " $@
-	$(Q) $(CC) $(OBJS) $(LIBS) -o $@
+	$(Q) $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $@
 
 $(GUEST_INIT): guest/init.c
 	$(E) "  LINK    " $@
tools/kvm/include/linux/types.h +1 -1
index 357799c..5e20f10 100644
@@ -2,6 +2,7 @@
 #define LINUX_TYPES_H
 
 #include <kvm/compiler.h>
+#define __SANE_USERSPACE_TYPES__	/* For PPC64, to get LL64 types */
 #include <asm/types.h>
 
 typedef __u64 u64;
--

To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

author
#10 lore raw

PATCH v2 5/23 kvm tools: Add arch-specific KVM_RUN exit handling via kvm_cpu__handle_exit()

In reply to a message not in the archive

This patch creates a new function in x86/kvm-cpu.c, kvm_cpu__handle_exit(), in which arch-specific exit reasons can be handled outside of the common runloop.

---
 tools/kvm/include/kvm/kvm-cpu.h |    2 ++
 tools/kvm/kvm-cpu.c             |   10 ++++++++--
 tools/kvm/x86/kvm-cpu.c         |    5 +++++
 3 files changed, 15 insertions(+), 2 deletions(-)
tools/kvm/include/kvm/kvm-cpu.h +2 -0
index 719e286..15618f1 100644
@@ -2,6 +2,7 @@
 #define KVM__KVM_CPU_H
 
 #include "kvm/kvm-cpu-arch.h"
+#include <stdbool.h>
 
 struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id);
 void kvm_cpu__delete(struct kvm_cpu *vcpu);
@@ -11,6 +12,7 @@ void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu);
 void kvm_cpu__run(struct kvm_cpu *vcpu);
 void kvm_cpu__reboot(void);
 int kvm_cpu__start(struct kvm_cpu *cpu);
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu);
 
 int kvm_cpu__get_debug_fd(void);
 void kvm_cpu__set_debug_fd(int fd);
tools/kvm/kvm-cpu.c +8 -2
index 5aba3bb..9bc0796 100644
@@ -137,8 +137,14 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 			goto exit_kvm;
 		case KVM_EXIT_SHUTDOWN:
 			goto exit_kvm;
-		default:
-			goto panic_kvm;
+		default: {
+			bool ret;
+
+			ret = kvm_cpu__handle_exit(cpu);
+			if (!ret)
+				goto panic_kvm;
+			break;
+		}
 		}
 		kvm_cpu__handle_coalesced_mmio(cpu);
 	}
tools/kvm/x86/kvm-cpu.c +5 -0
index b26b208..a0d10cc 100644
@@ -212,6 +212,11 @@ void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
 	kvm_cpu__setup_msrs(vcpu);
 }
 
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
+{
+	return false;
+}
+
 static void print_dtable(const char *name, struct kvm_dtable *dtable)
 {
 	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
author
#11 lore raw

PATCH v2 6/23 kvm tools: Don't die if KVM_CAP_NR_VCPUS isn't available

In reply to a message not in the archive

We die() if we can't read KVM_CAP_NR_VCPUS, but the API docs suggest to assume the value 4 in this case. This is pertinent to PPC KVM, which currently does not support this CAP.

---
 tools/kvm/kvm.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
tools/kvm/kvm.c +5 -1
index 0356d74..0bbe9ba 100644
@@ -266,7 +266,11 @@ int kvm__recommended_cpus(struct kvm *kvm)
 
 	ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_NR_VCPUS);
 	if (ret <= 0)
-		die_perror("KVM_CAP_NR_VCPUS");
+		/*
+		 * api.txt states that if KVM_CAP_NR_VCPUS does not exist,
+		 * assume 4.
+		 */
+		return 4;
 
 	return ret;
 }
author
#12 lore raw

PATCH v2 7/23 kvm tools: Fix KVM_RUN exit code check

In reply to a message not in the archive

kvm_cpu__run() currently die()s if KVM_RUN returns non-zero. Some architectures may return positive values in non-error cases, whereas real errors are always negative return values. Check for those instead.

---
 tools/kvm/kvm-cpu.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
tools/kvm/kvm-cpu.c +1 -1
index 9bc0796..884a89f 100644
@@ -30,7 +30,7 @@ void kvm_cpu__run(struct kvm_cpu *vcpu)
 	int err;
 
 	err = ioctl(vcpu->vcpu_fd, KVM_RUN, 0);
-	if (err && (errno != EINTR && errno != EAGAIN))
+	if (err < 0 && (errno != EINTR && errno != EAGAIN))
 		die_perror("KVM_RUN failed");
 }
 
author
#13 lore raw

PATCH v2 8/23 kvm tools: Add kvm__arch_periodic_poll()

In reply to a message not in the archive

Currently, the SIGALRM handler calls device poll functions (for serial, virtio console) directly. Which devices are present and which require polling is a system-specific decision, so create a new function called from common code & move the x86-specific poll calls into it.

---
 tools/kvm/builtin-run.c     |    3 +--
 tools/kvm/include/kvm/kvm.h |    1 +
 tools/kvm/x86/kvm.c         |    8 ++++++++
 3 files changed, 10 insertions(+), 2 deletions(-)
tools/kvm/builtin-run.c +1 -2
index e273398..47a2f09 100644
@@ -522,8 +522,7 @@ static void handle_debug(int fd, u32 type, u32 len, u8 *msg)
 
 static void handle_sigalrm(int sig)
 {
-	serial8250__inject_interrupt(kvm);
-	virtio_console__inject_interrupt(kvm);
+	kvm__arch_periodic_poll(kvm);
 }
 
 static void handle_stop(int fd, u32 type, u32 len, u8 *msg)
tools/kvm/include/kvm/kvm.h +1 -0
index ca1acc0..60842d5 100644
@@ -56,6 +56,7 @@ void kvm__remove_socket(const char *name);
 void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
 void kvm__arch_setup_firmware(struct kvm *kvm);
 bool kvm__arch_cpu_supports_vm(void);
+void kvm__arch_periodic_poll(struct kvm *kvm);
 
 int load_flat_binary(struct kvm *kvm, int fd);
 bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline, u16 vidmode);
tools/kvm/x86/kvm.c +8 -0
index ac6c91e..70df27e 100644
@@ -4,6 +4,8 @@
 #include "kvm/interrupt.h"
 #include "kvm/mptable.h"
 #include "kvm/util.h"
+#include "kvm/8250-serial.h"
+#include "kvm/virtio-console.h"
 
 #include <asm/bootparam.h>
 #include <linux/kvm.h>
@@ -328,3 +330,9 @@ void kvm__arch_setup_firmware(struct kvm *kvm)
 	/* MP table */
 	mptable_setup(kvm, kvm->nrcpus);
 }
+
+void kvm__arch_periodic_poll(struct kvm *kvm)
+{
+	serial8250__inject_interrupt(kvm);
+	virtio_console__inject_interrupt(kvm);
+}
author
#14 lore raw

PATCH v2 9/23 kvm tools: Move arch-specific cmdline init into kvm__arch_set_cmdline()

In reply to a message not in the archive

Different systems will want different base kernel commandlines, e.g. non-x86 systems probably don't need noapic, i8042.* etc., so set the commandline up in arch-specific code. Then, if the resulting commandline is empty, don't strcat a space onto the front.

---
 tools/kvm/builtin-run.c     |   12 +++++-------
 tools/kvm/include/kvm/kvm.h |    1 +
 tools/kvm/x86/kvm.c         |   11 +++++++++++
 3 files changed, 17 insertions(+), 7 deletions(-)
tools/kvm/builtin-run.c +5 -7
index 47a2f09..68a3246 100644
@@ -835,13 +835,11 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		vidmode = 0;
 
 	memset(real_cmdline, 0, sizeof(real_cmdline));
-	strcpy(real_cmdline, "noapic noacpi pci=conf1 reboot=k panic=1 i8042.direct=1 "
-				"i8042.dumbkbd=1 i8042.nopnp=1");
-	if (vnc || sdl) {
-		strcat(real_cmdline, " video=vesafb console=tty0");
-	} else
-		strcat(real_cmdline, " console=ttyS0 earlyprintk=serial i8042.noaux=1");
-	strcat(real_cmdline, " ");
+	kvm__arch_set_cmdline(real_cmdline, vnc || sdl);
+
+	if (strlen(real_cmdline) > 0)
+		strcat(real_cmdline, " ");
+
 	if (kernel_cmdline)
 		strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline));
 
tools/kvm/include/kvm/kvm.h +1 -0
index 60842d5..fae2ba9 100644
@@ -53,6 +53,7 @@ int kvm__get_sock_by_instance(const char *name);
 int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
 void kvm__remove_socket(const char *name);
 
+void kvm__arch_set_cmdline(char *cmdline, bool video);
 void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
 void kvm__arch_setup_firmware(struct kvm *kvm);
 bool kvm__arch_cpu_supports_vm(void);
tools/kvm/x86/kvm.c +11 -0
index 70df27e..b49b372 100644
@@ -119,6 +119,17 @@ void kvm__init_ram(struct kvm *kvm)
 	}
 }
 
+/* Arch-specific commandline setup */
+void kvm__arch_set_cmdline(char *cmdline, bool video)
+{
+	strcpy(cmdline, "noapic noacpi pci=conf1 reboot=k panic=1 i8042.direct=1 "
+				"i8042.dumbkbd=1 i8042.nopnp=1");
+	if (video) {
+		strcat(cmdline, " video=vesafb console=tty0");
+	} else
+		strcat(cmdline, " console=ttyS0 earlyprintk=serial i8042.noaux=1");
+}
+
 /* Architecture-specific KVM init */
 void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name)
 {
author
#15 lore raw

PATCH v2 10/23 kvm tools: Add CONSOLE_HV term type and allow it to be selected

In reply to a message not in the archive

This patch paves the way for adding a hypervisor console, useful on systems that support one out of the box yet don't have either serial port or virtio console support (e.g. kernels expecting POWER SPAPR).

---
 tools/kvm/builtin-run.c      |    8 ++++++--
 tools/kvm/include/kvm/term.h |    1 +
 2 files changed, 7 insertions(+), 2 deletions(-)
tools/kvm/builtin-run.c +6 -2
index 68a3246..c067685 100644
@@ -416,7 +416,7 @@ static const struct option options[] = {
 	OPT_BOOLEAN('\0', "rng", &virtio_rng, "Enable virtio Random Number Generator"),
 	OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name",
 		     "Enable virtio 9p to share files between host and guest", virtio_9p_rootdir_parser),
-	OPT_STRING('\0', "console", &console, "serial or virtio",
+	OPT_STRING('\0', "console", &console, "serial, virtio or hv",
 			"Console to use"),
 	OPT_STRING('\0', "dev", &dev, "device_file", "KVM device file"),
 	OPT_CALLBACK('\0', "tty", NULL, "tty id",
@@ -776,8 +776,12 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	if (!strncmp(console, "virtio", 6))
 		active_console  = CONSOLE_VIRTIO;
-	else
+	else if (!strncmp(console, "serial", 6))
 		active_console  = CONSOLE_8250;
+	else if (!strncmp(console, "hv", 2))
+		active_console = CONSOLE_HV;
+	else
+		pr_warning("No console!");
 
 	if (!host_ip)
 		host_ip = DEFAULT_HOST_ADDR;
tools/kvm/include/kvm/term.h +1 -0
index 938c26f..a6a9822 100644
@@ -6,6 +6,7 @@
 
 #define CONSOLE_8250	1
 #define CONSOLE_VIRTIO	2
+#define CONSOLE_HV	3
 
 int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term);
 int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term);
author
#16 lore raw

PATCH v2 11/23 kvm tools: Fix term_getc(), term_getc_iov() endian bugs

In reply to a message not in the archive

term_getc()'s int c has one byte written into it (at its lowest address) by read_in_full(). This is expected to be the least significant byte, but that isn't the case on BE! Use correct type, unsigned char. A similar issue exists in term_getc_iov(), which needs to write a char to the iov rather than an int.

---
 tools/kvm/term.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)
tools/kvm/term.c +2 -5
index fb5d71c..b7d8934 100644
@@ -30,16 +30,13 @@ int term_fds[4][2];
 
 int term_getc(int who, int term)
 {
-	int c;
+	unsigned char c;
 
 	if (who != active_console)
 		return -1;
-
 	if (read_in_full(term_fds[term][TERM_FD_IN], &c, 1) < 0)
 		return -1;
 
-	c &= 0xff;
-
 	if (term_got_escape) {
 		term_got_escape = false;
 		if (c == 'x')
@@ -84,7 +81,7 @@ int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term)
 	if (c < 0)
 		return 0;
 
-	*((int *)iov[TERM_FD_IN].iov_base)	= c;
+	*((char *)iov[TERM_FD_IN].iov_base)	= (char)c;
 
 	return sizeof(char);
 }
author
#17 lore raw

PATCH v2 12/23 kvm tools: Allow initrd_check() to match a cpio

In reply to a message not in the archive

cpios are valid as initrds too, so allow them through the check.

---
 tools/kvm/kvm.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)
tools/kvm/kvm.c +5 -3
index 0bbe9ba..d26e3d7 100644
@@ -351,10 +351,11 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
 /* RFC 1952 */
 #define GZIP_ID1		0x1f
 #define GZIP_ID2		0x8b
-
+#define CPIO_MAGIC		"0707"
+/* initrd may be gzipped, or a plain cpio */
 static bool initrd_check(int fd)
 {
-	unsigned char id[2];
+	unsigned char id[4];
 
 	if (read_in_full(fd, id, ARRAY_SIZE(id)) < 0)
 		return false;
@@ -362,7 +363,8 @@ static bool initrd_check(int fd)
 	if (lseek(fd, 0, SEEK_SET) < 0)
 		die_perror("lseek");
 
-	return id[0] == GZIP_ID1 && id[1] == GZIP_ID2;
+	return (id[0] == GZIP_ID1 && id[1] == GZIP_ID2) ||
+		!memcmp(id, CPIO_MAGIC, 4);
 }
 
 bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
author
#18 lore raw

PATCH v2 13/23 kvm tools: Allow load_flat_binary() to load an initrd alongside

In reply to a message not in the archive

This patch passes the initrd fd and commandline to load_flat_binary(), which may be used to load both the kernel & an initrd (stashing or inserting the commandline as appropriate) in the same way that load_bzimage() does. This is especially useful when load_bzimage() is unused for a particular architecture. :-)

---
 tools/kvm/include/kvm/kvm.h |    2 +-
 tools/kvm/kvm.c             |   10 ++++++----
 tools/kvm/x86/kvm.c         |   13 ++++++++++---
 3 files changed, 17 insertions(+), 8 deletions(-)
tools/kvm/include/kvm/kvm.h +1 -1
index fae2ba9..5fe6e75 100644
@@ -59,7 +59,7 @@ void kvm__arch_setup_firmware(struct kvm *kvm);
 bool kvm__arch_cpu_supports_vm(void);
 void kvm__arch_periodic_poll(struct kvm *kvm);
 
-int load_flat_binary(struct kvm *kvm, int fd);
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline);
 bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline, u16 vidmode);
 
 /*
tools/kvm/kvm.c +6 -4
index d26e3d7..c54f886 100644
@@ -388,23 +388,25 @@ bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
 
 	ret = load_bzimage(kvm, fd_kernel, fd_initrd, kernel_cmdline, vidmode);
 
-	if (initrd_filename)
-		close(fd_initrd);
-
 	if (ret)
 		goto found_kernel;
 
 	pr_warning("%s is not a bzImage. Trying to load it as a flat binary...", kernel_filename);
 
-	ret = load_flat_binary(kvm, fd_kernel);
+	ret = load_flat_binary(kvm, fd_kernel, fd_initrd, kernel_cmdline);
+
 	if (ret)
 		goto found_kernel;
 
+	if (initrd_filename)
+		close(fd_initrd);
 	close(fd_kernel);
 
 	die("%s is not a valid bzImage or flat binary", kernel_filename);
 
 found_kernel:
+	if (initrd_filename)
+		close(fd_initrd);
 	close(fd_kernel);
 
 	return ret;
tools/kvm/x86/kvm.c +10 -3
index b49b372..a116f4b 100644
@@ -197,17 +197,24 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
 #define BOOT_PROTOCOL_REQUIRED	0x206
 #define LOAD_HIGH		0x01
 
-int load_flat_binary(struct kvm *kvm, int fd)
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
 {
 	void *p;
 	int nr;
 
-	if (lseek(fd, 0, SEEK_SET) < 0)
+	/*
+	 * Some architectures may support loading an initrd alongside the flat kernel,
+	 * but we do not.
+	 */
+	if (fd_initrd != -1)
+		pr_warning("Loading initrd with flat binary not supported.");
+
+	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
 		die_perror("lseek");
 
 	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
 
-	while ((nr = read(fd, p, 65536)) > 0)
+	while ((nr = read(fd_kernel, p, 65536)) > 0)
 		p += nr;
 
 	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
author
#19 lore raw

PATCH v2 14/23 kvm tools: Initialise PCI before devices start getting registered with PCI

In reply to a message not in the archive

Re-arrange pci__init() in builtin-run such that it comes before devices are initialised.

---
 tools/kvm/builtin-run.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
tools/kvm/builtin-run.c +2 -2
index c067685..99db522 100644
@@ -828,6 +828,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	kvm->nrcpus = nrcpus;
 
+	pci__init();
+
 	/*
 	 * vidmode should be either specified
 	 * either set by default
@@ -895,8 +897,6 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	serial8250__init(kvm);
 
-	pci__init();
-
 	if (active_console == CONSOLE_VIRTIO)
 		virtio_console__init(kvm);
 
author
#20 lore raw

PATCH v2 15/23 kvm tools: Perform CPU and firmware setup after devices are added

In reply to a message not in the archive

Currently some devices (in this case kbd, fb, vesa) are initialised after CPU/firmware setup. On some platforms (e.g. PPC) kvm__arch_setup_firmware() may be making a device tree. Any devices added after this point will be missed!

Tiny refactor of builtin-run.c, moving timer start, firmware setup, cpu init to occur last.

---
 tools/kvm/builtin-run.c |   24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)
tools/kvm/builtin-run.c +14 -10
index 99db522..7491428 100644
@@ -932,16 +932,6 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		virtio_net__init(&net_params);
 	}
 
-	kvm__start_timer(kvm);
-
-	kvm__arch_setup_firmware(kvm);
-
-	for (i = 0; i < nrcpus; i++) {
-		kvm_cpus[i] = kvm_cpu__init(kvm, i);
-		if (!kvm_cpus[i])
-			die("unable to initialize KVM VCPU");
-	}
-
 	kvm__init_ram(kvm);
 
 #ifdef CONFIG_X86
@@ -965,6 +955,20 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	fb__start();
 
+	/* Device init all done; firmware init must
+	 * come after this (it may set up device trees etc.)
+	 */
+
+	kvm__start_timer(kvm);
+
+	kvm__arch_setup_firmware(kvm);
+
+	for (i = 0; i < nrcpus; i++) {
+		kvm_cpus[i] = kvm_cpu__init(kvm, i);
+		if (!kvm_cpus[i])
+			die("unable to initialize KVM VCPU");
+	}
+
 	thread_pool__init(nr_online_cpus);
 	ioeventfd__start();
 
author
#21 lore raw

PATCH v2 16/23 kvm tools: Init IRQs after determining nrcpus

In reply to a message not in the archive

IRQ init may involve per-CPU setup/allocation of resources, so make sure kvm->nrcpus is initialised before calling irq__init().

---
 tools/kvm/builtin-run.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
tools/kvm/builtin-run.c +2 -2
index 7491428..7969901 100644
@@ -809,8 +809,6 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	kvm = kvm__init(dev, ram_size, guest_name);
 
-	irq__init(kvm);
-
 	kvm->single_step = single_step;
 
 	ioeventfd__init();
@@ -828,6 +826,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	kvm->nrcpus = nrcpus;
 
+	irq__init(kvm);
+
 	pci__init();
 
 	/*
author
#22 lore raw

PATCH v2 17/23 kvm tools: Add ability to map guest RAM from hugetlbfs

In reply to a message not in the archive

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()). For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

---
 tools/kvm/builtin-run.c      |    4 ++-
 tools/kvm/include/kvm/kvm.h  |    4 +-
 tools/kvm/include/kvm/util.h |    4 +++
 tools/kvm/kvm.c              |    4 +-
 tools/kvm/util.c             |   45 ++++++++++++++++++++++++++++++++++++++++++
 tools/kvm/x86/kvm.c          |   20 +++++++++++++++--
 6 files changed, 73 insertions(+), 8 deletions(-)
tools/kvm/builtin-run.c +3 -1
index 7969901..0acfe81 100644
@@ -82,6 +82,7 @@ static const char *guest_mac;
 static const char *host_mac;
 static const char *script;
 static const char *guest_name;
+static const char *hugetlbfs_path;
 static struct virtio_net_params *net_params;
 static bool single_step;
 static bool readonly_image[MAX_DISK_IMAGES];
@@ -422,6 +423,7 @@ static const struct option options[] = {
 	OPT_CALLBACK('\0', "tty", NULL, "tty id",
 		     "Remap guest TTY into a pty on the host",
 		     tty_parser),
+	OPT_STRING('\0', "hugetlbfs", &hugetlbfs_path, "path", "Hugetlbfs path"),
 
 	OPT_GROUP("Kernel options:"),
 	OPT_STRING('k', "kernel", &kernel_filename, "kernel",
@@ -807,7 +809,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		guest_name = default_name;
 	}
 
-	kvm = kvm__init(dev, ram_size, guest_name);
+	kvm = kvm__init(dev, hugetlbfs_path, ram_size, guest_name);
 
 	kvm->single_step = single_step;
 
tools/kvm/include/kvm/kvm.h +2 -2
index 5fe6e75..7159952 100644
@@ -30,7 +30,7 @@ struct kvm_ext {
 void kvm__set_dir(const char *fmt, ...);
 const char *kvm__get_dir(void);
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name);
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
 int kvm__recommended_cpus(struct kvm *kvm);
 int kvm__max_cpus(struct kvm *kvm);
 void kvm__init_ram(struct kvm *kvm);
@@ -54,7 +54,7 @@ int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
 void kvm__remove_socket(const char *name);
 
 void kvm__arch_set_cmdline(char *cmdline, bool video);
-void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
+void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
 void kvm__arch_setup_firmware(struct kvm *kvm);
 bool kvm__arch_cpu_supports_vm(void);
 void kvm__arch_periodic_poll(struct kvm *kvm);
tools/kvm/include/kvm/util.h +4 -0
index dc2e0b9..1f6fbbd 100644
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <sys/param.h>
 #include <sys/types.h>
+#include <linux/types.h>
 
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
@@ -75,4 +76,7 @@ static inline void msleep(unsigned int msecs)
 {
 	usleep(MSECS_TO_USECS(msecs));
 }
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size);
+
 #endif /* KVM__UTIL_H */
tools/kvm/kvm.c +2 -2
index c54f886..35ca2c5 100644
@@ -306,7 +306,7 @@ int kvm__max_cpus(struct kvm *kvm)
 	return ret;
 }
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
 {
 	struct kvm *kvm;
 	int ret;
@@ -339,7 +339,7 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
 	if (kvm__check_extensions(kvm))
 		die("A required KVM extention is not supported by OS");
 
-	kvm__arch_init(kvm, kvm_dev, ram_size, name);
+	kvm__arch_init(kvm, kvm_dev, hugetlbfs_path, ram_size, name);
 
 	kvm->name = name;
 
tools/kvm/util.c +45 -0

54 lines not on this page · raw message

tools/kvm/x86/kvm.c +17 -3
index a116f4b..31671e7 100644
@@ -130,8 +130,22 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
 		strcat(cmdline, " console=ttyS0 earlyprintk=serial i8042.noaux=1");
 }
 
+/* This function wraps the decision between hugetlbfs map (if requested) or normal mmap */
+static void *mmap_anon_or_hugetlbfs(const char *hugetlbfs_path, u64 size)
+{
+	if (hugetlbfs_path) {
+		/*
+		 * We don't /need/ to map guest RAM from hugetlbfs, but we do so
+		 * if the user specifies a hugetlbfs path.
+		 */
+		return mmap_hugetlbfs(hugetlbfs_path, size);
+	} else {
+		return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+	}
+}
+
 /* Architecture-specific KVM init */
-void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name)
+void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
 {
 	struct kvm_pit_config pit_config = { .flags = 0, };
 	int ret;
@@ -147,9 +161,9 @@ void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const ch
 	kvm->ram_size		= ram_size;
 
 	if (kvm->ram_size < KVM_32BIT_GAP_START) {
-		kvm->ram_start = mmap(NULL, ram_size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+		kvm->ram_start = mmap_anon_or_hugetlbfs(hugetlbfs_path, ram_size);
 	} else {
-		kvm->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+		kvm->ram_start = mmap_anon_or_hugetlbfs(hugetlbfs_path, ram_size + KVM_32BIT_GAP_SIZE);
 		if (kvm->ram_start != MAP_FAILED) {
 			/*
 			 * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
#23 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

Quoted 152 lines · Matt Evans

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()). For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

---
 tools/kvm/builtin-run.c      |    4 ++-
 tools/kvm/include/kvm/kvm.h  |    4 +-
 tools/kvm/include/kvm/util.h |    4 +++
 tools/kvm/kvm.c              |    4 +-
 tools/kvm/util.c             |   45 ++++++++++++++++++++++++++++++++++++++++++
 tools/kvm/x86/kvm.c          |   20 +++++++++++++++--
 6 files changed, 73 insertions(+), 8 deletions(-)
tools/kvm/builtin-run.c +3 -1
index 7969901..0acfe81 100644
@@ -82,6 +82,7 @@ static const char *guest_mac;
 static const char *host_mac;
 static const char *script;
 static const char *guest_name;
+static const char *hugetlbfs_path;
 static struct virtio_net_params *net_params;
 static bool single_step;
 static bool readonly_image[MAX_DISK_IMAGES];
@@ -422,6 +423,7 @@ static const struct option options[] = {
 	OPT_CALLBACK('\0', "tty", NULL, "tty id",
 		     "Remap guest TTY into a pty on the host",
 		     tty_parser),
+	OPT_STRING('\0', "hugetlbfs", &hugetlbfs_path, "path", "Hugetlbfs path"),
 
 	OPT_GROUP("Kernel options:"),
 	OPT_STRING('k', "kernel", &kernel_filename, "kernel",
@@ -807,7 +809,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		guest_name = default_name;
 	}
 
-	kvm = kvm__init(dev, ram_size, guest_name);
+	kvm = kvm__init(dev, hugetlbfs_path, ram_size, guest_name);
 
 	kvm->single_step = single_step;
 
tools/kvm/include/kvm/kvm.h +2 -2
index 5fe6e75..7159952 100644
@@ -30,7 +30,7 @@ struct kvm_ext {
 void kvm__set_dir(const char *fmt, ...);
 const char *kvm__get_dir(void);
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name);
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
 int kvm__recommended_cpus(struct kvm *kvm);
 int kvm__max_cpus(struct kvm *kvm);
 void kvm__init_ram(struct kvm *kvm);
@@ -54,7 +54,7 @@ int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
 void kvm__remove_socket(const char *name);
 
 void kvm__arch_set_cmdline(char *cmdline, bool video);
-void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
+void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
 void kvm__arch_setup_firmware(struct kvm *kvm);
 bool kvm__arch_cpu_supports_vm(void);
 void kvm__arch_periodic_poll(struct kvm *kvm);
tools/kvm/include/kvm/util.h +4 -0
index dc2e0b9..1f6fbbd 100644
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <sys/param.h>
 #include <sys/types.h>
+#include <linux/types.h>
 
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
@@ -75,4 +76,7 @@ static inline void msleep(unsigned int msecs)
 {
 	usleep(MSECS_TO_USECS(msecs));
 }
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size);
+
 #endif /* KVM__UTIL_H */
tools/kvm/kvm.c +2 -2
index c54f886..35ca2c5 100644
@@ -306,7 +306,7 @@ int kvm__max_cpus(struct kvm *kvm)
 	return ret;
 }
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
 {
 	struct kvm *kvm;
 	int ret;
@@ -339,7 +339,7 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
 	if (kvm__check_extensions(kvm))
 		die("A required KVM extention is not supported by OS");
 
-	kvm__arch_init(kvm, kvm_dev, ram_size, name);
+	kvm__arch_init(kvm, kvm_dev, hugetlbfs_path, ram_size, name);
 
 	kvm->name = name;
 
tools/kvm/util.c +30 -0
index 4efbce9..90b6a3b 100644
@@ -4,6 +4,11 @@
 
 #include "kvm/util.h"
 
+#include <linux/magic.h>	/* For HUGETLBFS_MAGIC */
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
 static void report(const char *prefix, const char *err, va_list params)
 {
 	char msg[1024];
@@ -99,3 +104,43 @@ size_t strlcat(char *dest, const char *src, size_t count)
 
 	return res;
 }
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size)
+{
+	char mpath[PATH_MAX];
+	int fd;
+	int r;
+	struct statfs sfs;
+	void *addr;
+
+	do {
+		/*
+		 * QEMU seems to work around this returning EINTR...  Let's do
+		 * that too.
+		 */
+		r = statfs(htlbfs_path, &sfs);
+	} while (r && errno == EINTR);
+
+	if (r)
+		die("Can't stat %s\n", htlbfs_path);
+
+	if (sfs.f_type != HUGETLBFS_MAGIC) {
+		die("%s is not hugetlbfs!\n", htlbfs_path);
+	}
+
+	if (sfs.f_bsize == 0 || (unsigned long)sfs.f_bsize > size) {

tools/kvm/util.c size_t strlcat(char *dest, const char *src, size_t count) · line 141

Quoted 10 lines
tools/kvm/util.c +10 -0
+		die("Can't use hugetlbfs pagesize %ld for mem size %lld\n",
+		    sfs.f_bsize, size);
+	}
+
+	snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path);
+	fd = mkstemp(mpath);
+	if (fd < 0)
+		die("Can't open %s for hugetlbfs map\n", mpath);
+	unlink(mpath);
+	ftruncate(fd, size);

Getting this thing here:

cc1: warnings being treated as errors
util.c: In function 'mmap_hugetlbfs':
util.c:141:11: error: ignoring return value of 'ftruncate', declared with attribute warn_unused_result
make: *** [util.o] Error 1

Signature · 1 line
Sasha.
author
#24 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

Quoted 166 lines · Sasha Levin
Quoted 152 lines · Matt Evans

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()). For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

---
 tools/kvm/builtin-run.c      |    4 ++-
 tools/kvm/include/kvm/kvm.h  |    4 +-
 tools/kvm/include/kvm/util.h |    4 +++
 tools/kvm/kvm.c              |    4 +-
 tools/kvm/util.c             |   45 ++++++++++++++++++++++++++++++++++++++++++
 tools/kvm/x86/kvm.c          |   20 +++++++++++++++--
 6 files changed, 73 insertions(+), 8 deletions(-)
tools/kvm/builtin-run.c +3 -1
index 7969901..0acfe81 100644
@@ -82,6 +82,7 @@ static const char *guest_mac;
 static const char *host_mac;
 static const char *script;
 static const char *guest_name;
+static const char *hugetlbfs_path;
 static struct virtio_net_params *net_params;
 static bool single_step;
 static bool readonly_image[MAX_DISK_IMAGES];
@@ -422,6 +423,7 @@ static const struct option options[] = {
 	OPT_CALLBACK('\0', "tty", NULL, "tty id",
 		     "Remap guest TTY into a pty on the host",
 		     tty_parser),
+	OPT_STRING('\0', "hugetlbfs", &hugetlbfs_path, "path", "Hugetlbfs path"),
 
 	OPT_GROUP("Kernel options:"),
 	OPT_STRING('k', "kernel", &kernel_filename, "kernel",
@@ -807,7 +809,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 		guest_name = default_name;
 	}
 
-	kvm = kvm__init(dev, ram_size, guest_name);
+	kvm = kvm__init(dev, hugetlbfs_path, ram_size, guest_name);
 
 	kvm->single_step = single_step;
 
tools/kvm/include/kvm/kvm.h +2 -2
index 5fe6e75..7159952 100644
@@ -30,7 +30,7 @@ struct kvm_ext {
 void kvm__set_dir(const char *fmt, ...);
 const char *kvm__get_dir(void);
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name);
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
 int kvm__recommended_cpus(struct kvm *kvm);
 int kvm__max_cpus(struct kvm *kvm);
 void kvm__init_ram(struct kvm *kvm);
@@ -54,7 +54,7 @@ int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
 void kvm__remove_socket(const char *name);
 
 void kvm__arch_set_cmdline(char *cmdline, bool video);
-void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
+void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
 void kvm__arch_setup_firmware(struct kvm *kvm);
 bool kvm__arch_cpu_supports_vm(void);
 void kvm__arch_periodic_poll(struct kvm *kvm);
tools/kvm/include/kvm/util.h +4 -0
index dc2e0b9..1f6fbbd 100644
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <sys/param.h>
 #include <sys/types.h>
+#include <linux/types.h>
 
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
@@ -75,4 +76,7 @@ static inline void msleep(unsigned int msecs)
 {
 	usleep(MSECS_TO_USECS(msecs));
 }
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size);
+
 #endif /* KVM__UTIL_H */
tools/kvm/kvm.c +2 -2
index c54f886..35ca2c5 100644
@@ -306,7 +306,7 @@ int kvm__max_cpus(struct kvm *kvm)
 	return ret;
 }
 
-struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
 {
 	struct kvm *kvm;
 	int ret;
@@ -339,7 +339,7 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
 	if (kvm__check_extensions(kvm))
 		die("A required KVM extention is not supported by OS");
 
-	kvm__arch_init(kvm, kvm_dev, ram_size, name);
+	kvm__arch_init(kvm, kvm_dev, hugetlbfs_path, ram_size, name);
 
 	kvm->name = name;
 
tools/kvm/util.c +30 -0
index 4efbce9..90b6a3b 100644
@@ -4,6 +4,11 @@
 
 #include "kvm/util.h"
 
+#include <linux/magic.h>	/* For HUGETLBFS_MAGIC */
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
 static void report(const char *prefix, const char *err, va_list params)
 {
 	char msg[1024];
@@ -99,3 +104,43 @@ size_t strlcat(char *dest, const char *src, size_t count)
 
 	return res;
 }
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size)
+{
+	char mpath[PATH_MAX];
+	int fd;
+	int r;
+	struct statfs sfs;
+	void *addr;
+
+	do {
+		/*
+		 * QEMU seems to work around this returning EINTR...  Let's do
+		 * that too.
+		 */
+		r = statfs(htlbfs_path, &sfs);
+	} while (r && errno == EINTR);
+
+	if (r)
+		die("Can't stat %s\n", htlbfs_path);
+
+	if (sfs.f_type != HUGETLBFS_MAGIC) {
+		die("%s is not hugetlbfs!\n", htlbfs_path);
+	}
+
+	if (sfs.f_bsize == 0 || (unsigned long)sfs.f_bsize > size) {

tools/kvm/util.c size_t strlcat(char *dest, const char *src, size_t count) · line 141

Quoted 10 lines
tools/kvm/util.c +10 -0
+		die("Can't use hugetlbfs pagesize %ld for mem size %lld\n",
+		    sfs.f_bsize, size);
+	}
+
+	snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path);
+	fd = mkstemp(mpath);
+	if (fd < 0)
+		die("Can't open %s for hugetlbfs map\n", mpath);
+	unlink(mpath);
+	ftruncate(fd, size);

Getting this thing here:

Quoted 5 lines

cc1: warnings being treated as errors
util.c: In function 'mmap_hugetlbfs':
util.c:141:11: error: ignoring return value of 'ftruncate', declared with attribute warn_unused_result
make: *** [util.o] Error 1

Ooookay, I swear I'm not seeing that here, GCC 4.6.2 & no extra -W flags added.

I've added a check of ftruncate()'s return value, anyway.

Thanks,

Matt

#25 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

In reply to Matt Evans
Quoted 11 lines · Matt Evans

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()).  For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

tools/kvm/util.c +5 -0
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size)
+{
+       char mpath[PATH_MAX];
+       int fd;
+       int r;

tools/kvm/util.c size_t strlcat(char *dest, const char *src, size_t count)

Quoted 10 lines
tools/kvm/util.c +10 -0
+       struct statfs sfs;
+       void *addr;
+
+       do {
+               /*
+                * QEMU seems to work around this returning EINTR...  Let's do
+                * that too.
+                */
+               r = statfs(htlbfs_path, &sfs);
+       } while (r && errno = EINTR);

Can this really happen? What about EAGAIN? The retry logic really wants to live in tools/kvm/read-write.c as a xstatfs() wrapper if we do need this.

Pekka

author
#26 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

Quoted 18 lines · Pekka Enberg
Quoted 17 lines · Matt Evans

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()). For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

tools/kvm/util.c +11 -0
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size)
+{
+       char mpath[PATH_MAX];
+       int fd;
+       int r;
+       struct statfs sfs;
+       void *addr;
+
+       do {
+               /*
+                * QEMU seems to work around this returning EINTR...  Let's do
Quoted 8 lines

tools/kvm/util.c size_t strlcat(char *dest, const char *src, size_t count) · line 122

Quoted 4 lines
tools/kvm/util.c +4 -0
+                * that too.
+                */
+               r = statfs(htlbfs_path, &sfs);
+       } while (r && errno == EINTR);

Can this really happen? What about EAGAIN? The retry logic really wants to live in tools/kvm/read-write.c as a xstatfs() wrapper if we do need this.

I don't think it can. As per the comment, I thought QEMU knew something I didn't but I haven't seen any other reason for doing this. I'll remove it, thanks for the sanity jolt.

Matt

#27 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

In reply to Matt Evans
Quoted 5 lines · Matt Evans

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()).  For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

Btw, why don't you want to use MADV_HUGEPAGE for this? You could just do it unconditionally, no?

author
#28 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

Quoted 9 lines · Pekka Enberg
Quoted 5 lines · Matt Evans

Add a --hugetlbfs commandline option to give a path to hugetlbfs-map guest memory (down in kvm__arch_init()). For x86, guest memory is a normal ANON mmap() if this option is not provided, otherwise a hugetlbfs mmap.

Btw, why don't you want to use MADV_HUGEPAGE for this? You could just do it unconditionally, no?

Well, I'm manually mapping from hugetlbfs as currently* PPC KVM requires hugepages to back guest RAM and MADV_HUGEPAGE is just a hint, no? I also wanted things to work on kernels without transparent hugepages enabled. I think it's safer to do things explicitly, as if the user requests hugepages it's more transparent (I'm thinking benchmarking, etc.) to be definitely using hugepages.

Cheers,

Matt

*: I know Paul's posted patches to implement smallpage support... so this will
change in time.

#29 lore raw

Re: [PATCH V2 17/23] kvm tools: Add ability to map guest RAM from hugetlbfs

Quoted 5 lines · Matt Evans

Well, I'm manually mapping from hugetlbfs as currently* PPC KVM requires hugepages to back guest RAM and MADV_HUGEPAGE is just a hint, no?  I also wanted things to work on kernels without transparent hugepages enabled.  I think it's safer to do things explicitly, as if the user requests hugepages it's more transparent (I'm thinking benchmarking, etc.) to be definitely using hugepages.

OK, makes sense. You should probably mention that in the changelog.

author
#30 lore raw

PATCH v2 18/23 kvm tools: Move PCI_MAX_DEVICES to pci.h

In reply to a message not in the archive

Other pieces of kvmtool may be interested in PCI_MAX_DEVICES.

---
 tools/kvm/include/kvm/pci.h |    1 +
 tools/kvm/pci.c             |    1 -
 2 files changed, 1 insertions(+), 1 deletions(-)
tools/kvm/include/kvm/pci.h +1 -0
index f71af0b..b578ad7 100644
@@ -6,6 +6,7 @@
 #include <linux/pci_regs.h>
 #include <linux/msi.h>
 
+#define PCI_MAX_DEVICES			256
 /*
  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
  * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
tools/kvm/pci.c +0 -1
index d1afc05..920e13e 100644
@@ -5,7 +5,6 @@
 
 #include <assert.h>
 
-#define PCI_MAX_DEVICES			256
 #define PCI_BAR_OFFSET(b)		(offsetof(struct pci_device_header, bar[b]))
 
 static struct pci_device_header		*pci_devices[PCI_MAX_DEVICES];
author
#31 lore raw

PATCH v2 19/23 kvm tools: Endian-sanitise pci.h and PCI device setup

In reply to a message not in the archive

vesa, pci-shmem and virtio-pci devices need to set up config space with little-endian conversions (as config space is LE). The pci_config_address bitfield also needs to be reversed when building on BE systems.

---
 tools/kvm/hw/pci-shmem.c       |   23 +++++++++++----------
 tools/kvm/hw/vesa.c            |   15 +++++++------
 tools/kvm/include/kvm/ioport.h |   11 +++++----
 tools/kvm/include/kvm/pci.h    |   40 ++++++++++++++++++++++++++------------
 tools/kvm/pci.c                |    4 +-
 tools/kvm/virtio/pci.c         |   41 +++++++++++++++++++++------------------
 6 files changed, 77 insertions(+), 57 deletions(-)
tools/kvm/hw/pci-shmem.c +12 -11
index 780a377..fd954c5 100644
@@ -8,21 +8,22 @@
 #include "kvm/ioeventfd.h"
 
 #include <linux/kvm.h>
+#include <linux/byteorder.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 
 static struct pci_device_header pci_shmem_pci_device = {
-	.vendor_id	= PCI_VENDOR_ID_REDHAT_QUMRANET,
-	.device_id	= 0x1110,
+	.vendor_id	= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+	.device_id	= cpu_to_le16(0x1110),
 	.header_type	= PCI_HEADER_TYPE_NORMAL,
-	.class		= 0xFF0000,	/* misc pci device */
-	.status		= PCI_STATUS_CAP_LIST,
+	.class[2]	= 0xFF,	/* misc pci device */
+	.status		= cpu_to_le16(PCI_STATUS_CAP_LIST),
 	.capabilities	= (void *)&pci_shmem_pci_device.msix - (void *)&pci_shmem_pci_device,
 	.msix.cap	= PCI_CAP_ID_MSIX,
-	.msix.ctrl	= 1,
-	.msix.table_offset = 1,		/* Use BAR 1 */
-	.msix.pba_offset = 0x1001,	/* Use BAR 1 */
+	.msix.ctrl	= cpu_to_le16(1),
+	.msix.table_offset = cpu_to_le32(1),		/* Use BAR 1 */
+	.msix.pba_offset = cpu_to_le32(0x1001),		/* Use BAR 1 */
 };
 
 /* registers for the Inter-VM shared memory device */
@@ -123,7 +124,7 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm)
 		if (fd < 0)
 			return fd;
 
-		if (pci_shmem_pci_device.msix.ctrl & PCI_MSIX_FLAGS_ENABLE) {
+		if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
 			gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
 		} else {
 			gsi = pci_shmem_pci_device.irq_line;
@@ -241,11 +242,11 @@ int pci_shmem__init(struct kvm *kvm)
 	 * 1 - MSI-X MMIO space
 	 * 2 - Shared memory block
 	 */
-	pci_shmem_pci_device.bar[0] = ivshmem_registers | PCI_BASE_ADDRESS_SPACE_IO;
+	pci_shmem_pci_device.bar[0] = cpu_to_le32(ivshmem_registers | PCI_BASE_ADDRESS_SPACE_IO);
 	pci_shmem_pci_device.bar_size[0] = shmem_region->size;
-	pci_shmem_pci_device.bar[1] = msix_block | PCI_BASE_ADDRESS_SPACE_MEMORY;
+	pci_shmem_pci_device.bar[1] = cpu_to_le32(msix_block | PCI_BASE_ADDRESS_SPACE_MEMORY);
 	pci_shmem_pci_device.bar_size[1] = 0x1010;
-	pci_shmem_pci_device.bar[2] = shmem_region->phys_addr | PCI_BASE_ADDRESS_SPACE_MEMORY;
+	pci_shmem_pci_device.bar[2] = cpu_to_le32(shmem_region->phys_addr | PCI_BASE_ADDRESS_SPACE_MEMORY);
 	pci_shmem_pci_device.bar_size[2] = shmem_region->size;
 
 	pci__register(&pci_shmem_pci_device, dev);
tools/kvm/hw/vesa.c +8 -7
index 22b1652..63f1082 100644
@@ -8,6 +8,7 @@
 #include "kvm/irq.h"
 #include "kvm/kvm.h"
 #include "kvm/pci.h"
+#include <linux/byteorder.h>
 #include <sys/mman.h>
 
 #include <sys/types.h>
@@ -31,14 +32,14 @@ static struct ioport_operations vesa_io_ops = {
 };
 
 static struct pci_device_header vesa_pci_device = {
-	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
-	.device_id		= PCI_DEVICE_ID_VESA,
+	.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+	.device_id		= cpu_to_le16(PCI_DEVICE_ID_VESA),
 	.header_type		= PCI_HEADER_TYPE_NORMAL,
 	.revision_id		= 0,
-	.class			= 0x030000,
-	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-	.subsys_id		= PCI_SUBSYSTEM_ID_VESA,
-	.bar[1]			= VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY,
+	.class[2]		= 0x03,
+	.subsys_vendor_id	= cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+	.subsys_id		= cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
+	.bar[1]			= cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY),
 	.bar_size[1]		= VESA_MEM_SIZE,
 };
 
@@ -56,7 +57,7 @@ struct framebuffer *vesa__init(struct kvm *kvm)
 	vesa_pci_device.irq_pin		= pin;
 	vesa_pci_device.irq_line	= line;
 	vesa_base_addr			= ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
-	vesa_pci_device.bar[0]		= vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO;
+	vesa_pci_device.bar[0]		= cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
 	pci__register(&vesa_pci_device, dev);
 
 	mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
tools/kvm/include/kvm/ioport.h +6 -5
index 61a70ec..09bf876 100644
@@ -7,6 +7,7 @@
 #include <limits.h>
 #include <asm/types.h>
 #include <linux/types.h>
+#include <linux/byteorder.h>
 
 /* some ports we reserve for own use */
 #define IOPORT_DBG			0xe0
@@ -36,15 +37,15 @@ static inline u8 ioport__read8(u8 *data)
 {
 	return *data;
 }
-
+/* On BE platforms, PCI I/O is byteswapped, i.e. LE, so swap back. */
 static inline u16 ioport__read16(u16 *data)
 {
-	return *data;
+	return le16_to_cpu(*data);
 }
 
 static inline u32 ioport__read32(u32 *data)
 {
-	return *data;
+	return le32_to_cpu(*data);
 }
 
 static inline void ioport__write8(u8 *data, u8 value)
@@ -54,12 +55,12 @@ static inline void ioport__write8(u8 *data, u8 value)
 
 static inline void ioport__write16(u16 *data, u16 value)
 {
-	*data		 = value;
+	*data		 = cpu_to_le16(value);
 }
 
 static inline void ioport__write32(u32 *data, u32 value)
 {
-	*data		 = value;
+	*data		 = cpu_to_le32(value);
 }
 
 #endif /* KVM__IOPORT_H */
tools/kvm/include/kvm/pci.h +27 -13
index b578ad7..21f93d0 100644
@@ -5,6 +5,7 @@
 #include <linux/kvm.h>
 #include <linux/pci_regs.h>
 #include <linux/msi.h>
+#include <endian.h>
 
 #define PCI_MAX_DEVICES			256
 /*
@@ -17,14 +18,27 @@
 #define PCI_CONFIG_BUS_FORWARD	0xcfa
 #define PCI_IO_SIZE		0x100
 
-struct pci_config_address {
-	unsigned	zeros		: 2;		/* 1  .. 0  */
-	unsigned	register_number	: 6;		/* 7  .. 2  */
-	unsigned	function_number	: 3;		/* 10 .. 8  */
-	unsigned	device_number	: 5;		/* 15 .. 11 */
-	unsigned	bus_number	: 8;		/* 23 .. 16 */
-	unsigned	reserved	: 7;		/* 30 .. 24 */
-	unsigned	enable_bit	: 1;		/* 31       */
+union pci_config_address {
+	struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+		unsigned	zeros		: 2;		/* 1  .. 0  */
+		unsigned	register_number	: 6;		/* 7  .. 2  */
+		unsigned	function_number	: 3;		/* 10 .. 8  */
+		unsigned	device_number	: 5;		/* 15 .. 11 */
+		unsigned	bus_number	: 8;		/* 23 .. 16 */
+		unsigned	reserved	: 7;		/* 30 .. 24 */
+		unsigned	enable_bit	: 1;		/* 31       */
+#else
+		unsigned	enable_bit	: 1;		/* 31       */
+		unsigned	reserved	: 7;		/* 30 .. 24 */
+		unsigned	bus_number	: 8;		/* 23 .. 16 */
+		unsigned	device_number	: 5;		/* 15 .. 11 */
+		unsigned	function_number	: 3;		/* 10 .. 8  */
+		unsigned	register_number	: 6;		/* 7  .. 2  */
+		unsigned	zeros		: 2;		/* 1  .. 0  */
+#endif
+	};
+	u32 w;
 };
 
 struct msix_table {
@@ -45,8 +59,8 @@ struct pci_device_header {
 	u16		device_id;
 	u16		command;
 	u16		status;
-	u16		revision_id		:  8;
-	u32		class			: 24;
+	u8		revision_id;
+	u8		class[3];
 	u8		cacheline_size;
 	u8		latency_timer;
 	u8		header_type;
@@ -56,8 +70,8 @@ struct pci_device_header {
 	u16		subsys_vendor_id;
 	u16		subsys_id;
 	u32		exp_rom_bar;
-	u32		capabilities		:  8;
-	u32		reserved1		: 24;
+	u8		capabilities;
+	u8		reserved1[3];
 	u32		reserved2;
 	u8		irq_line;
 	u8		irq_pin;
@@ -66,7 +80,7 @@ struct pci_device_header {
 	struct msix_cap msix;
 	u8		empty[136]; /* Rest of PCI config space */
 	u32		bar_size[6];
-};
+} __attribute__((packed));
 
 void pci__init(void);
 void pci__register(struct pci_device_header *dev, u8 dev_num);
tools/kvm/pci.c +2 -2
index 920e13e..5bbcbc7 100644
@@ -9,7 +9,7 @@
 
 static struct pci_device_header		*pci_devices[PCI_MAX_DEVICES];
 
-static struct pci_config_address	pci_config_address;
+static union pci_config_address		pci_config_address;
 
 /* This is within our PCI gap - in an unused area */
 static u32 io_space_blocks		= KVM_32BIT_GAP_START + 0x1000000;
@@ -105,7 +105,7 @@ static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port
 			 * When the kernel got the size it would write the address
 			 * back.
 			 */
-			if (ioport__read32(p + offset)) {
+			if (*(u32 *)(p + offset)) {
 				/* See if kernel tries to mask one of the BARs */
 				if ((offset >= PCI_BAR_OFFSET(0)) &&
 				    (offset <= PCI_BAR_OFFSET(6)) &&
tools/kvm/virtio/pci.c +22 -19

84 lines not on this page · raw message

author
#32 lore raw

PATCH v2 20/23 kvm tools: Correctly set virtio-pci bar_size and remove hardwired address

In reply to a message not in the archive

The BAR addresses are set up fine, but missed the bar_size[] array which is now updated correspondingly.

Use PCI_IO_SIZE instead of '0x100'.

---
 tools/kvm/virtio/pci.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)
tools/kvm/virtio/pci.c +5 -2
index acb7d96..0b44a19 100644
@@ -293,8 +293,8 @@ int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
 	vpci->msix_pba_block = pci_get_io_space_block(PCI_IO_SIZE);
 
 	vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vtrans);
-	kvm__register_mmio(kvm, vpci->msix_io_block, 0x100, callback_mmio_table, vpci);
-	kvm__register_mmio(kvm, vpci->msix_pba_block, 0x100, callback_mmio_pba, vpci);
+	kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE, callback_mmio_table, vpci);
+	kvm__register_mmio(kvm, vpci->msix_pba_block, PCI_IO_SIZE, callback_mmio_pba, vpci);
 
 	vpci->pci_hdr = (struct pci_device_header) {
 		.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
@@ -313,6 +313,9 @@ int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
 						      | PCI_BASE_ADDRESS_MEM_TYPE_64),
 		.status			= cpu_to_le16(PCI_STATUS_CAP_LIST),
 		.capabilities		= (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr,
+		.bar_size[0]		= IOPORT_SIZE,
+		.bar_size[1]		= PCI_IO_SIZE,
+		.bar_size[3]		= PCI_IO_SIZE,
 	};
 
 	vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
author
#33 lore raw

PATCH v2 21/23 kvm tools: Add pci__config_{rd,wr}(), pci__find_dev()

In reply to a message not in the archive

This allows config space access in a more natural manner than clunky x86 IO ports, and is useful for other architectures. Internally, the x86 IO port access uses these new config space interfaces.

---
 tools/kvm/include/kvm/pci.h |    9 +++++-
 tools/kvm/pci.c             |   63 ++++++++++++++++++++++++++-----------------
 2 files changed, 45 insertions(+), 27 deletions(-)
tools/kvm/include/kvm/pci.h +7 -2
index 21f93d0..07b5403 100644
@@ -7,6 +7,8 @@
 #include <linux/msi.h>
 #include <endian.h>
 
+#include "kvm/kvm.h"
+
 #define PCI_MAX_DEVICES			256
 /*
  * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
@@ -21,7 +23,7 @@
 union pci_config_address {
 	struct {
 #if __BYTE_ORDER == __LITTLE_ENDIAN
-		unsigned	zeros		: 2;		/* 1  .. 0  */
+		unsigned	reg_offset	: 2;		/* 1  .. 0  */
 		unsigned	register_number	: 6;		/* 7  .. 2  */
 		unsigned	function_number	: 3;		/* 10 .. 8  */
 		unsigned	device_number	: 5;		/* 15 .. 11 */
@@ -35,7 +37,7 @@ union pci_config_address {
 		unsigned	device_number	: 5;		/* 15 .. 11 */
 		unsigned	function_number	: 3;		/* 10 .. 8  */
 		unsigned	register_number	: 6;		/* 7  .. 2  */
-		unsigned	zeros		: 2;		/* 1  .. 0  */
+		unsigned	reg_offset	: 2;		/* 1  .. 0  */
 #endif
 	};
 	u32 w;
@@ -84,6 +86,9 @@ struct pci_device_header {
 
 void pci__init(void);
 void pci__register(struct pci_device_header *dev, u8 dev_num);
+struct pci_device_header *pci__find_dev(u8 dev_num);
 u32 pci_get_io_space_block(u32 size);
+void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
+void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
 
 #endif /* KVM__PCI_H */
tools/kvm/pci.c +38 -25

108 lines not on this page · raw message

author
#34 lore raw

PATCH v2 22/23 kvm tools: Arch-specific define for PCI MMIO allocation area

In reply to a message not in the archive

pci_get_io_space_block() used to grab addresses from KVM_32BIT_GAP_START + 0x1000000, which is x86-specific. Create a new define, KVM_PCI_MMIO_AREA, to specify a bus address these allocations can come from.

---
 tools/kvm/pci.c                      |    8 ++++++--
 tools/kvm/x86/include/kvm/kvm-arch.h |    5 +++++
 2 files changed, 11 insertions(+), 2 deletions(-)
tools/kvm/pci.c +6 -2
index 95df169..59b2618 100644
@@ -11,8 +11,12 @@ static struct pci_device_header		*pci_devices[PCI_MAX_DEVICES];
 
 static union pci_config_address		pci_config_address;
 
-/* This is within our PCI gap - in an unused area */
-static u32 io_space_blocks		= KVM_32BIT_GAP_START + 0x1000000;
+/* This is within our PCI gap - in an unused area.
+ * Note this is a PCI *bus address*, is used to assign BARs etc.!
+ * (That's why it can still 32bit even with 64bit guests-- 64bit
+ * PCI isn't currently supported.)
+ */
+static u32 io_space_blocks		= KVM_PCI_MMIO_AREA;
 
 u32 pci_get_io_space_block(u32 size)
 {
tools/kvm/x86/include/kvm/kvm-arch.h +5 -0
index 02aa8b9..686b1b8 100644
@@ -18,6 +18,11 @@
 
 #define KVM_MMIO_START		KVM_32BIT_GAP_START
 
+/* This is the address that pci_get_io_space_block() starts allocating
+ * from.  Note that this is a PCI bus address (though same on x86).
+ */
+#define KVM_PCI_MMIO_AREA	(KVM_MMIO_START + 0x1000000)
+
 struct kvm {
 	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
 	int			vm_fd;		/* For VM ioctls() */
author
#35 lore raw

PATCH v2 23/23 kvm tools: Create arch-specific kvm_cpu__emulate_{mm}io()

In reply to a message not in the archive

Different architectures will deal with MMIO exits differently. For example, KVM_EXIT_IO is x86-specific, and I/O cycles are often synthesised by steering into windows in PCI bridges on other architectures.

This patch calls arch-specific kvm_cpu__emulate_io() and kvm_cpu__emulate_mmio() from the main runloop's IO and MMIO exit handlers. For x86, these directly call kvm__emulate_io() and kvm__emulate_mmio() but other architectures will perform some address munging before passing on the call.

---
 tools/kvm/kvm-cpu.c                      |   34 +++++++++++++++---------------
 tools/kvm/x86/include/kvm/kvm-cpu-arch.h |   17 ++++++++++++++-
 2 files changed, 33 insertions(+), 18 deletions(-)
tools/kvm/kvm-cpu.c +17 -17
index 884a89f..4df9ead 100644
@@ -52,11 +52,11 @@ static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu *cpu)
 		while (cpu->ring->first != cpu->ring->last) {
 			struct kvm_coalesced_mmio *m;
 			m = &cpu->ring->coalesced_mmio[cpu->ring->first];
-			kvm__emulate_mmio(cpu->kvm,
-					m->phys_addr,
-					m->data,
-					m->len,
-					1);
+			kvm_cpu__emulate_mmio(cpu->kvm,
+					      m->phys_addr,
+					      m->data,
+					      m->len,
+					      1);
 			cpu->ring->first = (cpu->ring->first + 1) % KVM_COALESCED_MMIO_MAX;
 		}
 	}
@@ -106,13 +106,13 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 		case KVM_EXIT_IO: {
 			bool ret;
 
-			ret = kvm__emulate_io(cpu->kvm,
-					cpu->kvm_run->io.port,
-					(u8 *)cpu->kvm_run +
-					cpu->kvm_run->io.data_offset,
-					cpu->kvm_run->io.direction,
-					cpu->kvm_run->io.size,
-					cpu->kvm_run->io.count);
+			ret = kvm_cpu__emulate_io(cpu->kvm,
+						  cpu->kvm_run->io.port,
+						  (u8 *)cpu->kvm_run +
+						  cpu->kvm_run->io.data_offset,
+						  cpu->kvm_run->io.direction,
+						  cpu->kvm_run->io.size,
+						  cpu->kvm_run->io.count);
 
 			if (!ret)
 				goto panic_kvm;
@@ -121,11 +121,11 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 		case KVM_EXIT_MMIO: {
 			bool ret;
 
-			ret = kvm__emulate_mmio(cpu->kvm,
-					cpu->kvm_run->mmio.phys_addr,
-					cpu->kvm_run->mmio.data,
-					cpu->kvm_run->mmio.len,
-					cpu->kvm_run->mmio.is_write);
+			ret = kvm_cpu__emulate_mmio(cpu->kvm,
+						    cpu->kvm_run->mmio.phys_addr,
+						    cpu->kvm_run->mmio.data,
+						    cpu->kvm_run->mmio.len,
+						    cpu->kvm_run->mmio.is_write);
 
 			if (!ret)
 				goto panic_kvm;
tools/kvm/x86/include/kvm/kvm-cpu-arch.h +16 -1
index ed1c727..f138a92 100644
@@ -4,7 +4,8 @@
 /* Architecture-specific kvm_cpu definitions. */
 
 #include <linux/kvm.h>	/* for struct kvm_regs */
-
+#include "kvm/kvm.h"	/* for kvm__emulate_{mm}io() */
+#include <stdbool.h>
 #include <pthread.h>
 
 struct kvm;
@@ -30,4 +31,18 @@ struct kvm_cpu {
 	struct kvm_coalesced_mmio_ring	*ring;
 };
 
+/*
+ * As these are such simple wrappers, let's have them in the header so they'll
+ * be cheaper to call:
+ */
+static inline bool kvm_cpu__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+	return kvm__emulate_io(kvm, port, data, direction, size, count);
+}
+
+static inline bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+	return kvm_cpu__emulate_mmio(kvm, phys_addr, data, len, is_write);
+}
+
 #endif /* KVM__KVM_CPU_ARCH_H */
#36 lore raw

Re: [PATCH V2 23/23] kvm tools: Create arch-specific kvm_cpu__emulate_{mm}io()

Quoted 6 lines · Matt Evans
tools/kvm/x86/include/kvm/kvm-cpu-arch.h +2 -0
@@ -30,4 +31,18 @@ struct kvm_cpu {
        struct kvm_coalesced_mmio_ring  *ring;
 };
 
+/*
+ * As these are such simple wrappers, let's have them in the header so they'll

tools/kvm/x86/include/kvm/kvm-cpu-arch.h struct kvm_cpu { · line 45

Quoted 10 lines
tools/kvm/x86/include/kvm/kvm-cpu-arch.h +10 -0
+ * be cheaper to call:
+ */
+static inline bool kvm_cpu__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+       return kvm__emulate_io(kvm, port, data, direction, size, count);
+}
+
+static inline bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+       return kvm_cpu__emulate_mmio(kvm, phys_addr, data, len, is_write);

This is probably wrong. kvm_cpu__emulate_mmio just calls itself over and over.

Quoted 3 lines
tools/kvm/x86/include/kvm/kvm-cpu-arch.h +2 -0
+}
+
 #endif /* KVM__KVM_CPU_ARCH_H */ 
Signature · 1 line
Sasha.
author
#37 lore raw

Re: [PATCH V2 23/23] kvm tools: Create arch-specific kvm_cpu__emulate_{mm}io()

Quoted 5 lines · Sasha Levin
Quoted 4 lines · Matt Evans
tools/kvm/x86/include/kvm/kvm-cpu-arch.h +0 -0
@@ -30,4 +31,18 @@ struct kvm_cpu {
        struct kvm_coalesced_mmio_ring  *ring;
 };
 
Quoted 15 lines

tools/kvm/x86/include/kvm/kvm-cpu-arch.h struct kvm_cpu { · line 45

Quoted 12 lines
tools/kvm/x86/include/kvm/kvm-cpu-arch.h +12 -0
+/*
+ * As these are such simple wrappers, let's have them in the header so they'll
+ * be cheaper to call:
+ */
+static inline bool kvm_cpu__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+       return kvm__emulate_io(kvm, port, data, direction, size, count);
+}
+
+static inline bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+       return kvm_cpu__emulate_mmio(kvm, phys_addr, data, len, is_write);

This is probably wrong. kvm_cpu__emulate_mmio just calls itself over and over.

Urgh, not just probably -- C&P strikes again. Consider it fixed.

Thanks!

Matt