arch/arm64/kvm/vgic/vgic-mmio-v2.c

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

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/vgic/vgic-mmio-v2.c
Extension
.c
Size
15655 bytes
Lines
586
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

switch (reg) {
		case KVM_VGIC_IMP_REV_2:
		case KVM_VGIC_IMP_REV_3:
			vcpu->kvm->arch.vgic.v2_groups_user_writable = true;
			dist->implementation_rev = reg;
			return 0;
		default:
			return -EINVAL;
		}
	}

	vgic_mmio_write_v2_misc(vcpu, addr, len, val);
	return 0;
}

static int vgic_mmio_uaccess_write_v2_group(struct kvm_vcpu *vcpu,
					    gpa_t addr, unsigned int len,
					    unsigned long val)
{
	if (vcpu->kvm->arch.vgic.v2_groups_user_writable)
		vgic_mmio_write_group(vcpu, addr, len, val);

	return 0;
}

static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
				 gpa_t addr, unsigned int len,
				 unsigned long val)
{
	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
	int intid = val & 0xf;
	int targets = (val >> 16) & 0xff;
	int mode = (val >> 24) & 0x03;
	struct kvm_vcpu *vcpu;
	unsigned long flags, c;

	switch (mode) {
	case 0x0:		/* as specified by targets */
		break;
	case 0x1:
		targets = (1U << nr_vcpus) - 1;			/* all, ... */
		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
		break;
	case 0x2:		/* this very vCPU only */
		targets = (1U << source_vcpu->vcpu_id);
		break;
	case 0x3:		/* reserved */
		return;
	}

	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
		struct vgic_irq *irq;

		if (!(targets & (1U << c)))
			continue;

		irq = vgic_get_vcpu_irq(vcpu, intid);

		raw_spin_lock_irqsave(&irq->irq_lock, flags);
		irq->pending_latch = true;
		irq->source |= 1U << source_vcpu->vcpu_id;

		vgic_queue_irq_unlock(source_vcpu->kvm, irq, flags);
		vgic_put_irq(source_vcpu->kvm, irq);
	}
}

static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
					   gpa_t addr, unsigned int len)
{
	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
	int i;
	u64 val = 0;

	for (i = 0; i < len; i++) {
		struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);

		val |= (u64)irq->targets << (i * 8);

		vgic_put_irq(vcpu->kvm, irq);
	}

	return val;
}

static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
				   gpa_t addr, unsigned int len,
				   unsigned long val)
{
	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);

Annotation

Implementation Notes