Add UEFI support for aarch64.

This commit is contained in:
Richard W.M. Jones 2015-02-04 15:34:14 +00:00
parent f287dc5662
commit 391fb81c16
16 changed files with 1780 additions and 2 deletions

View File

@ -0,0 +1,27 @@
From f4a88b45ad11265d39f17efdf2f54f6a48043655 Mon Sep 17 00:00:00 2001
From: Gonglei <arei.gonglei@huawei.com>
Date: Mon, 8 Dec 2014 19:52:41 +0800
Subject: [PATCH 01/15] fw_cfg: remove superfluous blank line
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit d504fb4cecdb7c6f3b18c4d83296e84b6e970595)
---
hw/nvram/fw_cfg.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index a7122ee..c4b78ed 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -621,7 +621,6 @@ static void fw_cfg_realize(DeviceState *dev, Error **errp)
FWCfgState *s = FW_CFG(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-
if (s->ctl_iobase + 1 == s->data_iobase) {
sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem);
} else {
--
2.1.0

View File

@ -0,0 +1,45 @@
From 366ca14a9ae8210540a7e4f6bb034b4f0d1c458d Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
Date: Thu, 11 Dec 2014 12:07:53 +0000
Subject: [PATCH 02/15] hw/arm/boot: fix uninitialized scalar variable warning
reported by coverity
Coverity reports the 'size' may be used uninitialized, but that can't happen,
because the caller has checked "if (binfo->dtb_filename || binfo->get_dtb)"
before call 'load_dtb'.
Here we simply remove the 'if (binfo->get_dtb)' to satisfy coverity.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Message-id: 1416826240-12368-1-git-send-email-zhang.zhanghailiang@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit a554ecb49d0021fd8bb0fd4f2f6be807b3c8b54f)
---
hw/arm/boot.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0014c34..e6a3c5b 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -329,6 +329,8 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
* Returns: the size of the device tree image on success,
* 0 if the image size exceeds the limit,
* -1 on errors.
+ *
+ * Note: Must not be called unless have_dtb(binfo) is true.
*/
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
hwaddr addr_limit)
@@ -352,7 +354,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
goto fail;
}
g_free(filename);
- } else if (binfo->get_dtb) {
+ } else {
fdt = binfo->get_dtb(binfo, &size);
if (!fdt) {
fprintf(stderr, "Board was unable to create a dtb blob\n");
--
2.1.0

View File

@ -0,0 +1,156 @@
From 7957f6ee42418f6b3de6148279b10faa292b2db2 Mon Sep 17 00:00:00 2001
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Date: Thu, 11 Dec 2014 11:46:36 +0000
Subject: [PATCH 03/15] Sort include/qemu/typedefs.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Mainly to make it less likely to conflict during merges.
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 64baadc2726ae929660dd0c61a42e8d9f3ba1828)
---
include/qemu/typedefs.h | 105 +++++++++++++++++++++++-------------------------
1 file changed, 50 insertions(+), 55 deletions(-)
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 3475177..57ff47f 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -3,80 +3,75 @@
/* A load of opaque types so that device init declarations don't have to
pull in all the real definitions. */
-typedef struct QEMUTimer QEMUTimer;
-typedef struct QEMUTimerListGroup QEMUTimerListGroup;
-typedef struct QEMUFile QEMUFile;
-typedef struct QEMUBH QEMUBH;
-
-typedef struct AioContext AioContext;
-
-typedef struct Visitor Visitor;
-
struct Monitor;
-typedef struct Monitor Monitor;
-typedef struct MigrationParams MigrationParams;
-
-typedef struct Property Property;
-typedef struct PropertyInfo PropertyInfo;
-typedef struct CompatProperty CompatProperty;
-typedef struct DeviceState DeviceState;
-typedef struct BusState BusState;
-typedef struct BusClass BusClass;
+/* Please keep this list in alphabetical order */
+typedef struct AdapterInfo AdapterInfo;
typedef struct AddressSpace AddressSpace;
-typedef struct MemoryRegion MemoryRegion;
-typedef struct MemoryRegionSection MemoryRegionSection;
-typedef struct MemoryListener MemoryListener;
-
-typedef struct MemoryMappingList MemoryMappingList;
-
-typedef struct QEMUMachine QEMUMachine;
-typedef struct MachineClass MachineClass;
-typedef struct MachineState MachineState;
-typedef struct NICInfo NICInfo;
-typedef struct HCIInfo HCIInfo;
+typedef struct AioContext AioContext;
typedef struct AudioState AudioState;
typedef struct BlockBackend BlockBackend;
typedef struct BlockDriverState BlockDriverState;
-typedef struct DriveInfo DriveInfo;
-typedef struct DisplayState DisplayState;
+typedef struct BusClass BusClass;
+typedef struct BusState BusState;
+typedef struct CharDriverState CharDriverState;
+typedef struct CompatProperty CompatProperty;
+typedef struct DeviceState DeviceState;
typedef struct DisplayChangeListener DisplayChangeListener;
+typedef struct DisplayState DisplayState;
typedef struct DisplaySurface DisplaySurface;
-typedef struct PixelFormat PixelFormat;
-typedef struct QemuConsole QemuConsole;
-typedef struct CharDriverState CharDriverState;
-typedef struct MACAddr MACAddr;
-typedef struct NetClientState NetClientState;
+typedef struct DriveInfo DriveInfo;
+typedef struct EventNotifier EventNotifier;
+typedef struct FWCfgState FWCfgState;
+typedef struct HCIInfo HCIInfo;
typedef struct I2CBus I2CBus;
+typedef struct I2SCodec I2SCodec;
typedef struct ISABus ISABus;
typedef struct ISADevice ISADevice;
-typedef struct SMBusDevice SMBusDevice;
-typedef struct PCIHostState PCIHostState;
-typedef struct PCIExpressHost PCIExpressHost;
+typedef struct MACAddr MACAddr;
+typedef struct MachineClass MachineClass;
+typedef struct MachineState MachineState;
+typedef struct MemoryListener MemoryListener;
+typedef struct MemoryMappingList MemoryMappingList;
+typedef struct MemoryRegion MemoryRegion;
+typedef struct MemoryRegionSection MemoryRegionSection;
+typedef struct MigrationParams MigrationParams;
+typedef struct Monitor Monitor;
+typedef struct MouseTransformInfo MouseTransformInfo;
+typedef struct MSIMessage MSIMessage;
+typedef struct NetClientState NetClientState;
+typedef struct NICInfo NICInfo;
+typedef struct PcGuestInfo PcGuestInfo;
+typedef struct PCIBridge PCIBridge;
typedef struct PCIBus PCIBus;
typedef struct PCIDevice PCIDevice;
-typedef struct PCIExpressDevice PCIExpressDevice;
-typedef struct PCIBridge PCIBridge;
-typedef struct PCIEAERMsg PCIEAERMsg;
-typedef struct PCIEAERLog PCIEAERLog;
typedef struct PCIEAERErr PCIEAERErr;
+typedef struct PCIEAERLog PCIEAERLog;
+typedef struct PCIEAERMsg PCIEAERMsg;
typedef struct PCIEPort PCIEPort;
typedef struct PCIESlot PCIESlot;
-typedef struct MSIMessage MSIMessage;
-typedef struct SerialState SerialState;
+typedef struct PCIExpressDevice PCIExpressDevice;
+typedef struct PCIExpressHost PCIExpressHost;
+typedef struct PCIHostState PCIHostState;
typedef struct PCMCIACardState PCMCIACardState;
-typedef struct MouseTransformInfo MouseTransformInfo;
-typedef struct uWireSlave uWireSlave;
-typedef struct I2SCodec I2SCodec;
-typedef struct SSIBus SSIBus;
-typedef struct EventNotifier EventNotifier;
-typedef struct VirtIODevice VirtIODevice;
+typedef struct PixelFormat PixelFormat;
+typedef struct PropertyInfo PropertyInfo;
+typedef struct Property Property;
+typedef struct QEMUBH QEMUBH;
+typedef struct QemuConsole QemuConsole;
+typedef struct QEMUFile QEMUFile;
+typedef struct QEMUMachine QEMUMachine;
typedef struct QEMUSGList QEMUSGList;
typedef struct QEMUSizedBuffer QEMUSizedBuffer;
-typedef struct SHPCDevice SHPCDevice;
-typedef struct FWCfgState FWCfgState;
-typedef struct PcGuestInfo PcGuestInfo;
+typedef struct QEMUTimerListGroup QEMUTimerListGroup;
+typedef struct QEMUTimer QEMUTimer;
typedef struct Range Range;
-typedef struct AdapterInfo AdapterInfo;
+typedef struct SerialState SerialState;
+typedef struct SHPCDevice SHPCDevice;
+typedef struct SMBusDevice SMBusDevice;
+typedef struct SSIBus SSIBus;
+typedef struct uWireSlave uWireSlave;
+typedef struct VirtIODevice VirtIODevice;
+typedef struct Visitor Visitor;
#endif /* QEMU_TYPEDEFS_H */
--
2.1.0

View File

@ -0,0 +1,339 @@
From e91399538669c6480ace3eb0f63b1c99645924bc Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:35 +0100
Subject: [PATCH 04/15] fw_cfg: hard separation between the MMIO and I/O port
mappings
We are going to introduce a wide data register for fw_cfg, but only for
the MMIO mapped device. The wide data register will also require the
tightening of endiannesses.
However we don't want to touch the I/O port mapped fw_cfg device at all.
Currently QEMU provides a single fw_cfg device type that can handle both
I/O port and MMIO mapping. This flexibility is not actually exploited by
any board in the tree, but it renders restricting the above changes to
MMIO very hard.
Therefore, let's derive two classes from TYPE_FW_CFG: TYPE_FW_CFG_IO and
TYPE_FW_CFG_MEM.
TYPE_FW_CFG_IO incorporates the base I/O port and the related combined
MemoryRegion. (NB: all boards in the tree that use the I/O port mapped
flavor opt for the combined mapping; that is, when the data port overlays
the high address byte of the selector port. Therefore we can drop the
capability to map those I/O ports separately.)
TYPE_FW_CFG_MEM incorporates the base addresses for the MMIO selector and
data registers, and their respective MemoryRegions.
The "realize" and "props" class members are specific to each new derived
class, and become unused for the base class. The base class retains the
"reset" member and the "vmsd" member, because the reset functionality and
the set of migrated data are not specific to the mapping.
The new functions fw_cfg_init_io() and fw_cfg_init_mem() expose the
possible mappings in separation. For now fw_cfg_init() is retained as a
compatibility shim that enforces the above assumptions.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-2-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 5712db6ae5101db645f71edc393368cd59bfd314)
---
hw/nvram/fw_cfg.c | 181 +++++++++++++++++++++++++++++++---------------
include/hw/nvram/fw_cfg.h | 2 +
include/qemu/typedefs.h | 2 +
3 files changed, 128 insertions(+), 57 deletions(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index c4b78ed..ab7bfff 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -32,10 +32,16 @@
#define FW_CFG_SIZE 2
#define FW_CFG_DATA_SIZE 1
-#define TYPE_FW_CFG "fw_cfg"
#define FW_CFG_NAME "fw_cfg"
#define FW_CFG_PATH "/machine/" FW_CFG_NAME
-#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
+
+#define TYPE_FW_CFG "fw_cfg"
+#define TYPE_FW_CFG_IO "fw_cfg_io"
+#define TYPE_FW_CFG_MEM "fw_cfg_mem"
+
+#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
+#define FW_CFG_IO(obj) OBJECT_CHECK(FWCfgIoState, (obj), TYPE_FW_CFG_IO)
+#define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM)
typedef struct FWCfgEntry {
uint32_t len;
@@ -50,8 +56,6 @@ struct FWCfgState {
SysBusDevice parent_obj;
/*< public >*/
- MemoryRegion ctl_iomem, data_iomem, comb_iomem;
- uint32_t ctl_iobase, data_iobase;
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
FWCfgFiles *files;
uint16_t cur_entry;
@@ -59,6 +63,23 @@ struct FWCfgState {
Notifier machine_ready;
};
+struct FWCfgIoState {
+ /*< private >*/
+ FWCfgState parent_obj;
+ /*< public >*/
+
+ MemoryRegion comb_iomem;
+ uint32_t iobase;
+};
+
+struct FWCfgMemState {
+ /*< private >*/
+ FWCfgState parent_obj;
+ /*< public >*/
+
+ MemoryRegion ctl_iomem, data_iomem;
+};
+
#define JPG_FILE 0
#define BMP_FILE 1
@@ -560,19 +581,11 @@ static void fw_cfg_machine_ready(struct Notifier *n, void *data)
qemu_register_reset(fw_cfg_machine_reset, s);
}
-FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
- hwaddr ctl_addr, hwaddr data_addr)
+
+
+static void fw_cfg_init1(DeviceState *dev)
{
- DeviceState *dev;
- SysBusDevice *d;
- FWCfgState *s;
-
- dev = qdev_create(NULL, TYPE_FW_CFG);
- qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
- qdev_prop_set_uint32(dev, "data_iobase", data_port);
- d = SYS_BUS_DEVICE(dev);
-
- s = FW_CFG(dev);
+ FWCfgState *s = FW_CFG(dev);
assert(!object_resolve_path(FW_CFG_PATH, NULL));
@@ -580,12 +593,6 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
qdev_init_nofail(dev);
- if (ctl_addr) {
- sysbus_mmio_map(d, 0, ctl_addr);
- }
- if (data_addr) {
- sysbus_mmio_map(d, 1, data_addr);
- }
fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4);
fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
@@ -596,48 +603,48 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
s->machine_ready.notify = fw_cfg_machine_ready;
qemu_add_machine_init_done_notifier(&s->machine_ready);
+}
+
+FWCfgState *fw_cfg_init_io(uint32_t iobase)
+{
+ DeviceState *dev;
- return s;
+ dev = qdev_create(NULL, TYPE_FW_CFG_IO);
+ qdev_prop_set_uint32(dev, "iobase", iobase);
+ fw_cfg_init1(dev);
+
+ return FW_CFG(dev);
}
-static void fw_cfg_initfn(Object *obj)
+FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- FWCfgState *s = FW_CFG(obj);
-
- memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s,
- "fwcfg.ctl", FW_CFG_SIZE);
- sysbus_init_mmio(sbd, &s->ctl_iomem);
- memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s,
- "fwcfg.data", FW_CFG_DATA_SIZE);
- sysbus_init_mmio(sbd, &s->data_iomem);
- /* In case ctl and data overlap: */
- memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s,
- "fwcfg", FW_CFG_SIZE);
+ DeviceState *dev;
+ SysBusDevice *sbd;
+
+ dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
+ fw_cfg_init1(dev);
+
+ sbd = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(sbd, 0, ctl_addr);
+ sysbus_mmio_map(sbd, 1, data_addr);
+
+ return FW_CFG(dev);
}
-static void fw_cfg_realize(DeviceState *dev, Error **errp)
+
+FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
+ hwaddr crl_addr, hwaddr data_addr)
{
- FWCfgState *s = FW_CFG(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-
- if (s->ctl_iobase + 1 == s->data_iobase) {
- sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem);
- } else {
- if (s->ctl_iobase) {
- sysbus_add_io(sbd, s->ctl_iobase, &s->ctl_iomem);
- }
- if (s->data_iobase) {
- sysbus_add_io(sbd, s->data_iobase, &s->data_iomem);
- }
+ if (ctl_port + 1 == data_port && crl_addr == 0 && data_addr == 0) {
+ return fw_cfg_init_io(ctl_port);
+ }
+ if (ctl_port == 0 && data_port == 0 && crl_addr != 0 && data_addr != 0) {
+ return fw_cfg_init_mem(crl_addr, data_addr);
}
+ assert(false);
+ return NULL;
}
-static Property fw_cfg_properties[] = {
- DEFINE_PROP_UINT32("ctl_iobase", FWCfgState, ctl_iobase, -1),
- DEFINE_PROP_UINT32("data_iobase", FWCfgState, data_iobase, -1),
- DEFINE_PROP_END_OF_LIST(),
-};
FWCfgState *fw_cfg_find(void)
{
@@ -648,23 +655,83 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = fw_cfg_realize;
dc->reset = fw_cfg_reset;
dc->vmsd = &vmstate_fw_cfg;
- dc->props = fw_cfg_properties;
}
static const TypeInfo fw_cfg_info = {
.name = TYPE_FW_CFG,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(FWCfgState),
- .instance_init = fw_cfg_initfn,
.class_init = fw_cfg_class_init,
};
+
+static Property fw_cfg_io_properties[] = {
+ DEFINE_PROP_UINT32("iobase", FWCfgIoState, iobase, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
+{
+ FWCfgIoState *s = FW_CFG_IO(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops,
+ FW_CFG(s), "fwcfg", FW_CFG_SIZE);
+ sysbus_add_io(sbd, s->iobase, &s->comb_iomem);
+}
+
+static void fw_cfg_io_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = fw_cfg_io_realize;
+ dc->props = fw_cfg_io_properties;
+}
+
+static const TypeInfo fw_cfg_io_info = {
+ .name = TYPE_FW_CFG_IO,
+ .parent = TYPE_FW_CFG,
+ .instance_size = sizeof(FWCfgIoState),
+ .class_init = fw_cfg_io_class_init,
+};
+
+
+static void fw_cfg_mem_realize(DeviceState *dev, Error **errp)
+{
+ FWCfgMemState *s = FW_CFG_MEM(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops,
+ FW_CFG(s), "fwcfg.ctl", FW_CFG_SIZE);
+ sysbus_init_mmio(sbd, &s->ctl_iomem);
+
+ memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops,
+ FW_CFG(s), "fwcfg.data", FW_CFG_DATA_SIZE);
+ sysbus_init_mmio(sbd, &s->data_iomem);
+}
+
+static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = fw_cfg_mem_realize;
+}
+
+static const TypeInfo fw_cfg_mem_info = {
+ .name = TYPE_FW_CFG_MEM,
+ .parent = TYPE_FW_CFG,
+ .instance_size = sizeof(FWCfgMemState),
+ .class_init = fw_cfg_mem_class_init,
+};
+
+
static void fw_cfg_register_types(void)
{
type_register_static(&fw_cfg_info);
+ type_register_static(&fw_cfg_io_info);
+ type_register_static(&fw_cfg_mem_info);
}
type_init(fw_cfg_register_types)
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 56e1ed7..fcc88ea 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -80,6 +80,8 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
size_t len);
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
hwaddr crl_addr, hwaddr data_addr);
+FWCfgState *fw_cfg_init_io(uint32_t iobase);
+FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr);
FWCfgState *fw_cfg_find(void);
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 57ff47f..f2bbaaf 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -22,6 +22,8 @@ typedef struct DisplayState DisplayState;
typedef struct DisplaySurface DisplaySurface;
typedef struct DriveInfo DriveInfo;
typedef struct EventNotifier EventNotifier;
+typedef struct FWCfgIoState FWCfgIoState;
+typedef struct FWCfgMemState FWCfgMemState;
typedef struct FWCfgState FWCfgState;
typedef struct HCIInfo HCIInfo;
typedef struct I2CBus I2CBus;
--
2.1.0

