[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH v3 08/18] xen/arm: vITS: Add virtual ITS driver
From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> This patch introduces virtual ITS driver with following functionality - Introduces helper functions to manage device table and ITT table in guest memory - Helper function to handle virtual ITS devices assigned to domain Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/vgic-v3-its.c | 266 +++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/domain.h | 2 + xen/include/asm-arm/gic-its.h | 49 ++++++++ 4 files changed, 318 insertions(+) diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 1821ed2..8590846 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -33,6 +33,7 @@ obj-y += traps.o obj-y += vgic.o vgic-v2.o obj-$(CONFIG_ARM_64) += vgic-v3.o obj-$(CONFIG_ARM_64) += gic-v3-its.o +obj-$(CONFIG_ARM_64) += vgic-v3-its.o obj-y += vtimer.o obj-y += vuart.o obj-y += hvm.o diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c new file mode 100644 index 0000000..ea52a87 --- /dev/null +++ b/xen/arch/arm/vgic-v3-its.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2015 Cavium Inc. + * Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <xen/bitops.h> +#include <xen/config.h> +#include <xen/init.h> +#include <xen/irq.h> +#include <xen/list.h> +#include <xen/sched.h> +#include <xen/sizes.h> +#include <asm/device.h> +#include <asm/mmio.h> +#include <asm/io.h> +#include <asm/gic_v3_defs.h> +#include <asm/gic.h> +#include <asm/vgic.h> +#include <asm/gic-its.h> +#include <xen/log2.h> + +/* GITS register definitions */ +#define VITS_GITS_TYPER_HCC (0xffU << 24) +#define VITS_GITS_TYPER_PTA_SHIFT (19) +#define VITS_GITS_DEV_BITS (0x14U << 13) +#define VITS_GITS_ID_BITS (0x13U << 8) +#define VITS_GITS_ITT_SIZE (0x7U << 4) +#define VITS_GITS_DISTRIBUTED (0x1U << 3) +#define VITS_GITS_PLPIS (0x1U << 0) + +/* GITS_PIDRn register values for ARM implementations */ +#define GITS_PIDR0_VAL (0x94) +#define GITS_PIDR1_VAL (0xb4) +#define GITS_PIDR2_VAL (0x3b) +#define GITS_PIDR3_VAL (0x00) +#define GITS_PIDR4_VAL (0x04) + +// #define DEBUG_ITS + +#ifdef DEBUG_ITS +# define DPRINTK(fmt, args...) dprintk(XENLOG_DEBUG, fmt, ##args) +#else +# define DPRINTK(fmt, args...) do {} while ( 0 ) +#endif + +#ifdef DEBUG_ITS +static void dump_cmd(its_cmd_block *cmd) +{ + printk("CMD[0] = 0x%lx CMD[1] = 0x%lx CMD[2] = 0x%lx CMD[3] = 0x%lx\n", + cmd->raw_cmd[0], cmd->raw_cmd[1], cmd->raw_cmd[2], cmd->raw_cmd[3]); +} +#endif + +/* ITS device table helper functions */ +int vits_vdevice_entry(struct domain *d, uint32_t dev_id, + struct vdevice_table *entry, int set) +{ + uint64_t offset; + paddr_t dt_entry; + struct page_info *page; + p2m_type_t p2mt; + void *p; + + offset = dev_id * sizeof(struct vdevice_table); + if ( offset > d->arch.vits->dt_size ) + { + dprintk(XENLOG_G_ERR, + "vITS:d%dv%d: Out of range offset 0x%lx id 0x%x size 0x%lx\n", + d->domain_id, current->vcpu_id, offset, dev_id, + d->arch.vits->dt_size); + return -EINVAL; + } + + dt_entry = d->arch.vits->dt_ipa + offset; + + page = get_page_from_gfn(d, paddr_to_pfn(dt_entry), &p2mt, P2M_ALLOC); + if ( !page ) + { + dprintk(XENLOG_G_ERR, "vITS:d%dv%d Failed to get VITT device table\n", + d->domain_id, current->vcpu_id); + return -EINVAL; + } + + if ( !p2m_is_ram(p2mt) ) + { + put_page(page); + dprintk(XENLOG_G_ERR, "vITS:d%dv%d with wrong attributes\n", + d->domain_id, current->vcpu_id); + return -EINVAL; + return -EINVAL; + } + + p = __map_domain_page(page); + /* Offset within the mapped page */ + offset = dt_entry & (PAGE_SIZE - 1); + + if ( set ) + memcpy(p + offset, entry, sizeof(struct vdevice_table)); + else + memcpy(entry, p + offset, sizeof(struct vdevice_table)); + + unmap_domain_page(p); + put_page(page); + + return 0; +} + +int vits_set_vdevice_entry(struct domain *d, uint32_t devid, + struct vdevice_table *entry) +{ + return vits_vdevice_entry(d, devid, entry, 1); +} + +int vits_get_vdevice_entry(struct domain *d, uint32_t devid, + struct vdevice_table *entry) +{ + return vits_vdevice_entry(d, devid, entry, 0); +} + +int vits_vitt_entry(struct domain *d, uint32_t devid, + uint32_t event, struct vitt *entry, int set) +{ + struct vdevice_table dt_entry; + struct page_info *page; + paddr_t vitt_entry; + p2m_type_t p2mt; + uint64_t offset; + void *p; + + if ( vits_get_vdevice_entry(d, devid, &dt_entry) ) + { + dprintk(XENLOG_G_ERR, "vITS:d%dv%d Fail to get vdevice for dev 0x%x\n", + d->domain_id, current->vcpu_id, devid); + return -EINVAL; + } + + /* dt_entry is validated when read */ + offset = event * sizeof(struct vitt); + if ( offset > dt_entry.vitt_size ) + { + dprintk(XENLOG_G_ERR, "vITS:d%dv%d ITT out of range\n", + d->domain_id, current->vcpu_id); + return -EINVAL; + } + + vitt_entry = dt_entry.vitt_ipa + offset; + page = get_page_from_gfn(d, paddr_to_pfn(vitt_entry), &p2mt, P2M_ALLOC); + if ( !page ) + { + dprintk(XENLOG_G_ERR, "vITS:d%dv%d Failed to get VITT device table\n", + d->domain_id, current->vcpu_id); + return -EINVAL; + } + + if ( !p2m_is_ram(p2mt) ) + { + put_page(page); + dprintk(XENLOG_G_ERR, "vITS:d%dv%d with wrong attributes\n", + d->domain_id, current->vcpu_id); + return -EINVAL; + } + + p = __map_domain_page(page); + /* Offset within the mapped page */ + offset = vitt_entry & (PAGE_SIZE - 1); + + if ( set ) + memcpy(p + offset, entry, sizeof(struct vitt)); + else + memcpy(entry, p + offset, sizeof(struct vitt)); + + unmap_domain_page(p); + put_page(page); + + return 0; +} + +int vits_set_vitt_entry(struct domain *d, uint32_t devid, + uint32_t event, struct vitt *entry) +{ + return vits_vitt_entry(d, devid, event, entry, 1); +} + +int vits_get_vitt_entry(struct domain *d, uint32_t devid, + uint32_t event, struct vitt *entry) +{ + return vits_vitt_entry(d, devid, event, entry, 0); +} + +/* RB-tree helpers for vits_device attached to a domain */ +struct vits_device * find_vits_device(struct rb_root *root, uint32_t devid) +{ + struct rb_node *node = root->rb_node; + + while ( node ) + { + struct vits_device *dev; + + dev = container_of(node, struct vits_device, node); + + if ( devid < dev->vdevid ) + node = node->rb_left; + else if ( devid > dev->vdevid ) + node = node->rb_right; + else + return dev; + } + + return NULL; +} + +int insert_vits_device(struct rb_root *root, struct vits_device *dev) +{ + struct rb_node **new, *parent; + + new = &root->rb_node; + parent = NULL; + while ( *new ) + { + struct vits_device *this; + + this = container_of(*new, struct vits_device, node); + + parent = *new; + if ( dev->vdevid < this->vdevid ) + new = &((*new)->rb_left); + else if ( dev->vdevid > this->vdevid ) + new = &((*new)->rb_right); + else + return -EEXIST; + } + + rb_link_node(&dev->node, parent, new); + rb_insert_color(&dev->node, root); + + return 0; +} + +int remove_vits_device(struct rb_root *root, struct vits_device *dev) +{ + if ( dev ) + rb_erase(&dev->node, root); + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-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 f1a087e..da73cf5 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -115,6 +115,8 @@ struct arch_domain #endif } vgic; + struct vgic_its *vits; + struct vuart { #define VUART_BUF_SIZE 128 char *buf; diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h index a47cf26..a1099a1 100644 --- a/xen/include/asm-arm/gic-its.h +++ b/xen/include/asm-arm/gic-its.h @@ -31,6 +31,35 @@ struct its_collection { u16 col_id; }; +/* + * Per domain virtual ITS structure. + * One per Physical ITS node available for the domain + */ +struct vgic_its +{ + spinlock_t lock; + /* Command queue base */ + paddr_t cmd_base; + /* Command queue write pointer */ + paddr_t cmd_write; + /* Command queue write saved pointer */ + paddr_t cmd_write_save; + /* Command queue read pointer */ + paddr_t cmd_read; + /* Command queue size */ + unsigned long cmd_qsize; + /* ITS physical node */ + struct its_node *its; + /* vITT device table ipa */ + paddr_t dt_ipa; + /* vITT device table size */ + uint64_t dt_size; + /* Radix-tree root of devices attached to this domain */ + struct rb_root dev_root; + /* collections mapped */ + struct its_collection *collections; +}; + /* ITS command structures */ typedef struct __packed { u64 cmd:8; @@ -200,6 +229,26 @@ struct its_device { struct rb_node node; }; +struct vits_device { + uint32_t vdevid; + uint32_t pdevid; + struct its_device *its_dev; + struct rb_node node; +}; + +struct vdevice_table { + uint64_t vitt_ipa; + uint32_t vitt_size; + uint32_t padding; +}; + +struct vitt { + uint16_t valid:1; + uint16_t pad:15; + uint16_t vcollection; + uint32_t vlpi; +}; + static inline uint8_t its_decode_cmd(its_cmd_block *cmd) { return cmd->raw_cmd[0] & 0xff; -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |