xref: /linux/arch/arm64/kvm/vgic/vgic-v5.c (revision 63eb28bb1402891b1ad2be02a530f29a9dd7f1cd)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <kvm/arm_vgic.h>
4 #include <linux/irqchip/arm-vgic-info.h>
5 
6 #include "vgic.h"
7 
8 /*
9  * Probe for a vGICv5 compatible interrupt controller, returning 0 on success.
10  * Currently only supports GICv3-based VMs on a GICv5 host, and hence only
11  * registers a VGIC_V3 device.
12  */
vgic_v5_probe(const struct gic_kvm_info * info)13 int vgic_v5_probe(const struct gic_kvm_info *info)
14 {
15 	u64 ich_vtr_el2;
16 	int ret;
17 
18 	if (!info->has_gcie_v3_compat)
19 		return -ENODEV;
20 
21 	kvm_vgic_global_state.type = VGIC_V5;
22 	kvm_vgic_global_state.has_gcie_v3_compat = true;
23 
24 	/* We only support v3 compat mode - use vGICv3 limits */
25 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
26 
27 	kvm_vgic_global_state.vcpu_base = 0;
28 	kvm_vgic_global_state.vctrl_base = NULL;
29 	kvm_vgic_global_state.can_emulate_gicv2 = false;
30 	kvm_vgic_global_state.has_gicv4 = false;
31 	kvm_vgic_global_state.has_gicv4_1 = false;
32 
33 	ich_vtr_el2 =  kvm_call_hyp_ret(__vgic_v3_get_gic_config);
34 	kvm_vgic_global_state.ich_vtr_el2 = (u32)ich_vtr_el2;
35 
36 	/*
37 	 * The ListRegs field is 5 bits, but there is an architectural
38 	 * maximum of 16 list registers. Just ignore bit 4...
39 	 */
40 	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
41 
42 	ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
43 	if (ret) {
44 		kvm_err("Cannot register GICv3-legacy KVM device.\n");
45 		return ret;
46 	}
47 
48 	static_branch_enable(&kvm_vgic_global_state.gicv3_cpuif);
49 	kvm_info("GCIE legacy system register CPU interface\n");
50 
51 	return 0;
52 }
53