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

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

File Facts

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

if (vgic_has_its(vcpu->kvm)) {
			value |= (INTERRUPT_ID_BITS_ITS - 1) << 19;
			value |= GICD_TYPER_LPIS;
		} else {
			value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
		}
		break;
	case GICD_TYPER2:
		if (vgic_supports_direct_sgis(vcpu->kvm))
			value = GICD_TYPER2_nASSGIcap;
		break;
	case GICD_IIDR:
		value = (PRODUCT_ID_KVM << GICD_IIDR_PRODUCT_ID_SHIFT) |
			(vgic->implementation_rev << GICD_IIDR_REVISION_SHIFT) |
			(IMPLEMENTER_ARM << GICD_IIDR_IMPLEMENTER_SHIFT);
		break;
	default:
		return 0;
	}

	return value;
}

static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
				    gpa_t addr, unsigned int len,
				    unsigned long val)
{
	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;

	switch (addr & 0x0c) {
	case GICD_CTLR: {
		bool was_enabled, is_hwsgi;

		mutex_lock(&vcpu->kvm->arch.config_lock);

		was_enabled = dist->enabled;
		is_hwsgi = dist->nassgireq;

		dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;

		/* Not a GICv4.1? No HW SGIs */
		if (!vgic_supports_direct_sgis(vcpu->kvm))
			val &= ~GICD_CTLR_nASSGIreq;

		/* Dist stays enabled? nASSGIreq is RO */
		if (was_enabled && dist->enabled) {
			val &= ~GICD_CTLR_nASSGIreq;
			val |= FIELD_PREP(GICD_CTLR_nASSGIreq, is_hwsgi);
		}

		/* Switching HW SGIs? */
		dist->nassgireq = val & GICD_CTLR_nASSGIreq;
		if (is_hwsgi != dist->nassgireq)
			vgic_v4_configure_vsgis(vcpu->kvm);

		if (vgic_supports_direct_sgis(vcpu->kvm) &&
		    was_enabled != dist->enabled)
			kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_RELOAD_GICv4);
		else if (!was_enabled && dist->enabled)
			vgic_kick_vcpus(vcpu->kvm);

		mutex_unlock(&vcpu->kvm->arch.config_lock);
		break;
	}
	case GICD_TYPER:
	case GICD_TYPER2:
	case GICD_IIDR:
		/* This is at best for documentation purposes... */
		return;
	}
}

static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
					   gpa_t addr, unsigned int len,
					   unsigned long val)
{
	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
	u32 reg;

	switch (addr & 0x0c) {
	case GICD_TYPER2:
		reg = vgic_mmio_read_v3_misc(vcpu, addr, len);

		if (reg == val)
			return 0;
		if (vgic_initialized(vcpu->kvm))
			return -EBUSY;
		if ((reg ^ val) & ~GICD_TYPER2_nASSGIcap)
			return -EINVAL;
		if (!system_supports_direct_sgis() && val)

Annotation

Implementation Notes