⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm_gic.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
        }    } else if (offset < 0xfe0) {        goto bad_reg;    } else /* offset >= 0xfe0 */ {        if (offset & 3) {            res = 0;        } else {            res = gic_id[(offset - 0xfe0) >> 2];        }    }    return res;bad_reg:    cpu_abort (cpu_single_env, "gic_dist_readb: Bad offset %x\n", offset);    return 0;}static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset){    uint32_t val;    val = gic_dist_readb(opaque, offset);    val |= gic_dist_readb(opaque, offset + 1) << 8;    return val;}static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset){    uint32_t val;    val = gic_dist_readw(opaque, offset);    val |= gic_dist_readw(opaque, offset + 2) << 16;    return val;}static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,                            uint32_t value){    gic_state *s = (gic_state *)opaque;    int irq;    int i;    offset -= s->base + 0x1000;    if (offset < 0x100) {        if (offset == 0) {            s->enabled = (value & 1);            DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");        } else if (offset < 4) {            /* ignored.  */        } else {            goto bad_reg;        }    } else if (offset < 0x180) {        /* Interrupt Set Enable.  */        irq = (offset - 0x100) * 8;        if (irq >= GIC_NIRQ)            goto bad_reg;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                if (!GIC_TEST_ENABLED(irq + i))                    DPRINTF("Enabled IRQ %d\n", irq + i);                GIC_SET_ENABLED(irq + i);                /* If a raised level triggered IRQ enabled then mark                   is as pending.  */                if (GIC_TEST_LEVEL(irq + i) && !GIC_TEST_TRIGGER(irq + i))                    GIC_SET_PENDING(irq + i);            }        }    } else if (offset < 0x200) {        /* Interrupt Clear Enable.  */        irq = (offset - 0x180) * 8;        if (irq >= GIC_NIRQ)            goto bad_reg;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                if (GIC_TEST_ENABLED(irq + i))                    DPRINTF("Disabled IRQ %d\n", irq + i);                GIC_CLEAR_ENABLED(irq + i);            }        }    } else if (offset < 0x280) {        /* Interrupt Set Pending.  */        irq = (offset - 0x200) * 8;        if (irq >= GIC_NIRQ)            goto bad_reg;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                GIC_SET_PENDING(irq + i);            }        }    } else if (offset < 0x300) {        /* Interrupt Clear Pending.  */        irq = (offset - 0x280) * 8;        if (irq >= GIC_NIRQ)            goto bad_reg;        for (i = 0; i < 8; i++) {            if (value & (1 << i)) {                GIC_CLEAR_PENDING(irq + i);            }        }    } else if (offset < 0x400) {        /* Interrupt Active.  */        goto bad_reg;    } else if (offset < 0x800) {        /* Interrupt Priority.  */        irq = offset - 0x400;        if (irq >= GIC_NIRQ)            goto bad_reg;        s->priority[irq] = value;    } else if (offset < 0xc00) {        /* Interrupt CPU Target.  */        irq = offset - 0x800;        if (irq >= GIC_NIRQ)            goto bad_reg;        s->irq_target[irq] = value;    } else if (offset < 0xf00) {        /* Interrupt Configuration.  */        irq = (offset - 0xc00) * 4;        if (irq >= GIC_NIRQ)            goto bad_reg;        for (i = 0; i < 4; i++) {            if (value & (1 << (i * 2))) {                GIC_SET_MODEL(irq + i);            } else {                GIC_CLEAR_MODEL(irq + i);            }            if (value & (2 << (i * 2))) {                GIC_SET_TRIGGER(irq + i);            } else {                GIC_CLEAR_TRIGGER(irq + i);            }        }    } else {        /* 0xf00 is only handled for word writes.  */        goto bad_reg;    }    gic_update(s);    return;bad_reg:    cpu_abort (cpu_single_env, "gic_dist_writeb: Bad offset %x\n", offset);}static void gic_dist_writew(void *opaque, target_phys_addr_t offset,                            uint32_t value){    gic_state *s = (gic_state *)opaque;    if (offset - s->base == 0xf00) {        GIC_SET_PENDING(value & 0x3ff);        gic_update(s);        return;    }    gic_dist_writeb(opaque, offset, value & 0xff);    gic_dist_writeb(opaque, offset + 1, value >> 8);}static void gic_dist_writel(void *opaque, target_phys_addr_t offset,                            uint32_t value){    gic_dist_writew(opaque, offset, value & 0xffff);    gic_dist_writew(opaque, offset + 2, value >> 16);}static CPUReadMemoryFunc *gic_dist_readfn[] = {   gic_dist_readb,   gic_dist_readw,   gic_dist_readl};static CPUWriteMemoryFunc *gic_dist_writefn[] = {   gic_dist_writeb,   gic_dist_writew,   gic_dist_writel};static uint32_t gic_cpu_read(void *opaque, target_phys_addr_t offset){    gic_state *s = (gic_state *)opaque;    offset -= s->base;    switch (offset) {    case 0x00: /* Control */        return s->cpu_enabled;    case 0x04: /* Priority mask */        return s->priority_mask;    case 0x08: /* Binary Point */        /* ??? Not implemented.  */        return 0;    case 0x0c: /* Acknowledge */        return gic_acknowledge_irq(s);    case 0x14: /* Runing Priority */        return s->running_priority;    case 0x18: /* Highest Pending Interrupt */        return s->current_pending;    default:        cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);        return 0;    }}static void gic_cpu_write(void *opaque, target_phys_addr_t offset,                          uint32_t value){    gic_state *s = (gic_state *)opaque;    offset -= s->base;    switch (offset) {    case 0x00: /* Control */        s->cpu_enabled = (value & 1);        DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");        break;    case 0x04: /* Priority mask */        s->priority_mask = (value & 0x3ff);        break;    case 0x08: /* Binary Point */        /* ??? Not implemented.  */        break;    case 0x10: /* End Of Interrupt */        return gic_complete_irq(s, value & 0x3ff);    default:        cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);        return;    }    gic_update(s);}static CPUReadMemoryFunc *gic_cpu_readfn[] = {   gic_cpu_read,   gic_cpu_read,   gic_cpu_read};static CPUWriteMemoryFunc *gic_cpu_writefn[] = {   gic_cpu_write,   gic_cpu_write,   gic_cpu_write};static void gic_reset(gic_state *s){    int i;    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));    s->priority_mask = 0xf0;    s->current_pending = 1023;    s->running_irq = 1023;    s->running_priority = 0x100;    for (i = 0; i < 15; i++) {        GIC_SET_ENABLED(i);        GIC_SET_TRIGGER(i);    }    s->enabled = 0;    s->cpu_enabled = 0;}void *arm_gic_init(uint32_t base, void *parent, int parent_irq){    gic_state *s;    int iomemtype;    s = (gic_state *)qemu_mallocz(sizeof(gic_state));    if (!s)        return NULL;    s->handler = gic_set_irq;    s->parent = parent;    s->parent_irq = parent_irq;    if (base != 0xffffffff) {        iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,                                           gic_cpu_writefn, s);        cpu_register_physical_memory(base, 0x00000fff, iomemtype);        iomemtype = cpu_register_io_memory(0, gic_dist_readfn,                                           gic_dist_writefn, s);        cpu_register_physical_memory(base + 0x1000, 0x00000fff, iomemtype);        s->base = base;    } else {        s->base = 0;    }    gic_reset(s);    return s;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -