This patch adds a "pseries" machine to qemu. This aims to emulate a
logical partition on an IBM pSeries machine, compliant to the
"PowerPC Architecture Platform Requirements" (PAPR) document.
This initial version is quite limited, it implements a basic machine
and PAPR hypercall emulation. So far only one hypercall is present -
H_PUT_TERM_CHAR - so that a (write-only) console is available.
Multiple CPUs are permitted, with SMP entry handled kexec() style.
The machine so far more resembles an old POWER4 style "full system
partition" rather than a modern LPAR, in that the guest manages the
page tables directly, rather than via hypercalls.
The machine requires qemu to be configured with --enable-fdt. The
machine can (so far) only be booted with -kernel - i.e. no partition
firmware is provided.
Signed-off-by: David Gibson<address@hidden>
---
Makefile.target | 2 +
hw/spapr.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/spapr.h | 246 ++++++++++++++++++++++++++++++++++++++++++
hw/spapr_hcall.c | 43 ++++++++
4 files changed, 605 insertions(+), 0 deletions(-)
create mode 100644 hw/spapr.c
create mode 100644 hw/spapr.h
create mode 100644 hw/spapr_hcall.c
diff --git a/Makefile.target b/Makefile.target
index f0df98e..e6a7557 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -231,6 +231,8 @@ obj-ppc-y += ppc_prep.o
obj-ppc-y += ppc_oldworld.o
# NewWorld PowerMac
obj-ppc-y += ppc_newworld.o
+# IBM pSeries (sPAPR)
+obj-ppc-y += spapr.o spapr_hcall.o
# PowerPC 4xx boards
obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-ppc-y += ppc440.o ppc440_bamboo.o
diff --git a/hw/spapr.c b/hw/spapr.c
@@ -0,0 +1,43 @@
+#include "sysemu.h"
+#include "cpu.h"
+#include "qemu-char.h"
+#include "hw/spapr.h"
+
+struct hypercall {
+ spapr_hcall_fn fn;
+} hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
+{
+ struct hypercall *hc;
+
+ assert(opcode<= MAX_HCALL_OPCODE);
+ assert((opcode& 0x3) == 0);
+
+ hc = hypercall_table + (opcode / 4);
+
+ assert(!hc->fn || (fn == hc->fn));
+
+ hc->fn = fn;
+}
+
+target_ulong spapr_hypercall(CPUState *env, sPAPREnvironment *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ if (msr_pr) {
+ fprintf(stderr, "Hypercall made with MSR=0x" TARGET_FMT_lx "\n",
+ env->msr);
+ return H_PRIVILEGE;
+ }
+
+ if ((opcode<= MAX_HCALL_OPCODE)
+&& ((opcode& 0x3) == 0)) {
+ struct hypercall *hc = hypercall_table + (opcode / 4);
+
+ if (hc->fn)
+ return hc->fn(env, spapr, opcode, args);
+ }
+
+ fprintf(stderr, "Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
+ return H_FUNCTION;
+}