aboutsummaryrefslogtreecommitdiff
path: root/hw/spapr.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2012-10-08 18:17:39 +0000
committerAlexander Graf <agraf@suse.de>2012-10-29 11:45:54 +0100
commit74d042e5cec78090194669a8a4417c0a49d46a3d (patch)
treee9d2a888f96dde333e160ea3b5a587634a12f2e6 /hw/spapr.c
parent1bfb37d1e077705de14f0f7fdc7b21749dbe4bc9 (diff)
pseries: Implement qemu initiated shutdowns using EPOW events
At present, using 'system_powerdown' from the monitor or otherwise instructing qemu to (cleanly) shut down a pseries guest will not work, because we did not have a method of signalling the shutdown request to the guest. PAPR does include a usable mechanism for this, though it is rather more involved than the equivalent on x86. This involves sending an EPOW (Environmental and POwer Warning) event through the PAPR event and error logging mechanism, which also has a number of other functions. This patch implements just enough of the event/error logging functionality to be able to send a shutdown event to the guest. At least with modern guest kernels and a userspace that is up and running, this means that system_powerdown from the qemu monitor should now work correctly on pseries guests. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/spapr.c')
-rw-r--r--hw/spapr.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/hw/spapr.c b/hw/spapr.c
index 1587bc3e03..8d0ad3cfe9 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -232,7 +232,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
hwaddr initrd_size,
hwaddr kernel_size,
const char *boot_device,
- const char *kernel_cmdline)
+ const char *kernel_cmdline,
+ uint32_t epow_irq)
{
void *fdt;
CPUPPCState *env;
@@ -403,6 +404,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_property(fdt, "ibm,associativity-reference-points",
refpoints, sizeof(refpoints))));
+ _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
+
_FDT((fdt_end_node(fdt)));
/* interrupt controller */
@@ -433,6 +436,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_end_node(fdt)));
+ /* event-sources */
+ spapr_events_fdt_skel(fdt, epow_irq);
+
_FDT((fdt_end_node(fdt))); /* close root node */
_FDT((fdt_finish(fdt)));
@@ -795,6 +801,9 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
spapr->icp = xics_system_init(XICS_IRQS);
spapr->next_irq = 16;
+ /* Set up EPOW events infrastructure */
+ spapr_events_init(spapr);
+
/* Set up IOMMU */
spapr_iommu_init();
@@ -903,7 +912,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
initrd_base, initrd_size,
kernel_size,
- boot_device, kernel_cmdline);
+ boot_device, kernel_cmdline,
+ spapr->epow_irq);
assert(spapr->fdt_skel != NULL);
}