summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--exec.c5
-rw-r--r--hw/ppc/ppc.c2
-rw-r--r--hw/ppc/spapr.c65
-rw-r--r--hw/ppc/spapr_irq.c50
-rw-r--r--include/hw/ppc/spapr.h1
-rw-r--r--target/ppc/cpu.h6
-rw-r--r--target/ppc/helper_regs.h2
-rw-r--r--target/ppc/translate.c66
-rw-r--r--target/ppc/translate/vsx-impl.inc.c2
9 files changed, 131 insertions, 68 deletions
diff --git a/exec.c b/exec.c
index 86a38d3b3b..6ab62f4eee 100644
--- a/exec.c
+++ b/exec.c
@@ -1692,9 +1692,10 @@ static int find_max_supported_pagesize(Object *obj, void *opaque)
     long *hpsize_min = opaque;
 
     if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
-        long hpsize = host_memory_backend_pagesize(MEMORY_BACKEND(obj));
+        HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+        long hpsize = host_memory_backend_pagesize(backend);
 
-        if (hpsize < *hpsize_min) {
+        if (host_memory_backend_is_mapped(backend) && (hpsize < *hpsize_min)) {
             *hpsize_min = hpsize;
         }
     }
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 49d57469fb..ad20584f26 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -1101,7 +1101,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
     tb_env = g_malloc0(sizeof(ppc_tb_t));
     env->tb_env = tb_env;
     tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
-    if (env->insns_flags & PPC_SEGMENT_64B) {
+    if (is_book3s_arch2x(env)) {
         /* All Book3S 64bit CPUs implement level based DEC logic */
         tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL;
     }
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6c16d6cfaf..b52b82d298 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1252,38 +1252,8 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
     _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)"));
     _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries"));
 
-    /*
-     * Add info to guest to indentify which host is it being run on
-     * and what is the uuid of the guest
-     */
-    if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) {
-        if (g_str_equal(spapr->host_model, "passthrough")) {
-            /* -M host-model=passthrough */
-            if (kvmppc_get_host_model(&buf)) {
-                _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
-                g_free(buf);
-            }
-        } else {
-            /* -M host-model=<user-string> */
-            _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
-        }
-    }
-
-    if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) {
-        if (g_str_equal(spapr->host_serial, "passthrough")) {
-            /* -M host-serial=passthrough */
-            if (kvmppc_get_host_serial(&buf)) {
-                _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
-                g_free(buf);
-            }
-        } else {
-            /* -M host-serial=<user-string> */
-            _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
-        }
-    }
-
+    /* Guest UUID & Name*/
     buf = qemu_uuid_unparse_strdup(&qemu_uuid);
-
     _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf));
     if (qemu_uuid_set) {
         _FDT(fdt_setprop_string(fdt, 0, "system-id", buf));
@@ -1295,6 +1265,21 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
                                 qemu_get_vm_name()));
     }
 
+    /* Host Model & Serial Number */
+    if (spapr->host_model) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
+    } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
+        g_free(buf);
+    }
+
+    if (spapr->host_serial) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
+    } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
+        g_free(buf);
+    }
+
     _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2));
     _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
 
@@ -2795,13 +2780,7 @@ static void spapr_machine_init(MachineState *machine)
 
     /* advertise XIVE on POWER9 machines */
     if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) {
-        if (ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
-                                  0, spapr->max_compat_pvr)) {
-            spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
-        } else if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) {
-            error_report("XIVE-only machines require a POWER9 CPU");
-            exit(1);
-        }
+        spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
     }
 
     /* init CPUs */
@@ -3352,12 +3331,12 @@ static void spapr_instance_init(Object *obj)
         spapr_get_host_model, spapr_set_host_model,
         &error_abort);
     object_property_set_description(obj, "host-model",
-        "Set host's model-id to use - none|passthrough|string", &error_abort);
+        "Host model to advertise in guest device tree", &error_abort);
     object_property_add_str(obj, "host-serial",
         spapr_get_host_serial, spapr_set_host_serial,
         &error_abort);
     object_property_set_description(obj, "host-serial",
-        "Set host's system-id to use - none|passthrough|string", &error_abort);
+        "Host serial number to advertise in guest device tree", &error_abort);
 }
 
 static void spapr_machine_finalizefn(Object *obj)
@@ -4381,18 +4360,14 @@ DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
 static void spapr_machine_3_1_class_options(MachineClass *mc)
 {
     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-    static GlobalProperty compat[] = {
-        { TYPE_SPAPR_MACHINE, "host-model", "passthrough" },
-        { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" },
-    };
 
     spapr_machine_4_0_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
-    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 
     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
     smc->update_dt_enabled = false;
     smc->dr_phb_enabled = false;
+    smc->broken_host_serial_model = true;
     smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
     smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
     smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 253e4de7fd..0a84e4cf63 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -16,6 +16,7 @@
 #include "hw/ppc/spapr_xive.h"
 #include "hw/ppc/xics.h"
 #include "hw/ppc/xics_spapr.h"
+#include "cpu-models.h"
 #include "sysemu/kvm.h"
 
 #include "trace.h"
@@ -582,12 +583,55 @@ SpaprIrq spapr_irq_dual = {
     .get_nodename = spapr_irq_get_nodename_dual,
 };
 
+
+static void spapr_irq_check(SpaprMachineState *spapr, Error **errp)
+{
+    MachineState *machine = MACHINE(spapr);
+
+    /*
+     * Sanity checks on non-P9 machines. On these, XIVE is not
+     * advertised, see spapr_dt_ov5_platform_support()
+     */
+    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
+                               0, spapr->max_compat_pvr)) {
+        /*
+         * If the 'dual' interrupt mode is selected, force XICS as CAS
+         * negotiation is useless.
+         */
+        if (spapr->irq == &spapr_irq_dual) {
+            spapr->irq = &spapr_irq_xics;
+            return;
+        }
+
+        /*
+         * Non-P9 machines using only XIVE is a bogus setup. We have two
+         * scenarios to take into account because of the compat mode:
+         *
+         * 1. POWER7/8 machines should fail to init later on when creating
+         *    the XIVE interrupt presenters because a POWER9 exception
+         *    model is required.
+
+         * 2. POWER9 machines using the POWER8 compat mode won't fail and
+         *    will let the OS boot with a partial XIVE setup : DT
+         *    properties but no hcalls.
+         *
+         * To cover both and not confuse the OS, add an early failure in
+         * QEMU.
+         */
+        if (spapr->irq == &spapr_irq_xive) {
+            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
+            return;
+        }
+    }
+}
+
 /*
  * sPAPR IRQ frontend routines for devices
  */
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
+    Error *local_err = NULL;
 
     if (machine_kernel_irqchip_split(machine)) {
         error_setg(errp, "kernel_irqchip split mode not supported on pseries");
@@ -600,6 +644,12 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
         return;
     }
 
+    spapr_irq_check(spapr, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
     /* Initialize the MSI IRQ allocator. */
     if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
         spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 2b4c05a2ec..5ea8081041 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -118,6 +118,7 @@ struct SpaprMachineClass {
     bool use_ohci_by_default;  /* use USB-OHCI instead of XHCI */
     bool pre_2_10_has_unused_icps;
     bool legacy_irq_allocation;
+    bool broken_host_serial_model; /* present real host info to the guest */
 
     void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
                           uint64_t *buid, hwaddr *pio, 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index fc12b4688e..0707177584 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2409,6 +2409,12 @@ enum {
 target_ulong cpu_read_xer(CPUPPCState *env);
 void cpu_write_xer(CPUPPCState *env, target_ulong xer);
 
+/*
+ * All 64-bit server processors compliant with arch 2.x, ie. 970 and newer,
+ * have PPC_SEGMENT_64B.
+ */
+#define is_book3s_arch2x(ctx) (!!((ctx)->insns_flags & PPC_SEGMENT_64B))
+
 static inline void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
 {
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index a2205e1044..c863abc0bf 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -152,7 +152,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
      * - 64-bit embedded implementations do not need any operation to be
      *   performed when PR is set.
      */
-    if ((env->insns_flags & PPC_SEGMENT_64B) && ((value >> MSR_PR) & 1)) {
+    if (is_book3s_arch2x(env) && ((value >> MSR_PR) & 1)) {
         value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR);
     }
 #endif
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 98b37cebc2..badc1ae1a3 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3747,20 +3747,52 @@ static void gen_bcond(DisasContext *ctx, int type)
     if ((bo & 0x4) == 0) {
         /* Decrement and test CTR */
         TCGv temp = tcg_temp_new();
-        if (unlikely(type == BCOND_CTR)) {
-            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
-            return;
-        }
-        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
-        if (NARROW_MODE(ctx)) {
-            tcg_gen_ext32u_tl(temp, cpu_ctr);
-        } else {
-            tcg_gen_mov_tl(temp, cpu_ctr);
-        }
-        if (bo & 0x2) {
-            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
+
+        if (type == BCOND_CTR) {
+            /*
+             * All ISAs up to v3 describe this form of bcctr as invalid but
+             * some processors, ie. 64-bit server processors compliant with
+             * arch 2.x, do implement a "test and decrement" logic instead,
+             * as described in their respective UMs. This logic involves CTR
+             * to act as both the branch target and a counter, which makes
+             * it basically useless and thus never used in real code.
+             *
+             * This form was hence chosen to trigger extra micro-architectural
+             * side-effect on real HW needed for the Spectre v2 workaround.
+             * It is up to guests that implement such workaround, ie. linux, to
+             * use this form in a way it just triggers the side-effect without
+             * doing anything else harmful.
+             */
+            if (unlikely(!is_book3s_arch2x(ctx))) {
+                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+                tcg_temp_free(temp);
+                tcg_temp_free(target);
+                return;
+            }
+
+            if (NARROW_MODE(ctx)) {
+                tcg_gen_ext32u_tl(temp, cpu_ctr);
+            } else {
+                tcg_gen_mov_tl(temp, cpu_ctr);
+            }
+            if (bo & 0x2) {
+                tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
+            } else {
+                tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
+            }
+            tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
         } else {
-            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
+            tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
+            if (NARROW_MODE(ctx)) {
+                tcg_gen_ext32u_tl(temp, cpu_ctr);
+            } else {
+                tcg_gen_mov_tl(temp, cpu_ctr);
+            }
+            if (bo & 0x2) {
+                tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
+            } else {
+                tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
+            }
         }
         tcg_temp_free(temp);
     }
@@ -3889,7 +3921,7 @@ static void gen_rfi(DisasContext *ctx)
     /* This instruction doesn't exist anymore on 64-bit server
      * processors compliant with arch 2.x
      */
-    if (ctx->insns_flags & PPC_SEGMENT_64B) {
+    if (is_book3s_arch2x(ctx)) {
         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
         return;
     }
@@ -6511,8 +6543,7 @@ static void gen_msgclr(DisasContext *ctx)
     GEN_PRIV;
 #else
     CHK_HV;
-    /* 64-bit server processors compliant with arch 2.x */
-    if (ctx->insns_flags & PPC_SEGMENT_64B) {
+    if (is_book3s_arch2x(ctx)) {
         gen_helper_book3s_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
     } else {
         gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
@@ -6526,8 +6557,7 @@ static void gen_msgsnd(DisasContext *ctx)
     GEN_PRIV;
 #else
     CHK_HV;
-    /* 64-bit server processors compliant with arch 2.x */
-    if (ctx->insns_flags & PPC_SEGMENT_64B) {
+    if (is_book3s_arch2x(ctx)) {
         gen_helper_book3s_msgsnd(cpu_gpr[rB(ctx->opcode)]);
     } else {
         gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c
index 508e9199c8..489b2436e4 100644
--- a/target/ppc/translate/vsx-impl.inc.c
+++ b/target/ppc/translate/vsx-impl.inc.c
@@ -356,8 +356,8 @@ static void gen_##name(DisasContext *ctx)                     \
     gen_set_access_type(ctx, ACCESS_INT);                     \
     EA = tcg_temp_new();                                      \
     gen_addr_reg_index(ctx, EA);                              \
+    get_cpu_vsrh(t0, xS(ctx->opcode));                        \
     gen_qemu_##operation(ctx, t0, EA);                        \
-    set_cpu_vsrh(xS(ctx->opcode), t0);                        \
     tcg_temp_free(EA);                                        \
     tcg_temp_free_i64(t0);                                    \
 }