pci.cc (10559:62f5f7363197) pci.cc (10565:23593fdaadcd)
1/*
2 * Copyright (c) 2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 */
39
40#include "debug/VIOPci.hh"
41#include "dev/virtio/pci.hh"
42#include "mem/packet_access.hh"
43#include "params/PciVirtIO.hh"
44
45PciVirtIO::PciVirtIO(const Params *params)
46 : PciDevice(params), queueNotify(0), interruptDeliveryPending(false),
47 vio(*params->vio), callbackKick(this)
48{
49 // Override the subsystem ID with the device ID from VirtIO
50 config.subsystemID = htole(vio.deviceId);
51 BARSize[0] = BAR0_SIZE_BASE + vio.configSize;
52
53 vio.registerKickCallback(&callbackKick);
54}
55
56PciVirtIO::~PciVirtIO()
57{
58}
59
60Tick
61PciVirtIO::read(PacketPtr pkt)
62{
63 const unsigned M5_VAR_USED size(pkt->getSize());
64 int bar;
65 Addr offset;
66 if (!getBAR(pkt->getAddr(), bar, offset))
67 panic("Invalid PCI memory access to unmapped memory.\n");
68 assert(bar == 0);
69
70 DPRINTF(VIOPci, "Reading offset 0x%x [len: %i]\n", offset, size);
71
72 // Forward device configuration writes to the device VirtIO model
73 if (offset >= OFF_VIO_DEVICE) {
74 vio.readConfig(pkt, offset - OFF_VIO_DEVICE);
75 return 0;
76 }
77
1/*
2 * Copyright (c) 2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 */
39
40#include "debug/VIOPci.hh"
41#include "dev/virtio/pci.hh"
42#include "mem/packet_access.hh"
43#include "params/PciVirtIO.hh"
44
45PciVirtIO::PciVirtIO(const Params *params)
46 : PciDevice(params), queueNotify(0), interruptDeliveryPending(false),
47 vio(*params->vio), callbackKick(this)
48{
49 // Override the subsystem ID with the device ID from VirtIO
50 config.subsystemID = htole(vio.deviceId);
51 BARSize[0] = BAR0_SIZE_BASE + vio.configSize;
52
53 vio.registerKickCallback(&callbackKick);
54}
55
56PciVirtIO::~PciVirtIO()
57{
58}
59
60Tick
61PciVirtIO::read(PacketPtr pkt)
62{
63 const unsigned M5_VAR_USED size(pkt->getSize());
64 int bar;
65 Addr offset;
66 if (!getBAR(pkt->getAddr(), bar, offset))
67 panic("Invalid PCI memory access to unmapped memory.\n");
68 assert(bar == 0);
69
70 DPRINTF(VIOPci, "Reading offset 0x%x [len: %i]\n", offset, size);
71
72 // Forward device configuration writes to the device VirtIO model
73 if (offset >= OFF_VIO_DEVICE) {
74 vio.readConfig(pkt, offset - OFF_VIO_DEVICE);
75 return 0;
76 }
77
78 pkt->allocate();
79
80 switch(offset) {
81 case OFF_DEVICE_FEATURES:
82 DPRINTF(VIOPci, " DEVICE_FEATURES request\n");
83 assert(size == sizeof(uint32_t));
84 pkt->set<uint32_t>(vio.deviceFeatures);
85 break;
86
87 case OFF_GUEST_FEATURES:
88 DPRINTF(VIOPci, " GUEST_FEATURES request\n");
89 assert(size == sizeof(uint32_t));
90 pkt->set<uint32_t>(vio.getGuestFeatures());
91 break;
92
93 case OFF_QUEUE_ADDRESS:
94 DPRINTF(VIOPci, " QUEUE_ADDRESS request\n");
95 assert(size == sizeof(uint32_t));
96 pkt->set<uint32_t>(vio.getQueueAddress());
97 break;
98
99 case OFF_QUEUE_SIZE:
100 DPRINTF(VIOPci, " QUEUE_SIZE request\n");
101 assert(size == sizeof(uint16_t));
102 pkt->set<uint16_t>(vio.getQueueSize());
103 break;
104
105 case OFF_QUEUE_SELECT:
106 DPRINTF(VIOPci, " QUEUE_SELECT\n");
107 assert(size == sizeof(uint16_t));
108 pkt->set<uint16_t>(vio.getQueueSelect());
109 break;
110
111 case OFF_QUEUE_NOTIFY:
112 DPRINTF(VIOPci, " QUEUE_NOTIFY request\n");
113 assert(size == sizeof(uint16_t));
114 pkt->set<uint16_t>(queueNotify);
115 break;
116
117 case OFF_DEVICE_STATUS:
118 DPRINTF(VIOPci, " DEVICE_STATUS request\n");
119 assert(size == sizeof(uint8_t));
120 pkt->set<uint8_t>(vio.getDeviceStatus());
121 break;
122
123 case OFF_ISR_STATUS: {
124 DPRINTF(VIOPci, " ISR_STATUS\n");
125 assert(size == sizeof(uint8_t));
126 uint8_t isr_status(interruptDeliveryPending ? 1 : 0);
127 interruptDeliveryPending = false;
128 pkt->set<uint8_t>(isr_status);
129 } break;
130
131 default:
132 panic("Unhandled read offset (0x%x)\n", offset);
133 }
134
135 return 0;
136}
137
138Tick
139PciVirtIO::write(PacketPtr pkt)
140{
141 const unsigned M5_VAR_USED size(pkt->getSize());
142 int bar;
143 Addr offset;
144 if (!getBAR(pkt->getAddr(), bar, offset))
145 panic("Invalid PCI memory access to unmapped memory.\n");
146 assert(bar == 0);
147
148 DPRINTF(VIOPci, "Writing offset 0x%x [len: %i]\n", offset, size);
149
150 // Forward device configuration writes to the device VirtIO model
151 if (offset >= OFF_VIO_DEVICE) {
152 vio.writeConfig(pkt, offset - OFF_VIO_DEVICE);
153 return 0;
154 }
155
78 switch(offset) {
79 case OFF_DEVICE_FEATURES:
80 DPRINTF(VIOPci, " DEVICE_FEATURES request\n");
81 assert(size == sizeof(uint32_t));
82 pkt->set<uint32_t>(vio.deviceFeatures);
83 break;
84
85 case OFF_GUEST_FEATURES:
86 DPRINTF(VIOPci, " GUEST_FEATURES request\n");
87 assert(size == sizeof(uint32_t));
88 pkt->set<uint32_t>(vio.getGuestFeatures());
89 break;
90
91 case OFF_QUEUE_ADDRESS:
92 DPRINTF(VIOPci, " QUEUE_ADDRESS request\n");
93 assert(size == sizeof(uint32_t));
94 pkt->set<uint32_t>(vio.getQueueAddress());
95 break;
96
97 case OFF_QUEUE_SIZE:
98 DPRINTF(VIOPci, " QUEUE_SIZE request\n");
99 assert(size == sizeof(uint16_t));
100 pkt->set<uint16_t>(vio.getQueueSize());
101 break;
102
103 case OFF_QUEUE_SELECT:
104 DPRINTF(VIOPci, " QUEUE_SELECT\n");
105 assert(size == sizeof(uint16_t));
106 pkt->set<uint16_t>(vio.getQueueSelect());
107 break;
108
109 case OFF_QUEUE_NOTIFY:
110 DPRINTF(VIOPci, " QUEUE_NOTIFY request\n");
111 assert(size == sizeof(uint16_t));
112 pkt->set<uint16_t>(queueNotify);
113 break;
114
115 case OFF_DEVICE_STATUS:
116 DPRINTF(VIOPci, " DEVICE_STATUS request\n");
117 assert(size == sizeof(uint8_t));
118 pkt->set<uint8_t>(vio.getDeviceStatus());
119 break;
120
121 case OFF_ISR_STATUS: {
122 DPRINTF(VIOPci, " ISR_STATUS\n");
123 assert(size == sizeof(uint8_t));
124 uint8_t isr_status(interruptDeliveryPending ? 1 : 0);
125 interruptDeliveryPending = false;
126 pkt->set<uint8_t>(isr_status);
127 } break;
128
129 default:
130 panic("Unhandled read offset (0x%x)\n", offset);
131 }
132
133 return 0;
134}
135
136Tick
137PciVirtIO::write(PacketPtr pkt)
138{
139 const unsigned M5_VAR_USED size(pkt->getSize());
140 int bar;
141 Addr offset;
142 if (!getBAR(pkt->getAddr(), bar, offset))
143 panic("Invalid PCI memory access to unmapped memory.\n");
144 assert(bar == 0);
145
146 DPRINTF(VIOPci, "Writing offset 0x%x [len: %i]\n", offset, size);
147
148 // Forward device configuration writes to the device VirtIO model
149 if (offset >= OFF_VIO_DEVICE) {
150 vio.writeConfig(pkt, offset - OFF_VIO_DEVICE);
151 return 0;
152 }
153
156 pkt->allocate();
157
158 switch(offset) {
159 case OFF_DEVICE_FEATURES:
160 warn("Guest tried to write device features.");
161 break;
162
163 case OFF_GUEST_FEATURES:
164 DPRINTF(VIOPci, " WRITE GUEST_FEATURES request\n");
165 assert(size == sizeof(uint32_t));
166 vio.setGuestFeatures(pkt->get<uint32_t>());
167 break;
168
169 case OFF_QUEUE_ADDRESS:
170 DPRINTF(VIOPci, " WRITE QUEUE_ADDRESS\n");
171 assert(size == sizeof(uint32_t));
172 vio.setQueueAddress(pkt->get<uint32_t>());
173 break;
174
175 case OFF_QUEUE_SIZE:
176 panic("Guest tried to write queue size.");
177 break;
178
179 case OFF_QUEUE_SELECT:
180 DPRINTF(VIOPci, " WRITE QUEUE_SELECT\n");
181 assert(size == sizeof(uint16_t));
182 vio.setQueueSelect(pkt->get<uint16_t>());
183 break;
184
185 case OFF_QUEUE_NOTIFY:
186 DPRINTF(VIOPci, " WRITE QUEUE_NOTIFY\n");
187 assert(size == sizeof(uint16_t));
188 queueNotify = pkt->get<uint16_t>();
189 vio.onNotify(queueNotify);
190 break;
191
192 case OFF_DEVICE_STATUS: {
193 assert(size == sizeof(uint8_t));
194 uint8_t status(pkt->get<uint8_t>());
195 DPRINTF(VIOPci, "VirtIO set status: 0x%x\n", status);
196 vio.setDeviceStatus(status);
197 } break;
198
199 case OFF_ISR_STATUS:
200 warn("Guest tried to write ISR status.");
201 break;
202
203 default:
204 panic("Unhandled read offset (0x%x)\n", offset);
205 }
206
207 return 0;
208}
209
210void
211PciVirtIO::kick()
212{
213 DPRINTF(VIOPci, "kick(): Sending interrupt...\n");
214 interruptDeliveryPending = true;
215 intrPost();
216}
217
218PciVirtIO *
219PciVirtIOParams::create()
220{
221 return new PciVirtIO(this);
222}
154 switch(offset) {
155 case OFF_DEVICE_FEATURES:
156 warn("Guest tried to write device features.");
157 break;
158
159 case OFF_GUEST_FEATURES:
160 DPRINTF(VIOPci, " WRITE GUEST_FEATURES request\n");
161 assert(size == sizeof(uint32_t));
162 vio.setGuestFeatures(pkt->get<uint32_t>());
163 break;
164
165 case OFF_QUEUE_ADDRESS:
166 DPRINTF(VIOPci, " WRITE QUEUE_ADDRESS\n");
167 assert(size == sizeof(uint32_t));
168 vio.setQueueAddress(pkt->get<uint32_t>());
169 break;
170
171 case OFF_QUEUE_SIZE:
172 panic("Guest tried to write queue size.");
173 break;
174
175 case OFF_QUEUE_SELECT:
176 DPRINTF(VIOPci, " WRITE QUEUE_SELECT\n");
177 assert(size == sizeof(uint16_t));
178 vio.setQueueSelect(pkt->get<uint16_t>());
179 break;
180
181 case OFF_QUEUE_NOTIFY:
182 DPRINTF(VIOPci, " WRITE QUEUE_NOTIFY\n");
183 assert(size == sizeof(uint16_t));
184 queueNotify = pkt->get<uint16_t>();
185 vio.onNotify(queueNotify);
186 break;
187
188 case OFF_DEVICE_STATUS: {
189 assert(size == sizeof(uint8_t));
190 uint8_t status(pkt->get<uint8_t>());
191 DPRINTF(VIOPci, "VirtIO set status: 0x%x\n", status);
192 vio.setDeviceStatus(status);
193 } break;
194
195 case OFF_ISR_STATUS:
196 warn("Guest tried to write ISR status.");
197 break;
198
199 default:
200 panic("Unhandled read offset (0x%x)\n", offset);
201 }
202
203 return 0;
204}
205
206void
207PciVirtIO::kick()
208{
209 DPRINTF(VIOPci, "kick(): Sending interrupt...\n");
210 interruptDeliveryPending = true;
211 intrPost();
212}
213
214PciVirtIO *
215PciVirtIOParams::create()
216{
217 return new PciVirtIO(this);
218}