@@ -737,6 +737,8 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
register_mmio_handler(d, &vpl011_mmio_handler,
vpl011->base_addr, GUEST_PL011_SIZE, NULL);
+ d->console.input_allowed = true;
+
return 0;
out1:
@@ -238,6 +238,8 @@ void __init pv_shim_setup_dom(struct domain *d, l4_pgentry_t *l4start,
* guest from depleting the shim memory pool.
*/
d->max_pages = domain_tot_pages(d);
+
+ d->console.input_allowed = true;
}
static void write_start_info(struct domain *d)
@@ -827,6 +827,8 @@ struct domain *domain_create(domid_t domid,
old_hwdom = hardware_domain;
hardware_domain = d;
+
+ d->console.input_allowed = true;
}
TRACE_TIME(TRC_DOM0_DOM_ADD, d->domain_id);
@@ -474,11 +474,26 @@ static unsigned int __read_mostly console_rx = 0;
#define max_console_rx (max_init_domid + 1)
+static struct domain *console_get_domain_by_id(domid_t domid)
+{
+ struct domain *d = rcu_lock_domain_by_id(domid);
+
+ if ( !d )
+ return NULL;
+
+ if ( d->console.input_allowed )
+ return d;
+
+ rcu_unlock_domain(d);
+
+ return NULL;
+}
+
struct domain *console_get_domain(void)
{
if ( console_rx == 0 )
return NULL;
- return rcu_lock_domain_by_id(console_rx - 1);
+ return console_get_domain_by_id(console_rx - 1);
}
void console_put_domain(struct domain *d)
@@ -487,6 +502,15 @@ void console_put_domain(struct domain *d)
rcu_unlock_domain(d);
}
+static bool console_check_focus_by_id(domid_t domid)
+{
+ struct domain *d = console_get_domain_by_id(domid);
+
+ console_put_domain(d);
+
+ return !!d;
+}
+
static void switch_serial_input(void)
{
unsigned int next_rx = console_rx;
@@ -498,7 +522,6 @@ static void switch_serial_input(void)
for ( ; ; )
{
domid_t domid;
- struct domain *d;
if ( next_rx++ >= max_console_rx )
{
@@ -511,10 +534,9 @@ static void switch_serial_input(void)
domid = get_initial_domain_id();
else
domid = next_rx - 1;
- d = rcu_lock_domain_by_id(domid);
- if ( d )
+
+ if ( console_check_focus_by_id(domid) )
{
- rcu_unlock_domain(d);
console_rx = next_rx;
printk("*** Serial input to DOM%u", domid);
break;
@@ -564,10 +586,25 @@ static void __serial_rx(char c)
/* Deliver input to the PV shim console. */
rc = consoled_guest_tx(c);
- if ( rc )
+ switch ( rc )
+ {
+ case 0:
+ break;
+
+ case -EBUSY: /* Loopback mode */
+ case -ENOSPC: /* FIFO is full */
guest_printk(d,
XENLOG_WARNING "failed to process console input: %d\n",
rc);
+ break;
+
+ default:
+ d->console.input_allowed = false;
+ guest_printk(d,
+ XENLOG_ERR "disabled console input: %d\n",
+ rc);
+ break;
+ }
console_put_domain(d);
}
@@ -512,7 +512,7 @@ struct domain
bool auto_node_affinity;
/* Is this guest fully privileged (aka dom0)? */
bool is_privileged;
- /* Can this guest access the Xen console? */
+ /* XSM: permission to use HYPERCALL_console_io hypercall */
bool is_console;
/* Is this guest being debugged by dom0? */
bool debugger_attached;
@@ -651,6 +651,12 @@ struct domain
unsigned int num_llc_colors;
const unsigned int *llc_colors;
#endif
+
+ /* Console settings. */
+ struct {
+ /* Permission to own physical console input. */
+ bool input_allowed;
+ } console;
} __aligned(PAGE_SIZE);
static inline struct page_list_head *page_to_list(
Add new flag in domain structure for marking permission to intercept the physical console input by the domain. Update console input switch logic accordingly. Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- xen/arch/arm/vpl011.c | 2 ++ xen/arch/x86/pv/shim.c | 2 ++ xen/common/domain.c | 2 ++ xen/drivers/char/console.c | 49 +++++++++++++++++++++++++++++++++----- xen/include/xen/sched.h | 8 ++++++- 5 files changed, 56 insertions(+), 7 deletions(-)