public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0 of 7] [v3] PowerPC kvm-userspace patches
@ 2008-03-18 20:06 Jerone Young
  2008-03-18 20:06 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Jerone Young @ 2008-03-18 20:06 UTC (permalink / raw)
  To: kvm-devel; +Cc: kvm-ppc-devel

This set address issues disscussed by Hollis & Anthony on the second go around.
As well as some minor fixes.

This set of patches enables the following:
        -Device tree Support
                - Add libfdt to kvm-userspace
                - Add bamboo device tree to qemu source
                - Detection of host Device Tree attributes
                - Device tree loading
                - Ability to specify initrd on the command line
                - Ability to add kernel arguments on the command line
        - Ability to load compressed uImages
        - Ability to specify memory on the command line

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 23+ messages in thread
* [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model
@ 2008-03-19 14:45 Jerone Young
  2008-03-19 18:02 ` [kvm-ppc-devel] " Hollis Blanchard
  0 siblings, 1 reply; 23+ messages in thread
From: Jerone Young @ 2008-03-19 14:45 UTC (permalink / raw)
  To: kvm-devel; +Cc: kvm-ppc-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205937724 18000
# Branch merge
# Node ID 257410f0c4f7c6fb23d93defb00d92d0ec066fc3
# Parent  4a064f92d8fa574cebac4d9b703d0a93c6387cea
Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model

This patch adds code to dynamically manipulate the device tree when loaded into memory. This allows us to finally have the ability to manipulate the kernel command line & initrd from the qemu command line. This will also let us setup different settings for the board.

This patch also now uses new uboot loader load_uimage() to load kernel image.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -617,7 +617,7 @@ OBJS+= unin_pci.o ppc_chrp.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
-OBJS+= ppc440.o ppc440_bamboo.o
+OBJS+= ppc440.o ppc440_bamboo.o device_tree.o
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
 OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
diff --git a/qemu/hw/device_tree.c b/qemu/hw/device_tree.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/device_tree.c
@@ -0,0 +1,181 @@
+/*
+ * Functions to help device tree manipulation using libfdt.
+ * It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "ppc440.h"
+
+#ifdef CONFIG_LIBFDT
+#include "libfdt.h"
+#endif
+
+#define DT_PROC_INTERFACE_PATH "/proc/device-tree"
+
+/* FUNCTIONS FOR READING FROM DEVICE TREE OF HOST IN /PROC */
+
+/* This function reads device-tree property files that are of
+ * a single cell size
+ */
+uint32_t read_proc_dt_prop_cell(char *path_in_device_tree)
+{
+	char *buf = NULL;
+	int i;
+	uint32_t num;
+	FILE *stream;
+
+	i = snprintf(buf, 0, "%s/%s", DT_PROC_INTERFACE_PATH,
+		path_in_device_tree);
+
+	buf = (char *)malloc(i);
+	if (buf == NULL) {
+		printf("%s: Unable to malloc string buffer buf\n",
+			__func__);
+		exit(1);
+	}
+
+	i = snprintf(buf, i+1, "%s/%s",  DT_PROC_INTERFACE_PATH,
+		path_in_device_tree);
+
+	stream = fopen(buf, "rb");
+	
+	if (stream == NULL) {
+		printf("%s: Unable to open '%s'\n", __func__, buf);
+		exit(1);
+	}
+
+	fread(&num, sizeof(num), 1, stream);
+	fclose(stream);
+
+	return num;
+} 
+
+/* FUNCTIONS FOR LOADING & MANIPULATION OF DEVICE TREE IN GUEST */
+
+#ifdef CONFIG_LIBFDT
+/* support functions */
+static int get_offset_of_node(void *fdt, char *node_path)
+{
+	int node_offset;
+	node_offset = fdt_path_offset(fdt, node_path);
+	if (node_offset < 0) {
+		printf("Unable to find node in device tree '%s'\n", 
+			node_path);
+		exit(1);
+	}
+	return node_offset;
+}
+
+/* public functions */
+void *load_device_tree(char *filename_path, unsigned long load_addr)
+{
+	int dt_file_size;
+	int dt_file_load_size;
+	int new_dt_size;
+	int ret;
+	void *dt_file = NULL;
+	void *fdt;
+	
+	dt_file_size = get_image_size(filename_path);
+	if (dt_file_size < 0) {
+		printf("Unable to get size of device tree file '%s'\n",
+			filename_path);
+		goto fail;
+	}
+	
+	/* First allocate space in qemu for device tree */
+	dt_file = qemu_malloc(dt_file_size);
+	if (dt_file == NULL) {
+		printf("Unable to allocate memory in qemu for device tree\n");
+		goto fail;
+	}
+	memset(dt_file, 0, dt_file_size);
+
+	dt_file_load_size = load_image(filename_path, dt_file);
+
+
+	/* XXX Second we place new copy of 2x size in guest memory 
+ 	 *  This give us enough room for manipulation.
+	 */
+	new_dt_size = dt_file_size * 2;
+
+	fdt = (void *)load_addr;
+
+	ret = fdt_open_into(dt_file, fdt, new_dt_size);
+	if (ret) {
+		printf("Unable to copy device tree in memory\n");
+		goto fail;
+	}
+	
+	/* Check sanity of device tree */
+	if (fdt_check_header(fdt)) {
+		printf ("Device tree file loaded into memory is invalid: %s\n",
+			filename_path);
+		goto fail;
+	}
+	/* free qemu memory with old device tree */
+	qemu_free(dt_file);	
+	return fdt;
+
+fail:
+	if (dt_file) 
+		qemu_free(dt_file);
+	return NULL;
+}
+
+void dump_device_tree_to_file(void *fdt, char *filename)
+{
+	int fd;
+	fd = open(filename, O_RDWR|O_CREAT);
+	if (fd < 0) {
+		printf("Failed to open file %s\n Cannot dum device-tree\n", 
+			filename);
+		return;
+	}
+	
+	write(fd, fdt, fdt_totalsize(fdt));
+	close(fd);
+}
+
+void dt_cell(void *fdt, char *node_path, char *property,
+		uint32_t val)
+{
+	int offset;
+	int ret;
+	offset = get_offset_of_node(fdt, node_path);
+	ret = fdt_setprop_cell(fdt, offset, property, val);
+	if (ret < 0) {
+		printf("Unable to set device tree property '%s'\n",
+			property);
+		exit(1);
+	}
+}
+
+void dt_string(void *fdt, char *node_path, char *property,
+		char *string)
+{
+	int offset;
+	int ret;
+	offset = get_offset_of_node(fdt, node_path);
+	ret = fdt_setprop_string(fdt, offset, property, string);
+	if (ret < 0) {
+		printf("Unable to set device tree property '%s'\n",
+			property);
+		exit(1);
+	}
+}
+#endif
diff --git a/qemu/hw/device_tree.h b/qemu/hw/device_tree.h
new file mode 100644
--- /dev/null
+++ b/qemu/hw/device_tree.h
@@ -0,0 +1,24 @@
+/*
+ * Header with function prototypes to help device tree manipulation using 
+ * libfdt. It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+/* device-tree proc support functions */
+uint32_t read_proc_dt_prop_cell(char *path_in_device_tree);
+
+#ifdef CONFIG_LIBFDT
+/* device tree functions */
+void *load_device_tree(char *filename_path, target_ulong load_addr);
+void dump_device_tree_to_file(void *fdt, char *filename);
+void dt_cell(void *fdt, char *node_path, char *property,
+		uint32_t val);
+void dt_string(void *fdt, char *node_path, char *property,
+		char *string);
+#endif
diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
--- a/qemu/hw/ppc440_bamboo.c
+++ b/qemu/hw/ppc440_bamboo.c
@@ -4,20 +4,16 @@
  * Copyright 2007 IBM Corporation.
  * Authors: Jerone Young <jyoung5@us.ibm.com>
  *
- * This work is licensed under the GNU GPL licence version 2 or later.
+ * This work is licensed under the GNU GPL license version 2 or later.
  *
  */
 
+#include "config.h"
 #include "ppc440.h"
+#include "qemu-kvm.h"
+#include "device_tree.h"
 
-#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
-
-#include "qemu-kvm.h"
-
-/* PPC 440 refrence demo board
- *
- * 440 PowerPC CPU
- */
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
 
 void bamboo_init(ram_addr_t ram_size, int vga_ram_size,
 			const char *boot_device, DisplayState *ds,
@@ -26,14 +22,21 @@ void bamboo_init(ram_addr_t ram_size, in
 			const char *initrd_filename,
 			const char *cpu_model)
 {
+	char *buf;
 	target_phys_addr_t ram_bases[2], ram_sizes[2];
 	qemu_irq *pic;
 	CPUState *env;
-	target_ulong ep;
+	target_ulong ep=0;
+	target_ulong la=0;
 	int is_linux=1; /* Will assume allways is Linux for now */
-	long kernel_size=0;
+	target_long kernel_size=0;
 	target_ulong initrd_base=0;
-	target_ulong initrd_size=0;
+	target_long initrd_size=0;
+	target_ulong dt_base=0;
+	void *fdt;
+	int ret;
+	uint32_t cpu_freq;
+	uint32_t timebase_freq;
 
 	printf("%s: START\n", __func__);
 
@@ -78,18 +81,23 @@ void bamboo_init(ram_addr_t ram_size, in
 
 	/* load kernel with uboot loader */
 	printf("%s: load kernel\n", __func__);
-	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
-	if (kernel_size < 0) {
+	ret = load_uimage(kernel_filename, &ep, &la, &kernel_size, &is_linux);
+	if (ret < 0) {
 		fprintf(stderr, "qemu: could not load kernel '%s'\n",
 			kernel_filename);
 		exit(1);
 	}
+	printf("kernel is at guest address: 0x%lx\n", (unsigned long)la);
 
 	/* load initrd */
 	if (initrd_filename) {
-		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
+        	initrd_base = kernel_size + la;
+		printf("%s: load initrd\n", __func__);
 		initrd_size = load_image(initrd_filename,
 				phys_ram_base + initrd_base);
+
+		printf("initrd is at guest address: 0x%lx\n", 
+					(unsigned long) initrd_base);
 
 		if (initrd_size < 0) {
 			fprintf(stderr,
@@ -99,17 +107,64 @@ void bamboo_init(ram_addr_t ram_size, in
 		}
 	}
 
+#ifdef CONFIG_LIBFDT
+	/* get variable for device tree */
+	cpu_freq = read_proc_dt_prop_cell("cpus/cpu@0/clock-frequency");
+	timebase_freq = read_proc_dt_prop_cell("cpus/cpu@0/timebase-frequency");
+
+	/* load binary device tree into qemu (not guest memory) */
+	printf("%s: load device tree file\n", __func__);
+	
+	/* get string size */
+	ret = snprintf(buf, 0, "%s/%s", bios_dir, 
+		BINARY_DEVICE_TREE_FILE);
+
+	buf = (char*) malloc(ret);
+	if (buf == NULL) {
+		printf("%s: Unable to malloc string buffer buf\n",
+			__func__);
+		exit(1);
+	}	
+
+	snprintf(buf, ret+1, "%s/%s", bios_dir, 
+		BINARY_DEVICE_TREE_FILE);
+
+	/* set base for device tree that will be in guest memory */
+	if (initrd_base)
+		dt_base = initrd_base + initrd_size;
+	else
+		dt_base = kernel_size + la;
+
+	fdt = load_device_tree(buf, (phys_ram_base + dt_base));
+	if (fdt == NULL) {
+		printf("Loading device tree failed!\n");
+		exit(1);
+	}
+
+	printf("device tree address is at guest address: 0x%lx\n",
+		(unsigned long) dt_base);
+
+	/* manipulate device tree in memory */
+	dt_cell(fdt, "/cpus/cpu@0", "clock-frequency", cpu_freq);
+	dt_cell(fdt, "/cpus/cpu@0", "timebase-frequency", timebase_freq);
+	dt_cell(fdt, "/chosen", "linux,initrd-start", initrd_base);
+	dt_cell(fdt, "/chosen", "linux,initrd-end",
+				(initrd_base + initrd_size));
+	dt_string(fdt, "/chosen", "bootargs", kernel_cmdline);
+#endif
+
 	if (kvm_enabled()) {
-	    /* XXX insert TLB entries */
-	    env->gpr[1] = (16<<20) - 8;
-	    env->gpr[4] = initrd_base;
-	    env->gpr[5] = initrd_size;
+		/* XXX insert TLB entries */
+		env->gpr[1] = (16<<20) - 8;
 
-	    env->nip = ep;
+#ifdef CONFIG_LIBFDT
+		/* location of device tree in register */
+		env->gpr[3] = dt_base;
+#endif
+		env->nip = ep;
 
-	    env->cpu_index = 0;
-	    printf("%s: loading kvm registers\n", __func__);
-	    kvm_load_registers(env);
+		printf("%s: loading kvm registers\n", __func__);
+		kvm_load_registers(env);
 	}
 
 	printf("%s: DONE\n", __func__);

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 23+ messages in thread
* [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model
@ 2008-03-12  4:50 Jerone Young
  2008-03-13  2:53 ` [kvm-ppc-devel] " Hollis Blanchard
  0 siblings, 1 reply; 23+ messages in thread
From: Jerone Young @ 2008-03-12  4:50 UTC (permalink / raw)
  To: kvm-ppc-devel; +Cc: kvm-devel

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1205296680 18000
# Branch merge
# Node ID 50fddb23a4c19ec6f359a4dd39e98712eb6bcaeb
# Parent  9c15709640cd55bf6f782d6856423363312493bb
Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model

This patch adds code to dynamically manipulate the device tree when loaded into memory. This allows us to finally have the ability to manipulate the kernel command line & initrd from the qemu command line. This will also let us setup different settings for the board.

This patch also now uses new uboot loader uboot_loader_l() to load kernel image.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -615,7 +615,7 @@ OBJS+= unin_pci.o ppc_chrp.o
 OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
-OBJS+= ppc440.o ppc440_bamboo.o
+OBJS+= ppc440.o ppc440_bamboo.o ppc_device_tree_support.o
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
 OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
diff --git a/qemu/hw/ppc440_bamboo.c b/qemu/hw/ppc440_bamboo.c
--- a/qemu/hw/ppc440_bamboo.c
+++ b/qemu/hw/ppc440_bamboo.c
@@ -8,11 +8,12 @@
  *
  */
 
+#include "config.h"
 #include "ppc440.h"
+#include "qemu-kvm.h"
+#include "ppc_device_tree_support.h"
 
-#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
-
-#include "qemu-kvm.h"
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
 
 /* PPC 440 refrence demo board
  *
@@ -26,14 +27,22 @@ void bamboo_init(ram_addr_t ram_size, in
 			const char *initrd_filename,
 			const char *cpu_model)
 {
+	char buf[1024];	
 	target_phys_addr_t ram_bases[2], ram_sizes[2];
 	qemu_irq *pic;
 	CPUState *env;
-	target_ulong ep;
+	target_ulong ep=0;
+	target_ulong la=0;
 	int is_linux=1; /* Will assume allways is Linux for now */
-	long kernel_size=0;
+	target_long kernel_size=0;
 	target_ulong initrd_base=0;
-	target_ulong initrd_size=0;
+	target_long initrd_size=0;
+	target_ulong dt_base=0;
+	void *fdt;
+	int ret;
+
+	uint32_t cpu_freq;
+	uint32_t timebase_freq;
 
 	printf("%s: START\n", __func__);
 
@@ -78,18 +87,23 @@ void bamboo_init(ram_addr_t ram_size, in
 
 	/* load kernel with uboot loader */
 	printf("%s: load kernel\n", __func__);
-	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
+	load_uboot_l(kernel_filename, &ep, &la, &kernel_size, &is_linux);
 	if (kernel_size < 0) {
 		fprintf(stderr, "qemu: could not load kernel '%s'\n",
 			kernel_filename);
 		exit(1);
 	}
+	printf("kernel is at guest address: 0x%lx\n", (unsigned long)la);
 
 	/* load initrd */
 	if (initrd_filename) {
-		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
+        	initrd_base = kernel_size + la;
+		printf("%s: load initrd\n", __func__);
 		initrd_size = load_image(initrd_filename,
 				phys_ram_base + initrd_base);
+
+		printf("initrd is at guest address: 0x%lx\n", 
+					(unsigned long) initrd_base);
 
 		if (initrd_size < 0) {
 			fprintf(stderr,
@@ -99,17 +113,58 @@ void bamboo_init(ram_addr_t ram_size, in
 		}
 	}
 
+#ifdef CONFIG_LIBFDT
+	/* get variable for device tree */
+	cpu_freq = get_proc_dt_prop_cpu_clock_freq();
+	timebase_freq = get_proc_dt_prop_cpu_timebase_freq();
+
+	/* load binary device tree into qemu (not guest memory) */
+	printf("%s: load device tree file\n", __func__);
+	
+	snprintf(buf, sizeof(buf), "%s/%s", bios_dir, 
+		BINARY_DEVICE_TREE_FILE);
+
+	/* set base for device tree that will be in guest memory */	
+	if (initrd_base)
+		dt_base = initrd_base + initrd_size;
+	else
+		dt_base = kernel_size + la;
+
+	fdt = load_device_tree(buf, (phys_ram_base + dt_base));
+	if (fdt == NULL) {
+		printf("Loading device tree failed!\n");
+		exit(1);
+	}
+
+	printf("device tree address is at guest address: 0x%lx\n", 
+		(unsigned long) dt_base);
+
+	/* manipulate device tree in memory */
+	set_dt_cpu_0_clock_freq_prop(fdt, cpu_freq);
+	set_dt_cpu_0_timebase_prop(fdt, timebase_freq);
+
+	set_dt_initrd_start_prop(fdt, initrd_base);
+	set_dt_initrd_end_prop(fdt, (initrd_base + initrd_size));
+
+	set_dt_bootargs_prop(fdt, kernel_cmdline);
+#endif
+
 	if (kvm_enabled()) {
-	    /* XXX insert TLB entries */
-	    env->gpr[1] = (16<<20) - 8;
-	    env->gpr[4] = initrd_base;
-	    env->gpr[5] = initrd_size;
 
-	    env->nip = ep;
+		/* XXX insert TLB entries */
+		env->gpr[1] = (16<<20) - 8;
 
-	    env->cpu_index = 0;
-	    printf("%s: loading kvm registers\n", __func__);
-	    kvm_load_registers(env);
+#ifdef CONFIG_LIBFDT
+		/* location of device tree in register */
+		env->gpr[3] = dt_base;
+#else
+		env->gpr[4] = initrd_base;
+		env->gpr[5] = initrd_size;
+#endif
+		env->nip = ep;
+
+		printf("%s: loading kvm registers\n", __func__);
+		kvm_load_registers(env);
 	}
 
 	printf("%s: DONE\n", __func__);
diff --git a/qemu/hw/ppc_device_tree_support.c b/qemu/hw/ppc_device_tree_support.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc_device_tree_support.c
@@ -0,0 +1,223 @@
+/*
+ * Functions to help device tree manipulation using libfdt.
+ * It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL licence version 2 or later.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "ppc440.h"
+
+#ifdef CONFIG_LIBFDT
+	#include "libfdt.h"
+#endif
+
+#define DT_PROC_INTERFACE_PATH "/proc/device-tree"
+
+/* FUNCTIONS FOR READING FROM DEVICE TREE OF HOST IN /PROC */
+
+/* This function reads device-tree property files that are of
+ * a single cell size
+ */
+static uint32_t read_proc_device_tree_prop_cell(char *path_in_device_tree)
+{
+	char buf[1024];
+	uint32_t num;
+	FILE *stream;
+
+	snprintf(buf, sizeof(buf), "%s/%s",  DT_PROC_INTERFACE_PATH,
+		path_in_device_tree);
+
+	stream = fopen(buf, "rb");
+	
+	if (stream == NULL)
+	{
+		printf("%s: Unable to open '%s'\n", __func__, buf);
+		exit(1);
+	}
+
+	fread(&num, sizeof(num), 1, stream);
+	fclose(stream);
+
+	return num;
+} 
+
+/* public functions */
+
+/* get cpu frequency in device tree */ 
+uint32_t get_proc_dt_prop_cpu_clock_freq()
+{
+	return read_proc_device_tree_prop_cell("cpus/cpu@0/clock-frequency");
+}
+
+/* get time base for cpu in device tree */
+uint32_t get_proc_dt_prop_cpu_timebase_freq()
+{
+	return read_proc_device_tree_prop_cell(
+				"cpus/cpu@0/timebase-frequency");
+}
+
+
+/* FUNCTIONS FOR LOADING & MANIPULATION OF DEVICE TREE IN GUEST */
+
+#ifdef CONFIG_LIBFDT
+/* support functions */
+static int get_offset_of_node(void *fdt, char *node_path)
+{
+	int node_offset;
+	node_offset = fdt_path_offset(fdt, node_path);
+	if (node_offset < 0) {
+		printf("Unable to find node in device tree '%s'\n", 
+			node_path);
+		exit(1);
+	}
+	return node_offset;
+}
+
+static void set_dt_prop_cell(void *fdt, int node_offset, char *prop_name,
+				uint32_t value)
+{
+	int ret;
+	ret = fdt_setprop_cell(fdt, node_offset, prop_name, value); 
+	if (ret < 0) {
+		printf("Unable to set device tree property '%s'\n",
+			prop_name);
+		exit(1);
+	}
+}
+
+static void set_dt_prop_string(void *fdt, int node_offset, char *prop_name,
+				char *string)
+{
+	int ret;
+	ret = fdt_setprop_string(fdt, node_offset, prop_name, string);
+	if (ret < 0) {
+		printf("Unable to set device tree property '%s'\n",
+			prop_name);
+		exit(1);
+	}
+}
+
+/* public functions */
+void *load_device_tree(char *filename_path, unsigned long load_addr)
+{
+	int dt_file_size;
+	int dt_file_load_size;
+	int new_dt_size;
+	int ret;
+	void *dt_file;
+	void *fdt;
+	
+	dt_file_size = get_image_size(filename_path);
+	if (dt_file_size < 0) {
+		printf("Unable to get size of device tree file");
+		goto fail;
+	}
+	
+	/* first allocate space in qemu for device tree */
+	dt_file = qemu_malloc(dt_file_size);
+	if (dt_file == NULL) {
+		printf("Unable to allocate memory in qemu for device tree\n");
+		goto fail;
+	}
+	memset(dt_file, 0, dt_file_size);
+
+	dt_file_load_size = load_image(filename_path, dt_file);
+
+
+	/* XXX Second we place new copy of 2x size in guest memory 
+ 	 *  This give us enough room for manipulation.
+	 */
+	new_dt_size = dt_file_size * 2;
+
+	fdt = (void *)load_addr;
+
+	ret = fdt_open_into(dt_file, fdt, new_dt_size);
+	if (ret) {
+		printf("Unable to copy device tree in memory\n");
+		goto fail;
+	}
+	
+	/* Check sanity of device tree */
+	if (fdt_check_header(fdt)) {
+		printf ("Device tree file loaded into memory is invalid: %s\n",
+			filename_path);
+		goto fail;
+	}
+	/* free qemu memory with old device tree */
+	qemu_free(dt_file);	
+	return fdt;
+
+fail:
+	if (dt_file) 
+		qemu_free(dt_file);
+	return NULL;
+}
+
+void dump_device_tree_to_file(void *fdt, char *filename)
+{
+	int fd;
+	fd = open(filename, O_RDWR|O_CREAT);
+	if (fd < 0) {
+		printf("Failed to open file %s\n Cannot dum device-tree\n", 
+			filename);
+		return;
+	}
+	
+	write(fd, fdt, fdt_totalsize(fdt));
+	close(fd);
+}
+
+void set_dt_cpu_0_clock_freq_prop(void *fdt, uint32_t freq)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/cpus/cpu@0");
+	set_dt_prop_cell(fdt, offset, "clock-frequency",
+			freq);
+}
+
+void set_dt_cpu_0_timebase_prop(void *fdt, uint32_t timebase)
+{	
+	int offset;
+	offset = get_offset_of_node(fdt, "/cpus/cpu@0");
+	set_dt_prop_cell(fdt, offset, "timebase-frequency",
+			timebase);
+
+}
+
+void set_dt_initrd_start_prop(void *fdt, uint32_t start_addr)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/chosen");
+	set_dt_prop_cell(fdt, offset, "linux,initrd-start",
+			start_addr);
+}
+
+void set_dt_initrd_end_prop(void *fdt, uint32_t end_addr)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/chosen");
+	set_dt_prop_cell(fdt, offset, "linux,initrd-end",
+			end_addr);
+}
+
+void set_dt_bootargs_prop(void *fdt, char *cmdline)
+{
+	int offset;
+	offset = get_offset_of_node(fdt, "/chosen");
+	set_dt_prop_string(fdt,offset, "bootargs", cmdline);
+}
+
+#endif
diff --git a/qemu/hw/ppc_device_tree_support.h b/qemu/hw/ppc_device_tree_support.h
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc_device_tree_support.h
@@ -0,0 +1,26 @@
+/*
+ * Header with function prototypes to help device tree manipulation using 
+ * libfdt. It also provides functions to read entries from device tree proc
+ * interface.
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL licence version 2 or later.
+ *
+ */
+
+/* device-tree proc support functions */
+uint32_t get_proc_dt_prop_cpu_clock_freq(void);
+uint32_t get_proc_dt_prop_cpu_timebase_freq(void);
+
+#ifdef CONFIG_LIBFDT
+/* device tree functions */ 
+void *load_device_tree(char *filename_path, target_ulong load_addr);
+void dump_device_tree_to_file(void *fdt, char *filename);
+void set_dt_cpu_0_clock_freq_prop(void *fdt, uint32_t freq);
+void set_dt_cpu_0_timebase_prop(void *fdt, uint32_t timebase);
+void set_dt_initrd_start_prop(void *fdt, uint32_t start_addr);
+void set_dt_initrd_end_prop(void *fdt, uint32_t end_addr);
+void set_dt_bootargs_prop(void *fdt, char *cmdline);
+#endif

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2008-03-19 18:02 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-18 20:06 [PATCH 0 of 7] [v3] PowerPC kvm-userspace patches Jerone Young
2008-03-18 20:06 ` [PATCH 1 of 7] Add libfdt to KVM userspace Jerone Young
2008-03-18 20:06 ` [PATCH 2 of 7] Add libfdt support to qemu Jerone Young
2008-03-18 21:16   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-18 21:22     ` Jerone Young
2008-03-18 21:28       ` Hollis Blanchard
2008-03-18 21:57         ` Jerone Young
2008-03-18 20:06 ` [PATCH 3 of 7] Create new load_uimage() & gunzip support to uboot loader in Qemu Jerone Young
2008-03-18 21:14   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-18 21:46     ` Jerone Young
2008-03-18 22:14       ` Hollis Blanchard
2008-03-18 20:06 ` [PATCH 4 of 7] Add PPC 440EP bamboo board device tree source & binary into qemu Jerone Young
2008-03-18 20:06 ` [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC bamboo board model Jerone Young
2008-03-18 21:25   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-18 21:35     ` Jerone Young
2008-03-18 22:08       ` Hollis Blanchard
2008-03-18 20:06 ` [PATCH 6 of 7] Modify PPC bamboo & ppc440 board models Jerone Young
2008-03-18 20:06 ` [PATCH 7 of 7] Add ability to specify ram on command line for bamboo board model Jerone Young
2008-03-18 21:03   ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-18 21:17     ` Jerone Young
  -- strict thread matches above, loose matches on Subject: below --
2008-03-19 14:45 [PATCH 5 of 7] Add dynamic device tree manipulation & change uboot loader for PPC " Jerone Young
2008-03-19 18:02 ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-12  4:50 Jerone Young
2008-03-13  2:53 ` [kvm-ppc-devel] " Hollis Blanchard
2008-03-13 22:27   ` Jerone Young

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox