mirror of https://github.com/xemu-project/xemu.git
* 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:
commit
e2a58ff493
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
8
memory.c
8
memory.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ®, 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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ®, 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, ®, 1);
|
||||
pca9552_init(i2cdev);
|
||||
|
||||
i2c_send(i2cdev, ®, 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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, ®, 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, ®, 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
18
vl.c
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue