Annotation of qemu/hw/iommu.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU SPARC iommu emulation
        !             3:  *
        !             4:  * Copyright (c) 2003-2005 Fabrice Bellard
        !             5:  * 
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: #include "vl.h"
        !            25: 
        !            26: /* debug iommu */
        !            27: //#define DEBUG_IOMMU
        !            28: 
        !            29: #ifdef DEBUG_IOMMU
        !            30: #define DPRINTF(fmt, args...) \
        !            31: do { printf("IOMMU: " fmt , ##args); } while (0)
        !            32: #else
        !            33: #define DPRINTF(fmt, args...)
        !            34: #endif
        !            35: 
        !            36: #define IOMMU_NREGS (3*4096)
        !            37: #define IOMMU_CTRL_IMPL     0xf0000000 /* Implementation */
        !            38: #define IOMMU_CTRL_VERS     0x0f000000 /* Version */
        !            39: #define IOMMU_CTRL_RNGE     0x0000001c /* Mapping RANGE */
        !            40: #define IOMMU_RNGE_16MB     0x00000000 /* 0xff000000 -> 0xffffffff */
        !            41: #define IOMMU_RNGE_32MB     0x00000004 /* 0xfe000000 -> 0xffffffff */
        !            42: #define IOMMU_RNGE_64MB     0x00000008 /* 0xfc000000 -> 0xffffffff */
        !            43: #define IOMMU_RNGE_128MB    0x0000000c /* 0xf8000000 -> 0xffffffff */
        !            44: #define IOMMU_RNGE_256MB    0x00000010 /* 0xf0000000 -> 0xffffffff */
        !            45: #define IOMMU_RNGE_512MB    0x00000014 /* 0xe0000000 -> 0xffffffff */
        !            46: #define IOMMU_RNGE_1GB      0x00000018 /* 0xc0000000 -> 0xffffffff */
        !            47: #define IOMMU_RNGE_2GB      0x0000001c /* 0x80000000 -> 0xffffffff */
        !            48: #define IOMMU_CTRL_ENAB     0x00000001 /* IOMMU Enable */
        !            49: 
        !            50: /* The format of an iopte in the page tables */
        !            51: #define IOPTE_PAGE          0x07ffff00 /* Physical page number (PA[30:12]) */
        !            52: #define IOPTE_CACHE         0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
        !            53: #define IOPTE_WRITE         0x00000004 /* Writeable */
        !            54: #define IOPTE_VALID         0x00000002 /* IOPTE is valid */
        !            55: #define IOPTE_WAZ           0x00000001 /* Write as zeros */
        !            56: 
        !            57: #define PAGE_SHIFT      12
        !            58: #define PAGE_SIZE       (1 << PAGE_SHIFT)
        !            59: #define PAGE_MASK      (PAGE_SIZE - 1)
        !            60: 
        !            61: typedef struct IOMMUState {
        !            62:     uint32_t addr;
        !            63:     uint32_t regs[IOMMU_NREGS];
        !            64:     uint32_t iostart;
        !            65: } IOMMUState;
        !            66: 
        !            67: static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
        !            68: {
        !            69:     IOMMUState *s = opaque;
        !            70:     uint32_t saddr;
        !            71: 
        !            72:     saddr = (addr - s->addr) >> 2;
        !            73:     switch (saddr) {
        !            74:     default:
        !            75:        DPRINTF("read reg[%d] = %x\n", saddr, s->regs[saddr]);
        !            76:        return s->regs[saddr];
        !            77:        break;
        !            78:     }
        !            79:     return 0;
        !            80: }
        !            81: 
        !            82: static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
        !            83: {
        !            84:     IOMMUState *s = opaque;
        !            85:     uint32_t saddr;
        !            86: 
        !            87:     saddr = (addr - s->addr) >> 2;
        !            88:     DPRINTF("write reg[%d] = %x\n", saddr, val);
        !            89:     switch (saddr) {
        !            90:     case 0:
        !            91:        switch (val & IOMMU_CTRL_RNGE) {
        !            92:        case IOMMU_RNGE_16MB:
        !            93:            s->iostart = 0xff000000;
        !            94:            break;
        !            95:        case IOMMU_RNGE_32MB:
        !            96:            s->iostart = 0xfe000000;
        !            97:            break;
        !            98:        case IOMMU_RNGE_64MB:
        !            99:            s->iostart = 0xfc000000;
        !           100:            break;
        !           101:        case IOMMU_RNGE_128MB:
        !           102:            s->iostart = 0xf8000000;
        !           103:            break;
        !           104:        case IOMMU_RNGE_256MB:
        !           105:            s->iostart = 0xf0000000;
        !           106:            break;
        !           107:        case IOMMU_RNGE_512MB:
        !           108:            s->iostart = 0xe0000000;
        !           109:            break;
        !           110:        case IOMMU_RNGE_1GB:
        !           111:            s->iostart = 0xc0000000;
        !           112:            break;
        !           113:        default:
        !           114:        case IOMMU_RNGE_2GB:
        !           115:            s->iostart = 0x80000000;
        !           116:            break;
        !           117:        }
        !           118:        DPRINTF("iostart = %x\n", s->iostart);
        !           119:        /* Fall through */
        !           120:     default:
        !           121:        s->regs[saddr] = val;
        !           122:        break;
        !           123:     }
        !           124: }
        !           125: 
        !           126: static CPUReadMemoryFunc *iommu_mem_read[3] = {
        !           127:     iommu_mem_readw,
        !           128:     iommu_mem_readw,
        !           129:     iommu_mem_readw,
        !           130: };
        !           131: 
        !           132: static CPUWriteMemoryFunc *iommu_mem_write[3] = {
        !           133:     iommu_mem_writew,
        !           134:     iommu_mem_writew,
        !           135:     iommu_mem_writew,
        !           136: };
        !           137: 
        !           138: uint32_t iommu_translate_local(void *opaque, uint32_t addr)
        !           139: {
        !           140:     IOMMUState *s = opaque;
        !           141:     uint32_t iopte, pa, tmppte;
        !           142: 
        !           143:     iopte = s->regs[1] << 4;
        !           144:     addr &= ~s->iostart;
        !           145:     iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
        !           146:     cpu_physical_memory_read(iopte, (void *) &pa, 4);
        !           147:     bswap32s(&pa);
        !           148:     tmppte = pa;
        !           149:     pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
        !           150:     DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte);
        !           151:     return pa;
        !           152: }
        !           153: 
        !           154: static void iommu_save(QEMUFile *f, void *opaque)
        !           155: {
        !           156:     IOMMUState *s = opaque;
        !           157:     int i;
        !           158:     
        !           159:     qemu_put_be32s(f, &s->addr);
        !           160:     for (i = 0; i < IOMMU_NREGS; i++)
        !           161:        qemu_put_be32s(f, &s->regs[i]);
        !           162:     qemu_put_be32s(f, &s->iostart);
        !           163: }
        !           164: 
        !           165: static int iommu_load(QEMUFile *f, void *opaque, int version_id)
        !           166: {
        !           167:     IOMMUState *s = opaque;
        !           168:     int i;
        !           169:     
        !           170:     if (version_id != 1)
        !           171:         return -EINVAL;
        !           172: 
        !           173:     qemu_get_be32s(f, &s->addr);
        !           174:     for (i = 0; i < IOMMU_NREGS; i++)
        !           175:        qemu_put_be32s(f, &s->regs[i]);
        !           176:     qemu_get_be32s(f, &s->iostart);
        !           177: 
        !           178:     return 0;
        !           179: }
        !           180: 
        !           181: static void iommu_reset(void *opaque)
        !           182: {
        !           183:     IOMMUState *s = opaque;
        !           184: 
        !           185:     memset(s->regs, 0, IOMMU_NREGS * 4);
        !           186:     s->iostart = 0;
        !           187: }
        !           188: 
        !           189: void *iommu_init(uint32_t addr)
        !           190: {
        !           191:     IOMMUState *s;
        !           192:     int iommu_io_memory;
        !           193: 
        !           194:     s = qemu_mallocz(sizeof(IOMMUState));
        !           195:     if (!s)
        !           196:         return NULL;
        !           197: 
        !           198:     s->addr = addr;
        !           199: 
        !           200:     iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
        !           201:     cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory);
        !           202:     
        !           203:     register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
        !           204:     qemu_register_reset(iommu_reset, s);
        !           205:     return s;
        !           206: }
        !           207: 

unix.superglobalmegacorp.com

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