aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ppc/spapr.c40
-rw-r--r--hw/ppc/spapr_hcall.c22
-rw-r--r--include/hw/ppc/spapr.h4
3 files changed, 55 insertions, 11 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 9300824c2a..aa6a07073d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -655,13 +655,28 @@ out:
return ret;
}
+static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt,
+ sPAPROptionVector *ov5_updates)
+{
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ int ret = 0;
+
+ /* Generate ibm,dynamic-reconfiguration-memory node if required */
+ if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) {
+ g_assert(smc->dr_lmb_enabled);
+ ret = spapr_populate_drconf_memory(spapr, fdt);
+ }
+
+ return ret;
+}
+
int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
target_ulong addr, target_ulong size,
- bool cpu_update)
+ bool cpu_update,
+ sPAPROptionVector *ov5_updates)
{
void *fdt, *fdt_skel;
sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine());
size -= sizeof(hdr);
@@ -680,10 +695,8 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
_FDT((spapr_fixup_cpu_dt(fdt, spapr)));
}
- /* Generate ibm,dynamic-reconfiguration-memory node if required */
- if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) {
- g_assert(smc->dr_lmb_enabled);
- _FDT((spapr_populate_drconf_memory(spapr, fdt)));
+ if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) {
+ return -1;
}
/* Pack resulting tree */
@@ -972,6 +985,13 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
_FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
}
+ /* ibm,client-architecture-support updates */
+ ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas);
+ if (ret < 0) {
+ error_report("couldn't setup CAS properties fdt");
+ exit(1);
+ }
+
return fdt;
}
@@ -1137,6 +1157,13 @@ static void ppc_spapr_reset(void)
rtas_addr = rtas_limit - RTAS_MAX_SIZE;
fdt_addr = rtas_addr - FDT_MAX_SIZE;
+ /* if this reset wasn't generated by CAS, we should reset our
+ * negotiated options and start from scratch */
+ if (!spapr->cas_reboot) {
+ spapr_ovec_cleanup(spapr->ov5_cas);
+ spapr->ov5_cas = spapr_ovec_new();
+ }
+
fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
spapr_load_rtas(spapr, fdt, rtas_addr);
@@ -1164,6 +1191,7 @@ static void ppc_spapr_reset(void)
first_cpu->halted = 0;
first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT;
+ spapr->cas_reboot = false;
}
static void spapr_create_nvram(sPAPRMachineState *spapr)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index f1d081b095..7c46d4625b 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -950,7 +950,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
unsigned compat_lvl = 0, cpu_version = 0;
unsigned max_lvl = get_compat_level(cpu_->max_compat);
int counter;
- sPAPROptionVector *ov5_guest;
+ sPAPROptionVector *ov5_guest, *ov5_cas_old, *ov5_updates;
/* Parse PVR list */
for (counter = 0; counter < 512; ++counter) {
@@ -1013,13 +1013,27 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
* of guest input. To model these properly we'd want some sort of mask,
* but since they only currently apply to memory migration as defined
* by LoPAPR 1.1, 14.5.4.8, which QEMU doesn't implement, we don't need
- * to worry about this.
+ * to worry about this for now.
*/
+ ov5_cas_old = spapr_ovec_clone(spapr->ov5_cas);
+ /* full range of negotiated ov5 capabilities */
spapr_ovec_intersect(spapr->ov5_cas, spapr->ov5, ov5_guest);
spapr_ovec_cleanup(ov5_guest);
+ /* capabilities that have been added since CAS-generated guest reset.
+ * if capabilities have since been removed, generate another reset
+ */
+ ov5_updates = spapr_ovec_new();
+ spapr->cas_reboot = spapr_ovec_diff(ov5_updates,
+ ov5_cas_old, spapr->ov5_cas);
+
+ if (!spapr->cas_reboot) {
+ spapr->cas_reboot =
+ (spapr_h_cas_compose_response(spapr, args[1], args[2], cpu_update,
+ ov5_updates) != 0);
+ }
+ spapr_ovec_cleanup(ov5_updates);
- if (spapr_h_cas_compose_response(spapr, args[1], args[2],
- cpu_update)) {
+ if (spapr->cas_reboot) {
qemu_system_reset_request();
}
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index a37eee870f..b6f9f1b632 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -75,6 +75,7 @@ struct sPAPRMachineState {
bool has_graphics;
sPAPROptionVector *ov5; /* QEMU-supported option vectors */
sPAPROptionVector *ov5_cas; /* negotiated (via CAS) option vectors */
+ bool cas_reboot;
uint32_t check_exception_irq;
Notifier epow_notifier;
@@ -586,7 +587,8 @@ void spapr_events_init(sPAPRMachineState *sm);
void spapr_dt_events(void *fdt, uint32_t check_exception_irq);
int spapr_h_cas_compose_response(sPAPRMachineState *sm,
target_ulong addr, target_ulong size,
- bool cpu_update);
+ bool cpu_update,
+ sPAPROptionVector *ov5_updates);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
void spapr_tce_table_enable(sPAPRTCETable *tcet,
uint32_t page_shift, uint64_t bus_offset,