[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v02 1/7] arm: introduce remoteprocessor iommu module
On Thu, 21 Aug 2014, Andrii Tseglytskyi wrote: > On Wed, Aug 20, 2014 at 10:40 PM, Andrii Tseglytskyi > <andrii.tseglytskyi@xxxxxxxxxxxxxxx> wrote: > > Hi Stefano, > > > > > > On Fri, Jul 4, 2014 at 4:59 PM, Stefano Stabellini > > <stefano.stabellini@xxxxxxxxxxxxx> wrote: > >> On Thu, 26 Jun 2014, Andrii Tseglytskyi wrote: > >>> This is a fisrst patch from patch series which was > >>> developed to handle remote (external) processors > >>> memory management units. Remote processors are > >>> typically used for graphic rendering (GPUs) and > >>> high quality video decoding (IPUs). They are typically > >>> installed on such multimedia SoCs as OMAP4 / OMAP5. > >>> > >>> As soon as remoteprocessor MMU typically works with > >>> pagetables filled by physical addresses, which are > >>> allocated by domU kernel, it is almost impossible to > >>> use them under Xen, intermediate physical addresses > >>> allocated by kernel, need to be translated to machine > >>> addresses. > >>> > >>> This patch introduces a simple framework to perform > >>> pfn -> mfn translation for external MMUs. > >>> It introduces basic data structures and algorithms > >>> needed for translation. > >>> > >>> Typically, when MMU is configured, some it registers > >>> are updated by new values. Introduced frameworks > >>> uses traps as starting point of remoteproc MMUs > >>> pagetables translation. > >>> > >>> Change-Id: Ia4d311a40289df46a003f5ae8706c150bee1885d > >>> Signed-off-by: Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx> > >> > >> There is one problem with this patch: you need to find a way to "pin" > >> the p2m entries for the pfns and mfns found in the pagetables translated > >> by remoteproc_iommu.c. Otherwise Xen might decide to change the pfn to > >> mfn mappings for the domain, breaking the pagetables already translated > >> by remoteproc_iommu.c. pfn to mfn mappings are not guaranteed to be > >> stable. At the moment Xen on ARM wouldn't change pfn to mfn mappings > >> under the guest feet, but features like memory sharing or swapping, > >> supported on x86, could cause it to happen. > >> > >> In the past I tried to introduce a way to "pin the mappings, but never > >> finished to upstream the patches, because it didn't need it anymore. > >> > >> > >> Give a look at: > >> > >> http://marc.info/?l=xen-devel&m=138029864707973 > >> > >> In particular you would need to introduce something like > >> the pin function and call it from mmu_translate_pagetable. > >> > > > > What if I try your series and re-send it if helpful for me? Can you > > link me to its latest code? > > > >> > >> > >>> xen/arch/arm/Makefile | 1 + > >>> xen/arch/arm/remoteproc_iommu.c | 412 > >>> ++++++++++++++++++++++++++++++++++++ > >>> xen/include/xen/remoteproc_iommu.h | 79 +++++++ > >>> 3 files changed, 492 insertions(+) > >>> create mode 100644 xen/arch/arm/remoteproc_iommu.c > >>> create mode 100644 xen/include/xen/remoteproc_iommu.h > >>> > >>> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile > >>> index d70f6d5..0204d1c 100644 > >>> --- a/xen/arch/arm/Makefile > >>> +++ b/xen/arch/arm/Makefile > >>> @@ -15,6 +15,7 @@ obj-y += io.o > >>> obj-y += irq.o > >>> obj-y += kernel.o > >>> obj-y += mm.o > >>> +obj-y += remoteproc_iommu.o > >>> obj-y += p2m.o > >>> obj-y += percpu.o > >>> obj-y += guestcopy.o > >>> diff --git a/xen/arch/arm/remoteproc_iommu.c > >>> b/xen/arch/arm/remoteproc_iommu.c > >>> new file mode 100644 > >>> index 0000000..b4d22d9 > >>> --- /dev/null > >>> +++ b/xen/arch/arm/remoteproc_iommu.c > >>> @@ -0,0 +1,412 @@ > >>> +/* > >>> + * xen/arch/arm/remoteproc_iommu.c > >>> + * > >>> + * Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx> > >>> + * Copyright (c) 2014 GlobalLogic > >>> + * > >>> + * This program is free software; you can redistribute it and/or modify > >>> + * it under the terms of the GNU General Public License as published by > >>> + * the Free Software Foundation; either version 2 of the License, or > >>> + * (at your option) any later version. > >>> + * > >>> + * 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. > >>> + */ > >>> + > >>> +#include <xen/config.h> > >>> +#include <xen/lib.h> > >>> +#include <xen/errno.h> > >>> +#include <xen/mm.h> > >>> +#include <xen/vmap.h> > >>> +#include <xen/init.h> > >>> +#include <xen/sched.h> > >>> +#include <xen/stdbool.h> > >>> +#include <asm/system.h> > >>> +#include <asm/current.h> > >>> +#include <asm/io.h> > >>> +#include <asm/p2m.h> > >>> + > >>> +#include <xen/remoteproc_iommu.h> > >>> + > >>> +#include "io.h" > >>> + > >>> +static struct mmu_info *mmu_list[] = { > >>> +}; > >>> + > >>> +#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); \ > >>> + } \ > >>> + __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; > >>> + > >>> + /* enumerate all registered MMU's and check is address in range */ > >>> + 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 int mmu_mmio_check(struct vcpu *v, paddr_t addr) > >>> +{ > >>> + return mmu_for_each(mmu_check_mem_range, addr); > >>> +} > >>> + > >>> +static int mmu_copy_pagetable(struct mmu_info *mmu, struct mmu_pagetable > >>> *pgt) > >>> +{ > >>> + void __iomem *pagetable = NULL; > >>> + u32 maddr, i; > >>> + > >>> + ASSERT(mmu); > >>> + ASSERT(pgt); > >>> + > >>> + if ( !pgt->paddr ) > >>> + return -EINVAL; > >>> + > >>> + /* pagetable size can be more than one page */ > >>> + for ( i = 0; i < MMU_PGD_TABLE_SIZE(mmu) / PAGE_SIZE; i++ ) > >>> + { > >>> + /* lookup address where remoteproc pagetable is stored by kernel > >>> */ > >>> + maddr = p2m_lookup(current->domain, pgt->paddr + i * PAGE_SIZE, > >>> NULL); > >>> + if ( !maddr ) > >>> + { > >>> + pr_mmu("failed to translate 0x%08lx to maddr", pgt->paddr + > >>> i * PAGE_SIZE); > >>> + return -EINVAL; > >>> + } > >>> + > >>> + pagetable = ioremap_nocache(maddr, MMU_PGD_TABLE_SIZE(mmu)); > >>> + if ( !pagetable ) > >>> + { > >>> + pr_mmu("failed to map pagetable"); > >>> + return -EINVAL; > >>> + } > >>> + > >>> + /* copy pagetable to hypervisor memory */ > >>> + clean_and_invalidate_xen_dcache_va_range(pagetable, PAGE_SIZE); > >>> + memcpy((u32*)((u32)pgt->kern_pagetable + i * PAGE_SIZE), > >>> pagetable, PAGE_SIZE); > >>> + > >>> + iounmap(pagetable); > >>> + } > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +struct mmu_pagetable *mmu_pagetable_lookup(struct mmu_info *mmu, u32 > >>> addr, bool is_maddr) > >>> +{ > >>> + struct mmu_pagetable *pgt; > >>> + u32 pgt_addr; > >>> + > >>> + list_for_each_entry(pgt, &mmu->pagetables_list, link_node) > >>> + { > >>> + if ( is_maddr ) > >>> + pgt_addr = pgt->maddr; > >>> + else > >>> + pgt_addr = pgt->paddr; > >>> + > >>> + if ( pgt_addr == addr ) > >>> + return pgt; > >>> + } > >>> + > >>> + return NULL; > >>> +} > >>> + > >>> +static struct mmu_pagetable *mmu_alloc_pagetable(struct mmu_info *mmu, > >>> u32 paddr) > >>> +{ > >>> + struct mmu_pagetable *pgt; > >>> + u32 pgt_size = MMU_PGD_TABLE_SIZE(mmu); > >>> + > >>> + pgt = xzalloc_bytes(sizeof(struct mmu_pagetable)); > >>> + if ( !pgt ) > >>> + { > >>> + pr_mmu("failed to alloc pagetable structure"); > >>> + return NULL; > >>> + } > >>> + > >>> + /* allocate pagetable managed by hypervisor */ > >>> + pgt->hyp_pagetable = xzalloc_bytes(pgt_size); > >>> + if ( !pgt->hyp_pagetable ) > >>> + { > >>> + pr_mmu("failed to alloc private hyp_pagetable"); > >>> + return NULL; > >>> + } > >>> + > >>> + /* alocate pagetable for ipa storing */ > >>> + pgt->kern_pagetable = xzalloc_bytes(pgt_size); > >>> + if ( !pgt->kern_pagetable ) > >>> + { > >>> + pr_mmu("failed to alloc private kern_pagetable"); > >>> + return NULL; > >>> + } > >>> + > >>> + pr_mmu("private pagetables for 0x%08x paddr %u bytes (main 0x%08x, > >>> temp 0x%08x)", > >>> + paddr, pgt_size, (u32)__pa(pgt->hyp_pagetable), > >>> (u32)__pa(pgt->kern_pagetable)); > >>> + > >>> + pgt->paddr = paddr; > >>> + > >>> + list_add(&pgt->link_node, &mmu->pagetables_list); > >>> + > >>> + return pgt; > >>> +} > >>> + > >>> +static u32 mmu_translate_pagetable(struct mmu_info *mmu, u32 paddr) > >>> +{ > >>> + struct mmu_pagetable *pgt; > >>> + int res; > >>> + > >>> + /* lookup using machine address first */ > >>> + pgt = mmu_pagetable_lookup(mmu, paddr, true); > >>> + if ( !pgt ) > >>> + { > >>> + /* lookup using kernel physical address */ > >>> + pgt = mmu_pagetable_lookup(mmu, paddr, false); > >>> + if ( !pgt ) > >>> + { > >>> + /* if pagetable doesn't exists in lookup list - allocate it > >>> */ > >>> + pgt = mmu_alloc_pagetable(mmu, paddr); > >>> + } > >>> + } > >>> + > >>> + pgt->maddr = MMU_INVALID_ADDRESS; > >>> + > >>> + /* copy pagetable from domain to hypervisor */ > >>> + res = mmu_copy_pagetable(mmu, pgt); > >>> + if ( res ) > >>> + return res; > >>> + > >>> + /* translate pagetable */ > >>> + pgt->maddr = mmu->translate_pfunc(mmu, pgt); > >>> + return pgt->maddr; > >>> +} > >>> + > >>> +static u32 mmu_trap_translate_pagetable(struct mmu_info *mmu, > >>> mmio_info_t *info) > >>> +{ > >>> + register_t *reg; > >>> + bool valid_trap = false; > >>> + u32 i, paddr; > >>> + > >>> + reg = select_user_reg(guest_cpu_user_regs(), info->dabt.reg); > >>> + > >>> + ASSERT(reg); > >>> + > >>> + paddr = *reg; > >>> + if ( !paddr ) > >>> + return MMU_INVALID_ADDRESS; > >>> + > >>> + /* check is the register is a valid TTB register */ > >>> + for ( i = 0; i < mmu->num_traps; i++ ) > >>> + { > >>> + if ( mmu->trap_offsets[i] == (info->gpa - mmu->mem_start) ) > >>> + { > >>> + valid_trap = true; > >>> + break; > >>> + } > >>> + } > >>> + > >>> + if ( !valid_trap ) > >>> + return MMU_INVALID_ADDRESS; > >>> + > >>> + return mmu_translate_pagetable(mmu, paddr); > >>> +} > >>> + > >>> +u32 mmu_translate_second_level(struct mmu_info *mmu, struct > >>> mmu_pagetable *pgt, > >>> + u32 maddr, u32 hyp_addr) > >> > >> Is this actually used anywhere? > >> > >> > >>> +{ > >>> + u32 *pte_table = NULL, *hyp_pte_table = NULL, pte_table_size = > >>> PAGE_SIZE; > >>> + u32 i; > >>> + > >>> + /* remap second level translation table */ > >>> + pte_table = ioremap_nocache(maddr, MMU_PTE_TABLE_SIZE(mmu)); > >>> + if ( !pte_table ) > >>> + { > >>> + pr_mmu("failed to map pte_table"); > >>> + return MMU_INVALID_ADDRESS; > >>> + } > >>> + > >>> + /* allocate new second level pagetable once */ > >>> + if ( 0 == hyp_addr ) > >>> + { > >>> + if ( MMU_PTE_TABLE_SIZE(mmu) > PAGE_SIZE ) > >>> + pte_table_size = MMU_PTE_TABLE_SIZE(mmu); > >>> + > >>> + hyp_pte_table = xzalloc_bytes(pte_table_size); > >>> + if ( !hyp_pte_table ) > >>> + { > >>> + pr_mmu("failed to alloc new iopt"); > >>> + return MMU_INVALID_ADDRESS; > >>> + } > >>> + } > >>> + else > >>> + { > >>> + hyp_pte_table = __va(hyp_addr & > >>> MMU_SECTION_MASK(mmu->pg_data->pte_shift)); > >>> + } > >>> + > >>> + /* 2-nd level translation */ > >>> + for ( i = 0; i < MMU_PTRS_PER_PTE(mmu); i++ ) > >>> + { > >>> + paddr_t pt_maddr, pt_paddr, pt_flags; > >>> + u32 pt_mask = MMU_SECTION_MASK(mmu->pg_data->pte_shift); > >>> + > >>> + if ( !pte_table[i] ) > >>> + { > >>> + /* handle the case when page was removed */ > >>> + if ( unlikely(hyp_pte_table[i]) ) > >>> + { > >>> + hyp_pte_table[i] = 0; > >>> + } > >>> + > >>> + continue; > >>> + } > >>> + > >>> + pt_paddr = pte_table[i] & pt_mask; > >>> + pt_flags = pte_table[i] & ~pt_mask; > >>> + pt_maddr = p2m_lookup(current->domain, pt_paddr, NULL); > >>> + ASSERT(pt_maddr != INVALID_PADDR); > >>> + > >>> + hyp_pte_table[i] = pt_maddr | pt_flags; > >>> + pgt->page_counter++; > >>> + } > >>> + > >>> + iounmap(pte_table); > >>> + > >>> + clean_and_invalidate_xen_dcache_va_range(hyp_pte_table, > >>> MMU_PTE_TABLE_SIZE(mmu)); > >>> + return __pa(hyp_pte_table); > >>> +} > >>> + > >>> +static int mmu_mmio_read(struct vcpu *v, mmio_info_t *info) > >>> +{ > >>> + struct mmu_info *mmu = NULL; > >>> + unsigned long flags; > >>> + register_t *r; > >>> + > >>> + r = select_user_reg(guest_cpu_user_regs(), info->dabt.reg); > >>> + > >>> + ASSERT(r); > >> > >> If you check on the domid in mmu_mmio_write, I would check here too > >> > >> > >>> + mmu = mmu_lookup(info->gpa); > >>> + if ( !mmu ) > >>> + { > >>> + pr_mmu("can't get mmu for addr 0x%08x", (u32)info->gpa); > >>> + return -EINVAL; > >>> + } > >>> + > >>> + spin_lock_irqsave(&mmu->lock, flags); > >>> + *r = readl(mmu->mem_map + ((u32)(info->gpa) - mmu->mem_start)); > >>> + spin_unlock_irqrestore(&mmu->lock, flags); > >>> + > >>> + return 1; > >> > >> It looks like you are returning the mfns here, is that correct? > >> > >> > >> > >>> +static int mmu_mmio_write(struct vcpu *v, mmio_info_t *info) > >>> +{ > >>> + struct mmu_info *mmu = NULL; > >>> + unsigned long flags; > >>> + register_t *r; > >>> + u32 new_addr, val; > >>> + > >>> + r = select_user_reg(guest_cpu_user_regs(), info->dabt.reg); > >>> + > >>> + ASSERT(r); > >>> + > >>> + /* dom0 should not access remoteproc MMU */ > >>> + if ( 0 == current->domain->domain_id ) > >>> + return 1; > >> > >> This is too specific to one particular configuration. > >> Would it be possible to generalize this somehow? At the very least you > >> could introduce an XSM label to access the pagetables, so that you can > >> dynamically configure the domains the can write to them. > >> > > > > I succeeded to enable XSM on our platform and enforce FLASK on boot, > > but I still have some questions: > > - What is this new XSM label ? Do you mean > > *seclabel='system_u:system_r:domU_t'* and change value of seclabel to > > something specific? > > As described in > > http://wiki.xen.org/wiki/Xen_Security_Modules_:_XSM-FLASK#Creating_domains_with_XSM_security_labels > > > > - Do I need to introduce a new policy for this? As far as I understand > > from previous link - it is obligatory for FLASK, therefore it is > > obligatory for XSM. In other words - all XSM related checks, which I > > may introduce won't work correctly without installing a policy, am I > > right ? > > > > Well. Looks like answer is 'yes'. I tried to play with XSM policy and > see how it works. Will try to introduce a new label for domain which > can access remoteprocessor MMU Yep, that's right. That is going to make your code much more flexible too. > > Regards, > > Andrii > > > >> > >>> + /* find corresponding MMU */ > >>> + mmu = mmu_lookup(info->gpa); > >>> + if ( !mmu ) > >>> + { > >>> + pr_mmu("can't get mmu for addr 0x%08x", (u32)info->gpa); > >>> + return -EINVAL; > >>> + } > >>> + > >>> + ASSERT(v->domain == current->domain); > >> > >> You can remove this assert. > >> > >> > >>> + spin_lock_irqsave(&mmu->lock, flags); > >>> + > >>> + /* get new address of translated pagetable */ > >>> + new_addr = mmu_trap_translate_pagetable(mmu, info); > >>> + if ( MMU_INVALID_ADDRESS != new_addr ) > >>> + val = new_addr; > >>> + else > >>> + val = *r; > >>> + > >>> + writel(val, mmu->mem_map + ((u32)(info->gpa) - mmu->mem_start)); > >>> + spin_unlock_irqrestore(&mmu->lock, flags); > >>> + > >>> + return 1; > >>> +} > >>> + > >>> +static int mmu_init(struct mmu_info *mmu, u32 data) > >>> +{ > >>> + ASSERT(mmu); > >>> + ASSERT(!mmu->mem_map); > >>> + > >>> + INIT_LIST_HEAD(&mmu->pagetables_list); > >>> + > >>> + /* map MMU memory */ > >>> + mmu->mem_map = ioremap_nocache(mmu->mem_start, mmu->mem_size); > >>> + if ( !mmu->mem_map ) > >>> + { > >>> + pr_mmu("failed to map memory"); > >>> + return -EINVAL; > >>> + } > >>> + > >>> + pr_mmu("memory map = 0x%pS", _p(mmu->mem_map)); > >>> + > >>> + spin_lock_init(&mmu->lock); > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +static int mmu_init_all(void) > >>> +{ > >>> + int res; > >>> + > >>> + res = mmu_for_each(mmu_init, 0); > >>> + if ( res ) > >>> + { > >>> + printk("%s error during init %d\n", __func__, res); > >>> + return res; > >>> + } > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +const struct mmio_handler remoteproc_mmio_handler = { > >>> + .check_handler = mmu_mmio_check, > >>> + .read_handler = mmu_mmio_read, > >>> + .write_handler = mmu_mmio_write, > >>> +}; > >>> + > >>> +__initcall(mmu_init_all); > >>> + > >>> +/* > >>> + * Local variables: > >>> + * mode: C > >>> + * c-file-style: "BSD" > >>> + * c-basic-offset: 4 > >>> + * indent-tabs-mode: nil > >>> + * End: > >>> + */ > >>> diff --git a/xen/include/xen/remoteproc_iommu.h > >>> b/xen/include/xen/remoteproc_iommu.h > >>> new file mode 100644 > >>> index 0000000..22e2951 > >>> --- /dev/null > >>> +++ b/xen/include/xen/remoteproc_iommu.h > >>> @@ -0,0 +1,79 @@ > >>> +/* > >>> + * xen/include/xen/remoteproc_iommu.h > >>> + * > >>> + * Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx> > >>> + * Copyright (c) 2014 GlobalLogic > >>> + * > >>> + * This program is free software; you can redistribute it and/or modify > >>> + * it under the terms of the GNU General Public License as published by > >>> + * the Free Software Foundation; either version 2 of the License, or > >>> + * (at your option) any later version. > >>> + * > >>> + * 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. > >>> + */ > >>> + > >>> +#ifndef _REMOTEPROC_IOMMU_H_ > >>> +#define _REMOTEPROC_IOMMU_H_ > >>> + > >>> +#include <asm/types.h> > >>> + > >>> +#define MMU_SECTION_SIZE(shift) (1UL << (shift)) > >>> +#define MMU_SECTION_MASK(shift) (~(MMU_SECTION_SIZE(shift) - 1)) > >>> + > >>> +/* 4096 first level descriptors for "supersection" and "section" */ > >>> +#define MMU_PTRS_PER_PGD(mmu) (1UL << (32 - > >>> (mmu->pg_data->pgd_shift))) > >>> +#define MMU_PGD_TABLE_SIZE(mmu) (MMU_PTRS_PER_PGD(mmu) * sizeof(u32)) > >>> + > >>> +/* 256 second level descriptors for "small" and "large" pages */ > >>> +#define MMU_PTRS_PER_PTE(mmu) (1UL << ((mmu->pg_data->pgd_shift) - > >>> (mmu->pg_data->pte_shift))) > >>> +#define MMU_PTE_TABLE_SIZE(mmu) (MMU_PTRS_PER_PTE(mmu) * sizeof(u32)) > >>> + > >>> +/* 16 sections in supersection */ > >>> +#define MMU_SECTION_PER_SUPER(mmu) (1UL << ((mmu->pg_data->super_shift) > >>> - (mmu->pg_data->section_shift))) > >>> + > >>> +#define MMU_INVALID_ADDRESS ((u32)(-1)) > >>> + > >>> +#define pr_mmu(fmt, ...) \ > >>> + printk("%s: %s: "fmt"\n", __func__, ((mmu) ? (mmu)->name : ""), > >>> ##__VA_ARGS__) > >>> + > >>> +struct pagetable_data { > >>> + /* 1st level translation */ > >>> + u32 pgd_shift; > >>> + u32 pte_shift; > >>> + u32 super_shift; > >>> + u32 section_shift; > >>> + /* 2nd level translation */ > >>> + u32 pte_large_shift; > >>> +}; > >>> + > >>> +struct mmu_pagetable { > >>> + u32 *hyp_pagetable; > >>> + u32 *kern_pagetable; > >>> + u32 paddr; > >>> + u32 maddr; > >>> + struct list_head link_node; > >>> + u32 page_counter; > >>> +}; > >>> + > >>> +struct mmu_info { > >>> + const char *name; > >>> + const struct pagetable_data *pg_data; > >>> + /* register where phys pointer to pagetable is stored */ > >>> + u32 *trap_offsets; > >>> + paddr_t mem_start; > >>> + u32 mem_size; > >>> + spinlock_t lock; > >>> + struct list_head pagetables_list; > >>> + u32 num_traps; > >>> + void __iomem *mem_map; > >>> + u32 (*translate_pfunc)(struct mmu_info *, struct mmu_pagetable > >>> *); > >>> + void (*print_pagetable_pfunc)(struct mmu_info *); > >>> +}; > >>> + > >>> +u32 mmu_translate_second_level(struct mmu_info *mmu, struct > >>> mmu_pagetable *pgt, > >>> + u32 maddr, u32 hyp_addr); > >>> + > >>> +#endif /* _REMOTEPROC_IOMMU_H_ */ > >>> -- > >>> 1.7.9.5 > >>> > >>> > >>> _______________________________________________ > >>> Xen-devel mailing list > >>> Xen-devel@xxxxxxxxxxxxx > >>> http://lists.xen.org/xen-devel > >>> > > > > > > > > -- > > > > Andrii Tseglytskyi | Embedded Dev > > GlobalLogic > > www.globallogic.com > > > > -- > > Andrii Tseglytskyi | Embedded Dev > GlobalLogic > www.globallogic.com > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |