target-arm queue:

* hw/dma/xlnx-zdma, xlnx_csu_dma: Require 'dma' link property to be set
  * hw/arm/Kconfig: no need to enable ACPI_MEMORY_HOTPLUG/ACPI_NVDIMM explicitly
  * target/arm/cpu: Introduce sve_vq_supported bitmap
  * docs/specs: Convert ACPI spec docs to rST
  * arch_init: Clean up and refactoring
  * hw/core/loader: In gunzip(), check index is in range before use, not after
  * softmmu/physmem.c: Remove unneeded NULL check in qemu_ram_alloc_from_fd()
  * softmmu/physmem.c: Check return value from realpath()
  * Zero-initialize sockaddr_in structs
  * raspi: Use error_fatal for SoC realize errors, not error_abort
  * target/arm: Avoid assertion trying to use KVM and multiple ASes
  * target/arm: Implement HSTR.TTEE
  * target/arm: Implement HSTR.TJDBX
  * target/arm: Do hflags rebuild in cpsr_write()
  * hw/arm/xlnx-versal, xlnx-zynqmp: Add unimplemented APU mmio
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmEnyRIZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3v97EACBt9tRBw9I6FOIT61FJKr6
 ZTaknJBT2rU7Yg9mTlQa+q/pZjVVtduD9oe7OxGNoCQCF6Bne435IayAXgPdrQtz
 GEiBrJ8ZSk8KmrbL/SJJra93OMrer3Y7kGwgFEQ5KmezCT70jzY9t+ysQYRGykMd
 sA10A76CDR3dl7/rYBCoSBXW7o5GNC2C/5MC+ikFJchQMrkd85eGgKOlZvf+zsDC
 uky+DmDOjv+LHbcky7Xd8Ln0CikgaSLbKBIdFmpemAIQ9KB6yQ2b0KOAIQWGyPbk
 LDphcUHlnoShhh3BspkX/kvm9rF/GzosnsyH6XfaH8fOCyr+zAdpN6+M96CpP7mw
 y5EOZxHk50XI2oC6wAnKrUFQd0CKW+fyHeUXtvIzA7y/JVkud1KOmmTNvNYu1ekK
 GHZCEPXj6bEVcp/Vk1rwdQPOueF2HloYKVs8cV7rrzb2r7JitR+exPvzyYmuifS5
 nUZOWT46662vtTaFikJBIeX6x+sqlKAfi1uEcMJ/tSVtsjIyqcFGqjcBKTEyBW93
 GX+bk4e6v+UuC9ch03u9VSE6TTA9wEFPladuhFdbKtvpj2qzkVmNtrdfVPO/Wl78
 O22rs6hCgl702OkrFDemFK2De0rfsHKxGo3114uL7CHClYbMMN3jUywZEkLGH/jV
 VabgHZaNkh3WYfQG1AbZ/w==
 =bYAy
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210826' into staging

target-arm queue:
 * hw/dma/xlnx-zdma, xlnx_csu_dma: Require 'dma' link property to be set
 * hw/arm/Kconfig: no need to enable ACPI_MEMORY_HOTPLUG/ACPI_NVDIMM explicitly
 * target/arm/cpu: Introduce sve_vq_supported bitmap
 * docs/specs: Convert ACPI spec docs to rST
 * arch_init: Clean up and refactoring
 * hw/core/loader: In gunzip(), check index is in range before use, not after
 * softmmu/physmem.c: Remove unneeded NULL check in qemu_ram_alloc_from_fd()
 * softmmu/physmem.c: Check return value from realpath()
 * Zero-initialize sockaddr_in structs
 * raspi: Use error_fatal for SoC realize errors, not error_abort
 * target/arm: Avoid assertion trying to use KVM and multiple ASes
 * target/arm: Implement HSTR.TTEE
 * target/arm: Implement HSTR.TJDBX
 * target/arm: Do hflags rebuild in cpsr_write()
 * hw/arm/xlnx-versal, xlnx-zynqmp: Add unimplemented APU mmio

# gpg: Signature made Thu 26 Aug 2021 18:02:10 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20210826: (37 commits)
  hw/arm/xlnx-zynqmp: Add unimplemented APU mmio
  hw/arm/xlnx-versal: Add unimplemented APU mmio
  target/arm: Do hflags rebuild in cpsr_write()
  target/arm: Implement HSTR.TJDBX
  target/arm: Implement HSTR.TTEE
  hw/arm/virt: Delete EL3 error checksnow provided in CPU realize
  target/arm: Avoid assertion trying to use KVM and multiple ASes
  raspi: Use error_fatal for SoC realize errors, not error_abort
  tests/tcg/multiarch/linux-test: Zero-initialize sockaddr structs
  tests/qtest/ipmi-bt-test: Zero-initialize sockaddr struct
  gdbstub: Zero-initialize sockaddr structs
  net: Zero sockaddr_in in parse_host_port()
  softmmu/physmem.c: Check return value from realpath()
  softmmu/physmem.c: Remove unneeded NULL check in qemu_ram_alloc_from_fd()
  hw/core/loader: In gunzip(), check index is in range before use, not after
  stubs: Remove unused arch_type.c stub
  arch_init.h: Don't include arch_init.h unnecessarily
  arch_init.h: Move QEMU_ARCH_VIRTIO_* to qdev-monitor.c
  arch_init.h: Add QEMU_ARCH_HEXAGON
  meson.build: Define QEMU_ARCH in config-target.h
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-08-26 18:03:57 +01:00
commit f214d8e015
57 changed files with 949 additions and 707 deletions

View File

@ -1751,6 +1751,10 @@ F: qapi/acpi.json
F: tests/qtest/bios-tables-test*
F: tests/qtest/acpi-utils.[hc]
F: tests/data/acpi/
F: docs/specs/acpi_cpu_hotplug.rst
F: docs/specs/acpi_mem_hotplug.rst
F: docs/specs/acpi_pci_hotplug.rst
F: docs/specs/acpi_hw_reduced_hotplug.rst
ACPI/HEST/GHES
R: Dongjiu Geng <gengdongjiu1@gmail.com>
@ -2057,6 +2061,7 @@ F: hw/acpi/nvdimm.c
F: hw/mem/nvdimm.c
F: include/hw/mem/nvdimm.h
F: docs/nvdimm.txt
F: docs/specs/acpi_nvdimm.rst
e1000x
M: Dmitry Fleytman <dmitry.fleytman@gmail.com>

View File

@ -56,7 +56,6 @@
#include "sysemu/iothread.h"
#include "block/block_int.h"
#include "block/trace.h"
#include "sysemu/arch_init.h"
#include "sysemu/runstate.h"
#include "sysemu/replay.h"
#include "qemu/cutils.h"

View File

@ -0,0 +1,235 @@
QEMU<->ACPI BIOS CPU hotplug interface
======================================
QEMU supports CPU hotplug via ACPI. This document
describes the interface between QEMU and the ACPI BIOS.
ACPI BIOS GPE.2 handler is dedicated for notifying OS about CPU hot-add
and hot-remove events.
Legacy ACPI CPU hotplug interface registers
-------------------------------------------
CPU present bitmap for:
- ICH9-LPC (IO port 0x0cd8-0xcf7, 1-byte access)
- PIIX-PM (IO port 0xaf00-0xaf1f, 1-byte access)
- One bit per CPU. Bit position reflects corresponding CPU APIC ID. Read-only.
- The first DWORD in bitmap is used in write mode to switch from legacy
to modern CPU hotplug interface, write 0 into it to do switch.
QEMU sets corresponding CPU bit on hot-add event and issues SCI
with GPE.2 event set. CPU present map is read by ACPI BIOS GPE.2 handler
to notify OS about CPU hot-add events. CPU hot-remove isn't supported.
Modern ACPI CPU hotplug interface registers
-------------------------------------------
Register block base address:
- ICH9-LPC IO port 0x0cd8
- PIIX-PM IO port 0xaf00
Register block size:
- ACPI_CPU_HOTPLUG_REG_LEN = 12
All accesses to registers described below, imply little-endian byte order.
Reserved registers behavior:
- write accesses are ignored
- read accesses return all bits set to 0.
The last stored value in 'CPU selector' must refer to a possible CPU, otherwise
- reads from any register return 0
- writes to any other register are ignored until valid value is stored into it
On QEMU start, 'CPU selector' is initialized to a valid value, on reset it
keeps the current value.
Read access behavior
^^^^^^^^^^^^^^^^^^^^
offset [0x0-0x3]
Command data 2: (DWORD access)
If value last stored in 'Command field' is:
0:
reads as 0x0
3:
upper 32 bits of architecture specific CPU ID value
other values:
reserved
offset [0x4]
CPU device status fields: (1 byte access)
bits:
0:
Device is enabled and may be used by guest
1:
Device insert event, used to distinguish device for which
no device check event to OSPM was issued.
It's valid only when bit 0 is set.
2:
Device remove event, used to distinguish device for which
no device eject request to OSPM was issued. Firmware must
ignore this bit.
3:
reserved and should be ignored by OSPM
4:
if set to 1, OSPM requests firmware to perform device eject.
5-7:
reserved and should be ignored by OSPM
offset [0x5-0x7]
reserved
offset [0x8]
Command data: (DWORD access)
If value last stored in 'Command field' is one of:
0:
contains 'CPU selector' value of a CPU with pending event[s]
3:
lower 32 bits of architecture specific CPU ID value
(in x86 case: APIC ID)
otherwise:
contains 0
Write access behavior
^^^^^^^^^^^^^^^^^^^^^
offset [0x0-0x3]
CPU selector: (DWORD access)
Selects active CPU device. All following accesses to other
registers will read/store data from/to selected CPU.
Valid values: [0 .. max_cpus)
offset [0x4]
CPU device control fields: (1 byte access)
bits:
0:
reserved, OSPM must clear it before writing to register.
1:
if set to 1 clears device insert event, set by OSPM
after it has emitted device check event for the
selected CPU device
2:
if set to 1 clears device remove event, set by OSPM
after it has emitted device eject request for the
selected CPU device.
3:
if set to 1 initiates device eject, set by OSPM when it
triggers CPU device removal and calls _EJ0 method or by firmware
when bit #4 is set. In case bit #4 were set, it's cleared as
part of device eject.
4:
if set to 1, OSPM hands over device eject to firmware.
Firmware shall issue device eject request as described above
(bit #3) and OSPM should not touch device eject bit (#3) in case
it's asked firmware to perform CPU device eject.
5-7:
reserved, OSPM must clear them before writing to register
offset[0x5]
Command field: (1 byte access)
value:
0:
selects a CPU device with inserting/removing events and
following reads from 'Command data' register return
selected CPU ('CPU selector' value).
If no CPU with events found, the current 'CPU selector' doesn't
change and corresponding insert/remove event flags are not modified.
1:
following writes to 'Command data' register set OST event
register in QEMU
2:
following writes to 'Command data' register set OST status
register in QEMU
3:
following reads from 'Command data' and 'Command data 2' return
architecture specific CPU ID value for currently selected CPU.
other values:
reserved
offset [0x6-0x7]
reserved
offset [0x8]
Command data: (DWORD access)
If last stored 'Command field' value is:
1:
stores value into OST event register
2:
stores value into OST status register, triggers
ACPI_DEVICE_OST QMP event from QEMU to external applications
with current values of OST event and status registers.
other values:
reserved
Typical usecases
----------------
(x86) Detecting and enabling modern CPU hotplug interface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QEMU starts with legacy CPU hotplug interface enabled. Detecting and
switching to modern interface is based on the 2 legacy CPU hotplug features:
#. Writes into CPU bitmap are ignored.
#. CPU bitmap always has bit #0 set, corresponding to boot CPU.
Use following steps to detect and enable modern CPU hotplug interface:
#. Store 0x0 to the 'CPU selector' register, attempting to switch to modern mode
#. Store 0x0 to the 'CPU selector' register, to ensure valid selector value
#. Store 0x0 to the 'Command field' register
#. Read the 'Command data 2' register.
If read value is 0x0, the modern interface is enabled.
Otherwise legacy or no CPU hotplug interface available
Get a cpu with pending event
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. Store 0x0 to the 'CPU selector' register.
#. Store 0x0 to the 'Command field' register.
#. Read the 'CPU device status fields' register.
#. If both bit #1 and bit #2 are clear in the value read, there is no CPU
with a pending event and selected CPU remains unchanged.
#. Otherwise, read the 'Command data' register. The value read is the
selector of the CPU with the pending event (which is already selected).
Enumerate CPUs present/non present CPUs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. Set the present CPU count to 0.
#. Set the iterator to 0.
#. Store 0x0 to the 'CPU selector' register, to ensure that it's in
a valid state and that access to other registers won't be ignored.
#. Store 0x0 to the 'Command field' register to make 'Command data'
register return 'CPU selector' value of selected CPU
#. Read the 'CPU device status fields' register.
#. If bit #0 is set, increment the present CPU count.
#. Increment the iterator.
#. Store the iterator to the 'CPU selector' register.
#. Read the 'Command data' register.
#. If the value read is not zero, goto 05.
#. Otherwise store 0x0 to the 'CPU selector' register, to put it
into a valid state and exit.
The iterator at this point equals "max_cpus".

View File

@ -1,160 +0,0 @@
QEMU<->ACPI BIOS CPU hotplug interface
--------------------------------------
QEMU supports CPU hotplug via ACPI. This document
describes the interface between QEMU and the ACPI BIOS.
ACPI BIOS GPE.2 handler is dedicated for notifying OS about CPU hot-add
and hot-remove events.
============================================
Legacy ACPI CPU hotplug interface registers:
--------------------------------------------
CPU present bitmap for:
ICH9-LPC (IO port 0x0cd8-0xcf7, 1-byte access)
PIIX-PM (IO port 0xaf00-0xaf1f, 1-byte access)
One bit per CPU. Bit position reflects corresponding CPU APIC ID. Read-only.
The first DWORD in bitmap is used in write mode to switch from legacy
to modern CPU hotplug interface, write 0 into it to do switch.
---------------------------------------------------------------
QEMU sets corresponding CPU bit on hot-add event and issues SCI
with GPE.2 event set. CPU present map is read by ACPI BIOS GPE.2 handler
to notify OS about CPU hot-add events. CPU hot-remove isn't supported.
=====================================
Modern ACPI CPU hotplug interface registers:
-------------------------------------
Register block base address:
ICH9-LPC IO port 0x0cd8
PIIX-PM IO port 0xaf00
Register block size:
ACPI_CPU_HOTPLUG_REG_LEN = 12
All accesses to registers described below, imply little-endian byte order.
Reserved resisters behavior:
- write accesses are ignored
- read accesses return all bits set to 0.
The last stored value in 'CPU selector' must refer to a possible CPU, otherwise
- reads from any register return 0
- writes to any other register are ignored until valid value is stored into it
On QEMU start, 'CPU selector' is initialized to a valid value, on reset it
keeps the current value.
read access:
offset:
[0x0-0x3] Command data 2: (DWORD access)
if value last stored in 'Command field':
0: reads as 0x0
3: upper 32 bits of architecture specific CPU ID value
other values: reserved
[0x4] CPU device status fields: (1 byte access)
bits:
0: Device is enabled and may be used by guest
1: Device insert event, used to distinguish device for which
no device check event to OSPM was issued.
It's valid only when bit 0 is set.
2: Device remove event, used to distinguish device for which
no device eject request to OSPM was issued. Firmware must
ignore this bit.
3: reserved and should be ignored by OSPM
4: if set to 1, OSPM requests firmware to perform device eject.
5-7: reserved and should be ignored by OSPM
[0x5-0x7] reserved
[0x8] Command data: (DWORD access)
contains 0 unless value last stored in 'Command field' is one of:
0: contains 'CPU selector' value of a CPU with pending event[s]
3: lower 32 bits of architecture specific CPU ID value
(in x86 case: APIC ID)
write access:
offset:
[0x0-0x3] CPU selector: (DWORD access)
selects active CPU device. All following accesses to other
registers will read/store data from/to selected CPU.
Valid values: [0 .. max_cpus)
[0x4] CPU device control fields: (1 byte access)
bits:
0: reserved, OSPM must clear it before writing to register.
1: if set to 1 clears device insert event, set by OSPM
after it has emitted device check event for the
selected CPU device
2: if set to 1 clears device remove event, set by OSPM
after it has emitted device eject request for the
selected CPU device.
3: if set to 1 initiates device eject, set by OSPM when it
triggers CPU device removal and calls _EJ0 method or by firmware
when bit #4 is set. In case bit #4 were set, it's cleared as
part of device eject.
4: if set to 1, OSPM hands over device eject to firmware.
Firmware shall issue device eject request as described above
(bit #3) and OSPM should not touch device eject bit (#3) in case
it's asked firmware to perform CPU device eject.
5-7: reserved, OSPM must clear them before writing to register
[0x5] Command field: (1 byte access)
value:
0: selects a CPU device with inserting/removing events and
following reads from 'Command data' register return
selected CPU ('CPU selector' value).
If no CPU with events found, the current 'CPU selector' doesn't
change and corresponding insert/remove event flags are not modified.
1: following writes to 'Command data' register set OST event
register in QEMU
2: following writes to 'Command data' register set OST status
register in QEMU
3: following reads from 'Command data' and 'Command data 2' return
architecture specific CPU ID value for currently selected CPU.
other values: reserved
[0x6-0x7] reserved
[0x8] Command data: (DWORD access)
if last stored 'Command field' value:
1: stores value into OST event register
2: stores value into OST status register, triggers
ACPI_DEVICE_OST QMP event from QEMU to external applications
with current values of OST event and status registers.
other values: reserved
Typical usecases:
- (x86) Detecting and enabling modern CPU hotplug interface.
QEMU starts with legacy CPU hotplug interface enabled. Detecting and
switching to modern interface is based on the 2 legacy CPU hotplug features:
1. Writes into CPU bitmap are ignored.
2. CPU bitmap always has bit#0 set, corresponding to boot CPU.
Use following steps to detect and enable modern CPU hotplug interface:
1. Store 0x0 to the 'CPU selector' register,
attempting to switch to modern mode
2. Store 0x0 to the 'CPU selector' register,
to ensure valid selector value
3. Store 0x0 to the 'Command field' register,
4. Read the 'Command data 2' register.
If read value is 0x0, the modern interface is enabled.
Otherwise legacy or no CPU hotplug interface available
- Get a cpu with pending event
1. Store 0x0 to the 'CPU selector' register.
2. Store 0x0 to the 'Command field' register.
3. Read the 'CPU device status fields' register.
4. If both bit#1 and bit#2 are clear in the value read, there is no CPU
with a pending event and selected CPU remains unchanged.
5. Otherwise, read the 'Command data' register. The value read is the
selector of the CPU with the pending event (which is already
selected).
- Enumerate CPUs present/non present CPUs
01. Set the present CPU count to 0.
02. Set the iterator to 0.
03. Store 0x0 to the 'CPU selector' register, to ensure that it's in
a valid state and that access to other registers won't be ignored.
04. Store 0x0 to the 'Command field' register to make 'Command data'
register return 'CPU selector' value of selected CPU
05. Read the 'CPU device status fields' register.
06. If bit#0 is set, increment the present CPU count.
07. Increment the iterator.
08. Store the iterator to the 'CPU selector' register.
09. Read the 'Command data' register.
10. If the value read is not zero, goto 05.
11. Otherwise store 0x0 to the 'CPU selector' register, to put it
into a valid state and exit.
The iterator at this point equals "max_cpus".

View File

@ -0,0 +1,128 @@
QEMU<->ACPI BIOS memory hotplug interface
=========================================
ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add
and hot-remove events.
Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access)
----------------------------------------------------------------
Read access behavior
^^^^^^^^^^^^^^^^^^^^
[0x0-0x3]
Lo part of memory device phys address
[0x4-0x7]
Hi part of memory device phys address
[0x8-0xb]
Lo part of memory device size in bytes
[0xc-0xf]
Hi part of memory device size in bytes
[0x10-0x13]
Memory device proximity domain
[0x14]
Memory device status fields
bits:
0:
Device is enabled and may be used by guest
1:
Device insert event, used to distinguish device for which
no device check event to OSPM was issued.
It's valid only when bit 1 is set.
2:
Device remove event, used to distinguish device for which
no device eject request to OSPM was issued.
3-7:
reserved and should be ignored by OSPM
[0x15-0x17]
reserved
Write access behavior
^^^^^^^^^^^^^^^^^^^^^
[0x0-0x3]
Memory device slot selector, selects active memory device.
All following accesses to other registers in 0xa00-0xa17
region will read/store data from/to selected memory device.
[0x4-0x7]
OST event code reported by OSPM
[0x8-0xb]
OST status code reported by OSPM
[0xc-0x13]
reserved, writes into it are ignored
[0x14]
Memory device control fields
bits:
0:
reserved, OSPM must clear it before writing to register.
Due to BUG in versions prior 2.4 that field isn't cleared
when other fields are written. Keep it reserved and don't
try to reuse it.
1:
if set to 1 clears device insert event, set by OSPM
after it has emitted device check event for the
selected memory device
2:
if set to 1 clears device remove event, set by OSPM
after it has emitted device eject request for the
selected memory device
3:
if set to 1 initiates device eject, set by OSPM when it
triggers memory device removal and calls _EJ0 method
4-7:
reserved, OSPM must clear them before writing to register
Selecting memory device slot beyond present range has no effect on platform:
- write accesses to memory hot-plug registers not documented above are ignored
- read accesses to memory hot-plug registers not documented above return
all bits set to 1.
Memory hot remove process diagram
---------------------------------
::
+-------------+ +-----------------------+ +------------------+
| 1. QEMU | | 2. QEMU | |3. QEMU |
| device_del +---->+ device unplug request +----->+Send SCI to guest,|
| | | cb | |return control to |
| | | | |management |
+-------------+ +-----------------------+ +------------------+
+---------------------------------------------------------------------+
+---------------------+ +-------------------------+
| OSPM: | remove event | OSPM: |
| send Eject Request, | | Scan memory devices |
| clear remove event +<-------------+ for event flags |
| | | |
+---------------------+ +-------------------------+
|
|
+---------v--------+ +-----------------------+
| Guest OS: | success | OSPM: |
| process Ejection +----------->+ Execute _EJ0 method, |
| request | | set eject bit in flags|
+------------------+ +-----------------------+
|failure |
v v
+------------------------+ +-----------------------+
| OSPM: | | QEMU: |
| set OST event & status | | call device unplug cb |
| fields | | |
+------------------------+ +-----------------------+
| |
v v
+------------------+ +-------------------+
|QEMU: | |QEMU: |
|Send OST QMP event| |Send device deleted|
| | |QMP event |
+------------------+ | |
+-------------------+

View File

@ -1,94 +0,0 @@
QEMU<->ACPI BIOS memory hotplug interface
--------------------------------------
ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add
and hot-remove events.
Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access):
---------------------------------------------------------------
0xa00:
read access:
[0x0-0x3] Lo part of memory device phys address
[0x4-0x7] Hi part of memory device phys address
[0x8-0xb] Lo part of memory device size in bytes
[0xc-0xf] Hi part of memory device size in bytes
[0x10-0x13] Memory device proximity domain
[0x14] Memory device status fields
bits:
0: Device is enabled and may be used by guest
1: Device insert event, used to distinguish device for which
no device check event to OSPM was issued.
It's valid only when bit 1 is set.
2: Device remove event, used to distinguish device for which
no device eject request to OSPM was issued.
3-7: reserved and should be ignored by OSPM
[0x15-0x17] reserved
write access:
[0x0-0x3] Memory device slot selector, selects active memory device.
All following accesses to other registers in 0xa00-0xa17
region will read/store data from/to selected memory device.
[0x4-0x7] OST event code reported by OSPM
[0x8-0xb] OST status code reported by OSPM
[0xc-0x13] reserved, writes into it are ignored
[0x14] Memory device control fields
bits:
0: reserved, OSPM must clear it before writing to register.
Due to BUG in versions prior 2.4 that field isn't cleared
when other fields are written. Keep it reserved and don't
try to reuse it.
1: if set to 1 clears device insert event, set by OSPM
after it has emitted device check event for the
selected memory device
2: if set to 1 clears device remove event, set by OSPM
after it has emitted device eject request for the
selected memory device
3: if set to 1 initiates device eject, set by OSPM when it
triggers memory device removal and calls _EJ0 method
4-7: reserved, OSPM must clear them before writing to register
Selecting memory device slot beyond present range has no effect on platform:
- write accesses to memory hot-plug registers not documented above are
ignored
- read accesses to memory hot-plug registers not documented above return
all bits set to 1.
Memory hot remove process diagram:
----------------------------------
+-------------++-----------------------++------------------+
|1.QEMU||2.QEMU||3.QEMU|
|device_del+---->+deviceunplugrequest+----->+SendSCItoguest,|
|||cb||returncontrolto|
+-------------++-----------------------+|management|
+------------------+
+---------------------------------------------------------------------+
+---------------------++-------------------------+
|OSPM:|removeevent|OSPM:|
|sendEjectRequest,||Scanmemorydevices|
|clearremoveevent+<-------------+foreventflags|
||||
+---------------------++-------------------------+
|
|
+---------v--------++-----------------------+
|GuestOS:|success|OSPM:|
|processEjection+----------->+Execute_EJ0method, |
|request ||setejectbitinflags|
+------------------++-----------------------+
|failure|
vv
+------------------------++-----------------------+
|OSPM:||QEMU:|
|setOSTevent&status||calldeviceunplugcb|
|fields|||
+------------------------++-----------------------+
||
vv
+------------------++-------------------+
|QEMU:||QEMU:|
|SendOSTQMPevent||Senddevicedeleted|
|||QMPevent|
+------------------+||
+-------------------+

