]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
pseries: Switch VGA endian on H_SET_MODE
authorDavid Gibson <david@gibson.dropbear.id.au>
Tue, 10 Feb 2015 04:36:16 +0000 (15:36 +1100)
committerAlexander Graf <agraf@suse.de>
Mon, 9 Mar 2015 14:00:03 +0000 (15:00 +0100)
When the guest switches the interrupt endian mode, which essentially
means a global machine endian switch, we want to change the VGA
framebuffer endian mode as well in order to be backward compatible
with existing guests who don't know about the new endian control
register.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
hw/ppc/spapr_hcall.c
hw/ppc/spapr_pci.c
include/hw/ppc/spapr.h

index 86514472feb6fcbd1add0649d5cdf76843bf18eb..4f76f1cbfe6debfc3d7ee46228c2f03d87b83608 100644 (file)
@@ -731,12 +731,14 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
         CPU_FOREACH(cs) {
             set_spr(cs, SPR_LPCR, 0, LPCR_ILE);
         }
+        spapr_pci_switch_vga(true);
         return H_SUCCESS;
 
     case H_SET_MODE_ENDIAN_LITTLE:
         CPU_FOREACH(cs) {
             set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE);
         }
+        spapr_pci_switch_vga(false);
         return H_SUCCESS;
     }
 
index cebdeb3516f9371b0a64e0abdb486b4d4c613a72..7d37d83b27ee5a35be9b979e447751c83c4423f3 100644 (file)
@@ -982,3 +982,31 @@ static void spapr_pci_register_types(void)
 }
 
 type_init(spapr_pci_register_types)
+
+static int spapr_switch_one_vga(DeviceState *dev, void *opaque)
+{
+    bool be = *(bool *)opaque;
+
+    if (object_dynamic_cast(OBJECT(dev), "VGA")
+        || object_dynamic_cast(OBJECT(dev), "secondary-vga")) {
+        object_property_set_bool(OBJECT(dev), be, "big-endian-framebuffer",
+                                 &error_abort);
+    }
+    return 0;
+}
+
+void spapr_pci_switch_vga(bool big_endian)
+{
+    sPAPRPHBState *sphb;
+
+    /*
+     * For backward compatibility with existing guests, we switch
+     * the endianness of the VGA controller when changing the guest
+     * interrupt mode
+     */
+    QLIST_FOREACH(sphb, &spapr->phbs, list) {
+        BusState *bus = &PCI_HOST_BRIDGE(sphb)->bus->qbus;
+        qbus_walk_children(bus, spapr_switch_one_vga, NULL, NULL, NULL,
+                           &big_endian);
+    }
+}
index a8e6817cb8874b7379bf539e55586b13eaf1b294..168b608af75940c1d1c3bd4f2d37018de49f78a4 100644 (file)
@@ -481,6 +481,7 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
                  uint32_t liobn, uint64_t window, uint32_t size);
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
                       sPAPRTCETable *tcet);
+void spapr_pci_switch_vga(bool big_endian);
 
 #define TYPE_SPAPR_RTC "spapr-rtc"