* Revert q35 to kernel irqchip (Alex)

* edu device fixes (Li Qiang)
 * cleanups (Marc-André, Peter)
 * Improvements to -accel help
 * Better support for IA32_MISC_ENABLE MSR (Wanpeng)
 * I2C test conversion to qgraph (Paolo)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJc9R6MAAoJEL/70l94x66D87kH/ikXGyVzENMyJZaro1Y+0bTk
 GJa7AkR7mUgjXkxGz4vkZCZ4dWuRYym50AW3JGEYXF2bpjAp1/xqfj1NZ4mJYggP
 GmIPKs7A3CKblWownrrEMRLWgVf4HMd59yBYqHwt+UwF6XNgT+O2seeEfW+XNMfC
 mQYWscbTrFGDd3SCX0E/r1xqerBa+EOvBq1bRu4os9U4OXP96RZrqyIKlpHU4ocm
 QuTFlZuOxat/xxflgQl4NZpi1RR3XR0VV0zF6Yym3Z2TA3T86c1sTuJgC+xEeIe8
 xDLaOwcmvlJUaYIAcE+1ReXg6x0y1/kEJDPppQQar7Jlp61Y7sMUAc71FQCLKvE=
 =uAc3
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* Revert q35 to kernel irqchip (Alex)
* edu device fixes (Li Qiang)
* cleanups (Marc-André, Peter)
* Improvements to -accel help
* Better support for IA32_MISC_ENABLE MSR (Wanpeng)
* I2C test conversion to qgraph (Paolo)

# gpg: Signature made Mon 03 Jun 2019 14:20:12 BST
# gpg:                using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream: (24 commits)
  q35: Revert to kernel irqchip
  configure: remove tpm_passthrough & tpm_emulator
  ci: store Patchew configuration in the tree
  libqos: i2c: move address into QI2CDevice
  tests: convert ds1338-test to qtest
  tests: convert OMAP i2c tests to qgraph
  libqos: add ARM imx25-pdk machine object
  libqos: add ARM n800 machine object
  libqos: convert I2C to qgraph
  libqos: split I2CAdapter initialization and allocation
  imx25-pdk: create ds1338 for qtest inside the test
  pca9552-test: do not rely on state across tests
  libqos: fix omap-i2c receiving more than 4 bytes
  libqos: move common i2c code to libqos
  qgraph: fix qos_node_contains with options
  qgraph: allow extra_device_opts on contains nodes
  edu: uses uint64_t in dma operation
  edu: mmio: allow 64-bit access in read dispatch
  edu: mmio: allow 64-bit access
  i386: Enable IA32_MISC_ENABLE MWAIT bit when exposing mwait/monitor
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-06-03 18:26:21 +01:00
commit e2a58ff493
29 changed files with 889 additions and 315 deletions

302
.patchew.yml Normal file
View File

@ -0,0 +1,302 @@
---
# Note: this file is still unused. It serves as a documentation for the
# Patchew configuration in case patchew.org disappears or has to be
# reinstalled.
#
# Patchew configuration is available to project administrators at
# https://patchew.org/api/v1/projects/1/config/ and can be configured
# to YAML using the following Python script:
#
# import json
# import sys
# import ruamel.yaml
#
# json_str = sys.stdin.read()
# yaml = ruamel.yaml.YAML()
# yaml.explicit_start = True
# data = json.loads(json_str, object_pairs_hook=ruamel.yaml.comments.CommentedMap)
# ruamel.yaml.scalarstring.walk_tree(data)
# yaml.dump(data, sys.stdout)
email:
notifications:
timeouts:
event: TestingReport
enabled: true
to_user: false
reply_subject: true
set_reply_to: true
in_reply_to: true
reply_to_all: false
subject_template: none
to: fam@euphon.net
cc: ''
body_template: |
{% if not is_timeout %} {{ cancel }} {% endif %}
Test '{{ test }}' timeout, log:
{{ log }}
ENOSPC:
event: TestingReport
enabled: true
to_user: false
reply_subject: false
set_reply_to: false
in_reply_to: true
reply_to_all: false
subject_template: Out of space error
to: fam@euphon.net
cc: ''
body_template: |
{% if passed %}
{{ cancel }}
{% endif %}
{% if 'No space left on device' in log %}
Tester {{ tester }} out of space when running {{ test }}
{{ log }}
{% else %}
{{ cancel }}
{% endif %}
FailureShort:
event: TestingReport
enabled: true
to_user: false
reply_subject: true
set_reply_to: true
in_reply_to: true
reply_to_all: true
subject_template: Testing failed
to: ''
cc: ''
body_template: |
{% if passed or not obj.message_id or is_timeout %}
{{ cancel }}
{% endif %}
{% if 'No space left on device' in log %}
{{ cancel }}
{% endif %}
Patchew URL: https://patchew.org/QEMU/{{ obj.message_id }}/
{% ansi2text log as logtext %}
{% if test == "checkpatch" %}
Hi,
This series seems to have some coding style problems. See output below for
more information:
{{ logtext }}
{% elif test == "docker-mingw@fedora" or test == "docker-quick@centos7" or test == "asan" %}
Hi,
This series failed the {{ test }} build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.
{% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %}
{% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %}
{% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %}
{% elif test == "s390x" or test == "FreeBSD" or test == "ppcle" or test == "ppcbe" %}
Hi,
This series failed build test on {{test}} host. Please find the details below.
{% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %}
{% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %}
{% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %}
{% else %}
{{ cancel }}
{% endif %}
The full log is available at
{{ log_url }}.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
testing:
tests:
asan:
enabled: true
requirements: docker
timeout: 3600
script: |
#!/bin/bash
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
docker-quick@centos7:
enabled: false
requirements: docker,x86_64
timeout: 3600
script: |
#!/bin/bash
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
checkpatch:
enabled: true
requirements: ''
timeout: 600
script: |
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
docker-mingw@fedora:
enabled: true
requirements: docker,x86_64
timeout: 3600
script: |
#! /bin/bash
test "$(uname -m)" = "x86_64"
ppcle:
enabled: false
requirements: ppcle
timeout: 3600
script: |
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
set -e
CC=$HOME/bin/cc
INSTALL=$PWD/install
BUILD=$PWD/build
mkdir -p $BUILD $INSTALL
SRC=$PWD
cd $BUILD
$SRC/configure --cc=$CC --prefix=$INSTALL
make -j4
# XXX: we need reliable clean up
# make check -j4 V=1
make install
echo
echo "=== ENV ==="
env
echo
echo "=== PACKAGES ==="
rpm -qa
ppcbe:
enabled: false
requirements: ppcbe
timeout: 3600
script: |
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
set -e
CC=$HOME/bin/cc
INSTALL=$PWD/install
BUILD=$PWD/build
mkdir -p $BUILD $INSTALL
SRC=$PWD
cd $BUILD
$SRC/configure --cc=$CC --prefix=$INSTALL
make -j4
# XXX: we need reliable clean up
# make check -j4 V=1
make install
echo
echo "=== ENV ==="
env
echo
echo "=== PACKAGES ==="
rpm -qa
FreeBSD:
enabled: true
requirements: qemu-x86,x86_64,git
timeout: 3600
script: |
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
if qemu-system-x86_64 --help >/dev/null 2>&1; then
QEMU=qemu-system-x86_64
elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then
QEMU=/usr/libexec/qemu-kvm
else
exit 1
fi
make vm-build-freebsd J=21 QEMU=$QEMU
exit 0
docker-clang@ubuntu:
enabled: true
requirements: docker,x86_64
timeout: 3600
script: |
#!/bin/bash
time make docker-test-clang@ubuntu SHOW_ENV=1 J=14 NETWORK=1
s390x:
enabled: true
requirements: s390x
timeout: 3600
script: |
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
set -e
CC=$HOME/bin/cc
INSTALL=$PWD/install
BUILD=$PWD/build
mkdir -p $BUILD $INSTALL
SRC=$PWD
cd $BUILD
$SRC/configure --cc=$CC --prefix=$INSTALL
make -j4
# XXX: we need reliable clean up
# make check -j4 V=1
make install
echo
echo "=== ENV ==="
env
echo
echo "=== PACKAGES ==="
rpm -qa
requirements:
x86_64:
script: |
#! /bin/bash
test "$(uname -m)" = "x86_64"
qemu-x86:
script: |
#!/bin/bash
if qemu-system-x86_64 --help >/dev/null 2>&1; then
:
elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then
:
else
exit 1
fi
ppcle:
script: |
#!/bin/bash
test "$(uname -m)" = "ppc64le"
ppcbe:
script: |
#!/bin/bash
test "$(uname -m)" = "ppc64"
git:
script: |
#! /bin/bash
git config user.name > /dev/null 2>&1
docker:
script: |
#!/bin/bash
docker ps || sudo -n docker ps
s390x:
script: |
#!/bin/bash
test "$(uname -m)" = "s390x"
git:
push_to: git@github.com:patchew-project/qemu
public_repo: https://github.com/patchew-project/qemu
url_template: https://github.com/patchew-project/qemu/tree/%t

10
configure vendored
View File

@ -6452,8 +6452,6 @@ echo "gcov $gcov_tool"
echo "gcov enabled $gcov"
echo "TPM support $tpm"
echo "libssh2 support $libssh2"
echo "TPM passthrough $tpm_passthrough"
echo "TPM emulator $tpm_emulator"
echo "QOM debugging $qom_cast_debug"
echo "Live block migration $live_block_migration"
echo "lzo support $lzo"
@ -7158,14 +7156,6 @@ fi
if test "$tpm" = "yes"; then
echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak
# TPM passthrough support?
if test "$tpm_passthrough" = "yes"; then
echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak
fi
# TPM emulator support?
if test "$tpm_emulator" = "yes"; then
echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak
fi
fi
echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak

View File

@ -131,15 +131,6 @@ static void imx25_pdk_init(MachineState *machine)
*/
if (!qtest_enabled()) {
arm_load_kernel(&s->soc.cpu, &imx25_pdk_binfo);
} else {
/*
* This I2C device doesn't exist on the real board.
* We add it here (only on qtest usage) to be able to do a bit
* of simple qtest. See "make check" for details.
*/
i2c_create_slave((I2CBus *)qdev_get_child_bus(DEVICE(&s->soc.i2c[0]),
"i2c-bus.0"),
"ds1338", 0x68);
}
}

View File

@ -24,6 +24,9 @@
#include "hw/pci/pci.h"
#include "hw/mem/nvdimm.h"
GlobalProperty hw_compat_4_0_1[] = {};
const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1);
GlobalProperty hw_compat_4_0[] = {};
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);

View File

@ -110,6 +110,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
/* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr;
GlobalProperty pc_compat_4_0_1[] = {};
const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1);
GlobalProperty pc_compat_4_0[] = {};
const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);

View File

@ -357,7 +357,7 @@ static void pc_q35_machine_options(MachineClass *m)
m->units_per_default_bus = 1;
m->default_machine_opts = "firmware=bios-256k.bin";
m->default_display = "std";
m->default_kernel_irqchip_split = true;
m->default_kernel_irqchip_split = false;
m->no_floppy = 1;
machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE);
@ -374,10 +374,22 @@ static void pc_q35_4_1_machine_options(MachineClass *m)
DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
pc_q35_4_1_machine_options);
static void pc_q35_4_0_machine_options(MachineClass *m)
static void pc_q35_4_0_1_machine_options(MachineClass *m)
{
pc_q35_4_1_machine_options(m);
m->alias = NULL;
compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len);
compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len);
}
DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL,
pc_q35_4_0_1_machine_options);
static void pc_q35_4_0_machine_options(MachineClass *m)
{
pc_q35_4_0_1_machine_options(m);
m->default_kernel_irqchip_split = true;
m->alias = NULL;
compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
}

View File

@ -98,23 +98,24 @@ static void edu_lower_irq(EduState *edu, uint32_t val)
}
}
static bool within(uint32_t addr, uint32_t start, uint32_t end)
static bool within(uint64_t addr, uint64_t start, uint64_t end)
{
return start <= addr && addr < end;
}
static void edu_check_range(uint32_t addr, uint32_t size1, uint32_t start,
uint32_t size2)
static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start,
uint64_t size2)
{
uint32_t end1 = addr + size1;
uint32_t end2 = start + size2;
uint64_t end1 = addr + size1;
uint64_t end2 = start + size2;
if (within(addr, start, end2) &&
end1 > addr && within(end1, start, end2)) {
return;
}
hw_error("EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!",
hw_error("EDU: DMA range 0x%016"PRIx64"-0x%016"PRIx64
" out of bounds (0x%016"PRIx64"-0x%016"PRIx64")!",
addr, end1 - 1, start, end2 - 1);
}
@ -139,13 +140,13 @@ static void edu_dma_timer(void *opaque)
}
if (EDU_DMA_DIR(edu->dma.cmd) == EDU_DMA_FROM_PCI) {
uint32_t dst = edu->dma.dst;
uint64_t dst = edu->dma.dst;
edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE);
dst -= DMA_START;
pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src),
edu->dma_buf + dst, edu->dma.cnt);
} else {
uint32_t src = edu->dma.src;
uint64_t src = edu->dma.src;
edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE);
src -= DMA_START;
pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst),
@ -185,7 +186,11 @@ static uint64_t edu_mmio_read(void *opaque, hwaddr addr, unsigned size)
EduState *edu = opaque;
uint64_t val = ~0ULL;
if (size != 4) {
if (addr < 0x80 && size != 4) {
return val;
}
if (addr >= 0x80 && size != 4 && size != 8) {
return val;
}
@ -289,6 +294,15 @@ static const MemoryRegionOps edu_mmio_ops = {
.read = edu_mmio_read,
.write = edu_mmio_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 8,
},
.impl = {
.min_access_size = 4,
.max_access_size = 8,
},
};
/*

View File

@ -1254,23 +1254,6 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize,
*/
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
/**
* memory_region_get_dirty: Check whether a range of bytes is dirty
* for a specified client.
*
* Checks whether a range of bytes has been written to since the last
* call to memory_region_reset_dirty() with the same @client. Dirty logging
* must be enabled.
*
* @mr: the memory region being queried.
* @addr: the address (relative to the start of the region) being queried.
* @size: the size of the range being queried.
* @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or
* %DIRTY_MEMORY_VGA.
*/
bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr size, unsigned client);
/**
* memory_region_set_dirty: Mark a range of bytes as dirty in a memory region.
*

View File

@ -292,6 +292,9 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
extern GlobalProperty hw_compat_4_0_1[];
extern const size_t hw_compat_4_0_1_len;
extern GlobalProperty hw_compat_4_0[];
extern const size_t hw_compat_4_0_len;

View File

@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
extern GlobalProperty pc_compat_4_0_1[];
extern const size_t pc_compat_4_0_1_len;
extern GlobalProperty pc_compat_4_0[];
extern const size_t pc_compat_4_0_len;

View File

@ -2027,14 +2027,6 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
memory_region_transaction_commit();
}
bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr size, unsigned client)
{
assert(mr->ram_block);
return cpu_physical_memory_get_dirty(memory_region_get_ram_addr(mr) + addr,
size, client);
}
void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr size)
{

View File

@ -1949,7 +1949,8 @@ sub process {
}
# no C99 // comments
if ($line =~ m{//}) {
if ($line =~ m{//} &&
$rawline !~ m{// SPDX-License-Identifier: }) {
ERROR("do not use C99 // comments\n" . $herecurr);
}
# Remove C99 comments.

View File

@ -4730,6 +4730,9 @@ static void x86_cpu_reset(CPUState *s)
env->pat = 0x0007040600070406ULL;
env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
if (env->features[FEAT_1_ECX] & CPUID_EXT_MONITOR) {
env->msr_ia32_misc_enable |= MSR_IA32_MISC_ENABLE_MWAIT;
}
memset(env->dr, 0, sizeof(env->dr));
env->dr[6] = DR6_FIXED_1;

View File

@ -387,6 +387,7 @@ typedef enum X86Seg {
#define MSR_IA32_MISC_ENABLE 0x1a0
/* Indicates good rep/movs microcode on some processors: */
#define MSR_IA32_MISC_ENABLE_DEFAULT 1
#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18)
#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg))
#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1)

View File

@ -255,9 +255,6 @@ check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF)
check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF)
check-qtest-arm-y += tests/tmp105-test$(EXESUF)
check-qtest-arm-y += tests/pca9552-test$(EXESUF)
check-qtest-arm-y += tests/ds1338-test$(EXESUF)
check-qtest-arm-y += tests/microbit-test$(EXESUF)
check-qtest-arm-y += tests/m25p80-test$(EXESUF)
check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
@ -678,7 +675,7 @@ libqgraph-obj-y = tests/libqos/qgraph.o
libqos-obj-y = $(libqgraph-obj-y) tests/libqos/pci.o tests/libqos/fw_cfg.o
libqos-obj-y += tests/libqos/malloc.o
libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
libqos-obj-y += tests/libqos/libqos.o
libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
libqos-spapr-obj-y += tests/libqos/rtas.o
@ -686,14 +683,15 @@ libqos-spapr-obj-y += tests/libqos/pci-spapr.o
libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
libqos-pc-obj-y += tests/libqos/ahci.o
libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
# Devices
qos-test-obj-y = tests/qos-test.o $(libqgraph-obj-y)
qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
qos-test-obj-y += tests/libqos/e1000e.o
qos-test-obj-y += tests/libqos/i2c.o
qos-test-obj-y += tests/libqos/i2c-imx.o
qos-test-obj-y += tests/libqos/i2c-omap.o
qos-test-obj-y += tests/libqos/sdhci.o
qos-test-obj-y += tests/libqos/tpci200.o
qos-test-obj-y += tests/libqos/virtio.o
@ -709,6 +707,8 @@ qos-test-obj-y += tests/libqos/virtio-serial.o
# Machines
qos-test-obj-y += tests/libqos/aarch64-xlnx-zcu102-machine.o
qos-test-obj-y += tests/libqos/arm-imx25-pdk-machine.o
qos-test-obj-y += tests/libqos/arm-n800-machine.o
qos-test-obj-y += tests/libqos/arm-raspi2-machine.o
qos-test-obj-y += tests/libqos/arm-sabrelite-machine.o
qos-test-obj-y += tests/libqos/arm-smdkc210-machine.o
@ -719,6 +719,7 @@ qos-test-obj-y += tests/libqos/x86_64_pc-machine.o
# Tests
qos-test-obj-y += tests/ac97-test.o
qos-test-obj-y += tests/ds1338-test.o
qos-test-obj-y += tests/e1000-test.o
qos-test-obj-y += tests/e1000e-test.o
qos-test-obj-y += tests/eepro100-test.o
@ -727,10 +728,12 @@ qos-test-obj-y += tests/ipoctal232-test.o
qos-test-obj-y += tests/megasas-test.o
qos-test-obj-y += tests/ne2000-test.o
qos-test-obj-y += tests/nvme-test.o
qos-test-obj-y += tests/pca9552-test.o
qos-test-obj-y += tests/pci-test.o
qos-test-obj-y += tests/pcnet-test.o
qos-test-obj-y += tests/sdhci-test.o
qos-test-obj-y += tests/spapr-phb-test.o
qos-test-obj-y += tests/tmp105-test.o
qos-test-obj-y += tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y)
qos-test-obj-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test.o $(chardev-obj-y) $(test-io-obj-y)
qos-test-obj-y += tests/virtio-test.o
@ -768,9 +771,6 @@ tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y)
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y)
tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y)
tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
tests/microbit-test$(EXESUF): tests/microbit-test.o
tests/m25p80-test$(EXESUF): tests/m25p80-test.o
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)

View File

@ -21,31 +21,22 @@
#include "libqtest.h"
#include "libqos/i2c.h"
#define IMX25_I2C_0_BASE 0x43F80000
#define DS1338_ADDR 0x68
static I2CAdapter *i2c;
static uint8_t addr;
static inline uint8_t bcd2bin(uint8_t x)
{
return ((x) & 0x0f) + ((x) >> 4) * 10;
}
static void send_and_receive(void)
static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc)
{
uint8_t cmd[1];
QI2CDevice *i2cdev = (QI2CDevice *)obj;
uint8_t resp[7];
time_t now = time(NULL);
struct tm *tm_ptr = gmtime(&now);
/* reset the index in the RTC memory */
cmd[0] = 0;
i2c_send(i2c, addr, cmd, 1);
/* retrieve the date */
i2c_recv(i2c, addr, resp, 7);
i2c_read_block(i2cdev, 0, resp, sizeof(resp));
/* check retrieved time againt local time */
g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday);
@ -53,23 +44,15 @@ static void send_and_receive(void)
g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year);
}
int main(int argc, char **argv)
static void ds1338_register_nodes(void)
{
QTestState *s = NULL;
int ret;
QOSGraphEdgeOptions opts = {
.extra_device_opts = "address=0x68"
};
add_qi2c_address(&opts, &(QI2CAddress) { DS1338_ADDR });
g_test_init(&argc, &argv, NULL);
s = qtest_start("-display none -machine imx25-pdk");
i2c = imx_i2c_create(s, IMX25_I2C_0_BASE);
addr = DS1338_ADDR;
qtest_add_func("/ds1338/tx-rx", send_and_receive);
ret = g_test_run();
qtest_quit(s);
g_free(i2c);
return ret;
qos_node_create_driver("ds1338", i2c_device_create);
qos_node_consumes("ds1338", "i2c-bus", &opts);
qos_add_test("tx-rx", "ds1338", send_and_receive, NULL);
}
libqos_init(ds1338_register_nodes);

View File

@ -0,0 +1,92 @@
/*
* libqos driver framework
*
* Copyright (c) 2019 Red Hat, Inc.
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* 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/>
*/
#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/malloc.h"
#include "libqos/qgraph.h"
#include "libqos/i2c.h"
#define ARM_PAGE_SIZE 4096
#define IMX25_PDK_RAM_START 0x80000000
#define IMX25_PDK_RAM_END 0x88000000
typedef struct QIMX25PDKMachine QIMX25PDKMachine;
struct QIMX25PDKMachine {
QOSGraphObject obj;
QGuestAllocator alloc;
IMXI2C i2c_1;
};
static void *imx25_pdk_get_driver(void *object, const char *interface)
{
QIMX25PDKMachine *machine = object;
if (!g_strcmp0(interface, "memory")) {
return &machine->alloc;
}
fprintf(stderr, "%s not present in arm/imx25_pdk\n", interface);
g_assert_not_reached();
}
static QOSGraphObject *imx25_pdk_get_device(void *obj, const char *device)
{
QIMX25PDKMachine *machine = obj;
if (!g_strcmp0(device, "imx.i2c")) {
return &machine->i2c_1.obj;
}
fprintf(stderr, "%s not present in arm/imx25_pdk\n", device);
g_assert_not_reached();
}
static void imx25_pdk_destructor(QOSGraphObject *obj)
{
QIMX25PDKMachine *machine = (QIMX25PDKMachine *) obj;
alloc_destroy(&machine->alloc);
}
static void *qos_create_machine_arm_imx25_pdk(QTestState *qts)
{
QIMX25PDKMachine *machine = g_new0(QIMX25PDKMachine, 1);
alloc_init(&machine->alloc, 0,
IMX25_PDK_RAM_START,
IMX25_PDK_RAM_END,
ARM_PAGE_SIZE);
machine->obj.get_device = imx25_pdk_get_device;
machine->obj.get_driver = imx25_pdk_get_driver;
machine->obj.destructor = imx25_pdk_destructor;
imx_i2c_init(&machine->i2c_1, qts, 0x43f80000);
return &machine->obj;
}
static void imx25_pdk_register_nodes(void)
{
QOSGraphEdgeOptions edge = {
.extra_device_opts = "bus=i2c-bus.0"
};
qos_node_create_machine("arm/imx25-pdk", qos_create_machine_arm_imx25_pdk);
qos_node_contains("arm/imx25-pdk", "imx.i2c", &edge, NULL);
}
libqos_init(imx25_pdk_register_nodes);

View File

@ -0,0 +1,92 @@
/*
* libqos driver framework
*
* Copyright (c) 2019 Red Hat, Inc.
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* 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/>
*/
#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/malloc.h"
#include "libqos/qgraph.h"
#include "libqos/i2c.h"
#define ARM_PAGE_SIZE 4096
#define N800_RAM_START 0x80000000
#define N800_RAM_END 0x88000000
typedef struct QN800Machine QN800Machine;
struct QN800Machine {
QOSGraphObject obj;
QGuestAllocator alloc;
OMAPI2C i2c_1;
};
static void *n800_get_driver(void *object, const char *interface)
{
QN800Machine *machine = object;
if (!g_strcmp0(interface, "memory")) {
return &machine->alloc;
}
fprintf(stderr, "%s not present in arm/n800\n", interface);
g_assert_not_reached();
}
static QOSGraphObject *n800_get_device(void *obj, const char *device)
{
QN800Machine *machine = obj;
if (!g_strcmp0(device, "omap_i2c")) {
return &machine->i2c_1.obj;
}
fprintf(stderr, "%s not present in arm/n800\n", device);
g_assert_not_reached();
}
static void n800_destructor(QOSGraphObject *obj)
{
QN800Machine *machine = (QN800Machine *) obj;
alloc_destroy(&machine->alloc);
}
static void *qos_create_machine_arm_n800(QTestState *qts)
{
QN800Machine *machine = g_new0(QN800Machine, 1);
alloc_init(&machine->alloc, 0,
N800_RAM_START,
N800_RAM_END,
ARM_PAGE_SIZE);
machine->obj.get_device = n800_get_device;
machine->obj.get_driver = n800_get_driver;
machine->obj.destructor = n800_destructor;
omap_i2c_init(&machine->i2c_1, qts, 0x48070000);
return &machine->obj;
}
static void n800_register_nodes(void)
{
QOSGraphEdgeOptions edge = {
.extra_device_opts = "bus=i2c-bus.0"
};
qos_node_create_machine("arm/n800", qos_create_machine_arm_n800);
qos_node_contains("arm/n800", "omap_i2c", &edge, NULL);
}
libqos_init(n800_register_nodes);

