All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support
@ 2008-01-18 21:50 Jerone Young
  2008-01-22 15:15 ` Nathan Lynch
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jerone Young @ 2008-01-18 21:50 UTC (permalink / raw)
  To: kvm-ppc

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1200692014 21600
# Node ID 1c5b26c965e85986cc93c6b905394a8b2a6b5950
# Parent  c1641ad67444cc0401fe3462b33dd88df01beae0
Add powerpc kvm qemu support

This patch adds code needed for support of powerpc in kvm qemu.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[PATCH] fill kvm_callback with arch specific dcr_read/dcr_write callbacks

This Patch adds the callback assignment and handlers for powerpc_dcr_read
and ppc_dcr_write which are called from libkvm.
This is the part of the patch that changes powerpc code and will be folded
to our combined patch for qemu-kvm-powerpc.c.

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

 qemu-kvm-powerpc.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)
* * *
* * *
[PATCH] cr not used

cr not used (not part of CPUState in qemu for ppc), but we don't need that
comment anymore.

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[PATCH] hflags works using qemu helper function

qemu has a calculation function to get valid hflags (as appliable to ppc) out
of env->msr. This patch uses this function from target-ppc/helper_regs.h to
solve that - remove todo

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[TODO] is available for ppc (at least atm)

is available for ppc (at least atm), remove todo

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[TOFOLD] interrupt injection is available in USE_KVM ifdefs

interrupt injection is available in USE_KVM ifdefs, remove todo

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
* * *
* * *
[PATCH] fix ppc440_init argument list

This argument list did not match the call from main in vl.c

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

 ppc440_boards_kvm.c |    1 -
 1 files changed, 1 deletion(-)
* * *
[PATCH] remove old shortcuts

these are no longer needed - patch will be fold into add_qemu_code later

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

 ppc440_boards_kvm.c |    7 -------
 1 files changed, 7 deletions(-)
* * *

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -299,7 +299,7 @@ OBJS+= libqemu.a
 
 # cpu emulator library
 LIBOBJS=exec.o kqemu.o qemu-kvm.o translate-op.o translate-all.o cpu-exec.o\
-        translate.o op.o host-utils.o qemu-kvm-helper.o
+        translate.o op.o host-utils.o
 ifdef CONFIG_SOFTFLOAT
 LIBOBJS+=fpu/softfloat.o
 else
@@ -310,15 +310,18 @@ ifeq ($(TARGET_ARCH), i386)
 ifeq ($(TARGET_ARCH), i386)
 LIBOBJS+=helper.o helper2.o
 LIBOBJS+=qemu-kvm-x86.o kvm-tpr-opt.o
+LIBOBJS+=qemu-kvm-helper.o
 endif
 
 ifeq ($(TARGET_ARCH), x86_64)
 LIBOBJS+=helper.o helper2.o
 LIBOBJS+=qemu-kvm-x86.o kvm-tpr-opt.o
+LIBOBJS+=qemu-kvm-helper.o
 endif
 
 ifeq ($(TARGET_BASE_ARCH), ppc)
 LIBOBJS+= op_helper.o helper.o
+LIBOBJS+= qemu-kvm-powerpc.o
 endif
 
 ifeq ($(TARGET_BASE_ARCH), mips)
@@ -477,6 +480,7 @@ ifeq ($(TARGET_BASE_ARCH), ia64)
 ifeq ($(TARGET_BASE_ARCH), ia64)
 # Hardware support
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= cirrus_vga.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o ipf.o
 VL_OBJS+= cirrus_vga.o parallel.o acpi.o piix_pci.o
 VL_OBJS+= usb-uhci.o smbus_eeprom.o
@@ -486,6 +490,7 @@ CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOI
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 # shared objects
 VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o
+VL_OBJS+= cirrus_vga.o
 # PREP target
 VL_OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
 VL_OBJS+= prep_pci.o ppc_prep.o
@@ -497,6 +502,7 @@ VL_OBJS+= unin_pci.o ppc_chrp.o
 VL_OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 VL_OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
+VL_OBJS+= $(LIBOBJS) ppc440_boards_kvm.o
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
 VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
@@ -656,6 +662,10 @@ firmware.o: firmware.c
 	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 endif
 
+ifeq ($(TARGET_ARCH), ppc)
+qemu-kvm-powerpc.o: qemu-kvm-powerpc.c qemu-kvm.h
+endif
+
 cpu-exec.o: cpu-exec.c
 	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
diff --git a/qemu/configure b/qemu/configure
--- a/qemu/configure
+++ b/qemu/configure
@@ -199,6 +199,9 @@ if [ "$cpu" = "ia64" ] ; then
      kvm="yes"
      gdbstub="no"
      slirp="no"
+fi
+if [ "$cpu" = "powerpc" ]; then
+     kvm="yes"
 fi
 ;;
 esac
@@ -1067,7 +1070,7 @@ echo "#define CONFIG_QEMU_PREFIX \"$inte
 
 configure_kvm() {
   if test $kvm = "yes" -a "$target_softmmu" = "yes" -a \
-          \( "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "ia64" \); then
+          \( "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "ia64" -o "$cpu" = "powerpc" \); then
     echo "#define USE_KVM 1" >> $config_h
     echo "CONFIG_KVM_KERNEL_INC=$kernel_path/include" >> $config_mak
   fi
@@ -1118,6 +1121,7 @@ elif test "$target_cpu" = "ppcemb" ; the
   echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
   echo "#define TARGET_PPC 1" >> $config_h
   echo "#define TARGET_PPCEMB 1" >> $config_h
+  configure_kvm
 elif test "$target_cpu" = "ppc64" ; then
   echo "TARGET_ARCH=ppc64" >> $config_mak
   echo "TARGET_ABI_DIR=ppc" >> $config_mak
diff --git a/qemu/hw/boards.h b/qemu/hw/boards.h
--- a/qemu/hw/boards.h
+++ b/qemu/hw/boards.h
@@ -32,6 +32,7 @@ extern QEMUMachine heathrow_machine;
 extern QEMUMachine heathrow_machine;
 extern QEMUMachine ref405ep_machine;
 extern QEMUMachine taihu_machine;
+extern QEMUMachine bambookvm_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
diff --git a/qemu/hw/ppc440_boards_kvm.c b/qemu/hw/ppc440_boards_kvm.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc440_boards_kvm.c
@@ -0,0 +1,251 @@
+/*
+ * Qemu PowerPC 440 board emualtion with KVM enlightnments
+ *
+ * Copyright 2007 IBM Corporation.
+ * Added by: Jerone Young <jyoung5@us.ibm.com>
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ *
+ */
+
+/* XXX THIS CODE IS STILL DRAFT! DO NOT POST TO THE LIST! */
+
+#include <sys/mman.h>
+
+#include "hw.h"
+#include "ppc.h"
+#include "ppc405.h"
+#include "pc.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "exec-all.h"
+#include "boards.h"
+
+#include "qemu-kvm.h"
+
+#define DEFAULT_RAM_SIZE 32*1024*1024
+
+#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
+
+
+/* PPC 440 refrence demo board
+ * 
+ * KVM 440 PowerPC CPU
+ *
+ * SDRAM (0x00000000)
+ */
+
+#define DCRN_CPR0_CFGADDR 0xc
+#define DCRN_CPR0_CFGDATA 0xd
+#define  CPR0_PLLC0 0x0020
+#define  CPR0_PLLD0 0x0060
+
+struct cpr0
+{
+	uint32_t cfgaddr;
+};
+
+static void dcr_write_cpr0(void *opaque, int dcrn, target_ulong val)
+{
+	struct cpr0 *cpr0 = opaque;
+
+	switch (dcrn) {
+	case DCRN_CPR0_CFGADDR:
+		cpr0->cfgaddr = val;
+		break;
+	}
+}
+
+static target_ulong dcr_read_cpr0(void *opaque, int dcrn)
+{
+	struct cpr0 *cpr0 = opaque;
+
+	switch (dcrn) {
+	case DCRN_CPR0_CFGDATA:
+		switch (cpr0->cfgaddr) {
+		case CPR0_PLLD0:
+			return 0x08020203;
+		}
+		break;
+	}
+	return 0;
+}
+
+//figure out where serial_hds is initialized!
+void ppc440_init(CPUState *env,
+		target_phys_addr_t ram_bases[2],
+		target_phys_addr_t ram_sizes[2],
+		qemu_irq **picp,
+		int do_init)
+{
+	ppc4xx_mmio_t *mmio;
+	qemu_irq *pic, *irqs;
+	struct cpr0 *cpr0;
+	ram_addr_t offset;
+	int i;
+	
+	printf("Inside %s\n", __func__);
+
+	ppc_dcr_init(env, NULL, NULL);
+
+	/* mmio */
+	printf("setup mmio\n");
+	mmio = ppc4xx_mmio_init(env, 0xEF600000);
+
+	// universal controller
+	printf("setup universal controller\n");
+	irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+	irqs[PPCUIC_OUTPUT_INT] +		((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+	irqs[PPCUIC_OUTPUT_CINT] +		((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+	pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+	*picp = pic;
+
+	/* SDRAM controller */
+	printf("trying to setup sdram controller\n");
+	ppc405_sdram_init(env, pic[14], 2, ram_bases, ram_sizes, do_init);
+	offset = 0;
+	for (i = 0; i < 2; i++)
+		offset += ram_sizes[i];
+
+	/* serial ports on page 126 of 440EP user manual */
+	if (serial_hds[0]) {
+		printf("Initializing first serial port\n");
+		ppc405_serial_init(env, mmio,0x300, pic[31], serial_hds[0]);
+	}
+	if (serial_hds[1]) {
+		printf("Initializing 2nd serial port\n");
+		ppc405_serial_init(env, mmio,0x400, pic[30], serial_hds[1]);	
+	}
+
+	cpr0 = qemu_mallocz(sizeof(struct cpr0));
+	ppc_dcr_register(env, DCRN_CPR0_CFGADDR, cpr0, NULL, dcr_write_cpr0);
+	ppc_dcr_register(env, DCRN_CPR0_CFGDATA, cpr0, dcr_read_cpr0, NULL);
+}
+
+
+static void bambooKVM_init(ram_addr_t ram_size, int vga_ram_size, 
+			const char *boot_device, DisplayState *ds,  
+			const char *kernel_filename,
+			const char *kernel_cmdline,
+			const char *initrd_filename,
+			const char *cpu_model)
+{
+	target_phys_addr_t ram_bases[2], ram_sizes[2];	
+	qemu_irq *pic;
+	CPUState *env;
+	target_ulong ep;
+	int is_linux=1; /* Will assume allways is Linux for now */
+	long kernel_size=0;
+	target_ulong initrd_base=0; 
+	target_ulong initrd_size=0;
+
+	printf("Entering %s\n", __func__);
+
+	/* Setup Memory */
+	if (ram_size)
+	{
+		printf("Ram size specified on command line is %d\n", (int)ram_size);
+	}
+	else {
+		printf("Using defualt ram size of %iMB\n",
+				(DEFAULT_RAM_SIZE/1024)/1024);
+		
+		ram_size = DEFAULT_RAM_SIZE;
+	}
+	
+	/* XXX For simplicity we will just have everything to into one
+ 	   memory stick. Until of course this needs to be changed */
+	ram_bases[0] = 0x0;
+	ram_sizes[0] = 0x08000000;
+	ram_bases[1] = 0x0;
+	ram_sizes[1] = 0x01000000;
+
+	printf("Ram size of domain is %d bytes\n", (int)ram_size);
+
+	/* Setup CPU */
+	/*XXX Change ppc_defs[] target-ppc/translate_init.c 
+ 	  is the table you want to look at for the value or arg 
+          To try "440EP" you have to define TODO_USER_ONLY
+         */
+	env = cpu_ppc_init("405");
+	if (!env) {
+		fprintf(stderr, "Unable to initilize CPU!\n");
+		exit(1);	
+	}
+
+	/* Allocate IRQ controller */
+	/* XXX not sure but this appears not be needed any more */
+	//ppc405_irq_init(env);	
+
+	/* call init */
+	printf("Calling function ppc440_init\n");
+	ppc440_init(env, ram_bases, ram_sizes, &pic,1);
+	printf("Done calling ppc440_init\n");
+
+	/* Setup KVM context */
+	if (kvm_qemu_init()) {
+		fprintf(stderr, "Could not init kvm qemu\n");
+		exit(1);
+	}
+
+	if (kvm_qemu_create_context() < 0) {
+		fprintf(stderr, "Could not create KVM context\n");
+		exit(1);
+	}
+	cpu_register_physical_memory(0, ram_size, 0);
+	kvm_cpu_register_physical_memory(0, ram_size, 0);
+
+	/* load kernel with uboot loader */
+	printf("%s: load kernel\n", __func__);
+	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
+	if (kernel_size < 0) {
+		fprintf(stderr, "qemu: could not load kernel '%s'\n",
+			kernel_filename);
+		exit(1);
+	}
+
+	/* load initrd */
+	if (initrd_filename) {
+		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
+		initrd_size = load_image(initrd_filename, 
+				phys_ram_base + initrd_base);
+		
+		if (initrd_size < 0) {
+			fprintf(stderr, 
+				"qemu: could not load initial ram disk '%s'\n",
+				initrd_filename);
+			exit(1);
+		}
+	}
+
+	/* XXX insert TLB entries */
+	env->gpr[1] = (16<<20) - 8;
+	env->gpr[4] = initrd_base;
+	env->gpr[5] = initrd_size;
+
+	/* Set program counter (ip in x86 terms .... but it's ep in ppc) */
+	env->nip = ep;
+        printf("Program Counter (ep) is being set to 0x%08x\n", ep);
+
+	/* lock RAM */
+	mlock(phys_ram_base, phys_ram_size);
+
+	/* run in kvm */
+	/* XXX SMP IS NOT SUPPORTED  YET */
+	printf("%s: running kvm functions\n", __func__);
+	env->cpu_index = 0;
+
+	/* XXX need a call to set ep */
+	printf("%s: loading kvm registers\n", __func__);
+	kvm_load_registers(env);
+
+	printf("%s: DONE\n", __func__);
+}
+
+QEMUMachine bambookvm_machine = {
+	"bambooKVM",
+	"bambooKVM",
+	bambooKVM_init,
+};
diff --git a/qemu/qemu-kvm-powerpc.c b/qemu/qemu-kvm-powerpc.c
new file mode 100644
--- /dev/null
+++ b/qemu/qemu-kvm-powerpc.c
@@ -0,0 +1,207 @@
+
+#include "config.h"
+#include "config-host.h"
+
+extern int kvm_allowed;
+extern int kvm_irqchip;
+
+#ifdef USE_KVM
+
+#include <string.h>
+#include "hw/hw.h"
+#include "sysemu.h"
+#include "cpu.h"
+#include "helper_regs.h"
+
+#include "qemu-kvm.h"
+#include <libkvm.h>
+#include <pthread.h>
+#include <sys/utsname.h>
+
+extern kvm_context_t kvm_context;
+extern __thread CPUState *vcpu_env;
+
+/* TODOs
+ * - figure out if this current code actually works!
+ * - ppc hflags work, but we need to check if generic code use hflags not
+     supportet by ppc (atm it only uses some halt related flags that become
+     interesting for smp support
+ */
+
+void cpu_reset(CPUState *env)
+{
+        /* XXX TODO */
+	/* currently we do not do anything here, but the idea
+         * is to reset any CPU registers to it's startup state.
+	 * This is used in qemu-kvm.c
+         * in function:  
+ 	 */
+}
+
+
+int kvm_arch_qemu_create_context(void)
+{
+	return 0;
+}
+
+void kvm_arch_load_regs(CPUState *env)
+{
+    struct kvm_regs regs;
+    int rc,i;
+
+    rc = kvm_get_regs(kvm_context, env->cpu_index, &regs);
+    if (rc = -1)
+        perror("kvm_get_regs FAILED");
+
+    /* cr is untouched in qemu and not existant in CPUState fr ppr */
+    regs.pc = env->nip;
+
+    regs.ctr = env->ctr;
+    regs.lr  = env->lr;
+    regs.xer = ppc_load_xer(env);
+    regs.msr = env->msr; 
+    /* hflags is a morphed to MSR on ppc, no need to sync that down to kvm */
+
+    regs.srr0 = env->spr[SPR_SRR0];
+    regs.srr1 = env->spr[SPR_SRR1];
+
+    regs.sprg0 = env->spr[SPR_SPRG0];
+    regs.sprg1 = env->spr[SPR_SPRG1];
+    regs.sprg2 = env->spr[SPR_SPRG2];
+    regs.sprg3 = env->spr[SPR_SPRG3];
+    regs.sprg4 = env->spr[SPR_SPRG4];
+    regs.sprg5 = env->spr[SPR_SPRG5];
+    regs.sprg6 = env->spr[SPR_SPRG6];
+    regs.sprg7 = env->spr[SPR_SPRG7];
+
+    for (i = 0;i < 32; i++){
+        regs.gpr[i] = env->gpr[i];
+        regs.fpr[i] = env->fpr[i];
+    }
+
+    rc = kvm_set_regs(kvm_context, env->cpu_index, &regs);
+    if (rc = -1)
+        perror("kvm_set_regs FAILED");
+}
+
+
+void kvm_arch_save_regs(CPUState *env)
+{
+    struct kvm_regs regs;
+    uint32_t i, rc;
+
+    rc = kvm_get_regs(kvm_context, env->cpu_index, &regs);
+    if (rc = -1)
+        perror("kvm_get_regs FAILED");
+
+    env->ctr =regs.ctr;
+    env->lr = regs.lr;
+    ppc_store_xer(env,regs.xer);
+    env->msr = regs.msr;
+    /* calculate hflags based on the current msr using the ppc qemu helper */
+    hreg_compute_hflags(env);
+
+    env->nip = regs.pc;
+
+    env->spr[SPR_SRR0] = regs.srr0;
+    env->spr[SPR_SRR1] = regs.srr1;
+
+    env->spr[SPR_SPRG0] = regs.sprg0;
+    env->spr[SPR_SPRG1] = regs.sprg1;
+    env->spr[SPR_SPRG2] = regs.sprg2;
+    env->spr[SPR_SPRG3] = regs.sprg3;
+    env->spr[SPR_SPRG4] = regs.sprg4;
+    env->spr[SPR_SPRG5] = regs.sprg5;
+    env->spr[SPR_SPRG6] = regs.sprg6;
+    env->spr[SPR_SPRG7] = regs.sprg7;
+
+    for (i = 0;i < 32; i++){
+        env->gpr[i] = regs.gpr[i];
+        env->fpr[i] = regs.fpr[i];
+    }
+
+}
+
+int kvm_arch_qemu_init_env(CPUState *cenv)
+{
+    return 0;
+}
+
+int kvm_arch_halt(void *opaque, int vcpu)
+{
+    CPUState *env = cpu_single_env;
+
+    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) 
+	&& (env->msr & (1<<MSR_EE)))
+    {
+            env->halted = 1;
+	    env->exception_index = EXCP_HLT;
+    }
+    return 1;
+}
+
+void kvm_arch_pre_kvm_run(void *opaque, int vcpu)
+{
+	return;
+}
+
+void kvm_arch_post_kvm_run(void *opaque, int vcpu)
+{
+    CPUState *env = vcpu_env;
+    cpu_single_env = env;
+    env->ready_for_interrupt_injection = \
+	kvm_is_ready_for_interrupt_injection(kvm_context, vcpu);
+}
+
+int kvm_arch_has_work(CPUState *env)
+{
+    if ((env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT)) &&
+	(env->msr & (1<<MSR_EE)))
+	return 1;
+    return 0;
+}
+
+/*XXX NEED WORK BAD! */
+int kvm_arch_try_push_interrupts(void *opaque)
+{
+    CPUState *env = cpu_single_env;
+    int r, irq;
+/* XXX ready_for_interrupt_injection is gone! */
+ // if (env->ready_for_interrupt_injection &&
+    if (
+        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->msr & (1<<MSR_EE))) {
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+/* XXX TODO all down here */
+/*
+	    irq = cpu_get_pic_interrupt(env);
+	    if (irq >= 0) {
+		r = kvm_inject_irq(kvm_context, env->cpu_index, irq);
+		if (r < 0)
+		    printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+	    }
+*/
+    }
+
+    return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
+}
+
+void kvm_arch_update_regs_for_sipi(CPUState *env)
+{
+    printf("%s: no kvm-powerpc multi processor support yet!\n", __func__);
+}
+
+/* map dcr access to existing qemu dcr emulation */
+int handle_powerpc_dcr_read(uint32_t dcrn, uint32_t *data)
+{
+    ppc_dcr_read(vcpu_env->dcr_env, dcrn, data);
+    return 0; /* XXX ignore failed DCR ops */
+}
+
+int handle_powerpc_dcr_write(uint32_t dcrn, uint32_t data)
+{
+    ppc_dcr_write(vcpu_env->dcr_env, dcrn, data);
+    return 0; /* XXX ignore failed DCR ops */
+}
+
+#endif
diff --git a/qemu/target-ppc/cpu.h b/qemu/target-ppc/cpu.h
--- a/qemu/target-ppc/cpu.h
+++ b/qemu/target-ppc/cpu.h
@@ -573,6 +573,11 @@ struct CPUPPCState {
     target_ulong msr;
     /* temporary general purpose registers */
     ppc_gpr_t tgpr[4]; /* Used to speed-up TLB assist handlers */
+	
+#ifdef USE_KVM
+    uint64_t tsc; /* time stamp counter */
+    uint8_t ready_for_interrupt_injection;
+#endif
 
     /* Floating point execution context */
     /* temporary float registers */
@@ -1421,4 +1426,11 @@ enum {
 
 /*****************************************************************************/
 
+/* hidden flags (hflags) - used internally by qemu to represent additional
+ * cpu states.
+ */
+#define HF_HALTED_SHIFT 1
+
+#define HF_HALTED_MASK 1<<HF_HALTED_SHIFT
+
 #endif /* !defined (__CPU_PPC_H__) */
diff --git a/qemu/vl.c b/qemu/vl.c
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -8318,6 +8318,7 @@ static void register_machines(void)
     qemu_register_machine(&prep_machine);
     qemu_register_machine(&ref405ep_machine);
     qemu_register_machine(&taihu_machine);
+    qemu_register_machine(&bambookvm_machine);
 #elif defined(TARGET_MIPS)
     qemu_register_machine(&mips_machine);
     qemu_register_machine(&mips_malta_machine);

-------------------------------------------------------------------------
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/
_______________________________________________
kvm-ppc-devel mailing list
kvm-ppc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-ppc-devel

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

* Re: [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support
  2008-01-18 21:50 [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support Jerone Young
@ 2008-01-22 15:15 ` Nathan Lynch
  2008-01-22 19:09 ` Jerone Young
  2008-01-25 23:34 ` Jerone Young
  2 siblings, 0 replies; 4+ messages in thread
