Compare commits

...

238 Commits

Author SHA1 Message Date
Mark Cave-Ayland
8498321421 sun4m: don't use legacy fw_cfg_init_mem() function
Instead initialise the device via qdev to allow us to set device properties
directly as required.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2018-08-20 19:18:31 +01:00
Mark Cave-Ayland
3ac24188ec sun4u: ensure kernel_top is always initialised
Valgrind reports that when loading a non-ELF kernel, kernel_top may be used
uninitialised when checking for an initrd.

Since there are no known non-ELF kernels for SPARC64 then we can simply
initialise kernel_top to 0 and then skip the initrd load process if it hasn't
been set by load_elf().

Reported-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2018-08-20 19:18:31 +01:00
Peter Maydell
d0092d90eb Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20180820' into staging
First round of s390x patches for 3.1:
- add compat machine for 3.1
- remove deprecated 's390-squash-mcss' option
- cpu models: add "max" cpu model, enhance feature group code
- kvm: add support for etoken facility and huge page backing

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

* remotes/cohuck/tags/s390x-20180820:
  s390x: Enable KVM huge page backing support
  s390x/kvm: add etoken facility
  linux-headers: update
  s390x/cpumodel: Add "-cpu max" support
  s390x: remove 's390-squash-mcss' option
  s390x/cpumodel: enum type S390FeatGroup now gets generated
  s390x: introduce 3.1 compat machine

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 17:41:18 +01:00
Peter Maydell
44b69d5037 tests/vm: Clean out old working directories on build
When we do a build inside one of the BSD VMs, first
delete any stale old build directories from the VM's
/var/tmp. This prevents the VM from running out of
disk space after it has been used for a dozen or
so builds.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 20180820124811.7982-1-peter.maydell@linaro.org
2018-08-20 17:07:53 +01:00
Peter Maydell
c8090972fa Merge remote-tracking branch 'remotes/marcel/tags/rdma-pull-request' into staging
RDMA queue

# gpg: Signature made Sat 18 Aug 2018 16:01:46 BST
# gpg:                using RSA key 36D4C0F0CF2FE46D
# gpg: Good signature from "Marcel Apfelbaum <marcel.apfelbaum@zoho.com>"
# gpg:                 aka "Marcel Apfelbaum <marcel@redhat.com>"
# gpg:                 aka "Marcel Apfelbaum <marcel.apfelbaum@gmail.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: B1C6 3A57 F92E 08F2 640F  31F5 36D4 C0F0 CF2F E46D

* remotes/marcel/tags/rdma-pull-request:
  config: split PVRDMA from RDMA
  hw/pvrdma: remove not needed include
  hw/rdma: Add reference to pci_dev in backend_dev
  hw/rdma: Bugfix - Support non-aligned buffers
  hw/rdma: Print backend QP number in hex format
  hw/rdma: Cosmetic change - move to generic function
  hw/pvrdma: Cosmetic change - indent right
  hw/rdma: Reorder resource cleanup
  hw/rdma: Do not allocate memory for non-dma MR
  hw/rdma: Delete useless structure RdmaRmUserMR
  hw/pvrdma: Make default pkey 0xFFFF
  hw/pvrdma: Clean CQE before use
  hw/rdma: Modify debug macros
  hw/pvrdma: Bugfix - provide the correct attr_mask to query_qp
  hw/rdma: Make distinction between device init and start modes

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 15:44:41 +01:00
Peter Maydell
62c34848ef Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180820' into staging
target-arm queue:
 * Fix crash on conditional instruction in an IT block
 * docs/generic-loader: mention U-Boot and Intel HEX executable formats
 * hw/intc/arm_gicv3_its: downgrade error_report to warn_report in kvm_arm_its_reset
 * imx_serial: Generate interrupt on receive data ready if enabled
 * Fix various minor bugs in AArch32 Hyp related coprocessor registers
 * Permit accesses to ELR_Hyp from Hyp mode via MSR/MRS (banked)
 * Implement AArch32 ERET instruction
 * hw/arm/virt: Add virt-3.1 machine type
 * sdhci: add i.MX SD Stable Clock bit
 * Remove now-obsolete MMIO request_ptr APIs
 * hw/timer/m48t59: Move away from old_mmio accessors
 * hw/watchdog/cmsdk_apb_watchdog: Implement CMSDK APB watchdog module
 * nvic: Expose NMI line
 * hw/dma/pl080: cleanups and new features required for use in MPS boards

# gpg: Signature made Mon 20 Aug 2018 11:30:12 BST
# gpg:                using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180820: (25 commits)
  hw/dma/pl080: Remove hw_error() if DMA is enabled
  hw/dma/pl080: Correct bug in register address decode logic
  hw/dma/pl080: Provide device reset function
  hw/dma/pl080: Don't use CPU address space for DMA accesses
  hw/dma/pl080: Support all three interrupt lines
  hw/dma/pl080: Allow use as embedded-struct device
  nvic: Expose NMI line
  hw/watchdog/cmsdk_apb_watchdog: Implement CMSDK APB watchdog module
  hw/timer/m48t59: Move away from old_mmio accessors
  hw/misc: Remove mmio_interface device
  memory: Remove MMIO request_ptr APIs
  hw/ssi/xilinx_spips: Remove unneeded MMIO request_ptr code
  sdhci: add i.MX SD Stable Clock bit
  hw/arm/virt: Add virt-3.1 machine type
  target/arm: Implement AArch32 ERET instruction
  target/arm: Permit accesses to ELR_Hyp from Hyp mode via MSR/MRS (banked)
  target/arm: Implement ESR_EL2/HSR for AArch32 and no-EL2
  target/arm: Implement AArch32 Hyp FARs
  target/arm: Implement AArch32 HVBAR
  target/arm: Add missing .cp = 15 to HMAIR1 and HAMAIR1 regdefs
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 13:22:21 +01:00
Janosch Frank
09c6c75480 s390x: Enable KVM huge page backing support
QEMU has had huge page support for a longer time already, but KVM
memory management under s390x needed some changes to work with huge
backings.

Now that we have support, let's enable it if requested and
available. Otherwise we now properly tell the user if there is no
support and back out instead of failing to run the VM later on.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180802070201.257406-1-frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
Christian Borntraeger
27e84d4ebd s390x/kvm: add etoken facility
Provide the etoken facility. We need to handle cpu model, migration and
clear reset.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Janosch Frank <frankja@linux.ibm.com>
Message-Id: <20180731090448.36662-3-borntraeger@de.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
Cornelia Huck
d36f7de829 linux-headers: update
Update to Linux upstream commit 2ad0d5269970
("Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net")

Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
David Hildenbrand
c61177881c s390x/cpumodel: Add "-cpu max" support
The "max" CPU model behaves like "-cpu host" when KVM is enabled, and like
a CPU with the maximum possible feature set when TCG is enabled.

While the "host" model can not be used under TCG ("kvm_required"), the
"max" model can and "Enables all features supported by the accelerator in
the current host".

So we can treat "host" just as a special case of "max" (like x86 does).
It differs to the "qemu" CPU model under TCG such that compatibility
handling will not be performed and that some experimental CPU features
not yet part of the "qemu" model might be indicated.

These are right now under TCG (see "qemu_MAX"):
- stfle53
- msa5-base
- zpci

This will result right now in the following warning when starting QEMU TCG
with the "max" model:
    "qemu-system-s390x: warning: 'msa5-base' requires 'kimd-sha-512'."

The "qemu" model (used as default in QEMU under TCG) will continue to
work without such warnings. The "max" model in the current form
might be interesting for kvm-unit-tests (where we would e.g. now also
test "msa5-base").

The "max" model is neither static nor migration safe (like the "host"
model). It is independent of the machine but dependends on the accelerator.
It can be used to detect the maximum CPU model also under TCG from upper
layers without having to care about CPU model names for CPU model
expansion.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180725091233.3300-1-david@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
[CH: minor wording changes]
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
Cornelia Huck
36699ab480 s390x: remove 's390-squash-mcss' option
This option has been deprecated for two releases; remove it.

Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Halil Pasic <pasic@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
Michael Mueller
a5f9ecc49d s390x/cpumodel: enum type S390FeatGroup now gets generated
The enumeration type S390FeatGroup is now generated as well.
This shall simplify the definition of new feature groups
without the requirement to modify existing code.

Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
Message-Id: <20180725143617.8731-1-mimu@linux.ibm.com>
Acked-by: David Hildenbrand <david@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
Cornelia Huck
9ca056d68f s390x: introduce 3.1 compat machine
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-08-20 14:18:49 +02:00
Peter Maydell
b85fad1588 hw/dma/pl080: Remove hw_error() if DMA is enabled
The PL08x model currently will unconditionally call hw_error()
if the DMA engine is enabled by the guest. This has been
present since the PL080 model was edded in 2006, and is
presumably either unintentional debug code left enabled,
or a guard against untested DMA engine code being used.

Remove the hw_error(), since we now have a guest which
will actually try to use the DMA engine (the self-test
binary for the AN505 MPS2 FPGA image).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
156448ab64 hw/dma/pl080: Correct bug in register address decode logic
A bug in the handling of the register address decode logic
for the PL08x meant that we were incorrectly treating
accesses to the DMA channel registers (DMACCxSrcAddr,
DMACCxDestaddr, DMACCxLLI, DMACCxControl, DMACCxConfiguration)
as bad offsets. Fix this long-standing bug.

Fixes: https://bugs.launchpad.net/qemu/+bug/1637974
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
c193304d4f hw/dma/pl080: Provide device reset function
The PL080/PL081 model is missing a reset function; implement it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
112a829f8f hw/dma/pl080: Don't use CPU address space for DMA accesses
Currently our PL080/PL081 model uses a combination of the CPU's
address space (via cpu_physical_memory_{read,write}()) and the
system address space for performing DMA accesses.

For the PL081s in the MPS FPGA images, their DMA accesses
must go via Master Security Controllers. Switch the
PL080/PL081 model to take a MemoryRegion property which
defines its downstream for making DMA accesses.

Since the PL08x are only used in two board models, we
make provision of the 'downstream' link mandatory and convert
both users at once, rather than having it be optional with
a default to the system address space.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
6d0ed6ba6c hw/dma/pl080: Support all three interrupt lines
The PL080 and PL081 have three outgoing interrupt lines:
 * DMACINTERR signals DMA errors
 * DMACINTTC is the DMA count interrupt
 * DMACINTR is a combined interrupt, the logical OR of the other two

We currently only implement DMACINTR, because that's all the
realview and versatile boards needed, but the instances of the
PL081 in the MPS2 firmware images use all three interrupt lines.
Implement the missing DMACINTERR and DMACINTTC.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
aa74e355f1 hw/dma/pl080: Allow use as embedded-struct device
Create a new include file for the pl081's device struct,
type macros, etc, so that it can be instantiated using
the "embedded struct" coding style.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
514b4f361b nvic: Expose NMI line
On real v7M hardware, the NMI line is an externally visible signal
that an SoC or board can toggle to assert an NMI. Expose it in
our QEMU NVIC and armv7m container objects so that a board model
can wire it up if it needs to.

In particular, the MPS2 watchdog is wired to NMI.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
050c2ea07b hw/watchdog/cmsdk_apb_watchdog: Implement CMSDK APB watchdog module
The Arm Cortex-M System Design Kit includes a simple watchdog module
based on a 32-bit down-counter. Implement this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:33 +01:00
Peter Maydell
62b9cf0a77 hw/timer/m48t59: Move away from old_mmio accessors
Move the m48t59 device away from using old_mmio MemoryRegionOps
accessors.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Message-id: 20180802180602.22047-1-peter.maydell@linaro.org
2018-08-20 11:24:33 +01:00
Peter Maydell
3eff40dbf4 hw/misc: Remove mmio_interface device
The mmio_interface device was a purely internal artifact
of the implementation of the memory subsystem's request_ptr
APIs. Now that we have removed those APIs, we can remove
the mmio_interface device too.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
Message-id: 20180817114619.22354-4-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
8c1c245378 memory: Remove MMIO request_ptr APIs
Remove the obsolete MMIO request_ptr APIs; they have no
users now.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
Message-id: 20180817114619.22354-3-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
5321fa68fd hw/ssi/xilinx_spips: Remove unneeded MMIO request_ptr code
We now support direct execution from MMIO regions in the
core memory subsystem. This means that we don't need to
have device-specific support for it, and we can remove
the request_ptr handling from the Xilinx SPIPS device.
(It was broken anyway due to race conditions, and disabled
by default.)

This device is the only in-tree user of this API.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
Message-id: 20180817114619.22354-2-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Hans-Erik Floryd
6bfd06da6e sdhci: add i.MX SD Stable Clock bit
Add the ESDHC PRSSTAT_SDSTB bit, using the value of SDHC_CLOCK_INT_STABLE.
Freescale recommends checking this bit when changing clock frequency.

Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
Message-id: 1534507843-4251-1-git-send-email-hans-erik.floryd@rt-labs.com
[PMM: fixed indentation]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:32 +01:00
Andrew Jones
22907d2b81 hw/arm/virt: Add virt-3.1 machine type
Signed-off-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:32 +01:00
Peter Maydell
55c544ed27 target/arm: Implement AArch32 ERET instruction
ARMv7VE introduced the ERET instruction, which is necessary to
return from an exception taken to Hyp mode. Implement this.
In A32 encoding it is a completely new encoding; in T32 it
is an adjustment of the behaviour of the existing
"SUBS PC, LR, #<imm8>" instruction.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-10-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
aec4dd09f1 target/arm: Permit accesses to ELR_Hyp from Hyp mode via MSR/MRS (banked)
The MSR (banked) and MRS (banked) instructions allow accesses to ELR_Hyp
from either Monitor or Hyp mode. Our translate time check
was overly strict and only permitted access from Monitor mode.

The runtime check we do in msr_mrs_banked_exc_checks() had the
correct code in it, but never got there because of the earlier
"currmode == tgtmode" check. Special case ELR_Hyp.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-9-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
68e78e332c target/arm: Implement ESR_EL2/HSR for AArch32 and no-EL2
The AArch32 HSR is the equivalent of AArch64 ESR_EL2;
we can implement it by marking our existing ESR_EL2 regdef
as STATE_BOTH. It also needs to be "RES0 from EL3 if
EL2 not implemented", so add the missing stanza to
el3_no_el2_cp_reginfo.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-8-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
cba517c31e target/arm: Implement AArch32 Hyp FARs
The AArch32 virtualization extensions support these fault address
registers:
 * HDFAR: aliased with AArch64 FAR_EL2[31:0] and AArch32 DFAR(S)
 * HIFAR: aliased with AArch64 FAR_EL2[63:32] and AArch32 IFAR(S)

Implement the accessors for these. This fixes in passing a bug
where we weren't implementing the "RES0 from EL3 if EL2 not
implemented" behaviour for AArch64 FAR_EL2.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-7-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
d79e0c0608 target/arm: Implement AArch32 HVBAR
Implement the AArch32 HVBAR register; we can do this just by
making the existing VBAR_EL2 regdefs be STATE_BOTH.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-5-peter.maydell@linaro.org
2018-08-20 11:24:32 +01:00
Peter Maydell
b5ede85bfb target/arm: Add missing .cp = 15 to HMAIR1 and HAMAIR1 regdefs
ARMCPRegInfo structs will default to .cp = 15 if they
are ARM_CP_STATE_BOTH, but not if they are ARM_CP_STATE_AA32
(because a coprocessor number of 0 is valid for AArch32).
We forgot to explicitly set .cp = 15 for the HMAIR1 and
HAMAIR1 regdefs, which meant they would UNDEF when the guest
tried to access them under cp15.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-3-peter.maydell@linaro.org
2018-08-20 11:24:31 +01:00
Peter Maydell
55b53c718b target/arm: Correct typo in HAMAIR1 regdef name
We implement the HAMAIR1 register as RAZ/WI; we had a typo in the
regdef, though, and were incorrectly naming it HMAIR1 (which is
a different register which we also implement as RAZ/WI).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180814124254.5229-2-peter.maydell@linaro.org
2018-08-20 11:24:31 +01:00
Hans-Erik Floryd
3c54cf7705 imx_serial: Generate interrupt on receive data ready if enabled
Generate an interrupt if USR2_RDR and UCR4_DREN are both set.

Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
Message-id: 1534341354-11956-1-git-send-email-hans-erik.floryd@rt-labs.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:31 +01:00
Jia He
84be3ef1de hw/intc/arm_gicv3_its: downgrade error_report to warn_report in kvm_arm_its_reset
In scripts/arch-run.bash of kvm-unit-tests, it will check the qemu
output log with:
if [ -z "$(echo "$errors" | grep -vi warning)" ]; then

Thus without the warning prefix, all of the test fail.

Since it is not unrecoverable error in kvm_arm_its_reset for
current implementation, downgrading the report from error to
warn makes sense.

Signed-off-by: Jia He <jia.he@hxt-semitech.com>
Message-id: 1531969910-32843-1-git-send-email-jia.he@hxt-semitech.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:31 +01:00
Stefan Hajnoczi
67c791f611 docs/generic-loader: mention U-Boot and Intel HEX executable formats
The generic loader device supports the U-Boot and Intel HEX executable
formats in addition to the document raw and ELF formats.  Reword the
documentation to include these formats and explain how various options
depend on the executable format.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20180816145554.9814-1-stefanha@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:31 +01:00
Roman Kapl
c2d9644e6d target/arm: Fix crash on conditional instruction in an IT block
If an instruction is conditional (like CBZ) and it is executed
conditionally (using the ITx instruction), a jump to an undefined
label is generated, and QEMU crashes.

CBZ in IT block is an UNPREDICTABLE behavior, but we should not
crash.  Honouring the condition code is allowed by the spec in this
case (constrained unpredictable, ARMv8, section K1.1.7), and matches
what we do for other "UNPREDICTABLE inside an IT block" instructions.

Fix the 'skip on condition' code to create a new label only if it
does not already exist.  Previously multiple labels were created, but
only the last one of them was set.

Signed-off-by: Roman Kapl <rka@sysgo.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180816120533.6587-1-rka@sysgo.com
[PMM: fixed ^ 1 being applied to wrong argument, fixed typo]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 11:24:31 +01:00
Peter Maydell
627fce6178 tests/boot-serial-test: Bump timeout to 6 minutes
On a SPARC host that I'm using as a build test machine, the
boot-serial-test for the SPARC guest machines takes about 65
seconds to execute. This means that it hits the current
60 second timer on these tests. Push the timeout up so
that it doesn't trigger spuriously on slow hosts like this one.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Message-id: 20180817161404.9420-1-peter.maydell@linaro.org
2018-08-20 10:39:27 +01:00
Peter Maydell
adaec191bf Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging
Machine queue, 2018-08-17

* Allow machine classes to specify if boot device suffixes should
  be ignored by get_boot_devices_list()
* Tiny coding style fixup

# gpg: Signature made Fri 17 Aug 2018 19:29:22 BST
# gpg:                using RSA key 2807936F984DC5A6
# 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:
  fw_cfg: ignore suffixes in the bootdevice list dependent on machine class
  sysbus: always allow explicit_ofw_unit_address() to override address generation
  machine: Fix coding style at machine_run_board_init()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-20 09:48:03 +01:00
Marcel Apfelbaum
21ab34c954 config: split PVRDMA from RDMA
In some BSD systems RDMA migration is possible while
the pvrdma device can't be used because the mremap system call
is missing.

Reported-by: Rebecca Cran <rebecca@bluestop.org>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180816151637.24553-1-marcel.apfelbaum@gmail.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2018-08-18 18:01:34 +03:00
Marcel Apfelbaum
72221d03b8 hw/pvrdma: remove not needed include
No need to include linux/types.h, is empty anyway.

Suggested-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180811171534.11917-1-marcel.apfelbaum@gmail.com>
Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com>
2018-08-18 18:01:27 +03:00
Yuval Shaia
430e440c59 hw/rdma: Add reference to pci_dev in backend_dev
The field backend_dev->dev is not initialized, fix it.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Message-Id: <20180805153518.2983-14-yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:01:20 +03:00
Yuval Shaia
7d2ce4b016 hw/rdma: Bugfix - Support non-aligned buffers
RDMA application can provide non-aligned buffers to be registered. In
such case the DMA address passed by driver is pointing to the beginning
of the physical address of the mapped page so we can't distinguish
between two addresses from the same page.

Fix it by keeping the offset of the virtual address in mr->virt.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-13-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:55 +03:00
Yuval Shaia
abc665aae3 hw/rdma: Print backend QP number in hex format
To be consistent with other prints throughout the code fix places that
print it as decimal number.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-12-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:48 +03:00
Yuval Shaia
292dce627b hw/rdma: Cosmetic change - move to generic function
To ease maintenance of struct comp_thread move all related code to
dedicated function.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-11-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:39 +03:00
Yuval Shaia
67b32fe250 hw/pvrdma: Cosmetic change - indent right
Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-10-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:30 +03:00
Yuval Shaia
7131c4b028 hw/rdma: Reorder resource cleanup
To be consistence with allocation do the reverse order in deallocation

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-9-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:22 +03:00
Yuval Shaia
4c408c9d5b hw/rdma: Do not allocate memory for non-dma MR
There is no use in the memory allocated for non-dma MR.
Delete the code that allocates it.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-8-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:15 +03:00
Yuval Shaia
7f99daadbd hw/rdma: Delete useless structure RdmaRmUserMR
The structure RdmaRmUserMR has no benefits, remove it an move all its
fields to struct RdmaRmMR.

Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Message-Id: <20180805153518.2983-7-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 18:00:06 +03:00
Yuval Shaia
6e7dba23af hw/pvrdma: Make default pkey 0xFFFF
0x7FFF is not the default pkey - fix it.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-6-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 17:59:58 +03:00
Yuval Shaia
eca0f2a6be hw/pvrdma: Clean CQE before use
Next CQE is fetched from CQ ring, clean it before usage as it still
carries old CQE values.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-5-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 17:59:50 +03:00
Yuval Shaia
ef846e026c hw/rdma: Modify debug macros
- Add line counter to ease navigation in log
- Print rdma instead of pvrdma

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-4-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 17:59:42 +03:00
Yuval Shaia
b462a13480 hw/pvrdma: Bugfix - provide the correct attr_mask to query_qp
Calling rdma_rm_query_qp with attr_mask equals to -1 leads to error
where backend query_qp fails to retrieve the needed QP attributes.
Fix it by providing the attr_mask we got from driver.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Message-Id: <20180805153518.2983-3-yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 17:59:33 +03:00
Yuval Shaia
751522275a hw/rdma: Make distinction between device init and start modes
There are certain operations that are well considered as part of device
configuration while others are needed only when "start" command is
triggered by the guest driver. An example of device initialization step
is msix_init and example of "device start" stage is the creation of a CQ
completion handler thread.

Driver expects such distinction - implement it.

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Message-Id: <20180805153518.2983-2-yuval.shaia@oracle.com>
Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
2018-08-18 17:59:23 +03:00
Peter Maydell
a544c9110d Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20180817.0' into staging
VFIO update 2018-08-17

 - Enhance balloon inhibitor for multiple users and use around vfio
   device assignment (Alex Williamson)

# gpg: Signature made Fri 17 Aug 2018 17:43:37 BST
# gpg:                using RSA key 239B9B6E3BB08B22
# gpg: Good signature from "Alex Williamson <alex.williamson@redhat.com>"
# gpg:                 aka "Alex Williamson <alex@shazbot.org>"
# gpg:                 aka "Alex Williamson <alwillia@redhat.com>"
# gpg:                 aka "Alex Williamson <alex.l.williamson@gmail.com>"
# Primary key fingerprint: 42F6 C04E 540B D1A9 9E7B  8A90 239B 9B6E 3BB0 8B22

* remotes/awilliam/tags/vfio-update-20180817.0:
  vfio/ccw/pci: Allow devices to opt-in for ballooning
  vfio: Inhibit ballooning based on group attachment to a container
  kvm: Use inhibit to prevent ballooning without synchronous mmu
  balloon: Allow multiple inhibit users

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-17 18:24:38 +01:00
Alex Williamson
238e917285 vfio/ccw/pci: Allow devices to opt-in for ballooning
If a vfio assigned device makes use of a physical IOMMU, then memory
ballooning is necessarily inhibited due to the page pinning, lack of
page level granularity at the IOMMU, and sufficient notifiers to both
remove the page on balloon inflation and add it back on deflation.
However, not all devices are backed by a physical IOMMU.  In the case
of mediated devices, if a vendor driver is well synchronized with the
guest driver, such that only pages actively used by the guest driver
are pinned by the host mdev vendor driver, then there should be no
overlap between pages available for the balloon driver and pages
actively in use by the device.  Under these conditions, ballooning
should be safe.

vfio-ccw devices are always mediated devices and always operate under
the constraints above.  Therefore we can consider all vfio-ccw devices
as balloon compatible.

The situation is far from straightforward with vfio-pci.  These
devices can be physical devices with physical IOMMU backing or
mediated devices where it is unknown whether a physical IOMMU is in
use or whether the vendor driver is well synchronized to the working
set of the guest driver.  The safest approach is therefore to assume
all vfio-pci devices are incompatible with ballooning, but allow user
opt-in should they have further insight into mediated devices.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2018-08-17 09:27:16 -06:00
Alex Williamson
c65ee43315 vfio: Inhibit ballooning based on group attachment to a container
We use a VFIOContainer to associate an AddressSpace to one or more
VFIOGroups.  The VFIOContainer represents the DMA context for that
AdressSpace for those VFIOGroups and is synchronized to changes in
that AddressSpace via a MemoryListener.  For IOMMU backed devices,
maintaining the DMA context for a VFIOGroup generally involves
pinning a host virtual address in order to create a stable host
physical address and then mapping a translation from the associated
guest physical address to that host physical address into the IOMMU.

While the above maintains the VFIOContainer synchronized to the QEMU
memory API of the VM, memory ballooning occurs outside of that API.
Inflating the memory balloon (ie. cooperatively capturing pages from
the guest for use by the host) simply uses MADV_DONTNEED to "zap"
pages from QEMU's host virtual address space.  The page pinning and
IOMMU mapping above remains in place, negating the host's ability to
reuse the page, but the host virtual to host physical mapping of the
page is invalidated outside of QEMU's memory API.

When the balloon is later deflated, attempting to cooperatively
return pages to the guest, the page is simply freed by the guest
balloon driver, allowing it to be used in the guest and incurring a
page fault when that occurs.  The page fault maps a new host physical
page backing the existing host virtual address, meanwhile the
VFIOContainer still maintains the translation to the original host
physical address.  At this point the guest vCPU and any assigned
devices will map different host physical addresses to the same guest
physical address.  Badness.

The IOMMU typically does not have page level granularity with which
it can track this mapping without also incurring inefficiencies in
using page size mappings throughout.  MMU notifiers in the host
kernel also provide indicators for invalidating the mapping on
balloon inflation, not for updating the mapping when the balloon is
deflated.  For these reasons we assume a default behavior that the
mapping of each VFIOGroup into the VFIOContainer is incompatible
with memory ballooning and increment the balloon inhibitor to match
the attached VFIOGroups.

Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2018-08-17 09:27:16 -06:00
Alex Williamson
f59489423a kvm: Use inhibit to prevent ballooning without synchronous mmu
Remove KVM specific tests in balloon_page(), instead marking
ballooning as inhibited without KVM_CAP_SYNC_MMU support.

Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2018-08-17 09:27:15 -06:00
Alex Williamson
01ccbec7bd balloon: Allow multiple inhibit users
A simple true/false internal state does not allow multiple users.  Fix
this within the existing interface by converting to a counter, so long
as the counter is elevated, ballooning is inhibited.

Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2018-08-17 09:27:15 -06:00
Peter Maydell
0abaa41d93 Merge remote-tracking branch 'remotes/ehabkost/tags/x86-next-pull-request' into staging
x86 queue, 2018-08-16

Bug fix:
* Some guests may crash when using "-cpu host" due to TOPOEXT,
  disable it by default

Features:
* PV_SEND_IPI feature bit
* Icelake-{Server,Client} CPU models
* New CPUID feature bits: PV_SEND_IPI, WBNOINVD, PCONFIG, ARCH_CAPABILITIES

Documentation:
* docs/qemu-cpu-models.texi

# gpg: Signature made Fri 17 Aug 2018 02:33:09 BST
# gpg:                using RSA key 2807936F984DC5A6
# 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/x86-next-pull-request:
  i386: Disable TOPOEXT by default on "-cpu host"
  target-i386: adds PV_SEND_IPI CPUID feature bit
  i386: Add new CPU model Icelake-{Server,Client}
  i386: Add CPUID bit for WBNOINVD
  i386: Add CPUID bit for PCONFIG
  i386: Add CPUID bit and feature words for IA32_ARCH_CAPABILITIES MSR
  i386: Add new MSR indices for IA32_PRED_CMD and IA32_ARCH_CAPABILITIES
  docs: add guidance on configuring CPU models for x86

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-17 09:46:00 +01:00
Mark Cave-Ayland
907aac2f6a fw_cfg: ignore suffixes in the bootdevice list dependent on machine class
For the older machines (such as Mac and SPARC) the DT nodes representing
bootdevices for disk nodes are irregular for mainly historical reasons.

Since the majority of bootdevice nodes for these machines either do not have a
separate disk node or require different (custom) names then it is much easier
for processing to just disable all suffixes for a particular machine.

Introduce a new ignore_boot_device_suffixes MachineClass property to control
bootdevice suffix generation, defaulting to false in order to preserve
compatibility.

Suggested-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Message-Id: <20180810124027.10698-1-mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 22:27:43 -03:00
Mark Cave-Ayland
be64d7776b sysbus: always allow explicit_ofw_unit_address() to override address generation
Some SysBusDevices either use sysbus_init_mmio() without
sysbus_mmio_map() or the first MMIO memory region doesn't represent the
bus address, causing a firmware device path with an invalid address to
be generated.

SysBusDeviceClass does provide a virtual explicit_ofw_unit_address()
method that can be used to override this process, but it was originally intended
only as as a fallback option meaning that any existing MMIO memory regions still
take priority whilst determining the firmware device address.

There is currently only one user of explicit_ofw_unit_address() and that
is the PCI expander bridge (PXB) device which has no MMIO/PIO resources
defined. This enables us to allow explicit_ofw_unit_address() to take
priority without affecting backwards compatibility, allowing the address
to be customised as required.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20180805112850.26063-2-mark.cave-ayland@ilande.co.uk>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 22:27:43 -03:00
Dou Liyang
3aeaac8fa2 machine: Fix coding style at machine_run_board_init()
Commit 7747abf114 ("hw/machine: Remove the Zero check of
nb_numa_nodes for numa_complete_configuration()") removed the
curly brackets.  Re-add them.

Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com>
Message-Id: <20180710105129.23296-1-douly.fnst@cn.fujitsu.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
[ehabkost: rewrote commit message]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 22:27:43 -03:00
Peter Maydell
b8f7ff1e10 Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-aug-2018' into staging
MIPS queue Aug 16, 2018

# gpg: Signature made Thu 16 Aug 2018 18:19:36 BST
# gpg:                using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>"
# 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: 8526 FBF1 5DA3 811F 4A01  DD75 D497 2A89 67F7 5A65

* remotes/amarkovic/tags/mips-queue-aug-2018:
  qemu-doc: Amend MIPS-related items
  linux-user: Add preprocessor availability control to some syscalls
  linux-user: Update MIPS syscall numbers up to kernel 4.18 headers
  elf: Add ELF flags for MIPS machine variants
  elf: Remove duplicate preprocessor constant definition
  target/mips: Check ELPA flag only in some cases of MFHC0 and MTHC0
  target/mips: Don't update BadVAddr register in Debug Mode
  target/mips: Implement CP0 Config1.WR bit functionality
  target/mips: Add CP0 BadInstrX register
  target/mips: Update some CP0 registers bit definitions
  target/mips: Fix two instances of shadow variables
  target/mips: Mark switch fallthroughs with interpretable comments
  target/mips: Avoid case statements formulated by ranges - part 2
  target/mips: Avoid case statements formulated by ranges - part 1
  MAINTAINERS: Update target/mips maintainer's email addresses

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 19:02:21 +01:00
Aleksandar Markovic
8639c5c954 qemu-doc: Amend MIPS-related items
Amend MIPS-related items in qemu-doc.texi

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Rikalo
4f7f892420 linux-user: Add preprocessor availability control to some syscalls
Add ability to target platforms to individually include user-mode
support for system calls from "stat" group of system calls.

This change is related to new nanoMIPS platform in the sense that
it supports a different set of "stat" system calls than any other
target. nanoMIPS does not support structures stat and stat64 at
all. Also, support for certain number of other system calls is
dropped in nanoMIPS (those are most of the time obsoleted system
calls).

Without this patch, build for nanoMIPS would fail.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
977324ac8c linux-user: Update MIPS syscall numbers up to kernel 4.18 headers
Synchronize content of linux-user/mips/syscall_nr.h and
linux-user/mips64/syscall_nr.h with Linux kernel 4.18 headers.
This adds 9 new syscall numbers, the last being NR_io_pgetevents.

Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
c20eafa197 elf: Add ELF flags for MIPS machine variants
Add MIPS machine variants ELF flags so that the emulation behavior
can be adjusted if needed.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
c19fd07ee5 elf: Remove duplicate preprocessor constant definition
Remove duplicate preprocessor constant definition for EF_MIPS_ARCH.

The duplicate was introduced in commit 45506bdd. It placed the
constant EF_MIPS_ARCH in a better place, however it did not remove
the original. This patch removes the original occurrence.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Yongbok Kim
59488dda1f target/mips: Check ELPA flag only in some cases of MFHC0 and MTHC0
MFHC0 and MTHC0 used to handle EntryLo0 and EntryLo1 registers only,
and placing ELPA flag checks before switch statement were technically
correct. However, after adding handling more registers, these checks
should be moved to act only in cases of handling EntryLo0 and
EntryLo1.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Yongbok Kim
e807bcc151 target/mips: Don't update BadVAddr register in Debug Mode
BadVAddr should not be updated if (env->hflags & MIPS_HFLAG_DM) is
set.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Stefan Markovic
fa192d4974 target/mips: Implement CP0 Config1.WR bit functionality
Add testing Config1.WR bit into watch exception handling logic.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Stefan Markovic
25beba9bf7 target/mips: Add CP0 BadInstrX register
Add CP0 BadInstrX register. This register will be used in nanoMIPS.

Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
0413d7a55a target/mips: Update some CP0 registers bit definitions
Update CP0 registers Config0, Config1, Config2, Config3,
Config4, and Config5 bit definitions.

Some of these bits will be utilized by upcoming nanoMIPS changes.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
e1555d7ddf target/mips: Fix two instances of shadow variables
Fix two instances of shadow variables. This cleans up entire file
translate.c from shadow variables.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
146dd620db target/mips: Mark switch fallthroughs with interpretable comments
Mark switch fallthroughs with comments, in cases fallthroughs
are intentional.

The comments "/* fall through */" are interpreted by compilers and
other tools, and they will not issue warnings in such cases. For gcc,
the warning is turnend on by -Wimplicit-fallthrough. With this patch,
there will be no such warnings in target/mips directory. If such
warning appears in future, it should be checked if it is intentional,
and, if yes, marked with a comment similar to those from this patch.

The comment must be just before next "case", otherwise gcc won't
understand it.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Rikalo
c38a1d5223 target/mips: Avoid case statements formulated by ranges - part 2
Remove "range style" case statements to make code analysis easier.
This patch handles cases when the values in the range in question
were not properly defined.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
c2e19f3c2b target/mips: Avoid case statements formulated by ranges - part 1
Remove "range style" case statements to make code analysis easier.

This is needed also for some upcoming nanoMIPS-related refactorings.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Aleksandar Markovic
4872fee23d MAINTAINERS: Update target/mips maintainer's email addresses
Update email addresses of Aleksandar Markovic and Paul Burton in the
MAINTAINERS file. Also, add corresponding items in the .mailmap file.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
2018-08-16 19:18:45 +02:00
Eduardo Habkost
7210a02c58 i386: Disable TOPOEXT by default on "-cpu host"
Enabling TOPOEXT is always allowed, but it can't be enabled
blindly by "-cpu host" because it may make guests crash if the
rest of the cache topology information isn't provided or isn't
consistent.

This addresses the bug reported at:
https://bugzilla.redhat.com/show_bug.cgi?id=1613277

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20180809221852.15285-1-ehabkost@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Reviewed-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Wanpeng Li
7f710c32bb target-i386: adds PV_SEND_IPI CPUID feature bit
Adds PV_SEND_IPI CPUID feature bit.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
Message-Id: <1530526971-1812-1-git-send-email-wanpengli@tencent.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Robert Hoo
8a11c62da9 i386: Add new CPU model Icelake-{Server,Client}
New CPU models mostly inherit features from ancestor Skylake, while addin new
features: UMIP, New Instructions ( PCONIFIG (server only), WBNOINVD,
AVX512_VBMI2, GFNI, AVX512_VNNI, VPCLMULQDQ, VAES, AVX512_BITALG),
Intel PT and 5-level paging (Server only). As well as
IA32_PRED_CMD, SSBD support for speculative execution
side channel mitigations.

Note:
For 5-level paging, Guest physical address width can be configured, with
parameter "phys-bits". Unless explicitly specified, we still use its default
value, even for Icelake-Server cpu model.
At present, hold on expose IA32_ARCH_CAPABILITIES to guest, as 1) This MSR
actually presents more than 1 'feature', maintainers are considering expanding current
features presentation of only CPUIDs to MSR bits; 2) a reasonable default value
for MSR_IA32_ARCH_CAPABILITIES needs to settled first. These 2 are actully
beyond Icelake CPU model itself but fundamental. So split these work apart
and do it later.
https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg00774.html
https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg00796.html

Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
Message-Id: <1530781798-183214-6-git-send-email-robert.hu@linux.intel.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Robert Hoo
59a80a19ca i386: Add CPUID bit for WBNOINVD
WBNOINVD: Write back and do not invalidate cache, enumerated by
CPUID.(EAX=80000008H, ECX=0):EBX[bit 9].

Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
Message-Id: <1530781798-183214-5-git-send-email-robert.hu@linux.intel.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Robert Hoo
5131dc433d i386: Add CPUID bit for PCONFIG
PCONFIG: Platform configuration, enumerated by CPUID.(EAX=07H, ECX=0):
EDX[bit18].

Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
Message-Id: <1530781798-183214-4-git-send-email-robert.hu@linux.intel.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Robert Hoo
3fc7c73139 i386: Add CPUID bit and feature words for IA32_ARCH_CAPABILITIES MSR
Support of IA32_PRED_CMD MSR already be enumerated by same CPUID bit as
SPEC_CTRL.

At present, mark CPUID_7_0_EDX_ARCH_CAPABILITIES unmigratable, per Paolo's
comment.

Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
Message-Id: <1530781798-183214-3-git-send-email-robert.hu@linux.intel.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Robert Hoo
8c80c99fcc i386: Add new MSR indices for IA32_PRED_CMD and IA32_ARCH_CAPABILITIES
IA32_PRED_CMD MSR gives software a way to issue commands that affect the state
of indirect branch predictors. Enumerated by CPUID.(EAX=7H,ECX=0):EDX[26].
IA32_ARCH_CAPABILITIES MSR enumerates architectural features of RDCL_NO and
IBRS_ALL. Enumerated by CPUID.(EAX=07H, ECX=0):EDX[29].

https://software.intel.com/sites/default/files/managed/c5/63/336996-Speculative-Execution-Side-Channel-Mitigations.pdf

Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
Message-Id: <1530781798-183214-2-git-send-email-robert.hu@linux.intel.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Daniel P. Berrangé
2544e9e4aa docs: add guidance on configuring CPU models for x86
With the recent set of CPU hardware vulnerabilities on x86, it is
increasingly difficult to understand which CPU configurations are
good to use and what flaws they might be vulnerable to.

This doc attempts to help management applications and administrators in
picking sensible CPU configuration on x86 hosts. It outlines which of
the named CPU models are good choices, and describes which extra CPU
flags should be enabled to allow the guest to mitigate hardware flaws.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20180627160103.13634-1-berrange@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2018-08-16 13:43:01 -03:00
Peter Maydell
bb16c0412a Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180816' into staging
target-arm queue:
 * Fixes for various bugs in SVE instructions
 * Add model of Freescale i.MX6 UltraLite 14x14 EVK Board
 * hw/arm: make bitbanded IO optional on ARMv7-M
 * Add model of Cortex-M0 CPU
 * Add support for loading Intel HEX files to the generic loader
 * imx_spi: Unset XCH when TX FIFO becomes empty
 * aspeed_sdmc: fix various bugs
 * Fix bugs in Arm FP16 instruction support
 * Fix aa64 FCADD and FCMLA decode
 * softfloat: Fix missing inexact for floating-point add
 * hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj()

# gpg: Signature made Thu 16 Aug 2018 14:33:41 BST
# gpg:                using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180816: (30 commits)
  hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj()
  softfloat: Fix missing inexact for floating-point add
  target/arm: Fix aa64 FCADD and FCMLA decode
  target/arm: Use FZ not FZ16 for SVE FCVT single-half and double-half
  target/arm: Use fp_status_fp16 for do_fmpa_zpzzz_h
  target/arm: Ignore float_flag_input_denormal from fp_status_f16
  target/arm: Adjust FPCR_MASK for FZ16
  aspeed: add a max_ram_size property to the memory controller
  aspeed_sdmc: Handle ECC training
  aspeed_sdmc: Init status always idle
  aspeed_sdmc: Set 'cache initial sequence' always true
  aspeed_sdmc: Fix saved values
  aspeed_sdmc: Extend number of valid registers
  imx_spi: Unset XCH when TX FIFO becomes empty
  Add QTest testcase for the Intel Hexadecimal
  loader: Implement .hex file loader
  loader: add rom transaction API
  loader: extract rom_free() function
  target/arm: add "cortex-m0" CPU model
  hw/arm: make bitbanded IO optional on ARMv7-M
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:35:50 +01:00
Thomas Huth
fcf13ca556 hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj()
Now that we've got the common sysbus_init_child_obj() function, we do
not need the local init_sysbus_child() anymore.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-id: 1534420566-15799-1-git-send-email-thuth@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Richard Henderson
64d450a0ea softfloat: Fix missing inexact for floating-point add
For 0x1.0000000000003p+0 + 0x1.ffffffep+14 = 0x1.0001fffp+15
we dropped the sticky bit and so failed to raise inexact.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180810193129.1556-7-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Richard Henderson
b8a4a96db3 target/arm: Fix aa64 FCADD and FCMLA decode
These insns require u=1; failed to include that in the switch
cases.  This probably happened during one of the rebases just
before final commit.

Fixes: d17b7cdcf4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180810193129.1556-6-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Richard Henderson
e4ab5124a5 target/arm: Use FZ not FZ16 for SVE FCVT single-half and double-half
We were using the wrong flush-to-zero bit for the non-half input.

Fixes: 46d33d1e3c
Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180810193129.1556-5-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Richard Henderson
52a339b11d target/arm: Use fp_status_fp16 for do_fmpa_zpzzz_h
This makes float16_muladd correctly use FZ16 not FZ.

Fixes: 6ceabaad11
Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180810193129.1556-4-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Richard Henderson
19062c169e target/arm: Ignore float_flag_input_denormal from fp_status_f16
When FZ is set, input_denormal exceptions are recognized, but this does
not happen with FZ16.  The softfloat code has no way to distinguish
these bits and will raise such exceptions into fp_status_f16.flags,
so ignore them when computing the accumulated flags.

Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180810193129.1556-3-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Richard Henderson
0b62159be3 target/arm: Adjust FPCR_MASK for FZ16
When support for FZ16 was added, we failed to include the bit
within FPCR_MASK, which means that it could never be set.
Continue to zero FZ16 when ARMv8.2-FP16 is not enabled.

Fixes: d81ce0ef2c
Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180810193129.1556-2-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Cédric Le Goater
ebe31c0a8e aspeed: add a max_ram_size property to the memory controller
This will be used to construct a memory region beyond the RAM region
to let firmwares scan the address space with load/store to guess how
much RAM the SoC has.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180807075757.7242-7-joel@jms.id.au
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Joel Stanley
a7b4569a4d aspeed_sdmc: Handle ECC training
This is required to ensure u-boot SDRAM training completes.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180807075757.7242-6-joel@jms.id.au
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Joel Stanley
33883ce840 aspeed_sdmc: Init status always idle
The ast2500 SDRAM training routine busy waits on the 'init cycle busy
state' bit in DDR PHY Control/Status register #1 (MCR60).

This ensures the bit always reads zero, and allows training to
complete with upstream u-boot on the ast2500-evb.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180807075757.7242-5-joel@jms.id.au
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Joel Stanley
b33f1e0b89 aspeed_sdmc: Set 'cache initial sequence' always true
The SDRAM training routine sets the 'Enable cache initial' bit, and then
waits for the 'cache initial sequence' to be done.

Have it always return done, as there is no other side effects that the
model needs to implement. This allows the upstream u-boot training to
proceed on the ast2500-evb board.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180807075757.7242-4-joel@jms.id.au
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Joel Stanley
d131bc28a6 aspeed_sdmc: Fix saved values
This fixes the intended protection of read-only values in the
configuration register. They were being always set to zero by mistake.

The read-only fields depend on the configured memory size of the system,
so they cannot be fixed at compile time. The most straight forward
option was to store them in the state structure.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180807075757.7242-3-joel@jms.id.au
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Joel Stanley
a40085d2ee aspeed_sdmc: Extend number of valid registers
The SDMC on the ast2500 has 170 registers.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180807075757.7242-2-joel@jms.id.au
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:58 +01:00
Trent Piepho
016d4b0127 imx_spi: Unset XCH when TX FIFO becomes empty
The current emulation will clear the XCH bit when a burst finishes.
This is not quite correct.  According to the i.MX7d referemce manual,
Rev 0.1, §10.1.7.3:

    This bit [XCH] is cleared automatically when all data in the TXFIFO
    and the shift register has been shifted out.

So XCH should be cleared when the FIFO empties, not on completion of a
burst.  The FIFO is 64 x 32 bits = 2048 bits, while the max burst size
is larger at 4096 bits.  So it's possible that the burst is not finished
after the TXFIFO empties.

Sending a large block (> 2048 bits) with the Linux driver will use a
burst that is larger than the TXFIFO.  After the TXFIFO has emptied XCH
does not become unset, as the burst is not yet finished.

What should happen after the TXFIFO empties is the driver will refill it
and set XCH.  The rising edge of XCH will trigger another transfer to
begin.  However, since the emulation does not set XCH to 0, there is no
rising edge and the next trasfer never begins.

Signed-off-by: Trent Piepho <tpiepho@impinj.com>
Message-id: 20180731201056.29257-1-tpiepho@impinj.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:29:57 +01:00
Su Hang
645d3cbebb Add QTest testcase for the Intel Hexadecimal
'test.hex' file is a memory test pattern stored in Hexadecimal Object
Format.  It loads at 0x10000 in RAM and contains values from 0 through
255.

The test case verifies that the expected memory test pattern was loaded.

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Suggested-by: Steffen Gortz <qemu.ml@steffen-goertz.de>
Suggested-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Su Hang <suhang16@mails.ucas.ac.cn>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
[PMM: changed qtest_startf() to qtest_initf() to work with
 current master after the refactoring in commit 88b988c895]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Su Hang
e4a25ed919 loader: Implement .hex file loader
This patch adds Intel Hexadecimal Object File format support to the
generic loader device.  The file format specification is available here:
http://www.piclist.com/techref/fileext/hex/intel.htm

This file format is often used with microcontrollers such as the
micro:bit, Arduino, STM32, etc.  Users expect to be able to run .hex
files directly with without first converting them to ELF.  Most
micro:bit code is developed in web-based IDEs without direct user access
to binutils so it is important for QEMU to handle this file format
natively.

Signed-off-by: Su Hang <suhang16@mails.ucas.ac.cn>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20180814162739.11814-6-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Stefan Hajnoczi
e2336043cc loader: add rom transaction API
Image file loaders may add a series of roms.  If an error occurs partway
through loading there is no easy way to drop previously added roms.

This patch adds a transaction mechanism that works like this:

  rom_transaction_begin();
  ...call rom_add_*()...
  rom_transaction_end(ok);

If ok is false then roms added in this transaction are dropped.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20180814162739.11814-5-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Stefan Hajnoczi
e7f5993354 loader: extract rom_free() function
The next patch will need to free a rom.  There is already code to do
this in rom_add_file().

Note that rom_add_file() uses:

  rom = g_malloc0(sizeof(*rom));
  ...
  if (rom->fw_dir) {
      g_free(rom->fw_dir);
      g_free(rom->fw_file);
  }

The conditional is unnecessary since g_free(NULL) is a no-op.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180814162739.11814-4-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Stefan Hajnoczi
191776b96a target/arm: add "cortex-m0" CPU model
Define a "cortex-m0" ARMv6-M CPU model.

Most of the register reset values set by other CPU models are not
relevant for the cut-down ARMv6-M architecture.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180814162739.11814-3-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Stefan Hajnoczi
a1c5a06224 hw/arm: make bitbanded IO optional on ARMv7-M
Some ARM CPUs have bitbanded IO, a memory region that allows convenient
bit access via 32-bit memory loads/stores.  This eliminates the need for
read-modify-update instruction sequences.

This patch makes this optional feature an ARMv7MState qdev property,
allowing boards to choose whether they want bitbanding or not.

Status of boards:
 * iotkit (Cortex M33), no bitband
 * mps2 (Cortex M3), bitband
 * msf2 (Cortex M3), bitband
 * stellaris (Cortex M3), bitband
 * stm32f205 (Cortex M3), bitband

As a side-effect of this patch, Peter Maydell noted that the Ethernet
controller on mps2 board is now accessible.  Previously they were hidden
by the bitband region (which does not exist on the real board).

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180814162739.11814-2-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Jean-Christophe Dubois
0550e3bf7f i.MX6UL: Add Freescale i.MX6 UltraLite 14x14 EVK Board
Tested by booting linux 4.18 (built using imx_v6_v7_defconfig) on the
emulated board.

Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 3f8eb4300206634dc01e04b12f65b73c0ad2f955.1532984236.git.jcd@tribudubois.net
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Jean-Christophe Dubois
31cbf933f0 i.MX6UL: Add i.MX6UL SOC
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 3853ec555d68e7e25d726170833b775796151a07.1532984236.git.jcd@tribudubois.net
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Jean-Christophe Dubois
781182e10f i.MX6UL: Add i.MX6UL specific CCM device
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 34b6704ceb81b49e35ce1ad162bf758e5141ff87.1532984236.git.jcd@tribudubois.net
[PMM: fixed some comment typos etc]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Richard Henderson
adf92eab90 target/arm: Add sve-max-vq cpu property to -cpu max
This allows the default (and maximum) vector length to be set
from the command-line.  Which is extraordinarily helpful in
debugging problems depending on vector length without having to
bake knowledge of PR_SET_SVE_VL into every guest binary.

Cc: qemu-stable@nongnu.org (3.0.1)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Richard Henderson
2bf5f3f91b target/arm: Dump SVE state if enabled
Also fold the FPCR/FPSR state onto the same line as PSTATE,
and mention but do not dump disabled FPU state.

Cc: qemu-stable@nongnu.org (3.0.1)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Richard Henderson
3cb506a399 target/arm: Reformat integer register dump
With PC, there are 33 registers.  Three per line lines up nicely
without overflowing 80 columns.

Cc: qemu-stable@nongnu.org (3.0.1)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:28 +01:00
Richard Henderson
50ef1cbf31 target/arm: Fix offset scaling for LD_zprr and ST_zprr
The scaling should be solely on the memory operation size; the number
of registers being loaded does not come in to the initial computation.

Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:27 +01:00
Richard Henderson
d0e372b029 target/arm: Fix offset for LD1R instructions
The immediate should be scaled by the size of the memory reference,
not the size of the elements into which it is loaded.

Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:27 +01:00
Richard Henderson
19f2acc915 target/arm: Fix sign-extension in sve do_ldr/do_str
The expression (int) imm + (uint32_t) len_align turns into uint32_t
and thus with negative imm produces a memory operation at the wrong
offset.  None of the numbers involved are particularly large, so
change everything to use int.

Cc: qemu-stable@nongnu.org (3.0.1)
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:27 +01:00
Richard Henderson
573ec0fe40 target/arm: Fix typo in helper_sve_ld1hss_r
Cc: qemu-stable@nongnu.org (3.0.1)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 14:05:27 +01:00
Peter Maydell
c542a9f979 Merge remote-tracking branch 'remotes/armbru/tags/pull-tests-2018-08-16' into staging
Testing patches for 2018-08-16

# gpg: Signature made Thu 16 Aug 2018 09:34:43 BST
# gpg:                using RSA key 3870B400EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-tests-2018-08-16: (25 commits)
  libqtest: Improve error reporting for bad read from QEMU
  tests/libqtest: Improve kill_qemu()
  libqtest: Rename qtest_FOOv() to qtest_vFOO() for consistency
  libqtest: Replace qtest_startf() by qtest_initf()
  libqtest: Enable compile-time format string checking
  migration-test: Clean up string interpolation into QMP, part 3
  migration-test: Clean up string interpolation into QMP, part 2
  migration-test: Clean up string interpolation into QMP, part 1
  migration-test: Make wait_command() cope with '%'
  tests: New helper qtest_qmp_receive_success()
  migration-test: Make wait_command() return the "return" member
  tests: Clean up string interpolation around qtest_qmp_device_add()
  cpu-plug-test: Don't pass integers as strings to device_add
  tests: Clean up string interpolation into QMP input (simple cases)
  tests: Pass literal format strings directly to qmp_FOO()
  qobject: qobject_from_jsonv() is dangerous, hide it away
  test-qobject-input-visitor: Avoid format string ambiguity
  libqtest: Simplify qmp_fd_vsend() a bit
  qobject: New qobject_from_vjsonf_nofail(), qdict_from_vjsonf_nofail()
  qobject: Replace qobject_from_jsonf() by qobject_from_jsonf_nofail()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-16 09:50:54 +01:00
Markus Armbruster
f9e986d237 libqtest: Improve error reporting for bad read from QEMU
When read() from the qtest socket or the QMP socket fails or EOFs, we
report "Broken pipe" and exit(1).  This commonly happens when QEMU
crashes.  It also happens when QEMU refuses to run because the test
passed it bad arguments.  Sadly, we neglect to report either.

Improve this by calling abort() instead of exit(1), so kill_qemu()
runs, and reports how QEMU died.  This improves error reporting to
something like

    /x86_64/device/introspect/list: Broken pipe
    tests/libqtest.c:129: kill_qemu() detected QEMU death from signal 6 (Aborted) (dumped core)

Three exit() remain in libqtest.c:

* In qmp_response(), when we can't parse a QMP reply read from the QMP
  socket.  Change to abort() for consistency.

* In qtest_qemu_binary(), when QTEST_QEMU_BINARY isn't in the
  environment.  This can only happen before we start QEMU.  Leave
  alone.

* In qtest_init_without_qmp_handshake(), when the fork()ed child fails
  to execlp().  Leave alone.

exit() elsewhere are unlikely due to QEMU dying on us.  If that should
turn out to be wrong, we can move kill_qemu() from @abrt_hooks to
atexit() or something.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180815141945.10457-2-armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
[Commit message tweaked slightly]
2018-08-16 08:43:53 +02:00
Eric Blake
71a268a5fd tests/libqtest: Improve kill_qemu()
In kill_qemu() we have an assert that checks that the QEMU process
didn't dump core:
            assert(!WCOREDUMP(wstatus));

Unfortunately the WCOREDUMP macro here means the resulting message
is not very easy to comprehend on at least some systems:

ahci-test: tests/libqtest.c:113: kill_qemu: Assertion `!(((__extension__ (((union { __typeof(wstatus) __in; int __i; }) { .__in = (wstatus) }).__i))) & 0x80)' failed.

and it doesn't identify what signal the process took. What's more,
WCOREDUMP is not reliable - in some cases, setrlimit() coupled with
kernel dump settings can result in the flag not being set.  It's
better to log ALL death by signal, instead of caring whether a core
dump was attempted (although once we know a signal happened, also
mentioning if a core dump is present can be helpful).

Furthermore, we are NOT detecting EINTR (while EINTR shouldn't be
happening if we didn't install signal handlers, it's still better
to always be robust).

Finally, even non-signal death with a non-zero status is suspicious,
since qemu's SIGINT handler is supposed to result in exit(0).

Instead of using a raw assert, print the information in an
easier to understand way:

/i386/ahci/sanity: tests/libqtest.c:129: kill_qemu() detected QEMU death from signal 11 (Segmentation fault) (core dumped)

(Of course, the really useful information would be why the QEMU
process dumped core in the first place, but we don't have that
by the time the test program has picked up the exit status.)

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180810132800.38549-1-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Core dump reporting and commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2018-08-16 08:42:10 +02:00
Markus Armbruster
248eef02c5 libqtest: Rename qtest_FOOv() to qtest_vFOO() for consistency
13 of 13 C99 library function pairs taking ... or a va_list parameter
are called FOO() and vFOO().  In QEMU, we sometimes call the one
taking a va_list FOOv() instead.  Bad taste.  libqtest.h uses both
spellings.  Normalize it to the standard spelling.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-24-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
88b988c895 libqtest: Replace qtest_startf() by qtest_initf()
qtest_init() creates a new QTestState, and leaves @global_qtest alone.
qtest_start() additionally assigns it to @global_qtest, but
qtest_startf() additionally assigns NULL to @global_qtest.  This makes
no sense.  Replace it by qtest_initf() that works like qtest_init(),
i.e. leaves @global_qtest alone.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-23-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
e3dc93be1a libqtest: Enable compile-time format string checking
qtest_qmp() & friends pass their format string and variable arguments
to qobject_from_vjsonf_nofail().  Unlike qobject_from_jsonv(), they
aren't decorated with GCC_FMT_ATTR().  Fix that to get compile-time
format string checking.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-22-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
c44a56d8ba migration-test: Clean up string interpolation into QMP, part 3
Leaving interpolation into JSON to qmp() is more robust than building
QMP input manually, as explained in the recent commit "tests: Clean up
string interpolation into QMP input (simple cases)".

migration-test.c interpolates strings into JSON in a few places:

* migrate_set_parameter() interpolates string parameter @value as a
  JSON number.  Change it to long long.  This requires changing
  migrate_check_parameter() similarly.

* migrate_set_capability() interpolates string parameter @value as a
  JSON boolean.  Change it to bool.

* deprecated_set_speed() interpolates string parameter @value as a
  JSON number.  Change it to long long.

Bonus: gets rid of non-literal format strings.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-21-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
b5bbd3f315 migration-test: Clean up string interpolation into QMP, part 2
Leaving interpolation into JSON to qmp() is more robust than building
QMP input manually, as explained in the recent commit "tests: Clean up
string interpolation into QMP input (simple cases)".

migrate() interpolates members into a JSON object.  Change it to take
its extra QMP arguments as arguments for qdict_from_jsonf_nofail()
instead of a string containing JSON members.

Bonus: gets rid of a non-literal format string.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-20-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
b7281c6989 migration-test: Clean up string interpolation into QMP, part 1
Leaving interpolation into JSON to qmp() is more robust than building
QMP input manually, as explained in the recent commit "tests: Clean up
string interpolation into QMP input (simple cases)".

migrate_recover() builds QMP input manually because wait_command()
can't interpolate.  Well, it can since the previous commit.  Simplify
accordingly.

Bonus: gets rid of a non-literal format string.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-19-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
4399596b15 migration-test: Make wait_command() cope with '%'
wait_command() passes its argument @command to qtest_qmp_send().
Falls apart if @command contain '%'.  Two ways to disarm this trap:
suppress interpretation of '%' by passing @command as argument to
format string "%s", or fix it by having wait_command() take the
variable arguments to go with @command.  Do the latter.

This is another step towards compile-time format string checking
without triggering -Wformat-nonliteral.

Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-18-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
3cd46d42fe tests: New helper qtest_qmp_receive_success()
Commit b21373d071 copied wait_command() from tests/migration-test.c
to tests/tpm-util.c.  Replace both copies by new libqtest helper
qtest_qmp_receive_success().  Also use it to simplify
qtest_qmp_device_del().

Bonus: gets rid of a non-literal format string.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Cc: Thomas Huth <thuth@redhat.com>
Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Stefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-17-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
e145416524 migration-test: Make wait_command() return the "return" member
All callers of wait_command() are only interested in the success
response's "return" member.  Lift its extraction into wait_command().

Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-16-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
82cab70bd8 tests: Clean up string interpolation around qtest_qmp_device_add()
Leaving interpolation into JSON to qmp() is more robust than building
QMP input manually, as explained in the commit before previous.

qtest_qmp_device_add() and its wrappers interpolate into JSON as
follows:

* qtest_qmp_device_add() interpolates members into a JSON object.

* So do its wrappers qpci_plug_device_test() and usb_test_hotplug().

* usb_test_hotplug() additionally interpolates strings and numbers
  into JSON strings.

Clean them up:

* Have qtest_qmp_device_add() take its extra device properties as
  arguments for qdict_from_jsonf_nofail() instead of a string
  containing JSON members.

* Drop qpci_plug_device_test(), use qtest_qmp_device_add()
  directly.

* Change usb_test_hotplug() parameter @port to string, to avoid
  interpolation.  Interpolate @hcd_id separately.

Bonus: gets rid of a non-literal format string.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Cc: Thomas Huth <thuth@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-15-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
530e79a822 cpu-plug-test: Don't pass integers as strings to device_add
test_plug_with_device_add_x86() plugs Haswell-i386-cpu and
Haswell-x86_64-cpu with device_add.  It passes socket-id, core-id,
thread-id as JSON strings.  The properties are actually integers.

test_plug_with_device_add_coreid() plugs power8_v2.0-spapr-cpu-core
and qemu-s390x-cpu with device_add.  It passes core-id as JSON string.
The properties are actually integers.

Passing JSON string values to integer properties works only due to
device_add implementation accidents.  Fix the test to pass JSON
numbers.  While there, use %u rather than %i with unsigned int.

Cc: Thomas Huth <thuth@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-14-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
015715f554 tests: Clean up string interpolation into QMP input (simple cases)
When you build QMP input manually like this

    cmd = g_strdup_printf("{ 'execute': 'migrate',"
                          "'arguments': { 'uri': '%s' } }",
                          uri);
    rsp = qmp(cmd);
    g_free(cmd);

you're responsible for escaping the interpolated values for JSON.  Not
done here, and therefore works only for sufficiently nice @uri.  For
instance, if @uri contained a single "'", qobject_from_vjsonf_nofail()
would abort.  A sufficiently nasty @uri could even inject unwanted
members into the arguments object.

Leaving interpolation into JSON to qmp() is more robust:

    rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri);

It's also more concise.

Clean up the simple cases where we interpolate exactly a JSON value.

Bonus: gets rid of non-literal format strings.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-13-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
62fff696d5 tests: Pass literal format strings directly to qmp_FOO()
The qmp_FOO() take a printf-like format string.  In a few places, we
assign a string literal to a variable and pass that instead of simply
passing the literal.  Clean that up.

Bonus: gets rid of non-literal format strings.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-12-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
2d36e84304 qobject: qobject_from_jsonv() is dangerous, hide it away
qobject_from_jsonv() takes ownership of %p arguments.  On failure, we
can't generally know whether we failed before or after %p, so
ownership becomes indeterminate.  To avoid leaks, callers passing %p
must terminate on error, e.g. by passing &error_abort.  Trap for the
unwary; document and give the function internal linkage.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-11-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
eac78bd430 test-qobject-input-visitor: Avoid format string ambiguity
When visitor_input_test_init_internal()'s argument @ap is null, then
@json_string is interpreted literally, else it's gets %-escapes
interpolated.  This is awkward.

One caller always passes null @ap, and the others never do.  Lift the
building of the QObject into the callers, where it can be done without
such ambiguity.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-10-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
69f0cb661a libqtest: Simplify qmp_fd_vsend() a bit
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-9-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
4ff184689b qobject: New qobject_from_vjsonf_nofail(), qdict_from_vjsonf_nofail()
Every printf()-like function sooner or later needs its vprintf()-like
buddy.  The next commit will need qobject_from_jsonf_nofail()'s buddy,
and qdict_from_jsonf_nofail()'s buddy will be used later in this
series.  Add both.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-8-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
6ce80fd803 qobject: Replace qobject_from_jsonf() by qobject_from_jsonf_nofail()
Commit ab45015a96 "qobject: Let qobject_from_jsonf() fail instead of
abort" fails to accomplish its stated aim: the function can still
abort due to its use of &error_abort.

Its rationale for letting it fail is that all remaining users cope
fine with failure.  Well, they're just fine with aborting, too; it's
what they do on failure.

Simply reverting the broken commit would bring back the unfortunate
asymmetry between qobject_from_jsonf() and qobject_from_jsonv(): one
aborts, the other returns null.  So also rename it to
qobject_from_jsonf_nofail().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-7-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Eric Blake
bb340eb238 libqtest: Document calling conventions
We have two flavors of vararg usage in qtest: qtest_hmp() etc. work
like sprintf(), and qtest_qmp() etc. work like qobject_from_jsonf().
Spell that out in the comments.

Also add GCC_FMT_ATTR() to qtest_hmp() etc. so that the compiler can
flag incorrect use.

We have some cleanup work to do before we can do the same for
qtest_qmp() etc.  This would get us the same better-than-nothing
checking we already have for qobject_from_jsonf(): common incorrect
uses of supported conversion specifications will be flagged
(e.g. passing a double for %d), but use of unsupported ones won't.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Rebased, comment wording tweaked, commit message rewritten]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180806065344.7103-6-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
055a1efc7c libqtest: Remove qtest_qmp_discard_response() & friends
qtest_qmp_discard_response(...) is shorthand for
qobject_unref(qtest_qmp(...), except it's not actually shorter.
Moreover, the presence of these functions encourage sloppy testing.
Remove them from libqtest.  Add them as macros to the tests that use
them, with a TODO comment asking for cleanup.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-5-armbru@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
be62e1724f libqtest: Clean up how we read the QMP greeting
qtest_init() still uses the qtest_qmp_discard_response(s, "") hack to
receive the greeting, even though we have qtest_qmp_receive() since
commit 66e0c7b187.  Put it to use.

Bonus: gets rid of an empty format string.  A step towards
compile-time format string checking without triggering
-Wformat-zero-length.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-4-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
f94648fe3d libqtest: Clean up how we read device_del messages
qtest_qmp_device_del() still uses the qmp("") hack to receive a
message, even though we have qmp_receive() since commit 66e0c7b187.
Put it to use.

Bonus: gets rid of empty format strings.  A step towards compile-time
format string checking without triggering -Wformat-zero-length.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-3-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Markus Armbruster
4277f1ebd9 libqtest: Rename functions to send QMP messages
The functions to receive messages are called qtest_qmp_receive() and
qmp_receive(), qmp_fd_receive().  The ones to send messages are called
qtest_async_qmp(), qtest_async_qmpv(), qmp_async(), qmp_fd_send(),
qmp_fd_sendv().  Inconsistent.  Rename the *_async* ones to
qmp_send(), qtest_qmp_send(), qtest_qmp_vsend().  Rename
qmp_fd_sendv() to qmp_fd_vsend().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-2-armbru@redhat.com>
2018-08-16 08:42:06 +02:00
Peter Maydell
d3bd57d9f6 Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches:

- Remove deprecated -drive options for geometry/serial/addr
- luks: Allow shared writers if the parents allow them (share-rw=on)
- qemu-img: Fix error when trying to convert to encrypted target image
- mirror: Fail gracefully for source == target
- I/O throttling: Fix behaviour during drain (always ignore the limits)
- bdrv_reopen() related fixes for bs->options/explicit_options content
- Documentation improvements

# gpg: Signature made Wed 15 Aug 2018 12:11:43 BST
# gpg:                using RSA key 7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream: (21 commits)
  qapi: block: Remove mentions of error types which were removed
  block: Simplify append_open_options()
  block: Update bs->options if bdrv_reopen() succeeds
  block: Simplify bdrv_reopen_abort()
  block: Remove children options from bs->{options,explicit_options}
  qdict: Make qdict_extract_subqdict() accept dst = NULL
  block: drop empty .bdrv_close handlers
  block: make .bdrv_close optional
  qemu-img: fix regression copying secrets during convert
  mirror: Fail gracefully for source == target
  qapi/block: Document restrictions for node names
  block: Remove dead deprecation warning code
  block: Remove deprecated -drive option serial
  block: Remove deprecated -drive option addr
  block: Remove deprecated -drive geometry options
  luks: Allow share-rw=on
  throttle-groups: Don't allow timers without throttled requests
  qemu-iotests: Update 093 to improve the draining test
  throttle-groups: Skip the round-robin if a member is being drained
  qemu-iotests: Test removing a throttle group member with a pending timer
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-15 22:11:08 +01:00
Peter Maydell
c146b54c7f Merge remote-tracking branch 'remotes/armbru/tags/pull-misc-2018-08-15' into staging
Miscellaneous patches for 2018-08-15

# gpg: Signature made Wed 15 Aug 2018 07:15:31 BST
# gpg:                using RSA key 3870B400EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-misc-2018-08-15:
  monitor: fix oob command leak
  tests: fix crumple/recursive leak
  qapi: Fix some pycodestyle-3 complaints
  tests: change /0.15/* tests to /qmp/*
  qmp-shell: learn to send commands with quoted arguments

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-15 20:20:34 +01:00
Peter Maydell
1d746ee95d Merge remote-tracking branch 'remotes/famz/tags/block-and-testing-pull-request' into staging
Block and testing patches for 3.1

- aio fixes by me
- nvme fixes by Paolo and me
- test improvements by Peter, Phil and me

# gpg: Signature made Wed 15 Aug 2018 04:11:43 BST
# gpg:                using RSA key CA35624C6A9171C6
# gpg: Good signature from "Fam Zheng <famz@redhat.com>"
# Primary key fingerprint: 5003 7CB7 9706 0F76 F021  AD56 CA35 624C 6A91 71C6

* remotes/famz/tags/block-and-testing-pull-request:
  aio-posix: Improve comment around marking node deleted
  tests/vm: Add vm-build-all/vm-clean-all in help text
  tests/vm: Use make's --output-sync option
  tests/vm: Bump guest RAM up from 2G to 4G
  tests/vm: Propagate V=1 down into the make inside the VM
  tests/vm: Pass the jobs parallelism setting to 'make check'
  tests: vm: Add vm-clean-all
  tests: Add centos VM testing
  tests: Allow overriding archive path with SRC_ARCHIVE
  tests: Add an option for snapshot (default: off)
  docker: Install more packages in centos7
  aio: Do aio_notify_accept only during blocking aio_poll
  aio-posix: Don't count ctx->notifier as progress when polling
  nvme: simplify plug/unplug
  nvme: Fix nvme_init error handling
  tests/vm: Add flex and bison to the vm image
  tests/vm: Only use -cpu 'host' if KVM is available

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-15 13:29:53 +01:00
Peter Maydell
48a539df4a Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180814' into staging
target-arm queue:
 * Implement more of ARMv6-M support
 * Support direct execution from non-RAM regions;
   use this to implmeent execution from small (<1K) MPU regions
 * GICv2: implement the virtualization extensions
 * support a virtualization-capable GICv2 in the virt and
   xlnx-zynqmp boards
 * arm: Fix return code of arm_load_elf() so we can detect
   failure to load the file correctly
 * Implement HCR_EL2.TGE ("trap general exceptions") bit
 * Implement tailchaining for M profile cores
 * Fix bugs in SVE compare, saturating add/sub, WHILE, MOVZ

# gpg: Signature made Tue 14 Aug 2018 17:23:38 BST
# gpg:                using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180814: (45 commits)
  target/arm: Fix typo in helper_sve_movz_d
  target/arm: Reorganize SVE WHILE
  target/arm: Fix typo in do_sat_addsub_64
  target/arm: Fix sign of sve_cmpeq_ppzw/sve_cmpne_ppzw
  target/arm: Implement tailchaining for M profile cores
  target/arm: Restore M-profile CONTROL.SPSEL before any tailchaining
  target/arm: Initialize exc_secure correctly in do_v7m_exception_exit()
  target/arm: Improve exception-taken logging
  target/arm: Treat SCTLR_EL1.M as if it were zero when HCR_EL2.TGE is set
  target/arm: Provide accessor functions for HCR_EL2.{IMO, FMO, AMO}
  target/arm: Honour HCR_EL2.TGE when raising synchronous exceptions
  target/arm: Honour HCR_EL2.TGE and MDCR_EL2.TDE in debug register access checks
  target/arm: Mask virtual interrupts if HCR_EL2.TGE is set
  arm: Fix return code of arm_load_elf
  arm/virt: Add support for GICv2 virtualization extensions
  xlnx-zynqmp: Improve GIC wiring and MMIO mapping
  intc/arm_gic: Improve traces
  intc/arm_gic: Implement maintenance interrupt generation
  intc/arm_gic: Implement gic_update_virt() function
  intc/arm_gic: Implement the virtual interface registers
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-15 12:00:53 +01:00
Peter Krempa
b5fc2d3066 qapi: block: Remove mentions of error types which were removed
Most of the various error classes were removed prior to the 1.2 release.
Remove mentions of the error classes which did not make it.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
261dbcb18f block: Simplify append_open_options()
This function returns a BDS's driver-specific options, excluding also
those from its children. Since we have just removed all children
options from bs->options there's no need to do this last step.

We allow references to children, though ("backing": "node0"), so those
we still have to remove.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
4c8350fe17 block: Update bs->options if bdrv_reopen() succeeds
If bdrv_reopen() succeeds then bs->explicit_options is updated with
the new values, but bs->options never changes.

Here's an example:

   { "execute": "blockdev-add",
     "arguments": {
       "driver": "qcow2",
       "node-name": "hd0",
       "overlap-check": "all",
       "file": {
         "driver": "file",
         "filename": "hd0.qcow2"
       }
     }
   }

After this, both bs->options and bs->explicit_options contain
"overlap-check": "all".

Now let's change that using qemu-io's reopen command:

   (qemu) qemu-io hd0 "reopen -o overlap-check=none"

After this, bs->explicit_options contains the new value but
bs->options still keeps the old one.

This patch updates bs->options after a BDS has been successfully
reopened.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
1bab38e7bd block: Simplify bdrv_reopen_abort()
If a bdrv_reopen_multiple() call fails, then the explicit_options
QDict has to be deleted for every entry in the reopen queue. This must
happen regardless of whether that entry's bdrv_reopen_prepare() call
succeeded or not.

This patch simplifies the cleanup code a bit.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
2f624b80ba block: Remove children options from bs->{options,explicit_options}
When bdrv_open_inherit() opens a BlockDriverState the options QDict
can contain options for some of its children, passed in the form of
child-name.option=value

So while each child is opened with that subset of options, those same
options remain stored in the parent BDS, leaving (at least) two copies
of each one of them ("child-name.option=value" in the parent and
"option=value" in the child).

Having the children options stored in the parent is unnecessary and it
can easily lead to an inconsistent state:

  $ qemu-img create -f qcow2 hd0.qcow2 10M
  $ qemu-img create -f qcow2 -b hd0.qcow2 hd1.qcow2
  $ qemu-img create -f qcow2 -b hd1.qcow2 hd2.qcow2

  $ $QEMU -drive file=hd2.qcow2,node-name=hd2,backing.node-name=hd1

This opens a chain of images hd0 <- hd1 <- hd2. Now let's remove hd1
using block_stream:

  (qemu) block_stream hd2 0 hd0.qcow2

After this hd2 contains backing.node-name=hd1, which is no longer
correct because hd1 doesn't exist anymore.

This patch removes all children options from the parent dictionaries
at the end of bdrv_open_inherit() and bdrv_reopen_queue_child().

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
655b4b67e3 qdict: Make qdict_extract_subqdict() accept dst = NULL
This function extracts all options from a QDict starting with a
certain prefix and puts them in a new QDict.

We'll have a couple of cases where we simply want to discard those
options instead of copying them, and that's what this patch does.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Vladimir Sementsov-Ogievskiy
f66b1f0e27 block: drop empty .bdrv_close handlers
.bdrv_close handler is optional after previous commit, no needs to keep
empty functions more.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Vladimir Sementsov-Ogievskiy
3c005293c2 block: make .bdrv_close optional
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Daniel P. Berrangé
8d65a3ccfd qemu-img: fix regression copying secrets during convert
When the convert command is creating an output file that needs
secrets, we need to ensure those secrets are passed to both the
blk_new_open and bdrv_create API calls.

This is done by qemu-img extracting all opts matching the name
suffix "key-secret". Unfortunately the code doing this was run after the
call to bdrv_create(), which meant the QemuOpts it was extracting
secrets from was now empty.

Previously this worked by luks as a bug meant the "key-secret"
parameters were not purged from the QemuOpts. This bug was fixed in

  commit b76b4f6045
  Author: Kevin Wolf <kwolf@redhat.com>
  Date:   Thu Jan 11 16:18:08 2018 +0100

    qcow2: Use visitor for options in qcow2_create()

Exposing the latent bug in qemu-img. This fix simply moves the copying
of secrets to before the bdrv_create() call.

Cc: qemu-stable@nongnu.org
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
86fae10c64 mirror: Fail gracefully for source == target
blockdev-mirror with the same node for source and target segfaults
today: A node is in its own backing chain, so mirror_start_job() decides
that this is an active commit. When adding the intermediate nodes with
block_job_add_bdrv(), it starts the iteration through the subchain with
the backing file of source, though, so it never reaches target and
instead runs into NULL at the base.

While we could fix that by starting with source itself, there is no
point in allowing mirroring a node into itself and I wouldn't be
surprised if this caused more problems later.

So just check for this scenario and error out.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
dbfdf6cb36 qapi/block: Document restrictions for node names
blockdev-add fails if an invalid node name is given, so we should
document what a valid node name even is.

Reported-by: Cong Li <coli@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Cong Li <coli@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
6984eb8da2 block: Remove dead deprecation warning code
This reinstates commit 6266e900b8,
which was temporarily reverted for the 3.0 release so that libvirt gets
some extra time to update their command lines.

We removed all options from the 'deprecated' array, so the code is dead
and can be removed as well.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
572023f7b2 block: Remove deprecated -drive option serial
This reinstates commit b008326744,
which was temporarily reverted for the 3.0 release so that libvirt gets
some extra time to update their command lines.

The -drive option serial was deprecated in QEMU 2.10. It's time to
remove it.

Tests need to be updated to set the serial number with -global instead
of using the -drive option.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
7f8fc97155 block: Remove deprecated -drive option addr
This reinstates commit eae3bd1eb7,
which was temporarily reverted for the 3.0 release so that libvirt gets
some extra time to update their command lines.

The -drive option addr was deprecated in QEMU 2.10. It's time to remove
it.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
b24ec3c462 block: Remove deprecated -drive geometry options
This reinstates commit a7aff6dd10,
which was temporarily reverted for the 3.0 release so that libvirt gets
some extra time to update their command lines.

The -drive options cyls, heads, secs and trans were deprecated in
QEMU 2.10. It's time to remove them.

hd-geo-test tested both the old version with geometry options in -drive
and the new one with -device. Therefore the code using -drive doesn't
have to be replaced there, we just need to remove the -drive test cases.
This in turn allows some simplification of the code.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2018-08-15 12:50:39 +02:00
Fam Zheng
497da8236a luks: Allow share-rw=on
Format drivers such as qcow2 don't allow sharing the same image between
two QEMU instances in order to prevent image corruptions, because of
metadata cache. LUKS driver don't modify metadata except for when
creating image, so it is safe to relax the permission. This makes
share-rw=on property work on virtual devices.

Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
25b8e4db7f throttle-groups: Don't allow timers without throttled requests
Commit 6fccbb475b fixed a bug caused by
QEMU attempting to remove a throttle group member with no pending
requests but an active timer set. This was the result of a previous
bdrv_drained_begin() call processing the throttled requests but
leaving the timer untouched.

Although the commit does solve the problem, the situation shouldn't
happen in the first place. If we try to drain a throttle group member
which has a timer set, we should cancel the timer instead of ignoring
it.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
3db3e9c621 qemu-iotests: Update 093 to improve the draining test
The previous patch fixes a problem in which draining a block device
with more than one throttled request can make it wait first for the
completion of requests in other members of the same group.

This patch updates test_remove_group_member() in iotest 093 to
reproduce that scenario. This updated test would hang QEMU without the
fix from the previous patch.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
5d8e4ca035 throttle-groups: Skip the round-robin if a member is being drained
In the throttling code after an I/O request has been completed the
next one is selected from a different member using a round-robin
algorithm. This ensures that all members get a chance to finish their
pending I/O requests.

However, if a group member has its I/O limits disabled (because it's
being drained) then we should always give it priority in order to have
all its pending requests finished as soon as possible.

If we don't do this we could have a member in the process of being
drained waiting for the throttled requests of other members, for which
the I/O limits still apply.

This can have additional consequences: if we're running in qtest mode
(with QEMU_CLOCK_VIRTUAL) then timers can only fire if we advance the
clock manually, so attempting to drain a block device can hang QEMU in
the BDRV_POLL_WHILE() loop at the end of bdrv_do_drained_begin().

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Alberto Garcia
ef7a6a3c2a qemu-iotests: Test removing a throttle group member with a pending timer
A throttle group can have several members, and each one of them can
have several pending requests in the queue.

The requests are processed in a round-robin fashion, so the algorithm
decides the drive that is going to run the next request and sets a
timer in it. Once the timer fires and the throttled request is run
then the next drive from the group is selected and a new timer is set.

If the user tried to remove a drive from a group and that drive had a
timer set then the code was not taking care of setting up a new timer
in one of the remaining members of the group, freezing their I/O.

This problem was fixed in 6fccbb475b,
and this patch adds a new test case that reproduces this exact
scenario.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-08-15 12:50:39 +02:00
Kevin Wolf
f62492bb8d block/qapi: Fix memory leak in qmp_query_blockstats()
For BlockBackends that are skipped in query-blockstats, we would leak
info since commit 567dcb31. Allocate info only later to avoid the memory
leak.

Fixes: CID 1394727
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
2018-08-15 12:50:39 +02:00
Marc-André Lureau
cb9ec42f33 monitor: fix oob command leak
Spotted by ASAN, during make check...

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0x7f8e27262c48 in malloc (/lib64/libasan.so.5+0xeec48)
    #1 0x7f8e26a5f3c5 in g_malloc (/lib64/libglib-2.0.so.0+0x523c5)
    #2 0x555ab67078a8 in qstring_from_str /home/elmarco/src/qq/qobject/qstring.c:67
    #3 0x555ab67071e4 in qstring_new /home/elmarco/src/qq/qobject/qstring.c:24
    #4 0x555ab6713fbf in qstring_from_escaped_str /home/elmarco/src/qq/qobject/json-parser.c:144
    #5 0x555ab671738c in parse_literal /home/elmarco/src/qq/qobject/json-parser.c:506
    #6 0x555ab67179c3 in parse_value /home/elmarco/src/qq/qobject/json-parser.c:569
    #7 0x555ab6715123 in parse_pair /home/elmarco/src/qq/qobject/json-parser.c:306
    #8 0x555ab6715483 in parse_object /home/elmarco/src/qq/qobject/json-parser.c:357
    #9 0x555ab671798b in parse_value /home/elmarco/src/qq/qobject/json-parser.c:561
    #10 0x555ab6717a6b in json_parser_parse_err /home/elmarco/src/qq/qobject/json-parser.c:592
    #11 0x555ab4fd4dcf in handle_qmp_command /home/elmarco/src/qq/monitor.c:4257
    #12 0x555ab6712c4d in json_message_process_token /home/elmarco/src/qq/qobject/json-streamer.c:105
    #13 0x555ab67e01e2 in json_lexer_feed_char /home/elmarco/src/qq/qobject/json-lexer.c:323
    #14 0x555ab67e0af6 in json_lexer_feed /home/elmarco/src/qq/qobject/json-lexer.c:373
    #15 0x555ab6713010 in json_message_parser_feed /home/elmarco/src/qq/qobject/json-streamer.c:124
    #16 0x555ab4fd58ec in monitor_qmp_read /home/elmarco/src/qq/monitor.c:4337
    #17 0x555ab6559df2 in qemu_chr_be_write_impl /home/elmarco/src/qq/chardev/char.c:175
    #18 0x555ab6559e95 in qemu_chr_be_write /home/elmarco/src/qq/chardev/char.c:187
    #19 0x555ab6560127 in fd_chr_read /home/elmarco/src/qq/chardev/char-fd.c:66
    #20 0x555ab65d9c73 in qio_channel_fd_source_dispatch /home/elmarco/src/qq/io/channel-watch.c:84
    #21 0x7f8e26a598ac in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x4c8ac)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180809114417.28718-4-marcandre.lureau@redhat.com>
[Screwed up in commit b27314567d]
Cc: qemu-stable@nongnu.org
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-08-15 08:12:57 +02:00
Marc-André Lureau
42478dacc8 tests: fix crumple/recursive leak
Spotted by ASAN:

=================================================================
==27907==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 4120 byte(s) in 1 object(s) allocated from:
    #0 0x7f913458ce50 in calloc (/lib64/libasan.so.5+0xeee50)
    #1 0x7f9133fd641d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5241d)
    #2 0x5561c6643c95 in qdict_crumple_test_recursive /home/elmarco/src/qq/tests/check-block-qdict.c:438
    #3 0x7f9133ff7c49  (/lib64/libglib-2.0.so.0+0x73c49)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180809114417.28718-2-marcandre.lureau@redhat.com>
[Screwed up in commit 2860b2b2cb]
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-08-15 08:12:19 +02:00
Markus Armbruster
b736e25a18 qapi: Fix some pycodestyle-3 complaints
Fix the following issues:

    common.py:873:13: E129 visually indented line with same indent as next logical line
    common.py:1766:5: E741 ambiguous variable name 'l'
    common.py:1784:1: E305 expected 2 blank lines after class or function definition, found 1
    common.py:1833:1: E305 expected 2 blank lines after class or function definition, found 1
    common.py:1843:1: E305 expected 2 blank lines after class or function definition, found 1
    visit.py:181:18: E127 continuation line over-indented for visual indent

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180621083551.775-1-armbru@redhat.com>
[Fixup squashed in:]
Message-ID: <871sd0nzw9.fsf@dusky.pond.sub.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2018-08-15 07:24:22 +02:00
Marc-André Lureau
214e4a5b38 tests: change /0.15/* tests to /qmp/*
Presumably 0.15 was the version it was first introduced, but
qmp keeps evolving. There is no point in having that version
as test prefix, 'qmp' makes more sense here.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180326150916.9602-12-marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-08-15 07:24:22 +02:00
Marc-André Lureau
fcfab75410 qmp-shell: learn to send commands with quoted arguments
Use shlex to split the CLI command, respecting quoted arguments, and
also comments. This allows to call for ex:

(QEMU) human-monitor-command command-line="screendump /dev/null"
{"execute": "human-monitor-command", "arguments": {"command-line": "screendump /dev/null"}}

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180326150916.9602-3-marcandre.lureau@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-08-15 07:24:22 +02:00
Fam Zheng
37a81812f7 aio-posix: Improve comment around marking node deleted
The counter is for qemu_lockcnt_inc/dec sections (read side),
qemu_lockcnt_lock/unlock is for the write side.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180803063917.30292-1-famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
af7e916869 tests/vm: Add vm-build-all/vm-clean-all in help text
Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180727083445.21436-1-famz@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Peter Maydell
f2d4becdc7 tests/vm: Use make's --output-sync option
Use make's --output-sync option when running tests inside VMs,
so that if we're building with parallelization the output doesn't
get scrambled.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20180803085230.30574-6-peter.maydell@linaro.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Peter Maydell
eb2712f568 tests/vm: Bump guest RAM up from 2G to 4G
Currently we run the guests in a VM which is given only 2G of RAM.
Since the guests are configured without any swap space, builds
can fail because the system runs out of memory and kills the
compiler, especially if the job count is set for a lot of
parallelism. Bump the setting up from 2G to 4G to give us some
more headroom.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20180803085230.30574-5-peter.maydell@linaro.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Peter Maydell
41e3340afe tests/vm: Propagate V=1 down into the make inside the VM
Invoking 'make vm-build-freebsd' and friends with V=1 should
propagate that verbosity setting down into the build run
inside the VM. Make sure we do that. This brings it into
line with how the container tests handle V=1.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20180803085230.30574-4-peter.maydell@linaro.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Peter Maydell
ebb61f804d tests/vm: Pass the jobs parallelism setting to 'make check'
Our test suite works for parallel execution too, and this can
noticeably speed up a test run; pass the 'jobs' setting to
it as well as to the build proper.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20180803085230.30574-3-peter.maydell@linaro.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
ebe95fa094 tests: vm: Add vm-clean-all
The images are big. Add a rule to clean up easily.

Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180716020008.31468-1-famz@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
1bd2698808 tests: Add centos VM testing
This one does docker testing in the VM. It is intended to replace the
native docker testing on patchew testers.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180712012829.20231-5-famz@redhat.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
73fb4f1de3 tests: Allow overriding archive path with SRC_ARCHIVE
In VM based tests, the source archive is created in host, we don't have
to run archive-source.sh again, as it complicates the Makefile and
scripts.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180712012829.20231-4-famz@redhat.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
983c2a777b tests: Add an option for snapshot (default: off)
Not using snapshot has the benefit of automatically persisting useful
test harnesses, such as docker images and ccache database. Although it
will lose some cleanness, it is imaginably useful for patchew.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180712012829.20231-2-famz@redhat.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
8158ed48bb docker: Install more packages in centos7
This makes test-block work.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180711065813.14894-1-famz@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
b37548fcd1 aio: Do aio_notify_accept only during blocking aio_poll
An aio_notify() pairs with an aio_notify_accept(). The former should
happen in the main thread or a vCPU thread, and the latter should be
done in the IOThread.

There is one rare case that the main thread or vCPU thread may "steal"
the aio_notify() event just raised by itself, in bdrv_set_aio_context()
[1]. The sequence is like this:

    main thread                     IO Thread
    ===============================================================
    bdrv_drained_begin()
      aio_disable_external(ctx)
                                    aio_poll(ctx, true)
                                      ctx->notify_me += 2
    ...
    bdrv_drained_end()
      ...
        aio_notify()
    ...
    bdrv_set_aio_context()
      aio_poll(ctx, false)
[1]     aio_notify_accept(ctx)
                                      ppoll() /* Hang! */

[1] is problematic. It will clear the ctx->notifier event so that
the blocked ppoll() will not return.

(For the curious, this bug was noticed when booting a number of VMs
simultaneously in RHV.  One or two of the VMs will hit this race
condition, making the VIRTIO device unresponsive to I/O commands. When
it hangs, Seabios is busy waiting for a read request to complete (read
MBR), right after initializing the virtio-blk-pci device, using 100%
guest CPU. See also https://bugzilla.redhat.com/show_bug.cgi?id=1562750
for the original bug analysis.)

aio_notify() only injects an event when ctx->notify_me is set,
correspondingly aio_notify_accept() is only useful when ctx->notify_me
_was_ set. Move the call to it into the "blocking" branch. This will
effectively skip [1] and fix the hang.

Furthermore, blocking aio_poll is only allowed on home thread
(in_aio_context_home_thread), because otherwise two blocking
aio_poll()'s can steal each other's ctx->notifier event and cause
hanging just like described above.

Cc: qemu-stable@nongnu.org
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180809132259.18402-3-famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
70232b5253 aio-posix: Don't count ctx->notifier as progress when polling
The same logic exists in fd polling. This change is especially important
to avoid busy loop once we limit aio_notify_accept() to blocking
aio_poll().

Cc: qemu-stable@nongnu.org
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20180809132259.18402-2-famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Paolo Bonzini
2f0d8947a6 nvme: simplify plug/unplug
bdrv_io_plug/bdrv_io_unplug take care of keeping a nesting count,
so change s->plugged to just a bool.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20180813144320.12382-2-pbonzini@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Fam Zheng
9582f357bb nvme: Fix nvme_init error handling
It is wrong to leave this field as 1, as nvme_close() called in the
error handling code in nvme_file_open() will use it and try to free
s->queues again.

Another problem is the cleaning ups are duplicated between the fail*
labels of nvme_init() and nvme_file_open(), which calls nvme_close().

A third problem is nvme_close() misses g_free() and
event_notifier_cleanup().

Fix all of them.

Cc: qemu-stable@nongnu.org
Signed-off-by: Fam Zheng <famz@redhat.com>

Message-Id: <20180712025420.4932-1-famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Philippe Mathieu-Daudé
a3f9f64bf9 tests/vm: Add flex and bison to the vm image
Similar to 79f24568e5, this fixes the following warnings:

           CHK version_gen.h
           LEX convert-dtsv0-lexer.lex.c
  make[1]: flex: Command not found
           BISON dtc-parser.tab.c
  make[1]: bison: Command not found
           LEX dtc-lexer.lex.c
  make[1]: flex: Command not found

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180628153535.1411-5-f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Philippe Mathieu-Daudé
dcf7ea4a78 tests/vm: Only use -cpu 'host' if KVM is available
If KVM is not available, then use the 'max' cpu.

This fixes:

  ERROR:root:Log:
  ERROR:root:qemu-system-x86_64: CPU model 'host' requires KVM
  Failed to prepare guest environment
  error: [Errno 104] Connection reset by peer
  source/qemu/tests/vm/Makefile.include:25: recipe for target 'tests/vm/ubuntu.i386.img' failed
  make: *** [tests/vm/ubuntu.i386.img] Error 2

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180628153535.1411-4-f4bug@amsat.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
2018-08-15 10:12:35 +08:00
Richard Henderson
054e7adf4e target/arm: Fix typo in helper_sve_movz_d
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180801123111.3595-5-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:22 +01:00
Richard Henderson
bbd0968c45 target/arm: Reorganize SVE WHILE
The pseudocode for this operation is an increment + compare loop,
so comparing <= the maximum integer produces an all-true predicate.

Rather than bound in both the inline code and the helper, pass the
helper the number of predicate bits to set instead of the number
of predicate elements to set.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180801123111.3595-4-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:22 +01:00
Richard Henderson
7a31e0c6c6 target/arm: Fix typo in do_sat_addsub_64
Used the wrong temporary in the computation of subtractive overflow.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180801123111.3595-3-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:22 +01:00
Richard Henderson
df4e001093 target/arm: Fix sign of sve_cmpeq_ppzw/sve_cmpne_ppzw
The normal vector element is sign-extended before
comparing with the wide vector element.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20180801123111.3595-2-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:22 +01:00
Peter Maydell
5f62d3b9e6 target/arm: Implement tailchaining for M profile cores
Tailchaining is an optimization in handling of exception return
for M-profile cores: if we are about to pop the exception stack
for an exception return, but there is a pending exception which
is higher priority than the priority we are returning to, then
instead of unstacking and then immediately taking the exception
and stacking registers again, we can chain to the pending
exception without unstacking and stacking.

For v6M and v7M it is IMPDEF whether tailchaining happens for pending
exceptions; for v8M this is architecturally required.  Implement it
in QEMU for all M-profile cores, since in practice v6M and v7M
hardware implementations generally do have it.

(We were already doing tailchaining for derived exceptions which
happened during exception return, like the validity checks and
stack access failures; these have always been required to be
tailchained for all versions of the architecture.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180720145647.8810-5-peter.maydell@linaro.org
2018-08-14 17:17:22 +01:00
Peter Maydell
89b1fec193 target/arm: Restore M-profile CONTROL.SPSEL before any tailchaining
On exception return for M-profile, we must restore the CONTROL.SPSEL
bit from the EXCRET value before we do any kind of tailchaining,
including for the derived exceptions on integrity check failures.
Otherwise we will give the guest an incorrect EXCRET.SPSEL value on
exception entry for the tailchained exception.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180720145647.8810-4-peter.maydell@linaro.org
2018-08-14 17:17:22 +01:00
Peter Maydell
b8109608bc target/arm: Initialize exc_secure correctly in do_v7m_exception_exit()
In do_v7m_exception_exit(), we use the exc_secure variable to track
whether the exception we're returning from is secure or non-secure.
Unfortunately the statement initializing this was accidentally
inside an "if (env->v7m.exception != ARMV7M_EXCP_NMI)" conditional,
which meant that we were using the wrong value for NMI handlers.
Move the initialization out to the right place.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180720145647.8810-3-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Peter Maydell
a9074977ef target/arm: Improve exception-taken logging
Improve the exception-taken logging by logging in
v7m_exception_taken() the exception we're going to take
and whether it is secure/nonsecure.

This requires us to move logging at many callsites from after the
call to before it, so that the logging appears in a sensible order.

(This will make tail-chaining produce more useful logs; for the
current callers of v7m_exception_taken() we know which exception
we're going to take, so custom log messages at the callsite sufficed;
for tail-chaining only v7m_exception_taken() knows the exception
number that we're going to tail-chain to.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180720145647.8810-2-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Peter Maydell
3d0e3080d8 target/arm: Treat SCTLR_EL1.M as if it were zero when HCR_EL2.TGE is set
One of the required effects of setting HCR_EL2.TGE is that when
SCR_EL3.NS is 1 then SCTLR_EL1.M must behave as if it is zero for
all purposes except direct reads. That is, it effectively disables
the MMU for the NS EL0/EL1 translation regime.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180724115950.17316-6-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Peter Maydell
ac656b166b target/arm: Provide accessor functions for HCR_EL2.{IMO, FMO, AMO}
The IMO, FMO and AMO bits in HCR_EL2 are defined to "behave as
1 for all purposes other than direct reads" if HCR_EL2.TGE
is set and HCR_EL2.E2H is 0, and to "behave as 0 for all
purposes other than direct reads" if HCR_EL2.TGE is set
and HRC_EL2.E2H is 1.

To avoid having to check E2H and TGE everywhere where we test IMO and
FMO, provide accessors arm_hcr_el2_imo(), arm_hcr_el2_fmo()and
arm_hcr_el2_amo().  We don't implement ARMv8.1-VHE yet, so the E2H
case will never be true, but we include the logic to save effort when
we eventually do get to that.

(Note that in several of these callsites the change doesn't
actually make a difference as either the callsite is handling
TGE specially anyway, or the CPU can't get into that situation
with TGE set; we change everywhere for consistency.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180724115950.17316-5-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Peter Maydell
7556edfb4d target/arm: Honour HCR_EL2.TGE when raising synchronous exceptions
Whene we raise a synchronous exception, if HCR_EL2.TGE is set then
exceptions targeting NS EL1 must be redirected to EL2.  Implement
this in raise_exception() -- all synchronous exceptions go through
this function.

(Asynchronous exceptions go via arm_cpu_exec_interrupt(), which
already honours HCR_EL2.TGE when it determines the target EL
in arm_phys_excp_target_el().)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180724115950.17316-4-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Peter Maydell
30ac6339dc target/arm: Honour HCR_EL2.TGE and MDCR_EL2.TDE in debug register access checks
Some debug registers can be trapped via MDCR_EL2 bits TDRA, TDOSA,
and TDA, which we implement in the functions access_tdra(),
access_tdosa() and access_tda(). If MDCR_EL2.TDE or HCR_EL2.TGE
are 1, the TDRA, TDOSA and TDA bits should behave as if they were 1.
Implement this by having the access functions check MDCR_EL2.TDE
and HCR_EL2.TGE.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180724115950.17316-3-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Peter Maydell
2ccf0fef63 target/arm: Mask virtual interrupts if HCR_EL2.TGE is set
If the "trap general exceptions" bit HCR_EL2.TGE is set, we
must mask all virtual interrupts (as per DDI0487C.a D1.14.3).
Implement this in arm_excp_unmasked().

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180724115950.17316-2-peter.maydell@linaro.org
2018-08-14 17:17:21 +01:00
Adam Lackorzynski
a3f0ecfd4e arm: Fix return code of arm_load_elf
Use an int64_t as a return type to restore
the negative check for arm_load_as.

Signed-off-by: Adam Lackorzynski <adam@l4re.org>
Message-id: 20180730173712.GG4987@os.inf.tu-dresden.de
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:21 +01:00
Luc Michel
55ef323358 arm/virt: Add support for GICv2 virtualization extensions
Add support for GICv2 virtualization extensions by mapping the necessary
I/O regions and connecting the maintenance IRQ lines.

Declare those additions in the device tree and in the ACPI tables.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-21-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:21 +01:00
Luc Michel
75b749af0c xlnx-zynqmp: Improve GIC wiring and MMIO mapping
This commit improve the way the GIC is realized and connected in the
ZynqMP SoC. The security extensions are enabled only if requested in the
machine state. The same goes for the virtualization extensions.

All the GIC to APU CPU(s) IRQ lines are now connected, including FIQ,
vIRQ and vFIQ. The missing CPU to GIC timers IRQ connections are also
added (HYP and SEC timers).

The GIC maintenance IRQs are back-wired to the correct GIC PPIs.

Finally, the MMIO mappings are reworked to take into account the ZynqMP
specifics. The GIC (v)CPU interface is aliased 16 times:
  * for the first 0x1000 bytes from 0xf9010000 to 0xf901f000
  * for the second 0x1000 bytes from 0xf9020000 to 0xf902f000
Mappings of the virtual interface and virtual CPU interface are mapped
only when virtualization extensions are requested. The
XlnxZynqMPGICRegion struct has been enhanced to be able to catch all
this information.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20180727095421.386-20-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:21 +01:00
Luc Michel
067a2b9c15 intc/arm_gic: Improve traces
Add some traces to the ARM GIC to catch register accesses (distributor,
(v)cpu interface and virtual interface), and to take into account
virtualization extensions (print `vcpu` instead of `cpu` when needed).

Also add some virtualization extensions specific traces: LR updating
and maintenance IRQ generation.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-19-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:21 +01:00
Luc Michel
50e579262d intc/arm_gic: Implement maintenance interrupt generation
Implement the maintenance interrupt generation that is part of the GICv2
virtualization extensions.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-18-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:21 +01:00
Luc Michel
cbe1282b56 intc/arm_gic: Implement gic_update_virt() function
Add the gic_update_virt() function to update the vCPU interface states
and raise vIRQ and vFIQ as needed. This commit renames gic_update() to
gic_update_internal() and generalizes it to handle both cases, with a
`virt' parameter to track whether we are updating the CPU or vCPU
interfaces.

The main difference between CPU and vCPU is the way we select the best
IRQ. This part has been split into the gic_get_best_(v)irq functions.
For the virt case, the LRs are iterated to find the best candidate.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-17-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
527d296f5d intc/arm_gic: Implement the virtual interface registers
Implement the read and write functions for the virtual interface of the
virtualization extensions in the GICv2.

One mirror region per CPU is also created, which maps to that specific
CPU id. This is required by the GIC architecture specification.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-16-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
2c679ac734 intc/arm_gic: Wire the vCPU interface
Add the read/write functions to handle accesses to the vCPU interface.
Those accesses are forwarded to the real CPU interface, with the CPU id
being converted to the corresponding vCPU id (vCPU id = CPU id +
GIC_NCPU).

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180727095421.386-15-luc.michel@greensocs.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
7eb079ec51 intc/arm_gic: Implement virtualization extensions in gic_cpu_(read|write)
Implement virtualization extensions in the gic_cpu_read() and
gic_cpu_write() functions. Those are the last bits missing to fully
support virtualization extensions in the CPU interface path.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-14-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
02f2e22d7c intc/arm_gic: Implement virtualization extensions in gic_(deactivate|complete_irq)
Implement virtualization extensions in the gic_deactivate_irq() and
gic_complete_irq() functions.

When the guest writes an invalid vIRQ to V_EOIR or V_DIR, since the
GICv2 specification is not entirely clear here, we adopt the behaviour
observed on real hardware:
  * When V_CTRL.EOIMode is false (EOI split is disabled):
    - In case of an invalid vIRQ write to V_EOIR:
      -> If some bits are set in H_APR, an invalid vIRQ write to V_EOIR
         triggers a priority drop, and increments V_HCR.EOICount.
      -> If V_APR is already cleared, nothing happen

    - An invalid vIRQ write to V_DIR is ignored.

  * When V_CTRL.EOIMode is true:
    - In case of an invalid vIRQ write to V_EOIR:
      -> If some bits are set in H_APR, an invalid vIRQ write to V_EOIR
         triggers a priority drop.
      -> If V_APR is already cleared, nothing happen

    - An invalid vIRQ write to V_DIR increments V_HCR.EOICount.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Message-id: 20180727095421.386-13-luc.michel@greensocs.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
439badd66d intc/arm_gic: Implement virtualization extensions in gic_acknowledge_irq
Implement virtualization extensions in the gic_acknowledge_irq()
function. This function changes the state of the highest priority IRQ
from pending to active.

When the current CPU is a vCPU, modifying the state of an IRQ modifies
the corresponding LR entry. However if we clear the pending flag before
setting the active one, we lose track of the LR entry as it becomes
invalid. The next call to gic_get_lr_entry() will fail.

To overcome this issue, we call gic_activate_irq() before
gic_clear_pending(). This does not change the general behaviour of
gic_acknowledge_irq.

We also move the SGI case in gic_clear_pending_sgi() to enhance
code readability as the virtualization extensions support adds a if-else
level.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-12-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
a1d7b8d896 intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio)
Implement virtualization extensions in gic_activate_irq() and
gic_drop_prio() and in gic_get_prio_from_apr_bits() called by
gic_drop_prio().

When the current CPU is a vCPU:
  - Use GIC_VIRT_MIN_BPR and GIC_VIRT_NR_APRS instead of their non-virt
  counterparts,
  - the vCPU APR is stored in the virtual interface, in h_apr.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-11-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
86b350f0d0 intc/arm_gic: Add virtualization enabled IRQ helper functions
Add some helper functions to gic_internal.h to get or change the state
of an IRQ. When the current CPU is not a vCPU, the call is forwarded to
the GIC distributor. Otherwise, it acts on the list register matching
the IRQ in the current CPU virtual interface.

gic_clear_active can have a side effect on the distributor, even in the
vCPU case, when the correponding LR has the HW field set.

Use those functions in the CPU interface code path to prepare for the
vCPU interface implementation.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180727095421.386-10-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
3dd0471b75 intc/arm_gic: Refactor secure/ns access check in the CPU interface
An access to the CPU interface is non-secure if the current GIC instance
implements the security extensions, and the memory access is actually
non-secure. Until then, it was checked with tests such as
  if (s->security_extn && !attrs.secure) { ... }
in various places of the CPU interface code.

With the implementation of the virtualization extensions, those tests
must be updated to take into account whether we are in a vCPU interface
or not. This is because the exposed vCPU interface does not implement
security extensions.

This commits replaces all those tests with a call to the
gic_cpu_ns_access() function to check if the current access to the CPU
interface is non-secure. This function takes into account whether the
current CPU is a vCPU or not.

Note that this function is used only in the (v)CPU interface code path.
The distributor code path is left unchanged, as the distributor is not
exposed to vCPUs at all.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180727095421.386-9-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
4a37e0e476 intc/arm_gic: Add virtualization extensions helper macros and functions
Add some helper macros and functions related to the virtualization
extensions to gic_internal.h.

The GICH_LR_* macros help extracting specific fields of a list register
value. The only tricky one is the priority field as only the MSB are
stored. The value must be shifted accordingly to obtain the correct
priority value.

gic_is_vcpu() and gic_get_vcpu_real_id() help with (v)CPU id manipulation
to abstract the fact that vCPU id are in the range
[ GIC_NCPU; (GIC_NCPU + num_cpu) [.

gic_lr_* and gic_virq_is_valid() help with the list registers.
gic_get_lr_entry() returns the LR entry for a given (vCPU, irq) pair. It
is meant to be used in contexts where we know for sure that the entry
exists, so we assert that entry is actually found, and the caller can
avoid the NULL check on the returned pointer.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-8-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
7c2fffd282 intc/arm_gic: Add virtual interface register definitions
Add the register definitions for the virtual interface of the GICv2.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-7-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
5773c0494a intc/arm_gic: Add the virtualization extensions to the GIC state
Add the necessary parts of the virtualization extensions state to the
GIC state. We choose to increase the size of the CPU interfaces state to
add space for the vCPU interfaces (the GIC_NCPU_VCPU macro). This way,
we'll be able to reuse most of the CPU interface code for the vCPUs.

The only exception is the APR value, which is stored in h_apr in the
virtual interface state for vCPUs. This is due to some complications
with the GIC VMState, for which we don't want to break backward
compatibility. APRs being stored in 2D arrays, increasing the second
dimension would lead to some ugly VMState description. To avoid
that, we keep it in h_apr for vCPUs.

The vCPUs are numbered from GIC_NCPU to (GIC_NCPU * 2) - 1. The
`gic_is_vcpu` function help to determine if a given CPU id correspond to
a physical CPU or a virtual one.

For the in-kernel KVM VGIC, since the exposed VGIC does not implement
the virtualization extensions, we report an error if the corresponding
property is set to true.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-6-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
b77473a0f7 vmstate.h: Provide VMSTATE_UINT16_SUB_ARRAY
Provide a VMSTATE_UINT16_SUB_ARRAY macro to save a uint16_t sub-array in
a VMState.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180727095421.386-5-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
50491c56a5 intc/arm_gic: Remove some dead code and put some functions static
Some functions are now only used in arm_gic.c, put them static. Some of
them where only used by the NVIC implementation and are not used
anymore, so remove them.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-4-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:20 +01:00
Luc Michel
3bb0b03897 intc/arm_gic: Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers
Implement GICD_ISACTIVERn and GICD_ICACTIVERn registers in the GICv2.
Those registers allow to set or clear the active state of an IRQ in the
distributor.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-3-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:19 +01:00
Luc Michel
67ce697ac8 intc/arm_gic: Refactor operations on the distributor
In preparation for the virtualization extensions implementation,
refactor the name of the functions and macros that act on the GIC
distributor to make that fact explicit. It will be useful to
differentiate them from the ones that will act on the virtual
interfaces.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20180727095421.386-2-luc.michel@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:19 +01:00
Peter Maydell
55a7cb144d accel/tcg: Check whether TLB entry is RAM consistently with how we set it up
We set up TLB entries in tlb_set_page_with_attrs(), where we have
some logic for determining whether the TLB entry is considered
to be RAM-backed, and thus has a valid addend field. When we
look at the TLB entry in get_page_addr_code(), we use different
logic for determining whether to treat the page as RAM-backed
and use the addend field. This is confusing, and in fact buggy,
because the code in tlb_set_page_with_attrs() correctly decides
that rom_device memory regions not in romd mode are not RAM-backed,
but the code in get_page_addr_code() thinks they are RAM-backed.
This typically results in "Bad ram pointer" assertion if the
guest tries to execute from such a memory region.

Fix this by making get_page_addr_code() just look at the
TLB_MMIO bit in the code_address field of the TLB, which
tlb_set_page_with_attrs() sets if and only if the addend
field is not valid for code execution.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180713150945.12348-1-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Peter Maydell
d4b6275df3 target/arm: Allow execution from small regions
Now that we have full support for small regions, including execution,
we can remove the workarounds where we marked all small regions as
non-executable for the M-profile MPU and SAU.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180710160013.26559-7-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Peter Maydell
20cb6ae472 accel/tcg: Return -1 for execution from MMIO regions in get_page_addr_code()
Now that all the callers can handle get_page_addr_code() returning -1,
remove all the code which tries to handle execution from MMIO regions
or small-MMU-region RAM areas. This will mean that we can correctly
execute from these areas, rather than ending up either aborting QEMU
or delivering an incorrect guest exception.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20180710160013.26559-6-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Peter Maydell
9739e3767a accel/tcg: tb_gen_code(): Create single-insn TB for execution from non-RAM
If get_page_addr_code() returns -1, this indicates that there is no RAM
page we can read a full TB from. Instead we must create a TB which
contains a single instruction and which we do not cache, so it is
executed only once.

Since this means we can now have TBs which are not in any page list,
we also need to make tb_phys_invalidate() handle them (by not trying
to remove them from a nonexistent page list).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180710160013.26559-5-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Peter Maydell
c360a0fd71 accel/tcg: Handle get_page_addr_code() returning -1 in tb_check_watchpoint()
When we support execution from non-RAM MMIO regions, get_page_addr_code()
will return -1 to indicate that there is no RAM at the requested address.
Handle this in tb_check_watchpoint() -- if the exception happened for a
PC which doesn't correspond to RAM then there is no need to invalidate
any TBs, because the one-instruction TB will not have been cached.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180710160013.26559-4-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Peter Maydell
7252f2dea9 accel/tcg: Handle get_page_addr_code() returning -1 in hashtable lookups
When we support execution from non-RAM MMIO regions, get_page_addr_code()
will return -1 to indicate that there is no RAM at the requested address.
Handle this in the cpu-exec TB hashtable lookup code, treating it as
"no match found".

Note that the call to get_page_addr_code() in tb_lookup_cmp() needs
no changes -- a return of -1 will already correctly result in the
function returning false.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180710160013.26559-3-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Peter Maydell
dbea78a4d6 accel/tcg: Pass read access type through to io_readx()
The io_readx() function needs to know whether the load it is
doing is an MMU_DATA_LOAD or an MMU_INST_FETCH, so that it
can pass the right value to the cpu_transaction_failed()
function. Plumb this information through from the softmmu
code.

This is currently not often going to give the wrong answer,
because usually instruction fetches go via get_page_addr_code().
However once we switch over to handling execution from non-RAM by
creating single-insn TBs, the path for an insn fetch to generate
a bus error will be through cpu_ld*_code() and io_readx(),
so without this change we will generate a d-side fault when we
should generate an i-side fault.

We also have to pass the access type via a CPU struct global
down to unassigned_mem_read(), for the benefit of the targets
which still use the cpu_unassigned_access() hook (m68k, mips,
sparc, xtensa).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20180710160013.26559-2-peter.maydell@linaro.org
2018-08-14 17:17:19 +01:00
Julia Suvorova
c4379b4874 nvic: Change NVIC to support ARMv6-M
The differences from ARMv7-M NVIC are:
  * ARMv6-M only supports up to 32 external interrupts
   (configurable feature already). The ICTR is reserved.
  * Active Bit Register is reserved.
  * ARMv6-M supports 4 priority levels against 256 in ARMv7-M.

Signed-off-by: Julia Suvorova <jusual@mail.ru>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:19 +01:00
Julia Suvorova
22ab346001 arm: Add ARMv6-M programmer's model support
Forbid stack alignment change. (CCR)
Reserve FAULTMASK, BASEPRI registers.
Report any fault as a HardFault. Disable MemManage, BusFault and
UsageFault, so they always escalated to HardFault. (SHCSR)

Signed-off-by: Julia Suvorova <jusual@mail.ru>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20180718095628.26442-1-jusual@mail.ru
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:19 +01:00
Julia Suvorova
7c9140afd5 nvic: Handle ARMv6-M SCS reserved registers
Handle SCS reserved registers listed in ARMv6-M ARM D3.6.1.
All reserved registers are RAZ/WI. ARM_FEATURE_M_MAIN is used for the
checks, because these registers are reserved in ARMv8-M Baseline too.

Signed-off-by: Julia Suvorova <jusual@mail.ru>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:19 +01:00
Julia Suvorova
def183446c target/arm: Forbid unprivileged mode for M Baseline
MSR handling is the only place where CONTROL.nPRIV is modified.

Signed-off-by: Julia Suvorova <jusual@mail.ru>
Message-id: 20180705222622.17139-1-jusual@mail.ru
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:17:18 +01:00
Peter Maydell
c7fb81a53c Open 3.1 development tree
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2018-08-14 17:10:49 +01:00
267 changed files with 8280 additions and 2563 deletions

View File

@@ -12,8 +12,11 @@ Fabrice Bellard <fabrice@bellard.org> bellard <bellard@c046a42c-6fe2-441c-8c8c-7
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
Jocelyn Mayer <l_indien@magic.fr> j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Paul Brook <paul@codesourcery.com> pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Paul Burton <paul.burton@mips.com> <paul.burton@imgtec.com>
Paul Burton <paul.burton@mips.com> <paul@archlinuxmips.org>
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@mips.com>
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@imgtec.com>
Paul Burton <pburton@wavecomp.com> <paul.burton@mips.com>
Paul Burton <pburton@wavecomp.com> <paul.burton@imgtec.com>
Paul Burton <pburton@wavecomp.com> <paul@archlinuxmips.org>
Thiemo Seufer <ths@networkno.de> ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
malc <av1474@comtv.ru> malc <malc@c046a42c-6fe2-441c-8c8c-71466251a162>

View File

@@ -187,7 +187,7 @@ F: disas/microblaze.c
MIPS
M: Aurelien Jarno <aurelien@aurel32.net>
M: Aleksandar Markovic <aleksandar.markovic@mips.com>
M: Aleksandar Markovic <amarkovic@wavecomp.com>
S: Maintained
F: target/mips/
F: hw/mips/
@@ -289,6 +289,7 @@ F: tests/tcg/i386/
F: tests/tcg/x86_64/
F: hw/i386/
F: disas/i386.c
F: docs/qemu-cpu-models.texi
T: git git://github.com/ehabkost/qemu.git x86-next
Xtensa
@@ -444,6 +445,7 @@ F: hw/char/pl011.c
F: include/hw/char/pl011.h
F: hw/display/pl110*
F: hw/dma/pl080.c
F: include/hw/dma/pl080.h
F: hw/dma/pl330.c
F: hw/gpio/pl061.c
F: hw/input/pl050.c
@@ -455,6 +457,8 @@ F: hw/timer/cmsdk-apb-timer.c
F: include/hw/timer/cmsdk-apb-timer.h
F: hw/char/cmsdk-apb-uart.c
F: include/hw/char/cmsdk-apb-uart.h
F: hw/watchdog/cmsdk-apb-watchdog.c
F: include/hw/watchdog/cmsdk-apb-watchdog.h
F: hw/misc/tz-ppc.c
F: include/hw/misc/tz-ppc.h
F: hw/misc/tz-mpc.c
@@ -718,7 +722,7 @@ S: Maintained
F: hw/mips/mips_malta.c
Mipssim
M: Aleksandar Markovic <aleksandar.markovic@mips.com>
M: Aleksandar Markovic <amarkovic@wavecomp.com>
S: Odd Fixes
F: hw/mips/mips_mipssim.c
F: hw/net/mipsnet.c
@@ -729,14 +733,15 @@ S: Maintained
F: hw/mips/mips_r4k.c
Fulong 2E
M: Aleksandar Markovic <aleksandar.markovic@mips.com>
M: Aleksandar Markovic <amarkovic@wavecomp.com>
S: Odd Fixes
F: hw/mips/mips_fulong2e.c
F: hw/isa/vt82c686.c
F: include/hw/isa/vt82c686.h
Boston
M: Paul Burton <paul.burton@mips.com>
M: Paul Burton <pburton@wavecomp.com>
S: Maintained
F: hw/core/loader-fit.c
F: hw/mips/boston.c
@@ -1323,6 +1328,12 @@ F: hw/core/generic-loader.c
F: include/hw/core/generic-loader.h
F: docs/generic-loader.txt
Intel Hexadecimal Object File Loader
M: Su Hang <suhang16@mails.ucas.ac.cn>
S: Maintained
F: tests/hexloader-test.c
F: tests/hex-loader-check-data/test.hex
CHRP NVRAM
M: Thomas Huth <thuth@redhat.com>
S: Maintained

View File

@@ -357,6 +357,7 @@ DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7
DOCS+=docs/interop/qemu-ga-ref.html docs/interop/qemu-ga-ref.txt docs/interop/qemu-ga-ref.7
DOCS+=docs/qemu-block-drivers.7
DOCS+=docs/qemu-cpu-models.7
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
@@ -778,6 +779,7 @@ distclean: clean
rm -f docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf
rm -f docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html
rm -f docs/qemu-block-drivers.7
rm -f docs/qemu-cpu-models.7
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
@@ -823,6 +825,7 @@ ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man7"
$(INSTALL_DATA) docs/interop/qemu-qmp-ref.7 "$(DESTDIR)$(mandir)/man7"
$(INSTALL_DATA) docs/qemu-block-drivers.7 "$(DESTDIR)$(mandir)/man7"
$(INSTALL_DATA) docs/qemu-cpu-models.7 "$(DESTDIR)$(mandir)/man7"
ifneq ($(TOOLS),)
$(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
@@ -965,6 +968,7 @@ fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi
qemu-ga.8: qemu-ga.texi
docs/qemu-block-drivers.7: docs/qemu-block-drivers.texi
docs/qemu-cpu-models.7: docs/qemu-cpu-models.texi
html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html
info: qemu-doc.info docs/interop/qemu-qmp-ref.info docs/interop/qemu-ga-ref.info
@@ -974,7 +978,8 @@ txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \
qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
qemu-monitor-info.texi docs/qemu-block-drivers.texi
qemu-monitor-info.texi docs/qemu-block-drivers.texi \
docs/qemu-cpu-models.texi
docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \
docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \

View File

@@ -240,6 +240,7 @@ trace-events-subdirs += hw/tpm
trace-events-subdirs += hw/usb
trace-events-subdirs += hw/vfio
trace-events-subdirs += hw/virtio
trace-events-subdirs += hw/watchdog
trace-events-subdirs += hw/xen
trace-events-subdirs += io
trace-events-subdirs += linux-user

View File

@@ -1 +1 @@
3.0.0
3.0.50

View File

@@ -39,6 +39,7 @@
#include "trace.h"
#include "hw/irq.h"
#include "sysemu/sev.h"
#include "sysemu/balloon.h"
#include "hw/boards.h"
@@ -1698,6 +1699,9 @@ static int kvm_init(MachineState *ms)
s->many_ioeventfds = kvm_check_many_ioeventfds();
s->sync_mmu = !!kvm_vm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
if (!s->sync_mmu) {
qemu_balloon_inhibit(true);
}
return 0;

View File

@@ -332,6 +332,9 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
desc.trace_vcpu_dstate = *cpu->trace_dstate;
desc.pc = pc;
phys_pc = get_page_addr_code(desc.env, pc);
if (phys_pc == -1) {
return NULL;
}
desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
h = tb_hash_func(phys_pc, pc, flags, cf_mask, *cpu->trace_dstate);
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);

View File

@@ -741,39 +741,6 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
prot, mmu_idx, size);
}
static void report_bad_exec(CPUState *cpu, target_ulong addr)
{
/* Accidentally executing outside RAM or ROM is quite common for
* several user-error situations, so report it in a way that
* makes it clear that this isn't a QEMU bug and provide suggestions
* about what a user could do to fix things.
*/
error_report("Trying to execute code outside RAM or ROM at 0x"
TARGET_FMT_lx, addr);
error_printf("This usually means one of the following happened:\n\n"
"(1) You told QEMU to execute a kernel for the wrong machine "
"type, and it crashed on startup (eg trying to run a "
"raspberry pi kernel on a versatilepb QEMU machine)\n"
"(2) You didn't give QEMU a kernel or BIOS filename at all, "
"and QEMU executed a ROM full of no-op instructions until "
"it fell off the end\n"
"(3) Your guest kernel has a bug and crashed by jumping "
"off into nowhere\n\n"
"This is almost always one of the first two, so check your "
"command line and that you are using the right type of kernel "
"for this machine.\n"
"If you think option (3) is likely then you can try debugging "
"your guest with the -d debug options; in particular "
"-d guest_errors will cause the log to include a dump of the "
"guest register state at this point.\n\n"
"Execution cannot continue; stopping here.\n\n");
/* Report also to the logs, with more detail including register dump */
qemu_log_mask(LOG_GUEST_ERROR, "qemu: fatal: Trying to execute code "
"outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
log_cpu_state_mask(LOG_GUEST_ERROR, cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
}
static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
{
ram_addr_t ram_addr;
@@ -789,7 +756,7 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
int mmu_idx,
target_ulong addr, uintptr_t retaddr,
bool recheck, int size)
bool recheck, MMUAccessType access_type, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr mr_offset;
@@ -831,6 +798,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
}
cpu->mem_io_vaddr = addr;
cpu->mem_io_access_type = access_type;
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
qemu_mutex_lock_iothread();
@@ -843,7 +811,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
section->offset_within_address_space -
section->offset_within_region;
cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_LOAD,
cpu_transaction_failed(cpu, physaddr, addr, size, access_type,
mmu_idx, iotlbentry->attrs, r, retaddr);
}
if (locked) {
@@ -958,11 +926,6 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
{
int mmu_idx, index;
void *p;
MemoryRegion *mr;
MemoryRegionSection *section;
CPUState *cpu = ENV_GET_CPU(env);
CPUIOTLBEntry *iotlbentry;
hwaddr physaddr, mr_offset;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = cpu_mmu_index(env, true);
@@ -973,69 +936,19 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
assert(tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr));
}
if (unlikely(env->tlb_table[mmu_idx][index].addr_code & TLB_RECHECK)) {
if (unlikely(env->tlb_table[mmu_idx][index].addr_code &
(TLB_RECHECK | TLB_MMIO))) {
/*
* This is a TLB_RECHECK access, where the MMU protection
* covers a smaller range than a target page, and we must
* repeat the MMU check here. This tlb_fill() call might
* longjump out if this access should cause a guest exception.
*/
int index;
target_ulong tlb_addr;
tlb_fill(cpu, addr, 0, MMU_INST_FETCH, mmu_idx, 0);
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
tlb_addr = env->tlb_table[mmu_idx][index].addr_code;
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
/* RAM access. We can't handle this, so for now just stop */
cpu_abort(cpu, "Unable to handle guest executing from RAM within "
"a small MPU region at 0x" TARGET_FMT_lx, addr);
}
/*
* Fall through to handle IO accesses (which will almost certainly
* also result in failure)
* Return -1 if we can't translate and execute from an entire
* page of RAM here, which will cause us to execute by loading
* and translating one insn at a time, without caching:
* - TLB_RECHECK: means the MMU protection covers a smaller range
* than a target page, so we must redo the MMU check every insn
* - TLB_MMIO: region is not backed by RAM
*/
return -1;
}
iotlbentry = &env->iotlb[mmu_idx][index];
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
if (memory_region_is_unassigned(mr)) {
qemu_mutex_lock_iothread();
if (memory_region_request_mmio_ptr(mr, addr)) {
qemu_mutex_unlock_iothread();
/* A MemoryRegion is potentially added so re-run the
* get_page_addr_code.
*/
return get_page_addr_code(env, addr);
}
qemu_mutex_unlock_iothread();
/* Give the new-style cpu_transaction_failed() hook first chance
* to handle this.
* This is not the ideal place to detect and generate CPU
* exceptions for instruction fetch failure (for instance
* we don't know the length of the access that the CPU would
* use, and it would be better to go ahead and try the access
* and use the MemTXResult it produced). However it is the
* simplest place we have currently available for the check.
*/
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
physaddr = mr_offset +
section->offset_within_address_space -
section->offset_within_region;
cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx,
iotlbentry->attrs, MEMTX_DECODE_ERROR, 0);
cpu_unassigned_access(cpu, addr, false, true, 0, 4);
/* The CPU's unassigned access hook might have longjumped out
* with an exception. If it didn't (or there was no hook) then
* we can't proceed further.
*/
report_bad_exec(cpu, addr);
exit(1);
}
p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
return qemu_ram_addr_from_host_nofail(p);
}

View File

@@ -99,11 +99,12 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
size_t mmu_idx, size_t index,
target_ulong addr,
uintptr_t retaddr,
bool recheck)
bool recheck,
MMUAccessType access_type)
{
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, recheck,
DATA_SIZE);
access_type, DATA_SIZE);
}
#endif
@@ -140,7 +141,8 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
/* ??? Note that the io helpers always read data in the target
byte ordering. We should push the LE/BE request down into io. */
res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
tlb_addr & TLB_RECHECK);
tlb_addr & TLB_RECHECK,
READ_ACCESS_TYPE);
res = TGT_LE(res);
return res;
}
@@ -207,7 +209,8 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
/* ??? Note that the io helpers always read data in the target
byte ordering. We should push the LE/BE request down into io. */
res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
tlb_addr & TLB_RECHECK);
tlb_addr & TLB_RECHECK,
READ_ACCESS_TYPE);
res = TGT_BE(res);
return res;
}

View File

@@ -1493,7 +1493,7 @@ static void tb_phys_invalidate__locked(TranslationBlock *tb)
*/
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
{
if (page_addr == -1) {
if (page_addr == -1 && tb->page_addr[0] != -1) {
page_lock_tb(tb);
do_tb_phys_invalidate(tb, true);
page_unlock_tb(tb);
@@ -1608,6 +1608,17 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
assert_memory_lock();
if (phys_pc == -1) {
/*
* If the TB is not associated with a physical RAM page then
* it must be a temporary one-insn TB, and we have nothing to do
* except fill in the page_addr[] fields.
*/
assert(tb->cflags & CF_NOCACHE);
tb->page_addr[0] = tb->page_addr[1] = -1;
return tb;
}
/*
* Add the TB to the page list, acquiring first the pages's locks.
* We keep the locks held until after inserting the TB in the hash table,
@@ -1677,6 +1688,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
phys_pc = get_page_addr_code(env, pc);
if (phys_pc == -1) {
/* Generate a temporary TB with 1 insn in it */
cflags &= ~CF_COUNT_MASK;
cflags |= CF_NOCACHE | 1;
}
buffer_overflow:
tb = tb_alloc(pc);
if (unlikely(!tb)) {
@@ -2121,7 +2138,9 @@ void tb_check_watchpoint(CPUState *cpu)
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
addr = get_page_addr_code(env, pc);
tb_invalidate_phys_range(addr, addr + 1);
if (addr != -1) {
tb_invalidate_phys_range(addr, addr + 1);
}
}
}

View File

@@ -26,6 +26,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/atomic.h"
#include "exec/cpu-common.h"
#include "sysemu/kvm.h"
#include "sysemu/balloon.h"
@@ -37,16 +38,22 @@
static QEMUBalloonEvent *balloon_event_fn;
static QEMUBalloonStatus *balloon_stat_fn;
static void *balloon_opaque;
static bool balloon_inhibited;
static int balloon_inhibit_count;
bool qemu_balloon_is_inhibited(void)
{
return balloon_inhibited;
return atomic_read(&balloon_inhibit_count) > 0;
}
void qemu_balloon_inhibit(bool state)
{
balloon_inhibited = state;
if (state) {
atomic_inc(&balloon_inhibit_count);
} else {
atomic_dec(&balloon_inhibit_count);
}
assert(atomic_read(&balloon_inhibit_count) >= 0);
}
static bool have_balloon(Error **errp)

46
block.c
View File

@@ -2584,6 +2584,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
BlockBackend *file = NULL;
BlockDriverState *bs;
BlockDriver *drv = NULL;
BdrvChild *child;
const char *drvname;
const char *backing;
Error *local_err = NULL;
@@ -2767,6 +2768,15 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
}
}
/* Remove all children options from bs->options and bs->explicit_options */
QLIST_FOREACH(child, &bs->children, next) {
char *child_key_dot;
child_key_dot = g_strdup_printf("%s.", child->name);
qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot);
qdict_extract_subqdict(bs->options, NULL, child_key_dot);
g_free(child_key_dot);
}
bdrv_refresh_filename(bs);
/* Check if any unknown options were used */
@@ -2976,6 +2986,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
}
child_key_dot = g_strdup_printf("%s.", child->name);
qdict_extract_subqdict(explicit_options, NULL, child_key_dot);
qdict_extract_subqdict(options, &new_child_options, child_key_dot);
g_free(child_key_dot);
@@ -3039,12 +3050,13 @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
cleanup:
QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
if (ret && bs_entry->prepared) {
bdrv_reopen_abort(&bs_entry->state);
} else if (ret) {
if (ret) {
if (bs_entry->prepared) {
bdrv_reopen_abort(&bs_entry->state);
}
qobject_unref(bs_entry->state.explicit_options);
qobject_unref(bs_entry->state.options);
}
qobject_unref(bs_entry->state.options);
g_free(bs_entry);
}
g_free(bs_queue);
@@ -3144,6 +3156,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
Error *local_err = NULL;
BlockDriver *drv;
QemuOpts *opts;
QDict *orig_reopen_opts;
const char *value;
bool read_only;
@@ -3151,6 +3164,11 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
assert(reopen_state->bs->drv != NULL);
drv = reopen_state->bs->drv;
/* This function and each driver's bdrv_reopen_prepare() remove
* entries from reopen_state->options as they are processed, so
* we need to make a copy of the original QDict. */
orig_reopen_opts = qdict_clone_shallow(reopen_state->options);
/* Process generic block layer options */
opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, reopen_state->options, &local_err);
@@ -3257,8 +3275,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
ret = 0;
/* Restore the original reopen_state->options QDict */
qobject_unref(reopen_state->options);
reopen_state->options = qobject_ref(orig_reopen_opts);
error:
qemu_opts_del(opts);
qobject_unref(orig_reopen_opts);
return ret;
}
@@ -3288,8 +3311,10 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
/* set BDS specific flags now */
qobject_unref(bs->explicit_options);
qobject_unref(bs->options);
bs->explicit_options = reopen_state->explicit_options;
bs->options = reopen_state->options;
bs->open_flags = reopen_state->flags;
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
@@ -3330,8 +3355,6 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
drv->bdrv_reopen_abort(reopen_state);
}
qobject_unref(reopen_state->explicit_options);
bdrv_abort_perm_update(reopen_state->bs);
}
@@ -3349,7 +3372,9 @@ static void bdrv_close(BlockDriverState *bs)
bdrv_drain(bs); /* in case flush left pending I/O */
if (bs->drv) {
bs->drv->bdrv_close(bs);
if (bs->drv->bdrv_close) {
bs->drv->bdrv_close(bs);
}
bs->drv = NULL;
}
@@ -5125,16 +5150,13 @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
QemuOptDesc *desc;
BdrvChild *child;
bool found_any = false;
const char *p;
for (entry = qdict_first(bs->options); entry;
entry = qdict_next(bs->options, entry))
{
/* Exclude options for children */
/* Exclude node-name references to children */
QLIST_FOREACH(child, &bs->children, next) {
if (strstart(qdict_entry_key(entry), child->name, &p)
&& (!*p || *p == '.'))
{
if (!strcmp(entry->key, child->name)) {
break;
}
}

View File

@@ -43,10 +43,6 @@ fail:
return ret;
}
static void blkreplay_close(BlockDriverState *bs)
{
}
static int64_t blkreplay_getlength(BlockDriverState *bs)
{
return bdrv_getlength(bs->file->bs);
@@ -135,7 +131,6 @@ static BlockDriver bdrv_blkreplay = {
.instance_size = 0,
.bdrv_open = blkreplay_open,
.bdrv_close = blkreplay_close,
.bdrv_child_perm = bdrv_filter_default_perms,
.bdrv_getlength = blkreplay_getlength,

View File

@@ -419,7 +419,6 @@ static void drive_info_del(DriveInfo *dinfo)
return;
}
qemu_opts_del(dinfo->opts);
g_free(dinfo->serial);
g_free(dinfo);
}

View File

@@ -239,10 +239,6 @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
bs->backing->bs->filename);
}
static void bdrv_commit_top_close(BlockDriverState *bs)
{
}
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
const BdrvChildRole *role,
BlockReopenQueue *reopen_queue,
@@ -260,7 +256,6 @@ static BlockDriver bdrv_commit_top = {
.bdrv_co_preadv = bdrv_commit_top_preadv,
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
.bdrv_close = bdrv_commit_top_close,
.bdrv_child_perm = bdrv_commit_top_child_perm,
};

View File

@@ -45,11 +45,6 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
}
static void cor_close(BlockDriverState *bs)
{
}
#define PERM_PASSTHROUGH (BLK_PERM_CONSISTENT_READ \
| BLK_PERM_WRITE \
| BLK_PERM_RESIZE)
@@ -143,7 +138,6 @@ BlockDriver bdrv_copy_on_read = {
.format_name = "copy-on-read",
.bdrv_open = cor_open,
.bdrv_close = cor_close,
.bdrv_child_perm = cor_child_perm,
.bdrv_getlength = cor_getlength,

View File

@@ -627,7 +627,9 @@ BlockDriver bdrv_crypto_luks = {
.bdrv_probe = block_crypto_probe_luks,
.bdrv_open = block_crypto_open_luks,
.bdrv_close = block_crypto_close,
.bdrv_child_perm = bdrv_format_default_perms,
/* This driver doesn't modify LUKS metadata except when creating image.
* Allow share-rw=on as a special case. */
.bdrv_child_perm = bdrv_filter_default_perms,
.bdrv_co_create = block_crypto_co_create_luks,
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
.bdrv_co_truncate = block_crypto_co_truncate,

View File

@@ -1426,10 +1426,6 @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
bs->backing->bs->filename);
}
static void bdrv_mirror_top_close(BlockDriverState *bs)
{
}
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
const BdrvChildRole *role,
BlockReopenQueue *reopen_queue,
@@ -1456,7 +1452,6 @@ static BlockDriver bdrv_mirror_top = {
.bdrv_co_flush = bdrv_mirror_top_flush,
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
.bdrv_close = bdrv_mirror_top_close,
.bdrv_child_perm = bdrv_mirror_top_child_perm,
};
@@ -1499,6 +1494,11 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
buf_size = DEFAULT_MIRROR_BUF_SIZE;
}
if (bs == target) {
error_setg(errp, "Can't mirror node into itself");
return;
}
/* In the case of active commit, add dummy driver to provide consistent
* reads on the top, while disabling it in the intermediate nodes, and make
* the backing chain writable. */

View File

@@ -97,10 +97,6 @@ static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
static void null_close(BlockDriverState *bs)
{
}
static int64_t null_getlength(BlockDriverState *bs)
{
BDRVNullState *s = bs->opaque;
@@ -263,7 +259,6 @@ static BlockDriver bdrv_null_co = {
.bdrv_file_open = null_file_open,
.bdrv_parse_filename = null_co_parse_filename,
.bdrv_close = null_close,
.bdrv_getlength = null_getlength,
.bdrv_co_preadv = null_co_preadv,
@@ -283,7 +278,6 @@ static BlockDriver bdrv_null_aio = {
.bdrv_file_open = null_file_open,
.bdrv_parse_filename = null_aio_parse_filename,
.bdrv_close = null_close,
.bdrv_getlength = null_getlength,
.bdrv_aio_preadv = null_aio_preadv,

View File

@@ -104,7 +104,7 @@ typedef struct {
uint64_t nsze; /* Namespace size reported by identify command */
int nsid; /* The namespace id to read/write data. */
uint64_t max_transfer;
int plugged;
bool plugged;
CoMutex dma_map_lock;
CoQueue dma_flush_queue;
@@ -569,13 +569,13 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
s->vfio = qemu_vfio_open_pci(device, errp);
if (!s->vfio) {
ret = -EINVAL;
goto fail;
goto out;
}
s->regs = qemu_vfio_pci_map_bar(s->vfio, 0, 0, NVME_BAR_SIZE, errp);
if (!s->regs) {
ret = -EINVAL;
goto fail;
goto out;
}
/* Perform initialize sequence as described in NVMe spec "7.6.1
@@ -585,7 +585,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
if (!(cap & (1ULL << 37))) {
error_setg(errp, "Device doesn't support NVMe command set");
ret = -EINVAL;
goto fail;
goto out;
}
s->page_size = MAX(4096, 1 << (12 + ((cap >> 48) & 0xF)));
@@ -603,7 +603,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
PRId64 " ms)",
timeout_ms);
ret = -ETIMEDOUT;
goto fail;
goto out;
}
}
@@ -613,7 +613,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
s->queues[0] = nvme_create_queue_pair(bs, 0, NVME_QUEUE_SIZE, errp);
if (!s->queues[0]) {
ret = -EINVAL;
goto fail;
goto out;
}
QEMU_BUILD_BUG_ON(NVME_QUEUE_SIZE & 0xF000);
s->regs->aqa = cpu_to_le32((NVME_QUEUE_SIZE << 16) | NVME_QUEUE_SIZE);
@@ -633,14 +633,14 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
PRId64 " ms)",
timeout_ms);
ret = -ETIMEDOUT;
goto fail_queue;
goto out;
}
}
ret = qemu_vfio_pci_init_irq(s->vfio, &s->irq_notifier,
VFIO_PCI_MSIX_IRQ_INDEX, errp);
if (ret) {
goto fail_queue;
goto out;
}
aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier,
false, nvme_handle_event, nvme_poll_cb);
@@ -649,30 +649,15 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
if (local_err) {
error_propagate(errp, local_err);
ret = -EIO;
goto fail_handler;
goto out;
}
/* Set up command queues. */
if (!nvme_add_io_queue(bs, errp)) {
ret = -EIO;
goto fail_handler;
}
return 0;
fail_handler:
aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier,
false, NULL, NULL);
fail_queue:
nvme_free_queue_pair(bs, s->queues[0]);
fail:
g_free(s->queues);
if (s->regs) {
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
}
if (s->vfio) {
qemu_vfio_close(s->vfio);
}
event_notifier_cleanup(&s->irq_notifier);
out:
/* Cleaning up is done in nvme_file_open() upon error. */
return ret;
}
@@ -739,8 +724,10 @@ static void nvme_close(BlockDriverState *bs)
for (i = 0; i < s->nr_queues; ++i) {
nvme_free_queue_pair(bs, s->queues[i]);
}
g_free(s->queues);
aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier,
false, NULL, NULL);
event_notifier_cleanup(&s->irq_notifier);
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
qemu_vfio_close(s->vfio);
}
@@ -1114,7 +1101,8 @@ static void nvme_attach_aio_context(BlockDriverState *bs,
static void nvme_aio_plug(BlockDriverState *bs)
{
BDRVNVMeState *s = bs->opaque;
s->plugged++;
assert(!s->plugged);
s->plugged = true;
}
static void nvme_aio_unplug(BlockDriverState *bs)
@@ -1122,14 +1110,13 @@ static void nvme_aio_unplug(BlockDriverState *bs)
int i;
BDRVNVMeState *s = bs->opaque;
assert(s->plugged);
if (!--s->plugged) {
for (i = 1; i < s->nr_queues; i++) {
NVMeQueuePair *q = s->queues[i];
qemu_mutex_lock(&q->lock);
nvme_kick(s, q);
nvme_process_completion(s, q);
qemu_mutex_unlock(&q->lock);
}
s->plugged = false;
for (i = 1; i < s->nr_queues; i++) {
NVMeQueuePair *q = s->queues[i];
qemu_mutex_lock(&q->lock);
nvme_kick(s, q);
nvme_process_completion(s, q);
qemu_mutex_unlock(&q->lock);
}
}

View File

@@ -594,7 +594,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
}
} else {
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
BlockStatsList *info = g_malloc0(sizeof(*info));
BlockStatsList *info;
AioContext *ctx = blk_get_aio_context(blk);
BlockStats *s;
char *qdev;
@@ -619,6 +619,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
bdrv_query_blk_stats(s->stats, blk);
aio_context_release(ctx);
info = g_malloc0(sizeof(*info));
info->value = s;
*p_next = info;
p_next = &info->next;

View File

@@ -459,10 +459,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
return 0;
}
static void raw_close(BlockDriverState *bs)
{
}
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
{
/* smallest possible positive score so that raw is used if and only if no
@@ -543,7 +539,6 @@ BlockDriver bdrv_raw = {
.bdrv_reopen_commit = &raw_reopen_commit,
.bdrv_reopen_abort = &raw_reopen_abort,
.bdrv_open = &raw_open,
.bdrv_close = &raw_close,
.bdrv_child_perm = bdrv_filter_default_perms,
.bdrv_co_create_opts = &raw_co_create_opts,
.bdrv_co_preadv = &raw_co_preadv,

View File

@@ -218,7 +218,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
qobject_unref(file_options);
qdict_put_str(options, "file", bdrv_get_node_name(file));
drv->bdrv_close(bs);
if (drv->bdrv_close) {
drv->bdrv_close(bs);
}
bdrv_unref_child(bs, bs->file);
bs->file = NULL;

View File

@@ -36,6 +36,7 @@
static void throttle_group_obj_init(Object *obj);
static void throttle_group_obj_complete(UserCreatable *obj, Error **errp);
static void timer_cb(ThrottleGroupMember *tgm, bool is_write);
/* The ThrottleGroup structure (with its ThrottleState) is shared
* among different ThrottleGroupMembers and it's independent from
@@ -221,6 +222,15 @@ static ThrottleGroupMember *next_throttle_token(ThrottleGroupMember *tgm,
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
ThrottleGroupMember *token, *start;
/* If this member has its I/O limits disabled then it means that
* it's being drained. Skip the round-robin search and return tgm
* immediately if it has pending requests. Otherwise we could be
* forcing it to wait for other member's throttled requests. */
if (tgm_has_pending_reqs(tgm, is_write) &&
atomic_read(&tgm->io_limits_disabled)) {
return tgm;
}
start = token = tg->tokens[is_write];
/* get next bs round in round robin style */
@@ -415,15 +425,31 @@ static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write
rd->tgm = tgm;
rd->is_write = is_write;
/* This function is called when a timer is fired or when
* throttle_group_restart_tgm() is called. Either way, there can
* be no timer pending on this tgm at this point */
assert(!timer_pending(tgm->throttle_timers.timers[is_write]));
co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd);
aio_co_enter(tgm->aio_context, co);
}
void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
{
int i;
if (tgm->throttle_state) {
throttle_group_restart_queue(tgm, 0);
throttle_group_restart_queue(tgm, 1);
for (i = 0; i < 2; i++) {
QEMUTimer *t = tgm->throttle_timers.timers[i];
if (timer_pending(t)) {
/* If there's a pending timer on this tgm, fire it now */
timer_del(t);
timer_cb(tgm, i);
} else {
/* Else run the next request from the queue manually */
throttle_group_restart_queue(tgm, i);
}
}
}
}
@@ -558,16 +584,11 @@ void throttle_group_unregister_tgm(ThrottleGroupMember *tgm)
return;
}
assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
assert(qemu_co_queue_empty(&tgm->throttled_reqs[0]));
assert(qemu_co_queue_empty(&tgm->throttled_reqs[1]));
qemu_mutex_lock(&tg->lock);
for (i = 0; i < 2; i++) {
if (timer_pending(tgm->throttle_timers.timers[i])) {
tg->any_timer_armed[i] = false;
schedule_next_request(tgm, i);
}
assert(tgm->pending_reqs[i] == 0);
assert(qemu_co_queue_empty(&tgm->throttled_reqs[i]));
assert(!timer_pending(tgm->throttle_timers.timers[i]));
if (tg->tokens[i] == tgm) {
token = throttle_group_next_tgm(tgm);
/* Take care of the case where this is the last tgm in the group */

View File

@@ -730,30 +730,6 @@ QemuOptsList qemu_legacy_drive_opts = {
.name = "if",
.type = QEMU_OPT_STRING,
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
},{
.name = "cyls",
.type = QEMU_OPT_NUMBER,
.help = "number of cylinders (ide disk geometry)",
},{
.name = "heads",
.type = QEMU_OPT_NUMBER,
.help = "number of heads (ide disk geometry)",
},{
.name = "secs",
.type = QEMU_OPT_NUMBER,
.help = "number of sectors (ide disk geometry)",
},{
.name = "trans",
.type = QEMU_OPT_STRING,
.help = "chs translation (auto, lba, none)",
},{
.name = "addr",
.type = QEMU_OPT_STRING,
.help = "pci address (virtio only)",
},{
.name = "serial",
.type = QEMU_OPT_STRING,
.help = "disk serial number",
},{
.name = "file",
.type = QEMU_OPT_STRING,
@@ -792,19 +768,13 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
QemuOpts *legacy_opts;
DriveMediaType media = MEDIA_DISK;
BlockInterfaceType type;
int cyls, heads, secs, translation;
int max_devs, bus_id, unit_id, index;
const char *devaddr;
const char *werror, *rerror;
bool read_only = false;
bool copy_on_read;
const char *serial;
const char *filename;
Error *local_err = NULL;
int i;
const char *deprecated[] = {
"serial", "trans", "secs", "heads", "cyls", "addr"
};
/* Change legacy command line options into QMP ones */
static const struct {
@@ -881,16 +851,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
goto fail;
}
/* Other deprecated options */
if (!qtest_enabled()) {
for (i = 0; i < ARRAY_SIZE(deprecated); i++) {
if (qemu_opt_get(legacy_opts, deprecated[i]) != NULL) {
error_report("'%s' is deprecated, please use the corresponding "
"option of '-device' instead", deprecated[i]);
}
}
}
/* Media type */
value = qemu_opt_get(legacy_opts, "media");
if (value) {
@@ -932,57 +892,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
type = block_default_type;
}
/* Geometry */
cyls = qemu_opt_get_number(legacy_opts, "cyls", 0);
heads = qemu_opt_get_number(legacy_opts, "heads", 0);
secs = qemu_opt_get_number(legacy_opts, "secs", 0);
if (cyls || heads || secs) {
if (cyls < 1) {
error_report("invalid physical cyls number");
goto fail;
}
if (heads < 1) {
error_report("invalid physical heads number");
goto fail;
}
if (secs < 1) {
error_report("invalid physical secs number");
goto fail;
}
}
translation = BIOS_ATA_TRANSLATION_AUTO;
value = qemu_opt_get(legacy_opts, "trans");
if (value != NULL) {
if (!cyls) {
error_report("'%s' trans must be used with cyls, heads and secs",
value);
goto fail;
}
if (!strcmp(value, "none")) {
translation = BIOS_ATA_TRANSLATION_NONE;
} else if (!strcmp(value, "lba")) {
translation = BIOS_ATA_TRANSLATION_LBA;
} else if (!strcmp(value, "large")) {
translation = BIOS_ATA_TRANSLATION_LARGE;
} else if (!strcmp(value, "rechs")) {
translation = BIOS_ATA_TRANSLATION_RECHS;
} else if (!strcmp(value, "auto")) {
translation = BIOS_ATA_TRANSLATION_AUTO;
} else {
error_report("'%s' invalid translation type", value);
goto fail;
}
}
if (media == MEDIA_CDROM) {
if (cyls || secs || heads) {
error_report("CHS can't be set with media=cdrom");
goto fail;
}
}
/* Device address specified by bus/unit or index.
* If none was specified, try to find the first free one. */
bus_id = qemu_opt_get_number(legacy_opts, "bus", 0);
@@ -1022,9 +931,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
goto fail;
}
/* Serial number */
serial = qemu_opt_get(legacy_opts, "serial");
/* no id supplied -> create one */
if (qemu_opts_id(all_opts) == NULL) {
char *new_id;
@@ -1044,12 +950,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
}
/* Add virtio block device */
devaddr = qemu_opt_get(legacy_opts, "addr");
if (devaddr && type != IF_VIRTIO) {
error_report("addr is not supported by this bus type");
goto fail;
}
if (type == IF_VIRTIO) {
QemuOpts *devopts;
devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
@@ -1061,9 +961,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
}
qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
&error_abort);
if (devaddr) {
qemu_opt_set(devopts, "addr", devaddr, &error_abort);
}
}
filename = qemu_opt_get(legacy_opts, "file");
@@ -1105,16 +1002,9 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
dinfo = g_malloc0(sizeof(*dinfo));
dinfo->opts = all_opts;
dinfo->cyls = cyls;
dinfo->heads = heads;
dinfo->secs = secs;
dinfo->trans = translation;
dinfo->type = type;
dinfo->bus = bus_id;
dinfo->unit = unit_id;
dinfo->devaddr = devaddr;
dinfo->serial = g_strdup(serial);
blk_set_legacy_dinfo(blk, dinfo);

View File

@@ -29,6 +29,7 @@
#include "qemu/error-report.h"
#include "sysemu/reset.h"
#include "hw/qdev-core.h"
#include "hw/boards.h"
typedef struct FWBootEntry FWBootEntry;
@@ -208,11 +209,13 @@ DeviceState *get_boot_device(uint32_t position)
* memory pointed by "size" is assigned total length of the array in bytes
*
*/
char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
char *get_boot_devices_list(size_t *size)
{
FWBootEntry *i;
size_t total = 0;
char *list = NULL;
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
bool ignore_suffixes = mc->ignore_boot_device_suffixes;
QTAILQ_FOREACH(i, &fw_boot_order, link) {
char *devpath = NULL, *suffix = NULL;

59
configure vendored
View File

@@ -375,6 +375,7 @@ hax="no"
hvf="no"
whpx="no"
rdma=""
pvrdma=""
gprof="no"
debug_tcg="no"
debug="no"
@@ -1363,6 +1364,10 @@ for opt do
;;
--disable-rdma) rdma="no"
;;
--enable-pvrdma) pvrdma="yes"
;;
--disable-pvrdma) pvrdma="no"
;;
--with-gtkabi=*) gtkabi="$optarg"
;;
--disable-vte) vte="no"
@@ -1669,7 +1674,8 @@ disabled with --disable-FEATURE, default is enabled if available:
hax HAX acceleration support
hvf Hypervisor.framework acceleration support
whpx Windows Hypervisor Platform acceleration support
rdma Enable RDMA-based migration and PVRDMA support
rdma Enable RDMA-based migration
pvrdma Enable PVRDMA support
vde support for vde network
netmap support for netmap network
linux-aio Linux AIO support
@@ -3064,6 +3070,48 @@ EOF
fi
fi
##########################################
# PVRDMA detection
cat > $TMPC <<EOF &&
#include <sys/mman.h>
int
main(void)
{
char buf = 0;
void *addr = &buf;
addr = mremap(addr, 0, 1, MREMAP_MAYMOVE | MREMAP_FIXED);
return 0;
}
EOF
if test "$rdma" = "yes" ; then
case "$pvrdma" in
"")
if compile_prog "" ""; then
pvrdma="yes"
else
pvrdma="no"
fi
;;
"yes")
if ! compile_prog "" ""; then
error_exit "PVRDMA is not supported since mremap is not implemented"
fi
pvrdma="yes"
;;
"no")
pvrdma="no"
;;
esac
else
if test "$pvrdma" = "yes" ; then
error_exit "PVRDMA requires rdma suppport"
fi
pvrdma="no"
fi
##########################################
# VNC SASL detection
@@ -5952,6 +6000,7 @@ if test "$tcg" = "yes" ; then
fi
echo "malloc trim support $malloc_trim"
echo "RDMA support $rdma"
echo "PVRDMA support $pvrdma"
echo "fdt support $fdt"
echo "membarrier $membarrier"
echo "preadv support $preadv"
@@ -6708,6 +6757,10 @@ if test "$rdma" = "yes" ; then
echo "RDMA_LIBS=$rdma_libs" >> $config_host_mak
fi
if test "$pvrdma" = "yes" ; then
echo "CONFIG_PVRDMA=y" >> $config_host_mak
fi
if test "$have_rtnetlink" = "yes" ; then
echo "CONFIG_RTNETLINK=y" >> $config_host_mak
fi
@@ -7382,6 +7435,10 @@ for test_file in $(find $source_path/tests/acpi-test-data -type f)
do
FILES="$FILES tests/acpi-test-data$(echo $test_file | sed -e 's/.*acpi-test-data//')"
done
for test_file in $(find $source_path/tests/hex-loader-check-data -type f)
do
FILES="$FILES tests/hex-loader-check-data$(echo $test_file | sed -e 's/.*hex-loader-check-data//')"
done
mkdir -p $DIRS
for f in $FILES ; do
if [ -e "$source_path/$f" ] && [ "$pwd_is_source_path" != "y" ]; then

View File

@@ -104,6 +104,7 @@ CONFIG_STM32F205_SOC=y
CONFIG_CMSDK_APB_TIMER=y
CONFIG_CMSDK_APB_UART=y
CONFIG_CMSDK_APB_WATCHDOG=y
CONFIG_MPS2_FPGAIO=y
CONFIG_MPS2_SCC=y
@@ -133,6 +134,7 @@ CONFIG_FSL_IMX6=y
CONFIG_FSL_IMX31=y
CONFIG_FSL_IMX25=y
CONFIG_FSL_IMX7=y
CONFIG_FSL_IMX6UL=y
CONFIG_IMX_I2C=y

View File

@@ -69,10 +69,6 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
if (!dinfo) {
goto err;
}
if (dinfo->devaddr) {
monitor_printf(mon, "Parameter addr not supported\n");
goto err;
}
switch (dinfo->type) {
case IF_NONE:

View File

@@ -434,6 +434,7 @@ Debugging
Add ``DEBUG=1`` and/or ``V=1`` to the make command to allow interactive
debugging and verbose output. If this is not enough, see the next section.
``V=1`` will be propagated down into the make jobs in the guest.
Manual invocation
-----------------

View File

@@ -56,25 +56,25 @@ An example of setting CPU 0's PC to 0x8000 is:
Loading Files
-------------
The loader device also allows files to be loaded into memory. It can load raw
files and ELF executable files. Raw files are loaded verbatim. ELF executable
files are loaded by an ELF loader. The syntax is shown below:
The loader device also allows files to be loaded into memory. It can load ELF,
U-Boot, and Intel HEX executable formats as well as raw images. The syntax is
shown below:
-device loader,file=<file>[,addr=<addr>][,cpu-num=<cpu-num>][,force-raw=<raw>]
<file> - A file to be loaded into memory
<addr> - The addr in memory that the file should be loaded. This is
ignored if you are using an ELF (unless force-raw is true).
This is required if you aren't loading an ELF.
<addr> - The memory address where the file should be loaded. This is
required for raw images and ignored for non-raw files.
<cpu-num> - This specifies the CPU that should be used. This is an
optional argument and will cause the CPU's PC to be set to
where the image is stored or in the case of an ELF file to
the value in the header. This option should only be used
for the boot image.
the memory address where the raw file is loaded or the entry
point specified in the executable format header. This option
should only be used for the boot image.
This will also cause the image to be written to the specified
CPU's address space. If not specified, the default is CPU 0.
<force-raw> - Setting force-raw=on forces the file to be treated as a raw
image. This can be used to load ELF files as if they were raw.
image. This can be used to load supported executable formats
as if they were raw.
All values are parsed using the standard QemuOps parsing. This allows the user
to specify any values in any format supported. By default the values

484
docs/qemu-cpu-models.texi Normal file
View File

@@ -0,0 +1,484 @@
@c man begin SYNOPSIS
QEMU / KVM CPU model configuration
@c man end
@c man begin DESCRIPTION
@menu
* recommendations_cpu_models_x86:: Recommendations for KVM CPU model configuration on x86 hosts
* cpu_model_syntax_apps:: Syntax for configuring CPU models
@end menu
QEMU / KVM virtualization supports two ways to configure CPU models
@table @option
@item Host passthrough
This passes the host CPU model features, model, stepping, exactly to the
guest. Note that KVM may filter out some host CPU model features if they
cannot be supported with virtualization. Live migration is unsafe when
this mode is used as libvirt / QEMU cannot guarantee a stable CPU is
exposed to the guest across hosts. This is the recommended CPU to use,
provided live migration is not required.
@item Named model
QEMU comes with a number of predefined named CPU models, that typically
refer to specific generations of hardware released by Intel and AMD.
These allow the guest VMs to have a degree of isolation from the host CPU,
allowing greater flexibility in live migrating between hosts with differing
hardware.
@end table
In both cases, it is possible to optionally add or remove individual CPU
features, to alter what is presented to the guest by default.
Libvirt supports a third way to configure CPU models known as "Host model".
This uses the QEMU "Named model" feature, automatically picking a CPU model
that is similar the host CPU, and then adding extra features to approximate
the host model as closely as possible. This does not guarantee the CPU family,
stepping, etc will precisely match the host CPU, as they would with "Host
passthrough", but gives much of the benefit of passthrough, while making
live migration safe.
@node recommendations_cpu_models_x86
@subsection Recommendations for KVM CPU model configuration on x86 hosts
The information that follows provides recommendations for configuring
CPU models on x86 hosts. The goals are to maximise performance, while
protecting guest OS against various CPU hardware flaws, and optionally
enabling live migration between hosts with hetergeneous CPU models.
@menu
* preferred_cpu_models_intel_x86:: Preferred CPU models for Intel x86 hosts
* important_cpu_features_intel_x86:: Important CPU features for Intel x86 hosts
* preferred_cpu_models_amd_x86:: Preferred CPU models for AMD x86 hosts
* important_cpu_features_amd_x86:: Important CPU features for AMD x86 hosts
* default_cpu_models_x86:: Default x86 CPU models
* other_non_recommended_cpu_models_x86:: Other non-recommended x86 CPUs
@end menu
@node preferred_cpu_models_intel_x86
@subsubsection Preferred CPU models for Intel x86 hosts
The following CPU models are preferred for use on Intel hosts. Administrators /
applications are recommended to use the CPU model that matches the generation
of the host CPUs in use. In a deployment with a mixture of host CPU models
between machines, if live migration compatibility is required, use the newest
CPU model that is compatible across all desired hosts.
@table @option
@item @code{Skylake-Server}
@item @code{Skylake-Server-IBRS}
Intel Xeon Processor (Skylake, 2016)
@item @code{Skylake-Client}
@item @code{Skylake-Client-IBRS}
Intel Core Processor (Skylake, 2015)
@item @code{Broadwell}
@item @code{Broadwell-IBRS}
@item @code{Broadwell-noTSX}
@item @code{Broadwell-noTSX-IBRS}
Intel Core Processor (Broadwell, 2014)
@item @code{Haswell}
@item @code{Haswell-IBRS}
@item @code{Haswell-noTSX}
@item @code{Haswell-noTSX-IBRS}
Intel Core Processor (Haswell, 2013)
@item @code{IvyBridge}
@item @code{IvyBridge-IBRS}
Intel Xeon E3-12xx v2 (Ivy Bridge, 2012)
@item @code{SandyBridge}
@item @code{SandyBridge-IBRS}
Intel Xeon E312xx (Sandy Bridge, 2011)
@item @code{Westmere}
@item @code{Westmere-IBRS}
Westmere E56xx/L56xx/X56xx (Nehalem-C, 2010)
@item @code{Nehalem}
@item @code{Nehalem-IBRS}
Intel Core i7 9xx (Nehalem Class Core i7, 2008)
@item @code{Penryn}
Intel Core 2 Duo P9xxx (Penryn Class Core 2, 2007)
@item @code{Conroe}
Intel Celeron_4x0 (Conroe/Merom Class Core 2, 2006)
@end table
@node important_cpu_features_intel_x86
@subsubsection Important CPU features for Intel x86 hosts
The following are important CPU features that should be used on Intel x86
hosts, when available in the host CPU. Some of them require explicit
configuration to enable, as they are not included by default in some, or all,
of the named CPU models listed above. In general all of these features are
included if using "Host passthrough" or "Host model".
@table @option
@item @code{pcid}
Recommended to mitigate the cost of the Meltdown (CVE-2017-5754) fix
Included by default in Haswell, Broadwell & Skylake Intel CPU models.
Should be explicitly turned on for Westmere, SandyBridge, and IvyBridge
Intel CPU models. Note that some desktop/mobile Westmere CPUs cannot
support this feature.
@item @code{spec-ctrl}
Required to enable the Spectre (CVE-2017-5753 and CVE-2017-5715) fix,
in cases where retpolines are not sufficient.
Included by default in Intel CPU models with -IBRS suffix.
Must be explicitly turned on for Intel CPU models without -IBRS suffix.
Requires the host CPU microcode to support this feature before it
can be used for guest CPUs.
@item @code{ssbd}
Required to enable the CVE-2018-3639 fix
Not included by default in any Intel CPU model.
Must be explicitly turned on for all Intel CPU models.
Requires the host CPU microcode to support this feature before it
can be used for guest CPUs.
@item @code{pdpe1gb}
Recommended to allow guest OS to use 1GB size pages
Not included by default in any Intel CPU model.
Should be explicitly turned on for all Intel CPU models.
Note that not all CPU hardware will support this feature.
@end table
@node preferred_cpu_models_amd_x86
@subsubsection Preferred CPU models for AMD x86 hosts
The following CPU models are preferred for use on Intel hosts. Administrators /
applications are recommended to use the CPU model that matches the generation
of the host CPUs in use. In a deployment with a mixture of host CPU models
between machines, if live migration compatibility is required, use the newest
CPU model that is compatible across all desired hosts.
@table @option
@item @code{EPYC}
@item @code{EPYC-IBPB}
AMD EPYC Processor (2017)
@item @code{Opteron_G5}
AMD Opteron 63xx class CPU (2012)
@item @code{Opteron_G4}
AMD Opteron 62xx class CPU (2011)
@item @code{Opteron_G3}
AMD Opteron 23xx (Gen 3 Class Opteron, 2009)
@item @code{Opteron_G2}
AMD Opteron 22xx (Gen 2 Class Opteron, 2006)
@item @code{Opteron_G1}
AMD Opteron 240 (Gen 1 Class Opteron, 2004)
@end table
@node important_cpu_features_amd_x86
@subsubsection Important CPU features for AMD x86 hosts
The following are important CPU features that should be used on AMD x86
hosts, when available in the host CPU. Some of them require explicit
configuration to enable, as they are not included by default in some, or all,
of the named CPU models listed above. In general all of these features are
included if using "Host passthrough" or "Host model".
@table @option
@item @code{ibpb}
Required to enable the Spectre (CVE-2017-5753 and CVE-2017-5715) fix,
in cases where retpolines are not sufficient.
Included by default in AMD CPU models with -IBPB suffix.
Must be explicitly turned on for AMD CPU models without -IBPB suffix.
Requires the host CPU microcode to support this feature before it
can be used for guest CPUs.
@item @code{virt-ssbd}
Required to enable the CVE-2018-3639 fix
Not included by default in any AMD CPU model.
Must be explicitly turned on for all AMD CPU models.
This should be provided to guests, even if amd-ssbd is also
provided, for maximum guest compatibility.
Note for some QEMU / libvirt versions, this must be force enabled
when when using "Host model", because this is a virtual feature
that doesn't exist in the physical host CPUs.
@item @code{amd-ssbd}
Required to enable the CVE-2018-3639 fix
Not included by default in any AMD CPU model.
Must be explicitly turned on for all AMD CPU models.
This provides higher performance than virt-ssbd so should be
exposed to guests whenever available in the host. virt-ssbd
should none the less also be exposed for maximum guest
compatability as some kernels only know about virt-ssbd.
@item @code{amd-no-ssb}
Recommended to indicate the host is not vulnerable CVE-2018-3639
Not included by default in any AMD CPU model.
Future hardware genarations of CPU will not be vulnerable to
CVE-2018-3639, and thus the guest should be told not to enable
its mitigations, by exposing amd-no-ssb. This is mutually
exclusive with virt-ssbd and amd-ssbd.
@item @code{pdpe1gb}
Recommended to allow guest OS to use 1GB size pages
Not included by default in any AMD CPU model.
Should be explicitly turned on for all AMD CPU models.
Note that not all CPU hardware will support this feature.
@end table
@node default_cpu_models_x86
@subsubsection Default x86 CPU models
The default QEMU CPU models are designed such that they can run on all hosts.
If an application does not wish to do perform any host compatibility checks
before launching guests, the default is guaranteed to work.
The default CPU models will, however, leave the guest OS vulnerable to various
CPU hardware flaws, so their use is strongly discouraged. Applications should
follow the earlier guidance to setup a better CPU configuration, with host
passthrough recommended if live migration is not needed.
@table @option
@item @code{qemu32}
@item @code{qemu64}
QEMU Virtual CPU version 2.5+ (32 & 64 bit variants)
qemu64 is used for x86_64 guests and qemu32 is used for i686 guests, when no
-cpu argument is given to QEMU, or no <cpu> is provided in libvirt XML.
@end table
@node other_non_recommended_cpu_models_x86
@subsubsection Other non-recommended x86 CPUs
The following CPUs models are compatible with most AMD and Intel x86 hosts, but
their usage is discouraged, as they expose a very limited featureset, which
prevents guests having optimal performance.
@table @option
@item @code{kvm32}
@item @code{kvm64}
Common KVM processor (32 & 64 bit variants)
Legacy models just for historical compatibility with ancient QEMU versions.
@item @code{486}
@item @code{athlon}
@item @code{phenom}
@item @code{coreduo}
@item @code{core2duo}
@item @code{n270}
@item @code{pentium}
@item @code{pentium2}
@item @code{pentium3}
Various very old x86 CPU models, mostly predating the introduction of
hardware assisted virtualization, that should thus not be required for
running virtual machines.
@end table
@node cpu_model_syntax_apps
@subsection Syntax for configuring CPU models
The example below illustrate the approach to configuring the various
CPU models / features in QEMU and libvirt
@menu
* cpu_model_syntax_qemu:: QEMU command line
* cpu_model_syntax_libvirt:: Libvirt guest XML
@end menu
@node cpu_model_syntax_qemu
@subsubsection QEMU command line
@table @option
@item Host passthrough
@example
$ qemu-system-x86_64 -cpu host
@end example
With feature customization:
@example
$ qemu-system-x86_64 -cpu host,-vmx,...
@end example
@item Named CPU models
@example
$ qemu-system-x86_64 -cpu Westmere
@end example
With feature customization:
@example
$ qemu-system-x86_64 -cpu Westmere,+pcid,...
@end example
@end table
@node cpu_model_syntax_libvirt
@subsubsection Libvirt guest XML
@table @option
@item Host passthrough
@example
<cpu mode='host-passthrough'/>
@end example
With feature customization:
@example
<cpu mode='host-passthrough'>
<feature name="vmx" policy="disable"/>
...
</cpu>
@end example
@item Host model
@example
<cpu mode='host-model'/>
@end example
With feature customization:
@example
<cpu mode='host-model'>
<feature name="vmx" policy="disable"/>
...
</cpu>
@end example
@item Named model
@example
<cpu mode='custom'>
<model name="Westmere"/>
</cpu>
@end example
With feature customization:
@example
<cpu mode='custom'>
<model name="Westmere"/>
<feature name="pcid" policy="require"/>
...
</cpu>
@end example
@end table
@c man end
@ignore
@setfilename qemu-cpu-models
@settitle QEMU / KVM CPU model configuration
@c man begin SEEALSO
The HTML documentation of QEMU for more precise information and Linux
user mode emulator invocation.
@c man end
@c man begin AUTHOR
Daniel P. Berrange
@c man end
@end ignore

6
exec.c
View File

@@ -402,12 +402,6 @@ static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr addr)
}
}
bool memory_region_is_unassigned(MemoryRegion *mr)
{
return mr != &io_mem_rom && mr != &io_mem_notdirty && !mr->rom_device
&& mr != &io_mem_watch;
}
/* Called from RCU critical section */
static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d,
hwaddr addr,

View File

@@ -701,7 +701,7 @@ static FloatParts addsub_floats(FloatParts a, FloatParts b, bool subtract,
}
a.frac += b.frac;
if (a.frac & DECOMPOSED_OVERFLOW_BIT) {
a.frac >>= 1;
shift64RightJamming(a.frac, 1, &a.frac);
a.exp += 1;
}
return a;

View File

@@ -1306,7 +1306,6 @@ ETEXI
.params = "[-n] [[<domain>:]<bus>:]<slot>\n"
"[file=file][,if=type][,bus=n]\n"
"[,unit=m][,media=d][,index=i]\n"
"[,cyls=c,heads=h,secs=s[,trans=t]]\n"
"[,snapshot=on|off][,cache=on|off]\n"
"[,readonly=on|off][,copy-on-read=on|off]",
.help = "add drive to PCI storage controller",

View File

@@ -36,3 +36,4 @@ obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
obj-$(CONFIG_IOTKIT) += iotkit.o
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o

View File

@@ -202,6 +202,7 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
*/
qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
/* Wire the NVIC up to the CPU */
sbd = SYS_BUS_DEVICE(&s->nvic);
@@ -211,25 +212,27 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->container, 0xe000e000,
sysbus_mmio_get_region(sbd, 0));
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
Object *obj = OBJECT(&s->bitband[i]);
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
if (s->enable_bitband) {
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
Object *obj = OBJECT(&s->bitband[i]);
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
object_property_set_int(obj, bitband_input_addr[i], "base", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
object_property_set_link(obj, OBJECT(s->board_memory),
"source-memory", &error_abort);
object_property_set_bool(obj, true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
object_property_set_int(obj, bitband_input_addr[i], "base", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
object_property_set_link(obj, OBJECT(s->board_memory),
"source-memory", &error_abort);
object_property_set_bool(obj, true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
return;
}
memory_region_add_subregion(&s->container, bitband_output_addr[i],
sysbus_mmio_get_region(sbd, 0));
memory_region_add_subregion(&s->container, bitband_output_addr[i],
sysbus_mmio_get_region(sbd, 0));
}
}
}
@@ -239,6 +242,7 @@ static Property armv7m_properties[] = {
MemoryRegion *),
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
DEFINE_PROP_END_OF_LIST(),
};

View File

@@ -31,6 +31,7 @@ static struct arm_boot_info aspeed_board_binfo = {
typedef struct AspeedBoardState {
AspeedSoCState soc;
MemoryRegion ram;
MemoryRegion max_ram;
} AspeedBoardState;
typedef struct AspeedBoardConfig {
@@ -127,6 +128,27 @@ static const AspeedBoardConfig aspeed_boards[] = {
},
};
/*
* The max ram region is for firmwares that scan the address space
* with load/store to guess how much RAM the SoC has.
*/
static uint64_t max_ram_read(void *opaque, hwaddr offset, unsigned size)
{
return 0;
}
static void max_ram_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
/* Discard writes */
}
static const MemoryRegionOps max_ram_ops = {
.read = max_ram_read,
.write = max_ram_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
#define FIRMWARE_ADDR 0x0
static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
@@ -187,6 +209,7 @@ static void aspeed_board_init(MachineState *machine,
AspeedBoardState *bmc;
AspeedSoCClass *sc;
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
ram_addr_t max_ram_size;
bmc = g_new0(AspeedBoardState, 1);
object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
@@ -226,6 +249,14 @@ static void aspeed_board_init(MachineState *machine,
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
&error_abort);
max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size",
&error_abort);
memory_region_init_io(&bmc->max_ram, NULL, &max_ram_ops, NULL,
"max_ram", max_ram_size - ram_size);
memory_region_add_subregion(get_system_memory(),
sc->info->sdram_base + ram_size,
&bmc->max_ram);
aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);

View File

@@ -155,6 +155,8 @@ static void aspeed_soc_init(Object *obj)
sc->info->silicon_rev);
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
"ram-size", &error_abort);
object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc),
"max-ram-size", &error_abort);
for (i = 0; i < sc->info->wdts_num; i++) {
object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);

View File

@@ -818,9 +818,9 @@ static int do_arm_linux_init(Object *obj, void *opaque)
return 0;
}
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, AddressSpace *as)
static int64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, AddressSpace *as)
{
bool elf_is64;
union {
@@ -829,7 +829,7 @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
} elf_header;
int data_swab = 0;
bool big_endian;
uint64_t ret = -1;
int64_t ret = -1;
Error *err = NULL;

617
hw/arm/fsl-imx6ul.c Normal file
View File

@@ -0,0 +1,617 @@
/*
* Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* i.MX6UL SOC emulation.
*
* Based on hw/arm/fsl-imx7.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "hw/arm/fsl-imx6ul.h"
#include "hw/misc/unimp.h"
#include "sysemu/sysemu.h"
#include "qemu/error-report.h"
#define NAME_SIZE 20
static void fsl_imx6ul_init(Object *obj)
{
FslIMX6ULState *s = FSL_IMX6UL(obj);
char name[NAME_SIZE];
int i;
for (i = 0; i < MIN(smp_cpus, FSL_IMX6UL_NUM_CPUS); i++) {
snprintf(name, NAME_SIZE, "cpu%d", i);
object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]),
"cortex-a7-" TYPE_ARM_CPU, &error_abort, NULL);
}
/*
* A7MPCORE
*/
sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, sizeof(s->a7mpcore),
TYPE_A15MPCORE_PRIV);
/*
* CCM
*/
sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX6UL_CCM);
/*
* SRC
*/
sysbus_init_child_obj(obj, "src", &s->src, sizeof(s->src), TYPE_IMX6_SRC);
/*
* GPCv2
*/
sysbus_init_child_obj(obj, "gpcv2", &s->gpcv2, sizeof(s->gpcv2),
TYPE_IMX_GPCV2);
/*
* SNVS
*/
sysbus_init_child_obj(obj, "snvs", &s->snvs, sizeof(s->snvs),
TYPE_IMX7_SNVS);
/*
* GPR
*/
sysbus_init_child_obj(obj, "gpr", &s->gpr, sizeof(s->gpr),
TYPE_IMX7_GPR);
/*
* GPIOs 1 to 5
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
snprintf(name, NAME_SIZE, "gpio%d", i);
sysbus_init_child_obj(obj, name, &s->gpio[i], sizeof(s->gpio[i]),
TYPE_IMX_GPIO);
}
/*
* GPT 1, 2
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
snprintf(name, NAME_SIZE, "gpt%d", i);
sysbus_init_child_obj(obj, name, &s->gpt[i], sizeof(s->gpt[i]),
TYPE_IMX7_GPT);
}
/*
* EPIT 1, 2
*/
for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
snprintf(name, NAME_SIZE, "epit%d", i + 1);
sysbus_init_child_obj(obj, name, &s->epit[i], sizeof(s->epit[i]),
TYPE_IMX_EPIT);
}
/*
* eCSPI
*/
for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
snprintf(name, NAME_SIZE, "spi%d", i + 1);
sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]),
TYPE_IMX_SPI);
}
/*
* I2C
*/
for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
snprintf(name, NAME_SIZE, "i2c%d", i + 1);
sysbus_init_child_obj(obj, name, &s->i2c[i], sizeof(s->i2c[i]),
TYPE_IMX_I2C);
}
/*
* UART
*/
for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
snprintf(name, NAME_SIZE, "uart%d", i);
sysbus_init_child_obj(obj, name, &s->uart[i], sizeof(s->uart[i]),
TYPE_IMX_SERIAL);
}
/*
* Ethernet
*/
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
snprintf(name, NAME_SIZE, "eth%d", i);
sysbus_init_child_obj(obj, name, &s->eth[i], sizeof(s->eth[i]),
TYPE_IMX_ENET);
}
/*
* SDHCI
*/
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
snprintf(name, NAME_SIZE, "usdhc%d", i);
sysbus_init_child_obj(obj, name, &s->usdhc[i], sizeof(s->usdhc[i]),
TYPE_IMX_USDHC);
}
/*
* Watchdog
*/
for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
snprintf(name, NAME_SIZE, "wdt%d", i);
sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]),
TYPE_IMX2_WDT);
}
}
static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
{
FslIMX6ULState *s = FSL_IMX6UL(dev);
int i;
qemu_irq irq;
char name[NAME_SIZE];
if (smp_cpus > FSL_IMX6UL_NUM_CPUS) {
error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
TYPE_FSL_IMX6UL, FSL_IMX6UL_NUM_CPUS, smp_cpus);
return;
}
for (i = 0; i < smp_cpus; i++) {
Object *o = OBJECT(&s->cpu[i]);
object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC,
"psci-conduit", &error_abort);
/* On uniprocessor, the CBAR is set to 0 */
if (smp_cpus > 1) {
object_property_set_int(o, FSL_IMX6UL_A7MPCORE_ADDR,
"reset-cbar", &error_abort);
}
if (i) {
/* Secondary CPUs start in PSCI powered-down state */
object_property_set_bool(o, true,
"start-powered-off", &error_abort);
}
object_property_set_bool(o, true, "realized", &error_abort);
}
/*
* A7MPCORE
*/
object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu",
&error_abort);
object_property_set_int(OBJECT(&s->a7mpcore),
FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL,
"num-irq", &error_abort);
object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR);
for (i = 0; i < smp_cpus; i++) {
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
DeviceState *d = DEVICE(qemu_get_cpu(i));
irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
sysbus_connect_irq(sbd, i, irq);
sysbus_connect_irq(sbd, i + smp_cpus, qdev_get_gpio_in(d, ARM_CPU_FIQ));
}
/*
* A7MPCORE DAP
*/
create_unimplemented_device("a7mpcore-dap", FSL_IMX6UL_A7MPCORE_DAP_ADDR,
0x100000);
/*
* GPT 1, 2
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
static const hwaddr FSL_IMX6UL_GPTn_ADDR[FSL_IMX6UL_NUM_GPTS] = {
FSL_IMX6UL_GPT1_ADDR,
FSL_IMX6UL_GPT2_ADDR,
};
static const int FSL_IMX6UL_GPTn_IRQ[FSL_IMX6UL_NUM_GPTS] = {
FSL_IMX6UL_GPT1_IRQ,
FSL_IMX6UL_GPT2_IRQ,
};
s->gpt[i].ccm = IMX_CCM(&s->ccm);
object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0,
FSL_IMX6UL_GPTn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_GPTn_IRQ[i]));
}
/*
* EPIT 1, 2
*/
for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
static const hwaddr FSL_IMX6UL_EPITn_ADDR[FSL_IMX6UL_NUM_EPITS] = {
FSL_IMX6UL_EPIT1_ADDR,
FSL_IMX6UL_EPIT2_ADDR,
};
static const int FSL_IMX6UL_EPITn_IRQ[FSL_IMX6UL_NUM_EPITS] = {
FSL_IMX6UL_EPIT1_IRQ,
FSL_IMX6UL_EPIT2_IRQ,
};
s->epit[i].ccm = IMX_CCM(&s->ccm);
object_property_set_bool(OBJECT(&s->epit[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0,
FSL_IMX6UL_EPITn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_EPITn_IRQ[i]));
}
/*
* GPIO
*/
for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
static const hwaddr FSL_IMX6UL_GPIOn_ADDR[FSL_IMX6UL_NUM_GPIOS] = {
FSL_IMX6UL_GPIO1_ADDR,
FSL_IMX6UL_GPIO2_ADDR,
FSL_IMX6UL_GPIO3_ADDR,
FSL_IMX6UL_GPIO4_ADDR,
FSL_IMX6UL_GPIO5_ADDR,
};
static const int FSL_IMX6UL_GPIOn_LOW_IRQ[FSL_IMX6UL_NUM_GPIOS] = {
FSL_IMX6UL_GPIO1_LOW_IRQ,
FSL_IMX6UL_GPIO2_LOW_IRQ,
FSL_IMX6UL_GPIO3_LOW_IRQ,
FSL_IMX6UL_GPIO4_LOW_IRQ,
FSL_IMX6UL_GPIO5_LOW_IRQ,
};
static const int FSL_IMX6UL_GPIOn_HIGH_IRQ[FSL_IMX6UL_NUM_GPIOS] = {
FSL_IMX6UL_GPIO1_HIGH_IRQ,
FSL_IMX6UL_GPIO2_HIGH_IRQ,
FSL_IMX6UL_GPIO3_HIGH_IRQ,
FSL_IMX6UL_GPIO4_HIGH_IRQ,
FSL_IMX6UL_GPIO5_HIGH_IRQ,
};
object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0,
FSL_IMX6UL_GPIOn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_GPIOn_LOW_IRQ[i]));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_GPIOn_HIGH_IRQ[i]));
}
/*
* IOMUXC and IOMUXC_GPR
*/
for (i = 0; i < 1; i++) {
static const hwaddr FSL_IMX6UL_IOMUXCn_ADDR[FSL_IMX6UL_NUM_IOMUXCS] = {
FSL_IMX6UL_IOMUXC_ADDR,
FSL_IMX6UL_IOMUXC_GPR_ADDR,
};
snprintf(name, NAME_SIZE, "iomuxc%d", i);
create_unimplemented_device(name, FSL_IMX6UL_IOMUXCn_ADDR[i], 0x4000);
}
/*
* CCM
*/
object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6UL_CCM_ADDR);
/*
* SRC
*/
object_property_set_bool(OBJECT(&s->src), true, "realized", &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6UL_SRC_ADDR);
/*
* GPCv2
*/
object_property_set_bool(OBJECT(&s->gpcv2), true,
"realized", &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX6UL_GPC_ADDR);
/* Initialize all ECSPI */
for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
static const hwaddr FSL_IMX6UL_SPIn_ADDR[FSL_IMX6UL_NUM_ECSPIS] = {
FSL_IMX6UL_ECSPI1_ADDR,
FSL_IMX6UL_ECSPI2_ADDR,
FSL_IMX6UL_ECSPI3_ADDR,
FSL_IMX6UL_ECSPI4_ADDR,
};
static const int FSL_IMX6UL_SPIn_IRQ[FSL_IMX6UL_NUM_ECSPIS] = {
FSL_IMX6UL_ECSPI1_IRQ,
FSL_IMX6UL_ECSPI2_IRQ,
FSL_IMX6UL_ECSPI3_IRQ,
FSL_IMX6UL_ECSPI4_IRQ,
};
/* Initialize the SPI */
object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
FSL_IMX6UL_SPIn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_SPIn_IRQ[i]));
}
/*
* I2C
*/
for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
static const hwaddr FSL_IMX6UL_I2Cn_ADDR[FSL_IMX6UL_NUM_I2CS] = {
FSL_IMX6UL_I2C1_ADDR,
FSL_IMX6UL_I2C2_ADDR,
FSL_IMX6UL_I2C3_ADDR,
FSL_IMX6UL_I2C4_ADDR,
};
static const int FSL_IMX6UL_I2Cn_IRQ[FSL_IMX6UL_NUM_I2CS] = {
FSL_IMX6UL_I2C1_IRQ,
FSL_IMX6UL_I2C2_IRQ,
FSL_IMX6UL_I2C3_IRQ,
FSL_IMX6UL_I2C4_IRQ,
};
object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX6UL_I2Cn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_I2Cn_IRQ[i]));
}
/*
* UART
*/
for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
static const hwaddr FSL_IMX6UL_UARTn_ADDR[FSL_IMX6UL_NUM_UARTS] = {
FSL_IMX6UL_UART1_ADDR,
FSL_IMX6UL_UART2_ADDR,
FSL_IMX6UL_UART3_ADDR,
FSL_IMX6UL_UART4_ADDR,
FSL_IMX6UL_UART5_ADDR,
FSL_IMX6UL_UART6_ADDR,
FSL_IMX6UL_UART7_ADDR,
FSL_IMX6UL_UART8_ADDR,
};
static const int FSL_IMX6UL_UARTn_IRQ[FSL_IMX6UL_NUM_UARTS] = {
FSL_IMX6UL_UART1_IRQ,
FSL_IMX6UL_UART2_IRQ,
FSL_IMX6UL_UART3_IRQ,
FSL_IMX6UL_UART4_IRQ,
FSL_IMX6UL_UART5_IRQ,
FSL_IMX6UL_UART6_IRQ,
FSL_IMX6UL_UART7_IRQ,
FSL_IMX6UL_UART8_IRQ,
};
qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
object_property_set_bool(OBJECT(&s->uart[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0,
FSL_IMX6UL_UARTn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_UARTn_IRQ[i]));
}
/*
* Ethernet
*/
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
static const hwaddr FSL_IMX6UL_ENETn_ADDR[FSL_IMX6UL_NUM_ETHS] = {
FSL_IMX6UL_ENET1_ADDR,
FSL_IMX6UL_ENET2_ADDR,
};
static const int FSL_IMX6UL_ENETn_IRQ[FSL_IMX6UL_NUM_ETHS] = {
FSL_IMX6UL_ENET1_IRQ,
FSL_IMX6UL_ENET2_IRQ,
};
static const int FSL_IMX6UL_ENETn_TIMER_IRQ[FSL_IMX6UL_NUM_ETHS] = {
FSL_IMX6UL_ENET1_TIMER_IRQ,
FSL_IMX6UL_ENET2_TIMER_IRQ,
};
object_property_set_uint(OBJECT(&s->eth[i]),
FSL_IMX6UL_ETH_NUM_TX_RINGS,
"tx-ring-num", &error_abort);
qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]);
object_property_set_bool(OBJECT(&s->eth[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0,
FSL_IMX6UL_ENETn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_ENETn_IRQ[i]));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
}
/*
* USDHC
*/
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
static const hwaddr FSL_IMX6UL_USDHCn_ADDR[FSL_IMX6UL_NUM_USDHCS] = {
FSL_IMX6UL_USDHC1_ADDR,
FSL_IMX6UL_USDHC2_ADDR,
};
static const int FSL_IMX6UL_USDHCn_IRQ[FSL_IMX6UL_NUM_USDHCS] = {
FSL_IMX6UL_USDHC1_IRQ,
FSL_IMX6UL_USDHC2_IRQ,
};
object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
FSL_IMX6UL_USDHCn_ADDR[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
FSL_IMX6UL_USDHCn_IRQ[i]));
}
/*
* SNVS
*/
object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX6UL_SNVS_HP_ADDR);
/*
* Watchdog
*/
for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
static const hwaddr FSL_IMX6UL_WDOGn_ADDR[FSL_IMX6UL_NUM_WDTS] = {
FSL_IMX6UL_WDOG1_ADDR,
FSL_IMX6UL_WDOG2_ADDR,
FSL_IMX6UL_WDOG3_ADDR,
};
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
FSL_IMX6UL_WDOGn_ADDR[i]);
}
/*
* GPR
*/
object_property_set_bool(OBJECT(&s->gpr), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX6UL_IOMUXC_GPR_ADDR);
/*
* SDMA
*/
create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
/*
* APHB_DMA
*/
create_unimplemented_device("aphb_dma", FSL_IMX6UL_APBH_DMA_ADDR,
FSL_IMX6UL_APBH_DMA_SIZE);
/*
* ADCs
*/
for (i = 0; i < FSL_IMX6UL_NUM_ADCS; i++) {
static const hwaddr FSL_IMX6UL_ADCn_ADDR[FSL_IMX6UL_NUM_ADCS] = {
FSL_IMX6UL_ADC1_ADDR,
FSL_IMX6UL_ADC2_ADDR,
};
snprintf(name, NAME_SIZE, "adc%d", i);
create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i], 0x4000);
}
/*
* LCD
*/
create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR, 0x4000);
/*
* ROM memory
*/
memory_region_init_rom(&s->rom, NULL, "imx6ul.rom",
FSL_IMX6UL_ROM_SIZE, &error_abort);
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_ROM_ADDR,
&s->rom);
/*
* CAAM memory
*/
memory_region_init_rom(&s->caam, NULL, "imx6ul.caam",
FSL_IMX6UL_CAAM_MEM_SIZE, &error_abort);
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_CAAM_MEM_ADDR,
&s->caam);
/*
* OCRAM memory
*/
memory_region_init_ram(&s->ocram, NULL, "imx6ul.ocram",
FSL_IMX6UL_OCRAM_MEM_SIZE,
&error_abort);
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_OCRAM_MEM_ADDR,
&s->ocram);
/*
* internal OCRAM (128 KB) is aliased over 512 KB
*/
memory_region_init_alias(&s->ocram_alias, NULL, "imx6ul.ocram_alias",
&s->ocram, 0, FSL_IMX6UL_OCRAM_ALIAS_SIZE);
memory_region_add_subregion(get_system_memory(),
FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias);
}
static void fsl_imx6ul_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = fsl_imx6ul_realize;
dc->desc = "i.MX6UL SOC";
/* Reason: Uses serial_hds and nd_table in realize() directly */
dc->user_creatable = false;
}
static const TypeInfo fsl_imx6ul_type_info = {
.name = TYPE_FSL_IMX6UL,
.parent = TYPE_DEVICE,
.instance_size = sizeof(FslIMX6ULState),
.instance_init = fsl_imx6ul_init,
.class_init = fsl_imx6ul_class_init,
};
static void fsl_imx6ul_register_types(void)
{
type_register_static(&fsl_imx6ul_type_info);
}
type_init(fsl_imx6ul_register_types)

85
hw/arm/mcimx6ul-evk.c Normal file
View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* MCIMX6UL_EVK Board System emulation.
*
* This code is licensed under the GPL, version 2 or later.
* See the file `COPYING' in the top level directory.
*
* It (partially) emulates a mcimx6ul_evk board, with a Freescale
* i.MX6ul SoC
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "hw/arm/fsl-imx6ul.h"
#include "hw/boards.h"
#include "sysemu/sysemu.h"
#include "qemu/error-report.h"
#include "sysemu/qtest.h"
typedef struct {
FslIMX6ULState soc;
MemoryRegion ram;
} MCIMX6ULEVK;
static void mcimx6ul_evk_init(MachineState *machine)
{
static struct arm_boot_info boot_info;
MCIMX6ULEVK *s = g_new0(MCIMX6ULEVK, 1);
int i;
if (machine->ram_size > FSL_IMX6UL_MMDC_SIZE) {
error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
machine->ram_size, FSL_IMX6UL_MMDC_SIZE);
exit(1);
}
boot_info = (struct arm_boot_info) {
.loader_start = FSL_IMX6UL_MMDC_ADDR,
.board_id = -1,
.ram_size = machine->ram_size,
.kernel_filename = machine->kernel_filename,
.kernel_cmdline = machine->kernel_cmdline,
.initrd_filename = machine->initrd_filename,
.nb_cpus = smp_cpus,
};
object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
TYPE_FSL_IMX6UL, &error_fatal, NULL);
object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
memory_region_allocate_system_memory(&s->ram, NULL, "mcimx6ul-evk.ram",
machine->ram_size);
memory_region_add_subregion(get_system_memory(),
FSL_IMX6UL_MMDC_ADDR, &s->ram);
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
BusState *bus;
DeviceState *carddev;
DriveInfo *di;
BlockBackend *blk;
di = drive_get_next(IF_SD);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(&s->soc.usdhc[i]), "sd-bus");
carddev = qdev_create(bus, TYPE_SD_CARD);
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
object_property_set_bool(OBJECT(carddev), true,
"realized", &error_fatal);
}
if (!qtest_enabled()) {
arm_load_kernel(&s->soc.cpu[0], &boot_info);
}
}
static void mcimx6ul_evk_machine_init(MachineClass *mc)
{
mc->desc = "Freescale i.MX6UL Evaluation Kit (Cortex A7)";
mc->init = mcimx6ul_evk_init;
mc->max_cpus = FSL_IMX6UL_NUM_CPUS;
}
DEFINE_MACHINE("mcimx6ul-evk", mcimx6ul_evk_machine_init)

View File

@@ -107,16 +107,6 @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
memory_region_add_subregion(get_system_memory(), base, mr);
}
static void init_sysbus_child(Object *parent, const char *childname,
void *child, size_t childsize,
const char *childtype)
{
object_initialize(child, childsize, childtype);
object_property_add_child(parent, childname, OBJECT(child), &error_abort);
qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
}
/* Most of the devices in the AN505 FPGA image sit behind
* Peripheral Protection Controllers. These data structures
* define the layout of which devices sit behind which PPCs.
@@ -149,9 +139,9 @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
*/
UnimplementedDeviceState *uds = opaque;
init_sysbus_child(OBJECT(mms), name, uds,
sizeof(UnimplementedDeviceState),
TYPE_UNIMPLEMENTED_DEVICE);
sysbus_init_child_obj(OBJECT(mms), name, uds,
sizeof(UnimplementedDeviceState),
TYPE_UNIMPLEMENTED_DEVICE);
qdev_prop_set_string(DEVICE(uds), "name", name);
qdev_prop_set_uint64(DEVICE(uds), "size", size);
object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
@@ -170,8 +160,8 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
DeviceState *iotkitdev = DEVICE(&mms->iotkit);
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
init_sysbus_child(OBJECT(mms), name, uart,
sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
TYPE_CMSDK_APB_UART);
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
@@ -248,8 +238,8 @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
init_sysbus_child(OBJECT(mms), mpcname, mpc,
sizeof(mms->ssram_mpc[0]), TYPE_TZ_MPC);
sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->ssram_mpc[0]),
TYPE_TZ_MPC);
object_property_set_link(OBJECT(mpc), OBJECT(ssram),
"downstream", &error_fatal);
object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
@@ -288,8 +278,8 @@ static void mps2tz_common_init(MachineState *machine)
exit(1);
}
init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
sizeof(mms->iotkit), TYPE_IOTKIT);
sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
sizeof(mms->iotkit), TYPE_IOTKIT);
iotkitdev = DEVICE(&mms->iotkit);
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
"memory", &error_abort);
@@ -421,8 +411,8 @@ static void mps2tz_common_init(MachineState *machine)
int port;
char *gpioname;
init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
sizeof(TZPPC), TYPE_TZ_PPC);
sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
sizeof(TZPPC), TYPE_TZ_PPC);
ppcdev = DEVICE(ppc);
for (port = 0; port < TZ_NUM_PORTS; port++) {

View File

@@ -186,6 +186,7 @@ static void mps2_common_init(MachineState *machine)
g_assert_not_reached();
}
qdev_prop_set_string(armv7m, "cpu-type", machine->cpu_type);
qdev_prop_set_bit(armv7m, "enable-bitband", true);
object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory),
"memory", &error_abort);
object_property_set_bool(OBJECT(&mms->armv7m), true, "realized",

View File

@@ -117,6 +117,7 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
armv7m = DEVICE(&s->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 81);
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
qdev_prop_set_bit(armv7m, "enable-bitband", true);
object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
"memory", &error_abort);
object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);

View File

@@ -201,7 +201,13 @@ static void realview_init(MachineState *machine,
pl011_create(0x1000c000, pic[15], serial_hd(3));
/* DMA controller is optional, apparently. */
sysbus_create_simple("pl081", 0x10030000, pic[24]);
dev = qdev_create(NULL, "pl081");
object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
&error_fatal);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0x10030000);
sysbus_connect_irq(busdev, 0, pic[24]);
sysbus_create_simple("sp804", 0x10011000, pic[4]);
sysbus_create_simple("sp804", 0x10012000, pic[5]);

View File

@@ -1304,6 +1304,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
nvic = qdev_create(NULL, TYPE_ARMV7M);
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
qdev_prop_set_bit(nvic, "enable-bitband", true);
object_property_set_link(OBJECT(nvic), OBJECT(get_system_memory()),
"memory", &error_abort);
/* This will exit with an error if the user passed us a bad cpu_type */

View File

@@ -109,6 +109,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
armv7m = DEVICE(&s->armv7m);
qdev_prop_set_uint32(armv7m, "num-irq", 96);
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
qdev_prop_set_bit(armv7m, "enable-bitband", true);
object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
"memory", &error_abort);
object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);

View File

@@ -287,7 +287,14 @@ static void versatile_init(MachineState *machine, int board_id)
pl011_create(0x101f3000, pic[14], serial_hd(2));
pl011_create(0x10009000, sic[6], serial_hd(3));
sysbus_create_simple("pl080", 0x10130000, pic[17]);
dev = qdev_create(NULL, "pl080");
object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
&error_fatal);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0x10130000);
sysbus_connect_irq(busdev, 0, pic[17]);
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
sysbus_create_simple("sp804", 0x101e3000, pic[5]);

View File

@@ -659,6 +659,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
gicc->length = sizeof(*gicc);
if (vms->gic_version == 2) {
gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
}
gicc->cpu_interface_number = cpu_to_le32(i);
gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
@@ -668,8 +670,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
}
if (vms->virt && vms->gic_version == 3) {
gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GICV3_MAINT_IRQ));
if (vms->virt) {
gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
}
}

View File

@@ -131,6 +131,8 @@ static const MemMapEntry a15memmap[] = {
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
[VIRT_GIC_HYP] = { 0x08030000, 0x00010000 },
[VIRT_GIC_VCPU] = { 0x08040000, 0x00010000 },
/* The space in between here is reserved for GICv3 CPU/vCPU/HYP */
[VIRT_GIC_ITS] = { 0x08080000, 0x00020000 },
/* This redistributor space allows up to 2*64kB*123 CPUs */
@@ -440,18 +442,33 @@ static void fdt_add_gic_node(VirtMachineState *vms)
if (vms->virt) {
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
}
} else {
/* 'cortex-a15-gic' means 'GIC v2' */
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
"arm,cortex-a15-gic");
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size);
if (!vms->virt) {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size);
} else {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
2, vms->memmap[VIRT_GIC_DIST].base,
2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_CPU].base,
2, vms->memmap[VIRT_GIC_CPU].size,
2, vms->memmap[VIRT_GIC_HYP].base,
2, vms->memmap[VIRT_GIC_HYP].size,
2, vms->memmap[VIRT_GIC_VCPU].base,
2, vms->memmap[VIRT_GIC_VCPU].size);
qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
}
}
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle);
@@ -573,6 +590,11 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
MIN(smp_cpus - redist0_count, redist1_capacity));
}
} else {
if (!kvm_irqchip_in_kernel()) {
qdev_prop_set_bit(gicdev, "has-virtualization-extensions",
vms->virt);
}
}
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
@@ -584,6 +606,10 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
}
} else {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
if (vms->virt) {
sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
}
}
/* Wire the outputs from each CPU's generic timer and the GICv3
@@ -610,9 +636,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
ppibase + timer_irq[irq]));
}
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
qdev_get_gpio_in(gicdev, ppibase
+ ARCH_GICV3_MAINT_IRQ));
if (type == 3) {
qemu_irq irq = qdev_get_gpio_in(gicdev,
ppibase + ARCH_GIC_MAINT_IRQ);
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
0, irq);
} else if (vms->virt) {
qemu_irq irq = qdev_get_gpio_in(gicdev,
ppibase + ARCH_GIC_MAINT_IRQ);
sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
}
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
qdev_get_gpio_in(gicdev, ppibase
+ VIRTUAL_PMU_IRQ));
@@ -1757,10 +1791,7 @@ static void machvirt_machine_init(void)
}
type_init(machvirt_machine_init);
#define VIRT_COMPAT_2_12 \
HW_COMPAT_2_12
static void virt_3_0_instance_init(Object *obj)
static void virt_3_1_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
@@ -1830,10 +1861,24 @@ static void virt_3_0_instance_init(Object *obj)
vms->irqmap = a15irqmap;
}
static void virt_machine_3_0_options(MachineClass *mc)
static void virt_machine_3_1_options(MachineClass *mc)
{
}
DEFINE_VIRT_MACHINE_AS_LATEST(3, 0)
DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
static void virt_3_0_instance_init(Object *obj)
{
virt_3_1_instance_init(obj);
}
static void virt_machine_3_0_options(MachineClass *mc)
{
virt_machine_3_1_options(mc);
}
DEFINE_VIRT_MACHINE(3, 0)
#define VIRT_COMPAT_2_12 \
HW_COMPAT_2_12
static void virt_2_12_instance_init(Object *obj)
{

View File

@@ -29,12 +29,17 @@
#define ARM_PHYS_TIMER_PPI 30
#define ARM_VIRT_TIMER_PPI 27
#define ARM_HYP_TIMER_PPI 26
#define ARM_SEC_TIMER_PPI 29
#define GIC_MAINTENANCE_PPI 25
#define GEM_REVISION 0x40070106
#define GIC_BASE_ADDR 0xf9000000
#define GIC_DIST_ADDR 0xf9010000
#define GIC_CPU_ADDR 0xf9020000
#define GIC_VIFACE_ADDR 0xf9040000
#define GIC_VCPU_ADDR 0xf9060000
#define SATA_INTR 133
#define SATA_ADDR 0xFD0C0000
@@ -111,11 +116,54 @@ static const int adma_ch_intr[XLNX_ZYNQMP_NUM_ADMA_CH] = {
typedef struct XlnxZynqMPGICRegion {
int region_index;
uint32_t address;
uint32_t offset;
bool virt;
} XlnxZynqMPGICRegion;
static const XlnxZynqMPGICRegion xlnx_zynqmp_gic_regions[] = {
{ .region_index = 0, .address = GIC_DIST_ADDR, },
{ .region_index = 1, .address = GIC_CPU_ADDR, },
/* Distributor */
{
.region_index = 0,
.address = GIC_DIST_ADDR,
.offset = 0,
.virt = false
},
/* CPU interface */
{
.region_index = 1,
.address = GIC_CPU_ADDR,
.offset = 0,
.virt = false
},
{
.region_index = 1,
.address = GIC_CPU_ADDR + 0x10000,
.offset = 0x1000,
.virt = false
},
/* Virtual interface */
{
.region_index = 2,
.address = GIC_VIFACE_ADDR,
.offset = 0,
.virt = true
},
/* Virtual CPU interface */
{
.region_index = 3,
.address = GIC_VCPU_ADDR,
.offset = 0,
.virt = true
},
{
.region_index = 3,
.address = GIC_VCPU_ADDR + 0x10000,
.offset = 0x1000,
.virt = true
},
};
static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index)
@@ -281,6 +329,9 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", num_apus);
qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", s->secure);
qdev_prop_set_bit(DEVICE(&s->gic),
"has-virtualization-extensions", s->virt);
/* Realize APUs before realizing the GIC. KVM requires this. */
for (i = 0; i < num_apus; i++) {
@@ -325,19 +376,23 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
for (i = 0; i < XLNX_ZYNQMP_GIC_REGIONS; i++) {
SysBusDevice *gic = SYS_BUS_DEVICE(&s->gic);
const XlnxZynqMPGICRegion *r = &xlnx_zynqmp_gic_regions[i];
MemoryRegion *mr = sysbus_mmio_get_region(gic, r->region_index);
MemoryRegion *mr;
uint32_t addr = r->address;
int j;
sysbus_mmio_map(gic, r->region_index, addr);
if (r->virt && !s->virt) {
continue;
}
mr = sysbus_mmio_get_region(gic, r->region_index);
for (j = 0; j < XLNX_ZYNQMP_GIC_ALIASES; j++) {
MemoryRegion *alias = &s->gic_mr[i][j];
addr += XLNX_ZYNQMP_GIC_REGION_SIZE;
memory_region_init_alias(alias, OBJECT(s), "zynqmp-gic-alias", mr,
0, XLNX_ZYNQMP_GIC_REGION_SIZE);
r->offset, XLNX_ZYNQMP_GIC_REGION_SIZE);
memory_region_add_subregion(system_memory, addr, alias);
addr += XLNX_ZYNQMP_GIC_REGION_SIZE;
}
}
@@ -347,12 +402,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
ARM_CPU_IRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + num_apus,
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
ARM_CPU_FIQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + num_apus * 2,
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
ARM_CPU_VIRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + num_apus * 3,
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
ARM_CPU_VFIQ));
irq = qdev_get_gpio_in(DEVICE(&s->gic),
arm_gic_ppi_index(i, ARM_PHYS_TIMER_PPI));
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 0, irq);
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), GTIMER_PHYS, irq);
irq = qdev_get_gpio_in(DEVICE(&s->gic),
arm_gic_ppi_index(i, ARM_VIRT_TIMER_PPI));
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), GTIMER_VIRT, irq);
irq = qdev_get_gpio_in(DEVICE(&s->gic),
arm_gic_ppi_index(i, ARM_HYP_TIMER_PPI));
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), GTIMER_HYP, irq);
irq = qdev_get_gpio_in(DEVICE(&s->gic),
arm_gic_ppi_index(i, ARM_SEC_TIMER_PPI));
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), GTIMER_SEC, irq);
if (s->virt) {
irq = qdev_get_gpio_in(DEVICE(&s->gic),
arm_gic_ppi_index(i, GIC_MAINTENANCE_PPI));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + num_apus * 4, irq);
}
}
if (s->has_rpu) {

View File

@@ -15,19 +15,6 @@
#include "qapi/qapi-types-block.h"
#include "qemu/error-report.h"
void blkconf_serial(BlockConf *conf, char **serial)
{
DriveInfo *dinfo;
if (!*serial) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = blk_legacy_dinfo(conf->blk);
if (dinfo) {
*serial = g_strdup(dinfo->serial);
}
}
}
void blkconf_blocksizes(BlockConf *conf)
{
BlockBackend *blk = conf->blk;
@@ -108,20 +95,6 @@ bool blkconf_geometry(BlockConf *conf, int *ptrans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
Error **errp)
{
DriveInfo *dinfo;
if (!conf->cyls && !conf->heads && !conf->secs) {
/* try to fall back to value set with legacy -drive cyls=... */
dinfo = blk_legacy_dinfo(conf->blk);
if (dinfo) {
conf->cyls = dinfo->cyls;
conf->heads = dinfo->heads;
conf->secs = dinfo->secs;
if (ptrans) {
*ptrans = dinfo->trans;
}
}
}
if (!conf->cyls && !conf->heads && !conf->secs) {
hd_geometry_guess(conf->blk,
&conf->cyls, &conf->heads, &conf->secs,

View File

@@ -1217,7 +1217,6 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
return;
}
blkconf_serial(&n->conf, &n->serial);
if (!n->serial) {
error_setg(errp, "serial property not set");
return;

View File

@@ -935,7 +935,6 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
return;
}
blkconf_serial(&conf->conf, &conf->serial);
if (!blkconf_apply_backend_options(&conf->conf,
blk_is_read_only(conf->conf.blk), true,
errp)) {

View File

@@ -74,8 +74,9 @@ static void imx_update(IMXSerialState *s)
mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
/*
* TCEN and TXDC are both bit 3
* RDR and DREN are both bit 0
*/
mask |= s->ucr4 & UCR4_TCEN;
mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
usr2 = s->usr2 & mask;

View File

@@ -147,6 +147,10 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,
as);
}
if (size < 0) {
size = load_targphys_hex_as(s->file, &entry, as);
}
}
if (size < 0 || s->force_raw) {

View File

@@ -840,6 +840,8 @@ struct Rom {
char *fw_dir;
char *fw_file;
bool committed;
hwaddr addr;
QTAILQ_ENTRY(Rom) next;
};
@@ -847,6 +849,17 @@ struct Rom {
static FWCfgState *fw_cfg;
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
/* rom->data must be heap-allocated (do not use with rom_add_elf_program()) */
static void rom_free(Rom *rom)
{
g_free(rom->data);
g_free(rom->path);
g_free(rom->name);
g_free(rom->fw_dir);
g_free(rom->fw_file);
g_free(rom);
}
static inline bool rom_order_compare(Rom *rom, Rom *item)
{
return ((uintptr_t)(void *)rom->as > (uintptr_t)(void *)item->as) ||
@@ -866,6 +879,8 @@ static void rom_insert(Rom *rom)
rom->as = &address_space_memory;
}
rom->committed = false;
/* List is ordered by load address in the same address space */
QTAILQ_FOREACH(item, &roms, next) {
if (rom_order_compare(rom, item)) {
@@ -995,15 +1010,7 @@ err:
if (fd != -1)
close(fd);
g_free(rom->data);
g_free(rom->path);
g_free(rom->name);
if (fw_dir) {
g_free(rom->fw_dir);
g_free(rom->fw_file);
}
g_free(rom);
rom_free(rom);
return -1;
}
@@ -1165,6 +1172,34 @@ void rom_reset_order_override(void)
fw_cfg_reset_order_override(fw_cfg);
}
void rom_transaction_begin(void)
{
Rom *rom;
/* Ignore ROMs added without the transaction API */
QTAILQ_FOREACH(rom, &roms, next) {
rom->committed = true;
}
}
void rom_transaction_end(bool commit)
{
Rom *rom;
Rom *tmp;
QTAILQ_FOREACH_SAFE(rom, &roms, next, tmp) {
if (rom->committed) {
continue;
}
if (commit) {
rom->committed = true;
} else {
QTAILQ_REMOVE(&roms, rom, next);
rom_free(rom);
}
}
}
static Rom *find_rom(hwaddr addr, size_t size)
{
Rom *rom;
@@ -1286,3 +1321,252 @@ void hmp_info_roms(Monitor *mon, const QDict *qdict)
}
}
}
typedef enum HexRecord HexRecord;
enum HexRecord {
DATA_RECORD = 0,
EOF_RECORD,
EXT_SEG_ADDR_RECORD,
START_SEG_ADDR_RECORD,
EXT_LINEAR_ADDR_RECORD,
START_LINEAR_ADDR_RECORD,
};
/* Each record contains a 16-bit address which is combined with the upper 16
* bits of the implicit "next address" to form a 32-bit address.
*/
#define NEXT_ADDR_MASK 0xffff0000
#define DATA_FIELD_MAX_LEN 0xff
#define LEN_EXCEPT_DATA 0x5
/* 0x5 = sizeof(byte_count) + sizeof(address) + sizeof(record_type) +
* sizeof(checksum) */
typedef struct {
uint8_t byte_count;
uint16_t address;
uint8_t record_type;
uint8_t data[DATA_FIELD_MAX_LEN];
uint8_t checksum;
} HexLine;
/* return 0 or -1 if error */
static bool parse_record(HexLine *line, uint8_t *our_checksum, const uint8_t c,
uint32_t *index, const bool in_process)
{
/* +-------+---------------+-------+---------------------+--------+
* | byte | |record | | |
* | count | address | type | data |checksum|
* +-------+---------------+-------+---------------------+--------+
* ^ ^ ^ ^ ^ ^
* |1 byte | 2 bytes |1 byte | 0-255 bytes | 1 byte |
*/
uint8_t value = 0;
uint32_t idx = *index;
/* ignore space */
if (g_ascii_isspace(c)) {
return true;
}
if (!g_ascii_isxdigit(c) || !in_process) {
return false;
}
value = g_ascii_xdigit_value(c);
value = (idx & 0x1) ? (value & 0xf) : (value << 4);
if (idx < 2) {
line->byte_count |= value;
} else if (2 <= idx && idx < 6) {
line->address <<= 4;
line->address += g_ascii_xdigit_value(c);
} else if (6 <= idx && idx < 8) {
line->record_type |= value;
} else if (8 <= idx && idx < 8 + 2 * line->byte_count) {
line->data[(idx - 8) >> 1] |= value;
} else if (8 + 2 * line->byte_count <= idx &&
idx < 10 + 2 * line->byte_count) {
line->checksum |= value;
} else {
return false;
}
*our_checksum += value;
++(*index);
return true;
}
typedef struct {
const char *filename;
HexLine line;
uint8_t *bin_buf;
hwaddr *start_addr;
int total_size;
uint32_t next_address_to_write;
uint32_t current_address;
uint32_t current_rom_index;
uint32_t rom_start_address;
AddressSpace *as;
} HexParser;
/* return size or -1 if error */
static int handle_record_type(HexParser *parser)
{
HexLine *line = &(parser->line);
switch (line->record_type) {
case DATA_RECORD:
parser->current_address =
(parser->next_address_to_write & NEXT_ADDR_MASK) | line->address;
/* verify this is a contiguous block of memory */
if (parser->current_address != parser->next_address_to_write) {
if (parser->current_rom_index != 0) {
rom_add_blob_fixed_as(parser->filename, parser->bin_buf,
parser->current_rom_index,
parser->rom_start_address, parser->as);
}
parser->rom_start_address = parser->current_address;
parser->current_rom_index = 0;
}
/* copy from line buffer to output bin_buf */
memcpy(parser->bin_buf + parser->current_rom_index, line->data,
line->byte_count);
parser->current_rom_index += line->byte_count;
parser->total_size += line->byte_count;
/* save next address to write */
parser->next_address_to_write =
parser->current_address + line->byte_count;
break;
case EOF_RECORD:
if (parser->current_rom_index != 0) {
rom_add_blob_fixed_as(parser->filename, parser->bin_buf,
parser->current_rom_index,
parser->rom_start_address, parser->as);
}
return parser->total_size;
case EXT_SEG_ADDR_RECORD:
case EXT_LINEAR_ADDR_RECORD:
if (line->byte_count != 2 && line->address != 0) {
return -1;
}
if (parser->current_rom_index != 0) {
rom_add_blob_fixed_as(parser->filename, parser->bin_buf,
parser->current_rom_index,
parser->rom_start_address, parser->as);
}
/* save next address to write,
* in case of non-contiguous block of memory */
parser->next_address_to_write = (line->data[0] << 12) |
(line->data[1] << 4);
if (line->record_type == EXT_LINEAR_ADDR_RECORD) {
parser->next_address_to_write <<= 12;
}
parser->rom_start_address = parser->next_address_to_write;
parser->current_rom_index = 0;
break;
case START_SEG_ADDR_RECORD:
if (line->byte_count != 4 && line->address != 0) {
return -1;
}
/* x86 16-bit CS:IP segmented addressing */
*(parser->start_addr) = (((line->data[0] << 8) | line->data[1]) << 4) +
((line->data[2] << 8) | line->data[3]);
break;
case START_LINEAR_ADDR_RECORD:
if (line->byte_count != 4 && line->address != 0) {
return -1;
}
*(parser->start_addr) = ldl_be_p(line->data);
break;
default:
return -1;
}
return parser->total_size;
}
/* return size or -1 if error */
static int parse_hex_blob(const char *filename, hwaddr *addr, uint8_t *hex_blob,
size_t hex_blob_size, AddressSpace *as)
{
bool in_process = false; /* avoid re-enter and
* check whether record begin with ':' */
uint8_t *end = hex_blob + hex_blob_size;
uint8_t our_checksum = 0;
uint32_t record_index = 0;
HexParser parser = {
.filename = filename,
.bin_buf = g_malloc(hex_blob_size),
.start_addr = addr,
.as = as,
};
rom_transaction_begin();
for (; hex_blob < end; ++hex_blob) {
switch (*hex_blob) {
case '\r':
case '\n':
if (!in_process) {
break;
}
in_process = false;
if ((LEN_EXCEPT_DATA + parser.line.byte_count) * 2 !=
record_index ||
our_checksum != 0) {
parser.total_size = -1;
goto out;
}
if (handle_record_type(&parser) == -1) {
parser.total_size = -1;
goto out;
}
break;
/* start of a new record. */
case ':':
memset(&parser.line, 0, sizeof(HexLine));
in_process = true;
record_index = 0;
break;
/* decoding lines */
default:
if (!parse_record(&parser.line, &our_checksum, *hex_blob,
&record_index, in_process)) {
parser.total_size = -1;
goto out;
}
break;
}
}
out:
g_free(parser.bin_buf);
rom_transaction_end(parser.total_size != -1);
return parser.total_size;
}
/* return size or -1 if error */
int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as)
{
gsize hex_blob_size;
gchar *hex_blob;
int total_size = 0;
if (!g_file_get_contents(filename, &hex_blob, &hex_blob_size, NULL)) {
return -1;
}
total_size = parse_hex_blob(filename, entry, (uint8_t *)hex_blob,
hex_blob_size, as);
g_free(hex_blob);
return total_size;
}

View File

@@ -793,8 +793,9 @@ void machine_run_board_init(MachineState *machine)
MachineClass *machine_class = MACHINE_GET_CLASS(machine);
numa_complete_configuration(machine);
if (nb_numa_nodes)
if (nb_numa_nodes) {
machine_numa_finish_cpu_init(machine);
}
/* If the machine supports the valid_cpu_types check and the user
* specified a CPU with -cpu check here that the user CPU is supported.

View File

@@ -293,16 +293,8 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
{
SysBusDevice *s = SYS_BUS_DEVICE(dev);
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(s);
/* for the explicit unit address fallback case: */
char *addr, *fw_dev_path;
if (s->num_mmio) {
return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
s->mmio[0].addr);
}
if (s->num_pio) {
return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
}
if (sbc->explicit_ofw_unit_address) {
addr = sbc->explicit_ofw_unit_address(s);
if (addr) {
@@ -311,6 +303,13 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
return fw_dev_path;
}
}
if (s->num_mmio) {
return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
s->mmio[0].addr);
}
if (s->num_pio) {
return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
}
return g_strdup(qdev_fw_name(dev));
}

View File

@@ -11,8 +11,9 @@
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "qemu/log.h"
#include "hw/dma/pl080.h"
#include "qapi/error.h"
#define PL080_MAX_CHANNELS 8
#define PL080_CONF_E 0x1
#define PL080_CONF_M1 0x2
#define PL080_CONF_M2 0x4
@@ -30,36 +31,6 @@
#define PL080_CCTRL_D 0x02000000
#define PL080_CCTRL_S 0x01000000
typedef struct {
uint32_t src;
uint32_t dest;
uint32_t lli;
uint32_t ctrl;
uint32_t conf;
} pl080_channel;
#define TYPE_PL080 "pl080"
#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
typedef struct PL080State {
SysBusDevice parent_obj;
MemoryRegion iomem;
uint8_t tc_int;
uint8_t tc_mask;
uint8_t err_int;
uint8_t err_mask;
uint32_t conf;
uint32_t sync;
uint32_t req_single;
uint32_t req_burst;
pl080_channel chan[PL080_MAX_CHANNELS];
int nchannels;
/* Flag to avoid recursive DMA invocations. */
int running;
qemu_irq irq;
} PL080State;
static const VMStateDescription vmstate_pl080_channel = {
.name = "pl080_channel",
.version_id = 1,
@@ -105,11 +76,12 @@ static const unsigned char pl081_id[] =
static void pl080_update(PL080State *s)
{
if ((s->tc_int & s->tc_mask)
|| (s->err_int & s->err_mask))
qemu_irq_raise(s->irq);
else
qemu_irq_lower(s->irq);
bool tclevel = (s->tc_int & s->tc_mask);
bool errlevel = (s->err_int & s->err_mask);
qemu_set_irq(s->interr, errlevel);
qemu_set_irq(s->inttc, tclevel);
qemu_set_irq(s->irq, errlevel || tclevel);
}
static void pl080_run(PL080State *s)
@@ -138,7 +110,6 @@ static void pl080_run(PL080State *s)
if ((s->conf & PL080_CONF_E) == 0)
return;
hw_error("DMA active\n");
/* If we are already in the middle of a DMA operation then indicate that
there may be new DMA requests and return immediately. */
if (s->running) {
@@ -190,14 +161,16 @@ again:
swidth = 1 << ((ch->ctrl >> 18) & 7);
dwidth = 1 << ((ch->ctrl >> 21) & 7);
for (n = 0; n < dwidth; n+= swidth) {
cpu_physical_memory_read(ch->src, buff + n, swidth);
address_space_read(&s->downstream_as, ch->src,
MEMTXATTRS_UNSPECIFIED, buff + n, swidth);
if (ch->ctrl & PL080_CCTRL_SI)
ch->src += swidth;
}
xsize = (dwidth < swidth) ? swidth : dwidth;
/* ??? This may pad the value incorrectly for dwidth < 32. */
for (n = 0; n < xsize; n += dwidth) {
cpu_physical_memory_write(ch->dest + n, buff + n, dwidth);
address_space_write(&s->downstream_as, ch->dest + n,
MEMTXATTRS_UNSPECIFIED, buff + n, dwidth);
if (ch->ctrl & PL080_CCTRL_DI)
ch->dest += swidth;
}
@@ -207,19 +180,19 @@ again:
if (size == 0) {
/* Transfer complete. */
if (ch->lli) {
ch->src = address_space_ldl_le(&address_space_memory,
ch->src = address_space_ldl_le(&s->downstream_as,
ch->lli,
MEMTXATTRS_UNSPECIFIED,
NULL);
ch->dest = address_space_ldl_le(&address_space_memory,
ch->dest = address_space_ldl_le(&s->downstream_as,
ch->lli + 4,
MEMTXATTRS_UNSPECIFIED,
NULL);
ch->ctrl = address_space_ldl_le(&address_space_memory,
ch->ctrl = address_space_ldl_le(&s->downstream_as,
ch->lli + 12,
MEMTXATTRS_UNSPECIFIED,
NULL);
ch->lli = address_space_ldl_le(&address_space_memory,
ch->lli = address_space_ldl_le(&s->downstream_as,
ch->lli + 8,
MEMTXATTRS_UNSPECIFIED,
NULL);
@@ -255,7 +228,7 @@ static uint64_t pl080_read(void *opaque, hwaddr offset,
i = (offset & 0xe0) >> 5;
if (i >= s->nchannels)
goto bad_offset;
switch (offset >> 2) {
switch ((offset >> 2) & 7) {
case 0: /* SrcAddr */
return s->chan[i].src;
case 1: /* DestAddr */
@@ -316,7 +289,7 @@ static void pl080_write(void *opaque, hwaddr offset,
i = (offset & 0xe0) >> 5;
if (i >= s->nchannels)
goto bad_offset;
switch (offset >> 2) {
switch ((offset >> 2) & 7) {
case 0: /* SrcAddr */
s->chan[i].src = value;
break;
@@ -334,6 +307,7 @@ static void pl080_write(void *opaque, hwaddr offset,
pl080_run(s);
break;
}
return;
}
switch (offset >> 2) {
case 2: /* IntTCClear */
@@ -374,6 +348,30 @@ static const MemoryRegionOps pl080_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void pl080_reset(DeviceState *dev)
{
PL080State *s = PL080(dev);
int i;
s->tc_int = 0;
s->tc_mask = 0;
s->err_int = 0;
s->err_mask = 0;
s->conf = 0;
s->sync = 0;
s->req_single = 0;
s->req_burst = 0;
s->running = 0;
for (i = 0; i < s->nchannels; i++) {
s->chan[i].src = 0;
s->chan[i].dest = 0;
s->chan[i].lli = 0;
s->chan[i].ctrl = 0;
s->chan[i].conf = 0;
}
}
static void pl080_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -382,9 +380,23 @@ static void pl080_init(Object *obj)
memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->interr);
sysbus_init_irq(sbd, &s->inttc);
s->nchannels = 8;
}
static void pl080_realize(DeviceState *dev, Error **errp)
{
PL080State *s = PL080(dev);
if (!s->downstream) {
error_setg(errp, "PL080 'downstream' link not set");
return;
}
address_space_init(&s->downstream_as, s->downstream, "pl080-downstream");
}
static void pl081_init(Object *obj)
{
PL080State *s = PL080(obj);
@@ -392,11 +404,20 @@ static void pl081_init(Object *obj)
s->nchannels = 2;
}
static Property pl080_properties[] = {
DEFINE_PROP_LINK("downstream", PL080State, downstream,
TYPE_MEMORY_REGION, MemoryRegion *),
DEFINE_PROP_END_OF_LIST(),
};
static void pl080_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->vmsd = &vmstate_pl080;
dc->realize = pl080_realize;
dc->props = pl080_properties;
dc->reset = pl080_reset;
}
static const TypeInfo pl080_info = {
@@ -408,7 +429,7 @@ static const TypeInfo pl080_info = {
};
static const TypeInfo pl081_info = {
.name = "pl081",
.name = TYPE_PL081,
.parent = TYPE_PL080,
.instance_init = pl081_init,
};

View File

@@ -188,7 +188,6 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
return;
}
blkconf_serial(&dev->conf, &dev->serial);
if (kind != IDE_CD) {
if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
errp)) {

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,13 @@ static int gic_post_load(void *opaque, int version_id)
return 0;
}
static bool gic_virt_state_needed(void *opaque)
{
GICState *s = (GICState *)opaque;
return s->virt_extn;
}
static const VMStateDescription vmstate_gic_irq_state = {
.name = "arm_gic_irq_state",
.version_id = 1,
@@ -62,6 +69,30 @@ static const VMStateDescription vmstate_gic_irq_state = {
}
};
static const VMStateDescription vmstate_gic_virt_state = {
.name = "arm_gic_virt_state",
.version_id = 1,
.minimum_version_id = 1,
.needed = gic_virt_state_needed,
.fields = (VMStateField[]) {
/* Virtual interface */
VMSTATE_UINT32_ARRAY(h_hcr, GICState, GIC_NCPU),
VMSTATE_UINT32_ARRAY(h_misr, GICState, GIC_NCPU),
VMSTATE_UINT32_2DARRAY(h_lr, GICState, GIC_MAX_LR, GIC_NCPU),
VMSTATE_UINT32_ARRAY(h_apr, GICState, GIC_NCPU),
/* Virtual CPU interfaces */
VMSTATE_UINT32_SUB_ARRAY(cpu_ctlr, GICState, GIC_NCPU, GIC_NCPU),
VMSTATE_UINT16_SUB_ARRAY(priority_mask, GICState, GIC_NCPU, GIC_NCPU),
VMSTATE_UINT16_SUB_ARRAY(running_priority, GICState, GIC_NCPU, GIC_NCPU),
VMSTATE_UINT16_SUB_ARRAY(current_pending, GICState, GIC_NCPU, GIC_NCPU),
VMSTATE_UINT8_SUB_ARRAY(bpr, GICState, GIC_NCPU, GIC_NCPU),
VMSTATE_UINT8_SUB_ARRAY(abpr, GICState, GIC_NCPU, GIC_NCPU),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_gic = {
.name = "arm_gic",
.version_id = 12,
@@ -70,26 +101,31 @@ static const VMStateDescription vmstate_gic = {
.post_load = gic_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(ctlr, GICState),
VMSTATE_UINT32_ARRAY(cpu_ctlr, GICState, GIC_NCPU),
VMSTATE_UINT32_SUB_ARRAY(cpu_ctlr, GICState, 0, GIC_NCPU),
VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
vmstate_gic_irq_state, gic_irq_state),
VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
VMSTATE_UINT8_2DARRAY(sgi_pending, GICState, GIC_NR_SGIS, GIC_NCPU),
VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU),
VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU),
VMSTATE_UINT16_SUB_ARRAY(priority_mask, GICState, 0, GIC_NCPU),
VMSTATE_UINT16_SUB_ARRAY(running_priority, GICState, 0, GIC_NCPU),
VMSTATE_UINT16_SUB_ARRAY(current_pending, GICState, 0, GIC_NCPU),
VMSTATE_UINT8_SUB_ARRAY(bpr, GICState, 0, GIC_NCPU),
VMSTATE_UINT8_SUB_ARRAY(abpr, GICState, 0, GIC_NCPU),
VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU),
VMSTATE_UINT32_2DARRAY(nsapr, GICState, GIC_NR_APRS, GIC_NCPU),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * []) {
&vmstate_gic_virt_state,
NULL
}
};
void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
const MemoryRegionOps *ops)
const MemoryRegionOps *ops,
const MemoryRegionOps *virt_ops)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
int i = s->num_irq - GIC_INTERNAL;
@@ -116,6 +152,11 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->parent_vfiq[i]);
}
if (s->virt_extn) {
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->maintenance_irq[i]);
}
}
/* Distributor */
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
@@ -127,6 +168,17 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
sysbus_init_mmio(sbd, &s->cpuiomem[0]);
if (s->virt_extn) {
memory_region_init_io(&s->vifaceiomem[0], OBJECT(s), virt_ops,
s, "gic_viface", 0x1000);
sysbus_init_mmio(sbd, &s->vifaceiomem[0]);
memory_region_init_io(&s->vcpuiomem, OBJECT(s),
virt_ops ? &virt_ops[1] : NULL,
s, "gic_vcpu", 0x2000);
sysbus_init_mmio(sbd, &s->vcpuiomem);
}
}
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
@@ -163,6 +215,48 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
"the security extensions");
return;
}
if (s->virt_extn) {
if (s->revision != 2) {
error_setg(errp, "GIC virtualization extensions are only "
"supported by revision 2");
return;
}
/* For now, set the number of implemented LRs to 4, as found in most
* real GICv2. This could be promoted as a QOM property if we need to
* emulate a variant with another num_lrs.
*/
s->num_lrs = 4;
}
}
static inline void arm_gic_common_reset_irq_state(GICState *s, int first_cpu,
int resetprio)
{
int i, j;
for (i = first_cpu; i < first_cpu + s->num_cpu; i++) {
if (s->revision == REV_11MPCORE) {
s->priority_mask[i] = 0xf0;
} else {
s->priority_mask[i] = resetprio;
}
s->current_pending[i] = 1023;
s->running_priority[i] = 0x100;
s->cpu_ctlr[i] = 0;
s->bpr[i] = gic_is_vcpu(i) ? GIC_VIRT_MIN_BPR : GIC_MIN_BPR;
s->abpr[i] = gic_is_vcpu(i) ? GIC_VIRT_MIN_ABPR : GIC_MIN_ABPR;
if (!gic_is_vcpu(i)) {
for (j = 0; j < GIC_INTERNAL; j++) {
s->priority1[j][i] = resetprio;
}
for (j = 0; j < GIC_NR_SGIS; j++) {
s->sgi_pending[j][i] = 0;
}
}
}
}
static void arm_gic_common_reset(DeviceState *dev)
@@ -185,27 +279,18 @@ static void arm_gic_common_reset(DeviceState *dev)
}
memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < s->num_cpu; i++) {
if (s->revision == REV_11MPCORE) {
s->priority_mask[i] = 0xf0;
} else {
s->priority_mask[i] = resetprio;
}
s->current_pending[i] = 1023;
s->running_priority[i] = 0x100;
s->cpu_ctlr[i] = 0;
s->bpr[i] = GIC_MIN_BPR;
s->abpr[i] = GIC_MIN_ABPR;
for (j = 0; j < GIC_INTERNAL; j++) {
s->priority1[j][i] = resetprio;
}
for (j = 0; j < GIC_NR_SGIS; j++) {
s->sgi_pending[j][i] = 0;
}
arm_gic_common_reset_irq_state(s, 0, resetprio);
if (s->virt_extn) {
/* vCPU states are stored at indexes GIC_NCPU .. GIC_NCPU+num_cpu.
* The exposed vCPU interface does not have security extensions.
*/
arm_gic_common_reset_irq_state(s, GIC_NCPU, 0);
}
for (i = 0; i < GIC_NR_SGIS; i++) {
GIC_SET_ENABLED(i, ALL_CPU_MASK);
GIC_SET_EDGE_TRIGGER(i);
GIC_DIST_SET_ENABLED(i, ALL_CPU_MASK);
GIC_DIST_SET_EDGE_TRIGGER(i);
}
for (i = 0; i < ARRAY_SIZE(s->priority2); i++) {
@@ -222,7 +307,20 @@ static void arm_gic_common_reset(DeviceState *dev)
}
if (s->security_extn && s->irq_reset_nonsecure) {
for (i = 0; i < GIC_MAXIRQ; i++) {
GIC_SET_GROUP(i, ALL_CPU_MASK);
GIC_DIST_SET_GROUP(i, ALL_CPU_MASK);
}
}
if (s->virt_extn) {
for (i = 0; i < s->num_lrs; i++) {
for (j = 0; j < s->num_cpu; j++) {
s->h_lr[i][j] = 0;
}
}
for (i = 0; i < s->num_cpu; i++) {
s->h_hcr[i] = 0;
s->h_misr[i] = 0;
}
}
@@ -255,6 +353,8 @@ static Property arm_gic_common_properties[] = {
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
/* True if the GIC should implement the security extensions */
DEFINE_PROP_BOOL("has-security-extensions", GICState, security_extn, 0),
/* True if the GIC should implement the virtualization extensions */
DEFINE_PROP_BOOL("has-virtualization-extensions", GICState, virt_extn, 0),
DEFINE_PROP_END_OF_LIST(),
};

View File

@@ -140,10 +140,10 @@ static void translate_group(GICState *s, int irq, int cpu,
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (to_kernel) {
*field = GIC_TEST_GROUP(irq, cm);
*field = GIC_DIST_TEST_GROUP(irq, cm);
} else {
if (*field & 1) {
GIC_SET_GROUP(irq, cm);
GIC_DIST_SET_GROUP(irq, cm);
}
}
}
@@ -154,10 +154,10 @@ static void translate_enabled(GICState *s, int irq, int cpu,
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (to_kernel) {
*field = GIC_TEST_ENABLED(irq, cm);
*field = GIC_DIST_TEST_ENABLED(irq, cm);
} else {
if (*field & 1) {
GIC_SET_ENABLED(irq, cm);
GIC_DIST_SET_ENABLED(irq, cm);
}
}
}
@@ -171,7 +171,7 @@ static void translate_pending(GICState *s, int irq, int cpu,
*field = gic_test_pending(s, irq, cm);
} else {
if (*field & 1) {
GIC_SET_PENDING(irq, cm);
GIC_DIST_SET_PENDING(irq, cm);
/* TODO: Capture is level-line is held high in the kernel */
}
}
@@ -183,10 +183,10 @@ static void translate_active(GICState *s, int irq, int cpu,
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (to_kernel) {
*field = GIC_TEST_ACTIVE(irq, cm);
*field = GIC_DIST_TEST_ACTIVE(irq, cm);
} else {
if (*field & 1) {
GIC_SET_ACTIVE(irq, cm);
GIC_DIST_SET_ACTIVE(irq, cm);
}
}
}
@@ -195,10 +195,10 @@ static void translate_trigger(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = (GIC_TEST_EDGE_TRIGGER(irq)) ? 0x2 : 0x0;
*field = (GIC_DIST_TEST_EDGE_TRIGGER(irq)) ? 0x2 : 0x0;
} else {
if (*field & 0x2) {
GIC_SET_EDGE_TRIGGER(irq);
GIC_DIST_SET_EDGE_TRIGGER(irq);
}
}
}
@@ -207,9 +207,10 @@ static void translate_priority(GICState *s, int irq, int cpu,
uint32_t *field, bool to_kernel)
{
if (to_kernel) {
*field = GIC_GET_PRIORITY(irq, cpu) & 0xff;
*field = GIC_DIST_GET_PRIORITY(irq, cpu) & 0xff;
} else {
gic_set_priority(s, cpu, irq, *field & 0xff, MEMTXATTRS_UNSPECIFIED);
gic_dist_set_priority(s, cpu, irq,
*field & 0xff, MEMTXATTRS_UNSPECIFIED);
}
}
@@ -510,6 +511,12 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
if (s->virt_extn) {
error_setg(errp, "the in-kernel VGIC does not implement the "
"virtualization extensions");
return;
}
if (!kvm_arm_gic_can_save_restore(s)) {
error_setg(&s->migration_blocker, "This operating system kernel does "
"not support vGICv2 migration");
@@ -521,7 +528,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
}
}
gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL, NULL);
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
qemu_irq irq = qdev_get_gpio_in(dev, i);

View File

@@ -85,7 +85,10 @@ static bool icv_access(CPUARMState *env, int hcr_flags)
* * access if NS EL1 and either IMO or FMO == 1:
* CTLR, DIR, PMR, RPR
*/
return (env->cp15.hcr_el2 & hcr_flags) && arm_current_el(env) == 1
bool flagmatch = ((hcr_flags & HCR_IMO) && arm_hcr_el2_imo(env)) ||
((hcr_flags & HCR_FMO) && arm_hcr_el2_fmo(env));
return flagmatch && arm_current_el(env) == 1
&& !arm_is_secure_below_el3(env);
}
@@ -1549,8 +1552,8 @@ static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
/* No need to include !IsSecure in route_*_to_el2 as it's only
* tested in cases where we know !IsSecure is true.
*/
route_fiq_to_el2 = env->cp15.hcr_el2 & HCR_FMO;
route_irq_to_el2 = env->cp15.hcr_el2 & HCR_IMO;
route_fiq_to_el2 = arm_hcr_el2_fmo(env);
route_irq_to_el2 = arm_hcr_el2_imo(env);
switch (arm_current_el(env)) {
case 3:
@@ -1893,7 +1896,7 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env,
switch (el) {
case 1:
if (arm_is_secure_below_el3(env) ||
((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) == 0)) {
(arm_hcr_el2_imo(env) == 0 && arm_hcr_el2_fmo(env) == 0)) {
r = CP_ACCESS_TRAP_EL3;
}
break;
@@ -1933,7 +1936,7 @@ static CPAccessResult gicv3_dir_access(CPUARMState *env,
static CPAccessResult gicv3_sgi_access(CPUARMState *env,
const ARMCPRegInfo *ri, bool isread)
{
if ((env->cp15.hcr_el2 & (HCR_IMO | HCR_FMO)) &&
if ((arm_hcr_el2_imo(env) || arm_hcr_el2_fmo(env)) &&
arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) {
/* Takes priority over a possible EL3 trap */
return CP_ACCESS_TRAP_EL2;
@@ -1958,8 +1961,7 @@ static CPAccessResult gicv3_fiq_access(CPUARMState *env,
if (env->cp15.scr_el3 & SCR_FIQ) {
switch (el) {
case 1:
if (arm_is_secure_below_el3(env) ||
((env->cp15.hcr_el2 & HCR_FMO) == 0)) {
if (arm_is_secure_below_el3(env) || !arm_hcr_el2_fmo(env)) {
r = CP_ACCESS_TRAP_EL3;
}
break;
@@ -1998,8 +2000,7 @@ static CPAccessResult gicv3_irq_access(CPUARMState *env,
if (env->cp15.scr_el3 & SCR_IRQ) {
switch (el) {
case 1:
if (arm_is_secure_below_el3(env) ||
((env->cp15.hcr_el2 & HCR_IMO) == 0)) {
if (arm_is_secure_below_el3(env) || !arm_hcr_el2_imo(env)) {
r = CP_ACCESS_TRAP_EL3;
}
break;

View File

@@ -211,7 +211,7 @@ static void kvm_arm_its_reset(DeviceState *dev)
return;
}
error_report("ITS KVM: full reset is not supported by the host kernel");
warn_report("ITS KVM: full reset is not supported by the host kernel");
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR)) {

View File

@@ -420,6 +420,8 @@ static void set_prio(NVICState *s, unsigned irq, bool secure, uint8_t prio)
assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */
assert(irq < s->num_irq);
prio &= MAKE_64BIT_MASK(8 - s->num_prio_bits, s->num_prio_bits);
if (secure) {
assert(exc_is_banked(irq));
s->sec_vectors[irq].prio = prio;
@@ -772,6 +774,24 @@ static void set_irq_level(void *opaque, int n, int level)
}
}
/* callback when external NMI line is changed */
static void nvic_nmi_trigger(void *opaque, int n, int level)
{
NVICState *s = opaque;
trace_nvic_set_nmi_level(level);
/*
* The architecture doesn't specify whether NMI should share
* the normal-interrupt behaviour of being resampled on
* exception handler return. We choose not to, so just
* set NMI pending here and don't track the current level.
*/
if (level) {
armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false);
}
}
static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
{
ARMCPU *cpu = s->cpu;
@@ -779,6 +799,9 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
switch (offset) {
case 4: /* Interrupt Control Type. */
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
goto bad_offset;
}
return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
case 0xc: /* CPPWR */
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
@@ -867,6 +890,9 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
}
return val;
case 0xd10: /* System Control. */
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
goto bad_offset;
}
return cpu->env.v7m.scr[attrs.secure];
case 0xd14: /* Configuration Control. */
/* The BFHFNMIGN bit is the only non-banked bit; we
@@ -876,6 +902,9 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
return val;
case 0xd24: /* System Handler Control and State (SHCSR) */
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
goto bad_offset;
}
val = 0;
if (attrs.secure) {
if (s->sec_vectors[ARMV7M_EXCP_MEM].active) {
@@ -988,12 +1017,21 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
}
return val;
case 0xd2c: /* Hard Fault Status. */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
return cpu->env.v7m.hfsr;
case 0xd30: /* Debug Fault Status. */
return cpu->env.v7m.dfsr;
case 0xd34: /* MMFAR MemManage Fault Address */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
return cpu->env.v7m.mmfar[attrs.secure];
case 0xd38: /* Bus Fault Address. */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
return cpu->env.v7m.bfar;
case 0xd3c: /* Aux Fault Status. */
/* TODO: Implement fault status registers. */
@@ -1263,9 +1301,12 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
"Setting VECTRESET when not in DEBUG mode "
"is UNPREDICTABLE\n");
}
s->prigroup[attrs.secure] = extract32(value,
R_V7M_AIRCR_PRIGROUP_SHIFT,
R_V7M_AIRCR_PRIGROUP_LENGTH);
if (arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
s->prigroup[attrs.secure] =
extract32(value,
R_V7M_AIRCR_PRIGROUP_SHIFT,
R_V7M_AIRCR_PRIGROUP_LENGTH);
}
if (attrs.secure) {
/* These bits are only writable by secure */
cpu->env.v7m.aircr = value &
@@ -1288,6 +1329,9 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
}
break;
case 0xd10: /* System Control. */
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
goto bad_offset;
}
/* We don't implement deep-sleep so these bits are RAZ/WI.
* The other bits in the register are banked.
* QEMU's implementation ignores SEVONPEND and SLEEPONEXIT, which
@@ -1297,6 +1341,10 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
cpu->env.v7m.scr[attrs.secure] = value;
break;
case 0xd14: /* Configuration Control. */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
value &= (R_V7M_CCR_STKALIGN_MASK |
R_V7M_CCR_BFHFNMIGN_MASK |
@@ -1321,6 +1369,9 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
cpu->env.v7m.ccr[attrs.secure] = value;
break;
case 0xd24: /* System Handler Control and State (SHCSR) */
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
goto bad_offset;
}
if (attrs.secure) {
s->sec_vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
/* Secure HardFault active bit cannot be written */
@@ -1389,15 +1440,24 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
nvic_irq_update(s);
break;
case 0xd2c: /* Hard Fault Status. */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
cpu->env.v7m.hfsr &= ~value; /* W1C */
break;
case 0xd30: /* Debug Fault Status. */
cpu->env.v7m.dfsr &= ~value; /* W1C */
break;
case 0xd34: /* Mem Manage Address. */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
cpu->env.v7m.mmfar[attrs.secure] = value;
return;
case 0xd38: /* Bus Fault Address. */
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
cpu->env.v7m.bfar = value;
return;
case 0xd3c: /* Aux Fault Status. */
@@ -1627,6 +1687,11 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
case 0xf00: /* Software Triggered Interrupt Register */
{
int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
goto bad_offset;
}
if (excnum < s->num_irq) {
armv7m_nvic_set_pending(s, excnum, false);
}
@@ -1752,6 +1817,11 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
break;
case 0x300 ... 0x33f: /* NVIC Active */
val = 0;
if (!arm_feature(&s->cpu->env, ARM_FEATURE_V7)) {
break;
}
startvec = 8 * (offset - 0x300) + NVIC_FIRST_IRQ; /* vector # */
for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
@@ -1771,7 +1841,13 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
}
}
break;
case 0xd18 ... 0xd23: /* System Handler Priority (SHPR1, SHPR2, SHPR3) */
case 0xd18: /* System Handler Priority (SHPR1) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
val = 0;
break;
}
/* fall through */
case 0xd1c ... 0xd23: /* System Handler Priority (SHPR2, SHPR3) */
val = 0;
for (i = 0; i < size; i++) {
unsigned hdlidx = (offset - 0xd14) + i;
@@ -1784,6 +1860,10 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
}
break;
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
val = 0;
break;
};
/* The BFSR bits [15:8] are shared between security states
* and we store them in the NS copy
*/
@@ -1876,7 +1956,12 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
}
nvic_irq_update(s);
return MEMTX_OK;
case 0xd18 ... 0xd23: /* System Handler Priority (SHPR1, SHPR2, SHPR3) */
case 0xd18: /* System Handler Priority (SHPR1) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
return MEMTX_OK;
}
/* fall through */
case 0xd1c ... 0xd23: /* System Handler Priority (SHPR2, SHPR3) */
for (i = 0; i < size; i++) {
unsigned hdlidx = (offset - 0xd14) + i;
int newprio = extract32(value, i * 8, 8);
@@ -1890,6 +1975,9 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
nvic_irq_update(s);
return MEMTX_OK;
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
return MEMTX_OK;
}
/* All bits are W1C, so construct 32 bit value with 0s in
* the parts not written by the access size
*/
@@ -2203,6 +2291,8 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
/* include space for internal exception vectors */
s->num_irq += NVIC_FIRST_IRQ;
s->num_prio_bits = arm_feature(&s->cpu->env, ARM_FEATURE_V7) ? 8 : 2;
object_property_set_bool(OBJECT(&s->systick[M_REG_NS]), true,
"realized", &err);
if (err != NULL) {
@@ -2310,6 +2400,7 @@ static void armv7m_nvic_instance_init(Object *obj)
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
M_REG_NUM_BANKS);
qdev_init_gpio_in_named(dev, nvic_nmi_trigger, "NMI", 1);
}
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)

View File

@@ -21,36 +21,38 @@
#ifndef QEMU_ARM_GIC_INTERNAL_H
#define QEMU_ARM_GIC_INTERNAL_H
#include "hw/registerfields.h"
#include "hw/intc/arm_gic.h"
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
#define GIC_BASE_IRQ 0
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true
#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false
#define GIC_TEST_MODEL(irq) s->irq_state[irq].model
#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level |= (cm)
#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false
#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \
#define GIC_DIST_SET_ENABLED(irq, cm) (s->irq_state[irq].enabled |= (cm))
#define GIC_DIST_CLEAR_ENABLED(irq, cm) (s->irq_state[irq].enabled &= ~(cm))
#define GIC_DIST_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
#define GIC_DIST_SET_PENDING(irq, cm) (s->irq_state[irq].pending |= (cm))
#define GIC_DIST_CLEAR_PENDING(irq, cm) (s->irq_state[irq].pending &= ~(cm))
#define GIC_DIST_SET_ACTIVE(irq, cm) (s->irq_state[irq].active |= (cm))
#define GIC_DIST_CLEAR_ACTIVE(irq, cm) (s->irq_state[irq].active &= ~(cm))
#define GIC_DIST_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
#define GIC_DIST_SET_MODEL(irq) (s->irq_state[irq].model = true)
#define GIC_DIST_CLEAR_MODEL(irq) (s->irq_state[irq].model = false)
#define GIC_DIST_TEST_MODEL(irq) (s->irq_state[irq].model)
#define GIC_DIST_SET_LEVEL(irq, cm) (s->irq_state[irq].level |= (cm))
#define GIC_DIST_CLEAR_LEVEL(irq, cm) (s->irq_state[irq].level &= ~(cm))
#define GIC_DIST_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
#define GIC_DIST_SET_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger = true)
#define GIC_DIST_CLEAR_EDGE_TRIGGER(irq) \
(s->irq_state[irq].edge_trigger = false)
#define GIC_DIST_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
#define GIC_DIST_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \
s->priority1[irq][cpu] : \
s->priority2[(irq) - GIC_INTERNAL])
#define GIC_TARGET(irq) s->irq_target[irq]
#define GIC_CLEAR_GROUP(irq, cm) (s->irq_state[irq].group &= ~(cm))
#define GIC_SET_GROUP(irq, cm) (s->irq_state[irq].group |= (cm))
#define GIC_TEST_GROUP(irq, cm) ((s->irq_state[irq].group & (cm)) != 0)
#define GIC_DIST_TARGET(irq) (s->irq_target[irq])
#define GIC_DIST_CLEAR_GROUP(irq, cm) (s->irq_state[irq].group &= ~(cm))
#define GIC_DIST_SET_GROUP(irq, cm) (s->irq_state[irq].group |= (cm))
#define GIC_DIST_TEST_GROUP(irq, cm) ((s->irq_state[irq].group & (cm)) != 0)
#define GICD_CTLR_EN_GRP0 (1U << 0)
#define GICD_CTLR_EN_GRP1 (1U << 1)
@@ -63,6 +65,91 @@
#define GICC_CTLR_EOIMODE (1U << 9)
#define GICC_CTLR_EOIMODE_NS (1U << 10)
REG32(GICH_HCR, 0x0)
FIELD(GICH_HCR, EN, 0, 1)
FIELD(GICH_HCR, UIE, 1, 1)
FIELD(GICH_HCR, LRENPIE, 2, 1)
FIELD(GICH_HCR, NPIE, 3, 1)
FIELD(GICH_HCR, VGRP0EIE, 4, 1)
FIELD(GICH_HCR, VGRP0DIE, 5, 1)
FIELD(GICH_HCR, VGRP1EIE, 6, 1)
FIELD(GICH_HCR, VGRP1DIE, 7, 1)
FIELD(GICH_HCR, EOICount, 27, 5)
#define GICH_HCR_MASK \
(R_GICH_HCR_EN_MASK | R_GICH_HCR_UIE_MASK | \
R_GICH_HCR_LRENPIE_MASK | R_GICH_HCR_NPIE_MASK | \
R_GICH_HCR_VGRP0EIE_MASK | R_GICH_HCR_VGRP0DIE_MASK | \
R_GICH_HCR_VGRP1EIE_MASK | R_GICH_HCR_VGRP1DIE_MASK | \
R_GICH_HCR_EOICount_MASK)
REG32(GICH_VTR, 0x4)
FIELD(GICH_VTR, ListRegs, 0, 6)
FIELD(GICH_VTR, PREbits, 26, 3)
FIELD(GICH_VTR, PRIbits, 29, 3)
REG32(GICH_VMCR, 0x8)
FIELD(GICH_VMCR, VMCCtlr, 0, 10)
FIELD(GICH_VMCR, VMABP, 18, 3)
FIELD(GICH_VMCR, VMBP, 21, 3)
FIELD(GICH_VMCR, VMPriMask, 27, 5)
REG32(GICH_MISR, 0x10)
FIELD(GICH_MISR, EOI, 0, 1)
FIELD(GICH_MISR, U, 1, 1)
FIELD(GICH_MISR, LRENP, 2, 1)
FIELD(GICH_MISR, NP, 3, 1)
FIELD(GICH_MISR, VGrp0E, 4, 1)
FIELD(GICH_MISR, VGrp0D, 5, 1)
FIELD(GICH_MISR, VGrp1E, 6, 1)
FIELD(GICH_MISR, VGrp1D, 7, 1)
REG32(GICH_EISR0, 0x20)
REG32(GICH_EISR1, 0x24)
REG32(GICH_ELRSR0, 0x30)
REG32(GICH_ELRSR1, 0x34)
REG32(GICH_APR, 0xf0)
REG32(GICH_LR0, 0x100)
FIELD(GICH_LR0, VirtualID, 0, 10)
FIELD(GICH_LR0, PhysicalID, 10, 10)
FIELD(GICH_LR0, CPUID, 10, 3)
FIELD(GICH_LR0, EOI, 19, 1)
FIELD(GICH_LR0, Priority, 23, 5)
FIELD(GICH_LR0, State, 28, 2)
FIELD(GICH_LR0, Grp1, 30, 1)
FIELD(GICH_LR0, HW, 31, 1)
/* Last LR register */
REG32(GICH_LR63, 0x1fc)
#define GICH_LR_MASK \
(R_GICH_LR0_VirtualID_MASK | R_GICH_LR0_PhysicalID_MASK | \
R_GICH_LR0_CPUID_MASK | R_GICH_LR0_EOI_MASK | \
R_GICH_LR0_Priority_MASK | R_GICH_LR0_State_MASK | \
R_GICH_LR0_Grp1_MASK | R_GICH_LR0_HW_MASK)
#define GICH_LR_STATE_INVALID 0
#define GICH_LR_STATE_PENDING 1
#define GICH_LR_STATE_ACTIVE 2
#define GICH_LR_STATE_ACTIVE_PENDING 3
#define GICH_LR_VIRT_ID(entry) (FIELD_EX32(entry, GICH_LR0, VirtualID))
#define GICH_LR_PHYS_ID(entry) (FIELD_EX32(entry, GICH_LR0, PhysicalID))
#define GICH_LR_CPUID(entry) (FIELD_EX32(entry, GICH_LR0, CPUID))
#define GICH_LR_EOI(entry) (FIELD_EX32(entry, GICH_LR0, EOI))
#define GICH_LR_PRIORITY(entry) (FIELD_EX32(entry, GICH_LR0, Priority) << 3)
#define GICH_LR_STATE(entry) (FIELD_EX32(entry, GICH_LR0, State))
#define GICH_LR_GROUP(entry) (FIELD_EX32(entry, GICH_LR0, Grp1))
#define GICH_LR_HW(entry) (FIELD_EX32(entry, GICH_LR0, HW))
#define GICH_LR_CLEAR_PENDING(entry) \
((entry) &= ~(GICH_LR_STATE_PENDING << R_GICH_LR0_State_SHIFT))
#define GICH_LR_SET_ACTIVE(entry) \
((entry) |= (GICH_LR_STATE_ACTIVE << R_GICH_LR0_State_SHIFT))
#define GICH_LR_CLEAR_ACTIVE(entry) \
((entry) &= ~(GICH_LR_STATE_ACTIVE << R_GICH_LR0_State_SHIFT))
/* Valid bits for GICC_CTLR for GICv1, v1 with security extensions,
* GICv2 and GICv2 with security extensions:
*/
@@ -74,13 +161,9 @@
/* The special cases for the revision property: */
#define REV_11MPCORE 0
void gic_set_pending_private(GICState *s, int cpu, int irq);
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s);
void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val,
MemTxAttrs attrs);
void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val,
MemTxAttrs attrs);
static inline bool gic_test_pending(GICState *s, int irq, int cm)
{
@@ -93,7 +176,148 @@ static inline bool gic_test_pending(GICState *s, int irq, int cm)
* GICD_ISPENDR to set the state pending.
*/
return (s->irq_state[irq].pending & cm) ||
(!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_LEVEL(irq, cm));
(!GIC_DIST_TEST_EDGE_TRIGGER(irq) && GIC_DIST_TEST_LEVEL(irq, cm));
}
}
static inline bool gic_is_vcpu(int cpu)
{
return cpu >= GIC_NCPU;
}
static inline int gic_get_vcpu_real_id(int cpu)
{
return (cpu >= GIC_NCPU) ? (cpu - GIC_NCPU) : cpu;
}
/* Return true if the given vIRQ state exists in a LR and is either active or
* pending and active.
*
* This function is used to check that a guest's `end of interrupt' or
* `interrupts deactivation' request is valid, and matches with a LR of an
* already acknowledged vIRQ (i.e. has the active bit set in its state).
*/
static inline bool gic_virq_is_valid(GICState *s, int irq, int vcpu)
{
int cpu = gic_get_vcpu_real_id(vcpu);
int lr_idx;
for (lr_idx = 0; lr_idx < s->num_lrs; lr_idx++) {
uint32_t *entry = &s->h_lr[lr_idx][cpu];
if ((GICH_LR_VIRT_ID(*entry) == irq) &&
(GICH_LR_STATE(*entry) & GICH_LR_STATE_ACTIVE)) {
return true;
}
}
return false;
}
/* Return a pointer on the LR entry matching the given vIRQ.
*
* This function is used to retrieve an LR for which we know for sure that the
* corresponding vIRQ exists in the current context (i.e. its current state is
* not `invalid'):
* - Either the corresponding vIRQ has been validated with gic_virq_is_valid()
* so it is `active' or `active and pending',
* - Or it was pending and has been selected by gic_get_best_virq(). It is now
* `pending', `active' or `active and pending', depending on what the guest
* already did with this vIRQ.
*
* Having multiple LRs with the same VirtualID leads to UNPREDICTABLE
* behaviour in the GIC. We choose to return the first one that matches.
*/
static inline uint32_t *gic_get_lr_entry(GICState *s, int irq, int vcpu)
{
int cpu = gic_get_vcpu_real_id(vcpu);
int lr_idx;
for (lr_idx = 0; lr_idx < s->num_lrs; lr_idx++) {
uint32_t *entry = &s->h_lr[lr_idx][cpu];
if ((GICH_LR_VIRT_ID(*entry) == irq) &&
(GICH_LR_STATE(*entry) != GICH_LR_STATE_INVALID)) {
return entry;
}
}
g_assert_not_reached();
}
static inline bool gic_test_group(GICState *s, int irq, int cpu)
{
if (gic_is_vcpu(cpu)) {
uint32_t *entry = gic_get_lr_entry(s, irq, cpu);
return GICH_LR_GROUP(*entry);
} else {
return GIC_DIST_TEST_GROUP(irq, 1 << cpu);
}
}
static inline void gic_clear_pending(GICState *s, int irq, int cpu)
{
if (gic_is_vcpu(cpu)) {
uint32_t *entry = gic_get_lr_entry(s, irq, cpu);
GICH_LR_CLEAR_PENDING(*entry);
} else {
/* Clear pending state for both level and edge triggered
* interrupts. (level triggered interrupts with an active line
* remain pending, see gic_test_pending)
*/
GIC_DIST_CLEAR_PENDING(irq, GIC_DIST_TEST_MODEL(irq) ? ALL_CPU_MASK
: (1 << cpu));
}
}
static inline void gic_set_active(GICState *s, int irq, int cpu)
{
if (gic_is_vcpu(cpu)) {
uint32_t *entry = gic_get_lr_entry(s, irq, cpu);
GICH_LR_SET_ACTIVE(*entry);
} else {
GIC_DIST_SET_ACTIVE(irq, 1 << cpu);
}
}
static inline void gic_clear_active(GICState *s, int irq, int cpu)
{
if (gic_is_vcpu(cpu)) {
uint32_t *entry = gic_get_lr_entry(s, irq, cpu);
GICH_LR_CLEAR_ACTIVE(*entry);
if (GICH_LR_HW(*entry)) {
/* Hardware interrupt. We must forward the deactivation request to
* the distributor.
*/
int phys_irq = GICH_LR_PHYS_ID(*entry);
int rcpu = gic_get_vcpu_real_id(cpu);
if (phys_irq < GIC_NR_SGIS || phys_irq >= GIC_MAXIRQ) {
/* UNPREDICTABLE behaviour, we choose to ignore the request */
return;
}
/* This is equivalent to a NS write to DIR on the physical CPU
* interface. Hence group0 interrupt deactivation is ignored if
* the GIC is secure.
*/
if (!s->security_extn || GIC_DIST_TEST_GROUP(phys_irq, 1 << rcpu)) {
GIC_DIST_CLEAR_ACTIVE(phys_irq, 1 << rcpu);
}
}
} else {
GIC_DIST_CLEAR_ACTIVE(irq, 1 << cpu);
}
}
static inline int gic_get_priority(GICState *s, int irq, int cpu)
{
if (gic_is_vcpu(cpu)) {
uint32_t *entry = gic_get_lr_entry(s, irq, cpu);
return GICH_LR_PRIORITY(*entry);
} else {
return GIC_DIST_GET_PRIORITY(irq, cpu);
}
}

View File

@@ -92,9 +92,17 @@ aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64
gic_enable_irq(int irq) "irq %d enabled"
gic_disable_irq(int irq) "irq %d disabled"
gic_set_irq(int irq, int level, int cpumask, int target) "irq %d level %d cpumask 0x%x target 0x%x"
gic_update_bestirq(int cpu, int irq, int prio, int priority_mask, int running_priority) "cpu %d irq %d priority %d cpu priority mask %d cpu running priority %d"
gic_update_bestirq(const char *s, int cpu, int irq, int prio, int priority_mask, int running_priority) "%s %d irq %d priority %d cpu priority mask %d cpu running priority %d"
gic_update_set_irq(int cpu, const char *name, int level) "cpu[%d]: %s = %d"
gic_acknowledge_irq(int cpu, int irq) "cpu %d acknowledged irq %d"
gic_acknowledge_irq(const char *s, int cpu, int irq) "%s %d acknowledged irq %d"
gic_cpu_write(const char *s, int cpu, int addr, uint32_t val) "%s %d iface write at 0x%08x 0x%08" PRIx32
gic_cpu_read(const char *s, int cpu, int addr, uint32_t val) "%s %d iface read at 0x%08x: 0x%08" PRIx32
gic_hyp_read(int addr, uint32_t val) "hyp read at 0x%08x: 0x%08" PRIx32
gic_hyp_write(int addr, uint32_t val) "hyp write at 0x%08x: 0x%08" PRIx32
gic_dist_read(int addr, unsigned int size, uint32_t val) "dist read at 0x%08x size %u: 0x%08" PRIx32
gic_dist_write(int addr, unsigned int size, uint32_t val) "dist write at 0x%08x size %u: 0x%08" PRIx32
gic_lr_entry(int cpu, int entry, uint32_t val) "cpu %d: new lr entry %d: 0x%08" PRIx32
gic_update_maintenance_irq(int cpu, int val) "cpu %d: maintenance = %d"
# hw/intc/arm_gicv3_cpuif.c
gicv3_icc_pmr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR read cpu 0x%x value 0x%" PRIx64
@@ -184,6 +192,7 @@ nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (pr
nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
nvic_set_nmi_level(int level) "NVIC external NMI level set to %d"
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"

View File

@@ -36,6 +36,7 @@ obj-$(CONFIG_IMX) += imx_ccm.o
obj-$(CONFIG_IMX) += imx31_ccm.o
obj-$(CONFIG_IMX) += imx25_ccm.o
obj-$(CONFIG_IMX) += imx6_ccm.o
obj-$(CONFIG_IMX) += imx6ul_ccm.o
obj-$(CONFIG_IMX) += imx6_src.o
obj-$(CONFIG_IMX) += imx7_ccm.o
obj-$(CONFIG_IMX) += imx2_wdt.o
@@ -70,5 +71,4 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
obj-$(CONFIG_AUX) += auxbus.o
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
obj-y += mmio_interface.o
obj-$(CONFIG_MSF2) += msf2-sysreg.o

View File

@@ -23,6 +23,14 @@
/* Configuration Register */
#define R_CONF (0x04 / 4)
/* Control/Status Register #1 (ast2500) */
#define R_STATUS1 (0x60 / 4)
#define PHY_BUSY_STATE BIT(0)
#define R_ECC_TEST_CTRL (0x70 / 4)
#define ECC_TEST_FINISHED BIT(12)
#define ECC_TEST_FAIL BIT(13)
/*
* Configuration register Ox4 (for Aspeed AST2400 SOC)
*
@@ -126,15 +134,33 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
case AST2400_A0_SILICON_REV:
case AST2400_A1_SILICON_REV:
data &= ~ASPEED_SDMC_READONLY_MASK;
data |= s->fixed_conf;
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
data |= s->fixed_conf;
break;
default:
g_assert_not_reached();
}
}
if (s->silicon_rev == AST2500_A0_SILICON_REV ||
s->silicon_rev == AST2500_A1_SILICON_REV) {
switch (addr) {
case R_STATUS1:
/* Will never return 'busy' */
data &= ~PHY_BUSY_STATE;
break;
case R_ECC_TEST_CTRL:
/* Always done, always happy */
data |= ECC_TEST_FINISHED;
data &= ~ECC_TEST_FAIL;
break;
default:
break;
}
}
s->regs[addr] = data;
}
@@ -198,25 +224,7 @@ static void aspeed_sdmc_reset(DeviceState *dev)
memset(s->regs, 0, sizeof(s->regs));
/* Set ram size bit and defaults values */
switch (s->silicon_rev) {
case AST2400_A0_SILICON_REV:
case AST2400_A1_SILICON_REV:
s->regs[R_CONF] |=
ASPEED_SDMC_VGA_COMPAT |
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
s->regs[R_CONF] |=
ASPEED_SDMC_HW_VERSION(1) |
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
default:
g_assert_not_reached();
}
s->regs[R_CONF] = s->fixed_conf;
}
static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
@@ -234,10 +242,18 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
case AST2400_A0_SILICON_REV:
case AST2400_A1_SILICON_REV:
s->ram_bits = ast2400_rambits(s);
s->max_ram_size = 512 << 20;
s->fixed_conf = ASPEED_SDMC_VGA_COMPAT |
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
s->ram_bits = ast2500_rambits(s);
s->max_ram_size = 1024 << 20;
s->fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
ASPEED_SDMC_CACHE_INITIAL_DONE |
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
default:
g_assert_not_reached();
@@ -261,6 +277,7 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
static Property aspeed_sdmc_properties[] = {
DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0),
DEFINE_PROP_END_OF_LIST(),
};

886
hw/misc/imx6ul_ccm.c Normal file
View File

@@ -0,0 +1,886 @@
/*
* IMX6UL Clock Control Module
*
* Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
* To get the timer frequencies right, we need to emulate at least part of
* the CCM.
*/
#include "qemu/osdep.h"
#include "hw/registerfields.h"
#include "hw/misc/imx6ul_ccm.h"
#include "qemu/log.h"
#include "trace.h"
static const char *imx6ul_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
switch (reg) {
case CCM_CCR:
return "CCR";
case CCM_CCDR:
return "CCDR";
case CCM_CSR:
return "CSR";
case CCM_CCSR:
return "CCSR";
case CCM_CACRR:
return "CACRR";
case CCM_CBCDR:
return "CBCDR";
case CCM_CBCMR:
return "CBCMR";
case CCM_CSCMR1:
return "CSCMR1";
case CCM_CSCMR2:
return "CSCMR2";
case CCM_CSCDR1:
return "CSCDR1";
case CCM_CS1CDR:
return "CS1CDR";
case CCM_CS2CDR:
return "CS2CDR";
case CCM_CDCDR:
return "CDCDR";
case CCM_CHSCCDR:
return "CHSCCDR";
case CCM_CSCDR2:
return "CSCDR2";
case CCM_CSCDR3:
return "CSCDR3";
case CCM_CDHIPR:
return "CDHIPR";
case CCM_CTOR:
return "CTOR";
case CCM_CLPCR:
return "CLPCR";
case CCM_CISR:
return "CISR";
case CCM_CIMR:
return "CIMR";
case CCM_CCOSR:
return "CCOSR";
case CCM_CGPR:
return "CGPR";
case CCM_CCGR0:
return "CCGR0";
case CCM_CCGR1:
return "CCGR1";
case CCM_CCGR2:
return "CCGR2";
case CCM_CCGR3:
return "CCGR3";
case CCM_CCGR4:
return "CCGR4";
case CCM_CCGR5:
return "CCGR5";
case CCM_CCGR6:
return "CCGR6";
case CCM_CMEOR:
return "CMEOR";
default:
sprintf(unknown, "%d ?", reg);
return unknown;
}
}
static const char *imx6ul_analog_reg_name(uint32_t reg)
{
static char unknown[20];
switch (reg) {
case CCM_ANALOG_PLL_ARM:
return "PLL_ARM";
case CCM_ANALOG_PLL_ARM_SET:
return "PLL_ARM_SET";
case CCM_ANALOG_PLL_ARM_CLR:
return "PLL_ARM_CLR";
case CCM_ANALOG_PLL_ARM_TOG:
return "PLL_ARM_TOG";
case CCM_ANALOG_PLL_USB1:
return "PLL_USB1";
case CCM_ANALOG_PLL_USB1_SET:
return "PLL_USB1_SET";
case CCM_ANALOG_PLL_USB1_CLR:
return "PLL_USB1_CLR";
case CCM_ANALOG_PLL_USB1_TOG:
return "PLL_USB1_TOG";
case CCM_ANALOG_PLL_USB2:
return "PLL_USB2";
case CCM_ANALOG_PLL_USB2_SET:
return "PLL_USB2_SET";
case CCM_ANALOG_PLL_USB2_CLR:
return "PLL_USB2_CLR";
case CCM_ANALOG_PLL_USB2_TOG:
return "PLL_USB2_TOG";
case CCM_ANALOG_PLL_SYS:
return "PLL_SYS";
case CCM_ANALOG_PLL_SYS_SET:
return "PLL_SYS_SET";
case CCM_ANALOG_PLL_SYS_CLR:
return "PLL_SYS_CLR";
case CCM_ANALOG_PLL_SYS_TOG:
return "PLL_SYS_TOG";
case CCM_ANALOG_PLL_SYS_SS:
return "PLL_SYS_SS";
case CCM_ANALOG_PLL_SYS_NUM:
return "PLL_SYS_NUM";
case CCM_ANALOG_PLL_SYS_DENOM:
return "PLL_SYS_DENOM";
case CCM_ANALOG_PLL_AUDIO:
return "PLL_AUDIO";
case CCM_ANALOG_PLL_AUDIO_SET:
return "PLL_AUDIO_SET";
case CCM_ANALOG_PLL_AUDIO_CLR:
return "PLL_AUDIO_CLR";
case CCM_ANALOG_PLL_AUDIO_TOG:
return "PLL_AUDIO_TOG";
case CCM_ANALOG_PLL_AUDIO_NUM:
return "PLL_AUDIO_NUM";
case CCM_ANALOG_PLL_AUDIO_DENOM:
return "PLL_AUDIO_DENOM";
case CCM_ANALOG_PLL_VIDEO:
return "PLL_VIDEO";
case CCM_ANALOG_PLL_VIDEO_SET:
return "PLL_VIDEO_SET";
case CCM_ANALOG_PLL_VIDEO_CLR:
return "PLL_VIDEO_CLR";
case CCM_ANALOG_PLL_VIDEO_TOG:
return "PLL_VIDEO_TOG";
case CCM_ANALOG_PLL_VIDEO_NUM:
return "PLL_VIDEO_NUM";
case CCM_ANALOG_PLL_VIDEO_DENOM:
return "PLL_VIDEO_DENOM";
case CCM_ANALOG_PLL_ENET:
return "PLL_ENET";
case CCM_ANALOG_PLL_ENET_SET:
return "PLL_ENET_SET";
case CCM_ANALOG_PLL_ENET_CLR:
return "PLL_ENET_CLR";
case CCM_ANALOG_PLL_ENET_TOG:
return "PLL_ENET_TOG";
case CCM_ANALOG_PFD_480:
return "PFD_480";
case CCM_ANALOG_PFD_480_SET:
return "PFD_480_SET";
case CCM_ANALOG_PFD_480_CLR:
return "PFD_480_CLR";
case CCM_ANALOG_PFD_480_TOG:
return "PFD_480_TOG";
case CCM_ANALOG_PFD_528:
return "PFD_528";
case CCM_ANALOG_PFD_528_SET:
return "PFD_528_SET";
case CCM_ANALOG_PFD_528_CLR:
return "PFD_528_CLR";
case CCM_ANALOG_PFD_528_TOG:
return "PFD_528_TOG";
case CCM_ANALOG_MISC0:
return "MISC0";
case CCM_ANALOG_MISC0_SET:
return "MISC0_SET";
case CCM_ANALOG_MISC0_CLR:
return "MISC0_CLR";
case CCM_ANALOG_MISC0_TOG:
return "MISC0_TOG";
case CCM_ANALOG_MISC2:
return "MISC2";
case CCM_ANALOG_MISC2_SET:
return "MISC2_SET";
case CCM_ANALOG_MISC2_CLR:
return "MISC2_CLR";
case CCM_ANALOG_MISC2_TOG:
return "MISC2_TOG";
case PMU_REG_1P1:
return "PMU_REG_1P1";
case PMU_REG_3P0:
return "PMU_REG_3P0";
case PMU_REG_2P5:
return "PMU_REG_2P5";
case PMU_REG_CORE:
return "PMU_REG_CORE";
case PMU_MISC1:
return "PMU_MISC1";
case PMU_MISC1_SET:
return "PMU_MISC1_SET";
case PMU_MISC1_CLR:
return "PMU_MISC1_CLR";
case PMU_MISC1_TOG:
return "PMU_MISC1_TOG";
case USB_ANALOG_DIGPROG:
return "USB_ANALOG_DIGPROG";
default:
sprintf(unknown, "%d ?", reg);
return unknown;
}
}
#define CKIH_FREQ 24000000 /* 24MHz crystal input */
static const VMStateDescription vmstate_imx6ul_ccm = {
.name = TYPE_IMX6UL_CCM,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX),
VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX),
VMSTATE_END_OF_LIST()
},
};
static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev)
{
uint64_t freq = CKIH_FREQ;
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev)
{
uint64_t freq = imx6ul_analog_get_osc_clk(dev);
if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS],
ANALOG_PLL_SYS, DIV_SELECT)) {
freq *= 22;
} else {
freq *= 20;
}
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev)
{
uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20;
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
freq = imx6ul_analog_get_pll2_clk(dev) * 18
/ FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
ANALOG_PFD_528, PFD0_FRAC);
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
freq = imx6ul_analog_get_pll2_clk(dev) * 18
/ FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
ANALOG_PFD_528, PFD2_FRAC);
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) {
case 0:
freq = imx6ul_analog_get_pll3_clk(dev);
break;
case 1:
freq = imx6ul_analog_get_osc_clk(dev);
break;
case 2:
freq = imx6ul_analog_pll2_bypass_clk(dev);
break;
case 3:
/* We should never get there as 3 is a reserved value */
qemu_log_mask(LOG_GUEST_ERROR,
"[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n",
TYPE_IMX6UL_CCM, __func__);
/* freq is set to 0 as we don't know what it should be */
break;
default:
g_assert_not_reached();
}
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) {
case 0:
freq = imx6ul_analog_get_pll2_clk(dev);
break;
case 1:
freq = imx6ul_analog_get_pll2_pfd2_clk(dev);
break;
case 2:
freq = imx6ul_analog_get_pll2_pfd0_clk(dev);
break;
case 3:
freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2;
break;
default:
g_assert_not_reached();
}
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev)
/ (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF));
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) {
case 0:
freq = imx6ul_ccm_get_periph_clk_sel_clk(dev);
break;
case 1:
freq = imx6ul_ccm_get_periph_clk2_clk(dev);
break;
default:
g_assert_not_reached();
}
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
freq = imx6ul_ccm_get_periph_sel_clk(dev)
/ (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF));
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
freq = imx6ul_ccm_get_ahb_clk(dev)
/ (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF));
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) {
case 0:
freq = imx6ul_ccm_get_ipg_clk(dev);
break;
case 1:
freq = imx6ul_analog_get_osc_clk(dev);
break;
default:
g_assert_not_reached();
}
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev)
{
uint64_t freq = 0;
freq = imx6ul_ccm_get_per_sel_clk(dev)
/ (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF));
trace_ccm_freq((uint32_t)freq);
return freq;
}
static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
{
uint32_t freq = 0;
IMX6ULCCMState *s = IMX6UL_CCM(dev);
switch (clock) {
case CLK_NONE:
break;
case CLK_IPG:
freq = imx6ul_ccm_get_ipg_clk(s);
break;
case CLK_IPG_HIGH:
freq = imx6ul_ccm_get_per_clk(s);
break;
case CLK_32k:
freq = CKIL_FREQ;
break;
case CLK_HIGH:
freq = CKIH_FREQ;
break;
case CLK_HIGH_DIV:
freq = CKIH_FREQ / 8;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
TYPE_IMX6UL_CCM, __func__, clock);
break;
}
trace_ccm_clock_freq(clock, freq);
return freq;
}
static void imx6ul_ccm_reset(DeviceState *dev)
{
IMX6ULCCMState *s = IMX6UL_CCM(dev);
trace_ccm_entry();
s->ccm[CCM_CCR] = 0x0401167F;
s->ccm[CCM_CCDR] = 0x00000000;
s->ccm[CCM_CSR] = 0x00000010;
s->ccm[CCM_CCSR] = 0x00000100;
s->ccm[CCM_CACRR] = 0x00000000;
s->ccm[CCM_CBCDR] = 0x00018D00;
s->ccm[CCM_CBCMR] = 0x24860324;
s->ccm[CCM_CSCMR1] = 0x04900080;
s->ccm[CCM_CSCMR2] = 0x03192F06;
s->ccm[CCM_CSCDR1] = 0x00490B00;
s->ccm[CCM_CS1CDR] = 0x0EC102C1;
s->ccm[CCM_CS2CDR] = 0x000336C1;
s->ccm[CCM_CDCDR] = 0x33F71F92;
s->ccm[CCM_CHSCCDR] = 0x000248A4;
s->ccm[CCM_CSCDR2] = 0x00029B48;
s->ccm[CCM_CSCDR3] = 0x00014841;
s->ccm[CCM_CDHIPR] = 0x00000000;
s->ccm[CCM_CTOR] = 0x00000000;
s->ccm[CCM_CLPCR] = 0x00000079;
s->ccm[CCM_CISR] = 0x00000000;
s->ccm[CCM_CIMR] = 0xFFFFFFFF;
s->ccm[CCM_CCOSR] = 0x000A0001;
s->ccm[CCM_CGPR] = 0x0000FE62;
s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063;
s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
s->analog[PMU_REG_1P1] = 0x00001073;
s->analog[PMU_REG_3P0] = 0x00000F74;
s->analog[PMU_REG_2P5] = 0x00001073;
s->analog[PMU_REG_CORE] = 0x00482012;
s->analog[PMU_MISC0] = 0x04000000;
s->analog[PMU_MISC1] = 0x00000000;
s->analog[PMU_MISC2] = 0x00272727;
s->analog[PMU_LOWPWR_CTRL] = 0x00004009;
s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004;
s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004;
s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
s->analog[USB_ANALOG_DIGPROG] = 0x00640000;
/* all PLLs need to be locked */
s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK;
s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK;
s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK;
s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK;
s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK;
s->analog[TEMPMON_TEMPSENSE0] = 0x00000001;
s->analog[TEMPMON_TEMPSENSE1] = 0x00000001;
s->analog[TEMPMON_TEMPSENSE2] = 0x00000000;
}
static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size)
{
uint32_t value = 0;
uint32_t index = offset >> 2;
IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
assert(index < CCM_MAX);
value = s->ccm[index];
trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
return (uint64_t)value;
}
static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
uint32_t index = offset >> 2;
IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
assert(index < CCM_MAX);
trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
/*
* We will do a better implementation later. In particular some bits
* cannot be written to.
*/
s->ccm[index] = (uint32_t)value;
}
static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
{
uint32_t value;
uint32_t index = offset >> 2;
IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
assert(index < CCM_ANALOG_MAX);
switch (index) {
case CCM_ANALOG_PLL_ARM_SET:
case CCM_ANALOG_PLL_USB1_SET:
case CCM_ANALOG_PLL_USB2_SET:
case CCM_ANALOG_PLL_SYS_SET:
case CCM_ANALOG_PLL_AUDIO_SET:
case CCM_ANALOG_PLL_VIDEO_SET:
case CCM_ANALOG_PLL_ENET_SET:
case CCM_ANALOG_PFD_480_SET:
case CCM_ANALOG_PFD_528_SET:
case CCM_ANALOG_MISC0_SET:
case PMU_MISC1_SET:
case CCM_ANALOG_MISC2_SET:
case USB_ANALOG_USB1_VBUS_DETECT_SET:
case USB_ANALOG_USB1_CHRG_DETECT_SET:
case USB_ANALOG_USB1_MISC_SET:
case USB_ANALOG_USB2_VBUS_DETECT_SET:
case USB_ANALOG_USB2_CHRG_DETECT_SET:
case USB_ANALOG_USB2_MISC_SET:
case TEMPMON_TEMPSENSE0_SET:
case TEMPMON_TEMPSENSE1_SET:
case TEMPMON_TEMPSENSE2_SET:
/*
* All REG_NAME_SET register access are in fact targeting
* the REG_NAME register.
*/
value = s->analog[index - 1];
break;
case CCM_ANALOG_PLL_ARM_CLR:
case CCM_ANALOG_PLL_USB1_CLR:
case CCM_ANALOG_PLL_USB2_CLR:
case CCM_ANALOG_PLL_SYS_CLR:
case CCM_ANALOG_PLL_AUDIO_CLR:
case CCM_ANALOG_PLL_VIDEO_CLR:
case CCM_ANALOG_PLL_ENET_CLR:
case CCM_ANALOG_PFD_480_CLR:
case CCM_ANALOG_PFD_528_CLR:
case CCM_ANALOG_MISC0_CLR:
case PMU_MISC1_CLR:
case CCM_ANALOG_MISC2_CLR:
case USB_ANALOG_USB1_VBUS_DETECT_CLR:
case USB_ANALOG_USB1_CHRG_DETECT_CLR:
case USB_ANALOG_USB1_MISC_CLR:
case USB_ANALOG_USB2_VBUS_DETECT_CLR:
case USB_ANALOG_USB2_CHRG_DETECT_CLR:
case USB_ANALOG_USB2_MISC_CLR:
case TEMPMON_TEMPSENSE0_CLR:
case TEMPMON_TEMPSENSE1_CLR:
case TEMPMON_TEMPSENSE2_CLR:
/*
* All REG_NAME_CLR register access are in fact targeting
* the REG_NAME register.
*/
value = s->analog[index - 2];
break;
case CCM_ANALOG_PLL_ARM_TOG:
case CCM_ANALOG_PLL_USB1_TOG:
case CCM_ANALOG_PLL_USB2_TOG:
case CCM_ANALOG_PLL_SYS_TOG:
case CCM_ANALOG_PLL_AUDIO_TOG:
case CCM_ANALOG_PLL_VIDEO_TOG:
case CCM_ANALOG_PLL_ENET_TOG:
case CCM_ANALOG_PFD_480_TOG:
case CCM_ANALOG_PFD_528_TOG:
case CCM_ANALOG_MISC0_TOG:
case PMU_MISC1_TOG:
case CCM_ANALOG_MISC2_TOG:
case USB_ANALOG_USB1_VBUS_DETECT_TOG:
case USB_ANALOG_USB1_CHRG_DETECT_TOG:
case USB_ANALOG_USB1_MISC_TOG:
case USB_ANALOG_USB2_VBUS_DETECT_TOG:
case USB_ANALOG_USB2_CHRG_DETECT_TOG:
case USB_ANALOG_USB2_MISC_TOG:
case TEMPMON_TEMPSENSE0_TOG:
case TEMPMON_TEMPSENSE1_TOG:
case TEMPMON_TEMPSENSE2_TOG:
/*
* All REG_NAME_TOG register access are in fact targeting
* the REG_NAME register.
*/
value = s->analog[index - 3];
break;
default:
value = s->analog[index];
break;
}
trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
return (uint64_t)value;
}
static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
uint32_t index = offset >> 2;
IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
assert(index < CCM_ANALOG_MAX);
trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
switch (index) {
case CCM_ANALOG_PLL_ARM_SET:
case CCM_ANALOG_PLL_USB1_SET:
case CCM_ANALOG_PLL_USB2_SET:
case CCM_ANALOG_PLL_SYS_SET:
case CCM_ANALOG_PLL_AUDIO_SET:
case CCM_ANALOG_PLL_VIDEO_SET:
case CCM_ANALOG_PLL_ENET_SET:
case CCM_ANALOG_PFD_480_SET:
case CCM_ANALOG_PFD_528_SET:
case CCM_ANALOG_MISC0_SET:
case PMU_MISC1_SET:
case CCM_ANALOG_MISC2_SET:
case USB_ANALOG_USB1_VBUS_DETECT_SET:
case USB_ANALOG_USB1_CHRG_DETECT_SET:
case USB_ANALOG_USB1_MISC_SET:
case USB_ANALOG_USB2_VBUS_DETECT_SET:
case USB_ANALOG_USB2_CHRG_DETECT_SET:
case USB_ANALOG_USB2_MISC_SET:
/*
* All REG_NAME_SET register access are in fact targeting
* the REG_NAME register. So we change the value of the
* REG_NAME register, setting bits passed in the value.
*/
s->analog[index - 1] |= value;
break;
case CCM_ANALOG_PLL_ARM_CLR:
case CCM_ANALOG_PLL_USB1_CLR:
case CCM_ANALOG_PLL_USB2_CLR:
case CCM_ANALOG_PLL_SYS_CLR:
case CCM_ANALOG_PLL_AUDIO_CLR:
case CCM_ANALOG_PLL_VIDEO_CLR:
case CCM_ANALOG_PLL_ENET_CLR:
case CCM_ANALOG_PFD_480_CLR:
case CCM_ANALOG_PFD_528_CLR:
case CCM_ANALOG_MISC0_CLR:
case PMU_MISC1_CLR:
case CCM_ANALOG_MISC2_CLR:
case USB_ANALOG_USB1_VBUS_DETECT_CLR:
case USB_ANALOG_USB1_CHRG_DETECT_CLR:
case USB_ANALOG_USB1_MISC_CLR:
case USB_ANALOG_USB2_VBUS_DETECT_CLR:
case USB_ANALOG_USB2_CHRG_DETECT_CLR:
case USB_ANALOG_USB2_MISC_CLR:
/*
* All REG_NAME_CLR register access are in fact targeting
* the REG_NAME register. So we change the value of the
* REG_NAME register, unsetting bits passed in the value.
*/
s->analog[index - 2] &= ~value;
break;
case CCM_ANALOG_PLL_ARM_TOG:
case CCM_ANALOG_PLL_USB1_TOG:
case CCM_ANALOG_PLL_USB2_TOG:
case CCM_ANALOG_PLL_SYS_TOG:
case CCM_ANALOG_PLL_AUDIO_TOG:
case CCM_ANALOG_PLL_VIDEO_TOG:
case CCM_ANALOG_PLL_ENET_TOG:
case CCM_ANALOG_PFD_480_TOG:
case CCM_ANALOG_PFD_528_TOG:
case CCM_ANALOG_MISC0_TOG:
case PMU_MISC1_TOG:
case CCM_ANALOG_MISC2_TOG:
case USB_ANALOG_USB1_VBUS_DETECT_TOG:
case USB_ANALOG_USB1_CHRG_DETECT_TOG:
case USB_ANALOG_USB1_MISC_TOG:
case USB_ANALOG_USB2_VBUS_DETECT_TOG:
case USB_ANALOG_USB2_CHRG_DETECT_TOG:
case USB_ANALOG_USB2_MISC_TOG:
/*
* All REG_NAME_TOG register access are in fact targeting
* the REG_NAME register. So we change the value of the
* REG_NAME register, toggling bits passed in the value.
*/
s->analog[index - 3] ^= value;
break;
default:
/*
* We will do a better implementation later. In particular some bits
* cannot be written to.
*/
s->analog[index] = value;
break;
}
}
static const struct MemoryRegionOps imx6ul_ccm_ops = {
.read = imx6ul_ccm_read,
.write = imx6ul_ccm_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
/*
* Our device would not work correctly if the guest was doing
* unaligned access. This might not be a limitation on the real
* device but in practice there is no reason for a guest to access
* this device unaligned.
*/
.min_access_size = 4,
.max_access_size = 4,
.unaligned = false,
},
};
static const struct MemoryRegionOps imx6ul_analog_ops = {
.read = imx6ul_analog_read,
.write = imx6ul_analog_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
/*
* Our device would not work correctly if the guest was doing
* unaligned access. This might not be a limitation on the real
* device but in practice there is no reason for a guest to access
* this device unaligned.
*/
.min_access_size = 4,
.max_access_size = 4,
.unaligned = false,
},
};
static void imx6ul_ccm_init(Object *obj)
{
DeviceState *dev = DEVICE(obj);
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
IMX6ULCCMState *s = IMX6UL_CCM(obj);
/* initialize a container for the all memory range */
memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000);
/* We initialize an IO memory region for the CCM part */
memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s,
TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
/* Add the CCM as a subregion at offset 0 */
memory_region_add_subregion(&s->container, 0, &s->ioccm);
/* We initialize an IO memory region for the ANALOG part */
memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s,
TYPE_IMX6UL_CCM ".analog",
CCM_ANALOG_MAX * sizeof(uint32_t));
/* Add the ANALOG as a subregion at offset 0x4000 */
memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
sysbus_init_mmio(sd, &s->container);
}
static void imx6ul_ccm_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
dc->reset = imx6ul_ccm_reset;
dc->vmsd = &vmstate_imx6ul_ccm;
dc->desc = "i.MX6UL Clock Control Module";
ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency;
}
static const TypeInfo imx6ul_ccm_info = {
.name = TYPE_IMX6UL_CCM,
.parent = TYPE_IMX_CCM,
.instance_size = sizeof(IMX6ULCCMState),
.instance_init = imx6ul_ccm_init,
.class_init = imx6ul_ccm_class_init,
};
static void imx6ul_ccm_register_types(void)
{
type_register_static(&imx6ul_ccm_info);
}
type_init(imx6ul_ccm_register_types)

View File

@@ -1,135 +0,0 @@
/*
* mmio_interface.c
*
* Copyright (C) 2017 : GreenSocs
* http://www.greensocs.com/ , email: info@greensocs.com
*
* Developed by :
* Frederic Konrad <fred.konrad@greensocs.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option)any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "trace.h"
#include "hw/qdev-properties.h"
#include "hw/misc/mmio_interface.h"
#include "qapi/error.h"
#ifndef DEBUG_MMIO_INTERFACE
#define DEBUG_MMIO_INTERFACE 0
#endif
static uint64_t mmio_interface_counter;
#define DPRINTF(fmt, ...) do { \
if (DEBUG_MMIO_INTERFACE) { \
qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## __VA_ARGS__);\
} \
} while (0)
static void mmio_interface_init(Object *obj)
{
MMIOInterface *s = MMIO_INTERFACE(obj);
if (DEBUG_MMIO_INTERFACE) {
s->id = mmio_interface_counter++;
}
DPRINTF("interface created\n");
s->host_ptr = 0;
s->subregion = 0;
}
static void mmio_interface_realize(DeviceState *dev, Error **errp)
{
MMIOInterface *s = MMIO_INTERFACE(dev);
DPRINTF("realize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
" %p\n", s->start, s->end, s->host_ptr);
if (!s->host_ptr) {
error_setg(errp, "host_ptr property must be set");
return;
}
if (!s->subregion) {
error_setg(errp, "subregion property must be set");
return;
}
memory_region_init_ram_ptr(&s->ram_mem, OBJECT(s), "ram",
s->end - s->start + 1, s->host_ptr);
memory_region_set_readonly(&s->ram_mem, s->ro);
memory_region_add_subregion(s->subregion, s->start, &s->ram_mem);
}
static void mmio_interface_unrealize(DeviceState *dev, Error **errp)
{
MMIOInterface *s = MMIO_INTERFACE(dev);
DPRINTF("unrealize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
" %p\n", s->start, s->end, s->host_ptr);
memory_region_del_subregion(s->subregion, &s->ram_mem);
}
static void mmio_interface_finalize(Object *obj)
{
MMIOInterface *s = MMIO_INTERFACE(obj);
DPRINTF("finalize from 0x%" PRIX64 " to 0x%" PRIX64 " map host pointer"
" %p\n", s->start, s->end, s->host_ptr);
object_unparent(OBJECT(&s->ram_mem));
}
static Property mmio_interface_properties[] = {
DEFINE_PROP_UINT64("start", MMIOInterface, start, 0),
DEFINE_PROP_UINT64("end", MMIOInterface, end, 0),
DEFINE_PROP_PTR("host_ptr", MMIOInterface, host_ptr),
DEFINE_PROP_BOOL("ro", MMIOInterface, ro, false),
DEFINE_PROP_MEMORY_REGION("subregion", MMIOInterface, subregion),
DEFINE_PROP_END_OF_LIST(),
};
static void mmio_interface_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = mmio_interface_realize;
dc->unrealize = mmio_interface_unrealize;
dc->props = mmio_interface_properties;
/* Reason: pointer property "host_ptr", and this device
* is an implementation detail of the memory subsystem,
* not intended to be created directly by the user.
*/
dc->user_creatable = false;
}
static const TypeInfo mmio_interface_info = {
.name = TYPE_MMIO_INTERFACE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(MMIOInterface),
.instance_init = mmio_interface_init,
.instance_finalize = mmio_interface_finalize,
.class_init = mmio_interface_class_init,
};
static void mmio_interface_register_types(void)
{
type_register_static(&mmio_interface_info);
}
type_init(mmio_interface_register_types)

View File

@@ -109,3 +109,10 @@ iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit Sec
iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
# hw/misc/imx6ul_ccm.c
ccm_entry(void) "\n"
ccm_freq(uint32_t freq) "freq = %d\n"
ccm_clock_freq(uint32_t clock, uint32_t freq) "(Clock = %d) = %d\n"
ccm_read_reg(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32 "\n"
ccm_write_reg(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32 "\n"

View File

@@ -861,7 +861,7 @@ static void fw_cfg_machine_reset(void *opaque)
void *ptr;
size_t len;
FWCfgState *s = opaque;
char *bootindex = get_boot_devices_list(&len, false);
char *bootindex = get_boot_devices_list(&len);
ptr = fw_cfg_modify_file(s, "bootorder", (uint8_t *)bootindex, len);
g_free(ptr);

View File

@@ -1160,7 +1160,7 @@ static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
const char *boot_device = machine->boot_order;
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
size_t cb = 0;
char *bootlist = get_boot_devices_list(&cb, true);
char *bootlist = get_boot_devices_list(&cb);
_FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
@@ -3949,6 +3949,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
mc->desc = "pSeries Logical Partition (PAPR compliant)";
mc->ignore_boot_device_suffixes = true;
/*
* We set up the default / latest behaviour here. The class_init

View File

@@ -1,4 +1,4 @@
ifeq ($(CONFIG_RDMA),y)
ifeq ($(CONFIG_PVRDMA),y)
obj-$(CONFIG_PCI) += rdma_utils.o rdma_backend.o rdma_rm.o
obj-$(CONFIG_PCI) += vmw/pvrdma_dev_ring.o vmw/pvrdma_cmd.o \
vmw/pvrdma_qp_ops.o vmw/pvrdma_main.o

View File

@@ -35,6 +35,7 @@
#define VENDOR_ERR_MR_SMALL 0x208
#define THR_NAME_LEN 16
#define THR_POLL_TO 5000
typedef struct BackendCtx {
uint64_t req_id;
@@ -91,35 +92,82 @@ static void *comp_handler_thread(void *arg)
int rc;
struct ibv_cq *ev_cq;
void *ev_ctx;
int flags;
GPollFD pfds[1];
/* Change to non-blocking mode */
flags = fcntl(backend_dev->channel->fd, F_GETFL);
rc = fcntl(backend_dev->channel->fd, F_SETFL, flags | O_NONBLOCK);
if (rc < 0) {
pr_dbg("Fail to change to non-blocking mode\n");
return NULL;
}
pr_dbg("Starting\n");
pfds[0].fd = backend_dev->channel->fd;
pfds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
backend_dev->comp_thread.is_running = true;
while (backend_dev->comp_thread.run) {
pr_dbg("Waiting for completion on channel %p\n", backend_dev->channel);
rc = ibv_get_cq_event(backend_dev->channel, &ev_cq, &ev_ctx);
pr_dbg("ibv_get_cq_event=%d\n", rc);
if (unlikely(rc)) {
pr_dbg("---> ibv_get_cq_event (%d)\n", rc);
continue;
do {
rc = qemu_poll_ns(pfds, 1, THR_POLL_TO * (int64_t)SCALE_MS);
} while (!rc && backend_dev->comp_thread.run);
if (backend_dev->comp_thread.run) {
pr_dbg("Waiting for completion on channel %p\n", backend_dev->channel);
rc = ibv_get_cq_event(backend_dev->channel, &ev_cq, &ev_ctx);
pr_dbg("ibv_get_cq_event=%d\n", rc);
if (unlikely(rc)) {
pr_dbg("---> ibv_get_cq_event (%d)\n", rc);
continue;
}
rc = ibv_req_notify_cq(ev_cq, 0);
if (unlikely(rc)) {
pr_dbg("Error %d from ibv_req_notify_cq\n", rc);
}
poll_cq(backend_dev->rdma_dev_res, ev_cq);
ibv_ack_cq_events(ev_cq, 1);
}
rc = ibv_req_notify_cq(ev_cq, 0);
if (unlikely(rc)) {
pr_dbg("Error %d from ibv_req_notify_cq\n", rc);
}
poll_cq(backend_dev->rdma_dev_res, ev_cq);
ibv_ack_cq_events(ev_cq, 1);
}
pr_dbg("Going down\n");
/* TODO: Post cqe for all remaining buffs that were posted */
backend_dev->comp_thread.is_running = false;
qemu_thread_exit(0);
return NULL;
}
static void stop_backend_thread(RdmaBackendThread *thread)
{
thread->run = false;
while (thread->is_running) {
pr_dbg("Waiting for thread to complete\n");
sleep(THR_POLL_TO / SCALE_US / 2);
}
}
static void start_comp_thread(RdmaBackendDev *backend_dev)
{
char thread_name[THR_NAME_LEN] = {0};
stop_backend_thread(&backend_dev->comp_thread);
snprintf(thread_name, sizeof(thread_name), "rdma_comp_%s",
ibv_get_device_name(backend_dev->ib_dev));
backend_dev->comp_thread.run = true;
qemu_thread_create(&backend_dev->comp_thread.thread, thread_name,
comp_handler_thread, backend_dev, QEMU_THREAD_DETACHED);
}
void rdma_backend_register_comp_handler(void (*handler)(int status,
unsigned int vendor_err, void *ctx))
{
@@ -223,8 +271,7 @@ static int build_host_sge_array(RdmaDeviceResources *rdma_dev_res,
return VENDOR_ERR_INVLKEY | ssge[ssge_idx].lkey;
}
dsge->addr = (uintptr_t)mr->user_mr.host_virt + ssge[ssge_idx].addr -
mr->user_mr.guest_start;
dsge->addr = (uintptr_t)mr->virt + ssge[ssge_idx].addr - mr->start;
dsge->length = ssge[ssge_idx].length;
dsge->lkey = rdma_backend_mr_lkey(&mr->backend_mr);
@@ -697,7 +744,7 @@ static int init_device_caps(RdmaBackendDev *backend_dev,
return 0;
}
int rdma_backend_init(RdmaBackendDev *backend_dev,
int rdma_backend_init(RdmaBackendDev *backend_dev, PCIDevice *pdev,
RdmaDeviceResources *rdma_dev_res,
const char *backend_device_name, uint8_t port_num,
uint8_t backend_gid_idx, struct ibv_device_attr *dev_attr,
@@ -706,10 +753,13 @@ int rdma_backend_init(RdmaBackendDev *backend_dev,
int i;
int ret = 0;
int num_ibv_devices;
char thread_name[THR_NAME_LEN] = {0};
struct ibv_device **dev_list;
struct ibv_port_attr port_attr;
memset(backend_dev, 0, sizeof(*backend_dev));
backend_dev->dev = pdev;
backend_dev->backend_gid_idx = backend_gid_idx;
backend_dev->port_num = port_num;
backend_dev->rdma_dev_res = rdma_dev_res;
@@ -800,11 +850,8 @@ int rdma_backend_init(RdmaBackendDev *backend_dev,
pr_dbg("interface_id=0x%" PRIx64 "\n",
be64_to_cpu(backend_dev->gid.global.interface_id));
snprintf(thread_name, sizeof(thread_name), "rdma_comp_%s",
ibv_get_device_name(backend_dev->ib_dev));
backend_dev->comp_thread.run = true;
qemu_thread_create(&backend_dev->comp_thread.thread, thread_name,
comp_handler_thread, backend_dev, QEMU_THREAD_DETACHED);
backend_dev->comp_thread.run = false;
backend_dev->comp_thread.is_running = false;
ah_cache_init();
@@ -823,8 +870,22 @@ out:
return ret;
}
void rdma_backend_start(RdmaBackendDev *backend_dev)
{
pr_dbg("Starting rdma_backend\n");
start_comp_thread(backend_dev);
}
void rdma_backend_stop(RdmaBackendDev *backend_dev)
{
pr_dbg("Stopping rdma_backend\n");
stop_backend_thread(&backend_dev->comp_thread);
}
void rdma_backend_fini(RdmaBackendDev *backend_dev)
{
rdma_backend_stop(backend_dev);
g_hash_table_destroy(ah_hash);
ibv_destroy_comp_channel(backend_dev->channel);
ibv_close_device(backend_dev->context);

View File

@@ -46,12 +46,14 @@ static inline uint32_t rdma_backend_mr_rkey(const RdmaBackendMR *mr)
return mr->ibmr ? mr->ibmr->rkey : 0;
}
int rdma_backend_init(RdmaBackendDev *backend_dev,
int rdma_backend_init(RdmaBackendDev *backend_dev, PCIDevice *pdev,
RdmaDeviceResources *rdma_dev_res,
const char *backend_device_name, uint8_t port_num,
uint8_t backend_gid_idx, struct ibv_device_attr *dev_attr,
Error **errp);
void rdma_backend_fini(RdmaBackendDev *backend_dev);
void rdma_backend_start(RdmaBackendDev *backend_dev);
void rdma_backend_stop(RdmaBackendDev *backend_dev);
void rdma_backend_register_comp_handler(void (*handler)(int status,
unsigned int vendor_err, void *ctx));
void rdma_backend_unregister_comp_handler(void);

View File

@@ -24,7 +24,8 @@ typedef struct RdmaDeviceResources RdmaDeviceResources;
typedef struct RdmaBackendThread {
QemuThread thread;
QemuMutex mutex;
bool run;
bool run; /* Set by thread manager to let thread know it should exit */
bool is_running; /* Set by the thread to report its status */
} RdmaBackendThread;
typedef struct RdmaBackendDev {

View File

@@ -144,8 +144,6 @@ int rdma_rm_alloc_mr(RdmaDeviceResources *dev_res, uint32_t pd_handle,
RdmaRmMR *mr;
int ret = 0;
RdmaRmPD *pd;
void *addr;
size_t length;
pd = rdma_rm_get_pd(dev_res, pd_handle);
if (!pd) {
@@ -158,40 +156,30 @@ int rdma_rm_alloc_mr(RdmaDeviceResources *dev_res, uint32_t pd_handle,
pr_dbg("Failed to allocate obj in table\n");
return -ENOMEM;
}
pr_dbg("mr_handle=%d\n", *mr_handle);
if (!host_virt) {
/* TODO: This is my guess but not so sure that this needs to be
* done */
length = TARGET_PAGE_SIZE;
addr = g_malloc(length);
} else {
mr->user_mr.host_virt = host_virt;
pr_dbg("host_virt=0x%p\n", mr->user_mr.host_virt);
mr->user_mr.length = guest_length;
pr_dbg("length=%zu\n", guest_length);
mr->user_mr.guest_start = guest_start;
pr_dbg("guest_start=0x%" PRIx64 "\n", mr->user_mr.guest_start);
pr_dbg("host_virt=0x%p\n", host_virt);
pr_dbg("guest_start=0x%" PRIx64 "\n", guest_start);
pr_dbg("length=%zu\n", guest_length);
length = mr->user_mr.length;
addr = mr->user_mr.host_virt;
if (host_virt) {
mr->virt = host_virt;
mr->start = guest_start;
mr->length = guest_length;
mr->virt += (mr->start & (TARGET_PAGE_SIZE - 1));
ret = rdma_backend_create_mr(&mr->backend_mr, &pd->backend_pd, mr->virt,
mr->length, access_flags);
if (ret) {
pr_dbg("Fail in rdma_backend_create_mr, err=%d\n", ret);
ret = -EIO;
goto out_dealloc_mr;
}
}
ret = rdma_backend_create_mr(&mr->backend_mr, &pd->backend_pd, addr, length,
access_flags);
if (ret) {
pr_dbg("Fail in rdma_backend_create_mr, err=%d\n", ret);
ret = -EIO;
goto out_dealloc_mr;
}
if (!host_virt) {
*lkey = mr->lkey = rdma_backend_mr_lkey(&mr->backend_mr);
*rkey = mr->rkey = rdma_backend_mr_rkey(&mr->backend_mr);
} else {
/* We keep mr_handle in lkey so send and recv get get mr ptr */
*lkey = *mr_handle;
*rkey = -1;
}
/* We keep mr_handle in lkey so send and recv get get mr ptr */
*lkey = *mr_handle;
*rkey = -1;
mr->pd_handle = pd_handle;
@@ -214,7 +202,11 @@ void rdma_rm_dealloc_mr(RdmaDeviceResources *dev_res, uint32_t mr_handle)
if (mr) {
rdma_backend_destroy_mr(&mr->backend_mr);
munmap(mr->user_mr.host_virt, mr->user_mr.length);
pr_dbg("start=0x%" PRIx64 "\n", mr->start);
if (mr->start) {
mr->virt -= (mr->start & (TARGET_PAGE_SIZE - 1));
munmap(mr->virt, mr->length);
}
res_tbl_dealloc(&dev_res->mr_tbl, mr_handle);
}
}
@@ -399,7 +391,7 @@ int rdma_rm_modify_qp(RdmaDeviceResources *dev_res, RdmaBackendDev *backend_dev,
RdmaRmQP *qp;
int ret;
pr_dbg("qpn=%d\n", qp_handle);
pr_dbg("qpn=0x%x\n", qp_handle);
qp = rdma_rm_get_qp(dev_res, qp_handle);
if (!qp) {
@@ -457,7 +449,7 @@ int rdma_rm_query_qp(RdmaDeviceResources *dev_res, RdmaBackendDev *backend_dev,
{
RdmaRmQP *qp;
pr_dbg("qpn=%d\n", qp_handle);
pr_dbg("qpn=0x%x\n", qp_handle);
qp = rdma_rm_get_qp(dev_res, qp_handle);
if (!qp) {
@@ -553,8 +545,9 @@ void rdma_rm_fini(RdmaDeviceResources *dev_res)
res_tbl_free(&dev_res->uc_tbl);
res_tbl_free(&dev_res->cqe_ctx_tbl);
res_tbl_free(&dev_res->qp_tbl);
res_tbl_free(&dev_res->cq_tbl);
res_tbl_free(&dev_res->mr_tbl);
res_tbl_free(&dev_res->cq_tbl);
res_tbl_free(&dev_res->pd_tbl);
g_hash_table_destroy(dev_res->qp_hash);
}

View File

@@ -55,16 +55,12 @@ typedef struct RdmaRmCQ {
bool notify;
} RdmaRmCQ;
typedef struct RdmaRmUserMR {
void *host_virt;
uint64_t guest_start;
size_t length;
} RdmaRmUserMR;
/* MR (DMA region) */
typedef struct RdmaRmMR {
RdmaBackendMR backend_mr;
RdmaRmUserMR user_mr;
void *virt;
uint64_t start;
size_t length;
uint32_t pd_handle;
uint32_t lkey;
uint32_t rkey;

View File

@@ -15,6 +15,10 @@
#include "rdma_utils.h"
#ifdef PVRDMA_DEBUG
unsigned long pr_dbg_cnt;
#endif
void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen)
{
void *p;

View File

@@ -22,18 +22,26 @@
#include "sysemu/dma.h"
#define pr_info(fmt, ...) \
fprintf(stdout, "%s: %-20s (%3d): " fmt, "pvrdma", __func__, __LINE__,\
fprintf(stdout, "%s: %-20s (%3d): " fmt, "rdma", __func__, __LINE__,\
## __VA_ARGS__)
#define pr_err(fmt, ...) \
fprintf(stderr, "%s: Error at %-20s (%3d): " fmt, "pvrdma", __func__, \
fprintf(stderr, "%s: Error at %-20s (%3d): " fmt, "rdma", __func__, \
__LINE__, ## __VA_ARGS__)
#ifdef PVRDMA_DEBUG
extern unsigned long pr_dbg_cnt;
#define init_pr_dbg(void) \
{ \
pr_dbg_cnt = 0; \
}
#define pr_dbg(fmt, ...) \
fprintf(stdout, "%s: %-20s (%3d): " fmt, "pvrdma", __func__, __LINE__,\
## __VA_ARGS__)
fprintf(stdout, "%lx %ld: %-20s (%3d): " fmt, pthread_self(), pr_dbg_cnt++, \
__func__, __LINE__, ## __VA_ARGS__)
#else
#define init_pr_dbg(void)
#define pr_dbg(fmt, ...)
#endif

View File

@@ -50,6 +50,9 @@
#define PVRDMA_HW_VERSION 17
#define PVRDMA_FW_VERSION 14
/* Some defaults */
#define PVRDMA_PKEY 0x7FFF
typedef struct DSRInfo {
dma_addr_t dma;
struct pvrdma_device_shared_region *dsr;

View File

@@ -16,7 +16,6 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "cpu.h"
#include <linux/types.h>
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_ids.h"
@@ -59,6 +58,7 @@ static void *pvrdma_map_to_pdir(PCIDevice *pdev, uint64_t pdir_dma,
}
host_virt = mremap(curr_page, 0, length, MREMAP_MAYMOVE);
pr_dbg("mremap %p -> %p\n", curr_page, host_virt);
if (host_virt == MAP_FAILED) {
host_virt = NULL;
error_report("PVRDMA: Failed to remap memory for host_virt");
@@ -166,7 +166,7 @@ static int query_pkey(PVRDMADev *dev, union pvrdma_cmd_req *req,
resp->hdr.ack = PVRDMA_CMD_QUERY_PKEY_RESP;
resp->hdr.err = 0;
resp->pkey = 0x7FFF;
resp->pkey = PVRDMA_PKEY;
pr_dbg("pkey=0x%x\n", resp->pkey);
return 0;
@@ -524,6 +524,7 @@ static int query_qp(PVRDMADev *dev, union pvrdma_cmd_req *req,
struct ibv_qp_init_attr init_attr;
pr_dbg("qp_handle=%d\n", cmd->qp_handle);
pr_dbg("attr_mask=0x%x\n", cmd->attr_mask);
memset(rsp, 0, sizeof(*rsp));
rsp->hdr.response = cmd->hdr.response;
@@ -531,8 +532,8 @@ static int query_qp(PVRDMADev *dev, union pvrdma_cmd_req *req,
rsp->hdr.err = rdma_rm_query_qp(&dev->rdma_dev_res, &dev->backend_dev,
cmd->qp_handle,
(struct ibv_qp_attr *)&resp->attrs, -1,
&init_attr);
(struct ibv_qp_attr *)&resp->attrs,
cmd->attr_mask, &init_attr);
pr_dbg("ret=%d\n", rsp->hdr.err);
return rsp->hdr.err;

View File

@@ -286,8 +286,78 @@ static void init_ports(PVRDMADev *dev, Error **errp)
}
}
static void uninit_msix(PCIDevice *pdev, int used_vectors)
{
PVRDMADev *dev = PVRDMA_DEV(pdev);
int i;
for (i = 0; i < used_vectors; i++) {
msix_vector_unuse(pdev, i);
}
msix_uninit(pdev, &dev->msix, &dev->msix);
}
static int init_msix(PCIDevice *pdev, Error **errp)
{
PVRDMADev *dev = PVRDMA_DEV(pdev);
int i;
int rc;
rc = msix_init(pdev, RDMA_MAX_INTRS, &dev->msix, RDMA_MSIX_BAR_IDX,
RDMA_MSIX_TABLE, &dev->msix, RDMA_MSIX_BAR_IDX,
RDMA_MSIX_PBA, 0, NULL);
if (rc < 0) {
error_setg(errp, "Failed to initialize MSI-X");
return rc;
}
for (i = 0; i < RDMA_MAX_INTRS; i++) {
rc = msix_vector_use(PCI_DEVICE(dev), i);
if (rc < 0) {
error_setg(errp, "Fail mark MSI-X vector %d", i);
uninit_msix(pdev, i);
return rc;
}
}
return 0;
}
static void pvrdma_fini(PCIDevice *pdev)
{
PVRDMADev *dev = PVRDMA_DEV(pdev);
pr_dbg("Closing device %s %x.%x\n", pdev->name, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
pvrdma_qp_ops_fini();
rdma_rm_fini(&dev->rdma_dev_res);
rdma_backend_fini(&dev->backend_dev);
free_dsr(dev);
if (msix_enabled(pdev)) {
uninit_msix(pdev, RDMA_MAX_INTRS);
}
}
static void pvrdma_stop(PVRDMADev *dev)
{
rdma_backend_stop(&dev->backend_dev);
}
static void pvrdma_start(PVRDMADev *dev)
{
rdma_backend_start(&dev->backend_dev);
}
static void activate_device(PVRDMADev *dev)
{
pvrdma_start(dev);
set_reg_val(dev, PVRDMA_REG_ERR, 0);
pr_dbg("Device activated\n");
}
@@ -300,7 +370,10 @@ static int unquiesce_device(PVRDMADev *dev)
static int reset_device(PVRDMADev *dev)
{
pvrdma_stop(dev);
pr_dbg("Device reset complete\n");
return 0;
}
@@ -357,7 +430,7 @@ static void regs_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
reset_device(dev);
break;
}
break;
break;
case PVRDMA_REG_IMR:
pr_dbg("Interrupt mask=0x%" PRIx64 "\n", val);
dev->interrupt_mask = val;
@@ -366,7 +439,7 @@ static void regs_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
if (val == 0) {
execute_command(dev);
}
break;
break;
default:
break;
}
@@ -469,45 +542,6 @@ static void init_regs(PCIDevice *pdev)
set_reg_val(dev, PVRDMA_REG_ERR, 0xFFFF);
}
static void uninit_msix(PCIDevice *pdev, int used_vectors)
{
PVRDMADev *dev = PVRDMA_DEV(pdev);
int i;
for (i = 0; i < used_vectors; i++) {
msix_vector_unuse(pdev, i);
}
msix_uninit(pdev, &dev->msix, &dev->msix);
}
static int init_msix(PCIDevice *pdev, Error **errp)
{
PVRDMADev *dev = PVRDMA_DEV(pdev);
int i;
int rc;
rc = msix_init(pdev, RDMA_MAX_INTRS, &dev->msix, RDMA_MSIX_BAR_IDX,
RDMA_MSIX_TABLE, &dev->msix, RDMA_MSIX_BAR_IDX,
RDMA_MSIX_PBA, 0, NULL);
if (rc < 0) {
error_setg(errp, "Failed to initialize MSI-X");
return rc;
}
for (i = 0; i < RDMA_MAX_INTRS; i++) {
rc = msix_vector_use(PCI_DEVICE(dev), i);
if (rc < 0) {
error_setg(errp, "Fail mark MSI-X vercor %d", i);
uninit_msix(pdev, i);
return rc;
}
}
return 0;
}
static void init_dev_caps(PVRDMADev *dev)
{
size_t pg_tbl_bytes = TARGET_PAGE_SIZE *
@@ -543,6 +577,8 @@ static void pvrdma_realize(PCIDevice *pdev, Error **errp)
Object *memdev_root;
bool ram_shared = false;
init_pr_dbg();
pr_dbg("Initializing device %s %x.%x\n", pdev->name,
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
@@ -575,7 +611,7 @@ static void pvrdma_realize(PCIDevice *pdev, Error **errp)
goto out;
}
rc = rdma_backend_init(&dev->backend_dev, &dev->rdma_dev_res,
rc = rdma_backend_init(&dev->backend_dev, pdev, &dev->rdma_dev_res,
dev->backend_device_name, dev->backend_port_num,
dev->backend_gid_idx, &dev->dev_attr, errp);
if (rc) {
@@ -602,22 +638,7 @@ out:
static void pvrdma_exit(PCIDevice *pdev)
{
PVRDMADev *dev = PVRDMA_DEV(pdev);
pr_dbg("Closing device %s %x.%x\n", pdev->name, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
pvrdma_qp_ops_fini();
rdma_rm_fini(&dev->rdma_dev_res);
rdma_backend_fini(&dev->backend_dev);
free_dsr(dev);
if (msix_enabled(pdev)) {
uninit_msix(pdev, RDMA_MAX_INTRS);
}
pvrdma_fini(pdev);
}
static void pvrdma_class_init(ObjectClass *klass, void *data)

View File

@@ -69,6 +69,7 @@ static int pvrdma_post_cqe(PVRDMADev *dev, uint32_t cq_handle,
return -EINVAL;
}
memset(cqe1, 0, sizeof(*cqe1));
cqe1->wr_id = cqe->wr_id;
cqe1->qp = cqe->qp;
cqe1->opcode = cqe->opcode;
@@ -129,7 +130,7 @@ int pvrdma_qp_send(PVRDMADev *dev, uint32_t qp_handle)
PvrdmaSqWqe *wqe;
PvrdmaRing *ring;
pr_dbg("qp_handle=%d\n", qp_handle);
pr_dbg("qp_handle=0x%x\n", qp_handle);
qp = rdma_rm_get_qp(&dev->rdma_dev_res, qp_handle);
if (unlikely(!qp)) {
@@ -173,7 +174,7 @@ int pvrdma_qp_recv(PVRDMADev *dev, uint32_t qp_handle)
PvrdmaRqWqe *wqe;
PvrdmaRing *ring;
pr_dbg("qp_handle=%d\n", qp_handle);
pr_dbg("qp_handle=0x%x\n", qp_handle);
qp = rdma_rm_get_qp(&dev->rdma_dev_res, qp_handle);
if (unlikely(!qp)) {

View File

@@ -98,13 +98,10 @@ static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
CcwDevice *cdev = CCW_DEVICE(ds);
CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
DeviceState *parent = DEVICE(cdev);
BusState *qbus = qdev_get_parent_bus(parent);
VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
SubchDev *sch;
Error *err = NULL;
sch = css_create_sch(cdev->devno, cbus->squash_mcss, errp);
sch = css_create_sch(cdev->devno, errp);
if (!sch) {
return;
}

View File

@@ -106,7 +106,6 @@ VirtualCssBus *virtual_css_bus_init(void)
/* Create bus on bridge device */
bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
cbus = VIRTUAL_CSS_BUS(bus);
cbus->squash_mcss = s390_get_squash_mcss();
/* Enable hotplugging */
qbus_set_hotplug_handler(bus, dev, &error_abort);

View File

@@ -2359,15 +2359,13 @@ const PropertyInfo css_devid_ro_propinfo = {
.get = get_css_devid,
};
SubchDev *css_create_sch(CssDevId bus_id, bool squash_mcss, Error **errp)
SubchDev *css_create_sch(CssDevId bus_id, Error **errp)
{
uint16_t schid = 0;
SubchDev *sch;
if (bus_id.valid) {
if (squash_mcss) {
bus_id.cssid = channel_subsys.default_cssid;
} else if (!channel_subsys.css[bus_id.cssid]) {
if (!channel_subsys.css[bus_id.cssid]) {
css_create_css_image(bus_id.cssid, false);
}

View File

@@ -67,8 +67,6 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
CcwDevice *ccw_dev = CCW_DEVICE(cdev);
CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
DeviceState *parent = DEVICE(ccw_dev);
BusState *qbus = qdev_get_parent_bus(parent);
VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
SubchDev *sch;
int ret;
Error *err = NULL;
@@ -78,7 +76,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
goto out_err_propagate;
}
sch = css_create_sch(ccw_dev->devno, cbus->squash_mcss, &err);
sch = css_create_sch(ccw_dev->devno, &err);
if (!sch) {
goto out_mdevid_free;
}

View File

@@ -282,19 +282,8 @@ static void ccw_init(MachineState *machine)
virtio_ccw_register_hcalls();
s390_enable_css_support(s390_cpu_addr2state(0));
/*
* Non mcss-e enabled guests only see the devices from the default
* css, which is determined by the value of the squash_mcss property.
*/
if (css_bus->squash_mcss) {
ret = css_create_css_image(0, true);
} else {
ret = css_create_css_image(VIRTUAL_CSSID, true);
}
if (qemu_opt_get(qemu_get_machine_opts(), "s390-squash-mcss")) {
warn_report("The machine property 's390-squash-mcss' is deprecated"
" (obsoleted by lifting the cssid restrictions).");
}
ret = css_create_css_image(VIRTUAL_CSSID, true);
assert(ret == 0);
if (css_migration_enabled()) {
@@ -575,21 +564,6 @@ static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
ms->loadparm[i] = ' '; /* pad right with spaces */
}
}
static inline bool machine_get_squash_mcss(Object *obj, Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
return ms->s390_squash_mcss;
}
static inline void machine_set_squash_mcss(Object *obj, bool value,
Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
ms->s390_squash_mcss = value;
}
static inline void s390_machine_initfn(Object *obj)
{
object_property_add_bool(obj, "aes-key-wrap",
@@ -614,13 +588,6 @@ static inline void s390_machine_initfn(Object *obj)
" to upper case) to pass to machine loader, boot manager,"
" and guest kernel",
NULL);
object_property_add_bool(obj, "s390-squash-mcss",
machine_get_squash_mcss,
machine_set_squash_mcss, NULL);
object_property_set_description(obj, "s390-squash-mcss", "(deprecated) "
"enable/disable squashing subchannels into the default css",
NULL);
object_property_set_bool(obj, false, "s390-squash-mcss", NULL);
}
static const TypeInfo ccw_machine_info = {
@@ -673,6 +640,9 @@ bool css_migration_enabled(void)
} \
type_init(ccw_machine_register_##suffix)
#define CCW_COMPAT_3_0 \
HW_COMPAT_3_0
#define CCW_COMPAT_2_12 \
HW_COMPAT_2_12
@@ -761,14 +731,26 @@ bool css_migration_enabled(void)
.value = "0",\
},
static void ccw_machine_3_1_instance_options(MachineState *machine)
{
}
static void ccw_machine_3_1_class_options(MachineClass *mc)
{
}
DEFINE_CCW_MACHINE(3_1, "3.1", true);
static void ccw_machine_3_0_instance_options(MachineState *machine)
{
ccw_machine_3_1_instance_options(machine);
}
static void ccw_machine_3_0_class_options(MachineClass *mc)
{
ccw_machine_3_1_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_3_0);
}
DEFINE_CCW_MACHINE(3_0, "3.0", true);
DEFINE_CCW_MACHINE(3_0, "3.0", false);
static void ccw_machine_2_12_instance_options(MachineState *machine)
{

View File

@@ -694,13 +694,10 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
CcwDevice *ccw_dev = CCW_DEVICE(dev);
CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
DeviceState *parent = DEVICE(ccw_dev);
BusState *qbus = qdev_get_parent_bus(parent);
VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
SubchDev *sch;
Error *err = NULL;
sch = css_create_sch(ccw_dev->devno, cbus->squash_mcss, errp);
sch = css_create_sch(ccw_dev->devno, errp);
if (!sch) {
return;
}

View File

@@ -2379,7 +2379,6 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
return;
}
blkconf_serial(&s->qdev.conf, &s->serial);
blkconf_blocksizes(&s->qdev.conf);
if (s->qdev.conf.logical_block_size >

View File

@@ -302,4 +302,6 @@ extern const VMStateDescription sdhci_vmstate;
#define ESDHC_CTRL_4BITBUS (0x1 << 1)
#define ESDHC_CTRL_8BITBUS (0x2 << 1)
#define ESDHC_PRNSTS_SDSTB (1 << 3)
#endif

View File

@@ -1651,6 +1651,14 @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
break;
case SDHC_PRNSTS:
/* Add SDSTB (SD Clock Stable) bit to PRNSTS */
ret = sdhci_read(opaque, offset, size) & ~ESDHC_PRNSTS_SDSTB;
if (s->clkcon & SDHC_CLOCK_INT_STABLE) {
ret |= ESDHC_PRNSTS_SDSTB;
}
break;
case ESDHC_DLL_CTRL:
case ESDHC_TUNE_CTRL_STATUS:
case ESDHC_UNDOCUMENTED_REG27:

View File

@@ -1035,7 +1035,17 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
ecc_init(hwdef->ecc_base, slavio_irq[28],
hwdef->ecc_version);
fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
fw_cfg = FW_CFG(dev);
qdev_prop_set_uint32(dev, "data_width", 1);
qdev_prop_set_bit(dev, "dma_enabled", false);
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
OBJECT(fw_cfg), NULL);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, CFG_ADDR);
sysbus_mmio_map(s, 1, CFG_ADDR + 2);
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);

View File

@@ -139,7 +139,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
unsigned int i;
long kernel_size;
uint8_t *ptr;
uint64_t kernel_top;
uint64_t kernel_top = 0;
linux_boot = (kernel_filename != NULL);
@@ -172,7 +172,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
}
/* load initrd above kernel */
*initrd_size = 0;
if (initrd_filename) {
if (initrd_filename && kernel_top) {
*initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
*initrd_size = load_image_targphys(initrd_filename,

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