From mboxrd@z Thu Jan 1 00:00:00 1970 From: vijay.kilari@gmail.com Subject: [PATCH v4 09/17] xen/arm: ITS: Add GITS registers emulation Date: Fri, 10 Jul 2015 13:12:44 +0530 Message-ID: <1436514172-3263-10-git-send-email-vijay.kilari@gmail.com> References: <1436514172-3263-1-git-send-email-vijay.kilari@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1436514172-3263-1-git-send-email-vijay.kilari@gmail.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Ian.Campbell@citrix.com, julien.grall@citrix.com, stefano.stabellini@eu.citrix.com, stefano.stabellini@citrix.com, tim@xen.org, xen-devel@lists.xen.org Cc: Prasun.Kapoor@caviumnetworks.com, Vijaya Kumar K , manish.jaggi@caviumnetworks.com, vijay.kilari@gmail.com List-Id: xen-devel@lists.xenproject.org From: Vijaya Kumar K Emulate GITS* registers Signed-off-by: Vijaya Kumar K --- v4: - Removed GICR register emulation --- xen/arch/arm/gic-v3-its.c | 11 ++ xen/arch/arm/vgic-v3-its.c | 319 ++++++++++++++++++++++++++++++++++++- xen/include/asm-arm/gic-its.h | 10 ++ xen/include/asm-arm/gic_v3_defs.h | 11 ++ 4 files changed, 349 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 1d2fdde..5e6c7f2 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -109,6 +109,16 @@ u32 its_get_nr_events(void) return (1 << its_data.id_bits); } +u32 its_get_id_bits(void) +{ + return its_data.id_bits; +} + +u32 its_get_dev_bits(void) +{ + return its_data.dev_bits; +} + static struct its_node * its_get_phys_node(u32 dev_id) { /* TODO: For now return ITS0 node. @@ -1309,6 +1319,7 @@ static int its_probe(struct dt_device_node *node) typer = readl_relaxed(its_base + GITS_TYPER); its->ite_size = ((typer >> 4) & 0xf) + 1; its_data.id_bits = GITS_TYPER_IDBITS(typer); + its_data.dev_bits = GITS_TYPER_DEVBITS(typer); its->cmd_base = xzalloc_bytes(ITS_CMD_QUEUE_SZ); if ( !its->cmd_base ) diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c index af2bacd..abf60e2 100644 --- a/xen/arch/arm/vgic-v3-its.c +++ b/xen/arch/arm/vgic-v3-its.c @@ -31,7 +31,9 @@ #include #include -#define DEBUG_ITS +// #define DEBUG_ITS +#define VITS_GITS_ITT_SIZE (0x7U << GITS_TYPER_ITT_SIZE_SHIFT) +#define VITS_GITS_PLPIS (0x1U) #ifdef DEBUG_ITS # define DPRINTK(fmt, args...) dprintk(XENLOG_DEBUG, fmt, ##args) @@ -568,7 +570,7 @@ static int vgic_its_read_virt_cmd(struct vcpu *v, return 0; } -int vgic_its_process_cmd(struct vcpu *v, struct vgic_its *vits) +static int vgic_its_process_cmd(struct vcpu *v, struct vgic_its *vits) { its_cmd_block virt_cmd; @@ -593,6 +595,319 @@ err: return 0; } +static inline void vits_spin_lock(struct vgic_its *vits) +{ + spin_lock(&vits->lock); +} + +static inline void vits_spin_unlock(struct vgic_its *vits) +{ + spin_unlock(&vits->lock); +} + +static int vgic_v3_gits_mmio_read(struct vcpu *v, mmio_info_t *info) +{ + struct vgic_its *vits = v->domain->arch.vits; + struct hsr_dabt dabt = info->dabt; + struct cpu_user_regs *regs = guest_cpu_user_regs(); + register_t *r = select_user_reg(regs, dabt.reg); + uint64_t val = 0; + uint32_t gits_reg; + + gits_reg = info->gpa - vits->gits_base; + + switch ( gits_reg ) + { + case GITS_CTLR: + if ( dabt.size != DABT_WORD ) goto bad_width; + vits_spin_lock(vits); + *r = vits->ctrl & GITS_CTLR_ENABLE; + vits_spin_unlock(vits); + return 1; + case GITS_IIDR: + if ( dabt.size != DABT_WORD ) goto bad_width; + *r = GICV3_GICD_IIDR_VAL; + return 1; + case GITS_TYPER: + case GITS_TYPER + 4: + vits_spin_lock(vits); + val = (((v->domain->max_vcpus + 1) << GITS_TYPER_HCC_SHIFT ) | + (its_get_dev_bits() - 1) << GITS_TYPER_DEVBITS_SHIFT | + (its_get_id_bits() - 1) << GITS_TYPER_IDBITS_SHIFT | + VITS_GITS_ITT_SIZE | VITS_GITS_PLPIS); + if ( (gits_reg % 8) == 0 && dabt.size == DABT_DOUBLE_WORD ) + *r = val; + else if ( dabt.size == DABT_WORD ) + { + if ( (gits_reg % 8) == 0 ) + *r = (u32)(val >> 32); + else + *r = (u32)val; + } + else + { + vits_spin_unlock(vits); + goto bad_width; + } + vits_spin_unlock(vits); + return 1; + case 0x0010 ... 0x007c: + case 0xc000 ... 0xffcc: + /* Implementation defined -- read ignored */ + goto read_as_zero; + case GITS_CBASER: + case GITS_CBASER + 4: + /* Only read support 32/64-bit access */ + vits_spin_lock(vits); + if ( (gits_reg % 8) == 0 && dabt.size == DABT_DOUBLE_WORD ) + *r = vits->cmd_base; + else if ( dabt.size == DABT_WORD ) + { + if ( (gits_reg % 8) == 0 ) + *r = (u32)vits->cmd_base; + else + *r = (u32)(vits->cmd_base >> 32); + } + else + { + vits_spin_unlock(vits); + goto bad_width; + } + vits_spin_unlock(vits); + return 1; + case GITS_CWRITER: + case GITS_CWRITER + 4: + /* Only read support 32/64-bit access */ + vits_spin_lock(vits); + if ( (gits_reg % 8) == 0 && dabt.size == DABT_DOUBLE_WORD ) + *r = vits->cmd_write; + else if ( dabt.size == DABT_WORD ) + { + if ( (gits_reg % 8) == 0 ) + *r = (u32)vits->cmd_write; + else + *r = (u32)(vits->cmd_write >> 32); + } + else + { + vits_spin_unlock(vits); + goto bad_width; + } + vits_spin_unlock(vits); + return 1; + case GITS_CREADR: + case GITS_CREADR + 4: + /* Only read support 32/64-bit access */ + vits_spin_lock(vits); + if ( (gits_reg % 8) == 0 && dabt.size == DABT_DOUBLE_WORD ) + *r = vits->cmd_read; + else if ( dabt.size == DABT_WORD ) + { + if ( (gits_reg % 8) == 0 ) + *r = (u32)vits->cmd_read; + else + *r = (u32)(vits->cmd_read >> 32); + } + else + { + vits_spin_unlock(vits); + goto bad_width; + } + vits_spin_unlock(vits); + return 1; + case 0x0098 ... 0x009c: + case 0x00a0 ... 0x00fc: + case 0x0140 ... 0xbffc: + /* Reserved -- read ignored */ + goto read_as_zero; + case GITS_BASER: + /* XXX: Support only 32-bit access */ + if ( dabt.size != DABT_DOUBLE_WORD || + (gits_reg % 8) != 0 ) + goto bad_width; + vits_spin_lock(vits); + *r = vits->baser; + vits_spin_unlock(vits); + return 1; + case GITS_BASER1 ... GITS_BASERN: + if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width; + *r = 0; + return 1; + case GITS_PIDR0: + if ( dabt.size != DABT_WORD ) + goto bad_width; + *r = GITS_PIDR0_VAL; + return 1; + case GITS_PIDR1: + if ( dabt.size != DABT_WORD ) + goto bad_width; + *r = GITS_PIDR1_VAL; + return 1; + case GITS_PIDR2: + if ( dabt.size != DABT_WORD ) + goto bad_width; + *r = GITS_PIDR2_VAL; + return 1; + case GITS_PIDR3: + if ( dabt.size != DABT_WORD ) + goto bad_width; + *r = GITS_PIDR3_VAL; + return 1; + case GITS_PIDR4: + if ( dabt.size != DABT_WORD ) + goto bad_width; + *r = GITS_PIDR4_VAL; + return 1; + case GITS_PIDR5 ... GITS_PIDR7: + goto read_as_zero_32; + default: + dprintk(XENLOG_G_ERR, "%pv: vITS: unhandled read r%d offset %#08x\n", + v, dabt.reg, gits_reg); + return 0; + } + +bad_width: + dprintk(XENLOG_G_ERR, "%pv: vITS: bad read width %d r%d offset %#08x\n", + v, dabt.size, dabt.reg, gits_reg); + domain_crash_synchronous(); + return 0; + +read_as_zero_32: + if ( dabt.size != DABT_WORD ) goto bad_width; +read_as_zero: + *r = 0; + return 1; +} + +/* + * GITS_BASER.Type[58:56],GITS_BASER.Entry_size[55:48] + * and GITS_BASER.Shareability[11:10] are read-only. + * Mask those fields while emulating GITS_BASER reg. + */ +#define GITS_BASER_MASK (~((0x7UL << GITS_BASER_TYPE_SHIFT) | \ + (0xffUL << GITS_BASER_ENTRY_SIZE_SHIFT) | \ + (0x3UL << GITS_BASER_SHAREABILITY_SHIFT))) + +static int vgic_v3_gits_mmio_write(struct vcpu *v, mmio_info_t *info) +{ + struct vgic_its *vits = v->domain->arch.vits; + struct hsr_dabt dabt = info->dabt; + struct cpu_user_regs *regs = guest_cpu_user_regs(); + register_t *r = select_user_reg(regs, dabt.reg); + int ret; + uint32_t gits_reg, sz, psz; + + gits_reg = info->gpa - vits->gits_base; + + switch ( gits_reg ) + { + case GITS_CTLR: + if ( dabt.size != DABT_WORD ) + goto bad_width; + vits_spin_lock(vits); + vits->ctrl = *r & GITS_CTLR_ENABLE; + vits_spin_unlock(vits); + return 1; + case GITS_IIDR: + /* R0 -- write ignored */ + goto write_ignore; + case GITS_TYPER: + case GITS_TYPER + 4: + /* R0 -- write ignored */ + goto write_ignore; + case 0x0010 ... 0x007c: + case 0xc000 ... 0xffcc: + /* Implementation defined -- write ignored */ + goto write_ignore; + case GITS_CBASER: + /* XXX: support 32-bit access */ + if ( dabt.size != DABT_DOUBLE_WORD ) + goto bad_width; + vits_spin_lock(vits); + vits->cmd_base = *r; + vits->cmd_qsize = SZ_4K * ((*r & GITS_BASER_PAGES_MASK_VAL) + 1); + if ( vits->cmd_qsize & GITS_BASER_VALID ) + vits->cmd_read = 0; + vits_spin_unlock(vits); + return 1; + case GITS_CBASER + 4: + /* XXX: Does not support word write */ + goto bad_width; + case GITS_CWRITER: + if ( dabt.size == DABT_BYTE ) goto bad_width; + /* XXX: Validate val */ + vits_spin_lock(vits); + vits->cmd_write = *r & 0xfffe0; + if ( !(vits->ctrl & GITS_CTLR_ENABLE) ) + return 1; + ret = vgic_its_process_cmd(v, vits); + vits_spin_unlock(vits); + return ret; + case GITS_CWRITER + 4: + if (dabt.size != DABT_WORD ) goto bad_width; + return 1; + case GITS_CREADR: + /* R0 -- write ignored */ + goto write_ignore; + case 0x0098 ... 0x009c: + case 0x00a0 ... 0x00fc: + case 0x0140 ... 0xbffc: + /* Reserved -- write ignored */ + goto write_ignore; + case GITS_BASER0: + /* XXX: Support 32-bit access */ + if ( dabt.size != DABT_DOUBLE_WORD ) + goto bad_width; + vits_spin_lock(vits); + vits->baser = vits->baser | (*r & GITS_BASER_MASK); + vits->dt_ipa = vits->baser & BIT_48_12_MASK; + psz = (vits->baser >> GITS_BASER_PAGE_SIZE_SHIFT) & + GITS_BASER_PAGE_SIZE_MASK_VAL; + if ( psz == GITS_BASER_PAGE_SIZE_4K_VAL ) + sz = 4; + else if ( psz == GITS_BASER_PAGE_SIZE_16K_VAL ) + sz = 16; + else + sz = 64; + + vits->dt_size = (vits->baser & GITS_BASER_PAGES_MASK_VAL) + * sz * SZ_1K; + vits_spin_unlock(vits); + return 1; + case GITS_BASER1 ... GITS_BASERN: + goto write_ignore_64; + case GITS_PIDR7 ... GITS_PIDR0: + /* R0 -- write ignored */ + goto write_ignore_32; + default: + dprintk(XENLOG_G_ERR, "%pv vITS: unhandled write r%d offset %#08x\n", + v, dabt.reg, gits_reg); + return 0; + } + +bad_width: + dprintk(XENLOG_G_ERR, "%pv: vITS: bad write width %d r%d offset %#08x\n", + v, dabt.size, dabt.reg, gits_reg); + domain_crash_synchronous(); + return 0; + +write_ignore_64: + if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width; + return 1; +write_ignore_32: + if ( dabt.size != DABT_WORD ) goto bad_width; + return 1; +write_ignore: + *r = 0; + return 1; +} + + +static const struct mmio_handler_ops vgic_gits_mmio_handler = { + .read_handler = vgic_v3_gits_mmio_read, + .write_handler = vgic_v3_gits_mmio_write, +}; + /* * Local variables: * mode: C diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h index f041efc..9c004c2 100644 --- a/xen/include/asm-arm/gic-its.h +++ b/xen/include/asm-arm/gic-its.h @@ -37,6 +37,8 @@ struct its_collection { struct vgic_its { spinlock_t lock; + /* Emulation of BASER0 */ + paddr_t baser; /* Command queue base */ paddr_t cmd_base; /* Command queue write pointer */ @@ -47,6 +49,12 @@ struct vgic_its paddr_t cmd_read; /* Command queue size */ unsigned long cmd_qsize; + /* ITS mmio physical base */ + paddr_t gits_base; + /* ITS mmio physical size */ + unsigned long gits_size; + /* GICR ctrl register */ + uint32_t ctrl; /* vITT device table ipa */ paddr_t dt_ipa; /* vITT device table size */ @@ -237,6 +245,8 @@ struct gic_its_info { uint32_t dev_bits; }; +u32 its_get_id_bits(void); +u32 its_get_dev_bits(void); u32 its_get_nr_events(void); int its_lpi_init(u32 id_bits); int its_init(struct rdist_prop *rdists); diff --git a/xen/include/asm-arm/gic_v3_defs.h b/xen/include/asm-arm/gic_v3_defs.h index 0443ae7..84366df 100644 --- a/xen/include/asm-arm/gic_v3_defs.h +++ b/xen/include/asm-arm/gic_v3_defs.h @@ -202,6 +202,7 @@ #define GITS_TYPER_IDBITS(r) ((((r) >> GITS_TYPER_IDBITS_SHIFT) & 0x1f) + 1) #define GITS_TYPER_PTA (1UL << 19) #define GITS_TYPER_HCC_SHIFT (24) +#define GITS_TYPER_ITT_SIZE_SHIFT (4) #define GITS_CBASER_VALID (1UL << 63) #define GITS_CBASER_nC (1UL << 59) @@ -228,6 +229,10 @@ #define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT) #define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT) #define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_4K_VAL (0) +#define GITS_BASER_PAGE_SIZE_16K_VAL (1) +#define GITS_BASER_PAGE_SIZE_MASK_VAL (0x3) +#define GITS_BASER_PAGES_MASK_VAL (0xff) #define GITS_BASER_TYPE_NONE 0 #define GITS_BASER_TYPE_DEVICE 1 #define GITS_BASER_TYPE_VCPU 2 @@ -236,6 +241,12 @@ #define GITS_BASER_TYPE_RESERVED5 5 #define GITS_BASER_TYPE_RESERVED6 6 #define GITS_BASER_TYPE_RESERVED7 7 +/* 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) /* * ITS commands -- 1.7.9.5