... | ... | ||
---|---|---|---|
14 | # starting QEMU: exec ./qemu-system-x86_64 -qtest unix:/tmp/qtest-267380.sock -qtest-log /dev/null -chardev socket,path=/tmp/qtest-267380.qmp,id=char0 -mon chardev=char0,mode=control -display none -audio none -device vmcoreinfo -accel qtest | 14 | # starting QEMU: exec ./qemu-system-x86_64 -qtest unix:/tmp/qtest-267380.sock -qtest-log /dev/null -chardev socket,path=/tmp/qtest-267380.qmp,id=char0 -mon chardev=char0,mode=control -display none -audio none -device vmcoreinfo -accel qtest |
15 | ok 1 /x86_64/vmcoreinfo/basic-write | 15 | ok 1 /x86_64/vmcoreinfo/basic-write |
16 | # End of vmcoreinfo tests | 16 | # End of vmcoreinfo tests |
17 | # End of x86_64 tests | 17 | # End of x86_64 tests |
18 | 18 | ||
19 | CI pipeline is green with this patch series: https://gitlab.com/anisinha/qemu/-/pipelines/1629670893 | ||
20 | |||
21 | checkpatch is clean: | ||
22 | |||
23 | $ ./scripts/checkpatch.pl patches-v6/* | ||
24 | Checking patches-v6/v6-0000-cover-letter.patch... | ||
25 | total: 0 errors, 0 warnings, 0 lines checked | ||
26 | |||
27 | patches-v6/v6-0000-cover-letter.patch has no obvious style problems and is ready for submission. | ||
28 | Checking patches-v6/v6-0001-libqos-fw_cfg-refactor-file-directory-iteraton-to.patch... | ||
29 | total: 0 errors, 0 warnings, 80 lines checked | ||
30 | |||
31 | patches-v6/v6-0001-libqos-fw_cfg-refactor-file-directory-iteraton-to.patch has no obvious style problems and is ready for submission. | ||
32 | Checking patches-v6/v6-0002-tests-qtest-libqos-add-DMA-support-for-writing-an.patch... | ||
33 | total: 0 errors, 0 warnings, 175 lines checked | ||
34 | |||
35 | patches-v6/v6-0002-tests-qtest-libqos-add-DMA-support-for-writing-an.patch has no obvious style problems and is ready for submission. | ||
36 | Checking patches-v6/v6-0003-tests-qtest-vmcoreinfo-add-a-unit-test-to-exerciz.patch... | ||
37 | total: 0 errors, 0 warnings, 111 lines checked | ||
38 | |||
39 | patches-v6/v6-0003-tests-qtest-vmcoreinfo-add-a-unit-test-to-exerciz.patch has no obvious style problems and is ready for submission. | ||
40 | |||
41 | |||
19 | cc: kraxel@redhat.com | 42 | cc: kraxel@redhat.com |
20 | cc: farosas@suse.de | 43 | cc: farosas@suse.de |
21 | cc: lvivier@redhat.com | 44 | cc: lvivier@redhat.com |
22 | cc: pbonzini@redhat.com | 45 | cc: pbonzini@redhat.com |
23 | cc: armbru@redhat.com | 46 | cc: armbru@redhat.com |
... | ... | ||
28 | 51 | ||
29 | changelog: | 52 | changelog: |
30 | v3: first working version of the patch. | 53 | v3: first working version of the patch. |
31 | v4: refactoring without any new changes put into a new patch. | 54 | v4: refactoring without any new changes put into a new patch. |
32 | v5: a new qtest added to exercize the two new write and read apis. | 55 | v5: a new qtest added to exercize the two new write and read apis. |
33 | 56 | v6: minor, coding style changed to standard qemu func prototype style - | |
57 | phil's sugestion. tags added and rebased to the latest. | ||
58 | |||
34 | all along, other review feedbacks has been taken into account. | 59 | all along, other review feedbacks has been taken into account. |
35 | 60 | ||
36 | Ani Sinha (3): | 61 | Ani Sinha (3): |
37 | libqos/fw_cfg: refactor file directory iteraton to make it more | 62 | libqos/fw_cfg: refactor file directory iteraton to make it more |
38 | reusable | 63 | reusable |
39 | tests/qtest/libqos: add DMA support for writing and reading fw_cfg | 64 | tests/qtest/libqos: add DMA support for writing and reading fw_cfg |
40 | files | 65 | files |
41 | tests/qtest/vmcoreinfo: add a unit test to exercize basic vmcoreinfo | 66 | tests/qtest/vmcoreinfo: add a unit test to exercize basic vmcoreinfo |
42 | function | 67 | function |
43 | 68 | ||
44 | MAINTAINERS | 2 + | 69 | MAINTAINERS | 2 + |
45 | tests/qtest/libqos/fw_cfg.c | 204 ++++++++++++++++++++++++++++++---- | 70 | tests/qtest/libqos/fw_cfg.c | 202 ++++++++++++++++++++++++++++++---- |
46 | tests/qtest/libqos/fw_cfg.h | 6 +- | 71 | tests/qtest/libqos/fw_cfg.h | 6 +- |
47 | tests/qtest/meson.build | 1 + | 72 | tests/qtest/meson.build | 1 + |
48 | tests/qtest/vmcoreinfo-test.c | 90 +++++++++++++++ | 73 | tests/qtest/vmcoreinfo-test.c | 90 +++++++++++++++ |
49 | 5 files changed, 280 insertions(+), 23 deletions(-) | 74 | 5 files changed, 277 insertions(+), 24 deletions(-) |
50 | create mode 100644 tests/qtest/vmcoreinfo-test.c | 75 | create mode 100644 tests/qtest/vmcoreinfo-test.c |
51 | 76 | ||
52 | -- | 77 | -- |
53 | 2.45.2 | 78 | 2.45.2 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | fw-cfg file directory iteration code can be used by other functions that may | ||
2 | want to implement fw-cfg file operations. Refactor it into a smaller helper | ||
3 | so that it can be reused. | ||
1 | 4 | ||
5 | No functional change. | ||
6 | |||
7 | Signed-off-by: Ani Sinha <anisinha@redhat.com> | ||
8 | Reviewed-by: Fabiano Rosas <farosas@suse.de> | ||
9 | --- | ||
10 | tests/qtest/libqos/fw_cfg.c | 63 +++++++++++++++++++++++-------------- | ||
11 | 1 file changed, 40 insertions(+), 23 deletions(-) | ||
12 | |||
13 | diff --git a/tests/qtest/libqos/fw_cfg.c b/tests/qtest/libqos/fw_cfg.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/tests/qtest/libqos/fw_cfg.c | ||
16 | +++ b/tests/qtest/libqos/fw_cfg.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) | ||
18 | qtest_writew(fw_cfg->qts, fw_cfg->base, key); | ||
19 | } | ||
20 | |||
21 | +static bool find_pdir_entry(QFWCFG *fw_cfg, const char *filename, | ||
22 | + uint16_t *sel, uint32_t *size) | ||
23 | +{ | ||
24 | + g_autofree unsigned char *filesbuf = NULL; | ||
25 | + uint32_t count; | ||
26 | + size_t dsize; | ||
27 | + FWCfgFile *pdir_entry; | ||
28 | + uint32_t i; | ||
29 | + bool found = false; | ||
30 | + | ||
31 | + *size = 0; | ||
32 | + *sel = 0; | ||
33 | + | ||
34 | + qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, &count, sizeof(count)); | ||
35 | + count = be32_to_cpu(count); | ||
36 | + dsize = sizeof(uint32_t) + count * sizeof(struct fw_cfg_file); | ||
37 | + filesbuf = g_malloc(dsize); | ||
38 | + qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, filesbuf, dsize); | ||
39 | + pdir_entry = (FWCfgFile *)(filesbuf + sizeof(uint32_t)); | ||
40 | + for (i = 0; i < count; ++i, ++pdir_entry) { | ||
41 | + if (!strcmp(pdir_entry->name, filename)) { | ||
42 | + *size = be32_to_cpu(pdir_entry->size); | ||
43 | + *sel = be16_to_cpu(pdir_entry->select); | ||
44 | + found = true; | ||
45 | + break; | ||
46 | + } | ||
47 | + } | ||
48 | + | ||
49 | + return found; | ||
50 | +} | ||
51 | + | ||
52 | /* | ||
53 | * The caller need check the return value. When the return value is | ||
54 | * nonzero, it means that some bytes have been transferred. | ||
55 | @@ -XXX,XX +XXX,XX @@ static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) | ||
56 | * populated, it has received only a starting slice of the fw_cfg file. | ||
57 | */ | ||
58 | size_t qfw_cfg_get_file(QFWCFG *fw_cfg, const char *filename, | ||
59 | - void *data, size_t buflen) | ||
60 | + void *data, size_t buflen) | ||
61 | { | ||
62 | - uint32_t count; | ||
63 | - uint32_t i; | ||
64 | - unsigned char *filesbuf = NULL; | ||
65 | - size_t dsize; | ||
66 | - FWCfgFile *pdir_entry; | ||
67 | size_t filesize = 0; | ||
68 | + uint32_t len; | ||
69 | + uint16_t sel; | ||
70 | |||
71 | - qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, &count, sizeof(count)); | ||
72 | - count = be32_to_cpu(count); | ||
73 | - dsize = sizeof(uint32_t) + count * sizeof(struct fw_cfg_file); | ||
74 | - filesbuf = g_malloc(dsize); | ||
75 | - qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, filesbuf, dsize); | ||
76 | - pdir_entry = (FWCfgFile *)(filesbuf + sizeof(uint32_t)); | ||
77 | - for (i = 0; i < count; ++i, ++pdir_entry) { | ||
78 | - if (!strcmp(pdir_entry->name, filename)) { | ||
79 | - uint32_t len = be32_to_cpu(pdir_entry->size); | ||
80 | - uint16_t sel = be16_to_cpu(pdir_entry->select); | ||
81 | - filesize = len; | ||
82 | - if (len > buflen) { | ||
83 | - len = buflen; | ||
84 | - } | ||
85 | - qfw_cfg_get(fw_cfg, sel, data, len); | ||
86 | - break; | ||
87 | + if (find_pdir_entry(fw_cfg, filename, &sel, &len)) { | ||
88 | + filesize = len; | ||
89 | + if (len > buflen) { | ||
90 | + len = buflen; | ||
91 | } | ||
92 | + qfw_cfg_get(fw_cfg, sel, data, len); | ||
93 | } | ||
94 | - g_free(filesbuf); | ||
95 | + | ||
96 | return filesize; | ||
97 | } | ||
98 | |||
99 | -- | ||
100 | 2.45.2 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | At present, the libqos/fw_cfg.c library does not support the modern DMA | ||
2 | interface which is required to write to the fw_cfg files. It only uses the IO | ||
3 | interface. Implement read and write methods based on DMA. This will enable | ||
4 | developers to add tests that writes to the fw_cfg file(s). The structure of | ||
5 | the code is taken from edk2 fw_cfg implementation. It has been tested by | ||
6 | writing a qtest that writes to a fw_cfg file. | ||
1 | 7 | ||
8 | Signed-off-by: Ani Sinha <anisinha@redhat.com> | ||
9 | --- | ||
10 | tests/qtest/libqos/fw_cfg.c | 139 ++++++++++++++++++++++++++++++++++++ | ||
11 | tests/qtest/libqos/fw_cfg.h | 6 +- | ||
12 | 2 files changed, 144 insertions(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/tests/qtest/libqos/fw_cfg.c b/tests/qtest/libqos/fw_cfg.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/tests/qtest/libqos/fw_cfg.c | ||
17 | +++ b/tests/qtest/libqos/fw_cfg.c | ||
18 | @@ -XXX,XX +XXX,XX @@ | ||
19 | |||
20 | #include "qemu/osdep.h" | ||
21 | #include "fw_cfg.h" | ||
22 | +#include "malloc-pc.h" | ||
23 | +#include "libqos-malloc.h" | ||
24 | #include "../libqtest.h" | ||
25 | #include "qemu/bswap.h" | ||
26 | #include "hw/nvram/fw_cfg.h" | ||
27 | @@ -XXX,XX +XXX,XX @@ static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) | ||
28 | qtest_writew(fw_cfg->qts, fw_cfg->base, key); | ||
29 | } | ||
30 | |||
31 | +static void qfw_cfg_dma_transfer(QFWCFG *fw_cfg, QOSState *qs, void *address, | ||
32 | + uint32_t length, uint32_t control) | ||
33 | +{ | ||
34 | + FWCfgDmaAccess access; | ||
35 | + uint32_t addr; | ||
36 | + uint64_t guest_access_addr; | ||
37 | + uint64_t gaddr; | ||
38 | + | ||
39 | + /* create a data buffer in guest memory */ | ||
40 | + gaddr = guest_alloc(&qs->alloc, length); | ||
41 | + | ||
42 | + if (control & FW_CFG_DMA_CTL_WRITE) { | ||
43 | + qtest_bufwrite(fw_cfg->qts, gaddr, address, length); | ||
44 | + } | ||
45 | + access.address = cpu_to_be64(gaddr); | ||
46 | + access.length = cpu_to_be32(length); | ||
47 | + access.control = cpu_to_be32(control); | ||
48 | + | ||
49 | + /* now create a separate buffer in guest memory for 'access' */ | ||
50 | + guest_access_addr = guest_alloc(&qs->alloc, sizeof(access)); | ||
51 | + qtest_bufwrite(fw_cfg->qts, guest_access_addr, &access, sizeof(access)); | ||
52 | + | ||
53 | + /* write lower 32 bits of address */ | ||
54 | + addr = cpu_to_be32((uint32_t)(uintptr_t)guest_access_addr); | ||
55 | + qtest_outl(fw_cfg->qts, fw_cfg->base + 8, addr); | ||
56 | + | ||
57 | + /* write upper 32 bits of address */ | ||
58 | + addr = cpu_to_be32((uint32_t)(uintptr_t)(guest_access_addr >> 32)); | ||
59 | + qtest_outl(fw_cfg->qts, fw_cfg->base + 4, addr); | ||
60 | + | ||
61 | + g_assert(!(be32_to_cpu(access.control) & FW_CFG_DMA_CTL_ERROR)); | ||
62 | + | ||
63 | + if (control & FW_CFG_DMA_CTL_READ) { | ||
64 | + qtest_bufread(fw_cfg->qts, gaddr, address, length); | ||
65 | + } | ||
66 | + | ||
67 | + guest_free(&qs->alloc, guest_access_addr); | ||
68 | + guest_free(&qs->alloc, gaddr); | ||
69 | +} | ||
70 | + | ||
71 | +static void qfw_cfg_write_entry(QFWCFG *fw_cfg, QOSState *qs, uint16_t key, | ||
72 | + void *buf, uint32_t len) | ||
73 | +{ | ||
74 | + qfw_cfg_select(fw_cfg, key); | ||
75 | + qfw_cfg_dma_transfer(fw_cfg, qs, buf, len, FW_CFG_DMA_CTL_WRITE); | ||
76 | +} | ||
77 | + | ||
78 | +static void qfw_cfg_read_entry(QFWCFG *fw_cfg, QOSState *qs, uint16_t key, | ||
79 | + void *buf, uint32_t len) | ||
80 | +{ | ||
81 | + qfw_cfg_select(fw_cfg, key); | ||
82 | + qfw_cfg_dma_transfer(fw_cfg, qs, buf, len, FW_CFG_DMA_CTL_READ); | ||
83 | +} | ||
84 | + | ||
85 | static bool find_pdir_entry(QFWCFG *fw_cfg, const char *filename, | ||
86 | uint16_t *sel, uint32_t *size) | ||
87 | { | ||
88 | @@ -XXX,XX +XXX,XX @@ size_t qfw_cfg_get_file(QFWCFG *fw_cfg, const char *filename, | ||
89 | return filesize; | ||
90 | } | ||
91 | |||
92 | +/* | ||
93 | + * The caller need check the return value. When the return value is | ||
94 | + * nonzero, it means that some bytes have been transferred. | ||
95 | + * | ||
96 | + * If the fw_cfg file in question is smaller than the allocated & passed-in | ||
97 | + * buffer, then the first len bytes were read. | ||
98 | + * | ||
99 | + * If the fw_cfg file in question is larger than the passed-in | ||
100 | + * buffer, then the return value explains how much was actually read. | ||
101 | + * | ||
102 | + * It is illegal to call this function if fw_cfg does not support DMA | ||
103 | + * interface. The caller should ensure that DMA is supported before | ||
104 | + * calling this function. | ||
105 | + * | ||
106 | + * Passed QOSState pointer qs must be initialized. qs->alloc must also be | ||
107 | + * properly initialized. | ||
108 | + */ | ||
109 | +size_t qfw_cfg_read_file(QFWCFG *fw_cfg, QOSState *qs, const char *filename, | ||
110 | + void *data, size_t buflen) | ||
111 | +{ | ||
112 | + uint32_t len = 0; | ||
113 | + uint16_t sel; | ||
114 | + uint32_t id; | ||
115 | + | ||
116 | + g_assert(qs); | ||
117 | + g_assert(filename); | ||
118 | + g_assert(data); | ||
119 | + g_assert(buflen); | ||
120 | + /* check if DMA is supported since we use DMA for read */ | ||
121 | + id = qfw_cfg_get_u32(fw_cfg, FW_CFG_ID); | ||
122 | + g_assert(id & FW_CFG_VERSION_DMA); | ||
123 | + | ||
124 | + if (find_pdir_entry(fw_cfg, filename, &sel, &len)) { | ||
125 | + if (len > buflen) { | ||
126 | + len = buflen; | ||
127 | + } | ||
128 | + qfw_cfg_read_entry(fw_cfg, qs, sel, data, len); | ||
129 | + } | ||
130 | + | ||
131 | + return len; | ||
132 | +} | ||
133 | + | ||
134 | +/* | ||
135 | + * The caller need check the return value. When the return value is | ||
136 | + * nonzero, it means that some bytes have been transferred. | ||
137 | + * | ||
138 | + * If the fw_cfg file in question is smaller than the allocated & passed-in | ||
139 | + * buffer, then the buffer has been partially written. | ||
140 | + * | ||
141 | + * If the fw_cfg file in question is larger than the passed-in | ||
142 | + * buffer, then the return value explains how much was actually written. | ||
143 | + * | ||
144 | + * It is illegal to call this function if fw_cfg does not support DMA | ||
145 | + * interface. The caller should ensure that DMA is supported before | ||
146 | + * calling this function. | ||
147 | + * | ||
148 | + * Passed QOSState pointer qs must be initialized. qs->alloc must also be | ||
149 | + * properly initialized. | ||
150 | + */ | ||
151 | +size_t qfw_cfg_write_file(QFWCFG *fw_cfg, QOSState *qs, const char *filename, | ||
152 | + void *data, size_t buflen) | ||
153 | +{ | ||
154 | + uint32_t len = 0; | ||
155 | + uint16_t sel; | ||
156 | + uint32_t id; | ||
157 | + | ||
158 | + g_assert(qs); | ||
159 | + g_assert(filename); | ||
160 | + g_assert(data); | ||
161 | + g_assert(buflen); | ||
162 | + /* write operation is only valid if DMA is supported */ | ||
163 | + id = qfw_cfg_get_u32(fw_cfg, FW_CFG_ID); | ||
164 | + g_assert(id & FW_CFG_VERSION_DMA); | ||
165 | + | ||
166 | + if (find_pdir_entry(fw_cfg, filename, &sel, &len)) { | ||
167 | + if (len > buflen) { | ||
168 | + len = buflen; | ||
169 | + } | ||
170 | + qfw_cfg_write_entry(fw_cfg, qs, sel, data, len); | ||
171 | + } | ||
172 | + return len; | ||
173 | +} | ||
174 | + | ||
175 | static void mm_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len) | ||
176 | { | ||
177 | uint8_t *ptr = data; | ||
178 | diff --git a/tests/qtest/libqos/fw_cfg.h b/tests/qtest/libqos/fw_cfg.h | ||
179 | index XXXXXXX..XXXXXXX 100644 | ||
180 | --- a/tests/qtest/libqos/fw_cfg.h | ||
181 | +++ b/tests/qtest/libqos/fw_cfg.h | ||
182 | @@ -XXX,XX +XXX,XX @@ | ||
183 | #define LIBQOS_FW_CFG_H | ||
184 | |||
185 | #include "../libqtest.h" | ||
186 | +#include "libqos.h" | ||
187 | |||
188 | typedef struct QFWCFG QFWCFG; | ||
189 | |||
190 | @@ -XXX,XX +XXX,XX @@ uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key); | ||
191 | uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key); | ||
192 | size_t qfw_cfg_get_file(QFWCFG *fw_cfg, const char *filename, | ||
193 | void *data, size_t buflen); | ||
194 | - | ||
195 | +size_t qfw_cfg_write_file(QFWCFG *fw_cfg, QOSState *qs, const char *filename, | ||
196 | + void *data, size_t buflen); | ||
197 | +size_t qfw_cfg_read_file(QFWCFG *fw_cfg, QOSState *qs, const char *filename, | ||
198 | + void *data, size_t buflen); | ||
199 | QFWCFG *mm_fw_cfg_init(QTestState *qts, uint64_t base); | ||
200 | void mm_fw_cfg_uninit(QFWCFG *fw_cfg); | ||
201 | QFWCFG *io_fw_cfg_init(QTestState *qts, uint16_t base); | ||
202 | -- | ||
203 | 2.45.2 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | A new qtest is written that exercizes the fw-cfg DMA based read and write ops | ||
2 | to write values into vmcoreinfo fw-cfg file and read them back and verify that | ||
3 | they are the same. | ||
1 | 4 | ||
5 | Signed-off-by: Ani Sinha <anisinha@redhat.com> | ||
6 | --- | ||
7 | MAINTAINERS | 2 + | ||
8 | tests/qtest/meson.build | 1 + | ||
9 | tests/qtest/vmcoreinfo-test.c | 90 +++++++++++++++++++++++++++++++++++ | ||
10 | 3 files changed, 93 insertions(+) | ||
11 | create mode 100644 tests/qtest/vmcoreinfo-test.c | ||
12 | |||
13 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/MAINTAINERS | ||
16 | +++ b/MAINTAINERS | ||
17 | @@ -XXX,XX +XXX,XX @@ F: include/system/device_tree.h | ||
18 | Dump | ||
19 | S: Supported | ||
20 | M: Marc-André Lureau <marcandre.lureau@redhat.com> | ||
21 | +R: Ani Sinha <anisinha@redhat.com> | ||
22 | F: dump/ | ||
23 | F: hw/misc/vmcoreinfo.c | ||
24 | F: include/hw/misc/vmcoreinfo.h | ||
25 | @@ -XXX,XX +XXX,XX @@ F: qapi/dump.json | ||
26 | F: scripts/dump-guest-memory.py | ||
27 | F: stubs/dump.c | ||
28 | F: docs/specs/vmcoreinfo.rst | ||
29 | +F: tests/qtest/vmcoreinfo-test.c | ||
30 | |||
31 | Error reporting | ||
32 | M: Markus Armbruster <armbru@redhat.com> | ||
33 | diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/tests/qtest/meson.build | ||
36 | +++ b/tests/qtest/meson.build | ||
37 | @@ -XXX,XX +XXX,XX @@ qtests_i386 = \ | ||
38 | (config_all_devices.has_key('CONFIG_AHCI_ICH9') ? ['tco-test'] : []) + \ | ||
39 | (config_all_devices.has_key('CONFIG_FDC_ISA') ? ['fdc-test'] : []) + \ | ||
40 | (config_all_devices.has_key('CONFIG_I440FX') ? ['fw_cfg-test'] : []) + \ | ||
41 | + (config_all_devices.has_key('CONFIG_FW_CFG_DMA') ? ['vmcoreinfo-test'] : []) + \ | ||
42 | (config_all_devices.has_key('CONFIG_I440FX') ? ['i440fx-test'] : []) + \ | ||
43 | (config_all_devices.has_key('CONFIG_I440FX') ? ['ide-test'] : []) + \ | ||
44 | (config_all_devices.has_key('CONFIG_I440FX') ? ['numa-test'] : []) + \ | ||
45 | diff --git a/tests/qtest/vmcoreinfo-test.c b/tests/qtest/vmcoreinfo-test.c | ||
46 | new file mode 100644 | ||
47 | index XXXXXXX..XXXXXXX | ||
48 | --- /dev/null | ||
49 | +++ b/tests/qtest/vmcoreinfo-test.c | ||
50 | @@ -XXX,XX +XXX,XX @@ | ||
51 | +/* | ||
52 | + * qtest vmcoreinfo test case | ||
53 | + * | ||
54 | + * Copyright Red Hat. 2025. | ||
55 | + * | ||
56 | + * Authors: | ||
57 | + * Ani Sinha <anisinha@redhat.com> | ||
58 | + * | ||
59 | + * This work is licensed under the terms of the GNU GPL, version 2 or later. | ||
60 | + * See the COPYING file in the top-level directory. | ||
61 | + */ | ||
62 | + | ||
63 | +#include "qemu/osdep.h" | ||
64 | +#include "qemu/units.h" | ||
65 | +#include "libqos/libqos-pc.h" | ||
66 | +#include "libqtest.h" | ||
67 | +#include "standard-headers/linux/qemu_fw_cfg.h" | ||
68 | +#include "libqos/fw_cfg.h" | ||
69 | +#include "qemu/bswap.h" | ||
70 | +#include "hw/misc/vmcoreinfo.h" | ||
71 | + | ||
72 | +static void test_vmcoreinfo_write_basic(void) | ||
73 | +{ | ||
74 | + QFWCFG *fw_cfg; | ||
75 | + QOSState *qs; | ||
76 | + FWCfgVMCoreInfo info; | ||
77 | + size_t filesize; | ||
78 | + uint16_t guest_format; | ||
79 | + uint16_t host_format; | ||
80 | + uint32_t size; | ||
81 | + uint64_t paddr; | ||
82 | + | ||
83 | + qs = qtest_pc_boot("-device vmcoreinfo"); | ||
84 | + fw_cfg = pc_fw_cfg_init(qs->qts); | ||
85 | + | ||
86 | + memset(&info, 0 , sizeof(info)); | ||
87 | + /* read vmcoreinfo and read back the host format */ | ||
88 | + filesize = qfw_cfg_read_file(fw_cfg, qs, FW_CFG_VMCOREINFO_FILENAME, | ||
89 | + &info, sizeof(info)); | ||
90 | + g_assert_cmpint(filesize, ==, sizeof(info)); | ||
91 | + | ||
92 | + host_format = le16_to_cpu(info.host_format); | ||
93 | + g_assert_cmpint(host_format, ==, FW_CFG_VMCOREINFO_FORMAT_ELF); | ||
94 | + | ||
95 | + memset(&info, 0 , sizeof(info)); | ||
96 | + info.guest_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF); | ||
97 | + info.size = cpu_to_le32(1 * MiB); | ||
98 | + info.paddr = cpu_to_le64(0xffffff00); | ||
99 | + info.host_format = cpu_to_le16(host_format); | ||
100 | + | ||
101 | + /* write the values to the host */ | ||
102 | + filesize = qfw_cfg_write_file(fw_cfg, qs, FW_CFG_VMCOREINFO_FILENAME, | ||
103 | + &info, sizeof(info)); | ||
104 | + g_assert_cmpint(filesize, ==, sizeof(info)); | ||
105 | + | ||
106 | + memset(&info, 0 , sizeof(info)); | ||
107 | + | ||
108 | + /* now read back the values we wrote and compare that they are the same */ | ||
109 | + filesize = qfw_cfg_read_file(fw_cfg, qs, FW_CFG_VMCOREINFO_FILENAME, | ||
110 | + &info, sizeof(info)); | ||
111 | + g_assert_cmpint(filesize, ==, sizeof(info)); | ||
112 | + | ||
113 | + size = le32_to_cpu(info.size); | ||
114 | + paddr = le64_to_cpu(info.paddr); | ||
115 | + guest_format = le16_to_cpu(info.guest_format); | ||
116 | + | ||
117 | + g_assert_cmpint(size, ==, 1 * MiB); | ||
118 | + g_assert_cmpint(paddr, ==, 0xffffff00); | ||
119 | + g_assert_cmpint(guest_format, ==, FW_CFG_VMCOREINFO_FORMAT_ELF); | ||
120 | + | ||
121 | + pc_fw_cfg_uninit(fw_cfg); | ||
122 | + qtest_shutdown(qs); | ||
123 | +} | ||
124 | + | ||
125 | +int main(int argc, char **argv) | ||
126 | +{ | ||
127 | + const char *arch = qtest_get_arch(); | ||
128 | + | ||
129 | + g_test_init(&argc, &argv, NULL); | ||
130 | + | ||
131 | + if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) { | ||
132 | + /* skip for non-x86 */ | ||
133 | + exit(EXIT_SUCCESS); | ||
134 | + } | ||
135 | + | ||
136 | + qtest_add_func("vmcoreinfo/basic-write", | ||
137 | + test_vmcoreinfo_write_basic); | ||
138 | + | ||
139 | + return g_test_run(); | ||
140 | +} | ||
141 | -- | ||
142 | 2.45.2 | ||
143 | |||
144 | diff view generated by jsdifflib |