diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index acfc49d558..5c621b39bd 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -521,6 +521,8 @@ struct domain *console_get_domain(void) { struct domain *d; + nrspin_lock_irq(&console_lock); + if ( console_rx == 0 ) return NULL; @@ -540,6 +542,8 @@ void console_put_domain(struct domain *d) { if ( d ) rcu_unlock_domain(d); + + nrspin_unlock_irq(&console_lock); } static void console_switch_input(void) @@ -598,11 +602,10 @@ static void __serial_rx(char c) if ( console_rx == 0 ) return handle_keypress(c, false); - nrspin_lock_irq(&console_lock); d = console_get_domain(); if ( !d ) { - nrspin_unlock_irq(&console_lock); + console_put_domain(d); return; } @@ -640,7 +643,6 @@ static void __serial_rx(char c) rc); console_put_domain(d); - nrspin_unlock_irq(&console_lock); } static void cf_check serial_rx(char c) @@ -754,7 +756,6 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, if ( copy_from_guest(kbuf, buffer, kcount) ) return -EFAULT; - nrspin_lock_irq(&console_lock); input = console_get_domain(); if ( input && cd == input ) { @@ -766,14 +767,12 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, /* Use direct console output as it could be interactive */ console_send(kbuf, kcount, flags); console_put_domain(input); - nrspin_unlock_irq(&console_lock); } else { char *kin = kbuf, *kout = kbuf, c; console_put_domain(input); - nrspin_unlock_irq(&console_lock); /* Strip non-printable characters */ do { @@ -836,12 +835,10 @@ long do_console_io( if ( count > INT_MAX ) break; - nrspin_lock_irq(&console_lock); d = console_get_domain(); if ( d != current->domain ) { console_put_domain(d); - nrspin_unlock_irq(&console_lock); return 0; } @@ -854,18 +851,23 @@ long do_console_io( len = SERIAL_RX_SIZE - idx; if ( (rc + len) > count ) len = count - rc; + + console_put_domain(d); if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) ) { rc = -EFAULT; + break; + } + d = console_get_domain(); + if ( d != current->domain ) + { console_put_domain(d); - nrspin_unlock_irq(&console_lock); break; } rc += len; serial_rx_cons += len; } console_put_domain(d); - nrspin_unlock_irq(&console_lock); break; default: rc = -ENOSYS;