1ff8f06eeSShlomo Pongratz /* 2ff8f06eeSShlomo Pongratz * ARM GICv3 support - common bits of emulated and KVM kernel model 3ff8f06eeSShlomo Pongratz * 4ff8f06eeSShlomo Pongratz * Copyright (c) 2012 Linaro Limited 5ff8f06eeSShlomo Pongratz * Copyright (c) 2015 Huawei. 6ff8f06eeSShlomo Pongratz * Written by Peter Maydell 7ff8f06eeSShlomo Pongratz * Extended to 64 cores by Shlomo Pongratz 8ff8f06eeSShlomo Pongratz * 9ff8f06eeSShlomo Pongratz * This program is free software; you can redistribute it and/or modify 10ff8f06eeSShlomo Pongratz * it under the terms of the GNU General Public License as published by 11ff8f06eeSShlomo Pongratz * the Free Software Foundation, either version 2 of the License, or 12ff8f06eeSShlomo Pongratz * (at your option) any later version. 13ff8f06eeSShlomo Pongratz * 14ff8f06eeSShlomo Pongratz * This program is distributed in the hope that it will be useful, 15ff8f06eeSShlomo Pongratz * but WITHOUT ANY WARRANTY; without even the implied warranty of 16ff8f06eeSShlomo Pongratz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17ff8f06eeSShlomo Pongratz * GNU General Public License for more details. 18ff8f06eeSShlomo Pongratz * 19ff8f06eeSShlomo Pongratz * You should have received a copy of the GNU General Public License along 20ff8f06eeSShlomo Pongratz * with this program; if not, see <http://www.gnu.org/licenses/>. 21ff8f06eeSShlomo Pongratz */ 22ff8f06eeSShlomo Pongratz 23*8ef94f0bSPeter Maydell #include "qemu/osdep.h" 24ff8f06eeSShlomo Pongratz #include "hw/intc/arm_gicv3_common.h" 25ff8f06eeSShlomo Pongratz 26ff8f06eeSShlomo Pongratz static void gicv3_pre_save(void *opaque) 27ff8f06eeSShlomo Pongratz { 28ff8f06eeSShlomo Pongratz GICv3State *s = (GICv3State *)opaque; 29ff8f06eeSShlomo Pongratz ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s); 30ff8f06eeSShlomo Pongratz 31ff8f06eeSShlomo Pongratz if (c->pre_save) { 32ff8f06eeSShlomo Pongratz c->pre_save(s); 33ff8f06eeSShlomo Pongratz } 34ff8f06eeSShlomo Pongratz } 35ff8f06eeSShlomo Pongratz 36ff8f06eeSShlomo Pongratz static int gicv3_post_load(void *opaque, int version_id) 37ff8f06eeSShlomo Pongratz { 38ff8f06eeSShlomo Pongratz GICv3State *s = (GICv3State *)opaque; 39ff8f06eeSShlomo Pongratz ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s); 40ff8f06eeSShlomo Pongratz 41ff8f06eeSShlomo Pongratz if (c->post_load) { 42ff8f06eeSShlomo Pongratz c->post_load(s); 43ff8f06eeSShlomo Pongratz } 44ff8f06eeSShlomo Pongratz return 0; 45ff8f06eeSShlomo Pongratz } 46ff8f06eeSShlomo Pongratz 47ff8f06eeSShlomo Pongratz static const VMStateDescription vmstate_gicv3 = { 48ff8f06eeSShlomo Pongratz .name = "arm_gicv3", 49ff8f06eeSShlomo Pongratz .unmigratable = 1, 50ff8f06eeSShlomo Pongratz .pre_save = gicv3_pre_save, 51ff8f06eeSShlomo Pongratz .post_load = gicv3_post_load, 52ff8f06eeSShlomo Pongratz }; 53ff8f06eeSShlomo Pongratz 54ff8f06eeSShlomo Pongratz void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, 55ff8f06eeSShlomo Pongratz const MemoryRegionOps *ops) 56ff8f06eeSShlomo Pongratz { 57ff8f06eeSShlomo Pongratz SysBusDevice *sbd = SYS_BUS_DEVICE(s); 58ff8f06eeSShlomo Pongratz int i; 59ff8f06eeSShlomo Pongratz 60ff8f06eeSShlomo Pongratz /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU. 61ff8f06eeSShlomo Pongratz * GPIO array layout is thus: 62ff8f06eeSShlomo Pongratz * [0..N-1] spi 63ff8f06eeSShlomo Pongratz * [N..N+31] PPIs for CPU 0 64ff8f06eeSShlomo Pongratz * [N+32..N+63] PPIs for CPU 1 65ff8f06eeSShlomo Pongratz * ... 66ff8f06eeSShlomo Pongratz */ 67ff8f06eeSShlomo Pongratz i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu; 68ff8f06eeSShlomo Pongratz qdev_init_gpio_in(DEVICE(s), handler, i); 69ff8f06eeSShlomo Pongratz 70ff8f06eeSShlomo Pongratz s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq)); 71ff8f06eeSShlomo Pongratz s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq)); 72ff8f06eeSShlomo Pongratz 73ff8f06eeSShlomo Pongratz for (i = 0; i < s->num_cpu; i++) { 74ff8f06eeSShlomo Pongratz sysbus_init_irq(sbd, &s->parent_irq[i]); 75ff8f06eeSShlomo Pongratz } 76ff8f06eeSShlomo Pongratz for (i = 0; i < s->num_cpu; i++) { 77ff8f06eeSShlomo Pongratz sysbus_init_irq(sbd, &s->parent_fiq[i]); 78ff8f06eeSShlomo Pongratz } 79ff8f06eeSShlomo Pongratz 80ff8f06eeSShlomo Pongratz memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s, 81ff8f06eeSShlomo Pongratz "gicv3_dist", 0x10000); 82ff8f06eeSShlomo Pongratz memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s, 83ff8f06eeSShlomo Pongratz "gicv3_redist", 0x20000 * s->num_cpu); 84ff8f06eeSShlomo Pongratz 85ff8f06eeSShlomo Pongratz sysbus_init_mmio(sbd, &s->iomem_dist); 86ff8f06eeSShlomo Pongratz sysbus_init_mmio(sbd, &s->iomem_redist); 87ff8f06eeSShlomo Pongratz } 88ff8f06eeSShlomo Pongratz 89ff8f06eeSShlomo Pongratz static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) 90ff8f06eeSShlomo Pongratz { 91ff8f06eeSShlomo Pongratz GICv3State *s = ARM_GICV3_COMMON(dev); 92ff8f06eeSShlomo Pongratz 93ff8f06eeSShlomo Pongratz /* revision property is actually reserved and currently used only in order 94ff8f06eeSShlomo Pongratz * to keep the interface compatible with GICv2 code, avoiding extra 95ff8f06eeSShlomo Pongratz * conditions. However, in future it could be used, for example, if we 96ff8f06eeSShlomo Pongratz * implement GICv4. 97ff8f06eeSShlomo Pongratz */ 98ff8f06eeSShlomo Pongratz if (s->revision != 3) { 99ff8f06eeSShlomo Pongratz error_setg(errp, "unsupported GIC revision %d", s->revision); 100ff8f06eeSShlomo Pongratz return; 101ff8f06eeSShlomo Pongratz } 102ff8f06eeSShlomo Pongratz } 103ff8f06eeSShlomo Pongratz 104ff8f06eeSShlomo Pongratz static void arm_gicv3_common_reset(DeviceState *dev) 105ff8f06eeSShlomo Pongratz { 106ff8f06eeSShlomo Pongratz /* TODO */ 107ff8f06eeSShlomo Pongratz } 108ff8f06eeSShlomo Pongratz 109ff8f06eeSShlomo Pongratz static Property arm_gicv3_common_properties[] = { 110ff8f06eeSShlomo Pongratz DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1), 111ff8f06eeSShlomo Pongratz DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32), 112ff8f06eeSShlomo Pongratz DEFINE_PROP_UINT32("revision", GICv3State, revision, 3), 113ff8f06eeSShlomo Pongratz DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0), 114ff8f06eeSShlomo Pongratz DEFINE_PROP_END_OF_LIST(), 115ff8f06eeSShlomo Pongratz }; 116ff8f06eeSShlomo Pongratz 117ff8f06eeSShlomo Pongratz static void arm_gicv3_common_class_init(ObjectClass *klass, void *data) 118ff8f06eeSShlomo Pongratz { 119ff8f06eeSShlomo Pongratz DeviceClass *dc = DEVICE_CLASS(klass); 120ff8f06eeSShlomo Pongratz 121ff8f06eeSShlomo Pongratz dc->reset = arm_gicv3_common_reset; 122ff8f06eeSShlomo Pongratz dc->realize = arm_gicv3_common_realize; 123ff8f06eeSShlomo Pongratz dc->props = arm_gicv3_common_properties; 124ff8f06eeSShlomo Pongratz dc->vmsd = &vmstate_gicv3; 125ff8f06eeSShlomo Pongratz } 126ff8f06eeSShlomo Pongratz 127ff8f06eeSShlomo Pongratz static const TypeInfo arm_gicv3_common_type = { 128ff8f06eeSShlomo Pongratz .name = TYPE_ARM_GICV3_COMMON, 129ff8f06eeSShlomo Pongratz .parent = TYPE_SYS_BUS_DEVICE, 130ff8f06eeSShlomo Pongratz .instance_size = sizeof(GICv3State), 131ff8f06eeSShlomo Pongratz .class_size = sizeof(ARMGICv3CommonClass), 132ff8f06eeSShlomo Pongratz .class_init = arm_gicv3_common_class_init, 133ff8f06eeSShlomo Pongratz .abstract = true, 134ff8f06eeSShlomo Pongratz }; 135ff8f06eeSShlomo Pongratz 136ff8f06eeSShlomo Pongratz static void register_types(void) 137ff8f06eeSShlomo Pongratz { 138ff8f06eeSShlomo Pongratz type_register_static(&arm_gicv3_common_type); 139ff8f06eeSShlomo Pongratz } 140ff8f06eeSShlomo Pongratz 141ff8f06eeSShlomo Pongratz type_init(register_types) 142