[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC v01 1/3] arm: omap: introduce iommu module
On 01/22/2014 03:52 PM, Andrii Tseglytskyi wrote: > omap IOMMU module is designed to handle access to external > omap MMUs, connected to the L3 bus. Hello Andrii, Thanks for the patch. See my comment inline (I won't add the same comment as Stefano). > Change-Id: I96bbf2738e9dd2e21662e0986ca15c60183e669e > Signed-off-by: Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx> > --- [..] > +struct mmu_info { > + const char *name; > + paddr_t mem_start; > + u32 mem_size; > + u32 *pagetable; > + void __iomem *mem_map; > +}; > + > +static struct mmu_info omap_ipu_mmu = { static const? > + .name = "IPU_L2_MMU", > + .mem_start = 0x55082000, > + .mem_size = 0x1000, > + .pagetable = NULL, > +}; > + > +static struct mmu_info omap_dsp_mmu = { static const? > + .name = "DSP_L2_MMU", > + .mem_start = 0x4a066000, > + .mem_size = 0x1000, > + .pagetable = NULL, > +}; > + > +static struct mmu_info *mmu_list[] = { static const? > + &omap_ipu_mmu, > + &omap_dsp_mmu, > +}; > + > +#define mmu_for_each(pfunc, data) > \ > +({ > \ > + u32 __i; > \ > + int __res = 0; > \ > + > \ > + for (__i = 0; __i < ARRAY_SIZE(mmu_list); __i++) { \ > + __res |= pfunc(mmu_list[__i], data); \ You res |= will result to a "wrong" errno if you have multiple failure. Would it be better to have: __res = pfunc(...) if ( __res ) break; > + } > \ > + __res; > \ > +}) > + > +static int mmu_check_mem_range(struct mmu_info *mmu, paddr_t addr) > +{ > + if ((addr >= mmu->mem_start) && (addr < (mmu->mem_start + > mmu->mem_size))) > + return 1; > + > + return 0; > +} > + > +static inline struct mmu_info *mmu_lookup(u32 addr) > +{ > + u32 i; > + > + for (i = 0; i < ARRAY_SIZE(mmu_list); i++) { > + if (mmu_check_mem_range(mmu_list[i], addr)) > + return mmu_list[i]; > + } > + > + return NULL; > +} > + > +static inline u32 mmu_virt_to_phys(u32 reg, u32 va, u32 mask) > +{ > + return (reg & mask) | (va & (~mask)); > +} > + > +static inline u32 mmu_phys_to_virt(u32 reg, u32 pa, u32 mask) > +{ > + return (reg & ~mask) | pa; > +} > + > +static int mmu_mmio_check(struct vcpu *v, paddr_t addr) > +{ > + return mmu_for_each(mmu_check_mem_range, addr); > +} As I understand your cover letter, the device (and therefore the MMU) is only passthrough to a single guest, right? If so, your mmu_mmio_check should check if the domain is handling the device. With your current code any guest can write to this range and rewriting the MMU page table. > + > +static int mmu_copy_pagetable(struct mmu_info *mmu) > +{ > + void __iomem *pagetable = NULL; > + u32 pgaddr; > + > + ASSERT(mmu); > + > + /* read address where kernel MMU pagetable is stored */ > + pgaddr = readl(mmu->mem_map + MMU_TTB); > + pagetable = ioremap(pgaddr, IOPGD_TABLE_SIZE); > + if (!pagetable) { > + printk("%s: %s failed to map pagetable\n", > + __func__, mmu->name); > + return -EINVAL; > + } > + > + /* > + * pagetable can be changed since last time > + * we accessed it therefore we need to copy it each time > + */ > + memcpy(mmu->pagetable, pagetable, IOPGD_TABLE_SIZE); > + > + iounmap(pagetable); > + > + return 0; > +} I'm confused, it should copy from the guest MMU pagetable, right? In this case you should use map_domain_page. ioremap *MUST* only be used with device memory, otherwise memory coherency is not guaranteed. [..] > +static int mmu_mmio_write(struct vcpu *v, mmio_info_t *info) > +{ > + struct domain *dom = v->domain; > + struct mmu_info *mmu = NULL; > + struct cpu_user_regs *regs = guest_cpu_user_regs(); > + register_t *r = select_user_reg(regs, info->dabt.reg); > + int res; > + > + mmu = mmu_lookup(info->gpa); > + if (!mmu) { > + printk("%s: can't get mmu for addr 0x%08x\n", __func__, > (u32)info->gpa); > + return -EINVAL; > + } > + > + /* > + * make sure that user register is written first in this function > + * following calls may expect valid data in it > + */ > + writel(*r, mmu->mem_map + ((u32)(info->gpa) - mmu->mem_start)); Hmmm ... I think this is very confusing, you should only write to the memory if mmu_trap_write_access has not failed. And use "*r" where it's needed. Writing to the device memory could have side effect (for instance updating the page table with the wrong translation...). > + > + res = mmu_trap_write_access(dom, mmu, info); > + if (res) > + return res; > + > + return 1; > +} > + > +static int mmu_init(struct mmu_info *mmu, u32 data) > +{ > + ASSERT(mmu); > + ASSERT(!mmu->mem_map); > + ASSERT(!mmu->pagetable); > + > + mmu->mem_map = ioremap(mmu->mem_start, mmu->mem_size); Can you use ioremap_nocache instead of ioremap? The behavior is the same but the former name is less confusing. -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |