From: Stefano Stabellini <sstabellini@kernel.org>
To: julien.grall@arm.com
Cc: Stefano Stabellini <stefanos@xilinx.com>,
sstabellini@kernel.org, andrii_anisov@epam.com,
xen-devel@lists.xen.org
Subject: [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU
Date: Fri, 6 Jul 2018 16:12:13 -0700 [thread overview]
Message-ID: <1530918736-13965-18-git-send-email-sstabellini@kernel.org> (raw)
In-Reply-To: <alpine.DEB.2.10.1807061523160.13502@sstabellini-ThinkPad-X260>
Make vpl011 being able to be used without a userspace component in Dom0.
In that case, output is printed to the Xen serial and input is received
from the Xen serial one character at a time.
Call domain_vpl011_init during construct_domU if vpl011 is enabled.
Introduce a new ring struct with only the ring array to avoid a waste of
memory. Introduce separate read_date and write_data functions for
initial domains: vpl011_write_data_noring is very simple and just writes
to the console, while vpl011_read_data_inring is a duplicate of
vpl011_read_data. Although textually almost identical, we are forced to
duplicate the functions because the struct layout is different.
Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v2:
- only init if vpl011
- rename vpl011_read_char to vpl011_rx_char
- remove spurious change
- fix coding style
- use different ring struct
- move the write_data changes to their own function
(vpl011_write_data_noring)
- duplicate vpl011_read_data
---
xen/arch/arm/domain_build.c | 10 ++-
xen/arch/arm/vpl011.c | 185 ++++++++++++++++++++++++++++++++++++++-----
xen/include/asm-arm/vpl011.h | 10 +++
3 files changed, 182 insertions(+), 23 deletions(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 718be48..d7e9040 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2531,7 +2531,15 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
if ( rc < 0 )
return rc;
- return __construct_domain(d, &kinfo);
+ rc = __construct_domain(d, &kinfo);
+ if ( rc < 0 )
+ return rc;
+
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+ if ( vpl011 )
+ rc = domain_vpl011_init(d, NULL);
+#endif
+ return rc;
}
int __init construct_dom0(struct domain *d)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index e75957f..d4aab64 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -83,6 +83,111 @@ static void vpl011_update_interrupt_status(struct domain *d)
#endif
}
+void vpl011_rx_char(struct domain *d, char c)
+{
+ unsigned long flags;
+ struct vpl011 *vpl011 = &d->arch.vpl011;
+ struct xencons_in *intf = vpl011->inring;
+ XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
+
+ VPL011_LOCK(d, flags);
+
+ in_cons = intf->in_cons;
+ in_prod = intf->in_prod;
+ if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == sizeof(intf->in) )
+ {
+ VPL011_UNLOCK(d, flags);
+ return;
+ }
+
+ intf->in[xencons_mask(in_prod, sizeof(intf->in))] = c;
+ intf->in_prod = in_prod + 1;
+
+ in_fifo_level = xencons_queued(in_prod,
+ in_cons,
+ sizeof(intf->in));
+
+ vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, 1024);
+ VPL011_UNLOCK(d, flags);
+}
+
+static void vpl011_write_data_noring(struct domain *d, uint8_t data)
+{
+ unsigned long flags;
+ struct vpl011 *vpl011 = &d->arch.vpl011;
+
+ VPL011_LOCK(d, flags);
+
+ printk("%c", data);
+ if (data == '\n')
+ printk("DOM%u: ", d->domain_id);
+
+ vpl011->uartris |= TXI;
+ vpl011->uartfr &= ~TXFE;
+ vpl011_update_interrupt_status(d);
+
+ VPL011_UNLOCK(d, flags);
+}
+
+static uint8_t vpl011_read_data_inring(struct domain *d)
+{
+ unsigned long flags;
+ uint8_t data = 0;
+ struct vpl011 *vpl011 = &d->arch.vpl011;
+ struct xencons_in *intf = vpl011->inring;
+ XENCONS_RING_IDX in_cons, in_prod;
+
+ VPL011_LOCK(d, flags);
+
+ in_cons = intf->in_cons;
+ in_prod = intf->in_prod;
+
+ smp_rmb();
+
+ /*
+ * It is expected that there will be data in the ring buffer when this
+ * function is called since the guest is expected to read the data register
+ * only if the TXFE flag is not set.
+ * If the guest still does read when TXFE bit is set then 0 will be returned.
+ */
+ if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) > 0 )
+ {
+ unsigned int fifo_level;
+
+ data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
+ in_cons += 1;
+ smp_mb();
+ intf->in_cons = in_cons;
+
+ fifo_level = xencons_queued(in_prod, in_cons, sizeof(intf->in));
+
+ /* If the FIFO is now empty, we clear the receive timeout interrupt. */
+ if ( fifo_level == 0 )
+ {
+ vpl011->uartfr |= RXFE;
+ vpl011->uartris &= ~RTI;
+ }
+
+ /* If the FIFO is more than half empty, we clear the RX interrupt. */
+ if ( fifo_level < sizeof(intf->in) - SBSA_UART_FIFO_LEVEL )
+ vpl011->uartris &= ~RXI;
+
+ vpl011_update_interrupt_status(d);
+ }
+ else
+ gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
+
+ /*
+ * We have consumed a character or the FIFO was empty, so clear the
+ * "FIFO full" bit.
+ */
+ vpl011->uartfr &= ~RXFF;
+
+ VPL011_UNLOCK(d, flags);
+
+ return data;
+}
+
static uint8_t vpl011_read_data(struct domain *d)
{
unsigned long flags;
@@ -246,7 +351,10 @@ static int vpl011_mmio_read(struct vcpu *v,
case DR:
if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
- *r = vreg_reg32_extract(vpl011_read_data(d), info);
+ if ( vpl011->ring_enable )
+ *r = vreg_reg32_extract(vpl011_read_data(d), info);
+ else
+ *r = vreg_reg32_extract(vpl011_read_data_inring(d), info);
return 1;
case RSR:
@@ -331,7 +439,10 @@ static int vpl011_mmio_write(struct vcpu *v,
vreg_reg32_update(&data, r, info);
data &= 0xFF;
- vpl011_write_data(v->domain, data);
+ if ( vpl011->ring_enable )
+ vpl011_write_data(v->domain, data);
+ else
+ vpl011_write_data_noring(v->domain, data);
return 1;
}
@@ -476,27 +587,47 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
if ( vpl011->ring.ring_buf )
return -EINVAL;
- /* Map the guest PFN to Xen address space. */
- rc = prepare_ring_for_helper(d,
- gfn_x(info->gfn),
- &vpl011->ring.ring_page,
- &vpl011->ring.ring_buf);
- if ( rc < 0 )
- goto out;
+ /*
+ * info is NULL for domUs started by Xen at boot time, with no
+ * corresponding userspace component in dom0
+ */
+ if ( info != NULL )
+ {
+ vpl011->ring_enable = true;
+
+ /* Map the guest PFN to Xen address space. */
+ rc = prepare_ring_for_helper(d,
+ gfn_x(info->gfn),
+ &vpl011->ring.ring_page,
+ &vpl011->ring.ring_buf);
+ if ( rc < 0 )
+ goto out;
+
+ rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
+ vpl011_notification);
+ if ( rc < 0 )
+ goto out1;
+
+ vpl011->evtchn = info->evtchn = rc;
+ }
+ else
+ {
+ vpl011->ring_enable = false;
+
+ vpl011->inring = xzalloc(struct xencons_in);
+ if ( vpl011->inring == NULL )
+ {
+ rc = -EINVAL;
+ goto out1;
+ }
+ }
rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
if ( !rc )
{
rc = -EINVAL;
- goto out1;
- }
-
- rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
- vpl011_notification);
- if ( rc < 0 )
goto out2;
-
- vpl011->evtchn = info->evtchn = rc;
+ }
spin_lock_init(&vpl011->lock);
@@ -509,7 +640,10 @@ out2:
vgic_free_virq(d, GUEST_VPL011_SPI);
out1:
- destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+ if ( vpl011->ring_enable )
+ destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+ else
+ xfree(vpl011->inring);
out:
return rc;
@@ -519,11 +653,18 @@ void domain_vpl011_deinit(struct domain *d)
{
struct vpl011 *vpl011 = &d->arch.vpl011;
- if ( !vpl011->ring.ring_buf )
- return;
+ if ( vpl011->ring_enable )
+ {
+ if ( !vpl011->ring.ring_buf )
+ return;
- free_xen_event_channel(d, vpl011->evtchn);
- destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+ free_xen_event_channel(d, vpl011->evtchn);
+ destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+ }
+ else
+ {
+ xfree(vpl011->inring);
+ }
}
/*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index c3d375b..be43abf 100644
--- a/xen/include/asm-arm/vpl011.h
+++ b/xen/include/asm-arm/vpl011.h
@@ -21,6 +21,7 @@
#include <public/domctl.h>
#include <public/io/ring.h>
+#include <public/io/console.h>
#include <asm/vreg.h>
#include <xen/mm.h>
@@ -30,12 +31,19 @@
#define SBSA_UART_FIFO_SIZE 32
+struct xencons_in {
+ char in[1024];
+ XENCONS_RING_IDX in_cons, in_prod;
+};
+
struct vpl011 {
+ bool ring_enable;
union {
struct {
void *ring_buf;
struct page_info *ring_page;
} ring;
+ struct xencons_in *inring;
};
uint32_t uartfr; /* Flag register */
uint32_t uartcr; /* Control register */
@@ -57,6 +65,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(struct domain *d, char c);
#else
static inline int domain_vpl011_init(struct domain *d,
struct vpl011_init_info *info)
@@ -65,6 +74,7 @@ static inline int domain_vpl011_init(struct domain *d,
}
static inline void domain_vpl011_deinit(struct domain *d) { }
+static inline void vpl011_rx_char(struct domain *d, char c) { }
#endif
#endif /* _VPL011_H_ */
--
1.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
next prev parent reply other threads:[~2018-07-06 23:12 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
2018-07-06 23:11 ` [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
2018-07-09 12:55 ` Julien Grall
2018-07-11 20:09 ` Stefano Stabellini
2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
2018-07-09 13:43 ` Julien Grall
2018-07-09 23:02 ` Stefano Stabellini
2018-07-10 17:57 ` Julien Grall
2018-07-11 21:42 ` Stefano Stabellini
2018-07-09 13:58 ` Julien Grall
2018-07-09 23:10 ` Stefano Stabellini
2018-07-23 18:01 ` Andrii Anisov
2018-07-23 18:32 ` Stefano Stabellini
2018-07-24 12:09 ` Andrii Anisov
2018-07-06 23:11 ` [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
2018-07-09 13:48 ` Julien Grall
2018-07-17 20:05 ` Stefano Stabellini
2018-07-17 20:26 ` Julien Grall
2018-07-18 17:10 ` Stefano Stabellini
2018-07-19 9:19 ` Julien Grall
2018-08-17 19:41 ` Daniel De Graaf
2018-07-06 23:11 ` [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
2018-07-09 13:59 ` Julien Grall
2018-07-06 23:12 ` [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
2018-07-09 14:07 ` Julien Grall
2018-07-13 22:41 ` Stefano Stabellini
2018-07-16 14:14 ` Julien Grall
2018-07-16 22:02 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
2018-07-09 14:11 ` Julien Grall
2018-07-09 21:51 ` Stefano Stabellini
2018-07-10 17:28 ` Julien Grall
2018-07-11 20:33 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
2018-07-09 14:12 ` Julien Grall
2018-07-06 23:12 ` [PATCH v2 08/21] xen/arm: increase MAX_MODULES Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules Stefano Stabellini
2018-07-09 14:53 ` Julien Grall
2018-07-10 0:00 ` Stefano Stabellini
2018-07-10 21:11 ` Julien Grall
2018-07-13 0:04 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 10/21] xen/arm: don't add duplicate boot modules Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 11/21] xen/arm: probe domU kernels and initrds Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 12/21] xen/arm: refactor construct_dom0 Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 13/21] xen/arm: introduce construct_domU Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 14/21] xen/arm: generate a simple device tree for domUs Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
2018-07-12 18:14 ` Julien Grall
2018-07-13 21:24 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 16/21] xen/arm: introduce a union in vpl011 Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail Stefano Stabellini
2018-07-24 9:58 ` Julien Grall
2018-07-27 22:37 ` Stefano Stabellini
2018-07-06 23:12 ` Stefano Stabellini [this message]
2018-07-24 11:00 ` [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU Julien Grall
2018-07-27 0:10 ` Stefano Stabellini
2018-07-27 11:00 ` Julien Grall
2018-07-27 21:42 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 19/21] xen/arm: introduce create_domUs Stefano Stabellini
2018-07-16 16:10 ` Jan Beulich
2018-07-16 21:44 ` Stefano Stabellini
2018-07-24 13:53 ` Julien Grall
2018-07-28 2:42 ` Stefano Stabellini
2018-07-30 10:26 ` Julien Grall
2018-07-30 18:15 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
2018-07-16 16:19 ` Jan Beulich
2018-07-16 21:55 ` Stefano Stabellini
2018-07-17 6:37 ` Jan Beulich
2018-07-17 16:43 ` Stefano Stabellini
2018-07-18 6:41 ` Jan Beulich
2018-07-18 16:51 ` Stefano Stabellini
2018-07-17 8:40 ` Jan Beulich
2018-07-17 16:33 ` Stefano Stabellini
2018-07-17 20:29 ` Julien Grall
2018-07-18 7:12 ` Jan Beulich
2018-07-18 16:59 ` Julien Grall
2018-07-19 6:10 ` Jan Beulich
2018-07-19 17:18 ` Stefano Stabellini
2018-07-18 17:01 ` Stefano Stabellini
2018-07-18 20:37 ` George Dunlap
2018-07-17 20:34 ` Julien Grall
2018-07-18 17:31 ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 21/21] xen/arm: split domain_build.c Stefano Stabellini
2018-07-12 18:18 ` [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Julien Grall
2018-07-13 20:54 ` Stefano Stabellini
2018-07-18 16:48 ` Julien Grall
2018-07-18 17:48 ` Stefano Stabellini
2018-07-23 17:13 ` Julien Grall
2018-07-23 17:52 ` Stefano Stabellini
2018-07-23 17:14 ` Andrii Anisov
2018-07-23 17:55 ` Stefano Stabellini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1530918736-13965-18-git-send-email-sstabellini@kernel.org \
--to=sstabellini@kernel.org \
--cc=andrii_anisov@epam.com \
--cc=julien.grall@arm.com \
--cc=stefanos@xilinx.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).