228
docs/specs/acpi_nvdimm.rst Normal file
View File

@ -0,0 +1,228 @@
QEMU<->ACPI BIOS NVDIMM interface
=================================
QEMU supports NVDIMM via ACPI. This document describes the basic concepts of
NVDIMM ACPI and the interface between QEMU and the ACPI BIOS.
NVDIMM ACPI Background
----------------------
NVDIMM is introduced in ACPI 6.0 which defines an NVDIMM root device under
_SB scope with a _HID of "ACPI0012". For each NVDIMM present or intended
to be supported by platform, platform firmware also exposes an ACPI
Namespace Device under the root device.
The NVDIMM child devices under the NVDIMM root device are defined with _ADR
corresponding to the NFIT device handle. The NVDIMM root device and the
NVDIMM devices can have device specific methods (_DSM) to provide additional
functions specific to a particular NVDIMM implementation.
This is an example from ACPI 6.0, a platform contains one NVDIMM::
Scope (\_SB){
Device (NVDR) // Root device
{
Name (_HID, "ACPI0012")
Method (_STA) {...}
Method (_FIT) {...}
Method (_DSM, ...) {...}
Device (NVD)
{
Name(_ADR, h) //where h is NFIT Device Handle for this NVDIMM
Method (_DSM, ...) {...}
}
}
}
Methods supported on both NVDIMM root device and NVDIMM device
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_DSM (Device Specific Method)
It is a control method that enables devices to provide device specific
control functions that are consumed by the device driver.
The NVDIMM DSM specification can be found at
http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
Arguments:
Arg0
A Buffer containing a UUID (16 Bytes)
Arg1
An Integer containing the Revision ID (4 Bytes)
Arg2
An Integer containing the Function Index (4 Bytes)
Arg3
A package containing parameters for the function specified by the
UUID, Revision ID, and Function Index
Return Value:
If Function Index = 0, a Buffer containing a function index bitfield.
Otherwise, the return value and type depends on the UUID, revision ID
and function index which are described in the DSM specification.
Methods on NVDIMM ROOT Device
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_FIT(Firmware Interface Table)
It evaluates to a buffer returning data in the format of a series of NFIT
Type Structure.
Arguments: None
Return Value:
A Buffer containing a list of NFIT Type structure entries.
The detailed definition of the structure can be found at ACPI 6.0: 5.2.25
NVDIMM Firmware Interface Table (NFIT).
QEMU NVDIMM Implementation
--------------------------
QEMU uses 4 bytes IO Port starting from 0x0a18 and a RAM-based memory page
for NVDIMM ACPI.
Memory:
QEMU uses BIOS Linker/loader feature to ask BIOS to allocate a memory
page and dynamically patch its address into an int32 object named "MEMA"
in ACPI.
This page is RAM-based and it is used to transfer data between _DSM
method and QEMU. If ACPI has control, this pages is owned by ACPI which
writes _DSM input data to it, otherwise, it is owned by QEMU which
emulates _DSM access and writes the output data to it.
ACPI writes _DSM Input Data (based on the offset in the page):
[0x0 - 0x3]
4 bytes, NVDIMM Device Handle.
The handle is completely QEMU internal thing, the values in
range [1, 0xFFFF] indicate nvdimm device. Other values are
reserved for other purposes.
Reserved handles:
- 0 is reserved for nvdimm root device named NVDR.
- 0x10000 is reserved for QEMU internal DSM function called on
the root device.
[0x4 - 0x7]
4 bytes, Revision ID, that is the Arg1 of _DSM method.
[0x8 - 0xB]
4 bytes. Function Index, that is the Arg2 of _DSM method.
[0xC - 0xFFF]
4084 bytes, the Arg3 of _DSM method.
QEMU writes Output Data (based on the offset in the page):
[0x0 - 0x3]
4 bytes, the length of result
[0x4 - 0xFFF]
4092 bytes, the DSM result filled by QEMU
IO Port 0x0a18 - 0xa1b:
ACPI writes the address of the memory page allocated by BIOS to this
port then QEMU gets the control and fills the result in the memory page.
Write Access:
[0x0a18 - 0xa1b]
4 bytes, the address of the memory page allocated by BIOS.
_DSM process diagram
--------------------
"MEMA" indicates the address of memory page allocated by BIOS.
::
+----------------------+ +-----------------------+
| 1. OSPM | | 2. OSPM |
| save _DSM input data | | write "MEMA" to | Exit to QEMU
| to the page +----->| IO port 0x0a18 +------------+
| indicated by "MEMA" | | | |
+----------------------+ +-----------------------+ |
|
v
+--------------------+ +-----------+ +------------------+--------+
| 5 QEMU | | 4 QEMU | | 3. QEMU |
| write _DSM result | | emulate | | get _DSM input data from |
| to the page +<------+ _DSM +<-----+ the page indicated by the |
| | | | | value from the IO port |
+--------+-----------+ +-----------+ +---------------------------+
|
| Enter Guest
|
v
+--------------------------+ +--------------+
| 6 OSPM | | 7 OSPM |
| result size is returned | | _DSM return |
| by reading DSM +----->+ |
| result from the page | | |
+--------------------------+ +--------------+
NVDIMM hotplug
--------------
ACPI BIOS GPE.4 handler is dedicated for notifying OS about nvdimm device
hot-add event.
QEMU internal use only _DSM functions
-------------------------------------
Read FIT
^^^^^^^^
_FIT method uses _DSM method to fetch NFIT structures blob from QEMU
in 1 page sized increments which are then concatenated and returned
as _FIT method result.
Input parameters:
Arg0
UUID {set to 648B9CF2-CDA1-4312-8AD9-49C4AF32BD62}
Arg1
Revision ID (set to 1)
Arg2
Function Index, 0x1
Arg3
A package containing a buffer whose layout is as follows:
+----------+--------+--------+-------------------------------------------+
| Field | Length | Offset | Description |
+----------+--------+--------+-------------------------------------------+
| offset | 4 | 0 | offset in QEMU's NFIT structures blob to |
| | | | read from |
+----------+--------+--------+-------------------------------------------+
Output layout in the dsm memory page:
+----------+--------+--------+-------------------------------------------+
| Field | Length | Offset | Description |
+----------+--------+--------+-------------------------------------------+
| length | 4 | 0 | length of entire returned data |
| | | | (including this header) |
+----------+--------+--------+-------------------------------------------+
| | | | return status codes |
| | | | |
| | | | - 0x0 - success |
| | | | - 0x100 - error caused by NFIT update |
| status | 4 | 4 | while read by _FIT wasn't completed |
| | | | - other codes follow Chapter 3 in |
| | | | DSM Spec Rev1 |
+----------+--------+--------+-------------------------------------------+
| fit data | Varies | 8 | contains FIT data. This field is present |
| | | | if status field is 0. |
+----------+--------+--------+-------------------------------------------+
The FIT offset is maintained by the OSPM itself, current offset plus
the size of the fit data returned by the function is the next offset
OSPM should read. When all FIT data has been read out, zero fit data
size is returned.
If it returns status code 0x100, OSPM should restart to read FIT (read
from offset 0 again).