View File

@ -30,13 +30,6 @@ enum IMXI2CDirection {
IMX_I2C_WRITE,
};
typedef struct IMXI2C {
I2CAdapter parent;
uint64_t addr;
} IMXI2C;
static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr,
enum IMXI2CDirection direction)
{
@ -47,7 +40,7 @@ static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr,
static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr,
const uint8_t *buf, uint16_t len)
{
IMXI2C *s = (IMXI2C *)i2c;
IMXI2C *s = container_of(i2c, IMXI2C, parent);
uint8_t data;
uint8_t status;
uint16_t size = 0;
@ -107,7 +100,7 @@ static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr,
static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr,
uint8_t *buf, uint16_t len)
{
IMXI2C *s = (IMXI2C *)i2c;
IMXI2C *s = container_of(i2c, IMXI2C, parent);
uint8_t data;
uint8_t status;
uint16_t size = 0;
@ -193,16 +186,31 @@ static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr,
g_assert((status & I2SR_IBB) == 0);
}
I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr)
static void *imx_i2c_get_driver(void *obj, const char *interface)
{
IMXI2C *s = g_malloc0(sizeof(*s));
I2CAdapter *i2c = (I2CAdapter *)s;
IMXI2C *s = obj;
if (!g_strcmp0(interface, "i2c-bus")) {
return &s->parent;
}
fprintf(stderr, "%s not present in imx-i2c\n", interface);
g_assert_not_reached();
}
void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr)
{
s->addr = addr;
i2c->send = imx_i2c_send;
i2c->recv = imx_i2c_recv;
i2c->qts = qts;
s->obj.get_driver = imx_i2c_get_driver;
return i2c;
s->parent.send = imx_i2c_send;
s->parent.recv = imx_i2c_recv;
s->parent.qts = qts;
}
static void imx_i2c_register_nodes(void)
{
qos_node_create_driver("imx.i2c", NULL);
qos_node_produces("imx.i2c", "i2c-bus");
}
libqos_init(imx_i2c_register_nodes);

View File

@ -40,12 +40,6 @@ enum OMAPI2CCONBits {
OMAP_I2C_CON_I2C_EN = 1 << 15,
};
typedef struct OMAPI2C {
I2CAdapter parent;
uint64_t addr;
} OMAPI2C;
static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr)
{
@ -59,7 +53,7 @@ static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr)
static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr,
const uint8_t *buf, uint16_t len)
{
OMAPI2C *s = (OMAPI2C *)i2c;
OMAPI2C *s = container_of(i2c, OMAPI2C, parent);
uint16_t data;
omap_i2c_set_slave_addr(s, addr);
@ -103,8 +97,9 @@ static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr,
static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr,
uint8_t *buf, uint16_t len)
{
OMAPI2C *s = (OMAPI2C *)i2c;
OMAPI2C *s = container_of(i2c, OMAPI2C, parent);
uint16_t data, stat;
uint16_t orig_len = len;
omap_i2c_set_slave_addr(s, addr);
@ -116,16 +111,24 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr,
OMAP_I2C_CON_STT |
OMAP_I2C_CON_STP;
qtest_writew(i2c->qts, s->addr + OMAP_I2C_CON, data);
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CON);
g_assert((data & OMAP_I2C_CON_STP) == 0);
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_STAT);
g_assert((data & OMAP_I2C_STAT_NACK) == 0);
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT);
g_assert_cmpuint(data, ==, len);
while (len > 0) {
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CON);
if (len <= 4) {
g_assert((data & OMAP_I2C_CON_STP) == 0);
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT);
g_assert_cmpuint(data, ==, orig_len);
} else {
g_assert((data & OMAP_I2C_CON_STP) != 0);
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT);
g_assert_cmpuint(data, ==, len - 4);
}
data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_STAT);
g_assert((data & OMAP_I2C_STAT_RRDY) != 0);
g_assert((data & OMAP_I2C_STAT_ROVR) == 0);
@ -152,21 +155,42 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr,
g_assert((data & OMAP_I2C_CON_STP) == 0);
}
I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr)
static void *omap_i2c_get_driver(void *obj, const char *interface)
{
OMAPI2C *s = g_malloc0(sizeof(*s));
I2CAdapter *i2c = (I2CAdapter *)s;
OMAPI2C *s = obj;
if (!g_strcmp0(interface, "i2c-bus")) {
return &s->parent;
}
fprintf(stderr, "%s not present in omap_i2c\n", interface);
g_assert_not_reached();
}
static void omap_i2c_start_hw(QOSGraphObject *object)
{
OMAPI2C *s = (OMAPI2C *) object;
uint16_t data;
/* verify the mmio address by looking for a known signature */
data = qtest_readw(s->parent.qts, s->addr + OMAP_I2C_REV);
g_assert_cmphex(data, ==, 0x34);
}
void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr)
{
s->addr = addr;
i2c->send = omap_i2c_send;
i2c->recv = omap_i2c_recv;
i2c->qts = qts;
s->obj.get_driver = omap_i2c_get_driver;
s->obj.start_hw = omap_i2c_start_hw;
/* verify the mmio address by looking for a known signature */
data = qtest_readw(qts, addr + OMAP_I2C_REV);
g_assert_cmphex(data, ==, 0x34);
return i2c;
s->parent.send = omap_i2c_send;
s->parent.recv = omap_i2c_recv;
s->parent.qts = qts;
}
static void omap_i2c_register_nodes(void)
{
qos_node_create_driver("omap_i2c", NULL);
qos_node_produces("omap_i2c", "i2c-bus");
}
libqos_init(omap_i2c_register_nodes);

View File

@ -10,14 +10,76 @@
#include "libqos/i2c.h"
#include "libqtest.h"
void i2c_send(I2CAdapter *i2c, uint8_t addr,
const uint8_t *buf, uint16_t len)
void i2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len)
{
i2c->send(i2c, addr, buf, len);
i2cdev->bus->send(i2cdev->bus, i2cdev->addr, buf, len);
}
void i2c_recv(I2CAdapter *i2c, uint8_t addr,
uint8_t *buf, uint16_t len)
void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
{
i2c->recv(i2c, addr, buf, len);
i2cdev->bus->recv(i2cdev->bus, i2cdev->addr, buf, len);
}
void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg,
uint8_t *buf, uint16_t len)
{
i2c_send(i2cdev, &reg, 1);
i2c_recv(i2cdev, buf, len);
}
void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg,
const uint8_t *buf, uint16_t len)
{
uint8_t *cmd = g_malloc(len + 1);
cmd[0] = reg;
memcpy(&cmd[1], buf, len);
i2c_send(i2cdev, cmd, len + 1);
g_free(cmd);
}
uint8_t i2c_get8(QI2CDevice *i2cdev, uint8_t reg)
{
uint8_t resp[1];
i2c_read_block(i2cdev, reg, resp, sizeof(resp));
return resp[0];
}
uint16_t i2c_get16(QI2CDevice *i2cdev, uint8_t reg)
{
uint8_t resp[2];
i2c_read_block(i2cdev, reg, resp, sizeof(resp));
return (resp[0] << 8) | resp[1];
}
void i2c_set8(QI2CDevice *i2cdev, uint8_t reg, uint8_t value)
{
i2c_write_block(i2cdev, reg, &value, 1);
}
void i2c_set16(QI2CDevice *i2cdev, uint8_t reg, uint16_t value)
{
uint8_t data[2];
data[0] = value >> 8;
data[1] = value & 255;
i2c_write_block(i2cdev, reg, data, sizeof(data));
}
void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr)
{
QI2CDevice *i2cdev = g_new0(QI2CDevice, 1);
i2cdev->bus = i2c_bus;
if (addr) {
i2cdev->addr = ((QI2CAddress *)addr)->addr;
}
return &i2cdev->obj;
}
void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr)
{
g_assert(addr);
opts->arg = addr;
opts->size_arg = sizeof(QI2CAddress);
}

View File

@ -10,6 +10,7 @@
#define LIBQOS_I2C_H
#include "libqtest.h"
#include "libqos/qgraph.h"
typedef struct I2CAdapter I2CAdapter;
struct I2CAdapter {
@ -21,17 +22,61 @@ struct I2CAdapter {
QTestState *qts;
};
#define OMAP2_I2C_1_BASE 0x48070000
typedef struct QI2CAddress QI2CAddress;
struct QI2CAddress {
uint8_t addr;
};
void i2c_send(I2CAdapter *i2c, uint8_t addr,
const uint8_t *buf, uint16_t len);
void i2c_recv(I2CAdapter *i2c, uint8_t addr,
uint8_t *buf, uint16_t len);
typedef struct QI2CDevice QI2CDevice;
struct QI2CDevice {
/*
* For now, all devices are simple enough that there is no need for
* them to define their own constructor and get_driver functions.
* Therefore, QOSGraphObject is included directly in QI2CDevice;
* the tests expect to get a QI2CDevice rather than doing something
* like obj->get_driver("i2c-device").
*
* In fact there is no i2c-device interface even, because there are
* no generic I2C tests).
*/
QOSGraphObject obj;
I2CAdapter *bus;
uint8_t addr;
};
/* libi2c-omap.c */
I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr);
void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr);
void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr);
/* libi2c-imx.c */
I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr);
void i2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len);
void i2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len);
void i2c_read_block(QI2CDevice *dev, uint8_t reg,
uint8_t *buf, uint16_t len);
void i2c_write_block(QI2CDevice *dev, uint8_t reg,
const uint8_t *buf, uint16_t len);
uint8_t i2c_get8(QI2CDevice *dev, uint8_t reg);
uint16_t i2c_get16(QI2CDevice *dev, uint8_t reg);
void i2c_set8(QI2CDevice *dev, uint8_t reg, uint8_t value);
void i2c_set16(QI2CDevice *dev, uint8_t reg, uint16_t value);
/* i2c-omap.c */
typedef struct OMAPI2C {
QOSGraphObject obj;
I2CAdapter parent;
uint64_t addr;
} OMAPI2C;
void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr);
/* i2c-imx.c */
typedef struct IMXI2C {
QOSGraphObject obj;
I2CAdapter parent;
uint64_t addr;
} IMXI2C;
void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr);
#endif

View File

@ -632,15 +632,19 @@ void qos_node_create_driver(const char *name, QOSCreateDriverFunc function)
}
void qos_node_contains(const char *container, const char *contained,
...)
QOSGraphEdgeOptions *opts, ...)
{
va_list va;
va_start(va, contained);
QOSGraphEdgeOptions *opts;
if (opts == NULL) {
add_edge(container, contained, QEDGE_CONTAINS, NULL);
return;
}
va_start(va, opts);
do {
opts = va_arg(va, QOSGraphEdgeOptions *);
add_edge(container, contained, QEDGE_CONTAINS, opts);
opts = va_arg(va, QOSGraphEdgeOptions *);
} while (opts != NULL);
va_end(va);

View File

@ -453,14 +453,16 @@ void qos_node_create_machine_args(const char *name,
void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
/**
* qos_node_contains(): creates an edge of type QEDGE_CONTAINS and
* adds it to the edge list mapped to @container in the
* 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.
*
* This edge will have @container as source and @contained as destination.
* The edges will have @container as source and @contained as destination.
*
* It also has the possibility to add optional NULL-terminated
* @opts parameters (see %QOSGraphEdgeOptions)
* If @opts is NULL, a single edge will be added with no options.
* If @opts is non-NULL, the arguments after @contained represent a
* NULL-terminated list of %QOSGraphEdgeOptions structs, and an
* edge will be added for each of them.
*
* This function can be useful when there are multiple devices
* with the same node name contained in a machine/other node
@ -480,7 +482,8 @@ void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
* For contains, op1.arg and op1.size_arg represent the arg to pass
* to @contained constructor to properly initialize it.
*/
void qos_node_contains(const char *container, const char *contained, ...);
void qos_node_contains(const char *container, const char *contained,
QOSGraphEdgeOptions *opts, ...);
/**
* qos_node_produces(): creates an edge of type QEDGE_PRODUCES and

View File

@ -10,107 +10,84 @@
#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/qgraph.h"
#include "libqos/i2c.h"
#include "hw/misc/pca9552_regs.h"
#define PCA9552_TEST_ID "pca9552-test"
#define PCA9552_TEST_ADDR 0x60
static I2CAdapter *i2c;
static uint8_t pca9552_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
static void pca9552_init(QI2CDevice *i2cdev)
{
uint8_t resp[1];
i2c_send(i2c, addr, &reg, 1);
i2c_recv(i2c, addr, resp, 1);
return resp[0];
/* Switch on LEDs 0 and 12 */
i2c_set8(i2cdev, PCA9552_LS0, 0x54);
i2c_set8(i2cdev, PCA9552_LS3, 0x54);
}
static void pca9552_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
uint8_t value)
{
uint8_t cmd[2];
uint8_t resp[1];
cmd[0] = reg;
cmd[1] = value;
i2c_send(i2c, addr, cmd, 2);
i2c_recv(i2c, addr, resp, 1);
g_assert_cmphex(resp[0], ==, cmd[1]);
}
static void receive_autoinc(void)
static void receive_autoinc(void *obj, void *data, QGuestAllocator *alloc)
{
QI2CDevice *i2cdev = (QI2CDevice *)obj;
uint8_t resp;
uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC;
i2c_send(i2c, PCA9552_TEST_ADDR, &reg, 1);
pca9552_init(i2cdev);
i2c_send(i2cdev, &reg, 1);
/* PCA9552_LS0 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
i2c_recv(i2cdev, &resp, 1);
g_assert_cmphex(resp, ==, 0x54);
/* PCA9552_LS1 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
i2c_recv(i2cdev, &resp, 1);
g_assert_cmphex(resp, ==, 0x55);
/* PCA9552_LS2 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
i2c_recv(i2cdev, &resp, 1);
g_assert_cmphex(resp, ==, 0x55);
/* PCA9552_LS3 */
i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1);
i2c_recv(i2cdev, &resp, 1);
g_assert_cmphex(resp, ==, 0x54);
}
static void send_and_receive(void)
static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc)
{
QI2CDevice *i2cdev = (QI2CDevice *)obj;
uint8_t value;
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0);
value = i2c_get8(i2cdev, PCA9552_LS0);
g_assert_cmphex(value, ==, 0x55);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0);
value = i2c_get8(i2cdev, PCA9552_INPUT0);
g_assert_cmphex(value, ==, 0x0);
/* Switch on LED 0 */
pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0);
pca9552_init(i2cdev);
value = i2c_get8(i2cdev, PCA9552_LS0);
g_assert_cmphex(value, ==, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0);
value = i2c_get8(i2cdev, PCA9552_INPUT0);
g_assert_cmphex(value, ==, 0x01);
/* Switch on LED 12 */
pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3);
value = i2c_get8(i2cdev, PCA9552_LS3);
g_assert_cmphex(value, ==, 0x54);
value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1);
value = i2c_get8(i2cdev, PCA9552_INPUT1);
g_assert_cmphex(value, ==, 0x10);
}
int main(int argc, char **argv)
static void pca9552_register_nodes(void)
{
QTestState *s = NULL;
int ret;
QOSGraphEdgeOptions opts = {
.extra_device_opts = "address=0x60"
};
add_qi2c_address(&opts, &(QI2CAddress) { 0x60 });
g_test_init(&argc, &argv, NULL);
qos_node_create_driver("pca9552", i2c_device_create);
qos_node_consumes("pca9552", "i2c-bus", &opts);
s = qtest_start("-machine n800 "
"-device pca9552,bus=i2c-bus.0,id=" PCA9552_TEST_ID
",address=0x60");
i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE);
qtest_add_func("/pca9552/tx-rx", send_and_receive);
qtest_add_func("/pca9552/rx-autoinc", receive_autoinc);
ret = g_test_run();
if (s) {
qtest_quit(s);
}
g_free(i2c);
return ret;
qos_add_test("tx-rx", "pca9552", send_and_receive, NULL);
qos_add_test("rx-autoinc", "pca9552", receive_autoinc, NULL);
}
libqos_init(pca9552_register_nodes);

View File

@ -340,7 +340,8 @@ static void walk_path(QOSGraphNode *orig_path, int len)
char **path_vec = g_new0(char *, (QOS_PATH_MAX_ELEMENT_SIZE * 2));
int path_vec_size = 0;
char *after_cmd = NULL, *before_cmd = NULL, *after_device = NULL;
char *after_cmd, *before_cmd, *after_device;
GString *after_device_str = g_string_new("");
char *node_name = orig_path->name, *path_str;
GString *cmd_line = g_string_new("");
@ -363,9 +364,8 @@ static void walk_path(QOSGraphNode *orig_path, int len)
/* append node command line + previous edge command line */
if (path->command_line && etype == QEDGE_CONSUMED_BY) {
g_string_append(cmd_line, path->command_line);
if (after_device) {
g_string_append(cmd_line, after_device);
}
g_string_append(cmd_line, after_device_str->str);
g_string_truncate(after_device_str, 0);
}
path_vec[path_vec_size++] = qos_graph_edge_get_name(path->path_edge);
@ -382,12 +382,15 @@ static void walk_path(QOSGraphNode *orig_path, int len)
if (after_cmd) {
g_string_append(cmd_line2, after_cmd);
}
if (after_device) {
g_string_append(after_device_str, after_device);
}
}
path_vec[path_vec_size++] = NULL;
if (after_device) {
g_string_append(cmd_line, after_device);
}
g_string_append(cmd_line, after_device_str->str);
g_string_free(after_device_str, true);
g_string_append(cmd_line, cmd_line2->str);
g_string_free(cmd_line2, true);

View File

