Annotation of qemu/hw/iommu.c, revision 1.1.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.