target-arm queue:

* Implement ID_PFR2
  * Conditionalize DBGDIDR
  * rename xlnx-zcu102.canbusN properties
  * provide powerdown/reset mechanism for secure firmware on 'virt' board
  * hw/misc: Fix arith overflow in NPCM7XX PWM module
  * target/arm: Replace magic value by MMU_DATA_LOAD definition
  * configure: fix preadv errors on Catalina macOS with new XCode
  * Various configure and other cleanups in preparation for iOS support
  * hvf: Add hypervisor entitlement to output binaries (needed for Big Sur)
  * Implement pvpanic-pci device
  * Convert the CMSDK timer devices to the Clock framework
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmAUMuIZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3m5ED/9uRVa571OwoyAztgS3HN6e
 Yi8ddj/isCB/shsJQn9Z6kOqg6WUejvLMyT3d3ulH81eje5s8s8xcGOkch8r7oV+
 2SAi80b92AdXsuIPqLeyx6dgJr8e/6MAzD8gYaAKEJsIbKWJFMb3O1OjyITrGM0N
 E1F3lLXAut9xxWXgvT+3ES2z+eRxI7gwr6PTDIoCQ5PqQUwqSt8hIn9VCZwaR6l1
 3570Yy0ScfDCgAZmk6tUVaPJ3gz8BEE11Iuq2R5N8YtYO9570dZDuvsH0RLplRr2
 Wns3ReggjySgB9qmL0ZEl7sLkUDKSS8ud9+75V6h69eUXRqdWUylKgEPjQOs9rFw
 lhLp0bz+J9KwC1UoQtUXA+/D9M+1xjj1iVhG4CWJe2p4xn5+gzCPz3RLQxLu4ekZ
 FLAEsph8ftqM9J4a1AsEUf6ghRkG2v/eSKaoBOl5Mq8BOaM+YEZ0T0ZeTQspM9tF
 iTHk22Ld2aX3aHCbXSnEfND+QEzQXgTQvUHXPTYpYAZPjK4PSfkm6CfsAlir71so
 TlxwTeoy94dnK4eQjcAHK9GnvRTt5AEImrmC89xAplMYtgBfGmMiFIDysvmCaedt
 EesNHhh3PAqh7wOiqVa96ALZeAys0LpoBVjzHlmXsfsRgUR+JzxKq3pq0PT1DMcn
 92gWwHt3AAqEn4dZ20KxBw==
 =INlE
 -----END PGP SIGNATURE-----

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

target-arm queue:
 * Implement ID_PFR2
 * Conditionalize DBGDIDR
 * rename xlnx-zcu102.canbusN properties
 * provide powerdown/reset mechanism for secure firmware on 'virt' board
 * hw/misc: Fix arith overflow in NPCM7XX PWM module
 * target/arm: Replace magic value by MMU_DATA_LOAD definition
 * configure: fix preadv errors on Catalina macOS with new XCode
 * Various configure and other cleanups in preparation for iOS support
 * hvf: Add hypervisor entitlement to output binaries (needed for Big Sur)
 * Implement pvpanic-pci device
 * Convert the CMSDK timer devices to the Clock framework

# gpg: Signature made Fri 29 Jan 2021 16:08:02 GMT
# 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-20210129-1: (46 commits)
  hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS
  arm: Remove frq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
  arm: Don't set freq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
  hw/arm/armsse: Use Clock to set system_clock_scale
  tests/qtest/cmsdk-apb-watchdog-test: Test clock changes
  hw/watchdog/cmsdk-apb-watchdog: Convert to use Clock input
  hw/timer/cmsdk-apb-dualtimer: Convert to use Clock input
  hw/timer/cmsdk-apb-timer: Convert to use Clock input
  hw/arm/stellaris: Create Clock input for watchdog
  hw/arm/stellaris: Convert SSYS to QOM device
  hw/arm/musca: Create and connect ARMSSE Clocks
  hw/arm/mps2-tz: Create and connect ARMSSE Clocks
  hw/arm/mps2: Create and connect SYSCLK Clock
  hw/arm/mps2: Inline CMSDK_APB_TIMER creation
  hw/arm/armsse: Wire up clocks
  hw/arm/armsse: Rename "MAINCLK" property to "MAINCLK_FRQ"
  hw/watchdog/cmsdk-apb-watchdog: Add Clock input
  hw/timer/cmsdk-apb-dualtimer: Add Clock input
  hw/timer/cmsdk-apb-timer: Add Clock input
  hw/timer/cmsdk-apb-timer: Rename CMSDKAPBTIMER struct to CMSDKAPBTimer
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-01-29 17:22:52 +00:00
commit 9df52f58e7
52 changed files with 1436 additions and 319 deletions

View File

@ -581,12 +581,15 @@ F: include/hw/rtc/pl031.h
F: include/hw/arm/primecell.h
F: hw/timer/cmsdk-apb-timer.c
F: include/hw/timer/cmsdk-apb-timer.h
F: tests/qtest/cmsdk-apb-timer-test.c
F: hw/timer/cmsdk-apb-dualtimer.c
F: include/hw/timer/cmsdk-apb-dualtimer.h
F: tests/qtest/cmsdk-apb-dualtimer-test.c
F: hw/char/cmsdk-apb-uart.c
F: include/hw/char/cmsdk-apb-uart.h
F: hw/watchdog/cmsdk-apb-watchdog.c
F: include/hw/watchdog/cmsdk-apb-watchdog.h
F: tests/qtest/cmsdk-apb-watchdog-test.c
F: hw/misc/tz-ppc.c
F: include/hw/misc/tz-ppc.h
F: hw/misc/tz-mpc.c

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.hypervisor</key>
<true/>
</dict>
</plist>

78
configure vendored
View File

@ -238,6 +238,7 @@ cpu=""
iasl="iasl"
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
cross_compile="no"
cross_prefix=""
audio_drv_list=""
block_drv_rw_whitelist=""
@ -318,6 +319,7 @@ fdt="auto"
netmap="no"
sdl="auto"
sdl_image="auto"
coreaudio="auto"
virtiofsd="auto"
virtfs="auto"
libudev="auto"
@ -469,6 +471,7 @@ for opt do
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
case "$opt" in
--cross-prefix=*) cross_prefix="$optarg"
cross_compile="yes"
;;
--cc=*) CC="$optarg"
;;
@ -622,13 +625,6 @@ fi
# the correct CPU with the --cpu option.
case $targetos in
Darwin)
# on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
# run 64-bit userspace code.
# If the user didn't specify a CPU explicitly and the kernel says this is
# 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
cpu="x86_64"
fi
HOST_DSOSUF=".dylib"
;;
SunOS)
@ -772,13 +768,8 @@ OpenBSD)
Darwin)
bsd="yes"
darwin="yes"
if [ "$cpu" = "x86_64" ] ; then
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
fi
audio_drv_list="coreaudio try-sdl"
audio_drv_list="try-coreaudio try-sdl"
audio_possible_drivers="coreaudio sdl"
QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS"
# Disable attempts to use ObjectiveC features in os/object.h since they
# won't work when we're compiling with gcc as a C compiler.
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
@ -1691,7 +1682,7 @@ $(echo Deprecated targets: $deprecated_targets_list | \
--target-list-exclude=LIST exclude a set of targets from the default target-list
Advanced options (experts only):
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
--cross-prefix=PREFIX use PREFIX for compile tools, PREFIX can be blank [$cross_prefix]
--cc=CC use C compiler CC [$cc]
--iasl=IASL use ACPI compiler IASL [$iasl]
--host-cc=CC use C compiler CC [$host_cc] for code run at
@ -3145,6 +3136,24 @@ EOF
fi
fi
##########################################
# detect CoreAudio
if test "$coreaudio" != "no" ; then
coreaudio_libs="-framework CoreAudio"
cat > $TMPC << EOF
#include <CoreAudio/CoreAudio.h>
int main(void)
{
return (int)AudioGetCurrentHostTime();
}
EOF
if compile_prog "" "$coreaudio_libs" ; then
coreaudio=yes
else
coreaudio=no
fi
fi
##########################################
# Sound support libraries probe
@ -3201,8 +3210,20 @@ for drv in $audio_drv_list; do
fi
;;
coreaudio)
coreaudio | try-coreaudio)
if test "$coreaudio" = "no"; then
if test "$drv" = "try-coreaudio"; then
audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio//')
else
error_exit "$drv check failed" \
"Make sure to have the $drv is available."
fi
else
coreaudio_libs="-framework CoreAudio"
if test "$drv" = "try-coreaudio"; then
audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio/coreaudio/')
fi
fi
;;
dsound)
@ -3531,19 +3552,6 @@ if compile_prog "" "" ; then
iovec=yes
fi
##########################################
# preadv probe
cat > $TMPC <<EOF
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
int main(void) { return preadv(0, 0, 0, 0); }
EOF
preadv=no
if compile_prog "" "" ; then
preadv=yes
fi
##########################################
# fdt probe
@ -5748,9 +5756,6 @@ fi
if test "$iovec" = "yes" ; then
echo "CONFIG_IOVEC=y" >> $config_host_mak
fi
if test "$preadv" = "yes" ; then
echo "CONFIG_PREADV=y" >> $config_host_mak
fi
if test "$membarrier" = "yes" ; then
echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
fi
@ -6297,6 +6302,7 @@ echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
echo "[binaries]" >> $cross
echo "c = [$(meson_quote $cc)]" >> $cross
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross
test -n "$objcc" && echo "objc = [$(meson_quote $objcc)]" >> $cross
echo "ar = [$(meson_quote $ar)]" >> $cross
echo "nm = [$(meson_quote $nm)]" >> $cross
echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross
@ -6306,7 +6312,7 @@ if has $sdl2_config; then
fi
echo "strip = [$(meson_quote $strip)]" >> $cross
echo "windres = [$(meson_quote $windres)]" >> $cross
if test -n "$cross_prefix"; then
if test "$cross_compile" = "yes"; then
cross_arg="--cross-file config-meson.cross"
echo "[host_machine]" >> $cross
if test "$mingw32" = "yes" ; then
@ -6315,10 +6321,16 @@ if test -n "$cross_prefix"; then
if test "$linux" = "yes" ; then
echo "system = 'linux'" >> $cross
fi
if test "$darwin" = "yes" ; then
echo "system = 'darwin'" >> $cross
fi
case "$ARCH" in
i386|x86_64)
i386)
echo "cpu_family = 'x86'" >> $cross
;;
x86_64)
echo "cpu_family = 'x86_64'" >> $cross
;;
ppc64le)
echo "cpu_family = 'ppc64'" >> $cross
;;

View File

@ -235,6 +235,22 @@ object during device instance init. For example:
/* set initial value to 10ns / 100MHz */
clock_set_ns(clk, 10);
To enforce that the clock is wired up by the board code, you can
call ``clock_has_source()`` in your device's realize method:
.. code-block:: c
if (!clock_has_source(s->clk)) {
error_setg(errp, "MyDevice: clk input must be connected");
return;
}
Note that this only checks that the clock has been wired up; it is
still possible that the output clock connected to it is disabled
or has not yet been configured, in which case the period will be
zero. You should use the clock callback to find out when the clock
period changes.
Fetching clock frequency/period
-------------------------------

View File

@ -64,6 +64,7 @@ PCI devices (other than virtio):
1b36:000d PCI xhci usb host adapter
1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
1b36:0010 PCIe NVMe device (-device nvme)
1b36:0011 PCI PVPanic device (-device pvpanic-pci)
All these devices are documented in docs/specs.

View File

@ -1,7 +1,7 @@
PVPANIC DEVICE
==============
pvpanic device is a simulated ISA device, through which a guest panic
pvpanic device is a simulated device, through which a guest panic
event is sent to qemu, and a QMP event is generated. This allows
management apps (e.g. libvirt) to be notified and respond to the event.
@ -9,6 +9,9 @@ The management app has the option of waiting for GUEST_PANICKED events,
and/or polling for guest-panicked RunState, to learn when the pvpanic
device has fired a panic event.
The pvpanic device can be implemented as an ISA device (using IOPORT) or as a
PCI device.
ISA Interface
-------------
@ -24,6 +27,14 @@ bit 1: a guest panic has happened and will be handled by the guest;
the host should record it or report it, but should not affect
the execution of the guest.
PCI Interface
-------------
The PCI interface is similar to the ISA interface except that it uses an MMIO
address space provided by its BAR0, 1 byte long. Any machine with a PCI bus
can enable a pvpanic device by adding '-device pvpanic-pci' to the command
line.
ACPI Interface
--------------

View File

@ -43,6 +43,8 @@ The virt board supports:
- Secure-World-only devices if the CPU has TrustZone:
- A second PL011 UART
- A second PL061 GPIO controller, with GPIO lines for triggering
a system reset or system poweroff
- A secure flash memory
- 16MB of secure RAM

View File

@ -17,6 +17,7 @@ config ARM_VIRT
select PL011 # UART
select PL031 # RTC
select PL061 # GPIO
select GPIO_PWR
select PLATFORM_BUS
select SMBIOS
select VIRTIO_MMIO

View File

@ -21,6 +21,7 @@
#include "hw/arm/armsse.h"
#include "hw/arm/boot.h"
#include "hw/irq.h"
#include "hw/qdev-clock.h"
/* Format of the System Information block SYS_CONFIG register */
typedef enum SysConfigFormat {
@ -47,7 +48,6 @@ static Property iotkit_properties[] = {
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
@ -59,7 +59,6 @@ static Property armsse_properties[] = {
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
@ -231,6 +230,16 @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
}
static void armsse_mainclk_update(void *opaque)
{
ARMSSE *s = ARM_SSE(opaque);
/*
* Set system_clock_scale from our Clock input; this is what
* controls the tick rate of the CPU SysTick timer.
*/
system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
}
static void armsse_init(Object *obj)
{
ARMSSE *s = ARM_SSE(obj);
@ -241,6 +250,10 @@ static void armsse_init(Object *obj)
assert(info->sram_banks <= MAX_SRAM_BANKS);
assert(info->num_cpus <= SSE_MAX_CPUS);
s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
armsse_mainclk_update, s);
s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
for (i = 0; i < info->num_cpus; i++) {
@ -447,9 +460,11 @@ static void armsse_realize(DeviceState *dev, Error **errp)
return;
}
if (!s->mainclk_frq) {
error_setg(errp, "MAINCLK property was not set");
return;
if (!clock_has_source(s->mainclk)) {
error_setg(errp, "MAINCLK clock was not connected");
}
if (!clock_has_source(s->s32kclk)) {
error_setg(errp, "S32KCLK clock was not connected");
}
assert(info->num_cpus <= SSE_MAX_CPUS);
@ -710,7 +725,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
* it to the appropriate PPC port; then we can realize the PPC and
* map its upstream ends to the right place in the container.
*/
qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
return;
}
@ -720,7 +735,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
&error_abort);
qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
return;
}
@ -730,7 +745,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
&error_abort);
qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
return;
}
@ -888,7 +903,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
/* Devices behind APB PPC1:
* 0x4002f000: S32K timer
*/
qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
return;
}
@ -981,7 +996,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
return;
}
@ -991,7 +1006,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
return;
}
@ -999,7 +1014,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
armsse_get_common_irq_in(s, 1));
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
return;
}
@ -1104,7 +1119,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
*/
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
/* Set initial system_clock_scale from MAINCLK */
armsse_mainclk_update(s);
}
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
@ -1127,9 +1143,11 @@ static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
static const VMStateDescription armsse_vmstate = {
.name = "iotkit",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_CLOCK(mainclk, ARMSSE),
VMSTATE_CLOCK(s32kclk, ARMSSE),
VMSTATE_UINT32(nsccfg, ARMSSE),
VMSTATE_END_OF_LIST()
}

View File

@ -62,6 +62,7 @@
#include "hw/net/lan9118.h"
#include "net/net.h"
#include "hw/core/split-irq.h"
#include "hw/qdev-clock.h"
#include "qom/object.h"
#define MPS2TZ_NUMIRQ 92
@ -100,6 +101,8 @@ struct MPS2TZMachineState {
qemu_or_irq uart_irq_orgate;
DeviceState *lan9118;
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
Clock *sysclk;
Clock *s32kclk;
};
#define TYPE_MPS2TZ_MACHINE "mps2tz"
@ -110,6 +113,8 @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
/* Main SYSCLK frequency in Hz */
#define SYSCLK_FRQ 20000000
/* Slow 32Khz S32KCLK frequency in Hz */
#define S32KCLK_FRQ (32 * 1000)
/* Create an alias of an entire original MemoryRegion @orig
* located at @base in the memory map.
@ -396,13 +401,20 @@ static void mps2tz_common_init(MachineState *machine)
exit(EXIT_FAILURE);
}
/* These clocks don't need migration because they are fixed-frequency */
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
mmc->armsse_type);
iotkitdev = DEVICE(&mms->iotkit);
object_property_set_link(OBJECT(&mms->iotkit), "memory",
OBJECT(system_memory), &error_abort);
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
/*

View File

@ -46,6 +46,7 @@
#include "hw/net/lan9118.h"
#include "net/net.h"
#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "hw/qdev-clock.h"
#include "qom/object.h"
typedef enum MPS2FPGAType {
@ -83,6 +84,8 @@ struct MPS2MachineState {
/* CMSDK APB subsystem */
CMSDKAPBDualTimer dualtimer;
CMSDKAPBWatchdog watchdog;
CMSDKAPBTimer timer[2];
Clock *sysclk;
};
#define TYPE_MPS2_MACHINE "mps2"
@ -139,6 +142,10 @@ static void mps2_common_init(MachineState *machine)
exit(EXIT_FAILURE);
}
/* This clock doesn't need migration because it is fixed-frequency */
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
/* The FPGA images have an odd combination of different RAMs,
* because in hardware they are different implementations and
* connected to different buses, giving varying performance/size
@ -330,18 +337,31 @@ static void mps2_common_init(MachineState *machine)
}
/* CMSDK APB subsystem */
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
for (i = 0; i < ARRAY_SIZE(mms->timer); i++) {
g_autofree char *name = g_strdup_printf("timer%d", i);
hwaddr base = 0x40000000 + i * 0x1000;
int irqno = 8 + i;
SysBusDevice *sbd;
object_initialize_child(OBJECT(mms), name, &mms->timer[i],
TYPE_CMSDK_APB_TIMER);
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
sysbus_realize_and_unref(sbd, &error_fatal);
sysbus_mmio_map(sbd, 0, base);
sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
}
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
TYPE_CMSDK_APB_DUALTIMER);
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
qdev_get_gpio_in(armv7m, 10));
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
TYPE_CMSDK_APB_WATCHDOG);
qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
qdev_get_gpio_in_named(armv7m, "NMI", 0));

View File