View File

@ -0,0 +1,139 @@
From 6b9b5f3220b48bab7340fa7cae6ee021280fa9f1 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:36 +0100
Subject: [PATCH 05/15] fw_cfg: move boards to fw_cfg_init_io() /
fw_cfg_init_mem()
This allows us to drop the fw_cfg_init() shim and to enforce the possible
mappings at compile time.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-3-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 66708822cd3007ae1ec5104d274a861148725e7a)
---
hw/i386/pc.c | 4 ++--
hw/nvram/fw_cfg.c | 14 --------------
hw/ppc/mac_newworld.c | 2 +-
hw/ppc/mac_oldworld.c | 2 +-
hw/sparc/sun4m.c | 2 +-
hw/sparc64/sun4u.c | 2 +-
include/hw/nvram/fw_cfg.h | 2 --
7 files changed, 6 insertions(+), 22 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f31d55e..f60965f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -648,7 +648,7 @@ static FWCfgState *bochs_bios_init(void)
int i, j;
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
- fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+ fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
/* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
*
* SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
@@ -1169,7 +1169,7 @@ FWCfgState *xen_load_linux(const char *kernel_filename,
assert(kernel_filename != NULL);
- fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+ fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
rom_set_fw(fw_cfg);
load_linux(fw_cfg, kernel_filename, initrd_filename,
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index ab7bfff..c48bc6e 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -632,20 +632,6 @@ FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
}
-FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
- hwaddr crl_addr, hwaddr data_addr)
-{
- if (ctl_port + 1 == data_port && crl_addr == 0 && data_addr == 0) {
- return fw_cfg_init_io(ctl_port);
- }
- if (ctl_port == 0 && data_port == 0 && crl_addr != 0 && data_addr != 0) {
- return fw_cfg_init_mem(crl_addr, data_addr);
- }
- assert(false);
- return NULL;
-}
-
-
FWCfgState *fw_cfg_find(void)
{
return FW_CFG(object_resolve_path(FW_CFG_PATH, NULL));
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 89aee71..5dac389 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -454,7 +454,7 @@ static void ppc_core99_init(MachineState *machine)
pmac_format_nvram_partition(nvr, 0x2000);
/* No PCI init: the BIOS will do it */
- fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+ fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 32c21a4..41fefb7 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -314,7 +314,7 @@ static void ppc_heathrow_init(MachineState *machine)
/* No PCI init: the BIOS will do it */
- fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+ fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 8273199..a12d3c4 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -1084,7 +1084,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
ecc_init(hwdef->ecc_base, slavio_irq[28],
hwdef->ecc_version);
- fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+ fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index f42112c..49fb678 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -892,7 +892,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
graphic_width, graphic_height, graphic_depth,
(uint8_t *)&nd_table[0].macaddr);
- fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+ fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index fcc88ea..a99586e 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -78,8 +78,6 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
void *data, size_t len);
void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
size_t len);
-FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
- hwaddr crl_addr, hwaddr data_addr);
FWCfgState *fw_cfg_init_io(uint32_t iobase);
FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr);
--
2.1.0

