Compare commits

...

126 Commits

Author SHA1 Message Date
Eduardo Habkost
ad904f6689 MAINTAINERS: Add Python scripts
Cleber and I are volunteering to review and queue patches for the
Python scripts and modules in scripts/.

I'm setting "M: Odd fixes" because not all scripts are actively
maintained.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20170915230744.22942-1-ehabkost@redhat.com>
[ehabkost: add tests/*.py too]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2017-09-22 11:39:55 -03:00
Eduardo Habkost
5810314e98 qemu.py: Call logging.basicConfig() automatically
Not all scripts using qemu.py configure the Python logging
module, and end up generating a "No handlers could be found for
logger" message instead of actual log messages.

To avoid requiring every script using qemu.py to configure
logging manually, call basicConfig() when creating a QEMUMachine
object.  This won't affect scripts that already set up logging,
but will ensure that scripts that don't configure logging keep
working.

Reported-by: Kevin Wolf <kwolf@redhat.com>
Fixes: 4738b0a85a
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20170921162234.847-1-ehabkost@redhat.com>
Reviewed-by: Cleber Rosa <crosa@redhat.com>
Acked-by: Lukáš Doktor <ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2017-09-22 11:39:17 -03:00
Peter Maydell
9ee660e7c1 Merge remote-tracking branch 'remotes/yongbok/tags/mips-20170921' into staging
MIPS patches 2017-09-21

Changes:
QOMify MIPS cpu
Improve macro parenthesization

# gpg: Signature made Thu 21 Sep 2017 13:50:37 BST
# gpg:                using RSA key 0x2238EB86D5F797C2
# gpg: Good signature from "Yongbok Kim <yongbok.kim@imgtec.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 8600 4CF5 3415 A5D9 4CFA  2B5C 2238 EB86 D5F7 97C2

* remotes/yongbok/tags/mips-20170921:
  mips: Improve macro parenthesization
  mips: replace cpu_mips_init() with cpu_generic_init()
  mips: MIPSCPU model subclasses
  mips: call cpu_mips_realize_env() from mips_cpu_realizefn()
  mips: split cpu_mips_realize_env() out of cpu_mips_init()
  mips: introduce internal.h and cleanup cpu.h
  mips: move hw/mips/cputimer.c to target/mips/

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-21 14:40:32 +01:00
Eric Blake
2a2be359c4 mips: Improve macro parenthesization
Although none of the existing macro call-sites were broken,
it's always better to write macros that properly parenthesize
arguments that can be complex expressions, so that the intended
order of operations is not broken.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:25:41 +01:00
Igor Mammedov
c4c8146cfd mips: replace cpu_mips_init() with cpu_generic_init()
now cpu_mips_init() reimplements subset of cpu_generic_init()
tasks, so just drop it and use cpu_generic_init() directly.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
[PMD: use internal.h instead of cpu.h]
Tested-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:25:37 +01:00
Igor Mammedov
41da212c9c mips: MIPSCPU model subclasses
Register separate QOM types for each mips cpu model,
so it would be possible to reuse generic CPU creation
routines.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
[PMD: use internal.h, use void* to hold cpu_def in MIPSCPUClass,
 mark MIPSCPU abstract, address Eduardo Habkost review]
Tested-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:25:30 +01:00
Philippe Mathieu-Daudé
df4dc10284 mips: call cpu_mips_realize_env() from mips_cpu_realizefn()
This changes the order between cpu_mips_realize_env() and
cpu_exec_initfn(), but cpu_exec_initfn() don't have anything that
depends on cpu_mips_realize_env() being called first.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:25:27 +01:00
Philippe Mathieu-Daudé
27e38392ca mips: split cpu_mips_realize_env() out of cpu_mips_init()
so it can be used in mips_cpu_realizefn() in the next commit

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:24:34 +01:00
Philippe Mathieu-Daudé
26aa3d9aec mips: introduce internal.h and cleanup cpu.h
no logical change, only code movement (and fix a comment typo).

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: James Hogan <james.hogan@imgtec.com>
Acked-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:24:34 +01:00
Philippe Mathieu-Daudé
5502b66fc7 mips: move hw/mips/cputimer.c to target/mips/
This timer is a required part of the MIPS32/MIPS64 System Control coprocessor
(CP0). Moving it with the other architecture related files will allow an opaque
use of CPUMIPSState* in the next commit (introduce "internal.h").

also remove it from 'user' targets, remove an unnecessary include.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: James Hogan <james.hogan@imgtec.com>
Acked-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
2017-09-21 13:24:34 +01:00
Peter Maydell
ff5667ed53 Merge remote-tracking branch 'remotes/mcayland/tags/qemu-sparc-signed' into staging
qemu-sparc update

# gpg: Signature made Thu 21 Sep 2017 08:42:30 BST
# gpg:                using RSA key 0x5BC2C56FAE0F321F
# gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>"
# Primary key fingerprint: CC62 1AB9 8E82 200D 915C  C9C4 5BC2 C56F AE0F 321F

* remotes/mcayland/tags/qemu-sparc-signed:
  sun4u: use sunhme as default on-board NIC
  net: add Sun HME (Happy Meal Ethernet) on-board NIC

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-21 10:56:09 +01:00
Peter Maydell
211ad3b412 Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20170920-tag' into staging
Xen 2017/09/20

# gpg: Signature made Thu 21 Sep 2017 03:20:02 BST
# gpg:                using RSA key 0x894F8F4870E1AE90
# gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>"
# gpg:                 aka "Stefano Stabellini <sstabellini@kernel.org>"
# Primary key fingerprint: D04E 33AB A51F 67BA 07D3  0AEA 894F 8F48 70E1 AE90

* remotes/sstabellini/tags/xen-20170920-tag:
  xen/pt: allow QEMU to request MSI unmasking at bind time
  xen-disk: use g_new0 to fix build

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-21 10:18:02 +01:00
Mark Cave-Ayland
8d9329719c sun4u: use sunhme as default on-board NIC
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Artyom Tarasenko <atar4qemu@gmail.com>
2017-09-21 08:38:42 +01:00
Mark Cave-Ayland
c110425d16 net: add Sun HME (Happy Meal Ethernet) on-board NIC
Enable it by default for the sparc64-softmmu configuration.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Artyom Tarasenko <atar4qemu@gmail.com>
2017-09-21 08:38:42 +01:00
Roger Pau Monne
a803633660 xen/pt: allow QEMU to request MSI unmasking at bind time
When a MSI interrupt is bound to a guest using
xc_domain_update_msi_irq (XEN_DOMCTL_bind_pt_irq) the interrupt is
left masked by default.

This causes problems with guests that first configure interrupts and
clean the per-entry MSIX table mask bit and afterwards enable MSIX
globally. In such scenario the Xen internal msixtbl handlers would not
detect the unmasking of MSIX entries because vectors are not yet
registered since MSIX is not enabled, and vectors would be left
masked.

Introduce a new flag in the gflags field to signal Xen whether a MSI
interrupt should be unmasked after being bound.

This also requires to track the mask register for MSI interrupts, so
QEMU can also notify to Xen whether the MSI interrupt should be bound
masked or unmasked

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reported-by: Andreas Kinzler <hfp@posteo.de>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
2017-09-20 19:05:27 -07:00
Olaf Hering
a3fd781f65 xen-disk: use g_new0 to fix build
g_malloc0_n is available since glib-2.24. To allow build with older glib
versions use the generic g_new0, which is already used in many other
places in the code.

Fixes commit 3284fad728 ("xen-disk: add support for multi-page shared rings")

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
2017-09-20 19:05:26 -07:00
Peter Maydell
b62b7ed0fc Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging
These patches fix regressions in 2.10

# gpg: Signature made Wed 20 Sep 2017 07:51:07 BST
# gpg:                using DSA key 0x02FC3AEB0101DBC2
# gpg: Good signature from "Greg Kurz <groug@kaod.org>"
# gpg:                 aka "Greg Kurz <groug@free.fr>"
# gpg:                 aka "Greg Kurz <gkurz@linux.vnet.ibm.com>"
# gpg:                 aka "Gregory Kurz (Groug) <groug@free.fr>"
# gpg:                 aka "[jpeg image of size 3330]"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2BD4 3B44 535E C0A7 9894  DBA2 02FC 3AEB 0101 DBC2

* remotes/gkurz/tags/for-upstream:
  9pfs: check the size of transport buffer before marshaling
  9pfs: fix name_to_path assertion in v9fs_complete_rename()
  9pfs: fix readdir() for 9p2000.u

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-20 20:33:48 +01:00
Peter Maydell
d3f5433c7b Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging
Machine/CPU/NUMA queue, 2017-09-19

# gpg: Signature made Tue 19 Sep 2017 21:17:01 BST
# gpg:                using RSA key 0x2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/machine-next-pull-request:
  MAINTAINERS: Update git URLs for my trees
  hw/acpi-build: Fix SRAT memory building in case of node 0 without RAM
  NUMA: Replace MAX_NODES with nb_numa_nodes in for loop
  numa: cpu: calculate/set default node-ids after all -numa CLI options are parsed
  arm: drop intermediate cpu_model -> cpu type parsing and use cpu type directly
  pc: use generic cpu_model parsing
  vl.c: convert cpu_model to cpu type and set of global properties before machine_init()
  cpu: make cpu_generic_init() abort QEMU on error
  qom: cpus: split cpu_generic_init() on feature parsing and cpu creation parts
  hostmem-file: Add "discard-data" option
  osdep: Define QEMU_MADV_REMOVE
  vl: Clean up user-creatable objects when exiting

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-20 17:35:36 +01:00
Jan Dakinevich
772a73692e 9pfs: check the size of transport buffer before marshaling
v9fs_do_readdir_with_stat() should check for a maximum buffer size
before an attempt to marshal gathered data. Otherwise, buffers assumed
as misconfigured and the transport would be broken.

The patch brings v9fs_do_readdir_with_stat() in conformity with
v9fs_do_readdir() behavior.

Signed-off-by: Jan Dakinevich <jan.dakinevich@gmail.com>
[groug, regression caused my commit 8d37de41ca # 2.10]
Signed-off-by: Greg Kurz <groug@kaod.org>
2017-09-20 08:48:52 +02:00
Jan Dakinevich
4d8bc7334b 9pfs: fix name_to_path assertion in v9fs_complete_rename()
The third parameter of v9fs_co_name_to_path() must not contain `/'
character.

The issue is most likely related to 9p2000.u protocol only.

Signed-off-by: Jan Dakinevich <jan.dakinevich@gmail.com>
[groug, regression caused by commit f57f587857 # 2.10]
Signed-off-by: Greg Kurz <groug@kaod.org>
2017-09-20 08:48:52 +02:00
Jan Dakinevich
6069537f43 9pfs: fix readdir() for 9p2000.u
If the client is using 9p2000.u, the following occurs:

$ cd ${virtfs_shared_dir}
$ mkdir -p a/b/c
$ ls a/b
ls: cannot access 'a/b/a': No such file or directory
ls: cannot access 'a/b/b': No such file or directory
a  b  c

instead of the expected:

$ ls a/b
c

This is a regression introduced by commit f57f5878578a;
local_name_to_path() now resolves ".." and "." in paths,
and v9fs_do_readdir_with_stat()->stat_to_v9stat() then
copies the basename of the resulting path to the response.
With the example above, this means that "." and ".." are
turned into "b" and "a" respectively...

stat_to_v9stat() currently assumes it is passed a full
canonicalized path and uses it to do two different things:
1) to pass it to v9fs_co_readlink() in case the file is a symbolic
   link
2) to set the name field of the V9fsStat structure to the basename
   part of the given path

It only has two users: v9fs_stat() and v9fs_do_readdir_with_stat().

v9fs_stat() really needs 1) and 2) to be performed since it starts
with the full canonicalized path stored in the fid. It is different
for v9fs_do_readdir_with_stat() though because the name we want to
put into the V9fsStat structure is the d_name field of the dirent
actually (ie, we want to keep the "." and ".." special names). So,
we only need 1) in this case.

This patch hence adds a basename argument to stat_to_v9stat(), to
be used to set the name field of the V9fsStat structure, and moves
the basename logic to v9fs_stat().

Signed-off-by: Jan Dakinevich <jan.dakinevich@gmail.com>
(groug, renamed old name argument to path and updated changelog)
Signed-off-by: Greg Kurz <groug@kaod.org>
2017-09-20 08:48:51 +02:00
Peter Maydell
c51700273a Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20170919-v2' into staging
Assorted s390x patches:
- introduce virtio-gpu-ccw, with virtio-gpu endian fixes
- lots of cleanup in the s390x code
- make device_add work for s390x cpus
- enable seccomp on s390x
- an ivshmem endian fix
- set the reserved DHCP client architecture id for netboot
- fixes in the css and pci support

# gpg: Signature made Tue 19 Sep 2017 17:39:45 BST
# gpg:                using RSA key 0xDECF6B93C6F02FAF
# 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-20170919-v2: (38 commits)
  MAINTAINERS/s390x: add terminal3270.c
  virtio-ccw: Create a virtio gpu device for the ccw bus
  virtio-gpu: Handle endian conversion
  s390x/ccw: create s390 phb for compat reasons as well
  configure: Allow --enable-seccomp on s390x, too
  virtio-ccw: remove stale comments on endianness
  s390x: allow CPU hotplug in random core-id order
  s390x: generate sclp cpu information from possible_cpus
  s390x: get rid of cpu_s390x_create()
  s390x: get rid of cpu_states and use possible_cpus instead
  s390x: implement query-hotpluggable-cpus
  s390x: CPU hot unplug via device_del cannot work for now
  s390x: allow cpu hotplug via device_add
  s390x: print CPU definitions in sorted order
  target/s390x: rename next_cpu_id to next_core_id
  target/s390x: use "core-id" for cpu number/address/id handling
  target/s390x: set cpu->id for linux user when realizing
  s390x: allow only 1 CPU with TCG
  target/s390x: use program_interrupt() in per_check_exception()
  target/s390x: use trigger_pgm_exception() in s390_cpu_handle_mmu_fault()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-19 18:08:48 +01:00
Christian Borntraeger
9d1c444921 MAINTAINERS/s390x: add terminal3270.c
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Message-Id: <20170918130455.144262-1-borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
Farhan Ali
1f8ad88935 virtio-ccw: Create a virtio gpu device for the ccw bus
Wire up the virtio-gpu device for the CCW bus. The virtio-gpu
is a virtio-1 device, so disable revision 0.

Signed-off-by: Farhan Ali <alifm@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <6c53f939cf2d64b66d2a6878b29c9bf3820f3d5b.1505485574.git.alifm@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
Farhan Ali
1715d6b59c virtio-gpu: Handle endian conversion
Virtio GPU code currently only supports litte endian format,
and so using the Virtio GPU device on a big endian machine
does not work.

Let's fix it by supporting the correct host cpu byte order.

Signed-off-by: Farhan Ali <alifm@linux.vnet.ibm.com>
Message-Id: <dc748e15f36db808f90b4f2393bc29ba7556a9f6.1505485574.git.alifm@linux.vnet.ibm.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
Cornelia Huck
8ad9087c4a s390x/ccw: create s390 phb for compat reasons as well
d32bd032d8 ("s390x/ccw: create s390 phb conditionally") made
registering the s390 pci host bridge conditional on presense
of the zpci facility bit. Sadly, that breaks migration from
machines that did not use the cpu model (2.7 and previous).

Create the s390 phb for pre-cpu model machines as well: We can
tweak s390_has_feat() to always indicate the zpci facility bit
when no cpu model is available (on 2.7 and previous compat machines).

Fixes: d32bd032d8 ("s390x/ccw: create s390 phb conditionally")
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
Thomas Huth
3aa35fcffc configure: Allow --enable-seccomp on s390x, too
libseccomp supports s390x since version 2.3.0, and I was able to start
a VM with "-sandbox on" without any obvious problems by using this patch,
so it should be safe to allow --enable-seccomp on s390x nowadays, too.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1505385363-27717-1-git-send-email-thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Eduardo Otubo <otubo@redhat.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
Halil Pasic
5ef5475868 virtio-ccw: remove stale comments on endianness
We have two stale comments suggesting one should think about virtio
config space endianness a bit longer. We have just done that, and came to
the conclusion we are fine as is: it's the responsibility of the virtio
device and not of the transport (and that is how it works now). Putting
the responsibility into the transport isn't even possible, because the
transport would have to know about the config space layout of each
device.

Let us remove the stale comments.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Suggested-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20170914105535.47941-1-pasic@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
a1422723f7 s390x: allow CPU hotplug in random core-id order
SCLP correctly indicates the core-id aka. CPU address for each available
CPU.

As the core-id corresponds to cpu_index, also a newly created kvm vcpu
gets assigned this core-id as vcpu id. So SIGP in the kernel works
correctly (it uses the vcpu id to lookup the correct CPU).

So there should be nothing hindering us from hotplugging CPUs in random
core-id order.

This now makes sure that the output from "query-hotpluggable-cpus"
is completely true. Until now, a specific order is implicit. Performance
vice, hotplugging CPUs in non-sequential order might not be the best thing
to do, as VCPU lookup inside KVM might be a little slower. But that
doesn't hinder us from supporting it.

next_core_id is now used by linux user only.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-23-david@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
bb535bb67e s390x: generate sclp cpu information from possible_cpus
This is the first step to allow hot plugging of CPUs in a non-sequential
order. If a cpu is available ("plugged") can directly be decided by
looking at the cpu state pointer.

This makes sure, that really only cpus attached to the machine are
reported.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-22-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
524d18d8bd s390x: get rid of cpu_s390x_create()
Now that there is only one user of cpu_s390x_create() left, make cpu
creation look like on x86.
- Perform the model/properties split and checks in s390_init_cpus()
- Parse features only once without having to remember if already parsed
- Pass only the typename to s390x_new_cpu()
- Use the typename of an existing CPU for hotplug via cpu-add

Acked-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-21-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
2b44178d87 s390x: get rid of cpu_states and use possible_cpus instead
Now that we have possible_cpus, we can get rid of the global variable
and rewrite s390_cpu_addr2state() to use it.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-20-david@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
4dc3b15188 s390x: implement query-hotpluggable-cpus
CPU hotplug is only possible on a per core basis on s390x. So let's
add possible_cpus and wire everything up properly.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-19-david@redhat.com>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
f2f3beb004 s390x: CPU hot unplug via device_del cannot work for now
device_del on a CPU will currently do nothing. Let's emit an error
telling that this is will currently not work (there is no architecture
support on s390x). Error message copied from ppc.

(qemu) device_del cpu1
device_del cpu1
CPU hot unplug not supported on this machine

Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-18-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
0347ab8469 s390x: allow cpu hotplug via device_add
E.g. the following now works:
    device_add host-s390-cpu,id=cpu1,core-id=1

The system will perform the same checks as when using cpu_add:
- If the core_id is already in use
- If the next sequential core_id isn't used
- If core-id >= max_cpu is specified

In addition, mixed CPU models are checked. E.g. if starting with
-cpu host and trying to hotplug "qemu-s390-cpu":
    "Mixed CPU models are not supported on s390x."

Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-17-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
99aa6bf29b s390x: print CPU definitions in sorted order
Other architectures provide nicely sorted lists, let's do it similarly on
s390x.

While at it, clean up the code we have to touch either way.

Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-16-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
b599fef28e target/s390x: rename next_cpu_id to next_core_id
Adapt to the new term "core_id". While at it, fix the type and drop the
initialization to 0 (which is superfluous).

Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-15-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
ca5c1457d6 target/s390x: use "core-id" for cpu number/address/id handling
Some time ago we discussed that using "id" as property name is not the
right thing to do, as it is a reserved property for other devices and
will not work with device_add.

Switch to the term "core-id" instead, and use it as an equivalent to
"CPU address" mentioned in the PoP. There is no such thing as cpu number,
so rename env.cpu_num to env.core_id. We use "core-id" as this is the
common term to use for device_add later on (x86 and ppc).

We can get rid of cpu->id now. Keep cpu_index and env->core_id in sync.
cpu_index was already implicitly used by e.g. cpu_exists(), so keeping
both in sync seems to be the right thing to do.

cpu_index will now no longer automatically get set via
cpu_exec_realizefn(). For now, we were lucky that both implicitly stayed
in sync.

Our new cpu property "core-id" can be a static property. Range checks can
be avoided by using the correct type and the "setting after realized"
check is done implicitly.

device_add will later need the reserved "id" property. Hotplugging a CPU
on s390x will then be: "device_add host-s390-cpu,id=cpu2,core-id=2".

Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-14-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
88556edd74 target/s390x: set cpu->id for linux user when realizing
scc->next_cpu_id is updated when realizing. Setting it just before that
point looks cleaner.

Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-13-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:32 +02:00
David Hildenbrand
b5684cd8c6 s390x: allow only 1 CPU with TCG
Specifying more than 1 CPU (e.g. -smp 5) leads to SIGP errors (the
guest tries to bring these CPUs up but fails), because we don't support
multiple CPUs on s390x under TCG.

Let's bail out if more than 1 is specified, so we don't raise people's
hope.

Tested-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-12-david@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
e0b1a8a14e target/s390x: use program_interrupt() in per_check_exception()
Clean it up by reusing program_interrupt(). Add a concern regarding
ilen.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-11-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
525f4b65c7 target/s390x: use trigger_pgm_exception() in s390_cpu_handle_mmu_fault()
This looks cleaner. linux-user will not use the ilen field, so setting
it doesn't do any harm.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-10-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
53d8e91d64 s390x: move sclp_service_call() to sclp.h
Implemented in sclp.c, so let's move it to the right include file.
Also adjust some includes.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-9-david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
ef2974cc27 target/s390x: move some s390x typedefs to cpu-qom.h
This allows us to drop inclusion of cpu_models.h in cpu-qom.h, and
prepares for using cpu-qom.h as a s390 specific version of typedefs.h

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-8-david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
19c69829d6 s390x: move subsystem_reset() to s390-virtio-ccw.h
Implemented in s390-virtio-ccw.c, so move it to the right header.
We can also drop the extern. Fix up one include.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-7-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
2c98a6c1ca s390x: move s390_virtio_hypercall() to s390-virtio-hcall.h
Implemented in hw/s390x/s390-virtio-hcall.c, so let's move it to the
right header file.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-6-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
7d57754690 s390x: rename s390-virtio.h to s390-virtio-hcall.h
The only interface left, so let's properly rename it.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-5-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
6286b41986 s390x: get rid of s390-virtio.c
It is a leftover from the days where we had still the !ccw virtio
machine. As this one is long gone, let's move everything to
s390-virtio-ccw.c.

Suggested-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-4-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:31:31 +02:00
David Hildenbrand
6fda014e1a cpu: drop old comments describing members
These comments are obviously stale.

Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-3-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
David Hildenbrand
7f579e272f exec,dump,i386,ppc,s390x: don't include exec/cpu-all.h explicitly
All but a handful of files include exec/cpu-all.h via cpu.h only.
As these files already include cpu.h, let's just drop the additional
include.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170913132417.24384-2-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Viktor Mihajlovski
a8fbbf1db7 s390: set DHCP client architecure id for netboot
Setting the client architecture DHCP option to 0x001f (s390 Basic) [1]
allows the DHCP server to return a s390-specific bootfile if wanted.
DHCP servers not configured for the option (or not yet recognizing the
option value) will continue to work as they have done before.

[1] https://www.iana.org/assignments/dhcpv6-parameters

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Message-Id: <1505126027-1704-1-git-send-email-mihajlov@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Halil Pasic
ce4a445388 s390x/css: remove unused error handling branch
The case in question actually never happens. Let us get rid of the dead
code.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Message-Id: <20170908152446.14606-4-pasic@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Halil Pasic
cc6a9f8dc9 s390x/css: fix NULL handling for CCW addresses
Back then in the time of df1fe5bb49 ("s390: Virtual channel subsystem
support.", 2013-01-24) -EIO used to map to a channel-program check (via
the default label of the switch statement).  Then 2dc95b4cac
("s390x/3270: 3270 data stream handling", 2016-04-01) came along
and that changed dramatically.

Let us roll back this undesired side effect, and go back to
channel-program check.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Fixes: 2dc95b4cac "s390x/3270: 3270 data stream handling"
Message-Id: <20170908152446.14606-3-pasic@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Halil Pasic
248b920df9 s390x/css: drop data-check in interpretation
The architecture says that channel-data check is indicating that
an uncorrected storage (memory) error has been detected in regard
to the data residing in main storage (memory) that is currently
used for an I/O operation. The described detection is done using
the CBC technology.

The ccw interpretation code is however generating a channel-data check
effectively when the (device specific) ccw_cb returns -EFAULT.  In case
of virtio-ccw devices this happens when mapping memory fails, or when a
NULL pointer is encountered. So this behavior is not architecture
conform.

Furthermore the best fit for these situations (null pointer, mapping a
piece of guest memory fails) from architectural perspective the condition
described as the channel subsystem refers to a location that is not
available, which when encountered shall result in a channel-program
check.

To fix this, all we have to do is to get rid of the switch case matching
-EFAULT: the default is generating a channel-program check.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Message-Id: <20170908152446.14606-2-pasic@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Thomas Huth
51af0ec9fa hw/misc/ivshmem: Fix ivshmem_recv_msg() to also work on big endian systems
The "slow" ivshmem-tests currently fail when they are running on a
big endian host:

$ uname -m
ppc64
$ V=1 QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 tests/ivshmem-test -m slow
/x86_64/ivshmem/single: OK
/x86_64/ivshmem/hotplug: OK
/x86_64/ivshmem/memdev: OK
/x86_64/ivshmem/pair: OK
/x86_64/ivshmem/server-msi: qemu-system-x86_64:
 -device ivshmem-doorbell,chardev=chr0,vectors=2: server sent invalid ID message
Broken pipe

The problem is that the server side code in ivshmem_server_send_one_msg()
correctly translates all messages IDs into little endian 64-bit values,
but the client side code in the ivshmem_recv_msg() function does not swap
the byte order back. Fix it by passing the value through le64_to_cpu().

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1504100343-26607-1-git-send-email-thuth@redhat.com>
Tested-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Yi Min Zhao
6c5e740247 s390x/pci: add iommu replay callback
Let's introduce iommu replay callback for s390 pci iommu memory region.
Currently we don't need any dma mapping replay. So let it return
directly. This implementation will avoid meaningless loops calling
translation callback.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Reviewed-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com>
Message-Id: <1504606380-49341-4-git-send-email-zyimin@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Yi Min Zhao
01c36195d6 s390x/pci: fixup ind_offset of msix routing entry
The guest uses the mpcifc instruction to register the aibvo of a zpci
device, which is the starting offset of indicators in the indicator
area and thus remains constant. Each msix vector is an offset from the
aibvo. When we map a msix route to an adapter route, we should not
modify the starting offset, but instead add the vector to the starting
offset to get the absolute offset in the specific route.

Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com>
Message-Id: <1504606380-49341-3-git-send-email-zyimin@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:33 +02:00
Yi Min Zhao
ceb7054fd4 s390x/pci: remove idx from msix msg data
PCIDevice pointer has been a parameter of kvm_arch_fixup_msi_route().
So we don't need to store zpci idx in msix message data to find out the
specific zpci device. Instead, we could use pci device id to find its
corresponding zpci device.

Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com>
Message-Id: <1504606380-49341-2-git-send-email-zyimin@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:32 +02:00
Thomas Huth
2f84a92ec6 tests: Enable the drive_del test also on s390x
We can use the drive_del test on s390x, too, to check that adding and
deleting also works fine with the virtio-ccw bus. But we have to make
sure that we use the devices with the "-ccw" suffix instead of the
"-pci" suffix for the virtio-ccw transport on s390x. Introduce a helper
function called qvirtio_get_dev_type() that returns the correct string
for the current architecture.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1504190408-11143-1-git-send-email-thuth@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:32 +02:00
Halil Pasic
6c86462220 s390x/css: fix cc handling for XSCH
The function ioinst_handle_xsch is presenting cc 2 when it's supposed to
present cc 1 and the other way around, because css_do_xsch has the error
codes mixed up. Because cc 1 has precedence over cc 2 we also have to
swap the two checks.

Let us fix this.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reported-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Message-Id: <20170831121828.85885-1-pasic@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2017-09-19 18:21:32 +02:00
Peter Maydell
7ec6a36491 Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* warning improvements (Alistair)
* KVM code cleanup (David)
* scsi-block support for rerror/werror (Fam)
* support for >64 vCPUs in Windows (Gonglei)
* SCSI fix (Hannes)
* SSE bugfixes (Joseph)
* SmartOS compilation fixes (Kamil)
* Hyper-V frequency MSR support (Ladi)
* move more files to accel/tcg (Philippe, Thomas)
* multiboot validation (PJP)
* virtqueue size configuration for virtio-scsi (Richard)
* Hyper-V header cleanup (Roman)
* Maintainer email update (Guangrong)
* checkpatch.pl --branch (Daniel), fixes (Greg)
* introducing scsi/ (me)

# gpg: Signature made Tue 19 Sep 2017 15:21:26 BST
# gpg:                using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream: (51 commits)
  docker: fix creation of archives
  default-configs: Replace $(and ...) with $(call land, ...)
  osdep.h: Prohibit disabling assert() in supported builds
  checkpatch: add hwaddr to @typeList
  accel/hax: move hax-stub.c to accel/stubs/
  target/i386: fix "info mem" for LA57 mode
  scripts: let checkpatch.pl process an entire GIT branch
  update-linux-headers: prepare for hyperv.h removal
  hyperv: add header with protocol definitions
  i386/cpu/hyperv: support over 64 vcpus for windows guests
  Convert remaining single line fprintf() to warn_report()
  Makefile: Remove libqemustub.a
  ptimer-test: do not link to libqemustub.a/libqemuutil.a
  target/mips: Convert VM clock update prints to warn_report
  General warn report fixups
  Convert multi-line fprintf() to warn_report()
  Convert single line fprintf(.../n) to warn_report()
  Convert remaining error_report() to warn_report()
  hw/i386: Improve some of the warning messages
  test-qga: add missing qemu-ga tool dependency
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-19 15:44:07 +01:00
Paolo Bonzini
7437866bfc docker: fix creation of archives
The pixman submodule does not exist anymore, and its removal broke
docker-based tests.  Fix it.

Cc: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Thomas Huth
d321e6d58e default-configs: Replace $(and ...) with $(call land, ...)
Using $(and ...) is dangerous here: It only works as long as the first
argument is set to 'y' or completely unset. It does not work if the
first argument is set to 'n' for example. Let's use the "land" make
function instead which has been written explicitely for this purpose.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1505759538-15365-1-git-send-email-thuth@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Eric Blake
262a69f428 osdep.h: Prohibit disabling assert() in supported builds
We already have several files that knowingly require assert()
to work, sometimes because refactoring the code for proper
error handling has not been tackled yet; there are probably
other files that have a similar situation but with no comments
documenting the same.  In fact, we have places in migration
that handle untrusted input with assertions, where disabling
the assertions risks a worse security hole than the current
behavior of losing the guest to SIGABRT when migration fails
because of the assertion.  Promote our current per-file
safety-valve to instead be project-wide, and expand it to also
cover glib's g_assert().

Note that we do NOT want to encourage 'assert(side-effects);'
(that is a bad practice that prevents copy-and-paste of code to
other projects that CAN disable assertions; plus it costs
unnecessary reviewer mental cycles to remember whether a project
special-cases the crippling of asserts); and we would LIKE to
fix migration to not rely on asserts (but that takes a big code
audit).  But in the meantime, we DO want to send a message
that anyone that disables assertions has to tweak code in order
to compile, making it obvious that they are taking on additional
risk that we are not going to support.  At the same time, leave
comments mentioning NDEBUG in files that we know still need to
be scrubbed, so there is at least something to grep for.

It would be possible to come up with some other mechanism for
doing runtime checking by default, but which does not abort
the program on failure, while leaving side effects in place
(unlike how crippling assert() avoids even the side effects),
perhaps under the name q_verify(); but it was not deemed worth
the effort (developers should not have to learn a replacement
when the standard C macro works just fine, and it would be a lot
of churn for little gain).  The patch specifically uses #error
rather than #warn so that a user is forced to tweak the header
to acknowledge the issue, even when not using a -Werror
compilation.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>

Message-Id: <20170911211320.25385-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Greg Kurz
825bfa0052 checkpatch: add hwaddr to @typeList
The script doesn't know about all possible types and learn them as
it parses the code. If it reaches a line with a type cast but the
type isn't known yet, it is misinterpreted as an identifier.

For example the following line:

    foo = (hwaddr) -1;

results in the following false-positive to be reported:

ERROR: spaces required around that '-' (ctx:VxV)

Let's add this standard QEMU type to the list of pre-known types.

Signed-off-by: Greg Kurz <groug@kaod.org>
Message-Id: <150538015789.8149.10902725348939486674.stgit@bahia.lan>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Philippe Mathieu-Daudé
4c44a007b5 accel/hax: move hax-stub.c to accel/stubs/
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170913221149.30382-1-f4bug@amsat.org>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2017-09-19 16:20:49 +02:00
Paolo Bonzini
128b52e8d1 target/i386: fix "info mem" for LA57 mode
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Daniel P. Berrange
8e1fe1753a scripts: let checkpatch.pl process an entire GIT branch
Currently before submitting a series, devs should run checkpatch.pl
across each patch to be submitted. This can be automated using a
command such as:

  git rebase -i master -x 'git show | ./scripts/checkpatch.pl -'

This is rather long winded to type, so this patch introduces a way
to tell checkpatch.pl to validate a series of GIT revisions.

There are now three modes it can operate in 1) check a patch 2) check a source
file, or 3) check a git branch.

If no flags are given, the mode is determined by checking the args passed to
the command. If the args contain a literal ".." it is treated as a GIT revision
list. If the args end in ".patch" or equal "-" it is treated as a patch file.
Otherwise it is treated as a source file.

This automatic guessing can be overridden using --[no-]patch --[no-]file or
--[no-]branch

For example to check a GIT revision list:

    $ ./scripts/checkpatch.pl master..
    total: 0 errors, 0 warnings, 297 lines checked

    b886d352a2bf58f0996471fb3991a138373a2957 has no obvious style problems and is ready for submission.
    total: 0 errors, 0 warnings, 182 lines checked

    2a731f9a9ce145e0e0df6d42dd2a3ce4dfc543fa has no obvious style problems and is ready for submission.
    total: 0 errors, 0 warnings, 102 lines checked

    11844169bcc0c8ed4449eb3744a69877ed329dd7 has no obvious style problems and is ready for submission.

If a genuine patch filename contains the characters '..' it is
possible to force interpretation of the arg as a patch

  $ ./scripts/checkpatch.pl --patch master..

will force it to load a patch file called "master..", or equivalently

  $ ./scripts/checkpatch.pl --no-branch master..

will simply turn off guessing of GIT revision lists.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20170913091000.9005-1-berrange@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Roman Kagan
40bf8e9aed update-linux-headers: prepare for hyperv.h removal
All definitions related to Hyper-V emulation are now taken from the QEMU
own header, so the one imported from the kernel is no longer needed.

Unfortunately it's included by kvm_para.h.

So, until this is fixed in the kernel, teach the header harvesting
script to substitute kernel's hyperv.h with a dummy.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Message-Id: <20170713201522.13765-3-rkagan@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Roman Kagan
5e95381260 hyperv: add header with protocol definitions
The definitions for Hyper-V emulation are currently taken from a header
imported from the Linux kernel.

However, as these describe a third-party protocol rather than a kernel
API, it probably wasn't a good idea to publish it in the kernel uapi.

This patch introduces a header that provides all the necessary
definitions, superseding the one coming from the kernel.

The new header supports (temporary) coexistence with the kernel one.
The constants explicitly named in the Hyper-V specification (e.g. msr
numbers) are defined in a non-conflicting way.  Other constants and
types have got new names.

While at this, the protocol data structures are defined in a more
conventional way, without bitfields, enums, and excessive unions.

The code using this stuff is adjusted, too; it can now be built both
with and without the kernel header in the tree.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Message-Id: <20170713201522.13765-2-rkagan@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Gonglei
6c69dfb67e i386/cpu/hyperv: support over 64 vcpus for windows guests
Starting with Windows Server 2012 and Windows 8, if
CPUID.40000005.EAX contains a value of -1, Windows assumes specific
limit to the number of VPs. In this case, Windows Server 2012
guest VMs may use more than 64 VPs, up to the maximum supported
number of processors applicable to the specific Windows
version being used.

https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs

For compatibility, Let's introduce a new property for X86CPU,
named "x-hv-max-vps" as Eduardo's suggestion, and set it
to 0x40 before machine 2.10.

(The "x-" prefix indicates that the property is not supposed to
be a stable user interface.)

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Message-Id: <1505143227-14324-1-git-send-email-arei.gonglei@huawei.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Alistair Francis
05cb8ed546 Convert remaining single line fprintf() to warn_report()
Convert any remaining uses of fprintf(stderr, "warning:"...
to use warn_report() instead. This helps standardise on a single
method of printing warnings to the user.

All of the warnings were changed using this command:
  find ./* -type f -exec sed -i 's|fprintf(.*".*warning[,:] |warn_report("|Ig' {} +

The #include lines and chagnes to the test Makefile were manually
updated to allow the code to compile.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Message-Id: <2c94ac3bb116cc6b8ebbcd66a254920a69665515.1503077821.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:49 +02:00
Paolo Bonzini
ebedb37c8d Makefile: Remove libqemustub.a
Using two libraries (libqemuutil.a and libqemustub.a) would sometimes
result in circular dependencies. To avoid these issues let's just
combine both into a single library that functions as both.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Message-Id: <54e6458745493d10901964624479a7d9a872f481.1503077821.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:20:31 +02:00
Paolo Bonzini
9ee24e98d3 ptimer-test: do not link to libqemustub.a/libqemuutil.a
This test provides its own mocks, so do not use the "standard"
stubs in libqemustub.a or the event loop implementation in
libqemuutil.a.

This is required on OS X, which otherwise brings in qemu-timer.o,
async.o and main-loop.o from libqemuutil.a.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 16:19:39 +02:00
Alistair Francis
288cb9490b target/mips: Convert VM clock update prints to warn_report
Convert the fprintf() messages in kvm_mips_update_state() to use
warn_report() as they aren't errors, but are just warnings.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: James Hogan <james.hogan@imgtec.com>
Message-Id: <e6acff8db6d264f913a18c86858b9aa600554e51.1505158760.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
Alistair Francis
b62e39b469 General warn report fixups
Tidy up some of the warn_report() messages after having converted them
to use warn_report().

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <9cb1d23551898c9c9a5f84da6773e99871285120.1505158760.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
Alistair Francis
8297be80f7 Convert multi-line fprintf() to warn_report()
Convert all the multi-line uses of fprintf(stderr, "warning:"..."\n"...
to use warn_report() instead. This helps standardise on a single
method of printing warnings to the user.

All of the warnings were changed using these commands:
  find ./* -type f -exec sed -i \
    'N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +
  find ./* -type f -exec sed -i \
    'N;N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +
  find ./* -type f -exec sed -i \
    'N;N;N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +
  find ./* -type f -exec sed -i \
    'N;N;N;N {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +
  find ./* -type f -exec sed -i \
    'N;N;N;N;N {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +
  find ./* -type f -exec sed -i \
    'N;N;N;N;N;N {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +
  find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N; {s|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig}' \
    {} +

Indentation fixed up manually afterwards.

Some of the lines were manually edited to reduce the line length to below
80 charecters. Some of the lines with newlines in the middle of the
string were also manually edit to avoid checkpatch errrors.

The #include lines were manually updated to allow the code to compile.

Several of the warning messages can be improved after this patch, to
keep this patch mechanical this has been moved into a later patch.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: Cornelia Huck <cohuck@redhat.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Jason Wang <jasowang@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <5def63849ca8f551630c6f2b45bcb1c482f765a6.1505158760.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
Alistair Francis
2ab4b13563 Convert single line fprintf(.../n) to warn_report()
Convert all the single line uses of fprintf(stderr, "warning:"..."\n"...
to use warn_report() instead. This helps standardise on a single
method of printing warnings to the user.

All of the warnings were changed using this command:
  find ./* -type f -exec sed -i \
    's|fprintf(.*".*warning[,:] \(.*\)\\n"\(.*\));|warn_report("\1"\2);|Ig' \
    {} +

Some of the lines were manually edited to reduce the line length to below
80 charecters.

The #include lines were manually updated to allow the code to compile.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Michael Roth <mdroth@linux.vnet.ibm.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: James Hogan <james.hogan@imgtec.com> [mips]
Message-Id: <ae8f8a7f0a88ded61743dff2adade21f8122a9e7.1505158760.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
Alistair Francis
55d527a94d Convert remaining error_report() to warn_report()
In a previous patch (3dc6f86936) we
converted uses of error_report("warning:"... to use warn_report()
instead. This was to help standardise on a single method of printing
warnings to the user.

There appears to have been some cases that slipped through in patch sets
applied around the same time, this patch catches the few remaining
cases.

All of the warnings were changed using this command:
  find ./* -type f -exec sed -i \
    's|error_report(".*warning[,:] |warn_report("|Ig' {} +

Indentation fixed up manually afterwards.

Two messages were manually fixed up as well.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Cornelia Huck <cohuck@redhat.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <eec8cba0d5434bd828639e5e45f12182490ff47d.1505158760.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
Alistair Francis
9e5d2c5273 hw/i386: Improve some of the warning messages
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Suggested-by: Eduardo Habkost <ehabkost@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <1d6ef2ccd9667878ed5820fcf17eef35957ea5d8.1505158760.git.alistair.francis@xilinx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
Philippe Mathieu-Daudé
4be75077b9 test-qga: add missing qemu-ga tool dependency
this fixes running 'make check-unit' without running 'make all' beforehand:

$ make check-unit
  ...
  GTESTER tests/test-qga
**
ERROR:tests/test-qga.c:73:fixture_setup: assertion failed (error == NULL): Failed to execute child process "/build/qemu/qemu-ga" (No such file or directory) (g-exec-error-quark, 8)
make: *** [check-tests/test-qga] Error 1

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170911210129.5874-1-f4bug@amsat.org>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
David Hildenbrand
67548f0965 kvm: kvm_log_sync() is only called with known memory sections
Flatview will make sure that we can only end up in this function with
memory sections that correspond to exactly one slot. So we don't
have to iterate multiple times. There won't be overlapping slots but
only matching slots.

Properly align the section and look up the corresponding slot. This
heavily simplifies this function.

We can now get rid of kvm_lookup_overlapping_slot().

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-7-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:34 +02:00
David Hildenbrand
343562e8fa kvm: kvm_log_start/stop are only called with known sections
Let's properly align the sections first and bail out if we would ever
get called with a memory section we don't know yet.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-6-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
David Hildenbrand
f357f564be kvm: we never have overlapping slots in kvm_set_phys_mem()
The way flatview handles memory sections, we will never have overlapping
memory sections in kvm.

address_space_update_topology_pass() will make sure that we will only
get called for

a) an existing memory section for which we only update parameters
(log_start, log_stop).
b) an existing memory section we want to delete (region_del)
c) a brand new memory section we want to add (region_add)

We cannot have overlapping memory sections in kvm as we will first remove
the overlapping sections and then add the ones without conflicts.

Therefore we can remove the complexity for handling prefix and suffix
slots.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-5-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
David Hildenbrand
2747e71672 kvm: use start + size for memory ranges
Convert kvm_lookup_matching_slot().

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-4-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
David Hildenbrand
5ea69c2e36 kvm: factor out alignment of memory section
Factor it out, so we can reuse it later.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-3-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
David Hildenbrand
89de4b9138 kvm: require JOIN_MEMORY_REGIONS_WORKS
We already require DESTROY_MEMORY_REGION_WORKS, JOIN_MEMORY_REGIONS_WORKS
was added just half a year later.

In addition, with flatview overlapping memory regions are first
removed before adding the changed one. So we can't really detect joining
memory regions this way.

Let's just get rid of this special handling.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-2-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Prasad J Pandit
ed4f86e8b6 multiboot: validate multiboot header address values
While loading kernel via multiboot-v1 image, (flags & 0x00010000)
indicates that multiboot header contains valid addresses to load
the kernel image. These addresses are used to compute kernel
size and kernel text offset in the OS image. Validate these
address values to avoid an OOB access issue.

This is CVE-2017-14167.

Reported-by: Thomas Garnier <thgarnie@google.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <20170907063256.7418-1-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Kamil Rytarowski
80cac47e95 scsi/esp: Rename the ESP macro to ESP_STATE
SunOS defines ESP (x86 register) in <sys/regset.h> as 7.

This fixes build on SmartOS (Joyent).

Signed-off-by: Kamil Rytarowski <n54@gmx.com>
Message-Id: <20170909142116.26816-1-n54@gmx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Kamil Rytarowski
a16878d224 memory: Rename queue to mrqueue (memory region queue)
SunOS declares struct queue in <netinet/in.h>.

This fixes build on SmartOS (Joyent).

Patch cherry-picked from pkgsrc by jperkin (Joyent).

Signed-off-by: Kamil Rytarowski <n54@gmx.com>
Message-Id: <20170903163304.17919-1-n54@gmx.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Philippe Mathieu-Daudé
3fdfb8b6a5 MAINTAINERS: update email, add missing test entry for megasas
and update maintainer email address

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170910171557.12689-1-f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Ladi Prosek
d72bc7f6f8 i386/kvm: advertise Hyper-V frequency MSRs
As of kernel commit eb82feea59d6 ("KVM: hyperv: support HV_X64_MSR_TSC_FREQUENCY
and HV_X64_MSR_APIC_FREQUENCY"), KVM supports two new MSRs which are required
for nested Hyper-V to read timestamps with RDTSC + TSC page.

This commit makes QEMU advertise the MSRs with CPUID.40000003H:EAX[11] and
CPUID.40000003H:EDX[8] as specified in the Hyper-V TLFS and experimentally
verified on a Hyper-V host. The feature is enabled with the existing hv-time CPU
flag, and only if the TSC frequency is stable across migrations and known.

Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170807085703.32267-5-lprosek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Ladi Prosek
4bb95b82df i386/kvm: introduce tsc_is_stable_and_known()
Move the "is TSC stable and known" condition to a reusable helper.

Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170807085703.32267-4-lprosek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Ladi Prosek
ddb98b5a9f i386/kvm: set tsc_khz before configuring Hyper-V CPUID
Timing-related Hyper-V enlightenments will benefit from knowing the final
tsc_khz value. This commit just moves the code in preparation for further
changes.

Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Message-Id: <20170807085703.32267-3-lprosek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Ladi Prosek
1d268dece4 i386/kvm: use a switch statement for MSR detection
Switch is easier on the eye and might lead to better codegen.

Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170807085703.32267-2-lprosek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Xiao Guangrong
7a5bd53d09 MAINTAINERS: update mail address for NVDIMM
My Intel mail account will be disabled soon, update the mail info
to my private mail

Signed-off-by: Xiao Guangrong <xiaoguangrong.eric@gmail.com>
Message-Id: <1490074437-17059-1-git-send-email-guangrong.xiao@linux.intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:33 +02:00
Paolo Bonzini
08e2c9f19c scsi: move block/scsi.h to include/scsi/constants.h
Complete the transition by renaming this header, which was
shared by block/iscsi.c and the SCSI emulation code.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:31 +02:00
Paolo Bonzini
1ead6b4e24 scsi: introduce sg_io_sense_from_errno
Move more knowledge of SG_IO out of hw/scsi/scsi-generic.c, for
reusability.

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Paolo Bonzini
a3760467c6 scsi: introduce scsi_build_sense
Move more knowledge of sense data format out of hw/scsi/scsi-bus.c
for reusability.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Paolo Bonzini
e5b5728cd3 scsi: move non-emulation specific code to scsi/
util/scsi.c includes some SCSI code that is shared by block/iscsi.c and
hw/scsi, but the introduction of the persistent reservation helper
will add many more instances of this.  There is also include/block/scsi.h,
which actually is not part of the core block layer.

The persistent reservation manager will also need a home.  A scsi/
directory provides one for both the aforementioned shared code and
the PR manager code.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Paolo Bonzini
37b6045c45 scsi: rename scsi_build_sense to scsi_convert_sense
After introducing the scsi/ subdirectory, there will be a scsi_build_sense
function that is the same as scsi_req_build_sense but without needing
a SCSIRequest.  The existing scsi_build_sense function gets in the way,
remove it.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Fam Zheng
14b207487f scsi-block: Support rerror/werror
This makes the werror/rerror options available on the scsi-block device,
to allow user specify error handling policy similar to scsi-hd.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20170821141008.19383-5-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Fam Zheng
a485b23425 scsi: Introduce scsi_sense_buf_to_errno
This recognizes the "fixed" and "descriptor" format sense data, extracts
the sense key/asc/ascq fields then converts them to an errno.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20170821141008.19383-4-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Fam Zheng
5efa3c0448 scsi: Improve scsi_sense_to_errno
Tweak the errno mapping to return more accurate/appropriate values.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20170821141008.19383-3-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Fam Zheng
2875135807 scsi: Refactor scsi sense interpreting code
So that it can be reused outside of iscsi.c.

Also update MAINTAINERS to include the new files in SCSI section.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20170821141008.19383-2-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Hannes Reinecke
b07fbce634 scsi-bus: correct responses for INQUIRY and REQUEST SENSE
According to SPC-3 INQUIRY and REQUEST SENSE should return GOOD
even on unsupported LUNS.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Message-Id: <1503049022-14749-1-git-send-email-hare@suse.de>
Reported-by: Laszlo Ersek <lersek@redhat.com>
Fixes: ded6ddc5a7
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
2017-09-19 14:09:11 +02:00
Richard W.M. Jones
5c0919d020 virtio-scsi: Add virtqueue_size parameter allowing virtqueue size to be set.
Since Linux switched to blk-mq as the default in Linux commit
5c279bd9e406 ("scsi: default to scsi-mq"), virtio-scsi LUNs consume
about 10x as much guest kernel memory.

This commit allows you to choose the virtqueue size for each
virtio-scsi-pci controller like this:

  -device virtio-scsi-pci,id=scsi,virtqueue_size=16

The default is still 128 as before.  Using smaller virtqueue_size
allows many more disks to be added to small memory virtual machines.
For a 1 vCPU, 500 MB, no swap VM I observed:

  With scsi-mq enabled (upstream kernel):              175 disks
    -"- ditto -"-   virtqueue_size=64:                 318 disks
    -"- ditto -"-   virtqueue_size=16:                 775 disks
  With scsi-mq disabled (kernel before 5c279bd9e406): 1755 disks

Note that to have any effect, this requires a kernel patch:

  https://lkml.org/lkml/2017/8/10/689

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20170810165255.20865-1-rjones@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Joseph Myers
aa406feadf target/i386: fix phminposuw in-place operation
The SSE4.1 phminposuw instruction finds the minimum 16-bit element in
the source vector, putting the value of that element in the low 16
bits of the destination vector, the index of that element in the next
three bits and zeroing the rest of the destination.  The helper for
this operation fills the destination from high to low, meaning that
when the source and destination are the same register, the minimum
source element can be overwritten before it is copied to the
destination.  This patch fixes it to fill the destination from low to
high instead, so the minimum source element is always copied first.
This fixes one gcc test failure in my GCC 6-based testing (and so
concludes the present sequence of patches, as I don't have any further
gcc test failures left in that testing that I attribute to QEMU bugs).

Signed-off-by: Joseph Myers <joseph@codesourcery.com>

Message-Id: <alpine.DEB.2.20.1708111422580.11919@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:11 +02:00
Joseph Myers
ae35eea7e4 target/i386: fix pcmpxstrx substring search
One of the cases of the SSE4.2 pcmpestri / pcmpestrm / pcmpistri /
pcmpistrm instructions does a substring search.  The implementation of
this case in the pcmpxstrx helper is incorrect.  The operation in this
case is a search for a string (argument d to the helper) in another
string (argument s to the helper); if a copy of d at a particular
position would run off the end of s, the resulting output bit should
be 0 whether or not the strings match in the region where they
overlap, but the QEMU implementation was wrongly comparing only up to
the point where s ends and counting it as a match if an initial
segment of d matched a terminal segment of s.  Here, "run off the end
of s" means that some byte of d would overlap some byte outside of s;
thus, if d has zero length, it is considered to match everywhere,
including after the end of s.  This patch fixes the implementation to
correspond with the proper instruction semantics.  This fixes four gcc
test failures in my GCC 6-based testing.

Signed-off-by: Joseph Myers <joseph@codesourcery.com>

Message-Id: <alpine.DEB.2.20.1708102139310.8101@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:10 +02:00
Joseph Myers
80e1960621 target/i386: fix packusdw in-place operation
The SSE4.1 packusdw instruction combines source and destination
vectors of signed 32-bit integers into a single vector of unsigned
16-bit integers, with unsigned saturation.  When the source and
destination are the same register, this means each 32-bit element of
that register is used twice as an input, to produce two of the 16-bit
output elements, and so if the operation is carried out
element-by-element in-place, no matter what the order in which it is
applied to the elements, the first element's operation will overwrite
some future input.  The helper for packssdw avoids this issue by
computing the result in a local temporary and copying it to the
destination at the end; this patch fixes the packusdw helper to do
likewise.  This fixes three gcc test failures in my GCC 6-based
testing.

Signed-off-by: Joseph Myers <joseph@codesourcery.com>

Message-Id: <alpine.DEB.2.20.1708100023050.9262@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:10 +02:00
Joseph Myers
c6a8242915 target/i386: set rip_offset for further SSE instructions
It turns out that my recent fix to set rip_offset when emulating some
SSE4.1 instructions needs generalizing to cover a wider class of
instructions.  Specifically, every instruction in the sse_op_table7
table, coming from various instruction set extensions, has an 8-bit
immediate operand that comes after any memory operand, and so needs
rip_offset set for correctness if there is a memory operand that is
rip-relative, and my patch only set it for a subset of those
instructions.  This patch moves the rip_offset setting to cover the
wider class of instructions, so fixing 9 further gcc testsuite
failures in my GCC 6-based testing.  (I do not know whether there
might be still further classes of instructions missing this setting.)

Signed-off-by: Joseph Myers <joseph@codesourcery.com>

Message-Id: <alpine.DEB.2.20.1708082350340.23380@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:10 +02:00
Joseph Myers
c6a56c8e99 target/i386: fix pmovsx/pmovzx in-place operations
The SSE4.1 pmovsx* and pmovzx* instructions take packed 1-byte, 2-byte
or 4-byte inputs and sign-extend or zero-extend them to a wider vector
output.  The associated helpers for these instructions do the
extension on each element in turn, starting with the lowest.  If the
input and output are the same register, this means that all the input
elements after the first have been overwritten before they are read.
This patch makes the helpers extend starting with the highest element,
not the lowest, to avoid such overwriting.  This fixes many GCC test
failures (161 in the gcc testsuite in my GCC 6-based testing) when
testing with a default CPU setting enabling those instructions.

Signed-off-by: Joseph Myers <joseph@codesourcery.com>

Message-Id: <alpine.DEB.2.20.1708082018390.23380@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-09-19 14:09:10 +02:00
Peter Maydell
11e06ce1ed Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging
# gpg: Signature made Tue 19 Sep 2017 01:10:40 BST
# gpg:                using RSA key 0x7DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>"
# Primary key fingerprint: FAEB 9711 A12C F475 812F  18F2 88A9 064D 1835 61EB
#      Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76  CBD0 7DEF 8106 AAFC 390E

* remotes/jnsnow/tags/ide-pull-request:
  hw/block/fdc: Convert to realize
  hw/ide: Convert DeviceClass init to realize
  AHCI: remove DPRINTF macro
  AHCI: pretty-print FIS to buffer instead of stderr
  AHCI: Rework IRQ constants
  AHCI: Replace DPRINTF with trace-events
  IDE: replace DEBUG_AIO with trace events
  ATAPI: Replace DEBUG_IDE_ATAPI with tracing events
  IDE: add tracing for data ports
  IDE: Add register hints to tracing
  IDE: replace DEBUG_IDE with tracing system
  hw/ide/microdrive: Mark the dscm1xxxx device with user_creatable = false
  ide: ahci: unparent children buses before freeing their memory

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-09-19 10:13:51 +01:00
Mao Zhongyi
ae34fce5f9 hw/block/fdc: Convert to realize
Convert floppy_drive_init() to realize and rename it to
floppy_drive_realize().

Cc: John Snow <jsnow@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>

Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 87119b34f32e2acf7166165fb5d8e6fca787b3bc.1505737465.git.maozy.fnst@cn.fujitsu.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 19:43:38 -04:00
Mao Zhongyi
794939e81d hw/ide: Convert DeviceClass init to realize
Replace init with realize in IDEDeviceClass, which has errp
as a parameter. So all the implementations now use error_setg
instead of error_report for reporting error.

Cc: John Snow <jsnow@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>

Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: c4d27b4b5d9e37468e63e35214ce4833ca271542.1505737465.git.maozy.fnst@cn.fujitsu.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 19:43:38 -04:00
John Snow
ac8d9f2e4c AHCI: remove DPRINTF macro
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170901001502.29915-10-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 19:41:11 -04:00
John Snow
797285c8db AHCI: pretty-print FIS to buffer instead of stderr
The current FIS printing routines dump the FIS to screen. adjust this
such that it dumps to buffer instead, then use this ability to have
FIS dump mechanisms via trace-events instead of compiled defines.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20170901001502.29915-9-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 19:41:11 -04:00
John Snow
5fa0feecaa AHCI: Rework IRQ constants
Create a new enum so that we can name the IRQ bits, which will make debugging
them a little nicer if we can print them out. Not handled in this patch, but
this will make it possible to get a nice debug printf detailing exactly which
status bits are set, as it can be multiple at any given time.

As a consequence of this patch, it is no longer possible to set multiple IRQ
codes at once, but nothing was utilizing this ability anyway.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170901001502.29915-8-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 19:41:11 -04:00
John Snow
e4baa9f00b AHCI: Replace DPRINTF with trace-events
There are a few hangers-on that will be dealt with individually
in forthcoming patches.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170901001502.29915-7-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 19:41:11 -04:00
John Snow
0e168d3551 IDE: replace DEBUG_AIO with trace events
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20170901001502.29915-6-jsnow@redhat.com
[Edited enum conditional for Clang --js]
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:26 -04:00
John Snow
82a13ff821 ATAPI: Replace DEBUG_IDE_ATAPI with tracing events
As part of the ongoing effort to modernize the tracing facilities for
the IDE family of devices, remove PRINTFs in the ATAPI device with
actual tracing events.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20170901001502.29915-5-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:26 -04:00
John Snow
1787efc3d2 IDE: add tracing for data ports
To be used sparingly, but still interesting in the case of small
firmwares designed to reproduce bugs in QEMU IDE.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170901001502.29915-4-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:26 -04:00
John Snow
335ca2f2f0 IDE: Add register hints to tracing
Name the registers for tracing purposes.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170901001502.29915-3-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:25 -04:00
John Snow
3eee2611dd IDE: replace DEBUG_IDE with tracing system
Remove the DEBUG_IDE preprocessor definition with something more
appropriately flexible, using the trace-events subsystem.

This will be less prone to bitrot and will more effectively allow
us to target just the functions we care about.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170901001502.29915-2-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:25 -04:00
Thomas Huth
4c93950659 hw/ide/microdrive: Mark the dscm1xxxx device with user_creatable = false
QEMU currently aborts with an assertion message when the user is trying
to remove a dscm1xxxx again:

$ aarch64-softmmu/qemu-system-aarch64 -S -M integratorcp -nographic
QEMU 2.9.93 monitor - type 'help' for more information
(qemu) device_add dscm1xxxx,id=xyz
(qemu) device_del xyz
**
ERROR:qemu/qdev-monitor.c:872:qdev_unplug: assertion failed: (hotplug_ctrl)
Aborted (core dumped)

Looks like this device has to be wired up in code and is not meant
to be hot-pluggable, so let's mark it with user_creatable = false.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1503543783-17192-1-git-send-email-thuth@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:25 -04:00
Igor Mammedov
955f5c7ba1 ide: ahci: unparent children buses before freeing their memory
Fixes read after freeing error reported
  https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg04243.html
  Message-Id: <59a56959-ca12-ea75-33fa-ff07eba1b090@redhat.com>

ich9-ahci device creates ide buses and attaches them as QOM children
at realize time, however it forgets to properly clean them up
at unrealize time and frees memory containing these children,
with following call-chain:

   qdev_device_add()
     object_property_set_bool('realized', true)
       device_set_realized()
          ...
          pci_qdev_realize() -> pci_ich9_ahci_realize() -> ahci_realize()
               ...
               s->dev = g_new0(AHCIDevice, ports);
               ...
                  AHCIDevice *ad = &s->dev[i];
                  ide_bus_new(&ad->port, sizeof(ad->port), qdev, i, 1);
                  ^^^ creates bus in memory allocated by above gnew()
                      and adds it as child propety to ahci device
          ...
          hotplug_handler_plug(); -> goto post_realize_fail;
          pci_qdev_unrealize() -> pci_ich9_uninit() -> ahci_uninit()
              ...
               g_free(s->dev);
               ^^^ free memory that holds children busses

          return with error from device_set_realized()

As result later when qdev_device_add() tries to unparent ich9-ahci
after failed device_set_realized(),
    object_unparent() -> object_property_del_child()
iterates over existing QOM children including buses added by
ide_bus_new() and tries to unparent them, which causes access to
freed memory where they where located.

Reported-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1503938085-169486-1-git-send-email-imammedo@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2017-09-18 15:01:25 -04:00
168 changed files with 4302 additions and 2485 deletions

View File

@@ -790,6 +790,7 @@ M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Alexander Graf <agraf@suse.de>
S: Supported
F: hw/char/sclp*.[hc]
F: hw/char/terminal3270.c
F: hw/s390x/
F: include/hw/s390x/
F: pc-bios/s390-ccw/
@@ -970,7 +971,9 @@ SCSI
M: Paolo Bonzini <pbonzini@redhat.com>
S: Supported
F: include/hw/scsi/*
F: include/scsi/*
F: hw/scsi/*
F: util/scsi*
F: tests/virtio-scsi-test.c
T: git git://github.com/bonzini/qemu.git scsi-next
@@ -1103,11 +1106,12 @@ F: hw/block/nvme*
F: tests/nvme-test.c
megasas
M: Hannes Reinecke <hare@suse.de>
M: Hannes Reinecke <hare@suse.com>
L: qemu-block@nongnu.org
S: Supported
F: hw/scsi/megasas.c
F: hw/scsi/mfi.h
F: tests/megasas-test.c
Network packet abstractions
M: Dmitry Fleytman <dmitry@daynix.com>
@@ -1131,7 +1135,7 @@ F: tests/rocker/
F: docs/specs/rocker.txt
NVDIMM
M: Xiao Guangrong <guangrong.xiao@linux.intel.com>
M: Xiao Guangrong <xiaoguangrong.eric@gmail.com>
S: Maintained
F: hw/acpi/nvdimm.c
F: hw/mem/nvdimm.c
@@ -1215,6 +1219,13 @@ F: migration/block*
F: include/block/aio.h
T: git git://github.com/stefanha/qemu.git block
Block SCSI subsystem
M: Paolo Bonzini <pbonzini@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: include/scsi/*
F: scsi/*
Block Jobs
M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
@@ -1392,6 +1403,14 @@ S: Maintained
F: include/sysemu/cryptodev*.h
F: backends/cryptodev*.c
Python scripts
M: Eduardo Habkost <ehabkost@redhat.com>
M: Cleber Rosa <crosa@redhat.com>
S: Odd fixes
F: scripts/qmp/*
F: scripts/*.py
F: tests/*.py
QAPI
M: Markus Armbruster <armbru@redhat.com>
M: Michael Roth <mdroth@linux.vnet.ibm.com>

View File

@@ -335,7 +335,7 @@ subdir-dtc:dtc/libfdt dtc/tests
dtc/%:
mkdir -p $@
$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(chardev-obj-y) \
$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
@@ -355,12 +355,11 @@ Makefile: $(version-obj-y)
######################################################################
# Build libraries
libqemustub.a: $(stub-obj-y)
libqemuutil.a: $(util-obj-y) $(trace-obj-y)
libqemuutil.a: $(util-obj-y) $(trace-obj-y) $(stub-obj-y)
######################################################################
COMMON_LDADDS = libqemuutil.a libqemustub.a
COMMON_LDADDS = libqemuutil.a
qemu-img.o: qemu-img-cmds.h

View File

@@ -11,7 +11,7 @@ chardev-obj-y = chardev/
block-obj-y += nbd/
block-obj-y += block.o blockjob.o
block-obj-y += block/
block-obj-y += block/ scsi/
block-obj-y += qemu-io-cmds.o
block-obj-$(CONFIG_REPLICATION) += replication.o
@@ -155,6 +155,7 @@ trace-events-subdirs += hw/acpi
trace-events-subdirs += hw/arm
trace-events-subdirs += hw/alpha
trace-events-subdirs += hw/xen
trace-events-subdirs += hw/ide
trace-events-subdirs += ui
trace-events-subdirs += audio
trace-events-subdirs += net

View File

@@ -101,7 +101,6 @@ obj-y += fpu/softfloat.o
obj-y += target/$(TARGET_BASE_ARCH)/
obj-y += disas.o
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o
obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decNumber.o
@@ -193,7 +192,7 @@ all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
$(QEMU_PROG_BUILD): config-devices.mak
COMMON_LDADDS = ../libqemuutil.a ../libqemustub.a
COMMON_LDADDS = ../libqemuutil.a
# build either PROG or PROGW
$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS)

View File

@@ -79,7 +79,6 @@ struct KVMState
int coalesced_mmio;
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
bool coalesced_flush_in_progress;
int broken_set_mem_region;
int vcpu_events;
int robust_singlestep;
int debugregs;
@@ -127,6 +126,7 @@ static bool kvm_immediate_exit;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
KVM_CAP_INFO(DESTROY_MEMORY_REGION_WORKS),
KVM_CAP_INFO(JOIN_MEMORY_REGIONS_WORKS),
KVM_CAP_LAST_INFO
};
@@ -172,7 +172,7 @@ static KVMSlot *kvm_alloc_slot(KVMMemoryListener *kml)
static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
hwaddr start_addr,
hwaddr end_addr)
hwaddr size)
{
KVMState *s = kvm_state;
int i;
@@ -180,8 +180,7 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
for (i = 0; i < s->nr_slots; i++) {
KVMSlot *mem = &kml->slots[i];
if (start_addr == mem->start_addr &&
end_addr == mem->start_addr + mem->memory_size) {
if (start_addr == mem->start_addr && size == mem->memory_size) {
return mem;
}
}
@@ -190,31 +189,33 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
}
/*
* Find overlapping slot with lowest start address
* Calculate and align the start address and the size of the section.
* Return the size. If the size is 0, the aligned section is empty.
*/
static KVMSlot *kvm_lookup_overlapping_slot(KVMMemoryListener *kml,
hwaddr start_addr,
hwaddr end_addr)
static hwaddr kvm_align_section(MemoryRegionSection *section,
hwaddr *start)
{
KVMState *s = kvm_state;
KVMSlot *found = NULL;
int i;
hwaddr size = int128_get64(section->size);
hwaddr delta;
for (i = 0; i < s->nr_slots; i++) {
KVMSlot *mem = &kml->slots[i];
*start = section->offset_within_address_space;
if (mem->memory_size == 0 ||
(found && found->start_addr < mem->start_addr)) {
continue;
}
if (end_addr > mem->start_addr &&
start_addr < mem->start_addr + mem->memory_size) {
found = mem;
}
/* kvm works in page size chunks, but the function may be called
with sub-page size and unaligned start address. Pad the start
address to next and truncate size to previous page boundary. */
delta = qemu_real_host_page_size - (*start & ~qemu_real_host_page_mask);
delta &= ~qemu_real_host_page_mask;
*start += delta;
if (delta > size) {
return 0;
}
size -= delta;
size &= qemu_real_host_page_mask;
if (*start & ~qemu_real_host_page_mask) {
return 0;
}
return found;
return size;
}
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
@@ -382,15 +383,21 @@ static int kvm_slot_update_flags(KVMMemoryListener *kml, KVMSlot *mem,
static int kvm_section_update_flags(KVMMemoryListener *kml,
MemoryRegionSection *section)
{
hwaddr phys_addr = section->offset_within_address_space;
ram_addr_t size = int128_get64(section->size);
KVMSlot *mem = kvm_lookup_matching_slot(kml, phys_addr, phys_addr + size);
hwaddr start_addr, size;
KVMSlot *mem;
if (mem == NULL) {
size = kvm_align_section(section, &start_addr);
if (!size) {
return 0;
} else {
return kvm_slot_update_flags(kml, mem, section->mr);
}
mem = kvm_lookup_matching_slot(kml, start_addr, size);
if (!mem) {
fprintf(stderr, "%s: error finding slot\n", __func__);
abort();
}
return kvm_slot_update_flags(kml, mem, section->mr);
}
static void kvm_log_start(MemoryListener *listener,
@@ -454,18 +461,16 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
MemoryRegionSection *section)
{
KVMState *s = kvm_state;
unsigned long size, allocated_size = 0;
struct kvm_dirty_log d = {};
KVMSlot *mem;
int ret = 0;
hwaddr start_addr = section->offset_within_address_space;
hwaddr end_addr = start_addr + int128_get64(section->size);
hwaddr start_addr, size;
d.dirty_bitmap = NULL;
while (start_addr < end_addr) {
mem = kvm_lookup_overlapping_slot(kml, start_addr, end_addr);
if (mem == NULL) {
break;
size = kvm_align_section(section, &start_addr);
if (size) {
mem = kvm_lookup_matching_slot(kml, start_addr, size);
if (!mem) {
fprintf(stderr, "%s: error finding slot\n", __func__);
abort();
}
/* XXX bad kernel interface alert
@@ -482,27 +487,20 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
*/
size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
/*HOST_LONG_BITS*/ 64) / 8;
if (!d.dirty_bitmap) {
d.dirty_bitmap = g_malloc(size);
} else if (size > allocated_size) {
d.dirty_bitmap = g_realloc(d.dirty_bitmap, size);
}
allocated_size = size;
memset(d.dirty_bitmap, 0, allocated_size);
d.dirty_bitmap = g_malloc0(size);
d.slot = mem->slot | (kml->as_id << 16);
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
DPRINTF("ioctl failed %d\n", errno);
ret = -1;
break;
g_free(d.dirty_bitmap);
return -1;
}
kvm_get_dirty_pages_log_range(section, d.dirty_bitmap);
start_addr = mem->start_addr + mem->memory_size;
g_free(d.dirty_bitmap);
}
g_free(d.dirty_bitmap);
return ret;
return 0;
}
static void kvm_coalesce_mmio_region(MemoryListener *listener,
@@ -696,30 +694,12 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
static void kvm_set_phys_mem(KVMMemoryListener *kml,
MemoryRegionSection *section, bool add)
{
KVMState *s = kvm_state;
KVMSlot *mem, old;
KVMSlot *mem;
int err;
MemoryRegion *mr = section->mr;
bool writeable = !mr->readonly && !mr->rom_device;
hwaddr start_addr = section->offset_within_address_space;
ram_addr_t size = int128_get64(section->size);
void *ram = NULL;
unsigned delta;
/* kvm works in page size chunks, but the function may be called
with sub-page size and unaligned start address. Pad the start
address to next and truncate size to previous page boundary. */
delta = qemu_real_host_page_size - (start_addr & ~qemu_real_host_page_mask);
delta &= ~qemu_real_host_page_mask;
if (delta > size) {
return;
}
start_addr += delta;
size -= delta;
size &= qemu_real_host_page_mask;
if (!size || (start_addr & ~qemu_real_host_page_mask)) {
return;
}
hwaddr start_addr, size;
void *ram;
if (!memory_region_is_ram(mr)) {
if (writeable || !kvm_readonly_mem_allowed) {
@@ -731,30 +711,25 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
}
}
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + delta;
size = kvm_align_section(section, &start_addr);
if (!size) {
return;
}
while (1) {
mem = kvm_lookup_overlapping_slot(kml, start_addr, start_addr + size);
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region +
(section->offset_within_address_space - start_addr);
mem = kvm_lookup_matching_slot(kml, start_addr, size);
if (!add) {
if (!mem) {
break;
}
if (add && start_addr >= mem->start_addr &&
(start_addr + size <= mem->start_addr + mem->memory_size) &&
(ram - start_addr == mem->ram - mem->start_addr)) {
/* The new slot fits into the existing one and comes with
* identical parameters - update flags and done. */
kvm_slot_update_flags(kml, mem, mr);
g_assert(!memory_region_is_ram(mr) && !writeable && !mr->romd_mode);
return;
}
old = *mem;
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
kvm_physical_sync_dirty_bitmap(kml, section);
}
/* unregister the overlapping slot */
/* unregister the slot */
mem->memory_size = 0;
err = kvm_set_user_memory_region(kml, mem);
if (err) {
@@ -762,84 +737,16 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
__func__, strerror(-err));
abort();
}
/* Workaround for older KVM versions: we can't join slots, even not by
* unregistering the previous ones and then registering the larger
* slot. We have to maintain the existing fragmentation. Sigh.
*
* This workaround assumes that the new slot starts at the same
* address as the first existing one. If not or if some overlapping
* slot comes around later, we will fail (not seen in practice so far)
* - and actually require a recent KVM version. */
if (s->broken_set_mem_region &&
old.start_addr == start_addr && old.memory_size < size && add) {
mem = kvm_alloc_slot(kml);
mem->memory_size = old.memory_size;
mem->start_addr = old.start_addr;
mem->ram = old.ram;
mem->flags = kvm_mem_flags(mr);
err = kvm_set_user_memory_region(kml, mem);
if (err) {
fprintf(stderr, "%s: error updating slot: %s\n", __func__,
strerror(-err));
abort();
}
start_addr += old.memory_size;
ram += old.memory_size;
size -= old.memory_size;
continue;
}
/* register prefix slot */
if (old.start_addr < start_addr) {
mem = kvm_alloc_slot(kml);
mem->memory_size = start_addr - old.start_addr;
mem->start_addr = old.start_addr;
mem->ram = old.ram;
mem->flags = kvm_mem_flags(mr);
err = kvm_set_user_memory_region(kml, mem);
if (err) {
fprintf(stderr, "%s: error registering prefix slot: %s\n",
__func__, strerror(-err));
#ifdef TARGET_PPC
fprintf(stderr, "%s: This is probably because your kernel's " \
"PAGE_SIZE is too big. Please try to use 4k " \
"PAGE_SIZE!\n", __func__);
#endif
abort();
}
}
/* register suffix slot */
if (old.start_addr + old.memory_size > start_addr + size) {
ram_addr_t size_delta;
mem = kvm_alloc_slot(kml);
mem->start_addr = start_addr + size;
size_delta = mem->start_addr - old.start_addr;
mem->memory_size = old.memory_size - size_delta;
mem->ram = old.ram + size_delta;
mem->flags = kvm_mem_flags(mr);
err = kvm_set_user_memory_region(kml, mem);
if (err) {
fprintf(stderr, "%s: error registering suffix slot: %s\n",
__func__, strerror(-err));
abort();
}
}
}
/* in case the KVM bug workaround already "consumed" the new slot */
if (!size) {
return;
}
if (!add) {
if (mem) {
/* update the slot */
kvm_slot_update_flags(kml, mem, mr);
return;
}
/* register the new slot */
mem = kvm_alloc_slot(kml);
mem->memory_size = size;
mem->start_addr = start_addr;
@@ -1629,10 +1536,9 @@ static int kvm_init(MachineState *ms)
while (nc->name) {
if (nc->num > soft_vcpus_limit) {
fprintf(stderr,
"Warning: Number of %s cpus requested (%d) exceeds "
"the recommended cpus supported by KVM (%d)\n",
nc->name, nc->num, soft_vcpus_limit);
warn_report("Number of %s cpus requested (%d) exceeds "
"the recommended cpus supported by KVM (%d)",
nc->name, nc->num, soft_vcpus_limit);
if (nc->num > hard_vcpus_limit) {
fprintf(stderr, "Number of %s cpus requested (%d) exceeds "
@@ -1692,12 +1598,6 @@ static int kvm_init(MachineState *ms)
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
s->broken_set_mem_region = 1;
ret = kvm_check_extension(s, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
if (ret > 0) {
s->broken_set_mem_region = 0;
}
#ifdef KVM_CAP_VCPU_EVENTS
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
#endif

View File

@@ -1,2 +1,3 @@
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o

View File

@@ -34,15 +34,20 @@
#include "qemu/bitops.h"
#include "qemu/bitmap.h"
#include "block/block_int.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "qemu/iov.h"
#include "qemu/uuid.h"
#include "qmp-commands.h"
#include "qapi/qmp/qstring.h"
#include "crypto/secret.h"
#include "scsi/utils.h"
/* Conflict between scsi/utils.h and libiscsi! :( */
#define SCSI_XFER_NONE ISCSI_XFER_NONE
#include <iscsi/iscsi.h>
#include <iscsi/scsi-lowlevel.h>
#undef SCSI_XFER_NONE
QEMU_BUILD_BUG_ON((int)SCSI_XFER_NONE != (int)ISCSI_XFER_NONE);
#ifdef __linux__
#include <scsi/sg.h>
@@ -209,47 +214,9 @@ static inline unsigned exp_random(double mean)
static int iscsi_translate_sense(struct scsi_sense *sense)
{
int ret;
switch (sense->key) {
case SCSI_SENSE_NOT_READY:
return -EBUSY;
case SCSI_SENSE_DATA_PROTECTION:
return -EACCES;
case SCSI_SENSE_COMMAND_ABORTED:
return -ECANCELED;
case SCSI_SENSE_ILLEGAL_REQUEST:
/* Parse ASCQ */
break;
default:
return -EIO;
}
switch (sense->ascq) {
case SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR:
case SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE:
case SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB:
case SCSI_SENSE_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST:
ret = -EINVAL;
break;
case SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE:
ret = -ENOSPC;
break;
case SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED:
ret = -ENOTSUP;
break;
case SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT:
case SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED:
case SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN:
ret = -ENOMEDIUM;
break;
case SCSI_SENSE_ASCQ_WRITE_PROTECTED:
ret = -EACCES;
break;
default:
ret = -EIO;
break;
}
return ret;
return - scsi_sense_to_errno(sense->key,
(sense->ascq & 0xFF00) >> 8,
sense->ascq & 0xFF);
}
/* Called (via iscsi_service) with QemuMutex held. */

View File

@@ -301,10 +301,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
}
if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS)) {
error_report("WARNING: a program lacking bitmap support "
"modified this file, so all bitmaps are now "
"considered inconsistent. Some clusters may be "
"leaked, run 'qemu-img check -r' on the image "
warn_report("a program lacking bitmap support "
"modified this file, so all bitmaps are now "
"considered inconsistent");
error_printf("Some clusters may be leaked, "
"run 'qemu-img check -r' on the image "
"file to fix.");
if (need_update_header != NULL) {
/* Updating is needed to drop invalid bitmap extension. */

View File

@@ -32,6 +32,7 @@
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qstring.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#ifndef S_IWGRP
#define S_IWGRP 0
@@ -1226,8 +1227,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
switch (s->fat_type) {
case 32:
fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
"You are welcome to do so!\n");
warn_report("FAT32 has not been tested. You are welcome to do so!");
break;
case 16:
case 12:
@@ -3028,7 +3028,8 @@ DLOG(checkpoint());
if (memcmp(direntries + k,
array_get(&(s->directory), dir_index + k),
sizeof(direntry_t))) {
fprintf(stderr, "Warning: tried to write to write-protected file\n");
warn_report("tried to write to write-protected "
"file");
return -1;
}
}

2
configure vendored
View File

@@ -2025,7 +2025,7 @@ if test "$seccomp" != "no" ; then
arm|aarch64)
libseccomp_minver="2.2.3"
;;
ppc|ppc64)
ppc|ppc64|s390x)
libseccomp_minver="2.3.0"
;;
*)

View File

@@ -43,4 +43,4 @@ CONFIG_VGA=y
CONFIG_VGA_PCI=y
CONFIG_IVSHMEM_DEVICE=$(CONFIG_IVSHMEM)
CONFIG_ROCKER=y
CONFIG_VHOST_USER_SCSI=$(and $(CONFIG_VHOST_USER),$(CONFIG_LINUX))
CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))

View File

@@ -43,7 +43,7 @@ CONFIG_XILINX_ETHLITE=y
CONFIG_PREP=y
CONFIG_MAC=y
CONFIG_E500=y
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
CONFIG_PLATFORM_BUS=y
CONFIG_ETSEC=y
CONFIG_LIBDECNUMBER=y

View File

@@ -48,7 +48,7 @@ CONFIG_POWERNV=y
CONFIG_PREP=y
CONFIG_MAC=y
CONFIG_E500=y
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
CONFIG_PLATFORM_BUS=y
CONFIG_ETSEC=y
CONFIG_LIBDECNUMBER=y
@@ -56,7 +56,7 @@ CONFIG_SM501=y
# For pSeries
CONFIG_XICS=$(CONFIG_PSERIES)
CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
# For PReP
CONFIG_SERIAL_ISA=y
CONFIG_MC146818RTC=y

View File

@@ -1,6 +1,6 @@
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=$(CONFIG_PCI)
CONFIG_VHOST_USER_SCSI=$(and $(CONFIG_VHOST_USER),$(CONFIG_LINUX))
CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
CONFIG_VIRTIO=y
CONFIG_SCLPCONSOLE=y
CONFIG_TERMINAL3270=y

View File

@@ -12,6 +12,7 @@ CONFIG_FDC=y
CONFIG_IDE_ISA=y
CONFIG_IDE_CMD646=y
CONFIG_PCI_APB=y
CONFIG_SUNHME=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_EMPTY_SLOT=y

View File

@@ -232,15 +232,15 @@ The utility code that is used by all binaries is built into a
static archive called libqemuutil.a, which is then linked to all the
binaries. In order to provide hooks that are only needed by some of the
binaries, code in libqemuutil.a may depend on other functions that are
not fully implemented by all QEMU binaries. To deal with this there is a
second library called libqemustub.a which provides dummy stubs for all
these functions. These will get lazy linked into the binary if the real
implementation is not present. In this way, the libqemustub.a static
library can be thought of as a portable implementation of the weak
symbols concept. All binaries should link to both libqemuutil.a and
libqemustub.a. e.g.
not fully implemented by all QEMU binaries. Dummy stubs for all these
functions are also provided by this library, and will only be linked
into the binary if the real implementation is not present. In a way,
the stubs can be thought of as a portable implementation of the weak
symbols concept.
qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.a libqemustub.a
All binaries should link to libqemuutil.a, e.g.:
qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.a
Windows platform portability

1
dump.c
View File

@@ -15,7 +15,6 @@
#include "qemu/cutils.h"
#include "elf.h"
#include "cpu.h"
#include "exec/cpu-all.h"
#include "exec/hwaddr.h"
#include "monitor/monitor.h"
#include "sysemu/kvm.h"

1
exec.c
View File

@@ -56,7 +56,6 @@
#endif
#endif
#include "exec/cpu-all.h"
#include "qemu/rcu_queue.h"
#include "qemu/main-loop.h"
#include "translate-all.h"

View File

@@ -803,12 +803,12 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
return mode;
}
static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *path,
const char *basename,
const struct stat *stbuf,
V9fsStat *v9stat)
{
int err;
const char *str;
memset(v9stat, 0, sizeof(*v9stat));
@@ -829,7 +829,7 @@ static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
v9fs_string_free(&v9stat->extension);
if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
err = v9fs_co_readlink(pdu, name, &v9stat->extension);
err = v9fs_co_readlink(pdu, path, &v9stat->extension);
if (err < 0) {
return err;
}
@@ -842,14 +842,7 @@ static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
"HARDLINKCOUNT", (unsigned long)stbuf->st_nlink);
}
str = strrchr(name->data, '/');
if (str) {
str += 1;
} else {
str = name->data;
}
v9fs_string_sprintf(&v9stat->name, "%s", str);
v9fs_string_sprintf(&v9stat->name, "%s", basename);
v9stat->size = 61 +
v9fs_string_size(&v9stat->name) +
@@ -1056,6 +1049,7 @@ static void coroutine_fn v9fs_stat(void *opaque)
struct stat stbuf;
V9fsFidState *fidp;
V9fsPDU *pdu = opaque;
char *basename;
err = pdu_unmarshal(pdu, offset, "d", &fid);
if (err < 0) {
@@ -1072,7 +1066,9 @@ static void coroutine_fn v9fs_stat(void *opaque)
if (err < 0) {
goto out;
}
err = stat_to_v9stat(pdu, &fidp->path, &stbuf, &v9stat);
basename = g_path_get_basename(fidp->path.data);
err = stat_to_v9stat(pdu, &fidp->path, basename, &stbuf, &v9stat);
g_free(basename);
if (err < 0) {
goto out;
}
@@ -1748,22 +1744,31 @@ static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
if (err < 0) {
break;
}
err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
err = stat_to_v9stat(pdu, &path, dent->d_name, &stbuf, &v9stat);
if (err < 0) {
break;
}
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
if ((count + v9stat.size + 2) > max_count) {
v9fs_readdir_unlock(&fidp->fs.dir);
v9fs_readdir_unlock(&fidp->fs.dir);
if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
/* Ran out of buffer. Set dir back to old position and return */
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
v9fs_stat_free(&v9stat);
v9fs_path_free(&path);
return count;
}
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
v9fs_readdir_unlock(&fidp->fs.dir);
if (len < 0) {
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
v9fs_stat_free(&v9stat);
v9fs_path_free(&path);
return len;
}
count += len;
v9fs_stat_free(&v9stat);
v9fs_path_free(&path);
@@ -2557,13 +2562,11 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
int32_t newdirfid,
V9fsString *name)
{
char *end;
int err = 0;
V9fsPath new_path;
V9fsFidState *tfidp;
V9fsState *s = pdu->s;
V9fsFidState *dirfidp = NULL;
char *old_name, *new_name;
v9fs_path_init(&new_path);
if (newdirfid != -1) {
@@ -2581,18 +2584,15 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
goto out;
}
} else {
old_name = fidp->path.data;
end = strrchr(old_name, '/');
if (end) {
end++;
} else {
end = old_name;
}
new_name = g_malloc0(end - old_name + name->size + 1);
strncat(new_name, old_name, end - old_name);
strncat(new_name + (end - old_name), name->data, name->size);
err = v9fs_co_name_to_path(pdu, NULL, new_name, &new_path);
g_free(new_name);
char *dir_name = g_path_get_dirname(fidp->path.data);
V9fsPath dir_path;
v9fs_path_init(&dir_path);
v9fs_path_sprintf(&dir_path, "%s", dir_name);
g_free(dir_name);
err = v9fs_co_name_to_path(pdu, &dir_path, name->data, &new_path);
v9fs_path_free(&dir_path);
if (err < 0) {
goto out;
}

View File

@@ -28,6 +28,7 @@
#include "qapi/opts-visitor.h"
#include "qapi-visit.h"
#include "qapi-event.h"
#include "qemu/error-report.h"
struct acpi_table_header {
uint16_t _length; /* our length, not actual part of the hdr */
@@ -183,10 +184,9 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen,
}
if (has_header && le32_to_cpu(ext_hdr->length) != acpi_payload_size) {
fprintf(stderr,
"warning: ACPI table has wrong length, header says "
"%" PRIu32 ", actual size %zu bytes\n",
le32_to_cpu(ext_hdr->length), acpi_payload_size);
warn_report("ACPI table has wrong length, header says "
"%" PRIu32 ", actual size %zu bytes",
le32_to_cpu(ext_hdr->length), acpi_payload_size);
}
ext_hdr->length = cpu_to_le32(acpi_payload_size);
@@ -221,7 +221,7 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen,
}
if (!has_header && changed_fields == 0) {
fprintf(stderr, "warning: ACPI table: no headers are specified\n");
warn_report("ACPI table: no headers are specified");
}
/* recalculate checksum */

View File

@@ -479,8 +479,8 @@ static void vexpress_modify_dtb(const struct arm_boot_info *info, void *fdt)
/* Not fatal, we just won't provide virtio. This will
* happen with older device tree blobs.
*/
fprintf(stderr, "QEMU: warning: couldn't find interrupt controller in "
"dtb; will not include virtio-mmio devices in the dtb.\n");
warn_report("couldn't find interrupt controller in "
"dtb; will not include virtio-mmio devices in the dtb");
} else {
int i;
const hwaddr *map = daughterboard->motherboard_map;

View File

@@ -517,7 +517,7 @@ static Property floppy_drive_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static int floppy_drive_init(DeviceState *qdev)
static void floppy_drive_realize(DeviceState *qdev, Error **errp)
{
FloppyDrive *dev = FLOPPY_DRIVE(qdev);
FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus);
@@ -535,15 +535,15 @@ static int floppy_drive_init(DeviceState *qdev)
}
if (dev->unit >= MAX_FD) {
error_report("Can't create floppy unit %d, bus supports only %d units",
dev->unit, MAX_FD);
return -1;
error_setg(errp, "Can't create floppy unit %d, bus supports "
"only %d units", dev->unit, MAX_FD);
return;
}
drive = get_drv(bus->fdc, dev->unit);
if (drive->blk) {
error_report("Floppy unit %d is in use", dev->unit);
return -1;
error_setg(errp, "Floppy unit %d is in use", dev->unit);
return;
}
if (!dev->conf.blk) {
@@ -557,8 +557,9 @@ static int floppy_drive_init(DeviceState *qdev)
if (dev->conf.logical_block_size != 512 ||
dev->conf.physical_block_size != 512)
{
error_report("Physical and logical block size must be 512 for floppy");
return -1;
error_setg(errp, "Physical and logical block size must "
"be 512 for floppy");
return;
}
/* rerror/werror aren't supported by fdc and therefore not even registered
@@ -570,20 +571,20 @@ static int floppy_drive_init(DeviceState *qdev)
blkconf_apply_backend_options(&dev->conf, blk_is_read_only(dev->conf.blk),
false, &local_err);
if (local_err) {
error_report_err(local_err);
return -1;
error_propagate(errp, local_err);
return;
}
/* 'enospc' is the default for -drive, 'report' is what blk_new() gives us
* for empty drives. */
if (blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC &&
blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) {
error_report("fdc doesn't support drive option werror");
return -1;
error_setg(errp, "fdc doesn't support drive option werror");
return;
}
if (blk_get_on_error(dev->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
error_report("fdc doesn't support drive option rerror");
return -1;
error_setg(errp, "fdc doesn't support drive option rerror");
return;
}
drive->conf = &dev->conf;
@@ -599,14 +600,12 @@ static int floppy_drive_init(DeviceState *qdev)
dev->type = drive->drive;
fd_revalidate(drive);
return 0;
}
static void floppy_drive_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = floppy_drive_init;
k->realize = floppy_drive_realize;
set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
k->bus_type = TYPE_FLOPPY_BUS;
k->props = floppy_drive_properties;

View File

@@ -22,7 +22,7 @@
#include "sysemu/blockdev.h"
#include "hw/virtio/virtio-blk.h"
#include "dataplane/virtio-blk.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#ifdef __linux__
# include <scsi/sg.h>
#endif

View File

@@ -1232,7 +1232,7 @@ static int blk_connect(struct XenDevice *xendev)
return -1;
}
domids = g_malloc0_n(blkdev->nr_ring_ref, sizeof(uint32_t));
domids = g_new0(uint32_t, blkdev->nr_ring_ref);
for (i = 0; i < blkdev->nr_ring_ref; i++) {
domids[i] = blkdev->xendev.dom;
}

