From aa0d7ed658f6afbdbcf4ceb8613b3c2cf5fbc7c4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 14 Mar 2019 19:20:07 +0100 Subject: [PATCH 01/24] test-thread-pool: be more reliable There is a rare race between the atomic_cmpxchg and bdrv_aio_cancel/bdrv_aio_cancel_async invocations. Detect it, the only sensible we can do about it is to exit long_cb immediately. Signed-off-by: Paolo Bonzini --- tests/test-thread-pool.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 9cdccb3a47..0b675923f6 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -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(); } } } From cbe6d6365a48bce4526c664170cda6fe738484f8 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Thu, 30 May 2019 17:57:55 -0400 Subject: [PATCH 02/24] vl: make -accel help to list enabled accelerators only Currently, -accel help shows all possible accelerators regardless if they are enabled in the binary or not. That is a different semantic from -cpu and -machine helps, for example. So this change makes it to list only the accelerators which support is compiled in the binary target. Note that it does not check if the accelerator is enabled in the host, so the help message's header was rewritten to emphasize that. Also qtest is not displayed given that it is used for internal testing purpose only. Signed-off-by: Wainer dos Santos Moschetta Message-Id: <20190530215755.328-2-wainersm@redhat.com> Signed-off-by: Paolo Bonzini --- vl.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index 139658d8b3..f023a8ca73 100644 --- a/vl.c +++ b/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, From 8d061278d3854fee9f907e31e0f3298263e84d82 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Fri, 26 Apr 2019 14:27:05 +0800 Subject: [PATCH 03/24] checkpatch: allow SPDX-License-Identifier According to: https://spdx.org/ids-how, let's still allow QEMU to use the SPDX license identifier: // SPDX-License-Identifier: *** CC: Paolo Bonzini Signed-off-by: Peter Xu Message-Id: <20190426062705.4651-1-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/checkpatch.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 88682cb0a9..c2aaf421da 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -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. From fdd6d824ef944538eced4f6134d4bafdfbf41b15 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 20 May 2019 11:08:28 +0800 Subject: [PATCH 04/24] memory: Remove memory_region_get_dirty() It's never used anywhere. Reviewed-by: Paolo Bonzini Signed-off-by: Peter Xu Message-Id: <20190520030839.6795-5-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 17 ----------------- memory.c | 8 -------- 2 files changed, 25 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 9144a47f57..e6140e8a04 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -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. * diff --git a/memory.c b/memory.c index 3071c4bdad..0920c105aa 100644 --- a/memory.c +++ b/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) { From 4cfd7bab3f5564f6c1a23b06f73d5aa2f957cd16 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Tue, 14 May 2019 14:06:39 +0800 Subject: [PATCH 05/24] i386: Enable IA32_MISC_ENABLE MWAIT bit when exposing mwait/monitor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CPUID.01H:ECX[bit 3] ought to mirror the value of the MSR IA32_MISC_ENABLE MWAIT bit and as userspace has control of them both, it is userspace's job to configure both bits to match on the initial setup. Cc: Eduardo Habkost Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Message-Id: <1557813999-9175-1-git-send-email-wanpengli@tencent.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 3 +++ target/i386/cpu.h | 1 + 2 files changed, 4 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 536d7d1520..c1ab86d63e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -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; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index fce6660bac..bd06523a53 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -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) From 20fb3105ce632e70500a92d7c76e02f28c2c07d4 Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Fri, 10 May 2019 09:43:47 -0700 Subject: [PATCH 06/24] edu: mmio: allow 64-bit access The edu spec says the MMIO area can be accessed by 64-bit. However currently the 'max_access_size' is not so the MMIO access dispatch can only access 32-bit one time. This patch fixes this to respect the spec. Signed-off-by: Li Qiang Reviewed-by: Philippe Mathieu-Daude Message-Id: <20190510164349.81507-2-liq3ea@163.com> Signed-off-by: Paolo Bonzini --- hw/misc/edu.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 91af452c9e..65fc32b928 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -289,6 +289,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, + }, + }; /* From c45eb53aabaa620c71ac567ddf4ee89802a97a70 Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Fri, 10 May 2019 09:43:48 -0700 Subject: [PATCH 07/24] edu: mmio: allow 64-bit access in read dispatch The edu spec says when address >= 0x80, the MMIO area can be accessed by 64-bit. Signed-off-by: Li Qiang Reviewed-by: Philippe Mathieu-Daude Message-Id: <20190510164349.81507-3-liq3ea@163.com> Signed-off-by: Paolo Bonzini --- hw/misc/edu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 65fc32b928..33de05141f 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -185,7 +185,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; } From 7fca21c8b376871892946651dddcb2f266dcca5a Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Fri, 10 May 2019 09:43:49 -0700 Subject: [PATCH 08/24] edu: uses uint64_t in dma operation The dma related variable dma.dst/src/cnt is dma_addr_t, it is uint64_t in x64 platform. Change these usage from uint32_to uint64_t to avoid trancation in edu_dma_timer. Signed-off-by: Li Qiang Message-Id: <20190510164349.81507-4-liq3ea@163.com> Signed-off-by: Paolo Bonzini --- hw/misc/edu.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 33de05141f..19e5545e2c 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -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), From de94b54aa04c06f5988221d2d7e6ee3469173c4b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 14:48:47 +0100 Subject: [PATCH 09/24] qgraph: allow extra_device_opts on contains nodes Allow choosing the bus that the device will be placed on, in case the machine has more than one. Otherwise, the bus may not match the base address of the controller we attach it to. Signed-off-by: Paolo Bonzini --- tests/qos-test.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/qos-test.c b/tests/qos-test.c index ae2fb5de1c..01b2a22c08 100644 --- a/tests/qos-test.c +++ b/tests/qos-test.c @@ -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); From 7d8ada6e4d20b47dcf42d22fc62599a9799eac7a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 17:14:12 +0100 Subject: [PATCH 10/24] qgraph: fix qos_node_contains with options Currently, if qos_node_contains was passed options, it would still create an edge without any options. Instead, in that case NULL acts as a terminator. Signed-off-by: Paolo Bonzini --- tests/libqos/qgraph.c | 12 ++++++++---- tests/libqos/qgraph.h | 15 +++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/libqos/qgraph.c b/tests/libqos/qgraph.c index b149caaaa9..7a7ae2a19e 100644 --- a/tests/libqos/qgraph.c +++ b/tests/libqos/qgraph.c @@ -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); diff --git a/tests/libqos/qgraph.h b/tests/libqos/qgraph.h index e799095b30..3a25dda4b2 100644 --- a/tests/libqos/qgraph.h +++ b/tests/libqos/qgraph.h @@ -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 From e8ecb706a8a3a75ea45387a3561b6debed9cacc3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 15:09:51 +0100 Subject: [PATCH 11/24] libqos: move common i2c code to libqos The functions to read/write 8-bit or 16-bit registers are the same in tmp105 and pca9552 tests, and in fact they are a special case of "read block"/"write block" functionality; read block in turn is used in ds1338-test. Move everything inside libqos-test, removing the duplication. Account for the small differences by adding to tmp105-test.c the "read register after writing" behavior that is specific to it. Signed-off-by: Paolo Bonzini --- tests/ds1338-test.c | 8 +---- tests/libqos/i2c.c | 47 ++++++++++++++++++++++++++ tests/libqos/i2c.h | 11 ++++++ tests/pca9552-test.c | 37 +++++--------------- tests/tmp105-test.c | 80 ++++++++++++-------------------------------- 5 files changed, 88 insertions(+), 95 deletions(-) diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c index 742dad9113..88f829f241 100644 --- a/tests/ds1338-test.c +++ b/tests/ds1338-test.c @@ -35,17 +35,11 @@ static inline uint8_t bcd2bin(uint8_t x) static void send_and_receive(void) { - uint8_t cmd[1]; 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(i2c, addr, 0, resp, sizeof(resp)); /* check retrieved time againt local time */ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday); diff --git a/tests/libqos/i2c.c b/tests/libqos/i2c.c index 23bc2a3eb2..daf9a96617 100644 --- a/tests/libqos/i2c.c +++ b/tests/libqos/i2c.c @@ -21,3 +21,50 @@ void i2c_recv(I2CAdapter *i2c, uint8_t addr, { i2c->recv(i2c, addr, buf, len); } + +void i2c_read_block(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + uint8_t *buf, uint16_t len) +{ + i2c_send(i2c, addr, ®, 1); + i2c_recv(i2c, addr, buf, len); +} + +void i2c_write_block(I2CAdapter *i2c, uint8_t addr, 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(i2c, addr, cmd, len + 1); + g_free(cmd); +} + +uint8_t i2c_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg) +{ + uint8_t resp[1]; + i2c_read_block(i2c, addr, reg, resp, sizeof(resp)); + return resp[0]; +} + +uint16_t i2c_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg) +{ + uint8_t resp[2]; + i2c_read_block(i2c, addr, reg, resp, sizeof(resp)); + return (resp[0] << 8) | resp[1]; +} + +void i2c_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + uint8_t value) +{ + i2c_write_block(i2c, addr, reg, &value, 1); +} + +void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + uint16_t value) +{ + uint8_t data[2]; + + data[0] = value >> 8; + data[1] = value & 255; + i2c_write_block(i2c, addr, reg, data, sizeof(data)); +} diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index cc01358a9f..a462114597 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -28,6 +28,17 @@ void i2c_send(I2CAdapter *i2c, uint8_t addr, void i2c_recv(I2CAdapter *i2c, uint8_t addr, uint8_t *buf, uint16_t len); +void i2c_read_block(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + uint8_t *buf, uint16_t len); +void i2c_write_block(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + const uint8_t *buf, uint16_t len); +uint8_t i2c_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg); +uint16_t i2c_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg); +void i2c_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + uint8_t value); +void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, + uint16_t value); + /* libi2c-omap.c */ I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr); diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index 5466a67ed7..06359b7435 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -18,27 +18,6 @@ static I2CAdapter *i2c; -static uint8_t pca9552_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 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) { uint8_t resp; @@ -67,26 +46,26 @@ static void send_and_receive(void) { uint8_t value; - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); g_assert_cmphex(value, ==, 0x55); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, 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); + i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); g_assert_cmphex(value, ==, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, 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); + i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3); g_assert_cmphex(value, ==, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1); g_assert_cmphex(value, ==, 0x10); } diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index 34cae7a582..c86d2571e2 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -19,50 +19,6 @@ 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; @@ -94,14 +50,14 @@ static void send_and_receive(void) 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(i2c, TMP105_TEST_ADDR, 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(i2c, TMP105_TEST_ADDR, 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(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); + value = i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG); g_assert_cmphex(value, ==, 0x60); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2c, TMP105_TEST_ADDR, 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(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x00); + g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x00); + value = i2c_get16(i2c, TMP105_TEST_ADDR, 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(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x20); + g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x20); + value = i2c_get16(i2c, TMP105_TEST_ADDR, 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(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x40); + g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x40); + value = i2c_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14e0); /* stored precision remains the same */ @@ -135,12 +94,15 @@ 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(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x60); + value = i2c_get16(i2c, TMP105_TEST_ADDR, 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(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234); + g_assert_cmphex(i2c_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW), ==, 0x1234); + i2c_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231); + g_assert_cmphex(i2c_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH), ==, 0x4231); } int main(int argc, char **argv) From 05095ece6f726dfd2244d4ed1b7e47e35ba7a922 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 16:49:59 +0100 Subject: [PATCH 12/24] libqos: fix omap-i2c receiving more than 4 bytes If more than 4 bytes are received, the FIFO cannot host the entire contents of the transfer and STP will be nonzero before entering the transfer loop. Also, CNT will contain the number of bytes left to be transferred instead of the total number of bytes in the transfer. (Reverse engineered from the omap_i2c.c source code; no available datasheet). This will fix ds1338-test for omap-i2c. Signed-off-by: Paolo Bonzini --- tests/libqos/i2c-omap.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c index 1ef6e7b200..bb65336832 100644 --- a/tests/libqos/i2c-omap.c +++ b/tests/libqos/i2c-omap.c @@ -105,6 +105,7 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, { OMAPI2C *s = (OMAPI2C *)i2c; uint16_t data, stat; + uint16_t orig_len = len; omap_i2c_set_slave_addr(s, addr); @@ -116,16 +117,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); From eadcd3b252dde196de10874fe999e1af803f22d3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 14:56:21 +0100 Subject: [PATCH 13/24] pca9552-test: do not rely on state across tests receive_autoinc is relying on the LED state that is set by send_and_receive. Stop doing that, because qgraph resets the machine between tests. Reviewed-by: Thomas Huth Signed-off-by: Paolo Bonzini --- tests/pca9552-test.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index 06359b7435..89b4445e29 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -18,11 +18,20 @@ static I2CAdapter *i2c; +static void pca9552_init(I2CAdapter *i2c) +{ + /* Switch on LEDs 0 and 12 */ + i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); + i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); +} + static void receive_autoinc(void) { uint8_t resp; uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC; + pca9552_init(i2cdev); + i2c_send(i2c, PCA9552_TEST_ADDR, ®, 1); /* PCA9552_LS0 */ @@ -52,16 +61,14 @@ static void send_and_receive(void) value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x0); - /* Switch on LED 0 */ - i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); + pca9552_init(i2cdev); + value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); g_assert_cmphex(value, ==, 0x54); value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x01); - /* Switch on LED 12 */ - i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3); g_assert_cmphex(value, ==, 0x54); From c4f00daa5b390a74f13a271e7237e173c527bbce Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 15:56:23 +0100 Subject: [PATCH 14/24] imx25-pdk: create ds1338 for qtest inside the test There is no need to have a test device created by the board. Instead, create it in the qtest so that we will be able to run it on other boards too. Reviewed-by: Thomas Huth Signed-off-by: Paolo Bonzini --- hw/arm/imx25_pdk.c | 9 --------- tests/ds1338-test.c | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c index eef1b184b0..a0423ffb67 100644 --- a/hw/arm/imx25_pdk.c +++ b/hw/arm/imx25_pdk.c @@ -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); } } diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c index 88f829f241..bd72a159cb 100644 --- a/tests/ds1338-test.c +++ b/tests/ds1338-test.c @@ -54,7 +54,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); - s = qtest_start("-display none -machine imx25-pdk"); + s = qtest_start("-display none -machine imx25-pdk -device ds1338,address=0x68"); i2c = imx_i2c_create(s, IMX25_I2C_0_BASE); addr = DS1338_ADDR; From 732c919cf04c0aaf1b092238e8b84cdb7adf657a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 17:12:25 +0100 Subject: [PATCH 15/24] libqos: split I2CAdapter initialization and allocation Provide *_init functions that populate an I2CAdapter struct without allocating one, and make the existing *_create functions wrap them. Because in the new setup *_create might return a pointer inside the IMXI2C or OMAPI2C struct, create companion *_free functions to go back to the outer pointer. All this is temporary until allocation will be handled entirely by qgraph. Signed-off-by: Paolo Bonzini --- tests/libqos/i2c-imx.c | 41 ++++++++++++++++++++++++----------------- tests/libqos/i2c-omap.c | 34 ++++++++++++++++++++++------------ tests/libqos/i2c.h | 22 +++++++++++++++++++--- tests/pca9552-test.c | 2 +- tests/tmp105-test.c | 2 +- 5 files changed, 67 insertions(+), 34 deletions(-) diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c index 0945f2ecdc..28289c521a 100644 --- a/tests/libqos/i2c-imx.c +++ b/tests/libqos/i2c-imx.c @@ -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,30 @@ static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((status & I2SR_IBB) == 0); } +void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr) +{ + s->addr = addr; + + s->parent.send = imx_i2c_send; + s->parent.recv = imx_i2c_recv; + s->parent.qts = qts; +} + I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr) { IMXI2C *s = g_malloc0(sizeof(*s)); - I2CAdapter *i2c = (I2CAdapter *)s; - s->addr = addr; - - i2c->send = imx_i2c_send; - i2c->recv = imx_i2c_recv; - i2c->qts = qts; - - return i2c; + imx_i2c_init(s, qts, addr); + return &s->parent; +} + +void imx_i2c_free(I2CAdapter *i2c) +{ + IMXI2C *s; + + if (!i2c) { + return; + } + s = container_of(i2c, IMXI2C, parent); + g_free(s); } diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c index bb65336832..c7cbb9ecdd 100644 --- a/tests/libqos/i2c-omap.c +++ b/tests/libqos/i2c-omap.c @@ -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,7 +97,7 @@ 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; @@ -161,9 +155,8 @@ 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) +void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr) { - OMAPI2C *s = g_malloc0(sizeof(*s)); I2CAdapter *i2c = (I2CAdapter *)s; uint16_t data; @@ -176,6 +169,23 @@ I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr) /* 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; +} + +I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr) +{ + OMAPI2C *s = g_malloc0(sizeof(*s)); + + omap_i2c_init(s, qts, addr); + return &s->parent; +} + +void omap_i2c_free(I2CAdapter *i2c) +{ + OMAPI2C *s; + + if (!i2c) { + return; + } + s = container_of(i2c, OMAPI2C, parent); + g_free(s); } diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index a462114597..877d2ab0e8 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -39,10 +39,26 @@ void i2c_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, uint16_t value); -/* libi2c-omap.c */ -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr); +/* i2c-omap.c */ +typedef struct OMAPI2C { + I2CAdapter parent; -/* libi2c-imx.c */ + uint64_t addr; +} OMAPI2C; + +void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr); +I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr); +void omap_i2c_free(I2CAdapter *i2c); + +/* i2c-imx.c */ +typedef struct IMXI2C { + I2CAdapter parent; + + uint64_t addr; +} IMXI2C; + +void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr); I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr); +void imx_i2c_free(I2CAdapter *i2c); #endif diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index 89b4445e29..f9509324e2 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -96,7 +96,7 @@ int main(int argc, char **argv) if (s) { qtest_quit(s); } - g_free(i2c); + omap_i2c_free(i2c); return ret; } diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index c86d2571e2..25ea05f5fd 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -122,7 +122,7 @@ int main(int argc, char **argv) ret = g_test_run(); qtest_quit(s); - g_free(i2c); + omap_i2c_free(i2c); return ret; } From c0825c63cfae0d4af1f1f91867c42e609f3ed13c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 13:48:23 +0100 Subject: [PATCH 16/24] libqos: convert I2C to qgraph Create an i2c-bus interface, corresponding to the I2CAdapter struct. Wrap IMXI2C and OMAPI2C with a QOSGraphObject, and add the get_driver function to retrieve the I2CAdapter. The conversion is still not complete; for simplicity, i2c_recv and i2c_send (along with their wrappers) still take an adapter/address pair. Fixing that would be complicated until the tests are converted to qgraph, so it is left for after the conversion. Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 2 ++ tests/libqos/i2c-imx.c | 20 ++++++++++++++++++++ tests/libqos/i2c-omap.c | 40 ++++++++++++++++++++++++++++++++-------- tests/libqos/i2c.c | 8 ++++++++ tests/libqos/i2c.h | 21 +++++++++++++++++++++ 5 files changed, 83 insertions(+), 8 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 1865f6b322..63f646acd2 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -694,6 +694,8 @@ libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o 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 += $(libqos-imx-obj-y) +qos-test-obj-y += $(libqos-omap-obj-y) qos-test-obj-y += tests/libqos/sdhci.o qos-test-obj-y += tests/libqos/tpci200.o qos-test-obj-y += tests/libqos/virtio.o diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c index 28289c521a..86d84a79e6 100644 --- a/tests/libqos/i2c-imx.c +++ b/tests/libqos/i2c-imx.c @@ -186,10 +186,22 @@ static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((status & I2SR_IBB) == 0); } +static void *imx_i2c_get_driver(void *obj, const char *interface) +{ + 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; + s->obj.get_driver = imx_i2c_get_driver; + s->parent.send = imx_i2c_send; s->parent.recv = imx_i2c_recv; s->parent.qts = qts; @@ -213,3 +225,11 @@ void imx_i2c_free(I2CAdapter *i2c) s = container_of(i2c, IMXI2C, parent); g_free(s); } + +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); diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c index c7cbb9ecdd..f94956488c 100644 --- a/tests/libqos/i2c-omap.c +++ b/tests/libqos/i2c-omap.c @@ -155,20 +155,36 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((data & OMAP_I2C_CON_STP) == 0); } -void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr) +static void *omap_i2c_get_driver(void *obj, const char *interface) { - 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); + s->parent.send = omap_i2c_send; + s->parent.recv = omap_i2c_recv; + s->parent.qts = qts; } I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr) @@ -189,3 +205,11 @@ void omap_i2c_free(I2CAdapter *i2c) s = container_of(i2c, OMAPI2C, parent); g_free(s); } + +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); diff --git a/tests/libqos/i2c.c b/tests/libqos/i2c.c index daf9a96617..8117d13170 100644 --- a/tests/libqos/i2c.c +++ b/tests/libqos/i2c.c @@ -68,3 +68,11 @@ void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, data[1] = value & 255; i2c_write_block(i2c, addr, 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; + return &i2cdev->obj; +} diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index 877d2ab0e8..0107cfc633 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -10,6 +10,7 @@ #define LIBQOS_I2C_H #include "libqtest.h" +#include "libqos/qgraph.h" typedef struct I2CAdapter I2CAdapter; struct I2CAdapter { @@ -21,8 +22,26 @@ struct I2CAdapter { QTestState *qts; }; +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; +}; + #define OMAP2_I2C_1_BASE 0x48070000 +void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr); + void i2c_send(I2CAdapter *i2c, uint8_t addr, const uint8_t *buf, uint16_t len); void i2c_recv(I2CAdapter *i2c, uint8_t addr, @@ -41,6 +60,7 @@ void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, /* i2c-omap.c */ typedef struct OMAPI2C { + QOSGraphObject obj; I2CAdapter parent; uint64_t addr; @@ -52,6 +72,7 @@ void omap_i2c_free(I2CAdapter *i2c); /* i2c-imx.c */ typedef struct IMXI2C { + QOSGraphObject obj; I2CAdapter parent; uint64_t addr; From 48963982e55a1c206ea20bed600e188655af2b4b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 13:52:23 +0100 Subject: [PATCH 17/24] libqos: add ARM n800 machine object This is used to test omap_i2c. Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 1 + tests/libqos/arm-n800-machine.c | 92 +++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 tests/libqos/arm-n800-machine.c diff --git a/tests/Makefile.include b/tests/Makefile.include index 63f646acd2..03a6483081 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -711,6 +711,7 @@ 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-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 diff --git a/tests/libqos/arm-n800-machine.c b/tests/libqos/arm-n800-machine.c new file mode 100644 index 0000000000..87279bdb26 --- /dev/null +++ b/tests/libqos/arm-n800-machine.c @@ -0,0 +1,92 @@ +/* + * libqos driver framework + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * 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 + */ + +#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); From 751a7a5d00b23e1977c0c082fe041efbde77d06c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 15:36:49 +0100 Subject: [PATCH 18/24] libqos: add ARM imx25-pdk machine object This is used to test imx_i2c. Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 1 + tests/libqos/arm-imx25-pdk-machine.c | 92 ++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 tests/libqos/arm-imx25-pdk-machine.c diff --git a/tests/Makefile.include b/tests/Makefile.include index 03a6483081..506181e21a 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -711,6 +711,7 @@ 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 diff --git a/tests/libqos/arm-imx25-pdk-machine.c b/tests/libqos/arm-imx25-pdk-machine.c new file mode 100644 index 0000000000..25066fb8a9 --- /dev/null +++ b/tests/libqos/arm-imx25-pdk-machine.c @@ -0,0 +1,92 @@ +/* + * libqos driver framework + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * 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 + */ + +#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); From 93c3fe2a349970aaba8d196b8c2cbcd7c472bb81 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 14:07:13 +0100 Subject: [PATCH 19/24] tests: convert OMAP i2c tests to qgraph This way, pca9952-test and tmp105-test will run for every machine that exposes an i2c-bus. Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 9 +++------ tests/libqos/i2c-omap.c | 19 ------------------ tests/libqos/i2c.h | 4 ---- tests/pca9552-test.c | 44 ++++++++++++++++++----------------------- tests/tmp105-test.c | 32 +++++++++++------------------- 5 files changed, 34 insertions(+), 74 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 506181e21a..0f1ddde84a 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -255,8 +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) @@ -686,7 +684,6 @@ 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 @@ -695,7 +692,7 @@ 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 += $(libqos-imx-obj-y) -qos-test-obj-y += $(libqos-omap-obj-y) +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 @@ -731,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 @@ -772,8 +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 diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c index f94956488c..9ae8214fa8 100644 --- a/tests/libqos/i2c-omap.c +++ b/tests/libqos/i2c-omap.c @@ -187,25 +187,6 @@ void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr) s->parent.qts = qts; } -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr) -{ - OMAPI2C *s = g_malloc0(sizeof(*s)); - - omap_i2c_init(s, qts, addr); - return &s->parent; -} - -void omap_i2c_free(I2CAdapter *i2c) -{ - OMAPI2C *s; - - if (!i2c) { - return; - } - s = container_of(i2c, OMAPI2C, parent); - g_free(s); -} - static void omap_i2c_register_nodes(void) { qos_node_create_driver("omap_i2c", NULL); diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index 0107cfc633..66b0e0d06e 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -38,8 +38,6 @@ struct QI2CDevice { I2CAdapter *bus; }; -#define OMAP2_I2C_1_BASE 0x48070000 - void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr); void i2c_send(I2CAdapter *i2c, uint8_t addr, @@ -67,8 +65,6 @@ typedef struct OMAPI2C { } OMAPI2C; void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr); -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr); -void omap_i2c_free(I2CAdapter *i2c); /* i2c-imx.c */ typedef struct IMXI2C { diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index f9509324e2..0598d0b1eb 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -10,23 +10,26 @@ #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 void pca9552_init(I2CAdapter *i2c) +static void pca9552_init(QI2CDevice *i2cdev) { + I2CAdapter *i2c = i2cdev->bus; + /* Switch on LEDs 0 and 12 */ i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); } -static void receive_autoinc(void) +static void receive_autoinc(void *obj, void *data, QGuestAllocator *alloc) { + QI2CDevice *i2cdev = (QI2CDevice *)obj; + I2CAdapter *i2c = i2cdev->bus; uint8_t resp; uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC; @@ -51,8 +54,10 @@ static void receive_autoinc(void) 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; + I2CAdapter *i2c = i2cdev->bus; uint8_t value; value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); @@ -76,27 +81,16 @@ static void send_and_receive(void) 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" + }; - 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); - } - omap_i2c_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); diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index 25ea05f5fd..4031876387 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -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,8 +18,6 @@ #define TMP105_TEST_ID "tmp105-test" #define TMP105_TEST_ADDR 0x49 -static I2CAdapter *i2c; - static int qmp_tmp105_get_temperature(const char *id) { QDict *response; @@ -43,9 +42,11 @@ 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; + I2CAdapter *i2c = i2cdev->bus; value = qmp_tmp105_get_temperature(TMP105_TEST_ID); g_assert_cmpuint(value, ==, 0); @@ -105,24 +106,15 @@ static void send_and_receive(void) g_assert_cmphex(i2c_get16(i2c, TMP105_TEST_ADDR, 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" + }; - 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); - omap_i2c_free(i2c); - - return ret; + qos_add_test("tx-rx", "tmp105", send_and_receive, NULL); } +libqos_init(tmp105_register_nodes); From 8130dbcbcda15b3fe5ae1da76bf48868c4ce90fb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 15:59:42 +0100 Subject: [PATCH 20/24] tests: convert ds1338-test to qtest This way, ds1338-test will run for every machine that exposes an i2c-bus. Signed-off-by: Paolo Bonzini --- tests/Makefile.include | 9 ++++----- tests/ds1338-test.c | 37 +++++++++++++------------------------ tests/libqos/i2c-imx.c | 19 ------------------- tests/libqos/i2c.h | 2 -- 4 files changed, 17 insertions(+), 50 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 0f1ddde84a..46a36c2c95 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -255,7 +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/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) @@ -676,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 @@ -684,14 +683,14 @@ 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-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 += $(libqos-imx-obj-y) +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 @@ -720,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 @@ -771,7 +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/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) diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c index bd72a159cb..fd8fbad533 100644 --- a/tests/ds1338-test.c +++ b/tests/ds1338-test.c @@ -21,25 +21,23 @@ #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) { + QI2CDevice *i2cdev = (QI2CDevice *)obj; + I2CAdapter *i2c = i2cdev->bus; + uint8_t resp[7]; time_t now = time(NULL); struct tm *tm_ptr = gmtime(&now); - i2c_read_block(i2c, addr, 0, resp, sizeof(resp)); + i2c_read_block(i2c, DS1338_ADDR, 0, resp, sizeof(resp)); /* check retrieved time againt local time */ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday); @@ -47,23 +45,14 @@ 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" + }; - g_test_init(&argc, &argv, NULL); - - s = qtest_start("-display none -machine imx25-pdk -device ds1338,address=0x68"); - 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); diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c index 86d84a79e6..f33ece55a3 100644 --- a/tests/libqos/i2c-imx.c +++ b/tests/libqos/i2c-imx.c @@ -207,25 +207,6 @@ void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr) s->parent.qts = qts; } -I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr) -{ - IMXI2C *s = g_malloc0(sizeof(*s)); - - imx_i2c_init(s, qts, addr); - return &s->parent; -} - -void imx_i2c_free(I2CAdapter *i2c) -{ - IMXI2C *s; - - if (!i2c) { - return; - } - s = container_of(i2c, IMXI2C, parent); - g_free(s); -} - static void imx_i2c_register_nodes(void) { qos_node_create_driver("imx.i2c", NULL); diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index 66b0e0d06e..2c8cc3eab5 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -75,7 +75,5 @@ typedef struct IMXI2C { } IMXI2C; void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr); -I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr); -void imx_i2c_free(I2CAdapter *i2c); #endif From 06599472ec40efef3de7cb2bc98d61e8d4b18a63 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 18 Mar 2019 15:06:50 +0100 Subject: [PATCH 21/24] libqos: i2c: move address into QI2CDevice This removes the hardcoded I2C address from the tests. The address is passed via QOSGraphEdgeOptions to i2c_device_create and stored in the QI2CDevice. The i2c_send and i2c_recv functions, along with their wrappers, therefore, can be changed to take a QI2CDevice rather than an adapter/address pair. Signed-off-by: Paolo Bonzini --- tests/ds1338-test.c | 4 ++-- tests/libqos/i2c.c | 51 +++++++++++++++++++++++++------------------- tests/libqos/i2c.h | 27 ++++++++++++----------- tests/pca9552-test.c | 31 ++++++++++++--------------- tests/tmp105-test.c | 44 +++++++++++++++++++------------------- 5 files changed, 82 insertions(+), 75 deletions(-) diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c index fd8fbad533..f6ade9a050 100644 --- a/tests/ds1338-test.c +++ b/tests/ds1338-test.c @@ -31,13 +31,12 @@ static inline uint8_t bcd2bin(uint8_t x) static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { QI2CDevice *i2cdev = (QI2CDevice *)obj; - I2CAdapter *i2c = i2cdev->bus; uint8_t resp[7]; time_t now = time(NULL); struct tm *tm_ptr = gmtime(&now); - i2c_read_block(i2c, DS1338_ADDR, 0, resp, sizeof(resp)); + i2c_read_block(i2cdev, 0, resp, sizeof(resp)); /* check retrieved time againt local time */ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday); @@ -50,6 +49,7 @@ static void ds1338_register_nodes(void) QOSGraphEdgeOptions opts = { .extra_device_opts = "address=0x68" }; + add_qi2c_address(&opts, &(QI2CAddress) { DS1338_ADDR }); qos_node_create_driver("ds1338", i2c_device_create); qos_node_consumes("ds1338", "i2c-bus", &opts); diff --git a/tests/libqos/i2c.c b/tests/libqos/i2c.c index 8117d13170..156114e745 100644 --- a/tests/libqos/i2c.c +++ b/tests/libqos/i2c.c @@ -10,63 +10,59 @@ #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(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t *buf, uint16_t len) +void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg, + uint8_t *buf, uint16_t len) { - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, buf, len); + i2c_send(i2cdev, ®, 1); + i2c_recv(i2cdev, buf, len); } -void i2c_write_block(I2CAdapter *i2c, uint8_t addr, uint8_t reg, +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(i2c, addr, cmd, len + 1); + i2c_send(i2cdev, cmd, len + 1); g_free(cmd); } -uint8_t i2c_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg) +uint8_t i2c_get8(QI2CDevice *i2cdev, uint8_t reg) { uint8_t resp[1]; - i2c_read_block(i2c, addr, reg, resp, sizeof(resp)); + i2c_read_block(i2cdev, reg, resp, sizeof(resp)); return resp[0]; } -uint16_t i2c_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg) +uint16_t i2c_get16(QI2CDevice *i2cdev, uint8_t reg) { uint8_t resp[2]; - i2c_read_block(i2c, addr, reg, resp, sizeof(resp)); + i2c_read_block(i2cdev, reg, resp, sizeof(resp)); return (resp[0] << 8) | resp[1]; } -void i2c_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t value) +void i2c_set8(QI2CDevice *i2cdev, uint8_t reg, uint8_t value) { - i2c_write_block(i2c, addr, reg, &value, 1); + i2c_write_block(i2cdev, reg, &value, 1); } -void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint16_t value) +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(i2c, addr, reg, data, sizeof(data)); + i2c_write_block(i2cdev, reg, data, sizeof(data)); } void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr) @@ -74,5 +70,16 @@ 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); +} diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index 2c8cc3eab5..945b65b34c 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -22,6 +22,11 @@ struct I2CAdapter { QTestState *qts; }; +typedef struct QI2CAddress QI2CAddress; +struct QI2CAddress { + uint8_t addr; +}; + typedef struct QI2CDevice QI2CDevice; struct QI2CDevice { /* @@ -36,25 +41,23 @@ struct QI2CDevice { */ QOSGraphObject obj; I2CAdapter *bus; + uint8_t addr; }; void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr); +void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *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); +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(I2CAdapter *i2c, uint8_t addr, uint8_t reg, +void i2c_read_block(QI2CDevice *dev, uint8_t reg, uint8_t *buf, uint16_t len); -void i2c_write_block(I2CAdapter *i2c, uint8_t addr, uint8_t reg, +void i2c_write_block(QI2CDevice *dev, uint8_t reg, const uint8_t *buf, uint16_t len); -uint8_t i2c_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg); -uint16_t i2c_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg); -void i2c_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t value); -void i2c_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint16_t value); +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 { diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index 0598d0b1eb..4b800d3c3e 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -19,65 +19,61 @@ static void pca9552_init(QI2CDevice *i2cdev) { - I2CAdapter *i2c = i2cdev->bus; - /* Switch on LEDs 0 and 12 */ - i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); - i2c_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); + i2c_set8(i2cdev, PCA9552_LS0, 0x54); + i2c_set8(i2cdev, PCA9552_LS3, 0x54); } static void receive_autoinc(void *obj, void *data, QGuestAllocator *alloc) { QI2CDevice *i2cdev = (QI2CDevice *)obj; - I2CAdapter *i2c = i2cdev->bus; uint8_t resp; uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC; pca9552_init(i2cdev); - i2c_send(i2c, PCA9552_TEST_ADDR, ®, 1); + 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 *obj, void *data, QGuestAllocator *alloc) { QI2CDevice *i2cdev = (QI2CDevice *)obj; - I2CAdapter *i2c = i2cdev->bus; uint8_t value; - value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + value = i2c_get8(i2cdev, PCA9552_LS0); g_assert_cmphex(value, ==, 0x55); - value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2cdev, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x0); pca9552_init(i2cdev); - value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + value = i2c_get8(i2cdev, PCA9552_LS0); g_assert_cmphex(value, ==, 0x54); - value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2cdev, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x01); - value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3); + value = i2c_get8(i2cdev, PCA9552_LS3); g_assert_cmphex(value, ==, 0x54); - value = i2c_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1); + value = i2c_get8(i2cdev, PCA9552_INPUT1); g_assert_cmphex(value, ==, 0x10); } @@ -86,6 +82,7 @@ static void pca9552_register_nodes(void) QOSGraphEdgeOptions opts = { .extra_device_opts = "address=0x60" }; + add_qi2c_address(&opts, &(QI2CAddress) { 0x60 }); qos_node_create_driver("pca9552", i2c_device_create); qos_node_consumes("pca9552", "i2c-bus", &opts); diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index 4031876387..f599309a4a 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -46,19 +46,18 @@ static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { uint16_t value; QI2CDevice *i2cdev = (QI2CDevice *)obj; - I2CAdapter *i2c = i2cdev->bus; value = qmp_tmp105_get_temperature(TMP105_TEST_ID); g_assert_cmpuint(value, ==, 0); - value = i2c_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 = i2c_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 */ @@ -67,27 +66,27 @@ static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2); /* Set config */ - i2c_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); - value = i2c_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 = i2c_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. */ - i2c_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x00); - g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x00); - value = i2c_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); - i2c_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x20); - g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x20); - value = i2c_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); - i2c_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x40); - g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x40); - value = i2c_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 */ @@ -95,15 +94,15 @@ static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) g_assert_cmpuint(value, >=, 20938 - TMP105_PRECISION/2); g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2); - i2c_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); - g_assert_cmphex(i2c_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG), ==, 0x60); - value = i2c_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); - i2c_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234); - g_assert_cmphex(i2c_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW), ==, 0x1234); - i2c_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231); - g_assert_cmphex(i2c_get16(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); } static void tmp105_register_nodes(void) @@ -111,6 +110,7 @@ static void tmp105_register_nodes(void) QOSGraphEdgeOptions opts = { .extra_device_opts = "id=" TMP105_TEST_ID ",address=0x49" }; + add_qi2c_address(&opts, &(QI2CAddress) { 0x49 }); qos_node_create_driver("tmp105", i2c_device_create); qos_node_consumes("tmp105", "i2c-bus", &opts); From f6adb8e7e3ed945a6ab36edd4c56a49a171761c0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 15 Mar 2019 10:16:20 +0100 Subject: [PATCH 22/24] ci: store Patchew configuration in the tree Patchew cannot yet retrieve the configuration from the QEMU Git tree, but this is planned. In the meanwhile, let's start storing it as YAML so that the Patchew configuration (currently accessible only to administrators) is public and documented. Signed-off-by: Paolo Bonzini --- .patchew.yml | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 .patchew.yml diff --git a/.patchew.yml b/.patchew.yml new file mode 100644 index 0000000000..988c29261f --- /dev/null +++ b/.patchew.yml @@ -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 From 7f27154d5042bae6fd9ac200e23a28ecca3387a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 24 May 2019 20:14:11 +0200 Subject: [PATCH 23/24] configure: remove tpm_passthrough & tpm_emulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a left-over from commit 7aaa6a16373 "tpm: express dependencies with Kconfig". Signed-off-by: Marc-André Lureau Message-Id: <20190524181411.8599-1-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- configure | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/configure b/configure index 6cdcfb2dc3..b091b82cb3 100755 --- a/configure +++ b/configure @@ -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 From c87759ce876a7a0b17c2bf4f0b964bd51f0ee871 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 14 May 2019 14:14:41 -0600 Subject: [PATCH 24/24] q35: Revert to kernel irqchip Commit b2fc91db8447 ("q35: set split kernel irqchip as default") changed the default for the pc-q35-4.0 machine type to use split irqchip, which turned out to have disasterous effects on vfio-pci INTx support. KVM resampling irqfds are registered for handling these interrupts, but these are non-functional in split irqchip mode. We can't simply test for split irqchip in QEMU as userspace handling of this interrupt is a significant performance regression versus KVM handling (GeForce GPUs assigned to Windows VMs are non-functional without forcing MSI mode or re-enabling kernel irqchip). The resolution is to revert the change in default irqchip mode in the pc-q35-4.1 machine and create a pc-q35-4.0.1 machine for the 4.0-stable branch. The qemu-q35-4.0 machine type should not be used in vfio-pci configurations for devices requiring legacy INTx support without explicitly modifying the VM configuration to use kernel irqchip. Link: https://bugs.launchpad.net/qemu/+bug/1826422 Fixes: b2fc91db8447 ("q35: set split kernel irqchip as default") Signed-off-by: Alex Williamson Reviewed-by: Peter Xu Message-Id: <155786484688.13873.6037015630912983760.stgit@gimli.home> Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 3 +++ hw/i386/pc.c | 3 +++ hw/i386/pc_q35.c | 16 ++++++++++++++-- include/hw/boards.h | 3 +++ include/hw/i386/pc.h | 3 +++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 16ba667434..f1a0f45f9c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -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); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2632b73f80..edc240bcbf 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -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); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 37dd350511..dcddc64662 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -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); } diff --git a/include/hw/boards.h b/include/hw/boards.h index 6f7916f88f..6ff02bf3e4 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -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; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 43df7230a2..5d5636241e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -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;