1*a7bf3034SPavel Fedin /* 2*a7bf3034SPavel Fedin * ARM Generic Interrupt Controller using KVM in-kernel support 3*a7bf3034SPavel Fedin * 4*a7bf3034SPavel Fedin * Copyright (c) 2015 Samsung Electronics Co., Ltd. 5*a7bf3034SPavel Fedin * Written by Pavel Fedin 6*a7bf3034SPavel Fedin * Based on vGICv2 code by Peter Maydell 7*a7bf3034SPavel Fedin * 8*a7bf3034SPavel Fedin * This program is free software; you can redistribute it and/or modify 9*a7bf3034SPavel Fedin * it under the terms of the GNU General Public License as published by 10*a7bf3034SPavel Fedin * the Free Software Foundation, either version 2 of the License, or 11*a7bf3034SPavel Fedin * (at your option) any later version. 12*a7bf3034SPavel Fedin * 13*a7bf3034SPavel Fedin * This program is distributed in the hope that it will be useful, 14*a7bf3034SPavel Fedin * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*a7bf3034SPavel Fedin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*a7bf3034SPavel Fedin * GNU General Public License for more details. 17*a7bf3034SPavel Fedin * 18*a7bf3034SPavel Fedin * You should have received a copy of the GNU General Public License along 19*a7bf3034SPavel Fedin * with this program; if not, see <http://www.gnu.org/licenses/>. 20*a7bf3034SPavel Fedin */ 21*a7bf3034SPavel Fedin 22*a7bf3034SPavel Fedin #include "hw/intc/arm_gicv3_common.h" 23*a7bf3034SPavel Fedin #include "hw/sysbus.h" 24*a7bf3034SPavel Fedin #include "sysemu/kvm.h" 25*a7bf3034SPavel Fedin #include "kvm_arm.h" 26*a7bf3034SPavel Fedin #include "vgic_common.h" 27*a7bf3034SPavel Fedin 28*a7bf3034SPavel Fedin #ifdef DEBUG_GICV3_KVM 29*a7bf3034SPavel Fedin #define DPRINTF(fmt, ...) \ 30*a7bf3034SPavel Fedin do { fprintf(stderr, "kvm_gicv3: " fmt, ## __VA_ARGS__); } while (0) 31*a7bf3034SPavel Fedin #else 32*a7bf3034SPavel Fedin #define DPRINTF(fmt, ...) \ 33*a7bf3034SPavel Fedin do { } while (0) 34*a7bf3034SPavel Fedin #endif 35*a7bf3034SPavel Fedin 36*a7bf3034SPavel Fedin #define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3" 37*a7bf3034SPavel Fedin #define KVM_ARM_GICV3(obj) \ 38*a7bf3034SPavel Fedin OBJECT_CHECK(GICv3State, (obj), TYPE_KVM_ARM_GICV3) 39*a7bf3034SPavel Fedin #define KVM_ARM_GICV3_CLASS(klass) \ 40*a7bf3034SPavel Fedin OBJECT_CLASS_CHECK(KVMARMGICv3Class, (klass), TYPE_KVM_ARM_GICV3) 41*a7bf3034SPavel Fedin #define KVM_ARM_GICV3_GET_CLASS(obj) \ 42*a7bf3034SPavel Fedin OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3) 43*a7bf3034SPavel Fedin 44*a7bf3034SPavel Fedin typedef struct KVMARMGICv3Class { 45*a7bf3034SPavel Fedin ARMGICv3CommonClass parent_class; 46*a7bf3034SPavel Fedin DeviceRealize parent_realize; 47*a7bf3034SPavel Fedin void (*parent_reset)(DeviceState *dev); 48*a7bf3034SPavel Fedin } KVMARMGICv3Class; 49*a7bf3034SPavel Fedin 50*a7bf3034SPavel Fedin static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level) 51*a7bf3034SPavel Fedin { 52*a7bf3034SPavel Fedin GICv3State *s = (GICv3State *)opaque; 53*a7bf3034SPavel Fedin 54*a7bf3034SPavel Fedin kvm_arm_gic_set_irq(s->num_irq, irq, level); 55*a7bf3034SPavel Fedin } 56*a7bf3034SPavel Fedin 57*a7bf3034SPavel Fedin static void kvm_arm_gicv3_put(GICv3State *s) 58*a7bf3034SPavel Fedin { 59*a7bf3034SPavel Fedin /* TODO */ 60*a7bf3034SPavel Fedin DPRINTF("Cannot put kernel gic state, no kernel interface\n"); 61*a7bf3034SPavel Fedin } 62*a7bf3034SPavel Fedin 63*a7bf3034SPavel Fedin static void kvm_arm_gicv3_get(GICv3State *s) 64*a7bf3034SPavel Fedin { 65*a7bf3034SPavel Fedin /* TODO */ 66*a7bf3034SPavel Fedin DPRINTF("Cannot get kernel gic state, no kernel interface\n"); 67*a7bf3034SPavel Fedin } 68*a7bf3034SPavel Fedin 69*a7bf3034SPavel Fedin static void kvm_arm_gicv3_reset(DeviceState *dev) 70*a7bf3034SPavel Fedin { 71*a7bf3034SPavel Fedin GICv3State *s = ARM_GICV3_COMMON(dev); 72*a7bf3034SPavel Fedin KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s); 73*a7bf3034SPavel Fedin 74*a7bf3034SPavel Fedin DPRINTF("Reset\n"); 75*a7bf3034SPavel Fedin 76*a7bf3034SPavel Fedin kgc->parent_reset(dev); 77*a7bf3034SPavel Fedin kvm_arm_gicv3_put(s); 78*a7bf3034SPavel Fedin } 79*a7bf3034SPavel Fedin 80*a7bf3034SPavel Fedin static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) 81*a7bf3034SPavel Fedin { 82*a7bf3034SPavel Fedin GICv3State *s = KVM_ARM_GICV3(dev); 83*a7bf3034SPavel Fedin KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s); 84*a7bf3034SPavel Fedin Error *local_err = NULL; 85*a7bf3034SPavel Fedin 86*a7bf3034SPavel Fedin DPRINTF("kvm_arm_gicv3_realize\n"); 87*a7bf3034SPavel Fedin 88*a7bf3034SPavel Fedin kgc->parent_realize(dev, &local_err); 89*a7bf3034SPavel Fedin if (local_err) { 90*a7bf3034SPavel Fedin error_propagate(errp, local_err); 91*a7bf3034SPavel Fedin return; 92*a7bf3034SPavel Fedin } 93*a7bf3034SPavel Fedin 94*a7bf3034SPavel Fedin if (s->security_extn) { 95*a7bf3034SPavel Fedin error_setg(errp, "the in-kernel VGICv3 does not implement the " 96*a7bf3034SPavel Fedin "security extensions"); 97*a7bf3034SPavel Fedin return; 98*a7bf3034SPavel Fedin } 99*a7bf3034SPavel Fedin 100*a7bf3034SPavel Fedin gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL); 101*a7bf3034SPavel Fedin 102*a7bf3034SPavel Fedin /* Try to create the device via the device control API */ 103*a7bf3034SPavel Fedin s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false); 104*a7bf3034SPavel Fedin if (s->dev_fd < 0) { 105*a7bf3034SPavel Fedin error_setg_errno(errp, -s->dev_fd, "error creating in-kernel VGIC"); 106*a7bf3034SPavel Fedin return; 107*a7bf3034SPavel Fedin } 108*a7bf3034SPavel Fedin 109*a7bf3034SPavel Fedin kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 110*a7bf3034SPavel Fedin 0, &s->num_irq, true); 111*a7bf3034SPavel Fedin 112*a7bf3034SPavel Fedin /* Tell the kernel to complete VGIC initialization now */ 113*a7bf3034SPavel Fedin kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, 114*a7bf3034SPavel Fedin KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); 115*a7bf3034SPavel Fedin 116*a7bf3034SPavel Fedin kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR, 117*a7bf3034SPavel Fedin KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd); 118*a7bf3034SPavel Fedin kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR, 119*a7bf3034SPavel Fedin KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd); 120*a7bf3034SPavel Fedin } 121*a7bf3034SPavel Fedin 122*a7bf3034SPavel Fedin static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) 123*a7bf3034SPavel Fedin { 124*a7bf3034SPavel Fedin DeviceClass *dc = DEVICE_CLASS(klass); 125*a7bf3034SPavel Fedin ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); 126*a7bf3034SPavel Fedin KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass); 127*a7bf3034SPavel Fedin 128*a7bf3034SPavel Fedin agcc->pre_save = kvm_arm_gicv3_get; 129*a7bf3034SPavel Fedin agcc->post_load = kvm_arm_gicv3_put; 130*a7bf3034SPavel Fedin kgc->parent_realize = dc->realize; 131*a7bf3034SPavel Fedin kgc->parent_reset = dc->reset; 132*a7bf3034SPavel Fedin dc->realize = kvm_arm_gicv3_realize; 133*a7bf3034SPavel Fedin dc->reset = kvm_arm_gicv3_reset; 134*a7bf3034SPavel Fedin } 135*a7bf3034SPavel Fedin 136*a7bf3034SPavel Fedin static const TypeInfo kvm_arm_gicv3_info = { 137*a7bf3034SPavel Fedin .name = TYPE_KVM_ARM_GICV3, 138*a7bf3034SPavel Fedin .parent = TYPE_ARM_GICV3_COMMON, 139*a7bf3034SPavel Fedin .instance_size = sizeof(GICv3State), 140*a7bf3034SPavel Fedin .class_init = kvm_arm_gicv3_class_init, 141*a7bf3034SPavel Fedin .class_size = sizeof(KVMARMGICv3Class), 142*a7bf3034SPavel Fedin }; 143*a7bf3034SPavel Fedin 144*a7bf3034SPavel Fedin static void kvm_arm_gicv3_register_types(void) 145*a7bf3034SPavel Fedin { 146*a7bf3034SPavel Fedin type_register_static(&kvm_arm_gicv3_info); 147*a7bf3034SPavel Fedin } 148*a7bf3034SPavel Fedin 149*a7bf3034SPavel Fedin type_init(kvm_arm_gicv3_register_types) 150