@ -33,6 +33,7 @@
#include "hw/misc/tz-ppc.h"
#include "hw/misc/unimp.h"
#include "hw/rtc/pl031.h"
#include "hw/qdev-clock.h"
#include "qom/object.h"
#define MUSCA_NUMIRQ_MAX 96
@ -82,6 +83,8 @@ struct MuscaMachineState {
UnimplementedDeviceState sdio;
UnimplementedDeviceState gpio;
UnimplementedDeviceState cryptoisland;
Clock *sysclk;
Clock *s32kclk;
};
#define TYPE_MUSCA_MACHINE "musca"
@ -96,6 +99,8 @@ OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE)
* don't model that in our SSE-200 model yet.
*/
#define SYSCLK_FRQ 40000000
/* Slow 32Khz S32KCLK frequency in Hz */
#define S32KCLK_FRQ (32 * 1000)
static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
{
@ -367,6 +372,11 @@ static void musca_init(MachineState *machine)
exit(1);
}
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
object_initialize_child(OBJECT(machine), "sse-200", &mms->sse,
TYPE_SSE200);
ssedev = DEVICE(&mms->sse);
@ -375,7 +385,8 @@ static void musca_init(MachineState *machine)
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
/*
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.

View File

@ -26,6 +26,7 @@
#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "migration/vmstate.h"
#include "hw/misc/unimp.h"
#include "hw/qdev-clock.h"
#include "cpu.h"
#include "qom/object.h"
@ -357,7 +358,12 @@ static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
/* System controller. */
typedef struct {
#define TYPE_STELLARIS_SYS "stellaris-sys"
OBJECT_DECLARE_SIMPLE_TYPE(ssys_state, STELLARIS_SYS)
struct ssys_state {
SysBusDevice parent_obj;
MemoryRegion iomem;
uint32_t pborctl;
uint32_t ldopctl;
@ -371,11 +377,19 @@ typedef struct {
uint32_t dcgc[3];
uint32_t clkvclr;
uint32_t ldoarst;
qemu_irq irq;
Clock *sysclk;
/* Properties (all read-only registers) */
uint32_t user0;
uint32_t user1;
qemu_irq irq;
stellaris_board_info *board;
} ssys_state;
uint32_t did0;
uint32_t did1;
uint32_t dc0;
uint32_t dc1;
uint32_t dc2;
uint32_t dc3;
uint32_t dc4;
};
static void ssys_update(ssys_state *s)
{
@ -430,7 +444,7 @@ static uint32_t pllcfg_fury[16] = {
static int ssys_board_class(const ssys_state *s)
{
uint32_t did0 = s->board->did0;
uint32_t did0 = s->did0;
switch (did0 & DID0_VER_MASK) {
case DID0_VER_0:
return DID0_CLASS_SANDSTORM;
@ -456,19 +470,19 @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
switch (offset) {
case 0x000: /* DID0 */
return s->board->did0;
return s->did0;
case 0x004: /* DID1 */
return s->board->did1;
return s->did1;
case 0x008: /* DC0 */
return s->board->dc0;
return s->dc0;
case 0x010: /* DC1 */
return s->board->dc1;
return s->dc1;
case 0x014: /* DC2 */
return s->board->dc2;
return s->dc2;
case 0x018: /* DC3 */
return s->board->dc3;
return s->dc3;
case 0x01c: /* DC4 */
return s->board->dc4;
return s->dc4;
case 0x030: /* PBORCTL */
return s->pborctl;
case 0x034: /* LDOPCTL */
@ -543,15 +557,26 @@ static bool ssys_use_rcc2(ssys_state *s)
}
/*
* Caculate the sys. clock period in ms.
* Calculate the system clock period. We only want to propagate
* this change to the rest of the system if we're not being called
* from migration post-load.
*/
static void ssys_calculate_system_clock(ssys_state *s)
static void ssys_calculate_system_clock(ssys_state *s, bool propagate_clock)
{
/*
* SYSDIV field specifies divisor: 0 == /1, 1 == /2, etc. Input
* clock is 200MHz, which is a period of 5 ns. Dividing the clock
* frequency by X is the same as multiplying the period by X.
*/
if (ssys_use_rcc2(s)) {
system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
} else {
system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
}
clock_set_ns(s->sysclk, system_clock_scale);
if (propagate_clock) {
clock_propagate(s->sysclk);
}
}
static void ssys_write(void *opaque, hwaddr offset,
@ -586,7 +611,7 @@ static void ssys_write(void *opaque, hwaddr offset,
s->int_status |= (1 << 6);
}
s->rcc = value;
ssys_calculate_system_clock(s);
ssys_calculate_system_clock(s, true);
break;
case 0x070: /* RCC2 */
if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
@ -598,7 +623,7 @@ static void ssys_write(void *opaque, hwaddr offset,
s->int_status |= (1 << 6);
}
s->rcc2 = value;
ssys_calculate_system_clock(s);
ssys_calculate_system_clock(s, true);
break;
case 0x100: /* RCGC0 */
s->rcgc[0] = value;
@ -646,9 +671,9 @@ static const MemoryRegionOps ssys_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void ssys_reset(void *opaque)
static void stellaris_sys_reset_enter(Object *obj, ResetType type)
{
ssys_state *s = (ssys_state *)opaque;
ssys_state *s = STELLARIS_SYS(obj);
s->pborctl = 0x7ffd;
s->rcc = 0x078e3ac0;
@ -661,14 +686,25 @@ static void ssys_reset(void *opaque)
s->rcgc[0] = 1;
s->scgc[0] = 1;
s->dcgc[0] = 1;
ssys_calculate_system_clock(s);
}
static void stellaris_sys_reset_hold(Object *obj)
{
ssys_state *s = STELLARIS_SYS(obj);
/* OK to propagate clocks from the hold phase */
ssys_calculate_system_clock(s, true);
}
static void stellaris_sys_reset_exit(Object *obj)
{
}
static int stellaris_sys_post_load(void *opaque, int version_id)
{
ssys_state *s = opaque;
ssys_calculate_system_clock(s);
ssys_calculate_system_clock(s, false);
return 0;
}
@ -691,30 +727,61 @@ static const VMStateDescription vmstate_stellaris_sys = {
VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
VMSTATE_UINT32(clkvclr, ssys_state),
VMSTATE_UINT32(ldoarst, ssys_state),
/* No field for sysclk -- handled in post-load instead */
VMSTATE_END_OF_LIST()
}
};
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
stellaris_board_info * board,
uint8_t *macaddr)
static Property stellaris_sys_properties[] = {
DEFINE_PROP_UINT32("user0", ssys_state, user0, 0),
DEFINE_PROP_UINT32("user1", ssys_state, user1, 0),
DEFINE_PROP_UINT32("did0", ssys_state, did0, 0),
DEFINE_PROP_UINT32("did1", ssys_state, did1, 0),
DEFINE_PROP_UINT32("dc0", ssys_state, dc0, 0),
DEFINE_PROP_UINT32("dc1", ssys_state, dc1, 0),
DEFINE_PROP_UINT32("dc2", ssys_state, dc2, 0),
DEFINE_PROP_UINT32("dc3", ssys_state, dc3, 0),
DEFINE_PROP_UINT32("dc4", ssys_state, dc4, 0),
DEFINE_PROP_END_OF_LIST()
};
static void stellaris_sys_instance_init(Object *obj)
{
ssys_state *s;
ssys_state *s = STELLARIS_SYS(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
s = g_new0(ssys_state, 1);
s->irq = irq;
s->board = board;
/* Most devices come preprogrammed with a MAC address in the user data. */
s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000);
memory_region_add_subregion(get_system_memory(), base, &s->iomem);
ssys_reset(s);
vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_stellaris_sys, s);
return 0;
memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
}
static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
stellaris_board_info *board,
uint8_t *macaddr)
{
DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
/* Most devices come preprogrammed with a MAC address in the user data. */
qdev_prop_set_uint32(dev, "user0",
macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
qdev_prop_set_uint32(dev, "user1",
macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
qdev_prop_set_uint32(dev, "did0", board->did0);
qdev_prop_set_uint32(dev, "did1", board->did1);
qdev_prop_set_uint32(dev, "dc0", board->dc0);
qdev_prop_set_uint32(dev, "dc1", board->dc1);
qdev_prop_set_uint32(dev, "dc2", board->dc2);
qdev_prop_set_uint32(dev, "dc3", board->dc3);
qdev_prop_set_uint32(dev, "dc4", board->dc4);
sysbus_realize_and_unref(sbd, &error_fatal);
sysbus_mmio_map(sbd, 0, base);
sysbus_connect_irq(sbd, 0, irq);
return dev;
}
/* I2C controller. */
@ -1280,6 +1347,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
int flash_size;
I2CBus *i2c;
DeviceState *dev;
DeviceState *ssys_dev;
int i;
int j;
@ -1330,16 +1398,15 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
}
}
stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
board, nd_table[0].macaddr.a);
ssys_dev = stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
board, nd_table[0].macaddr.a);
if (board->dc1 & (1 << 3)) { /* watchdog present */
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
/* system_clock_scale is valid now */
uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
qdev_connect_clock_in(dev, "WDOGCLK",
qdev_get_clock_out(ssys_dev, "SYSCLK"));
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev),
@ -1553,11 +1620,32 @@ static const TypeInfo stellaris_adc_info = {
.class_init = stellaris_adc_class_init,
};
static void stellaris_sys_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
dc->vmsd = &vmstate_stellaris_sys;
rc->phases.enter = stellaris_sys_reset_enter;
rc->phases.hold = stellaris_sys_reset_hold;
rc->phases.exit = stellaris_sys_reset_exit;
device_class_set_props(dc, stellaris_sys_properties);
}
static const TypeInfo stellaris_sys_info = {
.name = TYPE_STELLARIS_SYS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ssys_state),
.instance_init = stellaris_sys_instance_init,
.class_init = stellaris_sys_class_init,
};
static void stellaris_register_types(void)
{
type_register_static(&stellaris_i2c_info);
type_register_static(&stellaris_gptm_info);
type_register_static(&stellaris_adc_info);
type_register_static(&stellaris_sys_info);
}
type_init(stellaris_register_types)

View File