View File

@@ -30,6 +30,48 @@ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res);
static void
virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr)
{
le32_to_cpus(&hdr->type);
le32_to_cpus(&hdr->flags);
le64_to_cpus(&hdr->fence_id);
le32_to_cpus(&hdr->ctx_id);
le32_to_cpus(&hdr->padding);
}
static void virtio_gpu_bswap_32(void *ptr,
size_t size)
{
#ifdef HOST_WORDS_BIGENDIAN
size_t i;
struct virtio_gpu_ctrl_hdr *hdr = (struct virtio_gpu_ctrl_hdr *) ptr;
virtio_gpu_ctrl_hdr_bswap(hdr);
i = sizeof(struct virtio_gpu_ctrl_hdr);
while (i < size) {
le32_to_cpus((uint32_t *)(ptr + i));
i = i + sizeof(uint32_t);
}
#endif
}
static void
virtio_gpu_t2d_bswap(struct virtio_gpu_transfer_to_host_2d *t2d)
{
virtio_gpu_ctrl_hdr_bswap(&t2d->hdr);
le32_to_cpus(&t2d->r.x);
le32_to_cpus(&t2d->r.y);
le32_to_cpus(&t2d->r.width);
le32_to_cpus(&t2d->r.height);
le64_to_cpus(&t2d->offset);
le32_to_cpus(&t2d->resource_id);
le32_to_cpus(&t2d->padding);
}
#ifdef CONFIG_VIRGL
#include <virglrenderer.h>
#define VIRGL(_g, _virgl, _simple, ...) \
@@ -205,6 +247,7 @@ void virtio_gpu_ctrl_response(VirtIOGPU *g,
resp->fence_id = cmd->cmd_hdr.fence_id;
resp->ctx_id = cmd->cmd_hdr.ctx_id;
}
virtio_gpu_ctrl_hdr_bswap(resp);
s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len);
if (s != resp_len) {
qemu_log_mask(LOG_GUEST_ERROR,
@@ -236,8 +279,8 @@ virtio_gpu_fill_display_info(VirtIOGPU *g,
for (i = 0; i < g->conf.max_outputs; i++) {
if (g->enabled_output_bitmask & (1 << i)) {
dpy_info->pmodes[i].enabled = 1;
dpy_info->pmodes[i].r.width = g->req_state[i].width;
dpy_info->pmodes[i].r.height = g->req_state[i].height;
dpy_info->pmodes[i].r.width = cpu_to_le32(g->req_state[i].width);
dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height);
}
}
}
@@ -287,6 +330,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
struct virtio_gpu_resource_create_2d c2d;
VIRTIO_GPU_FILL_CMD(c2d);
virtio_gpu_bswap_32(&c2d, sizeof(c2d));
trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
@@ -360,6 +404,7 @@ static void virtio_gpu_resource_unref(VirtIOGPU *g,
struct virtio_gpu_resource_unref unref;
VIRTIO_GPU_FILL_CMD(unref);
virtio_gpu_bswap_32(&unref, sizeof(unref));
trace_virtio_gpu_cmd_res_unref(unref.resource_id);
res = virtio_gpu_find_resource(g, unref.resource_id);
@@ -383,6 +428,7 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
struct virtio_gpu_transfer_to_host_2d t2d;
VIRTIO_GPU_FILL_CMD(t2d);
virtio_gpu_t2d_bswap(&t2d);
trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
res = virtio_gpu_find_resource(g, t2d.resource_id);
@@ -439,6 +485,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
int i;
VIRTIO_GPU_FILL_CMD(rf);
virtio_gpu_bswap_32(&rf, sizeof(rf));
trace_virtio_gpu_cmd_res_flush(rf.resource_id,
rf.r.width, rf.r.height, rf.r.x, rf.r.y);
@@ -511,6 +558,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
struct virtio_gpu_set_scanout ss;
VIRTIO_GPU_FILL_CMD(ss);
virtio_gpu_bswap_32(&ss, sizeof(ss));
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
@@ -633,13 +681,15 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
*addr = g_malloc0(sizeof(uint64_t) * ab->nr_entries);
}
for (i = 0; i < ab->nr_entries; i++) {
hwaddr len = ents[i].length;
(*iov)[i].iov_len = ents[i].length;
(*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1);
uint64_t a = le64_to_cpu(ents[i].addr);
uint32_t l = le32_to_cpu(ents[i].length);
hwaddr len = l;
(*iov)[i].iov_len = l;
(*iov)[i].iov_base = cpu_physical_memory_map(a, &len, 1);
if (addr) {
(*addr)[i] = ents[i].addr;
(*addr)[i] = a;
}
if (!(*iov)[i].iov_base || len != ents[i].length) {
if (!(*iov)[i].iov_base || len != l) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
" resource %d element %d\n",
__func__, ab->resource_id, i);
@@ -686,6 +736,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
int ret;
VIRTIO_GPU_FILL_CMD(ab);
virtio_gpu_bswap_32(&ab, sizeof(ab));
trace_virtio_gpu_cmd_res_back_attach(ab.resource_id);
res = virtio_gpu_find_resource(g, ab.resource_id);
@@ -718,6 +769,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g,
struct virtio_gpu_resource_detach_backing detach;
VIRTIO_GPU_FILL_CMD(detach);
virtio_gpu_bswap_32(&detach, sizeof(detach));
trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
res = virtio_gpu_find_resource(g, detach.resource_id);
@@ -734,6 +786,7 @@ static void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
switch (cmd->cmd_hdr.type) {
case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
@@ -879,6 +932,7 @@ static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
"%s: cursor size incorrect %zu vs %zu\n",
__func__, s, sizeof(cursor_info));
} else {
virtio_gpu_bswap_32(&cursor_info, sizeof(cursor_info));
update_cursor(g, &cursor_info);
}
virtqueue_push(vq, elem, 0);
@@ -1135,7 +1189,7 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
}
g->config_size = sizeof(struct virtio_gpu_config);
g->virtio_config.num_scanouts = g->conf.max_outputs;
g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs);
virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
g->config_size);