View File

@ -1,188 +0,0 @@
QEMU<->ACPI BIOS NVDIMM interface
---------------------------------
QEMU supports NVDIMM via ACPI. This document describes the basic concepts of
NVDIMM ACPI and the interface between QEMU and the ACPI BIOS.
NVDIMM ACPI Background
----------------------
NVDIMM is introduced in ACPI 6.0 which defines an NVDIMM root device under
_SB scope with a _HID of “ACPI0012”. For each NVDIMM present or intended
to be supported by platform, platform firmware also exposes an ACPI
Namespace Device under the root device.
The NVDIMM child devices under the NVDIMM root device are defined with _ADR
corresponding to the NFIT device handle. The NVDIMM root device and the
NVDIMM devices can have device specific methods (_DSM) to provide additional
functions specific to a particular NVDIMM implementation.
This is an example from ACPI 6.0, a platform contains one NVDIMM:
Scope (\_SB){
Device (NVDR) // Root device
{
Name (_HID, “ACPI0012”)
Method (_STA) {...}
Method (_FIT) {...}
Method (_DSM, ...) {...}
Device (NVD)
{
Name(_ADR, h) //where h is NFIT Device Handle for this NVDIMM
Method (_DSM, ...) {...}
}
}
}
Method supported on both NVDIMM root device and NVDIMM device
_DSM (Device Specific Method)
It is a control method that enables devices to provide device specific
control functions that are consumed by the device driver.
The NVDIMM DSM specification can be found at:
http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
Arguments:
Arg0 A Buffer containing a UUID (16 Bytes)
Arg1 An Integer containing the Revision ID (4 Bytes)
Arg2 An Integer containing the Function Index (4 Bytes)
Arg3 A package containing parameters for the function specified by the
UUID, Revision ID, and Function Index
Return Value:
If Function Index = 0, a Buffer containing a function index bitfield.
Otherwise, the return value and type depends on the UUID, revision ID
and function index which are described in the DSM specification.
Methods on NVDIMM ROOT Device
_FIT(Firmware Interface Table)
It evaluates to a buffer returning data in the format of a series of NFIT
Type Structure.
Arguments: None
Return Value:
A Buffer containing a list of NFIT Type structure entries.
The detailed definition of the structure can be found at ACPI 6.0: 5.2.25
NVDIMM Firmware Interface Table (NFIT).
QEMU NVDIMM Implementation
==========================
QEMU uses 4 bytes IO Port starting from 0x0a18 and a RAM-based memory page
for NVDIMM ACPI.
Memory:
QEMU uses BIOS Linker/loader feature to ask BIOS to allocate a memory
page and dynamically patch its address into an int32 object named "MEMA"
in ACPI.
This page is RAM-based and it is used to transfer data between _DSM
method and QEMU. If ACPI has control, this pages is owned by ACPI which
writes _DSM input data to it, otherwise, it is owned by QEMU which
emulates _DSM access and writes the output data to it.
ACPI writes _DSM Input Data (based on the offset in the page):
[0x0 - 0x3]: 4 bytes, NVDIMM Device Handle.
The handle is completely QEMU internal thing, the values in
range [1, 0xFFFF] indicate nvdimm device. Other values are
reserved for other purposes.
Reserved handles:
0 is reserved for nvdimm root device named NVDR.
0x10000 is reserved for QEMU internal DSM function called on
the root device.
[0x4 - 0x7]: 4 bytes, Revision ID, that is the Arg1 of _DSM method.
[0x8 - 0xB]: 4 bytes. Function Index, that is the Arg2 of _DSM method.
[0xC - 0xFFF]: 4084 bytes, the Arg3 of _DSM method.
QEMU Writes Output Data (based on the offset in the page):
[0x0 - 0x3]: 4 bytes, the length of result
[0x4 - 0xFFF]: 4092 bytes, the DSM result filled by QEMU
IO Port 0x0a18 - 0xa1b:
ACPI writes the address of the memory page allocated by BIOS to this
port then QEMU gets the control and fills the result in the memory page.
write Access:
[0x0a18 - 0xa1b]: 4 bytes, the address of the memory page allocated
by BIOS.
_DSM process diagram:
---------------------
"MEMA" indicates the address of memory page allocated by BIOS.
+----------------------+ +-----------------------+
| 1.OSPM || 2. OSPM |
|save _DSM input data | | write "MEMA" to | Exit to QEMU
| to the page +----->| IO port 0x0a18 +------------+
| indicated by "MEMA" | | | |
+----------------------+ +-----------------------+ |
|
v
+------------- ----+ +-----------+ +------------------+--------+
| 5 QEMU | | 4 QEMU | | 3. QEMU |
| write _DSM result | | emulate | | get _DSM input data from |
| to the page +<------+ _DSM +<-----+ the page indicated by the |
| | | | | value from the IO port |
+--------+-----------+ +-----------+ +---------------------------+
|
| Enter Guest
|
v
+--------------------------+ +--------------+
| 6 OSPM | | 7 OSPM |
| result size is returned | | _DSM return |
| by reading DSM +----->+ |
| result from the page | | |
+--------------------------+ +--------------+
NVDIMM hotplug
--------------
ACPI BIOS GPE.4 handler is dedicated for notifying OS about nvdimm device
hot-add event.
QEMU internal use only _DSM function
------------------------------------
1) Read FIT
_FIT method uses _DSM method to fetch NFIT structures blob from QEMU
in 1 page sized increments which are then concatenated and returned
as _FIT method result.
Input parameters:
Arg0 UUID {set to 648B9CF2-CDA1-4312-8AD9-49C4AF32BD62}
Arg1 Revision ID (set to 1)
Arg2 - Function Index, 0x1
Arg3 - A package containing a buffer whose layout is as follows:
+----------+--------+--------+-------------------------------------------+
| Field | Length | Offset | Description |
+----------+--------+--------+-------------------------------------------+
| offset | 4 | 0 | offset in QEMU's NFIT structures blob to |
| | | | read from |
+----------+--------+--------+-------------------------------------------+
Output layout in the dsm memory page:
+----------+--------+--------+-------------------------------------------+
| Field | Length | Offset | Description |
+----------+--------+--------+-------------------------------------------+
| length | 4 | 0 | length of entire returned data |
| | | | (including this header) |
+----------+-----------------+-------------------------------------------+
| | | | return status codes |
| | | | 0x0 - success |
| | | | 0x100 - error caused by NFIT update while |
| status | 4 | 4 | read by _FIT wasn't completed, other |
| | | | codes follow Chapter 3 in DSM Spec Rev1 |
+----------+-----------------+-------------------------------------------+
| fit data | Varies | 8 | contains FIT data, this field is present |
| | | | if status field is 0; |
+----------+--------+--------+-------------------------------------------+
The FIT offset is maintained by the OSPM itself, current offset plus
the size of the fit data returned by the function is the next offset
OSPM should read. When all FIT data has been read out, zero fit data
size is returned.
If it returns status code 0x100, OSPM should restart to read FIT (read
from offset 0 again).

View File

@ -1,45 +1,48 @@
QEMU<->ACPI BIOS PCI hotplug interface
--------------------------------------
======================================
QEMU supports PCI hotplug via ACPI, for PCI bus 0. This document
describes the interface between QEMU and the ACPI BIOS.
ACPI GPE block (IO ports 0xafe0-0xafe3, byte access):
-----------------------------------------
ACPI GPE block (IO ports 0xafe0-0xafe3, byte access)
----------------------------------------------------
Generic ACPI GPE block. Bit 1 (GPE.1) used to notify PCI hotplug/eject
event to ACPI BIOS, via SCI interrupt.
PCI slot injection notification pending (IO port 0xae00-0xae03, 4-byte access):
---------------------------------------------------------------
PCI slot injection notification pending (IO port 0xae00-0xae03, 4-byte access)
------------------------------------------------------------------------------
Slot injection notification pending. One bit per slot.
Read by ACPI BIOS GPE.1 handler to notify OS of injection
events. Read-only.
PCI slot removal notification (IO port 0xae04-0xae07, 4-byte access):
-----------------------------------------------------
PCI slot removal notification (IO port 0xae04-0xae07, 4-byte access)
--------------------------------------------------------------------
Slot removal notification pending. One bit per slot.
Read by ACPI BIOS GPE.1 handler to notify OS of removal
events. Read-only.
PCI device eject (IO port 0xae08-0xae0b, 4-byte access):
----------------------------------------
PCI device eject (IO port 0xae08-0xae0b, 4-byte access)
-------------------------------------------------------
Write: Used by ACPI BIOS _EJ0 method to request device removal.
One bit per slot.
Read: Hotplug features register. Used by platform to identify features
available. Current base feature set (no bits set):
- Read-only "up" register @0xae00, 4-byte access, bit per slot
- Read-only "down" register @0xae04, 4-byte access, bit per slot
- Read/write "eject" register @0xae08, 4-byte access,
write: bit per slot eject, read: hotplug feature set
- Read-only hotplug capable register @0xae0c, 4-byte access, bit per slot
PCI removability status (IO port 0xae0c-0xae0f, 4-byte access):
-----------------------------------------------
- Read-only "up" register @0xae00, 4-byte access, bit per slot
- Read-only "down" register @0xae04, 4-byte access, bit per slot
- Read/write "eject" register @0xae08, 4-byte access,
write: bit per slot eject, read: hotplug feature set
- Read-only hotplug capable register @0xae0c, 4-byte access, bit per slot
PCI removability status (IO port 0xae0c-0xae0f, 4-byte access)
--------------------------------------------------------------
Used by ACPI BIOS _RMV method to indicate removability status to OS. One
bit per slot. Read-only
bit per slot. Read-only.

