From: Denis Mukhin <dmuk...@ford.com> The physical console input rotation depends on max_init_domid symbol, which is managed differently across architectures.
Instead of trying to manage max_init_domid in the arch-common code the console input rotation code can be reworked by removing dependency on max_init_domid entirely. To do that, introduce domid_find_with_input_allowed() in arch-independent location to find the ID of the next possible console owner domain. The IDs are rotated across non-system domain IDs and DOMID_XEN. Also, introduce helper console_set_domid() for updating identifier of the current console input owner (points to Xen or domain). Use domid_find_with_input_allowed() and console_set_domid() in console_switch_input(). Remove uses of max_init_domid in the code. Signed-off-by: Denis Mukhin <dmuk...@ford.com> --- Changes since v2: - reworked to traversing domain list directly - Link to v2: https://lore.kernel.org/xen-devel/20250331230508.440198-7-dmuk...@ford.com/ --- xen/arch/arm/include/asm/setup.h | 2 - xen/arch/arm/setup.c | 2 - xen/arch/ppc/include/asm/setup.h | 2 - xen/arch/riscv/include/asm/setup.h | 2 - xen/arch/x86/include/asm/setup.h | 2 - xen/common/device-tree/dom0less-build.c | 2 - xen/common/domain.c | 29 +++++++ xen/drivers/char/console.c | 102 +++++++++--------------- xen/include/xen/domain.h | 1 + 9 files changed, 66 insertions(+), 78 deletions(-) diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h index 6cf272c160..f107e8eebb 100644 --- a/xen/arch/arm/include/asm/setup.h +++ b/xen/arch/arm/include/asm/setup.h @@ -25,8 +25,6 @@ struct map_range_data struct rangeset *irq_ranges; }; -extern domid_t max_init_domid; - void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len); size_t estimate_efi_size(unsigned int mem_nr_banks); diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 10b46d0684..53e2f8b537 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -61,8 +61,6 @@ struct cpuinfo_arm __read_mostly system_cpuinfo; bool __read_mostly acpi_disabled; #endif -domid_t __read_mostly max_init_domid; - static __used void init_done(void) { int rc; diff --git a/xen/arch/ppc/include/asm/setup.h b/xen/arch/ppc/include/asm/setup.h index e4f64879b6..956fa6985a 100644 --- a/xen/arch/ppc/include/asm/setup.h +++ b/xen/arch/ppc/include/asm/setup.h @@ -1,6 +1,4 @@ #ifndef __ASM_PPC_SETUP_H__ #define __ASM_PPC_SETUP_H__ -#define max_init_domid (0) - #endif /* __ASM_PPC_SETUP_H__ */ diff --git a/xen/arch/riscv/include/asm/setup.h b/xen/arch/riscv/include/asm/setup.h index c9d69cdf51..d1fc64b673 100644 --- a/xen/arch/riscv/include/asm/setup.h +++ b/xen/arch/riscv/include/asm/setup.h @@ -5,8 +5,6 @@ #include <xen/types.h> -#define max_init_domid (0) - void setup_mm(void); void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len); diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h index ac34c69855..b67de8577f 100644 --- a/xen/arch/x86/include/asm/setup.h +++ b/xen/arch/x86/include/asm/setup.h @@ -69,6 +69,4 @@ extern bool opt_dom0_verbose; extern bool opt_dom0_cpuid_faulting; extern bool opt_dom0_msr_relaxed; -#define max_init_domid (0) - #endif diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c index 8e38affd0c..4c050b9ded 100644 --- a/xen/common/device-tree/dom0less-build.c +++ b/xen/common/device-tree/dom0less-build.c @@ -977,8 +977,6 @@ void __init create_domUs(void) domid = domid_alloc(DOMID_INVALID); if ( domid == DOMID_INVALID ) panic("Error allocating ID for domain %s\n", dt_node_name(node)); - if ( max_init_domid < domid ) - max_init_domid = domid; d = domain_create(domid, &d_cfg, flags); if ( IS_ERR(d) ) diff --git a/xen/common/domain.c b/xen/common/domain.c index 6a6cdd991b..90bd42b633 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -2460,6 +2460,35 @@ void domid_free(domid_t domid) spin_unlock(&domid_lock); } +/* + * Find the ID of the next possible console owner domain. + * + * @return Domain ID: DOMID_XEN or non-system domain IDs within + * the range of [0..CONFIG_MAX_DOMID-1]. + */ +domid_t domid_find_with_input_allowed(domid_t hint) +{ + struct domain *d; + domid_t domid = DOMID_XEN; + + spin_lock(&domlist_update_lock); + + for ( d = domid_to_domain(hint); + d && likely(get_domain(d)) && (d->domain_id < CONFIG_MAX_DOMID); + d = d->next_in_list ) + { + if ( d->console.input_allowed ) + { + domid = d->domain_id; + break; + } + } + + spin_unlock(&domlist_update_lock); + + return domid; +} + /* * Local variables: * mode: C diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index ccecda6523..ff20706ac9 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -462,26 +462,17 @@ static void cf_check dump_console_ring_key(unsigned char key) /* * CTRL-<switch_char> changes input direction, rotating among Xen, Dom0, - * and the DomUs started from Xen at boot. + * and the DomUs. */ #define switch_code (opt_conswitch[0]-'a'+1) -/* - * console_rx=0 => input to xen - * console_rx=1 => input to dom0 (or the sole shim domain) - * console_rx=N => input to dom(N-1) - */ -static unsigned int __read_mostly console_rx = 0; -#define max_console_rx (max_init_domid + 1) +/* Console owner domain identifier. */ +static domid_t __read_mostly console_rx = DOMID_XEN; static struct domain *console_get_domain(void) { - struct domain *d; + struct domain *d = rcu_lock_domain_by_id(console_rx); - if ( console_rx == 0 ) - return NULL; - - d = rcu_lock_domain_by_id(console_rx - 1); if ( !d ) return NULL; @@ -499,50 +490,14 @@ static void console_put_domain(struct domain *d) rcu_unlock_domain(d); } -domid_t console_get_domid(void) +static void console_set_domid(domid_t domid) { - if ( console_rx == 0 ) - return DOMID_XEN; - return console_rx - 1; -} + if ( domid == DOMID_XEN ) + printk("*** Serial input to Xen"); + else + printk("*** Serial input to DOM%u", domid); -static void console_switch_input(void) -{ - unsigned int next_rx = console_rx; - - /* - * Rotate among Xen, dom0 and boot-time created domUs while skipping - * switching serial input to non existing domains. - */ - for ( ; ; ) - { - domid_t domid; - struct domain *d; - - if ( next_rx++ >= max_console_rx ) - { - console_rx = 0; - printk("*** Serial input to Xen"); - break; - } - - if ( consoled_is_enabled() && next_rx == 1 ) - domid = get_initial_domain_id(); - else - domid = next_rx - 1; - d = rcu_lock_domain_by_id(domid); - if ( d ) - { - rcu_unlock_domain(d); - - if ( !d->console.input_allowed ) - break; - - console_rx = next_rx; - printk("*** Serial input to DOM%u", domid); - break; - } - } + console_rx = domid; if ( switch_code ) printk(" (type 'CTRL-%c' three times to switch input)", @@ -550,12 +505,35 @@ static void console_switch_input(void) printk("\n"); } +domid_t console_get_domid(void) +{ + return console_rx; +} + +/* + * Switch console focus. + * Rotates input focus among Xen and domains with console input permission. + */ +static void console_switch_input(void) +{ + domid_t hint; + + if ( console_rx == DOMID_XEN ) + hint = get_initial_domain_id(); + else + hint = console_rx + 1; + + hint = domid_find_with_input_allowed(hint); + + console_set_domid(hint); +} + static void __serial_rx(char c) { struct domain *d; int rc = 0; - if ( console_rx == 0 ) + if ( console_rx == DOMID_XEN ) return handle_keypress(c, false); d = console_get_domain(); @@ -1130,14 +1108,6 @@ void __init console_endboot(void) video_endboot(); - /* - * If user specifies so, we fool the switch routine to redirect input - * straight back to Xen. I use this convoluted method so we still print - * a useful 'how to switch' message. - */ - if ( opt_conswitch[1] == 'x' ) - console_rx = max_console_rx; - register_keyhandler('w', dump_console_ring_key, "synchronously dump console ring buffer (dmesg)", 0); register_irq_keyhandler('+', &do_inc_thresh, @@ -1147,8 +1117,8 @@ void __init console_endboot(void) register_irq_keyhandler('G', &do_toggle_guest, "toggle host/guest log level adjustment", 0); - /* Serial input is directed to DOM0 by default. */ - console_switch_input(); + if ( opt_conswitch[1] != 'x' ) + (void)console_set_domid(get_initial_domain_id()); } int __init console_has(const char *device) diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 8aab05ae93..a88eb34f3f 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -36,6 +36,7 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info); void arch_get_domain_info(const struct domain *d, struct xen_domctl_getdomaininfo *info); +domid_t domid_find_with_input_allowed(domid_t hint); domid_t get_initial_domain_id(void); domid_t domid_alloc(domid_t domid); -- 2.34.1