From: Matt Evans <matt@ozlabs.org>
To: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org
Subject: [PATCH 2/8] kvm tools: Generate SPAPR PPC64 guest device tree
Date: Tue, 06 Dec 2011 04:06:03 +0000 [thread overview]
Message-ID: <4EDD94AB.30303@ozlabs.org> (raw)
In-Reply-To: <cover.1323143103.git.matt@ozlabs.org>
The generated DT is the bare minimum structure required for SPAPR (on which
subsequent patches for VIO, XICS, PCI etc. will build); root node, cpus, memory.
Some aspects are currently hardwired for simplicity, for example advertised
page sizes, HPT size, SLB size, VMX/DFP, etc. Future support of a variety
of POWER CPUs should acquire this info from the host and encode appropriately.
This requires a 64-bit libfdt.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
tools/kvm/Makefile | 3 +-
tools/kvm/powerpc/kvm.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+), 1 deletions(-)
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 58815a2..dc18959 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -129,7 +129,8 @@ ifeq ($(uname_M), ppc64)
OBJS += powerpc/kvm.o
OBJS += powerpc/kvm-cpu.o
ARCH_INCLUDE := powerpc/include
- CFLAGS += -m64
+ CFLAGS += -m64
+ LIBS += -lfdt
endif
###
diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
index 036bfc0..d792bee 100644
--- a/tools/kvm/powerpc/kvm.c
+++ b/tools/kvm/powerpc/kvm.c
@@ -3,6 +3,9 @@
*
* Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
*
+ * Portions of FDT setup borrowed from QEMU, copyright 2010 David Gibson, IBM
+ * Corporation.
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
@@ -28,8 +31,11 @@
#include <asm/unistd.h>
#include <errno.h>
+#include <linux/byteorder.h>
#include <libfdt.h>
+#define HPT_ORDER 24
+
#define HUGETLBFS_PATH "/var/lib/hugetlbfs/global/pagesize-16MB/"
static char kern_cmdline[2048];
@@ -212,9 +218,144 @@ bool load_bzimage(struct kvm *kvm, int fd_kernel,
return false;
}
+#define SMT_THREADS 4
+
+#define _FDT(exp) \
+ do { \
+ int ret = (exp); \
+ if (ret < 0) { \
+ die("Error creating device tree: %s: %s\n", \
+ #exp, fdt_strerror(ret)); \
+ } \
+ } while (0)
+
+static uint32_t mfpvr(void)
+{
+ uint32_t r;
+ asm volatile ("mfpvr %0" : "=r"(r));
+ return r;
+}
+
static void setup_fdt(struct kvm *kvm)
{
+ uint64_t mem_reg_property[] = { 0, cpu_to_be64(kvm->ram_size) };
+ int smp_cpus = kvm->nrcpus;
+ uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
+ char hypertas_prop_kvm[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
+ "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
+ int i, j;
+ char cpu_name[30];
+ u8 staging_fdt[FDT_MAX_SIZE];
+ uint32_t pvr = mfpvr();
+
+ /* Generate an appropriate DT at kvm->fdt_gra */
+ void *fdt_dest = guest_flat_to_host(kvm, kvm->fdt_gra);
+ void *fdt = staging_fdt;
+
+ _FDT(fdt_create(fdt, FDT_MAX_SIZE));
+ _FDT(fdt_finish_reservemap(fdt));
+
+ _FDT(fdt_begin_node(fdt, ""));
+
+ _FDT(fdt_property_string(fdt, "device_type", "chrp"));
+ _FDT(fdt_property_string(fdt, "model", "IBM pSeries (emulated by kvmtool)"));
+ _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
+ _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
+
+ /* /chosen */
+ _FDT(fdt_begin_node(fdt, "chosen"));
+ /* cmdline */
+ _FDT(fdt_property_string(fdt, "bootargs", kern_cmdline));
+ /* Initrd */
+ if (kvm->initrd_size != 0) {
+ uint32_t ird_st_prop = cpu_to_be32(kvm->initrd_gra);
+ uint32_t ird_end_prop = cpu_to_be32(kvm->initrd_gra +
+ kvm->initrd_size);
+ _FDT(fdt_property(fdt, "linux,initrd-start",
+ &ird_st_prop, sizeof(ird_st_prop)));
+ _FDT(fdt_property(fdt, "linux,initrd-end",
+ &ird_end_prop, sizeof(ird_end_prop)));
+ }
+
+ /* Memory: We don't alloc. a separate RMA yet. If we ever need to
+ * (CAP_PPC_RMA = 2) then have one memory node for 0->RMAsize, and
+ * another RMAsize->endOfMem.
+ */
+ _FDT(fdt_begin_node(fdt, "memory@0"));
+ _FDT(fdt_property_string(fdt, "device_type", "memory"));
+ _FDT(fdt_property(fdt, "reg", mem_reg_property, sizeof(mem_reg_property)));
+ _FDT(fdt_end_node(fdt));
+
+ /* CPUs */
+ _FDT(fdt_begin_node(fdt, "cpus"));
+ _FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
+ _FDT(fdt_property_cell(fdt, "#size-cells", 0x0));
+
+ for (i = 0; i < smp_cpus; i += SMT_THREADS) {
+ /* These page and segment sizes are a basic minimum set. Really,
+ * we should be fancier and work out what the host supports then
+ * encode this here.
+ */
+ int32_t page_sizes_prop[] = {0xc, 0x0, 0x1, 0xc, 0x0,
+ 0x18, 0x100, 0x1, 0x18, 0x0};
+ int32_t seg_sizes_prop[] = {0x1c, 0x28, 0xffffffff, 0xffffffff};
+ int32_t pft_size_prop[] = { 0, HPT_ORDER };
+ uint32_t servers_prop[SMT_THREADS];
+ uint32_t gservers_prop[SMT_THREADS * 2];
+ int threads = (smp_cpus - i) >= SMT_THREADS ? SMT_THREADS :
+ smp_cpus - i;
+
+ sprintf(cpu_name, "PowerPC,POWER7@%d", i);
+ _FDT(fdt_begin_node(fdt, cpu_name));
+ _FDT(fdt_property_string(fdt, "name", "PowerPC,POWER7"));
+ _FDT(fdt_property_string(fdt, "device_type", "cpu"));
+
+ _FDT(fdt_property_cell(fdt, "reg", i));
+ _FDT(fdt_property_cell(fdt, "cpu-version", pvr));
+ _FDT(fdt_property_cell(fdt, "dcache-block-size", 0x00000080));
+ _FDT(fdt_property_cell(fdt, "icache-block-size", 0x00000080));
+ _FDT(fdt_property_cell(fdt, "timebase-frequency", 512000000));
+ _FDT(fdt_property_cell(fdt, "clock-frequency", 0xddbab200));
+
+ /* SLB size is hardwired as we currently assume POWERn */
+ _FDT(fdt_property_cell(fdt, "ibm,slb-size", 32));
+ /* HPT size is also hardwired; KVM currently fixes it at 16MB
+ * but the moment that changes we'll need to read it out of the
+ * kernel.
+ */
+ _FDT(fdt_property(fdt, "ibm,pft-size", pft_size_prop, sizeof(pft_size_prop)));
+
+ _FDT(fdt_property_string(fdt, "status", "okay"));
+ _FDT(fdt_property(fdt, "64-bit", NULL, 0));
+ /* A server for each thread in this core */
+ for (j = 0; j < SMT_THREADS; j++) {
+ servers_prop[j] = cpu_to_be32(i+j);
+ /* Hack borrowed from QEMU, direct the group queues back to cpu 0 */
+ gservers_prop[j*2] = cpu_to_be32(i+j);
+ gservers_prop[j*2 + 1] = 0;
+ }
+ _FDT(fdt_property(fdt, "ibm,ppc-interrupt-server#s",
+ servers_prop, threads * sizeof(uint32_t)));
+ _FDT(fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+ gservers_prop, threads * 2 * sizeof(uint32_t)));
+ _FDT(fdt_property(fdt, "ibm,segment-page-sizes",
+ page_sizes_prop, sizeof(page_sizes_prop)));
+ _FDT(fdt_property(fdt, "ibm,processor-segment-sizes",
+ seg_sizes_prop, sizeof(seg_sizes_prop)));
+ /* And VMX / DFP */
+ _FDT(fdt_property_cell(fdt, "ibm,vmx", 0x2));
+ _FDT(fdt_property_cell(fdt, "ibm,dfp", 0x1));
+ _FDT(fdt_end_node(fdt));
+ }
+ _FDT(fdt_end_node(fdt));
+
+ /* Finalise: */
+ _FDT(fdt_end_node(fdt)); /* Root node */
+ _FDT(fdt_finish(fdt));
+ _FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
+ _FDT(fdt_add_mem_rsv(fdt_dest, kvm->rtas_gra, kvm->rtas_size));
+ _FDT(fdt_pack(fdt_dest));
}
/**
WARNING: multiple messages have this Message-ID (diff)
From: Matt Evans <matt@ozlabs.org>
To: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org
Subject: [PATCH 2/8] kvm tools: Generate SPAPR PPC64 guest device tree
Date: Tue, 06 Dec 2011 15:06:03 +1100 [thread overview]
Message-ID: <4EDD94AB.30303@ozlabs.org> (raw)
In-Reply-To: <cover.1323143103.git.matt@ozlabs.org>
The generated DT is the bare minimum structure required for SPAPR (on which
subsequent patches for VIO, XICS, PCI etc. will build); root node, cpus, memory.
Some aspects are currently hardwired for simplicity, for example advertised
page sizes, HPT size, SLB size, VMX/DFP, etc. Future support of a variety
of POWER CPUs should acquire this info from the host and encode appropriately.
This requires a 64-bit libfdt.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
tools/kvm/Makefile | 3 +-
tools/kvm/powerpc/kvm.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+), 1 deletions(-)
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 58815a2..dc18959 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -129,7 +129,8 @@ ifeq ($(uname_M), ppc64)
OBJS += powerpc/kvm.o
OBJS += powerpc/kvm-cpu.o
ARCH_INCLUDE := powerpc/include
- CFLAGS += -m64
+ CFLAGS += -m64
+ LIBS += -lfdt
endif
###
diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
index 036bfc0..d792bee 100644
--- a/tools/kvm/powerpc/kvm.c
+++ b/tools/kvm/powerpc/kvm.c
@@ -3,6 +3,9 @@
*
* Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
*
+ * Portions of FDT setup borrowed from QEMU, copyright 2010 David Gibson, IBM
+ * Corporation.
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
@@ -28,8 +31,11 @@
#include <asm/unistd.h>
#include <errno.h>
+#include <linux/byteorder.h>
#include <libfdt.h>
+#define HPT_ORDER 24
+
#define HUGETLBFS_PATH "/var/lib/hugetlbfs/global/pagesize-16MB/"
static char kern_cmdline[2048];
@@ -212,9 +218,144 @@ bool load_bzimage(struct kvm *kvm, int fd_kernel,
return false;
}
+#define SMT_THREADS 4
+
+#define _FDT(exp) \
+ do { \
+ int ret = (exp); \
+ if (ret < 0) { \
+ die("Error creating device tree: %s: %s\n", \
+ #exp, fdt_strerror(ret)); \
+ } \
+ } while (0)
+
+static uint32_t mfpvr(void)
+{
+ uint32_t r;
+ asm volatile ("mfpvr %0" : "=r"(r));
+ return r;
+}
+
static void setup_fdt(struct kvm *kvm)
{
+ uint64_t mem_reg_property[] = { 0, cpu_to_be64(kvm->ram_size) };
+ int smp_cpus = kvm->nrcpus;
+ uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
+ char hypertas_prop_kvm[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
+ "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
+ int i, j;
+ char cpu_name[30];
+ u8 staging_fdt[FDT_MAX_SIZE];
+ uint32_t pvr = mfpvr();
+
+ /* Generate an appropriate DT at kvm->fdt_gra */
+ void *fdt_dest = guest_flat_to_host(kvm, kvm->fdt_gra);
+ void *fdt = staging_fdt;
+
+ _FDT(fdt_create(fdt, FDT_MAX_SIZE));
+ _FDT(fdt_finish_reservemap(fdt));
+
+ _FDT(fdt_begin_node(fdt, ""));
+
+ _FDT(fdt_property_string(fdt, "device_type", "chrp"));
+ _FDT(fdt_property_string(fdt, "model", "IBM pSeries (emulated by kvmtool)"));
+ _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
+ _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
+
+ /* /chosen */
+ _FDT(fdt_begin_node(fdt, "chosen"));
+ /* cmdline */
+ _FDT(fdt_property_string(fdt, "bootargs", kern_cmdline));
+ /* Initrd */
+ if (kvm->initrd_size != 0) {
+ uint32_t ird_st_prop = cpu_to_be32(kvm->initrd_gra);
+ uint32_t ird_end_prop = cpu_to_be32(kvm->initrd_gra +
+ kvm->initrd_size);
+ _FDT(fdt_property(fdt, "linux,initrd-start",
+ &ird_st_prop, sizeof(ird_st_prop)));
+ _FDT(fdt_property(fdt, "linux,initrd-end",
+ &ird_end_prop, sizeof(ird_end_prop)));
+ }
+
+ /* Memory: We don't alloc. a separate RMA yet. If we ever need to
+ * (CAP_PPC_RMA == 2) then have one memory node for 0->RMAsize, and
+ * another RMAsize->endOfMem.
+ */
+ _FDT(fdt_begin_node(fdt, "memory@0"));
+ _FDT(fdt_property_string(fdt, "device_type", "memory"));
+ _FDT(fdt_property(fdt, "reg", mem_reg_property, sizeof(mem_reg_property)));
+ _FDT(fdt_end_node(fdt));
+
+ /* CPUs */
+ _FDT(fdt_begin_node(fdt, "cpus"));
+ _FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
+ _FDT(fdt_property_cell(fdt, "#size-cells", 0x0));
+
+ for (i = 0; i < smp_cpus; i += SMT_THREADS) {
+ /* These page and segment sizes are a basic minimum set. Really,
+ * we should be fancier and work out what the host supports then
+ * encode this here.
+ */
+ int32_t page_sizes_prop[] = {0xc, 0x0, 0x1, 0xc, 0x0,
+ 0x18, 0x100, 0x1, 0x18, 0x0};
+ int32_t seg_sizes_prop[] = {0x1c, 0x28, 0xffffffff, 0xffffffff};
+ int32_t pft_size_prop[] = { 0, HPT_ORDER };
+ uint32_t servers_prop[SMT_THREADS];
+ uint32_t gservers_prop[SMT_THREADS * 2];
+ int threads = (smp_cpus - i) >= SMT_THREADS ? SMT_THREADS :
+ smp_cpus - i;
+
+ sprintf(cpu_name, "PowerPC,POWER7@%d", i);
+ _FDT(fdt_begin_node(fdt, cpu_name));
+ _FDT(fdt_property_string(fdt, "name", "PowerPC,POWER7"));
+ _FDT(fdt_property_string(fdt, "device_type", "cpu"));
+
+ _FDT(fdt_property_cell(fdt, "reg", i));
+ _FDT(fdt_property_cell(fdt, "cpu-version", pvr));
+ _FDT(fdt_property_cell(fdt, "dcache-block-size", 0x00000080));
+ _FDT(fdt_property_cell(fdt, "icache-block-size", 0x00000080));
+ _FDT(fdt_property_cell(fdt, "timebase-frequency", 512000000));
+ _FDT(fdt_property_cell(fdt, "clock-frequency", 0xddbab200));
+
+ /* SLB size is hardwired as we currently assume POWERn */
+ _FDT(fdt_property_cell(fdt, "ibm,slb-size", 32));
+ /* HPT size is also hardwired; KVM currently fixes it at 16MB
+ * but the moment that changes we'll need to read it out of the
+ * kernel.
+ */
+ _FDT(fdt_property(fdt, "ibm,pft-size", pft_size_prop, sizeof(pft_size_prop)));
+
+ _FDT(fdt_property_string(fdt, "status", "okay"));
+ _FDT(fdt_property(fdt, "64-bit", NULL, 0));
+ /* A server for each thread in this core */
+ for (j = 0; j < SMT_THREADS; j++) {
+ servers_prop[j] = cpu_to_be32(i+j);
+ /* Hack borrowed from QEMU, direct the group queues back to cpu 0 */
+ gservers_prop[j*2] = cpu_to_be32(i+j);
+ gservers_prop[j*2 + 1] = 0;
+ }
+ _FDT(fdt_property(fdt, "ibm,ppc-interrupt-server#s",
+ servers_prop, threads * sizeof(uint32_t)));
+ _FDT(fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+ gservers_prop, threads * 2 * sizeof(uint32_t)));
+ _FDT(fdt_property(fdt, "ibm,segment-page-sizes",
+ page_sizes_prop, sizeof(page_sizes_prop)));
+ _FDT(fdt_property(fdt, "ibm,processor-segment-sizes",
+ seg_sizes_prop, sizeof(seg_sizes_prop)));
+ /* And VMX / DFP */
+ _FDT(fdt_property_cell(fdt, "ibm,vmx", 0x2));
+ _FDT(fdt_property_cell(fdt, "ibm,dfp", 0x1));
+ _FDT(fdt_end_node(fdt));
+ }
+ _FDT(fdt_end_node(fdt));
+
+ /* Finalise: */
+ _FDT(fdt_end_node(fdt)); /* Root node */
+ _FDT(fdt_finish(fdt));
+ _FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
+ _FDT(fdt_add_mem_rsv(fdt_dest, kvm->rtas_gra, kvm->rtas_size));
+ _FDT(fdt_pack(fdt_dest));
}
/**
next prev parent reply other threads:[~2011-12-06 4:06 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1323143103.git.matt@ozlabs.org>
2011-12-06 4:05 ` [PATCH 1/8] kvm tools: Add initial SPAPR PPC64 architecture support Matt Evans
2011-12-06 4:05 ` Matt Evans
2011-12-06 18:03 ` Scott Wood
2011-12-06 18:03 ` Scott Wood
2011-12-06 18:33 ` Pekka Enberg
2011-12-06 18:33 ` Pekka Enberg
2011-12-06 18:54 ` Scott Wood
2011-12-06 18:54 ` Scott Wood
2011-12-07 7:35 ` Matt Evans
2011-12-07 7:35 ` Matt Evans
2011-12-07 18:31 ` Scott Wood
2011-12-07 18:31 ` Scott Wood
2011-12-08 2:57 ` Matt Evans
2011-12-08 2:57 ` Matt Evans
2011-12-06 4:06 ` Matt Evans [this message]
2011-12-06 4:06 ` [PATCH 2/8] kvm tools: Generate SPAPR PPC64 guest device tree Matt Evans
2011-12-06 4:06 ` [PATCH 3/8] kvm tools: Add SPAPR PPC64 hcall & rtascall structure Matt Evans
2011-12-06 4:06 ` Matt Evans
2011-12-06 4:06 ` [PATCH 4/8] kvm tools: Add SPAPR PPC64 HV console Matt Evans
2011-12-06 4:06 ` Matt Evans
2011-12-06 4:06 ` [PATCH 5/8] kvm tools: Add PPC64 XICS interrupt controller support Matt Evans
2011-12-06 4:06 ` Matt Evans
2011-12-06 4:06 ` [PATCH 6/8] kvm tools: Add PPC64 PCI Host Bridge Matt Evans
2011-12-06 4:06 ` Matt Evans
2011-12-06 4:06 ` [PATCH 7/8] kvm tools: Add PPC64 kvm_cpu__emulate_io() Matt Evans
2011-12-06 4:06 ` Matt Evans
2011-12-06 4:06 ` [PATCH 8/8] kvm tools: Make virtio-pci's ioeventfd__add_event() fall Matt Evans
2011-12-06 4:06 ` [PATCH 8/8] kvm tools: Make virtio-pci's ioeventfd__add_event() fall back gracefully if ioeventfds unavailable Matt Evans
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4EDD94AB.30303@ozlabs.org \
--to=matt@ozlabs.org \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.