View File

@ -13,3 +13,7 @@ guest hardware that is specific to QEMU.
acpi_hw_reduced_hotplug
tpm
acpi_hest_ghes
acpi_cpu_hotplug
acpi_mem_hotplug
acpi_pci_hotplug
acpi_nvdimm

View File

@ -3218,7 +3218,7 @@ static bool gdb_accept_socket(int gdb_fd)
static int gdbserver_open_socket(const char *path)
{
struct sockaddr_un sockaddr;
struct sockaddr_un sockaddr = {};
int fd, ret;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
@ -3247,7 +3247,7 @@ static int gdbserver_open_socket(const char *path)
static bool gdb_accept_tcp(int gdb_fd)
{
struct sockaddr_in sockaddr;
struct sockaddr_in sockaddr = {};
socklen_t len;
int fd;

View File

@ -25,9 +25,7 @@ config ARM_VIRT
select ACPI_PCI
select MEM_DEVICE
select DIMM
select ACPI_MEMORY_HOTPLUG
select ACPI_HW_REDUCED
select ACPI_NVDIMM
select ACPI_APEI
config CHEETAH

View File

@ -281,7 +281,7 @@ static void raspi_machine_init(MachineState *machine)
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram));
object_property_set_int(OBJECT(&s->soc), "board-rev", board_rev,
&error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* Create and plug in the SD cards */
di = drive_get_next(IF_SD);

View File

@ -1852,11 +1852,6 @@ static void machvirt_init(MachineState *machine)
}
if (vms->secure) {
if (kvm_enabled()) {
error_report("mach-virt: KVM does not support Security extensions");
exit(1);
}
/*
* The Secure view of the world is the same as the NonSecure,
* but with a few extra devices. Create it as a container region

View File

@ -218,6 +218,8 @@ static void versal_create_admas(Versal *s, qemu_irq *pic)
TYPE_XLNX_ZDMA);
dev = DEVICE(&s->lpd.iou.adma[i]);
object_property_set_int(OBJECT(dev), "bus-width", 128, &error_abort);
object_property_set_link(OBJECT(dev), "dma",
OBJECT(get_system_memory()), &error_fatal);
sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
@ -376,6 +378,8 @@ static void versal_unimp(Versal *s)
MM_CRL, MM_CRL_SIZE);
versal_unimp_area(s, "crf", &s->mr_ps,
MM_FPD_CRF, MM_FPD_CRF_SIZE);
versal_unimp_area(s, "apu", &s->mr_ps,
MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE);
versal_unimp_area(s, "crp", &s->mr_ps,
MM_PMC_CRP, MM_PMC_CRP_SIZE);
versal_unimp_area(s, "iou-scntr", &s->mr_ps,

View File

@ -20,6 +20,7 @@
#include "qemu/module.h"
#include "hw/arm/xlnx-zynqmp.h"
#include "hw/intc/arm_gic_common.h"
#include "hw/misc/unimp.h"
#include "hw/boards.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
@ -56,6 +57,9 @@
#define DPDMA_ADDR 0xfd4c0000
#define DPDMA_IRQ 116
#define APU_ADDR 0xfd5c0000
#define APU_SIZE 0x100
#define IPI_ADDR 0xFF300000
#define IPI_IRQ 64
@ -222,6 +226,32 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s,
qdev_realize(DEVICE(&s->rpu_cluster), NULL, &error_fatal);
}
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
{
static const struct UnimpInfo {
const char *name;
hwaddr base;
hwaddr size;
} unimp_areas[ARRAY_SIZE(s->mr_unimp)] = {
{ .name = "apu", APU_ADDR, APU_SIZE },
};
unsigned int nr;
for (nr = 0; nr < ARRAY_SIZE(unimp_areas); nr++) {
const struct UnimpInfo *info = &unimp_areas[nr];
DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
assert(info->name && info->base && info->size > 0);
qdev_prop_set_string(dev, "name", info->name);
qdev_prop_set_uint64(dev, "size", info->size);
object_property_add_child(OBJECT(s), info->name, OBJECT(dev));
sysbus_realize_and_unref(sbd, &error_fatal);
sysbus_mmio_map(sbd, 0, info->base);
}
}
static void xlnx_zynqmp_init(Object *obj)
{
MachineState *ms = MACHINE(qdev_get_machine());
@ -570,26 +600,6 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
g_free(bus_name);
}
if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi), errp)) {
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 1, LQSPI_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0, gic_spi[QSPI_IRQ]);
for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_BUS; i++) {
gchar *bus_name;
gchar *target_bus;
/* Alias controller SPI bus to the SoC itself */
bus_name = g_strdup_printf("qspi%d", i);
target_bus = g_strdup_printf("spi%d", i);
object_property_add_alias(OBJECT(s), bus_name,
OBJECT(&s->qspi), target_bus);
g_free(bus_name);
g_free(target_bus);
}
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dp), errp)) {
return;
}
@ -616,11 +626,17 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
xlnx_zynqmp_create_unimp_mmio(s);
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
if (!object_property_set_uint(OBJECT(&s->gdma[i]), "bus-width", 128,
errp)) {
return;
}
if (!object_property_set_link(OBJECT(&s->gdma[i]), "dma",
OBJECT(system_memory), errp)) {
return;
}
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gdma[i]), errp)) {
return;
}
@ -631,6 +647,10 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
}
for (i = 0; i < XLNX_ZYNQMP_NUM_ADMA_CH; i++) {
if (!object_property_set_link(OBJECT(&s->adma[i]), "dma",
OBJECT(system_memory), errp)) {
return;
}
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adma[i]), errp)) {
return;
}
@ -640,14 +660,36 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
gic_spi[adma_ch_intr[i]]);
}
if (!object_property_set_link(OBJECT(&s->qspi_dma), "dma",
OBJECT(system_memory), errp)) {
return;
}
if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi_dma), errp)) {
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi_dma), 0, QSPI_DMA_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0, gic_spi[QSPI_IRQ]);
object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
OBJECT(&s->qspi_dma), errp);
if (!object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
OBJECT(&s->qspi_dma), errp)) {
return;
}
if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi), errp)) {
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 1, LQSPI_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0, gic_spi[QSPI_IRQ]);
for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_BUS; i++) {
g_autofree gchar *bus_name = g_strdup_printf("qspi%d", i);
g_autofree gchar *target_bus = g_strdup_printf("spi%d", i);
/* Alias controller SPI bus to the SoC itself */
object_property_add_alias(OBJECT(s), bus_name,
OBJECT(&s->qspi), target_bus);
}
}
static Property xlnx_zynqmp_props[] = {

View File

@ -555,24 +555,35 @@ ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen)
/* skip header */
i = 10;
if (srclen < 4) {
goto toosmall;
}
flags = src[3];
if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
puts ("Error: Bad gzipped data\n");
return -1;
}
if ((flags & EXTRA_FIELD) != 0)
if ((flags & EXTRA_FIELD) != 0) {
if (srclen < 12) {
goto toosmall;
}
i = 12 + src[10] + (src[11] << 8);
if ((flags & ORIG_NAME) != 0)
while (src[i++] != 0)
;
if ((flags & COMMENT) != 0)
while (src[i++] != 0)
;
if ((flags & HEAD_CRC) != 0)
}
if ((flags & ORIG_NAME) != 0) {
while (i < srclen && src[i++] != 0) {
/* do nothing */
}
}
if ((flags & COMMENT) != 0) {
while (i < srclen && src[i++] != 0) {
/* do nothing */
}
}
if ((flags & HEAD_CRC) != 0) {
i += 2;
}
if (i >= srclen) {
puts ("Error: gunzip out of data in header\n");
return -1;
goto toosmall;
}
s.zalloc = zalloc;
@ -596,6 +607,10 @@ ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen)
inflateEnd(&s);
return dstbytes;
toosmall:
puts("Error: gunzip out of data in header\n");
return -1;
}
/* Load a U-Boot image. */

View File

@ -320,9 +320,9 @@ static bool zdma_load_descriptor(XlnxZDMA *s, uint64_t addr,
return false;
}
descr->addr = address_space_ldq_le(s->dma_as, addr, s->attr, NULL);
descr->size = address_space_ldl_le(s->dma_as, addr + 8, s->attr, NULL);
descr->attr = address_space_ldl_le(s->dma_as, addr + 12, s->attr, NULL);
descr->addr = address_space_ldq_le(&s->dma_as, addr, s->attr, NULL);
descr->size = address_space_ldl_le(&s->dma_as, addr + 8, s->attr, NULL);
descr->attr = address_space_ldl_le(&s->dma_as, addr + 12, s->attr, NULL);
return true;
}
@ -354,7 +354,7 @@ static void zdma_update_descr_addr(XlnxZDMA *s, bool type,
} else {
addr = zdma_get_regaddr64(s, basereg);
addr += sizeof(s->dsc_dst);
next = address_space_ldq_le(s->dma_as, addr, s->attr, NULL);
next = address_space_ldq_le(&s->dma_as, addr, s->attr, NULL);
}
zdma_put_regaddr64(s, basereg, next);
@ -421,7 +421,7 @@ static void zdma_write_dst(XlnxZDMA *s, uint8_t *buf, uint32_t len)
}
}
address_space_write(s->dma_as, s->dsc_dst.addr, s->attr, buf, dlen);
address_space_write(&s->dma_as, s->dsc_dst.addr, s->attr, buf, dlen);
if (burst_type == AXI_BURST_INCR) {
s->dsc_dst.addr += dlen;
}
@ -497,7 +497,7 @@ static void zdma_process_descr(XlnxZDMA *s)
len = s->cfg.bus_width / 8;
}
} else {
address_space_read(s->dma_as, src_addr, s->attr, s->buf, len);
address_space_read(&s->dma_as, src_addr, s->attr, s->buf, len);
if (burst_type == AXI_BURST_INCR) {
src_addr += len;
}
@ -765,6 +765,12 @@ static void zdma_realize(DeviceState *dev, Error **errp)
XlnxZDMA *s = XLNX_ZDMA(dev);
unsigned int i;
if (!s->dma_mr) {
error_setg(errp, TYPE_XLNX_ZDMA " 'dma' link not set");
return;
}
address_space_init(&s->dma_as, s->dma_mr, "zdma-dma");
for (i = 0; i < ARRAY_SIZE(zdma_regs_info); ++i) {
RegisterInfo *r = &s->regs_info[zdma_regs_info[i].addr / 4];
@ -777,12 +783,6 @@ static void zdma_realize(DeviceState *dev, Error **errp)
};
}
if (s->dma_mr) {
s->dma_as = g_malloc0(sizeof(AddressSpace));
address_space_init(s->dma_as, s->dma_mr, NULL);
} else {
s->dma_as = &address_space_memory;
}
s->attr = MEMTXATTRS_UNSPECIFIED;
}

