[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v4 2/8] emul/vuart: introduce framework for UART emulators
On 31.07.2025 21:21, dmkhn@xxxxxxxxx wrote: > 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. Yet then still - why "HAS"? Call it just VUART or VUART_FRAMEWORK or some such. > --- a/xen/common/Kconfig > +++ b/xen/common/Kconfig > @@ -1,6 +1,8 @@ > > menu "Common Features" > > +source "common/emul/Kconfig" > + > config COMPAT Why at the very top? > --- 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/ With this you can ... > --- /dev/null > +++ b/xen/common/emul/vuart/Makefile > @@ -0,0 +1 @@ > +obj-$(CONFIG_HAS_VUART) += vuart.o ... use the simpler obj-y here. > --- /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++) Nit: Xen style please. Any preferably no leading underscores; in no case two of them. > +extern const struct vuart_ops *const __start_vuart_array[]; > +extern const struct vuart_ops *const __start_vuart_end[]; Is there an actual need for this extra level of indirection? It is in the process of being done away with for vPCI. > +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); Here and below - shouldn't you call hooks only when the kind of driver is actually enabled for the domkain in question? > + 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; Unconditionally? > +void vuart_deinit(struct domain *d) > +{ > + const struct vuart_ops *vdev; > + > + for_each_vuart(vdev) > + vdev->deinit(d); > +} I can perhaps see why this hook wants to uniformly be set, but ... > +void vuart_dump_state(const struct domain *d) > +{ > + const struct vuart_ops *vdev; > + > + for_each_vuart(vdev) > + vdev->dump_state(d); > +} ... state dumping pretty surely wants to be optional? > +/* > + * Put character to the first suitable emulated UART's FIFO. > + */ What's "suitable"? Along the lines of the earlier remark, what if the domain has vUART kind A configured, ... > +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 ) ... but only kind B offers this hook? > + break; > + > + return vdev ? vdev->put_rx(d, c) : -ENODEV; The check for NULL helps for the "no vUART drivers" case, but it won't help if you exhausted the array without finding a driver with the wanted hook. > +} > + > +bool domain_has_vuart(const struct domain *d) > +{ > + uint32_t mask = 0; unsigned int? > --- 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); How verbose is this going to get? > --- /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> The order is wrong - types must be available before public headers are included. > +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; > +} With this, some of the other stubs should not be necessary. Declarations will suffice, e.g. for vuart_put_rx(). > --- 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.*)) \ This is r/o data afaict, so would want naming .rodata.vuart.*. Which in turn means the uses of the macros need to move up in the linker scripts. Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |