[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM



On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> OOI, on the previous version you said you will explore the CTRL-x N solution
> (where N is the domID console to switch too). What was the result here?

I meant I'll explore it as a follow-up to this series. I haven't looked
into it yet, but it is in my todo.


> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> > mechanism to allow for switching between Xen, Dom0, and any of the
> > initial DomU created from Xen alongside Dom0 out of information provided
> > via device tree.
> > 
> > Rename xen_rx to console_rx to match the new behavior.
> > 
> > Clarify existing comment about "notify the guest", making it clear that
> > it is only about the hardware domain.
> > 
> > Export a function named console_input_domain() to allow others to know
> > which domains has input at a given time.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xxxxxxxxxx>
> > CC: andrew.cooper3@xxxxxxxxxx
> > CC: George.Dunlap@xxxxxxxxxxxxx
> > CC: ian.jackson@xxxxxxxxxxxxx
> > CC: jbeulich@xxxxxxxx
> > CC: konrad.wilk@xxxxxxxxxx
> > CC: tim@xxxxxxx
> > CC: wei.liu2@xxxxxxxxxx
> > ---
> > Changes in v3:
> > - only call vpl011 functions ifdef CONFIG_SBSA_VUART_CONSOLE
> > - add blank line and spaces
> > - remove xen_rx from print messages
> > - rename xen_rx to console_rx
> > - keep switch_serial_input() at boot
> > - add better comments
> > - fix existing comment
> > - add warning if no guests console/uart is available
> > - add console_input_domain function
> > 
> > Changes in v2:
> > - only call vpl011_rx_char if the vpl011 has been initialized
> > ---
> >   xen/drivers/char/console.c | 71
> > +++++++++++++++++++++++++++++++++++++---------
> >   xen/include/xen/console.h  |  2 ++
> >   2 files changed, 60 insertions(+), 13 deletions(-)
> > 
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 0f05369..cd4dfb1 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -31,10 +31,13 @@
> >   #include <xen/early_printk.h>
> >   #include <xen/warning.h>
> >   #include <xen/pv_console.h>
> > +#include <asm/setup.h>
> >     #ifdef CONFIG_X86
> >   #include <xen/consoled.h>
> >   #include <asm/guest.h>
> > +#else
> > +#include <asm/vpl011.h>
> >   #endif
> >     /* console: comma-separated list of console outputs. */
> > @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
> >       free_xenheap_pages(buf, order);
> >   }
> >   -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> > +/*
> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> > + * DomUs.
> > + */
> >   #define switch_code (opt_conswitch[0]-'a'+1)
> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0.
> > */
> > +/*
> > + * console_rx=0 => input to xen
> > + * console_rx=1 => input to dom0
> > + * console_rx=N => input dom(N-1)
> > + */
> > +static int __read_mostly console_rx = 0;
> > +
> > +struct domain *console_input_domain(void)
> > +{
> > +    return get_domain_by_id(console_rx - 1);
> 
> Please take care of the case where console_rx == 0.

I'll do


> > +}
> >     static void switch_serial_input(void)
> >   {
> > -    static char *input_str[2] = { "DOM0", "Xen" };
> > -    xen_rx = !xen_rx;
> > -    printk("*** Serial input -> %s", input_str[xen_rx]);
> > +    console_rx++;
> > +    if ( console_rx == max_init_domid + 2 )
> > +        console_rx = 0;
> > +
> > +    if ( !console_rx )
> > +        printk("*** Serial input to Xen");
> > +    else
> > +        printk("*** Serial input to DOM%d", console_rx - 1);
> > +
> >       if ( switch_code )
> > -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> > -               opt_conswitch[0], input_str[!xen_rx]);
> > +        printk(" (type 'CTRL-%c' three times to switch input)",
> > +               opt_conswitch[0]);
> >       printk("\n");
> >   }
> >     static void __serial_rx(char c, struct cpu_user_regs *regs)
> >   {
> > -    if ( xen_rx )
> > +    if ( console_rx == 0 )
> >           return handle_keypress(c, regs);
> >   -    /* Deliver input to guest buffer, unless it is already full. */
> > -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > -    /* Always notify the guest: prevents receive path from getting stuck.
> > */
> > +    if ( console_rx == 1 )
> > +    {
> > +        /* Deliver input to guest buffer, unless it is already full. */
> > +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    }
> > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +    else
> > +    {
> > +        struct domain *d = get_domain_by_id(console_rx - 1);
> 
> I don't think this is correct to assume the domain will always be present.
> With this series, it would be possible to retire a domain and therefore
> get_domain_by_id() would return NULL here. This would result to a data abort
> below.

Well, spotted! I'll fix.


> Also, I think you want to use rcu_lock_by_domain here (I am not 100% sure
> though).

Uhm... I think you are right


> > +
> > +        /*
> > +         * If we have a properly initialized vpl011 console for the
> > +         * domain, without a full PV ring to Dom0 (in that case input
> > +         * comes from the PV ring), then send the character to it.
> > +         */
> > +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen !=
> > NULL )
> > +            vpl011_rx_char_xen(d, c);
> > +        else
> > +            printk("Cannot send chars to Dom%d: no UART available\n",
> > +                   d->domain_id);
> > +    }
> > +#endif
> > +    /*
> > +     * Always notify the hardware domain: prevents receive path from
> 
> That's not true. If you look at send_global_virq, it will send to the domain
> that register the VIRQ. That may be the hardware domain but could be someone
> else.

The comment and the code are from the existing code, they have only been
moved by this patch. I changed it from "Always notify the guest" to
"Always notify the hardware domain" for clarity. Would you like me to
improve the comment since I am at it? I am happy to include a specific
line, if you prefer.


> However, I still don't understand how this work in presence of multiple
> backend here. Why would you notify Domain B everytime a character is
> redirected to domain A/C/D the console?

You are right, I'll fix that



> > +     * getting stuck.
> > +     */
> >       send_global_virq(VIRQ_CONSOLE);
> >     #ifdef CONFIG_X86
> > @@ -923,7 +968,7 @@ void __init console_endboot(void)
> >        * a useful 'how to switch' message.
> >        */
> >       if ( opt_conswitch[1] == 'x' )
> > -        xen_rx = !xen_rx;
> > +        console_rx = 0;
> >         register_keyhandler('w', dump_console_ring_key,
> >                           "synchronously dump console ring buffer (dmesg)",
> > 0);
> > diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> > index ea06fd8..2fe3912 100644
> > --- a/xen/include/xen/console.h
> > +++ b/xen/include/xen/console.h
> > @@ -31,6 +31,8 @@ void console_end_sync(void);
> >   void console_start_log_everything(void);
> >   void console_end_log_everything(void);
> >   +struct domain *console_input_domain(void);
> > +
> >   /*
> >    * Steal output from the console. Returns +ve identifier, else -ve error.
> >    * Takes the handle of the serial line to steal, and steal callback
> > function.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.