[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] arm: implement vpl011 (UART) emulator.
# HG changeset patch # User Ian Campbell <ian.campbell@xxxxxxxxxx> # Date 1341309141 -3600 # Node ID f4e7fd47613cf914ea8896c8f11ec3dc6223f6ed # Parent a37ff29c027bf5de013eaf8033629cb69ed5836c arm: implement vpl011 (UART) emulator. This is not interended to provide a full emulation, but rather just enough to satisfy the use made by Linux' boot time decompressor code (which is too early for DT etc) Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> Acked-by: Tim Deegan <tim@xxxxxxx> Committed-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- diff -r a37ff29c027b -r f4e7fd47613c xen/arch/arm/Makefile --- a/xen/arch/arm/Makefile Tue Jul 03 10:52:20 2012 +0100 +++ b/xen/arch/arm/Makefile Tue Jul 03 10:52:21 2012 +0100 @@ -25,6 +25,7 @@ obj-y += shutdown.o obj-y += traps.o obj-y += vgic.o obj-y += vtimer.o +obj-y += vpl011.o #obj-bin-y += ....o diff -r a37ff29c027b -r f4e7fd47613c xen/arch/arm/domain.c --- a/xen/arch/arm/domain.c Tue Jul 03 10:52:20 2012 +0100 +++ b/xen/arch/arm/domain.c Tue Jul 03 10:52:21 2012 +0100 @@ -13,6 +13,7 @@ #include "gic.h" #include "vtimer.h" +#include "vpl011.h" DEFINE_PER_CPU(struct vcpu *, curr_vcpu); @@ -327,6 +328,10 @@ int arch_domain_create(struct domain *d, if ( (rc = domain_vgic_init(d)) != 0 ) goto fail; + /* Domain 0 gets a real UART not an emulated one */ + if ( d->domain_id && (rc = domain_uart0_init(d)) != 0 ) + goto fail; + rc = 0; fail: return rc; diff -r a37ff29c027b -r f4e7fd47613c xen/arch/arm/io.c --- a/xen/arch/arm/io.c Tue Jul 03 10:52:20 2012 +0100 +++ b/xen/arch/arm/io.c Tue Jul 03 10:52:21 2012 +0100 @@ -25,6 +25,7 @@ static const struct mmio_handler *const mmio_handlers[] = { &vgic_distr_mmio_handler, + &uart0_mmio_handler, }; #define MMIO_HANDLER_NR ARRAY_SIZE(mmio_handlers) diff -r a37ff29c027b -r f4e7fd47613c xen/arch/arm/io.h --- a/xen/arch/arm/io.h Tue Jul 03 10:52:20 2012 +0100 +++ b/xen/arch/arm/io.h Tue Jul 03 10:52:21 2012 +0100 @@ -40,6 +40,7 @@ struct mmio_handler { }; extern const struct mmio_handler vgic_distr_mmio_handler; +extern const struct mmio_handler uart0_mmio_handler; extern int handle_mmio(mmio_info_t *info); diff -r a37ff29c027b -r f4e7fd47613c xen/arch/arm/vpl011.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/arm/vpl011.c Tue Jul 03 10:52:21 2012 +0100 @@ -0,0 +1,145 @@ +/* + * xen/arch/arm/vpl011.c + * + * ARM PL011 UART Emulator (DEBUG) + * + * Ian Campbell <ian.campbell@xxxxxxxxxx> + * Copyright (c) 2012 Citrix Systems. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This is not intended to be a full emulation of a PL011 + * device. Rather it is intended to provide a sufficient veneer of one + * that early code (such as Linux's boot time decompressor) which + * hardcodes output directly to such a device are able to make progress. + * + * This device is not intended to be enumerable or exposed to the OS + * (e.g. via Device Tree). + */ + +#include <xen/config.h> +#include <xen/lib.h> +#include <xen/sched.h> +#include <xen/errno.h> +#include <xen/ctype.h> + +#include "io.h" + +#define UART0_START 0x1c090000 +#define UART0_END (UART0_START+65536) + +#define UARTDR 0x000 +#define UARTFR 0x018 + +int domain_uart0_init(struct domain *d) +{ + ASSERT( d->domain_id ); + + spin_lock_init(&d->arch.uart0.lock); + d->arch.uart0.idx = 0; + + d->arch.uart0.buf = xzalloc_array(char, VPL011_BUF_SIZE); + if ( !d->arch.uart0.buf ) + return -ENOMEM; + + return 0; + +} + +static void uart0_print_char(char c) +{ + struct vpl011 *uart = ¤t->domain->arch.uart0; + + /* Accept only printable characters, newline, and horizontal tab. */ + if ( !isprint(c) && (c != '\n') && (c != '\t') ) + return ; + + spin_lock(&uart->lock); + uart->buf[uart->idx++] = c; + if ( (uart->idx == (VPL011_BUF_SIZE - 2)) || (c == '\n') ) + { + if ( c != '\n' ) + uart->buf[uart->idx++] = '\n'; + uart->buf[uart->idx] = '\0'; + printk(XENLOG_G_DEBUG "DOM%u: %s", + current->domain->domain_id, uart->buf); + uart->idx = 0; + } + spin_unlock(&uart->lock); +} + +static int uart0_mmio_check(struct vcpu *v, paddr_t addr) +{ + return addr >= UART0_START && addr < UART0_END; +} + +static int uart0_mmio_read(struct vcpu *v, mmio_info_t *info) +{ + struct hsr_dabt dabt = info->dabt; + struct cpu_user_regs *regs = guest_cpu_user_regs(); + uint32_t *r = ®s->r0 + dabt.reg; + int offset = (int)(info->gpa - UART0_START); + + switch ( offset ) + { + case UARTDR: + *r = 0; + return 1; + case UARTFR: + *r = 0x87; /* All holding registers empty, ready to send etc */ + return 1; + default: + printk("VPL011: unhandled read r%d offset %#08x\n", + dabt.reg, offset); + domain_crash_synchronous(); + } +} + +static int uart0_mmio_write(struct vcpu *v, mmio_info_t *info) +{ + struct hsr_dabt dabt = info->dabt; + struct cpu_user_regs *regs = guest_cpu_user_regs(); + uint32_t *r = ®s->r0 + dabt.reg; + int offset = (int)(info->gpa - UART0_START); + + switch ( offset ) + { + case UARTDR: + /* ignore any status bits */ + uart0_print_char((int)((*r) & 0xFF)); + return 1; + case UARTFR: + /* Silently ignore */ + return 1; + default: + printk("VPL011: unhandled write r%d=%"PRIx32" offset %#08x\n", + dabt.reg, *r, offset); + domain_crash_synchronous(); + } +} + +const struct mmio_handler uart0_mmio_handler = { + .check_handler = uart0_mmio_check, + .read_handler = uart0_mmio_read, + .write_handler = uart0_mmio_write, +}; + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff -r a37ff29c027b -r f4e7fd47613c xen/arch/arm/vpl011.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/arm/vpl011.h Tue Jul 03 10:52:21 2012 +0100 @@ -0,0 +1,34 @@ +/* + * xen/arch/arm/vpl011.h + * + * ARM PL011 Emulation Support + * + * Ian Campbell <ian.campbell@xxxxxxxxxx> + * Copyright (c) 2012 Citrix Systems. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_VPL011_H__ +#define __ARCH_ARM_VPL011_H__ + +extern int domain_uart0_init(struct domain *d); + +#endif + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff -r a37ff29c027b -r f4e7fd47613c xen/include/asm-arm/domain.h --- a/xen/include/asm-arm/domain.h Tue Jul 03 10:52:20 2012 +0100 +++ b/xen/include/asm-arm/domain.h Tue Jul 03 10:52:21 2012 +0100 @@ -48,6 +48,14 @@ struct arch_domain struct vgic_irq_rank *shared_irqs; struct pending_irq *pending_irqs; } vgic; + + struct vpl011 { +#define VPL011_BUF_SIZE 128 + char *buf; + int idx; + spinlock_t lock; + } uart0; + } __cacheline_aligned; struct arch_vcpu _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |