diff options
-rw-r--r-- | hw/char/sclpconsole.c | 18 | ||||
-rw-r--r-- | hw/mips/mips_fulong2e.c | 4 | ||||
-rw-r--r-- | hw/mips/mips_jazz.c | 3 | ||||
-rw-r--r-- | hw/mips/mips_malta.c | 4 | ||||
-rw-r--r-- | hw/mips/mips_r4k.c | 4 | ||||
-rw-r--r-- | include/elf.h | 6 | ||||
-rw-r--r-- | include/sysemu/char.h | 1 | ||||
-rw-r--r-- | qemu-char.c | 50 | ||||
-rw-r--r-- | target-ppc/translate_init.c | 2 | ||||
-rw-r--r-- | target-s390x/Makefile.objs | 2 | ||||
-rw-r--r-- | target-s390x/arch_dump.c | 212 | ||||
-rw-r--r-- | target-s390x/cpu-qom.h | 5 | ||||
-rw-r--r-- | target-s390x/cpu.c | 2 | ||||
-rw-r--r-- | target-s390x/ioinst.c | 65 | ||||
-rw-r--r-- | target-s390x/kvm.c | 64 | ||||
-rw-r--r-- | tcg/tci/tcg-target.c | 3 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c | 10 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/maq_s_w_phl.c | 16 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dsp/maq_s_w_phr.c | 24 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c | 12 | ||||
-rw-r--r-- | tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c | 8 |
21 files changed, 382 insertions, 133 deletions
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index bcc7893230..eb3988c2e4 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -184,8 +184,6 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, size_t len) { - ssize_t ret = 0; - const uint8_t *iov_offset; SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); if (!scon->chr) { @@ -193,21 +191,7 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, return len; } - iov_offset = buf; - while (len > 0) { - ret = qemu_chr_fe_write(scon->chr, buf, len); - if (ret == 0) { - /* a pty doesn't seem to be connected - no error */ - len = 0; - } else if (ret == -EAGAIN || (ret > 0 && ret < len)) { - len -= ret; - iov_offset += ret; - } else { - len = 0; - } - } - - return ret; + return qemu_chr_fe_write_all(scon->chr, buf, len); } static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr) diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 99014415ca..b13750d0d9 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -43,6 +43,7 @@ #include "hw/timer/i8254.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define DEBUG_FULONG2E_INIT @@ -332,7 +333,8 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args) bios_size = -1; } - if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + if ((bios_size < 0 || bios_size > BIOS_SIZE) && + !kernel_filename && !qtest_enabled()) { fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); } } diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index d6e0860a83..36677cc652 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -42,6 +42,7 @@ #include "sysemu/blockdev.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" enum jazz_model_e { @@ -176,7 +177,7 @@ static void mips_jazz_init(MemoryRegion *address_space, } else { bios_size = -1; } - if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) { + if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) { fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); } diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 1589b59194..f56f34f3e6 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -48,6 +48,7 @@ #include "exec/address-spaces.h" #include "hw/sysbus.h" /* SysBusDevice */ #include "qemu/host-utils.h" +#include "sysemu/qtest.h" //#define DEBUG_BOARD_INIT @@ -1005,7 +1006,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) } else { bios_size = -1; } - if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + if ((bios_size < 0 || bios_size > BIOS_SIZE) && + !kernel_filename && !qtest_enabled()) { fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n", bios_name); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 7af08b8d0f..044f232de0 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -26,6 +26,7 @@ #include "hw/timer/i8254.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define MAX_IDE_BUS 2 @@ -244,8 +245,7 @@ void mips_r4k_init(QEMUMachineInitArgs *args) 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); } - } - else { + } else if (!qtest_enabled()) { /* not fatal */ fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); diff --git a/include/elf.h b/include/elf.h index cf0d3e2bd6..58bfbf8817 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1348,11 +1348,17 @@ typedef struct elf64_shdr { /* Notes used in ET_CORE */ #define NT_PRSTATUS 1 +#define NT_FPREGSET 2 #define NT_PRFPREG 2 #define NT_PRPSINFO 3 #define NT_TASKSTRUCT 4 #define NT_AUXV 6 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_S390_PREFIX 0x305 /* s390 prefix register */ +#define NT_S390_CTRS 0x304 /* s390 control registers */ +#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ +#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ +#define NT_S390_TIMER 0x301 /* s390 timer register */ /* Note header in a PT_NOTE section */ diff --git a/include/sysemu/char.h b/include/sysemu/char.h index e65e4a4844..8053130a97 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -77,6 +77,7 @@ struct CharDriverState { int explicit_fe_open; int explicit_be_open; int avail_connections; + int is_mux; QemuOpts *opts; QTAILQ_ENTRY(CharDriverState) next; }; diff --git a/qemu-char.c b/qemu-char.c index 3f606c935b..16f3ad77de 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -476,6 +476,46 @@ static void mux_chr_update_read_handler(CharDriverState *chr) mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); } +static bool muxes_realized; + +/** + * Called after processing of default and command-line-specified + * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached + * to a mux chardev. This is done here to ensure that + * output/prompts/banners are only displayed for the FE that has + * focus when initial command-line processing/machine init is + * completed. + * + * After this point, any new FE attached to any new or existing + * mux will receive CHR_EVENT_OPENED notifications for the BE + * immediately. + */ +static void muxes_realize_done(Notifier *notifier, void *unused) +{ + CharDriverState *chr; + + QTAILQ_FOREACH(chr, &chardevs, next) { + if (chr->is_mux) { + MuxDriver *d = chr->opaque; + int i; + + /* send OPENED to all already-attached FEs */ + for (i = 0; i < d->mux_cnt; i++) { + mux_chr_send_event(d, i, CHR_EVENT_OPENED); + } + /* mark mux as OPENED so any new FEs will immediately receive + * OPENED event + */ + qemu_chr_be_generic_open(chr); + } + } + muxes_realized = true; +} + +static Notifier muxes_realize_notify = { + .notify = muxes_realize_done, +}; + static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) { CharDriverState *chr; @@ -492,6 +532,11 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) chr->chr_accept_input = mux_chr_accept_input; /* Frontend guest-open / -close notification is not support with muxes */ chr->chr_set_fe_open = NULL; + /* only default to opened state if we've realized the initial + * set of muxes + */ + chr->explicit_be_open = muxes_realized ? 0 : 1; + chr->is_mux = 1; return chr; } @@ -3798,6 +3843,11 @@ static void register_types(void) /* Bug-compatibility: */ register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY, qemu_chr_parse_ringbuf); + /* this must be done after machine init, since we register FEs with muxes + * as part of realize functions like serial_isa_realizefn when -nographic + * is specified + */ + qemu_add_machine_init_done_notifier(&muxes_realize_notify); } type_init(register_types); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 0724226dd6..b14aec8e7b 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7825,7 +7825,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) error_setg(errp, "Unable to virtualize selected CPU with KVM"); return; } - } else { + } else if (tcg_enabled()) { if (ppc_fixup_cpu(cpu) != 0) { error_setg(errp, "Unable to emulate selected CPU with TCG"); return; diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index ab938e7ad8..f8731463ff 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,5 +1,5 @@ obj-y += translate.o helper.o cpu.o interrupt.o obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += ioinst.o +obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target-s390x/arch_dump.c b/target-s390x/arch_dump.c new file mode 100644 index 0000000000..f3e5144cc1 --- /dev/null +++ b/target-s390x/arch_dump.c @@ -0,0 +1,212 @@ +/* + * writing ELF notes for s390x arch + * + * + * Copyright IBM Corp. 2012, 2013 + * + * Ekaterina Tumanova <tumanova@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "cpu.h" +#include "elf.h" +#include "exec/cpu-all.h" +#include "sysemu/dump.h" +#include "sysemu/kvm.h" + + +struct S390xUserRegsStruct { + uint64_t psw[2]; + uint64_t gprs[16]; + uint32_t acrs[16]; +} QEMU_PACKED; + +typedef struct S390xUserRegsStruct S390xUserRegs; + +struct S390xElfPrstatusStruct { + uint8_t pad1[32]; + uint32_t pid; + uint8_t pad2[76]; + S390xUserRegs regs; + uint8_t pad3[16]; +} QEMU_PACKED; + +typedef struct S390xElfPrstatusStruct S390xElfPrstatus; + +struct S390xElfFpregsetStruct { + uint32_t fpc; + uint32_t pad; + uint64_t fprs[16]; +} QEMU_PACKED; + +typedef struct S390xElfFpregsetStruct S390xElfFpregset; + +typedef struct noteStruct { + Elf64_Nhdr hdr; + char name[5]; + char pad3[3]; + union { + S390xElfPrstatus prstatus; + S390xElfFpregset fpregset; + uint32_t prefix; + uint64_t timer; + uint64_t todcmp; + uint32_t todpreg; + uint64_t ctrs[16]; + } contents; +} QEMU_PACKED Note; + +static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu) +{ + int i; + S390xUserRegs *regs; + + note->hdr.n_type = cpu_to_be32(NT_PRSTATUS); + + regs = &(note->contents.prstatus.regs); + regs->psw[0] = cpu_to_be64(cpu->env.psw.mask); + regs->psw[1] = cpu_to_be64(cpu->env.psw.addr); + for (i = 0; i <= 15; i++) { + regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]); + regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]); + } +} + +static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu) +{ + int i; + + note->hdr.n_type = cpu_to_be32(NT_FPREGSET); + note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc); + for (i = 0; i <= 15; i++) { + note->contents.fpregset.fprs[i] = cpu_to_be64(cpu->env.fregs[i].ll); + } +} + + +static void s390x_write_elf64_timer(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_TIMER); + note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm)); +} + +static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP); + note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc)); +} + +static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG); + note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr)); +} + +static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu) +{ + int i; + + note->hdr.n_type = cpu_to_be32(NT_S390_CTRS); + + for (i = 0; i <= 15; i++) { + note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]); + } +} + +static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX); + note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa)); +} + + +struct NoteFuncDescStruct { + int contents_size; + void (*note_contents_func)(Note *note, S390CPU *cpu); +} note_func[] = { + {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus}, + {sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix}, + {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset}, + {sizeof(((Note *)0)->contents.ctrs), s390x_write_elf64_ctrs}, + {sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer}, + {sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp}, + {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg}, + { 0, NULL} +}; + +typedef struct NoteFuncDescStruct NoteFuncDesc; + + +static int s390x_write_all_elf64_notes(const char *note_name, + WriteCoreDumpFunction f, + S390CPU *cpu, int id, + void *opaque) +{ + Note note; + NoteFuncDesc *nf; + int note_size; + int ret = -1; + + for (nf = note_func; nf->note_contents_func; nf++) { + note.hdr.n_namesz = cpu_to_be32(sizeof(note.name)); + note.hdr.n_descsz = cpu_to_be32(nf->contents_size); + strncpy(note.name, note_name, sizeof(note.name)); + (*nf->note_contents_func)(¬e, cpu); + + note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size; + ret = f(¬e, note_size, opaque); + + if (ret < 0) { + return -1; + } + + } + + return 0; +} + + +int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, void *opaque) +{ + S390CPU *cpu = S390_CPU(cs); + return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque); +} + +int cpu_get_dump_info(ArchDumpInfo *info) +{ + info->d_machine = EM_S390; + info->d_endian = ELFDATA2MSB; + info->d_class = ELFCLASS64; + + return 0; +} + +ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) +{ + int name_size = 8; /* "CORE" or "QEMU" rounded */ + size_t elf_note_size = 0; + int note_head_size; + NoteFuncDesc *nf; + + assert(class == ELFCLASS64); + assert(machine == EM_S390); + + note_head_size = sizeof(Elf64_Nhdr); + + for (nf = note_func; nf->note_contents_func; nf++) { + elf_note_size = elf_note_size + note_head_size + name_size + + nf->contents_size; + } + + return (elf_note_size) * nr_cpus; +} + +int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, + CPUState *cpu, void *opaque) +{ + return 0; +} diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index 0d63b1cf20..cbe2341b3b 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -74,6 +74,11 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env) void s390_cpu_do_interrupt(CPUState *cpu); void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, int flags); +int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, void *opaque); + +int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, + CPUState *cpu, void *opaque); hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 9b824957f6..6be6c084a7 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -178,6 +178,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_write_register = s390_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = s390_cpu_get_phys_page_debug; + cc->write_elf64_note = s390_cpu_write_elf64_note; + cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote; #endif dc->vmsd = &vmstate_s390_cpu; cc->gdb_num_core_regs = S390_NUM_REGS; diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c index 28c508d541..85fd285736 100644 --- a/target-s390x/ioinst.c +++ b/target-s390x/ioinst.c @@ -151,23 +151,24 @@ int ioinst_handle_msch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) int cc; hwaddr len = sizeof(*schib); - if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { - program_interrupt(env, PGM_OPERAND, 2); + addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; } - trace_ioinst_sch_id("msch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); schib = s390_cpu_physical_memory_map(env, addr, &len, 0); if (!schib || len != sizeof(*schib)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } - if (!ioinst_schib_valid(schib)) { + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || + !ioinst_schib_valid(schib)) { program_interrupt(env, PGM_OPERAND, 2); cc = -EIO; goto out; } + trace_ioinst_sch_id("msch", cssid, ssid, schid); sch = css_find_subch(m, cssid, ssid, schid); if (sch && css_subch_visible(sch)) { ret = css_do_msch(sch, schib); @@ -222,24 +223,25 @@ int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) int cc; hwaddr len = sizeof(*orig_orb); - if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { - program_interrupt(env, PGM_OPERAND, 2); + addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; } - trace_ioinst_sch_id("ssch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0); if (!orig_orb || len != sizeof(*orig_orb)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } copy_orb_from_guest(&orb, orig_orb); - if (!ioinst_orb_valid(&orb)) { + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || + !ioinst_orb_valid(&orb)) { program_interrupt(env, PGM_OPERAND, 2); cc = -EIO; goto out; } + trace_ioinst_sch_id("ssch", cssid, ssid, schid); sch = css_find_subch(m, cssid, ssid, schid); if (sch && css_subch_visible(sch)) { ret = css_do_ssch(sch, &orb); @@ -272,9 +274,13 @@ int ioinst_handle_stcrw(CPUS390XState *env, uint32_t ipb) hwaddr len = sizeof(*crw); addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); + return -EIO; + } crw = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!crw || len != sizeof(*crw)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } @@ -294,18 +300,24 @@ int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) SCHIB *schib; hwaddr len = sizeof(*schib); - if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { - program_interrupt(env, PGM_OPERAND, 2); + addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; } - trace_ioinst_sch_id("stsch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); schib = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!schib || len != sizeof(*schib)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); + cc = -EIO; + goto out; + } + + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { + program_interrupt(env, PGM_OPERAND, 2); cc = -EIO; goto out; } + trace_ioinst_sch_id("stsch", cssid, ssid, schid); sch = css_find_subch(m, cssid, ssid, schid); if (sch) { if (css_subch_visible(sch)) { @@ -345,9 +357,13 @@ int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) } trace_ioinst_sch_id("tsch", cssid, ssid, schid); addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); + return -EIO; + } irb = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!irb || len != sizeof(*irb)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } @@ -580,7 +596,7 @@ int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb) } req = s390_cpu_physical_memory_map(env, addr, &map_size, 1); if (!req || map_size != TARGET_PAGE_SIZE) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); ret = -EIO; goto out; } @@ -625,12 +641,17 @@ int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb) trace_ioinst("tpi"); addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); + return -EIO; + } + lowcore = addr ? 0 : 1; len = lowcore ? 8 /* two words */ : 12 /* three words */; orig_len = len; int_code = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!int_code || (len != orig_len)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); ret = -EIO; goto out; } @@ -663,7 +684,7 @@ int ioinst_handle_schm(CPUS390XState *env, uint64_t reg1, uint64_t reg2, update = SCHM_REG1_UPD(reg1); dct = SCHM_REG1_DCT(reg1); - if (update && (reg2 & 0x0000000000000fff)) { + if (update && (reg2 & 0x000000000000001f)) { program_interrupt(env, PGM_OPERAND, 2); return -EIO; } diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index ab0e2b505f..26d18e3bcf 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -528,50 +528,19 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run, no_cc = 1; r = ioinst_handle_sal(env, env->regs[1]); break; - default: - r = -1; + case PRIV_SIGA: + /* Not provided, set CC = 3 for subchannel not operational */ + r = 3; break; + default: + return -1; } - if (r >= 0) { - if (!no_cc) { - setcc(cpu, r); - } - r = 0; - } else if (r < -1) { - r = 0; + if (r >= 0 && !no_cc) { + setcc(cpu, r); } - return r; -} -static int is_ioinst(uint8_t ipa0, uint8_t ipa1, uint8_t ipb) -{ - int ret = 0; - uint16_t ipa = (ipa0 << 8) | ipa1; - - switch (ipa) { - case IPA0_B2 | PRIV_CSCH: - case IPA0_B2 | PRIV_HSCH: - case IPA0_B2 | PRIV_MSCH: - case IPA0_B2 | PRIV_SSCH: - case IPA0_B2 | PRIV_STSCH: - case IPA0_B2 | PRIV_TPI: - case IPA0_B2 | PRIV_SAL: - case IPA0_B2 | PRIV_RSCH: - case IPA0_B2 | PRIV_STCRW: - case IPA0_B2 | PRIV_STCPS: - case IPA0_B2 | PRIV_RCHP: - case IPA0_B2 | PRIV_SCHM: - case IPA0_B2 | PRIV_CHSC: - case IPA0_B2 | PRIV_SIGA: - case IPA0_B2 | PRIV_XSCH: - case IPA0_B9 | PRIV_EQBS: - case IPA0_EB | PRIV_SQBS: - ret = 1; - break; - } - - return ret; + return 0; } static int handle_priv(S390CPU *cpu, struct kvm_run *run, @@ -587,15 +556,9 @@ static int handle_priv(S390CPU *cpu, struct kvm_run *run, r = kvm_sclp_service_call(cpu, run, ipbh0); break; default: - if (is_ioinst(ipa0, ipa1, ipb)) { - r = kvm_handle_css_inst(cpu, run, ipa0, ipa1, ipb); - if (r == -1) { - setcc(cpu, 3); - r = 0; - } - } else { - DPRINTF("KVM: unknown PRIV: 0x%x\n", ipa1); - r = -1; + r = kvm_handle_css_inst(cpu, run, ipa0, ipa1, ipb); + if (r == -1) { + DPRINTF("KVM: unhandled PRIV: 0x%x\n", ipa1); } break; } @@ -730,7 +693,7 @@ out: return 0; } -static int handle_instruction(S390CPU *cpu, struct kvm_run *run) +static void handle_instruction(S390CPU *cpu, struct kvm_run *run) { unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00); uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff; @@ -756,7 +719,6 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) if (r < 0) { enter_pgmcheck(cpu, 0x0001); } - return 0; } static bool is_special_wait_psw(CPUState *cs) @@ -776,7 +738,7 @@ static int handle_intercept(S390CPU *cpu) (long)cs->kvm_run->psw_addr); switch (icpt_code) { case ICPT_INSTRUCTION: - r = handle_instruction(cpu, run); + handle_instruction(cpu, run); break; case ICPT_WAITPSW: /* disabled wait, since enabled wait is handled in kernel */ diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index d1241b5692..e118bc7179 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -34,9 +34,6 @@ tcg_abort(); \ } while (0) -/* Single bit n. */ -#define BIT(n) (1 << (n)) - /* Bitfield n...m (in 32 bit value). */ #define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m) diff --git a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c index 22ab4d57ba..74058fe7ec 100644 --- a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c +++ b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c @@ -9,8 +9,8 @@ int main() rs = 0xBC0123AD; rt = 0x01643721; - resulth = 0x04; - resultl = 0xEE9794A3; + resulth = 0x00000004; + resultl = 0xF15F94A3; __asm ("mthi %0, $ac1\n\t" "mtlo %1, $ac1\n\t" @@ -23,12 +23,12 @@ int main() assert(ach == resulth); assert(acl == resultl); - ach = 0x1424Ef1f; + ach = 0x1424EF1F; acl = 0x1035219A; rs = 0x800083AD; rt = 0x80003721; - resulth = 0x1424ef1e; - resultl = 0x577ed901; + resulth = 0x1424EF1E; + resultl = 0xC5C0D901; __asm ("mthi %0, $ac1\n\t" "mtlo %1, $ac1\n\t" diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c index 292d68566d..0f7c070155 100644 --- a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c +++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c @@ -10,12 +10,12 @@ int main() int resulth, resultl; int resdsp; - achi = 0x05; - acli = 0xB4CB; + achi = 0x00000005; + acli = 0x0000B4CB; rs = 0xFF060000; rt = 0xCB000000; - resulth = 0x04; - resultl = 0x947438CB; + resulth = 0x00000005; + resultl = 0x006838CB; __asm ("mthi %2, $ac1\n\t" @@ -29,12 +29,12 @@ int main() assert(resulth == acho); assert(resultl == aclo); - achi = 0x06; - acli = 0xB4CB; + achi = 0x00000006; + acli = 0x0000B4CB; rs = 0x80000000; rt = 0x80000000; - resulth = 0x6; - resultl = 0x8000b4ca; + resulth = 0x00000006; + resultl = 0x8000B4CA; resdsp = 1; __asm diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c index 7b2ef2ab71..942722a530 100644 --- a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c +++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c @@ -10,12 +10,12 @@ int main() int resulth, resultl; int resdsp; - achi = 0x05; - acli = 0xB4CB; - rs = 0xFF06; - rt = 0xCB00; - resulth = 0x04; - resultl = 0x947438CB; + achi = 0x00000005; + acli = 0x0000B4CB; + rs = 0x0000FF06; + rt = 0x0000CB00; + resulth = 0x00000005; + resultl = 0x006838CB; __asm ("mthi %2, $ac1\n\t" @@ -29,12 +29,12 @@ int main() assert(resulth == acho); assert(resultl == aclo); - achi = 0x06; - acli = 0xB4CB; - rs = 0x8000; - rt = 0x8000; - resulth = 0x6; - resultl = 0x8000b4ca; + achi = 0x00000006; + acli = 0x0000B4CB; + rs = 0x00008000; + rt = 0x00008000; + resulth = 0x00000006; + resultl = 0x8000B4CA; resdsp = 1; __asm diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c index 798c4da5ca..d551d64ae2 100644 --- a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c +++ b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c @@ -4,14 +4,17 @@ int main() { int rs, rt, dsp; - int ach = 5, acl = 5; + int ach, acl; int resulth, resultl, resultdsp; + ach = 0x00000005; + acl = 0x00000005; rs = 0x00FF00FF; rt = 0x00010002; resulth = 0x00; resultl = 0x7FFFFFFF; resultdsp = 0x01; + dsp = 0; __asm ("wrdsp %2\n\t" "mthi %0, $ac1\n\t" @@ -27,13 +30,14 @@ int main() assert(ach == resulth); assert(acl == resultl); - ach = 9; - acl = 0xb; + ach = 0x00000009; + acl = 0x0000000B; rs = 0x800000FF; rt = 0x00018000; resulth = 0x00; - resultl = 0x7fffffff; + resultl = 0x7FFFFFFF; resultdsp = 0x01; + dsp = 0; __asm ("wrdsp %2\n\t" "mthi %0, $ac1\n\t" diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c index 14cdd7c0f5..e40543fd82 100644 --- a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c +++ b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c @@ -9,8 +9,8 @@ int main() rs = 0xBC0123AD; rt = 0x01643721; - resulth = 0x04; - resultl = 0xAEA3E09B; + resulth = 0x00000005; + resultl = 0x1CE5E09B; resultdsp = 0x00; __asm ("mthi %0, $ac1\n\t" @@ -27,12 +27,12 @@ int main() assert(ach == resulth); assert(acl == resultl); - ach = 0x99f13005; + ach = 0x99F13005; acl = 0x51730062; rs = 0x80008000; rt = 0x80008000; - resulth = 0x99f13004; + resulth = 0x99F13004; resultl = 0x51730064; resultdsp = 0x01; __asm |