|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 13/15] xen/arm: Allow vpl011 to be used by DomU
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.
Signed-off-by: Stefano Stabellini <stefanos@xxxxxxxxxx>
---
xen/arch/arm/domain_build.c | 9 +++-
xen/arch/arm/vpl011.c | 98 +++++++++++++++++++++++++++++++++-----------
xen/include/asm-arm/vpl011.h | 2 +
3 files changed, 84 insertions(+), 25 deletions(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index ff65057..97f14ca 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2482,7 +2482,14 @@ 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
+ 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 a281eab..5f1dc7a 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -34,6 +34,8 @@
#include <asm/vgic-emul.h>
#include <asm/vpl011.h>
+static void vpl011_data_avail(struct domain *d);
+
/*
* Since pl011 registers are 32-bit registers, all registers
* are handled similarly allowing 8-bit, 16-bit and 32-bit
@@ -77,6 +79,29 @@ static void vpl011_update_interrupt_status(struct domain *d)
#endif
}
+void vpl011_read_char(struct domain *d, char c)
+{
+ unsigned long flags;
+ XENCONS_RING_IDX in_cons, in_prod;
+ struct xencons_interface *intf = d->arch.vpl011.ring_buf;
+
+ 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;
+
+ VPL011_UNLOCK(d, flags);
+ vpl011_data_avail(d);
+}
+
static uint8_t vpl011_read_data(struct domain *d)
{
unsigned long flags;
@@ -166,9 +191,18 @@ static void vpl011_write_data(struct domain *d, uint8_t
data)
struct vpl011 *vpl011 = &d->arch.vpl011;
struct xencons_interface *intf = vpl011->ring_buf;
XENCONS_RING_IDX out_cons, out_prod;
+ unsigned int fifo_level = 0;
VPL011_LOCK(d, flags);
+ if ( vpl011->ring_page == NULL )
+ {
+ printk("%c", data);
+ if (data == '\n')
+ printk("DOM%u: ", d->domain_id);
+ goto done;
+ }
+
out_cons = intf->out_cons;
out_prod = intf->out_prod;
@@ -184,13 +218,10 @@ static void vpl011_write_data(struct domain *d, uint8_t
data)
if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) !=
sizeof (intf->out) )
{
- unsigned int fifo_level;
-
intf->out[xencons_mask(out_prod, sizeof(intf->out))] = data;
out_prod += 1;
smp_wmb();
intf->out_prod = out_prod;
-
fifo_level = xencons_queued(out_prod, out_cons, sizeof(intf->out));
if ( fifo_level == sizeof(intf->out) )
@@ -205,14 +236,15 @@ static void vpl011_write_data(struct domain *d, uint8_t
data)
*/
vpl011->uartfr |= BUSY;
}
-
- vpl011_update_tx_fifo_status(vpl011, fifo_level);
-
- vpl011_update_interrupt_status(d);
}
else
gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
+done:
+ vpl011_update_tx_fifo_status(vpl011, fifo_level);
+
+ vpl011_update_interrupt_status(d);
+
vpl011->uartfr &= ~TXFE;
VPL011_UNLOCK(d, flags);
@@ -462,13 +494,30 @@ int domain_vpl011_init(struct domain *d, struct
vpl011_init_info *info)
if ( vpl011->ring_buf )
return -EINVAL;
- /* Map the guest PFN to Xen address space. */
- rc = prepare_ring_for_helper(d,
- gfn_x(info->gfn),
- &vpl011->ring_page,
- &vpl011->ring_buf);
- if ( rc < 0 )
- goto out;
+ if ( info != NULL )
+ {
+ /* Map the guest PFN to Xen address space. */
+ rc = prepare_ring_for_helper(d,
+ gfn_x(info->gfn),
+ &vpl011->ring_page,
+ &vpl011->ring_buf);
+ if ( rc < 0 )
+ goto out;
+
+ rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
+ vpl011_notification);
+ if ( rc < 0 )
+ goto out2;
+
+ vpl011->evtchn = info->evtchn = rc;
+ } else {
+ vpl011->ring_buf = xzalloc(struct xencons_interface);
+ if ( vpl011->ring_buf == NULL )
+ {
+ rc = -EINVAL;
+ goto out;
+ }
+ }
rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
if ( !rc )
@@ -477,13 +526,6 @@ int domain_vpl011_init(struct domain *d, struct
vpl011_init_info *info)
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);
register_mmio_handler(d, &vpl011_mmio_handler,
@@ -495,7 +537,10 @@ out2:
vgic_free_virq(d, GUEST_VPL011_SPI);
out1:
- destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+ if ( vpl011->ring_page == NULL && vpl011->ring_buf != NULL )
+ xfree(vpl011->ring_buf);
+ else
+ destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
out:
return rc;
@@ -508,8 +553,13 @@ void domain_vpl011_deinit(struct domain *d)
if ( !vpl011->ring_buf )
return;
- free_xen_event_channel(d, vpl011->evtchn);
- destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+ if ( vpl011->ring_page == NULL && vpl011->ring_buf != NULL )
+ {
+ xfree(vpl011->ring_buf);
+ } else {
+ free_xen_event_channel(d, vpl011->evtchn);
+ destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+ }
}
/*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index db95ff8..8d9b0da 100644
--- a/xen/include/asm-arm/vpl011.h
+++ b/xen/include/asm-arm/vpl011.h
@@ -53,6 +53,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_read_char(struct domain *d, char c);
#else
static inline int domain_vpl011_init(struct domain *d,
struct vpl011_init_info *info)
@@ -61,6 +62,7 @@ static inline int domain_vpl011_init(struct domain *d,
}
static inline void domain_vpl011_deinit(struct domain *d) { }
+static inline void vpl011_read_char(struct domain *d, char c) { }
#endif
#endif /* _VPL011_H_ */
--
1.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |