Commit 0dc8ae5e authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20180301-v2' into staging



- add query-cpus-fast and deprecate query-cpus, while adding s390 cpu
  information
- remove s390x memory hotplug implementation, which is not useable in
  this form
- add boot menu support in the s390-ccw bios
- expose s390x guest crash information
- fixes and cleaups

# gpg: Signature made Thu 01 Mar 2018 12:54:47 GMT
# gpg:                using RSA key DECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>"
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20180301-v2: (27 commits)
  s390x/tcg: fix loading 31bit PSWs with the highest bit set
  s390x: remove s390_get_memslot_count
  s390x/sclp: remove memory hotplug support
  s390x/cpumodel: document S390FeatDef.bit not applicable
  hmp: change hmp_info_cpus to use query-cpus-fast
  qemu-doc: deprecate query-cpus
  qmp: add architecture specific cpu data for query-cpus-fast
  qmp: add query-cpus-fast
  qmp: expose s390-specific CPU info
  s390x/tcg: add various alignment checks
  s390x/tcg: fix disabling/enabling DAT
  s390/stattrib: Make SaveVMHandlers data static
  s390x/cpu: expose the guest crash information
  pc-bios/s390: Rebuild the s390x firmware images with the boot menu changes
  s390-ccw: interactive boot menu for scsi
  s390-ccw: use zipl values when no boot menu options are present
  s390-ccw: set cp_receive mask only when needed and consume pending service irqs
  s390-ccw: read user input for boot index via the SCLP console
  s390-ccw: print zipl boot menu
  s390-ccw: read stage2 boot loader data to find menu
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 9db0855e be8b49de
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -2100,6 +2100,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
#elif defined(TARGET_TRICORE)
        TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu);
        CPUTriCoreState *env = &tricore_cpu->env;
#elif defined(TARGET_S390X)
        S390CPU *s390_cpu = S390_CPU(cpu);
        CPUS390XState *env = &s390_cpu->env;
#endif

        cpu_synchronize_state(cpu);
@@ -2127,6 +2130,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
#elif defined(TARGET_TRICORE)
        info->value->arch = CPU_INFO_ARCH_TRICORE;
        info->value->u.tricore.PC = env->PC;
#elif defined(TARGET_S390X)
        info->value->arch = CPU_INFO_ARCH_S390;
        info->value->u.s390.cpu_state = env->cpu_state;
#else
        info->value->arch = CPU_INFO_ARCH_OTHER;
#endif
@@ -2150,6 +2156,54 @@ CpuInfoList *qmp_query_cpus(Error **errp)
    return head;
}

/*
 * fast means: we NEVER interrupt vCPU threads to retrieve
 * information from KVM.
 */
CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
{
    MachineState *ms = MACHINE(qdev_get_machine());
    MachineClass *mc = MACHINE_GET_CLASS(ms);
    CpuInfoFastList *head = NULL, *cur_item = NULL;
    CPUState *cpu;
#if defined(TARGET_S390X)
    S390CPU *s390_cpu;
    CPUS390XState *env;
#endif

    CPU_FOREACH(cpu) {
        CpuInfoFastList *info = g_malloc0(sizeof(*info));
        info->value = g_malloc0(sizeof(*info->value));

        info->value->cpu_index = cpu->cpu_index;
        info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
        info->value->thread_id = cpu->thread_id;

        info->value->has_props = !!mc->cpu_index_to_instance_props;
        if (info->value->has_props) {
            CpuInstanceProperties *props;
            props = g_malloc0(sizeof(*props));
            *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index);
            info->value->props = props;
        }

#if defined(TARGET_S390X)
        s390_cpu = S390_CPU(cpu);
        env = &s390_cpu->env;
        info->value->arch = CPU_INFO_ARCH_S390;
        info->value->u.s390.cpu_state = env->cpu_state;
#endif
        if (!cur_item) {
            head = cur_item = info;
        } else {
            cur_item->next = info;
            cur_item = info;
        }
    }

    return head;
}

void qmp_memsave(int64_t addr, int64_t size, const char *filename,
                 bool has_cpu, int64_t cpu_index, Error **errp)
{
+7 −34
Original line number Diff line number Diff line
@@ -360,50 +360,23 @@ void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict)

void hmp_info_cpus(Monitor *mon, const QDict *qdict)
{
    CpuInfoList *cpu_list, *cpu;
    CpuInfoFastList *cpu_list, *cpu;

    cpu_list = qmp_query_cpus(NULL);
    cpu_list = qmp_query_cpus_fast(NULL);

    for (cpu = cpu_list; cpu; cpu = cpu->next) {
        int active = ' ';

        if (cpu->value->CPU == monitor_get_cpu_index()) {
        if (cpu->value->cpu_index == monitor_get_cpu_index()) {
            active = '*';
        }

        monitor_printf(mon, "%c CPU #%" PRId64 ":", active, cpu->value->CPU);

        switch (cpu->value->arch) {
        case CPU_INFO_ARCH_X86:
            monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->u.x86.pc);
            break;
        case CPU_INFO_ARCH_PPC:
            monitor_printf(mon, " nip=0x%016" PRIx64, cpu->value->u.ppc.nip);
            break;
        case CPU_INFO_ARCH_SPARC:
            monitor_printf(mon, " pc=0x%016" PRIx64,
                           cpu->value->u.q_sparc.pc);
            monitor_printf(mon, " npc=0x%016" PRIx64,
                           cpu->value->u.q_sparc.npc);
            break;
        case CPU_INFO_ARCH_MIPS:
            monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.q_mips.PC);
            break;
        case CPU_INFO_ARCH_TRICORE:
            monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.tricore.PC);
            break;
        default:
            break;
        }

        if (cpu->value->halted) {
            monitor_printf(mon, " (halted)");
        }

        monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
        monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
                       cpu->value->cpu_index);
        monitor_printf(mon, " thread-id=%" PRId64 "\n", cpu->value->thread_id);
    }

    qapi_free_CpuInfoList(cpu_list);
    qapi_free_CpuInfoFastList(cpu_list);
}

static void print_block_info(Monitor *mon, BlockInfo *info,
+2 −2
Original line number Diff line number Diff line
@@ -192,8 +192,8 @@ static void qemu_s390_flic_notify(uint32_t type)
        cs->interrupt_request |= CPU_INTERRUPT_HARD;

        /* ignore CPUs that are not sleeping */
        if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING &&
            s390_cpu_get_state(cpu) != CPU_STATE_LOAD) {
        if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING &&
            s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD) {
            continue;
        }

+76 −1
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@
#include "hw/s390x/ebcdic.h"
#include "ipl.h"
#include "qemu/error-report.h"
#include "qemu/config-file.h"
#include "qemu/cutils.h"
#include "qemu/option.h"

#define KERN_IMAGE_START                0x010000UL
#define KERN_PARM_AREA                  0x010480UL
@@ -219,6 +222,61 @@ static Property s390_ipl_properties[] = {
    DEFINE_PROP_END_OF_LIST(),
};