@ -153,6 +153,7 @@ static const MemMapEntry base_memmap[] = {
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
@ -820,17 +821,80 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
}
}
static void create_gpio(const VirtMachineState *vms)
static void create_gpio_keys(const VirtMachineState *vms,
DeviceState *pl061_dev,
uint32_t phandle)
{
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
qdev_get_gpio_in(pl061_dev, 3));
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
"label", "GPIO Key Poweroff");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
KEY_POWER);
qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
"gpios", phandle, 3, 0);
}
#define SECURE_GPIO_POWEROFF 0
#define SECURE_GPIO_RESET 1
static void create_secure_gpio_pwr(const VirtMachineState *vms,
DeviceState *pl061_dev,
uint32_t phandle)
{
DeviceState *gpio_pwr_dev;
/* gpio-pwr */
gpio_pwr_dev = sysbus_create_simple("gpio-pwr", -1, NULL);
/* connect secure pl061 to gpio-pwr */
qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_RESET,
qdev_get_gpio_in_named(gpio_pwr_dev, "reset", 0));
qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF,
qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible",
"gpio-poweroff");
qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff",
"gpios", phandle, SECURE_GPIO_POWEROFF, 0);
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status",
"okay");
qemu_fdt_add_subnode(vms->fdt, "/gpio-restart");
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible",
"gpio-restart");
qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart",
"gpios", phandle, SECURE_GPIO_RESET, 0);
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status",
"okay");
}
static void create_gpio_devices(const VirtMachineState *vms, int gpio,
MemoryRegion *mem)
{
char *nodename;
DeviceState *pl061_dev;
hwaddr base = vms->memmap[VIRT_GPIO].base;
hwaddr size = vms->memmap[VIRT_GPIO].size;
int irq = vms->irqmap[VIRT_GPIO];
hwaddr base = vms->memmap[gpio].base;
hwaddr size = vms->memmap[gpio].size;
int irq = vms->irqmap[gpio];
const char compat[] = "arm,pl061\0arm,primecell";
SysBusDevice *s;
pl061_dev = sysbus_create_simple("pl061", base,
qdev_get_gpio_in(vms->gic, irq));
pl061_dev = qdev_new("pl061");
s = SYS_BUS_DEVICE(pl061_dev);
sysbus_realize_and_unref(s, &error_fatal);
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
@ -847,21 +911,19 @@ static void create_gpio(const VirtMachineState *vms)
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
qdev_get_gpio_in(pl061_dev, 3));
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
"label", "GPIO Key Poweroff");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
KEY_POWER);
qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
"gpios", phandle, 3, 0);
if (gpio != VIRT_GPIO) {
/* Mark as not usable by the normal world */
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
}
g_free(nodename);
/* Child gpio devices */
if (gpio == VIRT_GPIO) {
create_gpio_keys(vms, pl061_dev, phandle);
} else {
create_secure_gpio_pwr(vms, pl061_dev, phandle);
}
}
static void create_virtio_devices(const VirtMachineState *vms)
@ -1990,7 +2052,11 @@ static void machvirt_init(MachineState *machine)
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
vms->acpi_dev = create_acpi_ged(vms);
} else {
create_gpio(vms);
create_gpio_devices(vms, VIRT_GPIO, sysmem);
}
if (vms->secure && !vmc->no_secure_gpio) {
create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem);
}
/* connect powerdown request */
@ -2608,8 +2674,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 0)
static void virt_machine_5_2_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
virt_machine_6_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
vmc->no_secure_gpio = true;
}
DEFINE_VIRT_MACHINE(5, 2)

View File

@ -219,12 +219,12 @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
s->secure = false;
/* Default to virt (EL2) being disabled */
s->virt = false;
object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
(Object **)&s->canbus[0],
object_property_allow_set_link,
0);
object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
(Object **)&s->canbus[1],
object_property_allow_set_link,
0);

View File

@ -15,6 +15,7 @@
#include "sysemu/qtest.h"
#include "block/aio.h"
#include "sysemu/cpus.h"
#include "hw/clock.h"
#define DELTA_ADJUST 1
#define DELTA_NO_ADJUST -1
@ -348,6 +349,39 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
}
}
/* Set counter increment interval from a Clock */
void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clk,
unsigned int divisor)
{
/*
* The raw clock period is a 64-bit value in units of 2^-32 ns;
* put another way it's a 32.32 fixed-point ns value. Our internal
* representation of the period is 64.32 fixed point ns, so
* the conversion is simple.
*/
uint64_t raw_period = clock_get(clk);
uint64_t period_frac;
assert(s->in_transaction);
s->delta = ptimer_get_count(s);
s->period = extract64(raw_period, 32, 32);
period_frac = extract64(raw_period, 0, 32);
/*
* divisor specifies a possible frequency divisor between the
* clock and the timer, so it is a multiplier on the period.
* We do the multiply after splitting the raw period out into
* period and frac to avoid having to do a 32*64->96 multiply.
*/
s->period *= divisor;
period_frac *= divisor;
s->period += extract64(period_frac, 32, 32);
s->period_frac = (uint32_t)period_frac;
if (s->enabled) {
s->need_reload = true;
}
}
/* Set counter frequency in Hz. */
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
{

View File

@ -8,5 +8,8 @@ config PL061
config GPIO_KEY
bool
config GPIO_PWR
bool
config SIFIVE_GPIO
bool

70
hw/gpio/gpio_pwr.c Normal file
View File

@ -0,0 +1,70 @@
/*
* GPIO qemu power controller
*
* Copyright (c) 2020 Linaro Limited
*
* Author: Maxim Uvarov <maxim.uvarov@linaro.org>
*
* Virtual gpio driver which can be used on top of pl061
* to reboot and shutdown qemu virtual machine. One of use
* case is gpio driver for secure world application (ARM
* Trusted Firmware.).
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/*
* QEMU interface:
* two named input GPIO lines:
* 'reset' : when asserted, trigger system reset
* 'shutdown' : when asserted, trigger system shutdown
*/
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/runstate.h"
#define TYPE_GPIOPWR "gpio-pwr"
OBJECT_DECLARE_SIMPLE_TYPE(GPIO_PWR_State, GPIOPWR)
struct GPIO_PWR_State {
SysBusDevice parent_obj;
};
static void gpio_pwr_reset(void *opaque, int n, int level)
{
if (level) {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
}
static void gpio_pwr_shutdown(void *opaque, int n, int level)
{
if (level) {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
}
}
static void gpio_pwr_init(Object *obj)
{
DeviceState *dev = DEVICE(obj);
qdev_init_gpio_in_named(dev, gpio_pwr_reset, "reset", 1);
qdev_init_gpio_in_named(dev, gpio_pwr_shutdown, "shutdown", 1);
}
static const TypeInfo gpio_pwr_info = {
.name = TYPE_GPIOPWR,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(GPIO_PWR_State),
.instance_init = gpio_pwr_init,
};
static void gpio_pwr_register_types(void)
{
type_register_static(&gpio_pwr_info);
}
type_init(gpio_pwr_register_types)

View File

@ -1,5 +1,6 @@
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))

View File

@ -14,7 +14,7 @@ config PC
imply ISA_DEBUG
imply PARALLEL
imply PCI_DEVICES
imply PVPANIC
imply PVPANIC_ISA
imply QXL
imply SEV
imply SGA

View File

@ -121,9 +121,19 @@ config IOTKIT_SYSCTL
config IOTKIT_SYSINFO
bool
config PVPANIC
config PVPANIC_COMMON
bool
config PVPANIC_PCI
bool
default y if PCI_DEVICES
depends on PCI
select PVPANIC_COMMON
config PVPANIC_ISA
bool
depends on ISA_BUS
select PVPANIC_COMMON
config AUX
bool

View File

@ -13,6 +13,7 @@ softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c'))
softmmu_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c'))
# ARM devices
softmmu_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c'))
@ -98,7 +99,8 @@ softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c')
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
softmmu_ss.add(when: 'CONFIG_PVPANIC', if_true: files('pvpanic.c'))
softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))

View File

@ -58,6 +58,9 @@ REG32(NPCM7XX_PWM_PWDR3, 0x50);
#define NPCM7XX_CH_INV BIT(2)
#define NPCM7XX_CH_MOD BIT(3)
#define NPCM7XX_MAX_CMR 65535
#define NPCM7XX_MAX_CNR 65535
/* Offset of each PWM channel's prescaler in the PPR register. */
static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
/* Offset of each PWM channel's clock selector in the CSR register. */
@ -96,7 +99,7 @@ static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
{
uint64_t duty;
uint32_t duty;
if (p->running) {
if (p->cnr == 0) {
@ -104,7 +107,7 @@ static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
} else if (p->cmr >= p->cnr) {
duty = NPCM7XX_PWM_MAX_DUTY;
} else {
duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
}
} else {
duty = 0;
@ -357,7 +360,13 @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
case A_NPCM7XX_PWM_CNR2:
case A_NPCM7XX_PWM_CNR3:
p = &s->pwm[npcm7xx_cnr_index(offset)];
p->cnr = value;
if (value > NPCM7XX_MAX_CNR) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid cnr value: %u", __func__, value);
p->cnr = NPCM7XX_MAX_CNR;
} else {
p->cnr = value;
}
npcm7xx_pwm_update_output(p);
break;
@ -366,7 +375,13 @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
case A_NPCM7XX_PWM_CMR2:
case A_NPCM7XX_PWM_CMR3:
p = &s->pwm[npcm7xx_cmr_index(offset)];
p->cmr = value;
if (value > NPCM7XX_MAX_CMR) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid cmr value: %u", __func__, value);
p->cmr = NPCM7XX_MAX_CMR;
} else {
p->cmr = value;
}
npcm7xx_pwm_update_output(p);
break;

94
hw/misc/pvpanic-isa.c Normal file
View File

@ -0,0 +1,94 @@
/*
* QEMU simulated pvpanic device.
*
* Copyright Fujitsu, Corp. 2013
*
* Authors:
* Wen Congyang <wency@cn.fujitsu.com>
* Hu Tao <hutao@cn.fujitsu.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "sysemu/runstate.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/qdev-properties.h"
#include "hw/misc/pvpanic.h"
#include "qom/object.h"
#include "hw/isa/isa.h"
OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE)
/*
* PVPanicISAState for ISA device and
* use ioport.
*/
struct PVPanicISAState {
ISADevice parent_obj;
uint16_t ioport;
PVPanicState pvpanic;
};
static void pvpanic_isa_initfn(Object *obj)
{
PVPanicISAState *s = PVPANIC_ISA_DEVICE(obj);
pvpanic_setup_io(&s->pvpanic, DEVICE(s), 1);
}
static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
{
ISADevice *d = ISA_DEVICE(dev);
PVPanicISAState *s = PVPANIC_ISA_DEVICE(dev);
PVPanicState *ps = &s->pvpanic;
FWCfgState *fw_cfg = fw_cfg_find();
uint16_t *pvpanic_port;
if (!fw_cfg) {
return;
}
pvpanic_port = g_malloc(sizeof(*pvpanic_port));
*pvpanic_port = cpu_to_le16(s->ioport);
fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
sizeof(*pvpanic_port));
isa_register_ioport(d, &ps->mr, s->ioport);
}
static Property pvpanic_isa_properties[] = {
DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505),
DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
DEFINE_PROP_END_OF_LIST(),
};
static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pvpanic_isa_realizefn;
device_class_set_props(dc, pvpanic_isa_properties);
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static TypeInfo pvpanic_isa_info = {
.name = TYPE_PVPANIC_ISA_DEVICE,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(PVPanicISAState),
.instance_init = pvpanic_isa_initfn,
.class_init = pvpanic_isa_class_init,
};
static void pvpanic_register_types(void)
{
type_register_static(&pvpanic_isa_info);
}
type_init(pvpanic_register_types)

