Commit fff31599 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190726' into staging



target-arm queue:
 * Fix broken migration on pl330 device
 * Fix broken migration on stellaris-input device
 * Add type checks to vmstate varry macros to avoid this class of bugs
 * hw/arm/boot: Fix some remaining cases where we would put the
   initrd on top of the kernel image

# gpg: Signature made Fri 26 Jul 2019 16:19:17 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20190726:
  hw/arm/boot: Further improve initrd positioning code
  hw/arm/boot: Rename elf_{low, high}_addr to image_{low, high}_addr
  vmstate.h: Type check VMSTATE_STRUCT_VARRAY macros
  stellaris_input: Fix vmstate description of buttons field
  pl330: fix vmstate description

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents c985266e 67505c11
Loading
Loading
Loading
Loading
+27 −10
Original line number Diff line number Diff line
@@ -986,7 +986,9 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
    int kernel_size;
    int initrd_size;
    int is_linux = 0;
    uint64_t elf_entry, elf_low_addr, elf_high_addr;
    uint64_t elf_entry;
    /* Addresses of first byte used and first byte not used by the image */
    uint64_t image_low_addr = 0, image_high_addr = 0;
    int elf_machine;
    hwaddr entry;
    static const ARMInsnFixup *primary_loader;
@@ -1014,24 +1016,24 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
        info->nb_cpus = 1;

    /* Assume that raw images are linux kernels, and ELF images are not.  */
    kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
                               &elf_high_addr, elf_machine, as);
    kernel_size = arm_load_elf(info, &elf_entry, &image_low_addr,
                               &image_high_addr, elf_machine, as);
    if (kernel_size > 0 && have_dtb(info)) {
        /*
         * If there is still some room left at the base of RAM, try and put
         * the DTB there like we do for images loaded with -bios or -pflash.
         */
        if (elf_low_addr > info->loader_start
            || elf_high_addr < info->loader_start) {
        if (image_low_addr > info->loader_start
            || image_high_addr < info->loader_start) {
            /*
             * Set elf_low_addr as address limit for arm_load_dtb if it may be
             * Set image_low_addr as address limit for arm_load_dtb if it may be
             * pointing into RAM, otherwise pass '0' (no limit)
             */
            if (elf_low_addr < info->loader_start) {
                elf_low_addr = 0;
            if (image_low_addr < info->loader_start) {
                image_low_addr = 0;
            }
            info->dtb_start = info->loader_start;
            info->dtb_limit = elf_low_addr;
            info->dtb_limit = image_low_addr;
        }
    }
    entry = elf_entry;
@@ -1039,17 +1041,29 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
        uint64_t loadaddr = info->loader_start + KERNEL_NOLOAD_ADDR;
        kernel_size = load_uimage_as(info->kernel_filename, &entry, &loadaddr,
                                     &is_linux, NULL, NULL, as);
        if (kernel_size >= 0) {
            image_low_addr = loadaddr;
            image_high_addr = image_low_addr + kernel_size;
        }
    }
    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
        kernel_size = load_aarch64_image(info->kernel_filename,
                                         info->loader_start, &entry, as);
        is_linux = 1;
        if (kernel_size >= 0) {
            image_low_addr = entry;
            image_high_addr = image_low_addr + kernel_size;
        }
    } else if (kernel_size < 0) {
        /* 32-bit ARM */
        entry = info->loader_start + KERNEL_LOAD_ADDR;
        kernel_size = load_image_targphys_as(info->kernel_filename, entry,
                                             ram_end - KERNEL_LOAD_ADDR, as);
        is_linux = 1;
        if (kernel_size >= 0) {
            image_low_addr = entry;
            image_high_addr = image_low_addr + kernel_size;
        }
    }
    if (kernel_size < 0) {
        error_report("could not load kernel '%s'", info->kernel_filename);
@@ -1081,7 +1095,10 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
     * we might still make a bad choice here.
     */
    info->initrd_start = info->loader_start +
        MAX(MIN(info->ram_size / 2, 128 * 1024 * 1024), kernel_size);
        MIN(info->ram_size / 2, 128 * 1024 * 1024);
    if (image_high_addr) {
        info->initrd_start = MAX(info->initrd_start, image_high_addr);
    }
    info->initrd_start = TARGET_PAGE_ALIGN(info->initrd_start);

    if (is_linux) {
+9 −8
Original line number Diff line number Diff line
@@ -218,11 +218,12 @@ typedef struct PL330Queue {

static const VMStateDescription vmstate_pl330_queue = {
    .name = "pl330_queue",
    .version_id = 1,
    .minimum_version_id = 1,
    .version_id = 2,
    .minimum_version_id = 2,
    .fields = (VMStateField[]) {
        VMSTATE_STRUCT_VARRAY_UINT32(queue, PL330Queue, queue_size, 1,
                                 vmstate_pl330_queue_entry, PL330QueueEntry),
        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(queue, PL330Queue, queue_size,
                                             vmstate_pl330_queue_entry,
                                             PL330QueueEntry),
        VMSTATE_END_OF_LIST()
    }
};
@@ -278,11 +279,11 @@ struct PL330State {

static const VMStateDescription vmstate_pl330 = {
    .name = "pl330",
    .version_id = 1,
    .minimum_version_id = 1,
    .version_id = 2,
    .minimum_version_id = 2,
    .fields = (VMStateField[]) {
        VMSTATE_STRUCT(manager, PL330State, 0, vmstate_pl330_chan, PL330Chan),
        VMSTATE_STRUCT_VARRAY_UINT32(chan, PL330State, num_chnls, 0,
        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(chan, PL330State, num_chnls,
                                             vmstate_pl330_chan, PL330Chan),
        VMSTATE_VBUFFER_UINT32(lo_seqn, PL330State, 1, NULL, num_chnls),
        VMSTATE_VBUFFER_UINT32(hi_seqn, PL330State, 1, NULL, num_chnls),
+6 −4
Original line number Diff line number Diff line
@@ -60,12 +60,14 @@ static const VMStateDescription vmstate_stellaris_button = {

static const VMStateDescription vmstate_stellaris_gamepad = {
    .name = "stellaris_gamepad",
    .version_id = 1,
    .minimum_version_id = 1,
    .version_id = 2,
    .minimum_version_id = 2,
    .fields = (VMStateField[]) {
        VMSTATE_INT32(extension, gamepad_state),
        VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0,
                              vmstate_stellaris_button, gamepad_button),
        VMSTATE_STRUCT_VARRAY_POINTER_INT32(buttons, gamepad_state,
                                            num_buttons,
                                            vmstate_stellaris_button,
                                            gamepad_button),
        VMSTATE_END_OF_LIST()
    }
};
+24 −6
Original line number Diff line number Diff line
@@ -227,8 +227,22 @@ extern const VMStateInfo vmstate_info_bitmap;
extern const VMStateInfo vmstate_info_qtailq;

#define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
/*
 * Check that type t2 is an array of type t1 of size n,
 * e.g. if t1 is 'foo' and n is 32 then t2 must be 'foo[32]'
 */
#define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
#define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0)
/*
 * type of element 0 of the specified (array) field of the type.
 * Note that if the field is a pointer then this will return the
 * pointed-to type rather than complaining.
 */
#define typeof_elt_of_field(type, field) typeof(((type *)0)->field[0])
/* Check that field f in struct type t2 is an array of t1, of any size */
#define type_check_varray(t1, t2, f)                                 \
    (type_check(t1, typeof_elt_of_field(t2, f))                      \
     + QEMU_BUILD_BUG_ON_ZERO(!QEMU_IS_ARRAY(((t2 *)0)->f)))

#define vmstate_offset_value(_state, _field, _type)                  \
    (offsetof(_state, _field) +                                      \
@@ -253,6 +267,10 @@ extern const VMStateInfo vmstate_info_qtailq;
    vmstate_offset_array(_state, _field, uint8_t,                    \
                         sizeof(typeof_field(_state, _field)))

#define vmstate_offset_varray(_state, _field, _type)                 \
    (offsetof(_state, _field) +                                      \
     type_check_varray(_type, _state, _field))

/* In the macros below, if there is a _version, that means the macro's
 * field will be processed only if the version being received is >=
 * the _version specified.  In general, if you add a new field, you
@@ -347,7 +365,7 @@ extern const VMStateInfo vmstate_info_qtailq;
    .info       = &(_info),                                          \
    .size       = sizeof(_type),                                     \
    .flags      = VMS_VARRAY_UINT32|VMS_MULTIPLY_ELEMENTS,           \
    .offset     = offsetof(_state, _field),                          \
    .offset     = vmstate_offset_varray(_state, _field, _type),      \
}

#define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
@@ -376,7 +394,7 @@ extern const VMStateInfo vmstate_info_qtailq;
    .info       = &(_info),                                          \
    .size       = sizeof(_type),                                     \
    .flags      = VMS_VARRAY_INT32,                                  \
    .offset     = offsetof(_state, _field),                          \
    .offset     = vmstate_offset_varray(_state, _field, _type),      \
}

#define VMSTATE_VARRAY_INT32(_field, _state, _field_num, _version, _info, _type) {\
@@ -416,7 +434,7 @@ extern const VMStateInfo vmstate_info_qtailq;
    .info       = &(_info),                                          \
    .size       = sizeof(_type),                                     \
    .flags      = VMS_VARRAY_UINT16,                                 \
    .offset     = offsetof(_state, _field),                          \
    .offset     = vmstate_offset_varray(_state, _field, _type),      \
}

#define VMSTATE_VSTRUCT_TEST(_field, _state, _test, _version, _vmsd, _type, _struct_version) { \
@@ -520,7 +538,7 @@ extern const VMStateInfo vmstate_info_qtailq;
    .vmsd       = &(_vmsd),                                          \
    .size       = sizeof(_type),                                     \
    .flags      = VMS_STRUCT|VMS_VARRAY_UINT8,                       \
    .offset     = offsetof(_state, _field),                          \
    .offset     = vmstate_offset_varray(_state, _field, _type),      \
}

/* a variable length array (i.e. _type *_field) but we know the
@@ -573,7 +591,7 @@ extern const VMStateInfo vmstate_info_qtailq;
    .vmsd       = &(_vmsd),                                          \
    .size       = sizeof(_type),                                     \
    .flags      = VMS_STRUCT|VMS_VARRAY_INT32,                       \
    .offset     = offsetof(_state, _field),                          \
    .offset     = vmstate_offset_varray(_state, _field, _type),      \
}

#define VMSTATE_STRUCT_VARRAY_UINT32(_field, _state, _field_num, _version, _vmsd, _type) { \
@@ -583,7 +601,7 @@ extern const VMStateInfo vmstate_info_qtailq;
    .vmsd       = &(_vmsd),                                          \
    .size       = sizeof(_type),                                     \
    .flags      = VMS_STRUCT|VMS_VARRAY_UINT32,                      \
    .offset     = offsetof(_state, _field),                          \
    .offset     = vmstate_offset_varray(_state, _field, _type),      \
}

#define VMSTATE_STRUCT_VARRAY_ALLOC(_field, _state, _field_num, _version, _vmsd, _type) {\