View File

@ -0,0 +1,47 @@
From dfcc3acd2510e5adc3dbb67c83a131bf5fb017ec Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:37 +0100
Subject: [PATCH 06/15] fw_cfg_mem: max access size and region size are the
same for data register
Make it clear that the maximum access size to the MMIO data register
determines the full size of the memory region.
Currently the max access size is 1.
This patch doesn't change behavior.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-4-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 86099db3823fec1800225f89544014a98b227ed9)
---
hw/nvram/fw_cfg.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index c48bc6e..8deb860 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -31,7 +31,6 @@
#include "qemu/config-file.h"
#define FW_CFG_SIZE 2
-#define FW_CFG_DATA_SIZE 1
#define FW_CFG_NAME "fw_cfg"
#define FW_CFG_PATH "/machine/" FW_CFG_NAME
@@ -694,7 +693,8 @@ static void fw_cfg_mem_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->ctl_iomem);
memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops,
- FW_CFG(s), "fwcfg.data", FW_CFG_DATA_SIZE);
+ FW_CFG(s), "fwcfg.data",
+ fw_cfg_data_mem_ops.valid.max_access_size);
sysbus_init_mmio(sbd, &s->data_iomem);
}
--
2.1.0

View File

@ -0,0 +1,56 @@
From 172d29b5a320c8d656072db24e94ea21d1a5ed75 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:38 +0100
Subject: [PATCH 07/15] fw_cfg_mem: flip ctl_mem_ops and data_mem_ops to
DEVICE_BIG_ENDIAN
The standalone selector port (fw_cfg_ctl_mem_ops) is only used by big
endian guests to date (*), hence this change doesn't regress them. Paolo
and Alex have suggested / requested an explicit DEVICE_BIG_ENDIAN setting
here, for clarity.
(*) git grep -l fw_cfg_init_mem
hw/nvram/fw_cfg.c
hw/ppc/mac_newworld.c
hw/ppc/mac_oldworld.c
hw/sparc/sun4m.c
include/hw/nvram/fw_cfg.h
The standalone data port (fw_cfg_data_mem_ops) has max_access_size 1 (for
now), hence changing its endianness doesn't change behavior for existing
guest code.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-5-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit d789c84547abaaf82828b20998aee618b9327261)
---
hw/nvram/fw_cfg.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 8deb860..910ae14 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -332,14 +332,14 @@ static bool fw_cfg_comb_valid(void *opaque, hwaddr addr,
static const MemoryRegionOps fw_cfg_ctl_mem_ops = {
.write = fw_cfg_ctl_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
.valid.accepts = fw_cfg_ctl_mem_valid,
};
static const MemoryRegionOps fw_cfg_data_mem_ops = {
.read = fw_cfg_data_mem_read,
.write = fw_cfg_data_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 1,
--
2.1.0

View File

@ -0,0 +1,73 @@
From cdea522fe22d3996228c1b5a80b8d6e959da91aa Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Mon, 22 Dec 2014 13:11:39 +0100
Subject: [PATCH 08/15] exec: allows 8-byte accesses in subpage_ops
Otherwise fw_cfg accesses are split into 4-byte ones before they reach the
fw_cfg ops / handlers.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit ff6cff7554be06e95f8d712f66cd16bd6681c746)
---
exec.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/exec.c b/exec.c
index 71ac104..dee9543 100644
--- a/exec.c
+++ b/exec.c
@@ -1768,7 +1768,7 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
unsigned len)
{
subpage_t *subpage = opaque;
- uint8_t buf[4];
+ uint8_t buf[8];
#if defined(DEBUG_SUBPAGE)
printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
@@ -1782,6 +1782,8 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
return lduw_p(buf);
case 4:
return ldl_p(buf);
+ case 8:
+ return ldq_p(buf);
default:
abort();
}
@@ -1791,7 +1793,7 @@ static void subpage_write(void *opaque, hwaddr addr,
uint64_t value, unsigned len)
{
subpage_t *subpage = opaque;
- uint8_t buf[4];
+ uint8_t buf[8];
#if defined(DEBUG_SUBPAGE)
printf("%s: subpage %p len %u addr " TARGET_FMT_plx
@@ -1808,6 +1810,9 @@ static void subpage_write(void *opaque, hwaddr addr,
case 4:
stl_p(buf, value);
break;
+ case 8:
+ stq_p(buf, value);
+ break;
default:
abort();
}
@@ -1830,6 +1835,10 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
static const MemoryRegionOps subpage_ops = {
.read = subpage_read,
.write = subpage_write,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 8,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 8,
.valid.accepts = subpage_accepts,
.endianness = DEVICE_NATIVE_ENDIAN,
};
--
2.1.0

View File

@ -0,0 +1,168 @@
From 5e7e3b47666b777f3bf44cd91d87130f8ca1a7c1 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:40 +0100
Subject: [PATCH 09/15] fw_cfg_mem: introduce the "data_width" property
The "data_width" property is capable of changing the maximum valid access
size to the MMIO data register, and resizes the memory region similarly,
at device realization time.
The default value of "data_memwidth" is set so that we don't yet diverge
from "fw_cfg_data_mem_ops".
Most of the fw_cfg_mem users will stick with the default, and for them we
should continue using the statically allocated "fw_cfg_data_mem_ops". This
is beneficial for debugging because gdb can resolve pointers referencing
static objects to the names of those objects.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-7-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit cfaadf0e89e7c2a47462d5f96390c9a9b4de037c)
---
hw/nvram/fw_cfg.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 74 insertions(+), 5 deletions(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 910ae14..2950d68 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -77,6 +77,8 @@ struct FWCfgMemState {
/*< public >*/
MemoryRegion ctl_iomem, data_iomem;
+ uint32_t data_width;
+ MemoryRegionOps wide_data_ops;
};
#define JPG_FILE 0
@@ -284,13 +286,58 @@ static uint8_t fw_cfg_read(FWCfgState *s)
static uint64_t fw_cfg_data_mem_read(void *opaque, hwaddr addr,
unsigned size)
{
- return fw_cfg_read(opaque);
+ FWCfgState *s = opaque;
+ uint8_t buf[8];
+ unsigned i;
+
+ for (i = 0; i < size; ++i) {
+ buf[i] = fw_cfg_read(s);
+ }
+ switch (size) {
+ case 1:
+ return buf[0];
+ case 2:
+ return lduw_he_p(buf);
+ case 4:
+ return (uint32_t)ldl_he_p(buf);
+ case 8:
+ return ldq_he_p(buf);
+ }
+ abort();
}
static void fw_cfg_data_mem_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
- fw_cfg_write(opaque, (uint8_t)value);
+ FWCfgState *s = opaque;
+ uint8_t buf[8];
+ unsigned i;
+
+ switch (size) {
+ case 1:
+ buf[0] = value;
+ break;
+ case 2:
+ stw_he_p(buf, value);
+ break;
+ case 4:
+ stl_he_p(buf, value);
+ break;
+ case 8:
+ stq_he_p(buf, value);
+ break;
+ default:
+ abort();
+ }
+ for (i = 0; i < size; ++i) {
+ fw_cfg_write(s, buf[i]);
+ }
+}
+
+static bool fw_cfg_data_mem_valid(void *opaque, hwaddr addr,
+ unsigned size, bool is_write)
+{
+ return addr == 0;
}
static void fw_cfg_ctl_mem_write(void *opaque, hwaddr addr,
@@ -343,6 +390,7 @@ static const MemoryRegionOps fw_cfg_data_mem_ops = {
.valid = {
.min_access_size = 1,
.max_access_size = 1,
+ .accepts = fw_cfg_data_mem_valid,
},
};
@@ -621,6 +669,9 @@ FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
SysBusDevice *sbd;
dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
+ qdev_prop_set_uint32(dev, "data_width",
+ fw_cfg_data_mem_ops.valid.max_access_size);
+
fw_cfg_init1(dev);
sbd = SYS_BUS_DEVICE(dev);
@@ -683,18 +734,35 @@ static const TypeInfo fw_cfg_io_info = {
};
+static Property fw_cfg_mem_properties[] = {
+ DEFINE_PROP_UINT32("data_width", FWCfgMemState, data_width, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void fw_cfg_mem_realize(DeviceState *dev, Error **errp)
{
FWCfgMemState *s = FW_CFG_MEM(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops;
memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops,
FW_CFG(s), "fwcfg.ctl", FW_CFG_SIZE);
sysbus_init_mmio(sbd, &s->ctl_iomem);
- memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops,
- FW_CFG(s), "fwcfg.data",
- fw_cfg_data_mem_ops.valid.max_access_size);
+ if (s->data_width > data_ops->valid.max_access_size) {
+ /* memberwise copy because the "old_mmio" member is const */
+ s->wide_data_ops.read = data_ops->read;
+ s->wide_data_ops.write = data_ops->write;
+ s->wide_data_ops.endianness = data_ops->endianness;
+ s->wide_data_ops.valid = data_ops->valid;
+ s->wide_data_ops.impl = data_ops->impl;
+
+ s->wide_data_ops.valid.max_access_size = s->data_width;
+ s->wide_data_ops.impl.max_access_size = s->data_width;
+ data_ops = &s->wide_data_ops;
+ }
+ memory_region_init_io(&s->data_iomem, OBJECT(s), data_ops, FW_CFG(s),
+ "fwcfg.data", data_ops->valid.max_access_size);
sysbus_init_mmio(sbd, &s->data_iomem);
}
@@ -703,6 +771,7 @@ static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = fw_cfg_mem_realize;
+ dc->props = fw_cfg_mem_properties;
}
static const TypeInfo fw_cfg_mem_info = {
--
2.1.0

View File

@ -0,0 +1,99 @@
From 870ed93bb6c35e821031bbc3a3a297d0e60c67ab Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:41 +0100
Subject: [PATCH 10/15] fw_cfg_mem: expose the "data_width" property with
fw_cfg_init_mem_wide()
We rebase fw_cfg_init_mem() to the new function for compatibility with
current callers.
The behavior of the (big endian) multi-byte data reads is best shown
with a qtest session. Here, we are reading the first six bytes of
the UUID
$ arm-softmmu/qemu-system-arm -M virt -machine accel=qtest \
-qtest stdio -uuid 4600cb32-38ec-4b2f-8acb-81c6ea54f2d8
>>> writew 0x9020008 0x0200
<<< OK
>>> readl 0x9020000
<<< OK 0x000000004600cb32
Remember this is big endian. On big endian machines, it is stored
directly as 0x46 0x00 0xcb 0x32.
On a little endian machine, we have to first swap it, so that it becomes
0x32cb0046. When written to memory, it becomes 0x46 0x00 0xcb 0x32
again.
Reading byte-by-byte works too, of course:
>>> readb 0x9020000
<<< OK 0x0000000000000038
>>> readb 0x9020000
<<< OK 0x00000000000000ec
Here only a single byte is read at a time, so they are read in order
similar to the 1-byte data port that is already in PPC and SPARC
machines.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-8-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 6c87e3d5967a1d731b5f591a8f0ee6c319c14ca8)
---
hw/nvram/fw_cfg.c | 12 +++++++++---
include/hw/nvram/fw_cfg.h | 2 ++
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 2950d68..fcdf821 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -663,14 +663,14 @@ FWCfgState *fw_cfg_init_io(uint32_t iobase)
return FW_CFG(dev);
}
-FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
+FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, hwaddr data_addr,
+ uint32_t data_width)
{
DeviceState *dev;
SysBusDevice *sbd;
dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
- qdev_prop_set_uint32(dev, "data_width",
- fw_cfg_data_mem_ops.valid.max_access_size);
+ qdev_prop_set_uint32(dev, "data_width", data_width);
fw_cfg_init1(dev);
@@ -681,6 +681,12 @@ FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
return FW_CFG(dev);
}
+FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
+{
+ return fw_cfg_init_mem_wide(ctl_addr, data_addr,
+ fw_cfg_data_mem_ops.valid.max_access_size);
+}
+
FWCfgState *fw_cfg_find(void)
{
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index a99586e..6d8a8ac 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -80,6 +80,8 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
size_t len);
FWCfgState *fw_cfg_init_io(uint32_t iobase);
FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr);
+FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, hwaddr data_addr,
+ uint32_t data_width);
FWCfgState *fw_cfg_find(void);
--
2.1.0