94
hw/misc/pvpanic-pci.c Normal file
View File

@ -0,0 +1,94 @@
/*
* QEMU simulated PCI pvpanic device.
*
* Copyright (C) 2020 Oracle
*
* Authors:
* Mihai Carabas <mihai.carabas@oracle.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "sysemu/runstate.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "hw/misc/pvpanic.h"
#include "qom/object.h"
#include "hw/pci/pci.h"
OBJECT_DECLARE_SIMPLE_TYPE(PVPanicPCIState, PVPANIC_PCI_DEVICE)
/*
* PVPanicPCIState for PCI device
*/
typedef struct PVPanicPCIState {
PCIDevice dev;
PVPanicState pvpanic;
} PVPanicPCIState;
static const VMStateDescription vmstate_pvpanic_pci = {
.name = "pvpanic-pci",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(dev, PVPanicPCIState),
VMSTATE_END_OF_LIST()
}
};
static void pvpanic_pci_realizefn(PCIDevice *dev, Error **errp)
{
PVPanicPCIState *s = PVPANIC_PCI_DEVICE(dev);
PVPanicState *ps = &s->pvpanic;
pvpanic_setup_io(&s->pvpanic, DEVICE(s), 2);
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &ps->mr);
}
static Property pvpanic_pci_properties[] = {
DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
DEFINE_PROP_END_OF_LIST(),
};
static void pvpanic_pci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
device_class_set_props(dc, pvpanic_pci_properties);
pc->realize = pvpanic_pci_realizefn;
pc->vendor_id = PCI_VENDOR_ID_REDHAT;
pc->device_id = PCI_DEVICE_ID_REDHAT_PVPANIC;
pc->revision = 1;
pc->class_id = PCI_CLASS_SYSTEM_OTHER;
dc->vmsd = &vmstate_pvpanic_pci;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static TypeInfo pvpanic_pci_info = {
.name = TYPE_PVPANIC_PCI_DEVICE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PVPanicPCIState),
.class_init = pvpanic_pci_class_init,
.interfaces = (InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
{ }
}
};
static void pvpanic_register_types(void)
{
type_register_static(&pvpanic_pci_info);
}
type_init(pvpanic_register_types);

View File

@ -22,18 +22,6 @@
#include "hw/misc/pvpanic.h"
#include "qom/object.h"
/* The bit of supported pv event, TODO: include uapi header and remove this */
#define PVPANIC_F_PANICKED 0
#define PVPANIC_F_CRASHLOADED 1
/* The pv event value */
#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
typedef struct PVPanicState PVPanicState;
DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE,
TYPE_PVPANIC)
static void handle_event(int event)
{
static bool logged;
@ -54,90 +42,29 @@ static void handle_event(int event)
}
}
#include "hw/isa/isa.h"
struct PVPanicState {
ISADevice parent_obj;
MemoryRegion io;
uint16_t ioport;
uint8_t events;
};
/* return supported events on read */
static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
static uint64_t pvpanic_read(void *opaque, hwaddr addr, unsigned size)
{
PVPanicState *pvp = opaque;
return pvp->events;
}
static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
static void pvpanic_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
handle_event(val);
}
static const MemoryRegionOps pvpanic_ops = {
.read = pvpanic_ioport_read,
.write = pvpanic_ioport_write,
.read = pvpanic_read,
.write = pvpanic_write,
.impl = {
.min_access_size = 1,
.max_access_size = 1,
},
};
static void pvpanic_isa_initfn(Object *obj)
void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size)
{
PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
memory_region_init_io(&s->mr, OBJECT(dev), &pvpanic_ops, s, "pvpanic", size);
}
static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
{
ISADevice *d = ISA_DEVICE(dev);
PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
FWCfgState *fw_cfg = fw_cfg_find();
uint16_t *pvpanic_port;
if (!fw_cfg) {
return;
}
pvpanic_port = g_malloc(sizeof(*pvpanic_port));
*pvpanic_port = cpu_to_le16(s->ioport);
fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
sizeof(*pvpanic_port));
isa_register_ioport(d, &s->io, s->ioport);
}
static Property pvpanic_isa_properties[] = {
DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
DEFINE_PROP_UINT8("events", PVPanicState, events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
DEFINE_PROP_END_OF_LIST(),
};
static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pvpanic_isa_realizefn;
device_class_set_props(dc, pvpanic_isa_properties);
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static TypeInfo pvpanic_isa_info = {
.name = TYPE_PVPANIC,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(PVPanicState),
.instance_init = pvpanic_isa_initfn,
.class_init = pvpanic_isa_class_init,
};
static void pvpanic_register_types(void)
{
type_register_static(&pvpanic_isa_info);
}
type_init(pvpanic_register_types)

View File

@ -25,6 +25,7 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/registerfields.h"
#include "hw/qdev-clock.h"
#include "hw/timer/cmsdk-apb-dualtimer.h"
#include "migration/vmstate.h"
@ -105,6 +106,22 @@ static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
qemu_set_irq(s->timerintc, timintc);
}
static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
{
/* Return the divisor set by the current CONTROL.PRESCALE value */
switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
case 0:
return 1;
case 1:
return 16;
case 2:
case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
return 256;
default:
g_assert_not_reached();
}
}
static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
uint32_t newctrl)
{
@ -145,7 +162,7 @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
default:
g_assert_not_reached();
}
ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
}
if (changed & R_CONTROL_MODE_MASK) {
@ -413,7 +430,8 @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
* limit must both be set to 0xffff, so we wrap at 16 bits.
*/
ptimer_set_limit(m->timer, 0xffff, 1);
ptimer_set_freq(m->timer, m->parent->pclk_frq);
ptimer_set_period_from_clock(m->timer, m->parent->timclk,
cmsdk_dualtimermod_divisor(m));
ptimer_transaction_commit(m->timer);
}
@ -431,6 +449,20 @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
s->timeritop = 0;
}
static void cmsdk_apb_dualtimer_clk_update(void *opaque)
{
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
int i;
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
CMSDKAPBDualTimerModule *m = &s->timermod[i];
ptimer_transaction_begin(m->timer);
ptimer_set_period_from_clock(m->timer, m->parent->timclk,
cmsdk_dualtimermod_divisor(m));
ptimer_transaction_commit(m->timer);
}
}
static void cmsdk_apb_dualtimer_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@ -445,6 +477,8 @@ static void cmsdk_apb_dualtimer_init(Object *obj)
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
sysbus_init_irq(sbd, &s->timermod[i].timerint);
}
s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
cmsdk_apb_dualtimer_clk_update, s);
}
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
@ -452,8 +486,8 @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
int i;
if (s->pclk_frq == 0) {
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
if (!clock_has_source(s->timclk)) {
error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
return;
}
@ -485,9 +519,10 @@ static const VMStateDescription cmsdk_dualtimermod_vmstate = {
static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
.name = "cmsdk-apb-dualtimer",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_CLOCK(timclk, CMSDKAPBDualTimer),
VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
CMSDK_APB_DUALTIMER_NUM_MODULES,
1, cmsdk_dualtimermod_vmstate,
@ -498,11 +533,6 @@ static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
}
};
static Property cmsdk_apb_dualtimer_properties[] = {
DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -510,7 +540,6 @@ static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
dc->realize = cmsdk_apb_dualtimer_realize;
dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
dc->reset = cmsdk_apb_dualtimer_reset;
device_class_set_props(dc, cmsdk_apb_dualtimer_properties);
}
static const TypeInfo cmsdk_apb_dualtimer_info = {

View File

@ -35,6 +35,7 @@
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/registerfields.h"
#include "hw/qdev-clock.h"
#include "hw/timer/cmsdk-apb-timer.h"
#include "migration/vmstate.h"
@ -67,14 +68,14 @@ static const int timer_id[] = {
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s)
static void cmsdk_apb_timer_update(CMSDKAPBTimer *s)
{
qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK));
}
static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
{
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
uint64_t r;
switch (offset) {
@ -106,7 +107,7 @@ static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
trace_cmsdk_apb_timer_write(offset, value, size);
@ -181,7 +182,7 @@ static const MemoryRegionOps cmsdk_apb_timer_ops = {
static void cmsdk_apb_timer_tick(void *opaque)
{
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
if (s->ctrl & R_CTRL_IRQEN_MASK) {
s->intstatus |= R_INTSTATUS_IRQ_MASK;
@ -191,7 +192,7 @@ static void cmsdk_apb_timer_tick(void *opaque)
static void cmsdk_apb_timer_reset(DeviceState *dev)
{
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
trace_cmsdk_apb_timer_reset();
s->ctrl = 0;
@ -203,23 +204,34 @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
ptimer_transaction_commit(s->timer);
}
static void cmsdk_apb_timer_clk_update(void *opaque)
{
CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
ptimer_transaction_begin(s->timer);
ptimer_set_period_from_clock(s->timer, s->pclk, 1);
ptimer_transaction_commit(s->timer);
}
static void cmsdk_apb_timer_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj);
CMSDKAPBTimer *s = CMSDK_APB_TIMER(obj);
memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops,
s, "cmsdk-apb-timer", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->timerint);
s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
cmsdk_apb_timer_clk_update, s);
}
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
{
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
if (s->pclk_frq == 0) {
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
if (!clock_has_source(s->pclk)) {
error_setg(errp, "CMSDK APB timer: pclk clock must be connected");
return;
}
@ -230,29 +242,25 @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
ptimer_transaction_begin(s->timer);
ptimer_set_freq(s->timer, s->pclk_frq);
ptimer_set_period_from_clock(s->timer, s->pclk, 1);
ptimer_transaction_commit(s->timer);
}
static const VMStateDescription cmsdk_apb_timer_vmstate = {
.name = "cmsdk-apb-timer",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_PTIMER(timer, CMSDKAPBTIMER),
VMSTATE_UINT32(ctrl, CMSDKAPBTIMER),
VMSTATE_UINT32(value, CMSDKAPBTIMER),
VMSTATE_UINT32(reload, CMSDKAPBTIMER),
VMSTATE_UINT32(intstatus, CMSDKAPBTIMER),
VMSTATE_PTIMER(timer, CMSDKAPBTimer),
VMSTATE_CLOCK(pclk, CMSDKAPBTimer),
VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
VMSTATE_UINT32(value, CMSDKAPBTimer),
VMSTATE_UINT32(reload, CMSDKAPBTimer),
VMSTATE_UINT32(intstatus, CMSDKAPBTimer),
VMSTATE_END_OF_LIST()
}
};
static Property cmsdk_apb_timer_properties[] = {
DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -260,13 +268,12 @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
dc->realize = cmsdk_apb_timer_realize;
dc->vmsd = &cmsdk_apb_timer_vmstate;
dc->reset = cmsdk_apb_timer_reset;
device_class_set_props(dc, cmsdk_apb_timer_properties);
}
static const TypeInfo cmsdk_apb_timer_info = {
.name = TYPE_CMSDK_APB_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CMSDKAPBTIMER),
.instance_size = sizeof(CMSDKAPBTimer),
.instance_init = cmsdk_apb_timer_init,
.class_init = cmsdk_apb_timer_class_init,
};

View File

@ -30,6 +30,7 @@
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/registerfields.h"
#include "hw/qdev-clock.h"
#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "migration/vmstate.h"
@ -309,6 +310,15 @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
ptimer_transaction_commit(s->timer);
}
static void cmsdk_apb_watchdog_clk_update(void *opaque)
{
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
ptimer_transaction_begin(s->timer);
ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
ptimer_transaction_commit(s->timer);
}
static void cmsdk_apb_watchdog_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@ -318,6 +328,8 @@ static void cmsdk_apb_watchdog_init(Object *obj)
s, "cmsdk-apb-watchdog", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->wdogint);
s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
cmsdk_apb_watchdog_clk_update, s);
s->is_luminary = false;
s->id = cmsdk_apb_watchdog_id;
@ -327,9 +339,9 @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
{
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
if (s->wdogclk_frq == 0) {
if (!clock_has_source(s->wdogclk)) {
error_setg(errp,
"CMSDK APB watchdog: wdogclk-frq property must be set");
"CMSDK APB watchdog: WDOGCLK clock must be connected");
return;
}
@ -340,15 +352,16 @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
ptimer_transaction_begin(s->timer);
ptimer_set_freq(s->timer, s->wdogclk_frq);
ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
ptimer_transaction_commit(s->timer);
}
static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
.name = "cmsdk-apb-watchdog",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_CLOCK(wdogclk, CMSDKAPBWatchdog),
VMSTATE_PTIMER(timer, CMSDKAPBWatchdog),
VMSTATE_UINT32(control, CMSDKAPBWatchdog),
VMSTATE_UINT32(intstatus, CMSDKAPBWatchdog),
@ -360,11 +373,6 @@ static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
}
};
static Property cmsdk_apb_watchdog_properties[] = {
DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -372,7 +380,6 @@ static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
dc->realize = cmsdk_apb_watchdog_realize;
dc->vmsd = &cmsdk_apb_watchdog_vmstate;
dc->reset = cmsdk_apb_watchdog_reset;
device_class_set_props(dc, cmsdk_apb_watchdog_properties);
}
static const TypeInfo cmsdk_apb_watchdog_info = {

View File

@ -37,9 +37,10 @@
* per-CPU identity and control register blocks
*
* QEMU interface:
* + Clock input "MAINCLK": clock for CPUs and most peripherals
* + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
* + QOM property "memory" is a MemoryRegion containing the devices provided
* by the board model.
* + QOM property "MAINCLK" is the frequency of the main system clock
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
* (In hardware, the SSE-200 permits the number of expansion interrupts
* for the two CPUs to be configured separately, but we restrict it to
@ -103,6 +104,7 @@
#include "hw/misc/armsse-mhu.h"
#include "hw/misc/unimp.h"
#include "hw/or-irq.h"
#include "hw/clock.h"
#include "hw/core/split-irq.h"
#include "hw/cpu/cluster.h"
#include "qom/object.h"
@ -153,9 +155,9 @@ struct ARMSSE {
TZPPC apb_ppc0;
TZPPC apb_ppc1;
TZMPC mpc[IOTS_NUM_MPC];
CMSDKAPBTIMER timer0;
CMSDKAPBTIMER timer1;
CMSDKAPBTIMER s32ktimer;
CMSDKAPBTimer timer0;
CMSDKAPBTimer timer1;
CMSDKAPBTimer s32ktimer;
qemu_or_irq ppc_irq_orgate;
SplitIRQ sec_resp_splitter;
SplitIRQ ppc_irq_splitter[NUM_PPCS];
@ -209,10 +211,12 @@ struct ARMSSE {
uint32_t nsccfg;
Clock *mainclk;
Clock *s32kclk;
/* Properties */
MemoryRegion *board_memory;
uint32_t exp_numirq;
uint32_t mainclk_frq;
uint32_t sram_addr_width;
uint32_t init_svtor;
bool cpu_fpu[SSE_MAX_CPUS];

View File

@ -81,6 +81,7 @@ enum {
VIRT_GPIO,
VIRT_SECURE_UART,
VIRT_SECURE_MEM,
VIRT_SECURE_GPIO,
VIRT_PCDIMM_ACPI,
VIRT_ACPI_GED,
VIRT_NVDIMM_ACPI,
@ -127,6 +128,7 @@ struct VirtMachineClass {
bool kvm_no_adjvtime;
bool no_kvm_steal_time;
bool acpi_expose_flash;
bool no_secure_gpio;
};
struct VirtMachineState {

View File

@ -139,6 +139,21 @@ void clock_clear_callback(Clock *clk);
*/
void clock_set_source(Clock *clk, Clock *src);
/**
* clock_has_source:
* @clk: the clock
*
* Returns true if the clock has a source clock connected to it.
* This is useful for devices which have input clocks which must
* be connected by the board/SoC code which creates them. The
* device code can use this to check in its realize method that
* the clock has been connected.
*/
static inline bool clock_has_source(const Clock *clk)
{
return clk->source != NULL;
}
/**
* clock_set:
* @clk: the clock to initialize.

View File

@ -17,13 +17,33 @@
#include "qom/object.h"
#define TYPE_PVPANIC "pvpanic"
#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
#define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
#define PVPANIC_IOPORT_PROP "ioport"
/* The bit of supported pv event, TODO: include uapi header and remove this */
#define PVPANIC_F_PANICKED 0
#define PVPANIC_F_CRASHLOADED 1
/* The pv event value */
#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
/*
* PVPanicState for any device type
*/
typedef struct PVPanicState PVPanicState;
struct PVPanicState {
MemoryRegion mr;
uint8_t events;
};
void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size);
static inline uint16_t pvpanic_port(void)
{
Object *o = object_resolve_path_type("", TYPE_PVPANIC, NULL);
Object *o = object_resolve_path_type("", TYPE_PVPANIC_ISA_DEVICE, NULL);
if (!o) {
return 0;
}

View File

@ -107,6 +107,7 @@ extern bool pci_available;
#define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e
#define PCI_DEVICE_ID_REDHAT_MDPY 0x000f
#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
#define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
#define FMT_PCIBUS PRIx64

View File

@ -165,6 +165,28 @@ void ptimer_transaction_commit(ptimer_state *s);
*/
void ptimer_set_period(ptimer_state *s, int64_t period);
/**
* ptimer_set_period_from_clock - Set counter increment from a Clock
* @s: ptimer to configure
* @clk: pointer to Clock object to take period from
* @divisor: value to scale the clock frequency down by
*
* If the ptimer is being driven from a Clock, this is the preferred
* way to tell the ptimer about the period, because it avoids any
* possible rounding errors that might happen if the internal
* representation of the Clock period was converted to either a period
* in ns or a frequency in Hz.
*
* If the ptimer should run at the same frequency as the clock,
* pass 1 as the @divisor; if the ptimer should run at half the
* frequency, pass 2, and so on.
*
* This function will assert if it is called outside a
* ptimer_transaction_begin/commit block.
*/
void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clock,
unsigned int divisor);
/**
* ptimer_set_freq - Set counter frequency in Hz
* @s: ptimer to configure

View File

@ -16,7 +16,7 @@
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
*
* QEMU interface:
* + QOM property "pclk-frq": frequency at which the timer is clocked
* + Clock input "TIMCLK": clock (for both timers)
* + sysbus MMIO region 0: the register bank
* + sysbus IRQ 0: combined timer interrupt TIMINTC
* + sysbus IRO 1: timer block 1 interrupt TIMINT1
@ -28,6 +28,7 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "hw/clock.h"
#include "qom/object.h"
#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
@ -61,7 +62,7 @@ struct CMSDKAPBDualTimer {
/*< public >*/
MemoryRegion iomem;
qemu_irq timerintc;
uint32_t pclk_frq;
Clock *timclk;
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
uint32_t timeritcr;

View File

@ -15,20 +15,27 @@
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "hw/clock.h"
#include "qom/object.h"
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTIMER, CMSDK_APB_TIMER)
OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
struct CMSDKAPBTIMER {
/*
* QEMU interface:
* + Clock input "pclk": clock for the timer
* + sysbus MMIO region 0: the register bank
* + sysbus IRQ 0: timer interrupt TIMERINT
*/
struct CMSDKAPBTimer {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
qemu_irq timerint;
uint32_t pclk_frq;
struct ptimer_state *timer;
Clock *pclk;
uint32_t ctrl;
uint32_t value;
@ -36,25 +43,4 @@ struct CMSDKAPBTIMER {
uint32_t intstatus;
};
/**
* cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
* @addr: location in system memory to map registers
* @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
*/
static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
qemu_irq timerint,
uint32_t pclk_frq)
{
DeviceState *dev;
SysBusDevice *s;
dev = qdev_new(TYPE_CMSDK_APB_TIMER);
s = SYS_BUS_DEVICE(dev);
qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
sysbus_realize_and_unref(s, &error_fatal);
sysbus_mmio_map(s, 0, addr);
sysbus_connect_irq(s, 0, timerint);
return dev;
}
#endif

View File

@ -16,7 +16,7 @@
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
*
* QEMU interface:
* + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
* + Clock input "WDOGCLK": clock for the watchdog's timer
* + sysbus MMIO region 0: the register bank
* + sysbus IRQ 0: watchdog interrupt
*
@ -33,6 +33,7 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "hw/clock.h"
#include "qom/object.h"
#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
@ -51,9 +52,9 @@ struct CMSDKAPBWatchdog {
/*< public >*/
MemoryRegion iomem;
qemu_irq wdogint;
uint32_t wdogclk_frq;
bool is_luminary;
struct ptimer_state *timer;
Clock *wdogclk;
uint32_t control;
uint32_t intstatus;

View File

@ -710,4 +710,16 @@ static inline void qemu_thread_jit_write(void) {}
static inline void qemu_thread_jit_execute(void) {}
#endif
/**
* Platforms which do not support system() return ENOSYS
*/
#ifndef HAVE_SYSTEM_FUNCTION
#define system platform_does_not_support_system
static inline int platform_does_not_support_system(const char *command)
{
errno = ENOSYS;
return -1;
}
#endif /* !HAVE_SYSTEM_FUNCTION */
#endif

View File

@ -34,6 +34,7 @@ typedef struct BlockDriverState BlockDriverState;
typedef struct BusClass BusClass;
typedef struct BusState BusState;
typedef struct Chardev Chardev;
typedef struct Clock Clock;
typedef struct CompatProperty CompatProperty;
typedef struct CoMutex CoMutex;
typedef struct CPUAddressSpace CPUAddressSpace;

View File

@ -1127,6 +1127,9 @@ config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
@ -2164,9 +2167,14 @@ foreach target : target_dirs
}]
endif
foreach exe: execs
emulators += {exe['name']:
executable(exe['name'], exe['sources'],
install: true,
exe_name = exe['name']
exe_sign = 'CONFIG_HVF' in config_target
if exe_sign
exe_name += '-unsigned'
endif
emulator = executable(exe_name, exe['sources'],
install: not exe_sign,
c_args: c_args,
dependencies: arch_deps + deps + exe['dependencies'],
objects: lib.extract_all_objects(recursive: true),
@ -2174,7 +2182,23 @@ foreach target : target_dirs
link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
link_args: link_args,
gui_app: exe['gui'])
}
if exe_sign
emulators += {exe['name'] : custom_target(exe['name'],
install: true,
install_dir: get_option('bindir'),
depends: emulator,
output: exe['name'],
command: [
meson.current_source_dir() / 'scripts/entitlement.sh',
meson.current_build_dir() / exe_name,
meson.current_build_dir() / exe['name'],
meson.current_source_dir() / 'accel/hvf/entitlements.plist'
])
}
else
emulators += {exe['name']: emulator}
endif
if 'CONFIG_TRACE_SYSTEMTAP' in config_host
foreach stp: [
@ -2414,7 +2438,7 @@ summary_info += {'PIE': get_option('b_pie')}
summary_info += {'static build': config_host.has_key('CONFIG_STATIC')}
summary_info += {'malloc trim support': has_malloc_trim}
summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')}
summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')}
summary_info += {'preadv support': config_host_data.get('CONFIG_PREADV')}
summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')}
summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')}
summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')}

13
scripts/entitlement.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh -e
#
# Helper script for the build process to apply entitlements
SRC="$1"
DST="$2"
ENTITLEMENT="$3"
trap 'rm "$DST.tmp"' exit
cp -af "$SRC" "$DST.tmp"
codesign --entitlements "$ENTITLEMENT" --force -s - "$DST.tmp"
mv "$DST.tmp" "$DST"
trap '' exit

View File

@ -922,6 +922,7 @@ struct ARMCPU {
uint32_t id_mmfr4;
uint32_t id_pfr0;
uint32_t id_pfr1;
uint32_t id_pfr2;
uint32_t mvfr0;
uint32_t mvfr1;
uint32_t mvfr2;

View File

@ -6567,11 +6567,21 @@ static void define_debug_regs(ARMCPU *cpu)
*/
int i;
int wrps, brps, ctx_cmps;
ARMCPRegInfo dbgdidr = {
.name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL0_R, .accessfn = access_tda,
.type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
};
/*
* The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot
* use AArch32. Given that bit 15 is RES1, if the value is 0 then
* the register must not exist for this cpu.
*/
if (cpu->isar.dbgdidr != 0) {
ARMCPRegInfo dbgdidr = {
.name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
.opc1 = 0, .opc2 = 0,
.access = PL0_R, .accessfn = access_tda,
.type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
};
define_one_arm_cp_reg(cpu, &dbgdidr);
}
/* Note that all these register fields hold "number of Xs minus 1". */
brps = arm_num_brps(cpu);
@ -6580,7 +6590,6 @@ static void define_debug_regs(ARMCPU *cpu)
assert(ctx_cmps <= brps);
define_one_arm_cp_reg(cpu, &dbgdidr);
define_arm_cp_regs(cpu, debug_cp_reginfo);
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
@ -7662,11 +7671,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
.resetvalue = 0 },
{ .name = "MVFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
{ .name = "ID_PFR2", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
.resetvalue = 0 },
.resetvalue = cpu->isar.id_pfr2 },
{ .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
.access = PL1_R, .type = ARM_CP_CONST,
@ -12409,7 +12418,7 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
*attrs = (MemTxAttrs) {};
ret = get_phys_addr(env, addr, 0, mmu_idx, &phys_addr,
ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &phys_addr,
attrs, &prot, &page_size, &fi, &cacheattrs);
if (ret) {

View File

@ -578,6 +578,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 1, 0));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1,
ARM64_SYS_REG(3, 0, 0, 1, 1));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2,
ARM64_SYS_REG(3, 0, 0, 3, 4));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
ARM64_SYS_REG(3, 0, 0, 1, 2));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,

View File

@ -0,0 +1,130 @@
/*
* QTest testcase for the CMSDK APB dualtimer device
*
* Copyright (c) 2021 Linaro Limited
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "qemu/osdep.h"
#include "libqtest-single.h"
/* IoTKit/ARMSSE dualtimer; driven at 25MHz in mps2-an385, so 40ns per tick */
#define TIMER_BASE 0x40002000
#define TIMER1LOAD 0
#define TIMER1VALUE 4
#define TIMER1CONTROL 8
#define TIMER1INTCLR 0xc
#define TIMER1RIS 0x10
#define TIMER1MIS 0x14
#define TIMER1BGLOAD 0x18
#define TIMER2LOAD 0x20
#define TIMER2VALUE 0x24
#define TIMER2CONTROL 0x28
#define TIMER2INTCLR 0x2c
#define TIMER2RIS 0x30
#define TIMER2MIS 0x34
#define TIMER2BGLOAD 0x38
#define CTRL_ENABLE (1 << 7)
#define CTRL_PERIODIC (1 << 6)
#define CTRL_INTEN (1 << 5)
#define CTRL_PRESCALE_1 (0 << 2)
#define CTRL_PRESCALE_16 (1 << 2)
#define CTRL_PRESCALE_256 (2 << 2)
#define CTRL_32BIT (1 << 1)
#define CTRL_ONESHOT (1 << 0)
static void test_dualtimer(void)
{
g_assert_true(readl(TIMER_BASE + TIMER1RIS) == 0);
/* Start timer: will fire after 40000 ns */
writel(TIMER_BASE + TIMER1LOAD, 1000);
/* enable in free-running, wrapping, interrupt mode */
writel(TIMER_BASE + TIMER1CONTROL, CTRL_ENABLE | CTRL_INTEN);
/* Step to just past the 500th tick and check VALUE */
clock_step(500 * 40 + 1);
g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 500);
/* Just past the 1000th tick: timer should have fired */
clock_step(500 * 40);
g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 1);
g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0);
/*
* We are in free-running wrapping 16-bit mode, so on the following
* tick VALUE should have wrapped round to 0xffff.
*/
clock_step(40);
g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0xffff);
/* Check that any write to INTCLR clears interrupt */
writel(TIMER_BASE + TIMER1INTCLR, 1);
g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
/* Turn off the timer */
writel(TIMER_BASE + TIMER1CONTROL, 0);
}
static void test_prescale(void)
{
g_assert_true(readl(TIMER_BASE + TIMER2RIS) == 0);
/* Start timer: will fire after 40 * 256 * 1000 == 1024000 ns */
writel(TIMER_BASE + TIMER2LOAD, 1000);
/* enable in periodic, wrapping, interrupt mode, prescale 256 */
writel(TIMER_BASE + TIMER2CONTROL,
CTRL_ENABLE | CTRL_INTEN | CTRL_PERIODIC | CTRL_PRESCALE_256);
/* Step to just past the 500th tick and check VALUE */
clock_step(40 * 256 * 501);
g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 500);
/* Just past the 1000th tick: timer should have fired */
clock_step(40 * 256 * 500);
g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 1);
g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 0);
/* In periodic mode the tick VALUE now reloads */
clock_step(40 * 256);
g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 1000);
/* Check that any write to INTCLR clears interrupt */
writel(TIMER_BASE + TIMER2INTCLR, 1);
g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
/* Turn off the timer */
writel(TIMER_BASE + TIMER2CONTROL, 0);
}
int main(int argc, char **argv)
{
int r;
g_test_init(&argc, &argv, NULL);
qtest_start("-machine mps2-an385");
qtest_add_func("/cmsdk-apb-dualtimer/dualtimer", test_dualtimer);
qtest_add_func("/cmsdk-apb-dualtimer/prescale", test_prescale);
r = g_test_run();
qtest_end();
return r;
}

View File

@ -0,0 +1,75 @@
/*
* QTest testcase for the CMSDK APB timer device
*
* Copyright (c) 2021 Linaro Limited
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "qemu/osdep.h"
#include "libqtest-single.h"
/* IoTKit/ARMSSE-200 timer0; driven at 25MHz in mps2-an385, so 40ns per tick */
#define TIMER_BASE 0x40000000
#define CTRL 0
#define VALUE 4
#define RELOAD 8
#define INTSTATUS 0xc
static void test_timer(void)
{
g_assert_true(readl(TIMER_BASE + INTSTATUS) == 0);
/* Start timer: will fire after 40 * 1000 == 40000 ns */
writel(TIMER_BASE + RELOAD, 1000);
writel(TIMER_BASE + CTRL, 9);
/* Step to just past the 500th tick and check VALUE */
clock_step(40 * 500 + 1);
g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 500);
/* Just past the 1000th tick: timer should have fired */
clock_step(40 * 500);
g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 0);
/* VALUE reloads at the following tick */
clock_step(40);
g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 1000);
/* Check write-1-to-clear behaviour of INTSTATUS */
writel(TIMER_BASE + INTSTATUS, 0);
g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
writel(TIMER_BASE + INTSTATUS, 1);
g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
/* Turn off the timer */
writel(TIMER_BASE + CTRL, 0);
}
int main(int argc, char **argv)
{
int r;
g_test_init(&argc, &argv, NULL);
qtest_start("-machine mps2-an385");
qtest_add_func("/cmsdk-apb-timer/timer", test_timer);
r = g_test_run();
qtest_end();
return r;
}

