[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 2/8] emul/vuart: introduce framework for UART emulators
From: Denis Mukhin <dmukhin@xxxxxxxx> Introduce a driver framework to abstract UART emulators in the hypervisor. That allows for architecture-independent handling of virtual UARTs in the console driver and simplifies enabling new UART emulators. The framework is built under CONFIG_HAS_VUART, which will be automatically enabled once the user enables any UART emulator. Current implementation supports maximum of one vUART of each kind per domain. Use new domain_has_vuart() in the console driver code to check whether to forward console input to the domain using vUART. Note: existing vUARTs are deliberately *not* hooked to the new framework to minimize the scope of the patch: vpl011 (i.e. SBSA) emulator and "vuart" (i.e. minimalistic MMIO-mapped dtuart for hwdoms on Arm) are kept unmodified. Signed-off-by: Denis Mukhin <dmukhin@xxxxxxxx> --- Changes since v3: - new patch - original patch from ML: https://lore.kernel.org/xen-devel/20250624035443.344099-16-dmukhin@xxxxxxxx/ --- xen/arch/arm/xen.lds.S | 1 + xen/arch/ppc/xen.lds.S | 1 + xen/arch/riscv/xen.lds.S | 1 + xen/arch/x86/xen.lds.S | 1 + xen/common/Kconfig | 2 + xen/common/Makefile | 1 + xen/common/emul/Kconfig | 6 ++ xen/common/emul/Makefile | 1 + xen/common/emul/vuart/Kconfig | 6 ++ xen/common/emul/vuart/Makefile | 1 + xen/common/emul/vuart/vuart.c | 112 +++++++++++++++++++++++++++++++++ xen/common/keyhandler.c | 3 + xen/drivers/char/console.c | 4 ++ xen/include/xen/vuart.h | 84 +++++++++++++++++++++++++ xen/include/xen/xen.lds.h | 10 +++ 15 files changed, 234 insertions(+) create mode 100644 xen/common/emul/Kconfig create mode 100644 xen/common/emul/Makefile create mode 100644 xen/common/emul/vuart/Kconfig create mode 100644 xen/common/emul/vuart/Makefile create mode 100644 xen/common/emul/vuart/vuart.c create mode 100644 xen/include/xen/vuart.h diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index 9f30c3a13ed1..bdba7eaa4f65 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -58,6 +58,7 @@ SECTIONS *(.rodata) *(.rodata.*) VPCI_ARRAY + VUART_ARRAY *(.data.rel.ro) *(.data.rel.ro.*) diff --git a/xen/arch/ppc/xen.lds.S b/xen/arch/ppc/xen.lds.S index 1de0b77fc6b9..f9d4e5b0dcd8 100644 --- a/xen/arch/ppc/xen.lds.S +++ b/xen/arch/ppc/xen.lds.S @@ -52,6 +52,7 @@ SECTIONS *(.rodata) *(.rodata.*) VPCI_ARRAY + VUART_ARRAY *(.data.rel.ro) *(.data.rel.ro.*) diff --git a/xen/arch/riscv/xen.lds.S b/xen/arch/riscv/xen.lds.S index edcadff90bfe..59dcaa5fef9a 100644 --- a/xen/arch/riscv/xen.lds.S +++ b/xen/arch/riscv/xen.lds.S @@ -47,6 +47,7 @@ SECTIONS *(.rodata) *(.rodata.*) VPCI_ARRAY + VUART_ARRAY *(.data.rel.ro) *(.data.rel.ro.*) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index 8e9cac75b09e..43426df33092 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -136,6 +136,7 @@ SECTIONS *(.rodata) *(.rodata.*) VPCI_ARRAY + VUART_ARRAY *(.data.rel.ro) *(.data.rel.ro.*) diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 16936418a6e6..4e0bd524dc43 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -1,6 +1,8 @@ menu "Common Features" +source "common/emul/Kconfig" + config COMPAT bool help diff --git a/xen/common/Makefile b/xen/common/Makefile index c316957fcb36..c0734480ee4b 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -11,6 +11,7 @@ obj-$(filter-out $(CONFIG_X86),$(CONFIG_ACPI)) += device.o obj-$(CONFIG_DEVICE_TREE_PARSE) += device-tree/ obj-$(CONFIG_IOREQ_SERVER) += dm.o obj-y += domain.o +obj-y += emul/ obj-y += event_2l.o obj-y += event_channel.o obj-$(CONFIG_EVTCHN_FIFO) += event_fifo.o diff --git a/xen/common/emul/Kconfig b/xen/common/emul/Kconfig new file mode 100644 index 000000000000..7c6764d1756b --- /dev/null +++ b/xen/common/emul/Kconfig @@ -0,0 +1,6 @@ +menu "Domain Emulation Features" + visible if EXPERT + +source "common/emul/vuart/Kconfig" + +endmenu diff --git a/xen/common/emul/Makefile b/xen/common/emul/Makefile new file mode 100644 index 000000000000..670682102c13 --- /dev/null +++ b/xen/common/emul/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_HAS_VUART) += vuart/ diff --git a/xen/common/emul/vuart/Kconfig b/xen/common/emul/vuart/Kconfig new file mode 100644 index 000000000000..02f7dd6dc1a1 --- /dev/null +++ b/xen/common/emul/vuart/Kconfig @@ -0,0 +1,6 @@ +config HAS_VUART + bool + +menu "UART Emulation" + +endmenu diff --git a/xen/common/emul/vuart/Makefile b/xen/common/emul/vuart/Makefile new file mode 100644 index 000000000000..c6400b001e85 --- /dev/null +++ b/xen/common/emul/vuart/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_HAS_VUART) += vuart.o diff --git a/xen/common/emul/vuart/vuart.c b/xen/common/emul/vuart/vuart.c new file mode 100644 index 000000000000..14a7f8bd8b79 --- /dev/null +++ b/xen/common/emul/vuart/vuart.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * UART emulator framework. + * + * Copyright 2025 Ford Motor Company + */ + +#include <xen/errno.h> +#include <xen/sched.h> +#include <xen/vuart.h> + +#define VUART_ARRAY_SIZE (__start_vuart_end - __start_vuart_array) + +#define for_each_vuart(vdev) \ + for (unsigned __i = 0; \ + __i < VUART_ARRAY_SIZE && (vdev = __start_vuart_array[__i], 1); \ + __i++) + +extern const struct vuart_ops *const __start_vuart_array[]; +extern const struct vuart_ops *const __start_vuart_end[]; + +int vuart_add_node(struct domain *d, const void *node) +{ + const struct vuart_ops *vdev; + int rc; + + for_each_vuart(vdev) + { + if ( !vdev->add_node ) + continue; + + rc = vdev->add_node(d, node); + if ( rc ) + return rc; + } + + return 0; +} + +int vuart_init(struct domain *d, struct vuart_params *params) +{ + const struct vuart_ops *vdev; + int rc; + + if ( !domain_has_vuart(d) ) + return 0; + + for_each_vuart(vdev) + { + rc = vdev->init(d, params); + if ( rc ) + return rc; + } + + d->console.input_allowed = true; + + return 0; +} + +/* + * Release any resources taken by UART emulators. + * + * NB: no flags are cleared, since currently exit() is called only during + * domain destroy. + */ +void vuart_deinit(struct domain *d) +{ + const struct vuart_ops *vdev; + + for_each_vuart(vdev) + vdev->deinit(d); +} + +void vuart_dump_state(const struct domain *d) +{ + const struct vuart_ops *vdev; + + for_each_vuart(vdev) + vdev->dump_state(d); +} + +/* + * Put character to the first suitable emulated UART's FIFO. + */ +int vuart_put_rx(struct domain *d, char c) +{ + const struct vuart_ops *vdev = NULL; + + ASSERT(domain_has_vuart(d)); + + for_each_vuart(vdev) + if ( vdev->put_rx ) + break; + + return vdev ? vdev->put_rx(d, c) : -ENODEV; +} + +bool domain_has_vuart(const struct domain *d) +{ + uint32_t mask = 0; + + return !!(d->emulation_flags & mask); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index eccd97c565c6..af427d25dc0d 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -22,6 +22,7 @@ #include <xen/mm.h> #include <xen/watchdog.h> #include <xen/init.h> +#include <xen/vuart.h> #include <asm/div64.h> static unsigned char keypress_key; @@ -354,6 +355,8 @@ static void cf_check dump_domains(unsigned char key) v->periodic_period / 1000000); } } + + vuart_dump_state(d); } for_each_domain ( d ) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 963c7b043cd8..93254979817b 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -33,6 +33,7 @@ #include <asm/setup.h> #include <xen/sections.h> #include <xen/consoled.h> +#include <xen/vuart.h> #ifdef CONFIG_X86 #include <asm/guest.h> @@ -601,6 +602,7 @@ static void __serial_rx(char c) /* * Deliver input to the hardware domain buffer, unless it is * already full. + * NB: must be the first check: hardware domain may have emulated UART. */ if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE ) serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c; @@ -611,6 +613,8 @@ static void __serial_rx(char c) */ send_global_virq(VIRQ_CONSOLE); } + else if ( domain_has_vuart(d) ) + rc = vuart_put_rx(d, c); #ifdef CONFIG_SBSA_VUART_CONSOLE else /* Deliver input to the emulated UART. */ diff --git a/xen/include/xen/vuart.h b/xen/include/xen/vuart.h new file mode 100644 index 000000000000..e843026df4b1 --- /dev/null +++ b/xen/include/xen/vuart.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * UART emulator framework. + * + * Copyright 2025 Ford Motor Company + */ + +#ifndef XEN_VUART_H +#define XEN_VUART_H + +#include <public/xen.h> +#include <public/event_channel.h> +#include <xen/types.h> + +struct vuart_params { + domid_t console_domid; + gfn_t gfn; + evtchn_port_t evtchn; +}; + +struct vuart_ops { + int (*add_node)(struct domain *d, const void *node); + int (*init)(struct domain *d, struct vuart_params *params); + void (*deinit)(struct domain *d); + void (*dump_state)(const struct domain *d); + int (*put_rx)(struct domain *d, char c); +}; + +#define VUART_REGISTER(name, x) \ + static const struct vuart_ops *const __name##_entry \ + __used_section(".data.vuart." #name) = (x); + +#ifdef CONFIG_HAS_VUART + +int vuart_add_node(struct domain *d, const void *node); +int vuart_init(struct domain *d, struct vuart_params *params); +void vuart_deinit(struct domain *d); +void vuart_dump_state(const struct domain *d); +int vuart_put_rx(struct domain *d, char c); +bool domain_has_vuart(const struct domain *d); + +#else + +static inline int vuart_add_node(struct domain *d, const void *node) +{ + return 0; +} + +static inline int vuart_init(struct domain *d, struct vuart_params *params) +{ + return 0; +} + +static inline void vuart_deinit(struct domain *d) +{ +} + +static inline void vuart_dump_state(const struct domain *d) +{ +} + +static inline int vuart_put_rx(struct domain *d, char c) +{ + ASSERT_UNREACHABLE(); + return -ENODEV; +} + +static inline bool domain_has_vuart(const struct domain *d) +{ + return false; +} + +#endif /* CONFIG_HAS_VUART */ + +#endif /* XEN_VUART_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/xen/xen.lds.h b/xen/include/xen/xen.lds.h index b126dfe88792..c2da180948ca 100644 --- a/xen/include/xen/xen.lds.h +++ b/xen/include/xen/xen.lds.h @@ -194,4 +194,14 @@ #define VPCI_ARRAY #endif +#ifdef CONFIG_HAS_VUART +#define VUART_ARRAY \ + . = ALIGN(POINTER_ALIGN); \ + __start_vuart_array = .; \ + *(SORT(.data.vuart.*)) \ + __start_vuart_end = .; +#else +#define VUART_ARRAY +#endif + #endif /* __XEN_LDS_H__ */ -- 2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |