Annotation of qemu/roms/openbios/drivers/iommu.c, revision 1.1

1.1     ! root        1: /**
        !             2:  ** Proll (PROM replacement)
        !             3:  ** iommu.c: Functions for DVMA management.
        !             4:  ** Copyright 1999 Pete Zaitcev
        !             5:  ** This code is licensed under GNU General Public License.
        !             6:  **/
        !             7: #include "config.h"
        !             8: #include "libopenbios/bindings.h"
        !             9: #include "drivers/drivers.h"
        !            10: #include "iommu.h"
        !            11: #include "libopenbios/ofmem.h"
        !            12: 
        !            13: #ifdef CONFIG_DEBUG_IOMMU
        !            14: #define DPRINTF(fmt, args...)                   \
        !            15:     do { printk(fmt , ##args); } while (0)
        !            16: #else
        !            17: #define DPRINTF(fmt, args...)
        !            18: #endif
        !            19: 
        !            20: /*
        !            21:  * IOMMU parameters
        !            22:  */
        !            23: struct iommu {
        !            24:     struct iommu_regs *regs;
        !            25:     unsigned int *page_table;
        !            26:     unsigned long plow;     /* Base bus address */
        !            27: };
        !            28: 
        !            29: static struct iommu ciommu;
        !            30: 
        !            31: static void
        !            32: iommu_invalidate(struct iommu_regs *iregs)
        !            33: {
        !            34:     iregs->tlbflush = 0;
        !            35: }
        !            36: 
        !            37: /*
        !            38:  * XXX This is a problematic interface. We alloc _memory_ which is uncached.
        !            39:  * So if we ever reuse allocations somebody is going to get uncached pages.
        !            40:  * Returned address is always aligned by page.
        !            41:  * BTW, we were not going to give away anonymous storage, were we not?
        !            42:  */
        !            43: void *
        !            44: dvma_alloc(int size, unsigned int *pphys)
        !            45: {
        !            46:     void *va;
        !            47:     unsigned int pa, ba;
        !            48:     unsigned int npages;
        !            49:     unsigned int mva, mpa;
        !            50:     unsigned int i;
        !            51:     unsigned int *iopte;
        !            52:     struct iommu *t = &ciommu;
        !            53:     int ret;
        !            54: 
        !            55:     npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE;
        !            56:     ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE);
        !            57:     if (ret != 0)
        !            58:         return NULL;
        !            59: 
        !            60:     ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE);
        !            61:     if (ba == 0)
        !            62:         return NULL;
        !            63: 
        !            64:     pa = (unsigned int)va2pa((unsigned long)va);
        !            65: 
        !            66:     /*
        !            67:      * Change page attributes in MMU to uncached.
        !            68:      */
        !            69:     mva = (unsigned int) va;
        !            70:     mpa = (unsigned int) pa;
        !            71:     ofmem_arch_early_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa));
        !            72: 
        !            73:     /*
        !            74:      * Map into IOMMU page table.
        !            75:      */
        !            76:     mpa = (unsigned int) pa;
        !            77:     iopte = &t->page_table[(ba - t->plow) / PAGE_SIZE];
        !            78:     for (i = 0; i < npages; i++) {
        !            79:         *iopte++ = MKIOPTE(mpa);
        !            80:         mpa += PAGE_SIZE;
        !            81:     }
        !            82: 
        !            83:     *pphys = ba;
        !            84: 
        !            85:     return va;
        !            86: }
        !            87: 
        !            88: /*
        !            89:  * Initialize IOMMU
        !            90:  * This looks like initialization of CPU MMU but
        !            91:  * the routine is higher in food chain.
        !            92:  */
        !            93: static struct iommu_regs *
        !            94: iommu_init(struct iommu *t, uint64_t base)
        !            95: {
        !            96:     unsigned int *ptab;
        !            97:     int ptsize;
        !            98: #ifdef CONFIG_DEBUG_IOMMU
        !            99:     unsigned int impl, vers;
        !           100: #endif
        !           101:     unsigned int tmp;
        !           102:     struct iommu_regs *regs;
        !           103:     int ret;
        !           104:     unsigned long vasize;
        !           105: 
        !           106:     regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS);
        !           107:     if (regs == NULL) {
        !           108:         DPRINTF("Cannot map IOMMU\n");
        !           109:         for (;;) { }
        !           110:     }
        !           111:     t->regs = regs;
        !           112: #ifdef CONFIG_DEBUG_IOMMU
        !           113:     impl = (regs->control & IOMMU_CTRL_IMPL) >> 28;
        !           114:     vers = (regs->control & IOMMU_CTRL_VERS) >> 24;
        !           115: #endif
        !           116: 
        !           117:     tmp = regs->control;
        !           118:     tmp &= ~(IOMMU_CTRL_RNGE);
        !           119: 
        !           120:     tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB);
        !           121:     t->plow = 0xfe000000;              /* End - 32 MB */
        !           122:     /* Size of VA region that we manage */
        !           123:     vasize = 0x2000000; /* 32 MB */
        !           124: 
        !           125:     regs->control = tmp;
        !           126:     iommu_invalidate(regs);
        !           127: 
        !           128:     /* Allocate IOMMU page table */
        !           129:     /* Tremendous alignment causes great waste... */
        !           130:     ptsize = (vasize / PAGE_SIZE) * sizeof(int);
        !           131:     ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize);
        !           132:     if (ret != 0) {
        !           133:         DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize);
        !           134:         for (;;) { }
        !           135:     }
        !           136:     t->page_table = ptab;
        !           137: 
        !           138:     /* flush_cache_all(); */
        !           139:     /** flush_tlb_all(); **/
        !           140:     tmp = (unsigned int)va2pa((unsigned long)ptab);
        !           141:     regs->base = tmp >> 4;
        !           142:     iommu_invalidate(regs);
        !           143: 
        !           144:     DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n",
        !           145:             impl, vers, t->page_table, tmp, ptsize);
        !           146: 
        !           147:     mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000);
        !           148:     return regs;
        !           149: }
        !           150: 
        !           151: void
        !           152: ob_init_iommu(uint64_t base)
        !           153: {
        !           154:     struct iommu_regs *regs;
        !           155: 
        !           156:     regs = iommu_init(&ciommu, base);
        !           157: 
        !           158:     push_str("/iommu");
        !           159:     fword("find-device");
        !           160:     PUSH((unsigned long)regs);
        !           161:     fword("encode-int");
        !           162:     push_str("address");
        !           163:     fword("property");
        !           164: 
        !           165:     PUSH(base >> 32);
        !           166:     fword("encode-int");
        !           167:     PUSH(base & 0xffffffff);
        !           168:     fword("encode-int");
        !           169:     fword("encode+");
        !           170:     PUSH(IOMMU_REGS);
        !           171:     fword("encode-int");
        !           172:     fword("encode+");
        !           173:     push_str("reg");
        !           174:     fword("property");
        !           175: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.