* [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
@ 2014-07-28 15:35 Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 2/3] migration: load smaller RAMBlock to a bigger one if permitted Michael S. Tsirkin
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Michael S. Tsirkin @ 2014-07-28 15:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alexey Kardashevskiy, Alexander Graf, Markus Armbruster,
Gerd Hoffmann, imammedo, pbonzini, Laszlo Ersek,
=?UTF-8?q?Andreas=20F=C3=A4rber?=
Support resizeable blobs: we allocate more memory than currently
available in the blob, which can later be filled in.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/hw/loader.h | 14 +++++++--
include/hw/nvram/fw_cfg.h | 2 +-
hw/core/loader.c | 15 +++++----
hw/nvram/fw_cfg.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 96 insertions(+), 14 deletions(-)
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 796cbf9..ecce654 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -55,9 +55,19 @@ extern bool rom_file_has_mr;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom);
-void *rom_add_blob(const char *name, const void *blob, size_t len,
+void *rom_add_blob_resizeable(const char *name, const void *blob,
+ size_t len, size_t max_len,
+ hwaddr addr, const char *fw_file_name,
+ FWCfgReadCallback fw_callback,
+ void *callback_opaque);
+static inline void *rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr, const char *fw_file_name,
- FWCfgReadCallback fw_callback, void *callback_opaque);
+ FWCfgReadCallback fw_callback, void *callback_opaque)
+{
+ return rom_add_blob_resizeable(name, blob, len, len, addr,
+ fw_file_name, fw_callback, callback_opaque);
+}
+
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr);
int rom_load_all(void);
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 72b1549..da4f5c5 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -75,7 +75,7 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
size_t len);
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
FWCfgReadCallback callback, void *callback_opaque,
- void *data, size_t len);
+ void *data, size_t len, size_t max_len);
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
hwaddr crl_addr, hwaddr data_addr);
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 2bf6b8f..ad6ec67 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -720,9 +720,11 @@ err:
return -1;
}
-void *rom_add_blob(const char *name, const void *blob, size_t len,
- hwaddr addr, const char *fw_file_name,
- FWCfgReadCallback fw_callback, void *callback_opaque)
+void *rom_add_blob_resizeable(const char *name, const void *blob,
+ size_t len, size_t max_len,
+ hwaddr addr, const char *fw_file_name,
+ FWCfgReadCallback fw_callback,
+ void *callback_opaque)
{
Rom *rom;
void *data = NULL;
@@ -730,9 +732,10 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(name);
rom->addr = addr;
- rom->romsize = len;
- rom->datasize = len;
+ rom->romsize = max_len;
+ rom->datasize = max_len;
rom->data = g_malloc0(rom->datasize);
+ assert(len <= rom->datasize);
memcpy(rom->data, blob, len);
rom_insert(rom);
if (fw_file_name && fw_cfg) {
@@ -748,7 +751,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
fw_cfg_add_file_callback(fw_cfg, fw_file_name,
fw_callback, callback_opaque,
- data, rom->romsize);
+ data, rom->romsize, rom->datasize);
}
return data;
}
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index b71d251..65f233e 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -38,6 +38,8 @@
#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
typedef struct FWCfgEntry {
+ uint32_t max_len;
+ uint32_t reset_len;
uint32_t len;
uint8_t *data;
void *callback_opaque;
@@ -57,6 +59,9 @@ struct FWCfgState {
uint16_t cur_entry;
uint32_t cur_offset;
Notifier machine_ready;
+ /* Entry length: used for migration */
+#define FW_CFG_LEN_ENTRIES (2 * FW_CFG_MAX_ENTRY)
+ uint32_t len[FW_CFG_LEN_ENTRIES];
};
#define JPG_FILE 0
@@ -336,6 +341,13 @@ static const MemoryRegionOps fw_cfg_comb_mem_ops = {
static void fw_cfg_reset(DeviceState *d)
{
FWCfgState *s = FW_CFG(d);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ s->entries[i][j].len = s->entries[i][j].reset_len;
+ }
+ }
fw_cfg_select(s, 0);
}
@@ -373,14 +385,63 @@ static bool is_version_1(void *opaque, int version_id)
return version_id == 1;
}
+static void fw_cfg_pre_save(void *opaque)
+{
+ FWCfgState *s = FW_CFG(opaque);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ s->len[i * j] = s->entries[i][j].len;
+ }
+ }
+}
+
+static int fw_cfg_post_load(void *opaque, int version_id)
+{
+ FWCfgState *s = FW_CFG(opaque);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ if (s->entries[i][j].max_len < s->len[i * j]) {
+ return -1;
+ }
+ s->entries[i][j].len = s->len[i * j];
+ }
+ }
+ return 0;
+}
+
+static bool fw_cfg_len_needed(void *opaque, int version_id)
+{
+ FWCfgState *s = FW_CFG(opaque);
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
+ for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
+ if (s->entries[i][j].len != s->entries[i][j].max_len) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
static const VMStateDescription vmstate_fw_cfg = {
.name = "fw_cfg",
.version_id = 2,
.minimum_version_id = 1,
+ .post_load = fw_cfg_post_load,
+ .pre_save = fw_cfg_pre_save,
.fields = (VMStateField[]) {
VMSTATE_UINT16(cur_entry, FWCfgState),
VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
+ VMSTATE_ARRAY_TEST(len, FWCfgState, FW_CFG_LEN_ENTRIES,
+ fw_cfg_len_needed,
+ vmstate_info_uint32, uint32_t),
VMSTATE_END_OF_LIST()
}
};
@@ -388,23 +449,28 @@ static const VMStateDescription vmstate_fw_cfg = {
static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
FWCfgReadCallback callback,
void *callback_opaque,
- void *data, size_t len)
+ void *data, size_t len,
+ size_t max_len)
{
int arch = !!(key & FW_CFG_ARCH_LOCAL);
+ assert(len <= max_len);
+
key &= FW_CFG_ENTRY_MASK;
assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
s->entries[arch][key].data = data;
s->entries[arch][key].len = (uint32_t)len;
+ s->entries[arch][key].reset_len = (uint32_t)len;
+ s->entries[arch][key].max_len = (uint32_t)max_len;
s->entries[arch][key].read_callback = callback;
s->entries[arch][key].callback_opaque = callback_opaque;
}
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
{
- fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
+ fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len, len);
}
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
@@ -454,13 +520,15 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
s->entries[arch][key].data = data;
s->entries[arch][key].len = (uint32_t)len;
+ s->entries[arch][key].reset_len = (uint32_t)len;
+ s->entries[arch][key].max_len = (uint32_t)len;
s->entries[arch][key].callback_opaque = callback_opaque;
s->entries[arch][key].callback = callback;
}
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
FWCfgReadCallback callback, void *callback_opaque,
- void *data, size_t len)
+ void *data, size_t len, size_t max_len)
{
int i, index;
size_t dsize;
@@ -475,7 +543,8 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
assert(index < FW_CFG_FILE_SLOTS);
fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
- callback, callback_opaque, data, len);
+ callback, callback_opaque, data, len,
+ max_len);
pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
filename);
@@ -496,7 +565,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
void fw_cfg_add_file(FWCfgState *s, const char *filename,
void *data, size_t len)
{
- fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
+ fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len, len);
}
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
--
MST
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/3] migration: load smaller RAMBlock to a bigger one if permitted
2014-07-28 15:35 [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Michael S. Tsirkin
@ 2014-07-28 15:35 ` Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 3/3] loader: mark MR for resizeable blobs as extendable Michael S. Tsirkin
2014-07-28 16:52 ` [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Dr. David Alan Gilbert
2 siblings, 0 replies; 7+ messages in thread
From: Michael S. Tsirkin @ 2014-07-28 15:35 UTC (permalink / raw)
To: qemu-devel
Cc: Juan Quintela, Alexey Kardashevskiy, Alexander Graf,
Markus Armbruster, Orit Wasserman, Gonglei, Gerd Hoffmann,
imammedo, pbonzini, Laszlo Ersek,
=?UTF-8?q?Andreas=20F=C3=A4rber?=,
Dr. David Alan Gilbert
From: Igor Mammedov <imammedo@redhat.com>
Add API to mark memory region as extend-able on migration,
to allow migration code to load smaller RAMBlock into
a bigger one on destination QEMU instance.
This will allow to fix broken migration from QEMU 1.7/2.0 to
QEMU 2.1 due to ACPI tables size changes across 1.7/2.0/2.1
versions by marking ACPI tables ROM blob as extend-able.
So that smaller tables from previous version could be always
migrated to a bigger rom blob on new version.
Credits-for-idea: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/exec/memory.h | 11 +++++++++++
include/exec/ram_addr.h | 3 +++
arch_init.c | 22 +++++++++++++++++-----
exec.c | 8 ++++++++
memory.c | 5 +++++
5 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index e2c8e3e..f96ddbb 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -894,6 +894,17 @@ bool memory_region_present(MemoryRegion *container, hwaddr addr);
bool memory_region_is_mapped(MemoryRegion *mr);
/**
+ * memory_region_permit_extendable_migration: marks #MemoryRegion
+ * as extendable on migration, allowing the migration code to load
+ * source memory block of smaller size than destination memory block
+ * at migration time
+ *
+ * @mr: a #MemoryRegion whose #RAMBlock should be marked as
+ * extendable on migration
+ */
+void memory_region_permit_extendable_migration(MemoryRegion *mr);
+
+/**
* memory_region_find: translate an address/size relative to a
* MemoryRegion into a #MemoryRegionSection.
*
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 6593be1..7a6b782 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -34,6 +34,9 @@ void *qemu_get_ram_ptr(ram_addr_t addr);
void qemu_ram_free(ram_addr_t addr);
void qemu_ram_free_from_ptr(ram_addr_t addr);
+#define RAM_EXTENDABLE_ON_MIGRATE (1U << 31)
+void qemu_ram_set_extendable_on_migration(ram_addr_t addr);
+
static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
ram_addr_t length,
unsigned client)
diff --git a/arch_init.c b/arch_init.c
index 8ddaf35..2c0c238 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1071,11 +1071,23 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id))) {
- if (block->length != length) {
- error_report("Length mismatch: %s: " RAM_ADDR_FMT
- " in != " RAM_ADDR_FMT, id, length,
- block->length);
- ret = -EINVAL;
+ if (block->flags & RAM_EXTENDABLE_ON_MIGRATE) {
+ if (block->length < length) {
+ error_report("Length too big: %s: " RAM_ADDR_FMT
+ " in > " RAM_ADDR_FMT, id, length,
+ block->length);
+ ret = -EINVAL;
+ } else {
+ memset(block->host, 0, block->length);
+ }
+ } else {
+ if (block->length != length) {
+ error_report("Length mismatch: %s: "
+ RAM_ADDR_FMT " in != "
+ RAM_ADDR_FMT,
+ id, length, block->length);
+ ret = -EINVAL;
+ }
}
break;
}
diff --git a/exec.c b/exec.c
index 765bd94..02536f8e 100644
--- a/exec.c
+++ b/exec.c
@@ -1214,6 +1214,14 @@ void qemu_ram_unset_idstr(ram_addr_t addr)
}
}
+void qemu_ram_set_extendable_on_migration(ram_addr_t addr)
+{
+ RAMBlock *block = find_ram_block(addr);
+
+ assert(block != NULL);
+ block->flags |= RAM_EXTENDABLE_ON_MIGRATE;
+}
+
static int memory_try_enable_merging(void *addr, size_t len)
{
if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
diff --git a/memory.c b/memory.c
index 64d7176..744c746 100644
--- a/memory.c
+++ b/memory.c
@@ -1791,6 +1791,11 @@ bool memory_region_is_mapped(MemoryRegion *mr)
return mr->container ? true : false;
}
+void memory_region_permit_extendable_migration(MemoryRegion *mr)
+{
+ qemu_ram_set_extendable_on_migration(mr->ram_addr);
+}
+
MemoryRegionSection memory_region_find(MemoryRegion *mr,
hwaddr addr, uint64_t size)
{
--
MST
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 3/3] loader: mark MR for resizeable blobs as extendable
2014-07-28 15:35 [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 2/3] migration: load smaller RAMBlock to a bigger one if permitted Michael S. Tsirkin
@ 2014-07-28 15:35 ` Michael S. Tsirkin
2014-07-28 16:52 ` [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Dr. David Alan Gilbert
2 siblings, 0 replies; 7+ messages in thread
From: Michael S. Tsirkin @ 2014-07-28 15:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alexey Kardashevskiy, Alexander Graf, Markus Armbruster,
Gerd Hoffmann, imammedo, pbonzini, Laszlo Ersek,
=?UTF-8?q?Andreas=20F=C3=A4rber?=
This makes migration from older QEMU versions
more robust.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
hw/core/loader.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hw/core/loader.c b/hw/core/loader.c
index ad6ec67..fc00a87 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -745,6 +745,13 @@ void *rom_add_blob_resizeable(const char *name, const void *blob,
if (rom_file_has_mr) {
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
+ /* If there's padding at tail, blob is resizeable.
+ * Set flag to allow migration from older QEMU versions
+ * where this region could have been smaller.
+ */
+ if (max_len != len) {
+ memory_region_permit_extendable_migration(rom->mr);
+ }
} else {
data = rom->data;
}
--
MST
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
2014-07-28 15:35 [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 2/3] migration: load smaller RAMBlock to a bigger one if permitted Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 3/3] loader: mark MR for resizeable blobs as extendable Michael S. Tsirkin
@ 2014-07-28 16:52 ` Dr. David Alan Gilbert
2014-07-28 19:07 ` Michael S. Tsirkin
2 siblings, 1 reply; 7+ messages in thread
From: Dr. David Alan Gilbert @ 2014-07-28 16:52 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Alexander Graf, quintela, Alexey Kardashevskiy,
Markus Armbruster, qemu-devel, Gerd Hoffmann, pbonzini, imammedo,
Laszlo Ersek, =?UTF-8?q?Andreas=20F=C3=A4rber?=
* Michael S. Tsirkin (mst@redhat.com) wrote:
> Support resizeable blobs: we allocate more memory than currently
> available in the blob, which can later be filled in.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> include/hw/loader.h | 14 +++++++--
> include/hw/nvram/fw_cfg.h | 2 +-
> hw/core/loader.c | 15 +++++----
> hw/nvram/fw_cfg.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---
> 4 files changed, 96 insertions(+), 14 deletions(-)
>
> +static bool fw_cfg_len_needed(void *opaque, int version_id)
> +{
> + FWCfgState *s = FW_CFG(opaque);
> + int i, j;
> +
> + for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
> + for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
> + if (s->entries[i][j].len != s->entries[i][j].max_len) {
> + return true;
> + }
> + }
> + }
> +
> + return false;
> +}
This feels a bit delicate; it means that increasing the 'max_len' changes
the expected migration stream, which seems odd for a parameter whose
job is to make things easier to migrate.
Dave
> +
> static const VMStateDescription vmstate_fw_cfg = {
> .name = "fw_cfg",
> .version_id = 2,
> .minimum_version_id = 1,
> + .post_load = fw_cfg_post_load,
> + .pre_save = fw_cfg_pre_save,
> .fields = (VMStateField[]) {
> VMSTATE_UINT16(cur_entry, FWCfgState),
> VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
> VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
> + VMSTATE_ARRAY_TEST(len, FWCfgState, FW_CFG_LEN_ENTRIES,
> + fw_cfg_len_needed,
> + vmstate_info_uint32, uint32_t),
> VMSTATE_END_OF_LIST()
> }
> };
> @@ -388,23 +449,28 @@ static const VMStateDescription vmstate_fw_cfg = {
> static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
> FWCfgReadCallback callback,
> void *callback_opaque,
> - void *data, size_t len)
> + void *data, size_t len,
> + size_t max_len)
> {
> int arch = !!(key & FW_CFG_ARCH_LOCAL);
>
> + assert(len <= max_len);
> +
> key &= FW_CFG_ENTRY_MASK;
>
> assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
>
> s->entries[arch][key].data = data;
> s->entries[arch][key].len = (uint32_t)len;
> + s->entries[arch][key].reset_len = (uint32_t)len;
> + s->entries[arch][key].max_len = (uint32_t)max_len;
> s->entries[arch][key].read_callback = callback;
> s->entries[arch][key].callback_opaque = callback_opaque;
> }
>
> void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
> {
> - fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
> + fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len, len);
> }
>
> void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
> @@ -454,13 +520,15 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
>
> s->entries[arch][key].data = data;
> s->entries[arch][key].len = (uint32_t)len;
> + s->entries[arch][key].reset_len = (uint32_t)len;
> + s->entries[arch][key].max_len = (uint32_t)len;
> s->entries[arch][key].callback_opaque = callback_opaque;
> s->entries[arch][key].callback = callback;
> }
>
> void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> FWCfgReadCallback callback, void *callback_opaque,
> - void *data, size_t len)
> + void *data, size_t len, size_t max_len)
> {
> int i, index;
> size_t dsize;
> @@ -475,7 +543,8 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> assert(index < FW_CFG_FILE_SLOTS);
>
> fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
> - callback, callback_opaque, data, len);
> + callback, callback_opaque, data, len,
> + max_len);
>
> pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
> filename);
> @@ -496,7 +565,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> void fw_cfg_add_file(FWCfgState *s, const char *filename,
> void *data, size_t len)
> {
> - fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
> + fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len, len);
> }
>
> static void fw_cfg_machine_ready(struct Notifier *n, void *data)
> --
> MST
>
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
2014-07-28 16:52 ` [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Dr. David Alan Gilbert
@ 2014-07-28 19:07 ` Michael S. Tsirkin
2014-07-28 19:20 ` Paolo Bonzini
2014-07-29 8:02 ` Dr. David Alan Gilbert
0 siblings, 2 replies; 7+ messages in thread
From: Michael S. Tsirkin @ 2014-07-28 19:07 UTC (permalink / raw)
To: Dr. David Alan Gilbert
Cc: Alexander Graf, quintela, Alexey Kardashevskiy,
Markus Armbruster, qemu-devel, Gerd Hoffmann, pbonzini, imammedo,
Laszlo Ersek, =?UTF-8?q?Andreas=20F=C3=A4rber?=
On Mon, Jul 28, 2014 at 05:52:27PM +0100, Dr. David Alan Gilbert wrote:
> * Michael S. Tsirkin (mst@redhat.com) wrote:
> > Support resizeable blobs: we allocate more memory than currently
> > available in the blob, which can later be filled in.
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> > include/hw/loader.h | 14 +++++++--
> > include/hw/nvram/fw_cfg.h | 2 +-
> > hw/core/loader.c | 15 +++++----
> > hw/nvram/fw_cfg.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---
> > 4 files changed, 96 insertions(+), 14 deletions(-)
> >
>
>
> > +static bool fw_cfg_len_needed(void *opaque, int version_id)
> > +{
> > + FWCfgState *s = FW_CFG(opaque);
> > + int i, j;
> > +
> > + for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
> > + for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
> > + if (s->entries[i][j].len != s->entries[i][j].max_len) {
> > + return true;
> > + }
> > + }
> > + }
> > +
> > + return false;
> > +}
>
> This feels a bit delicate; it means that increasing the 'max_len' changes
> the expected migration stream, which seems odd for a parameter whose
> job is to make things easier to migrate.
>
> Dave
It's an API issue - so you are more comfortable with
an explicit flag?
> > +
> > static const VMStateDescription vmstate_fw_cfg = {
> > .name = "fw_cfg",
> > .version_id = 2,
> > .minimum_version_id = 1,
> > + .post_load = fw_cfg_post_load,
> > + .pre_save = fw_cfg_pre_save,
> > .fields = (VMStateField[]) {
> > VMSTATE_UINT16(cur_entry, FWCfgState),
> > VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
> > VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
> > + VMSTATE_ARRAY_TEST(len, FWCfgState, FW_CFG_LEN_ENTRIES,
> > + fw_cfg_len_needed,
> > + vmstate_info_uint32, uint32_t),
> > VMSTATE_END_OF_LIST()
> > }
> > };
> > @@ -388,23 +449,28 @@ static const VMStateDescription vmstate_fw_cfg = {
> > static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
> > FWCfgReadCallback callback,
> > void *callback_opaque,
> > - void *data, size_t len)
> > + void *data, size_t len,
> > + size_t max_len)
> > {
> > int arch = !!(key & FW_CFG_ARCH_LOCAL);
> >
> > + assert(len <= max_len);
> > +
> > key &= FW_CFG_ENTRY_MASK;
> >
> > assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
> >
> > s->entries[arch][key].data = data;
> > s->entries[arch][key].len = (uint32_t)len;
> > + s->entries[arch][key].reset_len = (uint32_t)len;
> > + s->entries[arch][key].max_len = (uint32_t)max_len;
> > s->entries[arch][key].read_callback = callback;
> > s->entries[arch][key].callback_opaque = callback_opaque;
> > }
> >
> > void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
> > {
> > - fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
> > + fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len, len);
> > }
> >
> > void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
> > @@ -454,13 +520,15 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
> >
> > s->entries[arch][key].data = data;
> > s->entries[arch][key].len = (uint32_t)len;
> > + s->entries[arch][key].reset_len = (uint32_t)len;
> > + s->entries[arch][key].max_len = (uint32_t)len;
> > s->entries[arch][key].callback_opaque = callback_opaque;
> > s->entries[arch][key].callback = callback;
> > }
> >
> > void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> > FWCfgReadCallback callback, void *callback_opaque,
> > - void *data, size_t len)
> > + void *data, size_t len, size_t max_len)
> > {
> > int i, index;
> > size_t dsize;
> > @@ -475,7 +543,8 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> > assert(index < FW_CFG_FILE_SLOTS);
> >
> > fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
> > - callback, callback_opaque, data, len);
> > + callback, callback_opaque, data, len,
> > + max_len);
> >
> > pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
> > filename);
> > @@ -496,7 +565,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> > void fw_cfg_add_file(FWCfgState *s, const char *filename,
> > void *data, size_t len)
> > {
> > - fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
> > + fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len, len);
> > }
> >
> > static void fw_cfg_machine_ready(struct Notifier *n, void *data)
> > --
> > MST
> >
> >
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
2014-07-28 19:07 ` Michael S. Tsirkin
@ 2014-07-28 19:20 ` Paolo Bonzini
2014-07-29 8:02 ` Dr. David Alan Gilbert
1 sibling, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2014-07-28 19:20 UTC (permalink / raw)
To: Michael S. Tsirkin, Dr. David Alan Gilbert
Cc: Alexander Graf, quintela, Alexey Kardashevskiy,
Markus Armbruster, qemu-devel, Gerd Hoffmann, imammedo,
Laszlo Ersek, Andreas Färber
Il 28/07/2014 21:07, Michael S. Tsirkin ha scritto:
> On Mon, Jul 28, 2014 at 05:52:27PM +0100, Dr. David Alan Gilbert wrote:
>> * Michael S. Tsirkin (mst@redhat.com) wrote:
>>> Support resizeable blobs: we allocate more memory than currently
>>> available in the blob, which can later be filled in.
>>>
>>> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>>> ---
>>> include/hw/loader.h | 14 +++++++--
>>> include/hw/nvram/fw_cfg.h | 2 +-
>>> hw/core/loader.c | 15 +++++----
>>> hw/nvram/fw_cfg.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---
>>> 4 files changed, 96 insertions(+), 14 deletions(-)
>>>
>>
>>
>>> +static bool fw_cfg_len_needed(void *opaque, int version_id)
>>> +{
>>> + FWCfgState *s = FW_CFG(opaque);
>>> + int i, j;
>>> +
>>> + for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
>>> + for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
>>> + if (s->entries[i][j].len != s->entries[i][j].max_len) {
>>> + return true;
>>> + }
>>> + }
>>> + }
>>> +
>>> + return false;
>>> +}
>>
>> This feels a bit delicate; it means that increasing the 'max_len' changes
>> the expected migration stream, which seems odd for a parameter whose
>> job is to make things easier to migrate.
>>
>> Dave
>
> It's an API issue - so you are more comfortable with
> an explicit flag?
Yeah, that would help but I think these patches are too much for 2.1.
Paolo
>>> +
>>> static const VMStateDescription vmstate_fw_cfg = {
>>> .name = "fw_cfg",
>>> .version_id = 2,
>>> .minimum_version_id = 1,
>>> + .post_load = fw_cfg_post_load,
>>> + .pre_save = fw_cfg_pre_save,
>>> .fields = (VMStateField[]) {
>>> VMSTATE_UINT16(cur_entry, FWCfgState),
>>> VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
>>> VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
>>> + VMSTATE_ARRAY_TEST(len, FWCfgState, FW_CFG_LEN_ENTRIES,
>>> + fw_cfg_len_needed,
>>> + vmstate_info_uint32, uint32_t),
>>> VMSTATE_END_OF_LIST()
>>> }
>>> };
>>> @@ -388,23 +449,28 @@ static const VMStateDescription vmstate_fw_cfg = {
>>> static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
>>> FWCfgReadCallback callback,
>>> void *callback_opaque,
>>> - void *data, size_t len)
>>> + void *data, size_t len,
>>> + size_t max_len)
>>> {
>>> int arch = !!(key & FW_CFG_ARCH_LOCAL);
>>>
>>> + assert(len <= max_len);
>>> +
>>> key &= FW_CFG_ENTRY_MASK;
>>>
>>> assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
>>>
>>> s->entries[arch][key].data = data;
>>> s->entries[arch][key].len = (uint32_t)len;
>>> + s->entries[arch][key].reset_len = (uint32_t)len;
>>> + s->entries[arch][key].max_len = (uint32_t)max_len;
>>> s->entries[arch][key].read_callback = callback;
>>> s->entries[arch][key].callback_opaque = callback_opaque;
>>> }
>>>
>>> void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
>>> {
>>> - fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
>>> + fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len, len);
>>> }
>>>
>>> void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
>>> @@ -454,13 +520,15 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
>>>
>>> s->entries[arch][key].data = data;
>>> s->entries[arch][key].len = (uint32_t)len;
>>> + s->entries[arch][key].reset_len = (uint32_t)len;
>>> + s->entries[arch][key].max_len = (uint32_t)len;
>>> s->entries[arch][key].callback_opaque = callback_opaque;
>>> s->entries[arch][key].callback = callback;
>>> }
>>>
>>> void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
>>> FWCfgReadCallback callback, void *callback_opaque,
>>> - void *data, size_t len)
>>> + void *data, size_t len, size_t max_len)
>>> {
>>> int i, index;
>>> size_t dsize;
>>> @@ -475,7 +543,8 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
>>> assert(index < FW_CFG_FILE_SLOTS);
>>>
>>> fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
>>> - callback, callback_opaque, data, len);
>>> + callback, callback_opaque, data, len,
>>> + max_len);
>>>
>>> pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
>>> filename);
>>> @@ -496,7 +565,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
>>> void fw_cfg_add_file(FWCfgState *s, const char *filename,
>>> void *data, size_t len)
>>> {
>>> - fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
>>> + fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len, len);
>>> }
>>>
>>> static void fw_cfg_machine_ready(struct Notifier *n, void *data)
>>> --
>>> MST
>>>
>>>
>> --
>> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs
2014-07-28 19:07 ` Michael S. Tsirkin
2014-07-28 19:20 ` Paolo Bonzini
@ 2014-07-29 8:02 ` Dr. David Alan Gilbert
1 sibling, 0 replies; 7+ messages in thread
From: Dr. David Alan Gilbert @ 2014-07-29 8:02 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Alexander Graf, quintela, Alexey Kardashevskiy,
Markus Armbruster, qemu-devel, Gerd Hoffmann, pbonzini, imammedo,
Laszlo Ersek, =?UTF-8?q?Andreas=20F=C3=A4rber?=
* Michael S. Tsirkin (mst@redhat.com) wrote:
> On Mon, Jul 28, 2014 at 05:52:27PM +0100, Dr. David Alan Gilbert wrote:
> > * Michael S. Tsirkin (mst@redhat.com) wrote:
> > > Support resizeable blobs: we allocate more memory than currently
> > > available in the blob, which can later be filled in.
> > >
> > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > ---
> > > include/hw/loader.h | 14 +++++++--
> > > include/hw/nvram/fw_cfg.h | 2 +-
> > > hw/core/loader.c | 15 +++++----
> > > hw/nvram/fw_cfg.c | 79 ++++++++++++++++++++++++++++++++++++++++++++---
> > > 4 files changed, 96 insertions(+), 14 deletions(-)
> > >
> >
> >
> > > +static bool fw_cfg_len_needed(void *opaque, int version_id)
> > > +{
> > > + FWCfgState *s = FW_CFG(opaque);
> > > + int i, j;
> > > +
> > > + for (i = 0; i < ARRAY_SIZE(s->entries); ++i) {
> > > + for (j = 0; j < ARRAY_SIZE(s->entries[0]); ++j) {
> > > + if (s->entries[i][j].len != s->entries[i][j].max_len) {
> > > + return true;
> > > + }
> > > + }
> > > + }
> > > +
> > > + return false;
> > > +}
> >
> > This feels a bit delicate; it means that increasing the 'max_len' changes
> > the expected migration stream, which seems odd for a parameter whose
> > job is to make things easier to migrate.
> >
> > Dave
>
> It's an API issue - so you are more comfortable with
> an explicit flag?
Yes, if it was something that was just switched on with new machine types
I wouldn't worry as much.
Dave
>
> > > +
> > > static const VMStateDescription vmstate_fw_cfg = {
> > > .name = "fw_cfg",
> > > .version_id = 2,
> > > .minimum_version_id = 1,
> > > + .post_load = fw_cfg_post_load,
> > > + .pre_save = fw_cfg_pre_save,
> > > .fields = (VMStateField[]) {
> > > VMSTATE_UINT16(cur_entry, FWCfgState),
> > > VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
> > > VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
> > > + VMSTATE_ARRAY_TEST(len, FWCfgState, FW_CFG_LEN_ENTRIES,
> > > + fw_cfg_len_needed,
> > > + vmstate_info_uint32, uint32_t),
> > > VMSTATE_END_OF_LIST()
> > > }
> > > };
> > > @@ -388,23 +449,28 @@ static const VMStateDescription vmstate_fw_cfg = {
> > > static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
> > > FWCfgReadCallback callback,
> > > void *callback_opaque,
> > > - void *data, size_t len)
> > > + void *data, size_t len,
> > > + size_t max_len)
> > > {
> > > int arch = !!(key & FW_CFG_ARCH_LOCAL);
> > >
> > > + assert(len <= max_len);
> > > +
> > > key &= FW_CFG_ENTRY_MASK;
> > >
> > > assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
> > >
> > > s->entries[arch][key].data = data;
> > > s->entries[arch][key].len = (uint32_t)len;
> > > + s->entries[arch][key].reset_len = (uint32_t)len;
> > > + s->entries[arch][key].max_len = (uint32_t)max_len;
> > > s->entries[arch][key].read_callback = callback;
> > > s->entries[arch][key].callback_opaque = callback_opaque;
> > > }
> > >
> > > void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
> > > {
> > > - fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
> > > + fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len, len);
> > > }
> > >
> > > void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
> > > @@ -454,13 +520,15 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
> > >
> > > s->entries[arch][key].data = data;
> > > s->entries[arch][key].len = (uint32_t)len;
> > > + s->entries[arch][key].reset_len = (uint32_t)len;
> > > + s->entries[arch][key].max_len = (uint32_t)len;
> > > s->entries[arch][key].callback_opaque = callback_opaque;
> > > s->entries[arch][key].callback = callback;
> > > }
> > >
> > > void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> > > FWCfgReadCallback callback, void *callback_opaque,
> > > - void *data, size_t len)
> > > + void *data, size_t len, size_t max_len)
> > > {
> > > int i, index;
> > > size_t dsize;
> > > @@ -475,7 +543,8 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> > > assert(index < FW_CFG_FILE_SLOTS);
> > >
> > > fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
> > > - callback, callback_opaque, data, len);
> > > + callback, callback_opaque, data, len,
> > > + max_len);
> > >
> > > pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
> > > filename);
> > > @@ -496,7 +565,7 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
> > > void fw_cfg_add_file(FWCfgState *s, const char *filename,
> > > void *data, size_t len)
> > > {
> > > - fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
> > > + fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len, len);
> > > }
> > >
> > > static void fw_cfg_machine_ready(struct Notifier *n, void *data)
> > > --
> > > MST
> > >
> > >
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-07-29 8:02 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-28 15:35 [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 2/3] migration: load smaller RAMBlock to a bigger one if permitted Michael S. Tsirkin
2014-07-28 15:35 ` [Qemu-devel] [PATCH 3/3] loader: mark MR for resizeable blobs as extendable Michael S. Tsirkin
2014-07-28 16:52 ` [Qemu-devel] [PATCH 1/3] loader: add support for resizeable blobs Dr. David Alan Gilbert
2014-07-28 19:07 ` Michael S. Tsirkin
2014-07-28 19:20 ` Paolo Bonzini
2014-07-29 8:02 ` Dr. David Alan Gilbert
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.