View File

@ -201,11 +201,11 @@ static uint32_t xlnx_csu_dma_read(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
uint32_t mlen = MIN(len - i, s->width);
result = address_space_rw(s->dma_as, addr, s->attr,
result = address_space_rw(&s->dma_as, addr, s->attr,
buf + i, mlen, false);
}
} else {
result = address_space_rw(s->dma_as, addr, s->attr, buf, len, false);
result = address_space_rw(&s->dma_as, addr, s->attr, buf, len, false);
}
if (result == MEMTX_OK) {
@ -232,12 +232,12 @@ static uint32_t xlnx_csu_dma_write(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
uint32_t mlen = MIN(len - i, s->width);
result = address_space_rw(s->dma_as, addr, s->attr,
result = address_space_rw(&s->dma_as, addr, s->attr,
buf, mlen, true);
buf += mlen;
}
} else {
result = address_space_rw(s->dma_as, addr, s->attr, buf, len, true);
result = address_space_rw(&s->dma_as, addr, s->attr, buf, len, true);
}
if (result != MEMTX_OK) {
@ -626,6 +626,17 @@ static void xlnx_csu_dma_realize(DeviceState *dev, Error **errp)
XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
RegisterInfoArray *reg_array;
if (!s->is_dst && !s->tx_dev) {
error_setg(errp, "zynqmp.csu-dma: Stream not connected");
return;
}
if (!s->dma_mr) {
error_setg(errp, TYPE_XLNX_CSU_DMA " 'dma' link not set");
return;
}
address_space_init(&s->dma_as, s->dma_mr, "csu-dma");
reg_array =
register_init_block32(dev, xlnx_csu_dma_regs_info[!!s->is_dst],
XLNX_CSU_DMA_R_MAX,
@ -640,21 +651,9 @@ static void xlnx_csu_dma_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
if (!s->is_dst && !s->tx_dev) {
error_setg(errp, "zynqmp.csu-dma: Stream not connected");
return;
}
s->src_timer = ptimer_init(xlnx_csu_dma_src_timeout_hit,
s, PTIMER_POLICY_DEFAULT);
if (s->dma_mr) {
s->dma_as = g_malloc0(sizeof(AddressSpace));
address_space_init(s->dma_as, s->dma_mr, NULL);
} else {
s->dma_as = &address_space_memory;
}
s->attr = MEMTXATTRS_UNSPECIFIED;
s->r_size_last_word = 0;

View File

@ -65,7 +65,6 @@
#include "hw/xen/start_info.h"
#include "ui/qemu-spice.h"
#include "exec/memory.h"
#include "sysemu/arch_init.h"
#include "qemu/bitmap.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"

View File

@ -43,7 +43,6 @@
#include "sysemu/kvm.h"
#include "hw/kvm/clock.h"
#include "hw/sysbus.h"
#include "sysemu/arch_init.h"
#include "hw/i2c/smbus_eeprom.h"
#include "hw/xen/xen-x86.h"
#include "exec/memory.h"

View File

@ -31,7 +31,6 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "hw/loader.h"
#include "sysemu/arch_init.h"
#include "hw/i2c/smbus_eeprom.h"
#include "hw/rtc/mc146818rtc.h"
#include "sysemu/kvm.h"

View File

@ -35,7 +35,6 @@
#include "hw/isa/isa.h"
#include "hw/block/fdc.h"
#include "sysemu/sysemu.h"
#include "sysemu/arch_init.h"
#include "hw/boards.h"
#include "net/net.h"
#include "hw/scsi/esp.h"

View File

@ -38,7 +38,6 @@
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
#include "hw/pci/pci.h"
#include "sysemu/arch_init.h"
#include "qemu/log.h"
#include "hw/mips/bios.h"
#include "hw/ide.h"

View File

@ -40,7 +40,6 @@
#include "hw/rtc/mc146818rtc.h"
#include "hw/isa/pc87312.h"
#include "hw/qdev-properties.h"
#include "sysemu/arch_init.h"
#include "sysemu/kvm.h"
#include "sysemu/reset.h"
#include "trace.h"

View File

@ -45,7 +45,6 @@
#include "hw/intc/sifive_plic.h"
#include "hw/misc/sifive_e_prci.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/sysemu.h"
static const MemMapEntry sifive_e_memmap[] = {

View File

@ -55,7 +55,6 @@
#include "hw/intc/sifive_plic.h"
#include "chardev/char.h"
#include "net/eth.h"
#include "sysemu/arch_init.h"
#include "sysemu/device_tree.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"

View File

@ -37,7 +37,6 @@
#include "hw/char/riscv_htif.h"
#include "hw/intc/sifive_clint.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/device_tree.h"
#include "sysemu/sysemu.h"

View File

@ -36,7 +36,6 @@
#include "hw/intc/sifive_plic.h"
#include "hw/misc/sifive_test.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/device_tree.h"
#include "sysemu/sysemu.h"
#include "hw/pci/pci.h"

View File

@ -167,6 +167,8 @@ struct Versal {
#define MM_IOU_SCNTRS_SIZE 0x10000
#define MM_FPD_CRF 0xfd1a0000U
#define MM_FPD_CRF_SIZE 0x140000
#define MM_FPD_FPD_APU 0xfd5c0000
#define MM_FPD_FPD_APU_SIZE 0x100
#define MM_PMC_SD0 0xf1040000U
#define MM_PMC_SD0_SIZE 0x10000

View File

@ -79,6 +79,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
/*
* Unimplemented mmio regions needed to boot some images.
*/
#define XLNX_ZYNQMP_NUM_UNIMP_AREAS 1
struct XlnxZynqMPState {
/*< private >*/
DeviceState parent_obj;
@ -96,6 +101,8 @@ struct XlnxZynqMPState {
MemoryRegion *ddr_ram;
MemoryRegion ddr_ram_low, ddr_ram_high;
MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS];
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];

View File

@ -56,7 +56,7 @@ struct XlnxZDMA {
MemoryRegion iomem;
MemTxAttrs attr;
MemoryRegion *dma_mr;
AddressSpace *dma_as;
AddressSpace dma_as;
qemu_irq irq_zdma_ch_imr;
struct {

View File

@ -30,7 +30,7 @@ typedef struct XlnxCSUDMA {
MemoryRegion iomem;
MemTxAttrs attr;
MemoryRegion *dma_mr;
AddressSpace *dma_as;
AddressSpace dma_as;
qemu_irq irq;
StreamSink *tx_dev; /* Used as generic StreamSink */
ptimer_state *src_timer;

View File

@ -23,22 +23,9 @@ enum {
QEMU_ARCH_RISCV = (1 << 19),
QEMU_ARCH_RX = (1 << 20),
QEMU_ARCH_AVR = (1 << 21),
QEMU_ARCH_NONE = (1 << 31),
QEMU_ARCH_HEXAGON = (1 << 22),
};
extern const uint32_t arch_type;
int kvm_available(void);
int xen_available(void);
/* default virtio transport per architecture */
#define QEMU_ARCH_VIRTIO_PCI (QEMU_ARCH_ALPHA | QEMU_ARCH_ARM | \
QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
QEMU_ARCH_MIPS | QEMU_ARCH_PPC | \
QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
#define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
#define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
#endif

View File

@ -289,7 +289,6 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T | CPSR_E, CPSRWriteByInstr);
arm_rebuild_hflags(env);
return 0;
}
@ -547,7 +546,6 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
__get_user(env->regs[15], &sc->arm_pc);
__get_user(cpsr, &sc->arm_cpsr);
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
arm_rebuild_hflags(env);
err |= !valid_user_regs(env);

View File

@ -1625,6 +1625,8 @@ foreach target : target_dirs
config_target_data.set(k, v)
endif
endforeach
config_target_data.set('QEMU_ARCH',
'QEMU_ARCH_' + config_target['TARGET_BASE_ARCH'].to_upper())
config_target_h += {target: configure_file(output: target + '-config-target.h',
configuration: config_target_data)}

View File

@ -27,7 +27,6 @@
#include "sysemu/kvm.h"
#include "sysemu/runstate.h"
#include "sysemu/runstate-action.h"
#include "sysemu/arch_init.h"
#include "sysemu/blockdev.h"
#include "sysemu/block-backend.h"
#include "qapi/error.h"
@ -58,7 +57,7 @@ KvmInfo *qmp_query_kvm(Error **errp)
KvmInfo *info = g_malloc0(sizeof(*info));
info->enabled = kvm_enabled();
info->present = kvm_available();
info->present = accel_find("kvm");
return info;
}

View File

@ -75,6 +75,8 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str,
const char *addr, *p, *r;
int port, ret = 0;
memset(saddr, 0, sizeof(*saddr));
substrings = g_strsplit(str, ":", 2);
if (!substrings || !substrings[0] || !substrings[1]) {
error_setg(errp, "host address '%s' doesn't contain ':' "

View File

@ -23,13 +23,6 @@
*/
#include "qemu/osdep.h"
#include "sysemu/arch_init.h"
#include "hw/pci/pci.h"
#include "hw/audio/soundhw.h"
#include "qapi/error.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "hw/acpi/acpi.h"
#include "qemu/help_option.h"
#ifdef TARGET_SPARC
int graphic_width = 1024;
@ -45,63 +38,4 @@ int graphic_height = 600;
int graphic_depth = 32;
#endif
#if defined(TARGET_ALPHA)
#define QEMU_ARCH QEMU_ARCH_ALPHA
#elif defined(TARGET_ARM)
#define QEMU_ARCH QEMU_ARCH_ARM
#elif defined(TARGET_CRIS)
#define QEMU_ARCH QEMU_ARCH_CRIS
#elif defined(TARGET_HPPA)
#define QEMU_ARCH QEMU_ARCH_HPPA
#elif defined(TARGET_I386)
#define QEMU_ARCH QEMU_ARCH_I386
#elif defined(TARGET_M68K)
#define QEMU_ARCH QEMU_ARCH_M68K
#elif defined(TARGET_MICROBLAZE)
#define QEMU_ARCH QEMU_ARCH_MICROBLAZE
#elif defined(TARGET_MIPS)
#define QEMU_ARCH QEMU_ARCH_MIPS
#elif defined(TARGET_NIOS2)
#define QEMU_ARCH QEMU_ARCH_NIOS2
#elif defined(TARGET_OPENRISC)
#define QEMU_ARCH QEMU_ARCH_OPENRISC
#elif defined(TARGET_PPC)
#define QEMU_ARCH QEMU_ARCH_PPC
#elif defined(TARGET_RISCV)
#define QEMU_ARCH QEMU_ARCH_RISCV
#elif defined(TARGET_RX)
#define QEMU_ARCH QEMU_ARCH_RX
#elif defined(TARGET_S390X)
#define QEMU_ARCH QEMU_ARCH_S390X
#elif defined(TARGET_SH4)
#define QEMU_ARCH QEMU_ARCH_SH4
#elif defined(TARGET_SPARC)
#define QEMU_ARCH QEMU_ARCH_SPARC
#elif defined(TARGET_TRICORE)
#define QEMU_ARCH QEMU_ARCH_TRICORE
#elif defined(TARGET_XTENSA)
#define QEMU_ARCH QEMU_ARCH_XTENSA
#elif defined(TARGET_AVR)
#define QEMU_ARCH QEMU_ARCH_AVR
#endif
const uint32_t arch_type = QEMU_ARCH;
int kvm_available(void)
{
#ifdef CONFIG_KVM
return 1;
#else
return 0;
#endif
}
int xen_available(void)
{
#ifdef CONFIG_XEN
return 1;
#else
return 0;
#endif
}

View File

@ -1451,6 +1451,9 @@ static int64_t get_file_align(int fd)
path = g_strdup_printf("/sys/dev/char/%d:%d",
major(st.st_rdev), minor(st.st_rdev));
rpath = realpath(path, NULL);
if (!rpath) {
return -errno;
}
rc = daxctl_new(&ctx);
if (rc) {
@ -2075,7 +2078,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
}
file_align = get_file_align(fd);
if (file_align > 0 && mr && file_align > mr->align) {
if (file_align > 0 && file_align > mr->align) {
error_setg(errp, "backing store align 0x%" PRIx64
" is larger than 'align' option 0x%" PRIx64,
file_align, mr->align);

View File

@ -52,6 +52,15 @@ typedef struct QDevAlias
uint32_t arch_mask;
} QDevAlias;
/* default virtio transport per architecture */
#define QEMU_ARCH_VIRTIO_PCI (QEMU_ARCH_ALPHA | QEMU_ARCH_ARM | \
QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
QEMU_ARCH_MIPS | QEMU_ARCH_PPC | \
QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
#define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
#define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
/* Please keep this table sorted by typename. */
static const QDevAlias qdev_alias_table[] = {
{ "AC97", "ac97" }, /* -soundhw name */

View File

@ -3448,21 +3448,21 @@ void qemu_init(int argc, char **argv, char **envp)
has_defaults = 0;
break;
case QEMU_OPTION_xen_domid:
if (!(xen_available())) {
if (!(accel_find("xen"))) {
error_report("Option not supported for this target");
exit(1);
}
xen_domid = atoi(optarg);
break;
case QEMU_OPTION_xen_attach:
if (!(xen_available())) {
if (!(accel_find("xen"))) {
error_report("Option not supported for this target");
exit(1);
}
xen_mode = XEN_ATTACH;
break;
case QEMU_OPTION_xen_domid_restrict:
if (!(xen_available())) {
if (!(accel_find("xen"))) {
error_report("Option not supported for this target");
exit(1);
}

View File

@ -1,4 +0,0 @@
#include "qemu/osdep.h"
#include "sysemu/arch_init.h"
const uint32_t arch_type = QEMU_ARCH_NONE;

View File

@ -1,4 +1,3 @@
stub_ss.add(files('arch_type.c'))
stub_ss.add(files('bdrv-next-monitor-owned.c'))
stub_ss.add(files('blk-commit-all.c'))
stub_ss.add(files('blk-exp-close-all.c'))

View File

@ -1422,6 +1422,29 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
}
}
if (kvm_enabled()) {
/*
* Catch all the cases which might cause us to create more than one
* address space for the CPU (otherwise we will assert() later in
* cpu_address_space_init()).
*/
if (arm_feature(env, ARM_FEATURE_M)) {
error_setg(errp,
"Cannot enable KVM when using an M-profile guest CPU");
return;
}
if (cpu->has_el3) {
error_setg(errp,
"Cannot enable KVM when guest CPU has EL3 enabled");
return;
}
if (cpu->tag_memory) {
error_setg(errp,
"Cannot enable KVM when guest CPUs has MTE enabled");
return;
}
}
{
uint64_t scale;

View File

@ -1020,9 +1020,13 @@ struct ARMCPU {
* While processing properties during initialization, corresponding
* sve_vq_init bits are set for bits in sve_vq_map that have been
* set by properties.
*
* Bits set in sve_vq_supported represent valid vector lengths for
* the CPU type.
*/
DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
DECLARE_BITMAP(sve_vq_supported, ARM_MAX_VQ);
/* Generic timer counter frequency, in Hz */
uint64_t gt_cntfrq_hz;
@ -1394,11 +1398,17 @@ uint32_t cpsr_read(CPUARMState *env);
typedef enum CPSRWriteType {
CPSRWriteByInstr = 0, /* from guest MSR or CPS */
CPSRWriteExceptionReturn = 1, /* from guest exception return insn */
CPSRWriteRaw = 2, /* trust values, do not switch reg banks */
CPSRWriteRaw = 2,
/* trust values, no reg bank switch, no hflags rebuild */
CPSRWriteByGDBStub = 3, /* from the GDB stub */
} CPSRWriteType;
/* Set the CPSR. Note that some bits of mask must be all-set or all-clear.*/
/*
* Set the CPSR. Note that some bits of mask must be all-set or all-clear.
* This will do an arm_rebuild_hflags() if any of the bits in @mask
* correspond to TB flags bits cached in the hflags, unless @write_type
* is CPSRWriteRaw.
*/
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
CPSRWriteType write_type);
@ -1537,6 +1547,9 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_ENSCXT (1U << 25)
#define SCR_ATA (1U << 26)
#define HSTR_TTEE (1 << 16)
#define HSTR_TJDBX (1 << 17)
/* Return the current FPSCR value. */
uint32_t vfp_get_fpscr(CPUARMState *env);
void vfp_set_fpscr(CPUARMState *env, uint32_t val);

View File

@ -265,14 +265,17 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
* any of the above. Finally, if SVE is not disabled, then at least one
* vector length must be enabled.
*/
DECLARE_BITMAP(kvm_supported, ARM_MAX_VQ);
DECLARE_BITMAP(tmp, ARM_MAX_VQ);
uint32_t vq, max_vq = 0;
/* Collect the set of vector lengths supported by KVM. */
bitmap_zero(kvm_supported, ARM_MAX_VQ);
/*
* CPU models specify a set of supported vector lengths which are
* enabled by default. Attempting to enable any vector length not set
* in the supported bitmap results in an error. When KVM is enabled we
* fetch the supported bitmap from the host.
*/
if (kvm_enabled() && kvm_arm_sve_supported()) {
kvm_arm_sve_get_vls(CPU(cpu), kvm_supported);
kvm_arm_sve_get_vls(CPU(cpu), cpu->sve_vq_supported);
} else if (kvm_enabled()) {
assert(!cpu_isar_feature(aa64_sve, cpu));
}
@ -299,7 +302,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
* For KVM we have to automatically enable all supported unitialized
* lengths, even when the smaller lengths are not all powers-of-two.
*/
bitmap_andnot(tmp, kvm_supported, cpu->sve_vq_init, max_vq);
bitmap_andnot(tmp, cpu->sve_vq_supported, cpu->sve_vq_init, max_vq);
bitmap_or(cpu->sve_vq_map, cpu->sve_vq_map, tmp, max_vq);
} else {
/* Propagate enabled bits down through required powers-of-two. */
@ -322,39 +325,30 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
/* Disabling a supported length disables all larger lengths. */
for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
if (test_bit(vq - 1, cpu->sve_vq_init) &&
test_bit(vq - 1, kvm_supported)) {
test_bit(vq - 1, cpu->sve_vq_supported)) {
break;
}
}
max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
bitmap_andnot(cpu->sve_vq_map, kvm_supported,
cpu->sve_vq_init, max_vq);
if (max_vq == 0 || bitmap_empty(cpu->sve_vq_map, max_vq)) {
error_setg(errp, "cannot disable sve%d", vq * 128);
error_append_hint(errp, "Disabling sve%d results in all "
"vector lengths being disabled.\n",
vq * 128);
error_append_hint(errp, "With SVE enabled, at least one "
"vector length must be enabled.\n");
return;
}
} else {
/* Disabling a power-of-two disables all larger lengths. */
if (test_bit(0, cpu->sve_vq_init)) {
error_setg(errp, "cannot disable sve128");
error_append_hint(errp, "Disabling sve128 results in all "
"vector lengths being disabled.\n");
error_append_hint(errp, "With SVE enabled, at least one "
"vector length must be enabled.\n");
return;
}
for (vq = 2; vq <= ARM_MAX_VQ; vq <<= 1) {
for (vq = 1; vq <= ARM_MAX_VQ; vq <<= 1) {
if (test_bit(vq - 1, cpu->sve_vq_init)) {
break;
}
}
max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
bitmap_complement(cpu->sve_vq_map, cpu->sve_vq_init, max_vq);
}
max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
bitmap_andnot(cpu->sve_vq_map, cpu->sve_vq_supported,
cpu->sve_vq_init, max_vq);
if (max_vq == 0 || bitmap_empty(cpu->sve_vq_map, max_vq)) {
error_setg(errp, "cannot disable sve%d", vq * 128);
error_append_hint(errp, "Disabling sve%d results in all "
"vector lengths being disabled.\n",
vq * 128);
error_append_hint(errp, "With SVE enabled, at least one "
"vector length must be enabled.\n");
return;
}
max_vq = find_last_bit(cpu->sve_vq_map, max_vq) + 1;
@ -390,46 +384,44 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
assert(max_vq != 0);
bitmap_clear(cpu->sve_vq_map, max_vq, ARM_MAX_VQ - max_vq);
if (kvm_enabled()) {
/* Ensure the set of lengths matches what KVM supports. */
bitmap_xor(tmp, cpu->sve_vq_map, kvm_supported, max_vq);
if (!bitmap_empty(tmp, max_vq)) {
vq = find_last_bit(tmp, max_vq) + 1;
if (test_bit(vq - 1, cpu->sve_vq_map)) {
if (cpu->sve_max_vq) {
error_setg(errp, "cannot set sve-max-vq=%d",
cpu->sve_max_vq);
error_append_hint(errp, "This KVM host does not support "
"the vector length %d-bits.\n",
vq * 128);
error_append_hint(errp, "It may not be possible to use "
"sve-max-vq with this KVM host. Try "
"using only sve<N> properties.\n");
} else {
error_setg(errp, "cannot enable sve%d", vq * 128);
error_append_hint(errp, "This KVM host does not support "
"the vector length %d-bits.\n",
vq * 128);
}
/* Ensure the set of lengths matches what is supported. */
bitmap_xor(tmp, cpu->sve_vq_map, cpu->sve_vq_supported, max_vq);
if (!bitmap_empty(tmp, max_vq)) {
vq = find_last_bit(tmp, max_vq) + 1;
if (test_bit(vq - 1, cpu->sve_vq_map)) {
if (cpu->sve_max_vq) {
error_setg(errp, "cannot set sve-max-vq=%d", cpu->sve_max_vq);
error_append_hint(errp, "This CPU does not support "
"the vector length %d-bits.\n", vq * 128);
error_append_hint(errp, "It may not be possible to use "
"sve-max-vq with this CPU. Try "
"using only sve<N> properties.\n");
} else {
error_setg(errp, "cannot enable sve%d", vq * 128);
error_append_hint(errp, "This CPU does not support "
"the vector length %d-bits.\n", vq * 128);
}
return;
} else {
if (kvm_enabled()) {
error_setg(errp, "cannot disable sve%d", vq * 128);
error_append_hint(errp, "The KVM host requires all "
"supported vector lengths smaller "
"than %d bits to also be enabled.\n",
max_vq * 128);
}
return;
}
} else {
/* Ensure all required powers-of-two are enabled. */
for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
if (!test_bit(vq - 1, cpu->sve_vq_map)) {
error_setg(errp, "cannot disable sve%d", vq * 128);
error_append_hint(errp, "sve%d is required as it "
"is a power-of-two length smaller than "
"the maximum, sve%d\n",
vq * 128, max_vq * 128);
return;
} else {
/* Ensure all required powers-of-two are enabled. */
for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
if (!test_bit(vq - 1, cpu->sve_vq_map)) {
error_setg(errp, "cannot disable sve%d", vq * 128);
error_append_hint(errp, "sve%d is required as it "
"is a power-of-two length smaller "
"than the maximum, sve%d\n",
vq * 128, max_vq * 128);
return;
}
}
}
}
}
@ -840,6 +832,8 @@ static void aarch64_max_initfn(Object *obj)
/* Default to PAUTH on, with the architected algorithm. */
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property);
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
bitmap_fill(cpu->sve_vq_supported, ARM_MAX_VQ);
}
aarch64_add_sve_properties(obj);

View File

@ -2446,20 +2446,34 @@ static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
env->teecr = value;
}
static CPAccessResult teecr_access(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
/*
* HSTR.TTEE only exists in v7A, not v8A, but v8A doesn't have T2EE
* at all, so we don't need to check whether we're v8A.
*/
if (arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) &&
(env->cp15.hstr_el2 & HSTR_TTEE)) {
return CP_ACCESS_TRAP_EL2;
}
return CP_ACCESS_OK;
}
static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
if (arm_current_el(env) == 0 && (env->teecr & 1)) {
return CP_ACCESS_TRAP;
}
return CP_ACCESS_OK;
return teecr_access(env, ri, isread);
}
static const ARMCPRegInfo t2ee_cp_reginfo[] = {
{ .name = "TEECR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 6, .opc2 = 0,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, teecr),
.resetvalue = 0,
.writefn = teecr_write },
.writefn = teecr_write, .accessfn = teecr_access },
{ .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
.access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
.accessfn = teehbr_access, .resetvalue = 0 },
@ -7588,6 +7602,21 @@ static CPAccessResult access_jazelle(CPUARMState *env, const ARMCPRegInfo *ri,
return CP_ACCESS_OK;
}
static CPAccessResult access_joscr_jmcr(CPUARMState *env,
const ARMCPRegInfo *ri, bool isread)
{
/*
* HSTR.TJDBX traps JOSCR and JMCR accesses, but it exists only
* in v7A, not in v8A.
*/
if (!arm_feature(env, ARM_FEATURE_V8) &&
arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) &&
(env->cp15.hstr_el2 & HSTR_TJDBX)) {
return CP_ACCESS_TRAP_EL2;
}
return CP_ACCESS_OK;
}
static const ARMCPRegInfo jazelle_regs[] = {
{ .name = "JIDR",
.cp = 14, .crn = 0, .crm = 0, .opc1 = 7, .opc2 = 0,
@ -7595,9 +7624,11 @@ static const ARMCPRegInfo jazelle_regs[] = {
.type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "JOSCR",
.cp = 14, .crn = 1, .crm = 0, .opc1 = 7, .opc2 = 0,
.accessfn = access_joscr_jmcr,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "JMCR",
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
.accessfn = access_joscr_jmcr,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
REGINFO_SENTINEL
};
@ -9215,6 +9246,8 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
CPSRWriteType write_type)
{
uint32_t changed_daif;
bool rebuild_hflags = (write_type != CPSRWriteRaw) &&
(mask & (CPSR_M | CPSR_E | CPSR_IL));
if (mask & CPSR_NZCV) {
env->ZF = (~val) & CPSR_Z;
@ -9334,6 +9367,9 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
}
mask &= ~CACHED_CPSR_BITS;
env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
if (rebuild_hflags) {
arm_rebuild_hflags(env);
}
}
/* Sign/zero extend */

View File

@ -73,6 +73,8 @@ DEF_HELPER_2(v7m_vlldm, void, env, i32)
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
DEF_HELPER_2(get_cp_reg, i32, env, ptr)

View File

@ -740,7 +740,7 @@ void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map)
uint32_t vq = 0;
int i, j;
bitmap_clear(map, 0, ARM_MAX_VQ);
bitmap_zero(map, ARM_MAX_VQ);
/*
* KVM ensures all host CPUs support the same set of vector lengths.

View File

@ -224,6 +224,22 @@ void HELPER(setend)(CPUARMState *env)
arm_rebuild_hflags(env);
}
void HELPER(check_bxj_trap)(CPUARMState *env, uint32_t rm)
{
/*
* Only called if in NS EL0 or EL1 for a BXJ for a v7A CPU;
* check if HSTR.TJDBX means we need to trap to EL2.
*/
if (env->cp15.hstr_el2 & HSTR_TJDBX) {
/*
* We know the condition code check passed, so take the IMPDEF
* choice to always report CV=1 COND 0xe
*/
uint32_t syn = syn_bxjtrap(1, 0xe, rm);
raise_exception_ra(env, EXCP_HYP_TRAP, syn, 2, GETPC());
}
}
#ifndef CONFIG_USER_ONLY
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
* The function returns the target EL (1-3) if the instruction is to be trapped;

View File

@ -36,6 +36,7 @@ enum arm_exception_class {
EC_ADVSIMDFPACCESSTRAP = 0x07,
EC_FPIDTRAP = 0x08,
EC_PACTRAP = 0x09,
EC_BXJTRAP = 0x0a,
EC_CP14RRTTRAP = 0x0c,
EC_BTITRAP = 0x0d,
EC_ILLEGALSTATE = 0x0e,
@ -215,6 +216,12 @@ static inline uint32_t syn_btitrap(int btype)
return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
}
static inline uint32_t syn_bxjtrap(int cv, int cond, int rm)
{
return (EC_BXJTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL |
(cv << 24) | (cond << 20) | rm;
}
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
{
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)

View File

@ -6440,6 +6440,18 @@ static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
return false;
}
/*
* v7A allows BXJ to be trapped via HSTR.TJDBX. We don't waste a
* TBFLAGS bit on a basically-never-happens case, so call a helper
* function to check for the trap and raise the exception if needed
* (passing it the register number for the syndrome value).
* v8A doesn't have this HSTR bit.
*/
if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
arm_dc_feature(s, ARM_FEATURE_EL2) &&
s->current_el < 2 && s->ns) {
gen_helper_check_bxj_trap(cpu_env, tcg_constant_i32(a->rm));
}
/* Trivial implementation equivalent to bx. */
gen_bx(s, load_reg(s, a->rm));
return true;

View File

@ -22,7 +22,6 @@
#include "disas/dis-asm.h"
#include "exec/gdbstub.h"
#include "kvm_ppc.h"
#include "sysemu/arch_init.h"
#include "sysemu/cpus.h"
#include "sysemu/hw_accel.h"
#include "sysemu/tcg.h"

View File

@ -34,7 +34,6 @@
#include "hw/s390x/pv.h"
#include "hw/boards.h"
#include "sysemu/arch_init.h"
#include "sysemu/sysemu.h"
#include "sysemu/tcg.h"
#include "hw/core/sysemu-cpu-ops.h"

View File

@ -378,7 +378,7 @@ static void test_enable_irq(void)
*/
static void open_socket(void)
{
struct sockaddr_in myaddr;
struct sockaddr_in myaddr = {};
socklen_t addrlen;
myaddr.sin_family = AF_INET;

View File

@ -251,7 +251,7 @@ static void test_time(void)
static int server_socket(void)
{
int val, fd;
struct sockaddr_in sockaddr;
struct sockaddr_in sockaddr = {};
/* server socket */
fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
@ -271,7 +271,7 @@ static int server_socket(void)
static int client_socket(uint16_t port)
{
int fd;
struct sockaddr_in sockaddr;
struct sockaddr_in sockaddr = {};
/* server socket */
fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));