* [PATCH v2 00/35] Introduce NS8250 UART emulator
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin, Oleksii Kurochko
The patch series introduces initial in-hypervisor emulator for
NS8250/NS16x50-compatible UARTs under CONFIG_HAS_VUART_NS8250.
In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
early guest OS bringup debugging, because it eliminates dependency on the
external emulator being operational by the time domains are created. Also,
there's no early console facility similar to vpl011 to support x86 guest OS
bring up.
The NS8250 emulator is disabled by default.
Series
======
- patches 1-11: preparation fixes for xen console and NS8250 emulator.
- patches 12-27: xen console driver cleanup, fixes and preparation for enabling
physical serial console focus assignment to the guest VM w/ virtual NS8250.
- patches 28-35: initial NS8250 emulator. That adds the I/O port emulator
for legacy PC COM UARTs, Kconfig option, enabling emulator and libxl
plumbing.
Limitations
===========
- Only x86;
- Only Linux guest tested so far;
- Only legacy COM{1,2,3,4} resources, no customization;
- Only Xen console as a backend, no inter-domain communication (similar to
vpl011 on Arm);
- Only 8-bit characters;
- Baud rate is not emulated;
- FIFO-less mode is not emulated properly;
- RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
has special FCR handling;
- No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
friends);
- Assumes no ISA-device IRQ sharing;
- MMIO-based UART is not supported.
Testing
=======
Gitlab CI:
https://gitlab.com/xen-project/people/dmukhin/xen/-/pipelines/1576164352
I tested boot of HVM linux guest w/ OVMF as the virtual firmware.
The emulator, if enabled via CONFIG_HAS_VUART_NS8250=y, will use COM1 (0x3f8)
resources by default.
To test w/ virtual COM1, the guest kernel parameters should contain
earlycon=uart,io,0x3f8,115200n8 console=uart,io,0x3f8,115200n8
Xen is able to forward physical console input to the domain w/ virtual NS8250.
To switch the console focus press Ctrl+aaa. If console= is given to the HVM
kernel, then the user shall be able to see the login prompt on xen console once
console focus is switched to the HVM guest.
Luca Fancellu helped big time w/ verifying the patch series on arm{32,64} w/
FVP Linux as a guest OS.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
Changes in v2:
- dropped kmalloc/kfree aliases
- fixed ECLAIR jobs (thanks Andrew Cooper)
- addressed console forwarding on arm32 and arm64 (thanks to Luca Fancellu)
- moved NS8250 debugging stubs into its own patch
- added fix for https://gitlab.com/xen-project/xen/-/issues/184
- Link to v1: https://lore.kernel.org/r/20241126-vuart-ns8250-v1-v1-0-87b9a8375b7a@ford.com
---
Denis Mukhin (35):
xen: introduce resource.h
xen/irq: introduce NO_IRQ
xen/ctype: introduce isconsole()
arm/vuart: use guest_printk()
arm/vuart: make domain_has_vuart() public
riscv/domain: introduce domain_has_vuart()
ppc/domain: introduce domain_has_vuart()
x86/domain: introduce domain_has_vuart()
x86/domain: print emulation_flags
xen/domain: add get_initial_domain_id()
xen/domain: enable max_init_domid for all architectures
xen/console: move vpl011-related code to vpl011 emulator
xen/console: rename console_input_domain
xen/console: rename switch_serial_input() to console_find_owner()
xen/console: rename console_rx to console_owner
xen/console: introduce printk_common()
xen/console: introduce consoled_is_enabled()
xen/console: introduce use of 'is_console' flag
xen/console: introduce console_set_owner()
xen/console: introduce console_owner_domid()
xen/console: introduce console_init_owner()
xen/console: introduce handle_keypress_in_domain()
xen/console: introduce console_write()
xen/console: introduce hwdom_crashconsole=
xen/console: simplify console owner switch hint
xen/console: make console buffer size configurable
xen/console: flush console ring to physical console
xen/8250-uart: add missing definitions
x86/hvm: add HVM-specific Kconfig
x86/hvm: add helpers for raising guest IRQs
x86/hvm: introduce NS8250 UART emulator
x86/hvm: add debugging facility to NS8250 UART emulator
x86/domain: implement domain_has_vuart()
xen/console: enable console owners w/ emulated NS8250
docs/misc: update console documentation
automation/eclair_analysis/ECLAIR/deviations.ecl | 2 +-
docs/misc/console.txt | 50 +-
docs/misc/xen-command-line.pandoc | 5 +
tools/libs/light/libxl_x86.c | 6 +-
tools/ocaml/libs/xc/xenctrl.ml | 1 +
tools/ocaml/libs/xc/xenctrl.mli | 1 +
tools/python/xen/lowlevel/xc/xc.c | 4 +-
xen/arch/arm/dom0less-build.c | 4 +-
xen/arch/arm/domain.c | 20 +-
xen/arch/arm/domctl.c | 5 +-
xen/arch/arm/include/asm/domain.h | 9 +
xen/arch/arm/include/asm/setup.h | 2 -
xen/arch/arm/include/asm/vpl011.h | 2 +-
xen/arch/arm/setup.c | 2 -
xen/arch/arm/vpl011.c | 19 +-
xen/arch/arm/vuart.c | 7 +-
xen/arch/ppc/include/asm/domain.h | 2 +
xen/arch/ppc/include/asm/setup.h | 2 -
xen/arch/riscv/include/asm/domain.h | 2 +
xen/arch/riscv/include/asm/setup.h | 2 -
xen/arch/x86/Kconfig | 66 +-
xen/arch/x86/dom0_build.c | 2 +
xen/arch/x86/domain.c | 16 +-
xen/arch/x86/hvm/Kconfig | 77 ++
xen/arch/x86/hvm/Makefile | 1 +
xen/arch/x86/hvm/hvm.c | 16 +-
xen/arch/x86/hvm/irq.c | 24 +
xen/arch/x86/hvm/vuart_ns8250.c | 1008 ++++++++++++++++++++++
xen/arch/x86/include/asm/domain.h | 8 +-
xen/arch/x86/include/asm/hvm/domain.h | 5 +
xen/arch/x86/include/asm/hvm/irq.h | 3 +
xen/arch/x86/include/asm/hvm/vuart_ns8250.h | 75 ++
xen/arch/x86/include/asm/pv/shim.h | 4 +-
xen/arch/x86/include/asm/setup.h | 2 -
xen/arch/x86/pv/shim.c | 6 +-
xen/common/device-tree/device-tree.c | 21 +-
xen/common/domain.c | 35 +-
xen/drivers/char/Kconfig | 23 +
xen/drivers/char/console.c | 394 +++++----
xen/drivers/char/consoled.c | 18 +-
xen/drivers/passthrough/arm/smmu.c | 15 +-
xen/include/public/arch-x86/xen.h | 14 +-
xen/include/xen/8250-uart.h | 81 +-
xen/include/xen/console.h | 4 +-
xen/include/xen/consoled.h | 35 +-
xen/include/xen/ctype.h | 3 +
xen/include/xen/domain.h | 5 +
xen/include/xen/irq.h | 1 +
xen/include/xen/lib.h | 3 +
xen/include/xen/resource.h | 40 +
50 files changed, 1799 insertions(+), 353 deletions(-)
---
base-commit: dc8e1b33a525d31989c0d1ffe6ae7794484e1d99
change-id: 20241205-vuart-ns8250-45847bc04140
Best regards,
--
Denis Mukhin <dmukhin@ford.com>
^ permalink raw reply [flat|nested] 218+ messages in thread* [PATCH v2 01/35] xen: introduce resource.h
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Move resource definitions to a new architecture-agnostic shared header file.
It will be used in follow on NS8250 emulator code to describe legacy
PC COM resources.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/common/device-tree/device-tree.c | 21 +------------------
xen/drivers/passthrough/arm/smmu.c | 15 +-------------
xen/include/xen/resource.h | 40 ++++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/xen/common/device-tree/device-tree.c b/xen/common/device-tree/device-tree.c
index d0528c5825651f7cc9ebca0c949229c9083063c6..e8f810b2fe10890c033ed3a9d4ca627010ad019b 100644
--- a/xen/common/device-tree/device-tree.c
+++ b/xen/common/device-tree/device-tree.c
@@ -24,6 +24,7 @@
#include <xen/ctype.h>
#include <asm/setup.h>
#include <xen/err.h>
+#include <xen/resource.h>
const void *device_tree_flattened;
dt_irq_xlate_func dt_irq_xlate;
@@ -535,26 +536,6 @@ int dt_child_n_size_cells(const struct dt_device_node *parent)
return __dt_n_size_cells(parent, true);
}
-/*
- * These are defined in Linux where much of this code comes from, but
- * are currently unused outside this file in the context of Xen.
- */
-#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
-
-#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
-#define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */
-#define IORESOURCE_MEM 0x00000200
-#define IORESOURCE_REG 0x00000300 /* Register offsets */
-#define IORESOURCE_IRQ 0x00000400
-#define IORESOURCE_DMA 0x00000800
-#define IORESOURCE_BUS 0x00001000
-
-#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */
-#define IORESOURCE_READONLY 0x00004000
-#define IORESOURCE_CACHEABLE 0x00008000
-#define IORESOURCE_RANGELENGTH 0x00010000
-#define IORESOURCE_SHADOWABLE 0x00020000
-
/*
* Default translator (generic bus)
*/
diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index 03d22bce1e497e41834c273f9048b98dcbd48a54..aa6a968b574dce7cc753e8070fad3a6e585cd9e7 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -50,6 +50,7 @@
#include <xen/rbtree.h>
#include <xen/sched.h>
#include <xen/sizes.h>
+#include <xen/resource.h>
#include <asm/atomic.h>
#include <asm/device.h>
#include <asm/io.h>
@@ -70,22 +71,8 @@
#define of_property_read_u32(np, pname, out) (!dt_property_read_u32(np, pname, out))
#define of_property_read_bool dt_property_read_bool
#define of_parse_phandle_with_args dt_parse_phandle_with_args
-
-/* Xen: Helpers to get device MMIO and IRQs */
-struct resource
-{
- paddr_t addr;
- paddr_t size;
- unsigned int type;
-};
-
-#define resource_size(res) (res)->size;
-
#define platform_device dt_device_node
-#define IORESOURCE_MEM 0
-#define IORESOURCE_IRQ 1
-
static struct resource *platform_get_resource(struct platform_device *pdev,
unsigned int type,
unsigned int num)
diff --git a/xen/include/xen/resource.h b/xen/include/xen/resource.h
new file mode 100644
index 0000000000000000000000000000000000000000..4962e17da8387b7f324317482b19cc9fe71433fc
--- /dev/null
+++ b/xen/include/xen/resource.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * System resource description.
+ *
+ * Reference:
+ * include/linux/ioport.h
+ */
+#if !defined(XEN__RESOURCE_H)
+#define XEN__RESOURCE_H
+
+#define IORESOURCE_BITS 0x000000FFU /* Bus-specific bits */
+
+#define IORESOURCE_TYPE_BITS 0x00001F00U /* Resource type */
+#define IORESOURCE_IO 0x00000100U /* PCI/ISA I/O ports */
+#define IORESOURCE_MEM 0x00000200U
+#define IORESOURCE_REG 0x00000300U /* Register offsets */
+#define IORESOURCE_IRQ 0x00000400U
+#define IORESOURCE_DMA 0x00000800U
+#define IORESOURCE_BUS 0x00001000U
+
+#define IORESOURCE_PREFETCH 0x00002000U /* No side effects */
+#define IORESOURCE_READONLY 0x00004000U
+#define IORESOURCE_CACHEABLE 0x00008000U
+#define IORESOURCE_RANGELENGTH 0x00010000U
+#define IORESOURCE_SHADOWABLE 0x00020000U
+
+#define IORESOURCE_UNKNOWN (~0U)
+
+struct resource {
+ paddr_t addr;
+ paddr_t size;
+ unsigned int type;
+};
+
+#define resource_size(res) (res)->size;
+
+#define foreach_resource(res) \
+ for (; res && res->type != IORESOURCE_UNKNOWN; res++)
+
+#endif /* #if !defined(XEN__RESOURCE_H) */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 01/35] xen: introduce resource.h
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Move resource definitions to a new architecture-agnostic shared header file.
It will be used in follow on NS8250 emulator code to describe legacy
PC COM resources.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/common/device-tree/device-tree.c | 21 +------------------
xen/drivers/passthrough/arm/smmu.c | 15 +-------------
xen/include/xen/resource.h | 40 ++++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/xen/common/device-tree/device-tree.c b/xen/common/device-tree/device-tree.c
index d0528c5825651f7cc9ebca0c949229c9083063c6..e8f810b2fe10890c033ed3a9d4ca627010ad019b 100644
--- a/xen/common/device-tree/device-tree.c
+++ b/xen/common/device-tree/device-tree.c
@@ -24,6 +24,7 @@
#include <xen/ctype.h>
#include <asm/setup.h>
#include <xen/err.h>
+#include <xen/resource.h>
const void *device_tree_flattened;
dt_irq_xlate_func dt_irq_xlate;
@@ -535,26 +536,6 @@ int dt_child_n_size_cells(const struct dt_device_node *parent)
return __dt_n_size_cells(parent, true);
}
-/*
- * These are defined in Linux where much of this code comes from, but
- * are currently unused outside this file in the context of Xen.
- */
-#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
-
-#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
-#define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */
-#define IORESOURCE_MEM 0x00000200
-#define IORESOURCE_REG 0x00000300 /* Register offsets */
-#define IORESOURCE_IRQ 0x00000400
-#define IORESOURCE_DMA 0x00000800
-#define IORESOURCE_BUS 0x00001000
-
-#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */
-#define IORESOURCE_READONLY 0x00004000
-#define IORESOURCE_CACHEABLE 0x00008000
-#define IORESOURCE_RANGELENGTH 0x00010000
-#define IORESOURCE_SHADOWABLE 0x00020000
-
/*
* Default translator (generic bus)
*/
diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index 03d22bce1e497e41834c273f9048b98dcbd48a54..aa6a968b574dce7cc753e8070fad3a6e585cd9e7 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -50,6 +50,7 @@
#include <xen/rbtree.h>
#include <xen/sched.h>
#include <xen/sizes.h>
+#include <xen/resource.h>
#include <asm/atomic.h>
#include <asm/device.h>
#include <asm/io.h>
@@ -70,22 +71,8 @@
#define of_property_read_u32(np, pname, out) (!dt_property_read_u32(np, pname, out))
#define of_property_read_bool dt_property_read_bool
#define of_parse_phandle_with_args dt_parse_phandle_with_args
-
-/* Xen: Helpers to get device MMIO and IRQs */
-struct resource
-{
- paddr_t addr;
- paddr_t size;
- unsigned int type;
-};
-
-#define resource_size(res) (res)->size;
-
#define platform_device dt_device_node
-#define IORESOURCE_MEM 0
-#define IORESOURCE_IRQ 1
-
static struct resource *platform_get_resource(struct platform_device *pdev,
unsigned int type,
unsigned int num)
diff --git a/xen/include/xen/resource.h b/xen/include/xen/resource.h
new file mode 100644
index 0000000000000000000000000000000000000000..4962e17da8387b7f324317482b19cc9fe71433fc
--- /dev/null
+++ b/xen/include/xen/resource.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * System resource description.
+ *
+ * Reference:
+ * include/linux/ioport.h
+ */
+#if !defined(XEN__RESOURCE_H)
+#define XEN__RESOURCE_H
+
+#define IORESOURCE_BITS 0x000000FFU /* Bus-specific bits */
+
+#define IORESOURCE_TYPE_BITS 0x00001F00U /* Resource type */
+#define IORESOURCE_IO 0x00000100U /* PCI/ISA I/O ports */
+#define IORESOURCE_MEM 0x00000200U
+#define IORESOURCE_REG 0x00000300U /* Register offsets */
+#define IORESOURCE_IRQ 0x00000400U
+#define IORESOURCE_DMA 0x00000800U
+#define IORESOURCE_BUS 0x00001000U
+
+#define IORESOURCE_PREFETCH 0x00002000U /* No side effects */
+#define IORESOURCE_READONLY 0x00004000U
+#define IORESOURCE_CACHEABLE 0x00008000U
+#define IORESOURCE_RANGELENGTH 0x00010000U
+#define IORESOURCE_SHADOWABLE 0x00020000U
+
+#define IORESOURCE_UNKNOWN (~0U)
+
+struct resource {
+ paddr_t addr;
+ paddr_t size;
+ unsigned int type;
+};
+
+#define resource_size(res) (res)->size;
+
+#define foreach_resource(res) \
+ for (; res && res->type != IORESOURCE_UNKNOWN; res++)
+
+#endif /* #if !defined(XEN__RESOURCE_H) */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 01/35] xen: introduce resource.h
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:13 ` Jan Beulich
2025-01-04 2:23 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:13 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- /dev/null
> +++ b/xen/include/xen/resource.h
> @@ -0,0 +1,40 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
GPL-2.0-only
> +/*
> + * System resource description.
> + *
> + * Reference:
> + * include/linux/ioport.h
I'm unsure of the usefulness of such a reference.
> + */
> +#if !defined(XEN__RESOURCE_H)
Nit: #ifdef / #ifndef please whenever possible (as long as not inconsistent
with adjacent code).
> +#define XEN__RESOURCE_H
> +
> +#define IORESOURCE_BITS 0x000000FFU /* Bus-specific bits */
> +
> +#define IORESOURCE_TYPE_BITS 0x00001F00U /* Resource type */
> +#define IORESOURCE_IO 0x00000100U /* PCI/ISA I/O ports */
> +#define IORESOURCE_MEM 0x00000200U
> +#define IORESOURCE_REG 0x00000300U /* Register offsets */
> +#define IORESOURCE_IRQ 0x00000400U
> +#define IORESOURCE_DMA 0x00000800U
> +#define IORESOURCE_BUS 0x00001000U
> +
> +#define IORESOURCE_PREFETCH 0x00002000U /* No side effects */
> +#define IORESOURCE_READONLY 0x00004000U
> +#define IORESOURCE_CACHEABLE 0x00008000U
> +#define IORESOURCE_RANGELENGTH 0x00010000U
> +#define IORESOURCE_SHADOWABLE 0x00020000U
> +
> +#define IORESOURCE_UNKNOWN (~0U)
> +
> +struct resource {
> + paddr_t addr;
> + paddr_t size;
> + unsigned int type;
> +};
> +
> +#define resource_size(res) (res)->size;
The semicolon surely was wrong before and is wrong now. Plus Misra
demands that such macro expansions be parenthesized, I think.
> +#define foreach_resource(res) \
> + for (; res && res->type != IORESOURCE_UNKNOWN; res++)
This one isn't being moved, but is being added. It's not used here,
which makes it difficult to judge its correctness. Perhaps better to
introduce this when its first needed, and then right away with the
required parentheses around uses of the macro parameter.
> +#endif /* #if !defined(XEN__RESOURCE_H) */
Just the guard identifier in the comment please.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 01/35] xen: introduce resource.h
2024-12-10 13:13 ` Jan Beulich
@ 2025-01-04 2:23 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:23 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:13 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- /dev/null
> > +++ b/xen/include/xen/resource.h
> > @@ -0,0 +1,40 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
>
>
> GPL-2.0-only
Fixed.
>
> > +/*
> > + * System resource description.
> > + *
> > + * Reference:
> > + * include/linux/ioport.h
>
>
> I'm unsure of the usefulness of such a reference.
These definitions are taken from Linux'es
include/linux/ioport.h
I think reference to the original code may help developers to borrow more
missing declarations in the future.
But sure, removed.
>
> > + */
> > +#if !defined(XEN__RESOURCE_H)
>
>
> Nit: #ifdef / #ifndef please whenever possible (as long as not inconsistent
> with adjacent code).
Sure.
>
> > +#define XEN__RESOURCE_H
> > +
> > +#define IORESOURCE_BITS 0x000000FFU /* Bus-specific bits /
> > +
> > +#define IORESOURCE_TYPE_BITS 0x00001F00U / Resource type /
> > +#define IORESOURCE_IO 0x00000100U / PCI/ISA I/O ports /
> > +#define IORESOURCE_MEM 0x00000200U
> > +#define IORESOURCE_REG 0x00000300U / Register offsets /
> > +#define IORESOURCE_IRQ 0x00000400U
> > +#define IORESOURCE_DMA 0x00000800U
> > +#define IORESOURCE_BUS 0x00001000U
> > +
> > +#define IORESOURCE_PREFETCH 0x00002000U / No side effects */
> > +#define IORESOURCE_READONLY 0x00004000U
> > +#define IORESOURCE_CACHEABLE 0x00008000U
> > +#define IORESOURCE_RANGELENGTH 0x00010000U
> > +#define IORESOURCE_SHADOWABLE 0x00020000U
> > +
> > +#define IORESOURCE_UNKNOWN (~0U)
> > +
> > +struct resource {
> > + paddr_t addr;
> > + paddr_t size;
> > + unsigned int type;
> > +};
> > +
> > +#define resource_size(res) (res)->size;
>
>
> The semicolon surely was wrong before and is wrong now. Plus Misra
> demands that such macro expansions be parenthesized, I think.
Fixed.
>
> > +#define foreach_resource(res) \
> > + for (; res && res->type != IORESOURCE_UNKNOWN; res++)
>
>
> This one isn't being moved, but is being added. It's not used here,
> which makes it difficult to judge its correctness. Perhaps better to
> introduce this when its first needed, and then right away with the
> required parentheses around uses of the macro parameter.
I moved that hunk into the place where it is first used (the emulator
patch).
>
> > +#endif /* #if !defined(XEN__RESOURCE_H) */
>
>
> Just the guard identifier in the comment please.
Done.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 01/35] xen: introduce resource.h
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 11:01 ` Roger Pau Monné
2025-01-04 3:10 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 11:01 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:31PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Move resource definitions to a new architecture-agnostic shared header file.
>
> It will be used in follow on NS8250 emulator code to describe legacy
> PC COM resources.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/common/device-tree/device-tree.c | 21 +------------------
> xen/drivers/passthrough/arm/smmu.c | 15 +-------------
> xen/include/xen/resource.h | 40 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 42 insertions(+), 34 deletions(-)
>
> diff --git a/xen/common/device-tree/device-tree.c b/xen/common/device-tree/device-tree.c
> index d0528c5825651f7cc9ebca0c949229c9083063c6..e8f810b2fe10890c033ed3a9d4ca627010ad019b 100644
> --- a/xen/common/device-tree/device-tree.c
> +++ b/xen/common/device-tree/device-tree.c
> @@ -24,6 +24,7 @@
> #include <xen/ctype.h>
> #include <asm/setup.h>
> #include <xen/err.h>
> +#include <xen/resource.h>
>
> const void *device_tree_flattened;
> dt_irq_xlate_func dt_irq_xlate;
> @@ -535,26 +536,6 @@ int dt_child_n_size_cells(const struct dt_device_node *parent)
> return __dt_n_size_cells(parent, true);
> }
>
> -/*
> - * These are defined in Linux where much of this code comes from, but
> - * are currently unused outside this file in the context of Xen.
> - */
> -#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
> -
> -#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
> -#define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */
> -#define IORESOURCE_MEM 0x00000200
> -#define IORESOURCE_REG 0x00000300 /* Register offsets */
> -#define IORESOURCE_IRQ 0x00000400
> -#define IORESOURCE_DMA 0x00000800
> -#define IORESOURCE_BUS 0x00001000
> -
> -#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */
> -#define IORESOURCE_READONLY 0x00004000
> -#define IORESOURCE_CACHEABLE 0x00008000
> -#define IORESOURCE_RANGELENGTH 0x00010000
> -#define IORESOURCE_SHADOWABLE 0x00020000
> -
> /*
> * Default translator (generic bus)
> */
> diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
> index 03d22bce1e497e41834c273f9048b98dcbd48a54..aa6a968b574dce7cc753e8070fad3a6e585cd9e7 100644
> --- a/xen/drivers/passthrough/arm/smmu.c
> +++ b/xen/drivers/passthrough/arm/smmu.c
> @@ -50,6 +50,7 @@
> #include <xen/rbtree.h>
> #include <xen/sched.h>
> #include <xen/sizes.h>
> +#include <xen/resource.h>
> #include <asm/atomic.h>
> #include <asm/device.h>
> #include <asm/io.h>
> @@ -70,22 +71,8 @@
> #define of_property_read_u32(np, pname, out) (!dt_property_read_u32(np, pname, out))
> #define of_property_read_bool dt_property_read_bool
> #define of_parse_phandle_with_args dt_parse_phandle_with_args
> -
> -/* Xen: Helpers to get device MMIO and IRQs */
> -struct resource
> -{
> - paddr_t addr;
> - paddr_t size;
> - unsigned int type;
> -};
> -
> -#define resource_size(res) (res)->size;
> -
> #define platform_device dt_device_node
>
> -#define IORESOURCE_MEM 0
> -#define IORESOURCE_IRQ 1
> -
> static struct resource *platform_get_resource(struct platform_device *pdev,
> unsigned int type,
> unsigned int num)
> diff --git a/xen/include/xen/resource.h b/xen/include/xen/resource.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..4962e17da8387b7f324317482b19cc9fe71433fc
> --- /dev/null
> +++ b/xen/include/xen/resource.h
> @@ -0,0 +1,40 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * System resource description.
> + *
> + * Reference:
> + * include/linux/ioport.h
> + */
> +#if !defined(XEN__RESOURCE_H)
> +#define XEN__RESOURCE_H
> +
> +#define IORESOURCE_BITS 0x000000FFU /* Bus-specific bits */
> +
> +#define IORESOURCE_TYPE_BITS 0x00001F00U /* Resource type */
> +#define IORESOURCE_IO 0x00000100U /* PCI/ISA I/O ports */
> +#define IORESOURCE_MEM 0x00000200U
> +#define IORESOURCE_REG 0x00000300U /* Register offsets */
> +#define IORESOURCE_IRQ 0x00000400U
> +#define IORESOURCE_DMA 0x00000800U
> +#define IORESOURCE_BUS 0x00001000U
> +
> +#define IORESOURCE_PREFETCH 0x00002000U /* No side effects */
> +#define IORESOURCE_READONLY 0x00004000U
> +#define IORESOURCE_CACHEABLE 0x00008000U
> +#define IORESOURCE_RANGELENGTH 0x00010000U
> +#define IORESOURCE_SHADOWABLE 0x00020000U
> +
> +#define IORESOURCE_UNKNOWN (~0U)
> +
> +struct resource {
> + paddr_t addr;
> + paddr_t size;
> + unsigned int type;
> +};
> +
> +#define resource_size(res) (res)->size;
> +
> +#define foreach_resource(res) \
Nit: we usually name those for_each_foo instead of foreach_foo.
> + for (; res && res->type != IORESOURCE_UNKNOWN; res++)
Missing spaces between parentheses:
for ( ; res && res->type != IORESOURCE_UNKNOWN; res++ )
Note that this macro will modify (advance) the res pointer, which is
maybe unexpected by the caller?
Also, the current logic forces the array of resources to always have a
trailing IORESOURCE_UNKNOWN element in order to break the loop, it
might be better to pass an explicit number of elements to iterate
against if possible?
As Jan said, it would be helpful to have an example usage of the
macro.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 01/35] xen: introduce resource.h
2024-12-11 11:01 ` Roger Pau Monné
@ 2025-01-04 3:10 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:10 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Wednesday, December 11th, 2024 at 3:01 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:31PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Move resource definitions to a new architecture-agnostic shared header file.
> >
> > It will be used in follow on NS8250 emulator code to describe legacy
> > PC COM resources.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/common/device-tree/device-tree.c | 21 +------------------
> > xen/drivers/passthrough/arm/smmu.c | 15 +-------------
> > xen/include/xen/resource.h | 40 ++++++++++++++++++++++++++++++++++++
> > 3 files changed, 42 insertions(+), 34 deletions(-)
> >
> > diff --git a/xen/common/device-tree/device-tree.c b/xen/common/device-tree/device-tree.c
> > index d0528c5825651f7cc9ebca0c949229c9083063c6..e8f810b2fe10890c033ed3a9d4ca627010ad019b 100644
> > --- a/xen/common/device-tree/device-tree.c
> > +++ b/xen/common/device-tree/device-tree.c
> > @@ -24,6 +24,7 @@
> > #include <xen/ctype.h>
> > #include <asm/setup.h>
> > #include <xen/err.h>
> > +#include <xen/resource.h>
> >
> > const void *device_tree_flattened;
> > dt_irq_xlate_func dt_irq_xlate;
> > @@ -535,26 +536,6 @@ int dt_child_n_size_cells(const struct dt_device_node *parent)
> > return __dt_n_size_cells(parent, true);
> > }
> >
> > -/*
> > - * These are defined in Linux where much of this code comes from, but
> > - * are currently unused outside this file in the context of Xen.
> > - /
> > -#define IORESOURCE_BITS 0x000000ff / Bus-specific bits /
> > -
> > -#define IORESOURCE_TYPE_BITS 0x00001f00 / Resource type /
> > -#define IORESOURCE_IO 0x00000100 / PCI/ISA I/O ports /
> > -#define IORESOURCE_MEM 0x00000200
> > -#define IORESOURCE_REG 0x00000300 / Register offsets /
> > -#define IORESOURCE_IRQ 0x00000400
> > -#define IORESOURCE_DMA 0x00000800
> > -#define IORESOURCE_BUS 0x00001000
> > -
> > -#define IORESOURCE_PREFETCH 0x00002000 / No side effects /
> > -#define IORESOURCE_READONLY 0x00004000
> > -#define IORESOURCE_CACHEABLE 0x00008000
> > -#define IORESOURCE_RANGELENGTH 0x00010000
> > -#define IORESOURCE_SHADOWABLE 0x00020000
> > -
> > /
> > * Default translator (generic bus)
> > /
> > diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
> > index 03d22bce1e497e41834c273f9048b98dcbd48a54..aa6a968b574dce7cc753e8070fad3a6e585cd9e7 100644
> > --- a/xen/drivers/passthrough/arm/smmu.c
> > +++ b/xen/drivers/passthrough/arm/smmu.c
> > @@ -50,6 +50,7 @@
> > #include <xen/rbtree.h>
> > #include <xen/sched.h>
> > #include <xen/sizes.h>
> > +#include <xen/resource.h>
> > #include <asm/atomic.h>
> > #include <asm/device.h>
> > #include <asm/io.h>
> > @@ -70,22 +71,8 @@
> > #define of_property_read_u32(np, pname, out) (!dt_property_read_u32(np, pname, out))
> > #define of_property_read_bool dt_property_read_bool
> > #define of_parse_phandle_with_args dt_parse_phandle_with_args
> > -
> > -/ Xen: Helpers to get device MMIO and IRQs */
> > -struct resource
> > -{
> > - paddr_t addr;
> > - paddr_t size;
> > - unsigned int type;
> > -};
> > -
> > -#define resource_size(res) (res)->size;
> > -
> > #define platform_device dt_device_node
> >
> > -#define IORESOURCE_MEM 0
> > -#define IORESOURCE_IRQ 1
> > -
> > static struct resource *platform_get_resource(struct platform_device pdev,
> > unsigned int type,
> > unsigned int num)
> > diff --git a/xen/include/xen/resource.h b/xen/include/xen/resource.h
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..4962e17da8387b7f324317482b19cc9fe71433fc
> > --- /dev/null
> > +++ b/xen/include/xen/resource.h
> > @@ -0,0 +1,40 @@
> > +/ SPDX-License-Identifier: GPL-2.0 /
> > +/
> > + * System resource description.
> > + *
> > + * Reference:
> > + * include/linux/ioport.h
> > + /
> > +#if !defined(XEN__RESOURCE_H)
> > +#define XEN__RESOURCE_H
> > +
> > +#define IORESOURCE_BITS 0x000000FFU / Bus-specific bits /
> > +
> > +#define IORESOURCE_TYPE_BITS 0x00001F00U / Resource type /
> > +#define IORESOURCE_IO 0x00000100U / PCI/ISA I/O ports /
> > +#define IORESOURCE_MEM 0x00000200U
> > +#define IORESOURCE_REG 0x00000300U / Register offsets /
> > +#define IORESOURCE_IRQ 0x00000400U
> > +#define IORESOURCE_DMA 0x00000800U
> > +#define IORESOURCE_BUS 0x00001000U
> > +
> > +#define IORESOURCE_PREFETCH 0x00002000U / No side effects */
> > +#define IORESOURCE_READONLY 0x00004000U
> > +#define IORESOURCE_CACHEABLE 0x00008000U
> > +#define IORESOURCE_RANGELENGTH 0x00010000U
> > +#define IORESOURCE_SHADOWABLE 0x00020000U
> > +
> > +#define IORESOURCE_UNKNOWN (~0U)
> > +
> > +struct resource {
> > + paddr_t addr;
> > + paddr_t size;
> > + unsigned int type;
> > +};
> > +
> > +#define resource_size(res) (res)->size;
> > +
> > +#define foreach_resource(res) \
>
>
> Nit: we usually name those for_each_foo instead of foreach_foo.
Fixed.
>
> > + for (; res && res->type != IORESOURCE_UNKNOWN; res++)
>
>
> Missing spaces between parentheses:
>
> for ( ; res && res->type != IORESOURCE_UNKNOWN; res++ )
Fixed.
>
>
> Note that this macro will modify (advance) the res pointer, which is
> maybe unexpected by the caller?
For my use case I rely on res pointer advance.
>
> Also, the current logic forces the array of resources to always have a
> trailing IORESOURCE_UNKNOWN element in order to break the loop, it
> might be better to pass an explicit number of elements to iterate
> against if possible?
Current use is pretty simple, I think I will keep it as is for now.
>
> As Jan said, it would be helpful to have an example usage of the
> macro.
I moved this definition into the patch where it is first used in v3 (UART emulator
patch).
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 02/35] xen/irq: introduce NO_IRQ
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Introduce definition for IRQ resource checks.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/include/xen/irq.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index 95034c0d6bb5f0aa7d5bb572aca59872508a438a..aee878293ecc0de6a938bcfea1140d36b4de745a 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -53,6 +53,7 @@ struct irqaction {
#define AUTO_ASSIGN_IRQ (-1)
#define NEVER_ASSIGN_IRQ (-2)
#define FREE_TO_ASSIGN_IRQ (-3)
+#define NO_IRQ (-4)
struct irq_desc;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 02/35] xen/irq: introduce NO_IRQ
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Introduce definition for IRQ resource checks.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/include/xen/irq.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index 95034c0d6bb5f0aa7d5bb572aca59872508a438a..aee878293ecc0de6a938bcfea1140d36b4de745a 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -53,6 +53,7 @@ struct irqaction {
#define AUTO_ASSIGN_IRQ (-1)
#define NEVER_ASSIGN_IRQ (-2)
#define FREE_TO_ASSIGN_IRQ (-3)
+#define NO_IRQ (-4)
struct irq_desc;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 02/35] xen/irq: introduce NO_IRQ
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:17 ` Jan Beulich
2025-01-04 2:26 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:17 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Introduce definition for IRQ resource checks.
How does this fit ...
> --- a/xen/include/xen/irq.h
> +++ b/xen/include/xen/irq.h
> @@ -53,6 +53,7 @@ struct irqaction {
> #define AUTO_ASSIGN_IRQ (-1)
> #define NEVER_ASSIGN_IRQ (-2)
> #define FREE_TO_ASSIGN_IRQ (-3)
> +#define NO_IRQ (-4)
... the grouping here? The constants in context aren't used anywhere,
so it's hard to see whether / how the new one fits here (and doesn't
instead belong into the new resource.h you introduce in patch 1). Once
again likely best to have this in the patch where it's first needed,
thus providing at least some context.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 02/35] xen/irq: introduce NO_IRQ
2024-12-10 13:17 ` Jan Beulich
@ 2025-01-04 2:26 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:26 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:17 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Introduce definition for IRQ resource checks.
>
>
> How does this fit ...
>
> > --- a/xen/include/xen/irq.h
> > +++ b/xen/include/xen/irq.h
> > @@ -53,6 +53,7 @@ struct irqaction {
> > #define AUTO_ASSIGN_IRQ (-1)
> > #define NEVER_ASSIGN_IRQ (-2)
> > #define FREE_TO_ASSIGN_IRQ (-3)
> > +#define NO_IRQ (-4)
>
>
> ... the grouping here? The constants in context aren't used anywhere,
> so it's hard to see whether / how the new one fits here (and doesn't
> instead belong into the new resource.h you introduce in patch 1). Once
> again likely best to have this in the patch where it's first needed,
> thus providing at least some context.
I ended up dropping this change.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 03/35] xen/ctype: introduce isconsole()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
There are several console drivers which have same checks w.r.t. printable
characters. The check is moved to new isconsole() macro and re-used in
the console drivers.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/vuart.c | 3 +--
xen/arch/x86/hvm/hvm.c | 3 +--
xen/drivers/char/console.c | 2 +-
xen/include/xen/ctype.h | 3 +++
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index d5ba483f1e63245e545346ad5045098152b8c152..ac76e2327bb84f05ea5716c6f5550f94812d2827 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -79,8 +79,7 @@ static void vuart_print_char(struct vcpu *v, char c)
struct domain *d = v->domain;
struct vuart *uart = &d->arch.vuart;
- /* Accept only printable characters, newline, and horizontal tab. */
- if ( !isprint(c) && (c != '\n') && (c != '\t') )
+ if ( !isconsole(c) )
return ;
spin_lock(&uart->lock);
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 74e58c653e6f697e7e563fd076bbbafaf257137d..493b699c708949b2109c26573a107565543f5d45 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -561,8 +561,7 @@ static int cf_check hvm_print_line(
if ( dir != IOREQ_WRITE )
return X86EMUL_UNHANDLEABLE;
- /* Accept only printable characters, newline, and horizontal tab. */
- if ( !isprint(c) && (c != '\n') && (c != '\t') )
+ if ( !isconsole(c) )
return X86EMUL_OKAY;
spin_lock(&cd->pbuf_lock);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 7da8c5296f3b62c6c45131c58fe5cf0e393e9ef3..bb56953bab681a13da8d41431aba4632f1919df9 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -674,7 +674,7 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
c = *kin++;
if ( c == '\n' )
break;
- if ( isprint(c) || c == '\t' )
+ if ( isconsole(c) )
*kout++ = c;
} while ( --kcount > 0 );
diff --git a/xen/include/xen/ctype.h b/xen/include/xen/ctype.h
index 773ac27aa44ac65e76e87cdec960450804310249..deebaad96ede34f16f61ece862c788232c1d1efd 100644
--- a/xen/include/xen/ctype.h
+++ b/xen/include/xen/ctype.h
@@ -4,6 +4,8 @@
/*
* NOTE! This ctype does not handle EOF like the standard C
* library is required to.
+ *
+ * See Rule 21.13 in docs/misra/rules.rst.
*/
#define _U 0x01 /* upper */
@@ -30,6 +32,7 @@ extern const unsigned char _ctype[];
#define isspace(c) ((__ismask(c)&(_S)) != 0)
#define isupper(c) ((__ismask(c)&(_U)) != 0)
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+#define isconsole(c) (isprint(c) || (c) == '\n' || (c) == '\t')
#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 03/35] xen/ctype: introduce isconsole()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
There are several console drivers which have same checks w.r.t. printable
characters. The check is moved to new isconsole() macro and re-used in
the console drivers.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/vuart.c | 3 +--
xen/arch/x86/hvm/hvm.c | 3 +--
xen/drivers/char/console.c | 2 +-
xen/include/xen/ctype.h | 3 +++
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index d5ba483f1e63245e545346ad5045098152b8c152..ac76e2327bb84f05ea5716c6f5550f94812d2827 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -79,8 +79,7 @@ static void vuart_print_char(struct vcpu *v, char c)
struct domain *d = v->domain;
struct vuart *uart = &d->arch.vuart;
- /* Accept only printable characters, newline, and horizontal tab. */
- if ( !isprint(c) && (c != '\n') && (c != '\t') )
+ if ( !isconsole(c) )
return ;
spin_lock(&uart->lock);
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 74e58c653e6f697e7e563fd076bbbafaf257137d..493b699c708949b2109c26573a107565543f5d45 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -561,8 +561,7 @@ static int cf_check hvm_print_line(
if ( dir != IOREQ_WRITE )
return X86EMUL_UNHANDLEABLE;
- /* Accept only printable characters, newline, and horizontal tab. */
- if ( !isprint(c) && (c != '\n') && (c != '\t') )
+ if ( !isconsole(c) )
return X86EMUL_OKAY;
spin_lock(&cd->pbuf_lock);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 7da8c5296f3b62c6c45131c58fe5cf0e393e9ef3..bb56953bab681a13da8d41431aba4632f1919df9 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -674,7 +674,7 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
c = *kin++;
if ( c == '\n' )
break;
- if ( isprint(c) || c == '\t' )
+ if ( isconsole(c) )
*kout++ = c;
} while ( --kcount > 0 );
diff --git a/xen/include/xen/ctype.h b/xen/include/xen/ctype.h
index 773ac27aa44ac65e76e87cdec960450804310249..deebaad96ede34f16f61ece862c788232c1d1efd 100644
--- a/xen/include/xen/ctype.h
+++ b/xen/include/xen/ctype.h
@@ -4,6 +4,8 @@
/*
* NOTE! This ctype does not handle EOF like the standard C
* library is required to.
+ *
+ * See Rule 21.13 in docs/misra/rules.rst.
*/
#define _U 0x01 /* upper */
@@ -30,6 +32,7 @@ extern const unsigned char _ctype[];
#define isspace(c) ((__ismask(c)&(_S)) != 0)
#define isupper(c) ((__ismask(c)&(_U)) != 0)
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+#define isconsole(c) (isprint(c) || (c) == '\n' || (c) == '\t')
#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 03/35] xen/ctype: introduce isconsole()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:22 ` Jan Beulich
2025-01-04 2:31 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:22 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> There are several console drivers which have same checks w.r.t. printable
> characters. The check is moved to new isconsole() macro and re-used in
> the console drivers.
Something named isconsole() imo can't be expected to do what is checked for
...
> --- a/xen/arch/arm/vuart.c
> +++ b/xen/arch/arm/vuart.c
> @@ -79,8 +79,7 @@ static void vuart_print_char(struct vcpu *v, char c)
> struct domain *d = v->domain;
> struct vuart *uart = &d->arch.vuart;
>
> - /* Accept only printable characters, newline, and horizontal tab. */
> - if ( !isprint(c) && (c != '\n') && (c != '\t') )
> + if ( !isconsole(c) )
> return ;
... e.g. here. If we really want such a further abstraction (of which I'm
unconvinced), then maybe isprintable() or (getting ling-ish)
is_console_printable().
> --- a/xen/include/xen/ctype.h
> +++ b/xen/include/xen/ctype.h
> @@ -4,6 +4,8 @@
> /*
> * NOTE! This ctype does not handle EOF like the standard C
> * library is required to.
> + *
> + * See Rule 21.13 in docs/misra/rules.rst.
> */
How's this change related to the purpose of the patch?
> @@ -30,6 +32,7 @@ extern const unsigned char _ctype[];
> #define isspace(c) ((__ismask(c)&(_S)) != 0)
> #define isupper(c) ((__ismask(c)&(_U)) != 0)
> #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
> +#define isconsole(c) (isprint(c) || (c) == '\n' || (c) == '\t')
In a pretty general purpose macro like this one I'm afraid I view it as
risky to evaluate the parameter more than once.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 03/35] xen/ctype: introduce isconsole()
2024-12-10 13:22 ` Jan Beulich
@ 2025-01-04 2:31 ` Denis Mukhin
2025-01-06 8:55 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:31 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:22 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > There are several console drivers which have same checks w.r.t. printable
> > characters. The check is moved to new isconsole() macro and re-used in
> > the console drivers.
>
>
> Something named isconsole() imo can't be expected to do what is checked for
I tried to follow the "short" naming notation in ctype.h.
I agree; changed the name to is_console_printable() as per below suggestion.
> ...
>
> > --- a/xen/arch/arm/vuart.c
> > +++ b/xen/arch/arm/vuart.c
> > @@ -79,8 +79,7 @@ static void vuart_print_char(struct vcpu *v, char c)
> > struct domain *d = v->domain;
> > struct vuart *uart = &d->arch.vuart;
> >
> > - /* Accept only printable characters, newline, and horizontal tab. */
> > - if ( !isprint(c) && (c != '\n') && (c != '\t') )
> > + if ( !isconsole(c) )
> > return ;
>
>
> ... e.g. here. If we really want such a further abstraction (of which I'm
> unconvinced), then maybe isprintable() or (getting ling-ish)
> is_console_printable().
Reworked to is_console_printable()
>
> > --- a/xen/include/xen/ctype.h
> > +++ b/xen/include/xen/ctype.h
> > @@ -4,6 +4,8 @@
> > /*
> > * NOTE! This ctype does not handle EOF like the standard C
> > * library is required to.
> > + *
> > + * See Rule 21.13 in docs/misra/rules.rst.
> > */
>
>
> How's this change related to the purpose of the patch?
Only because the very first version of the macro was failing
an ECLAIR job for me because of Rule 21.13 violation.
Updated the commit message (v3).
>
> > @@ -30,6 +32,7 @@ extern const unsigned char _ctype[];
> > #define isspace(c) ((__ismask(c)&(_S)) != 0)
> > #define isupper(c) ((__ismask(c)&(_U)) != 0)
> > #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
> > +#define isconsole(c) (isprint(c) || (c) == '\n' || (c) == '\t')
>
>
> In a pretty general purpose macro like this one I'm afraid I view it as
> risky to evaluate the parameter more than once.
Fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 03/35] xen/ctype: introduce isconsole()
2025-01-04 2:31 ` Denis Mukhin
@ 2025-01-06 8:55 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 8:55 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On 04.01.2025 03:31, Denis Mukhin wrote:
> On Tuesday, December 10th, 2024 at 5:22 AM, Jan Beulich <jbeulich@suse.com> wrote:
>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>> --- a/xen/include/xen/ctype.h
>>> +++ b/xen/include/xen/ctype.h
>>> @@ -4,6 +4,8 @@
>>> /*
>>> * NOTE! This ctype does not handle EOF like the standard C
>>> * library is required to.
>>> + *
>>> + * See Rule 21.13 in docs/misra/rules.rst.
>>> */
>>
>>
>> How's this change related to the purpose of the patch?
>
> Only because the very first version of the macro was failing
> an ECLAIR job for me because of Rule 21.13 violation.
>
> Updated the commit message (v3).
Well, no, in such an event please drop this comment change. Or else we end
up with Misra related comments about everywhere. After all _all_ Misra
rules need to be follow everywhere anyway.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 04/35] arm/vuart: use guest_printk()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Use guest_printk() in all current in-hypervisor UART emulators.
That slightly improves the logging as guest_printk() already prints the
domain ID.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/vpl011.c | 2 +-
xen/arch/arm/vuart.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 1fc3114cce9ddb48cf199834c8e9abe8cfba92b5..8ade6f2588b8bbcc58fb0f9edc324502a1992ce7 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -107,7 +107,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
if ( data != '\n' )
intf->out[intf->out_prod++] = '\n';
intf->out[intf->out_prod++] = '\0';
- printk("DOM%u: %s", d->domain_id, intf->out);
+ guest_printk(d, "%s", intf->out);
intf->out_prod = 0;
}
}
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index ac76e2327bb84f05ea5716c6f5550f94812d2827..38ce8cc14fac4132578059b696be952b29fab809 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -89,7 +89,7 @@ static void vuart_print_char(struct vcpu *v, char c)
if ( c != '\n' )
uart->buf[uart->idx++] = '\n';
uart->buf[uart->idx] = '\0';
- printk(XENLOG_G_DEBUG "DOM%u: %s", d->domain_id, uart->buf);
+ guest_printk(d, "%s", uart->buf);
uart->idx = 0;
}
spin_unlock(&uart->lock);
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 04/35] arm/vuart: use guest_printk()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Use guest_printk() in all current in-hypervisor UART emulators.
That slightly improves the logging as guest_printk() already prints the
domain ID.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/vpl011.c | 2 +-
xen/arch/arm/vuart.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 1fc3114cce9ddb48cf199834c8e9abe8cfba92b5..8ade6f2588b8bbcc58fb0f9edc324502a1992ce7 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -107,7 +107,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
if ( data != '\n' )
intf->out[intf->out_prod++] = '\n';
intf->out[intf->out_prod++] = '\0';
- printk("DOM%u: %s", d->domain_id, intf->out);
+ guest_printk(d, "%s", intf->out);
intf->out_prod = 0;
}
}
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index ac76e2327bb84f05ea5716c6f5550f94812d2827..38ce8cc14fac4132578059b696be952b29fab809 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -89,7 +89,7 @@ static void vuart_print_char(struct vcpu *v, char c)
if ( c != '\n' )
uart->buf[uart->idx++] = '\n';
uart->buf[uart->idx] = '\0';
- printk(XENLOG_G_DEBUG "DOM%u: %s", d->domain_id, uart->buf);
+ guest_printk(d, "%s", uart->buf);
uart->idx = 0;
}
spin_unlock(&uart->lock);
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* [PATCH v2 05/35] arm/vuart: make domain_has_vuart() public
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Move domain_has_vuart() to arch namespace as preparation code change for
architecture-agnostic way of forwarding physical console to the guest OS w/
in-hypervisor UART emulator.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/dom0less-build.c | 2 ++
xen/arch/arm/domain.c | 19 ++++++++++++-------
xen/arch/arm/domctl.c | 4 +++-
xen/arch/arm/include/asm/domain.h | 9 +++++++++
xen/arch/arm/vuart.c | 2 --
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index f328a044e9d3bb5c9d358456c2ead5d2f125fbb1..de64ee930fdfe9a1c2842761275641485f69f675 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -831,6 +831,8 @@ static int __init construct_domU(struct domain *d,
rc = domain_vpl011_init(d, NULL);
if ( rc < 0 )
return rc;
+
+ d->arch.emulation_flags |= ARM_EMU_VUART;
}
rc = prepare_dtb_domU(d, &kinfo);
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 3ba959f866338d2e7f7dc0e301cd79c10fbc4549..02f9d59b38b4b7f6f73d97c421c9948c90e681d5 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -769,14 +769,19 @@ int arch_domain_create(struct domain *d,
if ( !vgic_reserve_virq(d, GUEST_EVTCHN_PPI) )
BUG();
}
+ else
+ {
+ /*
+ * Virtual UART is only used by linux early printk and decompress code.
+ * Only use it for the hardware domain because the linux kernel may not
+ * support multi-platform.
+ */
+ rc = domain_vuart_init(d);
+ if ( rc )
+ goto fail;
- /*
- * Virtual UART is only used by linux early printk and decompress code.
- * Only use it for the hardware domain because the linux kernel may not
- * support multi-platform.
- */
- if ( is_hardware_domain(d) && (rc = domain_vuart_init(d)) )
- goto fail;
+ d->arch.emulation_flags |= ARM_EMU_VUART;
+ }
if ( (rc = domain_vpci_init(d)) != 0 )
goto fail;
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 9d047065ba13ffe003d2565879cd073e78f76893..f80d34bf5f3d323a15db7f032073be52ea1009ae 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -42,9 +42,11 @@ static int handle_vuart_init(struct domain *d,
return -EOPNOTSUPP;
rc = domain_vpl011_init(d, &info);
-
if ( !rc )
+ {
vuart_op->evtchn = info.evtchn;
+ d->arch.emulation_flags |= ARM_EMU_VUART;
+ }
return rc;
}
diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
index f1d72c6e48dfeba347b4cd091ca33603c368b7c0..2bbd3f472176bdcfbc0f95f9d8809343d11965c8 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -119,8 +119,17 @@ struct arch_domain
void *tee;
#endif
+ /* Emulated devices enabled bitmap. */
+ uint32_t emulation_flags;
+
} __cacheline_aligned;
+enum {
+ ARM_EMU_VUART = BIT(0, U),
+};
+
+#define domain_has_vuart(d) (!!((d)->arch.emulation_flags & ARM_EMU_VUART))
+
struct arch_vcpu
{
struct {
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index 38ce8cc14fac4132578059b696be952b29fab809..1fd980bd3a83820b382f875eb87ce4b8d83ccebe 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -31,8 +31,6 @@
#include "vuart.h"
-#define domain_has_vuart(d) ((d)->arch.vuart.info != NULL)
-
static int vuart_mmio_read(struct vcpu *v, mmio_info_t *info,
register_t *r, void *priv);
static int vuart_mmio_write(struct vcpu *v, mmio_info_t *info,
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 05/35] arm/vuart: make domain_has_vuart() public
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Move domain_has_vuart() to arch namespace as preparation code change for
architecture-agnostic way of forwarding physical console to the guest OS w/
in-hypervisor UART emulator.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/dom0less-build.c | 2 ++
xen/arch/arm/domain.c | 19 ++++++++++++-------
xen/arch/arm/domctl.c | 4 +++-
xen/arch/arm/include/asm/domain.h | 9 +++++++++
xen/arch/arm/vuart.c | 2 --
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index f328a044e9d3bb5c9d358456c2ead5d2f125fbb1..de64ee930fdfe9a1c2842761275641485f69f675 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -831,6 +831,8 @@ static int __init construct_domU(struct domain *d,
rc = domain_vpl011_init(d, NULL);
if ( rc < 0 )
return rc;
+
+ d->arch.emulation_flags |= ARM_EMU_VUART;
}
rc = prepare_dtb_domU(d, &kinfo);
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 3ba959f866338d2e7f7dc0e301cd79c10fbc4549..02f9d59b38b4b7f6f73d97c421c9948c90e681d5 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -769,14 +769,19 @@ int arch_domain_create(struct domain *d,
if ( !vgic_reserve_virq(d, GUEST_EVTCHN_PPI) )
BUG();
}
+ else
+ {
+ /*
+ * Virtual UART is only used by linux early printk and decompress code.
+ * Only use it for the hardware domain because the linux kernel may not
+ * support multi-platform.
+ */
+ rc = domain_vuart_init(d);
+ if ( rc )
+ goto fail;
- /*
- * Virtual UART is only used by linux early printk and decompress code.
- * Only use it for the hardware domain because the linux kernel may not
- * support multi-platform.
- */
- if ( is_hardware_domain(d) && (rc = domain_vuart_init(d)) )
- goto fail;
+ d->arch.emulation_flags |= ARM_EMU_VUART;
+ }
if ( (rc = domain_vpci_init(d)) != 0 )
goto fail;
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 9d047065ba13ffe003d2565879cd073e78f76893..f80d34bf5f3d323a15db7f032073be52ea1009ae 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -42,9 +42,11 @@ static int handle_vuart_init(struct domain *d,
return -EOPNOTSUPP;
rc = domain_vpl011_init(d, &info);
-
if ( !rc )
+ {
vuart_op->evtchn = info.evtchn;
+ d->arch.emulation_flags |= ARM_EMU_VUART;
+ }
return rc;
}
diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
index f1d72c6e48dfeba347b4cd091ca33603c368b7c0..2bbd3f472176bdcfbc0f95f9d8809343d11965c8 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -119,8 +119,17 @@ struct arch_domain
void *tee;
#endif
+ /* Emulated devices enabled bitmap. */
+ uint32_t emulation_flags;
+
} __cacheline_aligned;
+enum {
+ ARM_EMU_VUART = BIT(0, U),
+};
+
+#define domain_has_vuart(d) (!!((d)->arch.emulation_flags & ARM_EMU_VUART))
+
struct arch_vcpu
{
struct {
diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
index 38ce8cc14fac4132578059b696be952b29fab809..1fd980bd3a83820b382f875eb87ce4b8d83ccebe 100644
--- a/xen/arch/arm/vuart.c
+++ b/xen/arch/arm/vuart.c
@@ -31,8 +31,6 @@
#include "vuart.h"
-#define domain_has_vuart(d) ((d)->arch.vuart.info != NULL)
-
static int vuart_mmio_read(struct vcpu *v, mmio_info_t *info,
register_t *r, void *priv);
static int vuart_mmio_write(struct vcpu *v, mmio_info_t *info,
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* [PATCH v2 06/35] riscv/domain: introduce domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin, Oleksii Kurochko
Introduce domain_has_vuart() for RISC-V port to be used in the console driver.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/riscv/include/asm/domain.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h
index c3d965a559b6ce3661bf17166d0c51853ff295a2..efbc4f1ea2619a187fe30ede17d96de01e599220 100644
--- a/xen/arch/riscv/include/asm/domain.h
+++ b/xen/arch/riscv/include/asm/domain.h
@@ -10,6 +10,8 @@ struct hvm_domain
uint64_t params[HVM_NR_PARAMS];
};
+#define domain_has_vuart(d) false
+
struct arch_vcpu_io {
};
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 06/35] riscv/domain: introduce domain_has_vuart()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin, Oleksii Kurochko
From: Denis Mukhin <dmukhin@ford.com>
Introduce domain_has_vuart() for RISC-V port to be used in the console driver.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/riscv/include/asm/domain.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h
index c3d965a559b6ce3661bf17166d0c51853ff295a2..efbc4f1ea2619a187fe30ede17d96de01e599220 100644
--- a/xen/arch/riscv/include/asm/domain.h
+++ b/xen/arch/riscv/include/asm/domain.h
@@ -10,6 +10,8 @@ struct hvm_domain
uint64_t params[HVM_NR_PARAMS];
};
+#define domain_has_vuart(d) false
+
struct arch_vcpu_io {
};
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* [PATCH v2 07/35] ppc/domain: introduce domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Introduce domain_has_vuart() for PPC port to be used in the console driver.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/ppc/include/asm/domain.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xen/arch/ppc/include/asm/domain.h b/xen/arch/ppc/include/asm/domain.h
index 3a447272c6f28586bf0d610929adbf228579e13f..764978e6a61b9d7220ec10fe0763e3424d07d27a 100644
--- a/xen/arch/ppc/include/asm/domain.h
+++ b/xen/arch/ppc/include/asm/domain.h
@@ -10,6 +10,8 @@ struct hvm_domain
uint64_t params[HVM_NR_PARAMS];
};
+#define domain_has_vuart(d) false
+
/* TODO: Implement */
#define guest_mode(r) ({ (void)(r); BUG_ON("unimplemented"); 0; })
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 07/35] ppc/domain: introduce domain_has_vuart()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Introduce domain_has_vuart() for PPC port to be used in the console driver.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/ppc/include/asm/domain.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xen/arch/ppc/include/asm/domain.h b/xen/arch/ppc/include/asm/domain.h
index 3a447272c6f28586bf0d610929adbf228579e13f..764978e6a61b9d7220ec10fe0763e3424d07d27a 100644
--- a/xen/arch/ppc/include/asm/domain.h
+++ b/xen/arch/ppc/include/asm/domain.h
@@ -10,6 +10,8 @@ struct hvm_domain
uint64_t params[HVM_NR_PARAMS];
};
+#define domain_has_vuart(d) false
+
/* TODO: Implement */
#define guest_mode(r) ({ (void)(r); BUG_ON("unimplemented"); 0; })
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 07/35] ppc/domain: introduce domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:24 ` Jan Beulich
-1 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:24 UTC (permalink / raw)
To: dmukhin
Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, Shawn Anastasio,
xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Introduce domain_has_vuart() for PPC port to be used in the console driver.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/ppc/include/asm/domain.h | 2 ++
> 1 file changed, 2 insertions(+)
Please be sure to Cc the maintainer(s) of the file(s) you change. Else
it may be pretty unlikely that you'll ever get an ack.
Jan
> --- a/xen/arch/ppc/include/asm/domain.h
> +++ b/xen/arch/ppc/include/asm/domain.h
> @@ -10,6 +10,8 @@ struct hvm_domain
> uint64_t params[HVM_NR_PARAMS];
> };
>
> +#define domain_has_vuart(d) false
> +
> /* TODO: Implement */
> #define guest_mode(r) ({ (void)(r); BUG_ON("unimplemented"); 0; })
>
>
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 08/35] x86/domain: introduce domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Introduce domain_has_vuart() for x86 port to be used in the console driver.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/include/asm/domain.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index b79d6badd71c4d96279555df62fad75fe817a2b6..c1d0d1f47324e8cc678a4c76c43f86820a89e7b3 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -506,6 +506,9 @@ struct arch_domain
#define has_pirq(d) (!!((d)->arch.emulation_flags & X86_EMU_USE_PIRQ))
#define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
+/* NB: same symbol as in Arm port */
+#define domain_has_vuart(d) false
+
#define gdt_ldt_pt_idx(v) \
((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
#define pv_gdt_ptes(v) \
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 08/35] x86/domain: introduce domain_has_vuart()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Introduce domain_has_vuart() for x86 port to be used in the console driver.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/include/asm/domain.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index b79d6badd71c4d96279555df62fad75fe817a2b6..c1d0d1f47324e8cc678a4c76c43f86820a89e7b3 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -506,6 +506,9 @@ struct arch_domain
#define has_pirq(d) (!!((d)->arch.emulation_flags & X86_EMU_USE_PIRQ))
#define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
+/* NB: same symbol as in Arm port */
+#define domain_has_vuart(d) false
+
#define gdt_ldt_pt_idx(v) \
((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
#define pv_gdt_ptes(v) \
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 08/35] x86/domain: introduce domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:26 ` Jan Beulich
2025-01-04 2:34 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:26 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/arch/x86/include/asm/domain.h
> +++ b/xen/arch/x86/include/asm/domain.h
> @@ -506,6 +506,9 @@ struct arch_domain
> #define has_pirq(d) (!!((d)->arch.emulation_flags & X86_EMU_USE_PIRQ))
> #define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
>
> +/* NB: same symbol as in Arm port */
> +#define domain_has_vuart(d) false
This being the 3rd effectively identical patch, perhaps instead we want
to default domain_has_vuart() to false unless an arch provides its own
definition? Much like we do for a few other such items?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 08/35] x86/domain: introduce domain_has_vuart()
2024-12-10 13:26 ` Jan Beulich
@ 2025-01-04 2:34 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:34 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:26 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/arch/x86/include/asm/domain.h
> > +++ b/xen/arch/x86/include/asm/domain.h
> > @@ -506,6 +506,9 @@ struct arch_domain
> > #define has_pirq(d) (!!((d)->arch.emulation_flags & X86_EMU_USE_PIRQ))
> > #define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
> >
> > +/* NB: same symbol as in Arm port */
> > +#define domain_has_vuart(d) false
>
>
> This being the 3rd effectively identical patch, perhaps instead we want
> to default domain_has_vuart() to false unless an arch provides its own
> definition? Much like we do for a few other such items?
Ideally, domain_has_vuart() should depend on build flags and d->arch.emulation_flags
only. I have reworked the code, so that domain_has_vuart() is defined for all
architectures uniformly.
To do that, I plumbed d->arch.emulation_flags to all arch domain structures
and made arch-independent emulation flags declarations in v3.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 08/35] x86/domain: introduce domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 15:13 ` Roger Pau Monné
2025-01-04 3:11 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 15:13 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:38PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Introduce domain_has_vuart() for x86 port to be used in the console driver.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/x86/include/asm/domain.h | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
> index b79d6badd71c4d96279555df62fad75fe817a2b6..c1d0d1f47324e8cc678a4c76c43f86820a89e7b3 100644
> --- a/xen/arch/x86/include/asm/domain.h
> +++ b/xen/arch/x86/include/asm/domain.h
> @@ -506,6 +506,9 @@ struct arch_domain
> #define has_pirq(d) (!!((d)->arch.emulation_flags & X86_EMU_USE_PIRQ))
> #define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
>
> +/* NB: same symbol as in Arm port */
> +#define domain_has_vuart(d) false
Don't you need to consume d in the macro, ie:
#define domain_has_vuart(d) ((void)(d), false)
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 08/35] x86/domain: introduce domain_has_vuart()
2024-12-11 15:13 ` Roger Pau Monné
@ 2025-01-04 3:11 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:11 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Wednesday, December 11th, 2024 at 7:13 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:38PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Introduce domain_has_vuart() for x86 port to be used in the console driver.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/x86/include/asm/domain.h | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
> > index b79d6badd71c4d96279555df62fad75fe817a2b6..c1d0d1f47324e8cc678a4c76c43f86820a89e7b3 100644
> > --- a/xen/arch/x86/include/asm/domain.h
> > +++ b/xen/arch/x86/include/asm/domain.h
> > @@ -506,6 +506,9 @@ struct arch_domain
> > #define has_pirq(d) (!!((d)->arch.emulation_flags & X86_EMU_USE_PIRQ))
> > #define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
> >
> > +/* NB: same symbol as in Arm port */
> > +#define domain_has_vuart(d) false
>
>
> Don't you need to consume d in the macro, ie:
>
> #define domain_has_vuart(d) ((void)(d), false)
I reworked that code and merged per-arch domain_has_vuart() patches
into one arch-independent domain_has_vuart().
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Print d->arch.emulation_flags on the console for better traceability while
debugging in-hypervisor hardware emulators.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/domain.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 78a13e6812c9120901d0a70fb3bc1bd6a8b6917d..c88d422a64544531c1e1058fa484364bb4277d1e 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
if ( !emulation_flags_ok(d, emflags) )
{
- printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
+ printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
"with the current selection of emulators: %#x\n",
- d->domain_id, is_hvm_domain(d) ? "HVM" : "PV", emflags);
+ d->domain_id,
+ is_hvm_domain(d) ? "HVM" : "PV",
+ is_hardware_domain(d) ? "(hardware) " : "",
+ emflags);
return -EOPNOTSUPP;
}
+ printk(XENLOG_G_INFO "d%d: emulation_flags %#x\n", d->domain_id, emflags);
d->arch.emulation_flags = emflags;
#ifdef CONFIG_PV32
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 09/35] x86/domain: print emulation_flags
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Print d->arch.emulation_flags on the console for better traceability while
debugging in-hypervisor hardware emulators.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/domain.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 78a13e6812c9120901d0a70fb3bc1bd6a8b6917d..c88d422a64544531c1e1058fa484364bb4277d1e 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
if ( !emulation_flags_ok(d, emflags) )
{
- printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
+ printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
"with the current selection of emulators: %#x\n",
- d->domain_id, is_hvm_domain(d) ? "HVM" : "PV", emflags);
+ d->domain_id,
+ is_hvm_domain(d) ? "HVM" : "PV",
+ is_hardware_domain(d) ? "(hardware) " : "",
+ emflags);
return -EOPNOTSUPP;
}
+ printk(XENLOG_G_INFO "d%d: emulation_flags %#x\n", d->domain_id, emflags);
d->arch.emulation_flags = emflags;
#ifdef CONFIG_PV32
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:30 ` Jan Beulich
2025-01-04 3:55 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:30 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> Print d->arch.emulation_flags on the console for better traceability while
> debugging in-hypervisor hardware emulators.
Personally I disagree with such extra printing. And that would in this case
even apply if you used dprintk() or gdprintk(). However, if others support
the idea, I don't mean to stand in the way. Just that ...
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
>
> if ( !emulation_flags_ok(d, emflags) )
> {
> - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
> + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
> "with the current selection of emulators: %#x\n",
> - d->domain_id, is_hvm_domain(d) ? "HVM" : "PV", emflags);
> + d->domain_id,
... if already you touch this, please switch to %pd and also ...
> + is_hvm_domain(d) ? "HVM" : "PV",
> + is_hardware_domain(d) ? "(hardware) " : "",
> + emflags);
> return -EOPNOTSUPP;
> }
> + printk(XENLOG_G_INFO "d%d: emulation_flags %#x\n", d->domain_id, emflags);
.. use that here.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-10 13:30 ` Jan Beulich
@ 2025-01-04 3:55 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:55 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:30 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > Print d->arch.emulation_flags on the console for better traceability while
> > debugging in-hypervisor hardware emulators.
>
>
> Personally I disagree with such extra printing. And that would in this case
I plumbed this printout into 'q' keyhandler which looks much better place
to host this printout.
> even apply if you used dprintk() or gdprintk(). However, if others support
> the idea, I don't mean to stand in the way. Just that ...
>
> > --- a/xen/arch/x86/domain.c
> > +++ b/xen/arch/x86/domain.c
> > @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
> >
> > if ( !emulation_flags_ok(d, emflags) )
> > {
> > - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
> > + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
> > "with the current selection of emulators: %#x\n",
> > - d->domain_id, is_hvm_domain(d) ? "HVM" : "PV", emflags);
> > + d->domain_id,
>
>
> ... if already you touch this, please switch to %pd and also ...
>
> > + is_hvm_domain(d) ? "HVM" : "PV",
> > + is_hardware_domain(d) ? "(hardware) " : "",
> > + emflags);
> > return -EOPNOTSUPP;
> > }
> > + printk(XENLOG_G_INFO "d%d: emulation_flags %#x\n", d->domain_id, emflags);
>
>
> .. use that here.
Oh, that's nice! Thank you.
Fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 15:19 ` Roger Pau Monné
2024-12-12 11:53 ` Jan Beulich
2025-01-04 3:56 ` Denis Mukhin
-1 siblings, 2 replies; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 15:19 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:39PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Print d->arch.emulation_flags on the console for better traceability while
> debugging in-hypervisor hardware emulators.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/x86/domain.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index 78a13e6812c9120901d0a70fb3bc1bd6a8b6917d..c88d422a64544531c1e1058fa484364bb4277d1e 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
>
> if ( !emulation_flags_ok(d, emflags) )
> {
> - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
> + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
gprintk(XENLOG_ERR, "...
Might be more natural now that we have the macro (together with Jan's
suggestion to use %pd (same below).
> "with the current selection of emulators: %#x\n",
> - d->domain_id, is_hvm_domain(d) ? "HVM" : "PV", emflags);
> + d->domain_id,
> + is_hvm_domain(d) ? "HVM" : "PV",
> + is_hardware_domain(d) ? "(hardware) " : "",
> + emflags);
> return -EOPNOTSUPP;
> }
> + printk(XENLOG_G_INFO "d%d: emulation_flags %#x\n", d->domain_id, emflags);
This would need to be a dprintk at least, and the log level should be
XENLOG_DEBUG.
Maybe it would be better if you could print this information as part
of some debug key, for not having to print it for every guest
creation. Maybe as part of the 'q' debug key?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-11 15:19 ` Roger Pau Monné
@ 2024-12-12 11:53 ` Jan Beulich
2024-12-12 12:11 ` Roger Pau Monné
2025-01-04 3:56 ` Denis Mukhin
1 sibling, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-12 11:53 UTC (permalink / raw)
To: Roger Pau Monné
Cc: xen-devel, Andrew Cooper, Julien Grall, Stefano Stabellini,
dmukhin
On 11.12.2024 16:19, Roger Pau Monné wrote:
> On Thu, Dec 05, 2024 at 08:41:39PM -0800, Denis Mukhin via B4 Relay wrote:
>> --- a/xen/arch/x86/domain.c
>> +++ b/xen/arch/x86/domain.c
>> @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
>>
>> if ( !emulation_flags_ok(d, emflags) )
>> {
>> - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
>> + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
>
> gprintk(XENLOG_ERR, "...
>
> Might be more natural now that we have the macro (together with Jan's
> suggestion to use %pd (same below).
Yet why would we want to log current here, as gprintk() does?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-12 11:53 ` Jan Beulich
@ 2024-12-12 12:11 ` Roger Pau Monné
2024-12-12 12:50 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 12:11 UTC (permalink / raw)
To: Jan Beulich
Cc: xen-devel, Andrew Cooper, Julien Grall, Stefano Stabellini,
dmukhin
On Thu, Dec 12, 2024 at 12:53:45PM +0100, Jan Beulich wrote:
> On 11.12.2024 16:19, Roger Pau Monné wrote:
> > On Thu, Dec 05, 2024 at 08:41:39PM -0800, Denis Mukhin via B4 Relay wrote:
> >> --- a/xen/arch/x86/domain.c
> >> +++ b/xen/arch/x86/domain.c
> >> @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
> >>
> >> if ( !emulation_flags_ok(d, emflags) )
> >> {
> >> - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
> >> + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
> >
> > gprintk(XENLOG_ERR, "...
> >
> > Might be more natural now that we have the macro (together with Jan's
> > suggestion to use %pd (same below).
>
> Yet why would we want to log current here, as gprintk() does?
Right - I've forgotten that gprintk already prepends %pd.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-12 12:11 ` Roger Pau Monné
@ 2024-12-12 12:50 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-12 12:50 UTC (permalink / raw)
To: Roger Pau Monné
Cc: xen-devel, Andrew Cooper, Julien Grall, Stefano Stabellini,
dmukhin
On 12.12.2024 13:11, Roger Pau Monné wrote:
> On Thu, Dec 12, 2024 at 12:53:45PM +0100, Jan Beulich wrote:
>> On 11.12.2024 16:19, Roger Pau Monné wrote:
>>> On Thu, Dec 05, 2024 at 08:41:39PM -0800, Denis Mukhin via B4 Relay wrote:
>>>> --- a/xen/arch/x86/domain.c
>>>> +++ b/xen/arch/x86/domain.c
>>>> @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
>>>>
>>>> if ( !emulation_flags_ok(d, emflags) )
>>>> {
>>>> - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
>>>> + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
>>>
>>> gprintk(XENLOG_ERR, "...
>>>
>>> Might be more natural now that we have the macro (together with Jan's
>>> suggestion to use %pd (same below).
>>
>> Yet why would we want to log current here, as gprintk() does?
>
> Right - I've forgotten that gprintk already prepends %pd.
FTAOD: It's %pv and logging current, which isn't what is being logged here
(an incoming struct domain *).
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 09/35] x86/domain: print emulation_flags
2024-12-11 15:19 ` Roger Pau Monné
2024-12-12 11:53 ` Jan Beulich
@ 2025-01-04 3:56 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:56 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Wednesday, December 11th, 2024 at 7:19 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:39PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Print d->arch.emulation_flags on the console for better traceability while
> > debugging in-hypervisor hardware emulators.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/x86/domain.c | 8 ++++++--
> > 1 file changed, 6 insertions(+), 2 deletions(-)
> >
> > diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> > index 78a13e6812c9120901d0a70fb3bc1bd6a8b6917d..c88d422a64544531c1e1058fa484364bb4277d1e 100644
> > --- a/xen/arch/x86/domain.c
> > +++ b/xen/arch/x86/domain.c
> > @@ -818,11 +818,15 @@ int arch_domain_create(struct domain *d,
> >
> > if ( !emulation_flags_ok(d, emflags) )
> > {
> > - printk(XENLOG_G_ERR "d%d: Xen does not allow %s domain creation "
> > + printk(XENLOG_G_ERR "d%d: Xen does not allow %s %sdomain creation "
>
>
> gprintk(XENLOG_ERR, "...
>
> Might be more natural now that we have the macro (together with Jan's
> suggestion to use %pd (same below).
>
> > "with the current selection of emulators: %#x\n",
> > - d->domain_id, is_hvm_domain(d) ? "HVM" : "PV", emflags);
> > + d->domain_id,
> > + is_hvm_domain(d) ? "HVM" : "PV",
> > + is_hardware_domain(d) ? "(hardware) " : "",
> > + emflags);
> > return -EOPNOTSUPP;
> > }
> > + printk(XENLOG_G_INFO "d%d: emulation_flags %#x\n", d->domain_id, emflags);
>
>
> This would need to be a dprintk at least, and the log level should be
> XENLOG_DEBUG.
I moved emulation_flags printout to 'q' handler.
>
> Maybe it would be better if you could print this information as part
> of some debug key, for not having to print it for every guest
> creation. Maybe as part of the 'q' debug key?
Thank you for suggestion!
Fixed.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 10/35] xen/domain: add get_initial_domain_id()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Move get_initial_domain_id() to a public API and enable for all architectures.
That is pre-requisite change for console focus switch logic cleanup.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/include/asm/pv/shim.h | 4 ++--
xen/arch/x86/pv/shim.c | 4 ++--
xen/common/domain.c | 10 ++++++++++
xen/include/xen/domain.h | 2 ++
4 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/xen/arch/x86/include/asm/pv/shim.h b/xen/arch/x86/include/asm/pv/shim.h
index 6153e27005986881ad87e9db0b555b30edc59fc0..1515ad1b0680aa11ab91a152a1944fc1bb477a79 100644
--- a/xen/arch/x86/include/asm/pv/shim.h
+++ b/xen/arch/x86/include/asm/pv/shim.h
@@ -31,7 +31,7 @@ long cf_check pv_shim_cpu_up(void *data);
long cf_check pv_shim_cpu_down(void *data);
void pv_shim_online_memory(unsigned int nr, unsigned int order);
void pv_shim_offline_memory(unsigned int nr, unsigned int order);
-domid_t get_initial_domain_id(void);
+domid_t pv_shim_initial_domain_id(void);
uint64_t pv_shim_mem(uint64_t avail);
void pv_shim_fixup_e820(void);
const struct platform_bad_page *pv_shim_reserved_pages(unsigned int *size);
@@ -76,7 +76,7 @@ static inline void pv_shim_offline_memory(unsigned int nr, unsigned int order)
{
ASSERT_UNREACHABLE();
}
-static inline domid_t get_initial_domain_id(void)
+static inline domid_t pv_shim_initial_domain_id(void)
{
return 0;
}
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index 81e4a0516d18b359561f471f1d96e38977661ca7..17cb30620290c76cf42251f70cfa4199c0e165d1 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -328,7 +328,7 @@ int pv_shim_shutdown(uint8_t reason)
}
/* Update domain id. */
- d->domain_id = get_initial_domain_id();
+ d->domain_id = pv_shim_initial_domain_id();
/* Clean the iomem range. */
BUG_ON(iomem_deny_access(d, 0, ~0UL));
@@ -1016,7 +1016,7 @@ void pv_shim_offline_memory(unsigned int nr, unsigned int order)
}
}
-domid_t get_initial_domain_id(void)
+domid_t pv_shim_initial_domain_id(void)
{
uint32_t eax, ebx, ecx, edx;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 92263a4fbdc57159b4a32d9d4ee038f9f37804ed..2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -45,6 +45,7 @@
#ifdef CONFIG_X86
#include <asm/guest.h>
+#include <asm/pv/shim.h>
#endif
/* Linux config option: propageted to domain0 */
@@ -2229,6 +2230,15 @@ int continue_hypercall_on_cpu(
return 0;
}
+domid_t get_initial_domain_id(void)
+{
+#ifdef CONFIG_X86
+ return pv_shim_initial_domain_id();
+#else
+ return 0;
+#endif
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 3de56352911347a54cce310f0211bcc213d8a08d..601ef431cf621af44c867400499b73b845eb137a 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -171,4 +171,6 @@ extern bool vmtrace_available;
extern bool vpmu_is_available;
+domid_t get_initial_domain_id(void);
+
#endif /* __XEN_DOMAIN_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 10/35] xen/domain: add get_initial_domain_id()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Move get_initial_domain_id() to a public API and enable for all architectures.
That is pre-requisite change for console focus switch logic cleanup.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/include/asm/pv/shim.h | 4 ++--
xen/arch/x86/pv/shim.c | 4 ++--
xen/common/domain.c | 10 ++++++++++
xen/include/xen/domain.h | 2 ++
4 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/xen/arch/x86/include/asm/pv/shim.h b/xen/arch/x86/include/asm/pv/shim.h
index 6153e27005986881ad87e9db0b555b30edc59fc0..1515ad1b0680aa11ab91a152a1944fc1bb477a79 100644
--- a/xen/arch/x86/include/asm/pv/shim.h
+++ b/xen/arch/x86/include/asm/pv/shim.h
@@ -31,7 +31,7 @@ long cf_check pv_shim_cpu_up(void *data);
long cf_check pv_shim_cpu_down(void *data);
void pv_shim_online_memory(unsigned int nr, unsigned int order);
void pv_shim_offline_memory(unsigned int nr, unsigned int order);
-domid_t get_initial_domain_id(void);
+domid_t pv_shim_initial_domain_id(void);
uint64_t pv_shim_mem(uint64_t avail);
void pv_shim_fixup_e820(void);
const struct platform_bad_page *pv_shim_reserved_pages(unsigned int *size);
@@ -76,7 +76,7 @@ static inline void pv_shim_offline_memory(unsigned int nr, unsigned int order)
{
ASSERT_UNREACHABLE();
}
-static inline domid_t get_initial_domain_id(void)
+static inline domid_t pv_shim_initial_domain_id(void)
{
return 0;
}
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index 81e4a0516d18b359561f471f1d96e38977661ca7..17cb30620290c76cf42251f70cfa4199c0e165d1 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -328,7 +328,7 @@ int pv_shim_shutdown(uint8_t reason)
}
/* Update domain id. */
- d->domain_id = get_initial_domain_id();
+ d->domain_id = pv_shim_initial_domain_id();
/* Clean the iomem range. */
BUG_ON(iomem_deny_access(d, 0, ~0UL));
@@ -1016,7 +1016,7 @@ void pv_shim_offline_memory(unsigned int nr, unsigned int order)
}
}
-domid_t get_initial_domain_id(void)
+domid_t pv_shim_initial_domain_id(void)
{
uint32_t eax, ebx, ecx, edx;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 92263a4fbdc57159b4a32d9d4ee038f9f37804ed..2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -45,6 +45,7 @@
#ifdef CONFIG_X86
#include <asm/guest.h>
+#include <asm/pv/shim.h>
#endif
/* Linux config option: propageted to domain0 */
@@ -2229,6 +2230,15 @@ int continue_hypercall_on_cpu(
return 0;
}
+domid_t get_initial_domain_id(void)
+{
+#ifdef CONFIG_X86
+ return pv_shim_initial_domain_id();
+#else
+ return 0;
+#endif
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 3de56352911347a54cce310f0211bcc213d8a08d..601ef431cf621af44c867400499b73b845eb137a 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -171,4 +171,6 @@ extern bool vmtrace_available;
extern bool vpmu_is_available;
+domid_t get_initial_domain_id(void);
+
#endif /* __XEN_DOMAIN_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 10/35] xen/domain: add get_initial_domain_id()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:50 ` Jan Beulich
2025-01-04 2:50 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:50 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> Move get_initial_domain_id() to a public API and enable for all architectures.
> That is pre-requisite change for console focus switch logic cleanup.
Yet then how does this fit with dom0less, let alone hyperlaunch,
where multiple domains may be created right when Xen starts?
Plus, if you make this generic, shouldn't Arm also be adjusted to
use this function (if nothing else then to avoid things going out
of sync later on)?
> @@ -2229,6 +2230,15 @@ int continue_hypercall_on_cpu(
> return 0;
> }
>
> +domid_t get_initial_domain_id(void)
> +{
> +#ifdef CONFIG_X86
> + return pv_shim_initial_domain_id();
> +#else
> + return 0;
> +#endif
> +}
Imo this either wants to use CONFIG_PV_SHIM instead, eliminating the
need for the pv_shim_initial_domain_id() stub.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 10/35] xen/domain: add get_initial_domain_id()
2024-12-10 13:50 ` Jan Beulich
@ 2025-01-04 2:50 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:50 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:50 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > Move get_initial_domain_id() to a public API and enable for all architectures.
> > That is pre-requisite change for console focus switch logic cleanup.
>
>
> Yet then how does this fit with dom0less, let alone hyperlaunch,
> where multiple domains may be created right when Xen starts?
I see it now, thanks; fixed in v3.
>
> Plus, if you make this generic, shouldn't Arm also be adjusted to
> use this function (if nothing else then to avoid things going out
> of sync later on)?
Yes, Arm port should have been adjusted; thanks a lot!
Addressed.
>
> > @@ -2229,6 +2230,15 @@ int continue_hypercall_on_cpu(
> > return 0;
> > }
> >
> > +domid_t get_initial_domain_id(void)
> > +{
> > +#ifdef CONFIG_X86
> > + return pv_shim_initial_domain_id();
> > +#else
> > + return 0;
> > +#endif
> > +}
>
>
> Imo this either wants to use CONFIG_PV_SHIM instead, eliminating the
> need for the pv_shim_initial_domain_id() stub.
Fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 10/35] xen/domain: add get_initial_domain_id()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 16:50 ` Roger Pau Monné
2025-01-04 4:44 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 16:50 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:40PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Move get_initial_domain_id() to a public API and enable for all architectures.
> That is pre-requisite change for console focus switch logic cleanup.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/x86/include/asm/pv/shim.h | 4 ++--
> xen/arch/x86/pv/shim.c | 4 ++--
> xen/common/domain.c | 10 ++++++++++
> xen/include/xen/domain.h | 2 ++
> 4 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/xen/arch/x86/include/asm/pv/shim.h b/xen/arch/x86/include/asm/pv/shim.h
> index 6153e27005986881ad87e9db0b555b30edc59fc0..1515ad1b0680aa11ab91a152a1944fc1bb477a79 100644
> --- a/xen/arch/x86/include/asm/pv/shim.h
> +++ b/xen/arch/x86/include/asm/pv/shim.h
> @@ -31,7 +31,7 @@ long cf_check pv_shim_cpu_up(void *data);
> long cf_check pv_shim_cpu_down(void *data);
> void pv_shim_online_memory(unsigned int nr, unsigned int order);
> void pv_shim_offline_memory(unsigned int nr, unsigned int order);
> -domid_t get_initial_domain_id(void);
> +domid_t pv_shim_initial_domain_id(void);
> uint64_t pv_shim_mem(uint64_t avail);
> void pv_shim_fixup_e820(void);
> const struct platform_bad_page *pv_shim_reserved_pages(unsigned int *size);
> @@ -76,7 +76,7 @@ static inline void pv_shim_offline_memory(unsigned int nr, unsigned int order)
> {
> ASSERT_UNREACHABLE();
> }
> -static inline domid_t get_initial_domain_id(void)
> +static inline domid_t pv_shim_initial_domain_id(void)
> {
> return 0;
> }
> diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
> index 81e4a0516d18b359561f471f1d96e38977661ca7..17cb30620290c76cf42251f70cfa4199c0e165d1 100644
> --- a/xen/arch/x86/pv/shim.c
> +++ b/xen/arch/x86/pv/shim.c
> @@ -328,7 +328,7 @@ int pv_shim_shutdown(uint8_t reason)
> }
>
> /* Update domain id. */
> - d->domain_id = get_initial_domain_id();
> + d->domain_id = pv_shim_initial_domain_id();
Can't you leave this instance using get_initial_domain_id(), it should
DTRT when running in pv-shim mode.
>
> /* Clean the iomem range. */
> BUG_ON(iomem_deny_access(d, 0, ~0UL));
> @@ -1016,7 +1016,7 @@ void pv_shim_offline_memory(unsigned int nr, unsigned int order)
> }
> }
>
> -domid_t get_initial_domain_id(void)
> +domid_t pv_shim_initial_domain_id(void)
> {
> uint32_t eax, ebx, ecx, edx;
>
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index 92263a4fbdc57159b4a32d9d4ee038f9f37804ed..2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -45,6 +45,7 @@
>
> #ifdef CONFIG_X86
> #include <asm/guest.h>
> +#include <asm/pv/shim.h>
> #endif
>
> /* Linux config option: propageted to domain0 */
> @@ -2229,6 +2230,15 @@ int continue_hypercall_on_cpu(
> return 0;
> }
>
> +domid_t get_initial_domain_id(void)
> +{
> +#ifdef CONFIG_X86
> + return pv_shim_initial_domain_id();
> +#else
> + return 0;
> +#endif
> +}
Maybe there are further changes that make this a not suitable option,
but won't it be better to maybe do something like:
#ifndef HAS_ARCH_INITIAL_DOMID
static inline domid_t get_initial_domain_id(void) { return 0; }
#else
domid_t get_initial_domain_id(void);
#endif
In a generic header, and then in an x86 header you just
#define HAS_ARCH_INITIAL_DOMID
The ifdefary in get_initial_domain_id() if other arches need different
implementations seems undesirable.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 10/35] xen/domain: add get_initial_domain_id()
2024-12-11 16:50 ` Roger Pau Monné
@ 2025-01-04 4:44 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:44 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Wednesday, December 11th, 2024 at 8:50 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:40PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Move get_initial_domain_id() to a public API and enable for all architectures.
> > That is pre-requisite change for console focus switch logic cleanup.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/x86/include/asm/pv/shim.h | 4 ++--
> > xen/arch/x86/pv/shim.c | 4 ++--
> > xen/common/domain.c | 10 ++++++++++
> > xen/include/xen/domain.h | 2 ++
> > 4 files changed, 16 insertions(+), 4 deletions(-)
> >
> > diff --git a/xen/arch/x86/include/asm/pv/shim.h b/xen/arch/x86/include/asm/pv/shim.h
> > index 6153e27005986881ad87e9db0b555b30edc59fc0..1515ad1b0680aa11ab91a152a1944fc1bb477a79 100644
> > --- a/xen/arch/x86/include/asm/pv/shim.h
> > +++ b/xen/arch/x86/include/asm/pv/shim.h
> > @@ -31,7 +31,7 @@ long cf_check pv_shim_cpu_up(void *data);
> > long cf_check pv_shim_cpu_down(void *data);
> > void pv_shim_online_memory(unsigned int nr, unsigned int order);
> > void pv_shim_offline_memory(unsigned int nr, unsigned int order);
> > -domid_t get_initial_domain_id(void);
> > +domid_t pv_shim_initial_domain_id(void);
> > uint64_t pv_shim_mem(uint64_t avail);
> > void pv_shim_fixup_e820(void);
> > const struct platform_bad_page *pv_shim_reserved_pages(unsigned int *size);
> > @@ -76,7 +76,7 @@ static inline void pv_shim_offline_memory(unsigned int nr, unsigned int order)
> > {
> > ASSERT_UNREACHABLE();
> > }
> > -static inline domid_t get_initial_domain_id(void)
> > +static inline domid_t pv_shim_initial_domain_id(void)
> > {
> > return 0;
> > }
> > diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
> > index 81e4a0516d18b359561f471f1d96e38977661ca7..17cb30620290c76cf42251f70cfa4199c0e165d1 100644
> > --- a/xen/arch/x86/pv/shim.c
> > +++ b/xen/arch/x86/pv/shim.c
> > @@ -328,7 +328,7 @@ int pv_shim_shutdown(uint8_t reason)
> > }
> >
> > /* Update domain id. */
> > - d->domain_id = get_initial_domain_id();
> > + d->domain_id = pv_shim_initial_domain_id();
>
>
> Can't you leave this instance using get_initial_domain_id(), it should
> DTRT when running in pv-shim mode.
Reverted.
>
> > /* Clean the iomem range. */
> > BUG_ON(iomem_deny_access(d, 0, ~0UL));
> > @@ -1016,7 +1016,7 @@ void pv_shim_offline_memory(unsigned int nr, unsigned int order)
> > }
> > }
> >
> > -domid_t get_initial_domain_id(void)
> > +domid_t pv_shim_initial_domain_id(void)
> > {
> > uint32_t eax, ebx, ecx, edx;
> >
> > diff --git a/xen/common/domain.c b/xen/common/domain.c
> > index 92263a4fbdc57159b4a32d9d4ee038f9f37804ed..2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd 100644
> > --- a/xen/common/domain.c
> > +++ b/xen/common/domain.c
> > @@ -45,6 +45,7 @@
> >
> > #ifdef CONFIG_X86
> > #include <asm/guest.h>
> > +#include <asm/pv/shim.h>
> > #endif
> >
> > /* Linux config option: propageted to domain0 */
> > @@ -2229,6 +2230,15 @@ int continue_hypercall_on_cpu(
> > return 0;
> > }
> >
> > +domid_t get_initial_domain_id(void)
> > +{
> > +#ifdef CONFIG_X86
> > + return pv_shim_initial_domain_id();
> > +#else
> > + return 0;
> > +#endif
> > +}
>
>
> Maybe there are further changes that make this a not suitable option,
> but won't it be better to maybe do something like:
>
> #ifndef HAS_ARCH_INITIAL_DOMID
> static inline domid_t get_initial_domain_id(void) { return 0; }
> #else
> domid_t get_initial_domain_id(void);
> #endif
>
> In a generic header, and then in an x86 header you just
>
> #define HAS_ARCH_INITIAL_DOMID
>
> The ifdefary in get_initial_domain_id() if other arches need different
> implementations seems undesirable.
IMO, existing implementation of get_initial_domain_id() looks like
a layering violation: global get_initial_domain_id() does not belong to PV
shim layer.
The current equivalent of HAS_ARCH_INITIAL_DOMID is CONFIG_PV_SHIM, so I think
there's no need to define another config flag.
After addressing Jan's feedback and then moving the code around,
I kept pv_shim_get_initial_domain_id() in PV shim and #ifdefs
in common/domain.c (similar to domain_shutdown()).
Also, I switched to using hardware_domid instead of open-coded 0.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 11/35] xen/domain: enable max_init_domid for all architectures
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Move max_init_domid to a public API and enable for all architectures.
That is pre-requisite change for console focus switch logic cleanup.
max_init_domid is updated in domain_create().
Signed-off-by: Denis Mukhin <dmukhin@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/domain.c | 9 +++++++++
xen/include/xen/domain.h | 2 ++
7 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 64c227d171fc7b92e5b62d9fd42e5662871bd12b..d4e1670cd69cdd4475b2a5eb316d2c0601090ed7 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -19,8 +19,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 2e27af4560a504bf57daef572d4a768bd886145b..cb218fe3eb36f2cdda47cfa092fa99ee1ca4a14c 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -58,8 +58,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 e4f64879b68ca5aac24bd9544255143e6ef693f3..956fa6985adb23375bd41d3e5d34d9d5f0712bd5 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 844a2f0ef1d762b3a9bc90b61a336a23f1693cc9..978cad71d3df484e80ba19acc0e37b9278e941f0 100644
--- a/xen/arch/riscv/include/asm/setup.h
+++ b/xen/arch/riscv/include/asm/setup.h
@@ -3,8 +3,6 @@
#ifndef ASM__RISCV__SETUP_H
#define ASM__RISCV__SETUP_H
-#define max_init_domid (0)
-
void setup_mm(void);
#endif /* ASM__RISCV__SETUP_H */
diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h
index 5c2391a8684b66efdf4b092409ed33935db6b40c..296348655b9d146c73acc305cc9edd5fd46f7d47 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/domain.c b/xen/common/domain.c
index 2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd..9e57dd4122a726e2fb42efe9c029e775202be0e6 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -65,6 +65,9 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
static struct domain *domain_hash[DOMAIN_HASH_SIZE];
struct domain *domain_list;
+/* Last known non-system domain ID. */
+domid_t __read_mostly max_init_domid;
+
/*
* Insert a domain into the domlist/hash. This allows the domain to be looked
* up by domid, and therefore to be the subject of hypercalls/etc.
@@ -815,6 +818,12 @@ struct domain *domain_create(domid_t domid,
memcpy(d->handle, config->handle, sizeof(d->handle));
+ /*
+ * Housekeeping for physical console forwarding to the domain.
+ */
+ if ( !is_system_domain(d) && max_init_domid < domid )
+ max_init_domid = domid;
+
return d;
fail:
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 601ef431cf621af44c867400499b73b845eb137a..6102826a929ff7aad58a4bc40974815071a97446 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -171,6 +171,8 @@ extern bool vmtrace_available;
extern bool vpmu_is_available;
+extern domid_t max_init_domid;
+
domid_t get_initial_domain_id(void);
#endif /* __XEN_DOMAIN_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 11/35] xen/domain: enable max_init_domid for all architectures
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Move max_init_domid to a public API and enable for all architectures.
That is pre-requisite change for console focus switch logic cleanup.
max_init_domid is updated in domain_create().
Signed-off-by: Denis Mukhin <dmukhin@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/domain.c | 9 +++++++++
xen/include/xen/domain.h | 2 ++
7 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 64c227d171fc7b92e5b62d9fd42e5662871bd12b..d4e1670cd69cdd4475b2a5eb316d2c0601090ed7 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -19,8 +19,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 2e27af4560a504bf57daef572d4a768bd886145b..cb218fe3eb36f2cdda47cfa092fa99ee1ca4a14c 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -58,8 +58,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 e4f64879b68ca5aac24bd9544255143e6ef693f3..956fa6985adb23375bd41d3e5d34d9d5f0712bd5 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 844a2f0ef1d762b3a9bc90b61a336a23f1693cc9..978cad71d3df484e80ba19acc0e37b9278e941f0 100644
--- a/xen/arch/riscv/include/asm/setup.h
+++ b/xen/arch/riscv/include/asm/setup.h
@@ -3,8 +3,6 @@
#ifndef ASM__RISCV__SETUP_H
#define ASM__RISCV__SETUP_H
-#define max_init_domid (0)
-
void setup_mm(void);
#endif /* ASM__RISCV__SETUP_H */
diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h
index 5c2391a8684b66efdf4b092409ed33935db6b40c..296348655b9d146c73acc305cc9edd5fd46f7d47 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/domain.c b/xen/common/domain.c
index 2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd..9e57dd4122a726e2fb42efe9c029e775202be0e6 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -65,6 +65,9 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
static struct domain *domain_hash[DOMAIN_HASH_SIZE];
struct domain *domain_list;
+/* Last known non-system domain ID. */
+domid_t __read_mostly max_init_domid;
+
/*
* Insert a domain into the domlist/hash. This allows the domain to be looked
* up by domid, and therefore to be the subject of hypercalls/etc.
@@ -815,6 +818,12 @@ struct domain *domain_create(domid_t domid,
memcpy(d->handle, config->handle, sizeof(d->handle));
+ /*
+ * Housekeeping for physical console forwarding to the domain.
+ */
+ if ( !is_system_domain(d) && max_init_domid < domid )
+ max_init_domid = domid;
+
return d;
fail:
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 601ef431cf621af44c867400499b73b845eb137a..6102826a929ff7aad58a4bc40974815071a97446 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -171,6 +171,8 @@ extern bool vmtrace_available;
extern bool vpmu_is_available;
+extern domid_t max_init_domid;
+
domid_t get_initial_domain_id(void);
#endif /* __XEN_DOMAIN_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 11/35] xen/domain: enable max_init_domid for all architectures
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:57 ` Jan Beulich
2025-01-04 2:51 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:57 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -65,6 +65,9 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
> static struct domain *domain_hash[DOMAIN_HASH_SIZE];
> struct domain *domain_list;
>
> +/* Last known non-system domain ID. */
> +domid_t __read_mostly max_init_domid;
> +
> /*
> * Insert a domain into the domlist/hash. This allows the domain to be looked
> * up by domid, and therefore to be the subject of hypercalls/etc.
> @@ -815,6 +818,12 @@ struct domain *domain_create(domid_t domid,
>
> memcpy(d->handle, config->handle, sizeof(d->handle));
>
> + /*
> + * Housekeeping for physical console forwarding to the domain.
> + */
> + if ( !is_system_domain(d) && max_init_domid < domid )
> + max_init_domid = domid;
Yet this affects all domains, not just init ones. Either the variable
name is wrong then, or the updating logic needs adjustment. The comment
in the earlier hunk suggests the former, yet then this is a behavioral
change for Arm, correctness of which needs explaining.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 11/35] xen/domain: enable max_init_domid for all architectures
2024-12-10 13:57 ` Jan Beulich
@ 2025-01-04 2:51 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:51 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:57 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/common/domain.c
> > +++ b/xen/common/domain.c
> > @@ -65,6 +65,9 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
> > static struct domain *domain_hash[DOMAIN_HASH_SIZE];
> > struct domain *domain_list;
> >
> > +/* Last known non-system domain ID. /
> > +domid_t __read_mostly max_init_domid;
> > +
> > /
> > * Insert a domain into the domlist/hash. This allows the domain to be looked
> > * up by domid, and therefore to be the subject of hypercalls/etc.
> > @@ -815,6 +818,12 @@ struct domain *domain_create(domid_t domid,
> >
> > memcpy(d->handle, config->handle, sizeof(d->handle));
> >
> > + /*
> > + * Housekeeping for physical console forwarding to the domain.
> > + */
> > + if ( !is_system_domain(d) && max_init_domid < domid )
> > + max_init_domid = domid;
>
>
> Yet this affects all domains, not just init ones. Either the variable
> name is wrong then, or the updating logic needs adjustment. The comment
> in the earlier hunk suggests the former, yet then this is a behavioral
> change for Arm, correctness of which needs explaining.
Thanks, I have reworked that part.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 11/35] xen/domain: enable max_init_domid for all architectures
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 17:00 ` Roger Pau Monné
2025-01-04 3:13 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 17:00 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:41PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Move max_init_domid to a public API and enable for all architectures.
> That is pre-requisite change for console focus switch logic cleanup.
>
> max_init_domid is updated in domain_create().
>
> Signed-off-by: Denis Mukhin <dmukhin@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/domain.c | 9 +++++++++
> xen/include/xen/domain.h | 2 ++
> 7 files changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
> index 64c227d171fc7b92e5b62d9fd42e5662871bd12b..d4e1670cd69cdd4475b2a5eb316d2c0601090ed7 100644
> --- a/xen/arch/arm/include/asm/setup.h
> +++ b/xen/arch/arm/include/asm/setup.h
> @@ -19,8 +19,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 2e27af4560a504bf57daef572d4a768bd886145b..cb218fe3eb36f2cdda47cfa092fa99ee1ca4a14c 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -58,8 +58,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 e4f64879b68ca5aac24bd9544255143e6ef693f3..956fa6985adb23375bd41d3e5d34d9d5f0712bd5 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 844a2f0ef1d762b3a9bc90b61a336a23f1693cc9..978cad71d3df484e80ba19acc0e37b9278e941f0 100644
> --- a/xen/arch/riscv/include/asm/setup.h
> +++ b/xen/arch/riscv/include/asm/setup.h
> @@ -3,8 +3,6 @@
> #ifndef ASM__RISCV__SETUP_H
> #define ASM__RISCV__SETUP_H
>
> -#define max_init_domid (0)
> -
> void setup_mm(void);
>
> #endif /* ASM__RISCV__SETUP_H */
> diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h
> index 5c2391a8684b66efdf4b092409ed33935db6b40c..296348655b9d146c73acc305cc9edd5fd46f7d47 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/domain.c b/xen/common/domain.c
> index 2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd..9e57dd4122a726e2fb42efe9c029e775202be0e6 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -65,6 +65,9 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
> static struct domain *domain_hash[DOMAIN_HASH_SIZE];
> struct domain *domain_list;
>
> +/* Last known non-system domain ID. */
> +domid_t __read_mostly max_init_domid;
The comment (and implementation below) seems to differ from what Arm
dom0less code currently uses the variable for.
> +
> /*
> * Insert a domain into the domlist/hash. This allows the domain to be looked
> * up by domid, and therefore to be the subject of hypercalls/etc.
> @@ -815,6 +818,12 @@ struct domain *domain_create(domid_t domid,
>
> memcpy(d->handle, config->handle, sizeof(d->handle));
>
> + /*
> + * Housekeeping for physical console forwarding to the domain.
> + */
> + if ( !is_system_domain(d) && max_init_domid < domid )
> + max_init_domid = domid;
Don't you need to adjust the ARM dom0-less logic that deal with
increasing max_init_domid in create_domUs().
Also max_init_domid likely only wants to be updated for domains
created before the control domain is started, and hence could be
__ro_after_init instead of __read_mostly?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 11/35] xen/domain: enable max_init_domid for all architectures
2024-12-11 17:00 ` Roger Pau Monné
@ 2025-01-04 3:13 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:13 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Wednesday, December 11th, 2024 at 9:00 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:41PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Move max_init_domid to a public API and enable for all architectures.
> > That is pre-requisite change for console focus switch logic cleanup.
> >
> > max_init_domid is updated in domain_create().
> >
> > Signed-off-by: Denis Mukhin dmukhin@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/domain.c | 9 +++++++++
> > xen/include/xen/domain.h | 2 ++
> > 7 files changed, 11 insertions(+), 10 deletions(-)
> >
> > diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
> > index 64c227d171fc7b92e5b62d9fd42e5662871bd12b..d4e1670cd69cdd4475b2a5eb316d2c0601090ed7 100644
> > --- a/xen/arch/arm/include/asm/setup.h
> > +++ b/xen/arch/arm/include/asm/setup.h
> > @@ -19,8 +19,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 2e27af4560a504bf57daef572d4a768bd886145b..cb218fe3eb36f2cdda47cfa092fa99ee1ca4a14c 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -58,8 +58,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 e4f64879b68ca5aac24bd9544255143e6ef693f3..956fa6985adb23375bd41d3e5d34d9d5f0712bd5 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 844a2f0ef1d762b3a9bc90b61a336a23f1693cc9..978cad71d3df484e80ba19acc0e37b9278e941f0 100644
> > --- a/xen/arch/riscv/include/asm/setup.h
> > +++ b/xen/arch/riscv/include/asm/setup.h
> > @@ -3,8 +3,6 @@
> > #ifndef ASM__RISCV__SETUP_H
> > #define ASM__RISCV__SETUP_H
> >
> > -#define max_init_domid (0)
> > -
> > void setup_mm(void);
> >
> > #endif /* ASM__RISCV__SETUP_H */
> > diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h
> > index 5c2391a8684b66efdf4b092409ed33935db6b40c..296348655b9d146c73acc305cc9edd5fd46f7d47 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/domain.c b/xen/common/domain.c
> > index 2f67aa06ed50e69c27cedc8d7f6eb0b469fe81cd..9e57dd4122a726e2fb42efe9c029e775202be0e6 100644
> > --- a/xen/common/domain.c
> > +++ b/xen/common/domain.c
> > @@ -65,6 +65,9 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
> > static struct domain *domain_hash[DOMAIN_HASH_SIZE];
> > struct domain *domain_list;
> >
> > +/* Last known non-system domain ID. */
> > +domid_t __read_mostly max_init_domid;
>
>
> The comment (and implementation below) seems to differ from what Arm
> dom0less code currently uses the variable for.
Yep, thanks.
I realized that after receiving Jan's feedback.
Reworked.
>
> > +
> > /*
> > * Insert a domain into the domlist/hash. This allows the domain to be looked
> > * up by domid, and therefore to be the subject of hypercalls/etc.
> > @@ -815,6 +818,12 @@ struct domain *domain_create(domid_t domid,
> >
> > memcpy(d->handle, config->handle, sizeof(d->handle));
> >
> > + /*
> > + * Housekeeping for physical console forwarding to the domain.
> > + */
> > + if ( !is_system_domain(d) && max_init_domid < domid )
> > + max_init_domid = domid;
>
>
> Don't you need to adjust the ARM dom0-less logic that deal with
> increasing max_init_domid in create_domUs().
>
> Also max_init_domid likely only wants to be updated for domains
> created before the control domain is started, and hence could be
> __ro_after_init instead of __read_mostly?
I addressed that in v3, thanks!
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 12/35] xen/console: move vpl011-related code to vpl011 emulator
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Xen console driver has vpl011-related logic which shall belong vpl011 emulator
code. Move vpl011-related to vpl011.c.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/include/asm/vpl011.h | 2 +-
xen/arch/arm/vpl011.c | 15 +++++++++++----
xen/drivers/char/console.c | 4 +---
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/xen/arch/arm/include/asm/vpl011.h b/xen/arch/arm/include/asm/vpl011.h
index c09abcd7a9b3356d0809743517934adae00087f5..cc838682815c0d049ba33d3bf9966a64b2e527dd 100644
--- a/xen/arch/arm/include/asm/vpl011.h
+++ b/xen/arch/arm/include/asm/vpl011.h
@@ -69,7 +69,7 @@ struct vpl011_init_info {
int domain_vpl011_init(struct domain *d,
struct vpl011_init_info *info);
void domain_vpl011_deinit(struct domain *d);
-void vpl011_rx_char_xen(struct domain *d, char c);
+int vpl011_rx_char_xen(struct domain *d, char c);
#else
static inline int domain_vpl011_init(struct domain *d,
struct vpl011_init_info *info)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 8ade6f2588b8bbcc58fb0f9edc324502a1992ce7..fe36fe2bd1529a4114884580ded6d6fa55a22f0e 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -567,16 +567,21 @@ static void vpl011_data_avail(struct domain *d,
/*
* vpl011_rx_char_xen adds a char to a domain's vpl011 receive buffer.
- * It is only used when the vpl011 backend is in Xen.
*/
-void vpl011_rx_char_xen(struct domain *d, char c)
+int vpl011_rx_char_xen(struct domain *d, char c)
{
unsigned long flags;
struct vpl011 *vpl011 = &d->arch.vpl011;
struct vpl011_xen_backend *intf = vpl011->backend.xen;
XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
- ASSERT(!vpl011->backend_in_domain);
+ /* Forward input iff the vpl011 backend is in Xen. */
+ if ( vpl011->backend_in_domain )
+ return -ENODEV;
+
+ if ( intf == NULL )
+ return -ENODEV;
+
VPL011_LOCK(d, flags);
in_cons = intf->in_cons;
@@ -584,7 +589,7 @@ void vpl011_rx_char_xen(struct domain *d, char c)
if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == sizeof(intf->in) )
{
VPL011_UNLOCK(d, flags);
- return;
+ return -ENOSPC;
}
intf->in[xencons_mask(in_prod, sizeof(intf->in))] = c;
@@ -596,6 +601,8 @@ void vpl011_rx_char_xen(struct domain *d, char c)
vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, SBSA_UART_FIFO_SIZE);
VPL011_UNLOCK(d, flags);
+
+ return 0;
}
static void vpl011_notification(struct vcpu *v, unsigned int port)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index bb56953bab681a13da8d41431aba4632f1919df9..0af4b551801356f242f1770b3826608136d65653 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -559,9 +559,7 @@ static void __serial_rx(char c)
* 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 != NULL &&
- !d->arch.vpl011.backend_in_domain &&
- d->arch.vpl011.backend.xen != NULL )
+ if ( d != NULL )
vpl011_rx_char_xen(d, c);
else
printk("Cannot send chars to Dom%d: no UART available\n",
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 12/35] xen/console: move vpl011-related code to vpl011 emulator
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Xen console driver has vpl011-related logic which shall belong vpl011 emulator
code. Move vpl011-related to vpl011.c.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/include/asm/vpl011.h | 2 +-
xen/arch/arm/vpl011.c | 15 +++++++++++----
xen/drivers/char/console.c | 4 +---
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/xen/arch/arm/include/asm/vpl011.h b/xen/arch/arm/include/asm/vpl011.h
index c09abcd7a9b3356d0809743517934adae00087f5..cc838682815c0d049ba33d3bf9966a64b2e527dd 100644
--- a/xen/arch/arm/include/asm/vpl011.h
+++ b/xen/arch/arm/include/asm/vpl011.h
@@ -69,7 +69,7 @@ struct vpl011_init_info {
int domain_vpl011_init(struct domain *d,
struct vpl011_init_info *info);
void domain_vpl011_deinit(struct domain *d);
-void vpl011_rx_char_xen(struct domain *d, char c);
+int vpl011_rx_char_xen(struct domain *d, char c);
#else
static inline int domain_vpl011_init(struct domain *d,
struct vpl011_init_info *info)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 8ade6f2588b8bbcc58fb0f9edc324502a1992ce7..fe36fe2bd1529a4114884580ded6d6fa55a22f0e 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -567,16 +567,21 @@ static void vpl011_data_avail(struct domain *d,
/*
* vpl011_rx_char_xen adds a char to a domain's vpl011 receive buffer.
- * It is only used when the vpl011 backend is in Xen.
*/
-void vpl011_rx_char_xen(struct domain *d, char c)
+int vpl011_rx_char_xen(struct domain *d, char c)
{
unsigned long flags;
struct vpl011 *vpl011 = &d->arch.vpl011;
struct vpl011_xen_backend *intf = vpl011->backend.xen;
XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
- ASSERT(!vpl011->backend_in_domain);
+ /* Forward input iff the vpl011 backend is in Xen. */
+ if ( vpl011->backend_in_domain )
+ return -ENODEV;
+
+ if ( intf == NULL )
+ return -ENODEV;
+
VPL011_LOCK(d, flags);
in_cons = intf->in_cons;
@@ -584,7 +589,7 @@ void vpl011_rx_char_xen(struct domain *d, char c)
if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == sizeof(intf->in) )
{
VPL011_UNLOCK(d, flags);
- return;
+ return -ENOSPC;
}
intf->in[xencons_mask(in_prod, sizeof(intf->in))] = c;
@@ -596,6 +601,8 @@ void vpl011_rx_char_xen(struct domain *d, char c)
vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, SBSA_UART_FIFO_SIZE);
VPL011_UNLOCK(d, flags);
+
+ return 0;
}
static void vpl011_notification(struct vcpu *v, unsigned int port)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index bb56953bab681a13da8d41431aba4632f1919df9..0af4b551801356f242f1770b3826608136d65653 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -559,9 +559,7 @@ static void __serial_rx(char c)
* 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 != NULL &&
- !d->arch.vpl011.backend_in_domain &&
- d->arch.vpl011.backend.xen != NULL )
+ if ( d != NULL )
vpl011_rx_char_xen(d, c);
else
printk("Cannot send chars to Dom%d: no UART available\n",
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 12/35] xen/console: move vpl011-related code to vpl011 emulator
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 13:33 ` Jan Beulich
2025-01-04 2:49 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 13:33 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/arch/arm/include/asm/vpl011.h
> +++ b/xen/arch/arm/include/asm/vpl011.h
> @@ -69,7 +69,7 @@ struct vpl011_init_info {
> int domain_vpl011_init(struct domain *d,
> struct vpl011_init_info *info);
> void domain_vpl011_deinit(struct domain *d);
> -void vpl011_rx_char_xen(struct domain *d, char c);
> +int vpl011_rx_char_xen(struct domain *d, char c);
If you make the function return an error indicator, ...
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -559,9 +559,7 @@ static void __serial_rx(char c)
> * 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 != NULL &&
> - !d->arch.vpl011.backend_in_domain &&
> - d->arch.vpl011.backend.xen != NULL )
> + if ( d != NULL )
> vpl011_rx_char_xen(d, c);
> else
> printk("Cannot send chars to Dom%d: no UART available\n",
>
... how come that return value then isn't used anywhere?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 12/35] xen/console: move vpl011-related code to vpl011 emulator
2024-12-10 13:33 ` Jan Beulich
@ 2025-01-04 2:49 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:49 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 5:33 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/arch/arm/include/asm/vpl011.h
> > +++ b/xen/arch/arm/include/asm/vpl011.h
> > @@ -69,7 +69,7 @@ struct vpl011_init_info {
> > int domain_vpl011_init(struct domain *d,
> > struct vpl011_init_info *info);
> > void domain_vpl011_deinit(struct domain *d);
> > -void vpl011_rx_char_xen(struct domain *d, char c);
> > +int vpl011_rx_char_xen(struct domain *d, char c);
>
>
> If you make the function return an error indicator, ...
>
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -559,9 +559,7 @@ static void __serial_rx(char c)
> > * 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 != NULL &&
> > - !d->arch.vpl011.backend_in_domain &&
> > - d->arch.vpl011.backend.xen != NULL )
> > + if ( d != NULL )
> > vpl011_rx_char_xen(d, c);
> > else
> > printk("Cannot send chars to Dom%d: no UART available\n",
>
>
> ... how come that return value then isn't used anywhere?
That I overlooked; fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 13/35] xen/console: rename console_input_domain
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
console_input_domain() takes an RCU lock to protect domain structure.
That implies call to rcu_unlock_domain() after use.
Rename console_input_domain() to rcu_lock_domain_console_owner() to
highlight the need of calling rcu_unlock_domain().
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/vpl011.c | 2 +-
xen/drivers/char/console.c | 2 +-
xen/include/xen/console.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index fe36fe2bd1529a4114884580ded6d6fa55a22f0e..4d682e98553303b4a12f5cd7e5e67ab096cd7cc2 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -78,7 +78,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
unsigned long flags;
struct vpl011 *vpl011 = &d->arch.vpl011;
struct vpl011_xen_backend *intf = vpl011->backend.xen;
- struct domain *input = console_input_domain();
+ struct domain *input = rcu_lock_domain_console_owner();
VPL011_LOCK(d, flags);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 0af4b551801356f242f1770b3826608136d65653..01fcbd5581d11f8f4f2b23592255b5c744430a3e 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -477,7 +477,7 @@ static unsigned int __read_mostly console_rx = 0;
#ifdef CONFIG_SBSA_VUART_CONSOLE
/* Make sure to rcu_unlock_domain after use */
-struct domain *console_input_domain(void)
+struct domain *rcu_lock_domain_console_owner(void)
{
if ( console_rx == 0 )
return NULL;
diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
index 6dfbade3ece36352c74f1124305da945b210f2a7..0e211e44d9703c804e18f52c9743916f8d2a9d4e 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -31,7 +31,7 @@ void console_end_sync(void);
void console_start_log_everything(void);
void console_end_log_everything(void);
-struct domain *console_input_domain(void);
+struct domain *rcu_lock_domain_console_owner(void);
/*
* Steal output from the console. Returns +ve identifier, else -ve error.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 13/35] xen/console: rename console_input_domain
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
console_input_domain() takes an RCU lock to protect domain structure.
That implies call to rcu_unlock_domain() after use.
Rename console_input_domain() to rcu_lock_domain_console_owner() to
highlight the need of calling rcu_unlock_domain().
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/vpl011.c | 2 +-
xen/drivers/char/console.c | 2 +-
xen/include/xen/console.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index fe36fe2bd1529a4114884580ded6d6fa55a22f0e..4d682e98553303b4a12f5cd7e5e67ab096cd7cc2 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -78,7 +78,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
unsigned long flags;
struct vpl011 *vpl011 = &d->arch.vpl011;
struct vpl011_xen_backend *intf = vpl011->backend.xen;
- struct domain *input = console_input_domain();
+ struct domain *input = rcu_lock_domain_console_owner();
VPL011_LOCK(d, flags);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 0af4b551801356f242f1770b3826608136d65653..01fcbd5581d11f8f4f2b23592255b5c744430a3e 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -477,7 +477,7 @@ static unsigned int __read_mostly console_rx = 0;
#ifdef CONFIG_SBSA_VUART_CONSOLE
/* Make sure to rcu_unlock_domain after use */
-struct domain *console_input_domain(void)
+struct domain *rcu_lock_domain_console_owner(void)
{
if ( console_rx == 0 )
return NULL;
diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
index 6dfbade3ece36352c74f1124305da945b210f2a7..0e211e44d9703c804e18f52c9743916f8d2a9d4e 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -31,7 +31,7 @@ void console_end_sync(void);
void console_start_log_everything(void);
void console_end_log_everything(void);
-struct domain *console_input_domain(void);
+struct domain *rcu_lock_domain_console_owner(void);
/*
* Steal output from the console. Returns +ve identifier, else -ve error.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 13/35] xen/console: rename console_input_domain
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 14:01 ` Jan Beulich
2025-01-04 2:53 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 14:01 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> console_input_domain() takes an RCU lock to protect domain structure.
> That implies call to rcu_unlock_domain() after use.
>
> Rename console_input_domain() to rcu_lock_domain_console_owner() to
> highlight the need of calling rcu_unlock_domain().
While I can see where you're coming from, ...
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -477,7 +477,7 @@ static unsigned int __read_mostly console_rx = 0;
>
> #ifdef CONFIG_SBSA_VUART_CONSOLE
> /* Make sure to rcu_unlock_domain after use */
> -struct domain *console_input_domain(void)
> +struct domain *rcu_lock_domain_console_owner(void)
> {
> if ( console_rx == 0 )
> return NULL;
... the new name no longer expresses that a domain pointer is being returned
(out of thin air). I'm uncertain this is an improvement.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 13/35] xen/console: rename console_input_domain
2024-12-10 14:01 ` Jan Beulich
@ 2025-01-04 2:53 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:53 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 6:01 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > console_input_domain() takes an RCU lock to protect domain structure.
> > That implies call to rcu_unlock_domain() after use.
> >
> > Rename console_input_domain() to rcu_lock_domain_console_owner() to
> > highlight the need of calling rcu_unlock_domain().
>
>
> While I can see where you're coming from, ...
>
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -477,7 +477,7 @@ static unsigned int __read_mostly console_rx = 0;
> >
> > #ifdef CONFIG_SBSA_VUART_CONSOLE
> > /* Make sure to rcu_unlock_domain after use */
> > -struct domain *console_input_domain(void)
> > +struct domain *rcu_lock_domain_console_owner(void)
> > {
> > if ( console_rx == 0 )
> > return NULL;
>
>
> ... the new name no longer expresses that a domain pointer is being returned
> (out of thin air). I'm uncertain this is an improvement.
I introduced console_{get,put}_domain() in v3 as per Roger's suggestion.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 13/35] xen/console: rename console_input_domain
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 17:17 ` Roger Pau Monné
2025-01-04 3:13 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 17:17 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:43PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_input_domain() takes an RCU lock to protect domain structure.
> That implies call to rcu_unlock_domain() after use.
>
> Rename console_input_domain() to rcu_lock_domain_console_owner() to
> highlight the need of calling rcu_unlock_domain().
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/arm/vpl011.c | 2 +-
> xen/drivers/char/console.c | 2 +-
> xen/include/xen/console.h | 2 +-
> 3 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index fe36fe2bd1529a4114884580ded6d6fa55a22f0e..4d682e98553303b4a12f5cd7e5e67ab096cd7cc2 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -78,7 +78,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> unsigned long flags;
> struct vpl011 *vpl011 = &d->arch.vpl011;
> struct vpl011_xen_backend *intf = vpl011->backend.xen;
> - struct domain *input = console_input_domain();
> + struct domain *input = rcu_lock_domain_console_owner();
May I suggest console_get_domain() and then introducing a
console_put_domain() which is just a wrapper around
rcu_unlock_domain()?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 13/35] xen/console: rename console_input_domain
2024-12-11 17:17 ` Roger Pau Monné
@ 2025-01-04 3:13 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:13 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Wednesday, December 11th, 2024 at 9:17 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:43PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > console_input_domain() takes an RCU lock to protect domain structure.
> > That implies call to rcu_unlock_domain() after use.
> >
> > Rename console_input_domain() to rcu_lock_domain_console_owner() to
> > highlight the need of calling rcu_unlock_domain().
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/arm/vpl011.c | 2 +-
> > xen/drivers/char/console.c | 2 +-
> > xen/include/xen/console.h | 2 +-
> > 3 files changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index fe36fe2bd1529a4114884580ded6d6fa55a22f0e..4d682e98553303b4a12f5cd7e5e67ab096cd7cc2 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -78,7 +78,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> > unsigned long flags;
> > struct vpl011 *vpl011 = &d->arch.vpl011;
> > struct vpl011_xen_backend *intf = vpl011->backend.xen;
> > - struct domain *input = console_input_domain();
> > + struct domain *input = rcu_lock_domain_console_owner();
>
>
> May I suggest console_get_domain() and then introducing a
> console_put_domain() which is just a wrapper around
> rcu_unlock_domain()?
Agreed, that looks even better! Thanks.
Fixed.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 14/35] xen/console: rename switch_serial_input() to console_find_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Updated the name to highlight the logic of selection the physical console
owner: existing code does not switch only serial console, it also switches
video console and debugging console (debug I/O port and console hypercall).
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 01fcbd5581d11f8f4f2b23592255b5c744430a3e..f8a7db385c9525cabc69ceb1a84d73f57863aa45 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -485,7 +485,7 @@ struct domain *rcu_lock_domain_console_owner(void)
}
#endif
-static void switch_serial_input(void)
+static void console_find_owner(void)
{
unsigned int next_rx = console_rx;
@@ -588,7 +588,7 @@ static void cf_check serial_rx(char c)
/* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
if ( ++switch_code_count == 3 )
{
- switch_serial_input();
+ console_find_owner();
switch_code_count = 0;
}
return;
@@ -1128,7 +1128,7 @@ void __init console_endboot(void)
"toggle host/guest log level adjustment", 0);
/* Serial input is directed to DOM0 by default. */
- switch_serial_input();
+ console_find_owner();
}
int __init console_has(const char *device)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 14/35] xen/console: rename switch_serial_input() to console_find_owner()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Updated the name to highlight the logic of selection the physical console
owner: existing code does not switch only serial console, it also switches
video console and debugging console (debug I/O port and console hypercall).
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 01fcbd5581d11f8f4f2b23592255b5c744430a3e..f8a7db385c9525cabc69ceb1a84d73f57863aa45 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -485,7 +485,7 @@ struct domain *rcu_lock_domain_console_owner(void)
}
#endif
-static void switch_serial_input(void)
+static void console_find_owner(void)
{
unsigned int next_rx = console_rx;
@@ -588,7 +588,7 @@ static void cf_check serial_rx(char c)
/* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
if ( ++switch_code_count == 3 )
{
- switch_serial_input();
+ console_find_owner();
switch_code_count = 0;
}
return;
@@ -1128,7 +1128,7 @@ void __init console_endboot(void)
"toggle host/guest log level adjustment", 0);
/* Serial input is directed to DOM0 by default. */
- switch_serial_input();
+ console_find_owner();
}
int __init console_has(const char *device)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 14/35] xen/console: rename switch_serial_input() to console_find_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 14:13 ` Jan Beulich
2024-12-11 17:22 ` Roger Pau Monné
2025-01-04 2:54 ` Denis Mukhin
-1 siblings, 2 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 14:13 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Updated the name to highlight the logic of selection the physical console
> owner: existing code does not switch only serial console, it also switches
> video console and debugging console (debug I/O port and console hypercall).
I'm especially surprised you mention "video console" here. Afaics all of
this is only about console _input_, and no input comes from a video device.
Arguably "serial" in the original name is too narrow now. Yet "input"
continues to be quite appropriate.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 14/35] xen/console: rename switch_serial_input() to console_find_owner()
2024-12-10 14:13 ` Jan Beulich
@ 2024-12-11 17:22 ` Roger Pau Monné
2025-01-04 3:14 ` Denis Mukhin
2025-01-04 2:54 ` Denis Mukhin
1 sibling, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-11 17:22 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tue, Dec 10, 2024 at 03:13:20PM +0100, Jan Beulich wrote:
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > From: Denis Mukhin <dmukhin@ford.com>
> >
> > Updated the name to highlight the logic of selection the physical console
> > owner: existing code does not switch only serial console, it also switches
> > video console and debugging console (debug I/O port and console hypercall).
>
> I'm especially surprised you mention "video console" here. Afaics all of
> this is only about console _input_, and no input comes from a video device.
> Arguably "serial" in the original name is too narrow now. Yet "input"
> continues to be quite appropriate.
switch_console_input() maybe? switch_console_input_target() even?
I think the switch is also relevant, as it shuffles the input around,
console_find_owner() doesn't seem to convey that meaning.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 14/35] xen/console: rename switch_serial_input() to console_find_owner()
2024-12-11 17:22 ` Roger Pau Monné
@ 2025-01-04 3:14 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:14 UTC (permalink / raw)
To: Roger Pau Monné
Cc: Jan Beulich, dmukhin, Andrew Cooper, Julien Grall,
Stefano Stabellini, xen-devel
On Wednesday, December 11th, 2024 at 9:22 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Tue, Dec 10, 2024 at 03:13:20PM +0100, Jan Beulich wrote:
>
> > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> >
> > > From: Denis Mukhin dmukhin@ford.com
> > >
> > > Updated the name to highlight the logic of selection the physical console
> > > owner: existing code does not switch only serial console, it also switches
> > > video console and debugging console (debug I/O port and console hypercall).
> >
> > I'm especially surprised you mention "video console" here. Afaics all of
> > this is only about console input, and no input comes from a video device.
> > Arguably "serial" in the original name is too narrow now. Yet "input"
> > continues to be quite appropriate.
>
>
> switch_console_input() maybe? switch_console_input_target() even?
>
> I think the switch is also relevant, as it shuffles the input around,
> console_find_owner() doesn't seem to convey that meaning.
Renamed to console_switch_input() in v3
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 14/35] xen/console: rename switch_serial_input() to console_find_owner()
2024-12-10 14:13 ` Jan Beulich
2024-12-11 17:22 ` Roger Pau Monné
@ 2025-01-04 2:54 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:54 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 6:13 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Updated the name to highlight the logic of selection the physical console
> > owner: existing code does not switch only serial console, it also switches
> > video console and debugging console (debug I/O port and console hypercall).
>
>
> I'm especially surprised you mention "video console" here. Afaics all of
> this is only about console input, and no input comes from a video device.
> Arguably "serial" in the original name is too narrow now. Yet "input"
> continues to be quite appropriate.
Yes, sorry, the explanation is wrong.
Fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 15/35] xen/console: rename console_rx to console_owner
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Preparation for the follow on change to switch console_owner to
domid_t address space.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index f8a7db385c9525cabc69ceb1a84d73f57863aa45..86bf899ada8f8221ffc77bcffb1f58777a22198e 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -467,11 +467,11 @@ static void cf_check dump_console_ring_key(unsigned char key)
*/
#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)
+ * console_owner=0 => input to xen
+ * console_owner=1 => input to dom0 (or the sole shim domain)
+ * console_owner=N => input to dom(N-1)
*/
-static unsigned int __read_mostly console_rx = 0;
+static unsigned int __read_mostly console_owner = 0;
#define max_console_rx (max_init_domid + 1)
@@ -479,15 +479,15 @@ static unsigned int __read_mostly console_rx = 0;
/* Make sure to rcu_unlock_domain after use */
struct domain *rcu_lock_domain_console_owner(void)
{
- if ( console_rx == 0 )
+ if ( console_owner == 0 )
return NULL;
- return rcu_lock_domain_by_id(console_rx - 1);
+ return rcu_lock_domain_by_id(console_owner - 1);
}
#endif
static void console_find_owner(void)
{
- unsigned int next_rx = console_rx;
+ unsigned int next_rx = console_owner;
/*
* Rotate among Xen, dom0 and boot-time created domUs while skipping
@@ -500,7 +500,7 @@ static void console_find_owner(void)
if ( next_rx++ >= max_console_rx )
{
- console_rx = 0;
+ console_owner = 0;
printk("*** Serial input to Xen");
break;
}
@@ -515,7 +515,7 @@ static void console_find_owner(void)
if ( d )
{
rcu_unlock_domain(d);
- console_rx = next_rx;
+ console_owner = next_rx;
printk("*** Serial input to DOM%u", domid);
break;
}
@@ -529,7 +529,7 @@ static void console_find_owner(void)
static void __serial_rx(char c)
{
- switch ( console_rx )
+ switch ( console_owner )
{
case 0:
return handle_keypress(c, false);
@@ -552,7 +552,7 @@ static void __serial_rx(char c)
#ifdef CONFIG_SBSA_VUART_CONSOLE
default:
{
- struct domain *d = rcu_lock_domain_by_id(console_rx - 1);
+ struct domain *d = rcu_lock_domain_by_id(console_owner - 1);
/*
* If we have a properly initialized vpl011 console for the
@@ -563,7 +563,7 @@ static void __serial_rx(char c)
vpl011_rx_char_xen(d, c);
else
printk("Cannot send chars to Dom%d: no UART available\n",
- console_rx - 1);
+ console_owner - 1);
if ( d != NULL )
rcu_unlock_domain(d);
@@ -1116,7 +1116,7 @@ void __init console_endboot(void)
* a useful 'how to switch' message.
*/
if ( opt_conswitch[1] == 'x' )
- console_rx = max_console_rx;
+ console_owner = max_console_rx;
register_keyhandler('w', dump_console_ring_key,
"synchronously dump console ring buffer (dmesg)", 0);
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 15/35] xen/console: rename console_rx to console_owner
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Preparation for the follow on change to switch console_owner to
domid_t address space.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index f8a7db385c9525cabc69ceb1a84d73f57863aa45..86bf899ada8f8221ffc77bcffb1f58777a22198e 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -467,11 +467,11 @@ static void cf_check dump_console_ring_key(unsigned char key)
*/
#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)
+ * console_owner=0 => input to xen
+ * console_owner=1 => input to dom0 (or the sole shim domain)
+ * console_owner=N => input to dom(N-1)
*/
-static unsigned int __read_mostly console_rx = 0;
+static unsigned int __read_mostly console_owner = 0;
#define max_console_rx (max_init_domid + 1)
@@ -479,15 +479,15 @@ static unsigned int __read_mostly console_rx = 0;
/* Make sure to rcu_unlock_domain after use */
struct domain *rcu_lock_domain_console_owner(void)
{
- if ( console_rx == 0 )
+ if ( console_owner == 0 )
return NULL;
- return rcu_lock_domain_by_id(console_rx - 1);
+ return rcu_lock_domain_by_id(console_owner - 1);
}
#endif
static void console_find_owner(void)
{
- unsigned int next_rx = console_rx;
+ unsigned int next_rx = console_owner;
/*
* Rotate among Xen, dom0 and boot-time created domUs while skipping
@@ -500,7 +500,7 @@ static void console_find_owner(void)
if ( next_rx++ >= max_console_rx )
{
- console_rx = 0;
+ console_owner = 0;
printk("*** Serial input to Xen");
break;
}
@@ -515,7 +515,7 @@ static void console_find_owner(void)
if ( d )
{
rcu_unlock_domain(d);
- console_rx = next_rx;
+ console_owner = next_rx;
printk("*** Serial input to DOM%u", domid);
break;
}
@@ -529,7 +529,7 @@ static void console_find_owner(void)
static void __serial_rx(char c)
{
- switch ( console_rx )
+ switch ( console_owner )
{
case 0:
return handle_keypress(c, false);
@@ -552,7 +552,7 @@ static void __serial_rx(char c)
#ifdef CONFIG_SBSA_VUART_CONSOLE
default:
{
- struct domain *d = rcu_lock_domain_by_id(console_rx - 1);
+ struct domain *d = rcu_lock_domain_by_id(console_owner - 1);
/*
* If we have a properly initialized vpl011 console for the
@@ -563,7 +563,7 @@ static void __serial_rx(char c)
vpl011_rx_char_xen(d, c);
else
printk("Cannot send chars to Dom%d: no UART available\n",
- console_rx - 1);
+ console_owner - 1);
if ( d != NULL )
rcu_unlock_domain(d);
@@ -1116,7 +1116,7 @@ void __init console_endboot(void)
* a useful 'how to switch' message.
*/
if ( opt_conswitch[1] == 'x' )
- console_rx = max_console_rx;
+ console_owner = max_console_rx;
register_keyhandler('w', dump_console_ring_key,
"synchronously dump console ring buffer (dmesg)", 0);
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 15/35] xen/console: rename console_rx to console_owner
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 14:23 ` Jan Beulich
-1 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 14:23 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> Preparation for the follow on change to switch console_owner to
> domid_t address space.
As with the earlier change - it's one thing to (plan to) change the
number space, and another to go from input only to general console.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 15/35] xen/console: rename console_rx to console_owner
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-12 8:58 ` Roger Pau Monné
2025-01-04 3:20 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 8:58 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:45PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Preparation for the follow on change to switch console_owner to
> domid_t address space.
I'm a bit confused, is the plan to assign the console (so both RX and
TX) exclusively to a domain?
Otherwise this would better be named console_input_target or similar,
if you think console_rx is not clear enough (FWIW, I'm OK with the
name given the current usage).
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 15/35] xen/console: rename console_rx to console_owner
2024-12-12 8:58 ` Roger Pau Monné
@ 2025-01-04 3:20 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:20 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 12:58 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:45PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Preparation for the follow on change to switch console_owner to
> > domid_t address space.
>
>
> I'm a bit confused, is the plan to assign the console (so both RX and
> TX) exclusively to a domain?
The name change is because semantics of console_rx will be changed.
It will be pointing to domain ID instead of an integer number mapped
to domain ID.
I think "console owner" should be easier to follow.
>
> Otherwise this would better be named console_input_target or similar,
> if you think console_rx is not clear enough (FWIW, I'm OK with the
> name given the current usage).
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Introduce new printk() variant for convenient printouts which skip '(XEN)'
prefix on xen console. This is needed for the case when physical console is
owned by a domain w/ in-hypervisor UART emulation enabled.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
automation/eclair_analysis/ECLAIR/deviations.ecl | 2 +-
xen/drivers/char/console.c | 8 ++++++++
xen/include/xen/lib.h | 3 +++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/automation/eclair_analysis/ECLAIR/deviations.ecl b/automation/eclair_analysis/ECLAIR/deviations.ecl
index 2f58f292036e3561118ce9664a92756b1b938739..c59d075262e9e6618ea2a2d27611a537ded3a776 100644
--- a/automation/eclair_analysis/ECLAIR/deviations.ecl
+++ b/automation/eclair_analysis/ECLAIR/deviations.ecl
@@ -522,7 +522,7 @@ safe."
-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(^.*printf\\(.*\\)$)))"}
-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(panic)&&kind(function))))"}
-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(elf_call_log_callback)&&kind(function))))"}
--config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(vprintk_common)&&kind(function))))"}
+-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(^v?printk_common)&&kind(function))))"}
-config=MC3R1.R17.1,macros+={hide , "^va_(arg|start|copy|end)$"}
-doc_end
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 86bf899ada8f8221ffc77bcffb1f58777a22198e..f034ce5aab3f3bf59b0df9fa583ee9ce32dbf665 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -968,6 +968,14 @@ void printk(const char *fmt, ...)
va_end(args);
}
+void printk_common(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vprintk_common("", fmt, args);
+ va_end(args);
+}
+
void guest_printk(const struct domain *d, const char *fmt, ...)
{
va_list args;
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index 81b722ea3e801e9089aaf8758249feb3a758c4f7..8a7ff2e8af9089796ff28ef8d01c00e9845782ca 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -61,6 +61,9 @@ debugtrace_printk(const char *fmt, ...) {}
extern void printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2), cold));
+extern void printk_common(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
#define printk_once(fmt, args...) \
({ \
static bool __read_mostly once_; \
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 16/35] xen/console: introduce printk_common()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Introduce new printk() variant for convenient printouts which skip '(XEN)'
prefix on xen console. This is needed for the case when physical console is
owned by a domain w/ in-hypervisor UART emulation enabled.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
automation/eclair_analysis/ECLAIR/deviations.ecl | 2 +-
xen/drivers/char/console.c | 8 ++++++++
xen/include/xen/lib.h | 3 +++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/automation/eclair_analysis/ECLAIR/deviations.ecl b/automation/eclair_analysis/ECLAIR/deviations.ecl
index 2f58f292036e3561118ce9664a92756b1b938739..c59d075262e9e6618ea2a2d27611a537ded3a776 100644
--- a/automation/eclair_analysis/ECLAIR/deviations.ecl
+++ b/automation/eclair_analysis/ECLAIR/deviations.ecl
@@ -522,7 +522,7 @@ safe."
-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(^.*printf\\(.*\\)$)))"}
-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(panic)&&kind(function))))"}
-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(elf_call_log_callback)&&kind(function))))"}
--config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(vprintk_common)&&kind(function))))"}
+-config=MC3R1.R17.1,reports+={deliberate,"any_area(^.*va_list.*$&&context(ancestor_or_self(name(^v?printk_common)&&kind(function))))"}
-config=MC3R1.R17.1,macros+={hide , "^va_(arg|start|copy|end)$"}
-doc_end
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 86bf899ada8f8221ffc77bcffb1f58777a22198e..f034ce5aab3f3bf59b0df9fa583ee9ce32dbf665 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -968,6 +968,14 @@ void printk(const char *fmt, ...)
va_end(args);
}
+void printk_common(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vprintk_common("", fmt, args);
+ va_end(args);
+}
+
void guest_printk(const struct domain *d, const char *fmt, ...)
{
va_list args;
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index 81b722ea3e801e9089aaf8758249feb3a758c4f7..8a7ff2e8af9089796ff28ef8d01c00e9845782ca 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -61,6 +61,9 @@ debugtrace_printk(const char *fmt, ...) {}
extern void printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2), cold));
+extern void printk_common(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
#define printk_once(fmt, args...) \
({ \
static bool __read_mostly once_; \
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 14:27 ` Jan Beulich
2025-01-04 2:57 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 14:27 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> Introduce new printk() variant for convenient printouts which skip '(XEN)'
> prefix on xen console. This is needed for the case when physical console is
> owned by a domain w/ in-hypervisor UART emulation enabled.
Imo it should still be guest_printk() which is then used from there.
> --- a/xen/include/xen/lib.h
> +++ b/xen/include/xen/lib.h
> @@ -61,6 +61,9 @@ debugtrace_printk(const char *fmt, ...) {}
> extern void printk(const char *fmt, ...)
> __attribute__ ((format (printf, 1, 2), cold));
>
> +extern void printk_common(const char *fmt, ...)
> + __attribute__ ((format (printf, 1, 2)));
No "cold" attribute, compared to printk()?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-10 14:27 ` Jan Beulich
@ 2025-01-04 2:57 ` Denis Mukhin
2025-01-06 9:04 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 2:57 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 6:27 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > Introduce new printk() variant for convenient printouts which skip '(XEN)'
> > prefix on xen console. This is needed for the case when physical console is
> > owned by a domain w/ in-hypervisor UART emulation enabled.
>
>
> Imo it should still be guest_printk() which is then used from there.
I ended up w/ printk_noprefix(): vprintk_common() expects user-defined prefix,
while original printk_common() does not expect prefix. Such inconsistency
may be confusing because both functions are named xxx_common().
>
> > --- a/xen/include/xen/lib.h
> > +++ b/xen/include/xen/lib.h
> > @@ -61,6 +61,9 @@ debugtrace_printk(const char *fmt, ...) {}
> > extern void printk(const char *fmt, ...)
> > attribute ((format (printf, 1, 2), cold));
> >
> > +extern void printk_common(const char *fmt, ...)
> > + attribute ((format (printf, 1, 2)));
>
>
> No "cold" attribute, compared to printk()?
Thanks, fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2025-01-04 2:57 ` Denis Mukhin
@ 2025-01-06 9:04 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 9:04 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On 04.01.2025 03:57, Denis Mukhin wrote:
> On Tuesday, December 10th, 2024 at 6:27 AM, Jan Beulich <jbeulich@suse.com> wrote:
>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>
>>> Introduce new printk() variant for convenient printouts which skip '(XEN)'
>>> prefix on xen console. This is needed for the case when physical console is
>>> owned by a domain w/ in-hypervisor UART emulation enabled.
>>
>>
>> Imo it should still be guest_printk() which is then used from there.
>
> I ended up w/ printk_noprefix(): vprintk_common() expects user-defined prefix,
> while original printk_common() does not expect prefix. Such inconsistency
> may be confusing because both functions are named xxx_common().
Your reply at best partly addresses my comment: I didn't suggest a new name for
the new function, but I rather suggested that you use an existing one instead.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-12 9:14 ` Roger Pau Monné
2024-12-12 11:57 ` Jan Beulich
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 9:14 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Introduce new printk() variant for convenient printouts which skip '(XEN)'
> prefix on xen console. This is needed for the case when physical console is
> owned by a domain w/ in-hypervisor UART emulation enabled.
IIRC the ns8250 can only send or receive one byte (character) at a
time, so you should likely put that on the console as soon as it's
received?
For the hardware domain we explicitly don't buffer writes to the
console (see guest_console_write() hardware domain special handling).
I wonder however how you deal with domains that don't have the console
focus (ie: != console_rx), as for those I think you still want to use
the (d<domid>) prefix?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-12 9:14 ` Roger Pau Monné
@ 2024-12-12 11:57 ` Jan Beulich
2024-12-12 12:15 ` Roger Pau Monné
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-12 11:57 UTC (permalink / raw)
To: Roger Pau Monné, dmukhin
Cc: xen-devel, Andrew Cooper, Julien Grall, Stefano Stabellini
On 12.12.2024 10:14, Roger Pau Monné wrote:
> On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
>> From: Denis Mukhin <dmukhin@ford.com>
>>
>> Introduce new printk() variant for convenient printouts which skip '(XEN)'
>> prefix on xen console. This is needed for the case when physical console is
>> owned by a domain w/ in-hypervisor UART emulation enabled.
>
> IIRC the ns8250 can only send or receive one byte (character) at a
> time, so you should likely put that on the console as soon as it's
> received?
>
> For the hardware domain we explicitly don't buffer writes to the
> console (see guest_console_write() hardware domain special handling).
>
> I wonder however how you deal with domains that don't have the console
> focus (ie: != console_rx), as for those I think you still want to use
> the (d<domid>) prefix?
Imo no matter what domain has the focus, the (d<domid>) prefix should
always be logged. Just to avoid possible confusion.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-12 11:57 ` Jan Beulich
@ 2024-12-12 12:15 ` Roger Pau Monné
2024-12-12 12:52 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 12:15 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On Thu, Dec 12, 2024 at 12:57:25PM +0100, Jan Beulich wrote:
> On 12.12.2024 10:14, Roger Pau Monné wrote:
> > On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
> >> From: Denis Mukhin <dmukhin@ford.com>
> >>
> >> Introduce new printk() variant for convenient printouts which skip '(XEN)'
> >> prefix on xen console. This is needed for the case when physical console is
> >> owned by a domain w/ in-hypervisor UART emulation enabled.
> >
> > IIRC the ns8250 can only send or receive one byte (character) at a
> > time, so you should likely put that on the console as soon as it's
> > received?
> >
> > For the hardware domain we explicitly don't buffer writes to the
> > console (see guest_console_write() hardware domain special handling).
> >
> > I wonder however how you deal with domains that don't have the console
> > focus (ie: != console_rx), as for those I think you still want to use
> > the (d<domid>) prefix?
>
> Imo no matter what domain has the focus, the (d<domid>) prefix should
> always be logged. Just to avoid possible confusion.
WE don't do that currently for the hardware domain, because we avoid
doing any kind of line processing, as characters from the hardware
domain are send straight to the console without waiting for the
newline terminator (like we do for other domains).
Are you suggesting that in case of the console input being shared
between multiple domains they should all be treated as plain domUs and
thus lines should be buffered?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-12 12:15 ` Roger Pau Monné
@ 2024-12-12 12:52 ` Jan Beulich
2024-12-12 15:25 ` Roger Pau Monné
2024-12-13 1:03 ` Stefano Stabellini
0 siblings, 2 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-12 12:52 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On 12.12.2024 13:15, Roger Pau Monné wrote:
> On Thu, Dec 12, 2024 at 12:57:25PM +0100, Jan Beulich wrote:
>> On 12.12.2024 10:14, Roger Pau Monné wrote:
>>> On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
>>>> From: Denis Mukhin <dmukhin@ford.com>
>>>>
>>>> Introduce new printk() variant for convenient printouts which skip '(XEN)'
>>>> prefix on xen console. This is needed for the case when physical console is
>>>> owned by a domain w/ in-hypervisor UART emulation enabled.
>>>
>>> IIRC the ns8250 can only send or receive one byte (character) at a
>>> time, so you should likely put that on the console as soon as it's
>>> received?
>>>
>>> For the hardware domain we explicitly don't buffer writes to the
>>> console (see guest_console_write() hardware domain special handling).
>>>
>>> I wonder however how you deal with domains that don't have the console
>>> focus (ie: != console_rx), as for those I think you still want to use
>>> the (d<domid>) prefix?
>>
>> Imo no matter what domain has the focus, the (d<domid>) prefix should
>> always be logged. Just to avoid possible confusion.
>
> WE don't do that currently for the hardware domain, because we avoid
> doing any kind of line processing, as characters from the hardware
> domain are send straight to the console without waiting for the
> newline terminator (like we do for other domains).
Right, and that's kind of special, and aiui intentionally so. These are
the only un-prefixed lines logged.
> Are you suggesting that in case of the console input being shared
> between multiple domains they should all be treated as plain domUs and
> thus lines should be buffered?
No, I'm actually not suggesting anything here beyond perhaps reducing
the scope of this series to just what the equivalent of vpl011 would be
for the 8250 / 16550 case.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-12 12:52 ` Jan Beulich
@ 2024-12-12 15:25 ` Roger Pau Monné
2024-12-13 1:03 ` Stefano Stabellini
1 sibling, 0 replies; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 15:25 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On Thu, Dec 12, 2024 at 01:52:49PM +0100, Jan Beulich wrote:
> On 12.12.2024 13:15, Roger Pau Monné wrote:
> > On Thu, Dec 12, 2024 at 12:57:25PM +0100, Jan Beulich wrote:
> >> On 12.12.2024 10:14, Roger Pau Monné wrote:
> >>> On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
> >>>> From: Denis Mukhin <dmukhin@ford.com>
> >>>>
> >>>> Introduce new printk() variant for convenient printouts which skip '(XEN)'
> >>>> prefix on xen console. This is needed for the case when physical console is
> >>>> owned by a domain w/ in-hypervisor UART emulation enabled.
> >>>
> >>> IIRC the ns8250 can only send or receive one byte (character) at a
> >>> time, so you should likely put that on the console as soon as it's
> >>> received?
> >>>
> >>> For the hardware domain we explicitly don't buffer writes to the
> >>> console (see guest_console_write() hardware domain special handling).
> >>>
> >>> I wonder however how you deal with domains that don't have the console
> >>> focus (ie: != console_rx), as for those I think you still want to use
> >>> the (d<domid>) prefix?
> >>
> >> Imo no matter what domain has the focus, the (d<domid>) prefix should
> >> always be logged. Just to avoid possible confusion.
> >
> > WE don't do that currently for the hardware domain, because we avoid
> > doing any kind of line processing, as characters from the hardware
> > domain are send straight to the console without waiting for the
> > newline terminator (like we do for other domains).
>
> Right, and that's kind of special, and aiui intentionally so. These are
> the only un-prefixed lines logged.
>
> > Are you suggesting that in case of the console input being shared
> > between multiple domains they should all be treated as plain domUs and
> > thus lines should be buffered?
>
> No, I'm actually not suggesting anything here beyond perhaps reducing
> the scope of this series to just what the equivalent of vpl011 would be
> for the 8250 / 16550 case.
Indeed, reducing the scope would make it easier to get the actual
feature reviewed. There's a huge amount of pre-patching that will
possibly take some time to get agreement on (if suitable).
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-12 12:52 ` Jan Beulich
2024-12-12 15:25 ` Roger Pau Monné
@ 2024-12-13 1:03 ` Stefano Stabellini
2025-01-04 4:11 ` Denis Mukhin
1 sibling, 1 reply; 218+ messages in thread
From: Stefano Stabellini @ 2024-12-13 1:03 UTC (permalink / raw)
To: Jan Beulich
Cc: Roger Pau Monné, dmukhin, xen-devel, Andrew Cooper,
Julien Grall, Stefano Stabellini
[-- Attachment #1: Type: text/plain, Size: 2315 bytes --]
On Thu, 12 Dec 2024, Jan Beulich wrote:
> On 12.12.2024 13:15, Roger Pau Monné wrote:
> > On Thu, Dec 12, 2024 at 12:57:25PM +0100, Jan Beulich wrote:
> >> On 12.12.2024 10:14, Roger Pau Monné wrote:
> >>> On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
> >>>> From: Denis Mukhin <dmukhin@ford.com>
> >>>>
> >>>> Introduce new printk() variant for convenient printouts which skip '(XEN)'
> >>>> prefix on xen console. This is needed for the case when physical console is
> >>>> owned by a domain w/ in-hypervisor UART emulation enabled.
> >>>
> >>> IIRC the ns8250 can only send or receive one byte (character) at a
> >>> time, so you should likely put that on the console as soon as it's
> >>> received?
> >>>
> >>> For the hardware domain we explicitly don't buffer writes to the
> >>> console (see guest_console_write() hardware domain special handling).
> >>>
> >>> I wonder however how you deal with domains that don't have the console
> >>> focus (ie: != console_rx), as for those I think you still want to use
> >>> the (d<domid>) prefix?
> >>
> >> Imo no matter what domain has the focus, the (d<domid>) prefix should
> >> always be logged. Just to avoid possible confusion.
> >
> > WE don't do that currently for the hardware domain, because we avoid
> > doing any kind of line processing, as characters from the hardware
> > domain are send straight to the console without waiting for the
> > newline terminator (like we do for other domains).
>
> Right, and that's kind of special, and aiui intentionally so. These are
> the only un-prefixed lines logged.
I think we should provide a consistent behavior across architectures.
The current behavior with vpl011 and dom0less on ARM is the following:
- no prefix for Dom0 output
- DOM$NUM for DomUs when not in focus, otherwise no prefix
It is OK to change this behavior, but in that case I would ask that we
change it consistently also for ARM.
> > Are you suggesting that in case of the console input being shared
> > between multiple domains they should all be treated as plain domUs and
> > thus lines should be buffered?
>
> No, I'm actually not suggesting anything here beyond perhaps reducing
> the scope of this series to just what the equivalent of vpl011 would be
> for the 8250 / 16550 case.
I agree with this
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 16/35] xen/console: introduce printk_common()
2024-12-13 1:03 ` Stefano Stabellini
@ 2025-01-04 4:11 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:11 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Jan Beulich, Roger Pau Monné, dmukhin, xen-devel,
Andrew Cooper, Julien Grall
On Thursday, December 12th, 2024 at 5:03 PM, Stefano Stabellini <sstabellini@kernel.org> wrote:
>
>
> On Thu, 12 Dec 2024, Jan Beulich wrote:
>
> > On 12.12.2024 13:15, Roger Pau Monné wrote:
> >
> > > On Thu, Dec 12, 2024 at 12:57:25PM +0100, Jan Beulich wrote:
> > >
> > > > On 12.12.2024 10:14, Roger Pau Monné wrote:
> > > >
> > > > > On Thu, Dec 05, 2024 at 08:41:46PM -0800, Denis Mukhin via B4 Relay wrote:
> > > > >
> > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > >
> > > > > > Introduce new printk() variant for convenient printouts which skip '(XEN)'
> > > > > > prefix on xen console. This is needed for the case when physical console is
> > > > > > owned by a domain w/ in-hypervisor UART emulation enabled.
> > > > >
> > > > > IIRC the ns8250 can only send or receive one byte (character) at a
> > > > > time, so you should likely put that on the console as soon as it's
> > > > > received?
> > > > >
> > > > > For the hardware domain we explicitly don't buffer writes to the
> > > > > console (see guest_console_write() hardware domain special handling).
> > > > >
> > > > > I wonder however how you deal with domains that don't have the console
> > > > > focus (ie: != console_rx), as for those I think you still want to use
> > > > > the (d<domid>) prefix?
> > > >
> > > > Imo no matter what domain has the focus, the (d<domid>) prefix should
> > > > always be logged. Just to avoid possible confusion.
> > >
> > > WE don't do that currently for the hardware domain, because we avoid
> > > doing any kind of line processing, as characters from the hardware
> > > domain are send straight to the console without waiting for the
> > > newline terminator (like we do for other domains).
> >
> > Right, and that's kind of special, and aiui intentionally so. These are
> > the only un-prefixed lines logged.
>
>
> I think we should provide a consistent behavior across architectures.
> The current behavior with vpl011 and dom0less on ARM is the following:
>
> - no prefix for Dom0 output
> - DOM$NUM for DomUs when not in focus, otherwise no prefix
>
> It is OK to change this behavior, but in that case I would ask that we
> change it consistently also for ARM.
Addressed in v3.
>
> > > Are you suggesting that in case of the console input being shared
> > > between multiple domains they should all be treated as plain domUs and
> > > thus lines should be buffered?
> >
> > No, I'm actually not suggesting anything here beyond perhaps reducing
> > the scope of this series to just what the equivalent of vpl011 would be
> > for the 8250 / 16550 case.
>
>
> I agree with this
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
There are few places which check pv_shim console under CONFIG_PV_SHIM in xen
console driver. Instead of #ifdef-ing, use new consoled_is_enabled() to
customize the logic.
Header file now can be included w/o CONFIG_X86.
Signature of consoled_guest_{rx,tx} has changed to account for follow-on
console switch logic cleanup.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 10 +++-------
xen/drivers/char/consoled.c | 18 ++++++++++++++----
xen/include/xen/consoled.h | 35 +++++++++++++++++++++++++++++++++--
3 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index f034ce5aab3f3bf59b0df9fa583ee9ce32dbf665..60c055396b697869b04b9132b0dcfa832fabe932 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -33,9 +33,9 @@
#include <xen/pv_console.h>
#include <asm/setup.h>
#include <xen/sections.h>
+#include <xen/consoled.h>
#ifdef CONFIG_X86
-#include <xen/consoled.h>
#include <asm/guest.h>
#endif
#ifdef CONFIG_SBSA_VUART_CONSOLE
@@ -505,11 +505,9 @@ static void console_find_owner(void)
break;
}
-#ifdef CONFIG_PV_SHIM
- if ( next_rx == 1 )
+ if ( consoled_is_enabled() && next_rx == 1 )
domid = get_initial_domain_id();
else
-#endif
domid = next_rx - 1;
d = rcu_lock_domain_by_id(domid);
if ( d )
@@ -573,10 +571,8 @@ static void __serial_rx(char c)
#endif
}
-#ifdef CONFIG_X86
- if ( pv_shim && pv_console )
+ if ( consoled_is_enabled() )
consoled_guest_tx(c);
-#endif
}
static void cf_check serial_rx(char c)
diff --git a/xen/drivers/char/consoled.c b/xen/drivers/char/consoled.c
index b415b632cecc0a80e161b701d7b70ba4f3cc5fb8..d6624e7697f56e1a1959b0efa5dca104f34af002 100644
--- a/xen/drivers/char/consoled.c
+++ b/xen/drivers/char/consoled.c
@@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
static char buf[BUF_SZ + 1];
/* Receives characters from a domain's PV console */
-void consoled_guest_rx(void)
+int consoled_guest_rx(void)
{
size_t idx = 0;
XENCONS_RING_IDX cons, prod;
if ( !cons_ring )
- return;
+ return 0;
spin_lock(&rx_lock);
@@ -91,15 +91,17 @@ void consoled_guest_rx(void)
out:
spin_unlock(&rx_lock);
+
+ return 0;
}
/* Sends a character into a domain's PV console */
-void consoled_guest_tx(char c)
+int consoled_guest_tx(char c)
{
XENCONS_RING_IDX cons, prod;
if ( !cons_ring )
- return;
+ return 0;
cons = ACCESS_ONCE(cons_ring->in_cons);
prod = cons_ring->in_prod;
@@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
+
/* Write to the ring before updating the pointer */
smp_wmb();
ACCESS_ONCE(cons_ring->in_prod) = prod;
@@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
notify:
/* Always notify the guest: prevents receive path from getting stuck. */
pv_shim_inject_evtchn(pv_console_evtchn());
+
+ return 0;
+}
+
+bool consoled_is_enabled(void)
+{
+ return pv_shim && pv_console;
}
/*
diff --git a/xen/include/xen/consoled.h b/xen/include/xen/consoled.h
index bd7ab6329ee8a7c466484021247241ded8ed03c7..696677fa5a3be458a0ec93360e08376c3471f95b 100644
--- a/xen/include/xen/consoled.h
+++ b/xen/include/xen/consoled.h
@@ -3,10 +3,41 @@
#include <public/io/console.h>
+#if defined(CONFIG_PV_SHIM)
+
void consoled_set_ring_addr(struct xencons_interface *ring);
struct xencons_interface *consoled_get_ring_addr(void);
-void consoled_guest_rx(void);
-void consoled_guest_tx(char c);
+int consoled_guest_rx(void);
+int consoled_guest_tx(char c);
+bool consoled_is_enabled(void);
+
+#else
+
+static inline void consoled_set_ring_addr(struct xencons_interface *ring)
+{
+}
+
+static inline struct xencons_interface *consoled_get_ring_addr(void)
+{
+ return NULL;
+}
+
+static inline int consoled_guest_rx(void)
+{
+ return 0;
+}
+
+static inline int consoled_guest_tx(char c)
+{
+ return 0;
+}
+
+static inline bool consoled_is_enabled(void)
+{
+ return false;
+}
+
+#endif /* #if defined(CONFIG_PV_SHIM) */
#endif /* __XEN_CONSOLED_H__ */
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
There are few places which check pv_shim console under CONFIG_PV_SHIM in xen
console driver. Instead of #ifdef-ing, use new consoled_is_enabled() to
customize the logic.
Header file now can be included w/o CONFIG_X86.
Signature of consoled_guest_{rx,tx} has changed to account for follow-on
console switch logic cleanup.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 10 +++-------
xen/drivers/char/consoled.c | 18 ++++++++++++++----
xen/include/xen/consoled.h | 35 +++++++++++++++++++++++++++++++++--
3 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index f034ce5aab3f3bf59b0df9fa583ee9ce32dbf665..60c055396b697869b04b9132b0dcfa832fabe932 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -33,9 +33,9 @@
#include <xen/pv_console.h>
#include <asm/setup.h>
#include <xen/sections.h>
+#include <xen/consoled.h>
#ifdef CONFIG_X86
-#include <xen/consoled.h>
#include <asm/guest.h>
#endif
#ifdef CONFIG_SBSA_VUART_CONSOLE
@@ -505,11 +505,9 @@ static void console_find_owner(void)
break;
}
-#ifdef CONFIG_PV_SHIM
- if ( next_rx == 1 )
+ if ( consoled_is_enabled() && next_rx == 1 )
domid = get_initial_domain_id();
else
-#endif
domid = next_rx - 1;
d = rcu_lock_domain_by_id(domid);
if ( d )
@@ -573,10 +571,8 @@ static void __serial_rx(char c)
#endif
}
-#ifdef CONFIG_X86
- if ( pv_shim && pv_console )
+ if ( consoled_is_enabled() )
consoled_guest_tx(c);
-#endif
}
static void cf_check serial_rx(char c)
diff --git a/xen/drivers/char/consoled.c b/xen/drivers/char/consoled.c
index b415b632cecc0a80e161b701d7b70ba4f3cc5fb8..d6624e7697f56e1a1959b0efa5dca104f34af002 100644
--- a/xen/drivers/char/consoled.c
+++ b/xen/drivers/char/consoled.c
@@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
static char buf[BUF_SZ + 1];
/* Receives characters from a domain's PV console */
-void consoled_guest_rx(void)
+int consoled_guest_rx(void)
{
size_t idx = 0;
XENCONS_RING_IDX cons, prod;
if ( !cons_ring )
- return;
+ return 0;
spin_lock(&rx_lock);
@@ -91,15 +91,17 @@ void consoled_guest_rx(void)
out:
spin_unlock(&rx_lock);
+
+ return 0;
}
/* Sends a character into a domain's PV console */
-void consoled_guest_tx(char c)
+int consoled_guest_tx(char c)
{
XENCONS_RING_IDX cons, prod;
if ( !cons_ring )
- return;
+ return 0;
cons = ACCESS_ONCE(cons_ring->in_cons);
prod = cons_ring->in_prod;
@@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
+
/* Write to the ring before updating the pointer */
smp_wmb();
ACCESS_ONCE(cons_ring->in_prod) = prod;
@@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
notify:
/* Always notify the guest: prevents receive path from getting stuck. */
pv_shim_inject_evtchn(pv_console_evtchn());
+
+ return 0;
+}
+
+bool consoled_is_enabled(void)
+{
+ return pv_shim && pv_console;
}
/*
diff --git a/xen/include/xen/consoled.h b/xen/include/xen/consoled.h
index bd7ab6329ee8a7c466484021247241ded8ed03c7..696677fa5a3be458a0ec93360e08376c3471f95b 100644
--- a/xen/include/xen/consoled.h
+++ b/xen/include/xen/consoled.h
@@ -3,10 +3,41 @@
#include <public/io/console.h>
+#if defined(CONFIG_PV_SHIM)
+
void consoled_set_ring_addr(struct xencons_interface *ring);
struct xencons_interface *consoled_get_ring_addr(void);
-void consoled_guest_rx(void);
-void consoled_guest_tx(char c);
+int consoled_guest_rx(void);
+int consoled_guest_tx(char c);
+bool consoled_is_enabled(void);
+
+#else
+
+static inline void consoled_set_ring_addr(struct xencons_interface *ring)
+{
+}
+
+static inline struct xencons_interface *consoled_get_ring_addr(void)
+{
+ return NULL;
+}
+
+static inline int consoled_guest_rx(void)
+{
+ return 0;
+}
+
+static inline int consoled_guest_tx(char c)
+{
+ return 0;
+}
+
+static inline bool consoled_is_enabled(void)
+{
+ return false;
+}
+
+#endif /* #if defined(CONFIG_PV_SHIM) */
#endif /* __XEN_CONSOLED_H__ */
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 14:31 ` Jan Beulich
2025-01-04 3:00 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 14:31 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/drivers/char/consoled.c
> +++ b/xen/drivers/char/consoled.c
> @@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
> static char buf[BUF_SZ + 1];
>
> /* Receives characters from a domain's PV console */
> -void consoled_guest_rx(void)
> +int consoled_guest_rx(void)
> {
> size_t idx = 0;
> XENCONS_RING_IDX cons, prod;
>
> if ( !cons_ring )
> - return;
> + return 0;
>
> spin_lock(&rx_lock);
>
> @@ -91,15 +91,17 @@ void consoled_guest_rx(void)
>
> out:
> spin_unlock(&rx_lock);
> +
> + return 0;
> }
>
> /* Sends a character into a domain's PV console */
> -void consoled_guest_tx(char c)
> +int consoled_guest_tx(char c)
> {
> XENCONS_RING_IDX cons, prod;
>
> if ( !cons_ring )
> - return;
> + return 0;
>
> cons = ACCESS_ONCE(cons_ring->in_cons);
> prod = cons_ring->in_prod;
> @@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
>
> cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
>
> +
> /* Write to the ring before updating the pointer */
No excess blank lines please.
> @@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
> notify:
> /* Always notify the guest: prevents receive path from getting stuck. */
> pv_shim_inject_evtchn(pv_console_evtchn());
> +
> + return 0;
> +}
For both of the functions - what use is it to make the functions return
a value, when all they'd ever return is zero (and callers don't care)?
I'm also having a hard time seeing how this adjustment is related to ...
> +bool consoled_is_enabled(void)
> +{
> + return pv_shim && pv_console;
> }
... the introduction of this function (which by itself is probably fine).
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
2024-12-10 14:31 ` Jan Beulich
@ 2025-01-04 3:00 ` Denis Mukhin
2025-01-06 9:05 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:00 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 6:31 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/drivers/char/consoled.c
> > +++ b/xen/drivers/char/consoled.c
> > @@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
> > static char buf[BUF_SZ + 1];
> >
> > /* Receives characters from a domain's PV console */
> > -void consoled_guest_rx(void)
> > +int consoled_guest_rx(void)
> > {
> > size_t idx = 0;
> > XENCONS_RING_IDX cons, prod;
> >
> > if ( !cons_ring )
> > - return;
> > + return 0;
> >
> > spin_lock(&rx_lock);
> >
> > @@ -91,15 +91,17 @@ void consoled_guest_rx(void)
> >
> > out:
> > spin_unlock(&rx_lock);
> > +
> > + return 0;
> > }
> >
> > /* Sends a character into a domain's PV console */
> > -void consoled_guest_tx(char c)
> > +int consoled_guest_tx(char c)
> > {
> > XENCONS_RING_IDX cons, prod;
> >
> > if ( !cons_ring )
> > - return;
> > + return 0;
> >
> > cons = ACCESS_ONCE(cons_ring->in_cons);
> > prod = cons_ring->in_prod;
> > @@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
> >
> > cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
> >
> > +
> > /* Write to the ring before updating the pointer */
>
>
> No excess blank lines please.
Fixed.
>
> > @@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
> > notify:
> > /* Always notify the guest: prevents receive path from getting stuck. */
> > pv_shim_inject_evtchn(pv_console_evtchn());
> > +
> > + return 0;
> > +}
>
>
> For both of the functions - what use is it to make the functions return
> a value, when all they'd ever return is zero (and callers don't care)?
Fixed.
> I'm also having a hard time seeing how this adjustment is related to ...
>
> > +bool consoled_is_enabled(void)
> > +{
> > + return pv_shim && pv_console;
> > }
>
>
> ... the introduction of this function (which by itself is probably fine).
That will be a cleanup in console driver on the code path I touched wrt console
focus switch.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
2025-01-04 3:00 ` Denis Mukhin
@ 2025-01-06 9:05 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 9:05 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On 04.01.2025 04:00, Denis Mukhin wrote:
> On Tuesday, December 10th, 2024 at 6:31 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>>
>>
>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>
>>> --- a/xen/drivers/char/consoled.c
>>> +++ b/xen/drivers/char/consoled.c
>>> @@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
>>> static char buf[BUF_SZ + 1];
>>>
>>> /* Receives characters from a domain's PV console */
>>> -void consoled_guest_rx(void)
>>> +int consoled_guest_rx(void)
>>> {
>>> size_t idx = 0;
>>> XENCONS_RING_IDX cons, prod;
>>>
>>> if ( !cons_ring )
>>> - return;
>>> + return 0;
>>>
>>> spin_lock(&rx_lock);
>>>
>>> @@ -91,15 +91,17 @@ void consoled_guest_rx(void)
>>>
>>> out:
>>> spin_unlock(&rx_lock);
>>> +
>>> + return 0;
>>> }
>>>
>>> /* Sends a character into a domain's PV console */
>>> -void consoled_guest_tx(char c)
>>> +int consoled_guest_tx(char c)
>>> {
>>> XENCONS_RING_IDX cons, prod;
>>>
>>> if ( !cons_ring )
>>> - return;
>>> + return 0;
>>>
>>> cons = ACCESS_ONCE(cons_ring->in_cons);
>>> prod = cons_ring->in_prod;
>>> @@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
>>>
>>> cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
>>>
>>> +
>>> /* Write to the ring before updating the pointer */
>>
>>
>> No excess blank lines please.
>
> Fixed.
>
>>
>>> @@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
>>> notify:
>>> /* Always notify the guest: prevents receive path from getting stuck. */
>>> pv_shim_inject_evtchn(pv_console_evtchn());
>>> +
>>> + return 0;
>>> +}
>>
>>
>> For both of the functions - what use is it to make the functions return
>> a value, when all they'd ever return is zero (and callers don't care)?
>
> Fixed.
>
>> I'm also having a hard time seeing how this adjustment is related to ...
>>
>>> +bool consoled_is_enabled(void)
>>> +{
>>> + return pv_shim && pv_console;
>>> }
>>
>>
>> ... the introduction of this function (which by itself is probably fine).
>
> That will be a cleanup in console driver on the code path I touched wrt console
> focus switch.
Yet then please don't mix entirely independent things in a single patch.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-12 9:31 ` Roger Pau Monné
2025-01-04 3:21 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 9:31 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:47PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> There are few places which check pv_shim console under CONFIG_PV_SHIM in xen
> console driver. Instead of #ifdef-ing, use new consoled_is_enabled() to
> customize the logic.
>
> Header file now can be included w/o CONFIG_X86.
>
> Signature of consoled_guest_{rx,tx} has changed to account for follow-on
> console switch logic cleanup.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 10 +++-------
> xen/drivers/char/consoled.c | 18 ++++++++++++++----
> xen/include/xen/consoled.h | 35 +++++++++++++++++++++++++++++++++--
> 3 files changed, 50 insertions(+), 13 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index f034ce5aab3f3bf59b0df9fa583ee9ce32dbf665..60c055396b697869b04b9132b0dcfa832fabe932 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -33,9 +33,9 @@
> #include <xen/pv_console.h>
> #include <asm/setup.h>
> #include <xen/sections.h>
> +#include <xen/consoled.h>
>
> #ifdef CONFIG_X86
> -#include <xen/consoled.h>
> #include <asm/guest.h>
> #endif
> #ifdef CONFIG_SBSA_VUART_CONSOLE
> @@ -505,11 +505,9 @@ static void console_find_owner(void)
> break;
> }
>
> -#ifdef CONFIG_PV_SHIM
> - if ( next_rx == 1 )
> + if ( consoled_is_enabled() && next_rx == 1 )
> domid = get_initial_domain_id();
> else
> -#endif
> domid = next_rx - 1;
> d = rcu_lock_domain_by_id(domid);
> if ( d )
> @@ -573,10 +571,8 @@ static void __serial_rx(char c)
> #endif
> }
>
> -#ifdef CONFIG_X86
> - if ( pv_shim && pv_console )
> + if ( consoled_is_enabled() )
> consoled_guest_tx(c);
> -#endif
> }
>
> static void cf_check serial_rx(char c)
> diff --git a/xen/drivers/char/consoled.c b/xen/drivers/char/consoled.c
> index b415b632cecc0a80e161b701d7b70ba4f3cc5fb8..d6624e7697f56e1a1959b0efa5dca104f34af002 100644
> --- a/xen/drivers/char/consoled.c
> +++ b/xen/drivers/char/consoled.c
> @@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
> static char buf[BUF_SZ + 1];
>
> /* Receives characters from a domain's PV console */
> -void consoled_guest_rx(void)
> +int consoled_guest_rx(void)
> {
> size_t idx = 0;
> XENCONS_RING_IDX cons, prod;
>
> if ( !cons_ring )
> - return;
> + return 0;
>
> spin_lock(&rx_lock);
>
> @@ -91,15 +91,17 @@ void consoled_guest_rx(void)
>
> out:
> spin_unlock(&rx_lock);
> +
> + return 0;
> }
>
> /* Sends a character into a domain's PV console */
> -void consoled_guest_tx(char c)
> +int consoled_guest_tx(char c)
> {
> XENCONS_RING_IDX cons, prod;
>
> if ( !cons_ring )
> - return;
> + return 0;
>
> cons = ACCESS_ONCE(cons_ring->in_cons);
> prod = cons_ring->in_prod;
> @@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
>
> cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
>
> +
> /* Write to the ring before updating the pointer */
> smp_wmb();
> ACCESS_ONCE(cons_ring->in_prod) = prod;
> @@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
> notify:
> /* Always notify the guest: prevents receive path from getting stuck. */
> pv_shim_inject_evtchn(pv_console_evtchn());
> +
> + return 0;
> +}
> +
> +bool consoled_is_enabled(void)
> +{
> + return pv_shim && pv_console;
> }
>
> /*
> diff --git a/xen/include/xen/consoled.h b/xen/include/xen/consoled.h
> index bd7ab6329ee8a7c466484021247241ded8ed03c7..696677fa5a3be458a0ec93360e08376c3471f95b 100644
> --- a/xen/include/xen/consoled.h
> +++ b/xen/include/xen/consoled.h
> @@ -3,10 +3,41 @@
>
> #include <public/io/console.h>
>
> +#if defined(CONFIG_PV_SHIM)
> +
> void consoled_set_ring_addr(struct xencons_interface *ring);
> struct xencons_interface *consoled_get_ring_addr(void);
> -void consoled_guest_rx(void);
> -void consoled_guest_tx(char c);
> +int consoled_guest_rx(void);
> +int consoled_guest_tx(char c);
> +bool consoled_is_enabled(void);
> +
> +#else
> +
> +static inline void consoled_set_ring_addr(struct xencons_interface *ring)
> +{
> +}
> +
> +static inline struct xencons_interface *consoled_get_ring_addr(void)
> +{
> + return NULL;
> +}
> +
> +static inline int consoled_guest_rx(void)
> +{
> + return 0;
> +}
You don't need to provide dummy implementations of
consoled_{set,get}_ring_addr() and consoled_guest_rx(), they are only
called from code that's build when CONFIG_PV_SHIM is selected.
> +static inline int consoled_guest_tx(char c)
> +{
> + return 0;
For consoled_guest_tx() you want to add an ASSERT_UNREACHABLE(), as
it should never be called if !CONFIG_PV_SHIM?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 17/35] xen/console: introduce consoled_is_enabled()
2024-12-12 9:31 ` Roger Pau Monné
@ 2025-01-04 3:21 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:21 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 1:31 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:47PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > There are few places which check pv_shim console under CONFIG_PV_SHIM in xen
> > console driver. Instead of #ifdef-ing, use new consoled_is_enabled() to
> > customize the logic.
> >
> > Header file now can be included w/o CONFIG_X86.
> >
> > Signature of consoled_guest_{rx,tx} has changed to account for follow-on
> > console switch logic cleanup.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 10 +++-------
> > xen/drivers/char/consoled.c | 18 ++++++++++++++----
> > xen/include/xen/consoled.h | 35 +++++++++++++++++++++++++++++++++--
> > 3 files changed, 50 insertions(+), 13 deletions(-)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index f034ce5aab3f3bf59b0df9fa583ee9ce32dbf665..60c055396b697869b04b9132b0dcfa832fabe932 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -33,9 +33,9 @@
> > #include <xen/pv_console.h>
> > #include <asm/setup.h>
> > #include <xen/sections.h>
> > +#include <xen/consoled.h>
> >
> > #ifdef CONFIG_X86
> > -#include <xen/consoled.h>
> > #include <asm/guest.h>
> > #endif
> > #ifdef CONFIG_SBSA_VUART_CONSOLE
> > @@ -505,11 +505,9 @@ static void console_find_owner(void)
> > break;
> > }
> >
> > -#ifdef CONFIG_PV_SHIM
> > - if ( next_rx == 1 )
> > + if ( consoled_is_enabled() && next_rx == 1 )
> > domid = get_initial_domain_id();
> > else
> > -#endif
> > domid = next_rx - 1;
> > d = rcu_lock_domain_by_id(domid);
> > if ( d )
> > @@ -573,10 +571,8 @@ static void __serial_rx(char c)
> > #endif
> > }
> >
> > -#ifdef CONFIG_X86
> > - if ( pv_shim && pv_console )
> > + if ( consoled_is_enabled() )
> > consoled_guest_tx(c);
> > -#endif
> > }
> >
> > static void cf_check serial_rx(char c)
> > diff --git a/xen/drivers/char/consoled.c b/xen/drivers/char/consoled.c
> > index b415b632cecc0a80e161b701d7b70ba4f3cc5fb8..d6624e7697f56e1a1959b0efa5dca104f34af002 100644
> > --- a/xen/drivers/char/consoled.c
> > +++ b/xen/drivers/char/consoled.c
> > @@ -43,13 +43,13 @@ struct xencons_interface *consoled_get_ring_addr(void)
> > static char buf[BUF_SZ + 1];
> >
> > /* Receives characters from a domain's PV console */
> > -void consoled_guest_rx(void)
> > +int consoled_guest_rx(void)
> > {
> > size_t idx = 0;
> > XENCONS_RING_IDX cons, prod;
> >
> > if ( !cons_ring )
> > - return;
> > + return 0;
> >
> > spin_lock(&rx_lock);
> >
> > @@ -91,15 +91,17 @@ void consoled_guest_rx(void)
> >
> > out:
> > spin_unlock(&rx_lock);
> > +
> > + return 0;
> > }
> >
> > /* Sends a character into a domain's PV console */
> > -void consoled_guest_tx(char c)
> > +int consoled_guest_tx(char c)
> > {
> > XENCONS_RING_IDX cons, prod;
> >
> > if ( !cons_ring )
> > - return;
> > + return 0;
> >
> > cons = ACCESS_ONCE(cons_ring->in_cons);
> > prod = cons_ring->in_prod;
> > @@ -118,6 +120,7 @@ void consoled_guest_tx(char c)
> >
> > cons_ring->in[MASK_XENCONS_IDX(prod++, cons_ring->in)] = c;
> >
> > +
> > /* Write to the ring before updating the pointer /
> > smp_wmb();
> > ACCESS_ONCE(cons_ring->in_prod) = prod;
> > @@ -125,6 +128,13 @@ void consoled_guest_tx(char c)
> > notify:
> > / Always notify the guest: prevents receive path from getting stuck. */
> > pv_shim_inject_evtchn(pv_console_evtchn());
> > +
> > + return 0;
> > +}
> > +
> > +bool consoled_is_enabled(void)
> > +{
> > + return pv_shim && pv_console;
> > }
> >
> > /*
> > diff --git a/xen/include/xen/consoled.h b/xen/include/xen/consoled.h
> > index bd7ab6329ee8a7c466484021247241ded8ed03c7..696677fa5a3be458a0ec93360e08376c3471f95b 100644
> > --- a/xen/include/xen/consoled.h
> > +++ b/xen/include/xen/consoled.h
> > @@ -3,10 +3,41 @@
> >
> > #include <public/io/console.h>
> >
> > +#if defined(CONFIG_PV_SHIM)
> > +
> > void consoled_set_ring_addr(struct xencons_interface *ring);
> > struct xencons_interface *consoled_get_ring_addr(void);
> > -void consoled_guest_rx(void);
> > -void consoled_guest_tx(char c);
> > +int consoled_guest_rx(void);
> > +int consoled_guest_tx(char c);
> > +bool consoled_is_enabled(void);
> > +
> > +#else
> > +
> > +static inline void consoled_set_ring_addr(struct xencons_interface *ring)
> > +{
> > +}
> > +
> > +static inline struct xencons_interface *consoled_get_ring_addr(void)
> > +{
> > + return NULL;
> > +}
> > +
> > +static inline int consoled_guest_rx(void)
> > +{
> > + return 0;
> > +}
>
>
> You don't need to provide dummy implementations of
> consoled_{set,get}_ring_addr() and consoled_guest_rx(), they are only
> called from code that's build when CONFIG_PV_SHIM is selected.
Thanks; fixed.
>
> > +static inline int consoled_guest_tx(char c)
> > +{
> > + return 0;
>
>
> For consoled_guest_tx() you want to add an ASSERT_UNREACHABLE(), as
> it should never be called if !CONFIG_PV_SHIM?
Fixed.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 18/35] xen/console: introduce use of 'is_console' flag
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
The code now inspects d->is_console flag to decide whether the console focus
should move to the domain w/ console after administrator presses <Ctrl+aaa>.
Console owner domain switch logic updated accordingly.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/dom0less-build.c | 2 +-
xen/arch/arm/domain.c | 1 +
xen/arch/arm/domctl.c | 1 +
xen/arch/x86/pv/shim.c | 2 ++
xen/common/domain.c | 2 ++
xen/drivers/char/console.c | 14 ++++++++++----
6 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index de64ee930fdfe9a1c2842761275641485f69f675..32b5e8e16a28ae9a4951c8b7815638e69b66406a 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -833,6 +833,7 @@ static int __init construct_domU(struct domain *d,
return rc;
d->arch.emulation_flags |= ARM_EMU_VUART;
+ d->is_console = true;
}
rc = prepare_dtb_domU(d, &kinfo);
@@ -1015,7 +1016,6 @@ void __init create_domUs(void)
panic("Error creating domain %s (rc = %ld)\n",
dt_node_name(node), PTR_ERR(d));
- d->is_console = true;
dt_device_set_used_by(node, d->domain_id);
rc = construct_domU(d, node);
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 02f9d59b38b4b7f6f73d97c421c9948c90e681d5..c52d6e932a9a71b620ecefacc1e884338858e3ea 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -781,6 +781,7 @@ int arch_domain_create(struct domain *d,
goto fail;
d->arch.emulation_flags |= ARM_EMU_VUART;
+ d->is_console = true;
}
if ( (rc = domain_vpci_init(d)) != 0 )
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index f80d34bf5f3d323a15db7f032073be52ea1009ae..81b5caf17c4e0badb2eefa90b1522c107f844d06 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -46,6 +46,7 @@ static int handle_vuart_init(struct domain *d,
{
vuart_op->evtchn = info.evtchn;
d->arch.emulation_flags |= ARM_EMU_VUART;
+ d->is_console = true;
}
return rc;
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index 17cb30620290c76cf42251f70cfa4199c0e165d1..a55c1d2a1e616f8979677a198eb9caabc3afc6bf 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -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->is_console = true;
}
static void write_start_info(struct domain *d)
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 9e57dd4122a726e2fb42efe9c029e775202be0e6..aab546c0a8535e4f007cbbc9c5c552bcf66b5807 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -682,6 +682,8 @@ struct domain *domain_create(domid_t domid,
old_hwdom = hardware_domain;
hardware_domain = d;
+
+ d->is_console = true;
}
TRACE_TIME(TRC_DOM0_DOM_ADD, d->domain_id);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 60c055396b697869b04b9132b0dcfa832fabe932..8cbac54c66044ae8581e486a782102b75c8bfaa9 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -1,8 +1,8 @@
/******************************************************************************
* console.c
- *
+ *
* Emergency console I/O for Xen and the domain-0 guest OS.
- *
+ *
* Copyright (c) 2002-2004, K A Fraser.
*
* Added printf_ratelimit
@@ -509,14 +509,20 @@ static void console_find_owner(void)
domid = get_initial_domain_id();
else
domid = next_rx - 1;
+
d = rcu_lock_domain_by_id(domid);
- if ( d )
+ if ( d == NULL )
+ continue;
+
+ if ( d->is_console )
{
rcu_unlock_domain(d);
console_owner = next_rx;
printk("*** Serial input to DOM%u", domid);
break;
}
+
+ rcu_unlock_domain(d);
}
if ( switch_code )
@@ -814,7 +820,7 @@ static int printk_prefix_check(char *p, char **pp)
return ((atomic_read(&print_everything) != 0) ||
(loglvl < lower_thresh) ||
((loglvl < upper_thresh) && printk_ratelimit()));
-}
+}
static int cf_check parse_console_timestamps(const char *s)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 18/35] xen/console: introduce use of 'is_console' flag
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
The code now inspects d->is_console flag to decide whether the console focus
should move to the domain w/ console after administrator presses <Ctrl+aaa>.
Console owner domain switch logic updated accordingly.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/arm/dom0less-build.c | 2 +-
xen/arch/arm/domain.c | 1 +
xen/arch/arm/domctl.c | 1 +
xen/arch/x86/pv/shim.c | 2 ++
xen/common/domain.c | 2 ++
xen/drivers/char/console.c | 14 ++++++++++----
6 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index de64ee930fdfe9a1c2842761275641485f69f675..32b5e8e16a28ae9a4951c8b7815638e69b66406a 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -833,6 +833,7 @@ static int __init construct_domU(struct domain *d,
return rc;
d->arch.emulation_flags |= ARM_EMU_VUART;
+ d->is_console = true;
}
rc = prepare_dtb_domU(d, &kinfo);
@@ -1015,7 +1016,6 @@ void __init create_domUs(void)
panic("Error creating domain %s (rc = %ld)\n",
dt_node_name(node), PTR_ERR(d));
- d->is_console = true;
dt_device_set_used_by(node, d->domain_id);
rc = construct_domU(d, node);
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 02f9d59b38b4b7f6f73d97c421c9948c90e681d5..c52d6e932a9a71b620ecefacc1e884338858e3ea 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -781,6 +781,7 @@ int arch_domain_create(struct domain *d,
goto fail;
d->arch.emulation_flags |= ARM_EMU_VUART;
+ d->is_console = true;
}
if ( (rc = domain_vpci_init(d)) != 0 )
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index f80d34bf5f3d323a15db7f032073be52ea1009ae..81b5caf17c4e0badb2eefa90b1522c107f844d06 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -46,6 +46,7 @@ static int handle_vuart_init(struct domain *d,
{
vuart_op->evtchn = info.evtchn;
d->arch.emulation_flags |= ARM_EMU_VUART;
+ d->is_console = true;
}
return rc;
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index 17cb30620290c76cf42251f70cfa4199c0e165d1..a55c1d2a1e616f8979677a198eb9caabc3afc6bf 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -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->is_console = true;
}
static void write_start_info(struct domain *d)
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 9e57dd4122a726e2fb42efe9c029e775202be0e6..aab546c0a8535e4f007cbbc9c5c552bcf66b5807 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -682,6 +682,8 @@ struct domain *domain_create(domid_t domid,
old_hwdom = hardware_domain;
hardware_domain = d;
+
+ d->is_console = true;
}
TRACE_TIME(TRC_DOM0_DOM_ADD, d->domain_id);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 60c055396b697869b04b9132b0dcfa832fabe932..8cbac54c66044ae8581e486a782102b75c8bfaa9 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -1,8 +1,8 @@
/******************************************************************************
* console.c
- *
+ *
* Emergency console I/O for Xen and the domain-0 guest OS.
- *
+ *
* Copyright (c) 2002-2004, K A Fraser.
*
* Added printf_ratelimit
@@ -509,14 +509,20 @@ static void console_find_owner(void)
domid = get_initial_domain_id();
else
domid = next_rx - 1;
+
d = rcu_lock_domain_by_id(domid);
- if ( d )
+ if ( d == NULL )
+ continue;
+
+ if ( d->is_console )
{
rcu_unlock_domain(d);
console_owner = next_rx;
printk("*** Serial input to DOM%u", domid);
break;
}
+
+ rcu_unlock_domain(d);
}
if ( switch_code )
@@ -814,7 +820,7 @@ static int printk_prefix_check(char *p, char **pp)
return ((atomic_read(&print_everything) != 0) ||
(loglvl < lower_thresh) ||
((loglvl < upper_thresh) && printk_ratelimit()));
-}
+}
static int cf_check parse_console_timestamps(const char *s)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 18/35] xen/console: introduce use of 'is_console' flag
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 14:52 ` Jan Beulich
2025-01-04 3:05 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 14:52 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> The code now inspects d->is_console flag to decide whether the console focus
> should move to the domain w/ console after administrator presses <Ctrl+aaa>.
>
> Console owner domain switch logic updated accordingly.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Just as a remark, as it's a pre-existing problem: I'm unconvinced that
"is_console" is a good name here.
> @@ -509,14 +509,20 @@ static void console_find_owner(void)
> domid = get_initial_domain_id();
> else
> domid = next_rx - 1;
> +
> d = rcu_lock_domain_by_id(domid);
> - if ( d )
> + if ( d == NULL )
Seeing the original code, the more "natural" transformation would be to
!d (as we use elsewhere as well, to keep code short).
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 18/35] xen/console: introduce use of 'is_console' flag
2024-12-10 14:52 ` Jan Beulich
@ 2025-01-04 3:05 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:05 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 6:52 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > The code now inspects d->is_console flag to decide whether the console focus
> > should move to the domain w/ console after administrator presses <Ctrl+aaa>.
> >
> > Console owner domain switch logic updated accordingly.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
>
>
> Just as a remark, as it's a pre-existing problem: I'm unconvinced that
> "is_console" is a good name here.
I think it should be called something like console_perm.
I kept name as is for now, but I can make a change.
>
> > @@ -509,14 +509,20 @@ static void console_find_owner(void)
> > domid = get_initial_domain_id();
> > else
> > domid = next_rx - 1;
> > +
> > d = rcu_lock_domain_by_id(domid);
> > - if ( d )
> > + if ( d == NULL )
>
>
> Seeing the original code, the more "natural" transformation would be to
> !d (as we use elsewhere as well, to keep code short).
Fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
console_set_owner() is introduced for setting the new console owner.
Switches console owner to domain ID vs range of integer numbers mapped to
domain IDs.
This a public API to console driver, will be used in the follow on code change.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 122 ++++++++++++++++++++++++++-------------------
xen/include/xen/console.h | 1 +
2 files changed, 71 insertions(+), 52 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 8cbac54c66044ae8581e486a782102b75c8bfaa9..52cf64dbf6fd18d599cb88835d03501a23b3e3c4 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -463,82 +463,100 @@ 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_owner=0 => input to xen
- * console_owner=1 => input to dom0 (or the sole shim domain)
- * console_owner=N => input to dom(N-1)
+ * Current console owner domain ID: either Xen or domain w/ d->is_console ==
+ * true.
+ *
+ * Initialized in console_endboot().
*/
-static unsigned int __read_mostly console_owner = 0;
+static domid_t __read_mostly console_owner;
-#define max_console_rx (max_init_domid + 1)
+static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
+{
+ struct domain *d;
+
+ d = rcu_lock_domain_by_id(domid);
+
+ if ( d == NULL )
+ return NULL;
+
+ if ( d->is_console )
+ return d;
+
+ rcu_unlock_domain(d);
+
+ return NULL;
+}
-#ifdef CONFIG_SBSA_VUART_CONSOLE
/* Make sure to rcu_unlock_domain after use */
struct domain *rcu_lock_domain_console_owner(void)
{
- if ( console_owner == 0 )
- return NULL;
- return rcu_lock_domain_by_id(console_owner - 1);
+ return rcu_lock_domain_console_by_id(console_owner);
}
-#endif
-static void console_find_owner(void)
+static bool console_owner_possible(domid_t domid)
{
- unsigned int next_rx = console_owner;
-
- /*
- * 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_owner = 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 == NULL )
- continue;
-
- if ( d->is_console )
- {
- rcu_unlock_domain(d);
- console_owner = next_rx;
- printk("*** Serial input to DOM%u", domid);
- break;
- }
+ struct domain *d;
+ d = rcu_lock_domain_console_by_id(domid);
+ if ( d != NULL )
rcu_unlock_domain(d);
- }
+
+ return d != NULL;
+}
+
+int console_set_owner(domid_t domid)
+{
+ if ( domid == DOMID_XEN )
+ printk("*** Serial input to Xen");
+ else if ( console_owner_possible(domid) )
+ printk("*** Serial input to DOM%u", domid);
+ else
+ return -ENOENT;
+
+ console_owner = domid;
if ( switch_code )
printk(" (type 'CTRL-%c' three times to switch input)",
opt_conswitch[0]);
printk("\n");
+
+ return 0;
+}
+
+/*
+ * Switch console input focus.
+ * Rotates input focus among Xen, dom0 and boot-time created domUs while
+ * skipping switching serial input to non existing domains.
+ */
+static void console_find_owner(void)
+{
+ domid_t i, n = max_init_domid + 1;
+
+ if ( console_owner == DOMID_XEN )
+ i = get_initial_domain_id();
+ else
+ i = console_owner + 1;
+
+ for ( ; i < n; i++ )
+ if ( !console_set_owner(i) )
+ break;
+ if ( i == n )
+ console_set_owner(DOMID_XEN);
}
static void __serial_rx(char c)
{
switch ( console_owner )
{
- case 0:
+ case DOMID_XEN:
return handle_keypress(c, false);
- case 1:
+ case 0:
/*
* Deliver input to the hardware domain buffer, unless it is
* already full.
@@ -556,7 +574,7 @@ static void __serial_rx(char c)
#ifdef CONFIG_SBSA_VUART_CONSOLE
default:
{
- struct domain *d = rcu_lock_domain_by_id(console_owner - 1);
+ struct domain *d = rcu_lock_domain_by_id(console_owner);
/*
* If we have a properly initialized vpl011 console for the
@@ -567,7 +585,7 @@ static void __serial_rx(char c)
vpl011_rx_char_xen(d, c);
else
printk("Cannot send chars to Dom%d: no UART available\n",
- console_owner - 1);
+ console_owner);
if ( d != NULL )
rcu_unlock_domain(d);
@@ -1126,7 +1144,7 @@ void __init console_endboot(void)
* a useful 'how to switch' message.
*/
if ( opt_conswitch[1] == 'x' )
- console_owner = max_console_rx;
+ console_owner = DOMID_XEN;
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 0e211e44d9703c804e18f52c9743916f8d2a9d4e..57c482cfbf2da15b011e64841ea086e779f4588d 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -32,6 +32,7 @@ void console_start_log_everything(void);
void console_end_log_everything(void);
struct domain *rcu_lock_domain_console_owner(void);
+int console_set_owner(domid_t);
/*
* Steal output from the console. Returns +ve identifier, else -ve error.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 19/35] xen/console: introduce console_set_owner()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
console_set_owner() is introduced for setting the new console owner.
Switches console owner to domain ID vs range of integer numbers mapped to
domain IDs.
This a public API to console driver, will be used in the follow on code change.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 122 ++++++++++++++++++++++++++-------------------
xen/include/xen/console.h | 1 +
2 files changed, 71 insertions(+), 52 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 8cbac54c66044ae8581e486a782102b75c8bfaa9..52cf64dbf6fd18d599cb88835d03501a23b3e3c4 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -463,82 +463,100 @@ 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_owner=0 => input to xen
- * console_owner=1 => input to dom0 (or the sole shim domain)
- * console_owner=N => input to dom(N-1)
+ * Current console owner domain ID: either Xen or domain w/ d->is_console ==
+ * true.
+ *
+ * Initialized in console_endboot().
*/
-static unsigned int __read_mostly console_owner = 0;
+static domid_t __read_mostly console_owner;
-#define max_console_rx (max_init_domid + 1)
+static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
+{
+ struct domain *d;
+
+ d = rcu_lock_domain_by_id(domid);
+
+ if ( d == NULL )
+ return NULL;
+
+ if ( d->is_console )
+ return d;
+
+ rcu_unlock_domain(d);
+
+ return NULL;
+}
-#ifdef CONFIG_SBSA_VUART_CONSOLE
/* Make sure to rcu_unlock_domain after use */
struct domain *rcu_lock_domain_console_owner(void)
{
- if ( console_owner == 0 )
- return NULL;
- return rcu_lock_domain_by_id(console_owner - 1);
+ return rcu_lock_domain_console_by_id(console_owner);
}
-#endif
-static void console_find_owner(void)
+static bool console_owner_possible(domid_t domid)
{
- unsigned int next_rx = console_owner;
-
- /*
- * 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_owner = 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 == NULL )
- continue;
-
- if ( d->is_console )
- {
- rcu_unlock_domain(d);
- console_owner = next_rx;
- printk("*** Serial input to DOM%u", domid);
- break;
- }
+ struct domain *d;
+ d = rcu_lock_domain_console_by_id(domid);
+ if ( d != NULL )
rcu_unlock_domain(d);
- }
+
+ return d != NULL;
+}
+
+int console_set_owner(domid_t domid)
+{
+ if ( domid == DOMID_XEN )
+ printk("*** Serial input to Xen");
+ else if ( console_owner_possible(domid) )
+ printk("*** Serial input to DOM%u", domid);
+ else
+ return -ENOENT;
+
+ console_owner = domid;
if ( switch_code )
printk(" (type 'CTRL-%c' three times to switch input)",
opt_conswitch[0]);
printk("\n");
+
+ return 0;
+}
+
+/*
+ * Switch console input focus.
+ * Rotates input focus among Xen, dom0 and boot-time created domUs while
+ * skipping switching serial input to non existing domains.
+ */
+static void console_find_owner(void)
+{
+ domid_t i, n = max_init_domid + 1;
+
+ if ( console_owner == DOMID_XEN )
+ i = get_initial_domain_id();
+ else
+ i = console_owner + 1;
+
+ for ( ; i < n; i++ )
+ if ( !console_set_owner(i) )
+ break;
+ if ( i == n )
+ console_set_owner(DOMID_XEN);
}
static void __serial_rx(char c)
{
switch ( console_owner )
{
- case 0:
+ case DOMID_XEN:
return handle_keypress(c, false);
- case 1:
+ case 0:
/*
* Deliver input to the hardware domain buffer, unless it is
* already full.
@@ -556,7 +574,7 @@ static void __serial_rx(char c)
#ifdef CONFIG_SBSA_VUART_CONSOLE
default:
{
- struct domain *d = rcu_lock_domain_by_id(console_owner - 1);
+ struct domain *d = rcu_lock_domain_by_id(console_owner);
/*
* If we have a properly initialized vpl011 console for the
@@ -567,7 +585,7 @@ static void __serial_rx(char c)
vpl011_rx_char_xen(d, c);
else
printk("Cannot send chars to Dom%d: no UART available\n",
- console_owner - 1);
+ console_owner);
if ( d != NULL )
rcu_unlock_domain(d);
@@ -1126,7 +1144,7 @@ void __init console_endboot(void)
* a useful 'how to switch' message.
*/
if ( opt_conswitch[1] == 'x' )
- console_owner = max_console_rx;
+ console_owner = DOMID_XEN;
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 0e211e44d9703c804e18f52c9743916f8d2a9d4e..57c482cfbf2da15b011e64841ea086e779f4588d 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -32,6 +32,7 @@ void console_start_log_everything(void);
void console_end_log_everything(void);
struct domain *rcu_lock_domain_console_owner(void);
+int console_set_owner(domid_t);
/*
* Steal output from the console. Returns +ve identifier, else -ve error.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 15:02 ` Jan Beulich
2025-01-04 3:07 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-10 15:02 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
> - * console_owner=1 => input to dom0 (or the sole shim domain)
> - * console_owner=N => input to dom(N-1)
> + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
> + * true.
The switching of number space may better have been a separate patch.
Albeit maybe I'm just not seeing why it wants combining with the
introduction of console_set_owner().
Actually, is this switching actually complete? What about late hwdom,
which has a non-zero domain ID?
> + * Initialized in console_endboot().
> */
> -static unsigned int __read_mostly console_owner = 0;
> +static domid_t __read_mostly console_owner;
>
> -#define max_console_rx (max_init_domid + 1)
> +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
I think "domain" and "console" want switching in the name, as it's a
domain you're locking, not a console.
> +int console_set_owner(domid_t domid)
static? Iirc Misra doesn't like non-static functions which aren't called
from any other CU.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-10 15:02 ` Jan Beulich
@ 2025-01-04 3:07 ` Denis Mukhin
2025-01-06 9:08 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:07 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 7:02 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
> > - * console_owner=1 => input to dom0 (or the sole shim domain)
> > - * console_owner=N => input to dom(N-1)
> > + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
> > + * true.
>
>
> The switching of number space may better have been a separate patch.
> Albeit maybe I'm just not seeing why it wants combining with the
> introduction of console_set_owner().
This is the part I tried in different variations and finally
ended up w/ plumbing new console owner IDs "address space"
here: console_set_owner() takes domid_t and I decided against intermediate
patch, since it is not a big (in term of lines of code) change.
>
> Actually, is this switching actually complete? What about late hwdom,
> which has a non-zero domain ID?
I did reworks for max_init_domid in v3, I believe it should address late
hwdom scenario.
>
> > + * Initialized in console_endboot().
> > */
> > -static unsigned int __read_mostly console_owner = 0;
> > +static domid_t __read_mostly console_owner;
> >
> > -#define max_console_rx (max_init_domid + 1)
> > +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
>
>
> I think "domain" and "console" want switching in the name, as it's a
> domain you're locking, not a console.
Renamed to "console_get_domain_by_id".
>
> > +int console_set_owner(domid_t domid)
>
>
> static? Iirc Misra doesn't like non-static functions which aren't called
> from any other CU.
Yes, but there's a follow on patch which will undo static - hwdom_crashconsole=
patch - to drop the user to xen console once dom0 has crashed.
So since there's a need in globally visible symbol, I decided to get rid of static
right away.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2025-01-04 3:07 ` Denis Mukhin
@ 2025-01-06 9:08 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 9:08 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On 04.01.2025 04:07, Denis Mukhin wrote:
> On Tuesday, December 10th, 2024 at 7:02 AM, Jan Beulich <jbeulich@suse.com> wrote:
>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>> +int console_set_owner(domid_t domid)
>>
>>
>> static? Iirc Misra doesn't like non-static functions which aren't called
>> from any other CU.
>
> Yes, but there's a follow on patch which will undo static - hwdom_crashconsole=
> patch - to drop the user to xen console once dom0 has crashed.
> So since there's a need in globally visible symbol, I decided to get rid of static
> right away.
Yet you realize that any series may go in piecemeal, and therefore no Misra rule
may be violated at any patch boundary?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-12 10:12 ` Roger Pau Monné
2024-12-12 11:59 ` Jan Beulich
2025-01-04 3:30 ` Denis Mukhin
-1 siblings, 2 replies; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 10:12 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_set_owner() is introduced for setting the new console owner.
>
> Switches console owner to domain ID vs range of integer numbers mapped to
> domain IDs.
>
> This a public API to console driver, will be used in the follow on code change.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 122 ++++++++++++++++++++++++++-------------------
> xen/include/xen/console.h | 1 +
> 2 files changed, 71 insertions(+), 52 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 8cbac54c66044ae8581e486a782102b75c8bfaa9..52cf64dbf6fd18d599cb88835d03501a23b3e3c4 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
> - * console_owner=1 => input to dom0 (or the sole shim domain)
> - * console_owner=N => input to dom(N-1)
> + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
> + * true.
> + *
> + * Initialized in console_endboot().
> */
> -static unsigned int __read_mostly console_owner = 0;
> +static domid_t __read_mostly console_owner;
Should this be initialized to DOMID_XEN? I assume it doesn't make
much difference because the variable is not checked before
console_endboot() anyway, but it might be safer to initialize to a
value that assigns the console to Xen.
>
> -#define max_console_rx (max_init_domid + 1)
> +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
> +{
> + struct domain *d;
> +
> + d = rcu_lock_domain_by_id(domid);
> +
Nit: I would remove this newline.
> + if ( d == NULL )
> + return NULL;
> +
> + if ( d->is_console )
> + return d;
> +
> + rcu_unlock_domain(d);
> +
> + return NULL;
> +}
>
> -#ifdef CONFIG_SBSA_VUART_CONSOLE
> /* Make sure to rcu_unlock_domain after use */
> struct domain *rcu_lock_domain_console_owner(void)
> {
> - if ( console_owner == 0 )
> - return NULL;
> - return rcu_lock_domain_by_id(console_owner - 1);
> + return rcu_lock_domain_console_by_id(console_owner);
> }
> -#endif
>
> -static void console_find_owner(void)
> +static bool console_owner_possible(domid_t domid)
> {
> - unsigned int next_rx = console_owner;
> -
> - /*
> - * 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_owner = 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 == NULL )
> - continue;
> -
> - if ( d->is_console )
> - {
> - rcu_unlock_domain(d);
> - console_owner = next_rx;
> - printk("*** Serial input to DOM%u", domid);
> - break;
> - }
> + struct domain *d;
>
> + d = rcu_lock_domain_console_by_id(domid);
> + if ( d != NULL )
> rcu_unlock_domain(d);
> - }
> +
> + return d != NULL;
> +}
> +
> +int console_set_owner(domid_t domid)
> +{
> + if ( domid == DOMID_XEN )
> + printk("*** Serial input to Xen");
> + else if ( console_owner_possible(domid) )
> + printk("*** Serial input to DOM%u", domid);
> + else
> + return -ENOENT;
> +
> + console_owner = domid;
>
> if ( switch_code )
> printk(" (type 'CTRL-%c' three times to switch input)",
> opt_conswitch[0]);
> printk("\n");
> +
> + return 0;
> +}
> +
> +/*
> + * Switch console input focus.
> + * Rotates input focus among Xen, dom0 and boot-time created domUs while
> + * skipping switching serial input to non existing domains.
> + */
> +static void console_find_owner(void)
> +{
> + domid_t i, n = max_init_domid + 1;
n can be made const, I would even rename to nr for clarity, but that's
personal taste.
> +
> + if ( console_owner == DOMID_XEN )
> + i = get_initial_domain_id();
> + else
> + i = console_owner + 1;
> +
> + for ( ; i < n; i++ )
> + if ( !console_set_owner(i) )
> + break;
Hm, that could be a non-trivial amount of iteration if max_init_domid
is bumped for every domain created as you have it in patch 11/35
(albeit I'm not sure that was intended?)
> + if ( i == n )
> + console_set_owner(DOMID_XEN);
> }
>
> static void __serial_rx(char c)
> {
> switch ( console_owner )
> {
> - case 0:
> + case DOMID_XEN:
> return handle_keypress(c, false);
>
> - case 1:
> + case 0:
If console_owner now strictly contains a domid you cannot assume that
domid 0 is the hardware domain, you will need to handle this
differently and check whether the domain pointed by console_owner
passes the is_hardware_domain() check.
> /*
> * Deliver input to the hardware domain buffer, unless it is
> * already full.
> @@ -556,7 +574,7 @@ static void __serial_rx(char c)
> #ifdef CONFIG_SBSA_VUART_CONSOLE
> default:
> {
> - struct domain *d = rcu_lock_domain_by_id(console_owner - 1);
> + struct domain *d = rcu_lock_domain_by_id(console_owner);
>
> /*
> * If we have a properly initialized vpl011 console for the
> @@ -567,7 +585,7 @@ static void __serial_rx(char c)
> vpl011_rx_char_xen(d, c);
> else
> printk("Cannot send chars to Dom%d: no UART available\n",
> - console_owner - 1);
> + console_owner);
>
> if ( d != NULL )
> rcu_unlock_domain(d);
> @@ -1126,7 +1144,7 @@ void __init console_endboot(void)
> * a useful 'how to switch' message.
> */
> if ( opt_conswitch[1] == 'x' )
> - console_owner = max_console_rx;
> + console_owner = DOMID_XEN;
Hm, are you sure this still works as expected? Setting console_owner
== DOMID_XEN will cause the call to switch_serial_input() below to
switch the console back to the first domain in the system. Also
initializing console_owner to 0 by default would also cause the call
to switch_serial_input() to possibly switch it to the first domain
after domid 0 (or back to Xen).
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-12 10:12 ` Roger Pau Monné
@ 2024-12-12 11:59 ` Jan Beulich
2024-12-12 12:16 ` Roger Pau Monné
2025-01-04 3:31 ` Denis Mukhin
2025-01-04 3:30 ` Denis Mukhin
1 sibling, 2 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-12 11:59 UTC (permalink / raw)
To: Roger Pau Monné, dmukhin
Cc: xen-devel, Andrew Cooper, Julien Grall, Stefano Stabellini
On 12.12.2024 11:12, Roger Pau Monné wrote:
> On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
>> +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
>> +{
>> + struct domain *d;
>> +
>> + d = rcu_lock_domain_by_id(domid);
>> +
>
> Nit: I would remove this newline.
Or even better make the function call the variable's initializer.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-12 11:59 ` Jan Beulich
@ 2024-12-12 12:16 ` Roger Pau Monné
2025-01-04 3:31 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 12:16 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On Thu, Dec 12, 2024 at 12:59:30PM +0100, Jan Beulich wrote:
> On 12.12.2024 11:12, Roger Pau Monné wrote:
> > On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
> >> +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
> >> +{
> >> + struct domain *d;
> >> +
> >> + d = rcu_lock_domain_by_id(domid);
> >> +
> >
> > Nit: I would remove this newline.
>
> Or even better make the function call the variable's initializer.
Indeed, didn't catch that one.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-12 11:59 ` Jan Beulich
2024-12-12 12:16 ` Roger Pau Monné
@ 2025-01-04 3:31 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:31 UTC (permalink / raw)
To: Jan Beulich
Cc: Roger Pau Monné, dmukhin, xen-devel, Andrew Cooper,
Julien Grall, Stefano Stabellini
On Thursday, December 12th, 2024 at 3:59 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 12.12.2024 11:12, Roger Pau Monné wrote:
>
> > On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
> >
> > > +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
> > > +{
> > > + struct domain *d;
> > > +
> > > + d = rcu_lock_domain_by_id(domid);
> > > +
> >
> > Nit: I would remove this newline.
>
>
> Or even better make the function call the variable's initializer.
Fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2024-12-12 10:12 ` Roger Pau Monné
2024-12-12 11:59 ` Jan Beulich
@ 2025-01-04 3:30 ` Denis Mukhin
2025-01-06 9:58 ` Jan Beulich
1 sibling, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:30 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 2:12 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > console_set_owner() is introduced for setting the new console owner.
> >
> > Switches console owner to domain ID vs range of integer numbers mapped to
> > domain IDs.
> >
> > This a public API to console driver, will be used in the follow on code change.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 122 ++++++++++++++++++++++++++-------------------
> > xen/include/xen/console.h | 1 +
> > 2 files changed, 71 insertions(+), 52 deletions(-)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 8cbac54c66044ae8581e486a782102b75c8bfaa9..52cf64dbf6fd18d599cb88835d03501a23b3e3c4 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
> > - * console_owner=1 => input to dom0 (or the sole shim domain)
> > - * console_owner=N => input to dom(N-1)
> > + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
> > + * true.
> > + *
> > + * Initialized in console_endboot().
> > */
> > -static unsigned int __read_mostly console_owner = 0;
> > +static domid_t __read_mostly console_owner;
>
>
> Should this be initialized to DOMID_XEN? I assume it doesn't make
> much difference because the variable is not checked before
> console_endboot() anyway, but it might be safer to initialize to a
> value that assigns the console to Xen.
Fixed.
>
> > -#define max_console_rx (max_init_domid + 1)
> > +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
> > +{
> > + struct domain *d;
> > +
> > + d = rcu_lock_domain_by_id(domid);
> > +
>
>
> Nit: I would remove this newline.
Fixed.
>
> > + if ( d == NULL )
> > + return NULL;
> > +
> > + if ( d->is_console )
> > + return d;
> > +
> > + rcu_unlock_domain(d);
> > +
> > + return NULL;
> > +}
> >
> > -#ifdef CONFIG_SBSA_VUART_CONSOLE
> > /* Make sure to rcu_unlock_domain after use */
> > struct domain *rcu_lock_domain_console_owner(void)
> > {
> > - if ( console_owner == 0 )
> > - return NULL;
> > - return rcu_lock_domain_by_id(console_owner - 1);
> > + return rcu_lock_domain_console_by_id(console_owner);
> > }
> > -#endif
> >
> > -static void console_find_owner(void)
> > +static bool console_owner_possible(domid_t domid)
> > {
> > - unsigned int next_rx = console_owner;
> > -
> > - /*
> > - * 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_owner = 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 == NULL )
> > - continue;
> > -
> > - if ( d->is_console )
> > - {
> > - rcu_unlock_domain(d);
> > - console_owner = next_rx;
> > - printk("*** Serial input to DOM%u", domid);
> > - break;
> > - }
> > + struct domain *d;
> >
> > + d = rcu_lock_domain_console_by_id(domid);
> > + if ( d != NULL )
> > rcu_unlock_domain(d);
> > - }
> > +
> > + return d != NULL;
> > +}
> > +
> > +int console_set_owner(domid_t domid)
> > +{
> > + if ( domid == DOMID_XEN )
> > + printk("*** Serial input to Xen");
> > + else if ( console_owner_possible(domid) )
> > + printk("*** Serial input to DOM%u", domid);
> > + else
> > + return -ENOENT;
> > +
> > + console_owner = domid;
> >
> > if ( switch_code )
> > printk(" (type 'CTRL-%c' three times to switch input)",
> > opt_conswitch[0]);
> > printk("\n");
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * Switch console input focus.
> > + * Rotates input focus among Xen, dom0 and boot-time created domUs while
> > + * skipping switching serial input to non existing domains.
> > + */
> > +static void console_find_owner(void)
> > +{
> > + domid_t i, n = max_init_domid + 1;
>
>
> n can be made const, I would even rename to nr for clarity, but that's
> personal taste.
`max_init_domid` can change at run-time actually (e.g. after `xl create`).
I kept `n` as is.
>
> > +
> > + if ( console_owner == DOMID_XEN )
> > + i = get_initial_domain_id();
> > + else
> > + i = console_owner + 1;
> > +
> > + for ( ; i < n; i++ )
> > + if ( !console_set_owner(i) )
> > + break;
>
>
> Hm, that could be a non-trivial amount of iteration if max_init_domid
> is bumped for every domain created as you have it in patch 11/35
> (albeit I'm not sure that was intended?)
Yes, `max_init_domid` is advanced on each domain creation (v3).
>
> > + if ( i == n )
> > + console_set_owner(DOMID_XEN);
> > }
> >
> > static void __serial_rx(char c)
> > {
> > switch ( console_owner )
> > {
> > - case 0:
> > + case DOMID_XEN:
> > return handle_keypress(c, false);
> >
> > - case 1:
> > + case 0:
>
>
> If console_owner now strictly contains a domid you cannot assume that
> domid 0 is the hardware domain, you will need to handle this
> differently and check whether the domain pointed by console_owner
> passes the is_hardware_domain() check.
Fixed.
>
> > /*
> > * Deliver input to the hardware domain buffer, unless it is
> > * already full.
> > @@ -556,7 +574,7 @@ static void __serial_rx(char c)
> > #ifdef CONFIG_SBSA_VUART_CONSOLE
> > default:
> > {
> > - struct domain *d = rcu_lock_domain_by_id(console_owner - 1);
> > + struct domain *d = rcu_lock_domain_by_id(console_owner);
> >
> > /*
> > * If we have a properly initialized vpl011 console for the
> > @@ -567,7 +585,7 @@ static void __serial_rx(char c)
> > vpl011_rx_char_xen(d, c);
> > else
> > printk("Cannot send chars to Dom%d: no UART available\n",
> > - console_owner - 1);
> > + console_owner);
> >
> > if ( d != NULL )
> > rcu_unlock_domain(d);
> > @@ -1126,7 +1144,7 @@ void __init console_endboot(void)
> > * a useful 'how to switch' message.
> > */
> > if ( opt_conswitch[1] == 'x' )
> > - console_owner = max_console_rx;
> > + console_owner = DOMID_XEN;
>
>
> Hm, are you sure this still works as expected? Setting console_owner
> == DOMID_XEN will cause the call to switch_serial_input() below to
> switch the console back to the first domain in the system. Also
> initializing console_owner to 0 by default would also cause the call
> to switch_serial_input() to possibly switch it to the first domain
> after domid 0 (or back to Xen).
TBH, I did not test w/ conswitch=x originally, but after addressing
your other feedback that is now fixed.
Thank you.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2025-01-04 3:30 ` Denis Mukhin
@ 2025-01-06 9:58 ` Jan Beulich
2025-01-06 20:03 ` Denis Mukhin
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 9:58 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini, Roger Pau Monné
On 04.01.2025 04:30, Denis Mukhin wrote:
> On Thursday, December 12th, 2024 at 2:12 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>> On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
>>> --- a/xen/drivers/char/console.c
>>> +++ b/xen/drivers/char/console.c
>>> @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
>>> - * console_owner=1 => input to dom0 (or the sole shim domain)
>>> - * console_owner=N => input to dom(N-1)
>>> + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
>>> + * true.
>>> + *
>>> + * Initialized in console_endboot().
>>> */
>>> -static unsigned int __read_mostly console_owner = 0;
>>> +static domid_t __read_mostly console_owner;
>>
>>
>> Should this be initialized to DOMID_XEN? I assume it doesn't make
>> much difference because the variable is not checked before
>> console_endboot() anyway, but it might be safer to initialize to a
>> value that assigns the console to Xen.
>
> Fixed.
>
>>
>>> -#define max_console_rx (max_init_domid + 1)
>>> +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
>>> +{
>>> + struct domain *d;
>>> +
>>> + d = rcu_lock_domain_by_id(domid);
>>> +
>>
>>
>> Nit: I would remove this newline.
>
> Fixed.
>
>>
>>> + if ( d == NULL )
>>> + return NULL;
>>> +
>>> + if ( d->is_console )
>>> + return d;
>>> +
>>> + rcu_unlock_domain(d);
>>> +
>>> + return NULL;
>>> +}
>>>
>>> -#ifdef CONFIG_SBSA_VUART_CONSOLE
>>> /* Make sure to rcu_unlock_domain after use */
>>> struct domain *rcu_lock_domain_console_owner(void)
>>> {
>>> - if ( console_owner == 0 )
>>> - return NULL;
>>> - return rcu_lock_domain_by_id(console_owner - 1);
>>> + return rcu_lock_domain_console_by_id(console_owner);
>>> }
>>> -#endif
>>>
>>> -static void console_find_owner(void)
>>> +static bool console_owner_possible(domid_t domid)
>>> {
>>> - unsigned int next_rx = console_owner;
>>> -
>>> - /*
>>> - * 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_owner = 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 == NULL )
>>> - continue;
>>> -
>>> - if ( d->is_console )
>>> - {
>>> - rcu_unlock_domain(d);
>>> - console_owner = next_rx;
>>> - printk("*** Serial input to DOM%u", domid);
>>> - break;
>>> - }
>>> + struct domain *d;
>>>
>>> + d = rcu_lock_domain_console_by_id(domid);
>>> + if ( d != NULL )
>>> rcu_unlock_domain(d);
>>> - }
>>> +
>>> + return d != NULL;
>>> +}
>>> +
>>> +int console_set_owner(domid_t domid)
>>> +{
>>> + if ( domid == DOMID_XEN )
>>> + printk("*** Serial input to Xen");
>>> + else if ( console_owner_possible(domid) )
>>> + printk("*** Serial input to DOM%u", domid);
>>> + else
>>> + return -ENOENT;
>>> +
>>> + console_owner = domid;
>>>
>>> if ( switch_code )
>>> printk(" (type 'CTRL-%c' three times to switch input)",
>>> opt_conswitch[0]);
>>> printk("\n");
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/*
>>> + * Switch console input focus.
>>> + * Rotates input focus among Xen, dom0 and boot-time created domUs while
>>> + * skipping switching serial input to non existing domains.
>>> + */
>>> +static void console_find_owner(void)
>>> +{
>>> + domid_t i, n = max_init_domid + 1;
>>
>>
>> n can be made const, I would even rename to nr for clarity, but that's
>> personal taste.
>
> `max_init_domid` can change at run-time actually (e.g. after `xl create`).
> I kept `n` as is.
How does max_init_domid potentially changing affect (possible) const-ness of n?
However it changing, ...
>>> +
>>> + if ( console_owner == DOMID_XEN )
>>> + i = get_initial_domain_id();
>>> + else
>>> + i = console_owner + 1;
>>> +
>>> + for ( ; i < n; i++ )
>>> + if ( !console_set_owner(i) )
>>> + break;
>>
>>
>> Hm, that could be a non-trivial amount of iteration if max_init_domid
>> is bumped for every domain created as you have it in patch 11/35
>> (albeit I'm not sure that was intended?)
>
> Yes, `max_init_domid` is advanced on each domain creation (v3).
... as you confirm here, undermines what it's used for right now (if I'm
not mistaken), and would render the variable misnamed.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2025-01-06 9:58 ` Jan Beulich
@ 2025-01-06 20:03 ` Denis Mukhin
2025-01-07 8:37 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-06 20:03 UTC (permalink / raw)
To: Jan Beulich
Cc: Denis Mukhin, dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini, Roger Pau Monné
On Monday, January 6th, 2025 at 1:58 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 04.01.2025 04:30, Denis Mukhin wrote:
>
> > On Thursday, December 12th, 2024 at 2:12 AM, Roger Pau Monné roger.pau@citrix.com wrote:
> >
> > > On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
> > >
> > > > --- a/xen/drivers/char/console.c
> > > > +++ b/xen/drivers/char/console.c
> > > > @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
> > > > - * console_owner=1 => input to dom0 (or the sole shim domain)
> > > > - * console_owner=N => input to dom(N-1)
> > > > + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
> > > > + * true.
> > > > + *
> > > > + * Initialized in console_endboot().
> > > > */
> > > > -static unsigned int __read_mostly console_owner = 0;
> > > > +static domid_t __read_mostly console_owner;
> > >
> > > Should this be initialized to DOMID_XEN? I assume it doesn't make
> > > much difference because the variable is not checked before
> > > console_endboot() anyway, but it might be safer to initialize to a
> > > value that assigns the console to Xen.
> >
> > Fixed.
> >
> > > > -#define max_console_rx (max_init_domid + 1)
> > > > +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
> > > > +{
> > > > + struct domain *d;
> > > > +
> > > > + d = rcu_lock_domain_by_id(domid);
> > > > +
> > >
> > > Nit: I would remove this newline.
> >
> > Fixed.
> >
> > > > + if ( d == NULL )
> > > > + return NULL;
> > > > +
> > > > + if ( d->is_console )
> > > > + return d;
> > > > +
> > > > + rcu_unlock_domain(d);
> > > > +
> > > > + return NULL;
> > > > +}
> > > >
> > > > -#ifdef CONFIG_SBSA_VUART_CONSOLE
> > > > /* Make sure to rcu_unlock_domain after use */
> > > > struct domain *rcu_lock_domain_console_owner(void)
> > > > {
> > > > - if ( console_owner == 0 )
> > > > - return NULL;
> > > > - return rcu_lock_domain_by_id(console_owner - 1);
> > > > + return rcu_lock_domain_console_by_id(console_owner);
> > > > }
> > > > -#endif
> > > >
> > > > -static void console_find_owner(void)
> > > > +static bool console_owner_possible(domid_t domid)
> > > > {
> > > > - unsigned int next_rx = console_owner;
> > > > -
> > > > - /*
> > > > - * 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_owner = 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 == NULL )
> > > > - continue;
> > > > -
> > > > - if ( d->is_console )
> > > > - {
> > > > - rcu_unlock_domain(d);
> > > > - console_owner = next_rx;
> > > > - printk("*** Serial input to DOM%u", domid);
> > > > - break;
> > > > - }
> > > > + struct domain *d;
> > > >
> > > > + d = rcu_lock_domain_console_by_id(domid);
> > > > + if ( d != NULL )
> > > > rcu_unlock_domain(d);
> > > > - }
> > > > +
> > > > + return d != NULL;
> > > > +}
> > > > +
> > > > +int console_set_owner(domid_t domid)
> > > > +{
> > > > + if ( domid == DOMID_XEN )
> > > > + printk("*** Serial input to Xen");
> > > > + else if ( console_owner_possible(domid) )
> > > > + printk("*** Serial input to DOM%u", domid);
> > > > + else
> > > > + return -ENOENT;
> > > > +
> > > > + console_owner = domid;
> > > >
> > > > if ( switch_code )
> > > > printk(" (type 'CTRL-%c' three times to switch input)",
> > > > opt_conswitch[0]);
> > > > printk("\n");
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Switch console input focus.
> > > > + * Rotates input focus among Xen, dom0 and boot-time created domUs while
> > > > + * skipping switching serial input to non existing domains.
> > > > + */
> > > > +static void console_find_owner(void)
> > > > +{
> > > > + domid_t i, n = max_init_domid + 1;
> > >
> > > n can be made const, I would even rename to nr for clarity, but that's
> > > personal taste.
> >
> > `max_init_domid` can change at run-time actually (e.g. after `xl create`).
> > I kept `n` as is.
>
>
> How does max_init_domid potentially changing affect (possible) const-ness of n?
Sorry, what I meant is I kept the original name as is in v3.
Forgot to address `const`.
>
> However it changing, ...
>
> > > > +
> > > > + if ( console_owner == DOMID_XEN )
> > > > + i = get_initial_domain_id();
> > > > + else
> > > > + i = console_owner + 1;
> > > > +
> > > > + for ( ; i < n; i++ )
> > > > + if ( !console_set_owner(i) )
> > > > + break;
> > >
> > > Hm, that could be a non-trivial amount of iteration if max_init_domid
> > > is bumped for every domain created as you have it in patch 11/35
> > > (albeit I'm not sure that was intended?)
> >
> > Yes, `max_init_domid` is advanced on each domain creation (v3).
>
>
> ... as you confirm here, undermines what it's used for right now (if I'm
> not mistaken), and would render the variable misnamed.
Yes, the name will be a bit confusing.
Will something like `last_domid` work?
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 19/35] xen/console: introduce console_set_owner()
2025-01-06 20:03 ` Denis Mukhin
@ 2025-01-07 8:37 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-07 8:37 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini, Roger Pau Monné
On 06.01.2025 21:03, Denis Mukhin wrote:
>
> On Monday, January 6th, 2025 at 1:58 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>>
>>
>> On 04.01.2025 04:30, Denis Mukhin wrote:
>>
>>> On Thursday, December 12th, 2024 at 2:12 AM, Roger Pau Monné roger.pau@citrix.com wrote:
>>>
>>>> On Thu, Dec 05, 2024 at 08:41:49PM -0800, Denis Mukhin via B4 Relay wrote:
>>>>
>>>>> --- a/xen/drivers/char/console.c
>>>>> +++ b/xen/drivers/char/console.c
>>>>> @@ -463,82 +463,100 @@ 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_owner=0 => input to xen
>>>>> - * console_owner=1 => input to dom0 (or the sole shim domain)
>>>>> - * console_owner=N => input to dom(N-1)
>>>>> + * Current console owner domain ID: either Xen or domain w/ d->is_console ==
>>>>> + * true.
>>>>> + *
>>>>> + * Initialized in console_endboot().
>>>>> */
>>>>> -static unsigned int __read_mostly console_owner = 0;
>>>>> +static domid_t __read_mostly console_owner;
>>>>
>>>> Should this be initialized to DOMID_XEN? I assume it doesn't make
>>>> much difference because the variable is not checked before
>>>> console_endboot() anyway, but it might be safer to initialize to a
>>>> value that assigns the console to Xen.
>>>
>>> Fixed.
>>>
>>>>> -#define max_console_rx (max_init_domid + 1)
>>>>> +static struct domain *rcu_lock_domain_console_by_id(domid_t domid)
>>>>> +{
>>>>> + struct domain *d;
>>>>> +
>>>>> + d = rcu_lock_domain_by_id(domid);
>>>>> +
>>>>
>>>> Nit: I would remove this newline.
>>>
>>> Fixed.
>>>
>>>>> + if ( d == NULL )
>>>>> + return NULL;
>>>>> +
>>>>> + if ( d->is_console )
>>>>> + return d;
>>>>> +
>>>>> + rcu_unlock_domain(d);
>>>>> +
>>>>> + return NULL;
>>>>> +}
>>>>>
>>>>> -#ifdef CONFIG_SBSA_VUART_CONSOLE
>>>>> /* Make sure to rcu_unlock_domain after use */
>>>>> struct domain *rcu_lock_domain_console_owner(void)
>>>>> {
>>>>> - if ( console_owner == 0 )
>>>>> - return NULL;
>>>>> - return rcu_lock_domain_by_id(console_owner - 1);
>>>>> + return rcu_lock_domain_console_by_id(console_owner);
>>>>> }
>>>>> -#endif
>>>>>
>>>>> -static void console_find_owner(void)
>>>>> +static bool console_owner_possible(domid_t domid)
>>>>> {
>>>>> - unsigned int next_rx = console_owner;
>>>>> -
>>>>> - /*
>>>>> - * 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_owner = 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 == NULL )
>>>>> - continue;
>>>>> -
>>>>> - if ( d->is_console )
>>>>> - {
>>>>> - rcu_unlock_domain(d);
>>>>> - console_owner = next_rx;
>>>>> - printk("*** Serial input to DOM%u", domid);
>>>>> - break;
>>>>> - }
>>>>> + struct domain *d;
>>>>>
>>>>> + d = rcu_lock_domain_console_by_id(domid);
>>>>> + if ( d != NULL )
>>>>> rcu_unlock_domain(d);
>>>>> - }
>>>>> +
>>>>> + return d != NULL;
>>>>> +}
>>>>> +
>>>>> +int console_set_owner(domid_t domid)
>>>>> +{
>>>>> + if ( domid == DOMID_XEN )
>>>>> + printk("*** Serial input to Xen");
>>>>> + else if ( console_owner_possible(domid) )
>>>>> + printk("*** Serial input to DOM%u", domid);
>>>>> + else
>>>>> + return -ENOENT;
>>>>> +
>>>>> + console_owner = domid;
>>>>>
>>>>> if ( switch_code )
>>>>> printk(" (type 'CTRL-%c' three times to switch input)",
>>>>> opt_conswitch[0]);
>>>>> printk("\n");
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +/*
>>>>> + * Switch console input focus.
>>>>> + * Rotates input focus among Xen, dom0 and boot-time created domUs while
>>>>> + * skipping switching serial input to non existing domains.
>>>>> + */
>>>>> +static void console_find_owner(void)
>>>>> +{
>>>>> + domid_t i, n = max_init_domid + 1;
>>>>
>>>> n can be made const, I would even rename to nr for clarity, but that's
>>>> personal taste.
>>>
>>> `max_init_domid` can change at run-time actually (e.g. after `xl create`).
>>> I kept `n` as is.
>>
>>
>> How does max_init_domid potentially changing affect (possible) const-ness of n?
>
> Sorry, what I meant is I kept the original name as is in v3.
> Forgot to address `const`.
>
>>
>> However it changing, ...
>>
>>>>> +
>>>>> + if ( console_owner == DOMID_XEN )
>>>>> + i = get_initial_domain_id();
>>>>> + else
>>>>> + i = console_owner + 1;
>>>>> +
>>>>> + for ( ; i < n; i++ )
>>>>> + if ( !console_set_owner(i) )
>>>>> + break;
>>>>
>>>> Hm, that could be a non-trivial amount of iteration if max_init_domid
>>>> is bumped for every domain created as you have it in patch 11/35
>>>> (albeit I'm not sure that was intended?)
>>>
>>> Yes, `max_init_domid` is advanced on each domain creation (v3).
>>
>>
>> ... as you confirm here, undermines what it's used for right now (if I'm
>> not mistaken), and would render the variable misnamed.
>
> Yes, the name will be a bit confusing.
> Will something like `last_domid` work?
Well. First and foremost you need to make sure that existing uses of the
variable will continue to function as-is. Aiui that contradicts your
re-purposing of it. Which in turn would eliminate the question of how to
best rename it.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
console_owner_domid() is introduced to obtain the "console owner" domain ID.
The call is used in NS8250 emulator to identify the case when physical xen
console focus is owned by the domain w/ NS8250 emulator, in which case,
messages from guest OS are formatted w/o '(XEN)' prefix.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 5 +++++
xen/include/xen/console.h | 1 +
2 files changed, 6 insertions(+)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 52cf64dbf6fd18d599cb88835d03501a23b3e3c4..a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -498,6 +498,11 @@ struct domain *rcu_lock_domain_console_owner(void)
return rcu_lock_domain_console_by_id(console_owner);
}
+domid_t console_owner_domid(void)
+{
+ return console_owner;
+}
+
static bool console_owner_possible(domid_t domid)
{
struct domain *d;
diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
index 57c482cfbf2da15b011e64841ea086e779f4588d..83be5794aff6630beaad46f910fcc0fc6d833808 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -33,6 +33,7 @@ void console_end_log_everything(void);
struct domain *rcu_lock_domain_console_owner(void);
int console_set_owner(domid_t);
+domid_t console_owner_domid(void);
/*
* Steal output from the console. Returns +ve identifier, else -ve error.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 20/35] xen/console: introduce console_owner_domid()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
console_owner_domid() is introduced to obtain the "console owner" domain ID.
The call is used in NS8250 emulator to identify the case when physical xen
console focus is owned by the domain w/ NS8250 emulator, in which case,
messages from guest OS are formatted w/o '(XEN)' prefix.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 5 +++++
xen/include/xen/console.h | 1 +
2 files changed, 6 insertions(+)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 52cf64dbf6fd18d599cb88835d03501a23b3e3c4..a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -498,6 +498,11 @@ struct domain *rcu_lock_domain_console_owner(void)
return rcu_lock_domain_console_by_id(console_owner);
}
+domid_t console_owner_domid(void)
+{
+ return console_owner;
+}
+
static bool console_owner_possible(domid_t domid)
{
struct domain *d;
diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
index 57c482cfbf2da15b011e64841ea086e779f4588d..83be5794aff6630beaad46f910fcc0fc6d833808 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -33,6 +33,7 @@ void console_end_log_everything(void);
struct domain *rcu_lock_domain_console_owner(void);
int console_set_owner(domid_t);
+domid_t console_owner_domid(void);
/*
* Steal output from the console. Returns +ve identifier, else -ve error.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 22:11 ` Jason Andryuk
2024-12-11 7:33 ` Jan Beulich
2025-01-04 4:12 ` Denis Mukhin
-1 siblings, 2 replies; 218+ messages in thread
From: Jason Andryuk @ 2024-12-10 22:11 UTC (permalink / raw)
To: dmukhin, xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini
On 2024-12-05 23:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>
> The call is used in NS8250 emulator to identify the case when physical xen
> console focus is owned by the domain w/ NS8250 emulator, in which case,
> messages from guest OS are formatted w/o '(XEN)' prefix.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
I expected this to be used immediately by patch 21, but it is not. You
might want to re-order it directly before its first use is introduced.
I haven't gotten far enough to know when that is.
Regards,
Jason
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-10 22:11 ` Jason Andryuk
@ 2024-12-11 7:33 ` Jan Beulich
2025-01-04 4:16 ` Denis Mukhin
2025-01-04 4:12 ` Denis Mukhin
1 sibling, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-11 7:33 UTC (permalink / raw)
To: Jason Andryuk, dmukhin
Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 10.12.2024 23:11, Jason Andryuk wrote:
> On 2024-12-05 23:41, Denis Mukhin via B4 Relay wrote:
>> From: Denis Mukhin <dmukhin@ford.com>
>>
>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>
>> The call is used in NS8250 emulator to identify the case when physical xen
>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>
>> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
>
> Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
>
> I expected this to be used immediately by patch 21, but it is not. You
> might want to re-order it directly before its first use is introduced.
> I haven't gotten far enough to know when that is.
Plus, no matter how far in the future it is, there'll be a window where the
Misra rule of not having unreachable code in the project is violated. New
functions now really need introducing when their first caller appears.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-11 7:33 ` Jan Beulich
@ 2025-01-04 4:16 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:16 UTC (permalink / raw)
To: Jan Beulich
Cc: Jason Andryuk, dmukhin, Andrew Cooper, Julien Grall,
Stefano Stabellini, xen-devel
On Tuesday, December 10th, 2024 at 11:33 PM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 10.12.2024 23:11, Jason Andryuk wrote:
>
> > On 2024-12-05 23:41, Denis Mukhin via B4 Relay wrote:
> >
> > > From: Denis Mukhin dmukhin@ford.com
> > >
> > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > >
> > > The call is used in NS8250 emulator to identify the case when physical xen
> > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > >
> > > Signed-off-by: Denis Mukhin dmukhin@ford.com
> >
> > Reviewed-by: Jason Andryuk jason.andryuk@amd.com
> >
> > I expected this to be used immediately by patch 21, but it is not. You
> > might want to re-order it directly before its first use is introduced.
> > I haven't gotten far enough to know when that is.
>
>
> Plus, no matter how far in the future it is, there'll be a window where the
> Misra rule of not having unreachable code in the project is violated. New
> functions now really need introducing when their first caller appears.
I see, thank you for the explanation.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-10 22:11 ` Jason Andryuk
2024-12-11 7:33 ` Jan Beulich
@ 2025-01-04 4:12 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:12 UTC (permalink / raw)
To: Jason Andryuk
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Tuesday, December 10th, 2024 at 2:11 PM, Jason Andryuk <jason.andryuk@amd.com> wrote:
>
>
> On 2024-12-05 23:41, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >
> > The call is used in NS8250 emulator to identify the case when physical xen
> > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > messages from guest OS are formatted w/o '(XEN)' prefix.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
>
>
> Reviewed-by: Jason Andryuk jason.andryuk@amd.com
>
>
> I expected this to be used immediately by patch 21, but it is not. You
> might want to re-order it directly before its first use is introduced.
> I haven't gotten far enough to know when that is.
Yeah, sorry for that.
I ended up dropping this patch from the series.
>
> Regards,
> Jason
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 7:28 ` Jan Beulich
2025-01-04 4:15 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-11 7:28 UTC (permalink / raw)
To: dmukhin, xen-devel; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>
> The call is used in NS8250 emulator to identify the case when physical xen
> console focus is owned by the domain w/ NS8250 emulator, in which case,
> messages from guest OS are formatted w/o '(XEN)' prefix.
Such messages ought to be processed through guest_printk(), which wants a
domain pointer, not a domid_t anyway. Plus isn't that going to be
current->domain anyway at the callsite, eliminating the need for such a
helper altogether?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-11 7:28 ` Jan Beulich
@ 2025-01-04 4:15 ` Denis Mukhin
2025-01-06 9:14 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:15 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >
> > The call is used in NS8250 emulator to identify the case when physical xen
> > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > messages from guest OS are formatted w/o '(XEN)' prefix.
>
>
> Such messages ought to be processed through guest_printk(), which wants a
> domain pointer, not a domid_t anyway. Plus isn't that going to be
> current->domain anyway at the callsite, eliminating the need for such a
>
> helper altogether?
If the current domain is owning the physical console and printing, say, Linux
login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
can be disabled from Xen command line.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-04 4:15 ` Denis Mukhin
@ 2025-01-06 9:14 ` Jan Beulich
2025-01-06 18:48 ` Stefano Stabellini
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 9:14 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On 04.01.2025 05:15, Denis Mukhin wrote:
>
> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
>
>>
>>
>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>
>>> From: Denis Mukhin dmukhin@ford.com
>>>
>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>>
>>> The call is used in NS8250 emulator to identify the case when physical xen
>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>
>>
>> Such messages ought to be processed through guest_printk(), which wants a
>> domain pointer, not a domid_t anyway. Plus isn't that going to be
>> current->domain anyway at the callsite, eliminating the need for such a
>>
>> helper altogether?
>
> If the current domain is owning the physical console and printing, say, Linux
> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> can be disabled from Xen command line.
Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
which domain a message came from. As long as only Dom0 messages are left un-
prefixed, that's likely fine. Yet as soon as multiple domains can issue such
messages (and have console "focus") I think the prefix needs to be there.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-06 9:14 ` Jan Beulich
@ 2025-01-06 18:48 ` Stefano Stabellini
2025-01-07 8:40 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Stefano Stabellini @ 2025-01-06 18:48 UTC (permalink / raw)
To: Jan Beulich
Cc: Denis Mukhin, dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Stefano Stabellini
On Mon, 6 Jan 2025, Jan Beulich wrote:
> On 04.01.2025 05:15, Denis Mukhin wrote:
> >
> > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
> >
> >>
> >>
> >> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> >>
> >>> From: Denis Mukhin dmukhin@ford.com
> >>>
> >>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >>>
> >>> The call is used in NS8250 emulator to identify the case when physical xen
> >>> console focus is owned by the domain w/ NS8250 emulator, in which case,
> >>> messages from guest OS are formatted w/o '(XEN)' prefix.
> >>
> >>
> >> Such messages ought to be processed through guest_printk(), which wants a
> >> domain pointer, not a domid_t anyway. Plus isn't that going to be
> >> current->domain anyway at the callsite, eliminating the need for such a
> >>
> >> helper altogether?
> >
> > If the current domain is owning the physical console and printing, say, Linux
> > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > can be disabled from Xen command line.
>
> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> which domain a message came from. As long as only Dom0 messages are left un-
> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> messages (and have console "focus") I think the prefix needs to be there.
Hi Jan,
It looks like we are aligned on the desired behavior, but for clarity,
see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
here:
I think we should provide a consistent behavior across architectures.
The current behavior with vpl011 and dom0less on ARM is the following:
- no prefix for Dom0 output
- DOM$NUM for DomUs when not in focus, otherwise no prefix
It is OK to change this behavior, but in that case I would ask that we
change it consistently also for ARM.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-06 18:48 ` Stefano Stabellini
@ 2025-01-07 8:40 ` Jan Beulich
2025-01-07 23:40 ` Stefano Stabellini
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-07 8:40 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Denis Mukhin, dmukhin, xen-devel, Andrew Cooper, Julien Grall
On 06.01.2025 19:48, Stefano Stabellini wrote:
> On Mon, 6 Jan 2025, Jan Beulich wrote:
>> On 04.01.2025 05:15, Denis Mukhin wrote:
>>>
>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
>>>
>>>>
>>>>
>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>>>
>>>>> From: Denis Mukhin dmukhin@ford.com
>>>>>
>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>>>>
>>>>> The call is used in NS8250 emulator to identify the case when physical xen
>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>>>
>>>>
>>>> Such messages ought to be processed through guest_printk(), which wants a
>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
>>>> current->domain anyway at the callsite, eliminating the need for such a
>>>>
>>>> helper altogether?
>>>
>>> If the current domain is owning the physical console and printing, say, Linux
>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
>>> can be disabled from Xen command line.
>>
>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
>> which domain a message came from. As long as only Dom0 messages are left un-
>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
>> messages (and have console "focus") I think the prefix needs to be there.
>
> It looks like we are aligned on the desired behavior,
Hmm, no, I don't think we are. I don't ...
> but for clarity,
> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> here:
>
> I think we should provide a consistent behavior across architectures.
> The current behavior with vpl011 and dom0less on ARM is the following:
>
> - no prefix for Dom0 output
> - DOM$NUM for DomUs when not in focus, otherwise no prefix
... view this model as a desirable one. It leaves room for ambiguity.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-07 8:40 ` Jan Beulich
@ 2025-01-07 23:40 ` Stefano Stabellini
2025-01-08 7:28 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Stefano Stabellini @ 2025-01-07 23:40 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Denis Mukhin, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel,
Roger Pau Monné
On Tue, 7 Jan 2025, Jan Beulich wrote:
> On 06.01.2025 19:48, Stefano Stabellini wrote:
> > On Mon, 6 Jan 2025, Jan Beulich wrote:
> >> On 04.01.2025 05:15, Denis Mukhin wrote:
> >>>
> >>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
> >>>
> >>>>
> >>>>
> >>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> >>>>
> >>>>> From: Denis Mukhin dmukhin@ford.com
> >>>>>
> >>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >>>>>
> >>>>> The call is used in NS8250 emulator to identify the case when physical xen
> >>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
> >>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
> >>>>
> >>>>
> >>>> Such messages ought to be processed through guest_printk(), which wants a
> >>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
> >>>> current->domain anyway at the callsite, eliminating the need for such a
> >>>>
> >>>> helper altogether?
> >>>
> >>> If the current domain is owning the physical console and printing, say, Linux
> >>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> >>> can be disabled from Xen command line.
> >>
> >> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> >> which domain a message came from. As long as only Dom0 messages are left un-
> >> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> >> messages (and have console "focus") I think the prefix needs to be there.
> >
> > It looks like we are aligned on the desired behavior,
>
> Hmm, no, I don't think we are. I don't ...
>
> > but for clarity,
> > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > here:
> >
> > I think we should provide a consistent behavior across architectures.
> > The current behavior with vpl011 and dom0less on ARM is the following:
> >
> > - no prefix for Dom0 output
> > - DOM$NUM for DomUs when not in focus, otherwise no prefix
>
> ... view this model as a desirable one. It leaves room for ambiguity.
Adding a few more people in CC for feedback.
My priority is to keep the architectures aligned. It might be OK to
change output format, but then let's do it uniformly on ARM as well.
Jan, please clarify what you think would be better than the above. Is it
the following? I don't think I understood your preference.
- DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-07 23:40 ` Stefano Stabellini
@ 2025-01-08 7:28 ` Jan Beulich
2025-01-08 8:04 ` Roger Pau Monné
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-08 7:28 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Denis Mukhin, dmukhin, xen-devel, Andrew Cooper, Julien Grall,
Bertrand Marquis, Michal Orzel, Roger Pau Monné
On 08.01.2025 00:40, Stefano Stabellini wrote:
> On Tue, 7 Jan 2025, Jan Beulich wrote:
>> On 06.01.2025 19:48, Stefano Stabellini wrote:
>>> On Mon, 6 Jan 2025, Jan Beulich wrote:
>>>> On 04.01.2025 05:15, Denis Mukhin wrote:
>>>>>
>>>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>>>>>
>>>>>>> From: Denis Mukhin dmukhin@ford.com
>>>>>>>
>>>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>>>>>>
>>>>>>> The call is used in NS8250 emulator to identify the case when physical xen
>>>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>>>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>>>>>
>>>>>>
>>>>>> Such messages ought to be processed through guest_printk(), which wants a
>>>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
>>>>>> current->domain anyway at the callsite, eliminating the need for such a
>>>>>>
>>>>>> helper altogether?
>>>>>
>>>>> If the current domain is owning the physical console and printing, say, Linux
>>>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
>>>>> can be disabled from Xen command line.
>>>>
>>>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
>>>> which domain a message came from. As long as only Dom0 messages are left un-
>>>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
>>>> messages (and have console "focus") I think the prefix needs to be there.
>>>
>>> It looks like we are aligned on the desired behavior,
>>
>> Hmm, no, I don't think we are. I don't ...
>>
>>> but for clarity,
>>> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
>>> here:
>>>
>>> I think we should provide a consistent behavior across architectures.
>>> The current behavior with vpl011 and dom0less on ARM is the following:
>>>
>>> - no prefix for Dom0 output
>>> - DOM$NUM for DomUs when not in focus, otherwise no prefix
>>
>> ... view this model as a desirable one. It leaves room for ambiguity.
>
> Adding a few more people in CC for feedback.
>
> My priority is to keep the architectures aligned. It might be OK to
> change output format, but then let's do it uniformly on ARM as well.
>
> Jan, please clarify what you think would be better than the above. Is it
> the following? I don't think I understood your preference.
>
> - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
No, I mean like we have it with guest_printk() today. (XEN) for Xen's
own messages, (d<N>) for ordinary domains' ones, and no prefix
exclusively for the hardware/control domain. What is best to do when
hardware and control domains are distinct I'm uncertain - I'd be
inclined to suggest that the hardware domain then stay the one without
any prefix.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-08 7:28 ` Jan Beulich
@ 2025-01-08 8:04 ` Roger Pau Monné
2025-01-08 8:13 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2025-01-08 8:04 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Denis Mukhin, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel
On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> On 08.01.2025 00:40, Stefano Stabellini wrote:
> > On Tue, 7 Jan 2025, Jan Beulich wrote:
> >> On 06.01.2025 19:48, Stefano Stabellini wrote:
> >>> On Mon, 6 Jan 2025, Jan Beulich wrote:
> >>>> On 04.01.2025 05:15, Denis Mukhin wrote:
> >>>>>
> >>>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> >>>>>>
> >>>>>>> From: Denis Mukhin dmukhin@ford.com
> >>>>>>>
> >>>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >>>>>>>
> >>>>>>> The call is used in NS8250 emulator to identify the case when physical xen
> >>>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
> >>>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
> >>>>>>
> >>>>>>
> >>>>>> Such messages ought to be processed through guest_printk(), which wants a
> >>>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
> >>>>>> current->domain anyway at the callsite, eliminating the need for such a
> >>>>>>
> >>>>>> helper altogether?
> >>>>>
> >>>>> If the current domain is owning the physical console and printing, say, Linux
> >>>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> >>>>> can be disabled from Xen command line.
> >>>>
> >>>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> >>>> which domain a message came from. As long as only Dom0 messages are left un-
> >>>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> >>>> messages (and have console "focus") I think the prefix needs to be there.
> >>>
> >>> It looks like we are aligned on the desired behavior,
> >>
> >> Hmm, no, I don't think we are. I don't ...
> >>
> >>> but for clarity,
> >>> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> >>> here:
> >>>
> >>> I think we should provide a consistent behavior across architectures.
> >>> The current behavior with vpl011 and dom0less on ARM is the following:
> >>>
> >>> - no prefix for Dom0 output
> >>> - DOM$NUM for DomUs when not in focus, otherwise no prefix
> >>
> >> ... view this model as a desirable one. It leaves room for ambiguity.
> >
> > Adding a few more people in CC for feedback.
> >
> > My priority is to keep the architectures aligned. It might be OK to
> > change output format, but then let's do it uniformly on ARM as well.
> >
> > Jan, please clarify what you think would be better than the above. Is it
> > the following? I don't think I understood your preference.
> >
> > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
>
> No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> own messages, (d<N>) for ordinary domains' ones, and no prefix
> exclusively for the hardware/control domain. What is best to do when
> hardware and control domains are distinct I'm uncertain - I'd be
> inclined to suggest that the hardware domain then stay the one without
> any prefix.
One concern I have with this approach is whether the addition of the
(d<N>) prefixes will skew output of interactive applications. So far
the prefix is added to output from all domains different than dom0
because the console is not interactive for them, and hence no input
can be consumed.
If that changes however, and domains different than dom0 can get input
from the Xen console then I wonder how much the added prefix will skew
output. Another possible option would be to not print the prefix for
the domain that has the console input assigned (current target), and
print it for all other domains (even for dom0 when not in focus).
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-08 8:04 ` Roger Pau Monné
@ 2025-01-08 8:13 ` Jan Beulich
2025-01-08 8:35 ` Roger Pau Monné
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-08 8:13 UTC (permalink / raw)
To: Roger Pau Monné
Cc: Stefano Stabellini, Denis Mukhin, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel
On 08.01.2025 09:04, Roger Pau Monné wrote:
> On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
>> On 08.01.2025 00:40, Stefano Stabellini wrote:
>>> On Tue, 7 Jan 2025, Jan Beulich wrote:
>>>> On 06.01.2025 19:48, Stefano Stabellini wrote:
>>>>> On Mon, 6 Jan 2025, Jan Beulich wrote:
>>>>>> On 04.01.2025 05:15, Denis Mukhin wrote:
>>>>>>>
>>>>>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>>>>>>>
>>>>>>>>> From: Denis Mukhin dmukhin@ford.com
>>>>>>>>>
>>>>>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>>>>>>>>
>>>>>>>>> The call is used in NS8250 emulator to identify the case when physical xen
>>>>>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>>>>>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>>>>>>>
>>>>>>>>
>>>>>>>> Such messages ought to be processed through guest_printk(), which wants a
>>>>>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
>>>>>>>> current->domain anyway at the callsite, eliminating the need for such a
>>>>>>>>
>>>>>>>> helper altogether?
>>>>>>>
>>>>>>> If the current domain is owning the physical console and printing, say, Linux
>>>>>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
>>>>>>> can be disabled from Xen command line.
>>>>>>
>>>>>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
>>>>>> which domain a message came from. As long as only Dom0 messages are left un-
>>>>>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
>>>>>> messages (and have console "focus") I think the prefix needs to be there.
>>>>>
>>>>> It looks like we are aligned on the desired behavior,
>>>>
>>>> Hmm, no, I don't think we are. I don't ...
>>>>
>>>>> but for clarity,
>>>>> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
>>>>> here:
>>>>>
>>>>> I think we should provide a consistent behavior across architectures.
>>>>> The current behavior with vpl011 and dom0less on ARM is the following:
>>>>>
>>>>> - no prefix for Dom0 output
>>>>> - DOM$NUM for DomUs when not in focus, otherwise no prefix
>>>>
>>>> ... view this model as a desirable one. It leaves room for ambiguity.
>>>
>>> Adding a few more people in CC for feedback.
>>>
>>> My priority is to keep the architectures aligned. It might be OK to
>>> change output format, but then let's do it uniformly on ARM as well.
>>>
>>> Jan, please clarify what you think would be better than the above. Is it
>>> the following? I don't think I understood your preference.
>>>
>>> - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
>>
>> No, I mean like we have it with guest_printk() today. (XEN) for Xen's
>> own messages, (d<N>) for ordinary domains' ones, and no prefix
>> exclusively for the hardware/control domain. What is best to do when
>> hardware and control domains are distinct I'm uncertain - I'd be
>> inclined to suggest that the hardware domain then stay the one without
>> any prefix.
>
> One concern I have with this approach is whether the addition of the
> (d<N>) prefixes will skew output of interactive applications. So far
> the prefix is added to output from all domains different than dom0
> because the console is not interactive for them, and hence no input
> can be consumed.
Hmm, that's an aspect I have to admit I didn't think of.
> If that changes however, and domains different than dom0 can get input
> from the Xen console then I wonder how much the added prefix will skew
> output. Another possible option would be to not print the prefix for
> the domain that has the console input assigned (current target), and
> print it for all other domains (even for dom0 when not in focus).
That's largely what aiui was proposed. My extra requirement there would
then be that we make sure a log message is always emitted when console
focus shifts, so it's possible to identify the owner for any part of
the log.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-08 8:13 ` Jan Beulich
@ 2025-01-08 8:35 ` Roger Pau Monné
2025-01-08 22:15 ` Denis Mukhin
0 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2025-01-08 8:35 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Denis Mukhin, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel
On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
> On 08.01.2025 09:04, Roger Pau Monné wrote:
> > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> >> On 08.01.2025 00:40, Stefano Stabellini wrote:
> >>> On Tue, 7 Jan 2025, Jan Beulich wrote:
> >>>> On 06.01.2025 19:48, Stefano Stabellini wrote:
> >>>>> On Mon, 6 Jan 2025, Jan Beulich wrote:
> >>>>>> On 04.01.2025 05:15, Denis Mukhin wrote:
> >>>>>>>
> >>>>>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich <jbeulich@suse.com> wrote:
> >>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> >>>>>>>>
> >>>>>>>>> From: Denis Mukhin dmukhin@ford.com
> >>>>>>>>>
> >>>>>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >>>>>>>>>
> >>>>>>>>> The call is used in NS8250 emulator to identify the case when physical xen
> >>>>>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
> >>>>>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Such messages ought to be processed through guest_printk(), which wants a
> >>>>>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
> >>>>>>>> current->domain anyway at the callsite, eliminating the need for such a
> >>>>>>>>
> >>>>>>>> helper altogether?
> >>>>>>>
> >>>>>>> If the current domain is owning the physical console and printing, say, Linux
> >>>>>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> >>>>>>> can be disabled from Xen command line.
> >>>>>>
> >>>>>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> >>>>>> which domain a message came from. As long as only Dom0 messages are left un-
> >>>>>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> >>>>>> messages (and have console "focus") I think the prefix needs to be there.
> >>>>>
> >>>>> It looks like we are aligned on the desired behavior,
> >>>>
> >>>> Hmm, no, I don't think we are. I don't ...
> >>>>
> >>>>> but for clarity,
> >>>>> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> >>>>> here:
> >>>>>
> >>>>> I think we should provide a consistent behavior across architectures.
> >>>>> The current behavior with vpl011 and dom0less on ARM is the following:
> >>>>>
> >>>>> - no prefix for Dom0 output
> >>>>> - DOM$NUM for DomUs when not in focus, otherwise no prefix
> >>>>
> >>>> ... view this model as a desirable one. It leaves room for ambiguity.
> >>>
> >>> Adding a few more people in CC for feedback.
> >>>
> >>> My priority is to keep the architectures aligned. It might be OK to
> >>> change output format, but then let's do it uniformly on ARM as well.
> >>>
> >>> Jan, please clarify what you think would be better than the above. Is it
> >>> the following? I don't think I understood your preference.
> >>>
> >>> - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> >>
> >> No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> >> own messages, (d<N>) for ordinary domains' ones, and no prefix
> >> exclusively for the hardware/control domain. What is best to do when
> >> hardware and control domains are distinct I'm uncertain - I'd be
> >> inclined to suggest that the hardware domain then stay the one without
> >> any prefix.
> >
> > One concern I have with this approach is whether the addition of the
> > (d<N>) prefixes will skew output of interactive applications. So far
> > the prefix is added to output from all domains different than dom0
> > because the console is not interactive for them, and hence no input
> > can be consumed.
>
> Hmm, that's an aspect I have to admit I didn't think of.
>
> > If that changes however, and domains different than dom0 can get input
> > from the Xen console then I wonder how much the added prefix will skew
> > output. Another possible option would be to not print the prefix for
> > the domain that has the console input assigned (current target), and
> > print it for all other domains (even for dom0 when not in focus).
>
> That's largely what aiui was proposed. My extra requirement there would
> then be that we make sure a log message is always emitted when console
> focus shifts, so it's possible to identify the owner for any part of
> the log.
Indeed, printing console input shifting should be a requirement
regardless of how we decide to print the prefix.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-08 8:35 ` Roger Pau Monné
@ 2025-01-08 22:15 ` Denis Mukhin
2025-01-09 0:29 ` Stefano Stabellini
2025-01-09 8:27 ` Jan Beulich
0 siblings, 2 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-08 22:15 UTC (permalink / raw)
To: Roger Pau Monné
Cc: Jan Beulich, Stefano Stabellini, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel
On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
>
> > On 08.01.2025 09:04, Roger Pau Monné wrote:
> >
> > > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> > >
> > > > On 08.01.2025 00:40, Stefano Stabellini wrote:
> > > >
> > > > > On Tue, 7 Jan 2025, Jan Beulich wrote:
> > > > >
> > > > > > On 06.01.2025 19:48, Stefano Stabellini wrote:
> > > > > >
> > > > > > > On Mon, 6 Jan 2025, Jan Beulich wrote:
> > > > > > >
> > > > > > > > On 04.01.2025 05:15, Denis Mukhin wrote:
> > > > > > > >
> > > > > > > > > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
> > > > > > > > >
> > > > > > > > > > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > > > > > > > > >
> > > > > > > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > > > > > > >
> > > > > > > > > > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > > > > > > > > > >
> > > > > > > > > > > The call is used in NS8250 emulator to identify the case when physical xen
> > > > > > > > > > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > > > > > > > > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > > > > > > > > >
> > > > > > > > > > Such messages ought to be processed through guest_printk(), which wants a
> > > > > > > > > > domain pointer, not a domid_t anyway. Plus isn't that going to be
> > > > > > > > > > current->domain anyway at the callsite, eliminating the need for such a
> > > > > > > > > >
> > > > > > > > > > helper altogether?
> > > > > > > > >
> > > > > > > > > If the current domain is owning the physical console and printing, say, Linux
> > > > > > > > > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > > > > > > > > can be disabled from Xen command line.
> > > > > > > >
> > > > > > > > Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> > > > > > > > which domain a message came from. As long as only Dom0 messages are left un-
> > > > > > > > prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> > > > > > > > messages (and have console "focus") I think the prefix needs to be there.
> > > > > > >
> > > > > > > It looks like we are aligned on the desired behavior,
> > > > > >
> > > > > > Hmm, no, I don't think we are. I don't ...
> > > > > >
> > > > > > > but for clarity,
> > > > > > > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > > > > > > here:
> > > > > > >
> > > > > > > I think we should provide a consistent behavior across architectures.
> > > > > > > The current behavior with vpl011 and dom0less on ARM is the following:
> > > > > > >
> > > > > > > - no prefix for Dom0 output
> > > > > > > - DOM$NUM for DomUs when not in focus, otherwise no prefix
> > > > > >
> > > > > > ... view this model as a desirable one. It leaves room for ambiguity.
> > > > >
> > > > > Adding a few more people in CC for feedback.
> > > > >
> > > > > My priority is to keep the architectures aligned. It might be OK to
> > > > > change output format, but then let's do it uniformly on ARM as well.
> > > > >
> > > > > Jan, please clarify what you think would be better than the above. Is it
> > > > > the following? I don't think I understood your preference.
> > > > >
> > > > > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> > > >
> > > > No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> > > > own messages, (d<N>) for ordinary domains' ones, and no prefix
> > > > exclusively for the hardware/control domain. What is best to do when
> > > > hardware and control domains are distinct I'm uncertain - I'd be
> > > > inclined to suggest that the hardware domain then stay the one without
> > > > any prefix.
> > >
> > > One concern I have with this approach is whether the addition of the
> > > (d<N>) prefixes will skew output of interactive applications. So far
> > > the prefix is added to output from all domains different than dom0
> > > because the console is not interactive for them, and hence no input
> > > can be consumed.
> >
> > Hmm, that's an aspect I have to admit I didn't think of.
> >
> > > If that changes however, and domains different than dom0 can get input
> > > from the Xen console then I wonder how much the added prefix will skew
> > > output. Another possible option would be to not print the prefix for
> > > the domain that has the console input assigned (current target), and
> > > print it for all other domains (even for dom0 when not in focus).
> >
> > That's largely what aiui was proposed. My extra requirement there would
> > then be that we make sure a log message is always emitted when console
> > focus shifts, so it's possible to identify the owner for any part of
> > the log.
>
>
> Indeed, printing console input shifting should be a requirement
> regardless of how we decide to print the prefix.
Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
[[
...
(XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
(XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
(XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
...
]]
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-08 22:15 ` Denis Mukhin
@ 2025-01-09 0:29 ` Stefano Stabellini
2025-01-09 8:06 ` Roger Pau Monné
2025-01-09 8:25 ` Jan Beulich
2025-01-09 8:27 ` Jan Beulich
1 sibling, 2 replies; 218+ messages in thread
From: Stefano Stabellini @ 2025-01-09 0:29 UTC (permalink / raw)
To: Denis Mukhin
Cc: Roger Pau Monné, Jan Beulich, Stefano Stabellini, dmukhin,
xen-devel, Andrew Cooper, Julien Grall, Bertrand Marquis,
Michal Orzel
[-- Attachment #1: Type: text/plain, Size: 7223 bytes --]
On Wed, 8 Jan 2025, Denis Mukhin wrote:
> On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
> > On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
> > > On 08.01.2025 09:04, Roger Pau Monné wrote:
> > > > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> > > > > On 08.01.2025 00:40, Stefano Stabellini wrote:
> > > > > > On Tue, 7 Jan 2025, Jan Beulich wrote:
> > > > > > > On 06.01.2025 19:48, Stefano Stabellini wrote:
> > > > > > > > On Mon, 6 Jan 2025, Jan Beulich wrote:
> > > > > > > > > On 04.01.2025 05:15, Denis Mukhin wrote:
> > > > > > > > > > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
> > > > > > > > > > > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > > > > > > > > > >
> > > > > > > > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > > > > > > > >
> > > > > > > > > > > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > > > > > > > > > > >
> > > > > > > > > > > > The call is used in NS8250 emulator to identify the case when physical xen
> > > > > > > > > > > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > > > > > > > > > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > > > > > > > > > >
> > > > > > > > > > > Such messages ought to be processed through guest_printk(), which wants a
> > > > > > > > > > > domain pointer, not a domid_t anyway. Plus isn't that going to be
> > > > > > > > > > > current->domain anyway at the callsite, eliminating the need for such a
> > > > > > > > > > >
> > > > > > > > > > > helper altogether?
> > > > > > > > > >
> > > > > > > > > > If the current domain is owning the physical console and printing, say, Linux
> > > > > > > > > > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > > > > > > > > > can be disabled from Xen command line.
> > > > > > > > >
> > > > > > > > > Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> > > > > > > > > which domain a message came from. As long as only Dom0 messages are left un-
> > > > > > > > > prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> > > > > > > > > messages (and have console "focus") I think the prefix needs to be there.
> > > > > > > >
> > > > > > > > It looks like we are aligned on the desired behavior,
> > > > > > >
> > > > > > > Hmm, no, I don't think we are. I don't ...
> > > > > > >
> > > > > > > > but for clarity,
> > > > > > > > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > > > > > > > here:
> > > > > > > >
> > > > > > > > I think we should provide a consistent behavior across architectures.
> > > > > > > > The current behavior with vpl011 and dom0less on ARM is the following:
> > > > > > > >
> > > > > > > > - no prefix for Dom0 output
> > > > > > > > - DOM$NUM for DomUs when not in focus, otherwise no prefix
> > > > > > >
> > > > > > > ... view this model as a desirable one. It leaves room for ambiguity.
> > > > > >
> > > > > > Adding a few more people in CC for feedback.
> > > > > >
> > > > > > My priority is to keep the architectures aligned. It might be OK to
> > > > > > change output format, but then let's do it uniformly on ARM as well.
> > > > > >
> > > > > > Jan, please clarify what you think would be better than the above. Is it
> > > > > > the following? I don't think I understood your preference.
> > > > > >
> > > > > > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> > > > >
> > > > > No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> > > > > own messages, (d<N>) for ordinary domains' ones, and no prefix
> > > > > exclusively for the hardware/control domain. What is best to do when
> > > > > hardware and control domains are distinct I'm uncertain - I'd be
> > > > > inclined to suggest that the hardware domain then stay the one without
> > > > > any prefix.
> > > >
> > > > One concern I have with this approach is whether the addition of the
> > > > (d<N>) prefixes will skew output of interactive applications. So far
> > > > the prefix is added to output from all domains different than dom0
> > > > because the console is not interactive for them, and hence no input
> > > > can be consumed.
> > >
> > > Hmm, that's an aspect I have to admit I didn't think of.
> > >
> > > > If that changes however, and domains different than dom0 can get input
> > > > from the Xen console then I wonder how much the added prefix will skew
> > > > output. Another possible option would be to not print the prefix for
> > > > the domain that has the console input assigned (current target), and
> > > > print it for all other domains (even for dom0 when not in focus).
> > >
> > > That's largely what aiui was proposed. My extra requirement there would
> > > then be that we make sure a log message is always emitted when console
> > > focus shifts, so it's possible to identify the owner for any part of
> > > the log.
> >
> >
> > Indeed, printing console input shifting should be a requirement
> > regardless of how we decide to print the prefix.
>
> Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
> [[
> ...
> (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
> (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
> (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
> ...
> ]]
Roger, Jan, you should use Xen Dom0less more :-) This is the way it
already works on ARM. Let me expand on my earlier message that was too
terse.
At boot time, Xen prints messages with the (XEN) prefix as usual:
(XEN) Brought up 4 CPUs
When Dom0 starts, it has not prefix (and has input by default):
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
When a DomU starts, it has the following prefix (and doesn't have
input):
(XEN) DOM1: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
Eventually, both Linuxes finish booting, you can login into Dom0 as
usual. Messages from Dom1, if any, are still printed with (XEN) DOM1 as
prefix.
You can switch input to Dom1 with Ctrx-aaa, the same way that you do
today to switch between Xen and Dom0. Xen prints a message:
(XEN) *** Serial input to DOM1 (type 'CTRL-a' three times to switch input)
Now, as you type, you send characters to Dom1. And Dom1 doesn't have the
DOM1 prefix any longer, while it is still has (XEN) because the message
is printed by Xen on behalf of the domain:
(XEN) / # echo hello world
(XEN) hello world
If Dom0 prints anything in the backgrounds, it shows without prefixes:
hello world from dom0
If another domain, dom2, prints anything in the background, it shows
with (XEN) DOM2 prefix:
(XEN) DOM2: hello from dom2
I think it makes sense to be consistent across architectures and we
should default to the same behavior on x86 too. If we want to make
improvements, the one thing I could potentially see changing is adding a
DOM0 prefix to Dom0 messages when Dom0 does not have input. If we do
that, let's do it on both ARM and x86 architectures.
Cheers,
Stefano
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-09 0:29 ` Stefano Stabellini
@ 2025-01-09 8:06 ` Roger Pau Monné
2025-01-09 23:46 ` Stefano Stabellini
2025-01-09 8:25 ` Jan Beulich
1 sibling, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2025-01-09 8:06 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Denis Mukhin, Jan Beulich, dmukhin, xen-devel, Andrew Cooper,
Julien Grall, Bertrand Marquis, Michal Orzel
On Wed, Jan 08, 2025 at 04:29:24PM -0800, Stefano Stabellini wrote:
> On Wed, 8 Jan 2025, Denis Mukhin wrote:
> > On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
> > > On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
> > > > On 08.01.2025 09:04, Roger Pau Monné wrote:
> > > > > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> > > > > > On 08.01.2025 00:40, Stefano Stabellini wrote:
> > > > > > > On Tue, 7 Jan 2025, Jan Beulich wrote:
> > > > > > > > On 06.01.2025 19:48, Stefano Stabellini wrote:
> > > > > > > > > On Mon, 6 Jan 2025, Jan Beulich wrote:
> > > > > > > > > > On 04.01.2025 05:15, Denis Mukhin wrote:
> > > > > > > > > > > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
> > > > > > > > > > > > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > > > > > > > > >
> > > > > > > > > > > > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > > > > > > > > > > > >
> > > > > > > > > > > > > The call is used in NS8250 emulator to identify the case when physical xen
> > > > > > > > > > > > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > > > > > > > > > > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > > > > > > > > > > >
> > > > > > > > > > > > Such messages ought to be processed through guest_printk(), which wants a
> > > > > > > > > > > > domain pointer, not a domid_t anyway. Plus isn't that going to be
> > > > > > > > > > > > current->domain anyway at the callsite, eliminating the need for such a
> > > > > > > > > > > >
> > > > > > > > > > > > helper altogether?
> > > > > > > > > > >
> > > > > > > > > > > If the current domain is owning the physical console and printing, say, Linux
> > > > > > > > > > > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > > > > > > > > > > can be disabled from Xen command line.
> > > > > > > > > >
> > > > > > > > > > Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> > > > > > > > > > which domain a message came from. As long as only Dom0 messages are left un-
> > > > > > > > > > prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> > > > > > > > > > messages (and have console "focus") I think the prefix needs to be there.
> > > > > > > > >
> > > > > > > > > It looks like we are aligned on the desired behavior,
> > > > > > > >
> > > > > > > > Hmm, no, I don't think we are. I don't ...
> > > > > > > >
> > > > > > > > > but for clarity,
> > > > > > > > > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > > > > > > > > here:
> > > > > > > > >
> > > > > > > > > I think we should provide a consistent behavior across architectures.
> > > > > > > > > The current behavior with vpl011 and dom0less on ARM is the following:
> > > > > > > > >
> > > > > > > > > - no prefix for Dom0 output
> > > > > > > > > - DOM$NUM for DomUs when not in focus, otherwise no prefix
> > > > > > > >
> > > > > > > > ... view this model as a desirable one. It leaves room for ambiguity.
> > > > > > >
> > > > > > > Adding a few more people in CC for feedback.
> > > > > > >
> > > > > > > My priority is to keep the architectures aligned. It might be OK to
> > > > > > > change output format, but then let's do it uniformly on ARM as well.
> > > > > > >
> > > > > > > Jan, please clarify what you think would be better than the above. Is it
> > > > > > > the following? I don't think I understood your preference.
> > > > > > >
> > > > > > > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> > > > > >
> > > > > > No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> > > > > > own messages, (d<N>) for ordinary domains' ones, and no prefix
> > > > > > exclusively for the hardware/control domain. What is best to do when
> > > > > > hardware and control domains are distinct I'm uncertain - I'd be
> > > > > > inclined to suggest that the hardware domain then stay the one without
> > > > > > any prefix.
> > > > >
> > > > > One concern I have with this approach is whether the addition of the
> > > > > (d<N>) prefixes will skew output of interactive applications. So far
> > > > > the prefix is added to output from all domains different than dom0
> > > > > because the console is not interactive for them, and hence no input
> > > > > can be consumed.
> > > >
> > > > Hmm, that's an aspect I have to admit I didn't think of.
> > > >
> > > > > If that changes however, and domains different than dom0 can get input
> > > > > from the Xen console then I wonder how much the added prefix will skew
> > > > > output. Another possible option would be to not print the prefix for
> > > > > the domain that has the console input assigned (current target), and
> > > > > print it for all other domains (even for dom0 when not in focus).
> > > >
> > > > That's largely what aiui was proposed. My extra requirement there would
> > > > then be that we make sure a log message is always emitted when console
> > > > focus shifts, so it's possible to identify the owner for any part of
> > > > the log.
> > >
> > >
> > > Indeed, printing console input shifting should be a requirement
> > > regardless of how we decide to print the prefix.
> >
> > Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
> > [[
> > ...
> > (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
> > (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
> > (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
> > ...
> > ]]
>
>
> Roger, Jan, you should use Xen Dom0less more :-) This is the way it
> already works on ARM. Let me expand on my earlier message that was too
> terse.
Hehe, I should use ARM more in general I think :).
> At boot time, Xen prints messages with the (XEN) prefix as usual:
>
> (XEN) Brought up 4 CPUs
>
> When Dom0 starts, it has not prefix (and has input by default):
>
> [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
>
> When a DomU starts, it has the following prefix (and doesn't have
> input):
>
> (XEN) DOM1: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
>
>
> Eventually, both Linuxes finish booting, you can login into Dom0 as
> usual. Messages from Dom1, if any, are still printed with (XEN) DOM1 as
> prefix.
>
> You can switch input to Dom1 with Ctrx-aaa, the same way that you do
> today to switch between Xen and Dom0. Xen prints a message:
>
> (XEN) *** Serial input to DOM1 (type 'CTRL-a' three times to switch input)
>
> Now, as you type, you send characters to Dom1. And Dom1 doesn't have the
> DOM1 prefix any longer, while it is still has (XEN) because the message
> is printed by Xen on behalf of the domain:
>
> (XEN) / # echo hello world
> (XEN) hello world
>
> If Dom0 prints anything in the backgrounds, it shows without prefixes:
>
> hello world from dom0
>
> If another domain, dom2, prints anything in the background, it shows
> with (XEN) DOM2 prefix:
>
> (XEN) DOM2: hello from dom2
>
> I think it makes sense to be consistent across architectures and we
> should default to the same behavior on x86 too. If we want to make
> improvements, the one thing I could potentially see changing is adding a
> DOM0 prefix to Dom0 messages when Dom0 does not have input. If we do
> that, let's do it on both ARM and x86 architectures.
The usual prefix is (d<domid>) IIRC, that's what guest_printk() uses,
is there any reason dom0less uses "(XEN) DOM<domid>:" instead of the
guest_printk() prefix?
My preference would be use to (d<domid>) prefix for any guest output
that doesn't belong to the domain that's the recipient of the input
(iow: not in console input focus). And drop the (XEN) prefix from
guest output.
The rest looks all sensible to me. I think we should avoid adding any
prefixes to guest output when it has the console focus, as otherwise
interactive applications might not work correctly.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-09 8:06 ` Roger Pau Monné
@ 2025-01-09 23:46 ` Stefano Stabellini
2025-01-10 1:39 ` Denis Mukhin
0 siblings, 1 reply; 218+ messages in thread
From: Stefano Stabellini @ 2025-01-09 23:46 UTC (permalink / raw)
To: Roger Pau Monné
Cc: Stefano Stabellini, Denis Mukhin, Jan Beulich, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel
[-- Attachment #1: Type: text/plain, Size: 10201 bytes --]
On Thu, 9 Jan 2025, Roger Pau Monné wrote:
> On Wed, Jan 08, 2025 at 04:29:24PM -0800, Stefano Stabellini wrote:
> > On Wed, 8 Jan 2025, Denis Mukhin wrote:
> > > On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
> > > > On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
> > > > > On 08.01.2025 09:04, Roger Pau Monné wrote:
> > > > > > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> > > > > > > On 08.01.2025 00:40, Stefano Stabellini wrote:
> > > > > > > > On Tue, 7 Jan 2025, Jan Beulich wrote:
> > > > > > > > > On 06.01.2025 19:48, Stefano Stabellini wrote:
> > > > > > > > > > On Mon, 6 Jan 2025, Jan Beulich wrote:
> > > > > > > > > > > On 04.01.2025 05:15, Denis Mukhin wrote:
> > > > > > > > > > > > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
> > > > > > > > > > > > > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > The call is used in NS8250 emulator to identify the case when physical xen
> > > > > > > > > > > > > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > > > > > > > > > > > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Such messages ought to be processed through guest_printk(), which wants a
> > > > > > > > > > > > > domain pointer, not a domid_t anyway. Plus isn't that going to be
> > > > > > > > > > > > > current->domain anyway at the callsite, eliminating the need for such a
> > > > > > > > > > > > >
> > > > > > > > > > > > > helper altogether?
> > > > > > > > > > > >
> > > > > > > > > > > > If the current domain is owning the physical console and printing, say, Linux
> > > > > > > > > > > > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > > > > > > > > > > > can be disabled from Xen command line.
> > > > > > > > > > >
> > > > > > > > > > > Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> > > > > > > > > > > which domain a message came from. As long as only Dom0 messages are left un-
> > > > > > > > > > > prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> > > > > > > > > > > messages (and have console "focus") I think the prefix needs to be there.
> > > > > > > > > >
> > > > > > > > > > It looks like we are aligned on the desired behavior,
> > > > > > > > >
> > > > > > > > > Hmm, no, I don't think we are. I don't ...
> > > > > > > > >
> > > > > > > > > > but for clarity,
> > > > > > > > > > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > > > > > > > > > here:
> > > > > > > > > >
> > > > > > > > > > I think we should provide a consistent behavior across architectures.
> > > > > > > > > > The current behavior with vpl011 and dom0less on ARM is the following:
> > > > > > > > > >
> > > > > > > > > > - no prefix for Dom0 output
> > > > > > > > > > - DOM$NUM for DomUs when not in focus, otherwise no prefix
> > > > > > > > >
> > > > > > > > > ... view this model as a desirable one. It leaves room for ambiguity.
> > > > > > > >
> > > > > > > > Adding a few more people in CC for feedback.
> > > > > > > >
> > > > > > > > My priority is to keep the architectures aligned. It might be OK to
> > > > > > > > change output format, but then let's do it uniformly on ARM as well.
> > > > > > > >
> > > > > > > > Jan, please clarify what you think would be better than the above. Is it
> > > > > > > > the following? I don't think I understood your preference.
> > > > > > > >
> > > > > > > > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> > > > > > >
> > > > > > > No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> > > > > > > own messages, (d<N>) for ordinary domains' ones, and no prefix
> > > > > > > exclusively for the hardware/control domain. What is best to do when
> > > > > > > hardware and control domains are distinct I'm uncertain - I'd be
> > > > > > > inclined to suggest that the hardware domain then stay the one without
> > > > > > > any prefix.
> > > > > >
> > > > > > One concern I have with this approach is whether the addition of the
> > > > > > (d<N>) prefixes will skew output of interactive applications. So far
> > > > > > the prefix is added to output from all domains different than dom0
> > > > > > because the console is not interactive for them, and hence no input
> > > > > > can be consumed.
> > > > >
> > > > > Hmm, that's an aspect I have to admit I didn't think of.
> > > > >
> > > > > > If that changes however, and domains different than dom0 can get input
> > > > > > from the Xen console then I wonder how much the added prefix will skew
> > > > > > output. Another possible option would be to not print the prefix for
> > > > > > the domain that has the console input assigned (current target), and
> > > > > > print it for all other domains (even for dom0 when not in focus).
> > > > >
> > > > > That's largely what aiui was proposed. My extra requirement there would
> > > > > then be that we make sure a log message is always emitted when console
> > > > > focus shifts, so it's possible to identify the owner for any part of
> > > > > the log.
> > > >
> > > >
> > > > Indeed, printing console input shifting should be a requirement
> > > > regardless of how we decide to print the prefix.
> > >
> > > Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
> > > [[
> > > ...
> > > (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
> > > (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
> > > (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
> > > ...
> > > ]]
> >
> >
> > Roger, Jan, you should use Xen Dom0less more :-) This is the way it
> > already works on ARM. Let me expand on my earlier message that was too
> > terse.
>
> Hehe, I should use ARM more in general I think :).
>
> > At boot time, Xen prints messages with the (XEN) prefix as usual:
> >
> > (XEN) Brought up 4 CPUs
> >
> > When Dom0 starts, it has not prefix (and has input by default):
> >
> > [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> >
> > When a DomU starts, it has the following prefix (and doesn't have
> > input):
> >
> > (XEN) DOM1: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> >
> >
> > Eventually, both Linuxes finish booting, you can login into Dom0 as
> > usual. Messages from Dom1, if any, are still printed with (XEN) DOM1 as
> > prefix.
> >
> > You can switch input to Dom1 with Ctrx-aaa, the same way that you do
> > today to switch between Xen and Dom0. Xen prints a message:
> >
> > (XEN) *** Serial input to DOM1 (type 'CTRL-a' three times to switch input)
> >
> > Now, as you type, you send characters to Dom1. And Dom1 doesn't have the
> > DOM1 prefix any longer, while it is still has (XEN) because the message
> > is printed by Xen on behalf of the domain:
> >
> > (XEN) / # echo hello world
> > (XEN) hello world
> >
> > If Dom0 prints anything in the backgrounds, it shows without prefixes:
> >
> > hello world from dom0
> >
> > If another domain, dom2, prints anything in the background, it shows
> > with (XEN) DOM2 prefix:
> >
> > (XEN) DOM2: hello from dom2
> >
> > I think it makes sense to be consistent across architectures and we
> > should default to the same behavior on x86 too. If we want to make
> > improvements, the one thing I could potentially see changing is adding a
> > DOM0 prefix to Dom0 messages when Dom0 does not have input. If we do
> > that, let's do it on both ARM and x86 architectures.
>
> The usual prefix is (d<domid>) IIRC, that's what guest_printk() uses,
> is there any reason dom0less uses "(XEN) DOM<domid>:" instead of the
> guest_printk() prefix?
>
> My preference would be use to (d<domid>) prefix for any guest output
> that doesn't belong to the domain that's the recipient of the input
> (iow: not in console input focus). And drop the (XEN) prefix from
> guest output.
>
> The rest looks all sensible to me. I think we should avoid adding any
> prefixes to guest output when it has the console focus, as otherwise
> interactive applications might not work correctly.
I am OK with what you describe, I would kindly ask Denis to also modify
ARM vpl011 to match. Looking at the code, I don't know where the (XEN)
prefix is coming from, but for the DOM<domid> to d<domid> change, it
would be probably something like this:
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 1fc3114cce..959d172e96 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -107,7 +107,10 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
if ( data != '\n' )
intf->out[intf->out_prod++] = '\n';
intf->out[intf->out_prod++] = '\0';
- printk("DOM%u: %s", d->domain_id, intf->out);
+ if ( in_focus(d) )
+ printk("%s", intf->out);
+ else
+ guest_printk("%s", d, intf->out);
intf->out_prod = 0;
}
}
There is also one additional change needed to add the (d<domid>) prefix
for dom0 when not in focus. The Dom0 print typically comes from
do_console_io, so in pseudocode we would need something like:
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 7da8c5296f..5d250b642a 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -643,6 +643,9 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
/* Use direct console output as it could be interactive */
nrspin_lock_irq(&console_lock);
+ if ( !in_focus(cd) )
+ add_prefix(kbuf, "(d0) ");
+
console_serial_puts(kbuf, kcount);
video_puts(kbuf, kcount);
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-09 23:46 ` Stefano Stabellini
@ 2025-01-10 1:39 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-10 1:39 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Roger Pau Monné, Jan Beulich, dmukhin, xen-devel,
Andrew Cooper, Julien Grall, Bertrand Marquis, Michal Orzel
On Thursday, January 9th, 2025 at 3:46 PM, Stefano Stabellini <sstabellini@kernel.org> wrote:
>
>
> On Thu, 9 Jan 2025, Roger Pau Monné wrote:
>
> > On Wed, Jan 08, 2025 at 04:29:24PM -0800, Stefano Stabellini wrote:
> >
> > > On Wed, 8 Jan 2025, Denis Mukhin wrote:
> > >
> > > > On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné roger.pau@citrix.com wrote:
> > > >
> > > > > On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
> > > > >
> > > > > > On 08.01.2025 09:04, Roger Pau Monné wrote:
> > > > > >
> > > > > > > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> > > > > > >
> > > > > > > > On 08.01.2025 00:40, Stefano Stabellini wrote:
> > > > > > > >
> > > > > > > > > On Tue, 7 Jan 2025, Jan Beulich wrote:
> > > > > > > > >
> > > > > > > > > > On 06.01.2025 19:48, Stefano Stabellini wrote:
> > > > > > > > > >
> > > > > > > > > > > On Mon, 6 Jan 2025, Jan Beulich wrote:
> > > > > > > > > > >
> > > > > > > > > > > > On 04.01.2025 05:15, Denis Mukhin wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > The call is used in NS8250 emulator to identify the case when physical xen
> > > > > > > > > > > > > > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > > > > > > > > > > > > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Such messages ought to be processed through guest_printk(), which wants a
> > > > > > > > > > > > > > domain pointer, not a domid_t anyway. Plus isn't that going to be
> > > > > > > > > > > > > > current->domain anyway at the callsite, eliminating the need for such a
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > helper altogether?
> > > > > > > > > > > > >
> > > > > > > > > > > > > If the current domain is owning the physical console and printing, say, Linux
> > > > > > > > > > > > > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > > > > > > > > > > > > can be disabled from Xen command line.
> > > > > > > > > > > >
> > > > > > > > > > > > Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> > > > > > > > > > > > which domain a message came from. As long as only Dom0 messages are left un-
> > > > > > > > > > > > prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> > > > > > > > > > > > messages (and have console "focus") I think the prefix needs to be there.
> > > > > > > > > > >
> > > > > > > > > > > It looks like we are aligned on the desired behavior,
> > > > > > > > > >
> > > > > > > > > > Hmm, no, I don't think we are. I don't ...
> > > > > > > > > >
> > > > > > > > > > > but for clarity,
> > > > > > > > > > > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > > > > > > > > > > here:
> > > > > > > > > > >
> > > > > > > > > > > I think we should provide a consistent behavior across architectures.
> > > > > > > > > > > The current behavior with vpl011 and dom0less on ARM is the following:
> > > > > > > > > > >
> > > > > > > > > > > - no prefix for Dom0 output
> > > > > > > > > > > - DOM$NUM for DomUs when not in focus, otherwise no prefix
> > > > > > > > > >
> > > > > > > > > > ... view this model as a desirable one. It leaves room for ambiguity.
> > > > > > > > >
> > > > > > > > > Adding a few more people in CC for feedback.
> > > > > > > > >
> > > > > > > > > My priority is to keep the architectures aligned. It might be OK to
> > > > > > > > > change output format, but then let's do it uniformly on ARM as well.
> > > > > > > > >
> > > > > > > > > Jan, please clarify what you think would be better than the above. Is it
> > > > > > > > > the following? I don't think I understood your preference.
> > > > > > > > >
> > > > > > > > > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> > > > > > > >
> > > > > > > > No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> > > > > > > > own messages, (d<N>) for ordinary domains' ones, and no prefix
> > > > > > > > exclusively for the hardware/control domain. What is best to do when
> > > > > > > > hardware and control domains are distinct I'm uncertain - I'd be
> > > > > > > > inclined to suggest that the hardware domain then stay the one without
> > > > > > > > any prefix.
> > > > > > >
> > > > > > > One concern I have with this approach is whether the addition of the
> > > > > > > (d<N>) prefixes will skew output of interactive applications. So far
> > > > > > > the prefix is added to output from all domains different than dom0
> > > > > > > because the console is not interactive for them, and hence no input
> > > > > > > can be consumed.
> > > > > >
> > > > > > Hmm, that's an aspect I have to admit I didn't think of.
> > > > > >
> > > > > > > If that changes however, and domains different than dom0 can get input
> > > > > > > from the Xen console then I wonder how much the added prefix will skew
> > > > > > > output. Another possible option would be to not print the prefix for
> > > > > > > the domain that has the console input assigned (current target), and
> > > > > > > print it for all other domains (even for dom0 when not in focus).
> > > > > >
> > > > > > That's largely what aiui was proposed. My extra requirement there would
> > > > > > then be that we make sure a log message is always emitted when console
> > > > > > focus shifts, so it's possible to identify the owner for any part of
> > > > > > the log.
> > > > >
> > > > > Indeed, printing console input shifting should be a requirement
> > > > > regardless of how we decide to print the prefix.
> > > >
> > > > Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
> > > > [[
> > > > ...
> > > > (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
> > > > (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
> > > > (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
> > > > ...
> > > > ]]
> > >
> > > Roger, Jan, you should use Xen Dom0less more :-) This is the way it
> > > already works on ARM. Let me expand on my earlier message that was too
> > > terse.
> >
> > Hehe, I should use ARM more in general I think :).
> >
> > > At boot time, Xen prints messages with the (XEN) prefix as usual:
> > >
> > > (XEN) Brought up 4 CPUs
> > >
> > > When Dom0 starts, it has not prefix (and has input by default):
> > >
> > > [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> > >
> > > When a DomU starts, it has the following prefix (and doesn't have
> > > input):
> > >
> > > (XEN) DOM1: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> > >
> > > Eventually, both Linuxes finish booting, you can login into Dom0 as
> > > usual. Messages from Dom1, if any, are still printed with (XEN) DOM1 as
> > > prefix.
> > >
> > > You can switch input to Dom1 with Ctrx-aaa, the same way that you do
> > > today to switch between Xen and Dom0. Xen prints a message:
> > >
> > > (XEN) *** Serial input to DOM1 (type 'CTRL-a' three times to switch input)
> > >
> > > Now, as you type, you send characters to Dom1. And Dom1 doesn't have the
> > > DOM1 prefix any longer, while it is still has (XEN) because the message
> > > is printed by Xen on behalf of the domain:
> > >
> > > (XEN) / # echo hello world
> > > (XEN) hello world
> > >
> > > If Dom0 prints anything in the backgrounds, it shows without prefixes:
> > >
> > > hello world from dom0
> > >
> > > If another domain, dom2, prints anything in the background, it shows
> > > with (XEN) DOM2 prefix:
> > >
> > > (XEN) DOM2: hello from dom2
> > >
> > > I think it makes sense to be consistent across architectures and we
> > > should default to the same behavior on x86 too. If we want to make
> > > improvements, the one thing I could potentially see changing is adding a
> > > DOM0 prefix to Dom0 messages when Dom0 does not have input. If we do
> > > that, let's do it on both ARM and x86 architectures.
> >
> > The usual prefix is (d<domid>) IIRC, that's what guest_printk() uses,
> > is there any reason dom0less uses "(XEN) DOM<domid>:" instead of the
> > guest_printk() prefix?
> >
> > My preference would be use to (d<domid>) prefix for any guest output
> > that doesn't belong to the domain that's the recipient of the input
> > (iow: not in console input focus). And drop the (XEN) prefix from
> > guest output.
> >
> > The rest looks all sensible to me. I think we should avoid adding any
> > prefixes to guest output when it has the console focus, as otherwise
> > interactive applications might not work correctly.
>
>
> I am OK with what you describe, I would kindly ask Denis to also modify
> ARM vpl011 to match. Looking at the code, I don't know where the (XEN)
> prefix is coming from, but for the DOM<domid> to d<domid> change, it
Yep, I implemented such logic in v3 iteration of the series:
https://lore.kernel.org/xen-devel/20250103-vuart-ns8250-v3-v1-24-c5d36b31d66c@ford.com/
printk() adds "(XEN)" prefix (drivers/char/console.c)
>
> would be probably something like this:
>
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index 1fc3114cce..959d172e96 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -107,7 +107,10 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> if ( data != '\n' )
> intf->out[intf->out_prod++] = '\n';
>
> intf->out[intf->out_prod++] = '\0';
>
> - printk("DOM%u: %s", d->domain_id, intf->out);
>
> + if ( in_focus(d) )
> + printk("%s", intf->out);
>
> + else
> + guest_printk("%s", d, intf->out);
>
> intf->out_prod = 0;
>
> }
> }
>
> There is also one additional change needed to add the (d<domid>) prefix
>
> for dom0 when not in focus. The Dom0 print typically comes from
This change I missed. Thanks!
> do_console_io, so in pseudocode we would need something like:
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 7da8c5296f..5d250b642a 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -643,6 +643,9 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
> /* Use direct console output as it could be interactive */
> nrspin_lock_irq(&console_lock);
>
> + if ( !in_focus(cd) )
> + add_prefix(kbuf, "(d0) ");
> +
> console_serial_puts(kbuf, kcount);
> video_puts(kbuf, kcount);
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-09 0:29 ` Stefano Stabellini
2025-01-09 8:06 ` Roger Pau Monné
@ 2025-01-09 8:25 ` Jan Beulich
1 sibling, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-09 8:25 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Roger Pau Monné, dmukhin, xen-devel, Andrew Cooper,
Julien Grall, Bertrand Marquis, Michal Orzel, Denis Mukhin
On 09.01.2025 01:29, Stefano Stabellini wrote:
> On Wed, 8 Jan 2025, Denis Mukhin wrote:
>> On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>>> On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
>>>> On 08.01.2025 09:04, Roger Pau Monné wrote:
>>>>> On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
>>>>>> On 08.01.2025 00:40, Stefano Stabellini wrote:
>>>>>>> On Tue, 7 Jan 2025, Jan Beulich wrote:
>>>>>>>> On 06.01.2025 19:48, Stefano Stabellini wrote:
>>>>>>>>> On Mon, 6 Jan 2025, Jan Beulich wrote:
>>>>>>>>>> On 04.01.2025 05:15, Denis Mukhin wrote:
>>>>>>>>>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
>>>>>>>>>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> From: Denis Mukhin dmukhin@ford.com
>>>>>>>>>>>>>
>>>>>>>>>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The call is used in NS8250 emulator to identify the case when physical xen
>>>>>>>>>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>>>>>>>>>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>>>>>>>>>>>
>>>>>>>>>>>> Such messages ought to be processed through guest_printk(), which wants a
>>>>>>>>>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
>>>>>>>>>>>> current->domain anyway at the callsite, eliminating the need for such a
>>>>>>>>>>>>
>>>>>>>>>>>> helper altogether?
>>>>>>>>>>>
>>>>>>>>>>> If the current domain is owning the physical console and printing, say, Linux
>>>>>>>>>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
>>>>>>>>>>> can be disabled from Xen command line.
>>>>>>>>>>
>>>>>>>>>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
>>>>>>>>>> which domain a message came from. As long as only Dom0 messages are left un-
>>>>>>>>>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
>>>>>>>>>> messages (and have console "focus") I think the prefix needs to be there.
>>>>>>>>>
>>>>>>>>> It looks like we are aligned on the desired behavior,
>>>>>>>>
>>>>>>>> Hmm, no, I don't think we are. I don't ...
>>>>>>>>
>>>>>>>>> but for clarity,
>>>>>>>>> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
>>>>>>>>> here:
>>>>>>>>>
>>>>>>>>> I think we should provide a consistent behavior across architectures.
>>>>>>>>> The current behavior with vpl011 and dom0less on ARM is the following:
>>>>>>>>>
>>>>>>>>> - no prefix for Dom0 output
>>>>>>>>> - DOM$NUM for DomUs when not in focus, otherwise no prefix
>>>>>>>>
>>>>>>>> ... view this model as a desirable one. It leaves room for ambiguity.
>>>>>>>
>>>>>>> Adding a few more people in CC for feedback.
>>>>>>>
>>>>>>> My priority is to keep the architectures aligned. It might be OK to
>>>>>>> change output format, but then let's do it uniformly on ARM as well.
>>>>>>>
>>>>>>> Jan, please clarify what you think would be better than the above. Is it
>>>>>>> the following? I don't think I understood your preference.
>>>>>>>
>>>>>>> - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
>>>>>>
>>>>>> No, I mean like we have it with guest_printk() today. (XEN) for Xen's
>>>>>> own messages, (d<N>) for ordinary domains' ones, and no prefix
>>>>>> exclusively for the hardware/control domain. What is best to do when
>>>>>> hardware and control domains are distinct I'm uncertain - I'd be
>>>>>> inclined to suggest that the hardware domain then stay the one without
>>>>>> any prefix.
>>>>>
>>>>> One concern I have with this approach is whether the addition of the
>>>>> (d<N>) prefixes will skew output of interactive applications. So far
>>>>> the prefix is added to output from all domains different than dom0
>>>>> because the console is not interactive for them, and hence no input
>>>>> can be consumed.
>>>>
>>>> Hmm, that's an aspect I have to admit I didn't think of.
>>>>
>>>>> If that changes however, and domains different than dom0 can get input
>>>>> from the Xen console then I wonder how much the added prefix will skew
>>>>> output. Another possible option would be to not print the prefix for
>>>>> the domain that has the console input assigned (current target), and
>>>>> print it for all other domains (even for dom0 when not in focus).
>>>>
>>>> That's largely what aiui was proposed. My extra requirement there would
>>>> then be that we make sure a log message is always emitted when console
>>>> focus shifts, so it's possible to identify the owner for any part of
>>>> the log.
>>>
>>>
>>> Indeed, printing console input shifting should be a requirement
>>> regardless of how we decide to print the prefix.
>>
>> Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
>> [[
>> ...
>> (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
>> (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
>> (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
>> ...
>> ]]
>
>
> Roger, Jan, you should use Xen Dom0less more :-) This is the way it
> already works on ARM. Let me expand on my earlier message that was too
> terse.
>
> At boot time, Xen prints messages with the (XEN) prefix as usual:
>
> (XEN) Brought up 4 CPUs
>
> When Dom0 starts, it has not prefix (and has input by default):
>
> [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
>
> When a DomU starts, it has the following prefix (and doesn't have
> input):
>
> (XEN) DOM1: [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
Which is wrong - this isn't a Xen message. Such messages imo want prefixing
(d<N>), as guest_printk() does.
Jan
> Eventually, both Linuxes finish booting, you can login into Dom0 as
> usual. Messages from Dom1, if any, are still printed with (XEN) DOM1 as
> prefix.
>
> You can switch input to Dom1 with Ctrx-aaa, the same way that you do
> today to switch between Xen and Dom0. Xen prints a message:
>
> (XEN) *** Serial input to DOM1 (type 'CTRL-a' three times to switch input)
>
> Now, as you type, you send characters to Dom1. And Dom1 doesn't have the
> DOM1 prefix any longer, while it is still has (XEN) because the message
> is printed by Xen on behalf of the domain:
>
> (XEN) / # echo hello world
> (XEN) hello world
>
> If Dom0 prints anything in the backgrounds, it shows without prefixes:
>
> hello world from dom0
>
> If another domain, dom2, prints anything in the background, it shows
> with (XEN) DOM2 prefix:
>
> (XEN) DOM2: hello from dom2
>
> I think it makes sense to be consistent across architectures and we
> should default to the same behavior on x86 too. If we want to make
> improvements, the one thing I could potentially see changing is adding a
> DOM0 prefix to Dom0 messages when Dom0 does not have input. If we do
> that, let's do it on both ARM and x86 architectures.
>
> Cheers,
> Stefano
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-08 22:15 ` Denis Mukhin
2025-01-09 0:29 ` Stefano Stabellini
@ 2025-01-09 8:27 ` Jan Beulich
2025-01-10 1:34 ` Denis Mukhin
1 sibling, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-09 8:27 UTC (permalink / raw)
To: Denis Mukhin
Cc: Stefano Stabellini, dmukhin, xen-devel, Andrew Cooper,
Julien Grall, Bertrand Marquis, Michal Orzel,
Roger Pau Monné
On 08.01.2025 23:15, Denis Mukhin wrote:
> On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>>
>>
>> On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
>>
>>> On 08.01.2025 09:04, Roger Pau Monné wrote:
>>>
>>>> On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
>>>>
>>>>> On 08.01.2025 00:40, Stefano Stabellini wrote:
>>>>>
>>>>>> On Tue, 7 Jan 2025, Jan Beulich wrote:
>>>>>>
>>>>>>> On 06.01.2025 19:48, Stefano Stabellini wrote:
>>>>>>>
>>>>>>>> On Mon, 6 Jan 2025, Jan Beulich wrote:
>>>>>>>>
>>>>>>>>> On 04.01.2025 05:15, Denis Mukhin wrote:
>>>>>>>>>
>>>>>>>>>> On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
>>>>>>>>>>
>>>>>>>>>>> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>>>>>>>>>>>
>>>>>>>>>>>> From: Denis Mukhin dmukhin@ford.com
>>>>>>>>>>>>
>>>>>>>>>>>> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>>>>>>>>>>>>
>>>>>>>>>>>> The call is used in NS8250 emulator to identify the case when physical xen
>>>>>>>>>>>> console focus is owned by the domain w/ NS8250 emulator, in which case,
>>>>>>>>>>>> messages from guest OS are formatted w/o '(XEN)' prefix.
>>>>>>>>>>>
>>>>>>>>>>> Such messages ought to be processed through guest_printk(), which wants a
>>>>>>>>>>> domain pointer, not a domid_t anyway. Plus isn't that going to be
>>>>>>>>>>> current->domain anyway at the callsite, eliminating the need for such a
>>>>>>>>>>>
>>>>>>>>>>> helper altogether?
>>>>>>>>>>
>>>>>>>>>> If the current domain is owning the physical console and printing, say, Linux
>>>>>>>>>> login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
>>>>>>>>>> can be disabled from Xen command line.
>>>>>>>>>
>>>>>>>>> Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
>>>>>>>>> which domain a message came from. As long as only Dom0 messages are left un-
>>>>>>>>> prefixed, that's likely fine. Yet as soon as multiple domains can issue such
>>>>>>>>> messages (and have console "focus") I think the prefix needs to be there.
>>>>>>>>
>>>>>>>> It looks like we are aligned on the desired behavior,
>>>>>>>
>>>>>>> Hmm, no, I don't think we are. I don't ...
>>>>>>>
>>>>>>>> but for clarity,
>>>>>>>> see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
>>>>>>>> here:
>>>>>>>>
>>>>>>>> I think we should provide a consistent behavior across architectures.
>>>>>>>> The current behavior with vpl011 and dom0less on ARM is the following:
>>>>>>>>
>>>>>>>> - no prefix for Dom0 output
>>>>>>>> - DOM$NUM for DomUs when not in focus, otherwise no prefix
>>>>>>>
>>>>>>> ... view this model as a desirable one. It leaves room for ambiguity.
>>>>>>
>>>>>> Adding a few more people in CC for feedback.
>>>>>>
>>>>>> My priority is to keep the architectures aligned. It might be OK to
>>>>>> change output format, but then let's do it uniformly on ARM as well.
>>>>>>
>>>>>> Jan, please clarify what you think would be better than the above. Is it
>>>>>> the following? I don't think I understood your preference.
>>>>>>
>>>>>> - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
>>>>>
>>>>> No, I mean like we have it with guest_printk() today. (XEN) for Xen's
>>>>> own messages, (d<N>) for ordinary domains' ones, and no prefix
>>>>> exclusively for the hardware/control domain. What is best to do when
>>>>> hardware and control domains are distinct I'm uncertain - I'd be
>>>>> inclined to suggest that the hardware domain then stay the one without
>>>>> any prefix.
>>>>
>>>> One concern I have with this approach is whether the addition of the
>>>> (d<N>) prefixes will skew output of interactive applications. So far
>>>> the prefix is added to output from all domains different than dom0
>>>> because the console is not interactive for them, and hence no input
>>>> can be consumed.
>>>
>>> Hmm, that's an aspect I have to admit I didn't think of.
>>>
>>>> If that changes however, and domains different than dom0 can get input
>>>> from the Xen console then I wonder how much the added prefix will skew
>>>> output. Another possible option would be to not print the prefix for
>>>> the domain that has the console input assigned (current target), and
>>>> print it for all other domains (even for dom0 when not in focus).
>>>
>>> That's largely what aiui was proposed. My extra requirement there would
>>> then be that we make sure a log message is always emitted when console
>>> focus shifts, so it's possible to identify the owner for any part of
>>> the log.
>>
>> Indeed, printing console input shifting should be a requirement
>> regardless of how we decide to print the prefix.
>
> Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
> [[
> ...
> (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
> (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
> (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
> ...
> ]]
And just to double check: These messages aren't affected by "loglvl=" settings,
i.e. they're _always_ there (as asked for earlier; see context above)?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2025-01-09 8:27 ` Jan Beulich
@ 2025-01-10 1:34 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-10 1:34 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, dmukhin, xen-devel, Andrew Cooper,
Julien Grall, Bertrand Marquis, Michal Orzel,
Roger Pau Monné
On Thursday, January 9th, 2025 at 12:27 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 08.01.2025 23:15, Denis Mukhin wrote:
>
> > On Wednesday, January 8th, 2025 at 12:35 AM, Roger Pau Monné roger.pau@citrix.com wrote:
> >
> > > On Wed, Jan 08, 2025 at 09:13:02AM +0100, Jan Beulich wrote:
> > >
> > > > On 08.01.2025 09:04, Roger Pau Monné wrote:
> > > >
> > > > > On Wed, Jan 08, 2025 at 08:28:32AM +0100, Jan Beulich wrote:
> > > > >
> > > > > > On 08.01.2025 00:40, Stefano Stabellini wrote:
> > > > > >
> > > > > > > On Tue, 7 Jan 2025, Jan Beulich wrote:
> > > > > > >
> > > > > > > > On 06.01.2025 19:48, Stefano Stabellini wrote:
> > > > > > > >
> > > > > > > > > On Mon, 6 Jan 2025, Jan Beulich wrote:
> > > > > > > > >
> > > > > > > > > > On 04.01.2025 05:15, Denis Mukhin wrote:
> > > > > > > > > >
> > > > > > > > > > > On Tuesday, December 10th, 2024 at 11:28 PM, Jan Beulich jbeulich@suse.com wrote:
> > > > > > > > > > >
> > > > > > > > > > > > On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > > From: Denis Mukhin dmukhin@ford.com
> > > > > > > > > > > > >
> > > > > > > > > > > > > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> > > > > > > > > > > > >
> > > > > > > > > > > > > The call is used in NS8250 emulator to identify the case when physical xen
> > > > > > > > > > > > > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > > > > > > > > > > > > messages from guest OS are formatted w/o '(XEN)' prefix.
> > > > > > > > > > > >
> > > > > > > > > > > > Such messages ought to be processed through guest_printk(), which wants a
> > > > > > > > > > > > domain pointer, not a domid_t anyway. Plus isn't that going to be
> > > > > > > > > > > > current->domain anyway at the callsite, eliminating the need for such a
> > > > > > > > > > > >
> > > > > > > > > > > > helper altogether?
> > > > > > > > > > >
> > > > > > > > > > > If the current domain is owning the physical console and printing, say, Linux
> > > > > > > > > > > login prompt, there's no need to add "(XEN)" for every printout; adding timestamps
> > > > > > > > > > > can be disabled from Xen command line.
> > > > > > > > > >
> > > > > > > > > > Surely there shouldn't be (XEN), but without (d<N>) it'll be ambiguous in a log
> > > > > > > > > > which domain a message came from. As long as only Dom0 messages are left un-
> > > > > > > > > > prefixed, that's likely fine. Yet as soon as multiple domains can issue such
> > > > > > > > > > messages (and have console "focus") I think the prefix needs to be there.
> > > > > > > > >
> > > > > > > > > It looks like we are aligned on the desired behavior,
> > > > > > > >
> > > > > > > > Hmm, no, I don't think we are. I don't ...
> > > > > > > >
> > > > > > > > > but for clarity,
> > > > > > > > > see https://marc.info/?l=xen-devel&m=173405161613716, also copy/pasted
> > > > > > > > > here:
> > > > > > > > >
> > > > > > > > > I think we should provide a consistent behavior across architectures.
> > > > > > > > > The current behavior with vpl011 and dom0less on ARM is the following:
> > > > > > > > >
> > > > > > > > > - no prefix for Dom0 output
> > > > > > > > > - DOM$NUM for DomUs when not in focus, otherwise no prefix
> > > > > > > >
> > > > > > > > ... view this model as a desirable one. It leaves room for ambiguity.
> > > > > > >
> > > > > > > Adding a few more people in CC for feedback.
> > > > > > >
> > > > > > > My priority is to keep the architectures aligned. It might be OK to
> > > > > > > change output format, but then let's do it uniformly on ARM as well.
> > > > > > >
> > > > > > > Jan, please clarify what you think would be better than the above. Is it
> > > > > > > the following? I don't think I understood your preference.
> > > > > > >
> > > > > > > - DOM$NUM for Dom0 and DomUs when not in focus, otherwise no prefix
> > > > > >
> > > > > > No, I mean like we have it with guest_printk() today. (XEN) for Xen's
> > > > > > own messages, (d<N>) for ordinary domains' ones, and no prefix
> > > > > > exclusively for the hardware/control domain. What is best to do when
> > > > > > hardware and control domains are distinct I'm uncertain - I'd be
> > > > > > inclined to suggest that the hardware domain then stay the one without
> > > > > > any prefix.
> > > > >
> > > > > One concern I have with this approach is whether the addition of the
> > > > > (d<N>) prefixes will skew output of interactive applications. So far
> > > > > the prefix is added to output from all domains different than dom0
> > > > > because the console is not interactive for them, and hence no input
> > > > > can be consumed.
> > > >
> > > > Hmm, that's an aspect I have to admit I didn't think of.
> > > >
> > > > > If that changes however, and domains different than dom0 can get input
> > > > > from the Xen console then I wonder how much the added prefix will skew
> > > > > output. Another possible option would be to not print the prefix for
> > > > > the domain that has the console input assigned (current target), and
> > > > > print it for all other domains (even for dom0 when not in focus).
> > > >
> > > > That's largely what aiui was proposed. My extra requirement there would
> > > > then be that we make sure a log message is always emitted when console
> > > > focus shifts, so it's possible to identify the owner for any part of
> > > > the log.
> > >
> > > Indeed, printing console input shifting should be a requirement
> > > regardless of how we decide to print the prefix.
> >
> > Console input focus switch is indicated after pressing Crtl+aaa, e.g.:
> > [[
> > ...
> > (XEN) [15359.353038] *** Serial input to Xen (type 'CTRL-aaa' to switch input)
> > (XEN) [15361.176754] *** Serial input to DOM0 (type 'CTRL-aaa' to switch input)
> > (XEN) [15711.297202] *** Serial input to DOM1 (type 'CTRL-aaa' to switch input)
> > ...
> > ]]
>
>
> And just to double check: These messages aren't affected by "loglvl=" settings,
> i.e. they're always there (as asked for earlier; see context above)?
`loglvl=none` disables console switch indication (even w/o my patches).
I will fix that.
Thanks!
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
` (2 preceding siblings ...)
(?)
@ 2024-12-12 10:18 ` Roger Pau Monné
2025-01-04 4:11 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 10:18 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:50PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_owner_domid() is introduced to obtain the "console owner" domain ID.
>
> The call is used in NS8250 emulator to identify the case when physical xen
> console focus is owned by the domain w/ NS8250 emulator, in which case,
> messages from guest OS are formatted w/o '(XEN)' prefix.
Nit: it would be better to not use abbreviations such as w/ or w/o in
commit messages.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 5 +++++
> xen/include/xen/console.h | 1 +
> 2 files changed, 6 insertions(+)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 52cf64dbf6fd18d599cb88835d03501a23b3e3c4..a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -498,6 +498,11 @@ struct domain *rcu_lock_domain_console_owner(void)
> return rcu_lock_domain_console_by_id(console_owner);
> }
>
> +domid_t console_owner_domid(void)
> +{
> + return console_owner;
> +}
> +
> static bool console_owner_possible(domid_t domid)
> {
> struct domain *d;
> diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> index 57c482cfbf2da15b011e64841ea086e779f4588d..83be5794aff6630beaad46f910fcc0fc6d833808 100644
> --- a/xen/include/xen/console.h
> +++ b/xen/include/xen/console.h
> @@ -33,6 +33,7 @@ void console_end_log_everything(void);
>
> struct domain *rcu_lock_domain_console_owner(void);
> int console_set_owner(domid_t);
> +domid_t console_owner_domid(void);
I would expect that either the caller already has a domain locked, or
uses rcu_lock_domain_console_owner() to obtain the domain and then get
the domid? (d->domain_id?)
It's hard to tell why you need such way to get the console input
target domid in such a way without seeing a caller to the function.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 20/35] xen/console: introduce console_owner_domid()
2024-12-12 10:18 ` Roger Pau Monné
@ 2025-01-04 4:11 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:11 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 2:18 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:50PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > console_owner_domid() is introduced to obtain the "console owner" domain ID.
> >
> > The call is used in NS8250 emulator to identify the case when physical xen
> > console focus is owned by the domain w/ NS8250 emulator, in which case,
> > messages from guest OS are formatted w/o '(XEN)' prefix.
>
>
> Nit: it would be better to not use abbreviations such as w/ or w/o in
> commit messages.
Muscle memory; cleaned up in v3.
>
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 5 +++++
> > xen/include/xen/console.h | 1 +
> > 2 files changed, 6 insertions(+)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 52cf64dbf6fd18d599cb88835d03501a23b3e3c4..a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -498,6 +498,11 @@ struct domain *rcu_lock_domain_console_owner(void)
> > return rcu_lock_domain_console_by_id(console_owner);
> > }
> >
> > +domid_t console_owner_domid(void)
> > +{
> > + return console_owner;
> > +}
> > +
> > static bool console_owner_possible(domid_t domid)
> > {
> > struct domain *d;
> > diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> > index 57c482cfbf2da15b011e64841ea086e779f4588d..83be5794aff6630beaad46f910fcc0fc6d833808 100644
> > --- a/xen/include/xen/console.h
> > +++ b/xen/include/xen/console.h
> > @@ -33,6 +33,7 @@ void console_end_log_everything(void);
> >
> > struct domain *rcu_lock_domain_console_owner(void);
> > int console_set_owner(domid_t);
> > +domid_t console_owner_domid(void);
>
>
> I would expect that either the caller already has a domain locked, or
> uses rcu_lock_domain_console_owner() to obtain the domain and then get
> the domid? (d->domain_id?)
If the console focus in the guest, there's no need to prefix each guest OS
printout w/ "(XEN)" and a timestamp. To identify that current ns8250 emulator
is the one who's printing to the physical UART, I introduced this call.
I think ideally, domain should have a flag saying "currently has console
focus" which is set by the console focus switch logic in console driver.
>
>
> It's hard to tell why you need such way to get the console input
> target domid in such a way without seeing a caller to the function.
Sorry for that, addressed in v3.
I ended up dropping the patch after addressing all the feedback.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 21/35] xen/console: introduce console_init_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
console_init_owner() is introduced for selecting the boot-time console owner.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557..6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -554,6 +554,22 @@ static void console_find_owner(void)
console_set_owner(DOMID_XEN);
}
+static void console_init_owner(void)
+{
+ domid_t domid;
+
+ /*
+ * If user specifies so, we fool the switch routine to redirect input
+ * straight back to Xen.
+ */
+ if ( opt_conswitch[1] == 'x' )
+ domid = DOMID_XEN;
+ else
+ domid = get_initial_domain_id();
+
+ console_set_owner(domid);
+}
+
static void __serial_rx(char c)
{
switch ( console_owner )
@@ -1143,14 +1159,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_owner = DOMID_XEN;
-
register_keyhandler('w', dump_console_ring_key,
"synchronously dump console ring buffer (dmesg)", 0);
register_irq_keyhandler('+', &do_inc_thresh,
@@ -1160,8 +1168,7 @@ 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_find_owner();
+ console_init_owner();
}
int __init console_has(const char *device)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 21/35] xen/console: introduce console_init_owner()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
console_init_owner() is introduced for selecting the boot-time console owner.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557..6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -554,6 +554,22 @@ static void console_find_owner(void)
console_set_owner(DOMID_XEN);
}
+static void console_init_owner(void)
+{
+ domid_t domid;
+
+ /*
+ * If user specifies so, we fool the switch routine to redirect input
+ * straight back to Xen.
+ */
+ if ( opt_conswitch[1] == 'x' )
+ domid = DOMID_XEN;
+ else
+ domid = get_initial_domain_id();
+
+ console_set_owner(domid);
+}
+
static void __serial_rx(char c)
{
switch ( console_owner )
@@ -1143,14 +1159,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_owner = DOMID_XEN;
-
register_keyhandler('w', dump_console_ring_key,
"synchronously dump console ring buffer (dmesg)", 0);
register_irq_keyhandler('+', &do_inc_thresh,
@@ -1160,8 +1168,7 @@ 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_find_owner();
+ console_init_owner();
}
int __init console_has(const char *device)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 21/35] xen/console: introduce console_init_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 22:30 ` Jason Andryuk
-1 siblings, 0 replies; 218+ messages in thread
From: Jason Andryuk @ 2024-12-10 22:30 UTC (permalink / raw)
To: dmukhin, xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini
On 2024-12-05 23:41, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_init_owner() is introduced for selecting the boot-time console owner.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 21/35] xen/console: introduce console_init_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-11 7:31 ` Jan Beulich
2025-01-04 3:22 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-11 7:31 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -554,6 +554,22 @@ static void console_find_owner(void)
> console_set_owner(DOMID_XEN);
> }
>
> +static void console_init_owner(void)
> +{
> + domid_t domid;
> +
> + /*
> + * If user specifies so, we fool the switch routine to redirect input
> + * straight back to Xen.
> + */
> + if ( opt_conswitch[1] == 'x' )
> + domid = DOMID_XEN;
> + else
> + domid = get_initial_domain_id();
> +
> + console_set_owner(domid);
> +}
Is this function meant to gain a 2nd user? If not, what exactly is the goal
of introducing this new function?
If the function's addition is warranted, it wants to be __init, matching ...
> @@ -1160,8 +1168,7 @@ 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_find_owner();
> + console_init_owner();
> }
... sole caller.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 21/35] xen/console: introduce console_init_owner()
2024-12-11 7:31 ` Jan Beulich
@ 2025-01-04 3:22 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:22 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Tuesday, December 10th, 2024 at 11:31 PM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -554,6 +554,22 @@ static void console_find_owner(void)
> > console_set_owner(DOMID_XEN);
> > }
> >
> > +static void console_init_owner(void)
> > +{
> > + domid_t domid;
> > +
> > + /*
> > + * If user specifies so, we fool the switch routine to redirect input
> > + * straight back to Xen.
> > + */
> > + if ( opt_conswitch[1] == 'x' )
> > + domid = DOMID_XEN;
> > + else
> > + domid = get_initial_domain_id();
> > +
> > + console_set_owner(domid);
> > +}
>
>
> Is this function meant to gain a 2nd user? If not, what exactly is the goal
> of introducing this new function?
I cannot foresee the second user.
My rationale was moving all console ownership initialization into one place
so the code is better localized.
>
> If the function's addition is warranted, it wants to be __init, matching ...
I ended up dropping the patch in v3.
>
> > @@ -1160,8 +1168,7 @@ 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_find_owner();
> > + console_init_owner();
> > }
>
>
> ... sole caller.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 21/35] xen/console: introduce console_init_owner()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
` (2 preceding siblings ...)
(?)
@ 2024-12-12 10:23 ` Roger Pau Monné
2025-01-04 3:23 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 10:23 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:51PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> console_init_owner() is introduced for selecting the boot-time console owner.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 27 +++++++++++++++++----------
> 1 file changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557..6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -554,6 +554,22 @@ static void console_find_owner(void)
> console_set_owner(DOMID_XEN);
> }
>
> +static void console_init_owner(void)
__init attribute missing (given current call context), but see below.
> +{
> + domid_t domid;
> +
> + /*
> + * If user specifies so, we fool the switch routine to redirect input
> + * straight back to Xen.
> + */
> + if ( opt_conswitch[1] == 'x' )
> + domid = DOMID_XEN;
> + else
> + domid = get_initial_domain_id();
> +
> + console_set_owner(domid);
> +}
> +
> static void __serial_rx(char c)
> {
> switch ( console_owner )
> @@ -1143,14 +1159,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_owner = DOMID_XEN;
> -
> register_keyhandler('w', dump_console_ring_key,
> "synchronously dump console ring buffer (dmesg)", 0);
> register_irq_keyhandler('+', &do_inc_thresh,
> @@ -1160,8 +1168,7 @@ 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_find_owner();
> + console_init_owner();
Oh, so this is what fixes the regression introduced in patch 19/35.
THB I'm not sure it's worth introducing the console_init_owner()
helper if it's just for this usage. You could do:
console_set_owner(opt_conswitch[1] == 'x' ? DOMID_XEN
: get_initial_domain_id());
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 21/35] xen/console: introduce console_init_owner()
2024-12-12 10:23 ` Roger Pau Monné
@ 2025-01-04 3:23 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:23 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 2:23 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:51PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > console_init_owner() is introduced for selecting the boot-time console owner.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 27 +++++++++++++++++----------
> > 1 file changed, 17 insertions(+), 10 deletions(-)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index a8ab5c2bcb98e4cadf9ad2c9ad28d297977d0557..6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -554,6 +554,22 @@ static void console_find_owner(void)
> > console_set_owner(DOMID_XEN);
> > }
> >
> > +static void console_init_owner(void)
>
>
> __init attribute missing (given current call context), but see below.
>
> > +{
> > + domid_t domid;
> > +
> > + /*
> > + * If user specifies so, we fool the switch routine to redirect input
> > + * straight back to Xen.
> > + */
> > + if ( opt_conswitch[1] == 'x' )
> > + domid = DOMID_XEN;
> > + else
> > + domid = get_initial_domain_id();
> > +
> > + console_set_owner(domid);
> > +}
> > +
> > static void __serial_rx(char c)
> > {
> > switch ( console_owner )
> > @@ -1143,14 +1159,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_owner = DOMID_XEN;
> > -
> > register_keyhandler('w', dump_console_ring_key,
> > "synchronously dump console ring buffer (dmesg)", 0);
> > register_irq_keyhandler('+', &do_inc_thresh,
> > @@ -1160,8 +1168,7 @@ 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_find_owner();
> > + console_init_owner();
>
>
> Oh, so this is what fixes the regression introduced in patch 19/35.
> THB I'm not sure it's worth introducing the console_init_owner()
> helper if it's just for this usage. You could do:
>
> console_set_owner(opt_conswitch[1] == 'x' ? DOMID_XEN
> : get_initial_domain_id());
Right, thank you.
Addressed in v3.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 22/35] xen/console: introduce handle_keypress_in_domain()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
With introduction of NS8250 emulator for x86, the logic of switching console
focus gets more convoluted: HVM domain w/ NS8205 must be able to receive the
physical console input for guest VM debugging.
Also, existing code does not honor `hardware_dom=` xen command line parameter
(hardware domain ID does _not_ necessarily starts from 0).
Introduce handle_keypress_in_domain() to account for all scenarios of console
input forwarding.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 72 +++++++++++++++++++++++++++-------------------
1 file changed, 42 insertions(+), 30 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6..ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -570,14 +570,16 @@ static void console_init_owner(void)
console_set_owner(domid);
}
-static void __serial_rx(char c)
+static void handle_keypress_in_domain(struct domain *d, char c)
{
- switch ( console_owner )
- {
- case DOMID_XEN:
- return handle_keypress(c, false);
+ int rc = 0;
- case 0:
+ /*
+ * Deliver input to the hardware domain buffer.
+ * NB: must be the first check: hardware domain may have emulated UART.
+ */
+ if ( d == hardware_domain )
+ {
/*
* Deliver input to the hardware domain buffer, unless it is
* already full.
@@ -590,34 +592,44 @@ static void __serial_rx(char c)
* getting stuck.
*/
send_global_virq(VIRQ_CONSOLE);
- break;
-
-#ifdef CONFIG_SBSA_VUART_CONSOLE
- default:
- {
- struct domain *d = rcu_lock_domain_by_id(console_owner);
-
- /*
- * 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 != NULL )
- vpl011_rx_char_xen(d, c);
- else
- printk("Cannot send chars to Dom%d: no UART available\n",
- console_owner);
-
- if ( d != NULL )
- rcu_unlock_domain(d);
-
- break;
}
+ /*
+ * Deliver input to the emulated UART.
+ */
+ else if ( domain_has_vuart(d) )
+ {
+#if defined(CONFIG_SBSA_VUART_CONSOLE)
+ rc = vpl011_rx_char_xen(d, c);
#endif
}
-
+ /*
+ * Deliver input to the PV shim console.
+ */
if ( consoled_is_enabled() )
- consoled_guest_tx(c);
+ rc = consoled_guest_tx(c);
+
+ if ( rc && rc != -ENODEV )
+ printk(KERN_WARNING "console input domain %d: not ready: %d\n",
+ d->domain_id, rc);
+}
+
+static void __serial_rx(char c)
+{
+ struct domain *d;
+
+ if ( console_owner == DOMID_XEN )
+ {
+ handle_keypress(c, false);
+ return;
+ }
+
+ d = rcu_lock_domain_console_owner();
+ if ( d == NULL )
+ return;
+
+ handle_keypress_in_domain(d, c);
+
+ rcu_unlock_domain(d);
}
static void cf_check serial_rx(char c)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 22/35] xen/console: introduce handle_keypress_in_domain()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
With introduction of NS8250 emulator for x86, the logic of switching console
focus gets more convoluted: HVM domain w/ NS8205 must be able to receive the
physical console input for guest VM debugging.
Also, existing code does not honor `hardware_dom=` xen command line parameter
(hardware domain ID does _not_ necessarily starts from 0).
Introduce handle_keypress_in_domain() to account for all scenarios of console
input forwarding.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 72 +++++++++++++++++++++++++++-------------------
1 file changed, 42 insertions(+), 30 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6..ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -570,14 +570,16 @@ static void console_init_owner(void)
console_set_owner(domid);
}
-static void __serial_rx(char c)
+static void handle_keypress_in_domain(struct domain *d, char c)
{
- switch ( console_owner )
- {
- case DOMID_XEN:
- return handle_keypress(c, false);
+ int rc = 0;
- case 0:
+ /*
+ * Deliver input to the hardware domain buffer.
+ * NB: must be the first check: hardware domain may have emulated UART.
+ */
+ if ( d == hardware_domain )
+ {
/*
* Deliver input to the hardware domain buffer, unless it is
* already full.
@@ -590,34 +592,44 @@ static void __serial_rx(char c)
* getting stuck.
*/
send_global_virq(VIRQ_CONSOLE);
- break;
-
-#ifdef CONFIG_SBSA_VUART_CONSOLE
- default:
- {
- struct domain *d = rcu_lock_domain_by_id(console_owner);
-
- /*
- * 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 != NULL )
- vpl011_rx_char_xen(d, c);
- else
- printk("Cannot send chars to Dom%d: no UART available\n",
- console_owner);
-
- if ( d != NULL )
- rcu_unlock_domain(d);
-
- break;
}
+ /*
+ * Deliver input to the emulated UART.
+ */
+ else if ( domain_has_vuart(d) )
+ {
+#if defined(CONFIG_SBSA_VUART_CONSOLE)
+ rc = vpl011_rx_char_xen(d, c);
#endif
}
-
+ /*
+ * Deliver input to the PV shim console.
+ */
if ( consoled_is_enabled() )
- consoled_guest_tx(c);
+ rc = consoled_guest_tx(c);
+
+ if ( rc && rc != -ENODEV )
+ printk(KERN_WARNING "console input domain %d: not ready: %d\n",
+ d->domain_id, rc);
+}
+
+static void __serial_rx(char c)
+{
+ struct domain *d;
+
+ if ( console_owner == DOMID_XEN )
+ {
+ handle_keypress(c, false);
+ return;
+ }
+
+ d = rcu_lock_domain_console_owner();
+ if ( d == NULL )
+ return;
+
+ handle_keypress_in_domain(d, c);
+
+ rcu_unlock_domain(d);
}
static void cf_check serial_rx(char c)
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 22/35] xen/console: introduce handle_keypress_in_domain()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 10:51 ` Roger Pau Monné
2025-01-04 3:25 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 10:51 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:52PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> With introduction of NS8250 emulator for x86, the logic of switching console
> focus gets more convoluted: HVM domain w/ NS8205 must be able to receive the
> physical console input for guest VM debugging.
>
> Also, existing code does not honor `hardware_dom=` xen command line parameter
> (hardware domain ID does _not_ necessarily starts from 0).
>
> Introduce handle_keypress_in_domain() to account for all scenarios of console
> input forwarding.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 72 +++++++++++++++++++++++++++-------------------
> 1 file changed, 42 insertions(+), 30 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6..ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -570,14 +570,16 @@ static void console_init_owner(void)
> console_set_owner(domid);
> }
>
> -static void __serial_rx(char c)
> +static void handle_keypress_in_domain(struct domain *d, char c)
> {
> - switch ( console_owner )
> - {
> - case DOMID_XEN:
> - return handle_keypress(c, false);
> + int rc = 0;
>
> - case 0:
> + /*
> + * Deliver input to the hardware domain buffer.
> + * NB: must be the first check: hardware domain may have emulated UART.
> + */
> + if ( d == hardware_domain )
is_hardware_domain(d)
> + {
> /*
> * Deliver input to the hardware domain buffer, unless it is
> * already full.
> @@ -590,34 +592,44 @@ static void __serial_rx(char c)
> * getting stuck.
> */
> send_global_virq(VIRQ_CONSOLE);
> - break;
> -
> -#ifdef CONFIG_SBSA_VUART_CONSOLE
> - default:
> - {
> - struct domain *d = rcu_lock_domain_by_id(console_owner);
> -
> - /*
> - * 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 != NULL )
> - vpl011_rx_char_xen(d, c);
> - else
> - printk("Cannot send chars to Dom%d: no UART available\n",
> - console_owner);
> -
> - if ( d != NULL )
> - rcu_unlock_domain(d);
> -
> - break;
> }
> + /*
> + * Deliver input to the emulated UART.
> + */
For one-line comments you can use:
/* Deliver input to the emulated UART. */
I would however place the comment inside the `if` body.
> + else if ( domain_has_vuart(d) )
> + {
> +#if defined(CONFIG_SBSA_VUART_CONSOLE)
> + rc = vpl011_rx_char_xen(d, c);
> #endif
You can possibly make the preprocessor conditional also contain the
if condition itself? As otherwise the if condition is dead code.
> }
> -
> + /*
> + * Deliver input to the PV shim console.
> + */
> if ( consoled_is_enabled() )
> - consoled_guest_tx(c);
> + rc = consoled_guest_tx(c);
> +
> + if ( rc && rc != -ENODEV )
> + printk(KERN_WARNING "console input domain %d: not ready: %d\n",
> + d->domain_id, rc);
XENLOG_ERR instead of KERN_WARNING, and use %pd to print domains, ie:
printk(XENLOG_ERR "%pd: delivery of console input failed: %d\n",
d, rc);
And I wonder whether this should be printed just once per domain,
or whether the domain should be marked as not having a console
(is_console = false) after delivery of input keys failed.
Otherwise you could spam the console with such error messages on every
serial key press.
> +}
> +
> +static void __serial_rx(char c)
> +{
> + struct domain *d;
> +
> + if ( console_owner == DOMID_XEN )
> + {
> + handle_keypress(c, false);
> + return;
> + }
> +
> + d = rcu_lock_domain_console_owner();
> + if ( d == NULL )
> + return;
> +
> + handle_keypress_in_domain(d, c);
Is __serial_rx() the only caller of handle_keypress_in_domain() after
the series? If so, I'm not sure it's worth placing this logic in a
separate function.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 22/35] xen/console: introduce handle_keypress_in_domain()
2024-12-12 10:51 ` Roger Pau Monné
@ 2025-01-04 3:25 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:25 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 2:51 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:52PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > With introduction of NS8250 emulator for x86, the logic of switching console
> > focus gets more convoluted: HVM domain w/ NS8205 must be able to receive the
> > physical console input for guest VM debugging.
> >
> > Also, existing code does not honor `hardware_dom=` xen command line parameter
> > (hardware domain ID does not necessarily starts from 0).
> >
> > Introduce handle_keypress_in_domain() to account for all scenarios of console
> > input forwarding.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 72 +++++++++++++++++++++++++++-------------------
> > 1 file changed, 42 insertions(+), 30 deletions(-)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6..ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -570,14 +570,16 @@ static void console_init_owner(void)
> > console_set_owner(domid);
> > }
> >
> > -static void __serial_rx(char c)
> > +static void handle_keypress_in_domain(struct domain *d, char c)
> > {
> > - switch ( console_owner )
> > - {
> > - case DOMID_XEN:
> > - return handle_keypress(c, false);
> > + int rc = 0;
> >
> > - case 0:
> > + /*
> > + * Deliver input to the hardware domain buffer.
> > + * NB: must be the first check: hardware domain may have emulated UART.
> > + */
> > + if ( d == hardware_domain )
>
>
> is_hardware_domain(d)
Fixed.
>
> > + {
> > /*
> > * Deliver input to the hardware domain buffer, unless it is
> > * already full.
> > @@ -590,34 +592,44 @@ static void __serial_rx(char c)
> > * getting stuck.
> > */
> > send_global_virq(VIRQ_CONSOLE);
> > - break;
> > -
> > -#ifdef CONFIG_SBSA_VUART_CONSOLE
> > - default:
> > - {
> > - struct domain d = rcu_lock_domain_by_id(console_owner);
> > -
> > - /
> > - * 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 != NULL )
> > - vpl011_rx_char_xen(d, c);
> > - else
> > - printk("Cannot send chars to Dom%d: no UART available\n",
> > - console_owner);
> > -
> > - if ( d != NULL )
> > - rcu_unlock_domain(d);
> > -
> > - break;
> > }
> > + /
> > + * Deliver input to the emulated UART.
> > + */
>
>
> For one-line comments you can use:
> /* Deliver input to the emulated UART. */
Fixed.
>
> I would however place the comment inside the `if` body.
Sure, no problem. Fixed.
>
> > + else if ( domain_has_vuart(d) )
> > + {
> > +#if defined(CONFIG_SBSA_VUART_CONSOLE)
> > + rc = vpl011_rx_char_xen(d, c);
> > #endif
>
>
> You can possibly make the preprocessor conditional also contain the
> if condition itself? As otherwise the if condition is dead code.
I removed the ifdef in v3 and reworked domain_has_vuart()
so that it checks build flag and d->arch.emulated_flags under the hood.
>
> > }
> > -
> > + /*
> > + * Deliver input to the PV shim console.
> > + */
> > if ( consoled_is_enabled() )
> > - consoled_guest_tx(c);
> > + rc = consoled_guest_tx(c);
> > +
> > + if ( rc && rc != -ENODEV )
> > + printk(KERN_WARNING "console input domain %d: not ready: %d\n",
> > + d->domain_id, rc);
>
>
> XENLOG_ERR instead of KERN_WARNING, and use %pd to print domains, ie:
Addressed.
>
> printk(XENLOG_ERR "%pd: delivery of console input failed: %d\n",
> d, rc);
>
> And I wonder whether this should be printed just once per domain,
> or whether the domain should be marked as not having a console
> (is_console = false) after delivery of input keys failed.
>
> Otherwise you could spam the console with such error messages on every
> serial key press.
Thanks; fixed.
>
> > +}
> > +
> > +static void __serial_rx(char c)
> > +{
> > + struct domain *d;
> > +
> > + if ( console_owner == DOMID_XEN )
> > + {
> > + handle_keypress(c, false);
> > + return;
> > + }
> > +
> > + d = rcu_lock_domain_console_owner();
> > + if ( d == NULL )
> > + return;
> > +
> > + handle_keypress_in_domain(d, c);
>
>
> Is __serial_rx() the only caller of handle_keypress_in_domain() after
> the series? If so, I'm not sure it's worth placing this logic in a
> separate function.
Yep, that is the only caller; fixed.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 23/35] xen/console: introduce console_write()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
PV Linux kernel uses HYPERVISOR_console_io hypercall for early console which
ends up being handled by Xen's console driver's guest_console_write().
guest_console_write() duplicates the code from __putstr(), elimitate code
duplication.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 97 +++++++++++++++++++++++++---------------------
1 file changed, 53 insertions(+), 44 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a..115967d179998cba4a81578caba09db4e4aca7f7 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -63,6 +63,8 @@ static const char __initconst warning_sync_console[] =
"However it can introduce SIGNIFICANT latencies and affect\n"
"timekeeping. It is NOT recommended for production use!\n";
+/* Flag: use conring for early console; switches to opt_console_to_ring */
+static bool __read_mostly use_conring = true;
/* console_to_ring: send guest (incl. dom 0) console data to console ring. */
static bool __read_mostly opt_console_to_ring;
boolean_param("console_to_ring", opt_console_to_ring);
@@ -661,6 +663,16 @@ static void cf_check notify_dom0_con_ring(void *unused)
static DECLARE_SOFTIRQ_TASKLET(notify_dom0_con_ring_tasklet,
notify_dom0_con_ring, NULL);
+static bool console_locks_busted;
+
+static void conring_write(const char *str, size_t len)
+{
+ conring_puts(str, len);
+
+ if ( !console_locks_busted )
+ tasklet_schedule(¬ify_dom0_con_ring_tasklet);
+}
+
#ifdef CONFIG_X86
static inline void xen_console_write_debug_port(const char *buf, size_t len)
{
@@ -669,8 +681,44 @@ static inline void xen_console_write_debug_port(const char *buf, size_t len)
: "=&S" (tmp), "=&c" (tmp)
: "0" (buf), "1" (len), "d" (XEN_HVM_DEBUGCONS_IOPORT) );
}
+
+static void xen_console_write(const char *str, size_t len)
+{
+ if ( xen_guest )
+ xen_hypercall_console_write(str, len);
+ else
+ xen_console_write_debug_port(str, len);
+}
+#else
+static inline void xen_console_write(const char *str, size_t len)
+{
+}
#endif
+/*
+ * Write characters to console.
+ *
+ * That will handle all possible scenarios working w/ console
+ * - serial console;
+ * - video output;
+ * - __HYPERVISOR_console_io hypercall (x86 only);
+ * - debug I/O port (x86 only);
+ * - forward to Xen event channel.
+ */
+static void console_write(const char *str, size_t len)
+{
+ ASSERT(rspin_is_locked(&console_lock));
+
+ console_serial_puts(str, len);
+ video_puts(str, len);
+
+ if ( opt_console_xen )
+ xen_console_write(str, len);
+
+ if ( use_conring )
+ conring_write(str, len);
+}
+
static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
unsigned int count)
{
@@ -691,28 +739,8 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
if ( is_hardware_domain(cd) )
{
- /* Use direct console output as it could be interactive */
nrspin_lock_irq(&console_lock);
-
- console_serial_puts(kbuf, kcount);
- video_puts(kbuf, kcount);
-
-#ifdef CONFIG_X86
- if ( opt_console_xen )
- {
- if ( xen_guest )
- xen_hypercall_console_write(kbuf, kcount);
- else
- xen_console_write_debug_port(kbuf, kcount);
- }
-#endif
-
- if ( opt_console_to_ring )
- {
- conring_puts(kbuf, kcount);
- tasklet_schedule(¬ify_dom0_con_ring_tasklet);
- }
-
+ console_write(kbuf, kcount);
nrspin_unlock_irq(&console_lock);
}
else
@@ -813,31 +841,9 @@ long do_console_io(
* *****************************************************
*/
-static bool console_locks_busted;
-
static void __putstr(const char *str)
{
- size_t len = strlen(str);
-
- ASSERT(rspin_is_locked(&console_lock));
-
- console_serial_puts(str, len);
- video_puts(str, len);
-
-#ifdef CONFIG_X86
- if ( opt_console_xen )
- {
- if ( xen_guest )
- xen_hypercall_console_write(str, len);
- else
- xen_console_write_debug_port(str, len);
- }
-#endif
-
- conring_puts(str, len);
-
- if ( !console_locks_busted )
- tasklet_schedule(¬ify_dom0_con_ring_tasklet);
+ console_write(str, strlen(str));
}
static int printk_prefix_check(char *p, char **pp)
@@ -1171,6 +1177,9 @@ void __init console_endboot(void)
video_endboot();
+ use_conring = opt_console_to_ring;
+ smp_wmb();
+
register_keyhandler('w', dump_console_ring_key,
"synchronously dump console ring buffer (dmesg)", 0);
register_irq_keyhandler('+', &do_inc_thresh,
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 23/35] xen/console: introduce console_write()
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
PV Linux kernel uses HYPERVISOR_console_io hypercall for early console which
ends up being handled by Xen's console driver's guest_console_write().
guest_console_write() duplicates the code from __putstr(), elimitate code
duplication.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 97 +++++++++++++++++++++++++---------------------
1 file changed, 53 insertions(+), 44 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a..115967d179998cba4a81578caba09db4e4aca7f7 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -63,6 +63,8 @@ static const char __initconst warning_sync_console[] =
"However it can introduce SIGNIFICANT latencies and affect\n"
"timekeeping. It is NOT recommended for production use!\n";
+/* Flag: use conring for early console; switches to opt_console_to_ring */
+static bool __read_mostly use_conring = true;
/* console_to_ring: send guest (incl. dom 0) console data to console ring. */
static bool __read_mostly opt_console_to_ring;
boolean_param("console_to_ring", opt_console_to_ring);
@@ -661,6 +663,16 @@ static void cf_check notify_dom0_con_ring(void *unused)
static DECLARE_SOFTIRQ_TASKLET(notify_dom0_con_ring_tasklet,
notify_dom0_con_ring, NULL);
+static bool console_locks_busted;
+
+static void conring_write(const char *str, size_t len)
+{
+ conring_puts(str, len);
+
+ if ( !console_locks_busted )
+ tasklet_schedule(¬ify_dom0_con_ring_tasklet);
+}
+
#ifdef CONFIG_X86
static inline void xen_console_write_debug_port(const char *buf, size_t len)
{
@@ -669,8 +681,44 @@ static inline void xen_console_write_debug_port(const char *buf, size_t len)
: "=&S" (tmp), "=&c" (tmp)
: "0" (buf), "1" (len), "d" (XEN_HVM_DEBUGCONS_IOPORT) );
}
+
+static void xen_console_write(const char *str, size_t len)
+{
+ if ( xen_guest )
+ xen_hypercall_console_write(str, len);
+ else
+ xen_console_write_debug_port(str, len);
+}
+#else
+static inline void xen_console_write(const char *str, size_t len)
+{
+}
#endif
+/*
+ * Write characters to console.
+ *
+ * That will handle all possible scenarios working w/ console
+ * - serial console;
+ * - video output;
+ * - __HYPERVISOR_console_io hypercall (x86 only);
+ * - debug I/O port (x86 only);
+ * - forward to Xen event channel.
+ */
+static void console_write(const char *str, size_t len)
+{
+ ASSERT(rspin_is_locked(&console_lock));
+
+ console_serial_puts(str, len);
+ video_puts(str, len);
+
+ if ( opt_console_xen )
+ xen_console_write(str, len);
+
+ if ( use_conring )
+ conring_write(str, len);
+}
+
static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
unsigned int count)
{
@@ -691,28 +739,8 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
if ( is_hardware_domain(cd) )
{
- /* Use direct console output as it could be interactive */
nrspin_lock_irq(&console_lock);
-
- console_serial_puts(kbuf, kcount);
- video_puts(kbuf, kcount);
-
-#ifdef CONFIG_X86
- if ( opt_console_xen )
- {
- if ( xen_guest )
- xen_hypercall_console_write(kbuf, kcount);
- else
- xen_console_write_debug_port(kbuf, kcount);
- }
-#endif
-
- if ( opt_console_to_ring )
- {
- conring_puts(kbuf, kcount);
- tasklet_schedule(¬ify_dom0_con_ring_tasklet);
- }
-
+ console_write(kbuf, kcount);
nrspin_unlock_irq(&console_lock);
}
else
@@ -813,31 +841,9 @@ long do_console_io(
* *****************************************************
*/
-static bool console_locks_busted;
-
static void __putstr(const char *str)
{
- size_t len = strlen(str);
-
- ASSERT(rspin_is_locked(&console_lock));
-
- console_serial_puts(str, len);
- video_puts(str, len);
-
-#ifdef CONFIG_X86
- if ( opt_console_xen )
- {
- if ( xen_guest )
- xen_hypercall_console_write(str, len);
- else
- xen_console_write_debug_port(str, len);
- }
-#endif
-
- conring_puts(str, len);
-
- if ( !console_locks_busted )
- tasklet_schedule(¬ify_dom0_con_ring_tasklet);
+ console_write(str, strlen(str));
}
static int printk_prefix_check(char *p, char **pp)
@@ -1171,6 +1177,9 @@ void __init console_endboot(void)
video_endboot();
+ use_conring = opt_console_to_ring;
+ smp_wmb();
+
register_keyhandler('w', dump_console_ring_key,
"synchronously dump console ring buffer (dmesg)", 0);
register_irq_keyhandler('+', &do_inc_thresh,
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 23/35] xen/console: introduce console_write()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 12:04 ` Roger Pau Monné
2025-01-04 3:50 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 12:04 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:53PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> PV Linux kernel uses HYPERVISOR_console_io hypercall for early console which
> ends up being handled by Xen's console driver's guest_console_write().
>
> guest_console_write() duplicates the code from __putstr(), elimitate code
> duplication.
It might be better to split the code that unifies
guest_console_write() and __putstr() as a non-functional change.
While the introduction of use_conring is likely a functional change.
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 97 +++++++++++++++++++++++++---------------------
> 1 file changed, 53 insertions(+), 44 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a..115967d179998cba4a81578caba09db4e4aca7f7 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -63,6 +63,8 @@ static const char __initconst warning_sync_console[] =
> "However it can introduce SIGNIFICANT latencies and affect\n"
> "timekeeping. It is NOT recommended for production use!\n";
>
> +/* Flag: use conring for early console; switches to opt_console_to_ring */
> +static bool __read_mostly use_conring = true;
__ro_after_init instead of __read_mostly.
> /* console_to_ring: send guest (incl. dom 0) console data to console ring. */
> static bool __read_mostly opt_console_to_ring;
> boolean_param("console_to_ring", opt_console_to_ring);
> @@ -661,6 +663,16 @@ static void cf_check notify_dom0_con_ring(void *unused)
> static DECLARE_SOFTIRQ_TASKLET(notify_dom0_con_ring_tasklet,
> notify_dom0_con_ring, NULL);
>
> +static bool console_locks_busted;
> +
> +static void conring_write(const char *str, size_t len)
> +{
> + conring_puts(str, len);
> +
> + if ( !console_locks_busted )
> + tasklet_schedule(¬ify_dom0_con_ring_tasklet);
> +}
> +
> #ifdef CONFIG_X86
> static inline void xen_console_write_debug_port(const char *buf, size_t len)
> {
> @@ -669,8 +681,44 @@ static inline void xen_console_write_debug_port(const char *buf, size_t len)
> : "=&S" (tmp), "=&c" (tmp)
> : "0" (buf), "1" (len), "d" (XEN_HVM_DEBUGCONS_IOPORT) );
> }
> +
> +static void xen_console_write(const char *str, size_t len)
> +{
> + if ( xen_guest )
> + xen_hypercall_console_write(str, len);
> + else
> + xen_console_write_debug_port(str, len);
> +}
> +#else
> +static inline void xen_console_write(const char *str, size_t len)
> +{
opt_console_xen would only be set on x86 with the current command line
parsing done in console_init_preirq(), so you could add an
ASSERT_UNREACHABLE() here.
> +}
> #endif
>
> +/*
> + * Write characters to console.
> + *
> + * That will handle all possible scenarios working w/ console
> + * - serial console;
> + * - video output;
> + * - __HYPERVISOR_console_io hypercall (x86 only);
> + * - debug I/O port (x86 only);
> + * - forward to Xen event channel.
"Xen event channel" is not the correct term. I would use "PV
console". The event channel is just used to send the notification.
> + */
> +static void console_write(const char *str, size_t len)
> +{
> + ASSERT(rspin_is_locked(&console_lock));
> +
> + console_serial_puts(str, len);
> + video_puts(str, len);
> +
> + if ( opt_console_xen )
> + xen_console_write(str, len);
Are you sure this builds? opt_console_xen is only defined on x86, and
AFAICT console_write() is generic. AFAICT you need to keep the X86
preprocessor guards, or alternatively do something like:
#define opt_console_xen false
For non-x86 arches in xen/console.h
> +
> + if ( use_conring )
> + conring_write(str, len);
> +}
> +
> static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
> unsigned int count)
> {
> @@ -691,28 +739,8 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
>
> if ( is_hardware_domain(cd) )
> {
> - /* Use direct console output as it could be interactive */
> nrspin_lock_irq(&console_lock);
> -
> - console_serial_puts(kbuf, kcount);
> - video_puts(kbuf, kcount);
> -
> -#ifdef CONFIG_X86
> - if ( opt_console_xen )
> - {
> - if ( xen_guest )
> - xen_hypercall_console_write(kbuf, kcount);
> - else
> - xen_console_write_debug_port(kbuf, kcount);
> - }
> -#endif
> -
> - if ( opt_console_to_ring )
> - {
> - conring_puts(kbuf, kcount);
> - tasklet_schedule(¬ify_dom0_con_ring_tasklet);
> - }
> -
> + console_write(kbuf, kcount);
> nrspin_unlock_irq(&console_lock);
> }
> else
> @@ -813,31 +841,9 @@ long do_console_io(
> * *****************************************************
> */
>
> -static bool console_locks_busted;
> -
> static void __putstr(const char *str)
> {
> - size_t len = strlen(str);
> -
> - ASSERT(rspin_is_locked(&console_lock));
> -
> - console_serial_puts(str, len);
> - video_puts(str, len);
> -
> -#ifdef CONFIG_X86
> - if ( opt_console_xen )
> - {
> - if ( xen_guest )
> - xen_hypercall_console_write(str, len);
> - else
> - xen_console_write_debug_port(str, len);
> - }
> -#endif
> -
> - conring_puts(str, len);
> -
> - if ( !console_locks_busted )
> - tasklet_schedule(¬ify_dom0_con_ring_tasklet);
> + console_write(str, strlen(str));
> }
>
> static int printk_prefix_check(char *p, char **pp)
> @@ -1171,6 +1177,9 @@ void __init console_endboot(void)
>
> video_endboot();
>
> + use_conring = opt_console_to_ring;
> + smp_wmb();
Do you really need the barrier? If so it would need a comment
describing exactly why it's needed. I don't think it's possible for
the write to be reordered past the return of the function, which would
be enough to ensure correctness?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 23/35] xen/console: introduce console_write()
2024-12-12 12:04 ` Roger Pau Monné
@ 2025-01-04 3:50 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:50 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 4:04 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:53PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > PV Linux kernel uses HYPERVISOR_console_io hypercall for early console which
> > ends up being handled by Xen's console driver's guest_console_write().
> >
> > guest_console_write() duplicates the code from __putstr(), elimitate code
> > duplication.
>
>
> It might be better to split the code that unifies
> guest_console_write() and __putstr() as a non-functional change.
> While the introduction of use_conring is likely a functional change.
Actually `use_conring` is not needed.
guest_console_write() depends on `opt_console_to_ring` to call
conring_puts() while __putstr() has unconditional call to conring_puts().
I solved this by adding another parameter to console_write().
>
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 97 +++++++++++++++++++++++++---------------------
> > 1 file changed, 53 insertions(+), 44 deletions(-)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index ce3639a4cdcda00ea63e3bf119bc3b242cbfdf6a..115967d179998cba4a81578caba09db4e4aca7f7 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -63,6 +63,8 @@ static const char __initconst warning_sync_console[] =
> > "However it can introduce SIGNIFICANT latencies and affect\n"
> > "timekeeping. It is NOT recommended for production use!\n";
> >
> > +/* Flag: use conring for early console; switches to opt_console_to_ring */
> > +static bool __read_mostly use_conring = true;
>
>
> __ro_after_init instead of __read_mostly.
I dropped use_conring.
>
> > /* console_to_ring: send guest (incl. dom 0) console data to console ring. */
> > static bool __read_mostly opt_console_to_ring;
> > boolean_param("console_to_ring", opt_console_to_ring);
> > @@ -661,6 +663,16 @@ static void cf_check notify_dom0_con_ring(void *unused)
> > static DECLARE_SOFTIRQ_TASKLET(notify_dom0_con_ring_tasklet,
> > notify_dom0_con_ring, NULL);
> >
> > +static bool console_locks_busted;
> > +
> > +static void conring_write(const char *str, size_t len)
> > +{
> > + conring_puts(str, len);
> > +
> > + if ( !console_locks_busted )
> > + tasklet_schedule(¬ify_dom0_con_ring_tasklet);
> > +}
> > +
> > #ifdef CONFIG_X86
> > static inline void xen_console_write_debug_port(const char *buf, size_t len)
> > {
> > @@ -669,8 +681,44 @@ static inline void xen_console_write_debug_port(const char *buf, size_t len)
> > : "=&S" (tmp), "=&c" (tmp)
> > : "0" (buf), "1" (len), "d" (XEN_HVM_DEBUGCONS_IOPORT) );
> > }
> > +
> > +static void xen_console_write(const char *str, size_t len)
> > +{
> > + if ( xen_guest )
> > + xen_hypercall_console_write(str, len);
> > + else
> > + xen_console_write_debug_port(str, len);
> > +}
> > +#else
> > +static inline void xen_console_write(const char *str, size_t len)
> > +{
>
>
> opt_console_xen would only be set on x86 with the current command line
> parsing done in console_init_preirq(), so you could add an
> ASSERT_UNREACHABLE() here.
I re-arranged the code, `static inline` variant is not needed.
>
> > +}
> > #endif
> >
> > +/*
> > + * Write characters to console.
> > + *
> > + * That will handle all possible scenarios working w/ console
> > + * - serial console;
> > + * - video output;
> > + * - __HYPERVISOR_console_io hypercall (x86 only);
> > + * - debug I/O port (x86 only);
> > + * - forward to Xen event channel.
>
>
> "Xen event channel" is not the correct term. I would use "PV
> console". The event channel is just used to send the notification.
Thank you; fixed.
>
> > + */
> > +static void console_write(const char *str, size_t len)
> > +{
> > + ASSERT(rspin_is_locked(&console_lock));
> > +
> > + console_serial_puts(str, len);
> > + video_puts(str, len);
> > +
> > + if ( opt_console_xen )
> > + xen_console_write(str, len);
>
>
> Are you sure this builds? opt_console_xen is only defined on x86, and
> AFAICT console_write() is generic. AFAICT you need to keep the X86
> preprocessor guards, or alternatively do something like:
This is strange; CI did pass on that:
https://gitlab.com/xen-project/people/dmukhin/xen/-/pipelines/1576164352
Fixed.
>
> #define opt_console_xen false
>
> For non-x86 arches in xen/console.h
>
> > +
> > + if ( use_conring )
> > + conring_write(str, len);
> > +}
> > +
> > static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
> > unsigned int count)
> > {
> > @@ -691,28 +739,8 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
> >
> > if ( is_hardware_domain(cd) )
> > {
> > - /* Use direct console output as it could be interactive */
> > nrspin_lock_irq(&console_lock);
> > -
> > - console_serial_puts(kbuf, kcount);
> > - video_puts(kbuf, kcount);
> > -
> > -#ifdef CONFIG_X86
> > - if ( opt_console_xen )
> > - {
> > - if ( xen_guest )
> > - xen_hypercall_console_write(kbuf, kcount);
> > - else
> > - xen_console_write_debug_port(kbuf, kcount);
> > - }
> > -#endif
> > -
> > - if ( opt_console_to_ring )
> > - {
> > - conring_puts(kbuf, kcount);
> > - tasklet_schedule(¬ify_dom0_con_ring_tasklet);
> > - }
> > -
> > + console_write(kbuf, kcount);
> > nrspin_unlock_irq(&console_lock);
> > }
> > else
> > @@ -813,31 +841,9 @@ long do_console_io(
> > * *****************************************************
> > */
> >
> > -static bool console_locks_busted;
> > -
> > static void __putstr(const char *str)
> > {
> > - size_t len = strlen(str);
> > -
> > - ASSERT(rspin_is_locked(&console_lock));
> > -
> > - console_serial_puts(str, len);
> > - video_puts(str, len);
> > -
> > -#ifdef CONFIG_X86
> > - if ( opt_console_xen )
> > - {
> > - if ( xen_guest )
> > - xen_hypercall_console_write(str, len);
> > - else
> > - xen_console_write_debug_port(str, len);
> > - }
> > -#endif
> > -
> > - conring_puts(str, len);
> > -
> > - if ( !console_locks_busted )
> > - tasklet_schedule(¬ify_dom0_con_ring_tasklet);
> > + console_write(str, strlen(str));
> > }
> >
> > static int printk_prefix_check(char *p, char **pp)
> > @@ -1171,6 +1177,9 @@ void __init console_endboot(void)
> >
> > video_endboot();
> >
> > + use_conring = opt_console_to_ring;
> > + smp_wmb();
>
>
> Do you really need the barrier? If so it would need a comment
> describing exactly why it's needed. I don't think it's possible for
> the write to be reordered past the return of the function, which would
> be enough to ensure correctness?
I see where I got confused: the right place to add this initialization was
console_init_postirq(). I dropped the barrier and of `use_conring` altogether.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 24/35] xen/console: introduce hwdom_crashconsole=
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
The new command line switch `hwdom_crashconsole=BOOL` allows to switch serial
console input focus to xen for machine state inspection using keyhandler
mechanism after the hardware domain crashes.
The new command line switch is aliased via `dom0=...,crashconsole` knob.
Such functionality can be useful while debugging dom0 bringup.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
docs/misc/xen-command-line.pandoc | 5 +++++
xen/arch/x86/dom0_build.c | 2 ++
xen/common/domain.c | 14 +++++++++++++-
xen/include/xen/domain.h | 1 +
4 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 293dbc1a957ba6e668fd4d55d58e84f643822126..fb77d7dca1ea517f79d6713aa6909422f31e7724 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -806,6 +806,7 @@ Specify the bit width of the DMA heap.
### dom0
= List of [ pv | pvh, shadow=<bool>, verbose=<bool>,
+ crashconsole=<bool>,
cpuid-faulting=<bool>, msr-relaxed=<bool> ] (x86)
= List of [ sve=<integer> ] (Arm64)
@@ -839,6 +840,10 @@ Controls for how dom0 is constructed on x86 systems.
information during the dom0 build. It defaults to the compile time choice
of `CONFIG_VERBOSE_DEBUG`.
+* The `crashconsole` boolean instructs Xen to drop into emergency console
+ in case of dom0 crash. May be useful for dom0 bringup on a custom
+ hardware.
+
* The `cpuid-faulting` boolean is an interim option, is only applicable to
PV dom0, and defaults to true.
diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index e8f5bf5447bc47a6daa3d95787106a4c11e80d31..706aeec0ecbb565a415edbfb33ca2fd72967c560 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -286,6 +286,8 @@ int __init parse_arch_dom0_param(const char *s, const char *e)
opt_dom0_cpuid_faulting = val;
else if ( (val = parse_boolean("msr-relaxed", s, e)) >= 0 )
opt_dom0_msr_relaxed = val;
+ else if ( (val = parse_boolean("crashconsole", s, e)) >= 0 )
+ opt_hwdom_crashconsole = !!val;
else
return -EINVAL;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index aab546c0a8535e4f007cbbc9c5c552bcf66b5807..4fe69f294158dda7b2e0b9d98d49c34e04131cb8 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -56,6 +56,13 @@ unsigned int xen_processor_pmbits = XEN_PROCESSOR_PM_PX;
bool opt_dom0_vcpus_pin;
boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
+/*
+ * Hardware domain crash handler: if true, do not halt machine, but switch to
+ * Xen console for debugging.
+ */
+bool opt_hwdom_crashconsole;
+boolean_param("hwdom_crashconsole", opt_hwdom_crashconsole);
+
/* Protect updates/reads (resp.) of domain_list and domain_hash. */
DEFINE_SPINLOCK(domlist_update_lock);
DEFINE_RCU_READ_LOCK(domlist_read_lock);
@@ -1138,7 +1145,12 @@ int domain_shutdown(struct domain *d, u8 reason)
reason = d->shutdown_code;
if ( is_hardware_domain(d) )
- hwdom_shutdown(reason);
+ {
+ if ( opt_hwdom_crashconsole )
+ console_set_owner(DOMID_XEN);
+ else
+ hwdom_shutdown(reason);
+ }
if ( d->is_shutting_down )
{
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 6102826a929ff7aad58a4bc40974815071a97446..e0c52af878b69e28e2d19957d0d3a8234860ecba 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -150,6 +150,7 @@ extern unsigned int xen_processor_pmbits;
extern bool opt_dom0_vcpus_pin;
extern cpumask_t dom0_cpus;
extern bool dom0_affinity_relaxed;
+extern bool opt_hwdom_crashconsole;
/* vnuma topology per domain. */
struct vnuma_info {
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 24/35] xen/console: introduce hwdom_crashconsole=
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
The new command line switch `hwdom_crashconsole=BOOL` allows to switch serial
console input focus to xen for machine state inspection using keyhandler
mechanism after the hardware domain crashes.
The new command line switch is aliased via `dom0=...,crashconsole` knob.
Such functionality can be useful while debugging dom0 bringup.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
docs/misc/xen-command-line.pandoc | 5 +++++
xen/arch/x86/dom0_build.c | 2 ++
xen/common/domain.c | 14 +++++++++++++-
xen/include/xen/domain.h | 1 +
4 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 293dbc1a957ba6e668fd4d55d58e84f643822126..fb77d7dca1ea517f79d6713aa6909422f31e7724 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -806,6 +806,7 @@ Specify the bit width of the DMA heap.
### dom0
= List of [ pv | pvh, shadow=<bool>, verbose=<bool>,
+ crashconsole=<bool>,
cpuid-faulting=<bool>, msr-relaxed=<bool> ] (x86)
= List of [ sve=<integer> ] (Arm64)
@@ -839,6 +840,10 @@ Controls for how dom0 is constructed on x86 systems.
information during the dom0 build. It defaults to the compile time choice
of `CONFIG_VERBOSE_DEBUG`.
+* The `crashconsole` boolean instructs Xen to drop into emergency console
+ in case of dom0 crash. May be useful for dom0 bringup on a custom
+ hardware.
+
* The `cpuid-faulting` boolean is an interim option, is only applicable to
PV dom0, and defaults to true.
diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index e8f5bf5447bc47a6daa3d95787106a4c11e80d31..706aeec0ecbb565a415edbfb33ca2fd72967c560 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -286,6 +286,8 @@ int __init parse_arch_dom0_param(const char *s, const char *e)
opt_dom0_cpuid_faulting = val;
else if ( (val = parse_boolean("msr-relaxed", s, e)) >= 0 )
opt_dom0_msr_relaxed = val;
+ else if ( (val = parse_boolean("crashconsole", s, e)) >= 0 )
+ opt_hwdom_crashconsole = !!val;
else
return -EINVAL;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index aab546c0a8535e4f007cbbc9c5c552bcf66b5807..4fe69f294158dda7b2e0b9d98d49c34e04131cb8 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -56,6 +56,13 @@ unsigned int xen_processor_pmbits = XEN_PROCESSOR_PM_PX;
bool opt_dom0_vcpus_pin;
boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
+/*
+ * Hardware domain crash handler: if true, do not halt machine, but switch to
+ * Xen console for debugging.
+ */
+bool opt_hwdom_crashconsole;
+boolean_param("hwdom_crashconsole", opt_hwdom_crashconsole);
+
/* Protect updates/reads (resp.) of domain_list and domain_hash. */
DEFINE_SPINLOCK(domlist_update_lock);
DEFINE_RCU_READ_LOCK(domlist_read_lock);
@@ -1138,7 +1145,12 @@ int domain_shutdown(struct domain *d, u8 reason)
reason = d->shutdown_code;
if ( is_hardware_domain(d) )
- hwdom_shutdown(reason);
+ {
+ if ( opt_hwdom_crashconsole )
+ console_set_owner(DOMID_XEN);
+ else
+ hwdom_shutdown(reason);
+ }
if ( d->is_shutting_down )
{
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 6102826a929ff7aad58a4bc40974815071a97446..e0c52af878b69e28e2d19957d0d3a8234860ecba 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -150,6 +150,7 @@ extern unsigned int xen_processor_pmbits;
extern bool opt_dom0_vcpus_pin;
extern cpumask_t dom0_cpus;
extern bool dom0_affinity_relaxed;
+extern bool opt_hwdom_crashconsole;
/* vnuma topology per domain. */
struct vnuma_info {
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 24/35] xen/console: introduce hwdom_crashconsole=
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 12:29 ` Roger Pau Monné
2025-01-04 4:48 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 12:29 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:54PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> The new command line switch `hwdom_crashconsole=BOOL` allows to switch serial
> console input focus to xen for machine state inspection using keyhandler
> mechanism after the hardware domain crashes.
>
> The new command line switch is aliased via `dom0=...,crashconsole` knob.
>
> Such functionality can be useful while debugging dom0 bringup.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> docs/misc/xen-command-line.pandoc | 5 +++++
> xen/arch/x86/dom0_build.c | 2 ++
> xen/common/domain.c | 14 +++++++++++++-
> xen/include/xen/domain.h | 1 +
> 4 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 293dbc1a957ba6e668fd4d55d58e84f643822126..fb77d7dca1ea517f79d6713aa6909422f31e7724 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -806,6 +806,7 @@ Specify the bit width of the DMA heap.
>
> ### dom0
> = List of [ pv | pvh, shadow=<bool>, verbose=<bool>,
> + crashconsole=<bool>,
> cpuid-faulting=<bool>, msr-relaxed=<bool> ] (x86)
>
> = List of [ sve=<integer> ] (Arm64)
> @@ -839,6 +840,10 @@ Controls for how dom0 is constructed on x86 systems.
> information during the dom0 build. It defaults to the compile time choice
> of `CONFIG_VERBOSE_DEBUG`.
>
> +* The `crashconsole` boolean instructs Xen to drop into emergency console
> + in case of dom0 crash. May be useful for dom0 bringup on a custom
I think the 'a' is unneeded -> "on custom hardware."
I think however this would be clearer as:
"The `crashconsole` boolean instructs Xen to switch input console
focus to the hypervisor when dom0 shuts down and avoid performing
dom0 domain destruction. Should only be used for debugging
purposes."
It's IMO not clear what "instructs Xen to drop into emergency console"
implies for Xen.
> + hardware.
> +
> * The `cpuid-faulting` boolean is an interim option, is only applicable to
> PV dom0, and defaults to true.
>
> diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
> index e8f5bf5447bc47a6daa3d95787106a4c11e80d31..706aeec0ecbb565a415edbfb33ca2fd72967c560 100644
> --- a/xen/arch/x86/dom0_build.c
> +++ b/xen/arch/x86/dom0_build.c
> @@ -286,6 +286,8 @@ int __init parse_arch_dom0_param(const char *s, const char *e)
> opt_dom0_cpuid_faulting = val;
> else if ( (val = parse_boolean("msr-relaxed", s, e)) >= 0 )
> opt_dom0_msr_relaxed = val;
> + else if ( (val = parse_boolean("crashconsole", s, e)) >= 0 )
> + opt_hwdom_crashconsole = !!val;
> else
> return -EINVAL;
>
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index aab546c0a8535e4f007cbbc9c5c552bcf66b5807..4fe69f294158dda7b2e0b9d98d49c34e04131cb8 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -56,6 +56,13 @@ unsigned int xen_processor_pmbits = XEN_PROCESSOR_PM_PX;
> bool opt_dom0_vcpus_pin;
> boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
>
> +/*
> + * Hardware domain crash handler: if true, do not halt machine, but switch to
> + * Xen console for debugging.
> + */
> +bool opt_hwdom_crashconsole;
__ro_after_init.
> +boolean_param("hwdom_crashconsole", opt_hwdom_crashconsole);
This option doesn't seem to be documented at all in
xen-command-line.pandoc?
> +
> /* Protect updates/reads (resp.) of domain_list and domain_hash. */
> DEFINE_SPINLOCK(domlist_update_lock);
> DEFINE_RCU_READ_LOCK(domlist_read_lock);
> @@ -1138,7 +1145,12 @@ int domain_shutdown(struct domain *d, u8 reason)
> reason = d->shutdown_code;
>
> if ( is_hardware_domain(d) )
> - hwdom_shutdown(reason);
> + {
> + if ( opt_hwdom_crashconsole )
> + console_set_owner(DOMID_XEN);
Don't you need to pause all domain vCPUs and return early here to
avoid executing the rest of the function, that will likely destroy the
domain?
Maybe there's something I'm missing that prevents the hardware domain
destruction.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 24/35] xen/console: introduce hwdom_crashconsole=
2024-12-12 12:29 ` Roger Pau Monné
@ 2025-01-04 4:48 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:48 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 4:29 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:54PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > The new command line switch `hwdom_crashconsole=BOOL` allows to switch serial
> > console input focus to xen for machine state inspection using keyhandler
> > mechanism after the hardware domain crashes.
> >
> > The new command line switch is aliased via `dom0=...,crashconsole` knob.
> >
> > Such functionality can be useful while debugging dom0 bringup.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > docs/misc/xen-command-line.pandoc | 5 +++++
> > xen/arch/x86/dom0_build.c | 2 ++
> > xen/common/domain.c | 14 +++++++++++++-
> > xen/include/xen/domain.h | 1 +
> > 4 files changed, 21 insertions(+), 1 deletion(-)
> >
> > diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> > index 293dbc1a957ba6e668fd4d55d58e84f643822126..fb77d7dca1ea517f79d6713aa6909422f31e7724 100644
> > --- a/docs/misc/xen-command-line.pandoc
> > +++ b/docs/misc/xen-command-line.pandoc
> > @@ -806,6 +806,7 @@ Specify the bit width of the DMA heap.
> >
> > ### dom0
> > = List of [ pv | pvh, shadow=<bool>, verbose=<bool>,
> > + crashconsole=<bool>,
> > cpuid-faulting=<bool>, msr-relaxed=<bool> ] (x86)
> >
> > = List of [ sve=<integer> ] (Arm64)
> > @@ -839,6 +840,10 @@ Controls for how dom0 is constructed on x86 systems.
> > information during the dom0 build. It defaults to the compile time choice
> > of `CONFIG_VERBOSE_DEBUG`.
> >
> > +* The `crashconsole` boolean instructs Xen to drop into emergency console
> > + in case of dom0 crash. May be useful for dom0 bringup on a custom
>
>
> I think the 'a' is unneeded -> "on custom hardware."
Yep. Thank you.
>
>
> I think however this would be clearer as:
>
> "The `crashconsole` boolean instructs Xen to switch input console
> focus to the hypervisor when dom0 shuts down and avoid performing
> dom0 domain destruction. Should only be used for debugging
> purposes."
Fixed.
>
> It's IMO not clear what "instructs Xen to drop into emergency console"
> implies for Xen.
>
> > + hardware.
> > +
> > * The `cpuid-faulting` boolean is an interim option, is only applicable to
> > PV dom0, and defaults to true.
> >
> > diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
> > index e8f5bf5447bc47a6daa3d95787106a4c11e80d31..706aeec0ecbb565a415edbfb33ca2fd72967c560 100644
> > --- a/xen/arch/x86/dom0_build.c
> > +++ b/xen/arch/x86/dom0_build.c
> > @@ -286,6 +286,8 @@ int __init parse_arch_dom0_param(const char *s, const char *e)
> > opt_dom0_cpuid_faulting = val;
> > else if ( (val = parse_boolean("msr-relaxed", s, e)) >= 0 )
> > opt_dom0_msr_relaxed = val;
> > + else if ( (val = parse_boolean("crashconsole", s, e)) >= 0 )
> > + opt_hwdom_crashconsole = !!val;
> > else
> > return -EINVAL;
> >
> > diff --git a/xen/common/domain.c b/xen/common/domain.c
> > index aab546c0a8535e4f007cbbc9c5c552bcf66b5807..4fe69f294158dda7b2e0b9d98d49c34e04131cb8 100644
> > --- a/xen/common/domain.c
> > +++ b/xen/common/domain.c
> > @@ -56,6 +56,13 @@ unsigned int xen_processor_pmbits = XEN_PROCESSOR_PM_PX;
> > bool opt_dom0_vcpus_pin;
> > boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
> >
> > +/*
> > + * Hardware domain crash handler: if true, do not halt machine, but switch to
> > + * Xen console for debugging.
> > + */
> > +bool opt_hwdom_crashconsole;
>
>
> __ro_after_init.
Done.
>
> > +boolean_param("hwdom_crashconsole", opt_hwdom_crashconsole);
>
>
> This option doesn't seem to be documented at all in
> xen-command-line.pandoc?
Thanks; fixed.
>
> > +
> > /* Protect updates/reads (resp.) of domain_list and domain_hash. */
> > DEFINE_SPINLOCK(domlist_update_lock);
> > DEFINE_RCU_READ_LOCK(domlist_read_lock);
> > @@ -1138,7 +1145,12 @@ int domain_shutdown(struct domain *d, u8 reason)
> > reason = d->shutdown_code;
> >
> > if ( is_hardware_domain(d) )
> > - hwdom_shutdown(reason);
> > + {
> > + if ( opt_hwdom_crashconsole )
> > + console_set_owner(DOMID_XEN);
>
>
> Don't you need to pause all domain vCPUs and return early here to
> avoid executing the rest of the function, that will likely destroy the
> domain?
>
> Maybe there's something I'm missing that prevents the hardware domain
> destruction.
The point of this change is to drop the user to Xen console on crash instead
of unconditional system restart. TBH, I did not plan for "freezing" the domain
state. I also tested w/ non-hyperlaunch PV dom0 only (I used kexec to
start PV dom0 which was crashing).
My understanding, if I followed the code correctly, all is fine.
domain_destroy() is not called because asm_domain_crash_synchronous(), which
handles the crash, just spins around do_softirq():
void asm_domain_crash_synchronous(unsigned long addr)
{
...
__domain_crash(current->domain); // that will call domain_crash()
for ( ; ; )
do_softirq();
}
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 25/35] xen/console: simplify console owner switch hint
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Update the hint w/ the combination of keys to press to switch physical console
to the next owner.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 115967d179998cba4a81578caba09db4e4aca7f7..d22fb4a253af26f9b51d91bd408e1dbf4bb5a7c1 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -528,8 +528,8 @@ int console_set_owner(domid_t domid)
console_owner = domid;
if ( switch_code )
- printk(" (type 'CTRL-%c' three times to switch input)",
- opt_conswitch[0]);
+ printk(" (type 'CTRL-%c%c%c' to switch input)",
+ opt_conswitch[0], opt_conswitch[0], opt_conswitch[0]);
printk("\n");
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 25/35] xen/console: simplify console owner switch hint
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Update the hint w/ the combination of keys to press to switch physical console
to the next owner.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 115967d179998cba4a81578caba09db4e4aca7f7..d22fb4a253af26f9b51d91bd408e1dbf4bb5a7c1 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -528,8 +528,8 @@ int console_set_owner(domid_t domid)
console_owner = domid;
if ( switch_code )
- printk(" (type 'CTRL-%c' three times to switch input)",
- opt_conswitch[0]);
+ printk(" (type 'CTRL-%c%c%c' to switch input)",
+ opt_conswitch[0], opt_conswitch[0], opt_conswitch[0]);
printk("\n");
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* [PATCH v2 26/35] xen/console: make console buffer size configurable
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Add new CONRING_LOG_SHIFT Kconfig parameter to specify the boot console buffer
size as a power of 2.
Bump default size to 32 KiB.
Link: https://gitlab.com/xen-project/xen/-/issues/185
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/Kconfig | 23 +++++++++++++++++++++++
xen/drivers/char/console.c | 4 ++--
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/xen/drivers/char/Kconfig b/xen/drivers/char/Kconfig
index e6e12bb4139717f9319031f51f5d20155d2caee2..3bc892fc38d8cdeb3c76ea44d747f712a8d0d372 100644
--- a/xen/drivers/char/Kconfig
+++ b/xen/drivers/char/Kconfig
@@ -96,6 +96,29 @@ config SERIAL_TX_BUFSIZE
Default value is 32768 (32KiB).
+config CONRING_LOG_SHIFT
+ int "Console buffer size"
+ range 14 25
+ default 15
+ help
+ Select the boot console buffer size as a power of 2.
+ Run-time console buffer size is the same as the boot console size,
+ unless enforced via 'conring_size=' boot parameter.
+
+ Examples:
+ 25 => 32 MiB
+ 24 => 16 MiB
+ 23 => 8 MiB
+ 22 => 4 MiB
+ 21 => 2 MiB
+ 20 => 1 MiB
+ 19 => 512 KiB
+ 18 => 256 KiB
+ 17 => 128 KiB
+ 16 => 64 KiB
+ 15 => 32 KiB
+ 14 => 16 KiB
+
config XHCI
bool "XHCI DbC UART driver"
depends on X86
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index d22fb4a253af26f9b51d91bd408e1dbf4bb5a7c1..581ee22b85302a54db5b9d5d28e8b2d689d31403 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -104,11 +104,11 @@ static int cf_check parse_console_timestamps(const char *s);
custom_runtime_param("console_timestamps", parse_console_timestamps,
con_timestamp_mode_upd);
-/* conring_size: allows a large console ring than default (16kB). */
+/* conring_size: allows a large console ring than default (32 KiB). */
static uint32_t __initdata opt_conring_size;
size_param("conring_size", opt_conring_size);
-#define _CONRING_SIZE 16384
+#define _CONRING_SIZE (1U << CONFIG_CONRING_LOG_SHIFT)
#define CONRING_IDX_MASK(i) ((i)&(conring_size-1))
static char __initdata _conring[_CONRING_SIZE];
static char *__read_mostly conring = _conring;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 26/35] xen/console: make console buffer size configurable
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Add new CONRING_LOG_SHIFT Kconfig parameter to specify the boot console buffer
size as a power of 2.
Bump default size to 32 KiB.
Link: https://gitlab.com/xen-project/xen/-/issues/185
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/Kconfig | 23 +++++++++++++++++++++++
xen/drivers/char/console.c | 4 ++--
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/xen/drivers/char/Kconfig b/xen/drivers/char/Kconfig
index e6e12bb4139717f9319031f51f5d20155d2caee2..3bc892fc38d8cdeb3c76ea44d747f712a8d0d372 100644
--- a/xen/drivers/char/Kconfig
+++ b/xen/drivers/char/Kconfig
@@ -96,6 +96,29 @@ config SERIAL_TX_BUFSIZE
Default value is 32768 (32KiB).
+config CONRING_LOG_SHIFT
+ int "Console buffer size"
+ range 14 25
+ default 15
+ help
+ Select the boot console buffer size as a power of 2.
+ Run-time console buffer size is the same as the boot console size,
+ unless enforced via 'conring_size=' boot parameter.
+
+ Examples:
+ 25 => 32 MiB
+ 24 => 16 MiB
+ 23 => 8 MiB
+ 22 => 4 MiB
+ 21 => 2 MiB
+ 20 => 1 MiB
+ 19 => 512 KiB
+ 18 => 256 KiB
+ 17 => 128 KiB
+ 16 => 64 KiB
+ 15 => 32 KiB
+ 14 => 16 KiB
+
config XHCI
bool "XHCI DbC UART driver"
depends on X86
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index d22fb4a253af26f9b51d91bd408e1dbf4bb5a7c1..581ee22b85302a54db5b9d5d28e8b2d689d31403 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -104,11 +104,11 @@ static int cf_check parse_console_timestamps(const char *s);
custom_runtime_param("console_timestamps", parse_console_timestamps,
con_timestamp_mode_upd);
-/* conring_size: allows a large console ring than default (16kB). */
+/* conring_size: allows a large console ring than default (32 KiB). */
static uint32_t __initdata opt_conring_size;
size_param("conring_size", opt_conring_size);
-#define _CONRING_SIZE 16384
+#define _CONRING_SIZE (1U << CONFIG_CONRING_LOG_SHIFT)
#define CONRING_IDX_MASK(i) ((i)&(conring_size-1))
static char __initdata _conring[_CONRING_SIZE];
static char *__read_mostly conring = _conring;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 26/35] xen/console: make console buffer size configurable
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 12:47 ` Roger Pau Monné
2025-01-04 3:52 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 12:47 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:56PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Add new CONRING_LOG_SHIFT Kconfig parameter to specify the boot console buffer
> size as a power of 2.
>
> Bump default size to 32 KiB.
>
> Link: https://gitlab.com/xen-project/xen/-/issues/185
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Thanks for taking care of this.
> ---
> xen/drivers/char/Kconfig | 23 +++++++++++++++++++++++
> xen/drivers/char/console.c | 4 ++--
> 2 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/xen/drivers/char/Kconfig b/xen/drivers/char/Kconfig
> index e6e12bb4139717f9319031f51f5d20155d2caee2..3bc892fc38d8cdeb3c76ea44d747f712a8d0d372 100644
> --- a/xen/drivers/char/Kconfig
> +++ b/xen/drivers/char/Kconfig
> @@ -96,6 +96,29 @@ config SERIAL_TX_BUFSIZE
>
> Default value is 32768 (32KiB).
>
> +config CONRING_LOG_SHIFT
> + int "Console buffer size"
> + range 14 25
> + default 15
> + help
> + Select the boot console buffer size as a power of 2.
> + Run-time console buffer size is the same as the boot console size,
> + unless enforced via 'conring_size=' boot parameter.
> +
> + Examples:
> + 25 => 32 MiB
> + 24 => 16 MiB
> + 23 => 8 MiB
> + 22 => 4 MiB
> + 21 => 2 MiB
> + 20 => 1 MiB
> + 19 => 512 KiB
> + 18 => 256 KiB
> + 17 => 128 KiB
> + 16 => 64 KiB
> + 15 => 32 KiB
> + 14 => 16 KiB
It might be better to do something similar to what we do in
SERIAL_TX_BUFSIZE, that the user provides a value in KiB which is
rounded down to the nearest power of 2?
> +
> config XHCI
> bool "XHCI DbC UART driver"
> depends on X86
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index d22fb4a253af26f9b51d91bd408e1dbf4bb5a7c1..581ee22b85302a54db5b9d5d28e8b2d689d31403 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -104,11 +104,11 @@ static int cf_check parse_console_timestamps(const char *s);
> custom_runtime_param("console_timestamps", parse_console_timestamps,
> con_timestamp_mode_upd);
>
> -/* conring_size: allows a large console ring than default (16kB). */
> +/* conring_size: allows a large console ring than default (32 KiB). */
> static uint32_t __initdata opt_conring_size;
> size_param("conring_size", opt_conring_size);
You also need to update xen-command-line.pandoc to mention the default
size is now set in Kconfig. And here I would mention
CONFIG_CONRING_SIZE rather than explicit 32 KiB, because that's just
the default in Kconfig, but might not be the default in the build
itself.
FWIW, you could define:
#define _CONRING_SIZE (CONFIG_CONRING_SIZE & (CONFIG_CONRING_SIZE - 1))
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 26/35] xen/console: make console buffer size configurable
2024-12-12 12:47 ` Roger Pau Monné
@ 2025-01-04 3:52 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:52 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 4:47 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:56PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Add new CONRING_LOG_SHIFT Kconfig parameter to specify the boot console buffer
> > size as a power of 2.
> >
> > Bump default size to 32 KiB.
> >
> > Link: https://gitlab.com/xen-project/xen/-/issues/185
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
>
>
> Thanks for taking care of this.
>
> > ---
> > xen/drivers/char/Kconfig | 23 +++++++++++++++++++++++
> > xen/drivers/char/console.c | 4 ++--
> > 2 files changed, 25 insertions(+), 2 deletions(-)
> >
> > diff --git a/xen/drivers/char/Kconfig b/xen/drivers/char/Kconfig
> > index e6e12bb4139717f9319031f51f5d20155d2caee2..3bc892fc38d8cdeb3c76ea44d747f712a8d0d372 100644
> > --- a/xen/drivers/char/Kconfig
> > +++ b/xen/drivers/char/Kconfig
> > @@ -96,6 +96,29 @@ config SERIAL_TX_BUFSIZE
> >
> > Default value is 32768 (32KiB).
> >
> > +config CONRING_LOG_SHIFT
> > + int "Console buffer size"
> > + range 14 25
> > + default 15
> > + help
> > + Select the boot console buffer size as a power of 2.
> > + Run-time console buffer size is the same as the boot console size,
> > + unless enforced via 'conring_size=' boot parameter.
> > +
> > + Examples:
> > + 25 => 32 MiB
> > + 24 => 16 MiB
> > + 23 => 8 MiB
> > + 22 => 4 MiB
> > + 21 => 2 MiB
> > + 20 => 1 MiB
> > + 19 => 512 KiB
> > + 18 => 256 KiB
> > + 17 => 128 KiB
> > + 16 => 64 KiB
> > + 15 => 32 KiB
> > + 14 => 16 KiB
>
>
> It might be better to do something similar to what we do in
> SERIAL_TX_BUFSIZE, that the user provides a value in KiB which is
> rounded down to the nearest power of 2?
TBH, I do not think there should be a way for the user to allow reserving huge
amounts of RAM for the console ring. Plus, using logarithmic scale may avoid
confusion, w/o it user-defined CONFIG_CONRING_SIZE will not necessarily
match the real _CONRING_SIZE value.
But I see your point: Kconfig should match existing conring_size= spec which
defines number of bytes.
>
> > +
> > config XHCI
> > bool "XHCI DbC UART driver"
> > depends on X86
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index d22fb4a253af26f9b51d91bd408e1dbf4bb5a7c1..581ee22b85302a54db5b9d5d28e8b2d689d31403 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -104,11 +104,11 @@ static int cf_check parse_console_timestamps(const char *s);
> > custom_runtime_param("console_timestamps", parse_console_timestamps,
> > con_timestamp_mode_upd);
> >
> > -/* conring_size: allows a large console ring than default (16kB). /
> > +/ conring_size: allows a large console ring than default (32 KiB). */
> > static uint32_t __initdata opt_conring_size;
> > size_param("conring_size", opt_conring_size);
>
>
> You also need to update xen-command-line.pandoc to mention the default
> size is now set in Kconfig. And here I would mention
> CONFIG_CONRING_SIZE rather than explicit 32 KiB, because that's just
> the default in Kconfig, but might not be the default in the build
> itself.
Done.
>
> FWIW, you could define:
>
> #define _CONRING_SIZE (CONFIG_CONRING_SIZE & (CONFIG_CONRING_SIZE - 1))
Done.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 27/35] xen/console: flush console ring to physical console
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Messages printed before the serial and VGA consoles are initialized end up in
the internal console buffer (conring). Flush contents of conring to all
external consoles after external consoles are fully initialied.
Link: https://gitlab.com/xen-project/xen/-/issues/184
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 54 +++++++++++++++++++++++++++++++++-------------
1 file changed, 39 insertions(+), 15 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 581ee22b85302a54db5b9d5d28e8b2d689d31403..a26daee9c4c4b1134d0ae3d105ffdb656340b6df 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -426,23 +426,35 @@ void console_serial_puts(const char *s, size_t nr)
pv_console_puts(s, nr);
}
-static void cf_check dump_console_ring_key(unsigned char key)
+/*
+ * Write characters to physical console(s).
+ * That covers:
+ * - serial console;
+ * - video output.
+ */
+static void console_puts(const char *str, size_t len)
+{
+ ASSERT(rspin_is_locked(&console_lock));
+
+ console_serial_puts(str, len);
+ video_puts(str, len);
+}
+
+/*
+ * Flush contents of the conring to the physical console devices.
+ */
+static int console_flush(void)
{
uint32_t idx, len, sofar, c;
unsigned int order;
char *buf;
- printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
-
- /* create a buffer in which we'll copy the ring in the correct
- order and NUL terminate */
order = get_order_from_bytes(conring_size + 1);
buf = alloc_xenheap_pages(order, 0);
if ( buf == NULL )
- {
- printk("unable to allocate memory!\n");
- return;
- }
+ return -ENOMEM;
+
+ nrspin_lock_irq(&console_lock);
c = conringc;
sofar = 0;
@@ -457,10 +469,23 @@ static void cf_check dump_console_ring_key(unsigned char key)
c += len;
}
- console_serial_puts(buf, sofar);
- video_puts(buf, sofar);
+ console_puts(buf, sofar);
+
+ nrspin_unlock_irq(&console_lock);
free_xenheap_pages(buf, order);
+
+ return 0;
+}
+
+static void cf_check dump_console_ring_key(unsigned char key)
+{
+ int rc;
+
+ printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
+ rc = console_flush();
+ if ( rc )
+ printk("failed to dump console ring buffer: %d\n", rc);
}
/*
@@ -707,10 +732,7 @@ static inline void xen_console_write(const char *str, size_t len)
*/
static void console_write(const char *str, size_t len)
{
- ASSERT(rspin_is_locked(&console_lock));
-
- console_serial_puts(str, len);
- video_puts(str, len);
+ console_puts(str, len);
if ( opt_console_xen )
xen_console_write(str, len);
@@ -1177,6 +1199,8 @@ void __init console_endboot(void)
video_endboot();
+ /* NB: send conring contents to all enabled physical consoles, if any */
+ console_flush();
use_conring = opt_console_to_ring;
smp_wmb();
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 27/35] xen/console: flush console ring to physical console
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Messages printed before the serial and VGA consoles are initialized end up in
the internal console buffer (conring). Flush contents of conring to all
external consoles after external consoles are fully initialied.
Link: https://gitlab.com/xen-project/xen/-/issues/184
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 54 +++++++++++++++++++++++++++++++++-------------
1 file changed, 39 insertions(+), 15 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 581ee22b85302a54db5b9d5d28e8b2d689d31403..a26daee9c4c4b1134d0ae3d105ffdb656340b6df 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -426,23 +426,35 @@ void console_serial_puts(const char *s, size_t nr)
pv_console_puts(s, nr);
}
-static void cf_check dump_console_ring_key(unsigned char key)
+/*
+ * Write characters to physical console(s).
+ * That covers:
+ * - serial console;
+ * - video output.
+ */
+static void console_puts(const char *str, size_t len)
+{
+ ASSERT(rspin_is_locked(&console_lock));
+
+ console_serial_puts(str, len);
+ video_puts(str, len);
+}
+
+/*
+ * Flush contents of the conring to the physical console devices.
+ */
+static int console_flush(void)
{
uint32_t idx, len, sofar, c;
unsigned int order;
char *buf;
- printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
-
- /* create a buffer in which we'll copy the ring in the correct
- order and NUL terminate */
order = get_order_from_bytes(conring_size + 1);
buf = alloc_xenheap_pages(order, 0);
if ( buf == NULL )
- {
- printk("unable to allocate memory!\n");
- return;
- }
+ return -ENOMEM;
+
+ nrspin_lock_irq(&console_lock);
c = conringc;
sofar = 0;
@@ -457,10 +469,23 @@ static void cf_check dump_console_ring_key(unsigned char key)
c += len;
}
- console_serial_puts(buf, sofar);
- video_puts(buf, sofar);
+ console_puts(buf, sofar);
+
+ nrspin_unlock_irq(&console_lock);
free_xenheap_pages(buf, order);
+
+ return 0;
+}
+
+static void cf_check dump_console_ring_key(unsigned char key)
+{
+ int rc;
+
+ printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
+ rc = console_flush();
+ if ( rc )
+ printk("failed to dump console ring buffer: %d\n", rc);
}
/*
@@ -707,10 +732,7 @@ static inline void xen_console_write(const char *str, size_t len)
*/
static void console_write(const char *str, size_t len)
{
- ASSERT(rspin_is_locked(&console_lock));
-
- console_serial_puts(str, len);
- video_puts(str, len);
+ console_puts(str, len);
if ( opt_console_xen )
xen_console_write(str, len);
@@ -1177,6 +1199,8 @@ void __init console_endboot(void)
video_endboot();
+ /* NB: send conring contents to all enabled physical consoles, if any */
+ console_flush();
use_conring = opt_console_to_ring;
smp_wmb();
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 27/35] xen/console: flush console ring to physical console
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 14:21 ` Roger Pau Monné
2025-01-04 3:56 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 14:21 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:57PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Messages printed before the serial and VGA consoles are initialized end up in
> the internal console buffer (conring). Flush contents of conring to all
> external consoles after external consoles are fully initialied.
>
> Link: https://gitlab.com/xen-project/xen/-/issues/184
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 54 +++++++++++++++++++++++++++++++++-------------
> 1 file changed, 39 insertions(+), 15 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 581ee22b85302a54db5b9d5d28e8b2d689d31403..a26daee9c4c4b1134d0ae3d105ffdb656340b6df 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -426,23 +426,35 @@ void console_serial_puts(const char *s, size_t nr)
> pv_console_puts(s, nr);
> }
>
> -static void cf_check dump_console_ring_key(unsigned char key)
> +/*
> + * Write characters to physical console(s).
> + * That covers:
> + * - serial console;
> + * - video output.
> + */
> +static void console_puts(const char *str, size_t len)
> +{
> + ASSERT(rspin_is_locked(&console_lock));
> +
> + console_serial_puts(str, len);
> + video_puts(str, len);
> +}
> +
> +/*
> + * Flush contents of the conring to the physical console devices.
> + */
> +static int console_flush(void)
> {
> uint32_t idx, len, sofar, c;
> unsigned int order;
> char *buf;
>
> - printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
> -
> - /* create a buffer in which we'll copy the ring in the correct
> - order and NUL terminate */
> order = get_order_from_bytes(conring_size + 1);
> buf = alloc_xenheap_pages(order, 0);
> if ( buf == NULL )
> - {
> - printk("unable to allocate memory!\n");
> - return;
> - }
> + return -ENOMEM;
> +
> + nrspin_lock_irq(&console_lock);
>
> c = conringc;
> sofar = 0;
> @@ -457,10 +469,23 @@ static void cf_check dump_console_ring_key(unsigned char key)
> c += len;
> }
>
> - console_serial_puts(buf, sofar);
> - video_puts(buf, sofar);
> + console_puts(buf, sofar);
> +
> + nrspin_unlock_irq(&console_lock);
>
> free_xenheap_pages(buf, order);
> +
> + return 0;
> +}
> +
> +static void cf_check dump_console_ring_key(unsigned char key)
> +{
> + int rc;
> +
> + printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
> + rc = console_flush();
> + if ( rc )
> + printk("failed to dump console ring buffer: %d\n", rc);
> }
>
> /*
> @@ -707,10 +732,7 @@ static inline void xen_console_write(const char *str, size_t len)
> */
> static void console_write(const char *str, size_t len)
> {
> - ASSERT(rspin_is_locked(&console_lock));
> -
> - console_serial_puts(str, len);
> - video_puts(str, len);
> + console_puts(str, len);
>
> if ( opt_console_xen )
> xen_console_write(str, len);
> @@ -1177,6 +1199,8 @@ void __init console_endboot(void)
>
> video_endboot();
>
> + /* NB: send conring contents to all enabled physical consoles, if any */
> + console_flush();
This is way too late: at this point Xen has already finished booting,
and is about to handover execution to dom0. Flushing here will result
in duplicating almost all Xen output already printed?
The flush needs to be done inside of console_init_preirq(), just
before printing xen_banner() I think. This sequentially after the
console has been initialized. Otherwise you are just duplicating
messages.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 27/35] xen/console: flush console ring to physical console
2024-12-12 14:21 ` Roger Pau Monné
@ 2025-01-04 3:56 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:56 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 6:21 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:57PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Messages printed before the serial and VGA consoles are initialized end up in
> > the internal console buffer (conring). Flush contents of conring to all
> > external consoles after external consoles are fully initialied.
> >
> > Link: https://gitlab.com/xen-project/xen/-/issues/184
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 54 +++++++++++++++++++++++++++++++++-------------
> > 1 file changed, 39 insertions(+), 15 deletions(-)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 581ee22b85302a54db5b9d5d28e8b2d689d31403..a26daee9c4c4b1134d0ae3d105ffdb656340b6df 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -426,23 +426,35 @@ void console_serial_puts(const char *s, size_t nr)
> > pv_console_puts(s, nr);
> > }
> >
> > -static void cf_check dump_console_ring_key(unsigned char key)
> > +/*
> > + * Write characters to physical console(s).
> > + * That covers:
> > + * - serial console;
> > + * - video output.
> > + */
> > +static void console_puts(const char str, size_t len)
> > +{
> > + ASSERT(rspin_is_locked(&console_lock));
> > +
> > + console_serial_puts(str, len);
> > + video_puts(str, len);
> > +}
> > +
> > +/
> > + * Flush contents of the conring to the physical console devices.
> > + */
> > +static int console_flush(void)
> > {
> > uint32_t idx, len, sofar, c;
> > unsigned int order;
> > char *buf;
> >
> > - printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
> > -
> > - /* create a buffer in which we'll copy the ring in the correct
> > - order and NUL terminate */
> > order = get_order_from_bytes(conring_size + 1);
> > buf = alloc_xenheap_pages(order, 0);
> > if ( buf == NULL )
> > - {
> > - printk("unable to allocate memory!\n");
> > - return;
> > - }
> > + return -ENOMEM;
> > +
> > + nrspin_lock_irq(&console_lock);
> >
> > c = conringc;
> > sofar = 0;
> > @@ -457,10 +469,23 @@ static void cf_check dump_console_ring_key(unsigned char key)
> > c += len;
> > }
> >
> > - console_serial_puts(buf, sofar);
> > - video_puts(buf, sofar);
> > + console_puts(buf, sofar);
> > +
> > + nrspin_unlock_irq(&console_lock);
> >
> > free_xenheap_pages(buf, order);
> > +
> > + return 0;
> > +}
> > +
> > +static void cf_check dump_console_ring_key(unsigned char key)
> > +{
> > + int rc;
> > +
> > + printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
> > + rc = console_flush();
> > + if ( rc )
> > + printk("failed to dump console ring buffer: %d\n", rc);
> > }
> >
> > /*
> > @@ -707,10 +732,7 @@ static inline void xen_console_write(const char *str, size_t len)
> > */
> > static void console_write(const char *str, size_t len)
> > {
> > - ASSERT(rspin_is_locked(&console_lock));
> > -
> > - console_serial_puts(str, len);
> > - video_puts(str, len);
> > + console_puts(str, len);
> >
> > if ( opt_console_xen )
> > xen_console_write(str, len);
> > @@ -1177,6 +1199,8 @@ void __init console_endboot(void)
> >
> > video_endboot();
> >
> > + /* NB: send conring contents to all enabled physical consoles, if any */
> > + console_flush();
>
>
> This is way too late: at this point Xen has already finished booting,
> and is about to handover execution to dom0. Flushing here will result
> in duplicating almost all Xen output already printed?
Yes, indeed; fixed.
>
> The flush needs to be done inside of console_init_preirq(), just
> before printing xen_banner() I think. This sequentially after the
> console has been initialized. Otherwise you are just duplicating
> messages.
Fixed.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 28/35] xen/8250-uart: add missing definitions
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Added missing definitions needed for NS8250 UART emulator.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/include/xen/8250-uart.h | 81 +++++++++++++++++++++++++++++++++------------
1 file changed, 60 insertions(+), 21 deletions(-)
diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
index d13352940c13c50bac17d4cdf2f3bf584380776a..4a69b2b225140efda287bdf96fa0caa4aa70074f 100644
--- a/xen/include/xen/8250-uart.h
+++ b/xen/include/xen/8250-uart.h
@@ -32,16 +32,22 @@
#define UART_MCR 0x04 /* Modem control */
#define UART_LSR 0x05 /* line status */
#define UART_MSR 0x06 /* Modem status */
+#define UART_SCR 0x07 /* Scratch pad */
#define UART_USR 0x1f /* Status register (DW) */
#define UART_DLL 0x00 /* divisor latch (ls) (DLAB=1) */
#define UART_DLM 0x01 /* divisor latch (ms) (DLAB=1) */
#define UART_XR_EFR 0x09 /* Enhanced function register (Exar) */
+/* ns8250 emulator: range of emulated registers [0..UART_MAX-1] */
+#define UART_MAX (UART_SCR + 1)
+
/* Interrupt Enable Register */
#define UART_IER_ERDAI 0x01 /* rx data recv'd */
#define UART_IER_ETHREI 0x02 /* tx reg. empty */
#define UART_IER_ELSI 0x04 /* rx line status */
#define UART_IER_EMSI 0x08 /* MODEM status */
+#define UART_IER_MASK \
+ (UART_IER_ERDAI | UART_IER_ETHREI | UART_IER_ELSI | UART_IER_EMSI)
/* Interrupt Identification Register */
#define UART_IIR_NOINT 0x01 /* no interrupt pending */
@@ -51,12 +57,21 @@
#define UART_IIR_THR 0x02 /* - tx reg. empty */
#define UART_IIR_MSI 0x00 /* - MODEM status */
#define UART_IIR_BSY 0x07 /* - busy detect (DW) */
+#define UART_IIR_FE0 BIT(6, U) /* FIFO enable #0 */
+#define UART_IIR_FE1 BIT(7, U) /* FIFO enable #1 */
+#define UART_IIR_FE_MASK (UART_IIR_FE0 | UART_IIR_FE1)
/* FIFO Control Register */
-#define UART_FCR_ENABLE 0x01 /* enable FIFO */
-#define UART_FCR_CLRX 0x02 /* clear Rx FIFO */
-#define UART_FCR_CLTX 0x04 /* clear Tx FIFO */
-#define UART_FCR_DMA 0x10 /* enter DMA mode */
+#define UART_FCR_ENABLE BIT(0, U) /* enable FIFO */
+#define UART_FCR_CLRX BIT(1, U) /* clear Rx FIFO */
+#define UART_FCR_CLTX BIT(2, U) /* clear Tx FIFO */
+#define UART_FCR_DMA BIT(3, U) /* enter DMA mode */
+#define UART_FCR_RESERVED0 BIT(4, U) /* reserved; always 0 */
+#define UART_FCR_RESERVED1 BIT(5, U) /* reserved; always 0 */
+#define UART_FCR_RTB0 BIT(6, U) /* receiver trigger bit #0 */
+#define UART_FCR_RTB1 BIT(7, U) /* receiver trigger bit #1 */
+#define UART_FCR_TRG_MASK (UART_FCR_RTB0 | UART_FCR_RTB1)
+
#define UART_FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */
#define UART_FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */
#define UART_FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */
@@ -64,17 +79,17 @@
/*
* Note: The FIFO trigger levels are chip specific:
- * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
- * PC16550D: 1 4 8 14 xx xx xx xx
- * TI16C550A: 1 4 8 14 xx xx xx xx
- * TI16C550C: 1 4 8 14 xx xx xx xx
- * ST16C550: 1 4 8 14 xx xx xx xx
- * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
- * NS16C552: 1 4 8 14 xx xx xx xx
- * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
- * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
- * TI16C752: 8 16 56 60 8 16 32 56
- * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
+ * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
+ * PC16550D: 1 4 8 14 xx xx xx xx
+ * TI16C550A: 1 4 8 14 xx xx xx xx
+ * TI16C550C: 1 4 8 14 xx xx xx xx
+ * ST16C550: 1 4 8 14 xx xx xx xx
+ * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
+ * NS16C552: 1 4 8 14 xx xx xx xx
+ * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
+ * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
+ * TI16C752: 8 16 56 60 8 16 32 56
+ * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
*/
#define UART_FCR_R_TRIG_00 0x00
#define UART_FCR_R_TRIG_01 0x40
@@ -96,11 +111,31 @@
#define UART_LCR_CONF_MODE_B 0xBF /* Configuration mode B */
/* Modem Control Register */
-#define UART_MCR_DTR 0x01 /* Data Terminal Ready */
-#define UART_MCR_RTS 0x02 /* Request to Send */
-#define UART_MCR_OUT2 0x08 /* OUT2: interrupt mask */
-#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
-#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
+#define UART_MCR_DTR BIT(0, U) /* Data Terminal Ready */
+#define UART_MCR_RTS BIT(1, U) /* Request to Send */
+#define UART_MCR_OUT1 BIT(2, U) /* OUT1: interrupt mask */
+#define UART_MCR_OUT2 BIT(3, U) /* OUT2: interrupt mask */
+#define UART_MCR_LOOP BIT(4, U) /* Enable loopback test mode */
+#define UART_MCR_RESERVED0 BIT(5, U) /* Reserved #0 */
+#define UART_MCR_RESERVED1 BIT(6, U) /* Reserved #1 */
+#define UART_MCR_TCRTLR BIT(6, U) /* Access TCR/TLR (TI16C752, EFR[4]=1) */
+#define UART_MCR_RESERVED2 BIT(7, U) /* Reserved #2 */
+#define UART_MCR_MASK \
+ (UART_MCR_DTR | UART_MCR_RTS | \
+ UART_MCR_OUT1 | UART_MCR_OUT2 | \
+ UART_MCR_LOOP)
+
+/* Modem Status Register */
+#define UART_MSR_DCTS BIT(0, U) /* Change in CTS */
+#define UART_MSR_DDSR BIT(1, U) /* Change in DSR */
+#define UART_MSR_TERI BIT(2, U) /* Change in RI */
+#define UART_MSR_DDCD BIT(3, U) /* Change in CTS */
+#define UART_MSR_CTS BIT(4, U)
+#define UART_MSR_DSR BIT(5, U)
+#define UART_MSR_RI BIT(6, U)
+#define UART_MSR_DCD BIT(7, U)
+#define UART_MSR_DELTA \
+ (UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_TERI | UART_MSR_DDCD)
/* Line Status Register */
#define UART_LSR_DR 0x01 /* Data ready */
@@ -111,6 +146,7 @@
#define UART_LSR_THRE 0x20 /* Xmit hold reg empty */
#define UART_LSR_TEMT 0x40 /* Xmitter empty */
#define UART_LSR_ERR 0x80 /* Error */
+#define UART_LSR_MASK (UART_LSR_OE | UART_LSR_BI)
/* These parity settings can be ORed directly into the LCR. */
#define UART_PARITY_NONE (0<<3)
@@ -119,7 +155,10 @@
#define UART_PARITY_MARK (5<<3)
#define UART_PARITY_SPACE (7<<3)
-/* Frequency of external clock source. This definition assumes PC platform. */
+/*
+ * Frequency of external UART clock source.
+ * Same as IBM PC master input clock frequency.
+ */
#define UART_CLOCK_HZ 1843200
/* Bits in Exar specific UART_XR_EFR register */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* [PATCH v2 28/35] xen/8250-uart: add missing definitions
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Added missing definitions needed for NS8250 UART emulator.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/include/xen/8250-uart.h | 81 +++++++++++++++++++++++++++++++++------------
1 file changed, 60 insertions(+), 21 deletions(-)
diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
index d13352940c13c50bac17d4cdf2f3bf584380776a..4a69b2b225140efda287bdf96fa0caa4aa70074f 100644
--- a/xen/include/xen/8250-uart.h
+++ b/xen/include/xen/8250-uart.h
@@ -32,16 +32,22 @@
#define UART_MCR 0x04 /* Modem control */
#define UART_LSR 0x05 /* line status */
#define UART_MSR 0x06 /* Modem status */
+#define UART_SCR 0x07 /* Scratch pad */
#define UART_USR 0x1f /* Status register (DW) */
#define UART_DLL 0x00 /* divisor latch (ls) (DLAB=1) */
#define UART_DLM 0x01 /* divisor latch (ms) (DLAB=1) */
#define UART_XR_EFR 0x09 /* Enhanced function register (Exar) */
+/* ns8250 emulator: range of emulated registers [0..UART_MAX-1] */
+#define UART_MAX (UART_SCR + 1)
+
/* Interrupt Enable Register */
#define UART_IER_ERDAI 0x01 /* rx data recv'd */
#define UART_IER_ETHREI 0x02 /* tx reg. empty */
#define UART_IER_ELSI 0x04 /* rx line status */
#define UART_IER_EMSI 0x08 /* MODEM status */
+#define UART_IER_MASK \
+ (UART_IER_ERDAI | UART_IER_ETHREI | UART_IER_ELSI | UART_IER_EMSI)
/* Interrupt Identification Register */
#define UART_IIR_NOINT 0x01 /* no interrupt pending */
@@ -51,12 +57,21 @@
#define UART_IIR_THR 0x02 /* - tx reg. empty */
#define UART_IIR_MSI 0x00 /* - MODEM status */
#define UART_IIR_BSY 0x07 /* - busy detect (DW) */
+#define UART_IIR_FE0 BIT(6, U) /* FIFO enable #0 */
+#define UART_IIR_FE1 BIT(7, U) /* FIFO enable #1 */
+#define UART_IIR_FE_MASK (UART_IIR_FE0 | UART_IIR_FE1)
/* FIFO Control Register */
-#define UART_FCR_ENABLE 0x01 /* enable FIFO */
-#define UART_FCR_CLRX 0x02 /* clear Rx FIFO */
-#define UART_FCR_CLTX 0x04 /* clear Tx FIFO */
-#define UART_FCR_DMA 0x10 /* enter DMA mode */
+#define UART_FCR_ENABLE BIT(0, U) /* enable FIFO */
+#define UART_FCR_CLRX BIT(1, U) /* clear Rx FIFO */
+#define UART_FCR_CLTX BIT(2, U) /* clear Tx FIFO */
+#define UART_FCR_DMA BIT(3, U) /* enter DMA mode */
+#define UART_FCR_RESERVED0 BIT(4, U) /* reserved; always 0 */
+#define UART_FCR_RESERVED1 BIT(5, U) /* reserved; always 0 */
+#define UART_FCR_RTB0 BIT(6, U) /* receiver trigger bit #0 */
+#define UART_FCR_RTB1 BIT(7, U) /* receiver trigger bit #1 */
+#define UART_FCR_TRG_MASK (UART_FCR_RTB0 | UART_FCR_RTB1)
+
#define UART_FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */
#define UART_FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */
#define UART_FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */
@@ -64,17 +79,17 @@
/*
* Note: The FIFO trigger levels are chip specific:
- * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
- * PC16550D: 1 4 8 14 xx xx xx xx
- * TI16C550A: 1 4 8 14 xx xx xx xx
- * TI16C550C: 1 4 8 14 xx xx xx xx
- * ST16C550: 1 4 8 14 xx xx xx xx
- * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
- * NS16C552: 1 4 8 14 xx xx xx xx
- * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
- * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
- * TI16C752: 8 16 56 60 8 16 32 56
- * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
+ * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
+ * PC16550D: 1 4 8 14 xx xx xx xx
+ * TI16C550A: 1 4 8 14 xx xx xx xx
+ * TI16C550C: 1 4 8 14 xx xx xx xx
+ * ST16C550: 1 4 8 14 xx xx xx xx
+ * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
+ * NS16C552: 1 4 8 14 xx xx xx xx
+ * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
+ * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
+ * TI16C752: 8 16 56 60 8 16 32 56
+ * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
*/
#define UART_FCR_R_TRIG_00 0x00
#define UART_FCR_R_TRIG_01 0x40
@@ -96,11 +111,31 @@
#define UART_LCR_CONF_MODE_B 0xBF /* Configuration mode B */
/* Modem Control Register */
-#define UART_MCR_DTR 0x01 /* Data Terminal Ready */
-#define UART_MCR_RTS 0x02 /* Request to Send */
-#define UART_MCR_OUT2 0x08 /* OUT2: interrupt mask */
-#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
-#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
+#define UART_MCR_DTR BIT(0, U) /* Data Terminal Ready */
+#define UART_MCR_RTS BIT(1, U) /* Request to Send */
+#define UART_MCR_OUT1 BIT(2, U) /* OUT1: interrupt mask */
+#define UART_MCR_OUT2 BIT(3, U) /* OUT2: interrupt mask */
+#define UART_MCR_LOOP BIT(4, U) /* Enable loopback test mode */
+#define UART_MCR_RESERVED0 BIT(5, U) /* Reserved #0 */
+#define UART_MCR_RESERVED1 BIT(6, U) /* Reserved #1 */
+#define UART_MCR_TCRTLR BIT(6, U) /* Access TCR/TLR (TI16C752, EFR[4]=1) */
+#define UART_MCR_RESERVED2 BIT(7, U) /* Reserved #2 */
+#define UART_MCR_MASK \
+ (UART_MCR_DTR | UART_MCR_RTS | \
+ UART_MCR_OUT1 | UART_MCR_OUT2 | \
+ UART_MCR_LOOP)
+
+/* Modem Status Register */
+#define UART_MSR_DCTS BIT(0, U) /* Change in CTS */
+#define UART_MSR_DDSR BIT(1, U) /* Change in DSR */
+#define UART_MSR_TERI BIT(2, U) /* Change in RI */
+#define UART_MSR_DDCD BIT(3, U) /* Change in CTS */
+#define UART_MSR_CTS BIT(4, U)
+#define UART_MSR_DSR BIT(5, U)
+#define UART_MSR_RI BIT(6, U)
+#define UART_MSR_DCD BIT(7, U)
+#define UART_MSR_DELTA \
+ (UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_TERI | UART_MSR_DDCD)
/* Line Status Register */
#define UART_LSR_DR 0x01 /* Data ready */
@@ -111,6 +146,7 @@
#define UART_LSR_THRE 0x20 /* Xmit hold reg empty */
#define UART_LSR_TEMT 0x40 /* Xmitter empty */
#define UART_LSR_ERR 0x80 /* Error */
+#define UART_LSR_MASK (UART_LSR_OE | UART_LSR_BI)
/* These parity settings can be ORed directly into the LCR. */
#define UART_PARITY_NONE (0<<3)
@@ -119,7 +155,10 @@
#define UART_PARITY_MARK (5<<3)
#define UART_PARITY_SPACE (7<<3)
-/* Frequency of external clock source. This definition assumes PC platform. */
+/*
+ * Frequency of external UART clock source.
+ * Same as IBM PC master input clock frequency.
+ */
#define UART_CLOCK_HZ 1843200
/* Bits in Exar specific UART_XR_EFR register */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* Re: [PATCH v2 28/35] xen/8250-uart: add missing definitions
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 14:29 ` Roger Pau Monné
2025-01-04 4:01 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 14:29 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:58PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Added missing definitions needed for NS8250 UART emulator.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/include/xen/8250-uart.h | 81 +++++++++++++++++++++++++++++++++------------
> 1 file changed, 60 insertions(+), 21 deletions(-)
>
> diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
> index d13352940c13c50bac17d4cdf2f3bf584380776a..4a69b2b225140efda287bdf96fa0caa4aa70074f 100644
> --- a/xen/include/xen/8250-uart.h
> +++ b/xen/include/xen/8250-uart.h
> @@ -32,16 +32,22 @@
> #define UART_MCR 0x04 /* Modem control */
> #define UART_LSR 0x05 /* line status */
> #define UART_MSR 0x06 /* Modem status */
> +#define UART_SCR 0x07 /* Scratch pad */
> #define UART_USR 0x1f /* Status register (DW) */
> #define UART_DLL 0x00 /* divisor latch (ls) (DLAB=1) */
> #define UART_DLM 0x01 /* divisor latch (ms) (DLAB=1) */
> #define UART_XR_EFR 0x09 /* Enhanced function register (Exar) */
>
> +/* ns8250 emulator: range of emulated registers [0..UART_MAX-1] */
> +#define UART_MAX (UART_SCR + 1)
> +
> /* Interrupt Enable Register */
> #define UART_IER_ERDAI 0x01 /* rx data recv'd */
> #define UART_IER_ETHREI 0x02 /* tx reg. empty */
> #define UART_IER_ELSI 0x04 /* rx line status */
> #define UART_IER_EMSI 0x08 /* MODEM status */
> +#define UART_IER_MASK \
> + (UART_IER_ERDAI | UART_IER_ETHREI | UART_IER_ELSI | UART_IER_EMSI)
>
> /* Interrupt Identification Register */
> #define UART_IIR_NOINT 0x01 /* no interrupt pending */
> @@ -51,12 +57,21 @@
> #define UART_IIR_THR 0x02 /* - tx reg. empty */
> #define UART_IIR_MSI 0x00 /* - MODEM status */
> #define UART_IIR_BSY 0x07 /* - busy detect (DW) */
> +#define UART_IIR_FE0 BIT(6, U) /* FIFO enable #0 */
> +#define UART_IIR_FE1 BIT(7, U) /* FIFO enable #1 */
> +#define UART_IIR_FE_MASK (UART_IIR_FE0 | UART_IIR_FE1)
>
> /* FIFO Control Register */
> -#define UART_FCR_ENABLE 0x01 /* enable FIFO */
> -#define UART_FCR_CLRX 0x02 /* clear Rx FIFO */
> -#define UART_FCR_CLTX 0x04 /* clear Tx FIFO */
> -#define UART_FCR_DMA 0x10 /* enter DMA mode */
> +#define UART_FCR_ENABLE BIT(0, U) /* enable FIFO */
> +#define UART_FCR_CLRX BIT(1, U) /* clear Rx FIFO */
> +#define UART_FCR_CLTX BIT(2, U) /* clear Tx FIFO */
> +#define UART_FCR_DMA BIT(3, U) /* enter DMA mode */
> +#define UART_FCR_RESERVED0 BIT(4, U) /* reserved; always 0 */
> +#define UART_FCR_RESERVED1 BIT(5, U) /* reserved; always 0 */
We don't usually define reserved bits I think, as I assume those won't
be used by the code?
Maybe a reserved mask for the hole register, to ensure the access to
the register doesn't attempt to set reserved bits? But even then the
best we can do when emulating is print a warning message.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 28/35] xen/8250-uart: add missing definitions
2024-12-12 14:29 ` Roger Pau Monné
@ 2025-01-04 4:01 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:01 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 6:29 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:58PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Added missing definitions needed for NS8250 UART emulator.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/include/xen/8250-uart.h | 81 +++++++++++++++++++++++++++++++++------------
> > 1 file changed, 60 insertions(+), 21 deletions(-)
> >
> > diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
> > index d13352940c13c50bac17d4cdf2f3bf584380776a..4a69b2b225140efda287bdf96fa0caa4aa70074f 100644
> > --- a/xen/include/xen/8250-uart.h
> > +++ b/xen/include/xen/8250-uart.h
> > @@ -32,16 +32,22 @@
> > #define UART_MCR 0x04 /* Modem control /
> > #define UART_LSR 0x05 / line status /
> > #define UART_MSR 0x06 / Modem status /
> > +#define UART_SCR 0x07 / Scratch pad /
> > #define UART_USR 0x1f / Status register (DW) /
> > #define UART_DLL 0x00 / divisor latch (ls) (DLAB=1) /
> > #define UART_DLM 0x01 / divisor latch (ms) (DLAB=1) /
> > #define UART_XR_EFR 0x09 / Enhanced function register (Exar) */
> >
> > +/* ns8250 emulator: range of emulated registers [0..UART_MAX-1] /
> > +#define UART_MAX (UART_SCR + 1)
> > +
> > / Interrupt Enable Register /
> > #define UART_IER_ERDAI 0x01 / rx data recv'd /
> > #define UART_IER_ETHREI 0x02 / tx reg. empty /
> > #define UART_IER_ELSI 0x04 / rx line status /
> > #define UART_IER_EMSI 0x08 / MODEM status */
> > +#define UART_IER_MASK \
> > + (UART_IER_ERDAI | UART_IER_ETHREI | UART_IER_ELSI | UART_IER_EMSI)
> >
> > /* Interrupt Identification Register /
> > #define UART_IIR_NOINT 0x01 / no interrupt pending /
> > @@ -51,12 +57,21 @@
> > #define UART_IIR_THR 0x02 / - tx reg. empty /
> > #define UART_IIR_MSI 0x00 / - MODEM status /
> > #define UART_IIR_BSY 0x07 / - busy detect (DW) /
> > +#define UART_IIR_FE0 BIT(6, U) / FIFO enable #0 /
> > +#define UART_IIR_FE1 BIT(7, U) / FIFO enable #1 */
> > +#define UART_IIR_FE_MASK (UART_IIR_FE0 | UART_IIR_FE1)
> >
> > /* FIFO Control Register /
> > -#define UART_FCR_ENABLE 0x01 / enable FIFO /
> > -#define UART_FCR_CLRX 0x02 / clear Rx FIFO /
> > -#define UART_FCR_CLTX 0x04 / clear Tx FIFO /
> > -#define UART_FCR_DMA 0x10 / enter DMA mode /
> > +#define UART_FCR_ENABLE BIT(0, U) / enable FIFO /
> > +#define UART_FCR_CLRX BIT(1, U) / clear Rx FIFO /
> > +#define UART_FCR_CLTX BIT(2, U) / clear Tx FIFO /
> > +#define UART_FCR_DMA BIT(3, U) / enter DMA mode /
> > +#define UART_FCR_RESERVED0 BIT(4, U) / reserved; always 0 /
> > +#define UART_FCR_RESERVED1 BIT(5, U) / reserved; always 0 */
>
>
> We don't usually define reserved bits I think, as I assume those won't
> be used by the code?
I found examples of reserved bits being defined and not used in the
code base, e.g. PCI_PM_CAP_RESERVED.
IMO marking reserved bits in the code will immediately explain
readers the purpose of those bits.
>
> Maybe a reserved mask for the hole register, to ensure the access to
> the register doesn't attempt to set reserved bits? But even then the
> best we can do when emulating is print a warning message.
Added warning messages in the emulator code (v3).
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 28/35] xen/8250-uart: add missing definitions
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-12 15:07 ` Jan Beulich
2025-01-04 4:00 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-12 15:07 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
> --- a/xen/include/xen/8250-uart.h
> +++ b/xen/include/xen/8250-uart.h
> @@ -32,16 +32,22 @@
> #define UART_MCR 0x04 /* Modem control */
> #define UART_LSR 0x05 /* line status */
> #define UART_MSR 0x06 /* Modem status */
> +#define UART_SCR 0x07 /* Scratch pad */
> #define UART_USR 0x1f /* Status register (DW) */
> #define UART_DLL 0x00 /* divisor latch (ls) (DLAB=1) */
> #define UART_DLM 0x01 /* divisor latch (ms) (DLAB=1) */
> #define UART_XR_EFR 0x09 /* Enhanced function register (Exar) */
>
> +/* ns8250 emulator: range of emulated registers [0..UART_MAX-1] */
> +#define UART_MAX (UART_SCR + 1)
There are two issues here: "max" means "highest within range", yet
you define it as "first invalid", i.e. something we'd normally call
"_NR" or "_NUM". And then, as the comment says, this is a limit the
emulation is going to expose, not something generally applicable to
UARTs of this kind. Hence the UART_ prefix alone isn't quite correct
either.
> @@ -51,12 +57,21 @@
> #define UART_IIR_THR 0x02 /* - tx reg. empty */
> #define UART_IIR_MSI 0x00 /* - MODEM status */
> #define UART_IIR_BSY 0x07 /* - busy detect (DW) */
> +#define UART_IIR_FE0 BIT(6, U) /* FIFO enable #0 */
> +#define UART_IIR_FE1 BIT(7, U) /* FIFO enable #1 */
> +#define UART_IIR_FE_MASK (UART_IIR_FE0 | UART_IIR_FE1)
Much like BSY is a 3-bit field, aiui this is a 2-bit one.
> /* FIFO Control Register */
> -#define UART_FCR_ENABLE 0x01 /* enable FIFO */
> -#define UART_FCR_CLRX 0x02 /* clear Rx FIFO */
> -#define UART_FCR_CLTX 0x04 /* clear Tx FIFO */
> -#define UART_FCR_DMA 0x10 /* enter DMA mode */
> +#define UART_FCR_ENABLE BIT(0, U) /* enable FIFO */
> +#define UART_FCR_CLRX BIT(1, U) /* clear Rx FIFO */
> +#define UART_FCR_CLTX BIT(2, U) /* clear Tx FIFO */
> +#define UART_FCR_DMA BIT(3, U) /* enter DMA mode */
> +#define UART_FCR_RESERVED0 BIT(4, U) /* reserved; always 0 */
> +#define UART_FCR_RESERVED1 BIT(5, U) /* reserved; always 0 */
> +#define UART_FCR_RTB0 BIT(6, U) /* receiver trigger bit #0 */
> +#define UART_FCR_RTB1 BIT(7, U) /* receiver trigger bit #1 */
> +#define UART_FCR_TRG_MASK (UART_FCR_RTB0 | UART_FCR_RTB1)
Much like the top two bits here are, and - as Roger has said - the
reserved bits probably also should be.
> @@ -64,17 +79,17 @@
>
> /*
> * Note: The FIFO trigger levels are chip specific:
> - * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
> - * PC16550D: 1 4 8 14 xx xx xx xx
> - * TI16C550A: 1 4 8 14 xx xx xx xx
> - * TI16C550C: 1 4 8 14 xx xx xx xx
> - * ST16C550: 1 4 8 14 xx xx xx xx
> - * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
> - * NS16C552: 1 4 8 14 xx xx xx xx
> - * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
> - * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
> - * TI16C752: 8 16 56 60 8 16 32 56
> - * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
> + * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
> + * PC16550D: 1 4 8 14 xx xx xx xx
> + * TI16C550A: 1 4 8 14 xx xx xx xx
> + * TI16C550C: 1 4 8 14 xx xx xx xx
> + * ST16C550: 1 4 8 14 xx xx xx xx
> + * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
> + * NS16C552: 1 4 8 14 xx xx xx xx
> + * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
> + * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
> + * TI16C752: 8 16 56 60 8 16 32 56
> + * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
> */
While perhaps okay, the adjustment of this table still looks unrelated.
It wants at least mentioning in the description, to clarify it's an
intentional change (as opposed to e.g. being an effect of how your
editor is configured).
> @@ -96,11 +111,31 @@
> #define UART_LCR_CONF_MODE_B 0xBF /* Configuration mode B */
>
> /* Modem Control Register */
> -#define UART_MCR_DTR 0x01 /* Data Terminal Ready */
> -#define UART_MCR_RTS 0x02 /* Request to Send */
> -#define UART_MCR_OUT2 0x08 /* OUT2: interrupt mask */
> -#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
> -#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
> +#define UART_MCR_DTR BIT(0, U) /* Data Terminal Ready */
> +#define UART_MCR_RTS BIT(1, U) /* Request to Send */
> +#define UART_MCR_OUT1 BIT(2, U) /* OUT1: interrupt mask */
> +#define UART_MCR_OUT2 BIT(3, U) /* OUT2: interrupt mask */
> +#define UART_MCR_LOOP BIT(4, U) /* Enable loopback test mode */
> +#define UART_MCR_RESERVED0 BIT(5, U) /* Reserved #0 */
> +#define UART_MCR_RESERVED1 BIT(6, U) /* Reserved #1 */
> +#define UART_MCR_TCRTLR BIT(6, U) /* Access TCR/TLR (TI16C752, EFR[4]=1) */
> +#define UART_MCR_RESERVED2 BIT(7, U) /* Reserved #2 */
> +#define UART_MCR_MASK \
> + (UART_MCR_DTR | UART_MCR_RTS | \
> + UART_MCR_OUT1 | UART_MCR_OUT2 | \
> + UART_MCR_LOOP)
> +
> +/* Modem Status Register */
> +#define UART_MSR_DCTS BIT(0, U) /* Change in CTS */
> +#define UART_MSR_DDSR BIT(1, U) /* Change in DSR */
> +#define UART_MSR_TERI BIT(2, U) /* Change in RI */
> +#define UART_MSR_DDCD BIT(3, U) /* Change in CTS */
> +#define UART_MSR_CTS BIT(4, U)
> +#define UART_MSR_DSR BIT(5, U)
> +#define UART_MSR_RI BIT(6, U)
> +#define UART_MSR_DCD BIT(7, U)
As you introduce these constants, I think you also want to switch the sole
MSR read we have to actually use them.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 28/35] xen/8250-uart: add missing definitions
2024-12-12 15:07 ` Jan Beulich
@ 2025-01-04 4:00 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:00 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Thursday, December 12th, 2024 at 7:07 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:41, Denis Mukhin via B4 Relay wrote:
>
> > --- a/xen/include/xen/8250-uart.h
> > +++ b/xen/include/xen/8250-uart.h
> > @@ -32,16 +32,22 @@
> > #define UART_MCR 0x04 /* Modem control /
> > #define UART_LSR 0x05 / line status /
> > #define UART_MSR 0x06 / Modem status /
> > +#define UART_SCR 0x07 / Scratch pad /
> > #define UART_USR 0x1f / Status register (DW) /
> > #define UART_DLL 0x00 / divisor latch (ls) (DLAB=1) /
> > #define UART_DLM 0x01 / divisor latch (ms) (DLAB=1) /
> > #define UART_XR_EFR 0x09 / Enhanced function register (Exar) */
> >
> > +/* ns8250 emulator: range of emulated registers [0..UART_MAX-1] */
> > +#define UART_MAX (UART_SCR + 1)
>
>
> There are two issues here: "max" means "highest within range", yet
> you define it as "first invalid", i.e. something we'd normally call
> "_NR" or "NUM". And then, as the comment says, this is a limit the
> emulation is going to expose, not something generally applicable to
> UARTs of this kind. Hence the UART prefix alone isn't quite correct
> either.
I did renaming and moved declaration to the UART emulator code.
>
> > @@ -51,12 +57,21 @@
> > #define UART_IIR_THR 0x02 /* - tx reg. empty /
> > #define UART_IIR_MSI 0x00 / - MODEM status /
> > #define UART_IIR_BSY 0x07 / - busy detect (DW) /
> > +#define UART_IIR_FE0 BIT(6, U) / FIFO enable #0 /
> > +#define UART_IIR_FE1 BIT(7, U) / FIFO enable #1 */
> > +#define UART_IIR_FE_MASK (UART_IIR_FE0 | UART_IIR_FE1)
>
>
> Much like BSY is a 3-bit field, aiui this is a 2-bit one.
Updated to 2-bit mask.
>
> > /* FIFO Control Register /
> > -#define UART_FCR_ENABLE 0x01 / enable FIFO /
> > -#define UART_FCR_CLRX 0x02 / clear Rx FIFO /
> > -#define UART_FCR_CLTX 0x04 / clear Tx FIFO /
> > -#define UART_FCR_DMA 0x10 / enter DMA mode /
> > +#define UART_FCR_ENABLE BIT(0, U) / enable FIFO /
> > +#define UART_FCR_CLRX BIT(1, U) / clear Rx FIFO /
> > +#define UART_FCR_CLTX BIT(2, U) / clear Tx FIFO /
> > +#define UART_FCR_DMA BIT(3, U) / enter DMA mode /
> > +#define UART_FCR_RESERVED0 BIT(4, U) / reserved; always 0 /
> > +#define UART_FCR_RESERVED1 BIT(5, U) / reserved; always 0 /
> > +#define UART_FCR_RTB0 BIT(6, U) / receiver trigger bit #0 /
> > +#define UART_FCR_RTB1 BIT(7, U) / receiver trigger bit #1 */
> > +#define UART_FCR_TRG_MASK (UART_FCR_RTB0 | UART_FCR_RTB1)
>
>
> Much like the top two bits here are, and - as Roger has said - the
> reserved bits probably also should be.
I kept reserved bits as is.
I think that will help to avoid confusion whether support for those bits
is missing in the driver code or those are reserved.
There are other examples, e.g. PCI_PM_CAP_RESERVED when reserved bits
declared and not necessarily used in the code base.
>
> > @@ -64,17 +79,17 @@
> >
> > /*
> > * Note: The FIFO trigger levels are chip specific:
> > - * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
> > - * PC16550D: 1 4 8 14 xx xx xx xx
> > - * TI16C550A: 1 4 8 14 xx xx xx xx
> > - * TI16C550C: 1 4 8 14 xx xx xx xx
> > - * ST16C550: 1 4 8 14 xx xx xx xx
> > - * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
> > - * NS16C552: 1 4 8 14 xx xx xx xx
> > - * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
> > - * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
> > - * TI16C752: 8 16 56 60 8 16 32 56
> > - * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
> > + * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
> > + * PC16550D: 1 4 8 14 xx xx xx xx
> > + * TI16C550A: 1 4 8 14 xx xx xx xx
> > + * TI16C550C: 1 4 8 14 xx xx xx xx
> > + * ST16C550: 1 4 8 14 xx xx xx xx
> > + * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
> > + * NS16C552: 1 4 8 14 xx xx xx xx
> > + * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
> > + * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
> > + * TI16C752: 8 16 56 60 8 16 32 56
> > + * Tegra: 1 4 8 14 16 8 4 1 PORT_TEGRA
> > */
>
>
> While perhaps okay, the adjustment of this table still looks unrelated.
> It wants at least mentioning in the description, to clarify it's an
> intentional change (as opposed to e.g. being an effect of how your
> editor is configured).
Thanks, I updated the commit message.
>
> > @@ -96,11 +111,31 @@
> > #define UART_LCR_CONF_MODE_B 0xBF /* Configuration mode B */
> >
> > /* Modem Control Register /
> > -#define UART_MCR_DTR 0x01 / Data Terminal Ready /
> > -#define UART_MCR_RTS 0x02 / Request to Send /
> > -#define UART_MCR_OUT2 0x08 / OUT2: interrupt mask /
> > -#define UART_MCR_LOOP 0x10 / Enable loopback test mode /
> > -#define UART_MCR_TCRTLR 0x40 / Access TCR/TLR (TI16C752, EFR[4]=1) /
> > +#define UART_MCR_DTR BIT(0, U) / Data Terminal Ready /
> > +#define UART_MCR_RTS BIT(1, U) / Request to Send /
> > +#define UART_MCR_OUT1 BIT(2, U) / OUT1: interrupt mask /
> > +#define UART_MCR_OUT2 BIT(3, U) / OUT2: interrupt mask /
> > +#define UART_MCR_LOOP BIT(4, U) / Enable loopback test mode /
> > +#define UART_MCR_RESERVED0 BIT(5, U) / Reserved #0 /
> > +#define UART_MCR_RESERVED1 BIT(6, U) / Reserved #1 /
> > +#define UART_MCR_TCRTLR BIT(6, U) / Access TCR/TLR (TI16C752, EFR[4]=1) /
> > +#define UART_MCR_RESERVED2 BIT(7, U) / Reserved #2 /
> > +#define UART_MCR_MASK \
> > + (UART_MCR_DTR | UART_MCR_RTS | \
> > + UART_MCR_OUT1 | UART_MCR_OUT2 | \
> > + UART_MCR_LOOP)
> > +
> > +/ Modem Status Register /
> > +#define UART_MSR_DCTS BIT(0, U) / Change in CTS /
> > +#define UART_MSR_DDSR BIT(1, U) / Change in DSR /
> > +#define UART_MSR_TERI BIT(2, U) / Change in RI /
> > +#define UART_MSR_DDCD BIT(3, U) / Change in CTS */
> > +#define UART_MSR_CTS BIT(4, U)
> > +#define UART_MSR_DSR BIT(5, U)
> > +#define UART_MSR_RI BIT(6, U)
> > +#define UART_MSR_DCD BIT(7, U)
>
>
> As you introduce these constants, I think you also want to switch the sole
> MSR read we have to actually use them.
Sure, no problem; fixed.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 29/35] x86/hvm: add HVM-specific Kconfig
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Add separate menu for configuring HVM build-time settings.
That will help organizing HVM-specific options under a separate menu.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/Kconfig | 66 +++---------------------------------------------
xen/arch/x86/hvm/Kconfig | 63 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 63 deletions(-)
diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 9cdd04721afa1916c7edd8fdf7d606858c73ce88..5afee9a9f9bafa3c760b06b8601fad4cad3b7191 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -107,42 +107,9 @@ config PV_LINEAR_PT
If unsure, say Y.
-config HVM
- bool "HVM support"
- depends on !PV_SHIM_EXCLUSIVE
- default !PV_SHIM
- select COMPAT
- select IOREQ_SERVER
- select MEM_ACCESS_ALWAYS_ON
- help
- Interfaces to support HVM domains. HVM domains require hardware
- virtualisation extensions (e.g. Intel VT-x, AMD SVM), but can boot
- guests which have no specific Xen knowledge.
-
- This option is needed if you want to run HVM or PVH domains.
-
- If unsure, say Y.
-
-config AMD_SVM
- bool "AMD-V" if EXPERT
- depends on HVM
- default y
- help
- Enables virtual machine extensions on platforms that implement the
- AMD Virtualization Technology (AMD-V).
- If your system includes a processor with AMD-V support, say Y.
- If in doubt, say Y.
-
-config INTEL_VMX
- bool "Intel VT-x" if EXPERT
- depends on HVM
- default y
- select ARCH_VCPU_IOREQ_COMPLETION
- help
- Enables virtual machine extensions on platforms that implement the
- Intel Virtualization Technology (Intel VT-x).
- If your system includes a processor with Intel VT-x support, say Y.
- If in doubt, say Y.
+menu "HVM Support"
+source "arch/x86/hvm/Kconfig"
+endmenu
config XEN_SHSTK
bool "Supervisor Shadow Stacks"
@@ -201,25 +168,6 @@ config BIGMEM
If unsure, say N.
-config HVM_FEP
- bool "HVM Forced Emulation Prefix support (UNSUPPORTED)" if UNSUPPORTED
- default DEBUG
- depends on HVM
- help
-
- Compiles in a feature that allows HVM guest to arbitrarily
- exercise the instruction emulator.
-
- This feature can only be enabled during boot time with
- appropriate hypervisor command line option. Please read
- hypervisor command line documentation before trying to use
- this feature.
-
- This is strictly for testing purposes, and not appropriate
- for use in production.
-
- If unsure, say N.
-
config TBOOT
bool "Xen tboot support (UNSUPPORTED)"
depends on INTEL && UNSUPPORTED
@@ -348,14 +296,6 @@ config HYPERV_GUEST
endif
-config MEM_PAGING
- bool "Xen memory paging support (UNSUPPORTED)" if UNSUPPORTED
- depends on HVM
-
-config MEM_SHARING
- bool "Xen memory sharing support (UNSUPPORTED)" if UNSUPPORTED
- depends on HVM
-
config REQUIRE_NX
bool "Require NX (No eXecute) support"
help
diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..361bb6572e633f3cf0fc972a3b391e8341c33361
--- /dev/null
+++ b/xen/arch/x86/hvm/Kconfig
@@ -0,0 +1,63 @@
+config HVM
+ bool "HVM support"
+ depends on !PV_SHIM_EXCLUSIVE
+ default !PV_SHIM
+ select COMPAT
+ select IOREQ_SERVER
+ select MEM_ACCESS_ALWAYS_ON
+ help
+ Interfaces to support HVM domains. HVM domains require hardware
+ virtualisation extensions (e.g. Intel VT-x, AMD SVM), but can boot
+ guests which have no specific Xen knowledge.
+
+ This option is needed if you want to run HVM or PVH domains.
+
+ If unsure, say Y.
+
+config AMD_SVM
+ bool "AMD-V" if EXPERT
+ depends on HVM
+ default y
+ help
+ Enables virtual machine extensions on platforms that implement the
+ AMD Virtualization Technology (AMD-V).
+ If your system includes a processor with AMD-V support, say Y.
+ If in doubt, say Y.
+
+config INTEL_VMX
+ bool "Intel VT-x" if EXPERT
+ depends on HVM
+ default y
+ select ARCH_VCPU_IOREQ_COMPLETION
+ help
+ Enables virtual machine extensions on platforms that implement the
+ Intel Virtualization Technology (Intel VT-x).
+ If your system includes a processor with Intel VT-x support, say Y.
+ If in doubt, say Y.
+
+config MEM_PAGING
+ bool "Xen memory paging support (UNSUPPORTED)" if UNSUPPORTED
+ depends on HVM
+
+config MEM_SHARING
+ bool "Xen memory sharing support (UNSUPPORTED)" if UNSUPPORTED
+ depends on HVM
+
+config HVM_FEP
+ bool "HVM Forced Emulation Prefix support (UNSUPPORTED)" if UNSUPPORTED
+ default DEBUG
+ depends on HVM
+ help
+
+ Compiles in a feature that allows HVM guest to arbitrarily
+ exercise the instruction emulator.
+
+ This feature can only be enabled during boot time with
+ appropriate hypervisor command line option. Please read
+ hypervisor command line documentation before trying to use
+ this feature.
+
+ This is strictly for testing purposes, and not appropriate
+ for use in production.
+
+ If unsure, say N.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 29/35] x86/hvm: add HVM-specific Kconfig
@ 2024-12-06 4:41 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:41 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Add separate menu for configuring HVM build-time settings.
That will help organizing HVM-specific options under a separate menu.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/Kconfig | 66 +++---------------------------------------------
xen/arch/x86/hvm/Kconfig | 63 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 63 deletions(-)
diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 9cdd04721afa1916c7edd8fdf7d606858c73ce88..5afee9a9f9bafa3c760b06b8601fad4cad3b7191 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -107,42 +107,9 @@ config PV_LINEAR_PT
If unsure, say Y.
-config HVM
- bool "HVM support"
- depends on !PV_SHIM_EXCLUSIVE
- default !PV_SHIM
- select COMPAT
- select IOREQ_SERVER
- select MEM_ACCESS_ALWAYS_ON
- help
- Interfaces to support HVM domains. HVM domains require hardware
- virtualisation extensions (e.g. Intel VT-x, AMD SVM), but can boot
- guests which have no specific Xen knowledge.
-
- This option is needed if you want to run HVM or PVH domains.
-
- If unsure, say Y.
-
-config AMD_SVM
- bool "AMD-V" if EXPERT
- depends on HVM
- default y
- help
- Enables virtual machine extensions on platforms that implement the
- AMD Virtualization Technology (AMD-V).
- If your system includes a processor with AMD-V support, say Y.
- If in doubt, say Y.
-
-config INTEL_VMX
- bool "Intel VT-x" if EXPERT
- depends on HVM
- default y
- select ARCH_VCPU_IOREQ_COMPLETION
- help
- Enables virtual machine extensions on platforms that implement the
- Intel Virtualization Technology (Intel VT-x).
- If your system includes a processor with Intel VT-x support, say Y.
- If in doubt, say Y.
+menu "HVM Support"
+source "arch/x86/hvm/Kconfig"
+endmenu
config XEN_SHSTK
bool "Supervisor Shadow Stacks"
@@ -201,25 +168,6 @@ config BIGMEM
If unsure, say N.
-config HVM_FEP
- bool "HVM Forced Emulation Prefix support (UNSUPPORTED)" if UNSUPPORTED
- default DEBUG
- depends on HVM
- help
-
- Compiles in a feature that allows HVM guest to arbitrarily
- exercise the instruction emulator.
-
- This feature can only be enabled during boot time with
- appropriate hypervisor command line option. Please read
- hypervisor command line documentation before trying to use
- this feature.
-
- This is strictly for testing purposes, and not appropriate
- for use in production.
-
- If unsure, say N.
-
config TBOOT
bool "Xen tboot support (UNSUPPORTED)"
depends on INTEL && UNSUPPORTED
@@ -348,14 +296,6 @@ config HYPERV_GUEST
endif
-config MEM_PAGING
- bool "Xen memory paging support (UNSUPPORTED)" if UNSUPPORTED
- depends on HVM
-
-config MEM_SHARING
- bool "Xen memory sharing support (UNSUPPORTED)" if UNSUPPORTED
- depends on HVM
-
config REQUIRE_NX
bool "Require NX (No eXecute) support"
help
diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..361bb6572e633f3cf0fc972a3b391e8341c33361
--- /dev/null
+++ b/xen/arch/x86/hvm/Kconfig
@@ -0,0 +1,63 @@
+config HVM
+ bool "HVM support"
+ depends on !PV_SHIM_EXCLUSIVE
+ default !PV_SHIM
+ select COMPAT
+ select IOREQ_SERVER
+ select MEM_ACCESS_ALWAYS_ON
+ help
+ Interfaces to support HVM domains. HVM domains require hardware
+ virtualisation extensions (e.g. Intel VT-x, AMD SVM), but can boot
+ guests which have no specific Xen knowledge.
+
+ This option is needed if you want to run HVM or PVH domains.
+
+ If unsure, say Y.
+
+config AMD_SVM
+ bool "AMD-V" if EXPERT
+ depends on HVM
+ default y
+ help
+ Enables virtual machine extensions on platforms that implement the
+ AMD Virtualization Technology (AMD-V).
+ If your system includes a processor with AMD-V support, say Y.
+ If in doubt, say Y.
+
+config INTEL_VMX
+ bool "Intel VT-x" if EXPERT
+ depends on HVM
+ default y
+ select ARCH_VCPU_IOREQ_COMPLETION
+ help
+ Enables virtual machine extensions on platforms that implement the
+ Intel Virtualization Technology (Intel VT-x).
+ If your system includes a processor with Intel VT-x support, say Y.
+ If in doubt, say Y.
+
+config MEM_PAGING
+ bool "Xen memory paging support (UNSUPPORTED)" if UNSUPPORTED
+ depends on HVM
+
+config MEM_SHARING
+ bool "Xen memory sharing support (UNSUPPORTED)" if UNSUPPORTED
+ depends on HVM
+
+config HVM_FEP
+ bool "HVM Forced Emulation Prefix support (UNSUPPORTED)" if UNSUPPORTED
+ default DEBUG
+ depends on HVM
+ help
+
+ Compiles in a feature that allows HVM guest to arbitrarily
+ exercise the instruction emulator.
+
+ This feature can only be enabled during boot time with
+ appropriate hypervisor command line option. Please read
+ hypervisor command line documentation before trying to use
+ this feature.
+
+ This is strictly for testing purposes, and not appropriate
+ for use in production.
+
+ If unsure, say N.
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 29/35] x86/hvm: add HVM-specific Kconfig
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 15:06 ` Roger Pau Monné
2025-01-04 3:58 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 15:06 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:41:59PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Add separate menu for configuring HVM build-time settings.
> That will help organizing HVM-specific options under a separate menu.
Instead of being a separate menu, which feels a bit odd under default
settings because there's just an "HVM support" option inside, could
you make it look like the PV support menu, that indents PV specific
options:
[*] PV support
[ ] Support for 32bit PV guests
[*] Support for PV linear pagetables
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 29/35] x86/hvm: add HVM-specific Kconfig
2024-12-12 15:06 ` Roger Pau Monné
@ 2025-01-04 3:58 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:58 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 7:06 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:59PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Add separate menu for configuring HVM build-time settings.
> > That will help organizing HVM-specific options under a separate menu.
>
>
> Instead of being a separate menu, which feels a bit odd under default
> settings because there's just an "HVM support" option inside, could
> you make it look like the PV support menu, that indents PV specific
> options:
>
> [] PV support
> [ ] Support for 32bit PV guests
> [] Support for PV linear pagetables
My rationale is that code base at arch/x86/hvm deserves its own Kconfig because
there a bunch of configuration options just for arch/x86/hvm.
I think that will also help managing configuration since they all in dedicated
location.
I enabled "HVM menu" using correct Kconfig syntax in v3.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 30/35] x86/hvm: add helpers for raising guest IRQs
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Added convenience wrappers for asserting/de-asserting interrupts in the
hardware emulation code.
That will be used for PCI-based NS8250 emulator.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/hvm/irq.c | 24 ++++++++++++++++++++++++
xen/arch/x86/include/asm/hvm/irq.h | 3 +++
2 files changed, 27 insertions(+)
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 1eab44defca4c82ec35769617c66c380cc07d1b6..9e3a50d21dcf281c1015116094e47795c51ed5d0 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -242,6 +242,30 @@ void hvm_isa_irq_deassert(
spin_unlock(&d->arch.hvm.irq_lock);
}
+void hvm_irq_raise(struct domain *d, unsigned int irq)
+{
+ if ( irq < NR_ISAIRQS )
+ {
+ hvm_isa_irq_assert(d, irq, NULL);
+ }
+ else
+ {
+ hvm_gsi_assert(d, irq);
+ }
+}
+
+void hvm_irq_lower(struct domain *d, unsigned int irq)
+{
+ if ( irq < NR_ISAIRQS )
+ {
+ hvm_isa_irq_deassert(d, irq);
+ }
+ else
+ {
+ hvm_gsi_deassert(d, irq);
+ }
+}
+
static void hvm_set_callback_irq_level(struct vcpu *v)
{
struct domain *d = v->domain;
diff --git a/xen/arch/x86/include/asm/hvm/irq.h b/xen/arch/x86/include/asm/hvm/irq.h
index 87e89993a44f48f366fa84e851688f383cb562d4..27bb9f64171c1b8aac2cf119699e60c91e727177 100644
--- a/xen/arch/x86/include/asm/hvm/irq.h
+++ b/xen/arch/x86/include/asm/hvm/irq.h
@@ -210,6 +210,9 @@ void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
void hvm_set_callback_via(struct domain *d, uint64_t via);
+void hvm_irq_raise(struct domain *d, unsigned int irq);
+void hvm_irq_lower(struct domain *d, unsigned int irq);
+
struct pirq;
bool hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq);
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 30/35] x86/hvm: add helpers for raising guest IRQs
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Added convenience wrappers for asserting/de-asserting interrupts in the
hardware emulation code.
That will be used for PCI-based NS8250 emulator.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/hvm/irq.c | 24 ++++++++++++++++++++++++
xen/arch/x86/include/asm/hvm/irq.h | 3 +++
2 files changed, 27 insertions(+)
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 1eab44defca4c82ec35769617c66c380cc07d1b6..9e3a50d21dcf281c1015116094e47795c51ed5d0 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -242,6 +242,30 @@ void hvm_isa_irq_deassert(
spin_unlock(&d->arch.hvm.irq_lock);
}
+void hvm_irq_raise(struct domain *d, unsigned int irq)
+{
+ if ( irq < NR_ISAIRQS )
+ {
+ hvm_isa_irq_assert(d, irq, NULL);
+ }
+ else
+ {
+ hvm_gsi_assert(d, irq);
+ }
+}
+
+void hvm_irq_lower(struct domain *d, unsigned int irq)
+{
+ if ( irq < NR_ISAIRQS )
+ {
+ hvm_isa_irq_deassert(d, irq);
+ }
+ else
+ {
+ hvm_gsi_deassert(d, irq);
+ }
+}
+
static void hvm_set_callback_irq_level(struct vcpu *v)
{
struct domain *d = v->domain;
diff --git a/xen/arch/x86/include/asm/hvm/irq.h b/xen/arch/x86/include/asm/hvm/irq.h
index 87e89993a44f48f366fa84e851688f383cb562d4..27bb9f64171c1b8aac2cf119699e60c91e727177 100644
--- a/xen/arch/x86/include/asm/hvm/irq.h
+++ b/xen/arch/x86/include/asm/hvm/irq.h
@@ -210,6 +210,9 @@ void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
void hvm_set_callback_via(struct domain *d, uint64_t via);
+void hvm_irq_raise(struct domain *d, unsigned int irq);
+void hvm_irq_lower(struct domain *d, unsigned int irq);
+
struct pirq;
bool hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq);
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 30/35] x86/hvm: add helpers for raising guest IRQs
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-12 16:18 ` Roger Pau Monné
2025-01-04 4:02 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-12 16:18 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:42:00PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Added convenience wrappers for asserting/de-asserting interrupts in the
> hardware emulation code.
>
> That will be used for PCI-based NS8250 emulator.
Strictly speaking the ns8250 uart should only generate ISA interrupts
as I understand it, as it only uses IRQs 3 and 4? IOW from that code
you should only need to use hvm_isa_irq_assert().
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/x86/hvm/irq.c | 24 ++++++++++++++++++++++++
> xen/arch/x86/include/asm/hvm/irq.h | 3 +++
> 2 files changed, 27 insertions(+)
>
> diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
> index 1eab44defca4c82ec35769617c66c380cc07d1b6..9e3a50d21dcf281c1015116094e47795c51ed5d0 100644
> --- a/xen/arch/x86/hvm/irq.c
> +++ b/xen/arch/x86/hvm/irq.c
> @@ -242,6 +242,30 @@ void hvm_isa_irq_deassert(
> spin_unlock(&d->arch.hvm.irq_lock);
> }
>
> +void hvm_irq_raise(struct domain *d, unsigned int irq)
> +{
> + if ( irq < NR_ISAIRQS )
> + {
> + hvm_isa_irq_assert(d, irq, NULL);
> + }
> + else
> + {
> + hvm_gsi_assert(d, irq);
> + }
> +}
> +
> +void hvm_irq_lower(struct domain *d, unsigned int irq)
It would be better to use the assert/deassert nomenclature, like it's
used for the functions that are called.
> +{
> + if ( irq < NR_ISAIRQS )
> + {
> + hvm_isa_irq_deassert(d, irq);
> + }
> + else
> + {
> + hvm_gsi_deassert(d, irq);
> + }
> +}
The parameter to thins function is kind of fuzzy, as I understand it,
if the parameter is < NR_ISAIRQS it's an ISA IRQ, while if it's >=
NR_ISAIRQS it's a GSI?
It would also be helpul to mention that hvm_isa_irq_deassert() will
already do the ISA IRQ -> GSI conversion in case there are any source
overrides.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 30/35] x86/hvm: add helpers for raising guest IRQs
2024-12-12 16:18 ` Roger Pau Monné
@ 2025-01-04 4:02 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:02 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thursday, December 12th, 2024 at 8:18 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:42:00PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Added convenience wrappers for asserting/de-asserting interrupts in the
> > hardware emulation code.
> >
> > That will be used for PCI-based NS8250 emulator.
>
>
> Strictly speaking the ns8250 uart should only generate ISA interrupts
> as I understand it, as it only uses IRQs 3 and 4? IOW from that code
> you should only need to use hvm_isa_irq_assert().
Correct, current code uses IRQ#3 and IRQ#4 only.
I dropped the patch from the series for now.
>
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/x86/hvm/irq.c | 24 ++++++++++++++++++++++++
> > xen/arch/x86/include/asm/hvm/irq.h | 3 +++
> > 2 files changed, 27 insertions(+)
> >
> > diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
> > index 1eab44defca4c82ec35769617c66c380cc07d1b6..9e3a50d21dcf281c1015116094e47795c51ed5d0 100644
> > --- a/xen/arch/x86/hvm/irq.c
> > +++ b/xen/arch/x86/hvm/irq.c
> > @@ -242,6 +242,30 @@ void hvm_isa_irq_deassert(
> > spin_unlock(&d->arch.hvm.irq_lock);
> > }
> >
> > +void hvm_irq_raise(struct domain *d, unsigned int irq)
> > +{
> > + if ( irq < NR_ISAIRQS )
> > + {
> > + hvm_isa_irq_assert(d, irq, NULL);
> > + }
> > + else
> > + {
> > + hvm_gsi_assert(d, irq);
> > + }
> > +}
> > +
> > +void hvm_irq_lower(struct domain *d, unsigned int irq)
>
>
> It would be better to use the assert/deassert nomenclature, like it's
> used for the functions that are called.
>
> > +{
> > + if ( irq < NR_ISAIRQS )
> > + {
> > + hvm_isa_irq_deassert(d, irq);
> > + }
> > + else
> > + {
> > + hvm_gsi_deassert(d, irq);
> > + }
> > +}
>
>
> The parameter to thins function is kind of fuzzy, as I understand it,
> if the parameter is < NR_ISAIRQS it's an ISA IRQ, while if it's >=
>
> NR_ISAIRQS it's a GSI?
Yes, agree, mixing two address spaces is at least confusing.
I dropped the patch from the series.
>
> It would also be helpul to mention that hvm_isa_irq_deassert() will
> already do the ISA IRQ -> GSI conversion in case there are any source
>
> overrides.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Add initial in-hypervisor emulator for NS8250/NS16x50-compatible UARTs under
CONFIG_HAS_VUART_NS8250.
In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
early guest OS bringup debugging, because it eliminates dependency on the
external emulator being operational by the time domains are created. Also,
there's no early console facility similar to vpl011 to support x86 guest OS
bring up.
By default, CONFIG_HAS_VUART_NS8250 enables emulatio of NS8250 at I/O port
0x3f8, IRQ#4 in guest OS.
Limitations:
- Only x86;
- Only Linux guest tested so far;
- Only legacy COM{1,2,3,4} resources, no customization;
- Only Xen console as a backend, no inter-domain communication (similar to
vpl011 on Arm);
- Only 8-bit characters;
- Baud rate is not emulated;
- FIFO-less mode is not emulated properly;
- RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
has special FCR handling;
- No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
friends);
- Assumes no ISA-device IRQ sharing;
- MMIO-based UART is not supported.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/hvm/Kconfig | 14 +
xen/arch/x86/hvm/Makefile | 1 +
xen/arch/x86/hvm/hvm.c | 13 +
xen/arch/x86/hvm/vuart_ns8250.c | 886 ++++++++++++++++++++++++++++
xen/arch/x86/include/asm/hvm/domain.h | 5 +
xen/arch/x86/include/asm/hvm/vuart_ns8250.h | 75 +++
6 files changed, 994 insertions(+)
diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
index 361bb6572e633f3cf0fc972a3b391e8341c33361..af6e698b8be0d82af94b00c0cfdaf9a2bc24b154 100644
--- a/xen/arch/x86/hvm/Kconfig
+++ b/xen/arch/x86/hvm/Kconfig
@@ -61,3 +61,17 @@ config HVM_FEP
for use in production.
If unsure, say N.
+
+config HAS_VUART_NS8250
+ bool "NS8250-compatible UART Emulation"
+ depends on HVM && HAS_IOPORTS
+ default n
+ help
+ In-hypervisor NS8250/NS16x50 UART emulation.
+
+ Only legacy PC I/O ports are emulated.
+
+ This is strictly for testing purposes (early HVM guest console), and not
+ appropriate for use in production.
+
+ If unsure, say N.
diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index 4c1fa5c6c2bf75d336b39f343241bfced5b91b09..14761435e0694109f815da63289666c0f1cbf0ce 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -29,3 +29,4 @@ obj-y += vm_event.o
obj-y += vmsi.o
obj-y += vpic.o
obj-y += vpt.o
+obj-$(CONFIG_HAS_VUART_NS8250) += vuart_ns8250.o
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 493b699c708949b2109c26573a107565543f5d45..db61af7defc5f5da795b7a613fe4d32fbff7d93e 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -55,6 +55,7 @@
#include <asm/hvm/monitor.h>
#include <asm/hvm/viridian.h>
#include <asm/hvm/vm_event.h>
+#include <asm/hvm/vuart_ns8250.h>
#include <asm/altp2m.h>
#include <asm/mtrr.h>
#include <asm/apic.h>
@@ -679,6 +680,15 @@ int hvm_domain_initialise(struct domain *d,
if ( rc != 0 )
goto fail1;
+ if ( domain_has_vuart(d) )
+ {
+ rc = domain_vuart_init(d);
+ if ( rc == 0 )
+ d->is_console = true;
+ else if ( rc != -ENODEV )
+ goto out_vioapic_deinit;
+ }
+
stdvga_init(d);
rtc_init(d);
@@ -699,6 +709,9 @@ int hvm_domain_initialise(struct domain *d,
return 0;
fail2:
+ if ( domain_has_vuart(d) )
+ domain_vuart_free(d);
+ out_vioapic_deinit:
vioapic_deinit(d);
fail1:
if ( is_hardware_domain(d) )
diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
new file mode 100644
index 0000000000000000000000000000000000000000..779dbd80d7be4e070ea9df3ae736ecdc662a527a
--- /dev/null
+++ b/xen/arch/x86/hvm/vuart_ns8250.c
@@ -0,0 +1,886 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * NS8250-compatible UART Emulator.
+ *
+ * Limitations:
+ * - Only x86;
+ * - Only Linux guest tested so far;
+ * - Only legacy COM{1,2,3,4} resources, no customization;
+ * - Only Xen console as a backend, no inter-domain communication (similar to
+ * vpl011 on Arm);
+ * - Only 8-bit characters;
+ * - Baud rate is not emulated;
+ * - FIFO-less mode is not emulated properly;
+ * - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
+ * has special FCR handling;
+ * - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
+ * friends);
+ * - Assumes no ISA-device IRQ sharing;
+ * - MMIO-based UART is not supported;
+ * - PCI UART is not supported.
+ */
+
+#define pr_fmt(fmt) "ns8250: " fmt
+#define pr_log_level hvm_ns8250_log_level
+
+/* Development debugging */
+#define NS8250_LOG_LEVEL 0
+
+#include <xen/types.h>
+#include <xen/event.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <xen/trace.h>
+#include <xen/resource.h>
+#include <xen/ctype.h>
+#include <xen/param.h>
+#include <xen/console.h> /* console_input_domid() */
+#include <asm/setup.h> /* max_init_domid */
+#include <asm/iocap.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/vuart_ns8250.h>
+
+#if !defined(pr_fmt)
+#define pr_fmt(fmt) fmt
+#endif
+
+#if !defined(pr_log_level)
+#define pr_log_level 0
+#endif
+
+#define pr_err(fmt, args...) \
+ gprintk(KERN_ERR, pr_fmt(fmt), ## args)
+#define pr_warn(fmt, args...) \
+ if (pr_log_level) gprintk(KERN_WARNING, pr_fmt(fmt), ## args)
+#define pr_info(fmt, args...) \
+ if (pr_log_level) gprintk(KERN_INFO, pr_fmt(fmt), ## args)
+#define pr_debug(fmt, args...) \
+ if (pr_log_level) gprintk(KERN_DEBUG, pr_fmt(fmt), ## args)
+
+/*
+ * NS8250 emulator state machine logging (development only)
+ * FIXME: use similar to parse_guest_loglvl()
+ */
+static unsigned int __read_mostly hvm_ns8250_log_level = NS8250_LOG_LEVEL;
+integer_param("hvm.ns8250.log_level", hvm_ns8250_log_level);
+
+/*
+ * Default emulated NS8250 resources.
+ * If not specified, COM1 (I/O port 0x3f8, IRQ#4) is emulated.
+ * FIXME: follow Linux'es console= syntax or re-use
+ * ns16550_parse_port_config().
+ */
+static char __read_mostly hvm_ns8250_console[64];
+string_param("hvm.ns8250.console", hvm_ns8250_console);
+
+/* I/O access mask */
+static const uint32_t io_access_mask[] = {
+ [0] = 0X00000000U,
+ [1] = 0X000000FFU,
+ [2] = 0X0000FFFFU,
+ [4] = 0XFFFFFFFFU,
+};
+
+/*
+ * Legacy IBM PC NS8250 resources.
+ * There are only 4 I/O port ranges, hardcoding all of them here.
+ */
+static const struct {
+ const char *name;
+ const struct resource *res;
+} ns8250_x86_legacy_uarts[4] = {
+ [0] = {
+ .name = "com1",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x3F8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+ [1] = {
+ .name = "com2",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x2F8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+ [2] = {
+ .name = "com3",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x3E8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+ [3] = {
+ .name = "com4",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x2E8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+};
+
+static bool ns8250_fifo_rx_empty(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ return cons->in_prod == cons->in_cons;
+}
+
+static bool ns8250_fifo_rx_full(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ return cons->in_prod - cons->in_cons == sizeof(cons->in);
+}
+
+static void ns8250_fifo_rx_reset(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ cons->in_cons = cons->in_prod;
+}
+
+static int ns8250_fifo_rx_getchar(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+ int rc = -1;
+
+ if ( !ns8250_fifo_rx_empty(vdev) )
+ {
+ rc = cons->in[MASK_XENCONS_IDX(cons->in_cons, cons->in)];
+ cons->in_cons++;
+ }
+
+ return rc;
+}
+
+static int ns8250_fifo_rx_putchar(struct vuart_ns8250 *vdev, char c)
+{
+ struct xencons_interface *cons = vdev->cons;
+ int rc = 0;
+
+ /*
+ * FIFO-less 8250/16450 UARTs: newly arrived word overwrites the contents
+ * of the THR.
+ */
+ if ( ns8250_fifo_rx_full(vdev) )
+ {
+ ns8250_fifo_rx_reset(vdev);
+ rc = -ENOSPC;
+ }
+
+ cons->in[MASK_XENCONS_IDX(cons->in_prod, cons->in)] = c;
+ cons->in_prod++;
+
+ return rc;
+}
+
+/*
+ * Flush cached output to Xen console.
+ * Can be called from ns8250_exit().
+ */
+static void ns8250_fifo_tx_reset(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ if ( cons->out_prod == 0 )
+ return;
+
+ cons->out[cons->out_prod++] = '\0';
+
+ /*
+ * NB: do not show domain ID if the domain owning the virtual UART also
+ * owns Xen input console.
+ */
+ if ( vdev->owner->domain_id == console_owner_domid() )
+ printk_common("%s", cons->out);
+ else
+ guest_printk(vdev->owner, "%s", cons->out);
+
+ cons->out_prod = 0;
+}
+
+/*
+ * Send a character to Xen console.
+ */
+static void ns8250_fifo_tx_putchar(struct vuart_ns8250 *vdev, char ch)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ if ( !isconsole(ch) )
+ return;
+
+ cons->out[cons->out_prod] = ch;
+ cons->out_prod++;
+
+ if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1
+ || ch == '\n' || ch == '\0' )
+ ns8250_fifo_tx_reset(vdev);
+}
+
+static bool cf_check ns8250_iir_check_lsi(struct vuart_ns8250 *vdev)
+{
+ return !!( vdev->regs[UART_LSR] & UART_LSR_MASK );
+}
+
+static bool cf_check ns8250_iir_check_rda(struct vuart_ns8250 *vdev)
+{
+ return !ns8250_fifo_rx_empty(vdev);
+}
+
+static bool cf_check ns8250_iir_check_thr(struct vuart_ns8250 *vdev)
+{
+ return !!( vdev->flags & NS8250_IRQ_THRE_PENDING );
+}
+
+static bool cf_check ns8250_iir_check_msi(struct vuart_ns8250 *vdev)
+{
+ return !!( vdev->regs[UART_MSR] & UART_MSR_DELTA );
+}
+
+/*
+ * Interrupt identity reasons by priority.
+ * NB: highest priority are at lower indexes.
+ */
+static const struct {
+ uint8_t ier_mask;
+ uint8_t iir_mask;
+ bool (*iir_check)(struct vuart_ns8250 *vdev);
+} iir_by_prio[] = {
+ [0] = { UART_IER_ELSI, UART_IIR_LSI, ns8250_iir_check_lsi },
+ [1] = { UART_IER_ERDAI, UART_IIR_RDA, ns8250_iir_check_rda },
+ [2] = { UART_IER_ETHREI, UART_IIR_THR, ns8250_iir_check_thr },
+ [3] = { UART_IER_EMSI, UART_IIR_MSI, ns8250_iir_check_msi },
+};
+
+/*
+ * Define the interrupt identity reason.
+ * NB: NS8250 always reports high priority events first.
+ */
+static uint8_t ns8250_irq_reason(struct vuart_ns8250 *vdev)
+{
+ int i;
+
+ ASSERT( spin_is_locked(&vdev->lock) );
+ for ( i = 0; i < ARRAY_SIZE(iir_by_prio); i++ )
+ {
+ if ( (vdev->regs[UART_IER] & iir_by_prio[i].ier_mask)
+ && iir_by_prio[i].iir_check(vdev) )
+ return iir_by_prio[i].iir_mask;
+ }
+
+ return UART_IIR_NOINT;
+}
+
+/*
+ * Assert virtual NS8250 interrupt line.
+ */
+static void ns8250_irq_assert(struct vuart_ns8250 *vdev)
+{
+ uint8_t iir;
+
+ iir = ns8250_irq_reason(vdev);
+ if (iir & UART_IIR_NOINT)
+ hvm_irq_lower(vdev->owner, vdev->irq);
+ else
+ hvm_irq_raise(vdev->owner, vdev->irq);
+
+ pr_debug("IRQ#%d %x %s\n", vdev->irq, iir,
+ !!(iir & UART_IIR_NOINT) ? "lower" : "raise");
+}
+
+/*
+ * Emulate 8-bit write access to NS8250 register.
+ */
+static int ns8250_io_write8(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
+{
+ uint8_t val;
+ int rc = 0;
+
+ val = *data;
+
+ switch ( reg )
+ {
+ /* DLAB=0 */
+ case UART_THR:
+ if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
+ {
+ ns8250_fifo_rx_putchar(vdev, val);
+ vdev->regs[UART_LSR] |= UART_LSR_OE;
+ }
+ else
+ ns8250_fifo_tx_putchar(vdev, val);
+
+ vdev->flags |= NS8250_IRQ_THRE_PENDING;
+
+ break;
+
+ case UART_IER:
+ if ( val & vdev->regs[UART_IER] & UART_IER_ETHREI )
+ vdev->flags |= NS8250_IRQ_THRE_PENDING;
+
+ vdev->regs[UART_IER] = val & UART_IER_MASK;
+
+ break;
+
+ case UART_FCR: /* WO */
+ if ( val & UART_FCR_CLRX )
+ ns8250_fifo_rx_reset(vdev);
+
+ if ( val & UART_FCR_CLTX )
+ ns8250_fifo_tx_reset(vdev);
+
+ if ( !(val & UART_FCR_ENABLE) )
+ val = 0;
+
+ vdev->regs[UART_FCR] = val & (UART_FCR_ENABLE |
+ UART_FCR_DMA |
+ UART_FCR_TRG_MASK);
+
+ break;
+
+ case UART_LCR:
+ vdev->regs[UART_LCR] = val;
+ break;
+
+ case UART_MCR: {
+ uint8_t msr_curr, msr_next, msr_delta;
+
+ msr_curr = vdev->regs[UART_MSR];
+ msr_next = 0;
+ msr_delta = 0;
+
+ /* Set modem status */
+ if ( val & UART_MCR_LOOP )
+ {
+ if ( val & UART_MCR_DTR )
+ msr_next |= UART_MSR_DSR;
+ if ( val & UART_MCR_RTS )
+ msr_next |= UART_MSR_CTS;
+ if ( val & UART_MCR_OUT1 )
+ msr_next |= UART_MSR_RI;
+ if ( val & UART_MCR_OUT2 )
+ msr_next |= UART_MSR_DCD;
+ }
+ else
+ msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
+
+ /* Calculate changes in modem status */
+ if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
+ msr_delta |= UART_MSR_DCTS;
+ if ( (msr_curr & UART_MCR_RTS) ^ (msr_next & UART_MCR_RTS) )
+ msr_delta |= UART_MSR_DDSR;
+ if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
+ msr_delta |= UART_MSR_TERI;
+ if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
+ msr_delta |= UART_MSR_DDCD;
+
+ vdev->regs[UART_MCR] = val & UART_MCR_MASK;
+ vdev->regs[UART_MSR] = msr_next | msr_delta;
+
+ break;
+ }
+
+ case UART_LSR: /* RO */
+ case UART_MSR: /* RO */
+ rc = -EINVAL;
+ break;
+
+ /*
+ * NB: Firmware like OVMF rely on SCR presence to initialize the ns8250
+ * driver.
+ */
+ case UART_SCR:
+ vdev->regs[UART_SCR] = val;
+ break;
+
+ /* DLAB=1 */
+ case UART_MAX + UART_DLL:
+ vdev->dl = (vdev->dl & 0xFF00U) | val;
+ break;
+
+ case UART_MAX + UART_DLM:
+ vdev->dl = (val << 8) | (vdev->dl & 0x00FFU);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Emulate 16-bit write access to NS8250 register.
+ * NB: some guest OSes use outw() to access UART_DLL.
+ */
+static int ns8250_io_write16(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
+{
+ int rc;
+
+ switch ( reg )
+ {
+ case UART_MAX + UART_DLL:
+ vdev->dl = *data;
+ rc = 0;
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Emulate write access to NS8250 register.
+ */
+static int ns8250_io_write(
+ struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
+{
+ int rc = -EINVAL;
+
+ switch ( size )
+ {
+ case 1:
+ rc = ns8250_io_write8(vdev, reg, (uint8_t *)data);
+ break;
+
+ case 2:
+ rc = ns8250_io_write16(vdev, reg, (uint16_t *)data);
+ break;
+
+ default:
+ break;
+ }
+
+ ns8250_irq_assert(vdev);
+
+ return rc;
+}
+
+/*
+ * Emulate 8-bit read access to NS8250 register.
+ */
+static int ns8250_io_read8(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
+{
+ int rc = 0;
+ uint8_t val;
+
+ switch ( reg )
+ {
+ /* DLAB=0 */
+ case UART_RBR:
+ val = (uint8_t)ns8250_fifo_rx_getchar(vdev);
+ /* NB: do not forget to clear overrun condition */
+ vdev->regs[UART_LSR] &= ~UART_LSR_OE;
+ break;
+
+ case UART_IER: /* RO */
+ val = vdev->regs[UART_IER];
+ break;
+
+ case UART_IIR:
+ val = ns8250_irq_reason(vdev);
+ if ( val & UART_IIR_THR )
+ vdev->flags &= ~NS8250_IRQ_THRE_PENDING;
+
+ if ( vdev->regs[UART_FCR] & UART_FCR_ENABLE )
+ val |= UART_IIR_FE_MASK;
+
+ break;
+
+ case UART_LCR:
+ val = vdev->regs[UART_LCR];
+ break;
+
+ case UART_MCR:
+ val = vdev->regs[UART_MCR];
+ break;
+
+ case UART_LSR:
+ val = vdev->regs[UART_LSR] | UART_LSR_THRE | UART_LSR_TEMT;
+ if ( ns8250_fifo_rx_empty(vdev) )
+ val &= ~UART_LSR_DR;
+ else
+ val |= UART_LSR_DR;
+
+ vdev->regs[UART_LSR] = val & ~UART_LSR_MASK;
+
+ break;
+
+ case UART_MSR:
+ val = vdev->regs[UART_MSR];
+ vdev->regs[UART_MSR] &= ~UART_MSR_DELTA;
+ break;
+
+ case UART_SCR:
+ val = vdev->regs[UART_SCR];
+ break;
+
+ /* DLAB=1 */
+ case UART_MAX + UART_DLL:
+ val = vdev->dl & 0xFFU;
+ break;
+
+ case UART_MAX + UART_DLM:
+ val = vdev->dl >> 8;
+ break;
+
+ default:
+ val = (uint8_t)io_access_mask[1];
+ rc = -EINVAL;
+ break;
+ }
+
+ *data = val;
+
+ return rc;
+}
+
+/*
+ * Emulate 16-bit read access to NS8250 register.
+ */
+static int ns8250_io_read16(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
+{
+ uint16_t val;
+ int rc;
+
+ switch ( reg )
+ {
+ case UART_MAX + UART_DLL:
+ val = vdev->dl;
+ rc = 0;
+ break;
+
+ default:
+ val = (uint16_t)io_access_mask[2];
+ rc = -EINVAL;
+ break;
+ }
+
+ *data = val;
+
+ return rc;
+}
+
+/*
+ * Emulate read access to NS8250 register.
+ */
+static int ns8250_io_read(
+ struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
+{
+ int rc;
+
+ switch ( size )
+ {
+ case 1:
+ rc = ns8250_io_read8(vdev, reg, (uint8_t *)data);
+ break;
+
+ case 2:
+ rc = ns8250_io_read16(vdev, reg, (uint16_t *)data);
+ break;
+
+ default:
+ *data = io_access_mask[size];
+ rc = -EINVAL;
+ break;
+ }
+
+ ns8250_irq_assert(vdev);
+
+ return rc;
+}
+
+static const char *ns8250_regname(
+ const struct vuart_ns8250 *vdev, uint32_t reg, int dir)
+{
+ static const char *reg_names[UART_MAX + 2][2] = {
+ /* register W R */
+ [UART_RBR] = { "THR", "RBR" },
+ [UART_IER] = { "IER", "IER" },
+ [UART_IIR] = { "FCR", "IIR" },
+ [UART_LCR] = { "LCR", "LCR" },
+ [UART_MCR] = { "MCR", "MCR" },
+ [UART_LSR] = { "LSR", "LSR" },
+ [UART_MSR] = { "MSR", "MSR" },
+ [UART_SCR] = { "SCR", "SCR" },
+ [UART_MAX + UART_DLL] = { "DLL", "DLL" },
+ [UART_MAX + UART_DLM] = { "DLM", "DLM" },
+ };
+
+ return reg_names[reg][dir];
+}
+
+/*
+ * Emulate I/O access to NS8250 register.
+ */
+static int cf_check ns8250_io_handle(
+ int dir, unsigned int addr, unsigned int size, uint32_t *data)
+{
+#define op(dir) (((dir) == IOREQ_WRITE) ? 'W' : 'R')
+ struct domain *d = rcu_lock_current_domain();
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+ uint32_t offset, reg;
+ int rc;
+
+ spin_lock(&vdev->lock);
+
+ BUG_ON( vdev->owner != d );
+
+ if ( !(vdev->flags & NS8250_READY) )
+ {
+ pr_err("%c io 0x%04x %d 0x%08"PRIx32": propagate to external I/O emulator\n",
+ op(dir), addr, size, *data);
+ rc = X86EMUL_UNHANDLEABLE;
+ goto out;
+ }
+
+ reg = addr - vdev->io_addr;
+ BUG_ON( reg >= UART_MAX );
+ if ( reg % size != 0 )
+ {
+ pr_err("%c 0x%04x %d 0x%08"PRIx32": unaligned access\n",
+ op(dir), addr, size, *data & io_access_mask[size]);
+ rc = X86EMUL_OKAY;
+ goto out;
+ }
+
+ /* Redirect access to divisor latch registers */
+ if ( !!(vdev->regs[UART_LCR] & UART_LCR_DLAB)
+ && (reg == UART_DLL || reg == UART_DLM) )
+ offset = UART_MAX + reg;
+ else
+ offset = reg;
+
+ if ( dir == IOREQ_WRITE )
+ {
+ pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
+ op(dir), addr, size,
+ *data & io_access_mask[size],
+ ns8250_regname(vdev, offset, dir), reg);
+ rc = ns8250_io_write(vdev, offset, size, data);
+ }
+ else
+ {
+ rc = ns8250_io_read(vdev, offset, size, data);
+ pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
+ op(dir), addr, size,
+ *data & io_access_mask[size],
+ ns8250_regname(vdev, offset, dir), reg);
+ }
+ if ( rc )
+ pr_err("%c 0x%04x %d 0x%08"PRIx32": unsupported access\n",
+ op(dir), addr, size, *data & io_access_mask[size]);
+ rc = X86EMUL_OKAY;
+
+out:
+ spin_unlock(&vdev->lock);
+
+ return rc;
+#undef op
+}
+
+/*
+ * Parse virtual NS8250 configuration.
+ * hvm.ns8250.console=[com1|com2|com3|com4]
+ */
+static const struct resource *ns8250_parse(void)
+{
+ int i;
+
+ for ( i = 0; i < ARRAY_SIZE(ns8250_x86_legacy_uarts); i++ )
+ if ( !strcasecmp(hvm_ns8250_console, ns8250_x86_legacy_uarts[i].name) )
+ return ns8250_x86_legacy_uarts[i].res;
+
+ return ns8250_x86_legacy_uarts[0].res;
+}
+
+/*
+ * Claim virtual NS8250 resources to domain.
+ */
+static int ns8250_claim(
+ struct vuart_ns8250 *vdev, const struct resource *r, struct domain *d)
+{
+ unsigned long size;
+ unsigned long start;
+ unsigned long end;
+
+ vdev->irq = NO_IRQ;
+ vdev->io_addr = IORESOURCE_UNKNOWN;
+ vdev->io_size = IORESOURCE_UNKNOWN;
+
+ foreach_resource(r)
+ {
+ if ( r->type & IORESOURCE_IO )
+ {
+ size = r->size;
+ start = r->addr;
+ end = r->addr + r->size - 1;
+
+ if ( !ioports_access_permitted(d, start, end) )
+ ioports_permit_access(d, start, end);
+
+ register_portio_handler(d, start, size, ns8250_io_handle);
+
+ /* Used to assert I/O port handler */
+ vdev->io_addr = start;
+ vdev->io_size = size;
+ }
+ else if ( r->type & IORESOURCE_IRQ )
+ /* "Claim" virtual IRQ; assumes no ISA-device IRQ sharing */
+ vdev->irq = r->addr;
+ else
+ return -EINVAL;
+ }
+
+ if ( vdev->irq == NO_IRQ
+ || vdev->io_addr == IORESOURCE_UNKNOWN
+ || vdev->io_size == IORESOURCE_UNKNOWN )
+ return -ENODEV;
+
+ return 0;
+}
+
+/*
+ * Unclaim virtual NS8250 resources.
+ */
+static void ns8250_unclaim(struct vuart_ns8250 *vdev, struct domain *d)
+{
+ unsigned long size = vdev->io_size;
+ unsigned long start = vdev->io_addr;
+ unsigned long end = start + size - 1;
+
+ if ( ioports_access_permitted(d, start, end) )
+ ioports_deny_access(d, start, size);
+}
+
+static int ns8250_init(struct domain *d, const struct resource *r)
+{
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+ struct xencons_interface *cons;
+ int rc;
+
+ cons = _xzalloc(sizeof(*vdev->cons), sizeof(void *));
+ if ( cons == NULL )
+ return -ENOMEM;
+
+ rc = ns8250_claim(vdev, r, d);
+ if ( rc )
+ {
+ xfree(cons);
+ return rc;
+ }
+
+ spin_lock_init(&vdev->lock);
+ hvm_irq_lower(d, vdev->irq);
+
+ vdev->dl = (UART_CLOCK_HZ / 115200) >> 4; /* Report 115200 baud rate */
+ vdev->cons = cons;
+ vdev->owner = d;
+ vdev->flags = NS8250_READY | NS8250_IRQ_THRE_PENDING;
+
+ return 0;
+}
+
+static void ns8250_exit(struct domain *d)
+{
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+
+ spin_lock(&vdev->lock);
+
+ if ( !(vdev->flags & NS8250_READY) )
+ goto out;
+
+ ns8250_unclaim(vdev, d);
+ ns8250_fifo_tx_reset(vdev);
+ xfree(vdev->cons);
+
+ vdev->cons = NULL;
+ vdev->owner = NULL;
+ vdev->flags = 0;
+
+out:
+ spin_unlock(&vdev->lock);
+}
+
+int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
+{
+ int rc;
+
+ spin_lock(&vdev->lock);
+
+ if ( !(vdev->flags & NS8250_READY) )
+ {
+ rc = -ENODEV;
+ goto out;
+ }
+
+ /* Echo the user input on the console */
+ printk("%c", ch);
+
+ /*
+ * Device is in loopback mode; do nothing.
+ */
+ if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
+ {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ rc = ns8250_fifo_rx_putchar(vdev, ch);
+ if ( rc == -ENOSPC )
+ vdev->regs[UART_LSR] |= UART_LSR_OE | UART_LSR_DR;
+ else
+ /* NB: UART_LSR_DR is also set when UART_LSR is accessed. */
+ vdev->regs[UART_LSR] |= UART_LSR_DR;
+
+ /* FIXME: check FCR when to fire an interrupt */
+ ns8250_irq_assert(vdev);
+
+out:
+ spin_unlock(&vdev->lock);
+
+ return rc;
+}
+
+int domain_vuart_init(struct domain *d)
+{
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+ const struct resource *r;
+
+ memset(vdev, 0, sizeof(*vdev));
+
+ r = ns8250_parse();
+ if ( r != NULL )
+ return ns8250_init(d, r);
+
+ return -ENODEV;
+}
+
+void domain_vuart_free(struct domain *d)
+{
+ ns8250_exit(d);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/include/asm/hvm/domain.h b/xen/arch/x86/include/asm/hvm/domain.h
index 333501d5f2ac01676646b9b277b551f06d43c3a5..d4ce25896259fc9763477e88d56bacbe4f78af5b 100644
--- a/xen/arch/x86/include/asm/hvm/domain.h
+++ b/xen/arch/x86/include/asm/hvm/domain.h
@@ -16,6 +16,7 @@
#include <asm/hvm/io.h>
#include <asm/hvm/vmx/vmcs.h>
#include <asm/hvm/svm/vmcb.h>
+#include <asm/hvm/vuart_ns8250.h>
#ifdef CONFIG_MEM_SHARING
struct mem_sharing_domain
@@ -73,6 +74,10 @@ struct hvm_domain {
struct hvm_vioapic **vioapic;
unsigned int nr_vioapics;
+#if defined(CONFIG_HAS_VUART_NS8250)
+ struct vuart_ns8250 vuart;
+#endif
+
/*
* hvm_hw_pmtimer is a publicly-visible name. We will defer renaming
* it to the more appropriate hvm_hw_acpi until the expected
diff --git a/xen/arch/x86/include/asm/hvm/vuart_ns8250.h b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1013751f955441a9089ea38c96c4605a7f4cb75
--- /dev/null
+++ b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * NS8250-compatible UART Emulator.
+ */
+#if !defined(HVM__VUART_NS8250_H)
+#define HVM__VUART_NS8250_H
+
+#include <xen/spinlock.h>
+#include <xen/8250-uart.h>
+#include <public/io/console.h> /* xencons_interface */
+
+/*
+ * NS8250 emulator operational flags.
+ */
+enum {
+ /* Emulator is ready */
+ NS8250_READY = BIT(0, U),
+ /* Trigger re-delivery of THRE interrupt */
+ NS8250_IRQ_THRE_PENDING = BIT(1, U),
+};
+
+/*
+ * Virtual NS8250 device state.
+ */
+struct vuart_ns8250 {
+ uint16_t dl; /* Divisor Latch */
+ uint8_t regs[UART_MAX]; /* Registers */
+ uint32_t flags; /* Virtual device flags */
+ uint64_t io_addr; /* Guest I/O region base address */
+ uint64_t io_size; /* Guest I/O region size */
+ int irq; /* Guest IRQ# */
+ struct xencons_interface *cons; /* Emulated RX/TX FIFOs */
+ struct domain *owner; /* Owner domain */
+ spinlock_t lock; /* Protection */
+};
+
+#if defined(CONFIG_HAS_VUART_NS8250)
+
+int vuart_putchar(struct vuart_ns8250 *vdev, char ch);
+
+/*
+ * Match the names w/ arch/arm/vuart.h
+ * FIXME: move to common vuart.h
+ */
+int domain_vuart_init(struct domain *d);
+void domain_vuart_free(struct domain *d);
+
+#else
+
+static inline int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
+{
+ return -1;
+}
+
+static inline int domain_vuart_init(struct domain *d)
+{
+ return -ENODEV;
+}
+
+static inline void domain_vuart_free(struct domain *d)
+{
+}
+
+#endif /* #if defined(CONFIG_HAS_VUART_NS8250) */
+
+#endif /* #if !defined(HVM__VUART_NS8250_H) */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Add initial in-hypervisor emulator for NS8250/NS16x50-compatible UARTs under
CONFIG_HAS_VUART_NS8250.
In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
early guest OS bringup debugging, because it eliminates dependency on the
external emulator being operational by the time domains are created. Also,
there's no early console facility similar to vpl011 to support x86 guest OS
bring up.
By default, CONFIG_HAS_VUART_NS8250 enables emulatio of NS8250 at I/O port
0x3f8, IRQ#4 in guest OS.
Limitations:
- Only x86;
- Only Linux guest tested so far;
- Only legacy COM{1,2,3,4} resources, no customization;
- Only Xen console as a backend, no inter-domain communication (similar to
vpl011 on Arm);
- Only 8-bit characters;
- Baud rate is not emulated;
- FIFO-less mode is not emulated properly;
- RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
has special FCR handling;
- No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
friends);
- Assumes no ISA-device IRQ sharing;
- MMIO-based UART is not supported.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/hvm/Kconfig | 14 +
xen/arch/x86/hvm/Makefile | 1 +
xen/arch/x86/hvm/hvm.c | 13 +
xen/arch/x86/hvm/vuart_ns8250.c | 886 ++++++++++++++++++++++++++++
xen/arch/x86/include/asm/hvm/domain.h | 5 +
xen/arch/x86/include/asm/hvm/vuart_ns8250.h | 75 +++
6 files changed, 994 insertions(+)
diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
index 361bb6572e633f3cf0fc972a3b391e8341c33361..af6e698b8be0d82af94b00c0cfdaf9a2bc24b154 100644
--- a/xen/arch/x86/hvm/Kconfig
+++ b/xen/arch/x86/hvm/Kconfig
@@ -61,3 +61,17 @@ config HVM_FEP
for use in production.
If unsure, say N.
+
+config HAS_VUART_NS8250
+ bool "NS8250-compatible UART Emulation"
+ depends on HVM && HAS_IOPORTS
+ default n
+ help
+ In-hypervisor NS8250/NS16x50 UART emulation.
+
+ Only legacy PC I/O ports are emulated.
+
+ This is strictly for testing purposes (early HVM guest console), and not
+ appropriate for use in production.
+
+ If unsure, say N.
diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index 4c1fa5c6c2bf75d336b39f343241bfced5b91b09..14761435e0694109f815da63289666c0f1cbf0ce 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -29,3 +29,4 @@ obj-y += vm_event.o
obj-y += vmsi.o
obj-y += vpic.o
obj-y += vpt.o
+obj-$(CONFIG_HAS_VUART_NS8250) += vuart_ns8250.o
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 493b699c708949b2109c26573a107565543f5d45..db61af7defc5f5da795b7a613fe4d32fbff7d93e 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -55,6 +55,7 @@
#include <asm/hvm/monitor.h>
#include <asm/hvm/viridian.h>
#include <asm/hvm/vm_event.h>
+#include <asm/hvm/vuart_ns8250.h>
#include <asm/altp2m.h>
#include <asm/mtrr.h>
#include <asm/apic.h>
@@ -679,6 +680,15 @@ int hvm_domain_initialise(struct domain *d,
if ( rc != 0 )
goto fail1;
+ if ( domain_has_vuart(d) )
+ {
+ rc = domain_vuart_init(d);
+ if ( rc == 0 )
+ d->is_console = true;
+ else if ( rc != -ENODEV )
+ goto out_vioapic_deinit;
+ }
+
stdvga_init(d);
rtc_init(d);
@@ -699,6 +709,9 @@ int hvm_domain_initialise(struct domain *d,
return 0;
fail2:
+ if ( domain_has_vuart(d) )
+ domain_vuart_free(d);
+ out_vioapic_deinit:
vioapic_deinit(d);
fail1:
if ( is_hardware_domain(d) )
diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
new file mode 100644
index 0000000000000000000000000000000000000000..779dbd80d7be4e070ea9df3ae736ecdc662a527a
--- /dev/null
+++ b/xen/arch/x86/hvm/vuart_ns8250.c
@@ -0,0 +1,886 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * NS8250-compatible UART Emulator.
+ *
+ * Limitations:
+ * - Only x86;
+ * - Only Linux guest tested so far;
+ * - Only legacy COM{1,2,3,4} resources, no customization;
+ * - Only Xen console as a backend, no inter-domain communication (similar to
+ * vpl011 on Arm);
+ * - Only 8-bit characters;
+ * - Baud rate is not emulated;
+ * - FIFO-less mode is not emulated properly;
+ * - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
+ * has special FCR handling;
+ * - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
+ * friends);
+ * - Assumes no ISA-device IRQ sharing;
+ * - MMIO-based UART is not supported;
+ * - PCI UART is not supported.
+ */
+
+#define pr_fmt(fmt) "ns8250: " fmt
+#define pr_log_level hvm_ns8250_log_level
+
+/* Development debugging */
+#define NS8250_LOG_LEVEL 0
+
+#include <xen/types.h>
+#include <xen/event.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <xen/trace.h>
+#include <xen/resource.h>
+#include <xen/ctype.h>
+#include <xen/param.h>
+#include <xen/console.h> /* console_input_domid() */
+#include <asm/setup.h> /* max_init_domid */
+#include <asm/iocap.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/vuart_ns8250.h>
+
+#if !defined(pr_fmt)
+#define pr_fmt(fmt) fmt
+#endif
+
+#if !defined(pr_log_level)
+#define pr_log_level 0
+#endif
+
+#define pr_err(fmt, args...) \
+ gprintk(KERN_ERR, pr_fmt(fmt), ## args)
+#define pr_warn(fmt, args...) \
+ if (pr_log_level) gprintk(KERN_WARNING, pr_fmt(fmt), ## args)
+#define pr_info(fmt, args...) \
+ if (pr_log_level) gprintk(KERN_INFO, pr_fmt(fmt), ## args)
+#define pr_debug(fmt, args...) \
+ if (pr_log_level) gprintk(KERN_DEBUG, pr_fmt(fmt), ## args)
+
+/*
+ * NS8250 emulator state machine logging (development only)
+ * FIXME: use similar to parse_guest_loglvl()
+ */
+static unsigned int __read_mostly hvm_ns8250_log_level = NS8250_LOG_LEVEL;
+integer_param("hvm.ns8250.log_level", hvm_ns8250_log_level);
+
+/*
+ * Default emulated NS8250 resources.
+ * If not specified, COM1 (I/O port 0x3f8, IRQ#4) is emulated.
+ * FIXME: follow Linux'es console= syntax or re-use
+ * ns16550_parse_port_config().
+ */
+static char __read_mostly hvm_ns8250_console[64];
+string_param("hvm.ns8250.console", hvm_ns8250_console);
+
+/* I/O access mask */
+static const uint32_t io_access_mask[] = {
+ [0] = 0X00000000U,
+ [1] = 0X000000FFU,
+ [2] = 0X0000FFFFU,
+ [4] = 0XFFFFFFFFU,
+};
+
+/*
+ * Legacy IBM PC NS8250 resources.
+ * There are only 4 I/O port ranges, hardcoding all of them here.
+ */
+static const struct {
+ const char *name;
+ const struct resource *res;
+} ns8250_x86_legacy_uarts[4] = {
+ [0] = {
+ .name = "com1",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x3F8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+ [1] = {
+ .name = "com2",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x2F8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+ [2] = {
+ .name = "com3",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x3E8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+ [3] = {
+ .name = "com4",
+ .res = (const struct resource[]){
+ { .type = IORESOURCE_IO, .addr = 0x2E8, .size = UART_MAX },
+ { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
+ { .type = IORESOURCE_UNKNOWN },
+ },
+ },
+};
+
+static bool ns8250_fifo_rx_empty(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ return cons->in_prod == cons->in_cons;
+}
+
+static bool ns8250_fifo_rx_full(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ return cons->in_prod - cons->in_cons == sizeof(cons->in);
+}
+
+static void ns8250_fifo_rx_reset(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ cons->in_cons = cons->in_prod;
+}
+
+static int ns8250_fifo_rx_getchar(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+ int rc = -1;
+
+ if ( !ns8250_fifo_rx_empty(vdev) )
+ {
+ rc = cons->in[MASK_XENCONS_IDX(cons->in_cons, cons->in)];
+ cons->in_cons++;
+ }
+
+ return rc;
+}
+
+static int ns8250_fifo_rx_putchar(struct vuart_ns8250 *vdev, char c)
+{
+ struct xencons_interface *cons = vdev->cons;
+ int rc = 0;
+
+ /*
+ * FIFO-less 8250/16450 UARTs: newly arrived word overwrites the contents
+ * of the THR.
+ */
+ if ( ns8250_fifo_rx_full(vdev) )
+ {
+ ns8250_fifo_rx_reset(vdev);
+ rc = -ENOSPC;
+ }
+
+ cons->in[MASK_XENCONS_IDX(cons->in_prod, cons->in)] = c;
+ cons->in_prod++;
+
+ return rc;
+}
+
+/*
+ * Flush cached output to Xen console.
+ * Can be called from ns8250_exit().
+ */
+static void ns8250_fifo_tx_reset(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ if ( cons->out_prod == 0 )
+ return;
+
+ cons->out[cons->out_prod++] = '\0';
+
+ /*
+ * NB: do not show domain ID if the domain owning the virtual UART also
+ * owns Xen input console.
+ */
+ if ( vdev->owner->domain_id == console_owner_domid() )
+ printk_common("%s", cons->out);
+ else
+ guest_printk(vdev->owner, "%s", cons->out);
+
+ cons->out_prod = 0;
+}
+
+/*
+ * Send a character to Xen console.
+ */
+static void ns8250_fifo_tx_putchar(struct vuart_ns8250 *vdev, char ch)
+{
+ struct xencons_interface *cons = vdev->cons;
+
+ if ( !isconsole(ch) )
+ return;
+
+ cons->out[cons->out_prod] = ch;
+ cons->out_prod++;
+
+ if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1
+ || ch == '\n' || ch == '\0' )
+ ns8250_fifo_tx_reset(vdev);
+}
+
+static bool cf_check ns8250_iir_check_lsi(struct vuart_ns8250 *vdev)
+{
+ return !!( vdev->regs[UART_LSR] & UART_LSR_MASK );
+}
+
+static bool cf_check ns8250_iir_check_rda(struct vuart_ns8250 *vdev)
+{
+ return !ns8250_fifo_rx_empty(vdev);
+}
+
+static bool cf_check ns8250_iir_check_thr(struct vuart_ns8250 *vdev)
+{
+ return !!( vdev->flags & NS8250_IRQ_THRE_PENDING );
+}
+
+static bool cf_check ns8250_iir_check_msi(struct vuart_ns8250 *vdev)
+{
+ return !!( vdev->regs[UART_MSR] & UART_MSR_DELTA );
+}
+
+/*
+ * Interrupt identity reasons by priority.
+ * NB: highest priority are at lower indexes.
+ */
+static const struct {
+ uint8_t ier_mask;
+ uint8_t iir_mask;
+ bool (*iir_check)(struct vuart_ns8250 *vdev);
+} iir_by_prio[] = {
+ [0] = { UART_IER_ELSI, UART_IIR_LSI, ns8250_iir_check_lsi },
+ [1] = { UART_IER_ERDAI, UART_IIR_RDA, ns8250_iir_check_rda },
+ [2] = { UART_IER_ETHREI, UART_IIR_THR, ns8250_iir_check_thr },
+ [3] = { UART_IER_EMSI, UART_IIR_MSI, ns8250_iir_check_msi },
+};
+
+/*
+ * Define the interrupt identity reason.
+ * NB: NS8250 always reports high priority events first.
+ */
+static uint8_t ns8250_irq_reason(struct vuart_ns8250 *vdev)
+{
+ int i;
+
+ ASSERT( spin_is_locked(&vdev->lock) );
+ for ( i = 0; i < ARRAY_SIZE(iir_by_prio); i++ )
+ {
+ if ( (vdev->regs[UART_IER] & iir_by_prio[i].ier_mask)
+ && iir_by_prio[i].iir_check(vdev) )
+ return iir_by_prio[i].iir_mask;
+ }
+
+ return UART_IIR_NOINT;
+}
+
+/*
+ * Assert virtual NS8250 interrupt line.
+ */
+static void ns8250_irq_assert(struct vuart_ns8250 *vdev)
+{
+ uint8_t iir;
+
+ iir = ns8250_irq_reason(vdev);
+ if (iir & UART_IIR_NOINT)
+ hvm_irq_lower(vdev->owner, vdev->irq);
+ else
+ hvm_irq_raise(vdev->owner, vdev->irq);
+
+ pr_debug("IRQ#%d %x %s\n", vdev->irq, iir,
+ !!(iir & UART_IIR_NOINT) ? "lower" : "raise");
+}
+
+/*
+ * Emulate 8-bit write access to NS8250 register.
+ */
+static int ns8250_io_write8(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
+{
+ uint8_t val;
+ int rc = 0;
+
+ val = *data;
+
+ switch ( reg )
+ {
+ /* DLAB=0 */
+ case UART_THR:
+ if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
+ {
+ ns8250_fifo_rx_putchar(vdev, val);
+ vdev->regs[UART_LSR] |= UART_LSR_OE;
+ }
+ else
+ ns8250_fifo_tx_putchar(vdev, val);
+
+ vdev->flags |= NS8250_IRQ_THRE_PENDING;
+
+ break;
+
+ case UART_IER:
+ if ( val & vdev->regs[UART_IER] & UART_IER_ETHREI )
+ vdev->flags |= NS8250_IRQ_THRE_PENDING;
+
+ vdev->regs[UART_IER] = val & UART_IER_MASK;
+
+ break;
+
+ case UART_FCR: /* WO */
+ if ( val & UART_FCR_CLRX )
+ ns8250_fifo_rx_reset(vdev);
+
+ if ( val & UART_FCR_CLTX )
+ ns8250_fifo_tx_reset(vdev);
+
+ if ( !(val & UART_FCR_ENABLE) )
+ val = 0;
+
+ vdev->regs[UART_FCR] = val & (UART_FCR_ENABLE |
+ UART_FCR_DMA |
+ UART_FCR_TRG_MASK);
+
+ break;
+
+ case UART_LCR:
+ vdev->regs[UART_LCR] = val;
+ break;
+
+ case UART_MCR: {
+ uint8_t msr_curr, msr_next, msr_delta;
+
+ msr_curr = vdev->regs[UART_MSR];
+ msr_next = 0;
+ msr_delta = 0;
+
+ /* Set modem status */
+ if ( val & UART_MCR_LOOP )
+ {
+ if ( val & UART_MCR_DTR )
+ msr_next |= UART_MSR_DSR;
+ if ( val & UART_MCR_RTS )
+ msr_next |= UART_MSR_CTS;
+ if ( val & UART_MCR_OUT1 )
+ msr_next |= UART_MSR_RI;
+ if ( val & UART_MCR_OUT2 )
+ msr_next |= UART_MSR_DCD;
+ }
+ else
+ msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
+
+ /* Calculate changes in modem status */
+ if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
+ msr_delta |= UART_MSR_DCTS;
+ if ( (msr_curr & UART_MCR_RTS) ^ (msr_next & UART_MCR_RTS) )
+ msr_delta |= UART_MSR_DDSR;
+ if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
+ msr_delta |= UART_MSR_TERI;
+ if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
+ msr_delta |= UART_MSR_DDCD;
+
+ vdev->regs[UART_MCR] = val & UART_MCR_MASK;
+ vdev->regs[UART_MSR] = msr_next | msr_delta;
+
+ break;
+ }
+
+ case UART_LSR: /* RO */
+ case UART_MSR: /* RO */
+ rc = -EINVAL;
+ break;
+
+ /*
+ * NB: Firmware like OVMF rely on SCR presence to initialize the ns8250
+ * driver.
+ */
+ case UART_SCR:
+ vdev->regs[UART_SCR] = val;
+ break;
+
+ /* DLAB=1 */
+ case UART_MAX + UART_DLL:
+ vdev->dl = (vdev->dl & 0xFF00U) | val;
+ break;
+
+ case UART_MAX + UART_DLM:
+ vdev->dl = (val << 8) | (vdev->dl & 0x00FFU);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Emulate 16-bit write access to NS8250 register.
+ * NB: some guest OSes use outw() to access UART_DLL.
+ */
+static int ns8250_io_write16(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
+{
+ int rc;
+
+ switch ( reg )
+ {
+ case UART_MAX + UART_DLL:
+ vdev->dl = *data;
+ rc = 0;
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Emulate write access to NS8250 register.
+ */
+static int ns8250_io_write(
+ struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
+{
+ int rc = -EINVAL;
+
+ switch ( size )
+ {
+ case 1:
+ rc = ns8250_io_write8(vdev, reg, (uint8_t *)data);
+ break;
+
+ case 2:
+ rc = ns8250_io_write16(vdev, reg, (uint16_t *)data);
+ break;
+
+ default:
+ break;
+ }
+
+ ns8250_irq_assert(vdev);
+
+ return rc;
+}
+
+/*
+ * Emulate 8-bit read access to NS8250 register.
+ */
+static int ns8250_io_read8(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
+{
+ int rc = 0;
+ uint8_t val;
+
+ switch ( reg )
+ {
+ /* DLAB=0 */
+ case UART_RBR:
+ val = (uint8_t)ns8250_fifo_rx_getchar(vdev);
+ /* NB: do not forget to clear overrun condition */
+ vdev->regs[UART_LSR] &= ~UART_LSR_OE;
+ break;
+
+ case UART_IER: /* RO */
+ val = vdev->regs[UART_IER];
+ break;
+
+ case UART_IIR:
+ val = ns8250_irq_reason(vdev);
+ if ( val & UART_IIR_THR )
+ vdev->flags &= ~NS8250_IRQ_THRE_PENDING;
+
+ if ( vdev->regs[UART_FCR] & UART_FCR_ENABLE )
+ val |= UART_IIR_FE_MASK;
+
+ break;
+
+ case UART_LCR:
+ val = vdev->regs[UART_LCR];
+ break;
+
+ case UART_MCR:
+ val = vdev->regs[UART_MCR];
+ break;
+
+ case UART_LSR:
+ val = vdev->regs[UART_LSR] | UART_LSR_THRE | UART_LSR_TEMT;
+ if ( ns8250_fifo_rx_empty(vdev) )
+ val &= ~UART_LSR_DR;
+ else
+ val |= UART_LSR_DR;
+
+ vdev->regs[UART_LSR] = val & ~UART_LSR_MASK;
+
+ break;
+
+ case UART_MSR:
+ val = vdev->regs[UART_MSR];
+ vdev->regs[UART_MSR] &= ~UART_MSR_DELTA;
+ break;
+
+ case UART_SCR:
+ val = vdev->regs[UART_SCR];
+ break;
+
+ /* DLAB=1 */
+ case UART_MAX + UART_DLL:
+ val = vdev->dl & 0xFFU;
+ break;
+
+ case UART_MAX + UART_DLM:
+ val = vdev->dl >> 8;
+ break;
+
+ default:
+ val = (uint8_t)io_access_mask[1];
+ rc = -EINVAL;
+ break;
+ }
+
+ *data = val;
+
+ return rc;
+}
+
+/*
+ * Emulate 16-bit read access to NS8250 register.
+ */
+static int ns8250_io_read16(
+ struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
+{
+ uint16_t val;
+ int rc;
+
+ switch ( reg )
+ {
+ case UART_MAX + UART_DLL:
+ val = vdev->dl;
+ rc = 0;
+ break;
+
+ default:
+ val = (uint16_t)io_access_mask[2];
+ rc = -EINVAL;
+ break;
+ }
+
+ *data = val;
+
+ return rc;
+}
+
+/*
+ * Emulate read access to NS8250 register.
+ */
+static int ns8250_io_read(
+ struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
+{
+ int rc;
+
+ switch ( size )
+ {
+ case 1:
+ rc = ns8250_io_read8(vdev, reg, (uint8_t *)data);
+ break;
+
+ case 2:
+ rc = ns8250_io_read16(vdev, reg, (uint16_t *)data);
+ break;
+
+ default:
+ *data = io_access_mask[size];
+ rc = -EINVAL;
+ break;
+ }
+
+ ns8250_irq_assert(vdev);
+
+ return rc;
+}
+
+static const char *ns8250_regname(
+ const struct vuart_ns8250 *vdev, uint32_t reg, int dir)
+{
+ static const char *reg_names[UART_MAX + 2][2] = {
+ /* register W R */
+ [UART_RBR] = { "THR", "RBR" },
+ [UART_IER] = { "IER", "IER" },
+ [UART_IIR] = { "FCR", "IIR" },
+ [UART_LCR] = { "LCR", "LCR" },
+ [UART_MCR] = { "MCR", "MCR" },
+ [UART_LSR] = { "LSR", "LSR" },
+ [UART_MSR] = { "MSR", "MSR" },
+ [UART_SCR] = { "SCR", "SCR" },
+ [UART_MAX + UART_DLL] = { "DLL", "DLL" },
+ [UART_MAX + UART_DLM] = { "DLM", "DLM" },
+ };
+
+ return reg_names[reg][dir];
+}
+
+/*
+ * Emulate I/O access to NS8250 register.
+ */
+static int cf_check ns8250_io_handle(
+ int dir, unsigned int addr, unsigned int size, uint32_t *data)
+{
+#define op(dir) (((dir) == IOREQ_WRITE) ? 'W' : 'R')
+ struct domain *d = rcu_lock_current_domain();
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+ uint32_t offset, reg;
+ int rc;
+
+ spin_lock(&vdev->lock);
+
+ BUG_ON( vdev->owner != d );
+
+ if ( !(vdev->flags & NS8250_READY) )
+ {
+ pr_err("%c io 0x%04x %d 0x%08"PRIx32": propagate to external I/O emulator\n",
+ op(dir), addr, size, *data);
+ rc = X86EMUL_UNHANDLEABLE;
+ goto out;
+ }
+
+ reg = addr - vdev->io_addr;
+ BUG_ON( reg >= UART_MAX );
+ if ( reg % size != 0 )
+ {
+ pr_err("%c 0x%04x %d 0x%08"PRIx32": unaligned access\n",
+ op(dir), addr, size, *data & io_access_mask[size]);
+ rc = X86EMUL_OKAY;
+ goto out;
+ }
+
+ /* Redirect access to divisor latch registers */
+ if ( !!(vdev->regs[UART_LCR] & UART_LCR_DLAB)
+ && (reg == UART_DLL || reg == UART_DLM) )
+ offset = UART_MAX + reg;
+ else
+ offset = reg;
+
+ if ( dir == IOREQ_WRITE )
+ {
+ pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
+ op(dir), addr, size,
+ *data & io_access_mask[size],
+ ns8250_regname(vdev, offset, dir), reg);
+ rc = ns8250_io_write(vdev, offset, size, data);
+ }
+ else
+ {
+ rc = ns8250_io_read(vdev, offset, size, data);
+ pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
+ op(dir), addr, size,
+ *data & io_access_mask[size],
+ ns8250_regname(vdev, offset, dir), reg);
+ }
+ if ( rc )
+ pr_err("%c 0x%04x %d 0x%08"PRIx32": unsupported access\n",
+ op(dir), addr, size, *data & io_access_mask[size]);
+ rc = X86EMUL_OKAY;
+
+out:
+ spin_unlock(&vdev->lock);
+
+ return rc;
+#undef op
+}
+
+/*
+ * Parse virtual NS8250 configuration.
+ * hvm.ns8250.console=[com1|com2|com3|com4]
+ */
+static const struct resource *ns8250_parse(void)
+{
+ int i;
+
+ for ( i = 0; i < ARRAY_SIZE(ns8250_x86_legacy_uarts); i++ )
+ if ( !strcasecmp(hvm_ns8250_console, ns8250_x86_legacy_uarts[i].name) )
+ return ns8250_x86_legacy_uarts[i].res;
+
+ return ns8250_x86_legacy_uarts[0].res;
+}
+
+/*
+ * Claim virtual NS8250 resources to domain.
+ */
+static int ns8250_claim(
+ struct vuart_ns8250 *vdev, const struct resource *r, struct domain *d)
+{
+ unsigned long size;
+ unsigned long start;
+ unsigned long end;
+
+ vdev->irq = NO_IRQ;
+ vdev->io_addr = IORESOURCE_UNKNOWN;
+ vdev->io_size = IORESOURCE_UNKNOWN;
+
+ foreach_resource(r)
+ {
+ if ( r->type & IORESOURCE_IO )
+ {
+ size = r->size;
+ start = r->addr;
+ end = r->addr + r->size - 1;
+
+ if ( !ioports_access_permitted(d, start, end) )
+ ioports_permit_access(d, start, end);
+
+ register_portio_handler(d, start, size, ns8250_io_handle);
+
+ /* Used to assert I/O port handler */
+ vdev->io_addr = start;
+ vdev->io_size = size;
+ }
+ else if ( r->type & IORESOURCE_IRQ )
+ /* "Claim" virtual IRQ; assumes no ISA-device IRQ sharing */
+ vdev->irq = r->addr;
+ else
+ return -EINVAL;
+ }
+
+ if ( vdev->irq == NO_IRQ
+ || vdev->io_addr == IORESOURCE_UNKNOWN
+ || vdev->io_size == IORESOURCE_UNKNOWN )
+ return -ENODEV;
+
+ return 0;
+}
+
+/*
+ * Unclaim virtual NS8250 resources.
+ */
+static void ns8250_unclaim(struct vuart_ns8250 *vdev, struct domain *d)
+{
+ unsigned long size = vdev->io_size;
+ unsigned long start = vdev->io_addr;
+ unsigned long end = start + size - 1;
+
+ if ( ioports_access_permitted(d, start, end) )
+ ioports_deny_access(d, start, size);
+}
+
+static int ns8250_init(struct domain *d, const struct resource *r)
+{
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+ struct xencons_interface *cons;
+ int rc;
+
+ cons = _xzalloc(sizeof(*vdev->cons), sizeof(void *));
+ if ( cons == NULL )
+ return -ENOMEM;
+
+ rc = ns8250_claim(vdev, r, d);
+ if ( rc )
+ {
+ xfree(cons);
+ return rc;
+ }
+
+ spin_lock_init(&vdev->lock);
+ hvm_irq_lower(d, vdev->irq);
+
+ vdev->dl = (UART_CLOCK_HZ / 115200) >> 4; /* Report 115200 baud rate */
+ vdev->cons = cons;
+ vdev->owner = d;
+ vdev->flags = NS8250_READY | NS8250_IRQ_THRE_PENDING;
+
+ return 0;
+}
+
+static void ns8250_exit(struct domain *d)
+{
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+
+ spin_lock(&vdev->lock);
+
+ if ( !(vdev->flags & NS8250_READY) )
+ goto out;
+
+ ns8250_unclaim(vdev, d);
+ ns8250_fifo_tx_reset(vdev);
+ xfree(vdev->cons);
+
+ vdev->cons = NULL;
+ vdev->owner = NULL;
+ vdev->flags = 0;
+
+out:
+ spin_unlock(&vdev->lock);
+}
+
+int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
+{
+ int rc;
+
+ spin_lock(&vdev->lock);
+
+ if ( !(vdev->flags & NS8250_READY) )
+ {
+ rc = -ENODEV;
+ goto out;
+ }
+
+ /* Echo the user input on the console */
+ printk("%c", ch);
+
+ /*
+ * Device is in loopback mode; do nothing.
+ */
+ if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
+ {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ rc = ns8250_fifo_rx_putchar(vdev, ch);
+ if ( rc == -ENOSPC )
+ vdev->regs[UART_LSR] |= UART_LSR_OE | UART_LSR_DR;
+ else
+ /* NB: UART_LSR_DR is also set when UART_LSR is accessed. */
+ vdev->regs[UART_LSR] |= UART_LSR_DR;
+
+ /* FIXME: check FCR when to fire an interrupt */
+ ns8250_irq_assert(vdev);
+
+out:
+ spin_unlock(&vdev->lock);
+
+ return rc;
+}
+
+int domain_vuart_init(struct domain *d)
+{
+ struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
+ const struct resource *r;
+
+ memset(vdev, 0, sizeof(*vdev));
+
+ r = ns8250_parse();
+ if ( r != NULL )
+ return ns8250_init(d, r);
+
+ return -ENODEV;
+}
+
+void domain_vuart_free(struct domain *d)
+{
+ ns8250_exit(d);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/include/asm/hvm/domain.h b/xen/arch/x86/include/asm/hvm/domain.h
index 333501d5f2ac01676646b9b277b551f06d43c3a5..d4ce25896259fc9763477e88d56bacbe4f78af5b 100644
--- a/xen/arch/x86/include/asm/hvm/domain.h
+++ b/xen/arch/x86/include/asm/hvm/domain.h
@@ -16,6 +16,7 @@
#include <asm/hvm/io.h>
#include <asm/hvm/vmx/vmcs.h>
#include <asm/hvm/svm/vmcb.h>
+#include <asm/hvm/vuart_ns8250.h>
#ifdef CONFIG_MEM_SHARING
struct mem_sharing_domain
@@ -73,6 +74,10 @@ struct hvm_domain {
struct hvm_vioapic **vioapic;
unsigned int nr_vioapics;
+#if defined(CONFIG_HAS_VUART_NS8250)
+ struct vuart_ns8250 vuart;
+#endif
+
/*
* hvm_hw_pmtimer is a publicly-visible name. We will defer renaming
* it to the more appropriate hvm_hw_acpi until the expected
diff --git a/xen/arch/x86/include/asm/hvm/vuart_ns8250.h b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1013751f955441a9089ea38c96c4605a7f4cb75
--- /dev/null
+++ b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * NS8250-compatible UART Emulator.
+ */
+#if !defined(HVM__VUART_NS8250_H)
+#define HVM__VUART_NS8250_H
+
+#include <xen/spinlock.h>
+#include <xen/8250-uart.h>
+#include <public/io/console.h> /* xencons_interface */
+
+/*
+ * NS8250 emulator operational flags.
+ */
+enum {
+ /* Emulator is ready */
+ NS8250_READY = BIT(0, U),
+ /* Trigger re-delivery of THRE interrupt */
+ NS8250_IRQ_THRE_PENDING = BIT(1, U),
+};
+
+/*
+ * Virtual NS8250 device state.
+ */
+struct vuart_ns8250 {
+ uint16_t dl; /* Divisor Latch */
+ uint8_t regs[UART_MAX]; /* Registers */
+ uint32_t flags; /* Virtual device flags */
+ uint64_t io_addr; /* Guest I/O region base address */
+ uint64_t io_size; /* Guest I/O region size */
+ int irq; /* Guest IRQ# */
+ struct xencons_interface *cons; /* Emulated RX/TX FIFOs */
+ struct domain *owner; /* Owner domain */
+ spinlock_t lock; /* Protection */
+};
+
+#if defined(CONFIG_HAS_VUART_NS8250)
+
+int vuart_putchar(struct vuart_ns8250 *vdev, char ch);
+
+/*
+ * Match the names w/ arch/arm/vuart.h
+ * FIXME: move to common vuart.h
+ */
+int domain_vuart_init(struct domain *d);
+void domain_vuart_free(struct domain *d);
+
+#else
+
+static inline int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
+{
+ return -1;
+}
+
+static inline int domain_vuart_init(struct domain *d)
+{
+ return -ENODEV;
+}
+
+static inline void domain_vuart_free(struct domain *d)
+{
+}
+
+#endif /* #if defined(CONFIG_HAS_VUART_NS8250) */
+
+#endif /* #if !defined(HVM__VUART_NS8250_H) */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-13 11:43 ` Roger Pau Monné
2025-01-04 6:28 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-13 11:43 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:42:01PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Add initial in-hypervisor emulator for NS8250/NS16x50-compatible UARTs under
> CONFIG_HAS_VUART_NS8250.
>
> In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> early guest OS bringup debugging, because it eliminates dependency on the
> external emulator being operational by the time domains are created. Also,
> there's no early console facility similar to vpl011 to support x86 guest OS
> bring up.
>
> By default, CONFIG_HAS_VUART_NS8250 enables emulatio of NS8250 at I/O port
emulatio -> emulation
> 0x3f8, IRQ#4 in guest OS.
>
> Limitations:
> - Only x86;
> - Only Linux guest tested so far;
> - Only legacy COM{1,2,3,4} resources, no customization;
> - Only Xen console as a backend, no inter-domain communication (similar to
> vpl011 on Arm);
> - Only 8-bit characters;
> - Baud rate is not emulated;
> - FIFO-less mode is not emulated properly;
> - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
> has special FCR handling;
> - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
> friends);
> - Assumes no ISA-device IRQ sharing;
> - MMIO-based UART is not supported.
Do you have a reference to the specification you have used to
implement the driver?
Most of the comments below are quite generic, I haven't really looked
into the implementation details of the ns8520 emulated registers.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/x86/hvm/Kconfig | 14 +
> xen/arch/x86/hvm/Makefile | 1 +
> xen/arch/x86/hvm/hvm.c | 13 +
> xen/arch/x86/hvm/vuart_ns8250.c | 886 ++++++++++++++++++++++++++++
> xen/arch/x86/include/asm/hvm/domain.h | 5 +
> xen/arch/x86/include/asm/hvm/vuart_ns8250.h | 75 +++
> 6 files changed, 994 insertions(+)
>
> diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
> index 361bb6572e633f3cf0fc972a3b391e8341c33361..af6e698b8be0d82af94b00c0cfdaf9a2bc24b154 100644
> --- a/xen/arch/x86/hvm/Kconfig
> +++ b/xen/arch/x86/hvm/Kconfig
> @@ -61,3 +61,17 @@ config HVM_FEP
> for use in production.
>
> If unsure, say N.
> +
> +config HAS_VUART_NS8250
> + bool "NS8250-compatible UART Emulation"
> + depends on HVM && HAS_IOPORTS
> + default n
> + help
> + In-hypervisor NS8250/NS16x50 UART emulation.
> +
> + Only legacy PC I/O ports are emulated.
> +
> + This is strictly for testing purposes (early HVM guest console), and not
> + appropriate for use in production.
If it's strictly speaking for debug purposes, then it might be helpful
to tie it to CONFIG_DEBUG, or if maybe that's too broad, make it tied
to CONFIG_EXPERT, so that it's clear builds wit the option enabled
won't be security supported.
> +
> + If unsure, say N.
> diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
> index 4c1fa5c6c2bf75d336b39f343241bfced5b91b09..14761435e0694109f815da63289666c0f1cbf0ce 100644
> --- a/xen/arch/x86/hvm/Makefile
> +++ b/xen/arch/x86/hvm/Makefile
> @@ -29,3 +29,4 @@ obj-y += vm_event.o
> obj-y += vmsi.o
> obj-y += vpic.o
> obj-y += vpt.o
> +obj-$(CONFIG_HAS_VUART_NS8250) += vuart_ns8250.o
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 493b699c708949b2109c26573a107565543f5d45..db61af7defc5f5da795b7a613fe4d32fbff7d93e 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -55,6 +55,7 @@
> #include <asm/hvm/monitor.h>
> #include <asm/hvm/viridian.h>
> #include <asm/hvm/vm_event.h>
> +#include <asm/hvm/vuart_ns8250.h>
> #include <asm/altp2m.h>
> #include <asm/mtrr.h>
> #include <asm/apic.h>
> @@ -679,6 +680,15 @@ int hvm_domain_initialise(struct domain *d,
> if ( rc != 0 )
> goto fail1;
>
> + if ( domain_has_vuart(d) )
> + {
> + rc = domain_vuart_init(d);
> + if ( rc == 0 )
> + d->is_console = true;
> + else if ( rc != -ENODEV )
> + goto out_vioapic_deinit;
Why do you shallow the ENODEV error? If a user has asked for a vUART,
and there's no support in Xen it should error hard IMO, rather than
ignoring it and continue building the domain.
IMO emulation_flags_ok() should prevent hvm_domain_initialise() from
being called with vUART when there's no support built-in.
> + }
> +
> stdvga_init(d);
>
> rtc_init(d);
> @@ -699,6 +709,9 @@ int hvm_domain_initialise(struct domain *d,
> return 0;
>
> fail2:
> + if ( domain_has_vuart(d) )
> + domain_vuart_free(d);
> + out_vioapic_deinit:
> vioapic_deinit(d);
> fail1:
> if ( is_hardware_domain(d) )
> diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..779dbd80d7be4e070ea9df3ae736ecdc662a527a
> --- /dev/null
> +++ b/xen/arch/x86/hvm/vuart_ns8250.c
> @@ -0,0 +1,886 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * NS8250-compatible UART Emulator.
> + *
> + * Limitations:
> + * - Only x86;
> + * - Only Linux guest tested so far;
> + * - Only legacy COM{1,2,3,4} resources, no customization;
> + * - Only Xen console as a backend, no inter-domain communication (similar to
> + * vpl011 on Arm);
> + * - Only 8-bit characters;
> + * - Baud rate is not emulated;
> + * - FIFO-less mode is not emulated properly;
> + * - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
> + * has special FCR handling;
> + * - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
> + * friends);
> + * - Assumes no ISA-device IRQ sharing;
> + * - MMIO-based UART is not supported;
> + * - PCI UART is not supported.
IMO putting the limitations here is likely to make them go out of
sync, noting in the commit message should be enough.
> + */
> +
> +#define pr_fmt(fmt) "ns8250: " fmt
> +#define pr_log_level hvm_ns8250_log_level
> +
> +/* Development debugging */
> +#define NS8250_LOG_LEVEL 0
> +
> +#include <xen/types.h>
> +#include <xen/event.h>
> +#include <xen/lib.h>
> +#include <xen/errno.h>
> +#include <xen/sched.h>
> +#include <xen/trace.h>
> +#include <xen/resource.h>
> +#include <xen/ctype.h>
> +#include <xen/param.h>
> +#include <xen/console.h> /* console_input_domid() */
Includes would be better sorted alphabetically if possible.
> +#include <asm/setup.h> /* max_init_domid */
> +#include <asm/iocap.h>
> +#include <asm/hvm/hvm.h>
> +#include <asm/hvm/io.h>
> +#include <asm/hvm/vuart_ns8250.h>
> +
> +#if !defined(pr_fmt)
> +#define pr_fmt(fmt) fmt
> +#endif
> +
> +#if !defined(pr_log_level)
> +#define pr_log_level 0
> +#endif
> +
> +#define pr_err(fmt, args...) \
> + gprintk(KERN_ERR, pr_fmt(fmt), ## args)
> +#define pr_warn(fmt, args...) \
> + if (pr_log_level) gprintk(KERN_WARNING, pr_fmt(fmt), ## args)
> +#define pr_info(fmt, args...) \
> + if (pr_log_level) gprintk(KERN_INFO, pr_fmt(fmt), ## args)
> +#define pr_debug(fmt, args...) \
> + if (pr_log_level) gprintk(KERN_DEBUG, pr_fmt(fmt), ## args)
Is there any reason you cannot directly use gprintk() and need those
wrappers?
If the code has been imported from another project it would be good to
have a reference, so that we can pickup updates in the future.
> +
> +/*
> + * NS8250 emulator state machine logging (development only)
> + * FIXME: use similar to parse_guest_loglvl()
> + */
> +static unsigned int __read_mostly hvm_ns8250_log_level = NS8250_LOG_LEVEL;
> +integer_param("hvm.ns8250.log_level", hvm_ns8250_log_level);
WE don't have any existing instances of command line options with
dots, and also the documentation addition to xen-command-line.pandoc
seems to be missing from this patch.
My recommendation would be that the code here just uses normal logs
levels, users can adjust the minimum log level of pritned messages.
Adding ad-hoc log level settings for each subsystem just causes
confusion.
> +
> +/*
> + * Default emulated NS8250 resources.
> + * If not specified, COM1 (I/O port 0x3f8, IRQ#4) is emulated.
> + * FIXME: follow Linux'es console= syntax or re-use
> + * ns16550_parse_port_config().
> + */
> +static char __read_mostly hvm_ns8250_console[64];
> +string_param("hvm.ns8250.console", hvm_ns8250_console);
Same here, there seems to be no documentation about this option. And
you likely want this to be a custom_param so you can do the parsing
directly instead of storing into a buffer for later parsing.
> +
> +/* I/O access mask */
> +static const uint32_t io_access_mask[] = {
> + [0] = 0X00000000U,
> + [1] = 0X000000FFU,
> + [2] = 0X0000FFFFU,
> + [4] = 0XFFFFFFFFU,
lowercase x please.
> +};
> +
> +/*
> + * Legacy IBM PC NS8250 resources.
> + * There are only 4 I/O port ranges, hardcoding all of them here.
> + */
> +static const struct {
> + const char *name;
> + const struct resource *res;
> +} ns8250_x86_legacy_uarts[4] = {
> + [0] = {
> + .name = "com1",
> + .res = (const struct resource[]){
> + { .type = IORESOURCE_IO, .addr = 0x3F8, .size = UART_MAX },
> + { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
> + { .type = IORESOURCE_UNKNOWN },
> + },
> + },
> + [1] = {
> + .name = "com2",
> + .res = (const struct resource[]){
> + { .type = IORESOURCE_IO, .addr = 0x2F8, .size = UART_MAX },
> + { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
> + { .type = IORESOURCE_UNKNOWN },
> + },
> + },
> + [2] = {
> + .name = "com3",
> + .res = (const struct resource[]){
> + { .type = IORESOURCE_IO, .addr = 0x3E8, .size = UART_MAX },
> + { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
> + { .type = IORESOURCE_UNKNOWN },
> + },
> + },
> + [3] = {
> + .name = "com4",
> + .res = (const struct resource[]){
> + { .type = IORESOURCE_IO, .addr = 0x2E8, .size = UART_MAX },
> + { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
> + { .type = IORESOURCE_UNKNOWN },
> + },
> + },
> +};
> +
> +static bool ns8250_fifo_rx_empty(struct vuart_ns8250 *vdev)
> +{
> + struct xencons_interface *cons = vdev->cons;
const here and in the function parameter.
> +
> + return cons->in_prod == cons->in_cons;
> +}
> +
> +static bool ns8250_fifo_rx_full(struct vuart_ns8250 *vdev)
> +{
> + struct xencons_interface *cons = vdev->cons;
const here and in the function parameter.
> +
> + return cons->in_prod - cons->in_cons == sizeof(cons->in);
> +}
> +
> +static void ns8250_fifo_rx_reset(struct vuart_ns8250 *vdev)
> +{
> + struct xencons_interface *cons = vdev->cons;
> +
> + cons->in_cons = cons->in_prod;
> +}
> +
> +static int ns8250_fifo_rx_getchar(struct vuart_ns8250 *vdev)
> +{
> + struct xencons_interface *cons = vdev->cons;
> + int rc = -1;
-ENOENT maybe instead of -1?
> +
> + if ( !ns8250_fifo_rx_empty(vdev) )
> + {
> + rc = cons->in[MASK_XENCONS_IDX(cons->in_cons, cons->in)];
> + cons->in_cons++;
> + }
> +
> + return rc;
> +}
> +
> +static int ns8250_fifo_rx_putchar(struct vuart_ns8250 *vdev, char c)
> +{
> + struct xencons_interface *cons = vdev->cons;
> + int rc = 0;
> +
> + /*
> + * FIFO-less 8250/16450 UARTs: newly arrived word overwrites the contents
> + * of the THR.
> + */
> + if ( ns8250_fifo_rx_full(vdev) )
> + {
> + ns8250_fifo_rx_reset(vdev);
> + rc = -ENOSPC;
> + }
> +
> + cons->in[MASK_XENCONS_IDX(cons->in_prod, cons->in)] = c;
> + cons->in_prod++;
> +
> + return rc;
> +}
> +
> +/*
> + * Flush cached output to Xen console.
> + * Can be called from ns8250_exit().
> + */
> +static void ns8250_fifo_tx_reset(struct vuart_ns8250 *vdev)
> +{
> + struct xencons_interface *cons = vdev->cons;
> +
> + if ( cons->out_prod == 0 )
Don't you need to check that cons->out_prod == cons->out_cons instead?
> + return;
> +
> + cons->out[cons->out_prod++] = '\0';
You need to use MASK_XENCONS_IDX() otherwise this could result in a
buffer overflow?
If you expect (because of checks in other places) out_prod to always
be < ring size - 1, please add an assert to that extent here. But see
below about the usage of the ring indexes.
Also, no need for the trailing increment, you will unconditionally
reset out_prod to 0 just below.
> +
> + /*
> + * NB: do not show domain ID if the domain owning the virtual UART also
> + * owns Xen input console.
> + */
> + if ( vdev->owner->domain_id == console_owner_domid() )
> + printk_common("%s", cons->out);
> + else
> + guest_printk(vdev->owner, "%s", cons->out);
> +
> + cons->out_prod = 0;
You should rather do cons->out_cons = cons->out_prod?
Wait, you seem to use the out buffer differently than the input one,
and only advance out_prod but not out_cons?
It seems weird to drive the 'in' ring using both indexes, while the
'out' ring is just using one index.
> +}
> +
> +/*
> + * Send a character to Xen console.
> + */
> +static void ns8250_fifo_tx_putchar(struct vuart_ns8250 *vdev, char ch)
> +{
> + struct xencons_interface *cons = vdev->cons;
> +
> + if ( !isconsole(ch) )
> + return;
> +
> + cons->out[cons->out_prod] = ch;
> + cons->out_prod++;
> +
> + if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1
> + || ch == '\n' || ch == '\0' )
Bad indentation, should be:
if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1 ||
ch == '\n' || ch == '\0' )
Albeit I'm not sure you need the '\0' check, as isconsole('\0') will
already return false?
> + ns8250_fifo_tx_reset(vdev);
> +}
> +
> +static bool cf_check ns8250_iir_check_lsi(struct vuart_ns8250 *vdev)
vdev should be const.
> +{
> + return !!( vdev->regs[UART_LSR] & UART_LSR_MASK );
Extra spaces around the parentheses.
> +}
> +
> +static bool cf_check ns8250_iir_check_rda(struct vuart_ns8250 *vdev)
> +{
> + return !ns8250_fifo_rx_empty(vdev);
> +}
> +
> +static bool cf_check ns8250_iir_check_thr(struct vuart_ns8250 *vdev)
> +{
> + return !!( vdev->flags & NS8250_IRQ_THRE_PENDING );
> +}
> +
> +static bool cf_check ns8250_iir_check_msi(struct vuart_ns8250 *vdev)
const for all the 3 vdev parameters above.
> +{
> + return !!( vdev->regs[UART_MSR] & UART_MSR_DELTA );
Extra spaces around the parentheses.
> +}
> +
> +/*
> + * Interrupt identity reasons by priority.
> + * NB: highest priority are at lower indexes.
> + */
> +static const struct {
> + uint8_t ier_mask;
> + uint8_t iir_mask;
> + bool (*iir_check)(struct vuart_ns8250 *vdev);
> +} iir_by_prio[] = {
> + [0] = { UART_IER_ELSI, UART_IIR_LSI, ns8250_iir_check_lsi },
> + [1] = { UART_IER_ERDAI, UART_IIR_RDA, ns8250_iir_check_rda },
> + [2] = { UART_IER_ETHREI, UART_IIR_THR, ns8250_iir_check_thr },
> + [3] = { UART_IER_EMSI, UART_IIR_MSI, ns8250_iir_check_msi },
You don't need the explicit array indexes (at least with the ones you
are specifying here).
I think those interrupt reasons are not likely to change, and the
checker for each reason is a one line function. It would be better to
open-code the checking in ns8250_irq_reason(), as that will avoid the
indirect function call.
Otherwise iir_by_prio array should be declared in the scope of
ns8250_irq_reason(), as that's the only function where it's used.
> +};
> +
> +/*
> + * Define the interrupt identity reason.
> + * NB: NS8250 always reports high priority events first.
> + */
> +static uint8_t ns8250_irq_reason(struct vuart_ns8250 *vdev)
> +{
> + int i;
unsigned int.
> +
> + ASSERT( spin_is_locked(&vdev->lock) );
Extra spaces around the parentheses.
> + for ( i = 0; i < ARRAY_SIZE(iir_by_prio); i++ )
> + {
> + if ( (vdev->regs[UART_IER] & iir_by_prio[i].ier_mask)
> + && iir_by_prio[i].iir_check(vdev) )
Wrong placement of the &&, plus indentation.
> + return iir_by_prio[i].iir_mask;
> + }
> +
> + return UART_IIR_NOINT;
> +}
> +
> +/*
> + * Assert virtual NS8250 interrupt line.
> + */
> +static void ns8250_irq_assert(struct vuart_ns8250 *vdev)
> +{
> + uint8_t iir;
> +
> + iir = ns8250_irq_reason(vdev);
> + if (iir & UART_IIR_NOINT)
Missing spaces around the parentheses.
> + hvm_irq_lower(vdev->owner, vdev->irq);
> + else
> + hvm_irq_raise(vdev->owner, vdev->irq);
I think you should use hvm_isa_irq_{,de}assert(), as the interrupt
will unconditionally be < 16?
> +
> + pr_debug("IRQ#%d %x %s\n", vdev->irq, iir,
> + !!(iir & UART_IIR_NOINT) ? "lower" : "raise");
hm, this will get very verbose. While it might have been helpful
during development, I don't think it would be appropriate to print at
any debug level.
> +}
> +
> +/*
> + * Emulate 8-bit write access to NS8250 register.
> + */
> +static int ns8250_io_write8(
> + struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
> +{
> + uint8_t val;
> + int rc = 0;
> +
> + val = *data;
You can init val at declaration.
> +
> + switch ( reg )
> + {
> + /* DLAB=0 */
> + case UART_THR:
> + if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
> + {
> + ns8250_fifo_rx_putchar(vdev, val);
> + vdev->regs[UART_LSR] |= UART_LSR_OE;
> + }
> + else
> + ns8250_fifo_tx_putchar(vdev, val);
> +
> + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> +
> + break;
> +
> + case UART_IER:
> + if ( val & vdev->regs[UART_IER] & UART_IER_ETHREI )
> + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> +
> + vdev->regs[UART_IER] = val & UART_IER_MASK;
> +
> + break;
> +
> + case UART_FCR: /* WO */
> + if ( val & UART_FCR_CLRX )
> + ns8250_fifo_rx_reset(vdev);
> +
> + if ( val & UART_FCR_CLTX )
> + ns8250_fifo_tx_reset(vdev);
> +
> + if ( !(val & UART_FCR_ENABLE) )
> + val = 0;
> +
> + vdev->regs[UART_FCR] = val & (UART_FCR_ENABLE |
> + UART_FCR_DMA |
> + UART_FCR_TRG_MASK);
> +
> + break;
> +
> + case UART_LCR:
> + vdev->regs[UART_LCR] = val;
> + break;
> +
> + case UART_MCR: {
> + uint8_t msr_curr, msr_next, msr_delta;
> +
> + msr_curr = vdev->regs[UART_MSR];
> + msr_next = 0;
> + msr_delta = 0;
> +
> + /* Set modem status */
> + if ( val & UART_MCR_LOOP )
> + {
> + if ( val & UART_MCR_DTR )
> + msr_next |= UART_MSR_DSR;
> + if ( val & UART_MCR_RTS )
> + msr_next |= UART_MSR_CTS;
> + if ( val & UART_MCR_OUT1 )
> + msr_next |= UART_MSR_RI;
> + if ( val & UART_MCR_OUT2 )
> + msr_next |= UART_MSR_DCD;
> + }
> + else
> + msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
> +
> + /* Calculate changes in modem status */
> + if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
> + msr_delta |= UART_MSR_DCTS;
> + if ( (msr_curr & UART_MCR_RTS) ^ (msr_next & UART_MCR_RTS) )
> + msr_delta |= UART_MSR_DDSR;
> + if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
> + msr_delta |= UART_MSR_TERI;
> + if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
> + msr_delta |= UART_MSR_DDCD;
> +
> + vdev->regs[UART_MCR] = val & UART_MCR_MASK;
> + vdev->regs[UART_MSR] = msr_next | msr_delta;
> +
> + break;
> + }
> +
> + case UART_LSR: /* RO */
> + case UART_MSR: /* RO */
> + rc = -EINVAL;
> + break;
Why are those not handled by the default case below? Is there any
reason to explicitly mention those cases?
> +
> + /*
> + * NB: Firmware like OVMF rely on SCR presence to initialize the ns8250
> + * driver.
> + */
> + case UART_SCR:
> + vdev->regs[UART_SCR] = val;
> + break;
> +
> + /* DLAB=1 */
> + case UART_MAX + UART_DLL:
> + vdev->dl = (vdev->dl & 0xFF00U) | val;
> + break;
> +
> + case UART_MAX + UART_DLM:
> + vdev->dl = (val << 8) | (vdev->dl & 0x00FFU);
> + break;
> +
> + default:
> + rc = -EINVAL;
> + break;
Returning -EINVAL here is not correct I think, as the error gets
propagated into the return of the IO handler. Those handlers expect
to return a code in the range of X86EMUL_OKAY (see x86_emulate.h).
But most importantly, what do you expect the caller to do with such
error code? The access must be handled by the console driver, as it
belongs to it's range of IO ports. What would hardware do in this
case, ignore the write and continue operation?
If so, there's no point in returning any error from
ns8250_io_write8(), the best would be to log a debug message in case
of ignored accesses. This likely applies to all the handlers
implemented below.
> + }
> +
> + return rc;
> +}
> +
> +/*
> + * Emulate 16-bit write access to NS8250 register.
> + * NB: some guest OSes use outw() to access UART_DLL.
> + */
> +static int ns8250_io_write16(
> + struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
> +{
> + int rc;
> +
> + switch ( reg )
> + {
> + case UART_MAX + UART_DLL:
> + vdev->dl = *data;
> + rc = 0;
> + break;
> +
> + default:
> + rc = -EINVAL;
> + break;
> + }
> +
> + return rc;
> +}
> +
> +/*
> + * Emulate write access to NS8250 register.
> + */
> +static int ns8250_io_write(
> + struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
> +{
> + int rc = -EINVAL;
> +
> + switch ( size )
> + {
> + case 1:
> + rc = ns8250_io_write8(vdev, reg, (uint8_t *)data);
> + break;
> +
> + case 2:
> + rc = ns8250_io_write16(vdev, reg, (uint16_t *)data);
> + break;
> +
> + default:
> + break;
> + }
> +
> + ns8250_irq_assert(vdev);
> +
> + return rc;
> +}
> +
> +/*
> + * Emulate 8-bit read access to NS8250 register.
> + */
> +static int ns8250_io_read8(
> + struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
> +{
> + int rc = 0;
> + uint8_t val;
In order to avoid unintentionally leaking stack contents, it would be
best to initialize val at declaration:
uint8_t val = ~0;
> +
> + switch ( reg )
> + {
> + /* DLAB=0 */
> + case UART_RBR:
> + val = (uint8_t)ns8250_fifo_rx_getchar(vdev);
You seem to ignore that ns8250_fifo_rx_getchar() can return an error,
is it intended to just propagate the error to the caller then?
> + /* NB: do not forget to clear overrun condition */
> + vdev->regs[UART_LSR] &= ~UART_LSR_OE;
> + break;
> +
> + case UART_IER: /* RO */
> + val = vdev->regs[UART_IER];
> + break;
> +
> + case UART_IIR:
> + val = ns8250_irq_reason(vdev);
> + if ( val & UART_IIR_THR )
> + vdev->flags &= ~NS8250_IRQ_THRE_PENDING;
> +
> + if ( vdev->regs[UART_FCR] & UART_FCR_ENABLE )
> + val |= UART_IIR_FE_MASK;
> +
> + break;
> +
> + case UART_LCR:
> + val = vdev->regs[UART_LCR];
> + break;
> +
> + case UART_MCR:
> + val = vdev->regs[UART_MCR];
> + break;
> +
> + case UART_LSR:
> + val = vdev->regs[UART_LSR] | UART_LSR_THRE | UART_LSR_TEMT;
> + if ( ns8250_fifo_rx_empty(vdev) )
> + val &= ~UART_LSR_DR;
> + else
> + val |= UART_LSR_DR;
> +
> + vdev->regs[UART_LSR] = val & ~UART_LSR_MASK;
> +
> + break;
> +
> + case UART_MSR:
> + val = vdev->regs[UART_MSR];
> + vdev->regs[UART_MSR] &= ~UART_MSR_DELTA;
> + break;
> +
> + case UART_SCR:
> + val = vdev->regs[UART_SCR];
> + break;
> +
> + /* DLAB=1 */
> + case UART_MAX + UART_DLL:
> + val = vdev->dl & 0xFFU;
> + break;
> +
> + case UART_MAX + UART_DLM:
> + val = vdev->dl >> 8;
> + break;
> +
> + default:
> + val = (uint8_t)io_access_mask[1];
Hm, not sure why you need this mask, isn't it OK to just do val = ~0;?
However see comment above about initializing at definition.
> + rc = -EINVAL;
> + break;
> + }
> +
> + *data = val;
> +
> + return rc;
> +}
> +
> +/*
> + * Emulate 16-bit read access to NS8250 register.
> + */
> +static int ns8250_io_read16(
> + struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
> +{
> + uint16_t val;
Same comment as ns8250_io_read8() about initializing val at definition
and not using io_access_mask.
> + int rc;
> +
> + switch ( reg )
> + {
> + case UART_MAX + UART_DLL:
> + val = vdev->dl;
> + rc = 0;
> + break;
> +
> + default:
> + val = (uint16_t)io_access_mask[2];
> + rc = -EINVAL;
> + break;
> + }
> +
> + *data = val;
> +
> + return rc;
> +}
> +
> +/*
> + * Emulate read access to NS8250 register.
> + */
> +static int ns8250_io_read(
> + struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
> +{
> + int rc;
> +
> + switch ( size )
> + {
> + case 1:
> + rc = ns8250_io_read8(vdev, reg, (uint8_t *)data);
> + break;
> +
> + case 2:
> + rc = ns8250_io_read16(vdev, reg, (uint16_t *)data);
I get the feeling you could handle both 1 and 2 byte accesses in the
same function, as there's just a single register that allows 2 byte
accesses.
Is the split done because further (to be implemented) features will
require addition 2 byte accesses?
> + break;
> +
> + default:
> + *data = io_access_mask[size];
> + rc = -EINVAL;
> + break;
> + }
> +
> + ns8250_irq_assert(vdev);
> +
> + return rc;
> +}
> +
> +static const char *ns8250_regname(
> + const struct vuart_ns8250 *vdev, uint32_t reg, int dir)
> +{
> + static const char *reg_names[UART_MAX + 2][2] = {
> + /* register W R */
> + [UART_RBR] = { "THR", "RBR" },
> + [UART_IER] = { "IER", "IER" },
> + [UART_IIR] = { "FCR", "IIR" },
> + [UART_LCR] = { "LCR", "LCR" },
> + [UART_MCR] = { "MCR", "MCR" },
> + [UART_LSR] = { "LSR", "LSR" },
> + [UART_MSR] = { "MSR", "MSR" },
> + [UART_SCR] = { "SCR", "SCR" },
> + [UART_MAX + UART_DLL] = { "DLL", "DLL" },
> + [UART_MAX + UART_DLM] = { "DLM", "DLM" },
> + };
> +
To be in the safe saide I would assert that 'reg' and 'dir' are
between the array bounds.
> + return reg_names[reg][dir];
> +}
> +
> +/*
> + * Emulate I/O access to NS8250 register.
> + */
> +static int cf_check ns8250_io_handle(
> + int dir, unsigned int addr, unsigned int size, uint32_t *data)
> +{
> +#define op(dir) (((dir) == IOREQ_WRITE) ? 'W' : 'R')
> + struct domain *d = rcu_lock_current_domain();
> + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> + uint32_t offset, reg;
> + int rc;
> +
> + spin_lock(&vdev->lock);
> +
> + BUG_ON( vdev->owner != d );
Extra spaces around the parentheses.
However I would rather use:
if ( vdev->owner != d )
{
gprintk(XENLOG_ERR, "vUART owner %pd doesn't match current domain\n",
vdev->owner);
ASSERT_UNREACHABLE();
rcu_unlock_domain(d);
return X86EMU_OKAY;
}
And place it before the spin_lock() call.
> +
> + if ( !(vdev->flags & NS8250_READY) )
> + {
> + pr_err("%c io 0x%04x %d 0x%08"PRIx32": propagate to external I/O emulator\n",
> + op(dir), addr, size, *data);
> + rc = X86EMUL_UNHANDLEABLE;
I think you need to unconditionally return X86EMU_OKAY and just ignore
the access. I assume there's no point in attempting to forward this
access to any other handler, as it must be handled by the vuart
driver.
> + goto out;
> + }
> +
> + reg = addr - vdev->io_addr;
> + BUG_ON( reg >= UART_MAX );
If possible, might be best to use a construct similar to the one
proposed above with ASSERT_UNREACHABLE().
> + if ( reg % size != 0 )
IS_ALIGNED(reg, size) might be clearer.
> + {
> + pr_err("%c 0x%04x %d 0x%08"PRIx32": unaligned access\n",
> + op(dir), addr, size, *data & io_access_mask[size]);
> + rc = X86EMUL_OKAY;
> + goto out;
> + }
> +
> + /* Redirect access to divisor latch registers */
> + if ( !!(vdev->regs[UART_LCR] & UART_LCR_DLAB)
> + && (reg == UART_DLL || reg == UART_DLM) )
Indentation plus placement of the &&.
> + offset = UART_MAX + reg;
> + else
> + offset = reg;
> +
> + if ( dir == IOREQ_WRITE )
> + {
> + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> + op(dir), addr, size,
> + *data & io_access_mask[size],
> + ns8250_regname(vdev, offset, dir), reg);
> + rc = ns8250_io_write(vdev, offset, size, data);
> + }
> + else
> + {
> + rc = ns8250_io_read(vdev, offset, size, data);
> + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> + op(dir), addr, size,
> + *data & io_access_mask[size],
> + ns8250_regname(vdev, offset, dir), reg);
The pr_debug() are likely too verbose.
> + }
> + if ( rc )
> + pr_err("%c 0x%04x %d 0x%08"PRIx32": unsupported access\n",
> + op(dir), addr, size, *data & io_access_mask[size]);
> + rc = X86EMUL_OKAY;
> +
> +out:
> + spin_unlock(&vdev->lock);
You seem to have forgotten a rcu_unlock_domain() call here? (even if
it's a no-op).
> +
> + return rc;
> +#undef op
> +}
> +
> +/*
> + * Parse virtual NS8250 configuration.
> + * hvm.ns8250.console=[com1|com2|com3|com4]
> + */
> +static const struct resource *ns8250_parse(void)
> +{
> + int i;
> +
> + for ( i = 0; i < ARRAY_SIZE(ns8250_x86_legacy_uarts); i++ )
> + if ( !strcasecmp(hvm_ns8250_console, ns8250_x86_legacy_uarts[i].name) )
> + return ns8250_x86_legacy_uarts[i].res;
> +
> + return ns8250_x86_legacy_uarts[0].res;
> +}
> +
> +/*
> + * Claim virtual NS8250 resources to domain.
> + */
> +static int ns8250_claim(
> + struct vuart_ns8250 *vdev, const struct resource *r, struct domain *d)
> +{
> + unsigned long size;
> + unsigned long start;
> + unsigned long end;
> +
> + vdev->irq = NO_IRQ;
> + vdev->io_addr = IORESOURCE_UNKNOWN;
> + vdev->io_size = IORESOURCE_UNKNOWN;
> +
> + foreach_resource(r)
> + {
> + if ( r->type & IORESOURCE_IO )
> + {
> + size = r->size;
> + start = r->addr;
> + end = r->addr + r->size - 1;
> +
> + if ( !ioports_access_permitted(d, start, end) )
> + ioports_permit_access(d, start, end);
Are you sure this is intended? By using ioports_permit_access() you
are giving the domain access to the hardware (host) IO ports, and thus
possibly avoiding the trapping into the IO handlers.
However this is not very well-wired in HVM, because there's still an
extra guest IO port -> host IO port translation that you are not
adding.
You shouldn't need the ioports_permit_access() for using the emulated
vUART.
> +
> + register_portio_handler(d, start, size, ns8250_io_handle);
> +
> + /* Used to assert I/O port handler */
> + vdev->io_addr = start;
> + vdev->io_size = size;
> + }
> + else if ( r->type & IORESOURCE_IRQ )
> + /* "Claim" virtual IRQ; assumes no ISA-device IRQ sharing */
> + vdev->irq = r->addr;
> + else
> + return -EINVAL;
> + }
> +
> + if ( vdev->irq == NO_IRQ
> + || vdev->io_addr == IORESOURCE_UNKNOWN
> + || vdev->io_size == IORESOURCE_UNKNOWN )
> + return -ENODEV;
> +
> + return 0;
> +}
> +
> +/*
> + * Unclaim virtual NS8250 resources.
> + */
> +static void ns8250_unclaim(struct vuart_ns8250 *vdev, struct domain *d)
> +{
> + unsigned long size = vdev->io_size;
> + unsigned long start = vdev->io_addr;
> + unsigned long end = start + size - 1;
> +
> + if ( ioports_access_permitted(d, start, end) )
> + ioports_deny_access(d, start, size);
> +}
> +
> +static int ns8250_init(struct domain *d, const struct resource *r)
> +{
> + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> + struct xencons_interface *cons;
> + int rc;
> +
> + cons = _xzalloc(sizeof(*vdev->cons), sizeof(void *));
xvzalloc(typeof(*vdev->cons));
> + if ( cons == NULL )
> + return -ENOMEM;
> +
> + rc = ns8250_claim(vdev, r, d);
> + if ( rc )
> + {
> + xfree(cons);
> + return rc;
> + }
> +
> + spin_lock_init(&vdev->lock);
> + hvm_irq_lower(d, vdev->irq);
> +
> + vdev->dl = (UART_CLOCK_HZ / 115200) >> 4; /* Report 115200 baud rate */
> + vdev->cons = cons;
> + vdev->owner = d;
> + vdev->flags = NS8250_READY | NS8250_IRQ_THRE_PENDING;
> +
> + return 0;
> +}
> +
> +static void ns8250_exit(struct domain *d)
> +{
> + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> +
> + spin_lock(&vdev->lock);
> +
> + if ( !(vdev->flags & NS8250_READY) )
> + goto out;
> +
> + ns8250_unclaim(vdev, d);
> + ns8250_fifo_tx_reset(vdev);
> + xfree(vdev->cons);
> +
> + vdev->cons = NULL;
> + vdev->owner = NULL;
> + vdev->flags = 0;
> +
> +out:
> + spin_unlock(&vdev->lock);
> +}
> +
> +int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
> +{
> + int rc;
> +
> + spin_lock(&vdev->lock);
> +
> + if ( !(vdev->flags & NS8250_READY) )
> + {
> + rc = -ENODEV;
> + goto out;
> + }
> +
> + /* Echo the user input on the console */
> + printk("%c", ch);
FWIW, I would move the printk() after the error checks, so that the
character is only echoed if handled.
> +
> + /*
> + * Device is in loopback mode; do nothing.
> + */
> + if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
> + {
> + rc = -EBUSY;
> + goto out;
> + }
> +
> + rc = ns8250_fifo_rx_putchar(vdev, ch);
> + if ( rc == -ENOSPC )
> + vdev->regs[UART_LSR] |= UART_LSR_OE | UART_LSR_DR;
> + else
> + /* NB: UART_LSR_DR is also set when UART_LSR is accessed. */
> + vdev->regs[UART_LSR] |= UART_LSR_DR;
> +
> + /* FIXME: check FCR when to fire an interrupt */
> + ns8250_irq_assert(vdev);
> +
> +out:
> + spin_unlock(&vdev->lock);
> +
> + return rc;
> +}
> +
> +int domain_vuart_init(struct domain *d)
> +{
> + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> + const struct resource *r;
> +
> + memset(vdev, 0, sizeof(*vdev));
> +
> + r = ns8250_parse();
> + if ( r != NULL )
> + return ns8250_init(d, r);
> +
> + return -ENODEV;
> +}
> +
> +void domain_vuart_free(struct domain *d)
> +{
> + ns8250_exit(d);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/x86/include/asm/hvm/domain.h b/xen/arch/x86/include/asm/hvm/domain.h
> index 333501d5f2ac01676646b9b277b551f06d43c3a5..d4ce25896259fc9763477e88d56bacbe4f78af5b 100644
> --- a/xen/arch/x86/include/asm/hvm/domain.h
> +++ b/xen/arch/x86/include/asm/hvm/domain.h
> @@ -16,6 +16,7 @@
> #include <asm/hvm/io.h>
> #include <asm/hvm/vmx/vmcs.h>
> #include <asm/hvm/svm/vmcb.h>
> +#include <asm/hvm/vuart_ns8250.h>
>
> #ifdef CONFIG_MEM_SHARING
> struct mem_sharing_domain
> @@ -73,6 +74,10 @@ struct hvm_domain {
> struct hvm_vioapic **vioapic;
> unsigned int nr_vioapics;
>
> +#if defined(CONFIG_HAS_VUART_NS8250)
> + struct vuart_ns8250 vuart;
Since this is supposed to possibly be used by just a small amount of
domain on the system, I would rather make this a pointer:
struct vuart_ns8250 *vuart;
And embed the xencons_ring inside of it directly, so that you just
have to allocate vuart_ns8250.
> +#endif
> +
> /*
> * hvm_hw_pmtimer is a publicly-visible name. We will defer renaming
> * it to the more appropriate hvm_hw_acpi until the expected
> diff --git a/xen/arch/x86/include/asm/hvm/vuart_ns8250.h b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..e1013751f955441a9089ea38c96c4605a7f4cb75
> --- /dev/null
> +++ b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
> @@ -0,0 +1,75 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * NS8250-compatible UART Emulator.
> + */
> +#if !defined(HVM__VUART_NS8250_H)
As commented by Jan, better use #ifndef.
> +#define HVM__VUART_NS8250_H
> +
> +#include <xen/spinlock.h>
> +#include <xen/8250-uart.h>
> +#include <public/io/console.h> /* xencons_interface */
> +
> +/*
> + * NS8250 emulator operational flags.
> + */
> +enum {
> + /* Emulator is ready */
> + NS8250_READY = BIT(0, U),
> + /* Trigger re-delivery of THRE interrupt */
> + NS8250_IRQ_THRE_PENDING = BIT(1, U),
I'm unsure the unnamed enum buys you much here if you end up assigning
values anyway. You might as well do:
#define NS8250_READY BIT(0, U)
#define NS8250_IRQ_THRE_PENDING BIT(1, U)
It would be good if you could integrate this with the flags field
being declared using DECLARE_BITMAP(). Otherwise you might need some
build-time check to ensure max defined flag fits in the struct flags
field.
> +};
> +
> +/*
> + * Virtual NS8250 device state.
> + */
> +struct vuart_ns8250 {
> + uint16_t dl; /* Divisor Latch */
> + uint8_t regs[UART_MAX]; /* Registers */
Doesn't regs already account for the divisor latch register?
> + uint32_t flags; /* Virtual device flags */
See comment above about using DECLARE_BITMAP().
> + uint64_t io_addr; /* Guest I/O region base address */
IO space is limited to 16bits, hence there's no need to use a uint64_t
to store the address. Either uint16_t, or just a plain unsigned int
will suffice. Same for size below.
> + uint64_t io_size; /* Guest I/O region size */
> + int irq; /* Guest IRQ# */
> + struct xencons_interface *cons; /* Emulated RX/TX FIFOs */
Any reason you re-use the xencons interface? And any reason it's a
pointer instead of being part of vuart_ns8250 itself?
> + struct domain *owner; /* Owner domain */
> + spinlock_t lock; /* Protection */
> +};
> +
> +#if defined(CONFIG_HAS_VUART_NS8250)
> +
> +int vuart_putchar(struct vuart_ns8250 *vdev, char ch);
> +
> +/*
> + * Match the names w/ arch/arm/vuart.h
> + * FIXME: move to common vuart.h
> + */
> +int domain_vuart_init(struct domain *d);
> +void domain_vuart_free(struct domain *d);
> +
> +#else
> +
> +static inline int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
> +{
Hard to tell as there are no users of vuart_putchar() in this patch,
but it seems you might want an ASSERT_UNREACHABLE() here.
> + return -1;
> +}
> +
> +static inline int domain_vuart_init(struct domain *d)
> +{
> + return -ENODEV;
> +}
> +
> +static inline void domain_vuart_free(struct domain *d)
> +{
Both init and free calls are gated with domain_has_vuart(), so you
might want to also add ASSERT_UNREACHABLE() here.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2024-12-13 11:43 ` Roger Pau Monné
@ 2025-01-04 6:28 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 6:28 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Friday, December 13th, 2024 at 3:43 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:42:01PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Add initial in-hypervisor emulator for NS8250/NS16x50-compatible UARTs under
> > CONFIG_HAS_VUART_NS8250.
> >
> > In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> > early guest OS bringup debugging, because it eliminates dependency on the
> > external emulator being operational by the time domains are created. Also,
> > there's no early console facility similar to vpl011 to support x86 guest OS
> > bring up.
> >
> > By default, CONFIG_HAS_VUART_NS8250 enables emulatio of NS8250 at I/O port
>
>
> emulatio -> emulation
Fixed.
>
> > 0x3f8, IRQ#4 in guest OS.
> >
> > Limitations:
> > - Only x86;
> > - Only Linux guest tested so far;
> > - Only legacy COM{1,2,3,4} resources, no customization;
> > - Only Xen console as a backend, no inter-domain communication (similar to
> > vpl011 on Arm);
> > - Only 8-bit characters;
> > - Baud rate is not emulated;
> > - FIFO-less mode is not emulated properly;
> > - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
> > has special FCR handling;
> > - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
> > friends);
> > - Assumes no ISA-device IRQ sharing;
> > - MMIO-based UART is not supported.
>
>
> Do you have a reference to the specification you have used to
> implement the driver?
I used these two (added links in the code comment):
- https://download.freebsd.org/doc/en/articles/serial-uart/serial-uart_en.pdf
- https://www.ti.com/lit/ds/symlink/tl16c550c.pdf
>
> Most of the comments below are quite generic, I haven't really looked
> into the implementation details of the ns8520 emulated registers.
Thanks a lot for the review!
>
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/x86/hvm/Kconfig | 14 +
> > xen/arch/x86/hvm/Makefile | 1 +
> > xen/arch/x86/hvm/hvm.c | 13 +
> > xen/arch/x86/hvm/vuart_ns8250.c | 886 ++++++++++++++++++++++++++++
> > xen/arch/x86/include/asm/hvm/domain.h | 5 +
> > xen/arch/x86/include/asm/hvm/vuart_ns8250.h | 75 +++
> > 6 files changed, 994 insertions(+)
> >
> > diff --git a/xen/arch/x86/hvm/Kconfig b/xen/arch/x86/hvm/Kconfig
> > index 361bb6572e633f3cf0fc972a3b391e8341c33361..af6e698b8be0d82af94b00c0cfdaf9a2bc24b154 100644
> > --- a/xen/arch/x86/hvm/Kconfig
> > +++ b/xen/arch/x86/hvm/Kconfig
> > @@ -61,3 +61,17 @@ config HVM_FEP
> > for use in production.
> >
> > If unsure, say N.
> > +
> > +config HAS_VUART_NS8250
> > + bool "NS8250-compatible UART Emulation"
> > + depends on HVM && HAS_IOPORTS
> > + default n
> > + help
> > + In-hypervisor NS8250/NS16x50 UART emulation.
> > +
> > + Only legacy PC I/O ports are emulated.
> > +
> > + This is strictly for testing purposes (early HVM guest console), and not
> > + appropriate for use in production.
>
>
> If it's strictly speaking for debug purposes, then it might be helpful
> to tie it to CONFIG_DEBUG, or if maybe that's too broad, make it tied
> to CONFIG_EXPERT, so that it's clear builds wit the option enabled
> won't be security supported.
I made it dependent on CONFIG_EXPERT.
>
> > +
> > + If unsure, say N.
> > diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
> > index 4c1fa5c6c2bf75d336b39f343241bfced5b91b09..14761435e0694109f815da63289666c0f1cbf0ce 100644
> > --- a/xen/arch/x86/hvm/Makefile
> > +++ b/xen/arch/x86/hvm/Makefile
> > @@ -29,3 +29,4 @@ obj-y += vm_event.o
> > obj-y += vmsi.o
> > obj-y += vpic.o
> > obj-y += vpt.o
> > +obj-$(CONFIG_HAS_VUART_NS8250) += vuart_ns8250.o
> > diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> > index 493b699c708949b2109c26573a107565543f5d45..db61af7defc5f5da795b7a613fe4d32fbff7d93e 100644
> > --- a/xen/arch/x86/hvm/hvm.c
> > +++ b/xen/arch/x86/hvm/hvm.c
> > @@ -55,6 +55,7 @@
> > #include <asm/hvm/monitor.h>
> > #include <asm/hvm/viridian.h>
> > #include <asm/hvm/vm_event.h>
> > +#include <asm/hvm/vuart_ns8250.h>
> > #include <asm/altp2m.h>
> > #include <asm/mtrr.h>
> > #include <asm/apic.h>
> > @@ -679,6 +680,15 @@ int hvm_domain_initialise(struct domain *d,
> > if ( rc != 0 )
> > goto fail1;
> >
> > + if ( domain_has_vuart(d) )
> > + {
> > + rc = domain_vuart_init(d);
> > + if ( rc == 0 )
> > + d->is_console = true;
> > + else if ( rc != -ENODEV )
> > + goto out_vioapic_deinit;
>
>
> Why do you shallow the ENODEV error? If a user has asked for a vUART,
> and there's no support in Xen it should error hard IMO, rather than
> ignoring it and continue building the domain.
re: shallowing error: my thought was - since this emulator is for debugging
purposes at this point, it is better to proceed w/ domain creation, rather
than disallowing domain creation.
Fixed.
>
> IMO emulation_flags_ok() should prevent hvm_domain_initialise() from
> being called with vUART when there's no support built-in.
Fixed.
>
> > + }
> > +
> > stdvga_init(d);
> >
> > rtc_init(d);
> > @@ -699,6 +709,9 @@ int hvm_domain_initialise(struct domain *d,
> > return 0;
> >
> > fail2:
> > + if ( domain_has_vuart(d) )
> > + domain_vuart_free(d);
> > + out_vioapic_deinit:
> > vioapic_deinit(d);
> > fail1:
> > if ( is_hardware_domain(d) )
> > diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..779dbd80d7be4e070ea9df3ae736ecdc662a527a
> > --- /dev/null
> > +++ b/xen/arch/x86/hvm/vuart_ns8250.c
> > @@ -0,0 +1,886 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only /
> > +/
> > + * NS8250-compatible UART Emulator.
> > + *
> > + * Limitations:
> > + * - Only x86;
> > + * - Only Linux guest tested so far;
> > + * - Only legacy COM{1,2,3,4} resources, no customization;
> > + * - Only Xen console as a backend, no inter-domain communication (similar to
> > + * vpl011 on Arm);
> > + * - Only 8-bit characters;
> > + * - Baud rate is not emulated;
> > + * - FIFO-less mode is not emulated properly;
> > + * - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
> > + * has special FCR handling;
> > + * - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
> > + * friends);
> > + * - Assumes no ISA-device IRQ sharing;
> > + * - MMIO-based UART is not supported;
> > + * - PCI UART is not supported.
>
>
> IMO putting the limitations here is likely to make them go out of
> sync, noting in the commit message should be enough.
I cleaned up commit message and kept those limitations in the source
code only.
>
> > + /
> > +
> > +#define pr_fmt(fmt) "ns8250: " fmt
> > +#define pr_log_level hvm_ns8250_log_level
> > +
> > +/ Development debugging /
> > +#define NS8250_LOG_LEVEL 0
> > +
> > +#include <xen/types.h>
> > +#include <xen/event.h>
> > +#include <xen/lib.h>
> > +#include <xen/errno.h>
> > +#include <xen/sched.h>
> > +#include <xen/trace.h>
> > +#include <xen/resource.h>
> > +#include <xen/ctype.h>
> > +#include <xen/param.h>
> > +#include <xen/console.h> / console_input_domid() */
>
>
> Includes would be better sorted alphabetically if possible.
Done.
>
> > +#include <asm/setup.h> /* max_init_domid */
> > +#include <asm/iocap.h>
> > +#include <asm/hvm/hvm.h>
> > +#include <asm/hvm/io.h>
> > +#include <asm/hvm/vuart_ns8250.h>
> > +
> > +#if !defined(pr_fmt)
> > +#define pr_fmt(fmt) fmt
> > +#endif
> > +
> > +#if !defined(pr_log_level)
> > +#define pr_log_level 0
> > +#endif
> > +
> > +#define pr_err(fmt, args...) \
> > + gprintk(KERN_ERR, pr_fmt(fmt), ## args)
> > +#define pr_warn(fmt, args...) \
> > + if (pr_log_level) gprintk(KERN_WARNING, pr_fmt(fmt), ## args)
> > +#define pr_info(fmt, args...) \
> > + if (pr_log_level) gprintk(KERN_INFO, pr_fmt(fmt), ## args)
> > +#define pr_debug(fmt, args...) \
> > + if (pr_log_level) gprintk(KERN_DEBUG, pr_fmt(fmt), ## args)
>
>
> Is there any reason you cannot directly use gprintk() and need those
> wrappers?
Yes, I need to control emulator's printouts w/o changing global setting so
I can debug it; I plan for MMIO-based UART which will need more debugging.
>
> If the code has been imported from another project it would be good to
> have a reference, so that we can pickup updates in the future.
I looked at QEMU, bhyve and ACRN emulators as hints.
>
> > +
> > +/*
> > + * NS8250 emulator state machine logging (development only)
> > + * FIXME: use similar to parse_guest_loglvl()
> > + */
> > +static unsigned int __read_mostly hvm_ns8250_log_level = NS8250_LOG_LEVEL;
> > +integer_param("hvm.ns8250.log_level", hvm_ns8250_log_level);
>
>
> WE don't have any existing instances of command line options with
> dots, and also the documentation addition to xen-command-line.pandoc
> seems to be missing from this patch.
I reworked these options to Kconfig for now. Kconfig looks a better
alternative to control settings globally.
>
> My recommendation would be that the code here just uses normal logs
> levels, users can adjust the minimum log level of pritned messages.
> Adding ad-hoc log level settings for each subsystem just causes
> confusion.
I think I want to stick to having a way to control the verbosity of that
emulator independently of the rest of Xen subsystems. That helps debugging
this code. Initially, I looked into re-using HVM_DBG_LOG() facility, but
then decided against using it because it does not have a fine grain control
over debugging and it will be harder to port this emulator for other
architectures in the future.
>
> > +
> > +/*
> > + * Default emulated NS8250 resources.
> > + * If not specified, COM1 (I/O port 0x3f8, IRQ#4) is emulated.
> > + * FIXME: follow Linux'es console= syntax or re-use
> > + * ns16550_parse_port_config().
> > + */
> > +static char __read_mostly hvm_ns8250_console[64];
> > +string_param("hvm.ns8250.console", hvm_ns8250_console);
>
>
> Same here, there seems to be no documentation about this option. And
> you likely want this to be a custom_param so you can do the parsing
> directly instead of storing into a buffer for later parsing.
>
> > +
> > +/* I/O access mask */
> > +static const uint32_t io_access_mask[] = {
> > + [0] = 0X00000000U,
> > + [1] = 0X000000FFU,
> > + [2] = 0X0000FFFFU,
> > + [4] = 0XFFFFFFFFU,
>
>
> lowercase x please.
Fixed.
>
> > +};
> > +
> > +/*
> > + * Legacy IBM PC NS8250 resources.
> > + * There are only 4 I/O port ranges, hardcoding all of them here.
> > + */
> > +static const struct {
> > + const char *name;
> > + const struct resource *res;
> > +} ns8250_x86_legacy_uarts[4] = {
> > + [0] = {
> > + .name = "com1",
> > + .res = (const struct resource[]){
> > + { .type = IORESOURCE_IO, .addr = 0x3F8, .size = UART_MAX },
> > + { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
> > + { .type = IORESOURCE_UNKNOWN },
> > + },
> > + },
> > + [1] = {
> > + .name = "com2",
> > + .res = (const struct resource[]){
> > + { .type = IORESOURCE_IO, .addr = 0x2F8, .size = UART_MAX },
> > + { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
> > + { .type = IORESOURCE_UNKNOWN },
> > + },
> > + },
> > + [2] = {
> > + .name = "com3",
> > + .res = (const struct resource[]){
> > + { .type = IORESOURCE_IO, .addr = 0x3E8, .size = UART_MAX },
> > + { .type = IORESOURCE_IRQ, .addr = 4, .size = 1 },
> > + { .type = IORESOURCE_UNKNOWN },
> > + },
> > + },
> > + [3] = {
> > + .name = "com4",
> > + .res = (const struct resource[]){
> > + { .type = IORESOURCE_IO, .addr = 0x2E8, .size = UART_MAX },
> > + { .type = IORESOURCE_IRQ, .addr = 3, .size = 1 },
> > + { .type = IORESOURCE_UNKNOWN },
> > + },
> > + },
> > +};
> > +
> > +static bool ns8250_fifo_rx_empty(struct vuart_ns8250 *vdev)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
>
>
> const here and in the function parameter.
Done.
>
> > +
> > + return cons->in_prod == cons->in_cons;
> > +}
> > +
> > +static bool ns8250_fifo_rx_full(struct vuart_ns8250 *vdev)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
>
>
> const here and in the function parameter.
Done.
>
> > +
> > + return cons->in_prod - cons->in_cons == sizeof(cons->in);
> > +}
> > +
> > +static void ns8250_fifo_rx_reset(struct vuart_ns8250 *vdev)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
> > +
> > + cons->in_cons = cons->in_prod;
> > +}
> > +
> > +static int ns8250_fifo_rx_getchar(struct vuart_ns8250 *vdev)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
> > + int rc = -1;
>
>
> -ENOENT maybe instead of -1?
With -1 I do not have to filter out the error codes, the value can be directly
returned to the guest, 0xff will be eventually interpreted as a break signal
in the guest OS.
Changed to -ENODATA and plumbed error checking where necessary.
>
> > +
> > + if ( !ns8250_fifo_rx_empty(vdev) )
> > + {
> > + rc = cons->in[MASK_XENCONS_IDX(cons->in_cons, cons->in)];
> > + cons->in_cons++;
> > + }
> > +
> > + return rc;
> > +}
> > +
> > +static int ns8250_fifo_rx_putchar(struct vuart_ns8250 *vdev, char c)
> > +{
> > + struct xencons_interface cons = vdev->cons;
> > + int rc = 0;
> > +
> > + /
> > + * FIFO-less 8250/16450 UARTs: newly arrived word overwrites the contents
> > + * of the THR.
> > + /
> > + if ( ns8250_fifo_rx_full(vdev) )
> > + {
> > + ns8250_fifo_rx_reset(vdev);
> > + rc = -ENOSPC;
> > + }
> > +
> > + cons->in[MASK_XENCONS_IDX(cons->in_prod, cons->in)] = c;
> > + cons->in_prod++;
> > +
> > + return rc;
> > +}
> > +
> > +/
> > + * Flush cached output to Xen console.
> > + * Can be called from ns8250_exit().
> > + */
> > +static void ns8250_fifo_tx_reset(struct vuart_ns8250 *vdev)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
> > +
> > + if ( cons->out_prod == 0 )
>
>
> Don't you need to check that cons->out_prod == cons->out_cons instead?
xencons_interface usage here is a bit awkward.
The reason for that is I want to print messages on the physical console w/o
fragmenting them w/ "(XEN)" and timestamps, etc. prefixes -
NS16550-compatible UART FIFO is only 16 characters.
The idea is to collect the guest OS output until '\n' or until the
`size - 1` condition and then send the collected output all at once
to the physical console followed by resetting out_prod to 0.
This works fine for the debugging purposes (the main goal of the
emulator) and the baud rate is not emulated anyway (one of the limitations
of the emulator) - i.e. there's no timer for draining TX buffer.
With that, checking for 0 was enough.
Fixed.
>
> > + return;
> > +
> > + cons->out[cons->out_prod++] = '\0';
>
>
> You need to use MASK_XENCONS_IDX() otherwise this could result in a
> buffer overflow?
>
> If you expect (because of checks in other places) out_prod to always
> be < ring size - 1, please add an assert to that extent here. But see
> below about the usage of the ring indexes.
Added assertions.
>
> Also, no need for the trailing increment, you will unconditionally
> reset out_prod to 0 just below.
Fixed.
>
> > +
> > + /*
> > + * NB: do not show domain ID if the domain owning the virtual UART also
> > + * owns Xen input console.
> > + */
> > + if ( vdev->owner->domain_id == console_owner_domid() )
> > + printk_common("%s", cons->out);
> > + else
> > + guest_printk(vdev->owner, "%s", cons->out);
> > +
> > + cons->out_prod = 0;
>
>
> You should rather do cons->out_cons = cons->out_prod?
>
>
> Wait, you seem to use the out buffer differently than the input one,
> and only advance out_prod but not out_cons?
>
> It seems weird to drive the 'in' ring using both indexes, while the
> 'out' ring is just using one index.
Correct, the awkward way is because I need to accumulate long guest
output until '\n' before sending it all at once to Xen console.
>
> > +}
> > +
> > +/*
> > + * Send a character to Xen console.
> > + */
> > +static void ns8250_fifo_tx_putchar(struct vuart_ns8250 *vdev, char ch)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
> > +
> > + if ( !isconsole(ch) )
> > + return;
> > +
> > + cons->out[cons->out_prod] = ch;
> > + cons->out_prod++;
> > +
> > + if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1
> > + || ch == '\n' || ch == '\0' )
>
>
> Bad indentation, should be:
>
> if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1 ||
>
> ch == '\n' || ch == '\0' )
Fixed.
>
> Albeit I'm not sure you need the '\0' check, as isconsole('\0') will
> already return false?
>
> > + ns8250_fifo_tx_reset(vdev);
> > +}
> > +
> > +static bool cf_check ns8250_iir_check_lsi(struct vuart_ns8250 *vdev)
>
>
> vdev should be const.
Done.
>
> > +{
> > + return !!( vdev->regs[UART_LSR] & UART_LSR_MASK );
>
>
> Extra spaces around the parentheses.
Done.
>
> > +}
> > +
> > +static bool cf_check ns8250_iir_check_rda(struct vuart_ns8250 *vdev)
> > +{
> > + return !ns8250_fifo_rx_empty(vdev);
> > +}
> > +
> > +static bool cf_check ns8250_iir_check_thr(struct vuart_ns8250 *vdev)
> > +{
> > + return !!( vdev->flags & NS8250_IRQ_THRE_PENDING );
> > +}
> > +
> > +static bool cf_check ns8250_iir_check_msi(struct vuart_ns8250 *vdev)
>
>
> const for all the 3 vdev parameters above.
Yep, missed those. Done.
>
> > +{
> > + return !!( vdev->regs[UART_MSR] & UART_MSR_DELTA );
>
>
> Extra spaces around the parentheses.
Done.
>
> > +}
> > +
> > +/*
> > + * Interrupt identity reasons by priority.
> > + * NB: highest priority are at lower indexes.
> > + */
> > +static const struct {
> > + uint8_t ier_mask;
> > + uint8_t iir_mask;
> > + bool (*iir_check)(struct vuart_ns8250 *vdev);
> > +} iir_by_prio[] = {
> > + [0] = { UART_IER_ELSI, UART_IIR_LSI, ns8250_iir_check_lsi },
> > + [1] = { UART_IER_ERDAI, UART_IIR_RDA, ns8250_iir_check_rda },
> > + [2] = { UART_IER_ETHREI, UART_IIR_THR, ns8250_iir_check_thr },
> > + [3] = { UART_IER_EMSI, UART_IIR_MSI, ns8250_iir_check_msi },
>
>
> You don't need the explicit array indexes (at least with the ones you
> are specifying here).
>
> I think those interrupt reasons are not likely to change, and the
> checker for each reason is a one line function. It would be better to
> open-code the checking in ns8250_irq_reason(), as that will avoid the
> indirect function call.
>
> Otherwise iir_by_prio array should be declared in the scope of
> ns8250_irq_reason(), as that's the only function where it's used.
Moved iir_by_prio in scope of xxx_irq_reason()
>
> > +};
> > +
> > +/*
> > + * Define the interrupt identity reason.
> > + * NB: NS8250 always reports high priority events first.
> > + */
> > +static uint8_t ns8250_irq_reason(struct vuart_ns8250 *vdev)
> > +{
> > + int i;
>
>
> unsigned int.
Done.
>
> > +
> > + ASSERT( spin_is_locked(&vdev->lock) );
>
>
> Extra spaces around the parentheses.
Done.
>
> > + for ( i = 0; i < ARRAY_SIZE(iir_by_prio); i++ )
> > + {
> > + if ( (vdev->regs[UART_IER] & iir_by_prio[i].ier_mask)
> > + && iir_by_prio[i].iir_check(vdev) )
>
>
> Wrong placement of the &&, plus indentation.
Sorry, muscle memory; fixed.
>
> > + return iir_by_prio[i].iir_mask;
> > + }
> > +
> > + return UART_IIR_NOINT;
> > +}
> > +
> > +/*
> > + * Assert virtual NS8250 interrupt line.
> > + */
> > +static void ns8250_irq_assert(struct vuart_ns8250 *vdev)
> > +{
> > + uint8_t iir;
> > +
> > + iir = ns8250_irq_reason(vdev);
> > + if (iir & UART_IIR_NOINT)
>
>
> Missing spaces around the parentheses.
Fixed.
>
> > + hvm_irq_lower(vdev->owner, vdev->irq);
> > + else
> > + hvm_irq_raise(vdev->owner, vdev->irq);
>
>
> I think you should use hvm_isa_irq_{,de}assert(), as the interrupt
> will unconditionally be < 16?
Switched to hvm_isa_irq_{,de}assert().
>
> > +
> > + pr_debug("IRQ#%d %x %s\n", vdev->irq, iir,
> > + !!(iir & UART_IIR_NOINT) ? "lower" : "raise");
>
>
> hm, this will get very verbose. While it might have been helpful
> during development, I don't think it would be appropriate to print at
> any debug level.
That is one of the reasons why I have local pr_xxx() macros. These verbose
messages will be compiled out in the default vUART build.
>
> > +}
> > +
> > +/*
> > + * Emulate 8-bit write access to NS8250 register.
> > + */
> > +static int ns8250_io_write8(
> > + struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
> > +{
> > + uint8_t val;
> > + int rc = 0;
> > +
> > + val = *data;
>
>
> You can init val at declaration.
Sure; fixed.
>
> > +
> > + switch ( reg )
> > + {
> > + /* DLAB=0 /
> > + case UART_THR:
> > + if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
> > + {
> > + ns8250_fifo_rx_putchar(vdev, val);
> > + vdev->regs[UART_LSR] |= UART_LSR_OE;
> > + }
> > + else
> > + ns8250_fifo_tx_putchar(vdev, val);
> > +
> > + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> > +
> > + break;
> > +
> > + case UART_IER:
> > + if ( val & vdev->regs[UART_IER] & UART_IER_ETHREI )
> > + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> > +
> > + vdev->regs[UART_IER] = val & UART_IER_MASK;
> > +
> > + break;
> > +
> > + case UART_FCR: / WO /
> > + if ( val & UART_FCR_CLRX )
> > + ns8250_fifo_rx_reset(vdev);
> > +
> > + if ( val & UART_FCR_CLTX )
> > + ns8250_fifo_tx_reset(vdev);
> > +
> > + if ( !(val & UART_FCR_ENABLE) )
> > + val = 0;
> > +
> > + vdev->regs[UART_FCR] = val & (UART_FCR_ENABLE |
> > + UART_FCR_DMA |
> > + UART_FCR_TRG_MASK);
> > +
> > + break;
> > +
> > + case UART_LCR:
> > + vdev->regs[UART_LCR] = val;
> > + break;
> > +
> > + case UART_MCR: {
> > + uint8_t msr_curr, msr_next, msr_delta;
> > +
> > + msr_curr = vdev->regs[UART_MSR];
> > + msr_next = 0;
> > + msr_delta = 0;
> > +
> > + / Set modem status /
> > + if ( val & UART_MCR_LOOP )
> > + {
> > + if ( val & UART_MCR_DTR )
> > + msr_next |= UART_MSR_DSR;
> > + if ( val & UART_MCR_RTS )
> > + msr_next |= UART_MSR_CTS;
> > + if ( val & UART_MCR_OUT1 )
> > + msr_next |= UART_MSR_RI;
> > + if ( val & UART_MCR_OUT2 )
> > + msr_next |= UART_MSR_DCD;
> > + }
> > + else
> > + msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
> > +
> > + / Calculate changes in modem status /
> > + if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
> > + msr_delta |= UART_MSR_DCTS;
> > + if ( (msr_curr & UART_MCR_RTS) ^ (msr_next & UART_MCR_RTS) )
> > + msr_delta |= UART_MSR_DDSR;
> > + if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
> > + msr_delta |= UART_MSR_TERI;
> > + if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
> > + msr_delta |= UART_MSR_DDCD;
> > +
> > + vdev->regs[UART_MCR] = val & UART_MCR_MASK;
> > + vdev->regs[UART_MSR] = msr_next | msr_delta;
> > +
> > + break;
> > + }
> > +
> > + case UART_LSR: / RO /
> > + case UART_MSR: / RO */
> > + rc = -EINVAL;
> > + break;
>
>
> Why are those not handled by the default case below? Is there any
> reason to explicitly mention those cases?
Yes: the intent was to be deliberately explicit so it is easier to
understand this code in the future.
>
> > +
> > + /*
> > + * NB: Firmware like OVMF rely on SCR presence to initialize the ns8250
> > + * driver.
> > + /
> > + case UART_SCR:
> > + vdev->regs[UART_SCR] = val;
> > + break;
> > +
> > + / DLAB=1 */
> > + case UART_MAX + UART_DLL:
> > + vdev->dl = (vdev->dl & 0xFF00U) | val;
> > + break;
> > +
> > + case UART_MAX + UART_DLM:
> > + vdev->dl = (val << 8) | (vdev->dl & 0x00FFU);
> > + break;
> > +
> > + default:
> > + rc = -EINVAL;
> > + break;
>
>
> Returning -EINVAL here is not correct I think, as the error gets
> propagated into the return of the IO handler. Those handlers expect
> to return a code in the range of X86EMUL_OKAY (see x86_emulate.h).
>
> But most importantly, what do you expect the caller to do with such
> error code? The access must be handled by the console driver, as it
> belongs to it's range of IO ports. What would hardware do in this
> case, ignore the write and continue operation?
This I overlooked while doing self-review, thanks.
The initial idea was to assert the virtual IRQ only if no "errors" returned
from the register I/O access emulation code. But then I forgot to clean
that up.
Fixed.
>
> If so, there's no point in returning any error from
> ns8250_io_write8(), the best would be to log a debug message in case
> of ignored accesses. This likely applies to all the handlers
> implemented below.
Yep, agree; fixed.
>
> > + }
> > +
> > + return rc;
> > +}
> > +
> > +/*
> > + * Emulate 16-bit write access to NS8250 register.
> > + * NB: some guest OSes use outw() to access UART_DLL.
> > + */
> > +static int ns8250_io_write16(
> > + struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
> > +{
> > + int rc;
> > +
> > + switch ( reg )
> > + {
> > + case UART_MAX + UART_DLL:
> > + vdev->dl = data;
> > + rc = 0;
> > + break;
> > +
> > + default:
> > + rc = -EINVAL;
> > + break;
> > + }
> > +
> > + return rc;
> > +}
> > +
> > +/
> > + * Emulate write access to NS8250 register.
> > + */
> > +static int ns8250_io_write(
> > + struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
> > +{
> > + int rc = -EINVAL;
> > +
> > + switch ( size )
> > + {
> > + case 1:
> > + rc = ns8250_io_write8(vdev, reg, (uint8_t *)data);
> > + break;
> > +
> > + case 2:
> > + rc = ns8250_io_write16(vdev, reg, (uint16_t )data);
> > + break;
> > +
> > + default:
> > + break;
> > + }
> > +
> > + ns8250_irq_assert(vdev);
> > +
> > + return rc;
> > +}
> > +
> > +/
> > + * Emulate 8-bit read access to NS8250 register.
> > + */
> > +static int ns8250_io_read8(
> > + struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
> > +{
> > + int rc = 0;
> > + uint8_t val;
>
>
> In order to avoid unintentionally leaking stack contents, it would be
> best to initialize val at declaration:
Done.
>
> uint8_t val = ~0;
>
> > +
> > + switch ( reg )
> > + {
> > + /* DLAB=0 */
> > + case UART_RBR:
> > + val = (uint8_t)ns8250_fifo_rx_getchar(vdev);
>
>
> You seem to ignore that ns8250_fifo_rx_getchar() can return an error,
> is it intended to just propagate the error to the caller then?
The idea here is that UART_RBR read will emulate 0xff in case of RX FIFO
is empty which should be treated as a break signal by the guest OS.
I reworked that part so the code is followed easily.
>
> > + /* NB: do not forget to clear overrun condition /
> > + vdev->regs[UART_LSR] &= ~UART_LSR_OE;
> > + break;
> > +
> > + case UART_IER: / RO /
> > + val = vdev->regs[UART_IER];
> > + break;
> > +
> > + case UART_IIR:
> > + val = ns8250_irq_reason(vdev);
> > + if ( val & UART_IIR_THR )
> > + vdev->flags &= ~NS8250_IRQ_THRE_PENDING;
> > +
> > + if ( vdev->regs[UART_FCR] & UART_FCR_ENABLE )
> > + val |= UART_IIR_FE_MASK;
> > +
> > + break;
> > +
> > + case UART_LCR:
> > + val = vdev->regs[UART_LCR];
> > + break;
> > +
> > + case UART_MCR:
> > + val = vdev->regs[UART_MCR];
> > + break;
> > +
> > + case UART_LSR:
> > + val = vdev->regs[UART_LSR] | UART_LSR_THRE | UART_LSR_TEMT;
> > + if ( ns8250_fifo_rx_empty(vdev) )
> > + val &= ~UART_LSR_DR;
> > + else
> > + val |= UART_LSR_DR;
> > +
> > + vdev->regs[UART_LSR] = val & ~UART_LSR_MASK;
> > +
> > + break;
> > +
> > + case UART_MSR:
> > + val = vdev->regs[UART_MSR];
> > + vdev->regs[UART_MSR] &= ~UART_MSR_DELTA;
> > + break;
> > +
> > + case UART_SCR:
> > + val = vdev->regs[UART_SCR];
> > + break;
> > +
> > + / DLAB=1 */
> > + case UART_MAX + UART_DLL:
> > + val = vdev->dl & 0xFFU;
> > + break;
> > +
> > + case UART_MAX + UART_DLM:
> > + val = vdev->dl >> 8;
> > + break;
> > +
> > + default:
> > + val = (uint8_t)io_access_mask[1];
>
>
> Hm, not sure why you need this mask, isn't it OK to just do val = ~0;?
Dropped the mask.
>
> However see comment above about initializing at definition.
>
> > + rc = -EINVAL;
> > + break;
> > + }
> > +
> > + data = val;
> > +
> > + return rc;
> > +}
> > +
> > +/
> > + * Emulate 16-bit read access to NS8250 register.
> > + */
> > +static int ns8250_io_read16(
> > + struct vuart_ns8250 *vdev, uint32_t reg, uint16_t *data)
> > +{
> > + uint16_t val;
>
>
> Same comment as ns8250_io_read8() about initializing val at definition
> and not using io_access_mask.
Done.
>
> > + int rc;
> > +
> > + switch ( reg )
> > + {
> > + case UART_MAX + UART_DLL:
> > + val = vdev->dl;
> > + rc = 0;
> > + break;
> > +
> > + default:
> > + val = (uint16_t)io_access_mask[2];
> > + rc = -EINVAL;
> > + break;
> > + }
> > +
> > + data = val;
> > +
> > + return rc;
> > +}
> > +
> > +/
> > + * Emulate read access to NS8250 register.
> > + */
> > +static int ns8250_io_read(
> > + struct vuart_ns8250 *vdev, uint8_t reg, uint32_t size, uint32_t *data)
> > +{
> > + int rc;
> > +
> > + switch ( size )
> > + {
> > + case 1:
> > + rc = ns8250_io_read8(vdev, reg, (uint8_t *)data);
> > + break;
> > +
> > + case 2:
> > + rc = ns8250_io_read16(vdev, reg, (uint16_t *)data);
>
>
> I get the feeling you could handle both 1 and 2 byte accesses in the
> same function, as there's just a single register that allows 2 byte
> accesses.
I think it is possible to merge 1 and 2 bytes accesses. I wrote it this
way because it was easy to follow what's emulated. I kept this code as is
for now.
>
> Is the split done because further (to be implemented) features will
> require addition 2 byte accesses?
It does not seem there will be special 2 byte accesses involved for
MMIO-based UARTs.
>
> > + break;
> > +
> > + default:
> > + *data = io_access_mask[size];
> > + rc = -EINVAL;
> > + break;
> > + }
> > +
> > + ns8250_irq_assert(vdev);
> > +
> > + return rc;
> > +}
> > +
> > +static const char *ns8250_regname(
> > + const struct vuart_ns8250 *vdev, uint32_t reg, int dir)
> > +{
> > + static const char reg_names[UART_MAX + 2][2] = {
> > + / register W R */
> > + [UART_RBR] = { "THR", "RBR" },
> > + [UART_IER] = { "IER", "IER" },
> > + [UART_IIR] = { "FCR", "IIR" },
> > + [UART_LCR] = { "LCR", "LCR" },
> > + [UART_MCR] = { "MCR", "MCR" },
> > + [UART_LSR] = { "LSR", "LSR" },
> > + [UART_MSR] = { "MSR", "MSR" },
> > + [UART_SCR] = { "SCR", "SCR" },
> > + [UART_MAX + UART_DLL] = { "DLL", "DLL" },
> > + [UART_MAX + UART_DLM] = { "DLM", "DLM" },
> > + };
> > +
>
>
> To be in the safe saide I would assert that 'reg' and 'dir' are
> between the array bounds.
I dropped this function entirely.
>
> > + return reg_names[reg][dir];
> > +}
> > +
> > +/*
> > + * Emulate I/O access to NS8250 register.
> > + */
> > +static int cf_check ns8250_io_handle(
> > + int dir, unsigned int addr, unsigned int size, uint32_t *data)
> > +{
> > +#define op(dir) (((dir) == IOREQ_WRITE) ? 'W' : 'R')
> > + struct domain *d = rcu_lock_current_domain();
> > + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> > + uint32_t offset, reg;
> > + int rc;
> > +
> > + spin_lock(&vdev->lock);
> > +
> > + BUG_ON( vdev->owner != d );
>
>
> Extra spaces around the parentheses.
Done.
>
> However I would rather use:
>
> if ( vdev->owner != d )
>
> {
> gprintk(XENLOG_ERR, "vUART owner %pd doesn't match current domain\n",
> vdev->owner);
>
> ASSERT_UNREACHABLE();
> rcu_unlock_domain(d);
> return X86EMU_OKAY;
> }
>
> And place it before the spin_lock() call.
Thank you.
>
> > +
> > + if ( !(vdev->flags & NS8250_READY) )
> > + {
> > + pr_err("%c io 0x%04x %d 0x%08"PRIx32": propagate to external I/O emulator\n",
> > + op(dir), addr, size, *data);
> > + rc = X86EMUL_UNHANDLEABLE;
>
>
> I think you need to unconditionally return X86EMU_OKAY and just ignore
> the access. I assume there's no point in attempting to forward this
> access to any other handler, as it must be handled by the vuart
> driver.
Agreed, that is "the user has configured vUART" case, so all accesses
shall be trapped by the emulator.
Fixed.
>
> > + goto out;
> > + }
> > +
> > + reg = addr - vdev->io_addr;
> > + BUG_ON( reg >= UART_MAX );
>
>
> If possible, might be best to use a construct similar to the one
> proposed above with ASSERT_UNREACHABLE().
Done.
>
> > + if ( reg % size != 0 )
>
>
> IS_ALIGNED(reg, size) might be clearer.
Done.
>
> > + {
> > + pr_err("%c 0x%04x %d 0x%08"PRIx32": unaligned access\n",
> > + op(dir), addr, size, data & io_access_mask[size]);
> > + rc = X86EMUL_OKAY;
> > + goto out;
> > + }
> > +
> > + / Redirect access to divisor latch registers */
> > + if ( !!(vdev->regs[UART_LCR] & UART_LCR_DLAB)
> > + && (reg == UART_DLL || reg == UART_DLM) )
>
>
> Indentation plus placement of the &&.
Fixed.
>
> > + offset = UART_MAX + reg;
> > + else
> > + offset = reg;
> > +
> > + if ( dir == IOREQ_WRITE )
> > + {
> > + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> > + op(dir), addr, size,
> > + *data & io_access_mask[size],
> > + ns8250_regname(vdev, offset, dir), reg);
> > + rc = ns8250_io_write(vdev, offset, size, data);
> > + }
> > + else
> > + {
> > + rc = ns8250_io_read(vdev, offset, size, data);
> > + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> > + op(dir), addr, size,
> > + *data & io_access_mask[size],
> > + ns8250_regname(vdev, offset, dir), reg);
>
>
> The pr_debug() are likely too verbose.
Yes, those are verbose if enabled.
>
> > + }
> > + if ( rc )
> > + pr_err("%c 0x%04x %d 0x%08"PRIx32": unsupported access\n",
> > + op(dir), addr, size, *data & io_access_mask[size]);
> > + rc = X86EMUL_OKAY;
> > +
> > +out:
> > + spin_unlock(&vdev->lock);
>
>
> You seem to have forgotten a rcu_unlock_domain() call here? (even if
> it's a no-op).
I did not add it exactly because it is a no-op.
Fixed.
>
> > +
> > + return rc;
> > +#undef op
> > +}
> > +
> > +/*
> > + * Parse virtual NS8250 configuration.
> > + * hvm.ns8250.console=[com1|com2|com3|com4]
> > + */
> > +static const struct resource ns8250_parse(void)
> > +{
> > + int i;
> > +
> > + for ( i = 0; i < ARRAY_SIZE(ns8250_x86_legacy_uarts); i++ )
> > + if ( !strcasecmp(hvm_ns8250_console, ns8250_x86_legacy_uarts[i].name) )
> > + return ns8250_x86_legacy_uarts[i].res;
> > +
> > + return ns8250_x86_legacy_uarts[0].res;
> > +}
> > +
> > +/
> > + * Claim virtual NS8250 resources to domain.
> > + */
> > +static int ns8250_claim(
> > + struct vuart_ns8250 *vdev, const struct resource *r, struct domain *d)
> > +{
> > + unsigned long size;
> > + unsigned long start;
> > + unsigned long end;
> > +
> > + vdev->irq = NO_IRQ;
> > + vdev->io_addr = IORESOURCE_UNKNOWN;
> > + vdev->io_size = IORESOURCE_UNKNOWN;
> > +
> > + foreach_resource(r)
> > + {
> > + if ( r->type & IORESOURCE_IO )
> > + {
> > + size = r->size;
> > + start = r->addr;
> > + end = r->addr + r->size - 1;
> > +
> > + if ( !ioports_access_permitted(d, start, end) )
> > + ioports_permit_access(d, start, end);
>
>
> Are you sure this is intended? By using ioports_permit_access() you
> are giving the domain access to the hardware (host) IO ports, and thus
> possibly avoiding the trapping into the IO handlers.
>
> However this is not very well-wired in HVM, because there's still an
> extra guest IO port -> host IO port translation that you are not
>
> adding.
>
> You shouldn't need the ioports_permit_access() for using the emulated
> vUART.
I see it now.
I understood it exactly the opposite way: ioports_permit_access() will
*lead* to trap on access.
Fixed.
Thanks a lot!
>
> > +
> > + register_portio_handler(d, start, size, ns8250_io_handle);
> > +
> > + /* Used to assert I/O port handler /
> > + vdev->io_addr = start;
> > + vdev->io_size = size;
> > + }
> > + else if ( r->type & IORESOURCE_IRQ )
> > + / "Claim" virtual IRQ; assumes no ISA-device IRQ sharing /
> > + vdev->irq = r->addr;
> > + else
> > + return -EINVAL;
> > + }
> > +
> > + if ( vdev->irq == NO_IRQ
> > + || vdev->io_addr == IORESOURCE_UNKNOWN
> > + || vdev->io_size == IORESOURCE_UNKNOWN )
> > + return -ENODEV;
> > +
> > + return 0;
> > +}
> > +
> > +/
> > + * Unclaim virtual NS8250 resources.
> > + */
> > +static void ns8250_unclaim(struct vuart_ns8250 *vdev, struct domain *d)
> > +{
> > + unsigned long size = vdev->io_size;
> > + unsigned long start = vdev->io_addr;
> > + unsigned long end = start + size - 1;
> > +
> > + if ( ioports_access_permitted(d, start, end) )
> > + ioports_deny_access(d, start, size);
> > +}
> > +
> > +static int ns8250_init(struct domain *d, const struct resource *r)
> > +{
> > + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> > + struct xencons_interface *cons;
> > + int rc;
> > +
> > + cons = _xzalloc(sizeof(*vdev->cons), sizeof(void *));
>
>
> xvzalloc(typeof(*vdev->cons));
Done.
>
> > + if ( cons == NULL )
> > + return -ENOMEM;
> > +
> > + rc = ns8250_claim(vdev, r, d);
> > + if ( rc )
> > + {
> > + xfree(cons);
> > + return rc;
> > + }
> > +
> > + spin_lock_init(&vdev->lock);
> > + hvm_irq_lower(d, vdev->irq);
> > +
> > + vdev->dl = (UART_CLOCK_HZ / 115200) >> 4; /* Report 115200 baud rate */
> > + vdev->cons = cons;
> > + vdev->owner = d;
> > + vdev->flags = NS8250_READY | NS8250_IRQ_THRE_PENDING;
> > +
> > + return 0;
> > +}
> > +
> > +static void ns8250_exit(struct domain *d)
> > +{
> > + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> > +
> > + spin_lock(&vdev->lock);
> > +
> > + if ( !(vdev->flags & NS8250_READY) )
> > + goto out;
> > +
> > + ns8250_unclaim(vdev, d);
> > + ns8250_fifo_tx_reset(vdev);
> > + xfree(vdev->cons);
> > +
> > + vdev->cons = NULL;
> > + vdev->owner = NULL;
> > + vdev->flags = 0;
> > +
> > +out:
> > + spin_unlock(&vdev->lock);
> > +}
> > +
> > +int vuart_putchar(struct vuart_ns8250 vdev, char ch)
> > +{
> > + int rc;
> > +
> > + spin_lock(&vdev->lock);
> > +
> > + if ( !(vdev->flags & NS8250_READY) )
> > + {
> > + rc = -ENODEV;
> > + goto out;
> > + }
> > +
> > + / Echo the user input on the console */
> > + printk("%c", ch);
>
>
> FWIW, I would move the printk() after the error checks, so that the
> character is only echoed if handled.
Done.
>
> > +
> > + /*
> > + * Device is in loopback mode; do nothing.
> > + /
> > + if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
> > + {
> > + rc = -EBUSY;
> > + goto out;
> > + }
> > +
> > + rc = ns8250_fifo_rx_putchar(vdev, ch);
> > + if ( rc == -ENOSPC )
> > + vdev->regs[UART_LSR] |= UART_LSR_OE | UART_LSR_DR;
> > + else
> > + / NB: UART_LSR_DR is also set when UART_LSR is accessed. /
> > + vdev->regs[UART_LSR] |= UART_LSR_DR;
> > +
> > + / FIXME: check FCR when to fire an interrupt */
> > + ns8250_irq_assert(vdev);
> > +
> > +out:
> > + spin_unlock(&vdev->lock);
> > +
> > + return rc;
> > +}
> > +
> > +int domain_vuart_init(struct domain *d)
> > +{
> > + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> > + const struct resource *r;
> > +
> > + memset(vdev, 0, sizeof(*vdev));
> > +
> > + r = ns8250_parse();
> > + if ( r != NULL )
> > + return ns8250_init(d, r);
> > +
> > + return -ENODEV;
> > +}
> > +
> > +void domain_vuart_free(struct domain d)
> > +{
> > + ns8250_exit(d);
> > +}
> > +
> > +/
> > + * Local variables:
> > + * mode: C
> > + * c-file-style: "BSD"
> > + * c-basic-offset: 4
> > + * indent-tabs-mode: nil
> > + * End:
> > + */
> > diff --git a/xen/arch/x86/include/asm/hvm/domain.h b/xen/arch/x86/include/asm/hvm/domain.h
> > index 333501d5f2ac01676646b9b277b551f06d43c3a5..d4ce25896259fc9763477e88d56bacbe4f78af5b 100644
> > --- a/xen/arch/x86/include/asm/hvm/domain.h
> > +++ b/xen/arch/x86/include/asm/hvm/domain.h
> > @@ -16,6 +16,7 @@
> > #include <asm/hvm/io.h>
> > #include <asm/hvm/vmx/vmcs.h>
> > #include <asm/hvm/svm/vmcb.h>
> > +#include <asm/hvm/vuart_ns8250.h>
> >
> > #ifdef CONFIG_MEM_SHARING
> > struct mem_sharing_domain
> > @@ -73,6 +74,10 @@ struct hvm_domain {
> > struct hvm_vioapic **vioapic;
> > unsigned int nr_vioapics;
> >
> > +#if defined(CONFIG_HAS_VUART_NS8250)
> > + struct vuart_ns8250 vuart;
>
>
> Since this is supposed to possibly be used by just a small amount of
> domain on the system, I would rather make this a pointer:
>
> struct vuart_ns8250 *vuart;
>
> And embed the xencons_ring inside of it directly, so that you just
> have to allocate vuart_ns8250.
Fixed.
I ended up having just
void *vuart;
in hvm_domain after addressing Jan's feedback.
That will also eliminate the need for NS8250_READY flag.
>
> > +#endif
> > +
> > /*
> > * hvm_hw_pmtimer is a publicly-visible name. We will defer renaming
> > * it to the more appropriate hvm_hw_acpi until the expected
> > diff --git a/xen/arch/x86/include/asm/hvm/vuart_ns8250.h b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..e1013751f955441a9089ea38c96c4605a7f4cb75
> > --- /dev/null
> > +++ b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
> > @@ -0,0 +1,75 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only /
> > +/
> > + * NS8250-compatible UART Emulator.
> > + */
> > +#if !defined(HVM__VUART_NS8250_H)
>
>
> As commented by Jan, better use #ifndef.
Done.
>
> > +#define HVM__VUART_NS8250_H
> > +
> > +#include <xen/spinlock.h>
> > +#include <xen/8250-uart.h>
> > +#include <public/io/console.h> /* xencons_interface /
> > +
> > +/
> > + * NS8250 emulator operational flags.
> > + /
> > +enum {
> > + / Emulator is ready /
> > + NS8250_READY = BIT(0, U),
> > + / Trigger re-delivery of THRE interrupt */
> > + NS8250_IRQ_THRE_PENDING = BIT(1, U),
>
>
> I'm unsure the unnamed enum buys you much here if you end up assigning
> values anyway. You might as well do:
>
> #define NS8250_READY BIT(0, U)
> #define NS8250_IRQ_THRE_PENDING BIT(1, U)
re: why enum: muscle memory.
NS8250_READY is gone now that initialization code is reworked.
I also dropped the other flag and dropped enum.
>
> It would be good if you could integrate this with the flags field
> being declared using DECLARE_BITMAP(). Otherwise you might need some
> build-time check to ensure max defined flag fits in the struct flags
> field.
Dropped flags field.
>
> > +};
> > +
> > +/*
> > + * Virtual NS8250 device state.
> > + /
> > +struct vuart_ns8250 {
> > + uint16_t dl; / Divisor Latch /
> > + uint8_t regs[UART_MAX]; / Registers */
>
>
> Doesn't regs already account for the divisor latch register?
No, in this version `regs` registers are for DLAB=0.
Registers are accessed differently in NS16550 depending on type of
access (R/W) and LCR contents (DLAB={0,1}).
I added some more comments; register emulation is updated in v3.
>
> > + uint32_t flags; /* Virtual device flags */
>
>
> See comment above about using DECLARE_BITMAP().
>
> > + uint64_t io_addr; /* Guest I/O region base address */
>
>
> IO space is limited to 16bits, hence there's no need to use a uint64_t
> to store the address. Either uint16_t, or just a plain unsigned int
> will suffice. Same for size below.
It is uint64_t for the follow on MMIO-based UART.
>
> > + uint64_t io_size; /* Guest I/O region size /
> > + int irq; / Guest IRQ# */
> > + struct xencons_interface cons; / Emulated RX/TX FIFOs */
>
>
> Any reason you re-use the xencons interface? And any reason it's a
> pointer instead of being part of vuart_ns8250 itself?
re: why re-use xencons: few reasons.
I decided to re-use something which is already invented in the code
base, rather then inventing my own buffering.
My understanding is that xencons will be needed for inter-domain
communication: xencons has pretty large buffers which may help
in case of slow domain. And I wanted to avoid guest OS printouts
"fragmentation" w/ prefixes printk injects into the each log message,
so large buffers should work around fragmenting messages.
re: why its a pointer: I did not think that d->arch.hvm can actually
contain just a pointer to vuart_ns16550 (I reworked it to `void *`).
That is pretty-much cut-n-paste from Arm's vpl011 design.
>
> > + struct domain owner; / Owner domain /
> > + spinlock_t lock; / Protection */
> > +};
> > +
> > +#if defined(CONFIG_HAS_VUART_NS8250)
> > +
> > +int vuart_putchar(struct vuart_ns8250 vdev, char ch);
> > +
> > +/
> > + * Match the names w/ arch/arm/vuart.h
> > + * FIXME: move to common vuart.h
> > + */
> > +int domain_vuart_init(struct domain *d);
> > +void domain_vuart_free(struct domain *d);
> > +
> > +#else
> > +
> > +static inline int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
> > +{
>
>
> Hard to tell as there are no users of vuart_putchar() in this patch,
> but it seems you might want an ASSERT_UNREACHABLE() here.
Addressed in v3.
>
> > + return -1;
> > +}
> > +
> > +static inline int domain_vuart_init(struct domain *d)
> > +{
> > + return -ENODEV;
> > +}
> > +
> > +static inline void domain_vuart_free(struct domain *d)
> > +{
>
>
> Both init and free calls are gated with domain_has_vuart(), so you
> might want to also add ASSERT_UNREACHABLE() here.
Done.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-16 15:04 ` Jan Beulich
2025-01-04 5:31 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-16 15:04 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Add initial in-hypervisor emulator for NS8250/NS16x50-compatible UARTs under
> CONFIG_HAS_VUART_NS8250.
>
> In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> early guest OS bringup debugging, because it eliminates dependency on the
> external emulator being operational by the time domains are created. Also,
> there's no early console facility similar to vpl011 to support x86 guest OS
> bring up.
>
> By default, CONFIG_HAS_VUART_NS8250 enables emulatio of NS8250 at I/O port
> 0x3f8, IRQ#4 in guest OS.
>
> Limitations:
> - Only x86;
> - Only Linux guest tested so far;
> - Only legacy COM{1,2,3,4} resources, no customization;
> - Only Xen console as a backend, no inter-domain communication (similar to
> vpl011 on Arm);
> - Only 8-bit characters;
> - Baud rate is not emulated;
> - FIFO-less mode is not emulated properly;
With in particular this, why would it be called 8250 emulation in the first
place? The driver Xen uses for itself is in ns16550.c; I'd suggest to call
the child here ns16550 emulation right away, using vns16550.c as the file
name.
> --- a/xen/arch/x86/hvm/Kconfig
> +++ b/xen/arch/x86/hvm/Kconfig
> @@ -61,3 +61,17 @@ config HVM_FEP
> for use in production.
>
> If unsure, say N.
> +
> +config HAS_VUART_NS8250
> + bool "NS8250-compatible UART Emulation"
HAS_* options may not have prompts; they merely declare something to the
rest of the build system.
> + depends on HVM && HAS_IOPORTS
Why HAS_IOPORTS?
> + default n
No need for this.
> --- a/xen/arch/x86/hvm/Makefile
> +++ b/xen/arch/x86/hvm/Makefile
> @@ -29,3 +29,4 @@ obj-y += vm_event.o
> obj-y += vmsi.o
> obj-y += vpic.o
> obj-y += vpt.o
> +obj-$(CONFIG_HAS_VUART_NS8250) += vuart_ns8250.o
If the vuart name pretix is to remain, then please avoid underscores in
the names of new files, in favor of dashes.
> --- /dev/null
> +++ b/xen/arch/x86/hvm/vuart_ns8250.c
> @@ -0,0 +1,886 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * NS8250-compatible UART Emulator.
> + *
> + * Limitations:
> + * - Only x86;
> + * - Only Linux guest tested so far;
> + * - Only legacy COM{1,2,3,4} resources, no customization;
> + * - Only Xen console as a backend, no inter-domain communication (similar to
> + * vpl011 on Arm);
> + * - Only 8-bit characters;
> + * - Baud rate is not emulated;
> + * - FIFO-less mode is not emulated properly;
> + * - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
> + * has special FCR handling;
> + * - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
> + * friends);
> + * - Assumes no ISA-device IRQ sharing;
> + * - MMIO-based UART is not supported;
> + * - PCI UART is not supported.
> + */
> +
> +#define pr_fmt(fmt) "ns8250: " fmt
> +#define pr_log_level hvm_ns8250_log_level
> +
> +/* Development debugging */
> +#define NS8250_LOG_LEVEL 0
> +
> +#include <xen/types.h>
> +#include <xen/event.h>
> +#include <xen/lib.h>
> +#include <xen/errno.h>
> +#include <xen/sched.h>
> +#include <xen/trace.h>
> +#include <xen/resource.h>
> +#include <xen/ctype.h>
> +#include <xen/param.h>
> +#include <xen/console.h> /* console_input_domid() */
> +#include <asm/setup.h> /* max_init_domid */
> +#include <asm/iocap.h>
> +#include <asm/hvm/hvm.h>
> +#include <asm/hvm/io.h>
> +#include <asm/hvm/vuart_ns8250.h>
> +
> +#if !defined(pr_fmt)
> +#define pr_fmt(fmt) fmt
> +#endif
> +
> +#if !defined(pr_log_level)
> +#define pr_log_level 0
> +#endif
> +
> +#define pr_err(fmt, args...) \
> + gprintk(KERN_ERR, pr_fmt(fmt), ## args)
> +#define pr_warn(fmt, args...) \
> + if (pr_log_level) gprintk(KERN_WARNING, pr_fmt(fmt), ## args)
> +#define pr_info(fmt, args...) \
> + if (pr_log_level) gprintk(KERN_INFO, pr_fmt(fmt), ## args)
> +#define pr_debug(fmt, args...) \
> + if (pr_log_level) gprintk(KERN_DEBUG, pr_fmt(fmt), ## args)
On top of Roger's remark here: _If_ you use such wrapper macros, then
please arrange for them to be usable in arbitrary context. Think of
if ( condition )
pr_info(...);
else
...
> +/*
> + * NS8250 emulator state machine logging (development only)
> + * FIXME: use similar to parse_guest_loglvl()
> + */
> +static unsigned int __read_mostly hvm_ns8250_log_level = NS8250_LOG_LEVEL;
> +integer_param("hvm.ns8250.log_level", hvm_ns8250_log_level);
How can this be a command line option, when there may be many domains
making use of the in-Xen driver? This and ...
> +/*
> + * Default emulated NS8250 resources.
> + * If not specified, COM1 (I/O port 0x3f8, IRQ#4) is emulated.
> + * FIXME: follow Linux'es console= syntax or re-use
> + * ns16550_parse_port_config().
> + */
> +static char __read_mostly hvm_ns8250_console[64];
> +string_param("hvm.ns8250.console", hvm_ns8250_console);
... this need to be per-domain settings; a command line option may be
applicable to Dom0 alone.
> +/* I/O access mask */
> +static const uint32_t io_access_mask[] = {
> + [0] = 0X00000000U,
> + [1] = 0X000000FFU,
> + [2] = 0X0000FFFFU,
> + [4] = 0XFFFFFFFFU,
> +};
I don't think this is needed; we're doing similar port I/O emulation in
various other places, without resorting to such arrays.
> +/*
> + * Legacy IBM PC NS8250 resources.
> + * There are only 4 I/O port ranges, hardcoding all of them here.
> + */
> +static const struct {
> + const char *name;
> + const struct resource *res;
> +} ns8250_x86_legacy_uarts[4] = {
> + [0] = {
> + .name = "com1",
> + .res = (const struct resource[]){
> + { .type = IORESOURCE_IO, .addr = 0x3F8, .size = UART_MAX },
Considering this, ...
> +static int ns8250_io_write8(
> + struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
> +{
> + uint8_t val;
> + int rc = 0;
> +
> + val = *data;
> +
> + switch ( reg )
> + {
> + /* DLAB=0 */
> + case UART_THR:
> + if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
> + {
> + ns8250_fifo_rx_putchar(vdev, val);
> + vdev->regs[UART_LSR] |= UART_LSR_OE;
> + }
> + else
> + ns8250_fifo_tx_putchar(vdev, val);
> +
> + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> +
> + break;
> +
> + case UART_IER:
> + if ( val & vdev->regs[UART_IER] & UART_IER_ETHREI )
> + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> +
> + vdev->regs[UART_IER] = val & UART_IER_MASK;
> +
> + break;
> +
> + case UART_FCR: /* WO */
> + if ( val & UART_FCR_CLRX )
> + ns8250_fifo_rx_reset(vdev);
> +
> + if ( val & UART_FCR_CLTX )
> + ns8250_fifo_tx_reset(vdev);
> +
> + if ( !(val & UART_FCR_ENABLE) )
> + val = 0;
> +
> + vdev->regs[UART_FCR] = val & (UART_FCR_ENABLE |
> + UART_FCR_DMA |
> + UART_FCR_TRG_MASK);
> +
> + break;
> +
> + case UART_LCR:
> + vdev->regs[UART_LCR] = val;
> + break;
> +
> + case UART_MCR: {
> + uint8_t msr_curr, msr_next, msr_delta;
> +
> + msr_curr = vdev->regs[UART_MSR];
> + msr_next = 0;
> + msr_delta = 0;
> +
> + /* Set modem status */
> + if ( val & UART_MCR_LOOP )
> + {
> + if ( val & UART_MCR_DTR )
> + msr_next |= UART_MSR_DSR;
> + if ( val & UART_MCR_RTS )
> + msr_next |= UART_MSR_CTS;
> + if ( val & UART_MCR_OUT1 )
> + msr_next |= UART_MSR_RI;
> + if ( val & UART_MCR_OUT2 )
> + msr_next |= UART_MSR_DCD;
> + }
> + else
> + msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
> +
> + /* Calculate changes in modem status */
> + if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
> + msr_delta |= UART_MSR_DCTS;
> + if ( (msr_curr & UART_MCR_RTS) ^ (msr_next & UART_MCR_RTS) )
> + msr_delta |= UART_MSR_DDSR;
> + if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
> + msr_delta |= UART_MSR_TERI;
> + if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
> + msr_delta |= UART_MSR_DDCD;
> +
> + vdev->regs[UART_MCR] = val & UART_MCR_MASK;
> + vdev->regs[UART_MSR] = msr_next | msr_delta;
> +
> + break;
> + }
> +
> + case UART_LSR: /* RO */
> + case UART_MSR: /* RO */
> + rc = -EINVAL;
> + break;
> +
> + /*
> + * NB: Firmware like OVMF rely on SCR presence to initialize the ns8250
> + * driver.
> + */
> + case UART_SCR:
> + vdev->regs[UART_SCR] = val;
> + break;
> +
> + /* DLAB=1 */
> + case UART_MAX + UART_DLL:
... how can you go at or past UART_MAX here and ...
> + vdev->dl = (vdev->dl & 0xFF00U) | val;
> + break;
> +
> + case UART_MAX + UART_DLM:
... here? I notice a caller up the tree sets things up like this, but this
feels pretty fragile. How would one easily spot all producers and consumers
without also hitting all other uses of UART_MAX?
> +static int cf_check ns8250_io_handle(
> + int dir, unsigned int addr, unsigned int size, uint32_t *data)
> +{
> +#define op(dir) (((dir) == IOREQ_WRITE) ? 'W' : 'R')
> + struct domain *d = rcu_lock_current_domain();
> + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> + uint32_t offset, reg;
> + int rc;
> +
> + spin_lock(&vdev->lock);
> +
> + BUG_ON( vdev->owner != d );
> +
> + if ( !(vdev->flags & NS8250_READY) )
> + {
> + pr_err("%c io 0x%04x %d 0x%08"PRIx32": propagate to external I/O emulator\n",
> + op(dir), addr, size, *data);
> + rc = X86EMUL_UNHANDLEABLE;
> + goto out;
> + }
> +
> + reg = addr - vdev->io_addr;
> + BUG_ON( reg >= UART_MAX );
> + if ( reg % size != 0 )
> + {
> + pr_err("%c 0x%04x %d 0x%08"PRIx32": unaligned access\n",
> + op(dir), addr, size, *data & io_access_mask[size]);
> + rc = X86EMUL_OKAY;
> + goto out;
> + }
> +
> + /* Redirect access to divisor latch registers */
> + if ( !!(vdev->regs[UART_LCR] & UART_LCR_DLAB)
> + && (reg == UART_DLL || reg == UART_DLM) )
> + offset = UART_MAX + reg;
> + else
> + offset = reg;
> +
> + if ( dir == IOREQ_WRITE )
> + {
> + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> + op(dir), addr, size,
> + *data & io_access_mask[size],
> + ns8250_regname(vdev, offset, dir), reg);
> + rc = ns8250_io_write(vdev, offset, size, data);
> + }
> + else
> + {
> + rc = ns8250_io_read(vdev, offset, size, data);
> + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> + op(dir), addr, size,
> + *data & io_access_mask[size],
> + ns8250_regname(vdev, offset, dir), reg);
> + }
> + if ( rc )
> + pr_err("%c 0x%04x %d 0x%08"PRIx32": unsupported access\n",
> + op(dir), addr, size, *data & io_access_mask[size]);
> + rc = X86EMUL_OKAY;
> +
> +out:
Nit: Missing indentation (see ./CODING_STYLE). Also elsewhere.
> --- /dev/null
> +++ b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
> @@ -0,0 +1,75 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * NS8250-compatible UART Emulator.
> + */
> +#if !defined(HVM__VUART_NS8250_H)
> +#define HVM__VUART_NS8250_H
> +
> +#include <xen/spinlock.h>
> +#include <xen/8250-uart.h>
> +#include <public/io/console.h> /* xencons_interface */
I assume you mean ...
> +/*
> + * NS8250 emulator operational flags.
> + */
> +enum {
> + /* Emulator is ready */
> + NS8250_READY = BIT(0, U),
> + /* Trigger re-delivery of THRE interrupt */
> + NS8250_IRQ_THRE_PENDING = BIT(1, U),
> +};
> +
> +/*
> + * Virtual NS8250 device state.
> + */
> +struct vuart_ns8250 {
> + uint16_t dl; /* Divisor Latch */
> + uint8_t regs[UART_MAX]; /* Registers */
> + uint32_t flags; /* Virtual device flags */
> + uint64_t io_addr; /* Guest I/O region base address */
> + uint64_t io_size; /* Guest I/O region size */
> + int irq; /* Guest IRQ# */
> + struct xencons_interface *cons; /* Emulated RX/TX FIFOs */
... this use, but that doesn't even require a forward decl of the struct
in C (in C++ such a forward decl would be all that's needed).
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2024-12-16 15:04 ` Jan Beulich
@ 2025-01-04 5:31 ` Denis Mukhin
2025-01-06 9:19 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 5:31 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Monday, December 16th, 2024 at 7:04 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Add initial in-hypervisor emulator for NS8250/NS16x50-compatible UARTs under
> > CONFIG_HAS_VUART_NS8250.
> >
> > In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> > early guest OS bringup debugging, because it eliminates dependency on the
> > external emulator being operational by the time domains are created. Also,
> > there's no early console facility similar to vpl011 to support x86 guest OS
> > bring up.
> >
> > By default, CONFIG_HAS_VUART_NS8250 enables emulatio of NS8250 at I/O port
> > 0x3f8, IRQ#4 in guest OS.
> >
> > Limitations:
> > - Only x86;
> > - Only Linux guest tested so far;
> > - Only legacy COM{1,2,3,4} resources, no customization;
> > - Only Xen console as a backend, no inter-domain communication (similar to
> > vpl011 on Arm);
> > - Only 8-bit characters;
> > - Baud rate is not emulated;
> > - FIFO-less mode is not emulated properly;
>
>
> With in particular this, why would it be called 8250 emulation in the first
> place? The driver Xen uses for itself is in ns16550.c; I'd suggest to call
> the child here ns16550 emulation right away, using vns16550.c as the file
> name.
NS8250 is the predecessor of NS16550, registers are defined in 8250-uart.h,
hence I used vuart_ns8250.c.
I do not have a strong opinion on this naming. 16550 makes sense because
all UARTs have a FIFO now.
Renamed to vuart-ns16550.c.
>
> > --- a/xen/arch/x86/hvm/Kconfig
> > +++ b/xen/arch/x86/hvm/Kconfig
> > @@ -61,3 +61,17 @@ config HVM_FEP
> > for use in production.
> >
> > If unsure, say N.
> > +
> > +config HAS_VUART_NS8250
> > + bool "NS8250-compatible UART Emulation"
>
>
> HAS_* options may not have prompts; they merely declare something to the
> rest of the build system.
There are examples in the code using HAS_xxx configuration exactly the way
I used it. Specifically, all physical UART drivers are declared under HAS_xxx
(drivers/char/Kconfig).
I reworked that part.
>
> > + depends on HVM && HAS_IOPORTS
>
>
> Why HAS_IOPORTS?
It is meant to highlight the fact that MMIO-based UART is not supported.
It is not currently possible to enable the emulator for, say, Arm platforms.
>
> > + default n
>
>
> No need for this.
Fixed.
>
> > --- a/xen/arch/x86/hvm/Makefile
> > +++ b/xen/arch/x86/hvm/Makefile
> > @@ -29,3 +29,4 @@ obj-y += vm_event.o
> > obj-y += vmsi.o
> > obj-y += vpic.o
> > obj-y += vpt.o
> > +obj-$(CONFIG_HAS_VUART_NS8250) += vuart_ns8250.o
>
>
> If the vuart name pretix is to remain, then please avoid underscores in
> the names of new files, in favor of dashes.
I've seen such request few times on the mailing list and it seems the
recommendation is not followed all the time in the code base.
It's just all files in xen/arch/x86/hvm have underscores instead of
dashes.
IMO, this rule needs an explicit documentation in the coding style
guide. I'm happy to follow either dash- or underscore-way.
Addressed.
>
> > --- /dev/null
> > +++ b/xen/arch/x86/hvm/vuart_ns8250.c
> > @@ -0,0 +1,886 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only /
> > +/
> > + * NS8250-compatible UART Emulator.
> > + *
> > + * Limitations:
> > + * - Only x86;
> > + * - Only Linux guest tested so far;
> > + * - Only legacy COM{1,2,3,4} resources, no customization;
> > + * - Only Xen console as a backend, no inter-domain communication (similar to
> > + * vpl011 on Arm);
> > + * - Only 8-bit characters;
> > + * - Baud rate is not emulated;
> > + * - FIFO-less mode is not emulated properly;
> > + * - RX FIFO interrupt moderation (FCR) is not emulated properly, TL16C750
> > + * has special FCR handling;
> > + * - No integration w/ VM snapshotting (HVM_REGISTER_SAVE_RESTORE() and
> > + * friends);
> > + * - Assumes no ISA-device IRQ sharing;
> > + * - MMIO-based UART is not supported;
> > + * - PCI UART is not supported.
> > + /
> > +
> > +#define pr_fmt(fmt) "ns8250: " fmt
> > +#define pr_log_level hvm_ns8250_log_level
> > +
> > +/ Development debugging /
> > +#define NS8250_LOG_LEVEL 0
> > +
> > +#include <xen/types.h>
> > +#include <xen/event.h>
> > +#include <xen/lib.h>
> > +#include <xen/errno.h>
> > +#include <xen/sched.h>
> > +#include <xen/trace.h>
> > +#include <xen/resource.h>
> > +#include <xen/ctype.h>
> > +#include <xen/param.h>
> > +#include <xen/console.h> / console_input_domid() /
> > +#include <asm/setup.h> / max_init_domid */
> > +#include <asm/iocap.h>
> > +#include <asm/hvm/hvm.h>
> > +#include <asm/hvm/io.h>
> > +#include <asm/hvm/vuart_ns8250.h>
> > +
> > +#if !defined(pr_fmt)
> > +#define pr_fmt(fmt) fmt
> > +#endif
> > +
> > +#if !defined(pr_log_level)
> > +#define pr_log_level 0
> > +#endif
> > +
> > +#define pr_err(fmt, args...) \
> > + gprintk(KERN_ERR, pr_fmt(fmt), ## args)
> > +#define pr_warn(fmt, args...) \
> > + if (pr_log_level) gprintk(KERN_WARNING, pr_fmt(fmt), ## args)
> > +#define pr_info(fmt, args...) \
> > + if (pr_log_level) gprintk(KERN_INFO, pr_fmt(fmt), ## args)
> > +#define pr_debug(fmt, args...) \
> > + if (pr_log_level) gprintk(KERN_DEBUG, pr_fmt(fmt), ## args)
>
>
> On top of Roger's remark here: If you use such wrapper macros, then
> please arrange for them to be usable in arbitrary context. Think of
>
> if ( condition )
> pr_info(...);
> else
> ...
Done.
>
> > +/*
> > + * NS8250 emulator state machine logging (development only)
> > + * FIXME: use similar to parse_guest_loglvl()
> > + */
> > +static unsigned int __read_mostly hvm_ns8250_log_level = NS8250_LOG_LEVEL;
> > +integer_param("hvm.ns8250.log_level", hvm_ns8250_log_level);
>
>
> How can this be a command line option, when there may be many domains
> making use of the in-Xen driver? This and ...
TBH, I did not plan for configuring vUARTs per-domain. In its current shape,
the emulator is strictly for debugging purposes and not ready to be enabled
in production setup. Which means global configuration is fine, IMO. But then
I decided that it's trivial to allow selecton of any of x86 legacy UARTs.
Such global configuration was hooked into the command line parsing because
it allows to test xen + dom0 w/o rebuild.
Reworked to Kconfig setting.
>
> > +/*
> > + * Default emulated NS8250 resources.
> > + * If not specified, COM1 (I/O port 0x3f8, IRQ#4) is emulated.
> > + * FIXME: follow Linux'es console= syntax or re-use
> > + * ns16550_parse_port_config().
> > + */
> > +static char __read_mostly hvm_ns8250_console[64];
> > +string_param("hvm.ns8250.console", hvm_ns8250_console);
>
>
> ... this need to be per-domain settings; a command line option may be
> applicable to Dom0 alone.
>
> > +/* I/O access mask */
> > +static const uint32_t io_access_mask[] = {
> > + [0] = 0X00000000U,
> > + [1] = 0X000000FFU,
> > + [2] = 0X0000FFFFU,
> > + [4] = 0XFFFFFFFFU,
> > +};
>
>
> I don't think this is needed; we're doing similar port I/O emulation in
> various other places, without resorting to such arrays.
Dropped.
>
> > +/*
> > + * Legacy IBM PC NS8250 resources.
> > + * There are only 4 I/O port ranges, hardcoding all of them here.
> > + */
> > +static const struct {
> > + const char *name;
> > + const struct resource *res;
> > +} ns8250_x86_legacy_uarts[4] = {
> > + [0] = {
> > + .name = "com1",
> > + .res = (const struct resource[]){
> > + { .type = IORESOURCE_IO, .addr = 0x3F8, .size = UART_MAX },
>
>
> Considering this, ...
>
> > +static int ns8250_io_write8(
> > + struct vuart_ns8250 *vdev, uint32_t reg, uint8_t *data)
> > +{
> > + uint8_t val;
> > + int rc = 0;
> > +
> > + val = data;
> > +
> > + switch ( reg )
> > + {
> > + / DLAB=0 /
> > + case UART_THR:
> > + if ( vdev->regs[UART_MCR] & UART_MCR_LOOP )
> > + {
> > + ns8250_fifo_rx_putchar(vdev, val);
> > + vdev->regs[UART_LSR] |= UART_LSR_OE;
> > + }
> > + else
> > + ns8250_fifo_tx_putchar(vdev, val);
> > +
> > + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> > +
> > + break;
> > +
> > + case UART_IER:
> > + if ( val & vdev->regs[UART_IER] & UART_IER_ETHREI )
> > + vdev->flags |= NS8250_IRQ_THRE_PENDING;
> > +
> > + vdev->regs[UART_IER] = val & UART_IER_MASK;
> > +
> > + break;
> > +
> > + case UART_FCR: / WO /
> > + if ( val & UART_FCR_CLRX )
> > + ns8250_fifo_rx_reset(vdev);
> > +
> > + if ( val & UART_FCR_CLTX )
> > + ns8250_fifo_tx_reset(vdev);
> > +
> > + if ( !(val & UART_FCR_ENABLE) )
> > + val = 0;
> > +
> > + vdev->regs[UART_FCR] = val & (UART_FCR_ENABLE |
> > + UART_FCR_DMA |
> > + UART_FCR_TRG_MASK);
> > +
> > + break;
> > +
> > + case UART_LCR:
> > + vdev->regs[UART_LCR] = val;
> > + break;
> > +
> > + case UART_MCR: {
> > + uint8_t msr_curr, msr_next, msr_delta;
> > +
> > + msr_curr = vdev->regs[UART_MSR];
> > + msr_next = 0;
> > + msr_delta = 0;
> > +
> > + / Set modem status /
> > + if ( val & UART_MCR_LOOP )
> > + {
> > + if ( val & UART_MCR_DTR )
> > + msr_next |= UART_MSR_DSR;
> > + if ( val & UART_MCR_RTS )
> > + msr_next |= UART_MSR_CTS;
> > + if ( val & UART_MCR_OUT1 )
> > + msr_next |= UART_MSR_RI;
> > + if ( val & UART_MCR_OUT2 )
> > + msr_next |= UART_MSR_DCD;
> > + }
> > + else
> > + msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
> > +
> > + / Calculate changes in modem status /
> > + if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
> > + msr_delta |= UART_MSR_DCTS;
> > + if ( (msr_curr & UART_MCR_RTS) ^ (msr_next & UART_MCR_RTS) )
> > + msr_delta |= UART_MSR_DDSR;
> > + if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
> > + msr_delta |= UART_MSR_TERI;
> > + if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
> > + msr_delta |= UART_MSR_DDCD;
> > +
> > + vdev->regs[UART_MCR] = val & UART_MCR_MASK;
> > + vdev->regs[UART_MSR] = msr_next | msr_delta;
> > +
> > + break;
> > + }
> > +
> > + case UART_LSR: / RO /
> > + case UART_MSR: / RO /
> > + rc = -EINVAL;
> > + break;
> > +
> > + /
> > + * NB: Firmware like OVMF rely on SCR presence to initialize the ns8250
> > + * driver.
> > + /
> > + case UART_SCR:
> > + vdev->regs[UART_SCR] = val;
> > + break;
> > +
> > + / DLAB=1 */
> > + case UART_MAX + UART_DLL:
>
>
> ... how can you go at or past UART_MAX here and ...
>
> > + vdev->dl = (vdev->dl & 0xFF00U) | val;
> > + break;
> > +
> > + case UART_MAX + UART_DLM:
>
>
> ... here? I notice a caller up the tree sets things up like this, but this
> feels pretty fragile. How would one easily spot all producers and consumers
> without also hitting all other uses of UART_MAX?
The idea was to flatten the register address space regardless DLAB.
I also agree with your point: having all register handling stated explicitly
makes the code more understandable.
Reworked.
>
> > +static int cf_check ns8250_io_handle(
> > + int dir, unsigned int addr, unsigned int size, uint32_t *data)
> > +{
> > +#define op(dir) (((dir) == IOREQ_WRITE) ? 'W' : 'R')
> > + struct domain *d = rcu_lock_current_domain();
> > + struct vuart_ns8250 *vdev = &d->arch.hvm.vuart;
> > + uint32_t offset, reg;
> > + int rc;
> > +
> > + spin_lock(&vdev->lock);
> > +
> > + BUG_ON( vdev->owner != d );
> > +
> > + if ( !(vdev->flags & NS8250_READY) )
> > + {
> > + pr_err("%c io 0x%04x %d 0x%08"PRIx32": propagate to external I/O emulator\n",
> > + op(dir), addr, size, *data);
> > + rc = X86EMUL_UNHANDLEABLE;
> > + goto out;
> > + }
> > +
> > + reg = addr - vdev->io_addr;
> > + BUG_ON( reg >= UART_MAX );
> > + if ( reg % size != 0 )
> > + {
> > + pr_err("%c 0x%04x %d 0x%08"PRIx32": unaligned access\n",
> > + op(dir), addr, size, data & io_access_mask[size]);
> > + rc = X86EMUL_OKAY;
> > + goto out;
> > + }
> > +
> > + / Redirect access to divisor latch registers */
> > + if ( !!(vdev->regs[UART_LCR] & UART_LCR_DLAB)
> > + && (reg == UART_DLL || reg == UART_DLM) )
> > + offset = UART_MAX + reg;
> > + else
> > + offset = reg;
> > +
> > + if ( dir == IOREQ_WRITE )
> > + {
> > + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> > + op(dir), addr, size,
> > + *data & io_access_mask[size],
> > + ns8250_regname(vdev, offset, dir), reg);
> > + rc = ns8250_io_write(vdev, offset, size, data);
> > + }
> > + else
> > + {
> > + rc = ns8250_io_read(vdev, offset, size, data);
> > + pr_debug("%c 0x%04x %d 0x%08"PRIx32" %s[0x%02"PRIx32"]\n",
> > + op(dir), addr, size,
> > + *data & io_access_mask[size],
> > + ns8250_regname(vdev, offset, dir), reg);
> > + }
> > + if ( rc )
> > + pr_err("%c 0x%04x %d 0x%08"PRIx32": unsupported access\n",
> > + op(dir), addr, size, *data & io_access_mask[size]);
> > + rc = X86EMUL_OKAY;
> > +
> > +out:
>
>
> Nit: Missing indentation (see ./CODING_STYLE). Also elsewhere.
Fixed.
>
> > --- /dev/null
> > +++ b/xen/arch/x86/include/asm/hvm/vuart_ns8250.h
> > @@ -0,0 +1,75 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only /
> > +/
> > + * NS8250-compatible UART Emulator.
> > + /
> > +#if !defined(HVM__VUART_NS8250_H)
> > +#define HVM__VUART_NS8250_H
> > +
> > +#include <xen/spinlock.h>
> > +#include <xen/8250-uart.h>
> > +#include <public/io/console.h> / xencons_interface */
>
>
> I assume you mean ...
>
> > +/*
> > + * NS8250 emulator operational flags.
> > + /
> > +enum {
> > + / Emulator is ready /
> > + NS8250_READY = BIT(0, U),
> > + / Trigger re-delivery of THRE interrupt /
> > + NS8250_IRQ_THRE_PENDING = BIT(1, U),
> > +};
> > +
> > +/
> > + * Virtual NS8250 device state.
> > + /
> > +struct vuart_ns8250 {
> > + uint16_t dl; / Divisor Latch /
> > + uint8_t regs[UART_MAX]; / Registers /
> > + uint32_t flags; / Virtual device flags /
> > + uint64_t io_addr; / Guest I/O region base address /
> > + uint64_t io_size; / Guest I/O region size /
> > + int irq; / Guest IRQ# */
> > + struct xencons_interface cons; / Emulated RX/TX FIFOs */
>
>
> ... this use, but that doesn't even require a forward decl of the struct
> in C (in C++ such a forward decl would be all that's needed).
I declared vUART handler as `void *` in hvm_domain and moved all the data
types to .c, so there's no need in header file at all.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2025-01-04 5:31 ` Denis Mukhin
@ 2025-01-06 9:19 ` Jan Beulich
2025-01-06 20:16 ` Denis Mukhin
0 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2025-01-06 9:19 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On 04.01.2025 06:31, Denis Mukhin wrote:
> On Monday, December 16th, 2024 at 7:04 AM, Jan Beulich <jbeulich@suse.com> wrote:
>> On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
>>> + depends on HVM && HAS_IOPORTS
>>
>>
>> Why HAS_IOPORTS?
>
> It is meant to highlight the fact that MMIO-based UART is not supported.
> It is not currently possible to enable the emulator for, say, Arm platforms.
That I guessed, yet you realize that HAS_IOPORTS describes a host property,
not (so much) a guest one?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2025-01-06 9:19 ` Jan Beulich
@ 2025-01-06 20:16 ` Denis Mukhin
2025-01-07 8:43 ` Jan Beulich
0 siblings, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-06 20:16 UTC (permalink / raw)
To: Jan Beulich
Cc: Denis Mukhin, dmukhin, Andrew Cooper, Julien Grall,
Stefano Stabellini, xen-devel
On Monday, January 6th, 2025 at 1:19 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 04.01.2025 06:31, Denis Mukhin wrote:
>
> > On Monday, December 16th, 2024 at 7:04 AM, Jan Beulich jbeulich@suse.com wrote:
> >
> > > On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
> > >
> > > > + depends on HVM && HAS_IOPORTS
> > >
> > > Why HAS_IOPORTS?
> >
> > It is meant to highlight the fact that MMIO-based UART is not supported.
> > It is not currently possible to enable the emulator for, say, Arm platforms.
>
>
> That I guessed, yet you realize that HAS_IOPORTS describes a host property,
> not (so much) a guest one?
re: host property: yes; this is meant to be only a guardrail for porting of the
emulator code (if any) to other architectures, since there's no MMIO-based
NS16550 emulator yet.
I will drop this superfluous dependency in the next iteration.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 31/35] x86/hvm: introduce NS8250 UART emulator
2025-01-06 20:16 ` Denis Mukhin
@ 2025-01-07 8:43 ` Jan Beulich
0 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2025-01-07 8:43 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On 06.01.2025 21:16, Denis Mukhin wrote:
> On Monday, January 6th, 2025 at 1:19 AM, Jan Beulich <jbeulich@suse.com> wrote:
>> On 04.01.2025 06:31, Denis Mukhin wrote:
>>> On Monday, December 16th, 2024 at 7:04 AM, Jan Beulich jbeulich@suse.com wrote:
>>>> On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
>>>>
>>>>> + depends on HVM && HAS_IOPORTS
>>>>
>>>> Why HAS_IOPORTS?
>>>
>>> It is meant to highlight the fact that MMIO-based UART is not supported.
>>> It is not currently possible to enable the emulator for, say, Arm platforms.
>>
>>
>> That I guessed, yet you realize that HAS_IOPORTS describes a host property,
>> not (so much) a guest one?
>
> re: host property: yes; this is meant to be only a guardrail for porting of the
> emulator code (if any) to other architectures, since there's no MMIO-based
> NS16550 emulator yet.
>
> I will drop this superfluous dependency in the next iteration.
Just to clarify: If properly justified, I'm okay with the dependency to
be kept. Otoh the lack of MMIO handling will turn out as pretty obvious
if someone was to try to enable this emulation on an IO-port-less arch.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 32/35] x86/hvm: add debugging facility to NS8250 UART emulator
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Enable keyhandler mechanism for dumping state of emulated NS8250 on the
console.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/hvm/vuart_ns8250.c | 122 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 122 insertions(+)
diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
index 779dbd80d7be4e070ea9df3ae736ecdc662a527a..c8c75afaf2b2419d1dae999da1d1e400fd367791 100644
--- a/xen/arch/x86/hvm/vuart_ns8250.c
+++ b/xen/arch/x86/hvm/vuart_ns8250.c
@@ -25,6 +25,7 @@
/* Development debugging */
#define NS8250_LOG_LEVEL 0
+#undef NS8250_DEBUG
#include <xen/types.h>
#include <xen/event.h>
@@ -35,6 +36,9 @@
#include <xen/resource.h>
#include <xen/ctype.h>
#include <xen/param.h>
+#if defined(NS8250_DEBUG)
+#include <xen/keyhandler.h>
+#endif
#include <xen/console.h> /* console_input_domid() */
#include <asm/setup.h> /* max_init_domid */
#include <asm/iocap.h>
@@ -625,6 +629,121 @@ static const char *ns8250_regname(
return reg_names[reg][dir];
}
+#if defined(NS8250_DEBUG)
+static void ns8250_dump(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+ uint8_t val;
+
+ printk("I/O port %02"PRIx64" IRQ %d flags %"PRIx32" owner %d\n",
+ vdev->io_addr, vdev->irq,
+ vdev->flags, vdev->owner->domain_id);
+
+ printk("RX size %ld in_prod %d in_cons %d used %d\n",
+ sizeof(cons->in),
+ cons->in_prod, cons->in_cons,
+ cons->in_prod - cons->in_cons);
+
+ printk("TX size %ld out_prod %d out_cons %d used %d\n",
+ sizeof(cons->out),
+ cons->out_prod, cons->out_cons,
+ cons->out_prod - cons->out_cons);
+
+ printk("%02x RBR [ %c ] THR [ %c ] DLL %02x DLM %02x\n",
+ UART_RBR,
+ cons->in[MASK_XENCONS_IDX(cons->in_prod, cons)],
+ cons->out[MASK_XENCONS_IDX(cons->out_prod, cons)],
+ vdev->dl & 0xFFU, vdev->dl >> 8);
+
+ printk("%02"PRIx8" IER %02"PRIx8"\n", UART_IER, vdev->regs[UART_IER]);
+
+ val = (vdev->regs[UART_FCR] & UART_FCR_ENABLE) ? UART_IIR_FE_MASK : 0;
+ val |= ns8250_irq_reason(vdev);
+ printk("%02"PRIx8" FCR %02"PRIx8" IIR %02"PRIx8"\n",
+ UART_FCR, vdev->regs[UART_FCR], val);
+
+ printk("%02"PRIx8" LCR %02"PRIx8"\n", UART_LCR, vdev->regs[UART_LCR]);
+ printk("%02"PRIx8" MCR %02"PRIx8"\n", UART_MCR, vdev->regs[UART_MCR]);
+ printk("%02"PRIx8" LSR %02"PRIx8"\n", UART_LSR, vdev->regs[UART_LSR]);
+ printk("%02"PRIx8" MSR %02"PRIx8"\n", UART_MSR, vdev->regs[UART_MSR]);
+}
+
+static struct domain *rcu_find_first_domain_with_vuart(void)
+{
+ struct domain *d = NULL;
+ domid_t i;
+
+ for ( i = 0; i < max_init_domid + 1; i++ )
+ {
+ d = rcu_lock_domain_by_id(i);
+ if ( d == NULL )
+ continue;
+
+ if ( domain_has_vuart(d) )
+ break;
+
+ rcu_unlock_domain(d);
+ }
+
+ return d;
+}
+
+static void cf_check ns8250_keyhandler_show(unsigned char key)
+{
+ struct vuart_ns8250 *vdev;
+ struct domain *d;
+
+ d = rcu_find_first_domain_with_vuart();
+ if ( d == NULL )
+ return;
+
+ printk("'%c' pressed -> dumping virtual NS8250 state (d%d)\n",
+ key, d->domain_id);
+
+ vdev = &d->arch.hvm.vuart;
+ spin_lock(&vdev->lock);
+ ns8250_dump(vdev);
+ spin_unlock(&vdev->lock);
+
+ rcu_unlock_domain(d);
+}
+
+static void cf_check ns8250_keyhandler_irq(unsigned char key)
+{
+ struct vuart_ns8250 *vdev;
+ struct domain *d;
+
+ d = rcu_find_first_domain_with_vuart();
+ if ( d == NULL )
+ return;
+
+ printk("'%c' pressed -> triggering IRQ on virtual NS8250 (d%d)\n",
+ key, d->domain_id);
+
+ vdev = &d->arch.hvm.vuart;
+ spin_lock(&vdev->lock);
+ ns8250_irq_assert(vdev);
+ spin_unlock(&vdev->lock);
+
+ rcu_unlock_domain(d);
+}
+
+static void ns8250_keyhandler_init(void)
+{
+ register_keyhandler('1', ns8250_keyhandler_show,
+ "dump virtual NS8250 state", 0);
+ register_keyhandler('2', ns8250_keyhandler_irq,
+ "trigger IRQ from virtual NS8250", 0);
+}
+#else
+static inline void ns8250_keyhandler_init(void)
+{
+}
+static inline void ns8250_dump(struct vuart_ns8250 *vdev)
+{
+}
+#endif /* #if defined(NS8250_DEBUG) */
+
/*
* Emulate I/O access to NS8250 register.
*/
@@ -688,6 +807,7 @@ static int cf_check ns8250_io_handle(
rc = X86EMUL_OKAY;
out:
+ ns8250_dump(vdev);
spin_unlock(&vdev->lock);
return rc;
@@ -786,6 +906,7 @@ static int ns8250_init(struct domain *d, const struct resource *r)
}
spin_lock_init(&vdev->lock);
+ ns8250_keyhandler_init();
hvm_irq_lower(d, vdev->irq);
vdev->dl = (UART_CLOCK_HZ / 115200) >> 4; /* Report 115200 baud rate */
@@ -852,6 +973,7 @@ int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
ns8250_irq_assert(vdev);
out:
+ ns8250_dump(vdev);
spin_unlock(&vdev->lock);
return rc;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 32/35] x86/hvm: add debugging facility to NS8250 UART emulator
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Enable keyhandler mechanism for dumping state of emulated NS8250 on the
console.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/arch/x86/hvm/vuart_ns8250.c | 122 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 122 insertions(+)
diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
index 779dbd80d7be4e070ea9df3ae736ecdc662a527a..c8c75afaf2b2419d1dae999da1d1e400fd367791 100644
--- a/xen/arch/x86/hvm/vuart_ns8250.c
+++ b/xen/arch/x86/hvm/vuart_ns8250.c
@@ -25,6 +25,7 @@
/* Development debugging */
#define NS8250_LOG_LEVEL 0
+#undef NS8250_DEBUG
#include <xen/types.h>
#include <xen/event.h>
@@ -35,6 +36,9 @@
#include <xen/resource.h>
#include <xen/ctype.h>
#include <xen/param.h>
+#if defined(NS8250_DEBUG)
+#include <xen/keyhandler.h>
+#endif
#include <xen/console.h> /* console_input_domid() */
#include <asm/setup.h> /* max_init_domid */
#include <asm/iocap.h>
@@ -625,6 +629,121 @@ static const char *ns8250_regname(
return reg_names[reg][dir];
}
+#if defined(NS8250_DEBUG)
+static void ns8250_dump(struct vuart_ns8250 *vdev)
+{
+ struct xencons_interface *cons = vdev->cons;
+ uint8_t val;
+
+ printk("I/O port %02"PRIx64" IRQ %d flags %"PRIx32" owner %d\n",
+ vdev->io_addr, vdev->irq,
+ vdev->flags, vdev->owner->domain_id);
+
+ printk("RX size %ld in_prod %d in_cons %d used %d\n",
+ sizeof(cons->in),
+ cons->in_prod, cons->in_cons,
+ cons->in_prod - cons->in_cons);
+
+ printk("TX size %ld out_prod %d out_cons %d used %d\n",
+ sizeof(cons->out),
+ cons->out_prod, cons->out_cons,
+ cons->out_prod - cons->out_cons);
+
+ printk("%02x RBR [ %c ] THR [ %c ] DLL %02x DLM %02x\n",
+ UART_RBR,
+ cons->in[MASK_XENCONS_IDX(cons->in_prod, cons)],
+ cons->out[MASK_XENCONS_IDX(cons->out_prod, cons)],
+ vdev->dl & 0xFFU, vdev->dl >> 8);
+
+ printk("%02"PRIx8" IER %02"PRIx8"\n", UART_IER, vdev->regs[UART_IER]);
+
+ val = (vdev->regs[UART_FCR] & UART_FCR_ENABLE) ? UART_IIR_FE_MASK : 0;
+ val |= ns8250_irq_reason(vdev);
+ printk("%02"PRIx8" FCR %02"PRIx8" IIR %02"PRIx8"\n",
+ UART_FCR, vdev->regs[UART_FCR], val);
+
+ printk("%02"PRIx8" LCR %02"PRIx8"\n", UART_LCR, vdev->regs[UART_LCR]);
+ printk("%02"PRIx8" MCR %02"PRIx8"\n", UART_MCR, vdev->regs[UART_MCR]);
+ printk("%02"PRIx8" LSR %02"PRIx8"\n", UART_LSR, vdev->regs[UART_LSR]);
+ printk("%02"PRIx8" MSR %02"PRIx8"\n", UART_MSR, vdev->regs[UART_MSR]);
+}
+
+static struct domain *rcu_find_first_domain_with_vuart(void)
+{
+ struct domain *d = NULL;
+ domid_t i;
+
+ for ( i = 0; i < max_init_domid + 1; i++ )
+ {
+ d = rcu_lock_domain_by_id(i);
+ if ( d == NULL )
+ continue;
+
+ if ( domain_has_vuart(d) )
+ break;
+
+ rcu_unlock_domain(d);
+ }
+
+ return d;
+}
+
+static void cf_check ns8250_keyhandler_show(unsigned char key)
+{
+ struct vuart_ns8250 *vdev;
+ struct domain *d;
+
+ d = rcu_find_first_domain_with_vuart();
+ if ( d == NULL )
+ return;
+
+ printk("'%c' pressed -> dumping virtual NS8250 state (d%d)\n",
+ key, d->domain_id);
+
+ vdev = &d->arch.hvm.vuart;
+ spin_lock(&vdev->lock);
+ ns8250_dump(vdev);
+ spin_unlock(&vdev->lock);
+
+ rcu_unlock_domain(d);
+}
+
+static void cf_check ns8250_keyhandler_irq(unsigned char key)
+{
+ struct vuart_ns8250 *vdev;
+ struct domain *d;
+
+ d = rcu_find_first_domain_with_vuart();
+ if ( d == NULL )
+ return;
+
+ printk("'%c' pressed -> triggering IRQ on virtual NS8250 (d%d)\n",
+ key, d->domain_id);
+
+ vdev = &d->arch.hvm.vuart;
+ spin_lock(&vdev->lock);
+ ns8250_irq_assert(vdev);
+ spin_unlock(&vdev->lock);
+
+ rcu_unlock_domain(d);
+}
+
+static void ns8250_keyhandler_init(void)
+{
+ register_keyhandler('1', ns8250_keyhandler_show,
+ "dump virtual NS8250 state", 0);
+ register_keyhandler('2', ns8250_keyhandler_irq,
+ "trigger IRQ from virtual NS8250", 0);
+}
+#else
+static inline void ns8250_keyhandler_init(void)
+{
+}
+static inline void ns8250_dump(struct vuart_ns8250 *vdev)
+{
+}
+#endif /* #if defined(NS8250_DEBUG) */
+
/*
* Emulate I/O access to NS8250 register.
*/
@@ -688,6 +807,7 @@ static int cf_check ns8250_io_handle(
rc = X86EMUL_OKAY;
out:
+ ns8250_dump(vdev);
spin_unlock(&vdev->lock);
return rc;
@@ -786,6 +906,7 @@ static int ns8250_init(struct domain *d, const struct resource *r)
}
spin_lock_init(&vdev->lock);
+ ns8250_keyhandler_init();
hvm_irq_lower(d, vdev->irq);
vdev->dl = (UART_CLOCK_HZ / 115200) >> 4; /* Report 115200 baud rate */
@@ -852,6 +973,7 @@ int vuart_putchar(struct vuart_ns8250 *vdev, char ch)
ns8250_irq_assert(vdev);
out:
+ ns8250_dump(vdev);
spin_unlock(&vdev->lock);
return rc;
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 32/35] x86/hvm: add debugging facility to NS8250 UART emulator
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-13 12:08 ` Roger Pau Monné
2025-01-04 4:31 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-13 12:08 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:42:02PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Enable keyhandler mechanism for dumping state of emulated NS8250 on the
> console.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/arch/x86/hvm/vuart_ns8250.c | 122 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 122 insertions(+)
>
> diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
> index 779dbd80d7be4e070ea9df3ae736ecdc662a527a..c8c75afaf2b2419d1dae999da1d1e400fd367791 100644
> --- a/xen/arch/x86/hvm/vuart_ns8250.c
> +++ b/xen/arch/x86/hvm/vuart_ns8250.c
> @@ -25,6 +25,7 @@
>
> /* Development debugging */
> #define NS8250_LOG_LEVEL 0
> +#undef NS8250_DEBUG
>
> #include <xen/types.h>
> #include <xen/event.h>
> @@ -35,6 +36,9 @@
> #include <xen/resource.h>
> #include <xen/ctype.h>
> #include <xen/param.h>
> +#if defined(NS8250_DEBUG)
> +#include <xen/keyhandler.h>
> +#endif
> #include <xen/console.h> /* console_input_domid() */
> #include <asm/setup.h> /* max_init_domid */
> #include <asm/iocap.h>
> @@ -625,6 +629,121 @@ static const char *ns8250_regname(
> return reg_names[reg][dir];
> }
>
> +#if defined(NS8250_DEBUG)
I don't think the keyhandler should be gated on NS8250_DEBUG, it
should always be present if Xen is built with vUART support.
> +static void ns8250_dump(struct vuart_ns8250 *vdev)
> +{
> + struct xencons_interface *cons = vdev->cons;
const for both.
> + uint8_t val;
> +
> + printk("I/O port %02"PRIx64" IRQ %d flags %"PRIx32" owner %d\n",
I think you want 04 for the io_addr field width? So that the width is
always fixed, and %pd for owner.
> + vdev->io_addr, vdev->irq,
> + vdev->flags, vdev->owner->domain_id);
> +
> + printk("RX size %ld in_prod %d in_cons %d used %d\n",
> + sizeof(cons->in),
> + cons->in_prod, cons->in_cons,
> + cons->in_prod - cons->in_cons);
> +
> + printk("TX size %ld out_prod %d out_cons %d used %d\n",
> + sizeof(cons->out),
> + cons->out_prod, cons->out_cons,
> + cons->out_prod - cons->out_cons);
> +
> + printk("%02x RBR [ %c ] THR [ %c ] DLL %02x DLM %02x\n",
> + UART_RBR,
> + cons->in[MASK_XENCONS_IDX(cons->in_prod, cons)],
> + cons->out[MASK_XENCONS_IDX(cons->out_prod, cons)],
> + vdev->dl & 0xFFU, vdev->dl >> 8);
> +
> + printk("%02"PRIx8" IER %02"PRIx8"\n", UART_IER, vdev->regs[UART_IER]);
> +
> + val = (vdev->regs[UART_FCR] & UART_FCR_ENABLE) ? UART_IIR_FE_MASK : 0;
> + val |= ns8250_irq_reason(vdev);
> + printk("%02"PRIx8" FCR %02"PRIx8" IIR %02"PRIx8"\n",
> + UART_FCR, vdev->regs[UART_FCR], val);
> +
> + printk("%02"PRIx8" LCR %02"PRIx8"\n", UART_LCR, vdev->regs[UART_LCR]);
> + printk("%02"PRIx8" MCR %02"PRIx8"\n", UART_MCR, vdev->regs[UART_MCR]);
> + printk("%02"PRIx8" LSR %02"PRIx8"\n", UART_LSR, vdev->regs[UART_LSR]);
> + printk("%02"PRIx8" MSR %02"PRIx8"\n", UART_MSR, vdev->regs[UART_MSR]);
> +}
> +
> +static struct domain *rcu_find_first_domain_with_vuart(void)
> +{
> + struct domain *d = NULL;
> + domid_t i;
> +
> + for ( i = 0; i < max_init_domid + 1; i++ )
> + {
> + d = rcu_lock_domain_by_id(i);
> + if ( d == NULL )
> + continue;
> +
> + if ( domain_has_vuart(d) )
> + break;
> +
> + rcu_unlock_domain(d);
> + }
> +
> + return d;
> +}
> +
> +static void cf_check ns8250_keyhandler_show(unsigned char key)
> +{
> + struct vuart_ns8250 *vdev;
> + struct domain *d;
> +
> + d = rcu_find_first_domain_with_vuart();
> + if ( d == NULL )
> + return;
I wonder whether you should dump the state of all domains with a
vUART, rather than just a single domain?
> +
> + printk("'%c' pressed -> dumping virtual NS8250 state (d%d)\n",
> + key, d->domain_id);
> +
> + vdev = &d->arch.hvm.vuart;
> + spin_lock(&vdev->lock);
This should likely be a trylock, so that you can still print the
console state in case of a deadlock.
> + ns8250_dump(vdev);
> + spin_unlock(&vdev->lock);
> +
> + rcu_unlock_domain(d);
> +}
> +
> +static void cf_check ns8250_keyhandler_irq(unsigned char key)
> +{
> + struct vuart_ns8250 *vdev;
> + struct domain *d;
> +
> + d = rcu_find_first_domain_with_vuart();
> + if ( d == NULL )
> + return;
> +
> + printk("'%c' pressed -> triggering IRQ on virtual NS8250 (d%d)\n",
> + key, d->domain_id);
> +
> + vdev = &d->arch.hvm.vuart;
> + spin_lock(&vdev->lock);
> + ns8250_irq_assert(vdev);
> + spin_unlock(&vdev->lock);
> +
> + rcu_unlock_domain(d);
> +}
> +
> +static void ns8250_keyhandler_init(void)
> +{
> + register_keyhandler('1', ns8250_keyhandler_show,
> + "dump virtual NS8250 state", 0);
> + register_keyhandler('2', ns8250_keyhandler_irq,
> + "trigger IRQ from virtual NS8250", 0);
> +}
> +#else
> +static inline void ns8250_keyhandler_init(void)
> +{
> +}
> +static inline void ns8250_dump(struct vuart_ns8250 *vdev)
> +{
> +}
> +#endif /* #if defined(NS8250_DEBUG) */
> +
> /*
> * Emulate I/O access to NS8250 register.
> */
> @@ -688,6 +807,7 @@ static int cf_check ns8250_io_handle(
> rc = X86EMUL_OKAY;
>
> out:
> + ns8250_dump(vdev);
Likely a remaining of some debugging? Printing the state for every
access is too verbose.
> spin_unlock(&vdev->lock);
>
> return rc;
> @@ -786,6 +906,7 @@ static int ns8250_init(struct domain *d, const struct resource *r)
> }
>
> spin_lock_init(&vdev->lock);
> + ns8250_keyhandler_init();
The keyhandler init should be in a __initcall(), otherwise you are
calling it for each domain creation that has a vUART.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 32/35] x86/hvm: add debugging facility to NS8250 UART emulator
2024-12-13 12:08 ` Roger Pau Monné
@ 2025-01-04 4:31 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:31 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Friday, December 13th, 2024 at 4:08 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:42:02PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Enable keyhandler mechanism for dumping state of emulated NS8250 on the
> > console.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/arch/x86/hvm/vuart_ns8250.c | 122 ++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 122 insertions(+)
> >
> > diff --git a/xen/arch/x86/hvm/vuart_ns8250.c b/xen/arch/x86/hvm/vuart_ns8250.c
> > index 779dbd80d7be4e070ea9df3ae736ecdc662a527a..c8c75afaf2b2419d1dae999da1d1e400fd367791 100644
> > --- a/xen/arch/x86/hvm/vuart_ns8250.c
> > +++ b/xen/arch/x86/hvm/vuart_ns8250.c
> > @@ -25,6 +25,7 @@
> >
> > /* Development debugging */
> > #define NS8250_LOG_LEVEL 0
> > +#undef NS8250_DEBUG
> >
> > #include <xen/types.h>
> > #include <xen/event.h>
> > @@ -35,6 +36,9 @@
> > #include <xen/resource.h>
> > #include <xen/ctype.h>
> > #include <xen/param.h>
> > +#if defined(NS8250_DEBUG)
> > +#include <xen/keyhandler.h>
> > +#endif
> > #include <xen/console.h> /* console_input_domid() /
> > #include <asm/setup.h> / max_init_domid */
> > #include <asm/iocap.h>
> > @@ -625,6 +629,121 @@ static const char *ns8250_regname(
> > return reg_names[reg][dir];
> > }
> >
> > +#if defined(NS8250_DEBUG)
>
>
> I don't think the keyhandler should be gated on NS8250_DEBUG, it
> should always be present if Xen is built with vUART support.
>
> > +static void ns8250_dump(struct vuart_ns8250 *vdev)
> > +{
> > + struct xencons_interface *cons = vdev->cons;
>
>
> const for both.
Fixed.
>
> > + uint8_t val;
> > +
> > + printk("I/O port %02"PRIx64" IRQ %d flags %"PRIx32" owner %d\n",
>
>
> I think you want 04 for the io_addr field width? So that the width is
> always fixed, and %pd for owner.
Fixed.
>
> > + vdev->io_addr, vdev->irq,
> > + vdev->flags, vdev->owner->domain_id);
> > +
> > + printk("RX size %ld in_prod %d in_cons %d used %d\n",
> > + sizeof(cons->in),
> > + cons->in_prod, cons->in_cons,
> > + cons->in_prod - cons->in_cons);
> > +
> > + printk("TX size %ld out_prod %d out_cons %d used %d\n",
> > + sizeof(cons->out),
> > + cons->out_prod, cons->out_cons,
> > + cons->out_prod - cons->out_cons);
> > +
> > + printk("%02x RBR [ %c ] THR [ %c ] DLL %02x DLM %02x\n",
> > + UART_RBR,
> > + cons->in[MASK_XENCONS_IDX(cons->in_prod, cons)],
> > + cons->out[MASK_XENCONS_IDX(cons->out_prod, cons)],
> > + vdev->dl & 0xFFU, vdev->dl >> 8);
> > +
> > + printk("%02"PRIx8" IER %02"PRIx8"\n", UART_IER, vdev->regs[UART_IER]);
> > +
> > + val = (vdev->regs[UART_FCR] & UART_FCR_ENABLE) ? UART_IIR_FE_MASK : 0;
> > + val |= ns8250_irq_reason(vdev);
> > + printk("%02"PRIx8" FCR %02"PRIx8" IIR %02"PRIx8"\n",
> > + UART_FCR, vdev->regs[UART_FCR], val);
> > +
> > + printk("%02"PRIx8" LCR %02"PRIx8"\n", UART_LCR, vdev->regs[UART_LCR]);
> > + printk("%02"PRIx8" MCR %02"PRIx8"\n", UART_MCR, vdev->regs[UART_MCR]);
> > + printk("%02"PRIx8" LSR %02"PRIx8"\n", UART_LSR, vdev->regs[UART_LSR]);
> > + printk("%02"PRIx8" MSR %02"PRIx8"\n", UART_MSR, vdev->regs[UART_MSR]);
> > +}
> > +
> > +static struct domain *rcu_find_first_domain_with_vuart(void)
> > +{
> > + struct domain *d = NULL;
> > + domid_t i;
> > +
> > + for ( i = 0; i < max_init_domid + 1; i++ )
> > + {
> > + d = rcu_lock_domain_by_id(i);
> > + if ( d == NULL )
> > + continue;
> > +
> > + if ( domain_has_vuart(d) )
> > + break;
> > +
> > + rcu_unlock_domain(d);
> > + }
> > +
> > + return d;
> > +}
> > +
> > +static void cf_check ns8250_keyhandler_show(unsigned char key)
> > +{
> > + struct vuart_ns8250 *vdev;
> > + struct domain *d;
> > +
> > + d = rcu_find_first_domain_with_vuart();
> > + if ( d == NULL )
> > + return;
>
>
> I wonder whether you should dump the state of all domains with a
> vUART, rather than just a single domain?
Looks like 'q' handler is a better place for such printout.
>
> > +
> > + printk("'%c' pressed -> dumping virtual NS8250 state (d%d)\n",
> > + key, d->domain_id);
> > +
> > + vdev = &d->arch.hvm.vuart;
> > + spin_lock(&vdev->lock);
>
>
> This should likely be a trylock, so that you can still print the
> console state in case of a deadlock.
Fixed.
>
> > + ns8250_dump(vdev);
> > + spin_unlock(&vdev->lock);
> > +
> > + rcu_unlock_domain(d);
> > +}
> > +
> > +static void cf_check ns8250_keyhandler_irq(unsigned char key)
> > +{
> > + struct vuart_ns8250 *vdev;
> > + struct domain *d;
> > +
> > + d = rcu_find_first_domain_with_vuart();
> > + if ( d == NULL )
> > + return;
> > +
> > + printk("'%c' pressed -> triggering IRQ on virtual NS8250 (d%d)\n",
> > + key, d->domain_id);
> > +
> > + vdev = &d->arch.hvm.vuart;
> > + spin_lock(&vdev->lock);
> > + ns8250_irq_assert(vdev);
> > + spin_unlock(&vdev->lock);
> > +
> > + rcu_unlock_domain(d);
> > +}
> > +
> > +static void ns8250_keyhandler_init(void)
> > +{
> > + register_keyhandler('1', ns8250_keyhandler_show,
> > + "dump virtual NS8250 state", 0);
> > + register_keyhandler('2', ns8250_keyhandler_irq,
> > + "trigger IRQ from virtual NS8250", 0);
> > +}
> > +#else
> > +static inline void ns8250_keyhandler_init(void)
> > +{
> > +}
> > +static inline void ns8250_dump(struct vuart_ns8250 vdev)
> > +{
> > +}
> > +#endif / #if defined(NS8250_DEBUG) /
> > +
> > /
> > * Emulate I/O access to NS8250 register.
> > */
> > @@ -688,6 +807,7 @@ static int cf_check ns8250_io_handle(
> > rc = X86EMUL_OKAY;
> >
> > out:
> > + ns8250_dump(vdev);
>
>
> Likely a remaining of some debugging? Printing the state for every
> access is too verbose.
That was actually helpful for debugging.
Those calls will be compiled-out in default build w/ emulator.
>
> > spin_unlock(&vdev->lock);
> >
> > return rc;
> > @@ -786,6 +906,7 @@ static int ns8250_init(struct domain *d, const struct resource *r)
> > }
> >
> > spin_lock_init(&vdev->lock);
> > + ns8250_keyhandler_init();
>
>
> The keyhandler init should be in a __initcall(), otherwise you are
> calling it for each domain creation that has a vUART.
Thank you.
I nuked vUART keyhandlers altogether in v3.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 32/35] x86/hvm: add debugging facility to NS8250 UART emulator
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-16 15:08 ` Jan Beulich
2025-01-04 4:37 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-16 15:08 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
> +static void ns8250_keyhandler_init(void)
> +{
> + register_keyhandler('1', ns8250_keyhandler_show,
> + "dump virtual NS8250 state", 0);
> + register_keyhandler('2', ns8250_keyhandler_irq,
> + "trigger IRQ from virtual NS8250", 0);
Characters for key handlers are a pretty scarce resource. I'm afraid I
wouldn't want to see this committed, even if it may be helpful during
(initial) debugging. Even more so when both handlers only ever act on
a single domain. Imo both want to be domctl-s instead.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 32/35] x86/hvm: add debugging facility to NS8250 UART emulator
2024-12-16 15:08 ` Jan Beulich
@ 2025-01-04 4:37 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:37 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Monday, December 16th, 2024 at 7:08 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
>
> > +static void ns8250_keyhandler_init(void)
> > +{
> > + register_keyhandler('1', ns8250_keyhandler_show,
> > + "dump virtual NS8250 state", 0);
> > + register_keyhandler('2', ns8250_keyhandler_irq,
> > + "trigger IRQ from virtual NS8250", 0);
>
>
> Characters for key handlers are a pretty scarce resource. I'm afraid I
> wouldn't want to see this committed, even if it may be helpful during
> (initial) debugging. Even more so when both handlers only ever act on
> a single domain. Imo both want to be domctl-s instead.
re: keyhandler resource: yes, thank you, I understand that.
I did not know better way to add dev debugging; I hooked to 'q' handler
in v3. Triggering vUART interrupts - dropped.
So no keyhandlers in v3.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Add new emulation flag for virtual UART on x86 and plumb it through the stack.
This change enables NS8250 emulator initialization.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
tools/libs/light/libxl_x86.c | 6 +++++-
tools/ocaml/libs/xc/xenctrl.ml | 1 +
tools/ocaml/libs/xc/xenctrl.mli | 1 +
tools/python/xen/lowlevel/xc/xc.c | 4 +---
xen/arch/x86/domain.c | 8 +++++---
xen/arch/x86/include/asm/domain.h | 7 ++++---
xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
7 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
--- a/tools/libs/light/libxl_x86.c
+++ b/tools/libs/light/libxl_x86.c
@@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
{
switch(d_config->c_info.type) {
case LIBXL_DOMAIN_TYPE_HVM:
- config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
+ config->arch.emulation_flags = XEN_X86_EMU_ALL;
+ config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
+ /* Virtual UART is selected at Xen build time */
+ config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
+
if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
break;
diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
--- a/tools/ocaml/libs/xc/xenctrl.ml
+++ b/tools/ocaml/libs/xc/xenctrl.ml
@@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
| X86_EMU_PIT
| X86_EMU_USE_PIRQ
| X86_EMU_VPCI
+ | X86_EMU_VUART
type x86_arch_misc_flags =
| X86_MSR_RELAXED
diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
--- a/tools/ocaml/libs/xc/xenctrl.mli
+++ b/tools/ocaml/libs/xc/xenctrl.mli
@@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
| X86_EMU_PIT
| X86_EMU_USE_PIRQ
| X86_EMU_VPCI
+ | X86_EMU_VUART
type x86_arch_misc_flags =
| X86_MSR_RELAXED
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
#if defined (__i386) || defined(__x86_64__)
if ( config.flags & XEN_DOMCTL_CDF_hvm )
- config.arch.emulation_flags = XEN_X86_EMU_ALL &
- ~(XEN_X86_EMU_VPCI |
- XEN_X86_EMU_USE_PIRQ);
+ config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
#elif defined (__arm__) || defined(__aarch64__)
config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
#else
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
if ( is_hardware_domain(d) &&
emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
return false;
+
+ emflags &= ~X86_EMU_VUART;
if ( !is_hardware_domain(d) &&
- /* HVM PIRQ feature is user-selectable. */
- (emflags & ~X86_EMU_USE_PIRQ) !=
- (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
+ xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
emflags != X86_EMU_LAPIC )
return false;
}
@@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
emflags = config->arch.emulation_flags;
+ if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
+ emflags |= XEN_X86_EMU_VUART;
if ( is_hardware_domain(d) && is_pv_domain(d) )
emflags |= XEN_X86_EMU_PIT;
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index c1d0d1f47324e8cc678a4c76c43f86820a89e7b3..dacea6e1aad46e9f8710b2202bb81203c5e92807 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -484,7 +484,8 @@ struct arch_domain
#define X86_EMU_VPCI 0
#endif
-#define X86_EMU_PIT XEN_X86_EMU_PIT
+#define X86_EMU_PIT XEN_X86_EMU_PIT
+#define X86_EMU_VUART XEN_X86_EMU_VUART
/* This must match XEN_X86_EMU_ALL in xen.h */
#define X86_EMU_ALL (X86_EMU_LAPIC | X86_EMU_HPET | \
@@ -492,7 +493,7 @@ struct arch_domain
X86_EMU_IOAPIC | X86_EMU_PIC | \
X86_EMU_VGA | X86_EMU_IOMMU | \
X86_EMU_PIT | X86_EMU_USE_PIRQ | \
- X86_EMU_VPCI)
+ X86_EMU_VPCI | X86_EMU_VUART)
#define has_vlapic(d) (!!((d)->arch.emulation_flags & X86_EMU_LAPIC))
#define has_vhpet(d) (!!((d)->arch.emulation_flags & X86_EMU_HPET))
@@ -507,7 +508,7 @@ struct arch_domain
#define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
/* NB: same symbol as in Arm port */
-#define domain_has_vuart(d) false
+#define domain_has_vuart(d) (!!((d)->arch.emulation_flags & X86_EMU_VUART))
#define gdt_ldt_pt_idx(v) \
((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
index fc2487986642a7694578ab9d2f5f16d09761bff8..e7922e3f9ddc1742a464d228807279839df31e52 100644
--- a/xen/include/public/arch-x86/xen.h
+++ b/xen/include/public/arch-x86/xen.h
@@ -283,13 +283,25 @@ struct xen_arch_domainconfig {
#define XEN_X86_EMU_USE_PIRQ (1U<<_XEN_X86_EMU_USE_PIRQ)
#define _XEN_X86_EMU_VPCI 10
#define XEN_X86_EMU_VPCI (1U<<_XEN_X86_EMU_VPCI)
+#define _XEN_X86_EMU_VUART 11
+#define XEN_X86_EMU_VUART (1U<<_XEN_X86_EMU_VUART)
#define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | XEN_X86_EMU_HPET | \
XEN_X86_EMU_PM | XEN_X86_EMU_RTC | \
XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | \
XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | \
XEN_X86_EMU_PIT | XEN_X86_EMU_USE_PIRQ |\
- XEN_X86_EMU_VPCI)
+ XEN_X86_EMU_VPCI | XEN_X86_EMU_VUART)
+
+/* HVM PIRQ feature is user-selectable (libxl). */
+#define XEN_X86_EMU_HVM_SELECTABLE (XEN_X86_EMU_VPCI | \
+ XEN_X86_EMU_USE_PIRQ | \
+ XEN_X86_EMU_VUART)
+
+#define xen_emflags_allowable(x) ((x) & ~XEN_X86_EMU_HVM_SELECTABLE)
+
+#define XEN_X86_EMU_HVM_ALLOWABLE xen_emflags_allowable(XEN_X86_EMU_ALL)
+
uint32_t emulation_flags;
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Add new emulation flag for virtual UART on x86 and plumb it through the stack.
This change enables NS8250 emulator initialization.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
tools/libs/light/libxl_x86.c | 6 +++++-
tools/ocaml/libs/xc/xenctrl.ml | 1 +
tools/ocaml/libs/xc/xenctrl.mli | 1 +
tools/python/xen/lowlevel/xc/xc.c | 4 +---
xen/arch/x86/domain.c | 8 +++++---
xen/arch/x86/include/asm/domain.h | 7 ++++---
xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
7 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
--- a/tools/libs/light/libxl_x86.c
+++ b/tools/libs/light/libxl_x86.c
@@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
{
switch(d_config->c_info.type) {
case LIBXL_DOMAIN_TYPE_HVM:
- config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
+ config->arch.emulation_flags = XEN_X86_EMU_ALL;
+ config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
+ /* Virtual UART is selected at Xen build time */
+ config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
+
if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
break;
diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
--- a/tools/ocaml/libs/xc/xenctrl.ml
+++ b/tools/ocaml/libs/xc/xenctrl.ml
@@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
| X86_EMU_PIT
| X86_EMU_USE_PIRQ
| X86_EMU_VPCI
+ | X86_EMU_VUART
type x86_arch_misc_flags =
| X86_MSR_RELAXED
diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
--- a/tools/ocaml/libs/xc/xenctrl.mli
+++ b/tools/ocaml/libs/xc/xenctrl.mli
@@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
| X86_EMU_PIT
| X86_EMU_USE_PIRQ
| X86_EMU_VPCI
+ | X86_EMU_VUART
type x86_arch_misc_flags =
| X86_MSR_RELAXED
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
#if defined (__i386) || defined(__x86_64__)
if ( config.flags & XEN_DOMCTL_CDF_hvm )
- config.arch.emulation_flags = XEN_X86_EMU_ALL &
- ~(XEN_X86_EMU_VPCI |
- XEN_X86_EMU_USE_PIRQ);
+ config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
#elif defined (__arm__) || defined(__aarch64__)
config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
#else
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
if ( is_hardware_domain(d) &&
emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
return false;
+
+ emflags &= ~X86_EMU_VUART;
if ( !is_hardware_domain(d) &&
- /* HVM PIRQ feature is user-selectable. */
- (emflags & ~X86_EMU_USE_PIRQ) !=
- (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
+ xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
emflags != X86_EMU_LAPIC )
return false;
}
@@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
emflags = config->arch.emulation_flags;
+ if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
+ emflags |= XEN_X86_EMU_VUART;
if ( is_hardware_domain(d) && is_pv_domain(d) )
emflags |= XEN_X86_EMU_PIT;
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index c1d0d1f47324e8cc678a4c76c43f86820a89e7b3..dacea6e1aad46e9f8710b2202bb81203c5e92807 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -484,7 +484,8 @@ struct arch_domain
#define X86_EMU_VPCI 0
#endif
-#define X86_EMU_PIT XEN_X86_EMU_PIT
+#define X86_EMU_PIT XEN_X86_EMU_PIT
+#define X86_EMU_VUART XEN_X86_EMU_VUART
/* This must match XEN_X86_EMU_ALL in xen.h */
#define X86_EMU_ALL (X86_EMU_LAPIC | X86_EMU_HPET | \
@@ -492,7 +493,7 @@ struct arch_domain
X86_EMU_IOAPIC | X86_EMU_PIC | \
X86_EMU_VGA | X86_EMU_IOMMU | \
X86_EMU_PIT | X86_EMU_USE_PIRQ | \
- X86_EMU_VPCI)
+ X86_EMU_VPCI | X86_EMU_VUART)
#define has_vlapic(d) (!!((d)->arch.emulation_flags & X86_EMU_LAPIC))
#define has_vhpet(d) (!!((d)->arch.emulation_flags & X86_EMU_HPET))
@@ -507,7 +508,7 @@ struct arch_domain
#define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
/* NB: same symbol as in Arm port */
-#define domain_has_vuart(d) false
+#define domain_has_vuart(d) (!!((d)->arch.emulation_flags & X86_EMU_VUART))
#define gdt_ldt_pt_idx(v) \
((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
index fc2487986642a7694578ab9d2f5f16d09761bff8..e7922e3f9ddc1742a464d228807279839df31e52 100644
--- a/xen/include/public/arch-x86/xen.h
+++ b/xen/include/public/arch-x86/xen.h
@@ -283,13 +283,25 @@ struct xen_arch_domainconfig {
#define XEN_X86_EMU_USE_PIRQ (1U<<_XEN_X86_EMU_USE_PIRQ)
#define _XEN_X86_EMU_VPCI 10
#define XEN_X86_EMU_VPCI (1U<<_XEN_X86_EMU_VPCI)
+#define _XEN_X86_EMU_VUART 11
+#define XEN_X86_EMU_VUART (1U<<_XEN_X86_EMU_VUART)
#define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | XEN_X86_EMU_HPET | \
XEN_X86_EMU_PM | XEN_X86_EMU_RTC | \
XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | \
XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | \
XEN_X86_EMU_PIT | XEN_X86_EMU_USE_PIRQ |\
- XEN_X86_EMU_VPCI)
+ XEN_X86_EMU_VPCI | XEN_X86_EMU_VUART)
+
+/* HVM PIRQ feature is user-selectable (libxl). */
+#define XEN_X86_EMU_HVM_SELECTABLE (XEN_X86_EMU_VPCI | \
+ XEN_X86_EMU_USE_PIRQ | \
+ XEN_X86_EMU_VUART)
+
+#define xen_emflags_allowable(x) ((x) & ~XEN_X86_EMU_HVM_SELECTABLE)
+
+#define XEN_X86_EMU_HVM_ALLOWABLE xen_emflags_allowable(XEN_X86_EMU_ALL)
+
uint32_t emulation_flags;
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-13 12:23 ` Roger Pau Monné
2024-12-13 20:45 ` Stefano Stabellini
2025-01-04 5:19 ` Denis Mukhin
-1 siblings, 2 replies; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-13 12:23 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Thu, Dec 05, 2024 at 08:42:03PM -0800, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Add new emulation flag for virtual UART on x86 and plumb it through the stack.
>
> This change enables NS8250 emulator initialization.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> tools/libs/light/libxl_x86.c | 6 +++++-
> tools/ocaml/libs/xc/xenctrl.ml | 1 +
> tools/ocaml/libs/xc/xenctrl.mli | 1 +
> tools/python/xen/lowlevel/xc/xc.c | 4 +---
> xen/arch/x86/domain.c | 8 +++++---
> xen/arch/x86/include/asm/domain.h | 7 ++++---
> xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
> 7 files changed, 30 insertions(+), 11 deletions(-)
>
> diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
> index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
> --- a/tools/libs/light/libxl_x86.c
> +++ b/tools/libs/light/libxl_x86.c
> @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
> {
> switch(d_config->c_info.type) {
> case LIBXL_DOMAIN_TYPE_HVM:
> - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> + /* Virtual UART is selected at Xen build time */
> + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
> +
> if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
> config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
> break;
> diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
> index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
> --- a/tools/ocaml/libs/xc/xenctrl.ml
> +++ b/tools/ocaml/libs/xc/xenctrl.ml
> @@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
> | X86_EMU_PIT
> | X86_EMU_USE_PIRQ
> | X86_EMU_VPCI
> + | X86_EMU_VUART
>
> type x86_arch_misc_flags =
> | X86_MSR_RELAXED
> diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
> index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
> --- a/tools/ocaml/libs/xc/xenctrl.mli
> +++ b/tools/ocaml/libs/xc/xenctrl.mli
> @@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
> | X86_EMU_PIT
> | X86_EMU_USE_PIRQ
> | X86_EMU_VPCI
> + | X86_EMU_VUART
>
> type x86_arch_misc_flags =
> | X86_MSR_RELAXED
> diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
> --- a/tools/python/xen/lowlevel/xc/xc.c
> +++ b/tools/python/xen/lowlevel/xc/xc.c
> @@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
>
> #if defined (__i386) || defined(__x86_64__)
> if ( config.flags & XEN_DOMCTL_CDF_hvm )
> - config.arch.emulation_flags = XEN_X86_EMU_ALL &
> - ~(XEN_X86_EMU_VPCI |
> - XEN_X86_EMU_USE_PIRQ);
> + config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
> #elif defined (__arm__) || defined(__aarch64__)
> config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> #else
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
> if ( is_hardware_domain(d) &&
> emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
> return false;
> +
> + emflags &= ~X86_EMU_VUART;
I think you want to allow X86_EMU_VUART only for domains created by
Xen itself, so X86_EMU_VUART can only be valid if system_state <
SYS_STATE_active.
> if ( !is_hardware_domain(d) &&
> - /* HVM PIRQ feature is user-selectable. */
> - (emflags & ~X86_EMU_USE_PIRQ) !=
> - (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
> + xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
> emflags != X86_EMU_LAPIC )
> return false;
> }
> @@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
>
> emflags = config->arch.emulation_flags;
>
> + if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
> + emflags |= XEN_X86_EMU_VUART;
Doesn't this need to be limited to domains created by Xen itself, as
otherwise it's the toolstack that should specify the XEN_X86_EMU_VUART
flag, and even then the recommendation would be to use the vUART from
QEMU?
> if ( is_hardware_domain(d) && is_pv_domain(d) )
> emflags |= XEN_X86_EMU_PIT;
>
> diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
> index c1d0d1f47324e8cc678a4c76c43f86820a89e7b3..dacea6e1aad46e9f8710b2202bb81203c5e92807 100644
> --- a/xen/arch/x86/include/asm/domain.h
> +++ b/xen/arch/x86/include/asm/domain.h
> @@ -484,7 +484,8 @@ struct arch_domain
> #define X86_EMU_VPCI 0
> #endif
>
> -#define X86_EMU_PIT XEN_X86_EMU_PIT
> +#define X86_EMU_PIT XEN_X86_EMU_PIT
Unintended indentation change?
> +#define X86_EMU_VUART XEN_X86_EMU_VUART
>
> /* This must match XEN_X86_EMU_ALL in xen.h */
> #define X86_EMU_ALL (X86_EMU_LAPIC | X86_EMU_HPET | \
> @@ -492,7 +493,7 @@ struct arch_domain
> X86_EMU_IOAPIC | X86_EMU_PIC | \
> X86_EMU_VGA | X86_EMU_IOMMU | \
> X86_EMU_PIT | X86_EMU_USE_PIRQ | \
> - X86_EMU_VPCI)
> + X86_EMU_VPCI | X86_EMU_VUART)
>
> #define has_vlapic(d) (!!((d)->arch.emulation_flags & X86_EMU_LAPIC))
> #define has_vhpet(d) (!!((d)->arch.emulation_flags & X86_EMU_HPET))
> @@ -507,7 +508,7 @@ struct arch_domain
> #define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
>
> /* NB: same symbol as in Arm port */
> -#define domain_has_vuart(d) false
> +#define domain_has_vuart(d) (!!((d)->arch.emulation_flags & X86_EMU_VUART))
>
> #define gdt_ldt_pt_idx(v) \
> ((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
> diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
> index fc2487986642a7694578ab9d2f5f16d09761bff8..e7922e3f9ddc1742a464d228807279839df31e52 100644
> --- a/xen/include/public/arch-x86/xen.h
> +++ b/xen/include/public/arch-x86/xen.h
> @@ -283,13 +283,25 @@ struct xen_arch_domainconfig {
> #define XEN_X86_EMU_USE_PIRQ (1U<<_XEN_X86_EMU_USE_PIRQ)
> #define _XEN_X86_EMU_VPCI 10
> #define XEN_X86_EMU_VPCI (1U<<_XEN_X86_EMU_VPCI)
> +#define _XEN_X86_EMU_VUART 11
> +#define XEN_X86_EMU_VUART (1U<<_XEN_X86_EMU_VUART)
>
> #define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | XEN_X86_EMU_HPET | \
> XEN_X86_EMU_PM | XEN_X86_EMU_RTC | \
> XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | \
> XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | \
> XEN_X86_EMU_PIT | XEN_X86_EMU_USE_PIRQ |\
> - XEN_X86_EMU_VPCI)
> + XEN_X86_EMU_VPCI | XEN_X86_EMU_VUART)
> +
> +/* HVM PIRQ feature is user-selectable (libxl). */
> +#define XEN_X86_EMU_HVM_SELECTABLE (XEN_X86_EMU_VPCI | \
> + XEN_X86_EMU_USE_PIRQ | \
> + XEN_X86_EMU_VUART)
XEN_X86_EMU_HVM_OPTIONAL is maybe clearer?
Albeit PVH is kind of HVM.
> +
> +#define xen_emflags_allowable(x) ((x) & ~XEN_X86_EMU_HVM_SELECTABLE)
> +
> +#define XEN_X86_EMU_HVM_ALLOWABLE xen_emflags_allowable(XEN_X86_EMU_ALL)
XEN_X86_EMU_HVM_BASELINE I think would also be better?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-13 12:23 ` Roger Pau Monné
@ 2024-12-13 20:45 ` Stefano Stabellini
2024-12-16 8:40 ` Roger Pau Monné
2025-01-04 5:26 ` Denis Mukhin
2025-01-04 5:19 ` Denis Mukhin
1 sibling, 2 replies; 218+ messages in thread
From: Stefano Stabellini @ 2024-12-13 20:45 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
[-- Attachment #1: Type: text/plain, Size: 5599 bytes --]
On Fri, 13 Dec 2024, Roger Pau Monné wrote:
> On Thu, Dec 05, 2024 at 08:42:03PM -0800, Denis Mukhin via B4 Relay wrote:
> > From: Denis Mukhin <dmukhin@ford.com>
> >
> > Add new emulation flag for virtual UART on x86 and plumb it through the stack.
> >
> > This change enables NS8250 emulator initialization.
> >
> > Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> > ---
> > tools/libs/light/libxl_x86.c | 6 +++++-
> > tools/ocaml/libs/xc/xenctrl.ml | 1 +
> > tools/ocaml/libs/xc/xenctrl.mli | 1 +
> > tools/python/xen/lowlevel/xc/xc.c | 4 +---
> > xen/arch/x86/domain.c | 8 +++++---
> > xen/arch/x86/include/asm/domain.h | 7 ++++---
> > xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
> > 7 files changed, 30 insertions(+), 11 deletions(-)
> >
> > diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
> > index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
> > --- a/tools/libs/light/libxl_x86.c
> > +++ b/tools/libs/light/libxl_x86.c
> > @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
> > {
> > switch(d_config->c_info.type) {
> > case LIBXL_DOMAIN_TYPE_HVM:
> > - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> > + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> > + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> > + /* Virtual UART is selected at Xen build time */
> > + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
> > +
> > if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
> > config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
> > break;
> > diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
> > index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
> > --- a/tools/ocaml/libs/xc/xenctrl.ml
> > +++ b/tools/ocaml/libs/xc/xenctrl.ml
> > @@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
> > | X86_EMU_PIT
> > | X86_EMU_USE_PIRQ
> > | X86_EMU_VPCI
> > + | X86_EMU_VUART
> >
> > type x86_arch_misc_flags =
> > | X86_MSR_RELAXED
> > diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
> > index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
> > --- a/tools/ocaml/libs/xc/xenctrl.mli
> > +++ b/tools/ocaml/libs/xc/xenctrl.mli
> > @@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
> > | X86_EMU_PIT
> > | X86_EMU_USE_PIRQ
> > | X86_EMU_VPCI
> > + | X86_EMU_VUART
> >
> > type x86_arch_misc_flags =
> > | X86_MSR_RELAXED
> > diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> > index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
> > --- a/tools/python/xen/lowlevel/xc/xc.c
> > +++ b/tools/python/xen/lowlevel/xc/xc.c
> > @@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
> >
> > #if defined (__i386) || defined(__x86_64__)
> > if ( config.flags & XEN_DOMCTL_CDF_hvm )
> > - config.arch.emulation_flags = XEN_X86_EMU_ALL &
> > - ~(XEN_X86_EMU_VPCI |
> > - XEN_X86_EMU_USE_PIRQ);
> > + config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
> > #elif defined (__arm__) || defined(__aarch64__)
> > config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> > #else
> > diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> > index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
> > --- a/xen/arch/x86/domain.c
> > +++ b/xen/arch/x86/domain.c
> > @@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
> > if ( is_hardware_domain(d) &&
> > emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
> > return false;
> > +
> > + emflags &= ~X86_EMU_VUART;
>
> I think you want to allow X86_EMU_VUART only for domains created by
> Xen itself, so X86_EMU_VUART can only be valid if system_state <
> SYS_STATE_active.
>
> > if ( !is_hardware_domain(d) &&
> > - /* HVM PIRQ feature is user-selectable. */
> > - (emflags & ~X86_EMU_USE_PIRQ) !=
> > - (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
> > + xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
> > emflags != X86_EMU_LAPIC )
> > return false;
> > }
> > @@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
> >
> > emflags = config->arch.emulation_flags;
> >
> > + if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
> > + emflags |= XEN_X86_EMU_VUART;
>
> Doesn't this need to be limited to domains created by Xen itself, as
> otherwise it's the toolstack that should specify the XEN_X86_EMU_VUART
> flag, and even then the recommendation would be to use the vUART from
> QEMU?
While I agree with you that this feature is really useful mostly for the
domains created by Xen, as for those there is no other way to get early
output, I think Denis has been also testing successfully this feature
with PVH or HVM domains created by the toolstack.
I'll let you decide whether you want to expose the feature to xl created
domains, but yes my understanding is that they already work with this
series. One benefit would be that for PVH domains you could get early
output without having to start QEMU, but I'll leave this to you.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-13 20:45 ` Stefano Stabellini
@ 2024-12-16 8:40 ` Roger Pau Monné
2025-01-04 5:26 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-16 8:40 UTC (permalink / raw)
To: Stefano Stabellini
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall
On Fri, Dec 13, 2024 at 12:45:34PM -0800, Stefano Stabellini wrote:
> On Fri, 13 Dec 2024, Roger Pau Monné wrote:
> > On Thu, Dec 05, 2024 at 08:42:03PM -0800, Denis Mukhin via B4 Relay wrote:
> > > From: Denis Mukhin <dmukhin@ford.com>
> > >
> > > Add new emulation flag for virtual UART on x86 and plumb it through the stack.
> > >
> > > This change enables NS8250 emulator initialization.
> > >
> > > Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> > > ---
> > > tools/libs/light/libxl_x86.c | 6 +++++-
> > > tools/ocaml/libs/xc/xenctrl.ml | 1 +
> > > tools/ocaml/libs/xc/xenctrl.mli | 1 +
> > > tools/python/xen/lowlevel/xc/xc.c | 4 +---
> > > xen/arch/x86/domain.c | 8 +++++---
> > > xen/arch/x86/include/asm/domain.h | 7 ++++---
> > > xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
> > > 7 files changed, 30 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
> > > index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
> > > --- a/tools/libs/light/libxl_x86.c
> > > +++ b/tools/libs/light/libxl_x86.c
> > > @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
> > > {
> > > switch(d_config->c_info.type) {
> > > case LIBXL_DOMAIN_TYPE_HVM:
> > > - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> > > + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> > > + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> > > + /* Virtual UART is selected at Xen build time */
> > > + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
> > > +
> > > if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
> > > config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
> > > break;
> > > diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
> > > index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
> > > --- a/tools/ocaml/libs/xc/xenctrl.ml
> > > +++ b/tools/ocaml/libs/xc/xenctrl.ml
> > > @@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
> > > | X86_EMU_PIT
> > > | X86_EMU_USE_PIRQ
> > > | X86_EMU_VPCI
> > > + | X86_EMU_VUART
> > >
> > > type x86_arch_misc_flags =
> > > | X86_MSR_RELAXED
> > > diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
> > > index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
> > > --- a/tools/ocaml/libs/xc/xenctrl.mli
> > > +++ b/tools/ocaml/libs/xc/xenctrl.mli
> > > @@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
> > > | X86_EMU_PIT
> > > | X86_EMU_USE_PIRQ
> > > | X86_EMU_VPCI
> > > + | X86_EMU_VUART
> > >
> > > type x86_arch_misc_flags =
> > > | X86_MSR_RELAXED
> > > diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> > > index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
> > > --- a/tools/python/xen/lowlevel/xc/xc.c
> > > +++ b/tools/python/xen/lowlevel/xc/xc.c
> > > @@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
> > >
> > > #if defined (__i386) || defined(__x86_64__)
> > > if ( config.flags & XEN_DOMCTL_CDF_hvm )
> > > - config.arch.emulation_flags = XEN_X86_EMU_ALL &
> > > - ~(XEN_X86_EMU_VPCI |
> > > - XEN_X86_EMU_USE_PIRQ);
> > > + config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
> > > #elif defined (__arm__) || defined(__aarch64__)
> > > config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> > > #else
> > > diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> > > index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
> > > --- a/xen/arch/x86/domain.c
> > > +++ b/xen/arch/x86/domain.c
> > > @@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
> > > if ( is_hardware_domain(d) &&
> > > emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
> > > return false;
> > > +
> > > + emflags &= ~X86_EMU_VUART;
> >
> > I think you want to allow X86_EMU_VUART only for domains created by
> > Xen itself, so X86_EMU_VUART can only be valid if system_state <
> > SYS_STATE_active.
> >
> > > if ( !is_hardware_domain(d) &&
> > > - /* HVM PIRQ feature is user-selectable. */
> > > - (emflags & ~X86_EMU_USE_PIRQ) !=
> > > - (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
> > > + xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
> > > emflags != X86_EMU_LAPIC )
> > > return false;
> > > }
> > > @@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
> > >
> > > emflags = config->arch.emulation_flags;
> > >
> > > + if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
> > > + emflags |= XEN_X86_EMU_VUART;
> >
> > Doesn't this need to be limited to domains created by Xen itself, as
> > otherwise it's the toolstack that should specify the XEN_X86_EMU_VUART
> > flag, and even then the recommendation would be to use the vUART from
> > QEMU?
>
> While I agree with you that this feature is really useful mostly for the
> domains created by Xen, as for those there is no other way to get early
> output, I think Denis has been also testing successfully this feature
> with PVH or HVM domains created by the toolstack.
>
> I'll let you decide whether you want to expose the feature to xl created
> domains, but yes my understanding is that they already work with this
> series. One benefit would be that for PVH domains you could get early
> output without having to start QEMU, but I'll leave this to you.
I'm not opposed to allowing usage of the Xen emulated uart for
toolstack created domains, but then the option needs to be integrated
with xl/libxl IMO, so that it can be specified in the xl.cfg file, and
propagated from the toolstack into Xen using the emulation_flags
field. Just like all other emulated devices that are controlled by
emulation_flags.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-13 20:45 ` Stefano Stabellini
2024-12-16 8:40 ` Roger Pau Monné
@ 2025-01-04 5:26 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 5:26 UTC (permalink / raw)
To: Stefano Stabellini
Cc: Roger Pau Monné, dmukhin, xen-devel, Andrew Cooper,
Jan Beulich, Julien Grall
On Friday, December 13th, 2024 at 12:45 PM, Stefano Stabellini <sstabellini@kernel.org> wrote:
>
>
> On Fri, 13 Dec 2024, Roger Pau Monné wrote:
>
> > On Thu, Dec 05, 2024 at 08:42:03PM -0800, Denis Mukhin via B4 Relay wrote:
> >
> > > From: Denis Mukhin dmukhin@ford.com
> > >
> > > Add new emulation flag for virtual UART on x86 and plumb it through the stack.
> > >
> > > This change enables NS8250 emulator initialization.
> > >
> > > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > > ---
> > > tools/libs/light/libxl_x86.c | 6 +++++-
> > > tools/ocaml/libs/xc/xenctrl.ml | 1 +
> > > tools/ocaml/libs/xc/xenctrl.mli | 1 +
> > > tools/python/xen/lowlevel/xc/xc.c | 4 +---
> > > xen/arch/x86/domain.c | 8 +++++---
> > > xen/arch/x86/include/asm/domain.h | 7 ++++---
> > > xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
> > > 7 files changed, 30 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
> > > index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
> > > --- a/tools/libs/light/libxl_x86.c
> > > +++ b/tools/libs/light/libxl_x86.c
> > > @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc gc,
> > > {
> > > switch(d_config->c_info.type) {
> > > case LIBXL_DOMAIN_TYPE_HVM:
> > > - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> > > + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> > > + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> > > + / Virtual UART is selected at Xen build time */
> > > + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
> > > +
> > > if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
> > > config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
> > > break;
> > > diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
> > > index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
> > > --- a/tools/ocaml/libs/xc/xenctrl.ml
> > > +++ b/tools/ocaml/libs/xc/xenctrl.ml
> > > @@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
> > > | X86_EMU_PIT
> > > | X86_EMU_USE_PIRQ
> > > | X86_EMU_VPCI
> > > + | X86_EMU_VUART
> > >
> > > type x86_arch_misc_flags =
> > > | X86_MSR_RELAXED
> > > diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
> > > index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
> > > --- a/tools/ocaml/libs/xc/xenctrl.mli
> > > +++ b/tools/ocaml/libs/xc/xenctrl.mli
> > > @@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
> > > | X86_EMU_PIT
> > > | X86_EMU_USE_PIRQ
> > > | X86_EMU_VPCI
> > > + | X86_EMU_VUART
> > >
> > > type x86_arch_misc_flags =
> > > | X86_MSR_RELAXED
> > > diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> > > index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
> > > --- a/tools/python/xen/lowlevel/xc/xc.c
> > > +++ b/tools/python/xen/lowlevel/xc/xc.c
> > > @@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
> > >
> > > #if defined (__i386) || defined(x86_64)
> > > if ( config.flags & XEN_DOMCTL_CDF_hvm )
> > > - config.arch.emulation_flags = XEN_X86_EMU_ALL &
> > > - ~(XEN_X86_EMU_VPCI |
> > > - XEN_X86_EMU_USE_PIRQ);
> > > + config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
> > > #elif defined (arm) || defined(aarch64)
> > > config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> > > #else
> > > diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> > > index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
> > > --- a/xen/arch/x86/domain.c
> > > +++ b/xen/arch/x86/domain.c
> > > @@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
> > > if ( is_hardware_domain(d) &&
> > > emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
> > > return false;
> > > +
> > > + emflags &= ~X86_EMU_VUART;
> >
> > I think you want to allow X86_EMU_VUART only for domains created by
> > Xen itself, so X86_EMU_VUART can only be valid if system_state <
> > SYS_STATE_active.
> >
> > > if ( !is_hardware_domain(d) &&
> > > - /* HVM PIRQ feature is user-selectable. */
> > > - (emflags & ~X86_EMU_USE_PIRQ) !=
> > > - (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
> > > + xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
> > > emflags != X86_EMU_LAPIC )
> > > return false;
> > > }
> > > @@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
> > >
> > > emflags = config->arch.emulation_flags;
> > >
> > > + if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
> > > + emflags |= XEN_X86_EMU_VUART;
> >
> > Doesn't this need to be limited to domains created by Xen itself, as
> > otherwise it's the toolstack that should specify the XEN_X86_EMU_VUART
> > flag, and even then the recommendation would be to use the vUART from
> > QEMU?
>
>
> While I agree with you that this feature is really useful mostly for the
> domains created by Xen, as for those there is no other way to get early
> output, I think Denis has been also testing successfully this feature
> with PVH or HVM domains created by the toolstack.
I tested w/ HVM only for now.
PVH needs some more work as it does not have vPIC.
>
> I'll let you decide whether you want to expose the feature to xl created
> domains, but yes my understanding is that they already work with this
> series. One benefit would be that for PVH domains you could get early
> output without having to start QEMU, but I'll leave this to you.
TBH, I planned to enable xl support in the follow on series.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-13 12:23 ` Roger Pau Monné
2024-12-13 20:45 ` Stefano Stabellini
@ 2025-01-04 5:19 ` Denis Mukhin
2025-01-07 15:16 ` Roger Pau Monné
1 sibling, 1 reply; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 5:19 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Friday, December 13th, 2024 at 4:23 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:42:03PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Add new emulation flag for virtual UART on x86 and plumb it through the stack.
> >
> > This change enables NS8250 emulator initialization.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > tools/libs/light/libxl_x86.c | 6 +++++-
> > tools/ocaml/libs/xc/xenctrl.ml | 1 +
> > tools/ocaml/libs/xc/xenctrl.mli | 1 +
> > tools/python/xen/lowlevel/xc/xc.c | 4 +---
> > xen/arch/x86/domain.c | 8 +++++---
> > xen/arch/x86/include/asm/domain.h | 7 ++++---
> > xen/include/public/arch-x86/xen.h | 14 +++++++++++++-
> > 7 files changed, 30 insertions(+), 11 deletions(-)
> >
> > diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
> > index a3164a3077fec7e1b81a34074894dc646954a49a..de5f05e18cb0671bb031b101b9a7159eb0fe0178 100644
> > --- a/tools/libs/light/libxl_x86.c
> > +++ b/tools/libs/light/libxl_x86.c
> > @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc gc,
> > {
> > switch(d_config->c_info.type) {
> > case LIBXL_DOMAIN_TYPE_HVM:
> > - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> > + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> > + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> > + / Virtual UART is selected at Xen build time */
> > + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
> > +
> > if (!libxl_defbool_val(d_config->b_info.u.hvm.pirq))
> > config->arch.emulation_flags &= ~XEN_X86_EMU_USE_PIRQ;
> > break;
> > diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
> > index 2690f9a92316b812ad3d3ff0e1c36823070adb4a..647239b3e55e88b00eb8e9773a5267894cbbae54 100644
> > --- a/tools/ocaml/libs/xc/xenctrl.ml
> > +++ b/tools/ocaml/libs/xc/xenctrl.ml
> > @@ -47,6 +47,7 @@ type x86_arch_emulation_flags =
> > | X86_EMU_PIT
> > | X86_EMU_USE_PIRQ
> > | X86_EMU_VPCI
> > + | X86_EMU_VUART
> >
> > type x86_arch_misc_flags =
> > | X86_MSR_RELAXED
> > diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
> > index febbe1f6ae3f10c5abe45eaa3c06a8a67d9ba268..4f5f64c786e83e8a0c3dd3cdb0460f7095de4a62 100644
> > --- a/tools/ocaml/libs/xc/xenctrl.mli
> > +++ b/tools/ocaml/libs/xc/xenctrl.mli
> > @@ -41,6 +41,7 @@ type x86_arch_emulation_flags =
> > | X86_EMU_PIT
> > | X86_EMU_USE_PIRQ
> > | X86_EMU_VPCI
> > + | X86_EMU_VUART
> >
> > type x86_arch_misc_flags =
> > | X86_MSR_RELAXED
> > diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> > index 9feb12ae2b16e48cb5d0c3c45044ae226f152f2d..e54308956efc7061d58d2166ec9a95bc1dcd1781 100644
> > --- a/tools/python/xen/lowlevel/xc/xc.c
> > +++ b/tools/python/xen/lowlevel/xc/xc.c
> > @@ -159,9 +159,7 @@ static PyObject *pyxc_domain_create(XcObject *self,
> >
> > #if defined (__i386) || defined(x86_64)
> > if ( config.flags & XEN_DOMCTL_CDF_hvm )
> > - config.arch.emulation_flags = XEN_X86_EMU_ALL &
> > - ~(XEN_X86_EMU_VPCI |
> > - XEN_X86_EMU_USE_PIRQ);
> > + config.arch.emulation_flags = XEN_X86_EMU_HVM_ALLOWABLE;
> > #elif defined (arm) || defined(aarch64)
> > config.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> > #else
> > diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> > index c88d422a64544531c1e1058fa484364bb4277d1e..439da7adc92a3a8eb481075bf834da5f9670dd54 100644
> > --- a/xen/arch/x86/domain.c
> > +++ b/xen/arch/x86/domain.c
> > @@ -752,10 +752,10 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
> > if ( is_hardware_domain(d) &&
> > emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) )
> > return false;
> > +
> > + emflags &= ~X86_EMU_VUART;
>
>
> I think you want to allow X86_EMU_VUART only for domains created by
> Xen itself, so X86_EMU_VUART can only be valid if system_state <
> SYS_STATE_active.
I think vUART should be configurable for domains created via toolstack
as well as for domains created by Xen.
But, TBH, I did not plan for toolstack integration in this series.
For Xen-created domains enabling emulator for HVM domains only and enabling
it globally (since that's debugging/bringup only) seemed enough for the
initial change.
>
> > if ( !is_hardware_domain(d) &&
> > - /* HVM PIRQ feature is user-selectable. */
> > - (emflags & ~X86_EMU_USE_PIRQ) !=
> > - (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) &&
> > + xen_emflags_allowable(emflags) != XEN_X86_EMU_HVM_ALLOWABLE &&
> > emflags != X86_EMU_LAPIC )
> > return false;
> > }
> > @@ -806,6 +806,8 @@ int arch_domain_create(struct domain *d,
> >
> > emflags = config->arch.emulation_flags;
> >
> > + if ( IS_ENABLED(CONFIG_HAS_VUART_NS8250) && is_hvm_domain(d) )
> > + emflags |= XEN_X86_EMU_VUART;
>
>
> Doesn't this need to be limited to domains created by Xen itself, as
> otherwise it's the toolstack that should specify the XEN_X86_EMU_VUART
> flag, and even then the recommendation would be to use the vUART from
> QEMU?
re: toolstack: I agree, toolstack should support vUART configuration.
I plan to address it in the follow on series.
>
> > if ( is_hardware_domain(d) && is_pv_domain(d) )
> > emflags |= XEN_X86_EMU_PIT;
> >
> > diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
> > index c1d0d1f47324e8cc678a4c76c43f86820a89e7b3..dacea6e1aad46e9f8710b2202bb81203c5e92807 100644
> > --- a/xen/arch/x86/include/asm/domain.h
> > +++ b/xen/arch/x86/include/asm/domain.h
> > @@ -484,7 +484,8 @@ struct arch_domain
> > #define X86_EMU_VPCI 0
> > #endif
> >
> > -#define X86_EMU_PIT XEN_X86_EMU_PIT
> > +#define X86_EMU_PIT XEN_X86_EMU_PIT
>
>
> Unintended indentation change?
Actually, this change was intentional: it fixes the alignment against
previous #ifdefs.
>
> > +#define X86_EMU_VUART XEN_X86_EMU_VUART
> >
> > /* This must match XEN_X86_EMU_ALL in xen.h */
> > #define X86_EMU_ALL (X86_EMU_LAPIC | X86_EMU_HPET | \
> > @@ -492,7 +493,7 @@ struct arch_domain
> > X86_EMU_IOAPIC | X86_EMU_PIC | \
> > X86_EMU_VGA | X86_EMU_IOMMU | \
> > X86_EMU_PIT | X86_EMU_USE_PIRQ | \
> > - X86_EMU_VPCI)
> > + X86_EMU_VPCI | X86_EMU_VUART)
> >
> > #define has_vlapic(d) (!!((d)->arch.emulation_flags & X86_EMU_LAPIC))
> > #define has_vhpet(d) (!!((d)->arch.emulation_flags & X86_EMU_HPET))
> > @@ -507,7 +508,7 @@ struct arch_domain
> > #define has_vpci(d) (!!((d)->arch.emulation_flags & X86_EMU_VPCI))
> >
> > /* NB: same symbol as in Arm port */
> > -#define domain_has_vuart(d) false
> > +#define domain_has_vuart(d) (!!((d)->arch.emulation_flags & X86_EMU_VUART))
> >
> > #define gdt_ldt_pt_idx(v) \
> > ((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
> > diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
> > index fc2487986642a7694578ab9d2f5f16d09761bff8..e7922e3f9ddc1742a464d228807279839df31e52 100644
> > --- a/xen/include/public/arch-x86/xen.h
> > +++ b/xen/include/public/arch-x86/xen.h
> > @@ -283,13 +283,25 @@ struct xen_arch_domainconfig {
> > #define XEN_X86_EMU_USE_PIRQ (1U<<_XEN_X86_EMU_USE_PIRQ)
> > #define _XEN_X86_EMU_VPCI 10
> > #define XEN_X86_EMU_VPCI (1U<<_XEN_X86_EMU_VPCI)
> > +#define _XEN_X86_EMU_VUART 11
> > +#define XEN_X86_EMU_VUART (1U<<_XEN_X86_EMU_VUART)
> >
> > #define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | XEN_X86_EMU_HPET | \
> > XEN_X86_EMU_PM | XEN_X86_EMU_RTC | \
> > XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | \
> > XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | \
> > XEN_X86_EMU_PIT | XEN_X86_EMU_USE_PIRQ |\
> > - XEN_X86_EMU_VPCI)
> > + XEN_X86_EMU_VPCI | XEN_X86_EMU_VUART)
> > +
> > +/* HVM PIRQ feature is user-selectable (libxl). */
> > +#define XEN_X86_EMU_HVM_SELECTABLE (XEN_X86_EMU_VPCI | \
> > + XEN_X86_EMU_USE_PIRQ | \
> > + XEN_X86_EMU_VUART)
>
>
> XEN_X86_EMU_HVM_OPTIONAL is maybe clearer?
Looks like it, thanks for suggestion!
Fixed.
>
> Albeit PVH is kind of HVM.
PVH does not have vPIC so there's some more work to enable vUART
for PVH on x86: emulator currently supports only ISA IRQs.
>
> > +
> > +#define xen_emflags_allowable(x) ((x) & ~XEN_X86_EMU_HVM_SELECTABLE)
> > +
> > +#define XEN_X86_EMU_HVM_ALLOWABLE xen_emflags_allowable(XEN_X86_EMU_ALL)
>
>
> XEN_X86_EMU_HVM_BASELINE I think would also be better?
Fixed.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2025-01-04 5:19 ` Denis Mukhin
@ 2025-01-07 15:16 ` Roger Pau Monné
2025-01-07 17:33 ` Denis Mukhin
0 siblings, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2025-01-07 15:16 UTC (permalink / raw)
To: Denis Mukhin
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Sat, Jan 04, 2025 at 05:19:07AM +0000, Denis Mukhin wrote:
> On Friday, December 13th, 2024 at 4:23 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
> > Albeit PVH is kind of HVM.
>
> PVH does not have vPIC so there's some more work to enable vUART
> for PVH on x86: emulator currently supports only ISA IRQs.
But it does support vIO-APIC (as it's used for hardware PVH domain),
so serial interrupts could still be delivered using the vIO-APIC if
the guest has correctly configured the pin?
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2025-01-07 15:16 ` Roger Pau Monné
@ 2025-01-07 17:33 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-07 17:33 UTC (permalink / raw)
To: Roger Pau Monné
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Tuesday, January 7th, 2025 at 7:16 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Sat, Jan 04, 2025 at 05:19:07AM +0000, Denis Mukhin wrote:
>
> > On Friday, December 13th, 2024 at 4:23 AM, Roger Pau Monné roger.pau@citrix.com wrote:
> >
> > > Albeit PVH is kind of HVM.
> >
> > PVH does not have vPIC so there's some more work to enable vUART
> > for PVH on x86: emulator currently supports only ISA IRQs.
>
>
> But it does support vIO-APIC (as it's used for hardware PVH domain),
> so serial interrupts could still be delivered using the vIO-APIC if
> the guest has correctly configured the pin?
re: virtual I/O APIC: correct, that's what I meant by "more work":
I did not debug PVH in detail yet.
My plan is to enable PVH in a separate patch (timeline - v4, since v3
it out recently).
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
(?)
@ 2024-12-16 15:11 ` Jan Beulich
2025-01-04 5:26 ` Denis Mukhin
-1 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-16 15:11 UTC (permalink / raw)
To: dmukhin; +Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
> --- a/tools/libs/light/libxl_x86.c
> +++ b/tools/libs/light/libxl_x86.c
> @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
> {
> switch(d_config->c_info.type) {
> case LIBXL_DOMAIN_TYPE_HVM:
> - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> + /* Virtual UART is selected at Xen build time */
> + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
That is all domains, even post-boot created ones, only ever get the same
setting?
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 33/35] x86/domain: implement domain_has_vuart()
2024-12-16 15:11 ` Jan Beulich
@ 2025-01-04 5:26 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 5:26 UTC (permalink / raw)
To: Jan Beulich
Cc: dmukhin, Andrew Cooper, Julien Grall, Stefano Stabellini,
xen-devel
On Monday, December 16th, 2024 at 7:11 AM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 06.12.2024 05:42, Denis Mukhin via B4 Relay wrote:
>
> > --- a/tools/libs/light/libxl_x86.c
> > +++ b/tools/libs/light/libxl_x86.c
> > @@ -8,7 +8,11 @@ int libxl__arch_domain_prepare_config(libxl__gc gc,
> > {
> > switch(d_config->c_info.type) {
> > case LIBXL_DOMAIN_TYPE_HVM:
> > - config->arch.emulation_flags = (XEN_X86_EMU_ALL & ~XEN_X86_EMU_VPCI);
> > + config->arch.emulation_flags = XEN_X86_EMU_ALL;
> > + config->arch.emulation_flags &= ~XEN_X86_EMU_VPCI;
> > + / Virtual UART is selected at Xen build time */
> > + config->arch.emulation_flags &= ~XEN_X86_EMU_VUART;
>
>
> That is all domains, even post-boot created ones, only ever get the same
> setting?
Toolstack cannot control vUART configuration yet. vUART can be enabled for
HVM domains only at this point and only globally, which seemed enough for the
initial implementation.
PVH needs some more work because PVH does not have vPIC.
I did not plan to enable per-domain configuration in this patch series (plan
to address in the follow on series). The emulator is disabled in default Xen
configuration, so it should not affect the existing default behavior.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Enable console focus for domains w/ virtual NS8250.
Code change allows to capture the output from the guest OS now and send it to
the physical console device.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -41,6 +41,9 @@
#ifdef CONFIG_SBSA_VUART_CONSOLE
#include <asm/vpl011.h>
#endif
+#if defined(CONFIG_HAS_VUART_NS8250)
+#include <asm/hvm/vuart_ns8250.h>
+#endif
/* console: comma-separated list of console outputs. */
static char __initdata opt_console[30] = OPT_CONSOLE_STR;
@@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
{
#if defined(CONFIG_SBSA_VUART_CONSOLE)
rc = vpl011_rx_char_xen(d, c);
+#elif defined(CONFIG_HAS_VUART_NS8250)
+ rc = vuart_putchar(&d->arch.hvm.vuart, c);
#endif
}
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Enable console focus for domains w/ virtual NS8250.
Code change allows to capture the output from the guest OS now and send it to
the physical console device.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
xen/drivers/char/console.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -41,6 +41,9 @@
#ifdef CONFIG_SBSA_VUART_CONSOLE
#include <asm/vpl011.h>
#endif
+#if defined(CONFIG_HAS_VUART_NS8250)
+#include <asm/hvm/vuart_ns8250.h>
+#endif
/* console: comma-separated list of console outputs. */
static char __initdata opt_console[30] = OPT_CONSOLE_STR;
@@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
{
#if defined(CONFIG_SBSA_VUART_CONSOLE)
rc = vpl011_rx_char_xen(d, c);
+#elif defined(CONFIG_HAS_VUART_NS8250)
+ rc = vuart_putchar(&d->arch.hvm.vuart, c);
#endif
}
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* Re: [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
2024-12-06 4:42 ` Denis Mukhin via B4 Relay
(?)
@ 2024-12-10 22:46 ` Jason Andryuk
2024-12-11 7:35 ` Jan Beulich
` (2 more replies)
-1 siblings, 3 replies; 218+ messages in thread
From: Jason Andryuk @ 2024-12-10 22:46 UTC (permalink / raw)
To: dmukhin, xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini
On 2024-12-05 23:42, Denis Mukhin via B4 Relay wrote:
> From: Denis Mukhin <dmukhin@ford.com>
>
> Enable console focus for domains w/ virtual NS8250.
>
> Code change allows to capture the output from the guest OS now and send it to
> the physical console device.
>
> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
> ---
> xen/drivers/char/console.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -41,6 +41,9 @@
> #ifdef CONFIG_SBSA_VUART_CONSOLE
> #include <asm/vpl011.h>
> #endif
> +#if defined(CONFIG_HAS_VUART_NS8250)
> +#include <asm/hvm/vuart_ns8250.h>
> +#endif
>
> /* console: comma-separated list of console outputs. */
> static char __initdata opt_console[30] = OPT_CONSOLE_STR;
> @@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
> {
> #if defined(CONFIG_SBSA_VUART_CONSOLE)
> rc = vpl011_rx_char_xen(d, c);
> +#elif defined(CONFIG_HAS_VUART_NS8250)
> + rc = vuart_putchar(&d->arch.hvm.vuart, c);
> #endif
I think it would be nicer to just use a single name and avoid ifdef-ery.
vuart_putchar() is generic and matches domain_has_vuart(), so that
seems good.
You can then have a default stub that returns -ENODEV for when an
implementation is not built. (This goes along with Jan's suggestion of
a common, default domain_has_vuart().) Something like:
#ifndef vuart_putchar
static inline int vuart_putchar(struct domain *d, char c) {
return -ENODEV;
}
#define vuart_putchar vuart_putchar
#endif
and ARM can do:
#define vuart_putchar vpl011_rx_char_xen
x86 would need to change its arguments, but that should be straight forward.
What do you think?
Regards,
Jason
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
2024-12-10 22:46 ` Jason Andryuk
@ 2024-12-11 7:35 ` Jan Beulich
2024-12-11 7:38 ` Jan Beulich
2025-01-04 3:08 ` Denis Mukhin
2 siblings, 0 replies; 218+ messages in thread
From: Jan Beulich @ 2024-12-11 7:35 UTC (permalink / raw)
To: Jason Andryuk, dmukhin
Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 10.12.2024 23:46, Jason Andryuk wrote:
> On 2024-12-05 23:42, Denis Mukhin via B4 Relay wrote:
>> From: Denis Mukhin <dmukhin@ford.com>
>>
>> Enable console focus for domains w/ virtual NS8250.
>>
>> Code change allows to capture the output from the guest OS now and send it to
>> the physical console device.
>>
>> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
>> ---
>> xen/drivers/char/console.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
>> index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
>> --- a/xen/drivers/char/console.c
>> +++ b/xen/drivers/char/console.c
>> @@ -41,6 +41,9 @@
>> #ifdef CONFIG_SBSA_VUART_CONSOLE
>> #include <asm/vpl011.h>
>> #endif
>> +#if defined(CONFIG_HAS_VUART_NS8250)
>> +#include <asm/hvm/vuart_ns8250.h>
>> +#endif
>>
>> /* console: comma-separated list of console outputs. */
>> static char __initdata opt_console[30] = OPT_CONSOLE_STR;
>> @@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
>> {
>> #if defined(CONFIG_SBSA_VUART_CONSOLE)
>> rc = vpl011_rx_char_xen(d, c);
>> +#elif defined(CONFIG_HAS_VUART_NS8250)
>> + rc = vuart_putchar(&d->arch.hvm.vuart, c);
>> #endif
>
> I think it would be nicer to just use a single name and avoid ifdef-ery.
> vuart_putchar() is generic and matches domain_has_vuart(), so that
> seems good.
>
> You can then have a default stub that returns -ENODEV for when an
> implementation is not built. (This goes along with Jan's suggestion of
> a common, default domain_has_vuart().) Something like:
>
> #ifndef vuart_putchar
> static inline int vuart_putchar(struct domain *d, char c) {
> return -ENODEV;
> }
> #define vuart_putchar vuart_putchar
> #endif
>
> and ARM can do:
> #define vuart_putchar vpl011_rx_char_xen
+1
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
2024-12-10 22:46 ` Jason Andryuk
2024-12-11 7:35 ` Jan Beulich
@ 2024-12-11 7:38 ` Jan Beulich
2025-01-04 3:12 ` Denis Mukhin
2025-01-04 3:08 ` Denis Mukhin
2 siblings, 1 reply; 218+ messages in thread
From: Jan Beulich @ 2024-12-11 7:38 UTC (permalink / raw)
To: Jason Andryuk, dmukhin
Cc: Andrew Cooper, Julien Grall, Stefano Stabellini, xen-devel
On 10.12.2024 23:46, Jason Andryuk wrote:
> On 2024-12-05 23:42, Denis Mukhin via B4 Relay wrote:
>> From: Denis Mukhin <dmukhin@ford.com>
>>
>> Enable console focus for domains w/ virtual NS8250.
>>
>> Code change allows to capture the output from the guest OS now and send it to
>> the physical console device.
>>
>> Signed-off-by: Denis Mukhin <dmukhin@ford.com>
>> ---
>> xen/drivers/char/console.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
>> index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
>> --- a/xen/drivers/char/console.c
>> +++ b/xen/drivers/char/console.c
>> @@ -41,6 +41,9 @@
>> #ifdef CONFIG_SBSA_VUART_CONSOLE
>> #include <asm/vpl011.h>
>> #endif
>> +#if defined(CONFIG_HAS_VUART_NS8250)
>> +#include <asm/hvm/vuart_ns8250.h>
>> +#endif
>>
>> /* console: comma-separated list of console outputs. */
>> static char __initdata opt_console[30] = OPT_CONSOLE_STR;
>> @@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
>> {
>> #if defined(CONFIG_SBSA_VUART_CONSOLE)
>> rc = vpl011_rx_char_xen(d, c);
>> +#elif defined(CONFIG_HAS_VUART_NS8250)
>> + rc = vuart_putchar(&d->arch.hvm.vuart, c);
>> #endif
>
> I think it would be nicer to just use a single name and avoid ifdef-ery.
> vuart_putchar() is generic and matches domain_has_vuart(), so that
> seems good.
>
> You can then have a default stub that returns -ENODEV for when an
> implementation is not built. (This goes along with Jan's suggestion of
> a common, default domain_has_vuart().) Something like:
>
> #ifndef vuart_putchar
> static inline int vuart_putchar(struct domain *d, char c) {
> return -ENODEV;
> }
> #define vuart_putchar vuart_putchar
> #endif
>
> and ARM can do:
> #define vuart_putchar vpl011_rx_char_xen
>
> x86 would need to change its arguments, but that should be straight forward.
Actually, I don't even see a need for the stub:
{
#ifdef vuart_putchar
rc = vuart_putchar(d, c);
#endif
}
This way behavior won't change from what there is now, when vuart_putchar()
isn't defined.
Jan
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
2024-12-11 7:38 ` Jan Beulich
@ 2025-01-04 3:12 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:12 UTC (permalink / raw)
To: Jan Beulich
Cc: Jason Andryuk, dmukhin, Andrew Cooper, Julien Grall,
Stefano Stabellini, xen-devel
On Tuesday, December 10th, 2024 at 11:38 PM, Jan Beulich <jbeulich@suse.com> wrote:
>
>
> On 10.12.2024 23:46, Jason Andryuk wrote:
>
> > On 2024-12-05 23:42, Denis Mukhin via B4 Relay wrote:
> >
> > > From: Denis Mukhin dmukhin@ford.com
> > >
> > > Enable console focus for domains w/ virtual NS8250.
> > >
> > > Code change allows to capture the output from the guest OS now and send it to
> > > the physical console device.
> > >
> > > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > > ---
> > > xen/drivers/char/console.c | 5 +++++
> > > 1 file changed, 5 insertions(+)
> > >
> > > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > > index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
> > > --- a/xen/drivers/char/console.c
> > > +++ b/xen/drivers/char/console.c
> > > @@ -41,6 +41,9 @@
> > > #ifdef CONFIG_SBSA_VUART_CONSOLE
> > > #include <asm/vpl011.h>
> > > #endif
> > > +#if defined(CONFIG_HAS_VUART_NS8250)
> > > +#include <asm/hvm/vuart_ns8250.h>
> > > +#endif
> > >
> > > /* console: comma-separated list of console outputs. */
> > > static char __initdata opt_console[30] = OPT_CONSOLE_STR;
> > > @@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
> > > {
> > > #if defined(CONFIG_SBSA_VUART_CONSOLE)
> > > rc = vpl011_rx_char_xen(d, c);
> > > +#elif defined(CONFIG_HAS_VUART_NS8250)
> > > + rc = vuart_putchar(&d->arch.hvm.vuart, c);
> > > #endif
> >
> > I think it would be nicer to just use a single name and avoid ifdef-ery.
> > vuart_putchar() is generic and matches domain_has_vuart(), so that
> > seems good.
> >
> > You can then have a default stub that returns -ENODEV for when an
> > implementation is not built. (This goes along with Jan's suggestion of
> > a common, default domain_has_vuart().) Something like:
> >
> > #ifndef vuart_putchar
> > static inline int vuart_putchar(struct domain *d, char c) {
> > return -ENODEV;
> > }
> > #define vuart_putchar vuart_putchar
> > #endif
> >
> > and ARM can do:
> > #define vuart_putchar vpl011_rx_char_xen
> >
> > x86 would need to change its arguments, but that should be straight forward.
>
>
> Actually, I don't even see a need for the stub:
>
> {
> #ifdef vuart_putchar
> rc = vuart_putchar(d, c);
> #endif
> }
>
> This way behavior won't change from what there is now, when vuart_putchar()
> isn't defined.
I solved it by adding some arch-independent code for "virtual UARTs" in v3, which,
IMO, looks a cleaner solution.
>
> Jan
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 34/35] xen/console: enable console owners w/ emulated NS8250
2024-12-10 22:46 ` Jason Andryuk
2024-12-11 7:35 ` Jan Beulich
2024-12-11 7:38 ` Jan Beulich
@ 2025-01-04 3:08 ` Denis Mukhin
2 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 3:08 UTC (permalink / raw)
To: Jason Andryuk
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini
On Tuesday, December 10th, 2024 at 2:46 PM, Jason Andryuk <jason.andryuk@amd.com> wrote:
>
>
> On 2024-12-05 23:42, Denis Mukhin via B4 Relay wrote:
>
> > From: Denis Mukhin dmukhin@ford.com
> >
> > Enable console focus for domains w/ virtual NS8250.
> >
> > Code change allows to capture the output from the guest OS now and send it to
> > the physical console device.
> >
> > Signed-off-by: Denis Mukhin dmukhin@ford.com
> > ---
> > xen/drivers/char/console.c | 5 +++++
> > 1 file changed, 5 insertions(+)
> >
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index a26daee9c4c4b1134d0ae3d105ffdb656340b6df..798dfdf3412a2feef35e72946d6c59bee59a9251 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -41,6 +41,9 @@
> > #ifdef CONFIG_SBSA_VUART_CONSOLE
> > #include <asm/vpl011.h>
> > #endif
> > +#if defined(CONFIG_HAS_VUART_NS8250)
> > +#include <asm/hvm/vuart_ns8250.h>
> > +#endif
> >
> > /* console: comma-separated list of console outputs. */
> > static char __initdata opt_console[30] = OPT_CONSOLE_STR;
> > @@ -627,6 +630,8 @@ static void handle_keypress_in_domain(struct domain *d, char c)
> > {
> > #if defined(CONFIG_SBSA_VUART_CONSOLE)
> > rc = vpl011_rx_char_xen(d, c);
> > +#elif defined(CONFIG_HAS_VUART_NS8250)
> > + rc = vuart_putchar(&d->arch.hvm.vuart, c);
> > #endif
>
>
> I think it would be nicer to just use a single name and avoid ifdef-ery.
> vuart_putchar() is generic and matches domain_has_vuart(), so that
> seems good.
>
> You can then have a default stub that returns -ENODEV for when an
> implementation is not built. (This goes along with Jan's suggestion of
> a common, default domain_has_vuart().) Something like:
>
> #ifndef vuart_putchar
> static inline int vuart_putchar(struct domain *d, char c) {
> return -ENODEV;
> }
> #define vuart_putchar vuart_putchar
> #endif
>
> and ARM can do:
> #define vuart_putchar vpl011_rx_char_xen
>
> x86 would need to change its arguments, but that should be straight forward.
>
> What do you think?
I think this is a good suggestion, I had same plans for this code, TBH.
I only planned to do that later, but now addressed in v3.
I solved it by adding arch-independent virtdev-uart.c shim, each vUART
implementation should register itself in this shim.
Fixed.
>
> Regards,
> Jason
^ permalink raw reply [flat|nested] 218+ messages in thread
* [PATCH v2 35/35] docs/misc: update console documentation
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
-1 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
Minor update related to virtual UART support.
Also:
s/pv/PV/g
s/hvm/HVM/g
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
docs/misc/console.txt | 50 ++++++++++++++++++++++++++------------------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/docs/misc/console.txt b/docs/misc/console.txt
index 4e180f88ba1312d8fcc47d27622ec347d387ce12..7840729b0c95d9c4ea5295f17ce77c04177f48a5 100644
--- a/docs/misc/console.txt
+++ b/docs/misc/console.txt
@@ -4,11 +4,11 @@ Xen PV Console notes
stefano.stabellini@eu.citrix.com
-Xen traditionally provided a single pv console to pv guests, storing the
+Xen traditionally provided a single PV console to PV guests, storing the
relevant information in xenstore under /local/domain/$DOMID/console.
-Now many years after the introduction of the pv console we have
-multiple pv consoles support for pv and hvm guests; multiple pv
+Now many years after the introduction of the PV console we have
+multiple PV consoles support for PV and HVM guests; multiple PV
console backends (qemu and xenconsoled, see limitations below) and
emulated serial cards too.
@@ -103,48 +103,50 @@ The supported values are only xenconsoled or ioemu; xenconsoled has
several limitations: it can only be used for the first PV or virtual UART
console and it can only connect to a pty.
-Emulated serials are provided by qemu-dm only to hvm guests; the number
-of emulated serials depends on how many "-serial" command line options
-are given to qemu. The output of a serial is specified as argument to
-the -serial command line option to qemu. Qemu writes the tty name to
-xenstore in the following path:
+Emulated serials are provided to HVM guests by qemu-dm or in-hypervisor UART
+emulator (Xen needs to be re-compiled).
+
+In qemu-dm case, the number of emulated serials depends on how many "-serial"
+command line options are given to qemu. The output of a serial is specified as
+argument to the -serial command line option to qemu. Qemu writes the tty name
+to xenstore in the following path:
/local/domain/$DOMID/serial/$SERIAL_NUM/tty
xenconsole is the tool to connect to a PV or virtual UART console or an
emulated serial that has a pty as output. Xenconsole takes a domid as
-parameter plus an optional console type (pv for PV consoles, vuart for
-virtual UART or serial for emulated serials) and console number.
+parameter plus an optional console type ('pv' for PV consoles, 'vuart' for
+virtual UART or 'serial' for emulated serials) and console number.
Depending on the type and console number, xenconsole will look for the tty
node in different xenstore paths, as described above. If the user doesn't
-specify the console type xenconsole will try to guess: if the guest is a pv
-guest it defaults to PV console, if the guest is an hvm guest it defaults to
+specify the console type xenconsole will try to guess: if the guest is a PV
+guest it defaults to PV console, if the guest is an HVM guest it defaults to
emulated serial.
-By default xl creates a pv console for hvm guests, plus an emulated
+By default xl creates a PV console for HVM guests, plus an emulated
serial if the user specified 'serial = "pty"' in the VM config file.
-Considering that xenconsole defaults to emulated serials for hvm guests,
+Considering that xenconsole defaults to emulated serials for HVM guests,
executing xl create -c "domain" causes xenconsole to attach to the
emulated serial tty. This is most probably what the user wanted because
-currently no bootloaders support xen pv consoles so the only way to
+currently no bootloaders support xen PV consoles so the only way to
interact with a bootloader like grub over a console is to use the
emulated serial.
-However the pv console is still easy to use with Linux PV on HVM guests:
+However the PV console is still easy to use with Linux PV on HVM guests:
the user just need to pass "console=hvc0" to the kernel command line and
then execute "xl console -t pv <domain>" to connect to it.
When using stubdoms the serial cards are still emulated by qemu (this
time running in the stubdom), the number of serial cards and where the
output goes is still specified using qemu command line options.
-The difference is that for each emulated serial card there must be a pv
+The difference is that for each emulated serial card there must be a PV
console connection between the stubdom and dom0 to export the serial
-output from the stubdom to dom0. The pv console backend for stubdom's pv
-consoles is always ioemu because multiple pv consoles support is a
-requirement in this case, considering that minios has its own pv console
-too. In order to simplify the setup when using stubdoms the hvm guest
-can only have one pv console with xenstored as backend (the stubdom
-could provide pv console backends to the hvm guest but then it would
-need another pv console connection for each console backend to export
+output from the stubdom to dom0. The PV console backend for stubdom's PV
+consoles is always ioemu because multiple PV consoles support is a
+requirement in this case, considering that minios has its own PV console
+too. In order to simplify the setup when using stubdoms the HVM guest
+can only have one PV console with xenstored as backend (the stubdom
+could provide PV console backends to the HVM guest but then it would
+need another PV console connection for each console backend to export
the pty to dom0).
The xenconsole program supports a very simple protocol to notify parent about
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread* [PATCH v2 35/35] docs/misc: update console documentation
@ 2024-12-06 4:42 ` Denis Mukhin via B4 Relay
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin via B4 Relay @ 2024-12-06 4:42 UTC (permalink / raw)
To: xen-devel
Cc: Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Denis Mukhin
From: Denis Mukhin <dmukhin@ford.com>
Minor update related to virtual UART support.
Also:
s/pv/PV/g
s/hvm/HVM/g
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
docs/misc/console.txt | 50 ++++++++++++++++++++++++++------------------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/docs/misc/console.txt b/docs/misc/console.txt
index 4e180f88ba1312d8fcc47d27622ec347d387ce12..7840729b0c95d9c4ea5295f17ce77c04177f48a5 100644
--- a/docs/misc/console.txt
+++ b/docs/misc/console.txt
@@ -4,11 +4,11 @@ Xen PV Console notes
stefano.stabellini@eu.citrix.com
-Xen traditionally provided a single pv console to pv guests, storing the
+Xen traditionally provided a single PV console to PV guests, storing the
relevant information in xenstore under /local/domain/$DOMID/console.
-Now many years after the introduction of the pv console we have
-multiple pv consoles support for pv and hvm guests; multiple pv
+Now many years after the introduction of the PV console we have
+multiple PV consoles support for PV and HVM guests; multiple PV
console backends (qemu and xenconsoled, see limitations below) and
emulated serial cards too.
@@ -103,48 +103,50 @@ The supported values are only xenconsoled or ioemu; xenconsoled has
several limitations: it can only be used for the first PV or virtual UART
console and it can only connect to a pty.
-Emulated serials are provided by qemu-dm only to hvm guests; the number
-of emulated serials depends on how many "-serial" command line options
-are given to qemu. The output of a serial is specified as argument to
-the -serial command line option to qemu. Qemu writes the tty name to
-xenstore in the following path:
+Emulated serials are provided to HVM guests by qemu-dm or in-hypervisor UART
+emulator (Xen needs to be re-compiled).
+
+In qemu-dm case, the number of emulated serials depends on how many "-serial"
+command line options are given to qemu. The output of a serial is specified as
+argument to the -serial command line option to qemu. Qemu writes the tty name
+to xenstore in the following path:
/local/domain/$DOMID/serial/$SERIAL_NUM/tty
xenconsole is the tool to connect to a PV or virtual UART console or an
emulated serial that has a pty as output. Xenconsole takes a domid as
-parameter plus an optional console type (pv for PV consoles, vuart for
-virtual UART or serial for emulated serials) and console number.
+parameter plus an optional console type ('pv' for PV consoles, 'vuart' for
+virtual UART or 'serial' for emulated serials) and console number.
Depending on the type and console number, xenconsole will look for the tty
node in different xenstore paths, as described above. If the user doesn't
-specify the console type xenconsole will try to guess: if the guest is a pv
-guest it defaults to PV console, if the guest is an hvm guest it defaults to
+specify the console type xenconsole will try to guess: if the guest is a PV
+guest it defaults to PV console, if the guest is an HVM guest it defaults to
emulated serial.
-By default xl creates a pv console for hvm guests, plus an emulated
+By default xl creates a PV console for HVM guests, plus an emulated
serial if the user specified 'serial = "pty"' in the VM config file.
-Considering that xenconsole defaults to emulated serials for hvm guests,
+Considering that xenconsole defaults to emulated serials for HVM guests,
executing xl create -c "domain" causes xenconsole to attach to the
emulated serial tty. This is most probably what the user wanted because
-currently no bootloaders support xen pv consoles so the only way to
+currently no bootloaders support xen PV consoles so the only way to
interact with a bootloader like grub over a console is to use the
emulated serial.
-However the pv console is still easy to use with Linux PV on HVM guests:
+However the PV console is still easy to use with Linux PV on HVM guests:
the user just need to pass "console=hvc0" to the kernel command line and
then execute "xl console -t pv <domain>" to connect to it.
When using stubdoms the serial cards are still emulated by qemu (this
time running in the stubdom), the number of serial cards and where the
output goes is still specified using qemu command line options.
-The difference is that for each emulated serial card there must be a pv
+The difference is that for each emulated serial card there must be a PV
console connection between the stubdom and dom0 to export the serial
-output from the stubdom to dom0. The pv console backend for stubdom's pv
-consoles is always ioemu because multiple pv consoles support is a
-requirement in this case, considering that minios has its own pv console
-too. In order to simplify the setup when using stubdoms the hvm guest
-can only have one pv console with xenstored as backend (the stubdom
-could provide pv console backends to the hvm guest but then it would
-need another pv console connection for each console backend to export
+output from the stubdom to dom0. The PV console backend for stubdom's PV
+consoles is always ioemu because multiple PV consoles support is a
+requirement in this case, considering that minios has its own PV console
+too. In order to simplify the setup when using stubdoms the HVM guest
+can only have one PV console with xenstored as backend (the stubdom
+could provide PV console backends to the HVM guest but then it would
+need another PV console connection for each console backend to export
the pty to dom0).
The xenconsole program supports a very simple protocol to notify parent about
--
2.34.1
^ permalink raw reply related [flat|nested] 218+ messages in thread
* Re: [PATCH v2 00/35] Introduce NS8250 UART emulator
2024-12-06 4:41 ` Denis Mukhin via B4 Relay
` (35 preceding siblings ...)
(?)
@ 2024-12-14 18:05 ` Marek Marczykowski-Górecki
2024-12-16 9:04 ` Roger Pau Monné
2025-01-04 4:27 ` Denis Mukhin
-1 siblings, 2 replies; 218+ messages in thread
From: Marek Marczykowski-Górecki @ 2024-12-14 18:05 UTC (permalink / raw)
To: dmukhin
Cc: xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini, Oleksii Kurochko
[-- Attachment #1: Type: text/plain, Size: 916 bytes --]
On Thu, Dec 05, 2024 at 08:41:30PM -0800, Denis Mukhin via B4 Relay wrote:
> The patch series introduces initial in-hypervisor emulator for
> NS8250/NS16x50-compatible UARTs under CONFIG_HAS_VUART_NS8250.
>
> In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> early guest OS bringup debugging, because it eliminates dependency on the
> external emulator being operational by the time domains are created. Also,
> there's no early console facility similar to vpl011 to support x86 guest OS
> bring up.
>
> The NS8250 emulator is disabled by default.
On a high level, why the mechanism used by earlyprintk=xen (IIUC i/o
port 0xe9) isn't enough?
Hyperlaunch can't start full (Xen-unaware) HVM domains anyway, so
a requirement to use a Xen-specific interface for the console shouldn't be
an issue, no?
--
Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 218+ messages in thread* Re: [PATCH v2 00/35] Introduce NS8250 UART emulator
2024-12-14 18:05 ` [PATCH v2 00/35] Introduce NS8250 UART emulator Marek Marczykowski-Górecki
@ 2024-12-16 9:04 ` Roger Pau Monné
2025-01-04 4:28 ` Denis Mukhin
2025-01-04 4:27 ` Denis Mukhin
1 sibling, 1 reply; 218+ messages in thread
From: Roger Pau Monné @ 2024-12-16 9:04 UTC (permalink / raw)
To: Marek Marczykowski-Górecki
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini, Oleksii Kurochko
On Sat, Dec 14, 2024 at 07:05:15PM +0100, Marek Marczykowski-Górecki wrote:
> On Thu, Dec 05, 2024 at 08:41:30PM -0800, Denis Mukhin via B4 Relay wrote:
> > The patch series introduces initial in-hypervisor emulator for
> > NS8250/NS16x50-compatible UARTs under CONFIG_HAS_VUART_NS8250.
> >
> > In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> > early guest OS bringup debugging, because it eliminates dependency on the
> > external emulator being operational by the time domains are created. Also,
> > there's no early console facility similar to vpl011 to support x86 guest OS
> > bring up.
> >
> > The NS8250 emulator is disabled by default.
>
> On a high level, why the mechanism used by earlyprintk=xen (IIUC i/o
> port 0xe9) isn't enough?
> Hyperlaunch can't start full (Xen-unaware) HVM domains anyway, so
> a requirement to use a Xen-specific interface for the console shouldn't be
> an issue, no?
I assume the point is to provide a minimal set of non-Xen specific
interfaces so that a guest *could* work if made to use only those
interfaces. The 0xE9 hack is quite common for emergency printing, but
it doesn't allow for input, which the ns8250 does.
Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 00/35] Introduce NS8250 UART emulator
2024-12-16 9:04 ` Roger Pau Monné
@ 2025-01-04 4:28 ` Denis Mukhin
0 siblings, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:28 UTC (permalink / raw)
To: Roger Pau Monné
Cc: Marek Marczykowski-Górecki, dmukhin, xen-devel,
Andrew Cooper, Jan Beulich, Julien Grall, Stefano Stabellini,
Oleksii Kurochko
On Monday, December 16th, 2024 at 1:04 AM, Roger Pau Monné <roger.pau@citrix.com> wrote:
>
>
> On Sat, Dec 14, 2024 at 07:05:15PM +0100, Marek Marczykowski-Górecki wrote:
>
> > On Thu, Dec 05, 2024 at 08:41:30PM -0800, Denis Mukhin via B4 Relay wrote:
> >
> > > The patch series introduces initial in-hypervisor emulator for
> > > NS8250/NS16x50-compatible UARTs under CONFIG_HAS_VUART_NS8250.
> > >
> > > In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> > > early guest OS bringup debugging, because it eliminates dependency on the
> > > external emulator being operational by the time domains are created. Also,
> > > there's no early console facility similar to vpl011 to support x86 guest OS
> > > bring up.
> > >
> > > The NS8250 emulator is disabled by default.
> >
> > On a high level, why the mechanism used by earlyprintk=xen (IIUC i/o
> > port 0xe9) isn't enough?
> > Hyperlaunch can't start full (Xen-unaware) HVM domains anyway, so
> > a requirement to use a Xen-specific interface for the console shouldn't be
> > an issue, no?
>
>
> I assume the point is to provide a minimal set of non-Xen specific
> interfaces so that a guest could work if made to use only those
> interfaces. The 0xE9 hack is quite common for emergency printing, but
> it doesn't allow for input, which the ns8250 does.
Yes, my major objective was providing a simpler debugging facility under Xen
w/o modifying guest OS software.
>
> Thanks, Roger.
^ permalink raw reply [flat|nested] 218+ messages in thread
* Re: [PATCH v2 00/35] Introduce NS8250 UART emulator
2024-12-14 18:05 ` [PATCH v2 00/35] Introduce NS8250 UART emulator Marek Marczykowski-Górecki
2024-12-16 9:04 ` Roger Pau Monné
@ 2025-01-04 4:27 ` Denis Mukhin
1 sibling, 0 replies; 218+ messages in thread
From: Denis Mukhin @ 2025-01-04 4:27 UTC (permalink / raw)
To: Marek Marczykowski-Górecki
Cc: dmukhin, xen-devel, Andrew Cooper, Jan Beulich, Julien Grall,
Stefano Stabellini, Oleksii Kurochko
On Saturday, December 14th, 2024 at 10:05 AM, Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> wrote:
>
>
> On Thu, Dec 05, 2024 at 08:41:30PM -0800, Denis Mukhin via B4 Relay wrote:
>
> > The patch series introduces initial in-hypervisor emulator for
> > NS8250/NS16x50-compatible UARTs under CONFIG_HAS_VUART_NS8250.
> >
> > In parallel domain creation scenario (hyperlaunch), NS8520 emulator helps
> > early guest OS bringup debugging, because it eliminates dependency on the
> > external emulator being operational by the time domains are created. Also,
> > there's no early console facility similar to vpl011 to support x86 guest OS
> > bring up.
> >
> > The NS8250 emulator is disabled by default.
>
>
> On a high level, why the mechanism used by earlyprintk=xen (IIUC i/o
> port 0xe9) isn't enough?
I/O port 0xe9 needs some knowledge about Xen and potentially re-building/patching
guest OSes. The latter is not always possible right away. So using legacy
COM ports makes debugging a bit easier for engineers trying to bring up
Xen configuration.
> Hyperlaunch can't start full (Xen-unaware) HVM domains anyway, so
> a requirement to use a Xen-specific interface for the console shouldn't be
> an issue, no?
With hyperlaunch virtual firmware (e.g. OVMF) in HVM case will execute
in parallel, which means all serial output from virtual firmware can be
easily captured, i.e. debugging on a new hardware should be a bit easier.
My understanding that not all firmware support debug I/O port 0xe9.
Rebuilding a firmware may be a quest in itself, which can be skipped if x86
port of Xen has legacy COM UART emulation in hypervisor.
Also, my understanding (please correct me if I'm wrong) it should be
theoretically possible to craft a hyperlaunch configuration where each
non-hardware domain is headless and has its own physical block device
controller passed-through and has no dependency on hardware domain.
>
> --
> Best Regards,
> Marek Marczykowski-Górecki
> Invisible Things Lab
^ permalink raw reply [flat|nested] 218+ messages in thread