@@ -43,6 +43,7 @@ struct xencons_info {
4343 int irq ;
4444 int vtermno ;
4545 grant_ref_t gntref ;
46+ spinlock_t ring_lock ;
4647};
4748
4849static LIST_HEAD (xenconsoles );
@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons,
8990 XENCONS_RING_IDX cons , prod ;
9091 struct xencons_interface * intf = xencons -> intf ;
9192 int sent = 0 ;
93+ unsigned long flags ;
9294
95+ spin_lock_irqsave (& xencons -> ring_lock , flags );
9396 cons = intf -> out_cons ;
9497 prod = intf -> out_prod ;
9598 mb (); /* update queue values before going on */
9699
97100 if ((prod - cons ) > sizeof (intf -> out )) {
101+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
98102 pr_err_once ("xencons: Illegal ring page indices" );
99103 return - EINVAL ;
100104 }
@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons,
104108
105109 wmb (); /* write ring before updating pointer */
106110 intf -> out_prod = prod ;
111+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
107112
108113 if (sent )
109114 notify_daemon (xencons );
@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
146151 int recv = 0 ;
147152 struct xencons_info * xencons = vtermno_to_xencons (vtermno );
148153 unsigned int eoiflag = 0 ;
154+ unsigned long flags ;
149155
150156 if (xencons == NULL )
151157 return - EINVAL ;
152158 intf = xencons -> intf ;
153159
160+ spin_lock_irqsave (& xencons -> ring_lock , flags );
154161 cons = intf -> in_cons ;
155162 prod = intf -> in_prod ;
156163 mb (); /* get pointers before reading ring */
157164
158165 if ((prod - cons ) > sizeof (intf -> in )) {
166+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
159167 pr_err_once ("xencons: Illegal ring page indices" );
160168 return - EINVAL ;
161169 }
@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
179187 xencons -> out_cons = intf -> out_cons ;
180188 xencons -> out_cons_same = 0 ;
181189 }
190+ if (!recv && xencons -> out_cons_same ++ > 1 ) {
191+ eoiflag = XEN_EOI_FLAG_SPURIOUS ;
192+ }
193+ spin_unlock_irqrestore (& xencons -> ring_lock , flags );
194+
182195 if (recv ) {
183196 notify_daemon (xencons );
184- } else if (xencons -> out_cons_same ++ > 1 ) {
185- eoiflag = XEN_EOI_FLAG_SPURIOUS ;
186197 }
187198
188199 xen_irq_lateeoi (xencons -> irq , eoiflag );
@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void)
239250 info = kzalloc (sizeof (struct xencons_info ), GFP_KERNEL );
240251 if (!info )
241252 return - ENOMEM ;
253+ spin_lock_init (& info -> ring_lock );
242254 } else if (info -> intf != NULL ) {
243255 /* already configured */
244256 return 0 ;
@@ -275,6 +287,7 @@ static int xen_hvm_console_init(void)
275287
276288static int xencons_info_pv_init (struct xencons_info * info , int vtermno )
277289{
290+ spin_lock_init (& info -> ring_lock );
278291 info -> evtchn = xen_start_info -> console .domU .evtchn ;
279292 /* GFN == MFN for PV guest */
280293 info -> intf = gfn_to_virt (xen_start_info -> console .domU .mfn );
@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void)
325338 info = kzalloc (sizeof (struct xencons_info ), GFP_KERNEL );
326339 if (!info )
327340 return - ENOMEM ;
341+ spin_lock_init (& info -> ring_lock );
328342 }
329343
330344 info -> irq = bind_virq_to_irq (VIRQ_CONSOLE , 0 , false);
@@ -482,6 +496,7 @@ static int xencons_probe(struct xenbus_device *dev,
482496 info = kzalloc (sizeof (struct xencons_info ), GFP_KERNEL );
483497 if (!info )
484498 return - ENOMEM ;
499+ spin_lock_init (& info -> ring_lock );
485500 dev_set_drvdata (& dev -> dev , info );
486501 info -> xbdev = dev ;
487502 info -> vtermno = xenbus_devid_to_vtermno (devid );
0 commit comments