static void s390_ipl_set_boot_menu(S390IPLState *ipl)
{
    QemuOptsList *plist = qemu_find_opts("boot-opts");
    QemuOpts *opts = QTAILQ_FIRST(&plist->head);
    uint8_t *flags = &ipl->qipl.qipl_flags;
    uint32_t *timeout = &ipl->qipl.boot_menu_timeout;
    const char *tmp;
    unsigned long splash_time = 0;

    if (!get_boot_device(0)) {
        if (boot_menu) {
            error_report("boot menu requires a bootindex to be specified for "
                         "the IPL device.");
        }
        return;
    }

    switch (ipl->iplb.pbt) {
    case S390_IPL_TYPE_CCW:
        /* In the absence of -boot menu, use zipl parameters */
        if (!qemu_opt_get(opts, "menu")) {
            *flags |= QIPL_FLAG_BM_OPTS_ZIPL;
            return;
        }
        break;
    case S390_IPL_TYPE_QEMU_SCSI:
        break;
    default:
        error_report("boot menu is not supported for this device type.");
        return;
    }

    if (!boot_menu) {
        return;
    }

    *flags |= QIPL_FLAG_BM_OPTS_CMD;

    tmp = qemu_opt_get(opts, "splash-time");

    if (tmp && qemu_strtoul(tmp, NULL, 10, &splash_time)) {
        error_report("splash-time is invalid, forcing it to 0.");
        *timeout = 0;
        return;
    }

    if (splash_time > 0xffffffff) {
        error_report("splash-time is too large, forcing it to max value.");
        *timeout = 0xffffffff;
        return;
    }

    *timeout = cpu_to_be32(splash_time);
}

static bool s390_gen_initial_iplb(S390IPLState *ipl)
{
    DeviceState *dev_st;
@@ -399,6 +457,21 @@ void s390_reipl_request(void)
    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}

static void s390_ipl_prepare_qipl(S390CPU *cpu)
{
    S390IPLState *ipl = get_ipl_device();
    uint8_t *addr;
    uint64_t len = 4096;

    addr = cpu_physical_memory_map(cpu->env.psa, &len, 1);
    if (!addr || len < QIPL_ADDRESS + sizeof(QemuIplParameters)) {
        error_report("Cannot set QEMU IPL parameters");
        return;
    }
    memcpy(addr + QIPL_ADDRESS, &ipl->qipl, sizeof(QemuIplParameters));
    cpu_physical_memory_unmap(addr, len, 1, len);
}

void s390_ipl_prepare_cpu(S390CPU *cpu)
{
    S390IPLState *ipl = get_ipl_device();
@@ -418,8 +491,10 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
            error_report_err(err);
            vm_stop(RUN_STATE_INTERNAL_ERROR);
        }
        ipl->iplb.ccw.netboot_start_addr = cpu_to_be64(ipl->start_addr);
        ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr);
    }
    s390_ipl_set_boot_menu(ipl);
    s390_ipl_prepare_qipl(cpu);
}

static void s390_ipl_reset(DeviceState *dev)
+29 −2
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@
#include "cpu.h"

struct IplBlockCcw {
    uint64_t netboot_start_addr;
    uint8_t  reserved0[77];
    uint8_t  reserved0[85];
    uint8_t  ssid;
    uint16_t devno;
    uint8_t  vm_flags;
@@ -90,6 +89,33 @@ void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
void s390_reipl_request(void);

#define QIPL_ADDRESS  0xcc

/* Boot Menu flags */
#define QIPL_FLAG_BM_OPTS_CMD   0x80
#define QIPL_FLAG_BM_OPTS_ZIPL  0x40

/*
 * The QEMU IPL Parameters will be stored at absolute address
 * 204 (0xcc) which means it is 32-bit word aligned but not
 * double-word aligned.
 * Placement of data fields in this area must account for
 * their alignment needs. E.g., netboot_start_address must
 * have an offset of 4 + n * 8 bytes within the struct in order
 * to keep it double-word aligned.
 * The total size of the struct must never exceed 28 bytes.
 * This definition must be kept in sync with the defininition
 * in pc-bios/s390-ccw/iplb.h.
 */
struct QemuIplParameters {
    uint8_t  qipl_flags;
    uint8_t  reserved1[3];
    uint64_t netboot_start_addr;
    uint32_t boot_menu_timeout;
    uint8_t  reserved2[12];
} QEMU_PACKED;
typedef struct QemuIplParameters QemuIplParameters;

#define TYPE_S390_IPL "s390-ipl"
#define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL)

@@ -105,6 +131,7 @@ struct S390IPLState {
    bool iplb_valid;
    bool reipl_requested;
    bool netboot;
    QemuIplParameters qipl;

    /*< public >*/
    char *kernel;
Loading