@ -27,9 +27,10 @@ static int worker_cb(void *opaque)
static int long_cb(void *opaque)
{
WorkerTestData *data = opaque;
atomic_inc(&data->n);
g_usleep(2000000);
atomic_inc(&data->n);
if (atomic_cmpxchg(&data->n, 0, 1) == 0) {
g_usleep(2000000);
atomic_or(&data->n, 2);
}
return 0;
}
@ -171,7 +172,7 @@ static void do_test_cancel(bool sync)
/* Cancel the jobs that haven't been started yet. */
num_canceled = 0;
for (i = 0; i < 100; i++) {
if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) {
if (atomic_cmpxchg(&data[i].n, 0, 4) == 0) {
data[i].ret = -ECANCELED;
if (sync) {
bdrv_aio_cancel(data[i].aiocb);
@ -185,7 +186,7 @@ static void do_test_cancel(bool sync)
g_assert_cmpint(num_canceled, <, 100);
for (i = 0; i < 100; i++) {
if (data[i].aiocb && data[i].n != 3) {
if (data[i].aiocb && atomic_read(&data[i].n) < 4) {
if (sync) {
/* Canceling the others will be a blocking operation. */
bdrv_aio_cancel(data[i].aiocb);
@ -201,13 +202,22 @@ static void do_test_cancel(bool sync)
}
g_assert_cmpint(active, ==, 0);
for (i = 0; i < 100; i++) {
if (data[i].n == 3) {
g_assert(data[i].aiocb == NULL);
switch (data[i].n) {
case 0:
fprintf(stderr, "Callback not canceled but never started?\n");
abort();
case 3:
/* Couldn't be canceled asynchronously, must have completed. */
g_assert_cmpint(data[i].ret, ==, 0);
break;
case 4:
/* Could be canceled asynchronously, never started. */
g_assert_cmpint(data[i].ret, ==, -ECANCELED);
g_assert(data[i].aiocb == NULL);
} else {
g_assert_cmpint(data[i].n, ==, 2);
g_assert(data[i].ret == 0 || data[i].ret == -ECANCELED);
g_assert(data[i].aiocb == NULL);
break;
default:
fprintf(stderr, "Callback aborted while running?\n");
abort();
}
}
}

View File

@ -10,6 +10,7 @@
#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/qgraph.h"
#include "libqos/i2c.h"
#include "qapi/qmp/qdict.h"
#include "hw/misc/tmp105_regs.h"
@ -17,52 +18,6 @@
#define TMP105_TEST_ID "tmp105-test"
#define TMP105_TEST_ADDR 0x49
static I2CAdapter *i2c;
static uint16_t tmp105_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
{
uint8_t resp[1];
i2c_send(i2c, addr, &reg, 1);
i2c_recv(i2c, addr, resp, 1);
return resp[0];
}
static uint16_t tmp105_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
{
uint8_t resp[2];
i2c_send(i2c, addr, &reg, 1);
i2c_recv(i2c, addr, resp, 2);
return (resp[0] << 8) | resp[1];
}
static void tmp105_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
uint8_t value)
{
uint8_t cmd[2];
uint8_t resp[1];
cmd[0] = reg;
cmd[1] = value;
i2c_send(i2c, addr, cmd, 2);
i2c_recv(i2c, addr, resp, 1);
g_assert_cmphex(resp[0], ==, cmd[1]);
}
static void tmp105_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
uint16_t value)
{
uint8_t cmd[3];
uint8_t resp[2];
cmd[0] = reg;
cmd[1] = value >> 8;
cmd[2] = value & 255;
i2c_send(i2c, addr, cmd, 3);
i2c_recv(i2c, addr, resp, 2);
g_assert_cmphex(resp[0], ==, cmd[1]);
g_assert_cmphex(resp[1], ==, cmd[2]);
}
static int qmp_tmp105_get_temperature(const char *id)
{
QDict *response;
@ -87,21 +42,22 @@ static void qmp_tmp105_set_temperature(const char *id, int value)
}
#define TMP105_PRECISION (1000/16)
static void send_and_receive(void)
static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc)
{
uint16_t value;
QI2CDevice *i2cdev = (QI2CDevice *)obj;
value = qmp_tmp105_get_temperature(TMP105_TEST_ID);
g_assert_cmpuint(value, ==, 0);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0);
qmp_tmp105_set_temperature(TMP105_TEST_ID, 20000);
value = qmp_tmp105_get_temperature(TMP105_TEST_ID);
g_assert_cmpuint(value, ==, 20000);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0x1400);
qmp_tmp105_set_temperature(TMP105_TEST_ID, 20938); /* 20 + 15/16 */
@ -110,24 +66,27 @@ static void send_and_receive(void)
g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2);
/* Set config */
tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60);
value = tmp105_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG);
i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60);
value = i2c_get8(i2cdev, TMP105_REG_CONFIG);
g_assert_cmphex(value, ==, 0x60);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0x14f0);
/* Set precision to 9, 10, 11 bits. */
tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x00);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x00);
g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0x1480);
tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x20);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x20);
g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x20);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0x14c0);
tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x40);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x40);
g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x40);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0x14e0);
/* stored precision remains the same */
@ -135,32 +94,27 @@ static void send_and_receive(void)
g_assert_cmpuint(value, >=, 20938 - TMP105_PRECISION/2);
g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2);
tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60);
value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60);
g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x60);
value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE);
g_assert_cmphex(value, ==, 0x14f0);
tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234);
tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231);
i2c_set16(i2cdev, TMP105_REG_T_LOW, 0x1234);
g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_LOW), ==, 0x1234);
i2c_set16(i2cdev, TMP105_REG_T_HIGH, 0x4231);
g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_HIGH), ==, 0x4231);
}
int main(int argc, char **argv)
static void tmp105_register_nodes(void)
{
QTestState *s = NULL;
int ret;
QOSGraphEdgeOptions opts = {
.extra_device_opts = "id=" TMP105_TEST_ID ",address=0x49"
};
add_qi2c_address(&opts, &(QI2CAddress) { 0x49 });
g_test_init(&argc, &argv, NULL);
qos_node_create_driver("tmp105", i2c_device_create);
qos_node_consumes("tmp105", "i2c-bus", &opts);
s = qtest_start("-machine n800 "
"-device tmp105,bus=i2c-bus.0,id=" TMP105_TEST_ID
",address=0x49");
i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE);
qtest_add_func("/tmp105/tx-rx", send_and_receive);
ret = g_test_run();
qtest_quit(s);
g_free(i2c);
return ret;
qos_add_test("tx-rx", "tmp105", send_and_receive, NULL);
}
libqos_init(tmp105_register_nodes);

18
vl.c
View File

@ -3576,7 +3576,23 @@ int main(int argc, char **argv, char **envp)
optarg, true);
optarg = qemu_opt_get(accel_opts, "accel");
if (!optarg || is_help_option(optarg)) {
printf("Possible accelerators: kvm, xen, hax, tcg\n");
printf("Accelerators supported in QEMU binary:\n");
GSList *el, *accel_list = object_class_get_list(TYPE_ACCEL,
false);
for (el = accel_list; el; el = el->next) {
gchar *typename = g_strdup(object_class_get_name(
OBJECT_CLASS(el->data)));
/* omit qtest which is used for tests only */
if (g_strcmp0(typename, ACCEL_CLASS_NAME("qtest")) &&
g_str_has_suffix(typename, ACCEL_CLASS_SUFFIX)) {
gchar **optname = g_strsplit(typename,
ACCEL_CLASS_SUFFIX, 0);
printf("%s\n", optname[0]);
g_free(optname);
}
g_free(typename);
}
g_slist_free(accel_list);
exit(0);
}
opts = qemu_opts_create(qemu_find_opts("machine"), NULL,