1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14
15#include "qemu/main-loop.h"
16#include "tests/qtest/libqtest.h"
17#include "tests/qtest/libqos/pci.h"
18#include "tests/qtest/libqos/pci-pc.h"
19#include "fuzz.h"
20#include "fuzz/qos_fuzz.h"
21#include "fuzz/fork_fuzz.h"
22
23
24#define I440FX_PCI_HOST_BRIDGE_CFG 0xcf8
25#define I440FX_PCI_HOST_BRIDGE_DATA 0xcfc
26
27
28
29
30
31
32enum action_id {
33 WRITEB,
34 WRITEW,
35 WRITEL,
36 READB,
37 READW,
38 READL,
39 ACTION_MAX
40};
41
42static void i440fx_fuzz_qtest(QTestState *s,
43 const unsigned char *Data, size_t Size) {
44
45
46
47
48 typedef struct QTestFuzzAction {
49 uint8_t opcode;
50 uint8_t addr;
51 uint32_t value;
52 } QTestFuzzAction;
53 QTestFuzzAction a;
54
55 while (Size >= sizeof(a)) {
56
57 memcpy(&a, Data, sizeof(a));
58
59 uint16_t addr = a.addr % 2 ? I440FX_PCI_HOST_BRIDGE_CFG :
60 I440FX_PCI_HOST_BRIDGE_DATA;
61 switch (a.opcode % ACTION_MAX) {
62 case WRITEB:
63 qtest_outb(s, addr, (uint8_t)a.value);
64 break;
65 case WRITEW:
66 qtest_outw(s, addr, (uint16_t)a.value);
67 break;
68 case WRITEL:
69 qtest_outl(s, addr, (uint32_t)a.value);
70 break;
71 case READB:
72 qtest_inb(s, addr);
73 break;
74 case READW:
75 qtest_inw(s, addr);
76 break;
77 case READL:
78 qtest_inl(s, addr);
79 break;
80 }
81
82 Size -= sizeof(a);
83 Data += sizeof(a);
84 }
85 flush_events(s);
86}
87
88static void i440fx_fuzz_qos(QTestState *s,
89 const unsigned char *Data, size_t Size) {
90
91
92
93
94 typedef struct QOSFuzzAction {
95 uint8_t opcode;
96 uint8_t offset;
97 int devfn;
98 uint32_t value;
99 } QOSFuzzAction;
100
101 static QPCIBus *bus;
102 if (!bus) {
103 bus = qpci_new_pc(s, fuzz_qos_alloc);
104 }
105
106 QOSFuzzAction a;
107 while (Size >= sizeof(a)) {
108 memcpy(&a, Data, sizeof(a));
109 switch (a.opcode % ACTION_MAX) {
110 case WRITEB:
111 bus->config_writeb(bus, a.devfn, a.offset, (uint8_t)a.value);
112 break;
113 case WRITEW:
114 bus->config_writew(bus, a.devfn, a.offset, (uint16_t)a.value);
115 break;
116 case WRITEL:
117 bus->config_writel(bus, a.devfn, a.offset, (uint32_t)a.value);
118 break;
119 case READB:
120 bus->config_readb(bus, a.devfn, a.offset);
121 break;
122 case READW:
123 bus->config_readw(bus, a.devfn, a.offset);
124 break;
125 case READL:
126 bus->config_readl(bus, a.devfn, a.offset);
127 break;
128 }
129 Size -= sizeof(a);
130 Data += sizeof(a);
131 }
132 flush_events(s);
133}
134
135static void i440fx_fuzz_qos_fork(QTestState *s,
136 const unsigned char *Data, size_t Size) {
137 if (fork() == 0) {
138 i440fx_fuzz_qos(s, Data, Size);
139 _Exit(0);
140 } else {
141 wait(NULL);
142 }
143}
144
145static const char *i440fx_qtest_argv = TARGET_NAME " -machine accel=qtest"
146 "-m 0 -display none";
147static const char *i440fx_argv(FuzzTarget *t)
148{
149 return i440fx_qtest_argv;
150}
151
152static void fork_init(void)
153{
154 counter_shm_init();
155}
156
157static void register_pci_fuzz_targets(void)
158{
159
160 fuzz_add_target(&(FuzzTarget){
161 .name = "i440fx-qtest-reboot-fuzz",
162 .description = "Fuzz the i440fx using raw qtest commands and"
163 "rebooting after each run",
164 .get_init_cmdline = i440fx_argv,
165 .fuzz = i440fx_fuzz_qtest});
166
167
168 fuzz_add_qos_target(&(FuzzTarget){
169 .name = "i440fx-qos-fork-fuzz",
170 .description = "Fuzz the i440fx using raw qtest commands and"
171 "rebooting after each run",
172 .pre_vm_init = &fork_init,
173 .fuzz = i440fx_fuzz_qos_fork,},
174 "i440FX-pcihost",
175 &(QOSGraphTestOptions){}
176 );
177
178
179
180
181
182
183 fuzz_add_qos_target(&(FuzzTarget){
184 .name = "i440fx-qos-noreset-fuzz",
185 .description = "Fuzz the i440fx using raw qtest commands and"
186 "rebooting after each run",
187 .fuzz = i440fx_fuzz_qos,},
188 "i440FX-pcihost",
189 &(QOSGraphTestOptions){}
190 );
191}
192
193fuzz_target_init(register_pci_fuzz_targets);
194