diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-08-26 18:03:57 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-08-26 18:03:57 +0100 |
commit | f214d8e0150766c31172e16ef4b17674f549d852 (patch) | |
tree | bf264f12784e006e52ee326149259ea4940b6ab9 | |
parent | c83fcfaf8a54d0d034bd0edf7bbb3b0d16669be9 (diff) | |
parent | d2e6f370138a7f32bc28b20dcd55374b7a638f39 (diff) |
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>
57 files changed, 949 insertions, 707 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 6b3697962c..dffcb651f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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> diff --git a/blockdev.c b/blockdev.c index 3d8ac368a1..e79c5f3b5e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -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" diff --git a/docs/specs/acpi_cpu_hotplug.rst b/docs/specs/acpi_cpu_hotplug.rst new file mode 100644 index 0000000000..351057c967 --- /dev/null +++ b/docs/specs/acpi_cpu_hotplug.rst @@ -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". diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt deleted file mode 100644 index 9bd59ae0da..0000000000 --- a/docs/specs/acpi_cpu_hotplug.txt +++ /dev/null @@ -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". diff --git a/docs/specs/acpi_mem_hotplug.rst b/docs/specs/acpi_mem_hotplug.rst new file mode 100644 index 0000000000..069819bc3e --- /dev/null +++ b/docs/specs/acpi_mem_hotplug.rst @@ -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 | + +------------------+ | | + +-------------------+ diff --git a/docs/specs/acpi_mem_hotplug.txt b/docs/specs/acpi_mem_hotplug.txt deleted file mode 100644 index 3df3620ce4..0000000000 --- a/docs/specs/acpi_mem_hotplug.txt +++ /dev/null @@ -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 | - +------------------+ | | - +-------------------+ diff --git a/docs/specs/acpi_nvdimm.rst b/docs/specs/acpi_nvdimm.rst new file mode 100644 index 0000000000..ab0335253d --- /dev/null +++ b/docs/specs/acpi_nvdimm.rst @@ -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). diff --git a/docs/specs/acpi_nvdimm.txt b/docs/specs/acpi_nvdimm.txt deleted file mode 100644 index 3ec42ecbce..0000000000 --- a/docs/specs/acpi_nvdimm.txt +++ /dev/null @@ -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). diff --git a/docs/specs/acpi_pci_hotplug.txt b/docs/specs/acpi_pci_hotplug.rst index a839434f31..685bc5c322 100644 --- a/docs/specs/acpi_pci_hotplug.txt +++ b/docs/specs/acpi_pci_hotplug.rst @@ -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. diff --git a/docs/specs/index.rst b/docs/specs/index.rst index b7b08ea30d..65e9663916 100644 --- a/docs/specs/index.rst +++ b/docs/specs/index.rst @@ -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; diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 4ba0aca067..dc050b5c37 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -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 diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index b30a17871f..0ada91c05e 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -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); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 81eda46b0b..86c8a4ca3d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -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 diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fb776834f7..547a26603a 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -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, diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 3597e8db4d..4e5a471e30 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -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[] = { diff --git a/hw/core/loader.c b/hw/core/loader.c index 5b34869a54..c623318b73 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -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. */ diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c index fa38a55634..a5a92b4ff8 100644 --- a/hw/dma/xlnx-zdma.c +++ b/hw/dma/xlnx-zdma.c @@ -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; } diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c index 797b4fed8f..896bb3574d 100644 --- a/hw/dma/xlnx_csu_dma.c +++ b/hw/dma/xlnx_csu_dma.c @@ -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; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index c2b9d62a35..102b223946 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -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" diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 30b8bd6ea9..1bc30167ac 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -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" diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 04b4a4788d..eeb0b185b1 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -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" diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index d6183e1882..f5a26e174d 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -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" diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 7dcf175d72..b770b8d367 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -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" diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index acfc2a91d8..25a2e86b42 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -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" diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index ddc658c8d6..5b7b245e1f 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -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[] = { diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 87bbd10b21..6cc1a62b0f 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -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" diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index fead77f0c4..aae36f2cb4 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -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" diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 4a3cd2599a..0e55411045 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -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" diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 22a8fa5d11..9b79051747 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -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 diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index d3e2ef97f6..c84fe15996 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -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]; diff --git a/include/hw/dma/xlnx-zdma.h b/include/hw/dma/xlnx-zdma.h index 6602e7ffa7..efc75217d5 100644 --- a/include/hw/dma/xlnx-zdma.h +++ b/include/hw/dma/xlnx-zdma.h @@ -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 { diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h index 204d94c673..9e9dc551e9 100644 --- a/include/hw/dma/xlnx_csu_dma.h +++ b/include/hw/dma/xlnx_csu_dma.h @@ -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; diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index e723c467eb..70c579560a 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -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 diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index 32b68ee302..1dfcfd2d57 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -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); diff --git a/meson.build b/meson.build index b3e7ec0e92..bf63784812 100644 --- a/meson.build +++ b/meson.build @@ -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)} diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index f7d64a6457..5c0d5e116b 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -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; } @@ -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 ':' " diff --git a/softmmu/arch_init.c b/softmmu/arch_init.c index 6ff9f30bad..8919405c7b 100644 --- a/softmmu/arch_init.c +++ b/softmmu/arch_init.c @@ -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 -} diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 2e18947598..23e77cb771 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -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); diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 721dec2d82..a304754ab9 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -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 */ diff --git a/softmmu/vl.c b/softmmu/vl.c index 5ca11e7469..82d574fe4b 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -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); } diff --git a/stubs/arch_type.c b/stubs/arch_type.c deleted file mode 100644 index fc5423bc98..0000000000 --- a/stubs/arch_type.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "qemu/osdep.h" -#include "sysemu/arch_init.h" - -const uint32_t arch_type = QEMU_ARCH_NONE; diff --git a/stubs/meson.build b/stubs/meson.build index d3fa8646b3..717bfa9a99 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -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')) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a82e39dd97..d631c4683c 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -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; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 5cf8996ae3..6a987f65e4 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -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); diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index c690318a9b..2f0cbddab5 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -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); diff --git a/target/arm/helper.c b/target/arm/helper.c index 56c520cf8e..a7ae78146d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -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 */ diff --git a/target/arm/helper.h b/target/arm/helper.h index aee8f0019b..448a86edfd 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -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) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 59982d470d..e790d6c9a5 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -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. diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index e98fd86305..70b42b55fd 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -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; diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h index 39a31260f2..8dd88a0cb1 100644 --- a/target/arm/syndrome.h +++ b/target/arm/syndrome.h @@ -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) diff --git a/target/arm/translate.c b/target/arm/translate.c index 115aa768b6..24b7f49d76 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -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; diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 505a0ed6ac..319a272d4c 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -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" diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c index df2c6bf694..5471e01ee8 100644 --- a/target/s390x/cpu-sysemu.c +++ b/target/s390x/cpu-sysemu.c @@ -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" diff --git a/tests/qtest/ipmi-bt-test.c b/tests/qtest/ipmi-bt-test.c index 8492f02a9c..19612e9405 100644 --- a/tests/qtest/ipmi-bt-test.c +++ b/tests/qtest/ipmi-bt-test.c @@ -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; diff --git a/tests/tcg/multiarch/linux-test.c b/tests/tcg/multiarch/linux-test.c index c8c6aeddeb..019d8175ca 100644 --- a/tests/tcg/multiarch/linux-test.c +++ b/tests/tcg/multiarch/linux-test.c @@ -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)); |