@@ -43,6 +43,7 @@ struct xencons_info {
43
43
int irq ;
44
44
int vtermno ;
45
45
grant_ref_t gntref ;
46
+ spinlock_t ring_lock ;
46
47
};
47
48
48
49
static LIST_HEAD (xenconsoles );
@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons,
89
90
XENCONS_RING_IDX cons , prod ;
90
91
struct xencons_interface * intf = xencons -> intf ;
91
92
int sent = 0 ;
93
+ unsigned long flags ;
92
94
95
+ spin_lock_irqsave (& xencons -> ring_lock , flags );
93
96
cons = intf -> out_cons ;
94
97
prod = intf -> out_prod ;
95
98
mb (); /* update queue values before going on */
96
99
97
100
if ((prod - cons ) > sizeof (intf -> out )) {
101
+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
98
102
pr_err_once ("xencons: Illegal ring page indices" );
99
103
return - EINVAL ;
100
104
}
@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons,
104
108
105
109
wmb (); /* write ring before updating pointer */
106
110
intf -> out_prod = prod ;
111
+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
107
112
108
113
if (sent )
109
114
notify_daemon (xencons );
@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
146
151
int recv = 0 ;
147
152
struct xencons_info * xencons = vtermno_to_xencons (vtermno );
148
153
unsigned int eoiflag = 0 ;
154
+ unsigned long flags ;
149
155
150
156
if (xencons == NULL )
151
157
return - EINVAL ;
152
158
intf = xencons -> intf ;
153
159
160
+ spin_lock_irqsave (& xencons -> ring_lock , flags );
154
161
cons = intf -> in_cons ;
155
162
prod = intf -> in_prod ;
156
163
mb (); /* get pointers before reading ring */
157
164
158
165
if ((prod - cons ) > sizeof (intf -> in )) {
166
+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
159
167
pr_err_once ("xencons: Illegal ring page indices" );
160
168
return - EINVAL ;
161
169
}
@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
179
187
xencons -> out_cons = intf -> out_cons ;
180
188
xencons -> out_cons_same = 0 ;
181
189
}
190
+ if (!recv && xencons -> out_cons_same ++ > 1 ) {
191
+ eoiflag = XEN_EOI_FLAG_SPURIOUS ;
192
+ }
193
+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
194
+
182
195
if (recv ) {
183
196
notify_daemon (xencons );
184
- } else if (xencons -> out_cons_same ++ > 1 ) {
185
- eoiflag = XEN_EOI_FLAG_SPURIOUS ;
186
197
}
187
198
188
199
xen_irq_lateeoi (xencons -> irq , eoiflag );
@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void)
239
250
info = kzalloc (sizeof (struct xencons_info ), GFP_KERNEL );
240
251
if (!info )
241
252
return - ENOMEM ;
253
+ spin_lock_init (& info -> ring_lock );
242
254
} else if (info -> intf != NULL ) {
243
255
/* already configured */
244
256
return 0 ;
@@ -275,6 +287,7 @@ static int xen_hvm_console_init(void)
275
287
276
288
static int xencons_info_pv_init (struct xencons_info * info , int vtermno )
277
289
{
290
+ spin_lock_init (& info -> ring_lock );
278
291
info -> evtchn = xen_start_info -> console .domU .evtchn ;
279
292
/* GFN == MFN for PV guest */
280
293
info -> intf = gfn_to_virt (xen_start_info -> console .domU .mfn );
@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void)
325
338
info = kzalloc (sizeof (struct xencons_info ), GFP_KERNEL );
326
339
if (!info )
327
340
return - ENOMEM ;
341
+ spin_lock_init (& info -> ring_lock );
328
342
}
329
343
330
344
info -> irq = bind_virq_to_irq (VIRQ_CONSOLE , 0 , false);
@@ -482,6 +496,7 @@ static int xencons_probe(struct xenbus_device *dev,
482
496
info = kzalloc (sizeof (struct xencons_info ), GFP_KERNEL );
483
497
if (!info )
484
498
return - ENOMEM ;
499
+ spin_lock_init (& info -> ring_lock );
485
500
dev_set_drvdata (& dev -> dev , info );
486
501
info -> xbdev = dev ;
487
502
info -> vtermno = xenbus_devid_to_vtermno (devid );
0 commit comments