View File

@ -0,0 +1,131 @@
/*
* QTest testcase for the CMSDK APB watchdog device
*
* Copyright (c) 2021 Linaro Limited
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "libqtest-single.h"
/*
* lm3s811evb watchdog; at board startup this runs at 200MHz / 16 == 12.5MHz,
* which is 80ns per tick.
*/
#define WDOG_BASE 0x40000000
#define WDOGLOAD 0
#define WDOGVALUE 4
#define WDOGCONTROL 8
#define WDOGINTCLR 0xc
#define WDOGRIS 0x10
#define WDOGMIS 0x14
#define WDOGLOCK 0xc00
#define SSYS_BASE 0x400fe000
#define RCC 0x60
#define SYSDIV_SHIFT 23
#define SYSDIV_LENGTH 4
static void test_watchdog(void)
{
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
writel(WDOG_BASE + WDOGCONTROL, 1);
writel(WDOG_BASE + WDOGLOAD, 1000);
/* Step to just past the 500th tick */
clock_step(500 * 80 + 1);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
/* Just past the 1000th tick: timer should have fired */
clock_step(500 * 80);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
/* VALUE reloads at following tick */
clock_step(80);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
/* Writing any value to WDOGINTCLR clears the interrupt and reloads */
clock_step(500 * 80);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
writel(WDOG_BASE + WDOGINTCLR, 0);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
}
static void test_clock_change(void)
{
uint32_t rcc;
/*
* Test that writing to the stellaris board's RCC register to
* change the system clock frequency causes the watchdog
* to change the speed it counts at.
*/
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
writel(WDOG_BASE + WDOGCONTROL, 1);
writel(WDOG_BASE + WDOGLOAD, 1000);
/* Step to just past the 500th tick */
clock_step(80 * 500 + 1);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
/* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */
rcc = readl(SSYS_BASE + RCC);
g_assert_cmpuint(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf);
rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7);
writel(SSYS_BASE + RCC, rcc);
/* Just past the 1000th tick: timer should have fired */
clock_step(40 * 500);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
/* VALUE reloads at following tick */
clock_step(41);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
/* Writing any value to WDOGINTCLR clears the interrupt and reloads */
clock_step(40 * 500);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
writel(WDOG_BASE + WDOGINTCLR, 0);
g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
}
int main(int argc, char **argv)
{
int r;
g_test_init(&argc, &argv, NULL);
qtest_start("-machine lm3s811evb");
qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
qtest_add_func("/cmsdk-apb-watchdog/watchdog_clock_change",
test_clock_change);
r = g_test_run();
qtest_end();
return r;
}

View File

@ -33,7 +33,8 @@ qtests_i386 = \
(config_host.has_key('CONFIG_LINUX') and \
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
(config_all_devices.has_key('CONFIG_PVPANIC') ? ['pvpanic-test'] : []) + \
(config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
(config_all_devices.has_key('CONFIG_PVPANIC_PCI') ? ['pvpanic-pci-test'] : []) + \
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
@ -141,6 +142,9 @@ qtests_npcm7xx = \
'npcm7xx_timer-test',
'npcm7xx_watchdog_timer-test']
qtests_arm = \
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
['arm-cpu-features',

View File

@ -272,7 +272,7 @@ static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
{
uint64_t duty;
uint32_t duty;
if (cnr == 0) {
/* PWM is stopped. */
@ -280,7 +280,7 @@ static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
} else if (cmr >= cnr) {
duty = MAX_DUTY;
} else {
duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
duty = (uint64_t)MAX_DUTY * (cmr + 1) / (cnr + 1);
}
if (inverted) {

View File

@ -0,0 +1,98 @@
/*
* QTest testcase for PV Panic PCI device
*
* Copyright (C) 2020 Oracle
*
* Authors:
* Mihai Carabas <mihai.carabas@oracle.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "libqos/libqtest.h"
#include "qapi/qmp/qdict.h"
#include "libqos/pci.h"
#include "libqos/pci-pc.h"
#include "hw/pci/pci_regs.h"
static void test_panic_nopause(void)
{
uint8_t val;
QDict *response, *data;
QTestState *qts;
QPCIBus *pcibus;
QPCIDevice *dev;
QPCIBar bar;
qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=none");
pcibus = qpci_new_pc(qts, NULL);
dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
qpci_device_enable(dev);
bar = qpci_iomap(dev, 0, NULL);
qpci_memread(dev, bar, 0, &val, sizeof(val));
g_assert_cmpuint(val, ==, 3);
val = 1;
qpci_memwrite(dev, bar, 0, &val, sizeof(val));
response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
g_assert(qdict_haskey(response, "data"));
data = qdict_get_qdict(response, "data");
g_assert(qdict_haskey(data, "action"));
g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run");
qobject_unref(response);
g_free(dev);
qpci_free_pc(pcibus);
qtest_quit(qts);
}
static void test_panic(void)
{
uint8_t val;
QDict *response, *data;
QTestState *qts;
QPCIBus *pcibus;
QPCIDevice *dev;
QPCIBar bar;
qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=pause");
pcibus = qpci_new_pc(qts, NULL);
dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
qpci_device_enable(dev);
bar = qpci_iomap(dev, 0, NULL);
qpci_memread(dev, bar, 0, &val, sizeof(val));
g_assert_cmpuint(val, ==, 3);
val = 1;
qpci_memwrite(dev, bar, 0, &val, sizeof(val));
response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
g_assert(qdict_haskey(response, "data"));
data = qdict_get_qdict(response, "data");
g_assert(qdict_haskey(data, "action"));
g_assert_cmpstr(qdict_get_str(data, "action"), ==, "pause");
qobject_unref(response);
g_free(dev);
qpci_free_pc(pcibus);
qtest_quit(qts);
}
int main(int argc, char **argv)
{
int ret;
g_test_init(&argc, &argv, NULL);
qtest_add_func("/pvpanic-pci/panic", test_panic);
qtest_add_func("/pvpanic-pci/panic-nopause", test_panic_nopause);
ret = g_test_run();
return ret;
}

View File

@ -138,9 +138,9 @@ static void test_can_bus(void)
uint8_t can_timestamp = 1;
QTestState *qts = qtest_init("-machine xlnx-zcu102"
" -object can-bus,id=canbus0"
" -machine xlnx-zcu102.canbus0=canbus0"
" -machine xlnx-zcu102.canbus1=canbus0"
" -object can-bus,id=canbus"
" -machine canbus0=canbus"
" -machine canbus1=canbus"
);
/* Configure the CAN0 and CAN1. */
@ -175,9 +175,9 @@ static void test_can_loopback(void)
uint32_t status = 0;
QTestState *qts = qtest_init("-machine xlnx-zcu102"
" -object can-bus,id=canbus0"
" -machine xlnx-zcu102.canbus0=canbus0"
" -machine xlnx-zcu102.canbus1=canbus0"
" -object can-bus,id=canbus"
" -machine canbus0=canbus"
" -machine canbus1=canbus"
);
/* Configure the CAN0 in loopback mode. */
@ -223,9 +223,9 @@ static void test_can_filter(void)
uint8_t can_timestamp = 1;
QTestState *qts = qtest_init("-machine xlnx-zcu102"
" -object can-bus,id=canbus0"
" -machine xlnx-zcu102.canbus0=canbus0"
" -machine xlnx-zcu102.canbus1=canbus0"
" -object can-bus,id=canbus"
" -machine canbus0=canbus"
" -machine canbus1=canbus"
);
/* Configure the CAN0 and CAN1. */
@ -271,9 +271,9 @@ static void test_can_sleepmode(void)
uint8_t can_timestamp = 1;
QTestState *qts = qtest_init("-machine xlnx-zcu102"
" -object can-bus,id=canbus0"
" -machine xlnx-zcu102.canbus0=canbus0"
" -machine xlnx-zcu102.canbus1=canbus0"
" -object can-bus,id=canbus"
" -machine canbus0=canbus"
" -machine canbus1=canbus"
);
/* Configure the CAN0. */
@ -317,9 +317,9 @@ static void test_can_snoopmode(void)
uint8_t can_timestamp = 1;
QTestState *qts = qtest_init("-machine xlnx-zcu102"
" -object can-bus,id=canbus0"
" -machine xlnx-zcu102.canbus0=canbus0"
" -machine xlnx-zcu102.canbus1=canbus0"
" -object can-bus,id=canbus"
" -machine canbus0=canbus"
" -machine canbus1=canbus"
);
/* Configure the CAN0. */