[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 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

> 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.