[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 13/28] ARM: vITS: add command handling stub and MMIO emulation
On Thu, 11 May 2017, Andre Przywara wrote: > + case VREG64(GITS_CWRITER): > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + > + reg = its->cwriter; > + *r = vgic_reg64_extract(reg, info); Why is this not protected by a lock? Also from the comment above I cannot tell if it should be protected by its_lock or by vcmd_lock. > + break; > + case VREG64(GITS_CREADR): > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + > + reg = its->creadr; > + *r = vgic_reg64_extract(reg, info); > + break; Same here > + case VRANGE64(0x0098, 0x00F8): > + goto read_reserved; > + case VREG64(GITS_BASER0): /* device table */ > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + spin_lock(&its->its_lock); > + *r = vgic_reg64_extract(its->baser_dev, info); > + spin_unlock(&its->its_lock); > + break; > + case VREG64(GITS_BASER1): /* collection table */ > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + spin_lock(&its->its_lock); > + *r = vgic_reg64_extract(its->baser_coll, info); > + spin_unlock(&its->its_lock); > + break; > + case VRANGE64(GITS_BASER2, GITS_BASER7): > + goto read_as_zero_64; > + case VRANGE32(0x0140, 0xBFFC): > + goto read_reserved; > + case VRANGE32(0xC000, 0xFFCC): > + goto read_impl_defined; > + case VRANGE32(0xFFD0, 0xFFE4): > + goto read_impl_defined; > + case VREG32(GITS_PIDR2): > + if ( info->dabt.size != DABT_WORD ) goto bad_width; > + *r = vgic_reg32_extract(GIC_PIDR2_ARCH_GICv3, info); > + break; > + case VRANGE32(0xFFEC, 0xFFFC): > + goto read_impl_defined; > + default: > + printk(XENLOG_G_ERR > + "%pv: vGITS: unhandled read r%d offset %#04lx\n", > + v, info->dabt.reg, (unsigned long)info->gpa & 0xffff); > + return 0; > + } > + > + return 1; > + > +read_as_zero_64: > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + *r = 0; > + > + return 1; > + > +read_impl_defined: > + printk(XENLOG_G_DEBUG > + "%pv: vGITS: RAZ on implementation defined register offset > %#04lx\n", > + v, info->gpa & 0xffff); > + *r = 0; > + return 1; > + > +read_reserved: > + printk(XENLOG_G_DEBUG > + "%pv: vGITS: RAZ on reserved register offset %#04lx\n", > + v, info->gpa & 0xffff); > + *r = 0; > + return 1; > + > +bad_width: > + printk(XENLOG_G_ERR "vGITS: bad read width %d r%d offset %#04lx\n", > + info->dabt.size, info->dabt.reg, (unsigned long)info->gpa & > 0xffff); > + domain_crash_synchronous(); > + > + return 0; > +} > + > +/****************************** > + * ITS registers write access * > + ******************************/ > + > +static unsigned int its_baser_table_size(uint64_t baser) > +{ > + unsigned int ret, page_size[4] = {SZ_4K, SZ_16K, SZ_64K, SZ_64K}; > + > + ret = page_size[(baser >> GITS_BASER_PAGE_SIZE_SHIFT) & 3]; > + > + return ret * ((baser & GITS_BASER_SIZE_MASK) + 1); > +} > + > +static unsigned int its_baser_nr_entries(uint64_t baser) > +{ > + unsigned int entry_size = GITS_BASER_ENTRY_SIZE(baser); > + > + return its_baser_table_size(baser) / entry_size; > +} > + > +/* Must be called with the ITS lock held. */ > +static bool vgic_v3_verify_its_status(struct virt_its *its, bool status) > +{ > + ASSERT(spin_is_locked(&its->its_lock)); > + > + if ( !status ) > + return false; > + > + if ( !(its->cbaser & GITS_VALID_BIT) || > + !(its->baser_dev & GITS_VALID_BIT) || > + !(its->baser_coll & GITS_VALID_BIT) ) > + { > + printk(XENLOG_G_WARNING "d%d tried to enable ITS without having the > tables configured.\n", > + its->d->domain_id); > + return false; > + } > + > + return true; > +} > + > +static void sanitize_its_base_reg(uint64_t *reg) > +{ > + uint64_t r = *reg; > + > + /* Avoid outer shareable. */ > + switch ( (r >> GITS_BASER_SHAREABILITY_SHIFT) & 0x03 ) > + { > + case GIC_BASER_OuterShareable: > + r &= ~GITS_BASER_SHAREABILITY_MASK; > + r |= GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT; > + break; > + default: > + break; > + } > + > + /* Avoid any inner non-cacheable mapping. */ > + switch ( (r >> GITS_BASER_INNER_CACHEABILITY_SHIFT) & 0x07 ) > + { > + case GIC_BASER_CACHE_nCnB: > + case GIC_BASER_CACHE_nC: > + r &= ~GITS_BASER_INNER_CACHEABILITY_MASK; > + r |= GIC_BASER_CACHE_RaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT; > + break; > + default: > + break; > + } > + > + /* Only allow non-cacheable or same-as-inner. */ > + switch ( (r >> GITS_BASER_OUTER_CACHEABILITY_SHIFT) & 0x07 ) > + { > + case GIC_BASER_CACHE_SameAsInner: > + case GIC_BASER_CACHE_nC: > + break; > + default: > + r &= ~GITS_BASER_OUTER_CACHEABILITY_MASK; > + r |= GIC_BASER_CACHE_nC << GITS_BASER_OUTER_CACHEABILITY_SHIFT; > + break; > + } > + > + *reg = r; > +} > + > +static int vgic_v3_its_mmio_write(struct vcpu *v, mmio_info_t *info, > + register_t r, void *priv) > +{ > + struct domain *d = v->domain; > + struct virt_its *its = priv; > + uint64_t reg; > + uint32_t reg32; > + > + switch ( info->gpa & 0xffff ) > + { > + case VREG32(GITS_CTLR): > + { > + uint32_t ctlr; > + > + if ( info->dabt.size != DABT_WORD ) goto bad_width; > + > + /* > + * We need to take the vcmd_lock to prevent a guest from disabling > + * the ITS while commands are still processed. > + */ > + spin_lock(&its->vcmd_lock); > + spin_lock(&its->its_lock); > + ctlr = its->enabled ? GITS_CTLR_ENABLE : 0; > + reg32 = ctlr; > + vgic_reg32_update(®32, r, info); > + > + if ( ctlr ^ reg32 ) > + its->enabled = vgic_v3_verify_its_status(its, > + reg32 & > GITS_CTLR_ENABLE); > + spin_unlock(&its->its_lock); > + spin_unlock(&its->vcmd_lock); > + return 1; > + } > + > + case VREG32(GITS_IIDR): > + goto write_ignore_32; > + case VREG32(GITS_TYPER): > + goto write_ignore_32; > + case VRANGE32(0x0018, 0x001C): > + goto write_reserved; > + case VRANGE32(0x0020, 0x003C): > + goto write_impl_defined; > + case VRANGE32(0x0040, 0x007C): > + goto write_reserved; > + case VREG64(GITS_CBASER): > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + > + spin_lock(&its->its_lock); > + /* Changing base registers with the ITS enabled is UNPREDICTABLE. */ > + if ( its->enabled ) > + { > + spin_unlock(&its->its_lock); > + gdprintk(XENLOG_WARNING, > + "vGITS: tried to change CBASER with the ITS > enabled.\n"); > + return 1; > + } > + > + reg = its->cbaser; > + vgic_reg64_update(®, r, info); > + sanitize_its_base_reg(®); > + > + its->cbaser = reg; > + its->creadr = 0; > + spin_unlock(&its->its_lock); > + > + return 1; > + > + case VREG64(GITS_CWRITER): > + if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width; > + > + spin_lock(&its->vcmd_lock); > + reg = ITS_CMD_OFFSET(its->cwriter); > + vgic_reg64_update(®, r, info); > + its->cwriter = ITS_CMD_OFFSET(reg); > + > + if ( its->enabled ) > + if ( vgic_its_handle_cmds(d, its) ) > + gdprintk(XENLOG_WARNING, "error handling ITS commands\n"); > + > + spin_unlock(&its->vcmd_lock); OK, so it looks like the reads should be protected by vcmd_lock > + return 1; > + > + case VREG64(GITS_CREADR): _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |