File tree Expand file tree Collapse file tree 5 files changed +37
-1
lines changed Expand file tree Collapse file tree 5 files changed +37
-1
lines changed Original file line number Diff line number Diff line change @@ -1136,8 +1136,13 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
1136
1136
vcdev -> err = - EIO ;
1137
1137
}
1138
1138
virtio_ccw_check_activity (vcdev , activity );
1139
- /* Interrupts are disabled here */
1139
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
1140
+ /*
1141
+ * Paired with virtio_ccw_synchronize_cbs() and interrupts are
1142
+ * disabled here.
1143
+ */
1140
1144
read_lock (& vcdev -> irq_lock );
1145
+ #endif
1141
1146
for_each_set_bit (i , indicators (vcdev ),
1142
1147
sizeof (* indicators (vcdev )) * BITS_PER_BYTE ) {
1143
1148
/* The bit clear must happen before the vring kick. */
@@ -1146,7 +1151,9 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
1146
1151
vq = virtio_ccw_vq_by_ind (vcdev , i );
1147
1152
vring_interrupt (0 , vq );
1148
1153
}
1154
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
1149
1155
read_unlock (& vcdev -> irq_lock );
1156
+ #endif
1150
1157
if (test_bit (0 , indicators2 (vcdev ))) {
1151
1158
virtio_config_changed (& vcdev -> vdev );
1152
1159
clear_bit (0 , indicators2 (vcdev ));
Original file line number Diff line number Diff line change @@ -29,6 +29,19 @@ menuconfig VIRTIO_MENU
29
29
30
30
if VIRTIO_MENU
31
31
32
+ config VIRTIO_HARDEN_NOTIFICATION
33
+ bool "Harden virtio notification"
34
+ help
35
+ Enable this to harden the device notifications and suppress
36
+ those that happen at a time where notifications are illegal.
37
+
38
+ Experimental: Note that several drivers still have bugs that
39
+ may cause crashes or hangs when correct handling of
40
+ notifications is enforced; depending on the subset of
41
+ drivers and devices you use, this may or may not work.
42
+
43
+ If unsure, say N.
44
+
32
45
config VIRTIO_PCI
33
46
tristate "PCI driver for virtio devices"
34
47
depends on PCI
Original file line number Diff line number Diff line change @@ -219,6 +219,7 @@ static int virtio_features_ok(struct virtio_device *dev)
219
219
* */
220
220
void virtio_reset_device (struct virtio_device * dev )
221
221
{
222
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
222
223
/*
223
224
* The below virtio_synchronize_cbs() guarantees that any
224
225
* interrupt for this line arriving after
@@ -227,6 +228,7 @@ void virtio_reset_device(struct virtio_device *dev)
227
228
*/
228
229
virtio_break_device (dev );
229
230
virtio_synchronize_cbs (dev );
231
+ #endif
230
232
231
233
dev -> config -> reset (dev );
232
234
}
Original file line number Diff line number Diff line change @@ -1708,7 +1708,11 @@ static struct virtqueue *vring_create_virtqueue_packed(
1708
1708
vq -> we_own_ring = true;
1709
1709
vq -> notify = notify ;
1710
1710
vq -> weak_barriers = weak_barriers ;
1711
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
1711
1712
vq -> broken = true;
1713
+ #else
1714
+ vq -> broken = false;
1715
+ #endif
1712
1716
vq -> last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR );
1713
1717
vq -> event_triggered = false;
1714
1718
vq -> num_added = 0 ;
@@ -2154,9 +2158,13 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
2154
2158
}
2155
2159
2156
2160
if (unlikely (vq -> broken )) {
2161
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
2157
2162
dev_warn_once (& vq -> vq .vdev -> dev ,
2158
2163
"virtio vring IRQ raised before DRIVER_OK" );
2159
2164
return IRQ_NONE ;
2165
+ #else
2166
+ return IRQ_HANDLED ;
2167
+ #endif
2160
2168
}
2161
2169
2162
2170
/* Just a hint for performance: so it's ok that this can be racy! */
@@ -2199,7 +2207,11 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
2199
2207
vq -> we_own_ring = false;
2200
2208
vq -> notify = notify ;
2201
2209
vq -> weak_barriers = weak_barriers ;
2210
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
2202
2211
vq -> broken = true;
2212
+ #else
2213
+ vq -> broken = false;
2214
+ #endif
2203
2215
vq -> last_used_idx = 0 ;
2204
2216
vq -> event_triggered = false;
2205
2217
vq -> num_added = 0 ;
Original file line number Diff line number Diff line change @@ -257,13 +257,15 @@ void virtio_device_ready(struct virtio_device *dev)
257
257
258
258
WARN_ON (status & VIRTIO_CONFIG_S_DRIVER_OK );
259
259
260
+ #ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
260
261
/*
261
262
* The virtio_synchronize_cbs() makes sure vring_interrupt()
262
263
* will see the driver specific setup if it sees vq->broken
263
264
* as false (even if the notifications come before DRIVER_OK).
264
265
*/
265
266
virtio_synchronize_cbs (dev );
266
267
__virtio_unbreak_device (dev );
268
+ #endif
267
269
/*
268
270
* The transport should ensure the visibility of vq->broken
269
271
* before setting DRIVER_OK. See the comments for the transport
You can’t perform that action at this time.
0 commit comments