All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.