From 97575f928fe95515a4855487b233506e75675f66 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 8 Mar 2019 18:33:27 +0100 Subject: vfio-pci: enable by default CONFIG_VFIO_PCI was not "default y" - and once you do that, it is also important to disable it if PCI is not there. Reported-by: Alex Williamson Tested-by: Alex Williamson Signed-off-by: Paolo Bonzini --- hw/vfio/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/vfio/Kconfig b/hw/vfio/Kconfig index ebda9fdf22..34da2a3cfd 100644 --- a/hw/vfio/Kconfig +++ b/hw/vfio/Kconfig @@ -4,8 +4,9 @@ config VFIO config VFIO_PCI bool + default y select VFIO - depends on LINUX + depends on LINUX && PCI config VFIO_CCW bool -- cgit v1.2.3-55-g7522 From fcfd1bcc30c33795ca66b2f4f6c5bb4438e62865 Mon Sep 17 00:00:00 2001 From: David Abdurachmanov Date: Mon, 11 Mar 2019 10:12:56 +0100 Subject: riscv/Kconfig: enable PCI_DEVICES Re-enable PCI_DEVICES for RISC-V. The patch is based on other /Kconfig. Signed-off-by: David Abdurachmanov Fixes: 82a230d5a303 ("riscv-softmmu.mak: replace CONFIG_* with Kconfig "select" directives") Message-Id: <20190311091256.18385-1-david.abdurachmanov@gmail.com> Reviewed-by: Thomas Huth Signed-off-by: Paolo Bonzini --- hw/riscv/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'hw') diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index e0ee3043a6..8c7fc1f31d 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -26,6 +26,9 @@ config SPIKE config RISCV_VIRT bool + imply PCI_DEVICES + imply TEST_DEVICES + select PCI select HART select SERIAL select VIRTIO_MMIO -- cgit v1.2.3-55-g7522 From 5dc8ab361a6aed42560731eb9b4fdeff01ace948 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Thu, 14 Feb 2019 19:02:16 +0100 Subject: hw/i386/pc: run the multiboot loader before the PVH loader Some multiboot images could be in the ELF format. In the current implementation QEMU fails because we try to load these images as a PVH image. In order to fix this issue, we should try multiboot first (we already check the multiboot magic header before to load it). If it is not a multiboot image, we can try the PVH loader. Fixes: ab969087da6 ("pvh: Boot uncompressed kernel using direct boot ABI", 2019-01-15) Reported-by: Paolo Bonzini Signed-off-by: Stefano Garzarella Message-Id: <20190214180216.246707-1-sgarzare@redhat.com> Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 42128183e9..9c8f8332a9 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1209,6 +1209,17 @@ static void load_linux(PCMachineState *pcms, if (ldl_p(header+0x202) == 0x53726448) { protocol = lduw_p(header+0x206); } else { + /* + * This could be a multiboot kernel. If it is, let's stop treating it + * like a Linux kernel. + * Note: some multiboot images could be in the ELF format (the same of + * PVH), so we try multiboot first since we check the multiboot magic + * header before to load it. + */ + if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename, + kernel_cmdline, kernel_size, header)) { + return; + } /* * Check if the file is an uncompressed kernel file (ELF) and load it, * saving the PVH entry point used by the x86/HVM direct boot ABI. @@ -1262,12 +1273,6 @@ static void load_linux(PCMachineState *pcms, return; } - /* This looks like a multiboot kernel. If it is, let's stop - treating it like a Linux kernel. */ - if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename, - kernel_cmdline, kernel_size, header)) { - return; - } protocol = 0; } -- cgit v1.2.3-55-g7522 From f24c3a79a415042f6dc195f029a2ba7247d14cac Mon Sep 17 00:00:00 2001 From: Luwei Kang Date: Tue, 29 Jan 2019 18:52:59 -0500 Subject: i386: extended the cpuid_level when Intel PT is enabled Intel Processor Trace required CPUID[0x14] but the cpuid_level have no change when create a kvm guest with e.g. "-cpu qemu64,+intel-pt". Signed-off-by: Eduardo Habkost Signed-off-by: Luwei Kang Message-Id: <1548805979-12321-1-git-send-email-luwei.kang@intel.com> Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 1 + target/i386/cpu.c | 9 +++++++++ target/i386/cpu.h | 3 +++ 3 files changed, 13 insertions(+) (limited to 'hw') diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9c8f8332a9..c6d047b42b 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -136,6 +136,7 @@ GlobalProperty pc_compat_3_1[] = { { "Icelake-Client" "-" TYPE_X86_CPU, "mpx", "on" }, { "Icelake-Server" "-" TYPE_X86_CPU, "mpx", "on" }, { "Cascadelake-Server" "-" TYPE_X86_CPU, "stepping", "5" }, + { TYPE_X86_CPU, "x-intel-pt-auto-level", "off" }, }; const size_t pc_compat_3_1_len = G_N_ELEMENTS(pc_compat_3_1); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index d3aa6a815b..d90c01a059 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5031,6 +5031,13 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX); x86_cpu_adjust_feat_level(cpu, FEAT_SVM); x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE); + + /* Intel Processor Trace requires CPUID[0x14] */ + if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && + kvm_enabled() && cpu->intel_pt_auto_level) { + x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14); + } + /* SVM requires CPUID[0x8000000A] */ if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A); @@ -5824,6 +5831,8 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_INT32("x-hv-max-vps", X86CPU, hv_max_vps, -1), DEFINE_PROP_BOOL("x-hv-synic-kvm-only", X86CPU, hyperv_synic_kvm_only, false), + DEFINE_PROP_BOOL("x-intel-pt-auto-level", X86CPU, intel_pt_auto_level, + true), DEFINE_PROP_END_OF_LIST() }; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 95112b9118..83fb522554 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1454,6 +1454,9 @@ struct X86CPU { /* Enable auto level-increase for all CPUID leaves */ bool full_cpuid_auto_level; + /* Enable auto level-increase for Intel Processor Trace leave */ + bool intel_pt_auto_level; + /* if true fill the top bits of the MTRR_PHYSMASKn variable range */ bool fill_mtrr_mask; -- cgit v1.2.3-55-g7522 From d804232dc4a5400494442b04e0a066711f4f5b44 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 28 Feb 2019 18:59:42 +0100 Subject: virtio-scsi: Fix build with gcc 9 Build fails with gcc 9: CC ppc64-softmmu/hw/scsi/virtio-scsi.o hw/scsi/virtio-scsi.c: In function ‘virtio_scsi_do_tmf’: hw/scsi/virtio-scsi.c:265:39: error: taking address of packed member of ‘struct virtio_scsi_ctrl_tmf_req’ may result in an unaligned pointer value [-Werror=address-of-packed-member] 265 | virtio_tswap32s(VIRTIO_DEVICE(s), &req->req.tmf.subtype); | ^~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors All the fields in struct virtio_scsi_ctrl_tmf_req are naturally aligned, so we could in theory drop QEMU_PACKED. Unfortunately, the header file is imported from linux which already has the packed attribute. Trying to fix that in the update-linux-headers.sh script is likely to produce ugliness. Turn the call to virtio_tswap32s() into an assignment instead. Signed-off-by: Greg Kurz Message-Id: <155137678223.44753.5438092367451176318.stgit@bahia.lan> Signed-off-by: Paolo Bonzini --- hw/scsi/virtio-scsi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index ce99d288b0..839f120256 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -262,7 +262,13 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ req->resp.tmf.response = VIRTIO_SCSI_S_OK; - virtio_tswap32s(VIRTIO_DEVICE(s), &req->req.tmf.subtype); + /* + * req->req.tmf has the QEMU_PACKED attribute. Don't use virtio_tswap32s() + * to avoid compiler errors. + */ + req->req.tmf.subtype = + virtio_tswap32(VIRTIO_DEVICE(s), req->req.tmf.subtype); + switch (req->req.tmf.subtype) { case VIRTIO_SCSI_T_TMF_ABORT_TASK: case VIRTIO_SCSI_T_TMF_QUERY_TASK: -- cgit v1.2.3-55-g7522 From 12dd89f7006dc1208f6310600d98621e8e1ac0e6 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Fri, 15 Feb 2019 20:40:21 +0100 Subject: lsi: implement basic SBCL functionality HP-UX checks this register after sending data to the target. If there's no valid information present, it assumes the client disconnected because the kernel sent to much data. Implement at least some of the SBCL functionality that is possible without having a real SCSI bus. Signed-off-by: Sven Schnelle Message-Id: <20190215194021.20543-1-svens@stackframe.org> Signed-off-by: Paolo Bonzini --- hw/scsi/lsi53c895a.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 89def1421f..8ba07f8756 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -160,6 +160,11 @@ static const char *names[] = { #define LSI_CCNTL1_DDAC 0x08 #define LSI_CCNTL1_ZMOD 0x80 +#define LSI_SBCL_ATN 0x08 +#define LSI_SBCL_BSY 0x20 +#define LSI_SBCL_ACK 0x40 +#define LSI_SBCL_REQ 0x80 + /* Enable Response to Reselection */ #define LSI_SCID_RRE 0x60 @@ -258,6 +263,7 @@ typedef struct { uint8_t sdid; uint8_t ssid; uint8_t sfbr; + uint8_t sbcl; uint8_t stest1; uint8_t stest2; uint8_t stest3; @@ -356,6 +362,7 @@ static void lsi_soft_reset(LSIState *s) s->socl = 0; s->sdid = 0; s->ssid = 0; + s->sbcl = 0; s->stest1 = 0; s->stest2 = 0; s->stest3 = 0; @@ -530,6 +537,8 @@ static void lsi_script_dma_interrupt(LSIState *s, int stat) static inline void lsi_set_phase(LSIState *s, int phase) { + s->sbcl &= ~PHASE_MASK; + s->sbcl |= phase | LSI_SBCL_REQ; s->sstat1 = (s->sstat1 & ~PHASE_MASK) | phase; } @@ -567,6 +576,7 @@ static void lsi_disconnect(LSIState *s) { s->scntl1 &= ~LSI_SCNTL1_CON; s->sstat1 &= ~PHASE_MASK; + s->sbcl = 0; } static void lsi_bad_selection(LSIState *s, uint32_t id) @@ -1265,7 +1275,9 @@ again: s->scntl1 |= LSI_SCNTL1_CON; if (insn & (1 << 3)) { s->socl |= LSI_SOCL_ATN; + s->sbcl |= LSI_SBCL_ATN; } + s->sbcl |= LSI_SBCL_BSY; lsi_set_phase(s, PHASE_MO); break; case 1: /* Disconnect */ @@ -1297,8 +1309,14 @@ again: insn & (1 << 10) ? " CC" : ""); if (insn & (1 << 3)) { s->socl |= LSI_SOCL_ATN; + s->sbcl |= LSI_SBCL_ATN; lsi_set_phase(s, PHASE_MO); } + + if (insn & (1 << 6)) { + s->sbcl |= LSI_SBCL_ACK; + } + if (insn & (1 << 9)) { qemu_log_mask(LOG_UNIMP, "lsi_scsi: Target mode not implemented\n"); @@ -1314,7 +1332,13 @@ again: insn & (1 << 10) ? " CC" : ""); if (insn & (1 << 3)) { s->socl &= ~LSI_SOCL_ATN; + s->sbcl &= ~LSI_SBCL_ATN; } + + if (insn & (1 << 6)) { + s->sbcl &= ~LSI_SBCL_ACK; + } + if (insn & (1 << 10)) s->carry = 0; break; @@ -1591,9 +1615,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) ret = s->ssid; break; case 0xb: /* SBCL */ - /* ??? This is not correct. However it's (hopefully) only - used for diagnostics, so should be ok. */ - ret = 0; + ret = s->sbcl; break; case 0xc: /* DSTAT */ ret = s->dstat | LSI_DSTAT_DFE; @@ -2143,7 +2165,7 @@ static int lsi_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_lsi_scsi = { .name = "lsiscsi", - .version_id = 0, + .version_id = 1, .minimum_version_id = 0, .pre_save = lsi_pre_save, .post_load = lsi_post_load, @@ -2202,6 +2224,7 @@ static const VMStateDescription vmstate_lsi_scsi = { VMSTATE_UINT8(stime0, LSIState), VMSTATE_UINT8(respid0, LSIState), VMSTATE_UINT8(respid1, LSIState), + VMSTATE_UINT8_V(sbcl, LSIState, 1), VMSTATE_UINT32(mmrs, LSIState), VMSTATE_UINT32(mmws, LSIState), VMSTATE_UINT32(sfs, LSIState), -- cgit v1.2.3-55-g7522 From 2265e98b72df477a38271787485e2cd33df212b4 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sun, 17 Feb 2019 12:37:17 +0100 Subject: lsi: check if SIGP bit is already set in Wait reselect If SIGP is set, the 'Wait for Reselection' command should jump immediately to the address stored in the second DWORD of the instruction. This fixes spurious hangs in the HP-UX 11.11 installer when the SIGP bit gets set by the kernel before the 'Wait for Reselection' command is executed by SCRIPTS. Signed-off-by: Sven Schnelle Tested-by: Helge Deller Message-Id: <20190217113717.7077-1-svens@stackframe.org> Signed-off-by: Paolo Bonzini --- hw/scsi/lsi53c895a.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 8ba07f8756..bcff859bac 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -1297,8 +1297,10 @@ again: } break; case 2: /* Wait Reselect */ - if (!lsi_irq_on_rsl(s)) { - lsi_wait_reselect(s); + if (s->istat0 & LSI_ISTAT0_SIGP) { + s->dsp = s->dnad; + } else if (!lsi_irq_on_rsl(s)) { + lsi_wait_reselect(s); } break; case 3: /* Set */ -- cgit v1.2.3-55-g7522 From c8350ebd6789c9b7641e84d03fbf0f6dd3aacf60 Mon Sep 17 00:00:00 2001 From: David Kiarie Date: Mon, 4 Mar 2019 18:18:27 +0300 Subject: update copyright notice Signed-off-by: David Kiarie Message-Id: <20190304151827.1813-2-davidkiarie4@gmail.com> Signed-off-by: Paolo Bonzini --- hw/i386/amd_iommu.c | 2 +- hw/i386/amd_iommu.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 8ad707aba0..6eabdf9917 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -2,7 +2,7 @@ * QEMU emulation of AMD IOMMU (AMD-Vi) * * Copyright (C) 2011 Eduard - Gabriel Munteanu - * Copyright (C) 2015 David Kiarie, + * Copyright (C) 2015, 2016 David Kiarie Kahurani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h index c52886f3ed..0ff9095f32 100644 --- a/hw/i386/amd_iommu.h +++ b/hw/i386/amd_iommu.h @@ -2,7 +2,7 @@ * QEMU emulation of an AMD IOMMU (AMD-Vi) * * Copyright (C) 2011 Eduard - Gabriel Munteanu - * Copyright (C) 2015 David Kiarie, + * Copyright (C) 2015, 2016 David Kiarie Kahurani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3-55-g7522 From 1505421a48a75a36d2b421355d11d7c47d76c6d0 Mon Sep 17 00:00:00 2001 From: Zhengui Li Date: Thu, 7 Mar 2019 17:12:46 +0800 Subject: scsi-disk: Fix crash if request is invaild or disk is no medium Qemu will crash with the assertion error that "assert(r->req.aiocb != NULL)" in scsi_read_complete if request is invaild or disk is no medium. The error is below: qemu-kvm: hw/scsi/scsi_disk.c:299: scsi_read_complete: Assertion `r->req.aiocb != NULL' failed. This patch add a funtion scsi_read_complete_noio to fix it. Signed-off-by: Zhengui Li Message-Id: <1551949966-20092-1-git-send-email-lizhengui@huawei.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'hw') diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index d4e83aef0e..e7e865ab3b 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -296,22 +296,15 @@ static void scsi_dma_complete(void *opaque, int ret) aio_context_release(blk_get_aio_context(s->qdev.conf.blk)); } -static void scsi_read_complete(void * opaque, int ret) +static void scsi_read_complete_noio(SCSIDiskReq *r, int ret) { - SCSIDiskReq *r = (SCSIDiskReq *)opaque; - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - int n; + uint32_t n; - assert(r->req.aiocb != NULL); - r->req.aiocb = NULL; - aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); - if (scsi_disk_req_check_error(r, ret, true)) { + assert(r->req.aiocb == NULL); + if (scsi_disk_req_check_error(r, ret, false)) { goto done; } - block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); - trace_scsi_disk_read_complete(r->req.tag, r->qiov.size); - n = r->qiov.size / 512; r->sector += n; r->sector_count -= n; @@ -319,6 +312,24 @@ static void scsi_read_complete(void * opaque, int ret) done: scsi_req_unref(&r->req); +} + +static void scsi_read_complete(void *opaque, int ret) +{ + SCSIDiskReq *r = (SCSIDiskReq *)opaque; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + assert(r->req.aiocb != NULL); + r->req.aiocb = NULL; + + aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk)); + if (ret < 0) { + block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct); + } else { + block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct); + trace_scsi_disk_read_complete(r->req.tag, r->qiov.size); + } + scsi_read_complete_noio(r, ret); aio_context_release(blk_get_aio_context(s->qdev.conf.blk)); } @@ -395,12 +406,12 @@ static void scsi_read_data(SCSIRequest *req) scsi_req_ref(&r->req); if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { trace_scsi_disk_read_data_invalid(); - scsi_read_complete(r, -EINVAL); + scsi_read_complete_noio(r, -EINVAL); return; } if (!blk_is_available(req->dev->conf.blk)) { - scsi_read_complete(r, -ENOMEDIUM); + scsi_read_complete_noio(r, -ENOMEDIUM); return; } -- cgit v1.2.3-55-g7522 From 811a75ba51fccc8b365bafe8d79d6043ce0566e4 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 5 Mar 2019 20:55:15 +0100 Subject: lsi: use ldn_le_p()/stn_le_p() Instead of using the open-coded versions, use the helper already present as this makes the code easier to read and less error-prone. Signed-off-by: Sven Schnelle Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190305195519.24303-2-svens@stackframe.org> --- hw/scsi/lsi53c895a.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index bcff859bac..402b78507f 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -289,8 +289,7 @@ typedef struct { uint8_t sbr; uint32_t adder; - /* Script ram is stored as 32-bit words in host byteorder. */ - uint32_t script_ram[2048]; + uint8_t script_ram[2048 * sizeof(uint32_t)]; } LSIState; #define TYPE_LSI53C810 "lsi53c810" @@ -2079,29 +2078,14 @@ static void lsi_ram_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { LSIState *s = opaque; - uint32_t newval; - uint32_t mask; - int shift; - - newval = s->script_ram[addr >> 2]; - shift = (addr & 3) * 8; - mask = ((uint64_t)1 << (size * 8)) - 1; - newval &= ~(mask << shift); - newval |= val << shift; - s->script_ram[addr >> 2] = newval; + stn_le_p(s->script_ram + addr, size, val); } static uint64_t lsi_ram_read(void *opaque, hwaddr addr, unsigned size) { LSIState *s = opaque; - uint32_t val; - uint32_t mask; - - val = s->script_ram[addr >> 2]; - mask = ((uint64_t)1 << (size * 8)) - 1; - val >>= (addr & 3) * 8; - return val & mask; + return ldn_le_p(s->script_ram + addr, size); } static const MemoryRegionOps lsi_ram_ops = { @@ -2244,7 +2228,7 @@ static const VMStateDescription vmstate_lsi_scsi = { VMSTATE_BUFFER_UNSAFE(scratch, LSIState, 0, 18 * sizeof(uint32_t)), VMSTATE_UINT8(sbr, LSIState), - VMSTATE_BUFFER_UNSAFE(script_ram, LSIState, 0, 2048 * sizeof(uint32_t)), + VMSTATE_BUFFER_UNSAFE(script_ram, LSIState, 0, 8192), VMSTATE_END_OF_LIST() } }; -- cgit v1.2.3-55-g7522 From f08ec2b82a7de4f988d4def0f7c1ee69f47ceeee Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 5 Mar 2019 20:55:16 +0100 Subject: lsi: use enum type for s->waiting This makes the code easier to read - no functional change. Signed-off-by: Sven Schnelle Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190305195519.24303-3-svens@stackframe.org> --- hw/scsi/lsi53c895a.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 402b78507f..c17bb4f1f1 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -194,6 +194,13 @@ typedef struct lsi_request { QTAILQ_ENTRY(lsi_request) next; } lsi_request; +enum { + LSI_NOWAIT, /* SCRIPTS are running or stopped */ + LSI_WAIT_RESELECT, /* Wait Reselect instruction has been issued */ + LSI_DMA_SCRIPTS, /* processing DMA from lsi_execute_script */ + LSI_DMA_IN_PROGRESS, /* DMA operation is in progress */ +}; + typedef struct { /*< private >*/ PCIDevice parent_obj; @@ -212,10 +219,6 @@ typedef struct { int msg_action; int msg_len; uint8_t msg[LSI_MAX_MSGIN_LEN]; - /* 0 if SCRIPTS are running or stopped. - * 1 if a Wait Reselect instruction has been issued. - * 2 if processing DMA from lsi_execute_script. - * 3 if a DMA operation is in progress. */ int waiting; SCSIBus bus; int current_lun; @@ -322,7 +325,7 @@ static void lsi_soft_reset(LSIState *s) s->msg_action = 0; s->msg_len = 0; - s->waiting = 0; + s->waiting = LSI_NOWAIT; s->dsa = 0; s->dnad = 0; s->dbc = 0; @@ -564,10 +567,10 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase) static void lsi_resume_script(LSIState *s) { if (s->waiting != 2) { - s->waiting = 0; + s->waiting = LSI_NOWAIT; lsi_execute_script(s); } else { - s->waiting = 0; + s->waiting = LSI_NOWAIT; } } @@ -744,7 +747,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len) Since no interrupt stacking is implemented in the emulation, it is also required that there are no pending interrupts waiting for service from the device driver. */ - if (s->waiting == 1 || + if (s->waiting == LSI_WAIT_RESELECT || (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) && !(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) { /* Reselect device. */ @@ -789,7 +792,7 @@ static void lsi_transfer_data(SCSIRequest *req, uint32_t len) int out; assert(req->hba_private); - if (s->waiting == 1 || req->hba_private != s->current || + if (s->waiting == LSI_WAIT_RESELECT || req->hba_private != s->current || (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) { if (lsi_queue_req(s, req, len)) { return; @@ -803,7 +806,7 @@ static void lsi_transfer_data(SCSIRequest *req, uint32_t len) s->current->dma_len = len; s->command_complete = 1; if (s->waiting) { - if (s->waiting == 1 || s->dbc == 0) { + if (s->waiting == LSI_WAIT_RESELECT || s->dbc == 0) { lsi_resume_script(s); } else { lsi_do_dma(s, out); @@ -1093,7 +1096,7 @@ static void lsi_wait_reselect(LSIState *s) lsi_reselect(s, p); } if (s->current == NULL) { - s->waiting = 1; + s->waiting = LSI_WAIT_RESELECT; } } @@ -1202,16 +1205,16 @@ again: s->dnad64 = addr_high; switch (s->sstat1 & 0x7) { case PHASE_DO: - s->waiting = 2; + s->waiting = LSI_DMA_SCRIPTS; lsi_do_dma(s, 1); if (s->waiting) - s->waiting = 3; + s->waiting = LSI_DMA_IN_PROGRESS; break; case PHASE_DI: - s->waiting = 2; + s->waiting = LSI_DMA_SCRIPTS; lsi_do_dma(s, 0); if (s->waiting) - s->waiting = 3; + s->waiting = LSI_DMA_IN_PROGRESS; break; case PHASE_CMD: lsi_do_command(s); @@ -1278,6 +1281,7 @@ again: } s->sbcl |= LSI_SBCL_BSY; lsi_set_phase(s, PHASE_MO); + s->waiting = LSI_NOWAIT; break; case 1: /* Disconnect */ trace_lsi_execute_script_io_disconnect(); @@ -1544,7 +1548,7 @@ again: } } } - if (insn_processed > 10000 && !s->waiting) { + if (insn_processed > 10000 && s->waiting == LSI_NOWAIT) { /* Some windows drivers make the device spin waiting for a memory location to change. If we have been executed a lot of code then assume this is the case and force an unexpected device disconnect. @@ -1556,7 +1560,7 @@ again: } lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); lsi_disconnect(s); - } else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) { + } else if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) { if (s->dcntl & LSI_DCNTL_SSM) { lsi_script_dma_interrupt(s, LSI_DSTAT_SSI); } else { @@ -1887,9 +1891,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) s->istat0 &= ~LSI_ISTAT0_INTF; lsi_update_irq(s); } - if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) { + if (s->waiting == LSI_WAIT_RESELECT && val & LSI_ISTAT0_SIGP) { trace_lsi_awoken(); - s->waiting = 0; + s->waiting = LSI_NOWAIT; s->dsp = s->dnad; lsi_execute_script(s); } -- cgit v1.2.3-55-g7522 From 4ae63d371ef4a1ebc9d07fe88ccfd4981aa1ee4b Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 5 Mar 2019 20:55:17 +0100 Subject: lsi: use enum type for s->msg_action This makes the code easier to read - no functional change. Signed-off-by: Sven Schnelle Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190305195519.24303-4-svens@stackframe.org> --- hw/scsi/lsi53c895a.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index c17bb4f1f1..d67584e84a 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -201,6 +201,13 @@ enum { LSI_DMA_IN_PROGRESS, /* DMA operation is in progress */ }; +enum { + LSI_MSG_ACTION_COMMAND = 0, + LSI_MSG_ACTION_DISCONNECT = 1, + LSI_MSG_ACTION_DOUT = 2, + LSI_MSG_ACTION_DIN = 3, +}; + typedef struct { /*< private >*/ PCIDevice parent_obj; @@ -214,8 +221,6 @@ typedef struct { int carry; /* ??? Should this be an a visible register somewhere? */ int status; - /* Action to take at the end of a MSG IN phase. - 0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN. */ int msg_action; int msg_len; uint8_t msg[LSI_MAX_MSGIN_LEN]; @@ -323,7 +328,7 @@ static void lsi_soft_reset(LSIState *s) trace_lsi_reset(); s->carry = 0; - s->msg_action = 0; + s->msg_action = LSI_MSG_ACTION_COMMAND; s->msg_len = 0; s->waiting = LSI_NOWAIT; s->dsa = 0; @@ -686,7 +691,7 @@ static void lsi_reselect(LSIState *s, lsi_request *p) trace_lsi_reselect(id); s->scntl1 |= LSI_SCNTL1_CON; lsi_set_phase(s, PHASE_MI); - s->msg_action = p->out ? 2 : 3; + s->msg_action = p->out ? LSI_MSG_ACTION_DOUT : LSI_MSG_ACTION_DIN; s->current->dma_len = p->pending; lsi_add_msg_byte(s, 0x80); if (s->current->tag & LSI_TAG_VALID) { @@ -857,7 +862,7 @@ static void lsi_do_command(LSIState *s) lsi_add_msg_byte(s, 4); /* DISCONNECT */ /* wait data */ lsi_set_phase(s, PHASE_MI); - s->msg_action = 1; + s->msg_action = LSI_MSG_ACTION_DISCONNECT; lsi_queue_command(s); } else { /* wait command complete */ @@ -878,7 +883,7 @@ static void lsi_do_status(LSIState *s) s->sfbr = status; pci_dma_write(PCI_DEVICE(s), s->dnad, &status, 1); lsi_set_phase(s, PHASE_MI); - s->msg_action = 1; + s->msg_action = LSI_MSG_ACTION_DISCONNECT; lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */ } @@ -901,16 +906,16 @@ static void lsi_do_msgin(LSIState *s) /* ??? Check if ATN (not yet implemented) is asserted and maybe switch to PHASE_MO. */ switch (s->msg_action) { - case 0: + case LSI_MSG_ACTION_COMMAND: lsi_set_phase(s, PHASE_CMD); break; - case 1: + case LSI_MSG_ACTION_DISCONNECT: lsi_disconnect(s); break; - case 2: + case LSI_MSG_ACTION_DOUT: lsi_set_phase(s, PHASE_DO); break; - case 3: + case LSI_MSG_ACTION_DIN: lsi_set_phase(s, PHASE_DI); break; default: @@ -1062,7 +1067,7 @@ bad: qemu_log_mask(LOG_UNIMP, "Unimplemented message 0x%02x\n", msg); lsi_set_phase(s, PHASE_MI); lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */ - s->msg_action = 0; + s->msg_action = LSI_MSG_ACTION_COMMAND; } #define LSI_BUF_SIZE 4096 -- cgit v1.2.3-55-g7522 From 82cf2bcfe67c8802c186cfe3332efe43042e2478 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 5 Mar 2019 20:55:18 +0100 Subject: lsi: use SCSI phase names instead of numbers in trace This makes trace logs much easier to read, especially for people who are not fluent in SCSI. Signed-off-by: Sven Schnelle Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20190305195519.24303-5-svens@stackframe.org> --- hw/scsi/lsi53c895a.c | 31 +++++++++++++++++++++++-------- hw/scsi/trace-events | 6 +++--- 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index d67584e84a..66f217f8f6 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -306,6 +306,22 @@ typedef struct { #define LSI53C895A(obj) \ OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A) +static const char *scsi_phases[] = { + "DOUT", + "DIN", + "CMD", + "STATUS", + "RSVOUT", + "RSVIN", + "MSGOUT", + "MSGIN" +}; + +static const char *scsi_phase_name(int phase) +{ + return scsi_phases[phase & PHASE_MASK]; +} + static inline int lsi_irq_on_rsl(LSIState *s) { return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE); @@ -1201,8 +1217,9 @@ again: s->ia = s->dsp - 12; } if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { - trace_lsi_execute_script_blockmove_badphase(s->sstat1 & PHASE_MASK, - (insn >> 24) & 7); + trace_lsi_execute_script_blockmove_badphase( + scsi_phase_name(s->sstat1), + scsi_phase_name(insn >> 24)); lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0); break; } @@ -1234,8 +1251,8 @@ again: lsi_do_msgin(s); break; default: - qemu_log_mask(LOG_UNIMP, "lsi_scsi: Unimplemented phase %d\n", - s->sstat1 & PHASE_MASK); + qemu_log_mask(LOG_UNIMP, "lsi_scsi: Unimplemented phase %s\n", + scsi_phase_name(s->sstat1)); } s->dfifo = s->dbc & 0xff; s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3); @@ -1463,10 +1480,8 @@ again: cond = s->carry != 0; } if (cond == jmp && (insn & (1 << 17))) { - trace_lsi_execute_script_tc_compp( - (s->sstat1 & PHASE_MASK), - jmp ? '=' : '!', - ((insn >> 24) & 7)); + trace_lsi_execute_script_tc_compp(scsi_phase_name(s->sstat1), + jmp ? '=' : '!', scsi_phase_name(insn >> 24)); cond = (s->sstat1 & PHASE_MASK) == ((insn >> 24) & 7); } if (cond == jmp && (insn & (1 << 18))) { diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index 29aaa752d1..09f3fc3086 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -268,7 +268,7 @@ lsi_memcpy(uint32_t dest, uint32_t src, int count) "memcpy dest 0x%"PRIx32" src lsi_wait_reselect(void) "Wait Reselect" lsi_execute_script(uint32_t dsp, uint32_t insn, uint32_t addr) "SCRIPTS dsp=0x%"PRIx32" opcode 0x%"PRIx32" arg 0x%"PRIx32 lsi_execute_script_blockmove_delayed(void) "Delayed select timeout" -lsi_execute_script_blockmove_badphase(uint8_t phase, uint8_t expected) "Wrong phase got %d expected %d" +lsi_execute_script_blockmove_badphase(const char *phase, const char *expected) "Wrong phase got %s expected %s" lsi_execute_script_io_alreadyreselected(void) "Already reselected, jumping to alternative address" lsi_execute_script_io_selected(uint8_t id, const char *atn) "Selected target %d%s" lsi_execute_script_io_disconnect(void) "Wait Disconnect" @@ -278,8 +278,8 @@ lsi_execute_script_io_opcode(const char *opcode, int reg, const char *opname, ui lsi_execute_script_tc_nop(void) "NOP" lsi_execute_script_tc_delayedselect_timeout(void) "Delayed select timeout" lsi_execute_script_tc_compc(int result) "Compare carry %d" -lsi_execute_script_tc_compp(uint8_t phase, int op, uint8_t insn_phase) "Compare phase %d %c= %d" -lsi_execute_script_tc_compd(uint32_t sfbr, uint8_t mask, int op, int result) "Compare data 0x%"PRIx32" & 0x%x %c= 0x%x" +lsi_execute_script_tc_compp(const char *phase, char op, const char *insn_phase) "Compare phase %s %c= %s" +lsi_execute_script_tc_compd(uint32_t sfbr, uint8_t mask, char op, int result) "Compare data 0x%"PRIx32" & 0x%x %c= 0x%x" lsi_execute_script_tc_jump(uint32_t addr) "Jump to 0x%"PRIx32 lsi_execute_script_tc_call(uint32_t addr) "Call 0x%"PRIx32 lsi_execute_script_tc_return(uint32_t addr) "Return to 0x%"PRIx32 -- cgit v1.2.3-55-g7522 From 07163c99a9870d38d010f3528424525d7f7505b9 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 5 Mar 2019 20:55:19 +0100 Subject: lsi: return dfifo value Code was assigning DFIFO, but didn't return the value to users. Signed-off-by: Sven Schnelle Message-Id: <20190305195519.24303-6-svens@stackframe.org> --- hw/scsi/lsi53c895a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 66f217f8f6..bf6b6a52f1 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -1688,7 +1688,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) break; CASE_GET_REG32(temp, 0x1c) case 0x20: /* DFIFO */ - ret = 0; + ret = s->dfifo; break; case 0x21: /* CTEST4 */ ret = s->ctest4; -- cgit v1.2.3-55-g7522 From e6c165f364c669b1357f15602ae3bd1d12357135 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Mon, 18 Feb 2019 18:55:28 +0100 Subject: lsi: 810/895A are always little endian Signed-off-by: Sven Schnelle Message-Id: <20190218175529.11237-1-svens@stackframe.org> Signed-off-by: Paolo Bonzini --- hw/scsi/lsi53c895a.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index bf6b6a52f1..da7239d94f 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -2084,14 +2084,13 @@ static uint64_t lsi_mmio_read(void *opaque, hwaddr addr, unsigned size) { LSIState *s = opaque; - return lsi_reg_readb(s, addr & 0xff); } static const MemoryRegionOps lsi_mmio_ops = { .read = lsi_mmio_read, .write = lsi_mmio_write, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, .impl = { .min_access_size = 1, .max_access_size = 1, @@ -2115,7 +2114,7 @@ static uint64_t lsi_ram_read(void *opaque, hwaddr addr, static const MemoryRegionOps lsi_ram_ops = { .read = lsi_ram_read, .write = lsi_ram_write, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, }; static uint64_t lsi_io_read(void *opaque, hwaddr addr, @@ -2135,7 +2134,7 @@ static void lsi_io_write(void *opaque, hwaddr addr, static const MemoryRegionOps lsi_io_ops = { .read = lsi_io_read, .write = lsi_io_write, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, .impl = { .min_access_size = 1, .max_access_size = 1, -- cgit v1.2.3-55-g7522