View File

@ -0,0 +1,89 @@
From 892602338db279204d11212034bc9f359dc4c1c4 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:42 +0100
Subject: [PATCH 11/15] arm: add fw_cfg to "virt" board
fw_cfg already supports exposure over MMIO (used in ppc/mac_newworld.c,
ppc/mac_oldworld.c, sparc/sun4m.c); we can easily add it to the "virt"
board.
Because MMIO access is slow on ARM KVM, we enable the guest, with
fw_cfg_init_mem_wide(), to transfer up to 8 bytes with a single access.
This has been measured to speed up transfers up to 7.5-fold, relative to
single byte data access, on both ARM KVM and x86_64 TCG.
The MMIO register block of fw_cfg is advertized in the device tree. As
base address we pick 0x09020000, which conforms to the comment preceding
"a15memmap": it falls in the miscellaneous device I/O range 128MB..256MB,
and it is aligned at 64KB. The DTB properties follow the documentation in
the Linux source file "Documentation/devicetree/bindings/arm/fw-cfg.txt".
fw_cfg automatically exports a number of files to the guest; for example,
"bootorder" (see fw_cfg_machine_reset()).
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-9-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 578f3c7b083514b4fec0bf8fa0617934cdbdf826)
---
hw/arm/virt.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 314e55b..8af4aa0 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -68,6 +68,7 @@ enum {
VIRT_UART,
VIRT_MMIO,
VIRT_RTC,
+ VIRT_FW_CFG,
};
typedef struct MemMapEntry {
@@ -107,6 +108,7 @@ static const MemMapEntry a15memmap[] = {
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_UART] = { 0x09000000, 0x00001000 },
[VIRT_RTC] = { 0x09010000, 0x00001000 },
+ [VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
/* 0x10000000 .. 0x40000000 reserved for PCI */
@@ -519,6 +521,23 @@ static void create_flash(const VirtBoardInfo *vbi)
g_free(nodename);
}
+static void create_fw_cfg(const VirtBoardInfo *vbi)
+{
+ hwaddr base = vbi->memmap[VIRT_FW_CFG].base;
+ hwaddr size = vbi->memmap[VIRT_FW_CFG].size;
+ char *nodename;
+
+ fw_cfg_init_mem_wide(base + 8, base, 8);
+
+ nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
+ qemu_fdt_add_subnode(vbi->fdt, nodename);
+ qemu_fdt_setprop_string(vbi->fdt, nodename,
+ "compatible", "qemu,fw-cfg-mmio");
+ qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+ 2, base, 2, size);
+ g_free(nodename);
+}
+
static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
{
const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
@@ -604,6 +623,8 @@ static void machvirt_init(MachineState *machine)
*/
create_virtio_devices(vbi, pic);
+ create_fw_cfg(vbi);
+
vbi->bootinfo.ram_size = machine->ram_size;
vbi->bootinfo.kernel_filename = machine->kernel_filename;
vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;
--
2.1.0

View File

@ -0,0 +1,101 @@
From 29736faa92d5e4b4242786ee583ce339263d6adb Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:43 +0100
Subject: [PATCH 12/15] hw/loader: split out load_image_gzipped_buffer()
In the next patch we'd like to reuse the image decompression facility
without installing the output as a ROM at a specific guest-phys address.
In addition, expose LOAD_IMAGE_MAX_GUNZIP_BYTES, because that's a
straightforward "max_sz" argument for the new load_image_gzipped_buffer().
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-10-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 7d48a0f7217474899c5f5920b21f4cfdf4efa8d1)
---
hw/core/loader.c | 30 +++++++++++++++++++++---------
include/hw/loader.h | 9 +++++++++
2 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 7527fd3..f2b34da 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -614,14 +614,9 @@ int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
NULL, NULL);
}
-/* This simply prevents g_malloc in the function below from allocating
- * a huge amount of memory, by placing a limit on the maximum
- * uncompressed image size that load_image_gzipped will read.
- */
-#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
-
-/* Load a gzip-compressed kernel. */
-int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
+/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
+int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
+ uint8_t **buffer)
{
uint8_t *compressed_data = NULL;
uint8_t *data = NULL;
@@ -653,8 +648,11 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
goto out;
}
- rom_add_blob_fixed(filename, data, bytes, addr);
+ /* trim to actual size and return to caller */
+ *buffer = g_realloc(data, bytes);
ret = bytes;
+ /* ownership has been transferred to caller */
+ data = NULL;
out:
g_free(compressed_data);
@@ -662,6 +660,20 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
return ret;
}
+/* Load a gzip-compressed kernel. */
+int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
+{
+ int bytes;
+ uint8_t *data;
+
+ bytes = load_image_gzipped_buffer(filename, max_sz, &data);
+ if (bytes != -1) {
+ rom_add_blob_fixed(filename, data, bytes, addr);
+ g_free(data);
+ }
+ return bytes;
+}
+
/*
* Functions for reboot-persistent memory regions.
* - used for vga bios and option roms.
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 6481639..8997620 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -16,6 +16,15 @@ int load_image(const char *filename, uint8_t *addr); /* deprecated */
ssize_t load_image_size(const char *filename, void *addr, size_t size);
int load_image_targphys(const char *filename, hwaddr,
uint64_t max_sz);
+
+/* This is the limit on the maximum uncompressed image size that
+ * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
+ * g_malloc() in those functions from allocating a huge amount of memory.
+ */
+#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
+
+int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
+ uint8_t **buffer);
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_FAILED -1
--
2.1.0

View File

@ -0,0 +1,192 @@
From a4510adeb278b6781b16a5cc61cc5b7f00612130 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:44 +0100
Subject: [PATCH 13/15] hw/arm: pass pristine kernel image to guest firmware
over fw_cfg
Introduce the new boolean field "arm_boot_info.firmware_loaded". When this
field is set, it means that the portion of guest DRAM that the VCPU
normally starts to execute, or the pflash chip that the VCPU normally
starts to execute, has been populated by board-specific code with
full-fledged guest firmware code, before the board calls
arm_load_kernel().
Simultaneously, "arm_boot_info.firmware_loaded" guarantees that the board
code has set up the global firmware config instance, for arm_load_kernel()
to find with fw_cfg_find().
Guest kernel (-kernel) and guest firmware (-bios, -pflash) has always been
possible to specify independently on the command line. The following cases
should be considered:
nr -bios -pflash -kernel description
unit#0
-- ------- ------- ------- -------------------------------------------
1 present present absent Board code rejects this case, -bios and
present present present -pflash unit#0 are exclusive. Left intact
by this patch.
2 absent absent present Traditional kernel loading, with qemu's
minimal board firmware. Left intact by this
patch.
3 absent present absent Preexistent case for booting guest firmware
present absent absent loaded with -bios or -pflash. Left intact
by this patch.
4 absent absent absent Preexistent case for not loading any
firmware or kernel up-front. Left intact by
this patch.
5 present absent present New case introduced by this patch: kernel
absent present present image is passed to externally loaded
firmware in unmodified form, using fw_cfg.
An easy way to see that this patch doesn't interfere with existing cases
is to realize that "info->firmware_loaded" is constant zero at this point.
Which makes the "outer" condition unchanged, and the "inner" condition
(with the fw_cfg-related code) dead.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-11-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 07abe45c4814d42f3aca879d7932c5bc90d98bdf)
---
hw/arm/boot.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++---
include/hw/arm/arm.h | 5 +++
2 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index e6a3c5b..17bdaee 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -478,6 +478,55 @@ static void do_cpu_reset(void *opaque)
}
}
+/**
+ * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified
+ * by key.
+ * @fw_cfg: The firmware config instance to store the data in.
+ * @size_key: The firmware config key to store the size of the loaded
+ * data under, with fw_cfg_add_i32().
+ * @data_key: The firmware config key to store the loaded data under,
+ * with fw_cfg_add_bytes().
+ * @image_name: The name of the image file to load. If it is NULL, the
+ * function returns without doing anything.
+ * @try_decompress: Whether the image should be decompressed (gunzipped) before
+ * adding it to fw_cfg. If decompression fails, the image is
+ * loaded as-is.
+ *
+ * In case of failure, the function prints an error message to stderr and the
+ * process exits with status 1.
+ */
+static void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
+ uint16_t data_key, const char *image_name,
+ bool try_decompress)
+{
+ size_t size = -1;
+ uint8_t *data;
+
+ if (image_name == NULL) {
+ return;
+ }
+
+ if (try_decompress) {
+ size = load_image_gzipped_buffer(image_name,
+ LOAD_IMAGE_MAX_GUNZIP_BYTES, &data);
+ }
+
+ if (size == (size_t)-1) {
+ gchar *contents;
+ gsize length;
+
+ if (!g_file_get_contents(image_name, &contents, &length, NULL)) {
+ fprintf(stderr, "failed to load \"%s\"\n", image_name);
+ exit(1);
+ }
+ size = length;
+ data = (uint8_t *)contents;
+ }
+
+ fw_cfg_add_i32(fw_cfg, size_key, size);
+ fw_cfg_add_bytes(fw_cfg, data_key, data, size);
+}
+
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
{
CPUState *cs;
@@ -500,19 +549,48 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
}
/* Load the kernel. */
- if (!info->kernel_filename) {
+ if (!info->kernel_filename || info->firmware_loaded) {
if (have_dtb(info)) {
- /* If we have a device tree blob, but no kernel to supply it to,
- * copy it to the base of RAM for a bootloader to pick up.
+ /* If we have a device tree blob, but no kernel to supply it to (or
+ * the kernel is supposed to be loaded by the bootloader), copy the
+ * DTB to the base of RAM for the bootloader to pick up.
*/
if (load_dtb(info->loader_start, info, 0) < 0) {
exit(1);
}
}
- /* If no kernel specified, do nothing; we will start from address 0
- * (typically a boot ROM image) in the same way as hardware.
+ if (info->kernel_filename) {
+ FWCfgState *fw_cfg;
+ bool try_decompressing_kernel;
+
+ fw_cfg = fw_cfg_find();
+ try_decompressing_kernel = arm_feature(&cpu->env,
+ ARM_FEATURE_AARCH64);
+
+ /* Expose the kernel, the command line, and the initrd in fw_cfg.
+ * We don't process them here at all, it's all left to the
+ * firmware.
+ */
+ load_image_to_fw_cfg(fw_cfg,
+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
+ info->kernel_filename,
+ try_decompressing_kernel);
+ load_image_to_fw_cfg(fw_cfg,
+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
+ info->initrd_filename, false);
+
+ if (info->kernel_cmdline) {
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+ strlen(info->kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
+ info->kernel_cmdline);
+ }
+ }
+
+ /* We will start from address 0 (typically a boot ROM image) in the
+ * same way as hardware.
*/
return;
}
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index cefc9e6..dd69d66 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -66,6 +66,11 @@ struct arm_boot_info {
hwaddr initrd_start;
hwaddr initrd_size;
hwaddr entry;
+
+ /* Boot firmware has been loaded, typically at address 0, with -bios or
+ * -pflash. It also implies that fw_cfg_find() will succeed.
+ */
+ bool firmware_loaded;
};
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info);
--
2.1.0

View File

@ -0,0 +1,36 @@
From 6eaafa0eea15df4439488b535f4d53216e720857 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 22 Dec 2014 13:11:45 +0100
Subject: [PATCH 14/15] hw/arm/virt: enable passing of EFI-stubbed kernel to
guest UEFI firmware
The virt board already ensures mutual exclusion between -bios and -pflash
unit#0; we only need to set "bootinfo.firmware_loaded", introduced in the
previous patch, if either of those options was used to load the guest
firmware.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1419250305-31062-12-git-send-email-pbonzini@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit aa351061dbb0e3054db11c00a69395785c4186c8)
---
hw/arm/virt.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 8af4aa0..29fbdc1 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -633,6 +633,7 @@ static void machvirt_init(MachineState *machine)
vbi->bootinfo.board_id = -1;
vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
vbi->bootinfo.get_dtb = machvirt_dtb;
+ vbi->bootinfo.firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
}
--
2.1.0

View File

@ -0,0 +1,176 @@
From b627b2d476b3677e35d06bdc9fac26678fb92484 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Fri, 16 Jan 2015 11:54:30 +0000
Subject: [PATCH 15/15] fw_cfg: fix endianness in fw_cfg_data_mem_read() /
_write()
(1) Let's contemplate what device endianness means, for a memory mapped
device register (independently of QEMU -- that is, on physical hardware).
It determines the byte order that the device will put on the data bus when
the device is producing a *numerical value* for the CPU. This byte order
may differ from the CPU's own byte order, therefore when software wants to
consume the *numerical value*, it may have to swap the byte order first.
For example, suppose we have a device that exposes in a 2-byte register
the number of sheep we have to count before falling asleep. If the value
is decimal 37 (0x0025), then a big endian register will produce [0x00,
0x25], while a little endian register will produce [0x25, 0x00].
If the device register is big endian, but the CPU is little endian, the
numerical value will read as 0x2500 (decimal 9472), which software has to
byte swap before use.
However... if we ask the device about who stole our herd of sheep, and it
answers "XY", then the byte representation coming out of the register must
be [0x58, 0x59], regardless of the device register's endianness for
numeric values. And, software needs to copy these bytes into a string
field regardless of the CPU's own endianness.
(2) QEMU's device register accessor functions work with *numerical values*
exclusively, not strings:
The emulated register's read accessor function returns the numerical value
(eg. 37 decimal, 0x0025) as a *host-encoded* uint64_t. QEMU translates
this value for the guest to the endianness of the emulated device register
(which is recorded in MemoryRegionOps.endianness). Then guest code must
translate the numerical value from device register to guest CPU
endianness, before including it in any computation (see (1)).
(3) However, the data register of the fw_cfg device shall transfer strings
*only* -- that is, opaque blobs. Interpretation of any given blob is
subject to further agreement -- it can be an integer in an independently
determined byte order, or a genuine string, or an array of structs of
integers (in some byte order) and fixed size strings, and so on.
Because register emulation in QEMU is integer-preserving, not
string-preserving (see (2)), we have to jump through a few hoops.
(3a) We defined the memory mapped fw_cfg data register as
DEVICE_BIG_ENDIAN.
The particular choice is not really relevant -- we picked BE only for
consistency with the control register, which *does* transfer integers --
but our choice affects how we must host-encode values from fw_cfg strings.
(3b) Since we want the fw_cfg string "XY" to appear as the [0x58, 0x59]
array on the data register, *and* we picked DEVICE_BIG_ENDIAN, we must
compose the host (== C language) value 0x5859 in the read accessor
function.
(3c) When the guest performs the read access, the immediate uint16_t value
will be 0x5958 (in LE guests) and 0x5859 (in BE guests). However, the
uint16_t value does not matter. The only thing that matters is the byte
pattern [0x58, 0x59], which the guest code must copy into the target
string *without* any byte-swapping.
(4) Now I get to explain where I screwed up. :(
When we decided for big endian *integer* representation in the MMIO data
register -- see (3a) --, I mindlessly added an indiscriminate
byte-swizzling step to the (little endian) guest firmware.
This was a grave error -- it violates (3c) --, but I didn't realize it. I
only saw that the code I otherwise intended for fw_cfg_data_mem_read():
value = 0;
for (i = 0; i < size; ++i) {
value = (value << 8) | fw_cfg_read(s);
}
didn't produce the expected result in the guest.
In true facepalm style, instead of blaming my guest code (which violated
(3c)), I blamed my host code (which was correct). Ultimately, I coded
ldX_he_p() into fw_cfg_data_mem_read(), because that happened to work.
Obviously (...in retrospect) that was wrong. Only because my host happened
to be LE, ldX_he_p() composed the (otherwise incorrect) host value 0x5958
from the fw_cfg string "XY". And that happened to compensate for the bogus
indiscriminate byte-swizzling in my guest code.
Clearly the current code leaks the host endianness through to the guest,
which is wrong. Any device should work the same regardless of host
endianness.
The solution is to compose the host-endian representation (2) of the big
endian interpretation (3a, 3b) of the fw_cfg string, and to drop the wrong
byte-swizzling in the guest (3c).
Brown paper bag time for me.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-id: 1420024880-15416-1-git-send-email-lersek@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 36b62ae6a58f9a588fd33be9386e18a2b90103f5)
---
hw/nvram/fw_cfg.c | 41 +++++++----------------------------------
1 file changed, 7 insertions(+), 34 deletions(-)
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index fcdf821..78a37be 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -287,51 +287,24 @@ static uint64_t fw_cfg_data_mem_read(void *opaque, hwaddr addr,
unsigned size)
{
FWCfgState *s = opaque;
- uint8_t buf[8];
+ uint64_t value = 0;
unsigned i;
for (i = 0; i < size; ++i) {
- buf[i] = fw_cfg_read(s);
+ value = (value << 8) | fw_cfg_read(s);
}
- switch (size) {
- case 1:
- return buf[0];
- case 2:
- return lduw_he_p(buf);
- case 4:
- return (uint32_t)ldl_he_p(buf);
- case 8:
- return ldq_he_p(buf);
- }
- abort();
+ return value;
}
static void fw_cfg_data_mem_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
FWCfgState *s = opaque;
- uint8_t buf[8];
- unsigned i;
+ unsigned i = size;
- switch (size) {
- case 1:
- buf[0] = value;
- break;
- case 2:
- stw_he_p(buf, value);
- break;
- case 4:
- stl_he_p(buf, value);
- break;
- case 8:
- stq_he_p(buf, value);
- break;
- default:
- abort();
- }
- for (i = 0; i < size; ++i) {
- fw_cfg_write(s, buf[i]);
- }
+ do {
+ fw_cfg_write(s, value >> (8 * --i));
+ } while (i);
}
static bool fw_cfg_data_mem_valid(void *opaque, hwaddr addr,
--
2.1.0

View File

@ -153,7 +153,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 2.2.0
Release: 4%{?dist}
Release: 5%{?dist}
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
Group: Development/Tools
@ -193,7 +193,24 @@ Source12: bridge.conf
# qemu-kvm back compat wrapper
Source13: qemu-kvm.sh
Patch0001: 0001-libcacard-stop-linking-against-every-single-3rd-part.patch
Patch0000: 0001-libcacard-stop-linking-against-every-single-3rd-part.patch
# Add UEFI support for aarch64. Upstream in qemu > 2.2.0.
Patch0001: 0001-fw_cfg-remove-superfluous-blank-line.patch
Patch0002: 0002-hw-arm-boot-fix-uninitialized-scalar-variable-warnin.patch
Patch0003: 0003-Sort-include-qemu-typedefs.h.patch
Patch0004: 0004-fw_cfg-hard-separation-between-the-MMIO-and-I-O-port.patch
Patch0005: 0005-fw_cfg-move-boards-to-fw_cfg_init_io-fw_cfg_init_mem.patch
Patch0006: 0006-fw_cfg_mem-max-access-size-and-region-size-are-the-s.patch
Patch0007: 0007-fw_cfg_mem-flip-ctl_mem_ops-and-data_mem_ops-to-DEVI.patch
Patch0008: 0008-exec-allows-8-byte-accesses-in-subpage_ops.patch
Patch0009: 0009-fw_cfg_mem-introduce-the-data_width-property.patch
Patch0010: 0010-fw_cfg_mem-expose-the-data_width-property-with-fw_cf.patch
Patch0011: 0011-arm-add-fw_cfg-to-virt-board.patch
Patch0012: 0012-hw-loader-split-out-load_image_gzipped_buffer.patch
Patch0013: 0013-hw-arm-pass-pristine-kernel-image-to-guest-firmware-.patch
Patch0014: 0014-hw-arm-virt-enable-passing-of-EFI-stubbed-kernel-to-.patch
Patch0015: 0015-fw_cfg-fix-endianness-in-fw_cfg_data_mem_read-_write.patch
BuildRequires: SDL2-devel
BuildRequires: zlib-devel
@ -734,7 +751,22 @@ CAC emulation development files.
%prep
%setup -q -n qemu-2.2.0
%patch0000 -p1
%patch0001 -p1
%patch0002 -p1
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch0011 -p1
%patch0012 -p1
%patch0013 -p1
%patch0014 -p1
%patch0015 -p1
%build
%if %{with kvmonly}
@ -1504,6 +1536,9 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Wed Feb 4 2015 Richard W.M. Jones <rjones@redhat.com> - 2:2.2.0-5
- Add UEFI support for aarch64.
* Tue Feb 3 2015 Daniel P. Berrange <berrange@redhat.com> - 2:2.2.0-4
- Re-enable SPICE after previous build fixes circular dep