View File

@@ -2766,17 +2766,22 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
ACPI_BUILD_ALIGN_SIZE);
if (tables_blob->len > legacy_table_size) {
/* Should happen only with PCI bridges and -M pc-i440fx-2.0. */
warn_report("migration may not work.");
warn_report("ACPI table size %u exceeds %d bytes,"
" migration may not work",
tables_blob->len, legacy_table_size);
error_printf("Try removing CPUs, NUMA nodes, memory slots"
" or PCI bridges.");
}
g_array_set_size(tables_blob, legacy_table_size);
} else {
/* Make sure we have a buffer in case we need to resize the tables. */
if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
/* As of QEMU 2.1, this fires with 160 VCPUs and 255 memory slots. */
warn_report("ACPI tables are larger than 64k.");
warn_report("migration may not work.");
warn_report("please remove CPUs, NUMA nodes, "
"memory slots or PCI bridges.");
warn_report("ACPI table size %u exceeds %d bytes,"
" migration may not work",
tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
error_printf("Try removing CPUs, NUMA nodes, memory slots"
" or PCI bridges.");
}
acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
}

View File

@@ -221,15 +221,34 @@ int load_multiboot(FWCfgState *fw_cfg,
uint32_t mh_header_addr = ldl_p(header+i+12);
uint32_t mh_load_end_addr = ldl_p(header+i+20);
uint32_t mh_bss_end_addr = ldl_p(header+i+24);
mh_load_addr = ldl_p(header+i+16);
if (mh_header_addr < mh_load_addr) {
fprintf(stderr, "invalid mh_load_addr address\n");
exit(1);
}
uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
uint32_t mb_load_size = 0;
mh_entry_addr = ldl_p(header+i+28);
if (mh_load_end_addr) {
if (mh_bss_end_addr < mh_load_addr) {
fprintf(stderr, "invalid mh_bss_end_addr address\n");
exit(1);
}
mb_kernel_size = mh_bss_end_addr - mh_load_addr;
if (mh_load_end_addr < mh_load_addr) {
fprintf(stderr, "invalid mh_load_end_addr address\n");
exit(1);
}
mb_load_size = mh_load_end_addr - mh_load_addr;
} else {
if (kernel_file_size < mb_kernel_text_offset) {
fprintf(stderr, "invalid kernel_file_size\n");
exit(1);
}
mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
mb_load_size = mb_kernel_size;
}

View File

@@ -384,7 +384,7 @@ ISADevice *pc_find_fdc0(void)
warn_report("multiple floppy disk controllers with "
"iobase=0x3f0 have been found");
error_printf("the one being picked for CMOS setup might not reflect "
"your intent\n");
"your intent");
}
return state.floppy;
@@ -1278,7 +1278,7 @@ void pc_acpi_init(const char *default_dsdt)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
if (filename == NULL) {
fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
warn_report("failed to find %s", default_dsdt);
} else {
QemuOpts *opts = qemu_opts_create(qemu_find_opts("acpi"), NULL, 0,
&error_abort);
@@ -2066,9 +2066,8 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
}
if (value < (1ULL << 20)) {
warn_report("small max_ram_below_4g(%"PRIu64
") less than 1M. BIOS may not work..",
value);
warn_report("Only %" PRIu64 " bytes of RAM below the 4GiB boundary,"
"BIOS may not work with less than 1MiB", value);
}
pcms->max_ram_below_4g = value;

View File

@@ -101,9 +101,11 @@ static void pc_q35_init(MachineState *machine)
lowmem = pcms->max_ram_below_4g;
if (machine->ram_size - lowmem > lowmem &&
lowmem & ((1ULL << 30) - 1)) {
warn_report("Large machine and max_ram_below_4g(%"PRIu64
") not a multiple of 1G; possible bad performance.",
pcms->max_ram_below_4g);
warn_report("There is possibly poor performance as the ram size "
" (0x%" PRIx64 ") is more then twice the size of"
" max-ram-below-4g (%"PRIu64") and"
" max-ram-below-4g is not a multiple of 1G.",
(uint64_t)machine->ram_size, pcms->max_ram_below_4g);
}
}

View File

@@ -9,6 +9,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include <sys/resource.h>
@@ -125,8 +126,8 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
rlimit_as.rlim_cur = rlimit_as.rlim_max;
if (rlimit_as.rlim_max != RLIM_INFINITY) {
fprintf(stderr, "Warning: QEMU's maximum size of virtual"
" memory is not infinity.\n");
warn_report("QEMU's maximum size of virtual"
" memory is not infinity");
}
if (rlimit_as.rlim_max < MCACHE_MAX_SIZE + NON_MCACHE_MEMORY_SIZE) {
mapcache->max_mcache_size = rlimit_as.rlim_max -

View File

@@ -34,15 +34,7 @@
#include "hw/ide/pci.h"
#include "hw/ide/ahci_internal.h"
#define DEBUG_AHCI 0
#define DPRINTF(port, fmt, ...) \
do { \
if (DEBUG_AHCI) { \
fprintf(stderr, "ahci: %s: [%d] ", __func__, port); \
fprintf(stderr, fmt, ## __VA_ARGS__); \
} \
} while (0)
#include "trace.h"
static void check_cmd(AHCIState *s, int port);
static int handle_cmd(AHCIState *s, int port, uint8_t slot);
@@ -55,6 +47,27 @@ static bool ahci_map_fis_address(AHCIDevice *ad);
static void ahci_unmap_clb_address(AHCIDevice *ad);
static void ahci_unmap_fis_address(AHCIDevice *ad);
static const char *AHCIPortIRQ_lookup[AHCI_PORT_IRQ__COUNT] = {
[AHCI_PORT_IRQ_BIT_DHRS] = "DHRS",
[AHCI_PORT_IRQ_BIT_PSS] = "PSS",
[AHCI_PORT_IRQ_BIT_DSS] = "DSS",
[AHCI_PORT_IRQ_BIT_SDBS] = "SDBS",
[AHCI_PORT_IRQ_BIT_UFS] = "UFS",
[AHCI_PORT_IRQ_BIT_DPS] = "DPS",
[AHCI_PORT_IRQ_BIT_PCS] = "PCS",
[AHCI_PORT_IRQ_BIT_DMPS] = "DMPS",
[8 ... 21] = "RESERVED",
[AHCI_PORT_IRQ_BIT_PRCS] = "PRCS",
[AHCI_PORT_IRQ_BIT_IPMS] = "IPMS",
[AHCI_PORT_IRQ_BIT_OFS] = "OFS",
[25] = "RESERVED",
[AHCI_PORT_IRQ_BIT_INFS] = "INFS",
[AHCI_PORT_IRQ_BIT_IFS] = "IFS",
[AHCI_PORT_IRQ_BIT_HBDS] = "HBDS",
[AHCI_PORT_IRQ_BIT_HBFS] = "HBFS",
[AHCI_PORT_IRQ_BIT_TFES] = "TFES",
[AHCI_PORT_IRQ_BIT_CPDS] = "CPDS"
};
static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
{
@@ -114,9 +127,9 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
default:
val = 0;
}
DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val);
return val;
trace_ahci_port_read(s, port, offset, val);
return val;
}
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
@@ -125,7 +138,7 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
TYPE_PCI_DEVICE);
DPRINTF(0, "raise irq\n");
trace_ahci_irq_raise(s);
if (pci_dev && msi_enabled(pci_dev)) {
msi_notify(pci_dev, 0);
@@ -140,7 +153,7 @@ static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
TYPE_PCI_DEVICE);
DPRINTF(0, "lower irq\n");
trace_ahci_irq_lower(s);
if (!pci_dev || !msi_enabled(pci_dev)) {
qemu_irq_lower(s->irq);
@@ -150,8 +163,7 @@ static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
static void ahci_check_irq(AHCIState *s)
{
int i;
DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus);
uint32_t old_irq = s->control_regs.irqstatus;
s->control_regs.irqstatus = 0;
for (i = 0; i < s->ports; i++) {
@@ -160,7 +172,7 @@ static void ahci_check_irq(AHCIState *s)
s->control_regs.irqstatus |= (1 << i);
}
}
trace_ahci_check_irq(s, old_irq, s->control_regs.irqstatus);
if (s->control_regs.irqstatus &&
(s->control_regs.ghc & HOST_CTL_IRQ_EN)) {
ahci_irq_raise(s, NULL);
@@ -170,12 +182,18 @@ static void ahci_check_irq(AHCIState *s)
}
static void ahci_trigger_irq(AHCIState *s, AHCIDevice *d,
int irq_type)
enum AHCIPortIRQ irqbit)
{
DPRINTF(d->port_no, "trigger irq %#x -> %x\n",
irq_type, d->port_regs.irq_mask & irq_type);
g_assert(irqbit >= 0 && irqbit < 32);
uint32_t irq = 1U << irqbit;
uint32_t irqstat = d->port_regs.irq_stat | irq;
d->port_regs.irq_stat |= irq_type;
trace_ahci_trigger_irq(s, d->port_no,
AHCIPortIRQ_lookup[irqbit], irq,
d->port_regs.irq_stat, irqstat,
irqstat & d->port_regs.irq_mask);
d->port_regs.irq_stat = irqstat;
ahci_check_irq(s);
}
@@ -240,7 +258,7 @@ static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
{
AHCIPortRegs *pr = &s->dev[port].port_regs;
DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val);
trace_ahci_port_write(s, port, offset, val);
switch (offset) {
case PORT_LST_ADDR:
pr->lst_addr = val;
@@ -341,8 +359,6 @@ static uint64_t ahci_mem_read_32(void *opaque, hwaddr addr)
val = s->control_regs.version;
break;
}
DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val);
} else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
(addr < (AHCI_PORT_REGS_START_ADDR +
(s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {
@@ -350,6 +366,7 @@ static uint64_t ahci_mem_read_32(void *opaque, hwaddr addr)
addr & AHCI_PORT_ADDR_OFFSET_MASK);
}
trace_ahci_mem_read_32(s, addr, val);
return val;
}
@@ -379,8 +396,7 @@ static uint64_t ahci_mem_read(void *opaque, hwaddr addr, unsigned size)
val = (hi << 32 | lo) >> (ofst * 8);
}
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
addr, val, size);
trace_ahci_mem_read(opaque, size, addr, val);
return val;
}
@@ -390,8 +406,7 @@ static void ahci_mem_write(void *opaque, hwaddr addr,
{
AHCIState *s = opaque;
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
addr, val, size);
trace_ahci_mem_write(s, size, addr, val);
/* Only aligned reads are allowed on AHCI */
if (addr & 3) {
@@ -401,15 +416,12 @@ static void ahci_mem_write(void *opaque, hwaddr addr,
}
if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) {
DPRINTF(-1, "(addr 0x%08X), val 0x%08"PRIX64"\n", (unsigned) addr, val);
switch (addr) {
case HOST_CAP: /* R/WO, RO */
/* FIXME handle R/WO */
break;
case HOST_CTL: /* R/W */
if (val & HOST_CTL_RESET) {
DPRINTF(-1, "HBA Reset\n");
ahci_reset(s);
} else {
s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN;
@@ -427,7 +439,7 @@ static void ahci_mem_write(void *opaque, hwaddr addr,
/* FIXME report write? */
break;
default:
DPRINTF(-1, "write to unknown register 0x%x\n", (unsigned)addr);
trace_ahci_mem_write_unknown(s, size, addr, val);
}
} else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
(addr < (AHCI_PORT_REGS_START_ADDR +
@@ -559,7 +571,8 @@ static void ahci_set_signature(AHCIDevice *ad, uint32_t sig)
s->sector = sig >> 8 & 0xFF;
s->nsector = sig & 0xFF;
DPRINTF(ad->port_no, "set hcyl:lcyl:sect:nsect = 0x%08x\n", sig);
trace_ahci_set_signature(ad->hba, ad->port_no, s->nsector, s->sector,
s->lcyl, s->hcyl, sig);
}
static void ahci_reset_port(AHCIState *s, int port)
@@ -569,7 +582,7 @@ static void ahci_reset_port(AHCIState *s, int port)
IDEState *ide_state = &d->port.ifs[0];
int i;
DPRINTF(port, "reset port\n");
trace_ahci_reset_port(s, port);
ide_bus_reset(&d->port);
ide_state->ncq_queues = AHCI_MAX_CMDS;
@@ -622,20 +635,21 @@ static void ahci_reset_port(AHCIState *s, int port)
ahci_init_d2h(d);
}
static void debug_print_fis(uint8_t *fis, int cmd_len)
/* Buffer pretty output based on a raw FIS structure. */
static char *ahci_pretty_buffer_fis(uint8_t *fis, int cmd_len)
{
#if DEBUG_AHCI
int i;
GString *s = g_string_new("FIS:");
fprintf(stderr, "fis:");
for (i = 0; i < cmd_len; i++) {
if ((i & 0xf) == 0) {
fprintf(stderr, "\n%02x:",i);
g_string_append_printf(s, "\n0x%02x: ", i);
}
fprintf(stderr, "%02x ",fis[i]);
g_string_append_printf(s, "%02x ", fis[i]);
}
fprintf(stderr, "\n");
#endif
g_string_append_c(s, '\n');
return g_string_free(s, FALSE);
}
static bool ahci_map_fis_address(AHCIDevice *ad)
@@ -655,7 +669,7 @@ static bool ahci_map_fis_address(AHCIDevice *ad)
static void ahci_unmap_fis_address(AHCIDevice *ad)
{
if (ad->res_fis == NULL) {
DPRINTF(ad->port_no, "Attempt to unmap NULL FIS address\n");
trace_ahci_unmap_fis_address_null(ad->hba, ad->port_no);
return;
}
ad->port_regs.cmd &= ~PORT_CMD_FIS_ON;
@@ -682,7 +696,7 @@ static bool ahci_map_clb_address(AHCIDevice *ad)
static void ahci_unmap_clb_address(AHCIDevice *ad)
{
if (ad->lst == NULL) {
DPRINTF(ad->port_no, "Attempt to unmap NULL CLB address\n");
trace_ahci_unmap_clb_address_null(ad->hba, ad->port_no);
return;
}
ad->port_regs.cmd &= ~PORT_CMD_LIST_ON;
@@ -723,7 +737,7 @@ static void ahci_write_fis_sdb(AHCIState *s, NCQTransferState *ncq_tfs)
/* Trigger IRQ if interrupt bit is set (which currently, it always is) */
if (sdb_fis->flags & 0x40) {
ahci_trigger_irq(s, ad, PORT_IRQ_SDB_FIS);
ahci_trigger_irq(s, ad, AHCI_PORT_IRQ_BIT_SDBS);
}
}
@@ -766,10 +780,10 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len)
ad->port.ifs[0].status;
if (pio_fis[2] & ERR_STAT) {
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR);
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES);
}
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_PIOS_FIS);
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_PSS);
}
static bool ahci_write_fis_d2h(AHCIDevice *ad)
@@ -809,10 +823,10 @@ static bool ahci_write_fis_d2h(AHCIDevice *ad)
ad->port.ifs[0].status;
if (d2h_fis[2] & ERR_STAT) {
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR);
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES);
}
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS);
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_DHRS);
return true;
}
@@ -854,20 +868,22 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist,
IDEBus *bus = &ad->port;
BusState *qbus = BUS(bus);
trace_ahci_populate_sglist(ad->hba, ad->port_no);
if (!prdtl) {
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
trace_ahci_populate_sglist_no_prdtl(ad->hba, ad->port_no, opts);
return -1;
}
/* map PRDT */
if (!(prdt = dma_memory_map(ad->hba->as, prdt_addr, &prdt_len,
DMA_DIRECTION_TO_DEVICE))){
DPRINTF(ad->port_no, "map failed\n");
trace_ahci_populate_sglist_no_map(ad->hba, ad->port_no);
return -1;
}
if (prdt_len < real_prdt_len) {
DPRINTF(ad->port_no, "mapped less than expected\n");
trace_ahci_populate_sglist_short_map(ad->hba, ad->port_no);
r = -1;
goto out;
}
@@ -886,9 +902,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist,
sum += tbl_entry_size;
}
if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) {
DPRINTF(ad->port_no, "%s: Incorrect offset! "
"off_idx: %d, off_pos: %"PRId64"\n",
__func__, off_idx, off_pos);
trace_ahci_populate_sglist_bad_offset(ad->hba, ad->port_no,
off_idx, off_pos);
r = -1;
goto out;
}
@@ -934,8 +949,8 @@ static void ncq_finish(NCQTransferState *ncq_tfs)
ahci_write_fis_sdb(ncq_tfs->drive->hba, ncq_tfs);
DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n",
ncq_tfs->tag);
trace_ncq_finish(ncq_tfs->drive->hba, ncq_tfs->drive->port_no,
ncq_tfs->tag);
block_acct_done(blk_get_stats(ncq_tfs->drive->port.ifs[0].blk),
&ncq_tfs->acct);
@@ -999,12 +1014,8 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
switch (ncq_tfs->cmd) {
case READ_FPDMA_QUEUED:
DPRINTF(port, "NCQ reading %d sectors from LBA %"PRId64", tag %d\n",
ncq_tfs->sector_count, ncq_tfs->lba, ncq_tfs->tag);
DPRINTF(port, "tag %d aio read %"PRId64"\n",
ncq_tfs->tag, ncq_tfs->lba);
trace_execute_ncq_command_read(ad->hba, port, ncq_tfs->tag,
ncq_tfs->sector_count, ncq_tfs->lba);
dma_acct_start(ide_state->blk, &ncq_tfs->acct,
&ncq_tfs->sglist, BLOCK_ACCT_READ);
ncq_tfs->aiocb = dma_blk_read(ide_state->blk, &ncq_tfs->sglist,
@@ -1013,12 +1024,8 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
ncq_cb, ncq_tfs);
break;
case WRITE_FPDMA_QUEUED:
DPRINTF(port, "NCQ writing %d sectors to LBA %"PRId64", tag %d\n",
ncq_tfs->sector_count, ncq_tfs->lba, ncq_tfs->tag);
DPRINTF(port, "tag %d aio write %"PRId64"\n",
ncq_tfs->tag, ncq_tfs->lba);
trace_execute_ncq_command_read(ad->hba, port, ncq_tfs->tag,
ncq_tfs->sector_count, ncq_tfs->lba);
dma_acct_start(ide_state->blk, &ncq_tfs->acct,
&ncq_tfs->sglist, BLOCK_ACCT_WRITE);
ncq_tfs->aiocb = dma_blk_write(ide_state->blk, &ncq_tfs->sglist,
@@ -1027,8 +1034,8 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs)
ncq_cb, ncq_tfs);
break;
default:
DPRINTF(port, "error: unsupported NCQ command (0x%02x) received\n",
ncq_tfs->cmd);
trace_execute_ncq_command_unsup(ad->hba, port,
ncq_tfs->tag, ncq_tfs->cmd);
ncq_err(ncq_tfs);
}
}
@@ -1038,7 +1045,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
uint8_t slot)
{
AHCIDevice *ad = &s->dev[port];
IDEState *ide_state = &ad->port.ifs[0];
NCQFrame *ncq_fis = (NCQFrame*)cmd_fis;
uint8_t tag = ncq_fis->tag >> 3;
NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag];
@@ -1066,21 +1072,20 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
/* Sanity-check the NCQ packet */
if (tag != slot) {
DPRINTF(port, "Warn: NCQ slot (%d) did not match the given tag (%d)\n",
slot, tag);
trace_process_ncq_command_mismatch(s, port, tag, slot);
}
if (ncq_fis->aux0 || ncq_fis->aux1 || ncq_fis->aux2 || ncq_fis->aux3) {
DPRINTF(port, "Warn: Attempt to use NCQ auxiliary fields.\n");
trace_process_ncq_command_aux(s, port, tag);
}
if (ncq_fis->prio || ncq_fis->icc) {
DPRINTF(port, "Warn: Unsupported attempt to use PRIO/ICC fields\n");
trace_process_ncq_command_prioicc(s, port, tag);
}
if (ncq_fis->fua & NCQ_FIS_FUA_MASK) {
DPRINTF(port, "Warn: Unsupported attempt to use Force Unit Access\n");
trace_process_ncq_command_fua(s, port, tag);
}
if (ncq_fis->tag & NCQ_FIS_RARC_MASK) {
DPRINTF(port, "Warn: Unsupported attempt to use Rebuild Assist\n");
trace_process_ncq_command_rarc(s, port, tag);
}
ncq_tfs->sector_count = ((ncq_fis->sector_count_high << 8) |
@@ -1096,19 +1101,17 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
"is smaller than the requested size (0x%zx)",
ncq_tfs->sglist.size, size);
ncq_err(ncq_tfs);
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_OVERFLOW);
ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_OFS);
return;
} else if (ncq_tfs->sglist.size != size) {
DPRINTF(port, "Warn: PRDTL (0x%zx)"
" does not match requested size (0x%zx)",
ncq_tfs->sglist.size, size);
trace_process_ncq_command_large(s, port, tag,
ncq_tfs->sglist.size, size);
}
DPRINTF(port, "NCQ transfer LBA from %"PRId64" to %"PRId64", "
"drive max %"PRId64"\n",
ncq_tfs->lba, ncq_tfs->lba + ncq_tfs->sector_count - 1,
ide_state->nb_sectors - 1);
trace_process_ncq_command(s, port, tag,
ncq_fis->command,
ncq_tfs->lba,
ncq_tfs->lba + ncq_tfs->sector_count - 1);
execute_ncq_command(ncq_tfs);
}
@@ -1129,16 +1132,14 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
uint16_t opts = le16_to_cpu(cmd->opts);
if (cmd_fis[1] & 0x0F) {
DPRINTF(port, "Port Multiplier not supported."
" cmd_fis[0]=%02x cmd_fis[1]=%02x cmd_fis[2]=%02x\n",
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
trace_handle_reg_h2d_fis_pmp(s, port, cmd_fis[1],
cmd_fis[2], cmd_fis[3]);
return;
}
if (cmd_fis[1] & 0x70) {
DPRINTF(port, "Reserved flags set in H2D Register FIS."
" cmd_fis[0]=%02x cmd_fis[1]=%02x cmd_fis[2]=%02x\n",
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
trace_handle_reg_h2d_fis_res(s, port, cmd_fis[1],
cmd_fis[2], cmd_fis[3]);
return;
}
@@ -1192,7 +1193,11 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
* table to ide_state->io_buffer */
if (opts & AHCI_CMD_ATAPI) {
memcpy(ide_state->io_buffer, &cmd_fis[AHCI_COMMAND_TABLE_ACMD], 0x10);
debug_print_fis(ide_state->io_buffer, 0x10);
if (trace_event_get_state_backends(TRACE_HANDLE_REG_H2D_FIS_DUMP)) {
char *pretty_fis = ahci_pretty_buffer_fis(ide_state->io_buffer, 0x10);
trace_handle_reg_h2d_fis_dump(s, port, pretty_fis);
g_free(pretty_fis);
}
s->dev[port].done_atapi_packet = false;
/* XXX send PIO setup FIS */
}
@@ -1216,12 +1221,12 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
/* Engine currently busy, try again later */
DPRINTF(port, "engine busy\n");
trace_handle_cmd_busy(s, port);
return -1;
}
if (!s->dev[port].lst) {
DPRINTF(port, "error: lst not given but cmd handled");
trace_handle_cmd_nolist(s, port);
return -1;
}
cmd = get_cmd_header(s, port, slot);
@@ -1231,7 +1236,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
/* The device we are working for */
ide_state = &s->dev[port].port.ifs[0];
if (!ide_state->blk) {
DPRINTF(port, "error: guest accessed unused port");
trace_handle_cmd_badport(s, port);
return -1;
}
@@ -1240,25 +1245,25 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot)
cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len,
DMA_DIRECTION_FROM_DEVICE);
if (!cmd_fis) {
DPRINTF(port, "error: guest passed us an invalid cmd fis\n");
trace_handle_cmd_badfis(s, port);
return -1;
} else if (cmd_len != 0x80) {
ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_HBUS_ERR);
DPRINTF(port, "error: dma_memory_map failed: "
"(len(%02"PRIx64") != 0x80)\n",
cmd_len);
ahci_trigger_irq(s, &s->dev[port], AHCI_PORT_IRQ_BIT_HBFS);
trace_handle_cmd_badmap(s, port, cmd_len);
goto out;
}
debug_print_fis(cmd_fis, 0x80);
if (trace_event_get_state_backends(TRACE_HANDLE_CMD_FIS_DUMP)) {
char *pretty_fis = ahci_pretty_buffer_fis(cmd_fis, 0x80);
trace_handle_cmd_fis_dump(s, port, pretty_fis);
g_free(pretty_fis);
}
switch (cmd_fis[0]) {
case SATA_FIS_TYPE_REGISTER_H2D:
handle_reg_h2d_fis(s, port, slot, cmd_fis);
break;
default:
DPRINTF(port, "unknown command cmd_fis[0]=%02x cmd_fis[1]=%02x "
"cmd_fis[2]=%02x\n", cmd_fis[0], cmd_fis[1],
cmd_fis[2]);
trace_handle_cmd_unhandled_fis(s, port,
cmd_fis[0], cmd_fis[1], cmd_fis[2]);
break;
}
@@ -1299,9 +1304,9 @@ static void ahci_start_transfer(IDEDMA *dma)
has_sglist = 1;
}
DPRINTF(ad->port_no, "%sing %d bytes on %s w/%s sglist\n",
is_write ? "writ" : "read", size, is_atapi ? "atapi" : "ata",
has_sglist ? "" : "o");
trace_ahci_start_transfer(ad->hba, ad->port_no, is_write ? "writ" : "read",
size, is_atapi ? "atapi" : "ata",
has_sglist ? "" : "o");
if (has_sglist && size) {
if (is_write) {
@@ -1330,7 +1335,7 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s,
BlockCompletionFunc *dma_cb)
{
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
DPRINTF(ad->port_no, "\n");
trace_ahci_start_dma(ad->hba, ad->port_no);
s->io_buffer_offset = 0;
dma_cb(s, 0);
}
@@ -1368,12 +1373,12 @@ static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int32_t limit)
if (ahci_populate_sglist(ad, &s->sg, ad->cur_cmd,
limit, s->io_buffer_offset) == -1) {
DPRINTF(ad->port_no, "ahci_dma_prepare_buf failed.\n");
trace_ahci_dma_prepare_buf_fail(ad->hba, ad->port_no);
return -1;
}
s->io_buffer_size = s->sg.size;
DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
trace_ahci_dma_prepare_buf(ad->hba, ad->port_no, limit, s->io_buffer_size);
return s->io_buffer_size;
}
@@ -1409,11 +1414,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
/* free sglist, update byte count */
dma_buf_commit(s, l);
s->io_buffer_index += l;
DPRINTF(ad->port_no, "len=%#x\n", l);
trace_ahci_dma_rw_buf(ad->hba, ad->port_no, l);
return 1;
}
@@ -1421,7 +1424,7 @@ static void ahci_cmd_done(IDEDMA *dma)
{
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
DPRINTF(ad->port_no, "cmd done\n");
trace_ahci_cmd_done(ad->hba, ad->port_no);
/* update d2h status */
ahci_write_fis_d2h(ad);
@@ -1495,6 +1498,7 @@ void ahci_uninit(AHCIState *s)
ide_exit(s);
}
object_unparent(OBJECT(&ad->port));
}
g_free(s->dev);
@@ -1505,6 +1509,8 @@ void ahci_reset(AHCIState *s)
AHCIPortRegs *pr;
int i;
trace_ahci_reset(s);
s->control_regs.irqstatus = 0;
/* AHCI Enable (AE)
* The implementation of this bit is dependent upon the value of the
@@ -1755,6 +1761,7 @@ static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr,
unsigned size)
{
AllwinnerAHCIState *a = opaque;
AHCIState *s = &(SYSBUS_AHCI(a)->ahci);
uint64_t val = a->regs[addr/4];
switch (addr / 4) {
@@ -1765,8 +1772,7 @@ static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr,
val &= ~(0x1 << 24);
break;
}
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
addr, val, size);
trace_allwinner_ahci_mem_read(s, a, addr, val, size);
return val;
}
@@ -1774,9 +1780,9 @@ static void allwinner_ahci_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
AllwinnerAHCIState *a = opaque;
AHCIState *s = &(SYSBUS_AHCI(a)->ahci);
DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n",
addr, val, size);
trace_allwinner_ahci_mem_write(s, a, addr, val, size);
a->regs[addr/4] = val;
}

View File

@@ -91,6 +91,31 @@
#define PORT_CMD_ISSUE 0x38 /* command issue */
#define PORT_RESERVED 0x3c /* reserved */
/* Port interrupt bit descriptors */
enum AHCIPortIRQ {
AHCI_PORT_IRQ_BIT_DHRS = 0,
AHCI_PORT_IRQ_BIT_PSS = 1,
AHCI_PORT_IRQ_BIT_DSS = 2,
AHCI_PORT_IRQ_BIT_SDBS = 3,
AHCI_PORT_IRQ_BIT_UFS = 4,
AHCI_PORT_IRQ_BIT_DPS = 5,
AHCI_PORT_IRQ_BIT_PCS = 6,
AHCI_PORT_IRQ_BIT_DMPS = 7,
/* RESERVED */
AHCI_PORT_IRQ_BIT_PRCS = 22,
AHCI_PORT_IRQ_BIT_IPMS = 23,
AHCI_PORT_IRQ_BIT_OFS = 24,
/* RESERVED */
AHCI_PORT_IRQ_BIT_INFS = 26,
AHCI_PORT_IRQ_BIT_IFS = 27,
AHCI_PORT_IRQ_BIT_HBDS = 28,
AHCI_PORT_IRQ_BIT_HBFS = 29,
AHCI_PORT_IRQ_BIT_TFES = 30,
AHCI_PORT_IRQ_BIT_CPDS = 31,
AHCI_PORT_IRQ__COUNT = 32
};
/* PORT_IRQ_{STAT,MASK} bits */
#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */
#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
@@ -98,18 +123,19 @@
#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */
#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */
/* reserved */
#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */
#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */
#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */
#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
/* reserved */
#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \

View File

@@ -27,6 +27,7 @@
#include "hw/ide/internal.h"
#include "hw/scsi/scsi.h"
#include "sysemu/block-backend.h"
#include "trace.h"
#define ATAPI_SECTOR_BITS (2 + BDRV_SECTOR_BITS)
#define ATAPI_SECTOR_SIZE (1 << ATAPI_SECTOR_BITS)
@@ -116,9 +117,7 @@ cd_read_sector_sync(IDEState *s)
block_acct_start(blk_get_stats(s->blk), &s->acct,
ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
#ifdef DEBUG_IDE_ATAPI
printf("cd_read_sector_sync: lba=%d\n", s->lba);
#endif
trace_cd_read_sector_sync(s->lba);
switch (s->cd_sector_size) {
case 2048:
@@ -152,9 +151,7 @@ static void cd_read_sector_cb(void *opaque, int ret)
{
IDEState *s = opaque;
#ifdef DEBUG_IDE_ATAPI
printf("cd_read_sector_cb: lba=%d ret=%d\n", s->lba, ret);
#endif
trace_cd_read_sector_cb(s->lba, ret);
if (ret < 0) {
block_acct_failed(blk_get_stats(s->blk), &s->acct);
@@ -188,9 +185,7 @@ static int cd_read_sector(IDEState *s)
s->iov.iov_len = ATAPI_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
#ifdef DEBUG_IDE_ATAPI
printf("cd_read_sector: lba=%d\n", s->lba);
#endif
trace_cd_read_sector(s->lba);
block_acct_start(blk_get_stats(s->blk), &s->acct,
ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
@@ -213,9 +208,7 @@ void ide_atapi_cmd_ok(IDEState *s)
void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
{
#ifdef DEBUG_IDE_ATAPI
printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
#endif
trace_ide_atapi_cmd_error(s, sense_key, asc);
s->error = sense_key << 4;
s->status = READY_STAT | ERR_STAT;
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
@@ -252,19 +245,14 @@ static uint16_t atapi_byte_count_limit(IDEState *s)
void ide_atapi_cmd_reply_end(IDEState *s)
{
int byte_count_limit, size, ret;
#ifdef DEBUG_IDE_ATAPI
printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
s->packet_transfer_size,
s->elementary_transfer_size,
s->io_buffer_index);
#endif
trace_ide_atapi_cmd_reply_end(s, s->packet_transfer_size,
s->elementary_transfer_size,
s->io_buffer_index);
if (s->packet_transfer_size <= 0) {
/* end of transfer */
ide_atapi_cmd_ok(s);
ide_set_irq(s->bus);
#ifdef DEBUG_IDE_ATAPI
printf("end of transfer, status=0x%x\n", s->status);
#endif
trace_ide_atapi_cmd_reply_end_eot(s, s->status);
} else {
/* see if a new sector must be read */
if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
@@ -300,9 +288,7 @@ void ide_atapi_cmd_reply_end(IDEState *s)
/* a new transfer is needed */
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
byte_count_limit = atapi_byte_count_limit(s);
#ifdef DEBUG_IDE_ATAPI
printf("byte_count_limit=%d\n", byte_count_limit);
#endif
trace_ide_atapi_cmd_reply_end_bcl(s, byte_count_limit);
size = s->packet_transfer_size;
if (size > byte_count_limit) {
/* byte count limit must be even if this case */
@@ -324,9 +310,7 @@ void ide_atapi_cmd_reply_end(IDEState *s)
ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
size, ide_atapi_cmd_reply_end);
ide_set_irq(s->bus);
#ifdef DEBUG_IDE_ATAPI
printf("status=0x%x\n", s->status);
#endif
trace_ide_atapi_cmd_reply_end_new(s, s->status);
}
}
}
@@ -368,9 +352,7 @@ static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
static void ide_atapi_cmd_check_status(IDEState *s)
{
#ifdef DEBUG_IDE_ATAPI
printf("atapi_cmd_check_status\n");
#endif
trace_ide_atapi_cmd_check_status(s);
s->error = MC_ERR | (UNIT_ATTENTION << 4);
s->status = ERR_STAT;
s->nsector = 0;
@@ -434,10 +416,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
s->io_buffer_size = n * 2048;
data_offset = 0;
}
#ifdef DEBUG_AIO
printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
#endif
trace_ide_atapi_cmd_read_dma_cb_aio(s, s->lba, n);
s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE;
qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
@@ -477,10 +456,8 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
int sector_size)
{
#ifdef DEBUG_IDE_ATAPI
printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
lba, nb_sectors);
#endif
trace_ide_atapi_cmd_read(s, s->atapi_dma ? "dma" : "pio",
lba, nb_sectors);
if (s->atapi_dma) {
ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
} else {
@@ -1330,16 +1307,18 @@ void ide_atapi_cmd(IDEState *s)
uint8_t *buf = s->io_buffer;
const struct AtapiCmd *cmd = &atapi_cmd_table[s->io_buffer[0]];
#ifdef DEBUG_IDE_ATAPI
{
trace_ide_atapi_cmd(s, s->io_buffer[0]);
if (trace_event_get_state_backends(TRACE_IDE_ATAPI_CMD_PACKET)) {
/* Each pretty-printed byte needs two bytes and a space; */
char *ppacket = g_malloc(ATAPI_PACKET_SIZE * 3 + 1);
int i;
printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
printf(" %02x", buf[i]);
for (i = 0; i < ATAPI_PACKET_SIZE; i++) {
sprintf(ppacket + (i * 3), "%02x ", buf[i]);
}
printf("\n");
trace_ide_atapi_cmd_packet(s, s->lcyl | (s->hcyl << 8), ppacket);
g_free(ppacket);
}
#endif
/*
* If there's a UNIT_ATTENTION condition pending, only command flagged with

View File

@@ -32,6 +32,7 @@
#include "sysemu/dma.h"
#include "hw/ide/pci.h"
#include "trace.h"
/* CMD646 specific */
#define CFR 0x50
@@ -195,9 +196,8 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr,
val = 0xff;
break;
}
#ifdef DEBUG_IDE
printf("bmdma: readb " TARGET_FMT_plx " : 0x%02x\n", addr, val);
#endif
trace_bmdma_read_cmd646(addr, val);
return val;
}
@@ -211,9 +211,7 @@ static void bmdma_write(void *opaque, hwaddr addr,
return;
}
#ifdef DEBUG_IDE
printf("bmdma: writeb " TARGET_FMT_plx " : 0x%" PRIx64 "\n", addr, val);
#endif
trace_bmdma_write_cmd646(addr, val);
switch(addr & 3) {
case 0:
bmdma_cmd_writeb(bm, val);

View File

@@ -34,8 +34,10 @@
#include "hw/block/block.h"
#include "sysemu/block-backend.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "hw/ide/internal.h"
#include "trace.h"
/* These values were based on a Seagate ST3500418AS but have been modified
to make more sense in QEMU */
@@ -57,6 +59,21 @@ static const int smart_attributes[][12] = {
{ 190, 0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
};
const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT] = {
[IDE_DMA_READ] = "DMA READ",
[IDE_DMA_WRITE] = "DMA WRITE",
[IDE_DMA_TRIM] = "DMA TRIM",
[IDE_DMA_ATAPI] = "DMA ATAPI"
};
static const char *IDE_DMA_CMD_str(enum ide_dma_cmd enval)
{
if (enval >= IDE_DMA__BEGIN && enval < IDE_DMA__COUNT) {
return IDE_DMA_CMD_lookup[enval];
}
return "DMA UNKNOWN CMD";
}
static void ide_dummy_transfer_stop(IDEState *s);
static void padstr(char *str, const char *src, int len)
@@ -656,10 +673,7 @@ void ide_cancel_dma_sync(IDEState *s)
* write requests) pending and we can avoid to drain. */
QLIST_FOREACH(req, &s->buffered_requests, list) {
if (!req->orphaned) {
#ifdef DEBUG_IDE
printf("%s: invoking cb %p of buffered request %p with"
" -ECANCELED\n", __func__, req->original_cb, req);
#endif
trace_ide_cancel_dma_sync_buffered(req->original_cb, req);
req->original_cb(req->original_opaque, -ECANCELED);
}
req->orphaned = true;
@@ -678,9 +692,7 @@ void ide_cancel_dma_sync(IDEState *s)
* aio operation with preadv/pwritev.
*/
if (s->bus->dma->aiocb) {
#ifdef DEBUG_IDE
printf("%s: draining all remaining requests", __func__);
#endif
trace_ide_cancel_dma_sync_remaining();
blk_drain(s->blk);
assert(s->bus->dma->aiocb == NULL);
}
@@ -741,9 +753,7 @@ static void ide_sector_read(IDEState *s)
n = s->req_nb_sectors;
}
#if defined(DEBUG_IDE)
printf("sector=%" PRId64 "\n", sector_num);
#endif
trace_ide_sector_read(sector_num, n);
if (!ide_sect_range_ok(s, sector_num, n)) {
ide_rw_error(s);
@@ -866,10 +876,7 @@ static void ide_dma_cb(void *opaque, int ret)
goto eot;
}
#ifdef DEBUG_AIO
printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, cmd_cmd=%d\n",
sector_num, n, s->dma_cmd);
#endif
trace_ide_dma_cb(s, sector_num, n, IDE_DMA_CMD_str(s->dma_cmd));
if ((s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) &&
!ide_sect_range_ok(s, sector_num, n)) {
@@ -1005,14 +1012,14 @@ static void ide_sector_write(IDEState *s)
s->status = READY_STAT | SEEK_STAT | BUSY_STAT;
sector_num = ide_get_sector(s);
#if defined(DEBUG_IDE)
printf("sector=%" PRId64 "\n", sector_num);
#endif
n = s->nsector;
if (n > s->req_nb_sectors) {
n = s->req_nb_sectors;
}
trace_ide_sector_write(sector_num, n);
if (!ide_sect_range_ok(s, sector_num, n)) {
ide_rw_error(s);
block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
@@ -1191,60 +1198,83 @@ static void ide_clear_hob(IDEBus *bus)
bus->ifs[1].select &= ~(1 << 7);
}
/* IOport [W]rite [R]egisters */
enum ATA_IOPORT_WR {
ATA_IOPORT_WR_DATA = 0,
ATA_IOPORT_WR_FEATURES = 1,
ATA_IOPORT_WR_SECTOR_COUNT = 2,
ATA_IOPORT_WR_SECTOR_NUMBER = 3,
ATA_IOPORT_WR_CYLINDER_LOW = 4,
ATA_IOPORT_WR_CYLINDER_HIGH = 5,
ATA_IOPORT_WR_DEVICE_HEAD = 6,
ATA_IOPORT_WR_COMMAND = 7,
ATA_IOPORT_WR_NUM_REGISTERS,
};
const char *ATA_IOPORT_WR_lookup[ATA_IOPORT_WR_NUM_REGISTERS] = {
[ATA_IOPORT_WR_DATA] = "Data",
[ATA_IOPORT_WR_FEATURES] = "Features",
[ATA_IOPORT_WR_SECTOR_COUNT] = "Sector Count",
[ATA_IOPORT_WR_SECTOR_NUMBER] = "Sector Number",
[ATA_IOPORT_WR_CYLINDER_LOW] = "Cylinder Low",
[ATA_IOPORT_WR_CYLINDER_HIGH] = "Cylinder High",
[ATA_IOPORT_WR_DEVICE_HEAD] = "Device/Head",
[ATA_IOPORT_WR_COMMAND] = "Command"
};
void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
IDEBus *bus = opaque;
IDEState *s = idebus_active_if(bus);
int reg_num = addr & 7;
#ifdef DEBUG_IDE
printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
#endif
addr &= 7;
trace_ide_ioport_write(addr, ATA_IOPORT_WR_lookup[reg_num], val, bus, s);
/* ignore writes to command block while busy with previous command */
if (addr != 7 && (idebus_active_if(bus)->status & (BUSY_STAT|DRQ_STAT)))
if (reg_num != 7 && (s->status & (BUSY_STAT|DRQ_STAT))) {
return;
}
switch(addr) {
switch (reg_num) {
case 0:
break;
case 1:
ide_clear_hob(bus);
case ATA_IOPORT_WR_FEATURES:
ide_clear_hob(bus);
/* NOTE: data is written to the two drives */
bus->ifs[0].hob_feature = bus->ifs[0].feature;
bus->ifs[1].hob_feature = bus->ifs[1].feature;
bus->ifs[0].hob_feature = bus->ifs[0].feature;
bus->ifs[1].hob_feature = bus->ifs[1].feature;
bus->ifs[0].feature = val;
bus->ifs[1].feature = val;
break;
case 2:
case ATA_IOPORT_WR_SECTOR_COUNT:
ide_clear_hob(bus);
bus->ifs[0].hob_nsector = bus->ifs[0].nsector;
bus->ifs[1].hob_nsector = bus->ifs[1].nsector;
bus->ifs[0].nsector = val;
bus->ifs[1].nsector = val;
break;
case 3:
case ATA_IOPORT_WR_SECTOR_NUMBER:
ide_clear_hob(bus);
bus->ifs[0].hob_sector = bus->ifs[0].sector;
bus->ifs[1].hob_sector = bus->ifs[1].sector;
bus->ifs[0].sector = val;
bus->ifs[1].sector = val;
break;
case 4:
case ATA_IOPORT_WR_CYLINDER_LOW:
ide_clear_hob(bus);
bus->ifs[0].hob_lcyl = bus->ifs[0].lcyl;
bus->ifs[1].hob_lcyl = bus->ifs[1].lcyl;
bus->ifs[0].lcyl = val;
bus->ifs[1].lcyl = val;
break;
case 5:
case ATA_IOPORT_WR_CYLINDER_HIGH:
ide_clear_hob(bus);
bus->ifs[0].hob_hcyl = bus->ifs[0].hcyl;
bus->ifs[1].hob_hcyl = bus->ifs[1].hcyl;
bus->ifs[0].hcyl = val;
bus->ifs[1].hcyl = val;
break;
case 6:
case ATA_IOPORT_WR_DEVICE_HEAD:
/* FIXME: HOB readback uses bit 7 */
bus->ifs[0].select = (val & ~0x10) | 0xa0;
bus->ifs[1].select = (val | 0x10) | 0xa0;
@@ -1252,7 +1282,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
bus->unit = (val >> 4) & 1;
break;
default:
case 7:
case ATA_IOPORT_WR_COMMAND:
/* command */
ide_exec_cmd(bus, val);
break;
@@ -1261,9 +1291,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
static void ide_reset(IDEState *s)
{
#ifdef DEBUG_IDE
printf("ide: reset\n");
#endif
trace_ide_reset(s);
if (s->pio_aiocb) {
blk_aio_cancel(s->pio_aiocb);
@@ -2021,10 +2049,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
IDEState *s;
bool complete;
#if defined(DEBUG_IDE)
printf("ide: CMD=%02x\n", val);
#endif
s = idebus_active_if(bus);
trace_ide_exec_cmd(bus, s, val);
/* ignore commands to non existent slave */
if (s != bus->ifs && !s->blk) {
return;
@@ -2062,22 +2089,46 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
}
}
uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
/* IOport [R]ead [R]egisters */
enum ATA_IOPORT_RR {
ATA_IOPORT_RR_DATA = 0,
ATA_IOPORT_RR_ERROR = 1,
ATA_IOPORT_RR_SECTOR_COUNT = 2,
ATA_IOPORT_RR_SECTOR_NUMBER = 3,
ATA_IOPORT_RR_CYLINDER_LOW = 4,
ATA_IOPORT_RR_CYLINDER_HIGH = 5,
ATA_IOPORT_RR_DEVICE_HEAD = 6,
ATA_IOPORT_RR_STATUS = 7,
ATA_IOPORT_RR_NUM_REGISTERS,
};
const char *ATA_IOPORT_RR_lookup[ATA_IOPORT_RR_NUM_REGISTERS] = {
[ATA_IOPORT_RR_DATA] = "Data",
[ATA_IOPORT_RR_ERROR] = "Error",
[ATA_IOPORT_RR_SECTOR_COUNT] = "Sector Count",
[ATA_IOPORT_RR_SECTOR_NUMBER] = "Sector Number",
[ATA_IOPORT_RR_CYLINDER_LOW] = "Cylinder Low",
[ATA_IOPORT_RR_CYLINDER_HIGH] = "Cylinder High",
[ATA_IOPORT_RR_DEVICE_HEAD] = "Device/Head",
[ATA_IOPORT_RR_STATUS] = "Status"
};
uint32_t ide_ioport_read(void *opaque, uint32_t addr)
{
IDEBus *bus = opaque;
IDEState *s = idebus_active_if(bus);
uint32_t addr;
uint32_t reg_num;
int ret, hob;
addr = addr1 & 7;
reg_num = addr & 7;
/* FIXME: HOB readback uses bit 7, but it's always set right now */
//hob = s->select & (1 << 7);
hob = 0;
switch(addr) {
case 0:
switch (reg_num) {
case ATA_IOPORT_RR_DATA:
ret = 0xff;
break;
case 1:
case ATA_IOPORT_RR_ERROR:
if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
(s != bus->ifs && !s->blk)) {
ret = 0;
@@ -2087,7 +2138,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
ret = s->hob_feature;
}
break;
case 2:
case ATA_IOPORT_RR_SECTOR_COUNT:
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
ret = 0;
} else if (!hob) {
@@ -2096,7 +2147,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
ret = s->hob_nsector;
}
break;
case 3:
case ATA_IOPORT_RR_SECTOR_NUMBER:
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
ret = 0;
} else if (!hob) {
@@ -2105,7 +2156,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
ret = s->hob_sector;
}
break;
case 4:
case ATA_IOPORT_RR_CYLINDER_LOW:
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
ret = 0;
} else if (!hob) {
@@ -2114,7 +2165,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
ret = s->hob_lcyl;
}
break;
case 5:
case ATA_IOPORT_RR_CYLINDER_HIGH:
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
ret = 0;
} else if (!hob) {
@@ -2123,7 +2174,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
ret = s->hob_hcyl;
}
break;
case 6:
case ATA_IOPORT_RR_DEVICE_HEAD:
if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
ret = 0;
} else {
@@ -2131,7 +2182,7 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
}
break;
default:
case 7:
case ATA_IOPORT_RR_STATUS:
if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
(s != bus->ifs && !s->blk)) {
ret = 0;
@@ -2141,9 +2192,8 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
qemu_irq_lower(bus->irq);
break;
}
#ifdef DEBUG_IDE
printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
#endif
trace_ide_ioport_read(addr, ATA_IOPORT_RR_lookup[reg_num], ret, bus, s);
return ret;
}
@@ -2159,9 +2209,8 @@ uint32_t ide_status_read(void *opaque, uint32_t addr)
} else {
ret = s->status;
}
#ifdef DEBUG_IDE
printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
#endif
trace_ide_status_read(addr, ret, bus, s);
return ret;
}
@@ -2171,9 +2220,8 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
IDEState *s;
int i;
#ifdef DEBUG_IDE
printf("ide: write control addr=0x%x val=%02x\n", addr, val);
#endif
trace_ide_cmd_write(addr, val, bus);
/* common for both drives */
if (!(bus->cmd & IDE_CMD_RESET) &&
(val & IDE_CMD_RESET)) {
@@ -2224,6 +2272,8 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
IDEState *s = idebus_active_if(bus);
uint8_t *p;
trace_ide_data_writew(addr, val, bus, s);
/* PIO data access allowed only when DRQ bit is set. The result of a write
* during PIO out is indeterminate, just ignore it. */
if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
@@ -2269,6 +2319,8 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
s->status &= ~DRQ_STAT;
s->end_transfer_func(s);
}
trace_ide_data_readw(addr, ret, bus, s);
return ret;
}
@@ -2278,6 +2330,8 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
IDEState *s = idebus_active_if(bus);
uint8_t *p;
trace_ide_data_writel(addr, val, bus, s);
/* PIO data access allowed only when DRQ bit is set. The result of a write
* during PIO out is indeterminate, just ignore it. */
if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
@@ -2308,7 +2362,8 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
/* PIO data access allowed only when DRQ bit is set. The result of a read
* during PIO in is indeterminate, return 0 and don't move forward. */
if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
return 0;
ret = 0;
goto out;
}
p = s->data_ptr;
@@ -2323,6 +2378,9 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
s->status &= ~DRQ_STAT;
s->end_transfer_func(s);
}
out:
trace_ide_data_readl(addr, ret, bus, s);
return ret;
}
@@ -2346,9 +2404,7 @@ void ide_bus_reset(IDEBus *bus)
/* pending async DMA */
if (bus->dma->aiocb) {
#ifdef DEBUG_AIO
printf("aio_cancel\n");
#endif
trace_ide_bus_reset_aio();
blk_aio_cancel(bus->dma->aiocb);
bus->dma->aiocb = NULL;
}
@@ -2406,7 +2462,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
const char *version, const char *serial, const char *model,
uint64_t wwn,
uint32_t cylinders, uint32_t heads, uint32_t secs,
int chs_trans)
int chs_trans, Error **errp)
{
uint64_t nb_sectors;
@@ -2431,11 +2487,11 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
blk_set_guest_block_size(blk, 2048);
} else {
if (!blk_is_inserted(s->blk)) {
error_report("Device needs media, but drive is empty");
error_setg(errp, "Device needs media, but drive is empty");
return -1;
}
if (blk_is_read_only(blk)) {
error_report("Can't use a read-only drive");
error_setg(errp, "Can't use a read-only drive");
return -1;
}
blk_set_dev_ops(blk, &ide_hd_block_ops, s);

View File

@@ -575,12 +575,15 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
static void dscm1xxxx_class_init(ObjectClass *oc, void *data)
{
PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);
pcc->cis = dscm1xxxx_cis;
pcc->cis_len = sizeof(dscm1xxxx_cis);
pcc->attach = dscm1xxxx_attach;
pcc->detach = dscm1xxxx_detach;
/* Reason: Needs to be wired-up in code, see dscm1xxxx_init() */
dc->user_creatable = false;
}
static const TypeInfo dscm1xxxx_type_info = {

View File

@@ -31,6 +31,7 @@
#include "sysemu/dma.h"
#include "qemu/error-report.h"
#include "hw/ide/pci.h"
#include "trace.h"
#define BMDMA_PAGE_SIZE 4096
@@ -196,9 +197,7 @@ static void bmdma_reset(IDEDMA *dma)
{
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
#ifdef DEBUG_IDE
printf("ide: dma_reset\n");
#endif
trace_bmdma_reset();
bmdma_cancel(bm);
bm->cmd = 0;
bm->status = 0;
@@ -227,9 +226,7 @@ static void bmdma_irq(void *opaque, int n, int level)
void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
{
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
trace_bmdma_cmd_writeb(val);
/* Ignore writes to SSBM if it keeps the old value */
if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
@@ -258,9 +255,7 @@ static uint64_t bmdma_addr_read(void *opaque, hwaddr addr,
uint64_t data;
data = (bm->addr >> (addr * 8)) & mask;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, (unsigned)data);
#endif
trace_bmdma_addr_read(data);
return data;
}
@@ -271,9 +266,7 @@ static void bmdma_addr_write(void *opaque, hwaddr addr,
int shift = addr * 8;
uint32_t mask = (1ULL << (width * 8)) - 1;
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, (unsigned)data);
#endif
trace_bmdma_addr_write(data);
bm->addr &= ~(mask << shift);
bm->addr |= ((data & mask) << shift) & ~3;
}

View File

@@ -33,6 +33,7 @@
#include "sysemu/dma.h"
#include "hw/ide/pci.h"
#include "trace.h"
static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size)
{
@@ -54,9 +55,8 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size)
val = 0xff;
break;
}
#ifdef DEBUG_IDE
printf("bmdma: readb 0x%02x : 0x%02x\n", (uint8_t)addr, val);
#endif
trace_bmdma_read(addr, val);
return val;
}
@@ -69,9 +69,8 @@ static void bmdma_write(void *opaque, hwaddr addr,
return;
}
#ifdef DEBUG_IDE
printf("bmdma: writeb 0x%02x : 0x%02x\n", (uint8_t)addr, (uint8_t)val);
#endif
trace_bmdma_write(addr, val);
switch(addr & 3) {
case 0:
bmdma_cmd_writeb(bm, val);

View File

@@ -80,7 +80,7 @@ static char *idebus_get_fw_dev_path(DeviceState *dev)
return g_strdup(path);
}
static int ide_qdev_init(DeviceState *qdev)
static void ide_qdev_realize(DeviceState *qdev, Error **errp)
{
IDEDevice *dev = IDE_DEVICE(qdev);
IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
@@ -91,34 +91,31 @@ static int ide_qdev_init(DeviceState *qdev)
}
if (dev->unit >= bus->max_units) {
error_report("Can't create IDE unit %d, bus supports only %d units",
error_setg(errp, "Can't create IDE unit %d, bus supports only %d units",
dev->unit, bus->max_units);
goto err;
return;
}
switch (dev->unit) {
case 0:
if (bus->master) {
error_report("IDE unit %d is in use", dev->unit);
goto err;
error_setg(errp, "IDE unit %d is in use", dev->unit);
return;
}
bus->master = dev;
break;
case 1:
if (bus->slave) {
error_report("IDE unit %d is in use", dev->unit);
goto err;
error_setg(errp, "IDE unit %d is in use", dev->unit);
return;
}
bus->slave = dev;
break;
default:
error_report("Invalid IDE unit %d", dev->unit);
goto err;
error_setg(errp, "Invalid IDE unit %d", dev->unit);
return;
}
return dc->init(dev);
err:
return -1;
dc->realize(dev, errp);
}
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
@@ -159,7 +156,7 @@ typedef struct IDEDrive {
IDEDevice dev;
} IDEDrive;
static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
{
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
IDEState *s = bus->ifs + dev->unit;
@@ -168,8 +165,8 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
if (!dev->conf.blk) {
if (kind != IDE_CD) {
error_report("No drive specified");
return -1;
error_setg(errp, "No drive specified");
return;
} else {
/* Anonymous BlockBackend for an empty drive */
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
@@ -182,36 +179,36 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
dev->conf.discard_granularity = 512;
} else if (dev->conf.discard_granularity &&
dev->conf.discard_granularity != 512) {
error_report("discard_granularity must be 512 for ide");
return -1;
error_setg(errp, "discard_granularity must be 512 for ide");
return;
}
blkconf_blocksizes(&dev->conf);
if (dev->conf.logical_block_size != 512) {
error_report("logical_block_size must be 512 for IDE");
return -1;
error_setg(errp, "logical_block_size must be 512 for IDE");
return;
}
blkconf_serial(&dev->conf, &dev->serial);
if (kind != IDE_CD) {
blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err);
if (err) {
error_report_err(err);
return -1;
error_propagate(errp, err);
return;
}
}
blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, kind != IDE_CD,
&err);
if (err) {
error_report_err(err);
return -1;
error_propagate(errp, err);
return;
}
if (ide_init_drive(s, dev->conf.blk, kind,
dev->version, dev->serial, dev->model, dev->wwn,
dev->conf.cyls, dev->conf.heads, dev->conf.secs,
dev->chs_trans) < 0) {
return -1;
dev->chs_trans, errp) < 0) {
return;
}
if (!dev->version) {
@@ -223,8 +220,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
add_boot_device_path(dev->conf.bootindex, &dev->qdev,
dev->unit ? "/disk@1" : "/disk@0");
return 0;
}
static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name,
@@ -270,17 +265,17 @@ static void ide_dev_instance_init(Object *obj)
object_property_set_int(obj, -1, "bootindex", NULL);
}
static int ide_hd_initfn(IDEDevice *dev)
static void ide_hd_realize(IDEDevice *dev, Error **errp)
{
return ide_dev_initfn(dev, IDE_HD);
ide_dev_initfn(dev, IDE_HD, errp);
}
static int ide_cd_initfn(IDEDevice *dev)
static void ide_cd_realize(IDEDevice *dev, Error **errp)
{
return ide_dev_initfn(dev, IDE_CD);
ide_dev_initfn(dev, IDE_CD, errp);
}
static int ide_drive_initfn(IDEDevice *dev)
static void ide_drive_realize(IDEDevice *dev, Error **errp)
{
DriveInfo *dinfo = NULL;
@@ -288,7 +283,7 @@ static int ide_drive_initfn(IDEDevice *dev)
dinfo = blk_legacy_dinfo(dev->conf.blk);
}
return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD, errp);
}
#define DEFINE_IDE_DEV_PROPERTIES() \
@@ -311,10 +306,11 @@ static void ide_hd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
k->init = ide_hd_initfn;
k->realize = ide_hd_realize;
dc->fw_name = "drive";
dc->desc = "virtual IDE disk";
dc->props = ide_hd_properties;
dc->desc = "virtual IDE disk";
dc->props = ide_hd_properties;
}
static const TypeInfo ide_hd_info = {
@@ -333,10 +329,11 @@ static void ide_cd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
k->init = ide_cd_initfn;
k->realize = ide_cd_realize;
dc->fw_name = "drive";
dc->desc = "virtual IDE CD-ROM";
dc->props = ide_cd_properties;
dc->desc = "virtual IDE CD-ROM";
dc->props = ide_cd_properties;
}
static const TypeInfo ide_cd_info = {
@@ -355,10 +352,11 @@ static void ide_drive_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
k->init = ide_drive_initfn;
k->realize = ide_drive_realize;
dc->fw_name = "drive";
dc->desc = "virtual IDE disk or CD-ROM (legacy)";
dc->props = ide_drive_properties;
dc->desc = "virtual IDE disk or CD-ROM (legacy)";
dc->props = ide_drive_properties;
}
static const TypeInfo ide_drive_info = {
@@ -371,7 +369,7 @@ static const TypeInfo ide_drive_info = {
static void ide_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = ide_qdev_init;
k->realize = ide_qdev_realize;
set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
k->bus_type = TYPE_IDE_BUS;
k->props = ide_props;

111
hw/ide/trace-events Normal file
View File

@@ -0,0 +1,111 @@
# See docs/devel/tracing.txt for syntax documentation.
# hw/ide/core.c
# portio
ide_ioport_read(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
ide_ioport_write(uint32_t addr, const char *reg, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (%s); val 0x%02"PRIx32"; bus %p IDEState %p"
ide_status_read(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Alt Status); val 0x%02"PRIx32"; bus %p; IDEState %p"
ide_cmd_write(uint32_t addr, uint32_t val, void *bus) "IDE PIO wr @ 0x%"PRIx32" (Device Control); val 0x%02"PRIx32"; bus %p"
# Warning: verbose
ide_data_readw(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
ide_data_writew(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (Data: Word); val 0x%04"PRIx32"; bus %p; IDEState %p"
ide_data_readl(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO rd @ 0x%"PRIx32" (Data: Long); val 0x%08"PRIx32"; bus %p; IDEState %p"
ide_data_writel(uint32_t addr, uint32_t val, void *bus, void *s) "IDE PIO wr @ 0x%"PRIx32" (Data: Long); val 0x%08"PRIx32"; bus %p; IDEState %p"
# misc
ide_exec_cmd(void *bus, void *state, uint32_t cmd) "IDE exec cmd: bus %p; state %p; cmd 0x%02x"
ide_cancel_dma_sync_buffered(void *fn, void *req) "invoking cb %p of buffered request %p with -ECANCELED"
ide_cancel_dma_sync_remaining(void) "draining all remaining requests"
ide_sector_read(int64_t sector_num, int nsectors) "sector=%"PRId64" nsectors=%d"
ide_sector_write(int64_t sector_num, int nsectors) "sector=%"PRId64" nsectors=%d"
ide_reset(void *s) "IDEstate %p"
ide_bus_reset_aio(void) "aio_cancel"
ide_dma_cb(void *s, int64_t sector_num, int n, const char *dma) "IDEState %p; sector_num=%"PRId64" n=%d cmd=%s"
# BMDMA HBAs:
# hw/ide/cmd646.c
bmdma_read_cmd646(uint64_t addr, uint32_t val) "bmdma: readb 0x%"PRIx64" : 0x%02x"
bmdma_write_cmd646(uint64_t addr, uint64_t val) "bmdma: writeb 0x%"PRIx64" : 0x%02"PRIx64
# hw/ide/pci.c
bmdma_reset(void) ""
bmdma_cmd_writeb(uint32_t val) "val: 0x%08x"
bmdma_addr_read(uint64_t data) "data: 0x%016"PRIx64
bmdma_addr_write(uint64_t data) "data: 0x%016"PRIx64
# hw/ide/piix.c
bmdma_read(uint64_t addr, uint8_t val) "bmdma: readb 0x%"PRIx64" : 0x%02x"
bmdma_write(uint64_t addr, uint64_t val) "bmdma: writeb 0x%"PRIx64" : 0x%02"PRIx64
# hw/ide/via.c
bmdma_read_via(uint64_t addr, uint32_t val) "bmdma: readb 0x%"PRIx64" : 0x%02x"
bmdma_write_via(uint64_t addr, uint64_t val) "bmdma: writeb 0x%"PRIx64" : 0x%02"PRIx64
# hw/ide/atapi.c
cd_read_sector_sync(int lba) "lba=%d"
cd_read_sector_cb(int lba, int ret) "lba=%d ret=%d"
cd_read_sector(int lba) "lba=%d"
ide_atapi_cmd_error(void *s, int sense_key, int asc) "IDEState: %p; sense=0x%x asc=0x%x"
ide_atapi_cmd_reply_end(void *s, int tx_size, int elem_tx_size, int32_t index) "IDEState %p; reply: tx_size=%d elem_tx_size=%d index=%"PRId32
ide_atapi_cmd_reply_end_eot(void *s, int status) "IDEState: %p; end of transfer, status=0x%x"
ide_atapi_cmd_reply_end_bcl(void *s, int bcl) "IDEState: %p; byte_count_limit=%d"
ide_atapi_cmd_reply_end_new(void *s, int status) "IDEState: %p; new transfer started, status=0x%x"
ide_atapi_cmd_check_status(void *s) "IDEState: %p"
ide_atapi_cmd_read(void *s, const char *method, int lba, int nb_sectors) "IDEState: %p; read %s: LBA=%d nb_sectors=%d"
ide_atapi_cmd(void *s, uint8_t cmd) "IDEState: %p; cmd: 0x%02x"
ide_atapi_cmd_read_dma_cb_aio(void *s, int lba, int n) "IDEState: %p; aio read: lba=%d n=%d"
# Warning: Verbose
ide_atapi_cmd_packet(void *s, uint16_t limit, const char *packet) "IDEState: %p; limit=0x%x packet: %s"
# hw/ide/ahci.c
ahci_port_read(void *s, int port, int offset, uint32_t ret) "ahci(%p)[%d]: port read @ 0x%x: 0x%08x"
ahci_irq_raise(void *s) "ahci(%p): raise irq"
ahci_irq_lower(void *s) "ahci(%p): lower irq"
ahci_check_irq(void *s, uint32_t old, uint32_t new) "ahci(%p): check irq 0x%08x --> 0x%08x"
ahci_trigger_irq(void *s, int port, const char *name, uint32_t val, uint32_t old, uint32_t new, uint32_t effective) "ahci(%p)[%d]: trigger irq +%s (0x%08x); irqstat: 0x%08x --> 0x%08x; effective: 0x%08x"
ahci_port_write(void *s, int port, int offset, uint32_t val) "ahci(%p)[%d]: port write @ 0x%x: 0x%08x"
ahci_mem_read_32(void *s, uint64_t addr, uint32_t val) "ahci(%p): mem read @ 0x%"PRIx64": 0x%08x"
ahci_mem_read(void *s, unsigned size, uint64_t addr, uint64_t val) "ahci(%p): read%u @ 0x%"PRIx64": 0x%016"PRIx64
ahci_mem_write(void *s, unsigned size, uint64_t addr, uint64_t val) "ahci(%p): write%u @ 0x%"PRIx64": 0x%016"PRIx64
ahci_mem_write_unknown(void *s, unsigned size, uint64_t addr, uint64_t val) "ahci(%p): write%u to unknown register 0x%"PRIx64": 0x%016"PRIx64
ahci_set_signature(void *s, int port, uint8_t nsector, uint8_t sector, uint8_t lcyl, uint8_t hcyl, uint32_t sig) "ahci(%p)[%d]: set signature sector:0x%02x nsector:0x%02x lcyl:0x%02x hcyl:0x%02x (cumulatively: 0x%08x)"
ahci_reset_port(void *s, int port) "ahci(%p)[%d]: reset port"
ahci_unmap_fis_address_null(void *s, int port) "ahci(%p)[%d]: Attempt to unmap NULL FIS address"
ahci_unmap_clb_address_null(void *s, int port) "ahci(%p)[%d]: Attempt to unmap NULL CLB address"
ahci_populate_sglist(void *s, int port) "ahci(%p)[%d]"
ahci_populate_sglist_no_prdtl(void *s, int port, uint16_t opts) "ahci(%p)[%d]: no sg list given by guest: 0x%04x"
ahci_populate_sglist_no_map(void *s, int port) "ahci(%p)[%d]: DMA mapping failed"
ahci_populate_sglist_short_map(void *s, int port) "ahci(%p)[%d]: mapped less than expected"
ahci_populate_sglist_bad_offset(void *s, int port, int off_idx, int64_t off_pos) "ahci(%p)[%d]: Incorrect offset! off_idx: %d, off_pos: %"PRId64
ncq_finish(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: NCQ transfer finished"
execute_ncq_command_read(void *s, int port, uint8_t tag, int count, int64_t lba) "ahci(%p)[%d][tag:%d]: NCQ reading %d sectors from LBA %"PRId64
execute_ncq_command_write(void *s, int port, uint8_t tag, int count, int64_t lba) "ahci(%p)[%d][tag:%d]: NCQ writing %d sectors to LBA %"PRId64
execute_ncq_command_unsup(void *s, int port, uint8_t tag, uint8_t cmd) "ahci(%p)[%d][tag:%d]: error: unsupported NCQ command (0x%02x) received"
process_ncq_command_mismatch(void *s, int port, uint8_t tag, uint8_t slot) "ahci(%p)[%d][tag:%d]: Warning: NCQ slot (%d) did not match the given tag"
process_ncq_command_aux(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Attempt to use NCQ auxiliary fields"
process_ncq_command_prioicc(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Unsupported attempt to use PRIO/ICC fields"
process_ncq_command_fua(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Unsupported attempt to use Force Unit Access"
process_ncq_command_rarc(void *s, int port, uint8_t tag) "ahci(%p)[%d][tag:%d]: Warn: Unsupported attempt to use Rebuild Assist"
process_ncq_command_large(void *s, int port, uint8_t tag, size_t prdtl, size_t size) "ahci(%p)[%d][tag:%d]: Warn: PRDTL (0x%zx) does not match requested size (0x%zx)"
process_ncq_command(void *s, int port, uint8_t tag, uint8_t cmd, uint64_t lba, uint64_t end) "ahci(%p)[%d][tag:%d]: NCQ op 0x%02x on sectors [%"PRId64",%"PRId64"]"
handle_reg_h2d_fis_pmp(void *s, int port, char b0, char b1, char b2) "ahci(%p)[%d]: Port Multiplier not supported, FIS: 0x%02x-%02x-%02x"
handle_reg_h2d_fis_res(void *s, int port, char b0, char b1, char b2) "ahci(%p)[%d]: Reserved flags set in H2D Register FIS, FIS: 0x%02x-%02x-%02x"
handle_cmd_busy(void *s, int port) "ahci(%p)[%d]: engine busy"
handle_cmd_nolist(void *s, int port) "ahci(%p)[%d]: handle_cmd called without s->dev[port].lst"
handle_cmd_badport(void *s, int port) "ahci(%p)[%d]: guest accessed unused port"
handle_cmd_badfis(void *s, int port) "ahci(%p)[%d]: guest provided an invalid cmd FIS"
handle_cmd_badmap(void *s, int port, uint64_t len) "ahci(%p)[%d]: dma_memory_map failed, 0x%02"PRIx64" != 0x80"
handle_cmd_unhandled_fis(void *s, int port, uint8_t b0, uint8_t b1, uint8_t b2) "ahci(%p)[%d]: unhandled FIS type. cmd_fis: 0x%02x-%02x-%02x"
ahci_start_transfer(void *s, int port, const char *rw, uint32_t size, const char *tgt, const char *sgl) "ahci(%p)[%d]: %sing %d bytes on %s w/%s sglist"
ahci_start_dma(void *s, int port) "ahci(%p)[%d]: start dma"
ahci_dma_prepare_buf(void *s, int port, int32_t io_buffer_size, int32_t limit) "ahci(%p)[%d]: prepare buf limit=%"PRId32" prepared=%"PRId32
ahci_dma_prepare_buf_fail(void *s, int port) "ahci(%p)[%d]: sglist population failed"
ahci_dma_rw_buf(void *s, int port, int l) "ahci(%p)[%d] len=0x%x"
ahci_cmd_done(void *s, int port) "ahci(%p)[%d]: cmd done"
ahci_reset(void *s) "ahci(%p): HBA reset"
allwinner_ahci_mem_read(void *s, void *a, uint64_t addr, uint64_t val, unsigned size) "ahci(%p): read a=%p addr=0x%"HWADDR_PRIx" val=0x%"PRIx64", size=%d"
allwinner_ahci_mem_write(void *s, void *a, uint64_t addr, uint64_t val, unsigned size) "ahci(%p): write a=%p addr=0x%"HWADDR_PRIx" val=0x%"PRIx64", size=%d"
# Warning: Verbose
handle_reg_h2d_fis_dump(void *s, int port, const char *fis) "ahci(%p)[%d]: %s"
handle_cmd_fis_dump(void *s, int port, const char *fis) "ahci(%p)[%d]: %s"

View File

@@ -33,6 +33,7 @@
#include "sysemu/dma.h"
#include "hw/ide/pci.h"
#include "trace.h"
static uint64_t bmdma_read(void *opaque, hwaddr addr,
unsigned size)
@@ -55,9 +56,8 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr,
val = 0xff;
break;
}
#ifdef DEBUG_IDE
printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val);
#endif
trace_bmdma_read_via(addr, val);
return val;
}
@@ -70,9 +70,7 @@ static void bmdma_write(void *opaque, hwaddr addr,
return;
}
#ifdef DEBUG_IDE
printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
#endif
trace_bmdma_write_via(addr, val);
switch (addr & 3) {
case 0:
bmdma_cmd_writeb(bm, val);

View File

@@ -1,5 +1,5 @@
obj-y += mips_r4k.o mips_malta.o mips_mipssim.o
obj-y += addr.o cputimer.o mips_int.o
obj-y += addr.o mips_int.o
obj-$(CONFIG_JAZZ) += mips_jazz.o
obj-$(CONFIG_FULONG) += mips_fulong2e.o
obj-y += gt64xxx_pci.o

View File

@@ -71,7 +71,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
bool itu_present = false;
for (i = 0; i < s->num_vp; i++) {
cpu = cpu_mips_init(s->cpu_model);
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, s->cpu_model));
/* Init internal devices */
cpu_mips_irq_init_cpu(cpu);

View File

@@ -280,7 +280,7 @@ static void mips_fulong2e_init(MachineState *machine)
if (cpu_model == NULL) {
cpu_model = "Loongson-2E";
}
cpu = cpu_mips_init(cpu_model);
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
env = &cpu->env;
qemu_register_reset(main_cpu_reset, cpu);

View File

@@ -151,7 +151,7 @@ static void mips_jazz_init(MachineState *machine,
if (cpu_model == NULL) {
cpu_model = "R4000";
}
cpu = cpu_mips_init(cpu_model);
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
env = &cpu->env;
qemu_register_reset(main_cpu_reset, cpu);

View File

@@ -216,8 +216,8 @@ static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
}
if (ram_size) {
fprintf(stderr, "Warning: SPD cannot represent final %dMB"
" of SDRAM\n", (int)ram_size);
warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB"
" of SDRAM", ram_size);
}
/* fill in SPD memory information */
@@ -931,7 +931,7 @@ static void create_cpu_without_cps(const char *cpu_model,
int i;
for (i = 0; i < smp_cpus; i++) {
cpu = cpu_mips_init(cpu_model);
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
/* Init internal devices */
cpu_mips_irq_init_cpu(cpu);

View File

@@ -163,7 +163,7 @@ mips_mipssim_init(MachineState *machine)
cpu_model = "24Kf";
#endif
}
cpu = cpu_mips_init(cpu_model);
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
env = &cpu->env;
reset_info = g_malloc0(sizeof(ResetData));

View File

@@ -193,7 +193,7 @@ void mips_r4k_init(MachineState *machine)
cpu_model = "24Kf";
#endif
}
cpu = cpu_mips_init(cpu_model);
cpu = MIPS_CPU(cpu_generic_init(TYPE_MIPS_CPU, cpu_model));
env = &cpu->env;
reset_info = g_malloc0(sizeof(ResetData));
@@ -249,9 +249,8 @@ void mips_r4k_init(MachineState *machine)
fprintf(stderr, "qemu: Error registering flash memory.\n");
}
} else if (!qtest_enabled()) {
/* not fatal */
fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
bios_name);
/* not fatal */
warn_report("could not load MIPS bios '%s'", bios_name);
}
g_free(filename);

View File

@@ -331,7 +331,7 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)
s->iobase + APPLESMC_ERR_PORT);
if (!s->osk || (strlen(s->osk) != 64)) {
fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n");
warn_report("Using AppleSMC with invalid key");
s->osk = default_osk;
}

View File

@@ -653,7 +653,7 @@ static int64_t ivshmem_recv_msg(IVShmemState *s, int *pfd, Error **errp)
} while (n < sizeof(msg));
*pfd = qemu_chr_fe_get_msgfd(&s->server_chr);
return msg;
return le64_to_cpu(msg);
}
static void ivshmem_recv_setup(IVShmemState *s, Error **errp)

