1313#include "vm-arch.h"
1414#include "vm.h"
1515
16+ #define IRQCHIP_TYPE_GIC_V2 1
17+ #define IRQCHIP_TYPE_GIC_V3 2
18+
1619typedef struct {
1720 uint64_t entry ;
1821 size_t initrdsz ;
1922 int gic_fd ;
23+ int gic_type ;
2024
2125 /* This device is a bridge between mmio_bus and io_bus*/
2226 struct dev iodev ;
@@ -28,7 +32,7 @@ static int create_irqchip(vm_t *v)
2832{
2933 vm_arch_priv_t * priv = (vm_arch_priv_t * ) v -> priv ;
3034 uint64_t dist_addr = ARM_GIC_DIST_BASE ;
31- uint64_t redist_addr = ARM_GIC_REDIST_BASE ;
35+ uint64_t redist_cpui_addr = ARM_GIC_REDIST_CPUI_BASE ;
3236
3337 struct kvm_create_device device = {
3438 .type = KVM_DEV_TYPE_ARM_VGIC_V3 ,
@@ -38,16 +42,22 @@ static int create_irqchip(vm_t *v)
3842 .attr = KVM_VGIC_V3_ADDR_TYPE_DIST ,
3943 .addr = (uint64_t ) & dist_addr ,
4044 };
41- struct kvm_device_attr redist_attr = {
45+ struct kvm_device_attr redist_cpui_attr = {
4246 .group = KVM_DEV_ARM_VGIC_GRP_ADDR ,
4347 .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST ,
44- .addr = (uint64_t ) & redist_addr ,
48+ .addr = (uint64_t ) & redist_cpui_addr ,
4549 };
4650
51+ priv -> gic_type = IRQCHIP_TYPE_GIC_V3 ;
4752 if (ioctl (v -> vm_fd , KVM_CREATE_DEVICE , & device ) < 0 ) {
48- throw_err ("Failed to create GICv3 chip.\n" );
49- fprintf (stderr , "Your system may not support GICv3.\n" );
50- return -1 ;
53+ /* Try to create GICv2 chip */
54+ device .type = KVM_DEV_TYPE_ARM_VGIC_V2 ;
55+ if (ioctl (v -> vm_fd , KVM_CREATE_DEVICE , & device ) < 0 )
56+ return throw_err ("Failed to create IRQ chip\n" );
57+
58+ dist_attr .attr = KVM_VGIC_V2_ADDR_TYPE_DIST ;
59+ redist_cpui_attr .attr = KVM_VGIC_V2_ADDR_TYPE_CPU ;
60+ priv -> gic_type = IRQCHIP_TYPE_GIC_V2 ;
5161 }
5262
5363 priv -> gic_fd = device .fd ;
@@ -56,9 +66,11 @@ static int create_irqchip(vm_t *v)
5666 return throw_err (
5767 "Failed to set the address of the distributor of GIC.\n" );
5868
59- if (ioctl (priv -> gic_fd , KVM_SET_DEVICE_ATTR , & redist_attr ) < 0 )
60- return throw_err (
61- "Failed to set the address of the redistributor of GIC.\n" );
69+ if (ioctl (priv -> gic_fd , KVM_SET_DEVICE_ATTR , & redist_cpui_attr ) < 0 )
70+ return throw_err ("Failed to set the address of the %s of GIC.\n" ,
71+ device .type == KVM_DEV_TYPE_ARM_VGIC_V3
72+ ? "redistributer"
73+ : "CPU interface" );
6274
6375 return 0 ;
6476}
@@ -311,8 +323,11 @@ static int generate_fdt(vm_t *v)
311323 __FDT (begin_node , "intr" );
312324 uint64_t gic_reg [] = {
313325 cpu_to_fdt64 (ARM_GIC_DIST_BASE ), cpu_to_fdt64 (ARM_GIC_DIST_SIZE ),
314- cpu_to_fdt64 (ARM_GIC_REDIST_BASE ), cpu_to_fdt64 (ARM_GIC_REDIST_SIZE )};
315- __FDT (property_string , "compatible" , "arm,gic-v3" );
326+ cpu_to_fdt64 (ARM_GIC_REDIST_CPUI_BASE ), cpu_to_fdt64 (ARM_GIC_REDIST_CPUI_SIZE )};
327+ if (priv -> gic_type == IRQCHIP_TYPE_GIC_V3 )
328+ __FDT (property_string , "compatible" , "arm,gic-v3" );
329+ else
330+ __FDT (property_string , "compatible" , "arm,cortex-a15-gic" );
316331 __FDT (property_cell , "#interrupt-cells" , 3 );
317332 __FDT (property , "interrupt-controller" , NULL , 0 );
318333 __FDT (property , "reg" , & gic_reg , sizeof (gic_reg ));
0 commit comments