* Add some missing gitlab-CI job dependencies
* Re-enable "make check SPEED=slow" * Improve the gitlab-pipeline-status script * Clean up inclusing of qtest.h headers * Improve libqos/qgraph documentation * Fix downloading problem in the acceptance tests * Remove deprecated target tilegx * Add new bsd-user maintainers -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmBHTZERHHRodXRoQHJl ZGhhdC5jb20ACgkQLtnXdP5wLbW1bA//Xkqv1MXiTllIp9/MaayzrCXE4QI1yosA onaEQWBuchw2oO/riyayskD516J5q0dyMlQAWx2tv9N1wFC+F8gUcP/q0zpckqhu 79DyRj9upDYrCgmGUi+0O9qelv3f7VHB6B1bBZlJzA+W7WskrXYk97dXkezvGDQa a+D95upQiOLu2cxvEWTx+Z4Gz1R4NMM/JaudnMkNy/WECLOrEQr/bEgk60dwomO2 Vdb2t1DLwmjFXXQgBvP5olVk/4vHGcDCMOD3gy8TTt7sNv3VR7re18rUdWnOQcB8 hm3IRGLYZ/JYTqKutJ4QYpOFA1hUyKOLysi3Wj/jhuzV/n028izpPbeCsuWGZ1Ck QmdOdP/g8XZzPWekEEG+pL8gZgVM/HdJAm+Ameiwq2F6ybDXS75EgBzCjFC3p1kF KA6UFUD9tw2ZGIjy5vzJToTn4wtku6n9B9sP3nHeVQYbQtSFQhfQwP02NVM66dua PLSlIPP09jtmGS/LO9j+aw72bNhMJzpEORQvnoAOsbH8cgTpu6auzvKDg2+cMqGb pXBihfvhRvfk3RV8dn2nk929FS6hxybjW3aU9iZAG+Dg0YIPwFOk/w/awgbAjhYe bwywmRZSE1mkqm6brE8J1y6SORlcvontv6PLy5NYLe6gGHJex4j8U0zWKW0qDjNr hot+/3Mstsw= =8JHZ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/thuth-gitlab/tags/pull-request-2021-03-09' into staging * Add some missing gitlab-CI job dependencies * Re-enable "make check SPEED=slow" * Improve the gitlab-pipeline-status script * Clean up inclusing of qtest.h headers * Improve libqos/qgraph documentation * Fix downloading problem in the acceptance tests * Remove deprecated target tilegx * Add new bsd-user maintainers # gpg: Signature made Tue 09 Mar 2021 10:27:29 GMT # gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5 # gpg: issuer "thuth@redhat.com" # gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full] # gpg: aka "Thomas Huth <thuth@redhat.com>" [full] # gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full] # gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown] # Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5 * remotes/thuth-gitlab/tags/pull-request-2021-03-09: bsd-user: Add new maintainers Remove deprecated target tilegx Acceptance Tests: restore filtering of tests by target arch Acceptance Tests: restore downloading of VM images docs/devel/qgraph: improve qgraph documentation libqos/qgraph: format qgraph comments for sphinx documentation scripts/ci/gitlab-pipeline-status: give more info when pipeline not found scripts/ci/gitlab-pipeline-status: give more information on failures scripts/ci/gitlab-pipeline-status: split utlity function for HTTP GET meson: Re-enable the possibility to run "make check SPEED=slow" docker: OpenSBI build job depends on OpenSBI container docker: EDK2 build job depends on EDK2 container docker: Alpine build job depends on Alpine container qtest: delete superfluous inclusions of qtest.h Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
821e7ed167
@ -25,6 +25,7 @@ docker-edk2:
|
||||
|
||||
build-edk2:
|
||||
stage: build
|
||||
needs: ['docker-edk2']
|
||||
rules: # Only run this job when ...
|
||||
- changes: # ... roms/edk2/ is modified (submodule updated)
|
||||
- roms/edk2/*
|
||||
|
@ -25,6 +25,7 @@ docker-opensbi:
|
||||
|
||||
build-opensbi:
|
||||
stage: build
|
||||
needs: ['docker-opensbi']
|
||||
rules: # Only run this job when ...
|
||||
- changes: # ... roms/opensbi/ is modified (submodule updated)
|
||||
- roms/opensbi/*
|
||||
|
@ -76,6 +76,8 @@ include:
|
||||
|
||||
build-system-alpine:
|
||||
<<: *native_build_job_definition
|
||||
needs:
|
||||
- job: amd64-alpine-container
|
||||
variables:
|
||||
IMAGE: alpine
|
||||
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
|
||||
@ -497,8 +499,7 @@ build-deprecated:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-docs --disable-tools
|
||||
MAKE_CHECK_ARGS: build-tcg
|
||||
TARGETS: ppc64abi32-linux-user tilegx-linux-user lm32-softmmu
|
||||
unicore32-softmmu
|
||||
TARGETS: ppc64abi32-linux-user lm32-softmmu unicore32-softmmu
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
|
@ -2614,6 +2614,7 @@ S: Maintained
|
||||
F: softmmu/qtest.c
|
||||
F: accel/qtest/
|
||||
F: tests/qtest/
|
||||
F: docs/devel/qgraph.rst
|
||||
X: tests/qtest/bios-tables-test*
|
||||
|
||||
Device Fuzzing
|
||||
@ -2909,9 +2910,12 @@ F: thunk.c
|
||||
F: accel/tcg/user-exec*.c
|
||||
|
||||
BSD user
|
||||
S: Orphan
|
||||
M: Warner Losh <imp@bsdimp.com>
|
||||
R: Kyle Evans <kevans@freebsd.org>
|
||||
S: Maintained
|
||||
F: bsd-user/
|
||||
F: default-configs/targets/*-bsd-user.mak
|
||||
T: git https://github.com/qemu-bsd-user/qemu-bsd-user bsd-user-rebase-3.1
|
||||
|
||||
Linux user
|
||||
M: Laurent Vivier <laurent@vivier.eu>
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "tcg/tcg.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/compiler.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "exec/tb-hash.h"
|
||||
|
@ -57,7 +57,6 @@
|
||||
#include "block/block_int.h"
|
||||
#include "block/trace.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
2
configure
vendored
2
configure
vendored
@ -1655,7 +1655,7 @@ if [ "$ARCH" = "unknown" ]; then
|
||||
fi
|
||||
|
||||
default_target_list=""
|
||||
deprecated_targets_list=ppc64abi32-linux-user,tilegx-linux-user,lm32-softmmu,unicore32-softmmu
|
||||
deprecated_targets_list=ppc64abi32-linux-user,lm32-softmmu,unicore32-softmmu
|
||||
deprecated_features=""
|
||||
mak_wilds=""
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
TARGET_ARCH=tilegx
|
@ -12,6 +12,7 @@ Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:includehidden:
|
||||
|
||||
build-system
|
||||
style
|
||||
|
568
docs/devel/qgraph.rst
Normal file
568
docs/devel/qgraph.rst
Normal file
@ -0,0 +1,568 @@
|
||||
.. _qgraph:
|
||||
|
||||
========================================
|
||||
Qtest Driver Framework
|
||||
========================================
|
||||
|
||||
In order to test a specific driver, plain libqos tests need to
|
||||
take care of booting QEMU with the right machine and devices.
|
||||
This makes each test "hardcoded" for a specific configuration, reducing
|
||||
the possible coverage that it can reach.
|
||||
|
||||
For example, the sdhci device is supported on both x86_64 and ARM boards,
|
||||
therefore a generic sdhci test should test all machines and drivers that
|
||||
support that device.
|
||||
Using only libqos APIs, the test has to manually take care of
|
||||
covering all the setups, and build the correct command line.
|
||||
|
||||
This also introduces backward compability issues: if a device/driver command
|
||||
line name is changed, all tests that use that will not work
|
||||
properly anymore and need to be adjusted.
|
||||
|
||||
The aim of qgraph is to create a graph of drivers, machines and tests such that
|
||||
a test aimed to a certain driver does not have to care of
|
||||
booting the right QEMU machine, pick the right device, build the command line
|
||||
and so on. Instead, it only defines what type of device it is testing
|
||||
(interface in qgraph terms) and the framework takes care of
|
||||
covering all supported types of devices and machine architectures.
|
||||
|
||||
Following the above example, an interface would be ``sdhci``,
|
||||
so the sdhci-test should only care of linking its qgraph node with
|
||||
that interface. In this way, if the command line of a sdhci driver
|
||||
is changed, only the respective qgraph driver node has to be adjusted.
|
||||
|
||||
The graph is composed by nodes that represent machines, drivers, tests
|
||||
and edges that define the relationships between them (``CONSUMES``, ``PRODUCES``, and
|
||||
``CONTAINS``).
|
||||
|
||||
|
||||
Nodes
|
||||
^^^^^^
|
||||
|
||||
A node can be of four types:
|
||||
|
||||
- **QNODE_MACHINE**: for example ``arm/raspi2``
|
||||
- **QNODE_DRIVER**: for example ``generic-sdhci``
|
||||
- **QNODE_INTERFACE**: for example ``sdhci`` (interface for all ``-sdhci``
|
||||
drivers).
|
||||
An interface is not explicitly created, it will be automatically
|
||||
instantiated when a node consumes or produces it.
|
||||
An interface is simply a struct that abstracts the various drivers
|
||||
for the same type of device, and offers an API to the nodes that
|
||||
use it ("consume" relation in qgraph terms) that is implemented/backed up by the drivers that implement it ("produce" relation in qgraph terms).
|
||||
- **QNODE_TEST**: for example ``sdhci-test``. A test consumes an interface
|
||||
and tests the functions provided by it.
|
||||
|
||||
Notes for the nodes:
|
||||
|
||||
- QNODE_MACHINE: each machine struct must have a ``QGuestAllocator`` and
|
||||
implement ``get_driver()`` to return the allocator mapped to the interface
|
||||
"memory". The function can also return ``NULL`` if the allocator
|
||||
is not set.
|
||||
- QNODE_DRIVER: driver names must be unique, and machines and nodes
|
||||
planned to be "consumed" by other nodes must match QEMU
|
||||
drivers name, otherwise they won't be discovered
|
||||
|
||||
Edges
|
||||
^^^^^^
|
||||
|
||||
An edge relation between two nodes (drivers or machines) `X` and `Y` can be:
|
||||
|
||||
- ``X CONSUMES Y``: `Y` can be plugged into `X`
|
||||
- ``X PRODUCES Y``: `X` provides the interface `Y`
|
||||
- ``X CONTAINS Y``: `Y` is part of `X` component
|
||||
|
||||
Execution steps
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The basic framework steps are the following:
|
||||
|
||||
- All nodes and edges are created in their respective
|
||||
machine/driver/test files
|
||||
- The framework starts QEMU and asks for a list of available devices
|
||||
and machines (note that only machines and "consumed" nodes are mapped
|
||||
1:1 with QEMU devices)
|
||||
- The framework walks the graph starting from the available machines and
|
||||
performs a Depth First Search for tests
|
||||
- Once a test is found, the path is walked again and all drivers are
|
||||
allocated accordingly and the final interface is passed to the test
|
||||
- The test is executed
|
||||
- Unused objects are cleaned and the path discovery is continued
|
||||
|
||||
Depending on the QEMU binary used, only some drivers/machines will be
|
||||
available and only test that are reached by them will be executed.
|
||||
|
||||
Creating a new driver and its interface
|
||||
"""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Here we continue the ``sdhci`` use case, with the following scenario:
|
||||
|
||||
- ``sdhci-test`` aims to test the ``read[q,w], writeq`` functions
|
||||
offered by the ``sdhci`` drivers.
|
||||
- The current ``sdhci`` device is supported by both ``x86_64/pc`` and ``ARM``
|
||||
(in this example we focus on the ``arm-raspi2``) machines.
|
||||
- QEMU offers 2 types of drivers: ``QSDHCI_MemoryMapped`` for ``ARM`` and
|
||||
``QSDHCI_PCI`` for ``x86_64/pc``. Both implement the
|
||||
``read[q,w], writeq`` functions.
|
||||
|
||||
In order to implement such scenario in qgraph, the test developer needs to:
|
||||
|
||||
- Create the ``x86_64/pc`` machine node. This machine uses the
|
||||
``pci-bus`` architecture so it ``contains`` a PCI driver,
|
||||
``pci-bus-pc``. The actual path is
|
||||
|
||||
``x86_64/pc --contains--> 1440FX-pcihost --contains-->
|
||||
pci-bus-pc --produces--> pci-bus``.
|
||||
|
||||
For the sake of this example,
|
||||
we do not focus on the PCI interface implementation.
|
||||
- Create the ``sdhci-pci`` driver node, representing ``QSDHCI_PCI``.
|
||||
The driver uses the PCI bus (and its API),
|
||||
so it must ``consume`` the ``pci-bus`` generic interface (which abstracts
|
||||
all the pci drivers available)
|
||||
|
||||
``sdhci-pci --consumes--> pci-bus``
|
||||
- Create an ``arm/raspi2`` machine node. This machine ``contains``
|
||||
a ``generic-sdhci`` memory mapped ``sdhci`` driver node, representing
|
||||
``QSDHCI_MemoryMapped``.
|
||||
|
||||
``arm/raspi2 --contains--> generic-sdhci``
|
||||
- Create the ``sdhci`` interface node. This interface offers the
|
||||
functions that are shared by all ``sdhci`` devices.
|
||||
The interface is produced by ``sdhci-pci`` and ``generic-sdhci``,
|
||||
the available architecture-specific drivers.
|
||||
|
||||
``sdhci-pci --produces--> sdhci``
|
||||
|
||||
``generic-sdhci --produces--> sdhci``
|
||||
- Create the ``sdhci-test`` test node. The test ``consumes`` the
|
||||
``sdhci`` interface, using its API. It doesn't need to look at
|
||||
the supported machines or drivers.
|
||||
|
||||
``sdhci-test --consumes--> sdhci``
|
||||
|
||||
``arm-raspi2`` machine, simplified from
|
||||
``tests/qtest/libqos/arm-raspi2-machine.c``::
|
||||
|
||||
#include "qgraph.h"
|
||||
|
||||
struct QRaspi2Machine {
|
||||
QOSGraphObject obj;
|
||||
QGuestAllocator alloc;
|
||||
QSDHCI_MemoryMapped sdhci;
|
||||
};
|
||||
|
||||
static void *raspi2_get_driver(void *object, const char *interface)
|
||||
{
|
||||
QRaspi2Machine *machine = object;
|
||||
if (!g_strcmp0(interface, "memory")) {
|
||||
return &machine->alloc;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in arm/raspi2\n", interface);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static QOSGraphObject *raspi2_get_device(void *obj,
|
||||
const char *device)
|
||||
{
|
||||
QRaspi2Machine *machine = obj;
|
||||
if (!g_strcmp0(device, "generic-sdhci")) {
|
||||
return &machine->sdhci.obj;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in arm/raspi2\n", device);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void *qos_create_machine_arm_raspi2(QTestState *qts)
|
||||
{
|
||||
QRaspi2Machine *machine = g_new0(QRaspi2Machine, 1);
|
||||
|
||||
alloc_init(&machine->alloc, ...);
|
||||
|
||||
/* Get node(s) contained inside (CONTAINS) */
|
||||
machine->obj.get_device = raspi2_get_device;
|
||||
|
||||
/* Get node(s) produced (PRODUCES) */
|
||||
machine->obj.get_driver = raspi2_get_driver;
|
||||
|
||||
/* free the object */
|
||||
machine->obj.destructor = raspi2_destructor;
|
||||
qos_init_sdhci_mm(&machine->sdhci, ...);
|
||||
return &machine->obj;
|
||||
}
|
||||
|
||||
static void raspi2_register_nodes(void)
|
||||
{
|
||||
/* arm/raspi2 --contains--> generic-sdhci */
|
||||
qos_node_create_machine("arm/raspi2",
|
||||
qos_create_machine_arm_raspi2);
|
||||
qos_node_contains("arm/raspi2", "generic-sdhci", NULL);
|
||||
}
|
||||
|
||||
libqos_init(raspi2_register_nodes);
|
||||
|
||||
``x86_64/pc`` machine, simplified from
|
||||
``tests/qtest/libqos/x86_64_pc-machine.c``::
|
||||
|
||||
#include "qgraph.h"
|
||||
|
||||
struct i440FX_pcihost {
|
||||
QOSGraphObject obj;
|
||||
QPCIBusPC pci;
|
||||
};
|
||||
|
||||
struct QX86PCMachine {
|
||||
QOSGraphObject obj;
|
||||
QGuestAllocator alloc;
|
||||
i440FX_pcihost bridge;
|
||||
};
|
||||
|
||||
/* i440FX_pcihost */
|
||||
|
||||
static QOSGraphObject *i440FX_host_get_device(void *obj,
|
||||
const char *device)
|
||||
{
|
||||
i440FX_pcihost *host = obj;
|
||||
if (!g_strcmp0(device, "pci-bus-pc")) {
|
||||
return &host->pci.obj;
|
||||
}
|
||||
fprintf(stderr, "%s not present in i440FX-pcihost\n", device);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
/* x86_64/pc machine */
|
||||
|
||||
static void *pc_get_driver(void *object, const char *interface)
|
||||
{
|
||||
QX86PCMachine *machine = object;
|
||||
if (!g_strcmp0(interface, "memory")) {
|
||||
return &machine->alloc;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in x86_64/pc\n", interface);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static QOSGraphObject *pc_get_device(void *obj, const char *device)
|
||||
{
|
||||
QX86PCMachine *machine = obj;
|
||||
if (!g_strcmp0(device, "i440FX-pcihost")) {
|
||||
return &machine->bridge.obj;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in x86_64/pc\n", device);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void *qos_create_machine_pc(QTestState *qts)
|
||||
{
|
||||
QX86PCMachine *machine = g_new0(QX86PCMachine, 1);
|
||||
|
||||
/* Get node(s) contained inside (CONTAINS) */
|
||||
machine->obj.get_device = pc_get_device;
|
||||
|
||||
/* Get node(s) produced (PRODUCES) */
|
||||
machine->obj.get_driver = pc_get_driver;
|
||||
|
||||
/* free the object */
|
||||
machine->obj.destructor = pc_destructor;
|
||||
pc_alloc_init(&machine->alloc, qts, ALLOC_NO_FLAGS);
|
||||
|
||||
/* Get node(s) contained inside (CONTAINS) */
|
||||
machine->bridge.obj.get_device = i440FX_host_get_device;
|
||||
|
||||
return &machine->obj;
|
||||
}
|
||||
|
||||
static void pc_machine_register_nodes(void)
|
||||
{
|
||||
/* x86_64/pc --contains--> 1440FX-pcihost --contains-->
|
||||
* pci-bus-pc [--produces--> pci-bus (in pci.h)] */
|
||||
qos_node_create_machine("x86_64/pc", qos_create_machine_pc);
|
||||
qos_node_contains("x86_64/pc", "i440FX-pcihost", NULL);
|
||||
|
||||
/* contained drivers don't need a constructor,
|
||||
* they will be init by the parent */
|
||||
qos_node_create_driver("i440FX-pcihost", NULL);
|
||||
qos_node_contains("i440FX-pcihost", "pci-bus-pc", NULL);
|
||||
}
|
||||
|
||||
libqos_init(pc_machine_register_nodes);
|
||||
|
||||
``sdhci`` taken from ``tests/qtest/libqos/sdhci.c``::
|
||||
|
||||
/* Interface node, offers the sdhci API */
|
||||
struct QSDHCI {
|
||||
uint16_t (*readw)(QSDHCI *s, uint32_t reg);
|
||||
uint64_t (*readq)(QSDHCI *s, uint32_t reg);
|
||||
void (*writeq)(QSDHCI *s, uint32_t reg, uint64_t val);
|
||||
/* other fields */
|
||||
};
|
||||
|
||||
/* Memory Mapped implementation of QSDHCI */
|
||||
struct QSDHCI_MemoryMapped {
|
||||
QOSGraphObject obj;
|
||||
QSDHCI sdhci;
|
||||
/* other driver-specific fields */
|
||||
};
|
||||
|
||||
/* PCI implementation of QSDHCI */
|
||||
struct QSDHCI_PCI {
|
||||
QOSGraphObject obj;
|
||||
QSDHCI sdhci;
|
||||
/* other driver-specific fields */
|
||||
};
|
||||
|
||||
/* Memory mapped implementation of QSDHCI */
|
||||
|
||||
static void *sdhci_mm_get_driver(void *obj, const char *interface)
|
||||
{
|
||||
QSDHCI_MemoryMapped *smm = obj;
|
||||
if (!g_strcmp0(interface, "sdhci")) {
|
||||
return &smm->sdhci;
|
||||
}
|
||||
fprintf(stderr, "%s not present in generic-sdhci\n", interface);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void qos_init_sdhci_mm(QSDHCI_MemoryMapped *sdhci, QTestState *qts,
|
||||
uint32_t addr, QSDHCIProperties *common)
|
||||
{
|
||||
/* Get node contained inside (CONTAINS) */
|
||||
sdhci->obj.get_driver = sdhci_mm_get_driver;
|
||||
|
||||
/* SDHCI interface API */
|
||||
sdhci->sdhci.readw = sdhci_mm_readw;
|
||||
sdhci->sdhci.readq = sdhci_mm_readq;
|
||||
sdhci->sdhci.writeq = sdhci_mm_writeq;
|
||||
sdhci->qts = qts;
|
||||
}
|
||||
|
||||
/* PCI implementation of QSDHCI */
|
||||
|
||||
static void *sdhci_pci_get_driver(void *object,
|
||||
const char *interface)
|
||||
{
|
||||
QSDHCI_PCI *spci = object;
|
||||
if (!g_strcmp0(interface, "sdhci")) {
|
||||
return &spci->sdhci;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in sdhci-pci\n", interface);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void *sdhci_pci_create(void *pci_bus,
|
||||
QGuestAllocator *alloc,
|
||||
void *addr)
|
||||
{
|
||||
QSDHCI_PCI *spci = g_new0(QSDHCI_PCI, 1);
|
||||
QPCIBus *bus = pci_bus;
|
||||
uint64_t barsize;
|
||||
|
||||
qpci_device_init(&spci->dev, bus, addr);
|
||||
|
||||
/* SDHCI interface API */
|
||||
spci->sdhci.readw = sdhci_pci_readw;
|
||||
spci->sdhci.readq = sdhci_pci_readq;
|
||||
spci->sdhci.writeq = sdhci_pci_writeq;
|
||||
|
||||
/* Get node(s) produced (PRODUCES) */
|
||||
spci->obj.get_driver = sdhci_pci_get_driver;
|
||||
|
||||
spci->obj.start_hw = sdhci_pci_start_hw;
|
||||
spci->obj.destructor = sdhci_destructor;
|
||||
return &spci->obj;
|
||||
}
|
||||
|
||||
static void qsdhci_register_nodes(void)
|
||||
{
|
||||
QOSGraphEdgeOptions opts = {
|
||||
.extra_device_opts = "addr=04.0",
|
||||
};
|
||||
|
||||
/* generic-sdhci */
|
||||
/* generic-sdhci --produces--> sdhci */
|
||||
qos_node_create_driver("generic-sdhci", NULL);
|
||||
qos_node_produces("generic-sdhci", "sdhci");
|
||||
|
||||
/* sdhci-pci */
|
||||
/* sdhci-pci --produces--> sdhci
|
||||
* sdhci-pci --consumes--> pci-bus */
|
||||
qos_node_create_driver("sdhci-pci", sdhci_pci_create);
|
||||
qos_node_produces("sdhci-pci", "sdhci");
|
||||
qos_node_consumes("sdhci-pci", "pci-bus", &opts);
|
||||
}
|
||||
|
||||
libqos_init(qsdhci_register_nodes);
|
||||
|
||||
In the above example, all possible types of relations are created::
|
||||
|
||||
x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc
|
||||
|
|
||||
sdhci-pci --consumes--> pci-bus <--produces--+
|
||||
|
|
||||
+--produces--+
|
||||
|
|
||||
v
|
||||
sdhci
|
||||
^
|
||||
|
|
||||
+--produces-- +
|
||||
|
|
||||
arm/raspi2 --contains--> generic-sdhci
|
||||
|
||||
or inverting the consumes edge in consumed_by::
|
||||
|
||||
x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc
|
||||
|
|
||||
sdhci-pci <--consumed by-- pci-bus <--produces--+
|
||||
|
|
||||
+--produces--+
|
||||
|
|
||||
v
|
||||
sdhci
|
||||
^
|
||||
|
|
||||
+--produces-- +
|
||||
|
|
||||
arm/raspi2 --contains--> generic-sdhci
|
||||
|
||||
Adding a new test
|
||||
"""""""""""""""""
|
||||
|
||||
Given the above setup, adding a new test is very simple.
|
||||
``sdhci-test``, taken from ``tests/qtest/sdhci-test.c``::
|
||||
|
||||
static void check_capab_sdma(QSDHCI *s, bool supported)
|
||||
{
|
||||
uint64_t capab, capab_sdma;
|
||||
|
||||
capab = s->readq(s, SDHC_CAPAB);
|
||||
capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA);
|
||||
g_assert_cmpuint(capab_sdma, ==, supported);
|
||||
}
|
||||
|
||||
static void test_registers(void *obj, void *data,
|
||||
QGuestAllocator *alloc)
|
||||
{
|
||||
QSDHCI *s = obj;
|
||||
|
||||
/* example test */
|
||||
check_capab_sdma(s, s->props.capab.sdma);
|
||||
}
|
||||
|
||||
static void register_sdhci_test(void)
|
||||
{
|
||||
/* sdhci-test --consumes--> sdhci */
|
||||
qos_add_test("registers", "sdhci", test_registers, NULL);
|
||||
}
|
||||
|
||||
libqos_init(register_sdhci_test);
|
||||
|
||||
Here a new test is created, consuming ``sdhci`` interface node
|
||||
and creating a valid path from both machines to a test.
|
||||
Final graph will be like this::
|
||||
|
||||
x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc
|
||||
|
|
||||
sdhci-pci --consumes--> pci-bus <--produces--+
|
||||
|
|
||||
+--produces--+
|
||||
|
|
||||
v
|
||||
sdhci <--consumes-- sdhci-test
|
||||
^
|
||||
|
|
||||
+--produces-- +
|
||||
|
|
||||
arm/raspi2 --contains--> generic-sdhci
|
||||
|
||||
or inverting the consumes edge in consumed_by::
|
||||
|
||||
x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc
|
||||
|
|
||||
sdhci-pci <--consumed by-- pci-bus <--produces--+
|
||||
|
|
||||
+--produces--+
|
||||
|
|
||||
v
|
||||
sdhci --consumed by--> sdhci-test
|
||||
^
|
||||
|
|
||||
+--produces-- +
|
||||
|
|
||||
arm/raspi2 --contains--> generic-sdhci
|
||||
|
||||
Assuming there the binary is
|
||||
``QTEST_QEMU_BINARY=./qemu-system-x86_64``
|
||||
a valid test path will be:
|
||||
``/x86_64/pc/1440FX-pcihost/pci-bus-pc/pci-bus/sdhci-pc/sdhci/sdhci-test``
|
||||
|
||||
and for the binary ``QTEST_QEMU_BINARY=./qemu-system-arm``:
|
||||
|
||||
``/arm/raspi2/generic-sdhci/sdhci/sdhci-test``
|
||||
|
||||
Additional examples are also in ``test-qgraph.c``
|
||||
|
||||
Command line:
|
||||
""""""""""""""
|
||||
|
||||
Command line is built by using node names and optional arguments
|
||||
passed by the user when building the edges.
|
||||
|
||||
There are three types of command line arguments:
|
||||
|
||||
- ``in node`` : created from the node name. For example, machines will
|
||||
have ``-M <machine>`` to its command line, while devices
|
||||
``-device <device>``. It is automatically done by the framework.
|
||||
- ``after node`` : added as additional argument to the node name.
|
||||
This argument is added optionally when creating edges,
|
||||
by setting the parameter ``after_cmd_line`` and
|
||||
``extra_edge_opts`` in ``QOSGraphEdgeOptions``.
|
||||
The framework automatically adds
|
||||
a comma before ``extra_edge_opts``,
|
||||
because it is going to add attributes
|
||||
after the destination node pointed by
|
||||
the edge containing these options, and automatically
|
||||
adds a space before ``after_cmd_line``, because it
|
||||
adds an additional device, not an attribute.
|
||||
- ``before node`` : added as additional argument to the node name.
|
||||
This argument is added optionally when creating edges,
|
||||
by setting the parameter ``before_cmd_line`` in
|
||||
``QOSGraphEdgeOptions``. This attribute
|
||||
is going to add attributes before the destination node
|
||||
pointed by the edge containing these options. It is
|
||||
helpful to commands that are not node-representable,
|
||||
such as ``-fdsev`` or ``-netdev``.
|
||||
|
||||
While adding command line in edges is always used, not all nodes names are
|
||||
used in every path walk: this is because the contained or produced ones
|
||||
are already added by QEMU, so only nodes that "consumes" will be used to
|
||||
build the command line. Also, nodes that will have ``{ "abstract" : true }``
|
||||
as QMP attribute will loose their command line, since they are not proper
|
||||
devices to be added in QEMU.
|
||||
|
||||
Example::
|
||||
|
||||
QOSGraphEdgeOptions opts = {
|
||||
.before_cmd_line = "-drive id=drv0,if=none,file=null-co://,"
|
||||
"file.read-zeroes=on,format=raw",
|
||||
.after_cmd_line = "-device scsi-hd,bus=vs0.0,drive=drv0",
|
||||
|
||||
opts.extra_device_opts = "id=vs0";
|
||||
};
|
||||
|
||||
qos_node_create_driver("virtio-scsi-device",
|
||||
virtio_scsi_device_create);
|
||||
qos_node_consumes("virtio-scsi-device", "virtio-bus", &opts);
|
||||
|
||||
Will produce the following command line:
|
||||
``-drive id=drv0,if=none,file=null-co://, -device virtio-scsi-device,id=vs0 -device scsi-hd,bus=vs0.0,drive=drv0``
|
||||
|
||||
Qgraph API reference
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. kernel-doc:: tests/qtest/libqos/qgraph.h
|
@ -2,6 +2,11 @@
|
||||
QTest Device Emulation Testing Framework
|
||||
========================================
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
qgraph
|
||||
|
||||
QTest is a device emulation testing framework. It can be very useful to test
|
||||
device models; it could also control certain aspects of QEMU (such as virtual
|
||||
clock stepping), with a special purpose "qtest" protocol. Refer to
|
||||
@ -24,6 +29,9 @@ On top of libqtest, a higher level library, ``libqos``, was created to
|
||||
encapsulate common tasks of device drivers, such as memory management and
|
||||
communicating with system buses or devices. Many virtual device tests use
|
||||
libqos instead of directly calling into libqtest.
|
||||
Libqos also offers the Qgraph API to increase each test coverage and
|
||||
automate QEMU command line arguments and devices setup.
|
||||
Refer to :ref:`qgraph` for Qgraph explanation and API.
|
||||
|
||||
Steps to add a new QTest case are:
|
||||
|
||||
|
@ -402,14 +402,6 @@ it out of sheepdog volumes into an alternative storage backend.
|
||||
linux-user mode CPUs
|
||||
--------------------
|
||||
|
||||
``tilegx`` CPUs (since 5.1.0)
|
||||
'''''''''''''''''''''''''''''
|
||||
|
||||
The ``tilegx`` guest CPU support (which was only implemented in
|
||||
linux-user mode) is deprecated and will be removed in a future version
|
||||
of QEMU. Support for this CPU was removed from the upstream Linux
|
||||
kernel in 2018, and has also been dropped from glibc.
|
||||
|
||||
``ppc64abi32`` CPUs (since 5.2.0)
|
||||
'''''''''''''''''''''''''''''''''
|
||||
|
||||
|
@ -142,6 +142,20 @@ This machine has been renamed ``fuloong2e``.
|
||||
These machine types were very old and likely could not be used for live
|
||||
migration from old QEMU versions anymore. Use a newer machine type instead.
|
||||
|
||||
|
||||
linux-user mode CPUs
|
||||
--------------------
|
||||
|
||||
``tilegx`` CPUs (removed in 6.0)
|
||||
''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``tilegx`` guest CPU support has been removed without replacement. It was
|
||||
only implemented in linux-user mode, but support for this CPU was removed from
|
||||
the upstream Linux kernel in 2018, and it has also been dropped from glibc, so
|
||||
there is no new Linux development taking place with this architecture. For
|
||||
running the old binaries, you can use older versions of QEMU.
|
||||
|
||||
|
||||
Related binaries
|
||||
----------------
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "coth.h"
|
||||
#include "trace.h"
|
||||
#include "migration/blocker.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/xxhash.h"
|
||||
#include <math.h>
|
||||
#include <linux/limits.h>
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "hw/loader.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "elf.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "hw/block/flash.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/* Device addresses */
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "hw/boards.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/log.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "qom/object.h"
|
||||
#include "net/can_emu.h"
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "hw/audio/wm8750.h"
|
||||
#include "audio/audio.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
|
@ -58,7 +58,6 @@
|
||||
#include "sysemu/numa.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/xen.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "kvm/kvm_i386.h"
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
#include "hw/misc/ivshmem.h"
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "ppc405.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/ppc-uic.h"
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "trace.h"
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "ppc405.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/char/serial.h"
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "cpu-models.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/tcg.h"
|
||||
|
||||
#include "hw/ppc/spapr.h"
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "hw/pci/msix.h"
|
||||
#include "hw/vfio/vfio.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
bool spapr_phb_eeh_available(SpaprPhbState *sphb)
|
||||
{
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_vio.h"
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "chardev/char.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
static const MemMapEntry spike_memmap[] = {
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
|
@ -206,8 +206,6 @@ typedef struct mips_elf_abiflags_v0 {
|
||||
|
||||
#define EM_AARCH64 183
|
||||
|
||||
#define EM_TILEGX 191 /* TILE-Gx */
|
||||
|
||||
#define EM_MOXIE 223 /* Moxie processor family */
|
||||
#define EM_MOXIE_OLD 0xFEED
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#pragma GCC poison TARGET_SH4
|
||||
#pragma GCC poison TARGET_SPARC
|
||||
#pragma GCC poison TARGET_SPARC64
|
||||
#pragma GCC poison TARGET_TILEGX
|
||||
#pragma GCC poison TARGET_TRICORE
|
||||
#pragma GCC poison TARGET_UNICORE32
|
||||
#pragma GCC poison TARGET_XTENSA
|
||||
|
@ -1387,29 +1387,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
|
||||
#endif /* TARGET_S390X */
|
||||
|
||||
#ifdef TARGET_TILEGX
|
||||
|
||||
/* 42 bits real used address, a half for user mode */
|
||||
#define ELF_START_MMAP (0x00000020000000000ULL)
|
||||
|
||||
#define elf_check_arch(x) ((x) == EM_TILEGX)
|
||||
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#define ELF_DATA ELFDATA2LSB
|
||||
#define ELF_ARCH EM_TILEGX
|
||||
|
||||
static inline void init_thread(struct target_pt_regs *regs,
|
||||
struct image_info *infop)
|
||||
{
|
||||
regs->pc = infop->entry;
|
||||
regs->sp = infop->start_stack;
|
||||
|
||||
}
|
||||
|
||||
#define ELF_EXEC_PAGESIZE 65536 /* TILE-Gx page size is 64KB */
|
||||
|
||||
#endif /* TARGET_TILEGX */
|
||||
|
||||
#ifdef TARGET_RISCV
|
||||
|
||||
#define ELF_START_MMAP 0x80000000
|
||||
|
@ -72,8 +72,7 @@
|
||||
|
||||
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
|
||||
|| defined(TARGET_M68K) || defined(TARGET_CRIS) \
|
||||
|| defined(TARGET_S390X) \
|
||||
|| defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
|
||||
|| defined(TARGET_S390X) || defined(TARGET_OPENRISC) \
|
||||
|| defined(TARGET_NIOS2) || defined(TARGET_RISCV) \
|
||||
|| defined(TARGET_XTENSA)
|
||||
|
||||
@ -691,10 +690,6 @@ typedef struct target_siginfo {
|
||||
#define TARGET_ILL_PRVREG (6) /* privileged register */
|
||||
#define TARGET_ILL_COPROC (7) /* coprocessor error */
|
||||
#define TARGET_ILL_BADSTK (8) /* internal stack error */
|
||||
#ifdef TARGET_TILEGX
|
||||
#define TARGET_ILL_DBLFLT (9) /* double fault */
|
||||
#define TARGET_ILL_HARDWALL (10) /* user networks hardwall violation */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
@ -2149,8 +2144,7 @@ struct target_stat64 {
|
||||
abi_ulong __unused5;
|
||||
};
|
||||
|
||||
#elif defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) || \
|
||||
defined(TARGET_NIOS2) || defined(TARGET_RISCV)
|
||||
#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV)
|
||||
|
||||
/* These are the asm-generic versions of the stat and stat64 structures */
|
||||
|
||||
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* qemu user cpu loop
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu.h"
|
||||
#include "cpu_loop-common.h"
|
||||
|
||||
static void gen_sigill_reg(CPUTLGState *env)
|
||||
{
|
||||
target_siginfo_t info;
|
||||
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_PRVREG;
|
||||
info._sifields._sigfault._addr = env->pc;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
|
||||
static void do_signal(CPUTLGState *env, int signo, int sigcode)
|
||||
{
|
||||
target_siginfo_t info;
|
||||
|
||||
info.si_signo = signo;
|
||||
info.si_errno = 0;
|
||||
info._sifields._sigfault._addr = env->pc;
|
||||
|
||||
if (signo == TARGET_SIGSEGV) {
|
||||
/* The passed in sigcode is a dummy; check for a page mapping
|
||||
and pass either MAPERR or ACCERR. */
|
||||
target_ulong addr = env->excaddr;
|
||||
info._sifields._sigfault._addr = addr;
|
||||
if (page_check_range(addr, 1, PAGE_VALID) < 0) {
|
||||
sigcode = TARGET_SEGV_MAPERR;
|
||||
} else {
|
||||
sigcode = TARGET_SEGV_ACCERR;
|
||||
}
|
||||
}
|
||||
info.si_code = sigcode;
|
||||
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
|
||||
static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr)
|
||||
{
|
||||
env->excaddr = addr;
|
||||
do_signal(env, TARGET_SIGSEGV, 0);
|
||||
}
|
||||
|
||||
static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val)
|
||||
{
|
||||
if (unlikely(reg >= TILEGX_R_COUNT)) {
|
||||
switch (reg) {
|
||||
case TILEGX_R_SN:
|
||||
case TILEGX_R_ZERO:
|
||||
return;
|
||||
case TILEGX_R_IDN0:
|
||||
case TILEGX_R_IDN1:
|
||||
case TILEGX_R_UDN0:
|
||||
case TILEGX_R_UDN1:
|
||||
case TILEGX_R_UDN2:
|
||||
case TILEGX_R_UDN3:
|
||||
gen_sigill_reg(env);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
env->regs[reg] = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the 8-byte contents of the CmpValue SPR with the 8-byte value in
|
||||
* memory at the address held in the first source register. If the values are
|
||||
* not equal, then no memory operation is performed. If the values are equal,
|
||||
* the 8-byte quantity from the second source register is written into memory
|
||||
* at the address held in the first source register. In either case, the result
|
||||
* of the instruction is the value read from memory. The compare and write to
|
||||
* memory are atomic and thus can be used for synchronization purposes. This
|
||||
* instruction only operates for addresses aligned to a 8-byte boundary.
|
||||
* Unaligned memory access causes an Unaligned Data Reference interrupt.
|
||||
*
|
||||
* Functional Description (64-bit)
|
||||
* uint64_t memVal = memoryReadDoubleWord (rf[SrcA]);
|
||||
* rf[Dest] = memVal;
|
||||
* if (memVal == SPR[CmpValueSPR])
|
||||
* memoryWriteDoubleWord (rf[SrcA], rf[SrcB]);
|
||||
*
|
||||
* Functional Description (32-bit)
|
||||
* uint64_t memVal = signExtend32 (memoryReadWord (rf[SrcA]));
|
||||
* rf[Dest] = memVal;
|
||||
* if (memVal == signExtend32 (SPR[CmpValueSPR]))
|
||||
* memoryWriteWord (rf[SrcA], rf[SrcB]);
|
||||
*
|
||||
*
|
||||
* This function also processes exch and exch4 which need not process SPR.
|
||||
*/
|
||||
static void do_exch(CPUTLGState *env, bool quad, bool cmp)
|
||||
{
|
||||
target_ulong addr;
|
||||
target_long val, sprval;
|
||||
|
||||
start_exclusive();
|
||||
|
||||
addr = env->atomic_srca;
|
||||
if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
|
||||
goto sigsegv_maperr;
|
||||
}
|
||||
|
||||
if (cmp) {
|
||||
if (quad) {
|
||||
sprval = env->spregs[TILEGX_SPR_CMPEXCH];
|
||||
} else {
|
||||
sprval = sextract64(env->spregs[TILEGX_SPR_CMPEXCH], 0, 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmp || val == sprval) {
|
||||
target_long valb = env->atomic_srcb;
|
||||
if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) {
|
||||
goto sigsegv_maperr;
|
||||
}
|
||||
}
|
||||
|
||||
set_regval(env, env->atomic_dstr, val);
|
||||
end_exclusive();
|
||||
return;
|
||||
|
||||
sigsegv_maperr:
|
||||
end_exclusive();
|
||||
gen_sigsegv_maperr(env, addr);
|
||||
}
|
||||
|
||||
static void do_fetch(CPUTLGState *env, int trapnr, bool quad)
|
||||
{
|
||||
int8_t write = 1;
|
||||
target_ulong addr;
|
||||
target_long val, valb;
|
||||
|
||||
start_exclusive();
|
||||
|
||||
addr = env->atomic_srca;
|
||||
valb = env->atomic_srcb;
|
||||
if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
|
||||
goto sigsegv_maperr;
|
||||
}
|
||||
|
||||
switch (trapnr) {
|
||||
case TILEGX_EXCP_OPCODE_FETCHADD:
|
||||
case TILEGX_EXCP_OPCODE_FETCHADD4:
|
||||
valb += val;
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_FETCHADDGEZ:
|
||||
valb += val;
|
||||
if (valb < 0) {
|
||||
write = 0;
|
||||
}
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_FETCHADDGEZ4:
|
||||
valb += val;
|
||||
if ((int32_t)valb < 0) {
|
||||
write = 0;
|
||||
}
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_FETCHAND:
|
||||
case TILEGX_EXCP_OPCODE_FETCHAND4:
|
||||
valb &= val;
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_FETCHOR:
|
||||
case TILEGX_EXCP_OPCODE_FETCHOR4:
|
||||
valb |= val;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (write) {
|
||||
if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) {
|
||||
goto sigsegv_maperr;
|
||||
}
|
||||
}
|
||||
|
||||
set_regval(env, env->atomic_dstr, val);
|
||||
end_exclusive();
|
||||
return;
|
||||
|
||||
sigsegv_maperr:
|
||||
end_exclusive();
|
||||
gen_sigsegv_maperr(env, addr);
|
||||
}
|
||||
|
||||
void cpu_loop(CPUTLGState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr;
|
||||
|
||||
while (1) {
|
||||
cpu_exec_start(cs);
|
||||
trapnr = cpu_exec(cs);
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case TILEGX_EXCP_SYSCALL:
|
||||
{
|
||||
abi_ulong ret = do_syscall(env, env->regs[TILEGX_R_NR],
|
||||
env->regs[0], env->regs[1],
|
||||
env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7]);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 8;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[TILEGX_R_RE] = ret;
|
||||
env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(ret) ? -ret : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TILEGX_EXCP_OPCODE_EXCH:
|
||||
do_exch(env, true, false);
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_EXCH4:
|
||||
do_exch(env, false, false);
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_CMPEXCH:
|
||||
do_exch(env, true, true);
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_CMPEXCH4:
|
||||
do_exch(env, false, true);
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_FETCHADD:
|
||||
case TILEGX_EXCP_OPCODE_FETCHADDGEZ:
|
||||
case TILEGX_EXCP_OPCODE_FETCHAND:
|
||||
case TILEGX_EXCP_OPCODE_FETCHOR:
|
||||
do_fetch(env, trapnr, true);
|
||||
break;
|
||||
case TILEGX_EXCP_OPCODE_FETCHADD4:
|
||||
case TILEGX_EXCP_OPCODE_FETCHADDGEZ4:
|
||||
case TILEGX_EXCP_OPCODE_FETCHAND4:
|
||||
case TILEGX_EXCP_OPCODE_FETCHOR4:
|
||||
do_fetch(env, trapnr, false);
|
||||
break;
|
||||
case TILEGX_EXCP_SIGNAL:
|
||||
do_signal(env, env->signo, env->sigcode);
|
||||
break;
|
||||
case TILEGX_EXCP_REG_IDN_ACCESS:
|
||||
case TILEGX_EXCP_REG_UDN_ACCESS:
|
||||
gen_sigill_reg(env);
|
||||
break;
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
process_pending_signals(env);
|
||||
}
|
||||
}
|
||||
|
||||
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TILEGX_R_COUNT; i++) {
|
||||
env->regs[i] = regs->regs[i];
|
||||
}
|
||||
for (i = 0; i < TILEGX_SPR_COUNT; i++) {
|
||||
env->spregs[i] = 0;
|
||||
}
|
||||
env->pc = regs->pc;
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Emulation of Linux signals
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "signal-common.h"
|
||||
#include "linux-user/trace.h"
|
||||
|
||||
struct target_sigcontext {
|
||||
union {
|
||||
/* General-purpose registers. */
|
||||
abi_ulong gregs[56];
|
||||
struct {
|
||||
abi_ulong __gregs[53];
|
||||
abi_ulong tp; /* Aliases gregs[TREG_TP]. */
|
||||
abi_ulong sp; /* Aliases gregs[TREG_SP]. */
|
||||
abi_ulong lr; /* Aliases gregs[TREG_LR]. */
|
||||
};
|
||||
};
|
||||
abi_ulong pc; /* Program counter. */
|
||||
abi_ulong ics; /* In Interrupt Critical Section? */
|
||||
abi_ulong faultnum; /* Fault number. */
|
||||
abi_ulong pad[5];
|
||||
};
|
||||
|
||||
struct target_ucontext {
|
||||
abi_ulong tuc_flags;
|
||||
abi_ulong tuc_link;
|
||||
target_stack_t tuc_stack;
|
||||
struct target_sigcontext tuc_mcontext;
|
||||
target_sigset_t tuc_sigmask; /* mask last for extensibility */
|
||||
};
|
||||
|
||||
struct target_rt_sigframe {
|
||||
unsigned char save_area[16]; /* caller save area */
|
||||
struct target_siginfo info;
|
||||
struct target_ucontext uc;
|
||||
abi_ulong retcode[2];
|
||||
};
|
||||
|
||||
#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
|
||||
#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
|
||||
|
||||
|
||||
static void setup_sigcontext(struct target_sigcontext *sc,
|
||||
CPUArchState *env, int signo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TILEGX_R_COUNT; ++i) {
|
||||
__put_user(env->regs[i], &sc->gregs[i]);
|
||||
}
|
||||
|
||||
__put_user(env->pc, &sc->pc);
|
||||
__put_user(0, &sc->ics);
|
||||
__put_user(signo, &sc->faultnum);
|
||||
}
|
||||
|
||||
static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TILEGX_R_COUNT; ++i) {
|
||||
__get_user(env->regs[i], &sc->gregs[i]);
|
||||
}
|
||||
|
||||
__get_user(env->pc, &sc->pc);
|
||||
}
|
||||
|
||||
static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp = get_sp_from_cpustate(env);
|
||||
|
||||
if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
|
||||
return -1UL;
|
||||
}
|
||||
|
||||
sp = target_sigsp(sp, ka) - frame_size;
|
||||
sp &= -16UL;
|
||||
return sp;
|
||||
}
|
||||
|
||||
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
target_siginfo_t *info,
|
||||
target_sigset_t *set, CPUArchState *env)
|
||||
{
|
||||
abi_ulong frame_addr;
|
||||
struct target_rt_sigframe *frame;
|
||||
unsigned long restorer;
|
||||
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
trace_user_setup_rt_frame(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
|
||||
goto give_sigsegv;
|
||||
}
|
||||
|
||||
/* Always write at least the signal number for the stack backtracer. */
|
||||
if (ka->sa_flags & TARGET_SA_SIGINFO) {
|
||||
/* At sigreturn time, restore the callee-save registers too. */
|
||||
tswap_siginfo(&frame->info, info);
|
||||
/* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
|
||||
} else {
|
||||
__put_user(info->si_signo, &frame->info.si_signo);
|
||||
}
|
||||
|
||||
/* Create the ucontext. */
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
__put_user(0, &frame->uc.tuc_link);
|
||||
target_save_altstack(&frame->uc.tuc_stack, env);
|
||||
setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
|
||||
|
||||
if (ka->sa_flags & TARGET_SA_RESTORER) {
|
||||
restorer = (unsigned long) ka->sa_restorer;
|
||||
} else {
|
||||
__put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
|
||||
__put_user(INSN_SWINT1, &frame->retcode[1]);
|
||||
restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
|
||||
}
|
||||
env->pc = (unsigned long) ka->_sa_handler;
|
||||
env->regs[TILEGX_R_SP] = (unsigned long) frame;
|
||||
env->regs[TILEGX_R_LR] = restorer;
|
||||
env->regs[0] = (unsigned long) sig;
|
||||
env->regs[1] = (unsigned long) &frame->info;
|
||||
env->regs[2] = (unsigned long) &frame->uc;
|
||||
/* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
return;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig);
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUTLGState *env)
|
||||
{
|
||||
abi_ulong frame_addr = env->regs[TILEGX_R_SP];
|
||||
struct target_rt_sigframe *frame;
|
||||
sigset_t set;
|
||||
|
||||
trace_user_do_rt_sigreturn(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||
goto badframe;
|
||||
}
|
||||
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
|
||||
set_sigmask(&set);
|
||||
|
||||
restore_sigcontext(env, &frame->uc.tuc_mcontext);
|
||||
if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
|
||||
uc.tuc_stack),
|
||||
0, env->regs[TILEGX_R_SP]) == -EFAULT) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
}
|
@ -1 +0,0 @@
|
||||
#include "../generic/sockbits.h"
|
@ -1,327 +0,0 @@
|
||||
#ifndef TILEGX_SYSCALL_NR_H
|
||||
#define TILEGX_SYSCALL_NR_H
|
||||
|
||||
/*
|
||||
* Copy from linux kernel asm-generic/unistd.h, which tilegx uses.
|
||||
*/
|
||||
#define TARGET_NR_io_setup 0
|
||||
#define TARGET_NR_io_destroy 1
|
||||
#define TARGET_NR_io_submit 2
|
||||
#define TARGET_NR_io_cancel 3
|
||||
#define TARGET_NR_io_getevents 4
|
||||
#define TARGET_NR_setxattr 5
|
||||
#define TARGET_NR_lsetxattr 6
|
||||
#define TARGET_NR_fsetxattr 7
|
||||
#define TARGET_NR_getxattr 8
|
||||
#define TARGET_NR_lgetxattr 9
|
||||
#define TARGET_NR_fgetxattr 10
|
||||
#define TARGET_NR_listxattr 11
|
||||
#define TARGET_NR_llistxattr 12
|
||||
#define TARGET_NR_flistxattr 13
|
||||
#define TARGET_NR_removexattr 14
|
||||
#define TARGET_NR_lremovexattr 15
|
||||
#define TARGET_NR_fremovexattr 16
|
||||
#define TARGET_NR_getcwd 17
|
||||
#define TARGET_NR_lookup_dcookie 18
|
||||
#define TARGET_NR_eventfd2 19
|
||||
#define TARGET_NR_epoll_create1 20
|
||||
#define TARGET_NR_epoll_ctl 21
|
||||
#define TARGET_NR_epoll_pwait 22
|
||||
#define TARGET_NR_dup 23
|
||||
#define TARGET_NR_dup3 24
|
||||
#define TARGET_NR_fcntl 25
|
||||
#define TARGET_NR_inotify_init1 26
|
||||
#define TARGET_NR_inotify_add_watch 27
|
||||
#define TARGET_NR_inotify_rm_watch 28
|
||||
#define TARGET_NR_ioctl 29
|
||||
#define TARGET_NR_ioprio_set 30
|
||||
#define TARGET_NR_ioprio_get 31
|
||||
#define TARGET_NR_flock 32
|
||||
#define TARGET_NR_mknodat 33
|
||||
#define TARGET_NR_mkdirat 34
|
||||
#define TARGET_NR_unlinkat 35
|
||||
#define TARGET_NR_symlinkat 36
|
||||
#define TARGET_NR_linkat 37
|
||||
#define TARGET_NR_renameat 38
|
||||
#define TARGET_NR_umount2 39
|
||||
#define TARGET_NR_mount 40
|
||||
#define TARGET_NR_pivot_root 41
|
||||
#define TARGET_NR_nfsservctl 42
|
||||
#define TARGET_NR_statfs 43
|
||||
#define TARGET_NR_fstatfs 44
|
||||
#define TARGET_NR_truncate 45
|
||||
#define TARGET_NR_ftruncate 46
|
||||
#define TARGET_NR_fallocate 47
|
||||
#define TARGET_NR_faccessat 48
|
||||
#define TARGET_NR_chdir 49
|
||||
#define TARGET_NR_fchdir 50
|
||||
#define TARGET_NR_chroot 51
|
||||
#define TARGET_NR_fchmod 52
|
||||
#define TARGET_NR_fchmodat 53
|
||||
#define TARGET_NR_fchownat 54
|
||||
#define TARGET_NR_fchown 55
|
||||
#define TARGET_NR_openat 56
|
||||
#define TARGET_NR_close 57
|
||||
#define TARGET_NR_vhangup 58
|
||||
#define TARGET_NR_pipe2 59
|
||||
#define TARGET_NR_quotactl 60
|
||||
#define TARGET_NR_getdents64 61
|
||||
#define TARGET_NR_lseek 62
|
||||
#define TARGET_NR_read 63
|
||||
#define TARGET_NR_write 64
|
||||
#define TARGET_NR_readv 65
|
||||
#define TARGET_NR_writev 66
|
||||
#define TARGET_NR_pread64 67
|
||||
#define TARGET_NR_pwrite64 68
|
||||
#define TARGET_NR_preadv 69
|
||||
#define TARGET_NR_pwritev 70
|
||||
#define TARGET_NR_sendfile 71
|
||||
#define TARGET_NR_pselect6 72
|
||||
#define TARGET_NR_ppoll 73
|
||||
#define TARGET_NR_signalfd4 74
|
||||
#define TARGET_NR_vmsplice 75
|
||||
#define TARGET_NR_splice 76
|
||||
#define TARGET_NR_tee 77
|
||||
#define TARGET_NR_readlinkat 78
|
||||
#define TARGET_NR_fstatat64 79 /* let syscall.c known */
|
||||
#define TARGET_NR_fstat 80
|
||||
#define TARGET_NR_sync 81
|
||||
#define TARGET_NR_fsync 82
|
||||
#define TARGET_NR_fdatasync 83
|
||||
#define TARGET_NR_sync_file_range 84 /* For tilegx, no range2 */
|
||||
#define TARGET_NR_timerfd_create 85
|
||||
#define TARGET_NR_timerfd_settime 86
|
||||
#define TARGET_NR_timerfd_gettime 87
|
||||
#define TARGET_NR_utimensat 88
|
||||
#define TARGET_NR_acct 89
|
||||
#define TARGET_NR_capget 90
|
||||
#define TARGET_NR_capset 91
|
||||
#define TARGET_NR_personality 92
|
||||
#define TARGET_NR_exit 93
|
||||
#define TARGET_NR_exit_group 94
|
||||
#define TARGET_NR_waitid 95
|
||||
#define TARGET_NR_set_tid_address 96
|
||||
#define TARGET_NR_unshare 97
|
||||
#define TARGET_NR_futex 98
|
||||
#define TARGET_NR_set_robust_list 99
|
||||
#define TARGET_NR_get_robust_list 100
|
||||
#define TARGET_NR_nanosleep 101
|
||||
#define TARGET_NR_getitimer 102
|
||||
#define TARGET_NR_setitimer 103
|
||||
#define TARGET_NR_kexec_load 104
|
||||
#define TARGET_NR_init_module 105
|
||||
#define TARGET_NR_delete_module 106
|
||||
#define TARGET_NR_timer_create 107
|
||||
#define TARGET_NR_timer_gettime 108
|
||||
#define TARGET_NR_timer_getoverrun 109
|
||||
#define TARGET_NR_timer_settime 110
|
||||
#define TARGET_NR_timer_delete 111
|
||||
#define TARGET_NR_clock_settime 112
|
||||
#define TARGET_NR_clock_gettime 113
|
||||
#define TARGET_NR_clock_getres 114
|
||||
#define TARGET_NR_clock_nanosleep 115
|
||||
#define TARGET_NR_syslog 116
|
||||
#define TARGET_NR_ptrace 117
|
||||
#define TARGET_NR_sched_setparam 118
|
||||
#define TARGET_NR_sched_setscheduler 119
|
||||
#define TARGET_NR_sched_getscheduler 120
|
||||
#define TARGET_NR_sched_getparam 121
|
||||
#define TARGET_NR_sched_setaffinity 122
|
||||
#define TARGET_NR_sched_getaffinity 123
|
||||
#define TARGET_NR_sched_yield 124
|
||||
#define TARGET_NR_sched_get_priority_max 125
|
||||
#define TARGET_NR_sched_get_priority_min 126
|
||||
#define TARGET_NR_sched_rr_get_interval 127
|
||||
#define TARGET_NR_restart_syscall 128
|
||||
#define TARGET_NR_kill 129
|
||||
#define TARGET_NR_tkill 130
|
||||
#define TARGET_NR_tgkill 131
|
||||
#define TARGET_NR_sigaltstack 132
|
||||
#define TARGET_NR_rt_sigsuspend 133
|
||||
#define TARGET_NR_rt_sigaction 134
|
||||
#define TARGET_NR_rt_sigprocmask 135
|
||||
#define TARGET_NR_rt_sigpending 136
|
||||
#define TARGET_NR_rt_sigtimedwait 137
|
||||
#define TARGET_NR_rt_sigqueueinfo 138
|
||||
#define TARGET_NR_rt_sigreturn 139
|
||||
#define TARGET_NR_setpriority 140
|
||||
#define TARGET_NR_getpriority 141
|
||||
#define TARGET_NR_reboot 142
|
||||
#define TARGET_NR_setregid 143
|
||||
#define TARGET_NR_setgid 144
|
||||
#define TARGET_NR_setreuid 145
|
||||
#define TARGET_NR_setuid 146
|
||||
#define TARGET_NR_setresuid 147
|
||||
#define TARGET_NR_getresuid 148
|
||||
#define TARGET_NR_setresgid 149
|
||||
#define TARGET_NR_getresgid 150
|
||||
#define TARGET_NR_setfsuid 151
|
||||
#define TARGET_NR_setfsgid 152
|
||||
#define TARGET_NR_times 153
|
||||
#define TARGET_NR_setpgid 154
|
||||
#define TARGET_NR_getpgid 155
|
||||
#define TARGET_NR_getsid 156
|
||||
#define TARGET_NR_setsid 157
|
||||
#define TARGET_NR_getgroups 158
|
||||
#define TARGET_NR_setgroups 159
|
||||
#define TARGET_NR_uname 160
|
||||
#define TARGET_NR_sethostname 161
|
||||
#define TARGET_NR_setdomainname 162
|
||||
#define TARGET_NR_getrlimit 163
|
||||
#define TARGET_NR_setrlimit 164
|
||||
#define TARGET_NR_getrusage 165
|
||||
#define TARGET_NR_umask 166
|
||||
#define TARGET_NR_prctl 167
|
||||
#define TARGET_NR_getcpu 168
|
||||
#define TARGET_NR_gettimeofday 169
|
||||
#define TARGET_NR_settimeofday 170
|
||||
#define TARGET_NR_adjtimex 171
|
||||
#define TARGET_NR_getpid 172
|
||||
#define TARGET_NR_getppid 173
|
||||
#define TARGET_NR_getuid 174
|
||||
#define TARGET_NR_geteuid 175
|
||||
#define TARGET_NR_getgid 176
|
||||
#define TARGET_NR_getegid 177
|
||||
#define TARGET_NR_gettid 178
|
||||
#define TARGET_NR_sysinfo 179
|
||||
#define TARGET_NR_mq_open 180
|
||||
#define TARGET_NR_mq_unlink 181
|
||||
#define TARGET_NR_mq_timedsend 182
|
||||
#define TARGET_NR_mq_timedreceive 183
|
||||
#define TARGET_NR_mq_notify 184
|
||||
#define TARGET_NR_mq_getsetattr 185
|
||||
#define TARGET_NR_msgget 186
|
||||
#define TARGET_NR_msgctl 187
|
||||
#define TARGET_NR_msgrcv 188
|
||||
#define TARGET_NR_msgsnd 189
|
||||
#define TARGET_NR_semget 190
|
||||
#define TARGET_NR_semctl 191
|
||||
#define TARGET_NR_semtimedop 192
|
||||
#define TARGET_NR_semop 193
|
||||
#define TARGET_NR_shmget 194
|
||||
#define TARGET_NR_shmctl 195
|
||||
#define TARGET_NR_shmat 196
|
||||
#define TARGET_NR_shmdt 197
|
||||
#define TARGET_NR_socket 198
|
||||
#define TARGET_NR_socketpair 199
|
||||
#define TARGET_NR_bind 200
|
||||
#define TARGET_NR_listen 201
|
||||
#define TARGET_NR_accept 202
|
||||
#define TARGET_NR_connect 203
|
||||
#define TARGET_NR_getsockname 204
|
||||
#define TARGET_NR_getpeername 205
|
||||
#define TARGET_NR_sendto 206
|
||||
#define TARGET_NR_recvfrom 207
|
||||
#define TARGET_NR_setsockopt 208
|
||||
#define TARGET_NR_getsockopt 209
|
||||
#define TARGET_NR_shutdown 210
|
||||
#define TARGET_NR_sendmsg 211
|
||||
#define TARGET_NR_recvmsg 212
|
||||
#define TARGET_NR_readahead 213
|
||||
#define TARGET_NR_brk 214
|
||||
#define TARGET_NR_munmap 215
|
||||
#define TARGET_NR_mremap 216
|
||||
#define TARGET_NR_add_key 217
|
||||
#define TARGET_NR_request_key 218
|
||||
#define TARGET_NR_keyctl 219
|
||||
#define TARGET_NR_clone 220
|
||||
#define TARGET_NR_execve 221
|
||||
#define TARGET_NR_mmap 222
|
||||
#define TARGET_NR_fadvise64 223
|
||||
#define TARGET_NR_swapon 224
|
||||
#define TARGET_NR_swapoff 225
|
||||
#define TARGET_NR_mprotect 226
|
||||
#define TARGET_NR_msync 227
|
||||
#define TARGET_NR_mlock 228
|
||||
#define TARGET_NR_munlock 229
|
||||
#define TARGET_NR_mlockall 230
|
||||
#define TARGET_NR_munlockall 231
|
||||
#define TARGET_NR_mincore 232
|
||||
#define TARGET_NR_madvise 233
|
||||
#define TARGET_NR_remap_file_pages 234
|
||||
#define TARGET_NR_mbind 235
|
||||
#define TARGET_NR_get_mempolicy 236
|
||||
#define TARGET_NR_set_mempolicy 237
|
||||
#define TARGET_NR_migrate_pages 238
|
||||
#define TARGET_NR_move_pages 239
|
||||
#define TARGET_NR_rt_tgsigqueueinfo 240
|
||||
#define TARGET_NR_perf_event_open 241
|
||||
#define TARGET_NR_accept4 242
|
||||
#define TARGET_NR_recvmmsg 243
|
||||
|
||||
#define TARGET_NR_arch_specific_syscall 244
|
||||
#define TARGET_NR_cacheflush 245 /* tilegx own syscall */
|
||||
|
||||
#define TARGET_NR_wait4 260
|
||||
#define TARGET_NR_prlimit64 261
|
||||
#define TARGET_NR_fanotify_init 262
|
||||
#define TARGET_NR_fanotify_mark 263
|
||||
#define TARGET_NR_name_to_handle_at 264
|
||||
#define TARGET_NR_open_by_handle_at 265
|
||||
#define TARGET_NR_clock_adjtime 266
|
||||
#define TARGET_NR_syncfs 267
|
||||
#define TARGET_NR_setns 268
|
||||
#define TARGET_NR_sendmmsg 269
|
||||
#define TARGET_NR_process_vm_readv 270
|
||||
#define TARGET_NR_process_vm_writev 271
|
||||
#define TARGET_NR_kcmp 272
|
||||
#define TARGET_NR_finit_module 273
|
||||
#define TARGET_NR_sched_setattr 274
|
||||
#define TARGET_NR_sched_getattr 275
|
||||
#define TARGET_NR_renameat2 276
|
||||
#define TARGET_NR_seccomp 277
|
||||
#define TARGET_NR_getrandom 278
|
||||
#define TARGET_NR_memfd_create 279
|
||||
#define TARGET_NR_bpf 280
|
||||
#define TARGET_NR_execveat 281
|
||||
#define TARGET_NR_userfaultfd 282
|
||||
#define TARGET_NR_membarrier 283
|
||||
#define TARGET_NR_mlock2 284
|
||||
#define TARGET_NR_copy_file_range 285
|
||||
|
||||
#define TARGET_NR_open 1024
|
||||
#define TARGET_NR_link 1025
|
||||
#define TARGET_NR_unlink 1026
|
||||
#define TARGET_NR_mknod 1027
|
||||
#define TARGET_NR_chmod 1028
|
||||
#define TARGET_NR_chown 1029
|
||||
#define TARGET_NR_mkdir 1030
|
||||
#define TARGET_NR_rmdir 1031
|
||||
#define TARGET_NR_lchown 1032
|
||||
#define TARGET_NR_access 1033
|
||||
#define TARGET_NR_rename 1034
|
||||
#define TARGET_NR_readlink 1035
|
||||
#define TARGET_NR_symlink 1036
|
||||
#define TARGET_NR_utimes 1037
|
||||
#define TARGET_NR_stat64 1038 /* let syscall.c known */
|
||||
#define TARGET_NR_lstat 1039
|
||||
|
||||
#define TARGET_NR_pipe 1040
|
||||
#define TARGET_NR_dup2 1041
|
||||
#define TARGET_NR_epoll_create 1042
|
||||
#define TARGET_NR_inotify_init 1043
|
||||
#define TARGET_NR_eventfd 1044
|
||||
#define TARGET_NR_signalfd 1045
|
||||
|
||||
#define TARGET_NR_alarm 1059
|
||||
#define TARGET_NR_getpgrp 1060
|
||||
#define TARGET_NR_pause 1061
|
||||
#define TARGET_NR_time 1062
|
||||
#define TARGET_NR_utime 1063
|
||||
#define TARGET_NR_creat 1064
|
||||
#define TARGET_NR_getdents 1065
|
||||
#define TARGET_NR_futimesat 1066
|
||||
#define TARGET_NR_poll 1068
|
||||
#define TARGET_NR_epoll_wait 1069
|
||||
#define TARGET_NR_ustat 1070
|
||||
#define TARGET_NR_vfork 1071
|
||||
#define TARGET_NR_oldwait4 1072
|
||||
#define TARGET_NR_recv 1073
|
||||
#define TARGET_NR_send 1074
|
||||
#define TARGET_NR_bdflush 1075
|
||||
#define TARGET_NR_umount 1076
|
||||
#define TARGET_NR_uselib 1077
|
||||
#define TARGET_NR__sysctl 1078
|
||||
#define TARGET_NR_fork 1079
|
||||
|
||||
#endif
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* TILE-Gx specific CPU ABI and functions for linux-user
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TILEGX_TARGET_CPU_H
|
||||
#define TILEGX_TARGET_CPU_H
|
||||
|
||||
static inline void cpu_clone_regs_child(CPUTLGState *env, target_ulong newsp,
|
||||
unsigned flags)
|
||||
{
|
||||
if (newsp) {
|
||||
env->regs[TILEGX_R_SP] = newsp;
|
||||
}
|
||||
env->regs[TILEGX_R_RE] = 0;
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_parent(CPUTLGState *env, unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cpu_set_tls(CPUTLGState *env, target_ulong newtls)
|
||||
{
|
||||
env->regs[TILEGX_R_TP] = newtls;
|
||||
}
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUTLGState *state)
|
||||
{
|
||||
return state->regs[TILEGX_R_SP];
|
||||
}
|
||||
#endif
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TILEGX_TARGET_ELF_H
|
||||
#define TILEGX_TARGET_ELF_H
|
||||
static inline const char *cpu_get_model(uint32_t eflags)
|
||||
{
|
||||
return "any";
|
||||
}
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TILEGX_TARGET_FCNTL_H
|
||||
#define TILEGX_TARGET_FCNTL_H
|
||||
#include "../generic/fcntl.h"
|
||||
#endif
|
@ -1,23 +0,0 @@
|
||||
#ifndef TILEGX_TARGET_SIGNAL_H
|
||||
#define TILEGX_TARGET_SIGNAL_H
|
||||
|
||||
/* this struct defines a stack used during syscall handling */
|
||||
|
||||
typedef struct target_sigaltstack {
|
||||
abi_ulong ss_sp;
|
||||
abi_int ss_flags;
|
||||
abi_ulong ss_size;
|
||||
} target_stack_t;
|
||||
|
||||
/*
|
||||
* sigaltstack controls
|
||||
*/
|
||||
#define TARGET_SS_ONSTACK 1
|
||||
#define TARGET_SS_DISABLE 2
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_SIGSTKSZ 8192
|
||||
|
||||
#include "../generic/signal.h"
|
||||
|
||||
#endif /* TILEGX_TARGET_SIGNAL_H */
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* TILE-Gx specific structures for linux-user
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TILEGX_TARGET_STRUCTS_H
|
||||
#define TILEGX_TARGET_STRUCTS_H
|
||||
|
||||
struct target_ipc_perm {
|
||||
abi_int __key; /* Key. */
|
||||
abi_uint uid; /* Owner's user ID. */
|
||||
abi_uint gid; /* Owner's group ID. */
|
||||
abi_uint cuid; /* Creator's user ID. */
|
||||
abi_uint cgid; /* Creator's group ID. */
|
||||
abi_uint mode; /* Read/write permission. */
|
||||
abi_ushort __seq; /* Sequence number. */
|
||||
};
|
||||
|
||||
struct target_shmid_ds {
|
||||
struct target_ipc_perm shm_perm; /* operation permission struct */
|
||||
abi_long shm_segsz; /* size of segment in bytes */
|
||||
abi_ulong shm_atime; /* time of last shmat() */
|
||||
abi_ulong shm_dtime; /* time of last shmdt() */
|
||||
abi_ulong shm_ctime; /* time of last change by shmctl() */
|
||||
abi_int shm_cpid; /* pid of creator */
|
||||
abi_int shm_lpid; /* pid of last shmop */
|
||||
abi_ushort shm_nattch; /* number of current attaches */
|
||||
abi_ushort shm_unused; /* compatibility */
|
||||
abi_ulong __unused4;
|
||||
abi_ulong __unused5;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,44 +0,0 @@
|
||||
#ifndef TILEGX_TARGET_SYSCALL_H
|
||||
#define TILEGX_TARGET_SYSCALL_H
|
||||
|
||||
#define UNAME_MACHINE "tilegx"
|
||||
#define UNAME_MINIMUM_RELEASE "3.19"
|
||||
|
||||
#define MMAP_SHIFT TARGET_PAGE_BITS
|
||||
|
||||
#define TILEGX_IS_ERRNO(ret) \
|
||||
((ret) > 0xfffffffffffff000ULL) /* errno is 0 -- 4096 */
|
||||
|
||||
typedef uint64_t tilegx_reg_t;
|
||||
|
||||
struct target_pt_regs {
|
||||
|
||||
union {
|
||||
/* Saved main processor registers; 56..63 are special. */
|
||||
tilegx_reg_t regs[56];
|
||||
struct {
|
||||
tilegx_reg_t __regs[53];
|
||||
tilegx_reg_t tp; /* aliases regs[TREG_TP] */
|
||||
tilegx_reg_t sp; /* aliases regs[TREG_SP] */
|
||||
tilegx_reg_t lr; /* aliases regs[TREG_LR] */
|
||||
};
|
||||
};
|
||||
|
||||
/* Saved special registers. */
|
||||
tilegx_reg_t pc; /* stored in EX_CONTEXT_K_0 */
|
||||
tilegx_reg_t ex1; /* stored in EX_CONTEXT_K_1 (PL and ICS bit) */
|
||||
tilegx_reg_t faultnum; /* fault number (INT_SWINT_1 for syscall) */
|
||||
tilegx_reg_t orig_r0; /* r0 at syscall entry, else zero */
|
||||
tilegx_reg_t flags; /* flags (see below) */
|
||||
tilegx_reg_t cmpexch; /* value of CMPEXCH_VALUE SPR at interrupt */
|
||||
tilegx_reg_t pad[2];
|
||||
};
|
||||
|
||||
#define TARGET_MCL_CURRENT 1
|
||||
#define TARGET_MCL_FUTURE 2
|
||||
#define TARGET_MCL_ONFAULT 4
|
||||
|
||||
/* For faultnum */
|
||||
#define TARGET_INT_SWINT_1 14
|
||||
|
||||
#endif
|
@ -1 +0,0 @@
|
||||
#include "../generic/termbits.h"
|
@ -50,7 +50,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "net/filter.h"
|
||||
|
@ -48,24 +48,35 @@ def get_local_branch_commit(branch):
|
||||
return result
|
||||
|
||||
|
||||
def get_json_http_response(url):
|
||||
"""
|
||||
Returns the JSON content of an HTTP GET request to gitlab.com
|
||||
"""
|
||||
connection = http.client.HTTPSConnection('gitlab.com')
|
||||
connection.request('GET', url=url)
|
||||
response = connection.getresponse()
|
||||
if response.code != http.HTTPStatus.OK:
|
||||
msg = "Received unsuccessful response: %s (%s)" % (response.code,
|
||||
response.reason)
|
||||
raise CommunicationFailure(msg)
|
||||
return json.loads(response.read())
|
||||
|
||||
|
||||
def get_pipeline_status(project_id, commit_sha1):
|
||||
"""
|
||||
Returns the JSON content of the pipeline status API response
|
||||
"""
|
||||
url = '/api/v4/projects/{}/pipelines?sha={}'.format(project_id,
|
||||
commit_sha1)
|
||||
connection = http.client.HTTPSConnection('gitlab.com')
|
||||
connection.request('GET', url=url)
|
||||
response = connection.getresponse()
|
||||
if response.code != http.HTTPStatus.OK:
|
||||
raise CommunicationFailure("Failed to receive a successful response")
|
||||
json_response = json.loads(response.read())
|
||||
json_response = get_json_http_response(url)
|
||||
|
||||
# As far as I can tell, there should be only one pipeline for the same
|
||||
# project + commit. If this assumption is false, we can add further
|
||||
# filters to the url, such as username, and order_by.
|
||||
if not json_response:
|
||||
raise NoPipelineFound("No pipeline found")
|
||||
msg = "No pipeline found for project %s and commit %s" % (project_id,
|
||||
commit_sha1)
|
||||
raise NoPipelineFound(msg)
|
||||
return json_response[0]
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ print('''
|
||||
SPEED = quick
|
||||
|
||||
# $1 = environment, $2 = test command, $3 = test name, $4 = dir
|
||||
.test-human-tap = $1 $(if $4,(cd $4 && $2),$2) < /dev/null | ./scripts/tap-driver.pl --test-name="$3" $(if $(V),,--show-failures-only)
|
||||
.test-human-tap = $1 $(if $4,(cd $4 && $2),$2) -m $(SPEED) < /dev/null | ./scripts/tap-driver.pl --test-name="$3" $(if $(V),,--show-failures-only)
|
||||
.test-human-exitcode = $1 $(PYTHON) scripts/test-driver.py $(if $4,-C$4) $(if $(V),--verbose) -- $2 < /dev/null
|
||||
.test-tap-tap = $1 $(if $4,(cd $4 && $2),$2) < /dev/null | sed "s/^[a-z][a-z]* [0-9]*/& $3/" || true
|
||||
.test-tap-exitcode = printf "%s\\n" 1..1 "`$1 $(if $4,(cd $4 && $2),$2) < /dev/null > /dev/null || echo "not "`ok 1 $3"
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/seqlock.h"
|
||||
|
@ -18,7 +18,6 @@ subdir('rx')
|
||||
subdir('s390x')
|
||||
subdir('sh4')
|
||||
subdir('sparc')
|
||||
subdir('tilegx')
|
||||
subdir('tricore')
|
||||
subdir('unicore32')
|
||||
subdir('xtensa')
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "mmu-book3s-v3.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "disas/capstone.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* TILE-Gx cpu parameters for qemu.
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
* SPDX-License-Identifier: LGPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef TILEGX_CPU_PARAM_H
|
||||
#define TILEGX_CPU_PARAM_H 1
|
||||
|
||||
#define TARGET_LONG_BITS 64
|
||||
#define TARGET_PAGE_BITS 16 /* TILE-Gx uses 64KB page size */
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 42
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 64
|
||||
#define NB_MMU_MODES 1
|
||||
|
||||
#endif
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* QEMU TILE-Gx CPU
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/module.h"
|
||||
#include "linux-user/syscall_defs.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
static void tilegx_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
{
|
||||
static const char * const reg_names[TILEGX_R_COUNT] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
||||
"r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
|
||||
"r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
|
||||
"r48", "r49", "r50", "r51", "bp", "tp", "sp", "lr"
|
||||
};
|
||||
|
||||
TileGXCPU *cpu = TILEGX_CPU(cs);
|
||||
CPUTLGState *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TILEGX_R_COUNT; i++) {
|
||||
qemu_fprintf(f, "%-4s" TARGET_FMT_lx "%s",
|
||||
reg_names[i], env->regs[i],
|
||||
(i % 4) == 3 ? "\n" : " ");
|
||||
}
|
||||
qemu_fprintf(f, "PC " TARGET_FMT_lx " CEX " TARGET_FMT_lx "\n\n",
|
||||
env->pc, env->spregs[TILEGX_SPR_CMPEXCH]);
|
||||
}
|
||||
|
||||
static ObjectClass *tilegx_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
return object_class_by_name(TYPE_TILEGX_CPU);
|
||||
}
|
||||
|
||||
static void tilegx_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
TileGXCPU *cpu = TILEGX_CPU(cs);
|
||||
|
||||
cpu->env.pc = value;
|
||||
}
|
||||
|
||||
static bool tilegx_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tilegx_cpu_reset(DeviceState *dev)
|
||||
{
|
||||
CPUState *s = CPU(dev);
|
||||
TileGXCPU *cpu = TILEGX_CPU(s);
|
||||
TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(cpu);
|
||||
CPUTLGState *env = &cpu->env;
|
||||
|
||||
tcc->parent_reset(dev);
|
||||
|
||||
memset(env, 0, offsetof(CPUTLGState, end_reset_fields));
|
||||
}
|
||||
|
||||
static void tilegx_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_reset(cs);
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
tcc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
static void tilegx_cpu_initfn(Object *obj)
|
||||
{
|
||||
TileGXCPU *cpu = TILEGX_CPU(obj);
|
||||
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
}
|
||||
|
||||
static void tilegx_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
cs->exception_index = -1;
|
||||
}
|
||||
|
||||
static bool tilegx_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr)
|
||||
{
|
||||
TileGXCPU *cpu = TILEGX_CPU(cs);
|
||||
|
||||
/* The sigcode field will be filled in by do_signal in main.c. */
|
||||
cs->exception_index = TILEGX_EXCP_SIGNAL;
|
||||
cpu->env.excaddr = address;
|
||||
cpu->env.signo = TARGET_SIGSEGV;
|
||||
cpu->env.sigcode = 0;
|
||||
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
||||
static bool tilegx_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
tilegx_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
||||
static struct TCGCPUOps tilegx_tcg_ops = {
|
||||
.initialize = tilegx_tcg_init,
|
||||
.cpu_exec_interrupt = tilegx_cpu_exec_interrupt,
|
||||
.tlb_fill = tilegx_cpu_tlb_fill,
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.do_interrupt = tilegx_cpu_do_interrupt,
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
||||
static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
TileGXCPUClass *tcc = TILEGX_CPU_CLASS(oc);
|
||||
|
||||
device_class_set_parent_realize(dc, tilegx_cpu_realizefn,
|
||||
&tcc->parent_realize);
|
||||
|
||||
device_class_set_parent_reset(dc, tilegx_cpu_reset, &tcc->parent_reset);
|
||||
|
||||
cc->class_by_name = tilegx_cpu_class_by_name;
|
||||
cc->has_work = tilegx_cpu_has_work;
|
||||
cc->dump_state = tilegx_cpu_dump_state;
|
||||
cc->set_pc = tilegx_cpu_set_pc;
|
||||
cc->gdb_num_core_regs = 0;
|
||||
cc->tcg_ops = &tilegx_tcg_ops;
|
||||
}
|
||||
|
||||
static const TypeInfo tilegx_cpu_type_info = {
|
||||
.name = TYPE_TILEGX_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(TileGXCPU),
|
||||
.instance_init = tilegx_cpu_initfn,
|
||||
.class_size = sizeof(TileGXCPUClass),
|
||||
.class_init = tilegx_cpu_class_init,
|
||||
};
|
||||
|
||||
static void tilegx_cpu_register_types(void)
|
||||
{
|
||||
type_register_static(&tilegx_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(tilegx_cpu_register_types)
|
@ -1,160 +0,0 @@
|
||||
/*
|
||||
* TILE-Gx virtual CPU header
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TILEGX_CPU_H
|
||||
#define TILEGX_CPU_H
|
||||
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
/* TILE-Gx common register alias */
|
||||
#define TILEGX_R_RE 0 /* 0 register, for function/syscall return value */
|
||||
#define TILEGX_R_ERR 1 /* 1 register, for syscall errno flag */
|
||||
#define TILEGX_R_NR 10 /* 10 register, for syscall number */
|
||||
#define TILEGX_R_BP 52 /* 52 register, optional frame pointer */
|
||||
#define TILEGX_R_TP 53 /* TP register, thread local storage data */
|
||||
#define TILEGX_R_SP 54 /* SP register, stack pointer */
|
||||
#define TILEGX_R_LR 55 /* LR register, may save pc, but it is not pc */
|
||||
#define TILEGX_R_COUNT 56 /* Only 56 registers are really useful */
|
||||
#define TILEGX_R_SN 56 /* SN register, obsoleted, it likes zero register */
|
||||
#define TILEGX_R_IDN0 57 /* IDN0 register, cause IDN_ACCESS exception */
|
||||
#define TILEGX_R_IDN1 58 /* IDN1 register, cause IDN_ACCESS exception */
|
||||
#define TILEGX_R_UDN0 59 /* UDN0 register, cause UDN_ACCESS exception */
|
||||
#define TILEGX_R_UDN1 60 /* UDN1 register, cause UDN_ACCESS exception */
|
||||
#define TILEGX_R_UDN2 61 /* UDN2 register, cause UDN_ACCESS exception */
|
||||
#define TILEGX_R_UDN3 62 /* UDN3 register, cause UDN_ACCESS exception */
|
||||
#define TILEGX_R_ZERO 63 /* Zero register, always zero */
|
||||
#define TILEGX_R_NOREG 255 /* Invalid register value */
|
||||
|
||||
/* TILE-Gx special registers used by outside */
|
||||
enum {
|
||||
TILEGX_SPR_CMPEXCH = 0,
|
||||
TILEGX_SPR_CRITICAL_SEC = 1,
|
||||
TILEGX_SPR_SIM_CONTROL = 2,
|
||||
TILEGX_SPR_EX_CONTEXT_0_0 = 3,
|
||||
TILEGX_SPR_EX_CONTEXT_0_1 = 4,
|
||||
TILEGX_SPR_COUNT
|
||||
};
|
||||
|
||||
/* Exception numbers */
|
||||
typedef enum {
|
||||
TILEGX_EXCP_NONE = 0,
|
||||
TILEGX_EXCP_SYSCALL = 1,
|
||||
TILEGX_EXCP_SIGNAL = 2,
|
||||
TILEGX_EXCP_OPCODE_UNKNOWN = 0x101,
|
||||
TILEGX_EXCP_OPCODE_UNIMPLEMENTED = 0x102,
|
||||
TILEGX_EXCP_OPCODE_CMPEXCH = 0x103,
|
||||
TILEGX_EXCP_OPCODE_CMPEXCH4 = 0x104,
|
||||
TILEGX_EXCP_OPCODE_EXCH = 0x105,
|
||||
TILEGX_EXCP_OPCODE_EXCH4 = 0x106,
|
||||
TILEGX_EXCP_OPCODE_FETCHADD = 0x107,
|
||||
TILEGX_EXCP_OPCODE_FETCHADD4 = 0x108,
|
||||
TILEGX_EXCP_OPCODE_FETCHADDGEZ = 0x109,
|
||||
TILEGX_EXCP_OPCODE_FETCHADDGEZ4 = 0x10a,
|
||||
TILEGX_EXCP_OPCODE_FETCHAND = 0x10b,
|
||||
TILEGX_EXCP_OPCODE_FETCHAND4 = 0x10c,
|
||||
TILEGX_EXCP_OPCODE_FETCHOR = 0x10d,
|
||||
TILEGX_EXCP_OPCODE_FETCHOR4 = 0x10e,
|
||||
TILEGX_EXCP_REG_IDN_ACCESS = 0x181,
|
||||
TILEGX_EXCP_REG_UDN_ACCESS = 0x182,
|
||||
TILEGX_EXCP_UNALIGNMENT = 0x201,
|
||||
TILEGX_EXCP_DBUG_BREAK = 0x301
|
||||
} TileExcp;
|
||||
|
||||
typedef struct CPUTLGState {
|
||||
uint64_t regs[TILEGX_R_COUNT]; /* Common used registers by outside */
|
||||
uint64_t spregs[TILEGX_SPR_COUNT]; /* Special used registers by outside */
|
||||
uint64_t pc; /* Current pc */
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
uint64_t excaddr; /* exception address */
|
||||
uint64_t atomic_srca; /* Arguments to atomic "exceptions" */
|
||||
uint64_t atomic_srcb;
|
||||
uint32_t atomic_dstr;
|
||||
uint32_t signo; /* Signal number */
|
||||
uint32_t sigcode; /* Signal code */
|
||||
#endif
|
||||
|
||||
/* Fields up to this point are cleared by a CPU reset */
|
||||
struct {} end_reset_fields;
|
||||
} CPUTLGState;
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#define TYPE_TILEGX_CPU "tilegx-cpu"
|
||||
|
||||
OBJECT_DECLARE_TYPE(TileGXCPU, TileGXCPUClass,
|
||||
TILEGX_CPU)
|
||||
|
||||
/**
|
||||
* TileGXCPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A Tile-Gx CPU model.
|
||||
*/
|
||||
struct TileGXCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
DeviceReset parent_reset;
|
||||
};
|
||||
|
||||
/**
|
||||
* TileGXCPU:
|
||||
* @env: #CPUTLGState
|
||||
*
|
||||
* A Tile-GX CPU.
|
||||
*/
|
||||
struct TileGXCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUNegativeOffsetState neg;
|
||||
CPUTLGState env;
|
||||
};
|
||||
|
||||
|
||||
/* TILE-Gx memory attributes */
|
||||
#define MMU_USER_IDX 0 /* Current memory operation is in user mode */
|
||||
|
||||
typedef CPUTLGState CPUArchState;
|
||||
typedef TileGXCPU ArchCPU;
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
void tilegx_tcg_init(void);
|
||||
int cpu_tilegx_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
||||
#define CPU_RESOLVING_TYPE TYPE_TILEGX_CPU
|
||||
|
||||
#define cpu_signal_handler cpu_tilegx_signal_handler
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUTLGState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* QEMU TILE-Gx helpers
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include <zlib.h> /* For crc32 */
|
||||
#include "syscall_defs.h"
|
||||
|
||||
void helper_exception(CPUTLGState *env, uint32_t excp)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
cs->exception_index = excp;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
void helper_ext01_ics(CPUTLGState *env)
|
||||
{
|
||||
uint64_t val = env->spregs[TILEGX_SPR_EX_CONTEXT_0_1];
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
case 1:
|
||||
env->spregs[TILEGX_SPR_CRITICAL_SEC] = val;
|
||||
break;
|
||||
default:
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
env->signo = TARGET_SIGILL;
|
||||
env->sigcode = TARGET_ILL_ILLOPC;
|
||||
helper_exception(env, TILEGX_EXCP_SIGNAL);
|
||||
#else
|
||||
helper_exception(env, TILEGX_EXCP_OPCODE_UNIMPLEMENTED);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t helper_revbits(uint64_t arg)
|
||||
{
|
||||
return revbit64(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functional Description
|
||||
* uint64_t a = rf[SrcA];
|
||||
* uint64_t b = rf[SrcB];
|
||||
* uint64_t d = rf[Dest];
|
||||
* uint64_t output = 0;
|
||||
* unsigned int counter;
|
||||
* for (counter = 0; counter < (WORD_SIZE / BYTE_SIZE); counter++)
|
||||
* {
|
||||
* int sel = getByte (b, counter) & 0xf;
|
||||
* uint8_t byte = (sel < 8) ? getByte (d, sel) : getByte (a, (sel - 8));
|
||||
* output = setByte (output, counter, byte);
|
||||
* }
|
||||
* rf[Dest] = output;
|
||||
*/
|
||||
uint64_t helper_shufflebytes(uint64_t dest, uint64_t srca, uint64_t srcb)
|
||||
{
|
||||
uint64_t vdst = 0;
|
||||
int count;
|
||||
|
||||
for (count = 0; count < 64; count += 8) {
|
||||
uint64_t sel = srcb >> count;
|
||||
uint64_t src = (sel & 8) ? srca : dest;
|
||||
vdst |= extract64(src, (sel & 7) * 8, 8) << count;
|
||||
}
|
||||
|
||||
return vdst;
|
||||
}
|
||||
|
||||
uint64_t helper_crc32_8(uint64_t accum, uint64_t input)
|
||||
{
|
||||
uint8_t buf = input;
|
||||
|
||||
/* zlib crc32 converts the accumulator and output to one's complement. */
|
||||
return crc32(accum ^ 0xffffffff, &buf, 1) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
uint64_t helper_crc32_32(uint64_t accum, uint64_t input)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
|
||||
stl_le_p(buf, input);
|
||||
|
||||
/* zlib crc32 converts the accumulator and output to one's complement. */
|
||||
return crc32(accum ^ 0xffffffff, buf, 4) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
uint64_t helper_cmula(uint64_t srcd, uint64_t srca, uint64_t srcb)
|
||||
{
|
||||
uint32_t reala = (int16_t)srca;
|
||||
uint32_t imaga = (int16_t)(srca >> 16);
|
||||
uint32_t realb = (int16_t)srcb;
|
||||
uint32_t imagb = (int16_t)(srcb >> 16);
|
||||
uint32_t reald = srcd;
|
||||
uint32_t imagd = srcd >> 32;
|
||||
uint32_t realr = reala * realb - imaga * imagb + reald;
|
||||
uint32_t imagr = reala * imagb + imaga * realb + imagd;
|
||||
|
||||
return deposit64(realr, 32, 32, imagr);
|
||||
}
|
||||
|
||||
uint64_t helper_cmulaf(uint64_t srcd, uint64_t srca, uint64_t srcb)
|
||||
{
|
||||
uint32_t reala = (int16_t)srca;
|
||||
uint32_t imaga = (int16_t)(srca >> 16);
|
||||
uint32_t realb = (int16_t)srcb;
|
||||
uint32_t imagb = (int16_t)(srcb >> 16);
|
||||
uint32_t reald = (int16_t)srcd;
|
||||
uint32_t imagd = (int16_t)(srcd >> 16);
|
||||
int32_t realr = reala * realb - imaga * imagb;
|
||||
int32_t imagr = reala * imagb + imaga * realb;
|
||||
|
||||
return deposit32((realr >> 15) + reald, 16, 16, (imagr >> 15) + imagd);
|
||||
}
|
||||
|
||||
uint64_t helper_cmul2(uint64_t srca, uint64_t srcb, int shift, int round)
|
||||
{
|
||||
uint32_t reala = (int16_t)srca;
|
||||
uint32_t imaga = (int16_t)(srca >> 16);
|
||||
uint32_t realb = (int16_t)srcb;
|
||||
uint32_t imagb = (int16_t)(srcb >> 16);
|
||||
int32_t realr = reala * realb - imaga * imagb + round;
|
||||
int32_t imagr = reala * imagb + imaga * realb + round;
|
||||
|
||||
return deposit32(realr >> shift, 16, 16, imagr >> shift);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
DEF_HELPER_2(exception, noreturn, env, i32)
|
||||
DEF_HELPER_1(ext01_ics, void, env)
|
||||
DEF_HELPER_FLAGS_1(revbits, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(shufflebytes, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(crc32_8, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(crc32_32, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(cmula, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(cmulaf, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(cmul2, TCG_CALL_NO_RWG_SE, i64, i64, i64, int, int)
|
||||
|
||||
DEF_HELPER_FLAGS_2(v1int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v1int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v2int_h, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v2int_l, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(v1multu, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v2mults, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v1shl, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v1shru, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
@ -1,13 +0,0 @@
|
||||
tilegx_ss = ss.source_set()
|
||||
tilegx_ss.add(files(
|
||||
'cpu.c',
|
||||
'helper.c',
|
||||
'simd_helper.c',
|
||||
'translate.c',
|
||||
))
|
||||
tilegx_ss.add(zlib)
|
||||
|
||||
tilegx_softmmu_ss = ss.source_set()
|
||||
|
||||
target_arch += {'tilegx': tilegx_ss}
|
||||
target_softmmu_arch += {'tilegx': tilegx_softmmu_ss}
|
File diff suppressed because it is too large
Load Diff
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* QEMU TILE-Gx helpers
|
||||
*
|
||||
* Copyright (c) 2015 Chen Gang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
|
||||
/* Broadcast a value to all elements of a vector. */
|
||||
#define V1(X) (((X) & 0xff) * 0x0101010101010101ull)
|
||||
#define V2(X) (((X) & 0xffff) * 0x0001000100010001ull)
|
||||
|
||||
|
||||
uint64_t helper_v1multu(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i += 8) {
|
||||
unsigned ae = extract64(a, i, 8);
|
||||
unsigned be = extract64(b, i, 8);
|
||||
r = deposit64(r, i, 8, ae * be);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v2mults(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
/* While the instruction talks about signed inputs, with a
|
||||
truncated result the sign of the inputs doesn't matter. */
|
||||
for (i = 0; i < 64; i += 16) {
|
||||
unsigned ae = extract64(a, i, 16);
|
||||
unsigned be = extract64(b, i, 16);
|
||||
r = deposit64(r, i, 16, ae * be);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v1shl(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t m;
|
||||
|
||||
b &= 7;
|
||||
m = V1(0xff >> b);
|
||||
return (a & m) << b;
|
||||
}
|
||||
|
||||
uint64_t helper_v2shl(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t m;
|
||||
|
||||
b &= 15;
|
||||
m = V2(0xffff >> b);
|
||||
return (a & m) << b;
|
||||
}
|
||||
|
||||
uint64_t helper_v1shru(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t m;
|
||||
|
||||
b &= 7;
|
||||
m = V1(0xff << b);
|
||||
return (a & m) >> b;
|
||||
}
|
||||
|
||||
uint64_t helper_v2shru(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t m;
|
||||
|
||||
b &= 15;
|
||||
m = V2(0xffff << b);
|
||||
return (a & m) >> b;
|
||||
}
|
||||
|
||||
uint64_t helper_v1shrs(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
b &= 7;
|
||||
for (i = 0; i < 64; i += 8) {
|
||||
r = deposit64(r, i, 8, sextract64(a, i + b, 8 - b));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v2shrs(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
b &= 15;
|
||||
for (i = 0; i < 64; i += 16) {
|
||||
r = deposit64(r, i, 16, sextract64(a, i + b, 16 - b));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v1int_h(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i += 8) {
|
||||
r = deposit64(r, 2 * i + 8, 8, extract64(a, i + 32, 8));
|
||||
r = deposit64(r, 2 * i, 8, extract64(b, i + 32, 8));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v1int_l(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i += 8) {
|
||||
r = deposit64(r, 2 * i + 8, 8, extract64(a, i, 8));
|
||||
r = deposit64(r, 2 * i, 8, extract64(b, i, 8));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v2int_h(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i += 16) {
|
||||
r = deposit64(r, 2 * i + 16, 16, extract64(a, i + 32, 16));
|
||||
r = deposit64(r, 2 * i, 16, extract64(b, i + 32, 16));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t helper_v2int_l(uint64_t a, uint64_t b)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i += 16) {
|
||||
r = deposit64(r, 2 * i + 16, 16, extract64(a, i, 16));
|
||||
r = deposit64(r, 2 * i, 16, extract64(b, i, 16));
|
||||
}
|
||||
return r;
|
||||
}
|
@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#ifndef ARCH_SPR_DEF_64_H
|
||||
#define ARCH_SPR_DEF_64_H
|
||||
|
||||
#define SPR_AUX_PERF_COUNT_0 0x2105
|
||||
#define SPR_AUX_PERF_COUNT_1 0x2106
|
||||
#define SPR_AUX_PERF_COUNT_CTL 0x2107
|
||||
#define SPR_AUX_PERF_COUNT_STS 0x2108
|
||||
#define SPR_CMPEXCH_VALUE 0x2780
|
||||
#define SPR_CYCLE 0x2781
|
||||
#define SPR_DONE 0x2705
|
||||
#define SPR_DSTREAM_PF 0x2706
|
||||
#define SPR_EVENT_BEGIN 0x2782
|
||||
#define SPR_EVENT_END 0x2783
|
||||
#define SPR_EX_CONTEXT_0_0 0x2580
|
||||
#define SPR_EX_CONTEXT_0_1 0x2581
|
||||
#define SPR_EX_CONTEXT_0_1__PL_SHIFT 0
|
||||
#define SPR_EX_CONTEXT_0_1__PL_RMASK 0x3
|
||||
#define SPR_EX_CONTEXT_0_1__PL_MASK 0x3
|
||||
#define SPR_EX_CONTEXT_0_1__ICS_SHIFT 2
|
||||
#define SPR_EX_CONTEXT_0_1__ICS_RMASK 0x1
|
||||
#define SPR_EX_CONTEXT_0_1__ICS_MASK 0x4
|
||||
#define SPR_EX_CONTEXT_1_0 0x2480
|
||||
#define SPR_EX_CONTEXT_1_1 0x2481
|
||||
#define SPR_EX_CONTEXT_1_1__PL_SHIFT 0
|
||||
#define SPR_EX_CONTEXT_1_1__PL_RMASK 0x3
|
||||
#define SPR_EX_CONTEXT_1_1__PL_MASK 0x3
|
||||
#define SPR_EX_CONTEXT_1_1__ICS_SHIFT 2
|
||||
#define SPR_EX_CONTEXT_1_1__ICS_RMASK 0x1
|
||||
#define SPR_EX_CONTEXT_1_1__ICS_MASK 0x4
|
||||
#define SPR_EX_CONTEXT_2_0 0x2380
|
||||
#define SPR_EX_CONTEXT_2_1 0x2381
|
||||
#define SPR_EX_CONTEXT_2_1__PL_SHIFT 0
|
||||
#define SPR_EX_CONTEXT_2_1__PL_RMASK 0x3
|
||||
#define SPR_EX_CONTEXT_2_1__PL_MASK 0x3
|
||||
#define SPR_EX_CONTEXT_2_1__ICS_SHIFT 2
|
||||
#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1
|
||||
#define SPR_EX_CONTEXT_2_1__ICS_MASK 0x4
|
||||
#define SPR_FAIL 0x2707
|
||||
#define SPR_IDN_AVAIL_EN 0x1a05
|
||||
#define SPR_IDN_DATA_AVAIL 0x0a80
|
||||
#define SPR_IDN_DEADLOCK_TIMEOUT 0x1806
|
||||
#define SPR_IDN_DEMUX_COUNT_0 0x0a05
|
||||
#define SPR_IDN_DEMUX_COUNT_1 0x0a06
|
||||
#define SPR_IDN_DIRECTION_PROTECT 0x1405
|
||||
#define SPR_IDN_PENDING 0x0a08
|
||||
#define SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK 0x1
|
||||
#define SPR_INTCTRL_0_STATUS 0x2505
|
||||
#define SPR_INTCTRL_1_STATUS 0x2405
|
||||
#define SPR_INTCTRL_2_STATUS 0x2305
|
||||
#define SPR_INTERRUPT_CRITICAL_SECTION 0x2708
|
||||
#define SPR_INTERRUPT_MASK_0 0x2506
|
||||
#define SPR_INTERRUPT_MASK_1 0x2406
|
||||
#define SPR_INTERRUPT_MASK_2 0x2306
|
||||
#define SPR_INTERRUPT_MASK_RESET_0 0x2507
|
||||
#define SPR_INTERRUPT_MASK_RESET_1 0x2407
|
||||
#define SPR_INTERRUPT_MASK_RESET_2 0x2307
|
||||
#define SPR_INTERRUPT_MASK_SET_0 0x2508
|
||||
#define SPR_INTERRUPT_MASK_SET_1 0x2408
|
||||
#define SPR_INTERRUPT_MASK_SET_2 0x2308
|
||||
#define SPR_INTERRUPT_VECTOR_BASE_0 0x2509
|
||||
#define SPR_INTERRUPT_VECTOR_BASE_1 0x2409
|
||||
#define SPR_INTERRUPT_VECTOR_BASE_2 0x2309
|
||||
#define SPR_INTERRUPT_VECTOR_BASE_3 0x2209
|
||||
#define SPR_IPI_EVENT_0 0x1f05
|
||||
#define SPR_IPI_EVENT_1 0x1e05
|
||||
#define SPR_IPI_EVENT_2 0x1d05
|
||||
#define SPR_IPI_EVENT_RESET_0 0x1f06
|
||||
#define SPR_IPI_EVENT_RESET_1 0x1e06
|
||||
#define SPR_IPI_EVENT_RESET_2 0x1d06
|
||||
#define SPR_IPI_EVENT_SET_0 0x1f07
|
||||
#define SPR_IPI_EVENT_SET_1 0x1e07
|
||||
#define SPR_IPI_EVENT_SET_2 0x1d07
|
||||
#define SPR_IPI_MASK_0 0x1f08
|
||||
#define SPR_IPI_MASK_1 0x1e08
|
||||
#define SPR_IPI_MASK_2 0x1d08
|
||||
#define SPR_IPI_MASK_RESET_0 0x1f09
|
||||
#define SPR_IPI_MASK_RESET_1 0x1e09
|
||||
#define SPR_IPI_MASK_RESET_2 0x1d09
|
||||
#define SPR_IPI_MASK_SET_0 0x1f0a
|
||||
#define SPR_IPI_MASK_SET_1 0x1e0a
|
||||
#define SPR_IPI_MASK_SET_2 0x1d0a
|
||||
#define SPR_MPL_AUX_PERF_COUNT_SET_0 0x2100
|
||||
#define SPR_MPL_AUX_PERF_COUNT_SET_1 0x2101
|
||||
#define SPR_MPL_AUX_PERF_COUNT_SET_2 0x2102
|
||||
#define SPR_MPL_AUX_TILE_TIMER_SET_0 0x1700
|
||||
#define SPR_MPL_AUX_TILE_TIMER_SET_1 0x1701
|
||||
#define SPR_MPL_AUX_TILE_TIMER_SET_2 0x1702
|
||||
#define SPR_MPL_IDN_ACCESS_SET_0 0x0a00
|
||||
#define SPR_MPL_IDN_ACCESS_SET_1 0x0a01
|
||||
#define SPR_MPL_IDN_ACCESS_SET_2 0x0a02
|
||||
#define SPR_MPL_IDN_AVAIL_SET_0 0x1a00
|
||||
#define SPR_MPL_IDN_AVAIL_SET_1 0x1a01
|
||||
#define SPR_MPL_IDN_AVAIL_SET_2 0x1a02
|
||||
#define SPR_MPL_IDN_COMPLETE_SET_0 0x0500
|
||||
#define SPR_MPL_IDN_COMPLETE_SET_1 0x0501
|
||||
#define SPR_MPL_IDN_COMPLETE_SET_2 0x0502
|
||||
#define SPR_MPL_IDN_FIREWALL_SET_0 0x1400
|
||||
#define SPR_MPL_IDN_FIREWALL_SET_1 0x1401
|
||||
#define SPR_MPL_IDN_FIREWALL_SET_2 0x1402
|
||||
#define SPR_MPL_IDN_TIMER_SET_0 0x1800
|
||||
#define SPR_MPL_IDN_TIMER_SET_1 0x1801
|
||||
#define SPR_MPL_IDN_TIMER_SET_2 0x1802
|
||||
#define SPR_MPL_INTCTRL_0_SET_0 0x2500
|
||||
#define SPR_MPL_INTCTRL_0_SET_1 0x2501
|
||||
#define SPR_MPL_INTCTRL_0_SET_2 0x2502
|
||||
#define SPR_MPL_INTCTRL_1_SET_0 0x2400
|
||||
#define SPR_MPL_INTCTRL_1_SET_1 0x2401
|
||||
#define SPR_MPL_INTCTRL_1_SET_2 0x2402
|
||||
#define SPR_MPL_INTCTRL_2_SET_0 0x2300
|
||||
#define SPR_MPL_INTCTRL_2_SET_1 0x2301
|
||||
#define SPR_MPL_INTCTRL_2_SET_2 0x2302
|
||||
#define SPR_MPL_IPI_0 0x1f04
|
||||
#define SPR_MPL_IPI_0_SET_0 0x1f00
|
||||
#define SPR_MPL_IPI_0_SET_1 0x1f01
|
||||
#define SPR_MPL_IPI_0_SET_2 0x1f02
|
||||
#define SPR_MPL_IPI_1 0x1e04
|
||||
#define SPR_MPL_IPI_1_SET_0 0x1e00
|
||||
#define SPR_MPL_IPI_1_SET_1 0x1e01
|
||||
#define SPR_MPL_IPI_1_SET_2 0x1e02
|
||||
#define SPR_MPL_IPI_2 0x1d04
|
||||
#define SPR_MPL_IPI_2_SET_0 0x1d00
|
||||
#define SPR_MPL_IPI_2_SET_1 0x1d01
|
||||
#define SPR_MPL_IPI_2_SET_2 0x1d02
|
||||
#define SPR_MPL_PERF_COUNT_SET_0 0x2000
|
||||
#define SPR_MPL_PERF_COUNT_SET_1 0x2001
|
||||
#define SPR_MPL_PERF_COUNT_SET_2 0x2002
|
||||
#define SPR_MPL_UDN_ACCESS_SET_0 0x0b00
|
||||
#define SPR_MPL_UDN_ACCESS_SET_1 0x0b01
|
||||
#define SPR_MPL_UDN_ACCESS_SET_2 0x0b02
|
||||
#define SPR_MPL_UDN_AVAIL_SET_0 0x1b00
|
||||
#define SPR_MPL_UDN_AVAIL_SET_1 0x1b01
|
||||
#define SPR_MPL_UDN_AVAIL_SET_2 0x1b02
|
||||
#define SPR_MPL_UDN_COMPLETE_SET_0 0x0600
|
||||
#define SPR_MPL_UDN_COMPLETE_SET_1 0x0601
|
||||
#define SPR_MPL_UDN_COMPLETE_SET_2 0x0602
|
||||
#define SPR_MPL_UDN_FIREWALL_SET_0 0x1500
|
||||
#define SPR_MPL_UDN_FIREWALL_SET_1 0x1501
|
||||
#define SPR_MPL_UDN_FIREWALL_SET_2 0x1502
|
||||
#define SPR_MPL_UDN_TIMER_SET_0 0x1900
|
||||
#define SPR_MPL_UDN_TIMER_SET_1 0x1901
|
||||
#define SPR_MPL_UDN_TIMER_SET_2 0x1902
|
||||
#define SPR_MPL_WORLD_ACCESS_SET_0 0x2700
|
||||
#define SPR_MPL_WORLD_ACCESS_SET_1 0x2701
|
||||
#define SPR_MPL_WORLD_ACCESS_SET_2 0x2702
|
||||
#define SPR_PASS 0x2709
|
||||
#define SPR_PERF_COUNT_0 0x2005
|
||||
#define SPR_PERF_COUNT_1 0x2006
|
||||
#define SPR_PERF_COUNT_CTL 0x2007
|
||||
#define SPR_PERF_COUNT_DN_CTL 0x2008
|
||||
#define SPR_PERF_COUNT_STS 0x2009
|
||||
#define SPR_PROC_STATUS 0x2784
|
||||
#define SPR_SIM_CONTROL 0x2785
|
||||
#define SPR_SINGLE_STEP_CONTROL_0 0x0405
|
||||
#define SPR_SINGLE_STEP_CONTROL_0__CANCELED_MASK 0x1
|
||||
#define SPR_SINGLE_STEP_CONTROL_0__INHIBIT_MASK 0x2
|
||||
#define SPR_SINGLE_STEP_CONTROL_1 0x0305
|
||||
#define SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK 0x1
|
||||
#define SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK 0x2
|
||||
#define SPR_SINGLE_STEP_CONTROL_2 0x0205
|
||||
#define SPR_SINGLE_STEP_CONTROL_2__CANCELED_MASK 0x1
|
||||
#define SPR_SINGLE_STEP_CONTROL_2__INHIBIT_MASK 0x2
|
||||
#define SPR_SINGLE_STEP_EN_0_0 0x250a
|
||||
#define SPR_SINGLE_STEP_EN_0_1 0x240a
|
||||
#define SPR_SINGLE_STEP_EN_0_2 0x230a
|
||||
#define SPR_SINGLE_STEP_EN_1_0 0x250b
|
||||
#define SPR_SINGLE_STEP_EN_1_1 0x240b
|
||||
#define SPR_SINGLE_STEP_EN_1_2 0x230b
|
||||
#define SPR_SINGLE_STEP_EN_2_0 0x250c
|
||||
#define SPR_SINGLE_STEP_EN_2_1 0x240c
|
||||
#define SPR_SINGLE_STEP_EN_2_2 0x230c
|
||||
#define SPR_SYSTEM_SAVE_0_0 0x2582
|
||||
#define SPR_SYSTEM_SAVE_0_1 0x2583
|
||||
#define SPR_SYSTEM_SAVE_0_2 0x2584
|
||||
#define SPR_SYSTEM_SAVE_0_3 0x2585
|
||||
#define SPR_SYSTEM_SAVE_1_0 0x2482
|
||||
#define SPR_SYSTEM_SAVE_1_1 0x2483
|
||||
#define SPR_SYSTEM_SAVE_1_2 0x2484
|
||||
#define SPR_SYSTEM_SAVE_1_3 0x2485
|
||||
#define SPR_SYSTEM_SAVE_2_0 0x2382
|
||||
#define SPR_SYSTEM_SAVE_2_1 0x2383
|
||||
#define SPR_SYSTEM_SAVE_2_2 0x2384
|
||||
#define SPR_SYSTEM_SAVE_2_3 0x2385
|
||||
#define SPR_TILE_COORD 0x270b
|
||||
#define SPR_TILE_RTF_HWM 0x270c
|
||||
#define SPR_TILE_TIMER_CONTROL 0x1605
|
||||
#define SPR_UDN_AVAIL_EN 0x1b05
|
||||
#define SPR_UDN_DATA_AVAIL 0x0b80
|
||||
#define SPR_UDN_DEADLOCK_TIMEOUT 0x1906
|
||||
#define SPR_UDN_DEMUX_COUNT_0 0x0b05
|
||||
#define SPR_UDN_DEMUX_COUNT_1 0x0b06
|
||||
#define SPR_UDN_DEMUX_COUNT_2 0x0b07
|
||||
#define SPR_UDN_DEMUX_COUNT_3 0x0b08
|
||||
#define SPR_UDN_DIRECTION_PROTECT 0x1505
|
||||
#define SPR_UDN_PENDING 0x0b0a
|
||||
#define SPR_WATCH_MASK 0x200a
|
||||
#define SPR_WATCH_VAL 0x200b
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -92,7 +92,7 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
|
||||
# Any number of command separated loggers are accepted. For more
|
||||
# information please refer to "avocado --help".
|
||||
AVOCADO_SHOW=app
|
||||
AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGET_DIRS)))
|
||||
AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS)))
|
||||
|
||||
$(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
|
||||
$(call quiet-command, \
|
||||
@ -109,7 +109,8 @@ $(TESTS_RESULTS_DIR):
|
||||
|
||||
check-venv: $(TESTS_VENV_DIR)
|
||||
|
||||
FEDORA_31_ARCHES_CANDIDATES=$(patsubst ppc64,ppc64le,$(TARGETS))
|
||||
FEDORA_31_ARCHES_TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGETS)))
|
||||
FEDORA_31_ARCHES_CANDIDATES=$(patsubst ppc64,ppc64le,$(FEDORA_31_ARCHES_TARGETS))
|
||||
FEDORA_31_ARCHES := x86_64 aarch64 ppc64le s390x
|
||||
FEDORA_31_DOWNLOAD=$(filter $(FEDORA_31_ARCHES),$(FEDORA_31_ARCHES_CANDIDATES))
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
typedef struct QOSGraphObject QOSGraphObject;
|
||||
typedef struct QOSGraphNode QOSGraphNode;
|
||||
typedef struct QOSGraphEdge QOSGraphEdge;
|
||||
typedef struct QOSGraphNodeOptions QOSGraphNodeOptions;
|
||||
typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions;
|
||||
typedef struct QOSGraphTestOptions QOSGraphTestOptions;
|
||||
|
||||
@ -49,340 +48,94 @@ typedef void (*QOSStartFunct) (QOSGraphObject *object);
|
||||
typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg);
|
||||
|
||||
/**
|
||||
* SECTION: qgraph.h
|
||||
* @title: Qtest Driver Framework
|
||||
* @short_description: interfaces to organize drivers and tests
|
||||
* as nodes in a graph
|
||||
*
|
||||
* This Qgraph API provides all basic functions to create a graph
|
||||
* and instantiate nodes representing machines, drivers and tests
|
||||
* representing their relations with CONSUMES, PRODUCES, and CONTAINS
|
||||
* edges.
|
||||
*
|
||||
* The idea is to have a framework where each test asks for a specific
|
||||
* driver, and the framework takes care of allocating the proper devices
|
||||
* required and passing the correct command line arguments to QEMU.
|
||||
*
|
||||
* A node can be of four types:
|
||||
* - QNODE_MACHINE: for example "arm/raspi2"
|
||||
* - QNODE_DRIVER: for example "generic-sdhci"
|
||||
* - QNODE_INTERFACE: for example "sdhci" (interface for all "-sdhci" drivers)
|
||||
* an interface is not explicitly created, it will be auto-
|
||||
* matically instantiated when a node consumes or produces
|
||||
* it.
|
||||
* - QNODE_TEST: for example "sdhci-test", consumes an interface and tests
|
||||
* the functions provided
|
||||
*
|
||||
* Notes for the nodes:
|
||||
* - QNODE_MACHINE: each machine struct must have a QGuestAllocator and
|
||||
* implement get_driver to return the allocator passing
|
||||
* "memory". The function can also return NULL if the
|
||||
* allocator is not set.
|
||||
* - QNODE_DRIVER: driver names must be unique, and machines and nodes
|
||||
* planned to be "consumed" by other nodes must match QEMU
|
||||
* drivers name, otherwise they won't be discovered
|
||||
*
|
||||
* An edge relation between two nodes (drivers or machines) X and Y can be:
|
||||
* - X CONSUMES Y: Y can be plugged into X
|
||||
* - X PRODUCES Y: X provides the interface Y
|
||||
* - X CONTAINS Y: Y is part of X component
|
||||
*
|
||||
* Basic framework steps are the following:
|
||||
* - All nodes and edges are created in their respective
|
||||
* machine/driver/test files
|
||||
* - The framework starts QEMU and asks for a list of available devices
|
||||
* and machines (note that only machines and "consumed" nodes are mapped
|
||||
* 1:1 with QEMU devices)
|
||||
* - The framework walks the graph starting from the available machines and
|
||||
* performs a Depth First Search for tests
|
||||
* - Once a test is found, the path is walked again and all drivers are
|
||||
* allocated accordingly and the final interface is passed to the test
|
||||
* - The test is executed
|
||||
* - Unused objects are cleaned and the path discovery is continued
|
||||
*
|
||||
* Depending on the QEMU binary used, only some drivers/machines will be
|
||||
* available and only test that are reached by them will be executed.
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating new driver an its interface</title>
|
||||
* <programlisting>
|
||||
#include "qgraph.h"
|
||||
|
||||
struct My_driver {
|
||||
QOSGraphObject obj;
|
||||
Node_produced prod;
|
||||
Node_contained cont;
|
||||
}
|
||||
|
||||
static void my_destructor(QOSGraphObject *obj)
|
||||
{
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
static void my_get_driver(void *object, const char *interface) {
|
||||
My_driver *dev = object;
|
||||
if (!g_strcmp0(interface, "my_interface")) {
|
||||
return &dev->prod;
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
static void my_get_device(void *object, const char *device) {
|
||||
My_driver *dev = object;
|
||||
if (!g_strcmp0(device, "my_driver_contained")) {
|
||||
return &dev->cont;
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
static void *my_driver_constructor(void *node_consumed,
|
||||
QOSGraphObject *alloc)
|
||||
{
|
||||
My_driver dev = g_new(My_driver, 1);
|
||||
// get the node pointed by the produce edge
|
||||
dev->obj.get_driver = my_get_driver;
|
||||
// get the node pointed by the contains
|
||||
dev->obj.get_device = my_get_device;
|
||||
// free the object
|
||||
dev->obj.destructor = my_destructor;
|
||||
do_something_with_node_consumed(node_consumed);
|
||||
// set all fields of contained device
|
||||
init_contained_device(&dev->cont);
|
||||
return &dev->obj;
|
||||
}
|
||||
|
||||
static void register_my_driver(void)
|
||||
{
|
||||
qos_node_create_driver("my_driver", my_driver_constructor);
|
||||
// contained drivers don't need a constructor,
|
||||
// they will be init by the parent.
|
||||
qos_node_create_driver("my_driver_contained", NULL);
|
||||
|
||||
// For the sake of this example, assume machine x86_64/pc contains
|
||||
// "other_node".
|
||||
// This relation, along with the machine and "other_node" creation,
|
||||
// should be defined in the x86_64_pc-machine.c file.
|
||||
// "my_driver" will then consume "other_node"
|
||||
qos_node_contains("my_driver", "my_driver_contained");
|
||||
qos_node_produces("my_driver", "my_interface");
|
||||
qos_node_consumes("my_driver", "other_node");
|
||||
}
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* In the above example, all possible types of relations are created:
|
||||
* node "my_driver" consumes, contains and produces other nodes.
|
||||
* more specifically:
|
||||
* x86_64/pc -->contains--> other_node <--consumes-- my_driver
|
||||
* |
|
||||
* my_driver_contained <--contains--+
|
||||
* |
|
||||
* my_interface <--produces--+
|
||||
*
|
||||
* or inverting the consumes edge in consumed_by:
|
||||
*
|
||||
* x86_64/pc -->contains--> other_node --consumed_by--> my_driver
|
||||
* |
|
||||
* my_driver_contained <--contains--+
|
||||
* |
|
||||
* my_interface <--produces--+
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating new test</title>
|
||||
* <programlisting>
|
||||
* #include "qgraph.h"
|
||||
*
|
||||
* static void my_test_function(void *obj, void *data)
|
||||
* {
|
||||
* Node_produced *interface_to_test = obj;
|
||||
* // test interface_to_test
|
||||
* }
|
||||
*
|
||||
* static void register_my_test(void)
|
||||
* {
|
||||
* qos_add_test("my_interface", "my_test", my_test_function);
|
||||
* }
|
||||
*
|
||||
* libqos_init(register_my_test);
|
||||
*
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* Here a new test is created, consuming "my_interface" node
|
||||
* and creating a valid path from a machine to a test.
|
||||
* Final graph will be like this:
|
||||
* x86_64/pc -->contains--> other_node <--consumes-- my_driver
|
||||
* |
|
||||
* my_driver_contained <--contains--+
|
||||
* |
|
||||
* my_test --consumes--> my_interface <--produces--+
|
||||
*
|
||||
* or inverting the consumes edge in consumed_by:
|
||||
*
|
||||
* x86_64/pc -->contains--> other_node --consumed_by--> my_driver
|
||||
* |
|
||||
* my_driver_contained <--contains--+
|
||||
* |
|
||||
* my_test <--consumed_by-- my_interface <--produces--+
|
||||
*
|
||||
* Assuming there the binary is
|
||||
* QTEST_QEMU_BINARY=./qemu-system-x86_64
|
||||
* a valid test path will be:
|
||||
* "/x86_64/pc/other_node/my_driver/my_interface/my_test".
|
||||
*
|
||||
* Additional examples are also in test-qgraph.c
|
||||
*
|
||||
* Command line:
|
||||
* Command line is built by using node names and optional arguments
|
||||
* passed by the user when building the edges.
|
||||
*
|
||||
* There are three types of command line arguments:
|
||||
* - in node : created from the node name. For example, machines will
|
||||
* have "-M <machine>" to its command line, while devices
|
||||
* "-device <device>". It is automatically done by the
|
||||
* framework.
|
||||
* - after node : added as additional argument to the node name.
|
||||
* This argument is added optionally when creating edges,
|
||||
* by setting the parameter @after_cmd_line and
|
||||
* @extra_edge_opts in #QOSGraphEdgeOptions.
|
||||
* The framework automatically adds
|
||||
* a comma before @extra_edge_opts,
|
||||
* because it is going to add attributes
|
||||
* after the destination node pointed by
|
||||
* the edge containing these options, and automatically
|
||||
* adds a space before @after_cmd_line, because it
|
||||
* adds an additional device, not an attribute.
|
||||
* - before node : added as additional argument to the node name.
|
||||
* This argument is added optionally when creating edges,
|
||||
* by setting the parameter @before_cmd_line in
|
||||
* #QOSGraphEdgeOptions. This attribute
|
||||
* is going to add attributes before the destination node
|
||||
* pointed by the edge containing these options. It is
|
||||
* helpful to commands that are not node-representable,
|
||||
* such as "-fdsev" or "-netdev".
|
||||
*
|
||||
* While adding command line in edges is always used, not all nodes names are
|
||||
* used in every path walk: this is because the contained or produced ones
|
||||
* are already added by QEMU, so only nodes that "consumes" will be used to
|
||||
* build the command line. Also, nodes that will have { "abstract" : true }
|
||||
* as QMP attribute will loose their command line, since they are not proper
|
||||
* devices to be added in QEMU.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
QOSGraphEdgeOptions opts = {
|
||||
.arg = NULL,
|
||||
.size_arg = 0,
|
||||
.after_cmd_line = "-device other",
|
||||
.before_cmd_line = "-netdev something",
|
||||
.extra_edge_opts = "addr=04.0",
|
||||
};
|
||||
QOSGraphNode * node = qos_node_create_driver("my_node", constructor);
|
||||
qos_node_consumes_args("my_node", "interface", &opts);
|
||||
*
|
||||
* Will produce the following command line:
|
||||
* "-netdev something -device my_node,addr=04.0 -device other"
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edge options to be passed to the contains/consumes *_args function.
|
||||
* struct QOSGraphEdgeOptions:
|
||||
* Edge options to be passed to the contains/consumes \*_args function.
|
||||
* @arg: optional arg that will be used by dest edge
|
||||
* @size_arg: @arg size that will be used by dest edge
|
||||
* @extra_device_opts: optional additional command line for dest
|
||||
* edge, used to add additional attributes
|
||||
* *after* the node command line, the
|
||||
* framework automatically prepends ","
|
||||
* to this argument.
|
||||
* @before_cmd_line: optional additional command line for dest
|
||||
* edge, used to add additional attributes
|
||||
* *before* the node command line, usually
|
||||
* other non-node represented commands,
|
||||
* like "-fdsev synt"
|
||||
* @after_cmd_line: optional extra command line to be added
|
||||
* after the device command. This option
|
||||
* is used to add other devices
|
||||
* command line that depend on current node.
|
||||
* Automatically prepends " " to this argument
|
||||
* @edge_name: optional edge to differentiate multiple
|
||||
* devices with same node name
|
||||
*/
|
||||
struct QOSGraphEdgeOptions {
|
||||
void *arg; /*
|
||||
* optional arg that will be used by
|
||||
* dest edge
|
||||
*/
|
||||
uint32_t size_arg; /*
|
||||
* optional arg size that will be used by
|
||||
* dest edge
|
||||
*/
|
||||
const char *extra_device_opts;/*
|
||||
*optional additional command line for dest
|
||||
* edge, used to add additional attributes
|
||||
* *after* the node command line, the
|
||||
* framework automatically prepends ","
|
||||
* to this argument.
|
||||
*/
|
||||
const char *before_cmd_line; /*
|
||||
* optional additional command line for dest
|
||||
* edge, used to add additional attributes
|
||||
* *before* the node command line, usually
|
||||
* other non-node represented commands,
|
||||
* like "-fdsev synt"
|
||||
*/
|
||||
const char *after_cmd_line; /*
|
||||
* optional extra command line to be added
|
||||
* after the device command. This option
|
||||
* is used to add other devices
|
||||
* command line that depend on current node.
|
||||
* Automatically prepends " " to this
|
||||
* argument
|
||||
*/
|
||||
const char *edge_name; /*
|
||||
* optional edge to differentiate multiple
|
||||
* devices with same node name
|
||||
*/
|
||||
void *arg;
|
||||
uint32_t size_arg;
|
||||
const char *extra_device_opts;
|
||||
const char *before_cmd_line;
|
||||
const char *after_cmd_line;
|
||||
const char *edge_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct QOSGraphTestOptions:
|
||||
* Test options to be passed to the test functions.
|
||||
* @edge: edge arguments that will be used by test.
|
||||
* Note that test *does not* use edge_name,
|
||||
* and uses instead arg and size_arg as
|
||||
* data arg for its test function.
|
||||
* @arg: if @before is non-NULL, pass @arg there.
|
||||
* Otherwise pass it to the test function.
|
||||
* @before: executed before the test. Used to add
|
||||
* additional parameters to the command line
|
||||
* and modify the argument to the test function.
|
||||
* @subprocess: run the test in a subprocess.
|
||||
*/
|
||||
struct QOSGraphTestOptions {
|
||||
QOSGraphEdgeOptions edge; /* edge arguments that will be used by test.
|
||||
* Note that test *does not* use edge_name,
|
||||
* and uses instead arg and size_arg as
|
||||
* data arg for its test function.
|
||||
*/
|
||||
void *arg; /* passed to the .before function, or to the
|
||||
* test function if there is no .before
|
||||
* function
|
||||
*/
|
||||
QOSBeforeTest before; /* executed before the test. Can add
|
||||
* additional parameters to the command line
|
||||
* and modify the argument to the test function.
|
||||
*/
|
||||
bool subprocess; /* run the test in a subprocess */
|
||||
QOSGraphEdgeOptions edge;
|
||||
void *arg;
|
||||
QOSBeforeTest before;
|
||||
bool subprocess;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct QOSGraphObject:
|
||||
* Each driver, test or machine of this framework will have a
|
||||
* QOSGraphObject as first field.
|
||||
*
|
||||
* This set of functions offered by QOSGraphObject are executed
|
||||
* in different stages of the framework:
|
||||
* - get_driver / get_device : Once a machine-to-test path has been
|
||||
* found, the framework traverses it again and allocates all the
|
||||
* nodes, using the provided constructor. To satisfy their relations,
|
||||
* i.e. for produces or contains, where a struct constructor needs
|
||||
* an external parameter represented by the previous node,
|
||||
* the framework will call get_device (for contains) or
|
||||
* get_driver (for produces), depending on the edge type, passing
|
||||
* them the name of the next node to be taken and getting from them
|
||||
* the corresponding pointer to the actual structure of the next node to
|
||||
* be used in the path.
|
||||
*
|
||||
* - start_hw: This function is executed after all the path objects
|
||||
* have been allocated, but before the test is run. It starts the hw, setting
|
||||
* the initial configurations (*_device_enable) and making it ready for the
|
||||
* test.
|
||||
*
|
||||
* - destructor: Opposite to the node constructor, destroys the object.
|
||||
* This function is called after the test has been executed, and performs
|
||||
* a complete cleanup of each node allocated field. In case no constructor
|
||||
* is provided, no destructor will be called.
|
||||
*
|
||||
* @get_driver: see @get_device
|
||||
* @get_device: Once a machine-to-test path has been
|
||||
* found, the framework traverses it again and allocates all the
|
||||
* nodes, using the provided constructor. To satisfy their
|
||||
* relations, i.e. for produces or contains, where a struct
|
||||
* constructor needs an external parameter represented by the
|
||||
* previous node, the framework will call
|
||||
* @get_device (for contains) or @get_driver (for produces),
|
||||
* depending on the edge type, passing them the name of the next
|
||||
* node to be taken and getting from them the corresponding
|
||||
* pointer to the actual structure of the next node to
|
||||
* be used in the path.
|
||||
* @start_hw: This function is executed after all the path objects
|
||||
* have been allocated, but before the test is run. It starts the
|
||||
* hw, setting the initial configurations (\*_device_enable) and
|
||||
* making it ready for the test.
|
||||
* @destructor: Opposite to the node constructor, destroys the object.
|
||||
* This function is called after the test has been executed, and
|
||||
* performs a complete cleanup of each node allocated field.
|
||||
* In case no constructor is provided, no destructor will be
|
||||
* called.
|
||||
* @free: free the memory associated to the QOSGraphObject and its contained
|
||||
* children
|
||||
*/
|
||||
struct QOSGraphObject {
|
||||
/* for produces edges, returns void * */
|
||||
QOSGetDriver get_driver;
|
||||
/* for contains edges, returns a QOSGraphObject * */
|
||||
QOSGetDevice get_device;
|
||||
/* start the hw, get ready for the test */
|
||||
QOSStartFunct start_hw;
|
||||
/* destroy this QOSGraphObject */
|
||||
QOSDestructorFunc destructor;
|
||||
/* free the memory associated to the QOSGraphObject and its contained
|
||||
* children */
|
||||
GDestroyNotify free;
|
||||
};
|
||||
|
||||
@ -399,24 +152,30 @@ void qos_graph_init(void);
|
||||
void qos_graph_destroy(void);
|
||||
|
||||
/**
|
||||
* qos_node_destroy(): removes and frees a node from the,
|
||||
* qos_node_destroy(): removes and frees a node from the
|
||||
* nodes hash table.
|
||||
* @key: Name of the node
|
||||
*/
|
||||
void qos_node_destroy(void *key);
|
||||
|
||||
/**
|
||||
* qos_edge_destroy(): removes and frees an edge from the,
|
||||
* qos_edge_destroy(): removes and frees an edge from the
|
||||
* edges hash table.
|
||||
* @key: Name of the node
|
||||
*/
|
||||
void qos_edge_destroy(void *key);
|
||||
|
||||
/**
|
||||
* qos_add_test(): adds a test node @name to the nodes hash table.
|
||||
* @name: Name of the test
|
||||
* @interface: Name of the interface node it consumes
|
||||
* @test_func: Actual test to perform
|
||||
* @opts: Facultative options (see %QOSGraphTestOptions)
|
||||
*
|
||||
* The test will consume a @interface node, and once the
|
||||
* graph walking algorithm has found it, the @test_func will be
|
||||
* executed. It also has the possibility to
|
||||
* add an optional @opts (see %QOSGraphNodeOptions).
|
||||
* add an optional @opts (see %QOSGraphTestOptions).
|
||||
*
|
||||
* For tests, opts->edge.arg and size_arg represent the arg to pass
|
||||
* to @test_func
|
||||
@ -428,6 +187,8 @@ void qos_add_test(const char *name, const char *interface,
|
||||
/**
|
||||
* qos_node_create_machine(): creates the machine @name and
|
||||
* adds it to the node hash table.
|
||||
* @name: Name of the machine
|
||||
* @function: Machine constructor
|
||||
*
|
||||
* This node will be of type QNODE_MACHINE and have @function
|
||||
* as constructor
|
||||
@ -438,6 +199,9 @@ void qos_node_create_machine(const char *name, QOSCreateMachineFunc function);
|
||||
* qos_node_create_machine_args(): same as qos_node_create_machine,
|
||||
* but with the possibility to add an optional ", @opts" after -M machine
|
||||
* command line.
|
||||
* @name: Name of the machine
|
||||
* @function: Machine constructor
|
||||
* @opts: Optional additional command line
|
||||
*/
|
||||
void qos_node_create_machine_args(const char *name,
|
||||
QOSCreateMachineFunc function,
|
||||
@ -446,6 +210,8 @@ void qos_node_create_machine_args(const char *name,
|
||||
/**
|
||||
* qos_node_create_driver(): creates the driver @name and
|
||||
* adds it to the node hash table.
|
||||
* @name: Name of the driver
|
||||
* @function: Driver constructor
|
||||
*
|
||||
* This node will be of type QNODE_DRIVER and have @function
|
||||
* as constructor
|
||||
@ -453,17 +219,17 @@ void qos_node_create_machine_args(const char *name,
|
||||
void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
|
||||
|
||||
/**
|
||||
* Behaves as qos_node_create_driver() with the extension of allowing to
|
||||
* specify a different node name vs. associated QEMU device name.
|
||||
* qos_node_create_driver_named(): behaves as qos_node_create_driver() with the
|
||||
* extension of allowing to specify a different node name vs. associated QEMU
|
||||
* device name.
|
||||
* @name: Custom, unique name of the node to be created
|
||||
* @qemu_name: Actual (official) QEMU driver name the node shall be
|
||||
* associated with
|
||||
* @function: Driver constructor
|
||||
*
|
||||
* Use this function instead of qos_node_create_driver() if you need to create
|
||||
* several instances of the same QEMU device. You are free to choose a custom
|
||||
* node name, however the chosen node name must always be unique.
|
||||
*
|
||||
* @param name: custom, unique name of the node to be created
|
||||
* @param qemu_name: actual (official) QEMU driver name the node shall be
|
||||
* associated with
|
||||
* @param function: driver constructor
|
||||
*/
|
||||
void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
||||
QOSCreateDriverFunc function);
|
||||
@ -472,6 +238,9 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
||||
* qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS
|
||||
* and adds them to the edge list mapped to @container in the
|
||||
* edge hash table.
|
||||
* @container: Source node that "contains"
|
||||
* @contained: Destination node that "is contained"
|
||||
* @opts: Facultative options (see %QOSGraphEdgeOptions)
|
||||
*
|
||||
* The edges will have @container as source and @contained as destination.
|
||||
*
|
||||
@ -483,14 +252,17 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
|
||||
* This function can be useful when there are multiple devices
|
||||
* with the same node name contained in a machine/other node
|
||||
*
|
||||
* For example, if "arm/raspi2" contains 2 "generic-sdhci"
|
||||
* For example, if ``arm/raspi2`` contains 2 ``generic-sdhci``
|
||||
* devices, the right commands will be:
|
||||
* qos_node_create_machine("arm/raspi2");
|
||||
* qos_node_create_driver("generic-sdhci", constructor);
|
||||
* //assume rest of the fields are set NULL
|
||||
* QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
|
||||
* QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
|
||||
* qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL);
|
||||
*
|
||||
* .. code::
|
||||
*
|
||||
* qos_node_create_machine("arm/raspi2");
|
||||
* qos_node_create_driver("generic-sdhci", constructor);
|
||||
* // assume rest of the fields are set NULL
|
||||
* QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
|
||||
* QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
|
||||
* qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL);
|
||||
*
|
||||
* Of course this also requires that the @container's get_device function
|
||||
* should implement a case for "emmc" and "sdcard".
|
||||
@ -505,6 +277,8 @@ void qos_node_contains(const char *container, const char *contained,
|
||||
* qos_node_produces(): creates an edge of type QEDGE_PRODUCES and
|
||||
* adds it to the edge list mapped to @producer in the
|
||||
* edge hash table.
|
||||
* @producer: Source node that "produces"
|
||||
* @interface: Interface node that "is produced"
|
||||
*
|
||||
* This edge will have @producer as source and @interface as destination.
|
||||
*/
|
||||
@ -514,6 +288,9 @@ void qos_node_produces(const char *producer, const char *interface);
|
||||
* qos_node_consumes(): creates an edge of type QEDGE_CONSUMED_BY and
|
||||
* adds it to the edge list mapped to @interface in the
|
||||
* edge hash table.
|
||||
* @consumer: Node that "consumes"
|
||||
* @interface: Interface node that "is consumed by"
|
||||
* @opts: Facultative options (see %QOSGraphEdgeOptions)
|
||||
*
|
||||
* This edge will have @interface as source and @consumer as destination.
|
||||
* It also has the possibility to add an optional @opts
|
||||
@ -539,7 +316,7 @@ const char *qos_get_current_command_line(void);
|
||||
/**
|
||||
* qos_allocate_objects():
|
||||
* @qts: The #QTestState that will be referred to by the machine object.
|
||||
* @alloc: Where to store the allocator for the machine object, or %NULL.
|
||||
* @p_alloc: Where to store the allocator for the machine object, or %NULL.
|
||||
*
|
||||
* Allocate driver objects for the current test
|
||||
* path, but relative to the QTestState @qts.
|
||||
@ -551,24 +328,27 @@ void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc);
|
||||
|
||||
/**
|
||||
* qos_object_destroy(): calls the destructor for @obj
|
||||
* @obj: A #QOSGraphObject to destroy
|
||||
*/
|
||||
void qos_object_destroy(QOSGraphObject *obj);
|
||||
|
||||
/**
|
||||
* qos_object_queue_destroy(): queue the destructor for @obj so that it is
|
||||
* called at the end of the test
|
||||
* @obj: A #QOSGraphObject to destroy
|
||||
*/
|
||||
void qos_object_queue_destroy(QOSGraphObject *obj);
|
||||
|
||||
/**
|
||||
* qos_object_start_hw(): calls the start_hw function for @obj
|
||||
* @obj: A #QOSGraphObject containing the start_hw function
|
||||
*/
|
||||
void qos_object_start_hw(QOSGraphObject *obj);
|
||||
|
||||
/**
|
||||
* qos_machine_new(): instantiate a new machine node
|
||||
* @node: A machine node to be instantiated
|
||||
* @qts: The #QTestState that will be referred to by the machine object.
|
||||
* @node: Machine node to be instantiated
|
||||
* @qts: A #QTestState that will be referred to by the machine object.
|
||||
*
|
||||
* Returns a machine object.
|
||||
*/
|
||||
@ -587,8 +367,8 @@ QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent,
|
||||
QGuestAllocator *alloc, void *arg);
|
||||
|
||||
/**
|
||||
* Just for debugging purpose: prints all currently existing nodes and
|
||||
* edges to stdout.
|
||||
* qos_dump_graph(): prints all currently existing nodes and
|
||||
* edges to stdout. Just for debugging purposes.
|
||||
*
|
||||
* All qtests add themselves to the overall qos graph by calling qgraph
|
||||
* functions that add device nodes and edges between the individual graph
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
#include <pthread.h>
|
||||
|
Loading…
Reference in New Issue
Block a user