arch/arm64/kvm/vgic/vgic-init.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/vgic/vgic-init.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/vgic/vgic-init.c
Extension
.c
Size
21911 bytes
Lines
844
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

kvm_for_each_vcpu(i, vcpu, kvm) {
			struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
			kfree(vgic_cpu->private_irqs);
			vgic_cpu->private_irqs = NULL;
		}

		kvm->arch.vgic.vgic_model = 0;
		goto out_unlock;
	}

	if (type == KVM_DEV_TYPE_ARM_VGIC_V3)
		kvm->arch.vgic.nassgicap = system_supports_direct_sgis();

	/*
	 * We now know that we have a GICv5. The Arch Timer PPI interrupts may
	 * have been initialised at this stage, but will have done so assuming
	 * that we have an older GIC, meaning that the IntIDs won't be
	 * correct. We init them again, and this time they will be correct.
	 */
	if (type == KVM_DEV_TYPE_ARM_VGIC_V5)
		kvm_timer_init_vm(kvm);

out_unlock:
	mutex_unlock(&kvm->arch.config_lock);
	kvm_unlock_all_vcpus(kvm);
	return ret;
}

/* INIT/DESTROY */

/**
 * kvm_vgic_dist_init: initialize the dist data structures
 * @kvm: kvm struct pointer
 * @nr_spis: number of spis, frozen by caller
 */
static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
{
	struct vgic_dist *dist = &kvm->arch.vgic;
	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
	int i;

	dist->active_spis = (atomic_t)ATOMIC_INIT(0);
	dist->spis = kzalloc_objs(struct vgic_irq, nr_spis, GFP_KERNEL_ACCOUNT);
	if (!dist->spis)
		return  -ENOMEM;

	/*
	 * In the following code we do not take the irq struct lock since
	 * no other action on irq structs can happen while the VGIC is
	 * not initialized yet:
	 * If someone wants to inject an interrupt or does a MMIO access, we
	 * require prior initialization in case of a virtual GICv3 or trigger
	 * initialization when using a virtual GICv2.
	 */
	for (i = 0; i < nr_spis; i++) {
		struct vgic_irq *irq = &dist->spis[i];

		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
		INIT_LIST_HEAD(&irq->ap_list);
		raw_spin_lock_init(&irq->irq_lock);
		irq->vcpu = NULL;
		irq->target_vcpu = vcpu0;
		refcount_set(&irq->refcount, 0);
		switch (dist->vgic_model) {
		case KVM_DEV_TYPE_ARM_VGIC_V2:
			irq->targets = 0;
			irq->group = 0;
			break;
		case KVM_DEV_TYPE_ARM_VGIC_V3:
			irq->mpidr = 0;
			irq->group = 1;
			break;
		default:
			kfree(dist->spis);
			dist->spis = NULL;
			return -EINVAL;
		}
	}
	return 0;
}

/* Default GICv3 Maintenance Interrupt INTID, as per SBSA */
#define DEFAULT_MI_INTID	25

int kvm_vgic_vcpu_nv_init(struct kvm_vcpu *vcpu)
{
	int ret;

	guard(mutex)(&vcpu->kvm->arch.config_lock);

Annotation

Implementation Notes