View File

@@ -26,6 +26,7 @@ common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
common-obj-$(CONFIG_CADENCE) += cadence_gem.o
common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o
common-obj-$(CONFIG_LANCE) += lance.o
common-obj-$(CONFIG_SUNHME) += sunhme.o
common-obj-$(CONFIG_FTGMAC100) += ftgmac100.o
common-obj-$(CONFIG_SUNGEM) += sungem.o

978
hw/net/sunhme.c Normal file
View File

@@ -0,0 +1,978 @@
/*
* QEMU Sun Happy Meal Ethernet emulation
*
* Copyright (c) 2017 Mark Cave-Ayland
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "hw/net/mii.h"
#include "net/net.h"
#include "net/checksum.h"
#include "net/eth.h"
#include "sysemu/sysemu.h"
#include "trace.h"
#define HME_REG_SIZE 0x8000
#define HME_SEB_REG_SIZE 0x2000
#define HME_SEBI_RESET 0x0
#define HME_SEB_RESET_ETX 0x1
#define HME_SEB_RESET_ERX 0x2
#define HME_SEBI_STAT 0x100
#define HME_SEBI_STAT_LINUXBUG 0x108
#define HME_SEB_STAT_RXTOHOST 0x10000
#define HME_SEB_STAT_MIFIRQ 0x800000
#define HME_SEB_STAT_HOSTTOTX 0x1000000
#define HME_SEB_STAT_TXALL 0x2000000
#define HME_SEBI_IMASK 0x104
#define HME_SEBI_IMASK_LINUXBUG 0x10c
#define HME_ETX_REG_SIZE 0x2000
#define HME_ETXI_PENDING 0x0
#define HME_ETXI_RING 0x8
#define HME_ETXI_RING_ADDR 0xffffff00
#define HME_ETXI_RING_OFFSET 0xff
#define HME_ETXI_RSIZE 0x2c
#define HME_ERX_REG_SIZE 0x2000
#define HME_ERXI_CFG 0x0
#define HME_ERX_CFG_RINGSIZE 0x600
#define HME_ERX_CFG_RINGSIZE_SHIFT 9
#define HME_ERX_CFG_BYTEOFFSET 0x38
#define HME_ERX_CFG_BYTEOFFSET_SHIFT 3
#define HME_ERX_CFG_CSUMSTART 0x7f0000
#define HME_ERX_CFG_CSUMSHIFT 16
#define HME_ERXI_RING 0x4
#define HME_ERXI_RING_ADDR 0xffffff00
#define HME_ERXI_RING_OFFSET 0xff
#define HME_MAC_REG_SIZE 0x1000
#define HME_MACI_TXCFG 0x20c
#define HME_MAC_TXCFG_ENABLE 0x1
#define HME_MACI_RXCFG 0x30c
#define HME_MAC_RXCFG_ENABLE 0x1
#define HME_MAC_RXCFG_PMISC 0x40
#define HME_MAC_RXCFG_HENABLE 0x800
#define HME_MACI_MACADDR2 0x318
#define HME_MACI_MACADDR1 0x31c
#define HME_MACI_MACADDR0 0x320
#define HME_MACI_HASHTAB3 0x340
#define HME_MACI_HASHTAB2 0x344
#define HME_MACI_HASHTAB1 0x348
#define HME_MACI_HASHTAB0 0x34c
#define HME_MIF_REG_SIZE 0x20
#define HME_MIFI_FO 0xc
#define HME_MIF_FO_ST 0xc0000000
#define HME_MIF_FO_ST_SHIFT 30
#define HME_MIF_FO_OPC 0x30000000
#define HME_MIF_FO_OPC_SHIFT 28
#define HME_MIF_FO_PHYAD 0x0f800000
#define HME_MIF_FO_PHYAD_SHIFT 23
#define HME_MIF_FO_REGAD 0x007c0000
#define HME_MIF_FO_REGAD_SHIFT 18
#define HME_MIF_FO_TAMSB 0x20000
#define HME_MIF_FO_TALSB 0x10000
#define HME_MIF_FO_DATA 0xffff
#define HME_MIFI_CFG 0x10
#define HME_MIF_CFG_MDI0 0x100
#define HME_MIF_CFG_MDI1 0x200
#define HME_MIFI_IMASK 0x14
#define HME_MIFI_STAT 0x18
/* Wired HME PHY addresses */
#define HME_PHYAD_INTERNAL 1
#define HME_PHYAD_EXTERNAL 0
#define MII_COMMAND_START 0x1
#define MII_COMMAND_READ 0x2
#define MII_COMMAND_WRITE 0x1
#define TYPE_SUNHME "sunhme"
#define SUNHME(obj) OBJECT_CHECK(SunHMEState, (obj), TYPE_SUNHME)
/* Maximum size of buffer */
#define HME_FIFO_SIZE 0x800
/* Size of TX/RX descriptor */
#define HME_DESC_SIZE 0x8
#define HME_XD_OWN 0x80000000
#define HME_XD_OFL 0x40000000
#define HME_XD_SOP 0x40000000
#define HME_XD_EOP 0x20000000
#define HME_XD_RXLENMSK 0x3fff0000
#define HME_XD_RXLENSHIFT 16
#define HME_XD_RXCKSUM 0xffff
#define HME_XD_TXLENMSK 0x00001fff
#define HME_XD_TXCKSUM 0x10000000
#define HME_XD_TXCSSTUFF 0xff00000
#define HME_XD_TXCSSTUFFSHIFT 20
#define HME_XD_TXCSSTART 0xfc000
#define HME_XD_TXCSSTARTSHIFT 14
#define HME_MII_REGS_SIZE 0x20
typedef struct SunHMEState {
/*< private >*/
PCIDevice parent_obj;
NICState *nic;
NICConf conf;
MemoryRegion hme;
MemoryRegion sebreg;
MemoryRegion etxreg;
MemoryRegion erxreg;
MemoryRegion macreg;
MemoryRegion mifreg;
uint32_t sebregs[HME_SEB_REG_SIZE >> 2];
uint32_t etxregs[HME_ETX_REG_SIZE >> 2];
uint32_t erxregs[HME_ERX_REG_SIZE >> 2];
uint32_t macregs[HME_MAC_REG_SIZE >> 2];
uint32_t mifregs[HME_MIF_REG_SIZE >> 2];
uint16_t miiregs[HME_MII_REGS_SIZE];
} SunHMEState;
static Property sunhme_properties[] = {
DEFINE_NIC_PROPERTIES(SunHMEState, conf),
DEFINE_PROP_END_OF_LIST(),
};
static void sunhme_reset_tx(SunHMEState *s)
{
/* Indicate TX reset complete */
s->sebregs[HME_SEBI_RESET] &= ~HME_SEB_RESET_ETX;
}
static void sunhme_reset_rx(SunHMEState *s)
{
/* Indicate RX reset complete */
s->sebregs[HME_SEBI_RESET] &= ~HME_SEB_RESET_ERX;
}
static void sunhme_update_irq(SunHMEState *s)
{
PCIDevice *d = PCI_DEVICE(s);
int level;
/* MIF interrupt mask (16-bit) */
uint32_t mifmask = ~(s->mifregs[HME_MIFI_IMASK >> 2]) & 0xffff;
uint32_t mif = s->mifregs[HME_MIFI_STAT >> 2] & mifmask;
/* Main SEB interrupt mask (include MIF status from above) */
uint32_t sebmask = ~(s->sebregs[HME_SEBI_IMASK >> 2]) &
~HME_SEB_STAT_MIFIRQ;
uint32_t seb = s->sebregs[HME_SEBI_STAT >> 2] & sebmask;
if (mif) {
seb |= HME_SEB_STAT_MIFIRQ;
}
level = (seb ? 1 : 0);
pci_set_irq(d, level);
}
static void sunhme_seb_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
SunHMEState *s = SUNHME(opaque);
trace_sunhme_seb_write(addr, val);
/* Handly buggy Linux drivers before 4.13 which have
the wrong offsets for HME_SEBI_STAT and HME_SEBI_IMASK */
switch (addr) {
case HME_SEBI_STAT_LINUXBUG:
addr = HME_SEBI_STAT;
break;
case HME_SEBI_IMASK_LINUXBUG:
addr = HME_SEBI_IMASK;
break;
default:
break;
}
switch (addr) {
case HME_SEBI_RESET:
if (val & HME_SEB_RESET_ETX) {
sunhme_reset_tx(s);
}
if (val & HME_SEB_RESET_ERX) {
sunhme_reset_rx(s);
}
val = s->sebregs[HME_SEBI_RESET >> 2];
break;
}
s->sebregs[addr >> 2] = val;
}
static uint64_t sunhme_seb_read(void *opaque, hwaddr addr,
unsigned size)
{
SunHMEState *s = SUNHME(opaque);
uint64_t val;
/* Handly buggy Linux drivers before 4.13 which have
the wrong offsets for HME_SEBI_STAT and HME_SEBI_IMASK */
switch (addr) {
case HME_SEBI_STAT_LINUXBUG:
addr = HME_SEBI_STAT;
break;
case HME_SEBI_IMASK_LINUXBUG:
addr = HME_SEBI_IMASK;
break;
default:
break;
}
val = s->sebregs[addr >> 2];
switch (addr) {
case HME_SEBI_STAT:
/* Autoclear status (except MIF) */
s->sebregs[HME_SEBI_STAT >> 2] &= HME_SEB_STAT_MIFIRQ;
sunhme_update_irq(s);
break;
}
trace_sunhme_seb_read(addr, val);
return val;
}
static const MemoryRegionOps sunhme_seb_ops = {
.read = sunhme_seb_read,
.write = sunhme_seb_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static void sunhme_transmit(SunHMEState *s);
static void sunhme_etx_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
SunHMEState *s = SUNHME(opaque);
trace_sunhme_etx_write(addr, val);
switch (addr) {
case HME_ETXI_PENDING:
if (val) {
sunhme_transmit(s);
}
break;
}
s->etxregs[addr >> 2] = val;
}
static uint64_t sunhme_etx_read(void *opaque, hwaddr addr,
unsigned size)
{
SunHMEState *s = SUNHME(opaque);
uint64_t val;
val = s->etxregs[addr >> 2];
trace_sunhme_etx_read(addr, val);
return val;
}
static const MemoryRegionOps sunhme_etx_ops = {
.read = sunhme_etx_read,
.write = sunhme_etx_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static void sunhme_erx_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
SunHMEState *s = SUNHME(opaque);
trace_sunhme_erx_write(addr, val);
s->erxregs[addr >> 2] = val;
}
static uint64_t sunhme_erx_read(void *opaque, hwaddr addr,
unsigned size)
{
SunHMEState *s = SUNHME(opaque);
uint64_t val;
val = s->erxregs[addr >> 2];
trace_sunhme_erx_read(addr, val);
return val;
}
static const MemoryRegionOps sunhme_erx_ops = {
.read = sunhme_erx_read,
.write = sunhme_erx_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static void sunhme_mac_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
SunHMEState *s = SUNHME(opaque);
trace_sunhme_mac_write(addr, val);
s->macregs[addr >> 2] = val;
}
static uint64_t sunhme_mac_read(void *opaque, hwaddr addr,
unsigned size)
{
SunHMEState *s = SUNHME(opaque);
uint64_t val;
val = s->macregs[addr >> 2];
trace_sunhme_mac_read(addr, val);
return val;
}
static const MemoryRegionOps sunhme_mac_ops = {
.read = sunhme_mac_read,
.write = sunhme_mac_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static void sunhme_mii_write(SunHMEState *s, uint8_t reg, uint16_t data)
{
trace_sunhme_mii_write(reg, data);
switch (reg) {
case MII_BMCR:
if (data & MII_BMCR_RESET) {
/* Autoclear reset bit, enable auto negotiation */
data &= ~MII_BMCR_RESET;
data |= MII_BMCR_AUTOEN;
}
if (data & MII_BMCR_ANRESTART) {
/* Autoclear auto negotiation restart */
data &= ~MII_BMCR_ANRESTART;
/* Indicate negotiation complete */
s->miiregs[MII_BMSR] |= MII_BMSR_AN_COMP;
if (!qemu_get_queue(s->nic)->link_down) {
s->miiregs[MII_ANLPAR] |= MII_ANLPAR_TXFD;
s->miiregs[MII_BMSR] |= MII_BMSR_LINK_ST;
}
}
break;
}
s->miiregs[reg] = data;
}
static uint16_t sunhme_mii_read(SunHMEState *s, uint8_t reg)
{
uint16_t data = s->miiregs[reg];
trace_sunhme_mii_read(reg, data);
return data;
}
static void sunhme_mif_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
SunHMEState *s = SUNHME(opaque);
uint8_t cmd, reg;
uint16_t data;
trace_sunhme_mif_write(addr, val);
switch (addr) {
case HME_MIFI_CFG:
/* Mask the read-only bits */
val &= ~(HME_MIF_CFG_MDI0 | HME_MIF_CFG_MDI1);
val |= s->mifregs[HME_MIFI_CFG >> 2] &
(HME_MIF_CFG_MDI0 | HME_MIF_CFG_MDI1);
break;
case HME_MIFI_FO:
/* Detect start of MII command */
if ((val & HME_MIF_FO_ST) >> HME_MIF_FO_ST_SHIFT
!= MII_COMMAND_START) {
val |= HME_MIF_FO_TALSB;
break;
}
/* Internal phy only */
if ((val & HME_MIF_FO_PHYAD) >> HME_MIF_FO_PHYAD_SHIFT
!= HME_PHYAD_INTERNAL) {
val |= HME_MIF_FO_TALSB;
break;
}
cmd = (val & HME_MIF_FO_OPC) >> HME_MIF_FO_OPC_SHIFT;
reg = (val & HME_MIF_FO_REGAD) >> HME_MIF_FO_REGAD_SHIFT;
data = (val & HME_MIF_FO_DATA);
switch (cmd) {
case MII_COMMAND_WRITE:
sunhme_mii_write(s, reg, data);
break;
case MII_COMMAND_READ:
val &= ~HME_MIF_FO_DATA;
val |= sunhme_mii_read(s, reg);
break;
}
val |= HME_MIF_FO_TALSB;
break;
}
s->mifregs[addr >> 2] = val;
}
static uint64_t sunhme_mif_read(void *opaque, hwaddr addr,
unsigned size)
{
SunHMEState *s = SUNHME(opaque);
uint64_t val;
val = s->mifregs[addr >> 2];
switch (addr) {
case HME_MIFI_STAT:
/* Autoclear MIF interrupt status */
s->mifregs[HME_MIFI_STAT >> 2] = 0;
sunhme_update_irq(s);
break;
}
trace_sunhme_mif_read(addr, val);
return val;
}
static const MemoryRegionOps sunhme_mif_ops = {
.read = sunhme_mif_read,
.write = sunhme_mif_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static void sunhme_transmit_frame(SunHMEState *s, uint8_t *buf, int size)
{
qemu_send_packet(qemu_get_queue(s->nic), buf, size);
}
static inline int sunhme_get_tx_ring_count(SunHMEState *s)
{
return (s->etxregs[HME_ETXI_RSIZE >> 2] + 1) << 4;
}
static inline int sunhme_get_tx_ring_nr(SunHMEState *s)
{
return s->etxregs[HME_ETXI_RING >> 2] & HME_ETXI_RING_OFFSET;
}
static inline void sunhme_set_tx_ring_nr(SunHMEState *s, int i)
{
uint32_t ring = s->etxregs[HME_ETXI_RING >> 2] & ~HME_ETXI_RING_OFFSET;
ring |= i & HME_ETXI_RING_OFFSET;
s->etxregs[HME_ETXI_RING >> 2] = ring;
}
static void sunhme_transmit(SunHMEState *s)
{
PCIDevice *d = PCI_DEVICE(s);
dma_addr_t tb, addr;
uint32_t intstatus, status, buffer, sum = 0;
int cr, nr, len, xmit_pos, csum_offset = 0, csum_stuff_offset = 0;
uint16_t csum = 0;
uint8_t xmit_buffer[HME_FIFO_SIZE];
tb = s->etxregs[HME_ETXI_RING >> 2] & HME_ETXI_RING_ADDR;
nr = sunhme_get_tx_ring_count(s);
cr = sunhme_get_tx_ring_nr(s);
pci_dma_read(d, tb + cr * HME_DESC_SIZE, &status, 4);
pci_dma_read(d, tb + cr * HME_DESC_SIZE + 4, &buffer, 4);
xmit_pos = 0;
while (status & HME_XD_OWN) {
trace_sunhme_tx_desc(buffer, status, cr, nr);
/* Copy data into transmit buffer */
addr = buffer;
len = status & HME_XD_TXLENMSK;
if (xmit_pos + len > HME_FIFO_SIZE) {
len = HME_FIFO_SIZE - xmit_pos;
}
pci_dma_read(d, addr, &xmit_buffer[xmit_pos], len);
xmit_pos += len;
/* Detect start of packet for TX checksum */
if (status & HME_XD_SOP) {
sum = 0;
csum_offset = (status & HME_XD_TXCSSTART) >> HME_XD_TXCSSTARTSHIFT;
csum_stuff_offset = (status & HME_XD_TXCSSTUFF) >>
HME_XD_TXCSSTUFFSHIFT;
}
if (status & HME_XD_TXCKSUM) {
/* Only start calculation from csum_offset */
if (xmit_pos - len <= csum_offset && xmit_pos > csum_offset) {
sum += net_checksum_add(xmit_pos - csum_offset,
xmit_buffer + csum_offset);
trace_sunhme_tx_xsum_add(csum_offset, xmit_pos - csum_offset);
} else {
sum += net_checksum_add(len, xmit_buffer + xmit_pos - len);
trace_sunhme_tx_xsum_add(xmit_pos - len, len);
}
}
/* Detect end of packet for TX checksum */
if (status & HME_XD_EOP) {
/* Stuff the checksum if required */
if (status & HME_XD_TXCKSUM) {
csum = net_checksum_finish(sum);
stw_be_p(xmit_buffer + csum_stuff_offset, csum);
trace_sunhme_tx_xsum_stuff(csum, csum_stuff_offset);
}
if (s->macregs[HME_MACI_TXCFG >> 2] & HME_MAC_TXCFG_ENABLE) {
sunhme_transmit_frame(s, xmit_buffer, xmit_pos);
trace_sunhme_tx_done(xmit_pos);
}
}
/* Update status */
status &= ~HME_XD_OWN;
pci_dma_write(d, tb + cr * HME_DESC_SIZE, &status, 4);
/* Move onto next descriptor */
cr++;
if (cr >= nr) {
cr = 0;
}
sunhme_set_tx_ring_nr(s, cr);
pci_dma_read(d, tb + cr * HME_DESC_SIZE, &status, 4);
pci_dma_read(d, tb + cr * HME_DESC_SIZE + 4, &buffer, 4);
/* Indicate TX complete */
intstatus = s->sebregs[HME_SEBI_STAT >> 2];
intstatus |= HME_SEB_STAT_HOSTTOTX;
s->sebregs[HME_SEBI_STAT >> 2] = intstatus;
/* Autoclear TX pending */
s->etxregs[HME_ETXI_PENDING >> 2] = 0;
sunhme_update_irq(s);
}
/* TX FIFO now clear */
intstatus = s->sebregs[HME_SEBI_STAT >> 2];
intstatus |= HME_SEB_STAT_TXALL;
s->sebregs[HME_SEBI_STAT >> 2] = intstatus;
sunhme_update_irq(s);
}
static int sunhme_can_receive(NetClientState *nc)
{
SunHMEState *s = qemu_get_nic_opaque(nc);
return s->macregs[HME_MAC_RXCFG_ENABLE >> 2] & HME_MAC_RXCFG_ENABLE;
}
static void sunhme_link_status_changed(NetClientState *nc)
{
SunHMEState *s = qemu_get_nic_opaque(nc);
if (nc->link_down) {
s->miiregs[MII_ANLPAR] &= ~MII_ANLPAR_TXFD;
s->miiregs[MII_BMSR] &= ~MII_BMSR_LINK_ST;
} else {
s->miiregs[MII_ANLPAR] |= MII_ANLPAR_TXFD;
s->miiregs[MII_BMSR] |= MII_BMSR_LINK_ST;
}
/* Exact bits unknown */
s->mifregs[HME_MIFI_STAT >> 2] = 0xffff;
sunhme_update_irq(s);
}
static inline int sunhme_get_rx_ring_count(SunHMEState *s)
{
uint32_t rings = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_RINGSIZE)
>> HME_ERX_CFG_RINGSIZE_SHIFT;
switch (rings) {
case 0:
return 32;
case 1:
return 64;
case 2:
return 128;
case 3:
return 256;
}
return 0;
}
static inline int sunhme_get_rx_ring_nr(SunHMEState *s)
{
return s->erxregs[HME_ERXI_RING >> 2] & HME_ERXI_RING_OFFSET;
}
static inline void sunhme_set_rx_ring_nr(SunHMEState *s, int i)
{
uint32_t ring = s->erxregs[HME_ERXI_RING >> 2] & ~HME_ERXI_RING_OFFSET;
ring |= i & HME_ERXI_RING_OFFSET;
s->erxregs[HME_ERXI_RING >> 2] = ring;
}
#define POLYNOMIAL_LE 0xedb88320
static uint32_t sunhme_crc32_le(const uint8_t *p, int len)
{
uint32_t crc;
int carry, i, j;
uint8_t b;
crc = 0xffffffff;
for (i = 0; i < len; i++) {
b = *p++;
for (j = 0; j < 8; j++) {
carry = (crc & 0x1) ^ (b & 0x01);
crc >>= 1;
b >>= 1;
if (carry) {
crc = crc ^ POLYNOMIAL_LE;
}
}
}
return crc;
}
#define MIN_BUF_SIZE 60
static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf,
size_t size)
{
SunHMEState *s = qemu_get_nic_opaque(nc);
PCIDevice *d = PCI_DEVICE(s);
dma_addr_t rb, addr;
uint32_t intstatus, status, buffer, buffersize, sum;
uint16_t csum;
uint8_t buf1[60];
int nr, cr, len, rxoffset, csum_offset;
trace_sunhme_rx_incoming(size);
/* Do nothing if MAC RX disabled */
if (!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE)) {
return -1;
}
trace_sunhme_rx_filter_destmac(buf[0], buf[1], buf[2],
buf[3], buf[4], buf[5]);
/* Check destination MAC address */
if (!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_PMISC)) {
/* Try and match local MAC address */
if (((s->macregs[HME_MACI_MACADDR0 >> 2] & 0xff00) >> 8) == buf[0] &&
(s->macregs[HME_MACI_MACADDR0 >> 2] & 0xff) == buf[1] &&
((s->macregs[HME_MACI_MACADDR1 >> 2] & 0xff00) >> 8) == buf[2] &&
(s->macregs[HME_MACI_MACADDR1 >> 2] & 0xff) == buf[3] &&
((s->macregs[HME_MACI_MACADDR2 >> 2] & 0xff00) >> 8) == buf[4] &&
(s->macregs[HME_MACI_MACADDR2 >> 2] & 0xff) == buf[5]) {
/* Matched local MAC address */
trace_sunhme_rx_filter_local_match();
} else if (buf[0] == 0xff && buf[1] == 0xff && buf[2] == 0xff &&
buf[3] == 0xff && buf[4] == 0xff && buf[5] == 0xff) {
/* Matched broadcast address */
trace_sunhme_rx_filter_bcast_match();
} else if (s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_HENABLE) {
/* Didn't match local address, check hash filter */
int mcast_idx = sunhme_crc32_le(buf, 6) >> 26;
if (!(s->macregs[(HME_MACI_HASHTAB0 >> 2) - (mcast_idx >> 4)] &
(1 << (mcast_idx & 0xf)))) {
/* Didn't match hash filter */
trace_sunhme_rx_filter_hash_nomatch();
trace_sunhme_rx_filter_reject();
return 0;
} else {
trace_sunhme_rx_filter_hash_match();
}
} else {
/* Not for us */
trace_sunhme_rx_filter_reject();
return 0;
}
} else {
trace_sunhme_rx_filter_promisc_match();
}
trace_sunhme_rx_filter_accept();
/* If too small buffer, then expand it */
if (size < MIN_BUF_SIZE) {
memcpy(buf1, buf, size);
memset(buf1 + size, 0, MIN_BUF_SIZE - size);
buf = buf1;
size = MIN_BUF_SIZE;
}
rb = s->erxregs[HME_ERXI_RING >> 2] & HME_ERXI_RING_ADDR;
nr = sunhme_get_rx_ring_count(s);
cr = sunhme_get_rx_ring_nr(s);
pci_dma_read(d, rb + cr * HME_DESC_SIZE, &status, 4);
pci_dma_read(d, rb + cr * HME_DESC_SIZE + 4, &buffer, 4);
rxoffset = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_BYTEOFFSET) >>
HME_ERX_CFG_BYTEOFFSET_SHIFT;
addr = buffer + rxoffset;
buffersize = (status & HME_XD_RXLENMSK) >> HME_XD_RXLENSHIFT;
/* Detect receive overflow */
len = size;
if (size > buffersize) {
status |= HME_XD_OFL;
len = buffersize;
}
pci_dma_write(d, addr, buf, len);
trace_sunhme_rx_desc(buffer, rxoffset, status, len, cr, nr);
/* Calculate the receive checksum */
csum_offset = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_CSUMSTART) >>
HME_ERX_CFG_CSUMSHIFT << 1;
sum = 0;
sum += net_checksum_add(len - csum_offset, (uint8_t *)buf + csum_offset);
csum = net_checksum_finish(sum);
trace_sunhme_rx_xsum_calc(csum);
/* Update status */
status &= ~HME_XD_OWN;
status &= ~HME_XD_RXLENMSK;
status |= len << HME_XD_RXLENSHIFT;
status &= ~HME_XD_RXCKSUM;
status |= csum;
pci_dma_write(d, rb + cr * HME_DESC_SIZE, &status, 4);
cr++;
if (cr >= nr) {
cr = 0;
}
sunhme_set_rx_ring_nr(s, cr);
/* Indicate RX complete */
intstatus = s->sebregs[HME_SEBI_STAT >> 2];
intstatus |= HME_SEB_STAT_RXTOHOST;
s->sebregs[HME_SEBI_STAT >> 2] = intstatus;
sunhme_update_irq(s);
return len;
}
static NetClientInfo net_sunhme_info = {
.type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
.can_receive = sunhme_can_receive,
.receive = sunhme_receive,
.link_status_changed = sunhme_link_status_changed,
};
static void sunhme_realize(PCIDevice *pci_dev, Error **errp)
{
SunHMEState *s = SUNHME(pci_dev);
DeviceState *d = DEVICE(pci_dev);
uint8_t *pci_conf;
pci_conf = pci_dev->config;
pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
memory_region_init(&s->hme, OBJECT(pci_dev), "sunhme", HME_REG_SIZE);
pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->hme);
memory_region_init_io(&s->sebreg, OBJECT(pci_dev), &sunhme_seb_ops, s,
"sunhme.seb", HME_SEB_REG_SIZE);
memory_region_add_subregion(&s->hme, 0, &s->sebreg);
memory_region_init_io(&s->etxreg, OBJECT(pci_dev), &sunhme_etx_ops, s,
"sunhme.etx", HME_ETX_REG_SIZE);
memory_region_add_subregion(&s->hme, 0x2000, &s->etxreg);
memory_region_init_io(&s->erxreg, OBJECT(pci_dev), &sunhme_erx_ops, s,
"sunhme.erx", HME_ERX_REG_SIZE);
memory_region_add_subregion(&s->hme, 0x4000, &s->erxreg);
memory_region_init_io(&s->macreg, OBJECT(pci_dev), &sunhme_mac_ops, s,
"sunhme.mac", HME_MAC_REG_SIZE);
memory_region_add_subregion(&s->hme, 0x6000, &s->macreg);
memory_region_init_io(&s->mifreg, OBJECT(pci_dev), &sunhme_mif_ops, s,
"sunhme.mif", HME_MIF_REG_SIZE);
memory_region_add_subregion(&s->hme, 0x7000, &s->mifreg);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_sunhme_info, &s->conf,
object_get_typename(OBJECT(d)), d->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
static void sunhme_instance_init(Object *obj)
{
SunHMEState *s = SUNHME(obj);
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
DEVICE(obj), NULL);
}
static void sunhme_reset(DeviceState *ds)
{
SunHMEState *s = SUNHME(ds);
/* Configure internal transceiver */
s->mifregs[HME_MIFI_CFG >> 2] |= HME_MIF_CFG_MDI0;
/* Advetise auto, 100Mbps FD */
s->miiregs[MII_ANAR] = MII_ANAR_TXFD;
s->miiregs[MII_BMSR] = MII_BMSR_AUTONEG | MII_BMSR_100TX_FD |
MII_BMSR_AN_COMP;
if (!qemu_get_queue(s->nic)->link_down) {
s->miiregs[MII_ANLPAR] |= MII_ANLPAR_TXFD;
s->miiregs[MII_BMSR] |= MII_BMSR_LINK_ST;
}
/* Set manufacturer */
s->miiregs[MII_PHYID1] = DP83840_PHYID1;
s->miiregs[MII_PHYID2] = DP83840_PHYID2;
/* Configure default interrupt mask */
s->mifregs[HME_MIFI_IMASK >> 2] = 0xffff;
s->sebregs[HME_SEBI_IMASK >> 2] = 0xff7fffff;
}
static const VMStateDescription vmstate_hme = {
.name = "sunhme",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, SunHMEState),
VMSTATE_MACADDR(conf.macaddr, SunHMEState),
VMSTATE_UINT32_ARRAY(sebregs, SunHMEState, (HME_SEB_REG_SIZE >> 2)),
VMSTATE_UINT32_ARRAY(etxregs, SunHMEState, (HME_ETX_REG_SIZE >> 2)),
VMSTATE_UINT32_ARRAY(erxregs, SunHMEState, (HME_ERX_REG_SIZE >> 2)),
VMSTATE_UINT32_ARRAY(macregs, SunHMEState, (HME_MAC_REG_SIZE >> 2)),
VMSTATE_UINT32_ARRAY(mifregs, SunHMEState, (HME_MIF_REG_SIZE >> 2)),
VMSTATE_UINT16_ARRAY(miiregs, SunHMEState, HME_MII_REGS_SIZE),
VMSTATE_END_OF_LIST()
}
};
static void sunhme_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = sunhme_realize;
k->vendor_id = PCI_VENDOR_ID_SUN;
k->device_id = PCI_DEVICE_ID_SUN_HME;
k->class_id = PCI_CLASS_NETWORK_ETHERNET;
dc->vmsd = &vmstate_hme;
dc->reset = sunhme_reset;
dc->props = sunhme_properties;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo sunhme_info = {
.name = TYPE_SUNHME,
.parent = TYPE_PCI_DEVICE,
.class_init = sunhme_class_init,
.instance_size = sizeof(SunHMEState),
.instance_init = sunhme_instance_init,
};
static void sunhme_register_types(void)
{
type_register_static(&sunhme_info);
}
type_init(sunhme_register_types)

View File

@@ -322,3 +322,32 @@ sungem_mmio_mif_write(uint64_t addr, uint64_t val) "MMIO mif write to 0x%"PRIx64
sungem_mmio_mif_read(uint64_t addr, uint64_t val) "MMIO mif read from 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_pcs_write(uint64_t addr, uint64_t val) "MMIO pcs write to 0x%"PRIx64" val=0x%"PRIx64
sungem_mmio_pcs_read(uint64_t addr, uint64_t val) "MMIO pcs read from 0x%"PRIx64" val=0x%"PRIx64
# hw/net/sunhme.c
sunhme_seb_write(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_seb_read(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_etx_write(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_etx_read(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_erx_write(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_erx_read(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_mac_write(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_mac_read(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_mii_write(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_mii_read(uint8_t addr, uint16_t value) "addr 0x%x value 0x%x"
sunhme_mif_write(uint8_t addr, uint16_t value) "addr 0x%x value 0x%x"
sunhme_mif_read(uint64_t addr, uint64_t value) "addr 0x%"PRIx64" value 0x%"PRIx64
sunhme_tx_desc(uint64_t buffer, uint32_t status, int cr, int nr) "addr 0x%"PRIx64" status 0x%"PRIx32 " (ring %d/%d)"
sunhme_tx_xsum_add(int offset, int len) "adding xsum at offset %d, len %d"
sunhme_tx_xsum_stuff(uint16_t xsum, int offset) "stuffing xsum 0x%x at offset %d"
sunhme_tx_done(int len) "successfully transmitted frame with len %d"
sunhme_rx_incoming(size_t len) "received incoming frame with len %zu"
sunhme_rx_filter_destmac(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "received frame for MAC: %02x:%02x:%02x:%02x:%02x:%02x"
sunhme_rx_filter_local_match(void) "incoming frame matches local MAC address"
sunhme_rx_filter_bcast_match(void) "incoming frame matches broadcast MAC address"
sunhme_rx_filter_hash_nomatch(void) "incoming MAC address not in hash table"
sunhme_rx_filter_hash_match(void) "incoming MAC address found in hash table"
sunhme_rx_filter_promisc_match(void) "incoming frame accepted due to promiscuous mode"
sunhme_rx_filter_reject(void) "rejecting incoming frame"
sunhme_rx_filter_accept(void) "accepting incoming frame"
sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int nr) "addr 0x%"PRIx32"(+0x%x) status 0x%"PRIx32 " len %d (ring %d/%d)"
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"

View File

@@ -1,4 +1,3 @@
obj-y += s390-virtio.o
obj-y += s390-virtio-hcall.o
obj-y += sclp.o
obj-y += event-facility.o

View File

@@ -793,7 +793,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
CCW1 ccw;
if (!ccw_addr) {
return -EIO;
return -EINVAL; /* channel-program check */
}
/* Check doubleword aligned and 31 or 24 (fmt 0) bit addressable. */
if (ccw_addr & (sch->ccw_fmt_1 ? 0x80000007 : 0xff000007)) {
@@ -980,22 +980,6 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
s->cpa = sch->channel_prog + 8;
break;
case -EFAULT:
/* memory problem, generate channel data check */
s->ctrl &= ~SCSW_ACTL_START_PEND;
s->cstat = SCSW_CSTAT_DATA_CHECK;
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
s->cpa = sch->channel_prog + 8;
break;
case -EBUSY:
/* subchannel busy, generate deferred cc 1 */
s->flags &= ~SCSW_FLAGS_MASK_CC;
s->flags |= (1 << 8);
s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
s->ctrl |= SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
break;
case -EINPROGRESS:
/* channel program has been suspended */
s->ctrl &= ~SCSW_ACTL_START_PEND;
@@ -1276,16 +1260,16 @@ int css_do_xsch(SubchDev *sch)
goto out;
}
if (s->ctrl & SCSW_CTRL_MASK_STCTL) {
ret = -EINPROGRESS;
goto out;
}
if (!(s->ctrl & SCSW_CTRL_MASK_FCTL) ||
((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
(!(s->ctrl &
(SCSW_ACTL_RESUME_PEND | SCSW_ACTL_START_PEND | SCSW_ACTL_SUSP))) ||
(s->ctrl & SCSW_ACTL_SUBCH_ACTIVE)) {
ret = -EINPROGRESS;
goto out;
}
if (s->ctrl & SCSW_CTRL_MASK_STCTL) {
ret = -EBUSY;
goto out;
}

View File

@@ -199,8 +199,8 @@ static S390PCIBusDevice *s390_pci_find_dev_by_uid(S390pciState *s, uint16_t uid)
return NULL;
}
static S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target)
S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target)
{
S390PCIBusDevice *pbdev;
@@ -397,6 +397,17 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
return ret;
}
static void s390_pci_iommu_replay(IOMMUMemoryRegion *iommu,
IOMMUNotifier *notifier)
{
/* It's impossible to plug a pci device on s390x that already has iommu
* mappings which need to be replayed, that is due to the "one iommu per
* zpci device" construct. But when we support migration of vfio-pci
* devices in future, we need to revisit this.
*/
return;
}
static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
int devfn)
{
@@ -465,19 +476,13 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
S390PCIBusDevice *pbdev = opaque;
uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
uint32_t vec = data & ZPCI_MSI_VEC_MASK;
uint64_t ind_bit;
uint32_t sum_bit;
uint32_t e = 0;
DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec);
if (!pbdev) {
e |= (vec << ERR_EVENT_MVN_OFFSET);
s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e);
return;
}
assert(pbdev);
DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data,
pbdev->idx, vec);
if (pbdev->state != ZPCI_FS_ENABLED) {
return;
@@ -1051,6 +1056,7 @@ static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *data)
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = s390_translate_iommu;
imrc->replay = s390_pci_iommu_replay;
}
static const TypeInfo s390_iommu_memory_region_info = {

View File

@@ -322,6 +322,8 @@ void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid);
S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev);

View File

@@ -413,29 +413,6 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
return 0;
}
static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset,
uint64_t *data, uint8_t len)
{
uint32_t val;
uint8_t *msg_data;
if (offset % PCI_MSIX_ENTRY_SIZE != 8) {
return;
}
if (len != 4) {
DPRINTF("access msix table msg data but len is %d\n", len);
return;
}
msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_VECTOR_CTRL;
val = pci_get_long(msg_data) |
((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS);
pci_set_long(msg_data, val);
DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data);
}
static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
{
if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
@@ -508,7 +485,6 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
if (trap_msix(pbdev, offset, pcias)) {
offset = offset - pbdev->msix.table_offset;
mr = &pbdev->pdev->msix_table_mmio;
update_msix_table_msg_data(pbdev, offset, &data, len);
} else {
mr = pbdev->pdev->io_regions[pcias].memory;
}

View File

@@ -70,7 +70,8 @@ S390pciState *s390_get_phb(void)
return NULL;
}
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx)
S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target)
{
return NULL;
}

View File

@@ -2,6 +2,7 @@
* virtio ccw machine
*
* Copyright 2012 IBM Corp.
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
@@ -15,13 +16,14 @@
#include "cpu.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
#include "s390-virtio.h"
#include "hw/s390x/s390-virtio-hcall.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/ioinst.h"
#include "hw/s390x/css.h"
#include "virtio-ccw.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "s390-pci-bus.h"
#include "hw/s390x/storage-keys.h"
#include "hw/s390x/storage-attributes.h"
@@ -31,6 +33,67 @@
#include "hw/s390x/css-bridge.h"
#include "migration/register.h"
#include "cpu_models.h"
#include "qapi/qmp/qerror.h"
#include "hw/nmi.h"
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
{
static MachineState *ms;
if (!ms) {
ms = MACHINE(qdev_get_machine());
g_assert(ms->possible_cpus);
}
/* CPU address corresponds to the core_id and the index */
if (cpu_addr >= ms->possible_cpus->len) {
return NULL;
}
return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
}
static void s390_init_cpus(MachineState *machine)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *typename;
gchar **model_pieces;
ObjectClass *oc;
CPUClass *cc;
int i;
if (machine->cpu_model == NULL) {
machine->cpu_model = s390_default_cpu_model_name();
}
if (tcg_enabled() && max_cpus > 1) {
error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
"supported by TCG (1) on s390x", max_cpus);
exit(1);
}
/* initialize possible_cpus */
mc->possible_cpu_arch_ids(machine);
model_pieces = g_strsplit(machine->cpu_model, ",", 2);
if (!model_pieces[0]) {
error_report("Invalid/empty CPU model name");
exit(1);
}
oc = cpu_class_by_name(TYPE_S390_CPU, model_pieces[0]);
if (!oc) {
error_report("Unable to find CPU definition: %s", model_pieces[0]);
exit(1);
}
typename = object_class_get_name(oc);
cc = CPU_CLASS(oc);
/* after parsing, properties will be applied to all *typename* instances */
cc->parse_features(typename, model_pieces[1], &error_fatal);
g_strfreev(model_pieces);
for (i = 0; i < smp_cpus; i++) {
s390x_new_cpu(typename, i, &error_fatal);
}
}
static const char *const reset_dev_types[] = {
TYPE_VIRTUAL_CSS_BRIDGE,
@@ -94,7 +157,7 @@ static void virtio_ccw_register_hcalls(void)
virtio_ccw_hcall_early_printk);
}
void s390_memory_init(ram_addr_t mem_size)
static void s390_memory_init(ram_addr_t mem_size)
{
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -109,11 +172,105 @@ void s390_memory_init(ram_addr_t mem_size)
s390_stattrib_init();
}
#define S390_TOD_CLOCK_VALUE_MISSING 0x00
#define S390_TOD_CLOCK_VALUE_PRESENT 0x01
static void gtod_save(QEMUFile *f, void *opaque)
{
uint64_t tod_low;
uint8_t tod_high;
int r;
r = s390_get_clock(&tod_high, &tod_low);
if (r) {
warn_report("Unable to get guest clock for migration: %s",
strerror(-r));
error_printf("Guest clock will not be migrated "
"which could cause the guest to hang.");
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_MISSING);
return;
}
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_PRESENT);
qemu_put_byte(f, tod_high);
qemu_put_be64(f, tod_low);
}
static int gtod_load(QEMUFile *f, void *opaque, int version_id)
{
uint64_t tod_low;
uint8_t tod_high;
int r;
if (qemu_get_byte(f) == S390_TOD_CLOCK_VALUE_MISSING) {
warn_report("Guest clock was not migrated. This could "
"cause the guest to hang.");
return 0;
}
tod_high = qemu_get_byte(f);
tod_low = qemu_get_be64(f);
r = s390_set_clock(&tod_high, &tod_low);
if (r) {
warn_report("Unable to set guest clock for migration: %s",
strerror(-r));
error_printf("Guest clock will not be restored "
"which could cause the guest to hang.");
}
return 0;
}
static SaveVMHandlers savevm_gtod = {
.save_state = gtod_save,
.load_state = gtod_load,
};
static void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename, const char *firmware,
const char *netboot_fw, bool enforce_bios)
{
Object *new = object_new(TYPE_S390_IPL);
DeviceState *dev = DEVICE(new);
if (kernel_filename) {
qdev_prop_set_string(dev, "kernel", kernel_filename);
}
if (initrd_filename) {
qdev_prop_set_string(dev, "initrd", initrd_filename);
}
qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
qdev_prop_set_string(dev, "firmware", firmware);
qdev_prop_set_string(dev, "netboot_fw", netboot_fw);
qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
new, NULL);
object_unref(new);
qdev_init_nofail(dev);
}
static void s390_create_virtio_net(BusState *bus, const char *name)
{
int i;
for (i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
DeviceState *dev;
if (!nd->model) {
nd->model = g_strdup("virtio");
}
qemu_check_nic_model(nd, "virtio");
dev = qdev_create(bus, name);
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
}
}
static void ccw_init(MachineState *machine)
{
int ret;
@@ -167,14 +324,24 @@ static void ccw_init(MachineState *machine)
static void s390_cpu_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
gchar *name;
MachineState *ms = MACHINE(hotplug_dev);
S390CPU *cpu = S390_CPU(dev);
CPUState *cs = CPU(dev);
name = g_strdup_printf("cpu[%i]", cpu->env.cpu_num);
object_property_set_link(OBJECT(hotplug_dev), OBJECT(cs), name,
errp);
g_free(name);
g_assert(!ms->possible_cpus->cpus[cpu->env.core_id].cpu);
ms->possible_cpus->cpus[cpu->env.core_id].cpu = OBJECT(dev);
}
static void s390_machine_reset(void)
{
S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0));
s390_cmma_reset();
qemu_devices_reset();
s390_crypto_reset();
/* all cpus are stopped - configure and start the ipl cpu only */
s390_ipl_prepare_cpu(ipl_cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu);
}
static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
@@ -185,6 +352,45 @@ static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
}
}
static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
error_setg(errp, "CPU hot unplug not supported on this machine");
return;
}
}
static CpuInstanceProperties s390_cpu_index_to_props(MachineState *machine,
unsigned cpu_index)
{
g_assert(machine->possible_cpus && cpu_index < machine->possible_cpus->len);
return machine->possible_cpus->cpus[cpu_index].props;
}
static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
{
int i;
if (ms->possible_cpus) {
g_assert(ms->possible_cpus && ms->possible_cpus->len == max_cpus);
return ms->possible_cpus;
}
ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
sizeof(CPUArchId) * max_cpus);
ms->possible_cpus->len = max_cpus;
for (i = 0; i < ms->possible_cpus->len; i++) {
ms->possible_cpus->cpus[i].vcpus_count = 1;
ms->possible_cpus->cpus[i].arch_id = i;
ms->possible_cpus->cpus[i].props.has_core_id = true;
ms->possible_cpus->cpus[i].props.core_id = i;
}
return ms->possible_cpus;
}
static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
DeviceState *dev)
{
@@ -197,8 +403,21 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
static void s390_hot_add_cpu(const int64_t id, Error **errp)
{
MachineState *machine = MACHINE(qdev_get_machine());
ObjectClass *oc;
s390x_new_cpu(machine->cpu_model, id, errp);
g_assert(machine->possible_cpus->cpus[0].cpu);
oc = OBJECT_CLASS(CPU_GET_CLASS(machine->possible_cpus->cpus[0].cpu));
s390x_new_cpu(object_class_get_name(oc), id, errp);
}
static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
{
CPUState *cs = qemu_get_cpu(cpu_index);
if (s390_cpu_restart(S390_CPU(cs))) {
error_setg(errp, QERR_UNSUPPORTED);
}
}
static void ccw_machine_class_init(ObjectClass *oc, void *data)
@@ -223,8 +442,12 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
mc->no_sdcard = 1;
mc->use_sclp = 1;
mc->max_cpus = 248;
mc->has_hotpluggable_cpus = true;
mc->get_hotplug_handler = s390_get_hotplug_handler;
mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
hc->plug = s390_machine_device_plug;
hc->unplug_request = s390_machine_device_unplug_request;
nc->nmi_monitor_handler = s390_nmi;
}

View File

@@ -11,7 +11,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "hw/s390x/s390-virtio.h"
#include "hw/s390x/s390-virtio-hcall.h"
#define MAX_DIAG_SUBCODES 255

View File

@@ -0,0 +1,21 @@
/*
* Support for virtio hypercalls on s390x
*
* Copyright 2012 IBM Corp.
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
* your option) any later version. See the COPYING file in the top-level
* directory.
*/
#ifndef HW_S390_VIRTIO_HCALL_H
#define HW_S390_VIRTIO_HCALL_H
#include "standard-headers/asm-s390/kvm_virtio.h"
#include "standard-headers/asm-s390/virtio-ccw.h"
typedef int (*s390_virtio_fn)(const uint64_t *args);
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
int s390_virtio_hypercall(CPUS390XState *env);
#endif /* HW_S390_VIRTIO_HCALL_H */

View File

@@ -1,201 +0,0 @@
/*
* QEMU S390 virtio target
*
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
* Copyright IBM Corp 2012
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Contributions after 2012-10-29 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*
* You should have received a copy of the GNU (Lesser) General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/hw.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "sysemu/sysemu.h"
#include "net/net.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/virtio/virtio.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/s390-virtio.h"
#include "hw/s390x/storage-keys.h"
#include "hw/s390x/ipl.h"
#include "cpu.h"
#define MAX_BLK_DEVS 10
#define S390_TOD_CLOCK_VALUE_MISSING 0x00
#define S390_TOD_CLOCK_VALUE_PRESENT 0x01
static S390CPU **cpu_states;
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
{
if (cpu_addr >= max_cpus) {
return NULL;
}
/* Fast lookup via CPU ID */
return cpu_states[cpu_addr];
}
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
const char *firmware,
const char *netboot_fw,
bool enforce_bios)
{
Object *new = object_new(TYPE_S390_IPL);
DeviceState *dev = DEVICE(new);
if (kernel_filename) {
qdev_prop_set_string(dev, "kernel", kernel_filename);
}
if (initrd_filename) {
qdev_prop_set_string(dev, "initrd", initrd_filename);
}
qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
qdev_prop_set_string(dev, "firmware", firmware);
qdev_prop_set_string(dev, "netboot_fw", netboot_fw);
qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
new, NULL);
object_unref(new);
qdev_init_nofail(dev);
}
void s390_init_cpus(MachineState *machine)
{
int i;
gchar *name;
if (machine->cpu_model == NULL) {
machine->cpu_model = s390_default_cpu_model_name();
}
cpu_states = g_new0(S390CPU *, max_cpus);
for (i = 0; i < max_cpus; i++) {
name = g_strdup_printf("cpu[%i]", i);
object_property_add_link(OBJECT(machine), name, TYPE_S390_CPU,
(Object **) &cpu_states[i],
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
g_free(name);
}
for (i = 0; i < smp_cpus; i++) {
s390x_new_cpu(machine->cpu_model, i, &error_fatal);
}
}
void s390_create_virtio_net(BusState *bus, const char *name)
{
int i;
for (i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
DeviceState *dev;
if (!nd->model) {
nd->model = g_strdup("virtio");
}
qemu_check_nic_model(nd, "virtio");
dev = qdev_create(bus, name);
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
}
}
void gtod_save(QEMUFile *f, void *opaque)
{
uint64_t tod_low;
uint8_t tod_high;
int r;
r = s390_get_clock(&tod_high, &tod_low);
if (r) {
fprintf(stderr, "WARNING: Unable to get guest clock for migration. "
"Error code %d. Guest clock will not be migrated "
"which could cause the guest to hang.\n", r);
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_MISSING);
return;
}
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_PRESENT);
qemu_put_byte(f, tod_high);
qemu_put_be64(f, tod_low);
}
int gtod_load(QEMUFile *f, void *opaque, int version_id)
{
uint64_t tod_low;
uint8_t tod_high;
int r;
if (qemu_get_byte(f) == S390_TOD_CLOCK_VALUE_MISSING) {
fprintf(stderr, "WARNING: Guest clock was not migrated. This could "
"cause the guest to hang.\n");
return 0;
}
tod_high = qemu_get_byte(f);
tod_low = qemu_get_be64(f);
r = s390_set_clock(&tod_high, &tod_low);
if (r) {
fprintf(stderr, "WARNING: Unable to set guest clock value. "
"s390_get_clock returned error %d. This could cause "
"the guest to hang.\n", r);
}
return 0;
}
void s390_nmi(NMIState *n, int cpu_index, Error **errp)
{
CPUState *cs = qemu_get_cpu(cpu_index);
if (s390_cpu_restart(S390_CPU(cs))) {
error_setg(errp, QERR_UNSUPPORTED);
}
}
void s390_machine_reset(void)
{
S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0));
s390_cmma_reset();
qemu_devices_reset();
s390_crypto_reset();
/* all cpus are stopped - configure and start the ipl cpu only */
s390_ipl_prepare_cpu(ipl_cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu);
}

View File

@@ -1,35 +0,0 @@
/*
* Virtio interfaces for s390
*
* Copyright 2012 IBM Corp.
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
* your option) any later version. See the COPYING file in the top-level
* directory.
*/
#ifndef HW_S390_VIRTIO_H
#define HW_S390_VIRTIO_H
#include "hw/nmi.h"
#include "standard-headers/asm-s390/kvm_virtio.h"
#include "standard-headers/asm-s390/virtio-ccw.h"
typedef int (*s390_virtio_fn)(const uint64_t *args);
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
void s390_init_cpus(MachineState *machine);
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
const char *firmware,
const char *netboot_fw,
bool enforce_bios);
void s390_create_virtio_net(BusState *bus, const char *name);
void s390_nmi(NMIState *n, int cpu_index, Error **errp);
void s390_machine_reset(void);
void s390_memory_init(ram_addr_t mem_size);
void gtod_save(QEMUFile *f, void *opaque);
int gtod_load(QEMUFile *f, void *opaque, int version_id);
#endif

View File

@@ -34,16 +34,21 @@ static inline SCLPDevice *get_sclp_device(void)
return sclp;
}
static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int count)
static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count)
{
MachineState *ms = MACHINE(qdev_get_machine());
uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
int i;
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CPU, features);
for (i = 0; i < count; i++) {
entry[i].address = i;
entry[i].type = 0;
memcpy(entry[i].features, features, sizeof(entry[i].features));
for (i = 0, *count = 0; i < ms->possible_cpus->len; i++) {
if (!ms->possible_cpus->cpus[i].cpu) {
continue;
}
entry[*count].address = ms->possible_cpus->cpus[i].arch_id;
entry[*count].type = 0;
memcpy(entry[*count].features, features, sizeof(features));
(*count)++;
}
}
@@ -53,17 +58,13 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
ReadInfo *read_info = (ReadInfo *) sccb;
MachineState *machine = MACHINE(qdev_get_machine());
sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();
CPUState *cpu;
int cpu_count = 0;
int cpu_count;
int rnsize, rnmax;
int slots = MIN(machine->ram_slots, s390_get_memslot_count());
IplParameterBlock *ipib = s390_ipl_get_iplb();
CPU_FOREACH(cpu) {
cpu_count++;
}
/* CPU information */
prepare_cpu_entries(sclp, read_info->entries, &cpu_count);
read_info->entries_cpu = cpu_to_be16(cpu_count);
read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
read_info->highest_cpu = cpu_to_be16(max_cpus);
@@ -76,8 +77,6 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
read_info->conf_char_ext);
prepare_cpu_entries(sclp, read_info->entries, cpu_count);
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
SCLP_HAS_IOA_RECONFIG);
@@ -333,13 +332,9 @@ static void unassign_storage(SCLPDevice *sclp, SCCB *sccb)
static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
{
ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
CPUState *cpu;
int cpu_count = 0;
CPU_FOREACH(cpu) {
cpu_count++;
}
int cpu_count;
prepare_cpu_entries(sclp, cpu_info->entries, &cpu_count);
cpu_info->nr_configured = cpu_to_be16(cpu_count);
cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
cpu_info->nr_standby = cpu_to_be16(0);
@@ -348,7 +343,6 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
+ cpu_info->nr_configured*sizeof(CPUEntry));
prepare_cpu_entries(sclp, cpu_info->entries, cpu_count);
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

View File

@@ -487,7 +487,6 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
virtio_bus_get_vdev_config(&dev->bus, vdev->config);
/* XXX config space endianness */
cpu_physical_memory_write(ccw.cda, vdev->config, len);
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
@@ -510,7 +509,6 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
len = hw_len;
/* XXX config space endianness */
memcpy(vdev->config, config, len);
cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
virtio_bus_set_vdev_config(&dev->bus, vdev->config);
@@ -1007,6 +1005,15 @@ static void virtio_ccw_crypto_realize(VirtioCcwDevice *ccw_dev, Error **errp)
NULL);
}
static void virtio_ccw_gpu_realize(VirtioCcwDevice *ccw_dev, Error **errp)
{
VirtIOGPUCcw *dev = VIRTIO_GPU_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
/* DeviceState to VirtioCcwDevice. Note: used on datapath,
* be careful and test performance if you change this.
*/
@@ -1616,6 +1623,45 @@ static const TypeInfo virtio_ccw_crypto = {
.class_init = virtio_ccw_crypto_class_init,
};
static Property virtio_ccw_gpu_properties[] = {
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
VIRTIO_CCW_MAX_REV),
DEFINE_PROP_END_OF_LIST(),
};
static void virtio_ccw_gpu_instance_init(Object *obj)
{
VirtIOGPUCcw *dev = VIRTIO_GPU_CCW(obj);
VirtioCcwDevice *ccw_dev = VIRTIO_CCW_DEVICE(obj);
ccw_dev->force_revision_1 = true;
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_GPU);
}
static void virtio_ccw_gpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
k->realize = virtio_ccw_gpu_realize;
k->exit = virtio_ccw_exit;
dc->reset = virtio_ccw_reset;
dc->props = virtio_ccw_gpu_properties;
dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
static const TypeInfo virtio_ccw_gpu = {
.name = TYPE_VIRTIO_GPU_CCW,
.parent = TYPE_VIRTIO_CCW_DEVICE,
.instance_size = sizeof(VirtIOGPUCcw),
.instance_init = virtio_ccw_gpu_instance_init,
.class_init = virtio_ccw_gpu_class_init,
};
static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp)
{
VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
@@ -1815,6 +1861,7 @@ static void virtio_ccw_register(void)
type_register_static(&vhost_vsock_ccw_info);
#endif
type_register_static(&virtio_ccw_crypto);
type_register_static(&virtio_ccw_gpu);
}
type_init(virtio_ccw_register)

View File

@@ -27,6 +27,7 @@
#ifdef CONFIG_VHOST_VSOCK
#include "hw/virtio/vhost-vsock.h"
#endif /* CONFIG_VHOST_VSOCK */
#include "hw/virtio/virtio-gpu.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/css.h"
@@ -223,4 +224,13 @@ typedef struct VHostVSockCCWState {
#endif /* CONFIG_VHOST_VSOCK */
#define TYPE_VIRTIO_GPU_CCW "virtio-gpu-ccw"
#define VIRTIO_GPU_CCW(obj) \
OBJECT_CHECK(VirtIOGPUCcw, (obj), TYPE_VIRTIO_GPU_CCW)
typedef struct VirtIOGPUCcw {
VirtioCcwDevice parent_obj;
VirtIOGPU vdev;
} VirtIOGPUCcw;
#endif

View File

@@ -593,7 +593,7 @@ const VMStateDescription vmstate_esp = {
};
#define TYPE_ESP "esp"
#define ESP(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
typedef struct {
/*< private >*/
@@ -644,7 +644,7 @@ void esp_init(hwaddr espaddr, int it_shift,
ESPState *esp;
dev = qdev_create(NULL, TYPE_ESP);
sysbus = ESP(dev);
sysbus = ESP_STATE(dev);
esp = &sysbus->esp;
esp->dma_memory_read = dma_memory_read;
esp->dma_memory_write = dma_memory_write;
@@ -672,7 +672,7 @@ static const struct SCSIBusInfo esp_scsi_info = {
static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
{
SysBusESPState *sysbus = ESP(opaque);
SysBusESPState *sysbus = ESP_STATE(opaque);
ESPState *s = &sysbus->esp;
switch (irq) {
@@ -688,7 +688,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
static void sysbus_esp_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
SysBusESPState *sysbus = ESP(dev);
SysBusESPState *sysbus = ESP_STATE(dev);
ESPState *s = &sysbus->esp;
sysbus_init_irq(sbd, &s->irq);
@@ -706,7 +706,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error **errp)
static void sysbus_esp_hard_reset(DeviceState *dev)
{
SysBusESPState *sysbus = ESP(dev);
SysBusESPState *sysbus = ESP_STATE(dev);
esp_hard_reset(&sysbus->esp);
}

View File

@@ -27,7 +27,7 @@
#include "hw/pci/msix.h"
#include "qemu/iov.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "trace.h"
#include "qapi/error.h"
#include "mfi.h"

View File

@@ -28,7 +28,7 @@
#include "hw/pci/msi.h"
#include "qemu/iov.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "trace.h"
#include "mptsas.h"

View File

@@ -30,7 +30,7 @@
#include "hw/pci/msi.h"
#include "qemu/iov.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "trace.h"
#include "qapi/error.h"
#include "mptsas.h"
@@ -1236,11 +1236,9 @@ static void *mptsas_load_request(QEMUFile *f, SCSIRequest *sreq)
n = qemu_get_be32(f);
/* TODO: add a way for SCSIBusInfo's load_request to fail,
* and fail migration instead of asserting here.
* When we do, we might be able to re-enable NDEBUG below.
* This is just one thing (there are probably more) that must be
* fixed before we can allow NDEBUG compilation.
*/
#ifdef NDEBUG
#error building with NDEBUG is not supported
#endif
assert(n >= 0);
pci_dma_sglist_init(&req->qsg, pci, n);

View File

@@ -3,7 +3,7 @@
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "hw/qdev.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
@@ -516,8 +516,10 @@ static size_t scsi_sense_len(SCSIRequest *req)
static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
{
SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
int fixed_sense = (req->cmd.buf[1] & 1) == 0;
if (req->lun != 0) {
if (req->lun != 0 &&
buf[0] != INQUIRY && buf[0] != REQUEST_SENSE) {
scsi_req_build_sense(req, SENSE_CODE(LUN_NOT_SUPPORTED));
scsi_req_complete(req, CHECK_CONDITION);
return 0;
@@ -535,9 +537,28 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
break;
case REQUEST_SENSE:
scsi_target_alloc_buf(&r->req, scsi_sense_len(req));
r->len = scsi_device_get_sense(r->req.dev, r->buf,
MIN(req->cmd.xfer, r->buf_len),
(req->cmd.buf[1] & 1) == 0);
if (req->lun != 0) {
const struct SCSISense sense = SENSE_CODE(LUN_NOT_SUPPORTED);
if (fixed_sense) {
r->buf[0] = 0x70;
r->buf[2] = sense.key;
r->buf[10] = 10;
r->buf[12] = sense.asc;
r->buf[13] = sense.ascq;
r->len = MIN(req->cmd.xfer, SCSI_SENSE_LEN);
} else {
r->buf[0] = 0x72;
r->buf[1] = sense.key;
r->buf[2] = sense.asc;
r->buf[3] = sense.ascq;
r->len = 8;
}
} else {
r->len = scsi_device_get_sense(r->req.dev, r->buf,
MIN(req->cmd.xfer, r->buf_len),
fixed_sense);
}
if (r->req.dev->sense_is_ua) {
scsi_device_unit_attention_reported(req->dev);
r->req.dev->sense_len = 0;
@@ -769,7 +790,7 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
return 0;
}
ret = scsi_build_sense(req->sense, req->sense_len, buf, len, true);
ret = scsi_convert_sense(req->sense, req->sense_len, buf, len, true);
/*
* FIXME: clearing unit attention conditions upon autosense should be done
@@ -790,20 +811,14 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed)
{
return scsi_build_sense(dev->sense, dev->sense_len, buf, len, fixed);
return scsi_convert_sense(dev->sense, dev->sense_len, buf, len, fixed);
}
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
{
trace_scsi_req_build_sense(req->dev->id, req->lun, req->tag,
sense.key, sense.asc, sense.ascq);
memset(req->sense, 0, 18);
req->sense[0] = 0x70;
req->sense[2] = sense.key;
req->sense[7] = 10;
req->sense[12] = sense.asc;
req->sense[13] = sense.ascq;
req->sense_len = 18;
req->sense_len = scsi_build_sense(req->sense, sense);
}
static void scsi_req_enqueue_internal(SCSIRequest *req)
@@ -935,36 +950,6 @@ static int ata_passthrough_16_xfer(SCSIDevice *dev, uint8_t *buf)
return xfer * unit;
}
uint32_t scsi_data_cdb_xfer(uint8_t *buf)
{
if ((buf[0] >> 5) == 0 && buf[4] == 0) {
return 256;
} else {
return scsi_cdb_xfer(buf);
}
}
uint32_t scsi_cdb_xfer(uint8_t *buf)
{
switch (buf[0] >> 5) {
case 0:
return buf[4];
break;
case 1:
case 2:
return lduw_be_p(&buf[7]);
break;
case 4:
return ldl_be_p(&buf[10]) & 0xffffffffULL;
break;
case 5:
return ldl_be_p(&buf[6]) & 0xffffffffULL;
break;
default:
return -1;
}
}
static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
{
cmd->xfer = scsi_cdb_xfer(buf);
@@ -1277,53 +1262,6 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
}
}
static uint64_t scsi_cmd_lba(SCSICommand *cmd)
{
uint8_t *buf = cmd->buf;
uint64_t lba;
switch (buf[0] >> 5) {
case 0:
lba = ldl_be_p(&buf[0]) & 0x1fffff;
break;
case 1:
case 2:
case 5:
lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
break;
case 4:
lba = ldq_be_p(&buf[2]);
break;
default:
lba = -1;
}
return lba;
}
int scsi_cdb_length(uint8_t *buf) {
int cdb_len;
switch (buf[0] >> 5) {
case 0:
cdb_len = 6;
break;
case 1:
case 2:
cdb_len = 10;
break;
case 4:
cdb_len = 16;
break;
case 5:
cdb_len = 12;
break;
default:
cdb_len = -1;
}
return cdb_len;
}
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
{
int rc;
@@ -1370,326 +1308,6 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISense sense)
}
}
/*
* Predefined sense codes
*/
/* No sense data available */
const struct SCSISense sense_code_NO_SENSE = {
.key = NO_SENSE , .asc = 0x00 , .ascq = 0x00
};
/* LUN not ready, Manual intervention required */
const struct SCSISense sense_code_LUN_NOT_READY = {
.key = NOT_READY, .asc = 0x04, .ascq = 0x03
};
/* LUN not ready, Medium not present */
const struct SCSISense sense_code_NO_MEDIUM = {
.key = NOT_READY, .asc = 0x3a, .ascq = 0x00
};
/* LUN not ready, medium removal prevented */
const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = {
.key = NOT_READY, .asc = 0x53, .ascq = 0x02
};
/* Hardware error, internal target failure */
const struct SCSISense sense_code_TARGET_FAILURE = {
.key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00
};
/* Illegal request, invalid command operation code */
const struct SCSISense sense_code_INVALID_OPCODE = {
.key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00
};
/* Illegal request, LBA out of range */
const struct SCSISense sense_code_LBA_OUT_OF_RANGE = {
.key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00
};
/* Illegal request, Invalid field in CDB */
const struct SCSISense sense_code_INVALID_FIELD = {
.key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00
};
/* Illegal request, Invalid field in parameter list */
const struct SCSISense sense_code_INVALID_PARAM = {
.key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00
};
/* Illegal request, Parameter list length error */
const struct SCSISense sense_code_INVALID_PARAM_LEN = {
.key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00
};
/* Illegal request, LUN not supported */
const struct SCSISense sense_code_LUN_NOT_SUPPORTED = {
.key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00
};
/* Illegal request, Saving parameters not supported */
const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = {
.key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00
};
/* Illegal request, Incompatible medium installed */
const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = {
.key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00
};
/* Illegal request, medium removal prevented */
const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = {
.key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02
};
/* Illegal request, Invalid Transfer Tag */
const struct SCSISense sense_code_INVALID_TAG = {
.key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01
};
/* Command aborted, I/O process terminated */
const struct SCSISense sense_code_IO_ERROR = {
.key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
};
/* Command aborted, I_T Nexus loss occurred */
const struct SCSISense sense_code_I_T_NEXUS_LOSS = {
.key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07
};
/* Command aborted, Logical Unit failure */
const struct SCSISense sense_code_LUN_FAILURE = {
.key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
};
/* Command aborted, Overlapped Commands Attempted */
const struct SCSISense sense_code_OVERLAPPED_COMMANDS = {
.key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00
};
/* Unit attention, Capacity data has changed */
const struct SCSISense sense_code_CAPACITY_CHANGED = {
.key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
};
/* Unit attention, Power on, reset or bus device reset occurred */
const struct SCSISense sense_code_RESET = {
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00
};
/* Unit attention, No medium */
const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = {
.key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00
};
/* Unit attention, Medium may have changed */
const struct SCSISense sense_code_MEDIUM_CHANGED = {
.key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00
};
/* Unit attention, Reported LUNs data has changed */
const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = {
.key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e
};
/* Unit attention, Device internal reset */
const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = {
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04
};
/* Data Protection, Write Protected */
const struct SCSISense sense_code_WRITE_PROTECTED = {
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00
};
/* Data Protection, Space Allocation Failed Write Protect */
const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
};
/*
* scsi_build_sense
*
* Convert between fixed and descriptor sense buffers
*/
int scsi_build_sense(uint8_t *in_buf, int in_len,
uint8_t *buf, int len, bool fixed)
{
bool fixed_in;
SCSISense sense;
if (!fixed && len < 8) {
return 0;
}
if (in_len == 0) {
sense.key = NO_SENSE;
sense.asc = 0;
sense.ascq = 0;
} else {
fixed_in = (in_buf[0] & 2) == 0;
if (fixed == fixed_in) {
memcpy(buf, in_buf, MIN(len, in_len));
return MIN(len, in_len);
}
if (fixed_in) {
sense.key = in_buf[2];
sense.asc = in_buf[12];
sense.ascq = in_buf[13];
} else {
sense.key = in_buf[1];
sense.asc = in_buf[2];
sense.ascq = in_buf[3];
}
}
memset(buf, 0, len);
if (fixed) {
/* Return fixed format sense buffer */
buf[0] = 0x70;
buf[2] = sense.key;
buf[7] = 10;
buf[12] = sense.asc;
buf[13] = sense.ascq;
return MIN(len, SCSI_SENSE_LEN);
} else {
/* Return descriptor format sense buffer */
buf[0] = 0x72;
buf[1] = sense.key;
buf[2] = sense.asc;
buf[3] = sense.ascq;
return 8;
}
}
const char *scsi_command_name(uint8_t cmd)
{
static const char *names[] = {
[ TEST_UNIT_READY ] = "TEST_UNIT_READY",
[ REWIND ] = "REWIND",
[ REQUEST_SENSE ] = "REQUEST_SENSE",
[ FORMAT_UNIT ] = "FORMAT_UNIT",
[ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
[ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS",
/* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */
[ READ_6 ] = "READ_6",
[ WRITE_6 ] = "WRITE_6",
[ SET_CAPACITY ] = "SET_CAPACITY",
[ READ_REVERSE ] = "READ_REVERSE",
[ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
[ SPACE ] = "SPACE",
[ INQUIRY ] = "INQUIRY",
[ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
[ MAINTENANCE_IN ] = "MAINTENANCE_IN",
[ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
[ MODE_SELECT ] = "MODE_SELECT",
[ RESERVE ] = "RESERVE",
[ RELEASE ] = "RELEASE",
[ COPY ] = "COPY",
[ ERASE ] = "ERASE",
[ MODE_SENSE ] = "MODE_SENSE",
[ START_STOP ] = "START_STOP/LOAD_UNLOAD",
/* LOAD_UNLOAD and START_STOP use the same operation code */
[ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
[ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
[ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
[ READ_CAPACITY_10 ] = "READ_CAPACITY_10",
[ READ_10 ] = "READ_10",
[ WRITE_10 ] = "WRITE_10",
[ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT",
/* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */
[ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10",
[ VERIFY_10 ] = "VERIFY_10",
[ SEARCH_HIGH ] = "SEARCH_HIGH",
[ SEARCH_EQUAL ] = "SEARCH_EQUAL",
[ SEARCH_LOW ] = "SEARCH_LOW",
[ SET_LIMITS ] = "SET_LIMITS",
[ PRE_FETCH ] = "PRE_FETCH/READ_POSITION",
/* READ_POSITION and PRE_FETCH use the same operation code */
[ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
[ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
[ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE",
/* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */
[ MEDIUM_SCAN ] = "MEDIUM_SCAN",
[ COMPARE ] = "COMPARE",
[ COPY_VERIFY ] = "COPY_VERIFY",
[ WRITE_BUFFER ] = "WRITE_BUFFER",
[ READ_BUFFER ] = "READ_BUFFER",
[ UPDATE_BLOCK ] = "UPDATE_BLOCK",
[ READ_LONG_10 ] = "READ_LONG_10",
[ WRITE_LONG_10 ] = "WRITE_LONG_10",
[ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
[ WRITE_SAME_10 ] = "WRITE_SAME_10",
[ UNMAP ] = "UNMAP",
[ READ_TOC ] = "READ_TOC",
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
[ SANITIZE ] = "SANITIZE",
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
[ LOG_SELECT ] = "LOG_SELECT",
[ LOG_SENSE ] = "LOG_SENSE",
[ MODE_SELECT_10 ] = "MODE_SELECT_10",
[ RESERVE_10 ] = "RESERVE_10",
[ RELEASE_10 ] = "RELEASE_10",
[ MODE_SENSE_10 ] = "MODE_SENSE_10",
[ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
[ EXTENDED_COPY ] = "EXTENDED_COPY",
[ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
[ READ_16 ] = "READ_16",
[ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE",
[ WRITE_16 ] = "WRITE_16",
[ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
[ VERIFY_16 ] = "VERIFY_16",
[ PRE_FETCH_16 ] = "PRE_FETCH_16",
[ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
/* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
[ LOCATE_16 ] = "LOCATE_16",
[ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16",
/* ERASE_16 and WRITE_SAME_16 use the same operation code */
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
[ REPORT_LUNS ] = "REPORT_LUNS",
[ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12",
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
[ READ_12 ] = "READ_12",
[ WRITE_12 ] = "WRITE_12",
[ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE",
/* ERASE_12 and GET_PERFORMANCE use the same operation code */
[ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
[ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
[ VERIFY_12 ] = "VERIFY_12",
[ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
[ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
[ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
[ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
[ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING",
/* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
[ READ_CD ] = "READ_CD",
[ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
[ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE",
[ RESERVE_TRACK ] = "RESERVE_TRACK",
[ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
[ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE",
[ SET_CD_SPEED ] = "SET_CD_SPEED",
[ SET_READ_AHEAD ] = "SET_READ_AHEAD",
[ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE",
[ MECHANISM_STATUS ] = "MECHANISM_STATUS",
[ GET_EVENT_STATUS_NOTIFICATION ] = "GET_EVENT_STATUS_NOTIFICATION",
[ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION",
};
if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
return "*UNKNOWN*";
return names[cmd];
}
SCSIRequest *scsi_req_ref(SCSIRequest *req)
{
assert(req->refcount > 0);

View File

@@ -32,7 +32,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "sysemu/sysemu.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
@@ -106,7 +106,7 @@ typedef struct SCSIDiskState
bool tray_locked;
} SCSIDiskState;
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed);
static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed);
static void scsi_free_request(SCSIRequest *req)
{
@@ -184,19 +184,10 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed)
return true;
}
if (ret < 0) {
if (ret < 0 || (r->status && *r->status)) {
return scsi_handle_rw_error(r, -ret, acct_failed);
}
if (r->status && *r->status) {
if (acct_failed) {
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
}
scsi_req_complete(&r->req, *r->status);
return true;
}
return false;
}
@@ -422,13 +413,13 @@ static void scsi_read_data(SCSIRequest *req)
}
/*
* scsi_handle_rw_error has two return values. 0 means that the error
* must be ignored, 1 means that the error has been processed and the
* scsi_handle_rw_error has two return values. False means that the error
* must be ignored, true means that the error has been processed and the
* caller should not do anything else for this request. Note that
* scsi_handle_rw_error always manages its reference counts, independent
* of the return value.
*/
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
{
bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
@@ -440,6 +431,11 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
}
switch (error) {
case 0:
/* The command has run, no need to fake sense. */
assert(r->status && *r->status);
scsi_req_complete(&r->req, *r->status);
break;
case ENOMEDIUM:
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
break;
@@ -457,6 +453,18 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
break;
}
}
if (!error) {
assert(r->status && *r->status);
error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
if (error == ECANCELED || error == EAGAIN || error == ENOTCONN ||
error == 0) {
/* These errors are handled by guest. */
scsi_req_complete(&r->req, *r->status);
return true;
}
}
blk_error_action(s->qdev.conf.blk, action, is_read, error);
if (action == BLOCK_ERROR_ACTION_STOP) {
scsi_req_retry(&r->req);
@@ -1978,8 +1986,8 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
break;
case REQUEST_SENSE:
/* Just return "NO SENSE". */
buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
(req->cmd.buf[1] & 1) == 0);
buflen = scsi_convert_sense(NULL, 0, outbuf, r->buflen,
(req->cmd.buf[1] & 1) == 0);
if (buflen < 0) {
goto illegal_request;
}
@@ -2972,6 +2980,7 @@ static const TypeInfo scsi_cd_info = {
#ifdef __linux__
static Property scsi_block_properties[] = {
DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk),
DEFINE_PROP_END_OF_LIST(),
};

View File

@@ -34,15 +34,7 @@ do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
#include <scsi/sg.h>
#include "block/scsi.h"
#define SG_ERR_DRIVER_TIMEOUT 0x06
#define SG_ERR_DRIVER_SENSE 0x08
#define SG_ERR_DID_OK 0x00
#define SG_ERR_DID_NO_CONNECT 0x01
#define SG_ERR_DID_BUS_BUSY 0x02
#define SG_ERR_DID_TIME_OUT 0x03
#include "scsi/constants.h"
#ifndef MAX_UINT
#define MAX_UINT ((unsigned int)-1)
@@ -89,6 +81,7 @@ static void scsi_free_request(SCSIRequest *req)
static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
{
int status;
SCSISense sense;
assert(r->req.aiocb == NULL);
@@ -96,42 +89,15 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
scsi_req_cancel_complete(&r->req);
goto done;
}
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
r->req.sense_len = r->io_header.sb_len_wr;
status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
if (status == CHECK_CONDITION) {
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
r->req.sense_len = r->io_header.sb_len_wr;
} else {
scsi_req_build_sense(&r->req, sense);
}
}
if (ret != 0) {
switch (ret) {
case -EDOM:
status = TASK_SET_FULL;
break;
case -ENOMEM:
status = CHECK_CONDITION;
scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
break;
default:
status = CHECK_CONDITION;
scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
break;
}
} else {
if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
(r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
status = BUSY;
BADF("Driver Timeout\n");
} else if (r->io_header.host_status) {
status = CHECK_CONDITION;
scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
} else if (r->io_header.status) {
status = r->io_header.status;
} else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
status = CHECK_CONDITION;
} else {
status = GOOD;
}
}
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
r, r->req.tag, status);

View File

@@ -36,7 +36,7 @@
#include "cpu.h"
#include "hw/hw.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "srp.h"
#include "hw/qdev.h"
#include "hw/ppc/spapr.h"

View File

@@ -17,7 +17,7 @@
#include "qemu/error-report.h"
#include "sysemu/block-backend.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"

View File

@@ -21,7 +21,7 @@
#include "qemu/iov.h"
#include "sysemu/block-backend.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
@@ -867,10 +867,10 @@ void virtio_scsi_common_realize(DeviceState *dev,
s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, ctrl);
s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, evt);
s->ctrl_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, ctrl);
s->event_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, evt);
for (i = 0; i < s->conf.num_queues; i++) {
s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, cmd);
s->cmd_vqs[i] = virtio_add_queue(vdev, s->conf.virtqueue_size, cmd);
}
}
@@ -917,6 +917,8 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
static Property virtio_scsi_properties[] = {
DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
parent_obj.conf.virtqueue_size, 128),
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
0xFFFF),
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,

View File

@@ -28,7 +28,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "hw/pci/msi.h"
#include "vmw_pvscsi.h"
#include "trace.h"

View File

@@ -427,7 +427,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
unsigned int i;
uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
PCIBus *pci_bus, *pci_busA, *pci_busB;
PCIDevice *ebus;
PCIDevice *ebus, *pci_dev;
ISABus *isa_bus;
SysBusDevice *s;
qemu_irq *ivec_irqs, *pbm_irqs;
@@ -435,6 +435,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
DriveInfo *fd[MAX_FD];
DeviceState *dev;
FWCfgState *fw_cfg;
NICInfo *nd;
int onboard_nic_idx;
/* init CPUs */
cpu = sparc64_cpu_devinit(machine->cpu_model, hwdef->default_cpu_model,
@@ -464,8 +466,23 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
serial_hds_isa_init(isa_bus, i, MAX_SERIAL_PORTS);
parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
for(i = 0; i < nb_nics; i++)
pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
onboard_nic_idx = -1;
for (i = 0; i < nb_nics; i++) {
nd = &nd_table[i];
if (onboard_nic_idx == -1 &&
(!nd->model || strcmp(nd->model, "sunhme") == 0)) {
pci_dev = pci_create(pci_bus, -1, "sunhme");
dev = &pci_dev->qdev;
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
onboard_nic_idx = i;
} else {
pci_nic_init_nofail(nd, pci_bus, "ne2k_pci", NULL);
}
}
onboard_nic_idx = MAX(onboard_nic_idx, 0);
ide_drive_get(hd, ARRAY_SIZE(hd));
@@ -510,7 +527,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
/* XXX: need an option to load a NVRAM image */
0,
graphic_width, graphic_height, graphic_depth,
(uint8_t *)&nd_table[0].macaddr);
(uint8_t *)&nd_table[onboard_nic_idx].macaddr);
dev = qdev_create(NULL, TYPE_FW_CFG_IO);
qdev_prop_set_bit(dev, "dma_enabled", false);

View File

@@ -19,7 +19,7 @@
#include "hw/usb.h"
#include "hw/usb/desc.h"
#include "hw/scsi/scsi.h"
#include "block/scsi.h"
#include "scsi/constants.h"
/* --------------------------------------------------------------------- */

View File

@@ -32,6 +32,7 @@
#include "hw/usb/ehci-regs.h"
#include "hw/usb/hcd-ehci.h"
#include "trace.h"
#include "qemu/error-report.h"
#define FRAME_TIMER_FREQ 1000
#define FRAME_TIMER_NS (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ)
@@ -348,7 +349,7 @@ static void ehci_trace_sitd(EHCIState *s, hwaddr addr,
static void ehci_trace_guest_bug(EHCIState *s, const char *message)
{
trace_usb_ehci_guest_bug(message);
fprintf(stderr, "ehci warning: %s\n", message);
warn_report("%s", message);
}
static inline bool ehci_enabled(EHCIState *s)
@@ -1728,7 +1729,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
/* siTD is not active, nothing to do */;
} else {
/* TODO: split transfers are not implemented */
fprintf(stderr, "WARNING: Skipping active siTD\n");
warn_report("Skipping active siTD");
}
ehci_set_fetch_addr(ehci, async, sitd.next);

View File

@@ -26,6 +26,7 @@
#include "qapi/visitor.h"
#include "qapi-event.h"
#include "trace.h"
#include "qemu/error-report.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
@@ -292,7 +293,7 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
s->stats_vq_offset = offset;
if (qemu_gettimeofday(&tv) < 0) {
fprintf(stderr, "warning: %s: failed to get time of day\n", __func__);
warn_report("%s: failed to get time of day", __func__);
goto out;
}

View File

@@ -1025,11 +1025,9 @@ void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz)
/* TODO: teach all callers that this can fail, and return failure instead
* of asserting here.
* When we do, we might be able to re-enable NDEBUG below.
* This is just one thing (there are probably more) that must be
* fixed before we can allow NDEBUG compilation.
*/
#ifdef NDEBUG
#error building with NDEBUG is not supported
#endif
assert(ARRAY_SIZE(data.in_addr) >= data.in_num);
assert(ARRAY_SIZE(data.out_addr) >= data.out_num);

View File

@@ -180,6 +180,7 @@ typedef struct XenPTMSI {
uint32_t addr_hi; /* guest message upper address */
uint16_t data; /* guest message data */
uint32_t ctrl_offset; /* saved control offset */
uint32_t mask; /* guest mask bits */
int pirq; /* guest pirq corresponding */
bool initialized; /* when guest MSI is initialized */
bool mapped; /* when pirq is mapped */

View File

@@ -1315,6 +1315,22 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
return 0;
}
static int xen_pt_mask_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
uint32_t *val, uint32_t dev_value,
uint32_t valid_mask)
{
int rc;
rc = xen_pt_long_reg_write(s, cfg_entry, val, dev_value, valid_mask);
if (rc) {
return rc;
}
s->msi->mask = *val;
return 0;
}
/* MSI Capability Structure reg static information table */
static XenPTRegInfo xen_pt_emu_reg_msi[] = {
/* Next Pointer reg */
@@ -1393,7 +1409,7 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = {
.emu_mask = 0xFFFFFFFF,
.init = xen_pt_mask_reg_init,
.u.dw.read = xen_pt_long_reg_read,
.u.dw.write = xen_pt_long_reg_write,
.u.dw.write = xen_pt_mask_reg_write,
},
/* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */
{
@@ -1404,7 +1420,7 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = {
.emu_mask = 0xFFFFFFFF,
.init = xen_pt_mask_reg_init,
.u.dw.read = xen_pt_long_reg_read,
.u.dw.write = xen_pt_long_reg_write,
.u.dw.write = xen_pt_mask_reg_write,
},
/* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */
{

View File

@@ -24,6 +24,7 @@
#define XEN_PT_GFLAGS_SHIFT_DM 9
#define XEN_PT_GFLAGSSHIFT_DELIV_MODE 12
#define XEN_PT_GFLAGSSHIFT_TRG_MODE 15
#define XEN_PT_GFLAGSSHIFT_UNMASKED 16
#define latch(fld) latch[PCI_MSIX_ENTRY_##fld / sizeof(uint32_t)]
@@ -155,7 +156,8 @@ static int msi_msix_update(XenPCIPassthroughState *s,
int pirq,
bool is_msix,
int msix_entry,
int *old_pirq)
int *old_pirq,
bool masked)
{
PCIDevice *d = &s->dev;
uint8_t gvec = msi_vector(data);
@@ -171,6 +173,8 @@ static int msi_msix_update(XenPCIPassthroughState *s,
table_addr = s->msix->mmio_base_addr;
}
gflags |= masked ? 0 : (1u << XEN_PT_GFLAGSSHIFT_UNMASKED);
rc = xc_domain_update_msi_irq(xen_xc, xen_domid, gvec,
pirq, gflags, table_addr);
@@ -273,8 +277,10 @@ int xen_pt_msi_setup(XenPCIPassthroughState *s)
int xen_pt_msi_update(XenPCIPassthroughState *s)
{
XenPTMSI *msi = s->msi;
/* Current MSI emulation in QEMU only supports 1 vector */
return msi_msix_update(s, msi_addr64(msi), msi->data, msi->pirq,
false, 0, &msi->pirq);
false, 0, &msi->pirq, msi->mask & 1);
}
void xen_pt_msi_disable(XenPCIPassthroughState *s)
@@ -355,7 +361,8 @@ static int xen_pt_msix_update_one(XenPCIPassthroughState *s, int entry_nr,
}
rc = msi_msix_update(s, entry->addr, entry->data, pirq, true,
entry_nr, &entry->pirq);
entry_nr, &entry->pirq,
vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT);
if (!rc) {
entry->updated = false;

View File

@@ -371,6 +371,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
#define PC_COMPAT_2_10 \
HW_COMPAT_2_10 \
{\
.driver = TYPE_X86_CPU,\
.property = "x-hv-max-vps",\
.value = "0x40",\
},
#define PC_COMPAT_2_9 \
HW_COMPAT_2_9 \

View File

@@ -11,12 +11,10 @@
#include "sysemu/dma.h"
#include "sysemu/sysemu.h"
#include "hw/block/block.h"
#include "block/scsi.h"
#include "scsi/constants.h"
#include "qapi/error.h"
/* debug IDE devices */
//#define DEBUG_IDE
//#define DEBUG_IDE_ATAPI
//#define DEBUG_AIO
#define USE_DMA_CDROM
typedef struct IDEBus IDEBus;
@@ -335,12 +333,16 @@ struct unreported_events {
};
enum ide_dma_cmd {
IDE_DMA_READ,
IDE_DMA__BEGIN = 0,
IDE_DMA_READ = IDE_DMA__BEGIN,
IDE_DMA_WRITE,
IDE_DMA_TRIM,
IDE_DMA_ATAPI,
IDE_DMA__COUNT
};
extern const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT];
#define ide_cmd_is_read(s) \
((s)->dma_cmd == IDE_DMA_READ)
@@ -495,7 +497,7 @@ struct IDEBus {
typedef struct IDEDeviceClass {
DeviceClass parent_class;
int (*init)(IDEDevice *dev);
void (*realize)(IDEDevice *dev, Error **errp);
} IDEDeviceClass;
struct IDEDevice {
@@ -605,7 +607,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
const char *version, const char *serial, const char *model,
uint64_t wwn,
uint32_t cylinders, uint32_t heads, uint32_t secs,
int chs_trans);
int chs_trans, Error **errp);
void ide_init2(IDEBus *bus, qemu_irq irq);
void ide_exit(IDEState *s);
void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);

View File

@@ -104,6 +104,10 @@
#define RTL8211E_PHYID1 0x001c
#define RTL8211E_PHYID2 0xc915
/* National Semiconductor DP83840 */
#define DP83840_PHYID1 0x2000
#define DP83840_PHYID2 0x5c01
/* National Semiconductor DP83848 */
#define DP83848_PHYID1 0x2000
#define DP83848_PHYID2 0x5c90

View File

@@ -187,6 +187,7 @@
#define PCI_VENDOR_ID_SUN 0x108e
#define PCI_DEVICE_ID_SUN_EBUS 0x1000
#define PCI_DEVICE_ID_SUN_HME 0x1001
#define PCI_DEVICE_ID_SUN_SIMBA 0x5000
#define PCI_DEVICE_ID_SUN_SABRE 0xa000

View File

@@ -56,4 +56,6 @@ bool gs_allowed(void);
*/
bool css_migration_enabled(void);
void subsystem_reset(void);
#endif

View File

@@ -16,6 +16,7 @@
#include "hw/sysbus.h"
#include "hw/qdev.h"
#include "target/s390x/cpu-qom.h"
#define SCLP_CMD_CODE_MASK 0xffff00ff
@@ -242,5 +243,6 @@ sclpMemoryHotplugDev *init_sclp_memory_hotplug_dev(void);
sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void);
void sclp_service_interrupt(uint32_t sccb);
void raise_irq_cpu_hotplug(void);
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
#endif

View File

@@ -4,45 +4,20 @@
#include "hw/qdev.h"
#include "hw/block/block.h"
#include "sysemu/sysemu.h"
#include "scsi/utils.h"
#include "qemu/notify.h"
#define MAX_SCSI_DEVS 255
#define SCSI_CMD_BUF_SIZE 16
#define SCSI_SENSE_LEN 18
#define SCSI_SENSE_LEN_SCANNER 32
#define SCSI_INQUIRY_LEN 36
typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusInfo SCSIBusInfo;
typedef struct SCSICommand SCSICommand;
typedef struct SCSIDevice SCSIDevice;
typedef struct SCSIRequest SCSIRequest;
typedef struct SCSIReqOps SCSIReqOps;
enum SCSIXferMode {
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
};
typedef struct SCSISense {
uint8_t key;
uint8_t asc;
uint8_t ascq;
} SCSISense;
#define SCSI_SENSE_BUF_SIZE_OLD 96
#define SCSI_SENSE_BUF_SIZE 252
struct SCSICommand {
uint8_t buf[SCSI_CMD_BUF_SIZE];
int len;
size_t xfer;
uint64_t lba;
enum SCSIXferMode mode;
};
struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
@@ -180,73 +155,6 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated);
void scsi_legacy_handle_cmdline(void);
/*
* Predefined sense codes
*/
/* No sense data available */
extern const struct SCSISense sense_code_NO_SENSE;
/* LUN not ready, Manual intervention required */
extern const struct SCSISense sense_code_LUN_NOT_READY;
/* LUN not ready, Medium not present */
extern const struct SCSISense sense_code_NO_MEDIUM;
/* LUN not ready, medium removal prevented */
extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
/* Hardware error, internal target failure */
extern const struct SCSISense sense_code_TARGET_FAILURE;
/* Illegal request, invalid command operation code */
extern const struct SCSISense sense_code_INVALID_OPCODE;
/* Illegal request, LBA out of range */
extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
/* Illegal request, Invalid field in CDB */
extern const struct SCSISense sense_code_INVALID_FIELD;
/* Illegal request, Invalid field in parameter list */
extern const struct SCSISense sense_code_INVALID_PARAM;
/* Illegal request, Parameter list length error */
extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
/* Illegal request, LUN not supported */
extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
/* Illegal request, Saving parameters not supported */
extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
/* Illegal request, Incompatible format */
extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
/* Illegal request, medium removal prevented */
extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
/* Illegal request, Invalid Transfer Tag */
extern const struct SCSISense sense_code_INVALID_TAG;
/* Command aborted, I/O process terminated */
extern const struct SCSISense sense_code_IO_ERROR;
/* Command aborted, I_T Nexus loss occurred */
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
/* Command aborted, Logical Unit failure */
extern const struct SCSISense sense_code_LUN_FAILURE;
/* Command aborted, Overlapped Commands Attempted */
extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
/* LUN not ready, Capacity data has changed */
extern const struct SCSISense sense_code_CAPACITY_CHANGED;
/* LUN not ready, Medium not present */
extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
/* Unit attention, Power on, reset or bus device reset occurred */
extern const struct SCSISense sense_code_RESET;
/* Unit attention, Medium may have changed*/
extern const struct SCSISense sense_code_MEDIUM_CHANGED;
/* Unit attention, Reported LUNs data has changed */
extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
/* Unit attention, Device internal reset */
extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
/* Data Protection, Write Protected */
extern const struct SCSISense sense_code_WRITE_PROTECTED;
/* Data Protection, Space Allocation Failed Write Protect */
extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
#define SENSE_CODE(x) sense_code_ ## x
uint32_t scsi_data_cdb_xfer(uint8_t *buf);
uint32_t scsi_cdb_xfer(uint8_t *buf);
int scsi_cdb_length(uint8_t *buf);
int scsi_build_sense(uint8_t *in_buf, int in_len,
uint8_t *buf, int len, bool fixed);
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
uint32_t tag, uint32_t lun, void *hba_private);
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,

View File

@@ -32,7 +32,6 @@
#define VIRTIO_SCSI(obj) \
OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
#define VIRTIO_SCSI_VQ_SIZE 128
#define VIRTIO_SCSI_MAX_CHANNEL 0
#define VIRTIO_SCSI_MAX_TARGET 255
#define VIRTIO_SCSI_MAX_LUN 16383
@@ -48,6 +47,7 @@ typedef struct virtio_scsi_config VirtIOSCSIConfig;
struct VirtIOSCSIConf {
uint32_t num_queues;
uint32_t virtqueue_size;
uint32_t max_sectors;
uint32_t cmd_per_lun;
#ifdef CONFIG_VHOST_SCSI

View File

@@ -107,6 +107,22 @@ extern int daemon(int, int);
#include "glib-compat.h"
#include "qemu/typedefs.h"
/*
* We have a lot of unaudited code that may fail in strange ways, or
* even be a security risk during migration, if you disable assertions
* at compile-time. You may comment out these safety checks if you
* absolutely want to disable assertion overhead, but it is not
* supported upstream so the risk is all yours. Meanwhile, please
* submit patches to remove any side-effects inside an assertion, or
* fixing error handling that should use Error instead of assert.
*/
#ifdef NDEBUG
#error building with NDEBUG is not supported
#endif
#ifdef G_DISABLE_ASSERT
#error building with G_DISABLE_ASSERT is not supported
#endif
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif

View File

@@ -388,10 +388,10 @@ struct CPUState {
DECLARE_BITMAP(trace_dstate, CPU_TRACE_DSTATE_MAX_EVENTS);
/* TODO Move common fields from CPUArchState here. */
int cpu_index; /* used by alpha TCG */
uint32_t halted; /* used by alpha, cris, ppc TCG */
int cpu_index;
uint32_t halted;
uint32_t can_do_io;
int32_t exception_index; /* used by m68k TCG */
int32_t exception_index;
/* shared by kvm, hax and hvf */
bool vcpu_dirty;

View File

@@ -150,8 +150,6 @@
#define READ_CD 0xbe
#define SEND_DVD_STRUCTURE 0xbf
const char *scsi_command_name(uint8_t cmd);
/*
* SERVICE ACTION IN subcodes
*/

124
include/scsi/utils.h Normal file
View File

@@ -0,0 +1,124 @@
#ifndef SCSI_UTILS_H
#define SCSI_UTILS_H 1
#ifdef CONFIG_LINUX
#include <scsi/sg.h>
#endif
#define SCSI_CMD_BUF_SIZE 16
#define SCSI_SENSE_LEN 18
#define SCSI_SENSE_LEN_SCANNER 32
#define SCSI_INQUIRY_LEN 36
enum SCSIXferMode {
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
};
typedef struct SCSICommand {
uint8_t buf[SCSI_CMD_BUF_SIZE];
int len;
size_t xfer;
uint64_t lba;
enum SCSIXferMode mode;
} SCSICommand;
typedef struct SCSISense {
uint8_t key;
uint8_t asc;
uint8_t ascq;
} SCSISense;
int scsi_build_sense(uint8_t *buf, SCSISense sense);
/*
* Predefined sense codes
*/
/* No sense data available */
extern const struct SCSISense sense_code_NO_SENSE;
/* LUN not ready, Manual intervention required */
extern const struct SCSISense sense_code_LUN_NOT_READY;
/* LUN not ready, Medium not present */
extern const struct SCSISense sense_code_NO_MEDIUM;
/* LUN not ready, medium removal prevented */
extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
/* Hardware error, internal target failure */
extern const struct SCSISense sense_code_TARGET_FAILURE;
/* Illegal request, invalid command operation code */
extern const struct SCSISense sense_code_INVALID_OPCODE;
/* Illegal request, LBA out of range */
extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
/* Illegal request, Invalid field in CDB */
extern const struct SCSISense sense_code_INVALID_FIELD;
/* Illegal request, Invalid field in parameter list */
extern const struct SCSISense sense_code_INVALID_PARAM;
/* Illegal request, Parameter list length error */
extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
/* Illegal request, LUN not supported */
extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
/* Illegal request, Saving parameters not supported */
extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
/* Illegal request, Incompatible format */
extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
/* Illegal request, medium removal prevented */
extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
/* Illegal request, Invalid Transfer Tag */
extern const struct SCSISense sense_code_INVALID_TAG;
/* Command aborted, I/O process terminated */
extern const struct SCSISense sense_code_IO_ERROR;
/* Command aborted, I_T Nexus loss occurred */
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
/* Command aborted, Logical Unit failure */
extern const struct SCSISense sense_code_LUN_FAILURE;
/* Command aborted, Overlapped Commands Attempted */
extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
/* LUN not ready, Capacity data has changed */
extern const struct SCSISense sense_code_CAPACITY_CHANGED;
/* LUN not ready, Medium not present */
extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
/* Unit attention, Power on, reset or bus device reset occurred */
extern const struct SCSISense sense_code_RESET;
/* Unit attention, Medium may have changed*/
extern const struct SCSISense sense_code_MEDIUM_CHANGED;
/* Unit attention, Reported LUNs data has changed */
extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
/* Unit attention, Device internal reset */
extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
/* Data Protection, Write Protected */
extern const struct SCSISense sense_code_WRITE_PROTECTED;
/* Data Protection, Space Allocation Failed Write Protect */
extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
#define SENSE_CODE(x) sense_code_ ## x
int scsi_sense_to_errno(int key, int asc, int ascq);
int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size);
int scsi_convert_sense(uint8_t *in_buf, int in_len,
uint8_t *buf, int len, bool fixed);
const char *scsi_command_name(uint8_t cmd);
uint64_t scsi_cmd_lba(SCSICommand *cmd);
uint32_t scsi_data_cdb_xfer(uint8_t *buf);
uint32_t scsi_cdb_xfer(uint8_t *buf);
int scsi_cdb_length(uint8_t *buf);
/* Linux SG_IO interface. */
#ifdef CONFIG_LINUX
#define SG_ERR_DRIVER_TIMEOUT 0x06
#define SG_ERR_DRIVER_SENSE 0x08
#define SG_ERR_DID_OK 0x00
#define SG_ERR_DID_NO_CONNECT 0x01
#define SG_ERR_DID_BUS_BUSY 0x02
#define SG_ERR_DID_TIME_OUT 0x03
#define SG_ERR_DRIVER_SENSE 0x08
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
SCSISense *sense);
#endif
#endif

View File

@@ -2701,10 +2701,10 @@ typedef struct MemoryRegionList MemoryRegionList;
struct MemoryRegionList {
const MemoryRegion *mr;
QTAILQ_ENTRY(MemoryRegionList) queue;
QTAILQ_ENTRY(MemoryRegionList) mrqueue;
};
typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead;
typedef QTAILQ_HEAD(mrqueue, MemoryRegionList) MemoryRegionListHead;
#define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \
int128_sub((size), int128_one())) : 0)
@@ -2746,7 +2746,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
bool found = false;
/* check if the alias is already in the queue */
QTAILQ_FOREACH(ml, alias_print_queue, queue) {
QTAILQ_FOREACH(ml, alias_print_queue, mrqueue) {
if (ml->mr == mr->alias) {
found = true;
}
@@ -2755,7 +2755,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
if (!found) {
ml = g_new(MemoryRegionList, 1);
ml->mr = mr->alias;
QTAILQ_INSERT_TAIL(alias_print_queue, ml, queue);
QTAILQ_INSERT_TAIL(alias_print_queue, ml, mrqueue);
}
mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
" (prio %d, %s): alias %s @%s " TARGET_FMT_plx
@@ -2783,26 +2783,26 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) {
new_ml = g_new(MemoryRegionList, 1);
new_ml->mr = submr;
QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
if (new_ml->mr->addr < ml->mr->addr ||
(new_ml->mr->addr == ml->mr->addr &&
new_ml->mr->priority > ml->mr->priority)) {
QTAILQ_INSERT_BEFORE(ml, new_ml, queue);
QTAILQ_INSERT_BEFORE(ml, new_ml, mrqueue);
new_ml = NULL;
break;
}
}
if (new_ml) {
QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, queue);
QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, mrqueue);
}
}
QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start,
alias_print_queue);
}
QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, queue, next_ml) {
QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) {
g_free(ml);
}
}
@@ -2872,13 +2872,13 @@ void mtree_info(fprintf_function mon_printf, void *f, bool flatview)
}
/* print aliased regions */
QTAILQ_FOREACH(ml, &ml_head, queue) {
QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
mon_printf(f, "memory-region: %s\n", memory_region_name(ml->mr));
mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head);
mon_printf(f, "\n");
}
QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
QTAILQ_FOREACH_SAFE(ml, &ml_head, mrqueue, ml2) {
g_free(ml);
}
}

Some files were not shown because too many files have changed in this diff Show More