From patchwork Mon Apr 3 09:44:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhupinder Thakur X-Patchwork-Id: 96603 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp18541qgd; Mon, 3 Apr 2017 02:47:09 -0700 (PDT) X-Received: by 10.107.59.146 with SMTP id i140mr14915704ioa.100.1491212829812; Mon, 03 Apr 2017 02:47:09 -0700 (PDT) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id n192si14258563iod.213.2017.04.03.02.47.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 03 Apr 2017 02:47:09 -0700 (PDT) Received-SPF: neutral (google.com: 192.237.175.120 is neither permitted nor denied by best guess record for domain of xen-devel-bounces@lists.xen.org) client-ip=192.237.175.120; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=neutral (google.com: 192.237.175.120 is neither permitted nor denied by best guess record for domain of xen-devel-bounces@lists.xen.org) smtp.mailfrom=xen-devel-bounces@lists.xen.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cuyXa-0001MN-QR; Mon, 03 Apr 2017 09:44:50 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cuyXZ-0001MH-Qi for xen-devel@lists.xenproject.org; Mon, 03 Apr 2017 09:44:49 +0000 Received: from [193.109.254.147] by server-7.bemta-6.messagelabs.com id E0/86-04817-19912E85; Mon, 03 Apr 2017 09:44:49 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrCIsWRWlGSWpSXmKPExsXiVRtsoDtB8lG EwZMVnBbft0xmcmD0OPzhCksAYxRrZl5SfkUCa8aXuYuYClrqK64+3c7WwPg+qYuRi0NIYBaj xOeeBUwgDovAPGaJcytusIM4EgL9rBLtZ+4DOZxATozE/G3rmCDsKomv3y6A2UICWhJHT81mh RjVyiQxZfNaoAYODjYBE4lZHRIgNSICShL3Vk0G28AsMJ9RYm/PWVaQhLCAu8SM5RcZQepZBF Qlrs6LBAnzCnhL3Px3lBFil5zEzXOdzCAlnAI+ErdeJUCs9ZZ4dX8a2wRGgQWMDKsY1YtTi8p Si3QN9ZKKMtMzSnITM3N0DQ3M9HJTi4sT01NzEpOK9ZLzczcxAsOKAQh2MO587nSIUZKDSUmU 982dhxFCfEn5KZUZicUZ8UWlOanFhxhlODiUJHhzJR5FCAkWpaanVqRl5gADHCYtwcGjJMI7C STNW1yQmFucmQ6ROsVozLHo3+43TBwf+g+/YRJiycvPS5US590PUioAUppRmgc3CBZ5lxhlpY R5GYFOE+IpSC3KzSxBlX/FKM7BqCTMOw9kCk9mXgncvldApzABnfIE5Ave4pJEhJRUA6OG7j+ vvE8P+s057bz+3vDJkDt0I5ir6oO/yjQdow9HBb/sSrhTXtSmH5K/00Pl/HJrnpUTyqpb3p/w yuqY9+BQzOXKypsMBmGXF1WzXk0Iipoh1LnQUuvKk+Ib5qLRn6OKZJ8wf7y8vPlc2bL3Ocv6n +3u9V7Hn3XeeUJ4F0fXC9O3346Kn1NiKc5INNRiLipOBAC0knaDtwIAAA== X-Env-Sender: bhupinder.thakur@linaro.org X-Msg-Ref: server-12.tower-27.messagelabs.com!1491212686!93728541!1 X-Originating-IP: [74.125.83.48] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 35557 invoked from network); 3 Apr 2017 09:44:47 -0000 Received: from mail-pg0-f48.google.com (HELO mail-pg0-f48.google.com) (74.125.83.48) by server-12.tower-27.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 3 Apr 2017 09:44:47 -0000 Received: by mail-pg0-f48.google.com with SMTP id x125so115247007pgb.0 for ; Mon, 03 Apr 2017 02:44:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YloYqwUTUfSBvRRnsFmFA82AONP5vNg7MT4xlFbB4LE=; b=BsjC70NtKu0bytIb/9WGs1y1e/oS2WzFX+NG6S+Z0GKguPPkB27MxD5U0xUVsopaHj oscAwO38BXZjfKE0CLCT5OgFhNmRyKKsC0QVkPHCSIQQr5vdlPTyRrSpbhFmJkdxLL6D t2I5zTijqI385JWDz06MUh3AdhzYf5P1lXQoI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YloYqwUTUfSBvRRnsFmFA82AONP5vNg7MT4xlFbB4LE=; b=KQwu9q7qe1AeEIXx/iHIdISmTin+jNuuQd+iMNZRQdN/bjZC52AoDx9EXhaLGORboW f3LH0do7Dcz3rGKzle1NNY3NiMTxu+KPl8ZrVJ08l+r3CiJYlH/Qjb7oCWbfr4zx8HXQ Rnfd82bEU7lpHdEFgfOY/izxybp+we+W7xEMQukMwx8tPV/SRWPXD+yidXMgTBCX6WF9 gp3rE02Boc+GMMkIvTcntwL9Rb8qoJt1v6cIvUEgjaYJg0+ufbleo2dSwu2OrlMTIz6b vhakDb46pBB3IipNL62EgYvFWZKcTV8jAXP3t/z3LRtCKuZxRf5dz+nic8exrNA4Y1tu u/rg== X-Gm-Message-State: AFeK/H37xkX6I1eNmTLNPgLSKPP2HvURlTex7yO0TEPYwzQYxo3A8lXvORSkxY7e8eMy2FPc X-Received: by 10.84.232.131 with SMTP id i3mr20560846plk.172.1491212686280; Mon, 03 Apr 2017 02:44:46 -0700 (PDT) Received: from blr-ubuntu-linaro.wlan.qualcomm.com ([202.46.23.54]) by smtp.gmail.com with ESMTPSA id y7sm24751844pfk.93.2017.04.03.02.44.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 03 Apr 2017 02:44:45 -0700 (PDT) From: Bhupinder Thakur To: xen-devel@lists.xenproject.org Date: Mon, 3 Apr 2017 15:14:24 +0530 Message-Id: <1491212673-13476-2-git-send-email-bhupinder.thakur@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491212673-13476-1-git-send-email-bhupinder.thakur@linaro.org> References: <1491212673-13476-1-git-send-email-bhupinder.thakur@linaro.org> Cc: Wei Liu , Julien Grall , Stefano Stabellini , Ian Jackson Subject: [Xen-devel] [PATCH 01/10] xen/arm: vpl011: Add pl011 uart emulation in Xen X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" Add emulation code to emulate read/write access to pl011 registers and pl011 interrupts: - Emulate DR read/write by reading and writing from/to the IN and OUT ring buffers and raising an event to the backend when there is data in the OUT ring buffer and injecting an interrupt to the guest when there is data in the IN ring buffer - Other registers are related to interrupt management and essentially control when interrupts are delivered to the guest The SBSA compliant pl011 uart is covered in Appendix B of https://static.docs.arm.com/den0029/a/Server_Base_System_Architecture_v3_1_ARM_DEN_0029A.pdf Signed-off-by: Bhupinder Thakur --- xen/arch/arm/Kconfig | 5 + xen/arch/arm/Makefile | 1 + xen/arch/arm/vpl011.c | 339 +++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/domain.h | 5 + xen/include/asm-arm/pl011-uart.h | 2 + xen/include/public/arch-arm.h | 8 + xen/include/xen/vpl011.h | 67 ++++++++ 7 files changed, 427 insertions(+) create mode 100644 xen/arch/arm/vpl011.c create mode 100644 xen/include/xen/vpl011.h diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index 2e023d1..bfa86c7 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -45,6 +45,11 @@ config ACPI config HAS_GICV3 bool +config VPL011_CONSOLE + bool "Emulated pl011 console support" + default y + ---help--- + Allows a guest to use pl011 UART as a console endmenu menu "ARM errata workaround via the alternative framework" diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 7afb8a3..a94bdab 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -49,6 +49,7 @@ obj-y += vm_event.o obj-y += vtimer.o obj-y += vpsci.o obj-y += vuart.o +obj-$(CONFIG_VPL011_CONSOLE) += vpl011.o #obj-bin-y += ....o diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c new file mode 100644 index 0000000..eeb1cbf --- /dev/null +++ b/xen/arch/arm/vpl011.c @@ -0,0 +1,339 @@ +/* + * arch/arm/vpl011.c + * + * Virtual PL011 UART + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff}; + +static void vgic_inject_vpl011_spi(struct domain *d) +{ + struct vpl011_s *vpl011=&d->arch.vpl011; + + if ( (vpl011->uartris & vpl011->uartimsc) ) + vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI); +} + +static void vpl011_read_data(struct domain *d, uint8_t *data) +{ + unsigned long flags; + struct vpl011_s *vpl011=&d->arch.vpl011; + struct xencons_interface *intf=(struct xencons_interface *)vpl011->ring_buf; + + /* + * Initialize the data so that even if there is no data in ring buffer + * 0 is returned. + */ + *data = 0; + + VPL011_LOCK(d, flags); + + /* + * 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 event when TXFE bit is set then 0 will + * be returned. + */ + if ( !VPL011_IN_RING_EMPTY(intf) ) + { + *data = intf->in[MASK_XENCONS_IDX(intf->in_cons++, intf->in)]; + } + + if ( VPL011_IN_RING_EMPTY(intf) ) + { + vpl011->uartfr |= (RXFE); + vpl011->uartris &= ~(RXI); + } + + vpl011->uartfr &= ~(RXFF); + + VPL011_UNLOCK(d, flags); +} + +static void vpl011_write_data(struct domain *d, uint8_t data) +{ + unsigned long flags; + struct vpl011_s *vpl011=&d->arch.vpl011; + struct xencons_interface *intf=(struct xencons_interface *)vpl011->ring_buf; + + VPL011_LOCK(d, flags); + + /* + * It is expected that the ring is not full when this function is called + * as the guest is expected to write to the data register only when the + * TXFF flag is not set. + * In case the guest does write even when the TXFF flag is set then the + * data will be silently dropped. + */ + if ( !VPL011_OUT_RING_FULL(intf) ) + { + intf->out[MASK_XENCONS_IDX(intf->out_prod++, intf->out)] = data; + smp_wmb(); + } + + if ( VPL011_OUT_RING_FULL(intf) ) + { + vpl011->uartfr |= (TXFF); + vpl011->uartris &= ~(TXI); + } + + vpl011->uartfr |= (BUSY); + + vpl011->uartfr &= ~(TXFE); + + VPL011_UNLOCK(d, flags); + + /* raise an event to xenconsoled only if it is the first character in the buffer */ + if ( VPL011_RING_DEPTH(intf, out) == 1 ) + { + notify_via_xen_event_channel(d, d->arch.hvm_domain.params[HVM_PARAM_VCONSOLE_EVTCHN]); + } +} + +static int vpl011_mmio_read(struct vcpu *v, mmio_info_t *info, register_t *r, void *priv) +{ + uint8_t ch; + struct hsr_dabt dabt = info->dabt; + int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE); + struct vpl011_s *vpl011 = &v->domain->arch.vpl011; + + switch ( vpl011_reg ) + { + case DR: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + vpl011_read_data(v->domain, &ch); + *r = ch; + break; + + case RSR: + if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width; + + /* It always returns 0 as there are no physical errors. */ + *r = 0; + break; + + case FR: + if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width; + *r = (vpl011->uartfr & vpl011_reg_mask[dabt.size]); + break; + + case RIS: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + *r = (vpl011->uartris & vpl011_reg_mask[dabt.size]); + break; + + case MIS: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + *r = (vpl011->uartris & + vpl011->uartimsc & vpl011_reg_mask[dabt.size]); + break; + + case IMSC: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + *r = (vpl011->uartimsc & vpl011_reg_mask[dabt.size]); + break; + + case ICR: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + + /* Only write is valid. */ + return 0; + + default: + gprintk(XENLOG_ERR, "vpl011: unhandled read r%d offset %#08x\n", + dabt.reg, vpl011_reg); + return 0; + } + + return 1; + +bad_width: + gprintk(XENLOG_ERR, "vpl011: bad read width %d r%d offset %#08x\n", + dabt.size, dabt.reg, vpl011_reg); + domain_crash_synchronous(); + return 0; + +} + +static int vpl011_mmio_write(struct vcpu *v, mmio_info_t *info, register_t r, void *priv) +{ + uint8_t ch = ((struct uartdr_reg *)&r)->data; + struct hsr_dabt dabt = info->dabt; + int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE); + struct vpl011_s *vpl011 = &v->domain->arch.vpl011; + + switch ( vpl011_reg ) + { + case DR: + + if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width; + vpl011_write_data(v->domain, ch); + break; + + case RSR: /* Nothing to clear. */ + if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width; + break; + + case FR: + goto write_ignore; + case RIS: + case MIS: + goto word_write_ignore; + + case IMSC: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + vpl011->uartimsc = (r & vpl011_reg_mask[dabt.size]); + vgic_inject_vpl011_spi(v->domain); + break; + + case ICR: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + vpl011->uartris &= ~(r & vpl011_reg_mask[dabt.size]); + vgic_inject_vpl011_spi(v->domain); + break; + + default: + gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n", + dabt.reg, vpl011_reg); + return 0; + } + + return 1; + +write_ignore: + if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width; + return 1; + +word_write_ignore: + if ( !VALID_W_SIZE(dabt.size) ) goto bad_width; + return 1; + +bad_width: + gprintk(XENLOG_ERR, "vpl011: bad write width %d r%d offset %#08x\n", + dabt.size, dabt.reg, vpl011_reg); + domain_crash_synchronous(); + return 0; + +} + +static const struct mmio_handler_ops vpl011_mmio_handler = { + .read = vpl011_mmio_read, + .write = vpl011_mmio_write, +}; + +int vpl011_map_guest_page(struct domain *d) +{ + struct vpl011_s *vpl011 = &d->arch.vpl011; + + /* Map the guest PFN to Xen address space. */ + return prepare_ring_for_helper(d, + d->arch.hvm_domain.params[HVM_PARAM_VCONSOLE_PFN], + &vpl011->ring_page, + &vpl011->ring_buf); +} + +static void vpl011_data_avail(struct domain *d) +{ + unsigned long flags; + struct vpl011_s *vpl011 = &d->arch.vpl011; + struct xencons_interface *intf=(struct xencons_interface *)vpl011->ring_buf; + + VPL011_LOCK(d, flags); + + /* Update the uart rx state if the buffer is not empty. */ + if ( !VPL011_IN_RING_EMPTY(intf) ) + { + vpl011->uartfr &= ~(RXFE); + if ( VPL011_IN_RING_FULL(intf) ) + vpl011->uartfr |= (RXFF); + vpl011->uartris |= (RXI); + } + + /* Update the uart tx state if the buffer is not full. */ + if ( !VPL011_OUT_RING_FULL(intf) ) + { + vpl011->uartfr &= ~(TXFF); + vpl011->uartris |= (TXI); + if ( VPL011_OUT_RING_EMPTY(intf) ) + { + vpl011->uartfr &= ~(BUSY); + vpl011->uartfr |= (TXFE); + } + } + + VPL011_UNLOCK(d, flags); + + vgic_inject_vpl011_spi(d); + + if ( !VPL011_OUT_RING_EMPTY(intf) ) + { + ASSERT( d->arch.hvm_domain.params[HVM_PARAM_VCONSOLE_EVTCHN] != 0 ); + notify_via_xen_event_channel(d, d->arch.hvm_domain.params[HVM_PARAM_VCONSOLE_EVTCHN]); + } +} + + +static void vpl011_notification(struct vcpu *v, unsigned int port) +{ + vpl011_data_avail(v->domain); +} + +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config) +{ + int rc; + struct vpl011_s *vpl011 = &d->arch.vpl011; + + rc = alloc_unbound_xen_event_channel(d, 0, config->console_domid, + vpl011_notification); + if (rc < 0) + { + return rc; + } + d->arch.hvm_domain.params[HVM_PARAM_VCONSOLE_EVTCHN] = rc; + rc = vgic_reserve_virq(d, GUEST_VPL011_SPI); + if ( !rc ) + return rc; + register_mmio_handler(d, &vpl011_mmio_handler, GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL); + spin_lock_init(&vpl011->lock); + + vpl011->intialized = true; + + return 0; +} + +int domain_vpl011_deinit(struct domain *d) +{ + struct vpl011_s *vpl011 = &d->arch.vpl011; + + if ( vpl011->intialized ) + { + free_xen_event_channel(d, d->arch.hvm_domain.params[HVM_PARAM_VCONSOLE_EVTCHN]); + destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page); + } + + return 0; +} + diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 2d6fbb1..a122504 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -11,6 +11,7 @@ #include #include #include +#include struct hvm_domain { @@ -131,6 +132,10 @@ struct arch_domain struct { uint8_t privileged_call_enabled : 1; } monitor; + +#ifdef CONFIG_VPL011_CONSOLE + struct vpl011_s vpl011; +#endif } __cacheline_aligned; struct arch_vcpu diff --git a/xen/include/asm-arm/pl011-uart.h b/xen/include/asm-arm/pl011-uart.h index 123f477..57e9ec7 100644 --- a/xen/include/asm-arm/pl011-uart.h +++ b/xen/include/asm-arm/pl011-uart.h @@ -49,6 +49,8 @@ /* FR bits */ #define TXFE (1<<7) /* TX FIFO empty */ #define RXFE (1<<4) /* RX FIFO empty */ +#define TXFF (1<<5) /* TX FIFO full */ +#define RXFF (1<<6) /* RX FIFO full */ #define BUSY (1<<3) /* Transmit is not complete */ /* LCR_H bits */ diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index bd974fb..5f91207 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -322,6 +322,8 @@ struct xen_arch_domainconfig { * */ uint32_t clock_frequency; + + uint32_t console_domid; }; #endif /* __XEN__ || __XEN_TOOLS__ */ @@ -410,6 +412,10 @@ typedef uint64_t xen_callback_t; #define GUEST_ACPI_BASE 0x20000000ULL #define GUEST_ACPI_SIZE 0x02000000ULL +/* PL011 mappings */ +#define GUEST_PL011_BASE 0x22000000ULL +#define GUEST_PL011_SIZE 0x00001000ULL + /* * 16MB == 4096 pages reserved for guest to use as a region to map its * grant table in. @@ -444,6 +450,8 @@ typedef uint64_t xen_callback_t; #define GUEST_TIMER_PHYS_NS_PPI 30 #define GUEST_EVTCHN_PPI 31 +#define GUEST_VPL011_SPI 32 + /* PSCI functions */ #define PSCI_cpu_suspend 0 #define PSCI_cpu_off 1 diff --git a/xen/include/xen/vpl011.h b/xen/include/xen/vpl011.h new file mode 100644 index 0000000..f9f2aba --- /dev/null +++ b/xen/include/xen/vpl011.h @@ -0,0 +1,67 @@ +/* + * include/xen/vpl011.h + * + * Virtual PL011 UART + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; If not, see . + */ + +#ifndef _VPL011_H_ + +#define _VPL011_H_ + +/* helper macros */ +#define VPL011_RING_DEPTH(intf,dir) (((intf)->dir ## _prod - (intf)->dir ## _cons)) + +#define VPL011_RING_MAX_DEPTH(intf,dir) (sizeof((intf)->dir)-1) + +#define VPL011_IN_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, in) == 0) + +#define VPL011_OUT_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, out) == 0) + +#define VPL011_IN_RING_FULL(intf) (VPL011_RING_DEPTH(intf, in) == VPL011_RING_MAX_DEPTH(intf, in)) + +#define VPL011_OUT_RING_FULL(intf) (VPL011_RING_DEPTH(intf, out) == VPL011_RING_MAX_DEPTH(intf,out)) + +#define VPL011_LOCK(d,flags) spin_lock_irqsave(&(d)->arch.vpl011.lock, flags) +#define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags) + +#define VALID_BW_SIZE(size) ( size == DABT_BYTE || size == DABT_HALF_WORD || size == DABT_WORD ) +#define VALID_W_SIZE(size) ( size == DABT_HALF_WORD || size == DABT_WORD ) + +struct uartdr_reg { + uint8_t data; + uint8_t error_status:4; + uint8_t reserved1:4; + uint16_t reserved2; + uint32_t reserved3; +}; + +struct vpl011_s { + void *ring_buf; + struct page_info *ring_page; + uint32_t uartfr; /* flag register */ + uint32_t uartcr; /* control register */ + uint32_t uartimsc; /* interrupt mask register*/ + uint32_t uarticr; /* interrupt clear register */ + uint32_t uartris; /* raw interrupt status register */ + uint32_t uartmis; /* masked interrupt register */ + spinlock_t lock; + bool intialized; /* flag which tells whether vpl011 is initialized */ +}; + +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config); +int domain_vpl011_deinit(struct domain *d); +int vpl011_map_guest_page(struct domain *d); + +#endif