From: Nathan Lynch @ 2008-01-22 15:15 UTC (permalink / raw)
  To: kvm-ppc

Jerone Young wrote:
> --- /dev/null
> +++ b/qemu/hw/ppc440_boards_kvm.c
> @@ -0,0 +1,251 @@
> +/*
> + * Qemu PowerPC 440 board emualtion with KVM enlightnments

                                                enhancements?

> + *
> + * Copyright 2007 IBM Corporation.
> + * Added by: Jerone Young <jyoung5@us.ibm.com>
> + *
> + * This work is licensed under the GNU LGPL license, version 2.
> + *
> + */
> +
> +/* XXX THIS CODE IS STILL DRAFT! DO NOT POST TO THE LIST! */

heh


> +
> +#include <sys/mman.h>
> +
> +#include "hw.h"
> +#include "ppc.h"
> +#include "ppc405.h"
> +#include "pc.h"
> +#include "qemu-timer.h"
> +#include "sysemu.h"
> +#include "exec-all.h"
> +#include "boards.h"
> +
> +#include "qemu-kvm.h"
> +
> +#define DEFAULT_RAM_SIZE 32*1024*1024

You want parentheses around that expression.


> +static void bambooKVM_init(ram_addr_t ram_size, int vga_ram_size, 
> +			const char *boot_device, DisplayState *ds,  
> +			const char *kernel_filename,
> +			const char *kernel_cmdline,
> +			const char *initrd_filename,
> +			const char *cpu_model)
> +{

....

> +
> +	/* XXX insert TLB entries */
> +	env->gpr[1] = (16<<20) - 8;
> +	env->gpr[4] = initrd_base;
> +	env->gpr[5] = initrd_size;
> +
> +	/* Set program counter (ip in x86 terms .... but it's ep in ppc) */
> +	env->nip = ep;
> +        printf("Program Counter (ep) is being set to 0x%08x\n", ep);
> +
> +	/* lock RAM */
> +	mlock(phys_ram_base, phys_ram_size);

Do you care if that fails?


> +
> +	/* run in kvm */
> +	/* XXX SMP IS NOT SUPPORTED  YET */
> +	printf("%s: running kvm functions\n", __func__);
> +	env->cpu_index = 0;
> +
> +	/* XXX need a call to set ep */
> +	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/
_______________________________________________
kvm-ppc-devel mailing list
kvm-ppc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-ppc-devel

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

* Re: [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support
  2008-01-18 21:50 [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support Jerone Young
  2008-01-22 15:15 ` Nathan Lynch
@ 2008-01-22 19:09 ` Jerone Young
  2008-01-25 23:34 ` Jerone Young
  2 siblings, 0 replies; 4+ messages in thread
From: Jerone Young @ 2008-01-22 19:09 UTC (permalink / raw)
  To: kvm-ppc


On Tue, 2008-01-22 at 09:15 -0600, Nathan Lynch wrote:
> Jerone Young wrote:
> > --- /dev/null
> > +++ b/qemu/hw/ppc440_boards_kvm.c
> > @@ -0,0 +1,251 @@
> > +/*
> > + * Qemu PowerPC 440 board emualtion with KVM enlightnments
> 
>                                                 enhancements?
> 
> > + *
> > + * Copyright 2007 IBM Corporation.
> > + * Added by: Jerone Young <jyoung5@us.ibm.com>
> > + *
> > + * This work is licensed under the GNU LGPL license, version 2.
> > + *
> > + */
> > +
> > +/* XXX THIS CODE IS STILL DRAFT! DO NOT POST TO THE LIST! */
> 
> heh

I've cleaned this up in our internal repo. I plan on sending these
patches every friday till we get them in upstream KVM. But it was a last
minute decision to send what we had to the list. Next one will be a LOT
cleaner.

> 
> 
> > +
> > +#include <sys/mman.h>
> > +
> > +#include "hw.h"
> > +#include "ppc.h"
> > +#include "ppc405.h"
> > +#include "pc.h"
> > +#include "qemu-timer.h"
> > +#include "sysemu.h"
> > +#include "exec-all.h"
> > +#include "boards.h"
> > +
> > +#include "qemu-kvm.h"
> > +
> > +#define DEFAULT_RAM_SIZE 32*1024*1024
> 
> You want parentheses around that expression.

I've removed this now. But yes you are right, not having the parentheses
can cause problems if you have DEFAULT_RAM_SIZE^2 or something like
that.

> 
> 
> > +static void bambooKVM_init(ram_addr_t ram_size, int vga_ram_size, 
> > +			const char *boot_device, DisplayState *ds,  
> > +			const char *kernel_filename,
> > +			const char *kernel_cmdline,
> > +			const char *initrd_filename,
> > +			const char *cpu_model)
> > +{
> 
> ....
> 
> > +
> > +	/* XXX insert TLB entries */
> > +	env->gpr[1] = (16<<20) - 8;
> > +	env->gpr[4] = initrd_base;
> > +	env->gpr[5] = initrd_size;
> > +
> > +	/* Set program counter (ip in x86 terms .... but it's ep in ppc) */
> > +	env->nip = ep;
> > +        printf("Program Counter (ep) is being set to 0x%08x\n", ep);
> > +
> > +	/* lock RAM */
> > +	mlock(phys_ram_base, phys_ram_size);
> 
> Do you care if that fails?

Good catch. I'll add a check for it.

> 
> 
> > +
> > +	/* run in kvm */
> > +	/* XXX SMP IS NOT SUPPORTED  YET */
> > +	printf("%s: running kvm functions\n", __func__);
> > +	env->cpu_index = 0;
> > +
> > +	/* XXX need a call to set ep */
> > +	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/
_______________________________________________
kvm-ppc-devel mailing list
kvm-ppc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-ppc-devel

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

* [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support
  2008-01-18 21:50 [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support Jerone Young
  2008-01-22 15:15 ` Nathan Lynch
  2008-01-22 19:09 ` Jerone Young
@ 2008-01-25 23:34 ` Jerone Young
  2 siblings, 0 replies; 4+ messages in thread
From: Jerone Young @ 2008-01-25 23:34 UTC (permalink / raw)
  To: kvm-ppc

# HG changeset patch
# User Jerone Young <jyoung5@us.ibm.com>
# Date 1201288298 21600
# Node ID 8c7c65b2c7e8ecabe0e452e4098a5ff439dd9645
# Parent  1bba54954f3ed64959afc0d652fac4ccef714974
Add powerpc kvm qemu support

This patch adds code needed for support of powerpc in kvm qemu.

Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[PATCH] fill kvm_callback with arch specific dcr_read/dcr_write callbacks

This Patch adds the callback assignment and handlers for powerpc_dcr_read
and ppc_dcr_write which are called from libkvm.
This is the part of the patch that changes powerpc code and will be folded
to our combined patch for qemu-kvm-powerpc.c.

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

 qemu-kvm-powerpc.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)
* * *
* * *
[PATCH] cr not used

cr not used (not part of CPUState in qemu for ppc), but we don't need that
comment anymore.

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[PATCH] hflags works using qemu helper function

qemu has a calculation function to get valid hflags (as appliable to ppc) out
of env->msr. This patch uses this function from target-ppc/helper_regs.h to
solve that - remove todo

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[TODO] is available for ppc (at least atm)

is available for ppc (at least atm), remove todo

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
[TOFOLD] interrupt injection is available in USE_KVM ifdefs

interrupt injection is available in USE_KVM ifdefs, remove todo

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* * *
* * *
* * *
[PATCH] fix ppc440_init argument list

This argument list did not match the call from main in vl.c

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

 ppc440_boards_kvm.c |    1 -
 1 files changed, 1 deletion(-)
* * *
[PATCH] remove old shortcuts

these are no longer needed - patch will be fold into add_qemu_code later

Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

 ppc440_boards_kvm.c |    7 -------
 1 files changed, 7 deletions(-)
* * *

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -299,7 +299,7 @@ OBJS+= libqemu.a
 
 # cpu emulator library
 LIBOBJS=exec.o kqemu.o qemu-kvm.o translate-op.o translate-all.o cpu-exec.o\
-        translate.o op.o host-utils.o qemu-kvm-helper.o
+        translate.o op.o host-utils.o
 ifdef CONFIG_SOFTFLOAT
 LIBOBJS+=fpu/softfloat.o
 else
@@ -310,15 +310,18 @@ ifeq ($(TARGET_ARCH), i386)
 ifeq ($(TARGET_ARCH), i386)
 LIBOBJS+=helper.o helper2.o
 LIBOBJS+=qemu-kvm-x86.o kvm-tpr-opt.o
+LIBOBJS+=qemu-kvm-helper.o
 endif
 
 ifeq ($(TARGET_ARCH), x86_64)
 LIBOBJS+=helper.o helper2.o
 LIBOBJS+=qemu-kvm-x86.o kvm-tpr-opt.o
+LIBOBJS+=qemu-kvm-helper.o
 endif
 
 ifeq ($(TARGET_BASE_ARCH), ppc)
 LIBOBJS+= op_helper.o helper.o
+LIBOBJS+= qemu-kvm-powerpc.o
 endif
 
 ifeq ($(TARGET_BASE_ARCH), mips)
@@ -477,6 +480,7 @@ ifeq ($(TARGET_BASE_ARCH), ia64)
 ifeq ($(TARGET_BASE_ARCH), ia64)
 # Hardware support
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= cirrus_vga.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o ipf.o
 VL_OBJS+= cirrus_vga.o parallel.o acpi.o piix_pci.o
 VL_OBJS+= usb-uhci.o smbus_eeprom.o
@@ -486,6 +490,7 @@ CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOI
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 # shared objects
 VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o
+VL_OBJS+= cirrus_vga.o
 # PREP target
 VL_OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
 VL_OBJS+= prep_pci.o ppc_prep.o
@@ -497,6 +502,7 @@ VL_OBJS+= unin_pci.o ppc_chrp.o
 VL_OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 VL_OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
+VL_OBJS+= $(LIBOBJS) ppc440_boards_kvm.o
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
 VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
@@ -656,6 +662,10 @@ firmware.o: firmware.c
 	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 endif
 
+ifeq ($(TARGET_ARCH), ppc)
+qemu-kvm-powerpc.o: qemu-kvm-powerpc.c qemu-kvm.h
+endif
+
 cpu-exec.o: cpu-exec.c
 	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
diff --git a/qemu/configure b/qemu/configure
--- a/qemu/configure
+++ b/qemu/configure
@@ -199,6 +199,9 @@ if [ "$cpu" = "ia64" ] ; then
      kvm="yes"
      gdbstub="no"
      slirp="no"
+fi
+if [ "$cpu" = "powerpc" ]; then
+     kvm="yes"
 fi
 ;;
 esac
@@ -1067,7 +1070,7 @@ echo "#define CONFIG_QEMU_PREFIX \"$inte
 
 configure_kvm() {
   if test $kvm = "yes" -a "$target_softmmu" = "yes" -a \
-          \( "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "ia64" \); then
+          \( "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "ia64" -o "$cpu" = "powerpc" \); then
     echo "#define USE_KVM 1" >> $config_h
     echo "CONFIG_KVM_KERNEL_INC=$kernel_path/include" >> $config_mak
   fi
@@ -1118,6 +1121,7 @@ elif test "$target_cpu" = "ppcemb" ; the
   echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
   echo "#define TARGET_PPC 1" >> $config_h
   echo "#define TARGET_PPCEMB 1" >> $config_h
+  configure_kvm
 elif test "$target_cpu" = "ppc64" ; then
   echo "TARGET_ARCH=ppc64" >> $config_mak
   echo "TARGET_ABI_DIR=ppc" >> $config_mak
diff --git a/qemu/hw/boards.h b/qemu/hw/boards.h
--- a/qemu/hw/boards.h
+++ b/qemu/hw/boards.h
@@ -32,6 +32,7 @@ extern QEMUMachine heathrow_machine;
 extern QEMUMachine heathrow_machine;
 extern QEMUMachine ref405ep_machine;
 extern QEMUMachine taihu_machine;
+extern QEMUMachine bambookvm_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
diff --git a/qemu/hw/ppc440_boards_kvm.c b/qemu/hw/ppc440_boards_kvm.c
new file mode 100644
--- /dev/null
+++ b/qemu/hw/ppc440_boards_kvm.c
@@ -0,0 +1,230 @@
+/*
+ * Qemu PowerPC 440 board emualtion with KVM enlightnments
+ *
+ * Copyright 2007 IBM Corporation.
+ * Added by: Jerone Young <jyoung5@us.ibm.com>
+ *           
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ *
+ */
+
+#include <sys/mman.h>
+
+#include "hw.h"
+#include "ppc.h"
+#include "ppc405.h"
+#include "pc.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "exec-all.h"
+#include "boards.h"
+
+#include "qemu-kvm.h"
+
+#define KERNEL_LOAD_ADDR 0x400000 /* uboot loader puts kernel at 4MB */
+
+
+/* PPC 440 refrence demo board
+ * 
+ * KVM 440 PowerPC CPU
+ *
+ * SDRAM (0x00000000)
+ */
+
+#define DCRN_CPR0_CFGADDR 0xc
+#define DCRN_CPR0_CFGDATA 0xd
+#define  CPR0_PLLC0 0x0020
+#define  CPR0_PLLD0 0x0060
+
+struct cpr0
+{
+	uint32_t cfgaddr;
+};
+
+static void dcr_write_cpr0(void *opaque, int dcrn, target_ulong val)
+{
+	struct cpr0 *cpr0 = opaque;
+
+	switch (dcrn) {
+	case DCRN_CPR0_CFGADDR:
+		cpr0->cfgaddr = val;
+		break;
+	}
+}
+
+static target_ulong dcr_read_cpr0(void *opaque, int dcrn)
+{
+	struct cpr0 *cpr0 = opaque;
+
+	switch (dcrn) {
+	case DCRN_CPR0_CFGDATA:
+		switch (cpr0->cfgaddr) {
+		case CPR0_PLLD0:
+			return 0x08020203;
+		}
+		break;
+	}
+	return 0;
+}
+
+void ppc440_init(CPUState *env,
+		target_phys_addr_t ram_bases[2],
+		target_phys_addr_t ram_sizes[2],
+		qemu_irq **picp,
+		int do_init)
+{
+	ppc4xx_mmio_t *mmio;
+	qemu_irq *pic, *irqs;
+	struct cpr0 *cpr0;
+	ram_addr_t offset;
+	int i;
+	
+	printf("Inside %s\n", __func__);
+
+	ppc_dcr_init(env, NULL, NULL);
+
+	/* mmio */
+	printf("setup mmio\n");
+	mmio = ppc4xx_mmio_init(env, 0xEF600000);
+
+	/* universal controller */
+	printf("setup universal controller\n");
+	irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+	irqs[PPCUIC_OUTPUT_INT] +		((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+	irqs[PPCUIC_OUTPUT_CINT] +		((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+	pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+	*picp = pic;
+
+	/* SDRAM controller */
+	printf("trying to setup sdram controller\n");
+	ppc405_sdram_init(env, pic[14], 2, ram_bases, ram_sizes, do_init);
+	offset = 0;
+	for (i = 0; i < 2; i++)
+		offset += ram_sizes[i];
+
+	/* serial ports on page 126 of 440EP user manual */
+	if (serial_hds[0]) {
+		printf("Initializing first serial port\n");
+		ppc405_serial_init(env, mmio,0x300, pic[31], serial_hds[0]);
+	}
+	if (serial_hds[1]) {
+		printf("Initializing 2nd serial port\n");
+		ppc405_serial_init(env, mmio,0x400, pic[30], serial_hds[1]);	
+	}
+
+	cpr0 = qemu_mallocz(sizeof(struct cpr0));
+	ppc_dcr_register(env, DCRN_CPR0_CFGADDR, cpr0, NULL, dcr_write_cpr0);
+	ppc_dcr_register(env, DCRN_CPR0_CFGDATA, cpr0, dcr_read_cpr0, NULL);
+}
+
+
+static void bambooKVM_init(ram_addr_t ram_size, int vga_ram_size, 
+			const char *boot_device, DisplayState *ds,  
+			const char *kernel_filename,
+			const char *kernel_cmdline,
+			const char *initrd_filename,
+			const char *cpu_model)
+{
+	target_phys_addr_t ram_bases[2], ram_sizes[2];	
+	qemu_irq *pic;
+	CPUState *env;
+	target_ulong ep;
+	int is_linux=1; /* Will assume allways is Linux for now */
+	long kernel_size=0;
+	target_ulong initrd_base=0; 
+	target_ulong initrd_size=0;
+
+	printf("%s: START\n", __func__);
+
+	/* Setup Memory */
+	if (ram_size) {
+		printf("Ram size specified on command line is %i bytes\n", (int)ram_size);
+		printf("WARNING: RAM is hard coded to 144MB\n");
+	}
+	else {
+		printf("Using defualt ram size of %iMB\n", ((int)ram_size/1024)/1024);
+	}
+
+	/* Each bank can only have memory in configurations of
+ 	 *   16MB, 32MB, 64MB, 128MB, or 256MB
+ 	 */	
+	ram_bases[0] = 0x0;
+	ram_sizes[0] = 0x08000000;
+	ram_bases[1] = 0x0;
+	ram_sizes[1] = 0x01000000;
+
+	printf("Ram size of domain is %d bytes\n", (int)ram_size);
+
+	/* Setup CPU */
+	/* XXX We cheat for now and use 405 */
+	env = cpu_ppc_init("405");
+	if (!env) {
+		fprintf(stderr, "Unable to initilize CPU!\n");
+		exit(1);
+	}
+
+	/* call init */
+	printf("Calling function ppc440_init\n");
+	ppc440_init(env, ram_bases, ram_sizes, &pic,1);
+	printf("Done calling ppc440_init\n");
+
+	/* Register mem */
+	kvm_cpu_register_physical_memory(0, ram_size, 0);
+
+	/* load kernel with uboot loader */
+	printf("%s: load kernel\n", __func__);
+	kernel_size = load_uboot(kernel_filename, &ep, &is_linux);
+	if (kernel_size < 0) {
+		fprintf(stderr, "qemu: could not load kernel '%s'\n",
+			kernel_filename);
+		exit(1);
+	}
+
+	/* load initrd */
+	if (initrd_filename) {
+		initrd_base = kernel_size + KERNEL_LOAD_ADDR;
+		initrd_size = load_image(initrd_filename, 
+				phys_ram_base + initrd_base);
+		
+		if (initrd_size < 0) {
+			fprintf(stderr, 
+				"qemu: could not load initial ram disk '%s'\n",
+				initrd_filename);
+			exit(1);
+		}
+	}
+
+	/* XXX insert TLB entries */
+	env->gpr[1] = (16<<20) - 8;
+	env->gpr[4] = initrd_base;
+	env->gpr[5] = initrd_size;
+
+	/* Set program counter (ip in x86 terms .... but it's ep in ppc) */
+	env->nip = ep;
+        printf("Program Counter (ep) is being set to 0x%08x\n", ep);
+
+	/* lock RAM */
+	if (mlock(phys_ram_base, phys_ram_size) < 0) {
+		printf("Unable to lock physical ram!\n");
+		exit(1);
+	}
+
+	/* run in kvm */
+	/* XXX SMP IS NOT SUPPORTED  YET */
+	printf("%s: running kvm functions\n", __func__);
+	env->cpu_index = 0;
+
+	printf("%s: loading kvm registers\n", __func__);
+	kvm_load_registers(env);
+
+	printf("%s: DONE\n", __func__);
+}
+
+QEMUMachine bambookvm_machine = {
+	"bambooKVM",
+	"bambooKVM",
+	bambooKVM_init,
+};
diff --git a/qemu/qemu-kvm-powerpc.c b/qemu/qemu-kvm-powerpc.c
new file mode 100644
--- /dev/null
+++ b/qemu/qemu-kvm-powerpc.c
@@ -0,0 +1,204 @@
+
+#include "config.h"
+#include "config-host.h"
+
+extern int kvm_allowed;
+extern int kvm_irqchip;
+
+#ifdef USE_KVM
+
+#include <string.h>
+#include "hw/hw.h"
+#include "sysemu.h"
+#include "cpu.h"
+#include "helper_regs.h"
+
+#include "qemu-kvm.h"
+#include <libkvm.h>
+#include <pthread.h>
+#include <sys/utsname.h>
+
+extern kvm_context_t kvm_context;
+extern __thread CPUState *vcpu_env;
+
+/* TODOs
+ * - ppc hflags work, but we need to check if generic code use hflags not
+     supported by ppc (atm it only uses some halt related flags that become
+     interesting for smp support
+ */
+
+void cpu_reset(CPUState *env)
+{
+	/* lets see how this works out using qemu function to reset
+         * env structure
+         */
+	cpu_ppc_reset(env);
+
+}
+
+
+int kvm_arch_qemu_create_context(void)
+{
+	return 0;
+}
+
+void kvm_arch_load_regs(CPUState *env)
+{
+    struct kvm_regs regs;
+    int rc,i;
+
+    rc = kvm_get_regs(kvm_context, env->cpu_index, &regs);
+    if (rc = -1)
+        perror("kvm_get_regs FAILED");
+
+    /* cr is untouched in qemu and not existant in CPUState fr ppr */
+    regs.pc = env->nip;
+
+    regs.ctr = env->ctr;
+    regs.lr  = env->lr;
+    regs.xer = ppc_load_xer(env);
+    regs.msr = env->msr; 
+    /* hflags is a morphed to MSR on ppc, no need to sync that down to kvm */
+
+    regs.srr0 = env->spr[SPR_SRR0];
+    regs.srr1 = env->spr[SPR_SRR1];
+
+    regs.sprg0 = env->spr[SPR_SPRG0];
+    regs.sprg1 = env->spr[SPR_SPRG1];
+    regs.sprg2 = env->spr[SPR_SPRG2];
+    regs.sprg3 = env->spr[SPR_SPRG3];
+    regs.sprg4 = env->spr[SPR_SPRG4];
+    regs.sprg5 = env->spr[SPR_SPRG5];
+    regs.sprg6 = env->spr[SPR_SPRG6];
+    regs.sprg7 = env->spr[SPR_SPRG7];
+
+    for (i = 0;i < 32; i++){
+        regs.gpr[i] = env->gpr[i];
+        regs.fpr[i] = env->fpr[i];
+    }
+
+    rc = kvm_set_regs(kvm_context, env->cpu_index, &regs);
+    if (rc = -1)
+        perror("kvm_set_regs FAILED");
+}
+
+
+void kvm_arch_save_regs(CPUState *env)
+{
+    struct kvm_regs regs;
+    uint32_t i, rc;
+
+    rc = kvm_get_regs(kvm_context, env->cpu_index, &regs);
+    if (rc = -1)
+        perror("kvm_get_regs FAILED");
+
+    env->ctr =regs.ctr;
+    env->lr = regs.lr;
+    ppc_store_xer(env,regs.xer);
+    env->msr = regs.msr;
+    /* calculate hflags based on the current msr using the ppc qemu helper */
+    hreg_compute_hflags(env);
+
+    env->nip = regs.pc;
+
+    env->spr[SPR_SRR0] = regs.srr0;
+    env->spr[SPR_SRR1] = regs.srr1;
+
+    env->spr[SPR_SPRG0] = regs.sprg0;
+    env->spr[SPR_SPRG1] = regs.sprg1;
+    env->spr[SPR_SPRG2] = regs.sprg2;
+    env->spr[SPR_SPRG3] = regs.sprg3;
+    env->spr[SPR_SPRG4] = regs.sprg4;
+    env->spr[SPR_SPRG5] = regs.sprg5;
+    env->spr[SPR_SPRG6] = regs.sprg6;
+    env->spr[SPR_SPRG7] = regs.sprg7;
+
+    for (i = 0;i < 32; i++){
+        env->gpr[i] = regs.gpr[i];
+        env->fpr[i] = regs.fpr[i];
+    }
+
+}
+
+int kvm_arch_qemu_init_env(CPUState *cenv)
+{
+    return 0;
+}
+
+int kvm_arch_halt(void *opaque, int vcpu)
+{
+    CPUState *env = cpu_single_env;
+
+    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) 
+	&& (msr_ee))
+    {
+            env->halted = 1;
+	    env->exception_index = EXCP_HLT;
+    }
+    return 1;
+}
+
+void kvm_arch_pre_kvm_run(void *opaque, int vcpu)
+{
+	return;
+}
+
+void kvm_arch_post_kvm_run(void *opaque, int vcpu)
+{
+    CPUState *env = vcpu_env;
+    cpu_single_env = env;
+    env->ready_for_interrupt_injection = \
+	kvm_is_ready_for_interrupt_injection(kvm_context, vcpu);
+}
+
+int kvm_arch_has_work(CPUState *env)
+{
+    if ((env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT)) &&
+	(msr_ee))
+	return 1;
+    return 0;
+}
+
+int kvm_arch_try_push_interrupts(void *opaque)
+{
+    CPUState *env = cpu_single_env;
+    int r;
+    unsigned irq;
+
+    if (env->ready_for_interrupt_injection &&
+        (env->interrupt_request & CPU_INTERRUPT_HARD))
+       { 
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+
+            /* For now KVM disregards the 'irq' argument. However, in the
+             * future KVM could cache it in-kernel to avoid a heavyweight exit
+             * when reading the UIC. */
+            irq = -1U;
+
+            r = kvm_inject_irq(kvm_context, env->cpu_index, irq);
+            if (r < 0)
+                printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+    }
+
+    return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
+}
+
+void kvm_arch_update_regs_for_sipi(CPUState *env)
+{
+    printf("%s: no kvm-powerpc multi processor support yet!\n", __func__);
+}
+
+/* map dcr access to existing qemu dcr emulation */
+int handle_powerpc_dcr_read(uint32_t dcrn, uint32_t *data)
+{
+    ppc_dcr_read(vcpu_env->dcr_env, dcrn, data);
+    return 0; /* XXX ignore failed DCR ops */
+}
+
+int handle_powerpc_dcr_write(uint32_t dcrn, uint32_t data)
+{
+    ppc_dcr_write(vcpu_env->dcr_env, dcrn, data);
+    return 0; /* XXX ignore failed DCR ops */
+}
+
+#endif
diff --git a/qemu/target-ppc/cpu.h b/qemu/target-ppc/cpu.h
--- a/qemu/target-ppc/cpu.h
+++ b/qemu/target-ppc/cpu.h
@@ -573,6 +573,11 @@ struct CPUPPCState {
     target_ulong msr;
     /* temporary general purpose registers */
     ppc_gpr_t tgpr[4]; /* Used to speed-up TLB assist handlers */
+	
+#ifdef USE_KVM
+    uint64_t tsc; /* time stamp counter */
+    uint8_t ready_for_interrupt_injection;
+#endif
 
     /* Floating point execution context */
     /* temporary float registers */
@@ -1421,4 +1426,11 @@ enum {
 
 /*****************************************************************************/
 
+/* hidden flags (hflags) - used internally by qemu to represent additional
+ * cpu states.
+ */
+#define HF_HALTED_SHIFT 1
+
+#define HF_HALTED_MASK 1<<HF_HALTED_SHIFT
+
 #endif /* !defined (__CPU_PPC_H__) */
diff --git a/qemu/vl.c b/qemu/vl.c
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -8318,6 +8318,7 @@ static void register_machines(void)
     qemu_register_machine(&prep_machine);
     qemu_register_machine(&ref405ep_machine);
     qemu_register_machine(&taihu_machine);
+    qemu_register_machine(&bambookvm_machine);
 #elif defined(TARGET_MIPS)
     qemu_register_machine(&mips_machine);
     qemu_register_machine(&mips_malta_machine);

-------------------------------------------------------------------------
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/
_______________________________________________
kvm-ppc-devel mailing list
kvm-ppc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-ppc-devel

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

end of thread, other threads:[~2008-01-25 23:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-18 21:50 [kvm-ppc-devel] [PATCH 4 of 4] Add powerpc kvm qemu support Jerone Young
2008-01-22 15:15 ` Nathan Lynch
2008-01-22 19:09 ` Jerone Young
2008-01-25 23:34 ` Jerone Young

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.