mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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".
|
||||
@@ -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".
|
||||
@@ -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 |
|
||||
+------------------+ | |
|
||||
+-------------------+
|
||||
@@ -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 +---->+ 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 |
|
||||
+------------------+ | |
|
||||
+-------------------+
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
+64
-22
@@ -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[] = {
|
||||
|
||||
+25
-10
@@ -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. */
|
||||
|
||||
+12
-12
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+15
-16
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user