[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 18/38] arm: implement vpl011 (UART) emulator.
On Thu, 2012-06-07 at 11:18 +0100, Tim Deegan wrote: > At 10:34 +0100 on 07 Jun (1339065291), Ian Campbell wrote: > > On Thu, 2012-06-07 at 10:29 +0100, Tim Deegan wrote: > > > > +int domain_uart0_init(struct domain *d) > > > > +{ > > > > + int rc; > > > > + if ( d->domain_id == 0 ) > > > > + return 0; > > > > > > Why? There's no equivalent gate on the MMIO handlers. > > > > dom0 has the actual uart mapped at this address, not the emulated one. > > Maybe that should be written at the caller instead? > > Yes - ideally in the same place that puts the MMIO hooks in that will > call the other functions in this file. Turns out that there isn't actually such a place, these are part of a global list of mmio handlers which is traversed for any guest dabt. This might be something we want to improve (using bits in not-present p2m entries to identify specific handlers or whatever) but not right now I think. I've pulled the dom0 check out into the caller of the init function, but left an ASSERT behind. I also shortened that long line by using a #define for the end and removing the dom0 check from there too. 8<------------------------------------------------------------ >From 401e861ff99860d07e758c8d6e3260b8fb847fc5 Mon Sep 17 00:00:00 2001 From: Ian Campbell <ian.campbell@xxxxxxxxxx> Date: Mon, 14 May 2012 12:55:31 +0100 Subject: [PATCH] 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> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/domain.c | 5 ++ xen/arch/arm/io.c | 1 + xen/arch/arm/io.h | 1 + xen/arch/arm/vpl011.c | 145 ++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/vpl011.h | 34 ++++++++++ xen/include/asm-arm/domain.h | 8 ++ 7 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 xen/arch/arm/vpl011.c create mode 100644 xen/arch/arm/vpl011.h diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 9440a21..5a87ba6 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -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 --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 63bad07..931261b 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -13,6 +13,7 @@ #include "gic.h" #include "vtimer.h" +#include "vpl011.h" DEFINE_PER_CPU(struct vcpu *, curr_vcpu); @@ -215,6 +216,10 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) 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 --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c index 4461225..18f6164 100644 --- a/xen/arch/arm/io.c +++ b/xen/arch/arm/io.c @@ -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 --git a/xen/arch/arm/io.h b/xen/arch/arm/io.h index 8cc5ca7..9a507f5 100644 --- a/xen/arch/arm/io.h +++ b/xen/arch/arm/io.h @@ -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 --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c new file mode 100644 index 0000000..5dc8b28 --- /dev/null +++ b/xen/arch/arm/vpl011.c @@ -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 --git a/xen/arch/arm/vpl011.h b/xen/arch/arm/vpl011.h new file mode 100644 index 0000000..952d812 --- /dev/null +++ b/xen/arch/arm/vpl011.h @@ -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 --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 10ed540..f295a82 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -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 -- 1.7.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |