arch/arm64/kvm/sys_regs.c

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

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/sys_regs.c
Extension
.c
Size
163780 bytes
Lines
5863
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

struct sr_loc {
	enum sr_loc_attr loc;
	enum vcpu_sysreg map_reg;
	u64		 (*xlate)(u64);
};

static enum sr_loc_attr locate_direct_register(const struct kvm_vcpu *vcpu,
					       enum vcpu_sysreg reg)
{
	switch (reg) {
	case SCTLR_EL1:
	case CPACR_EL1:
	case TTBR0_EL1:
	case TTBR1_EL1:
	case TCR_EL1:
	case TCR2_EL1:
	case PIR_EL1:
	case PIRE0_EL1:
	case POR_EL1:
	case ESR_EL1:
	case AFSR0_EL1:
	case AFSR1_EL1:
	case FAR_EL1:
	case MAIR_EL1:
	case VBAR_EL1:
	case CONTEXTIDR_EL1:
	case AMAIR_EL1:
	case CNTKCTL_EL1:
	case ELR_EL1:
	case SPSR_EL1:
	case ZCR_EL1:
	case SCTLR2_EL1:
		/*
		 * EL1 registers which have an ELx2 mapping are loaded if
		 * we're not in hypervisor context.
		 */
		return is_hyp_ctxt(vcpu) ? SR_LOC_MEMORY : SR_LOC_LOADED;

	case TPIDR_EL0:
	case TPIDRRO_EL0:
	case TPIDR_EL1:
	case PAR_EL1:
	case DACR32_EL2:
	case IFSR32_EL2:
	case DBGVCR32_EL2:
		/* These registers are always loaded, no matter what */
		return SR_LOC_LOADED;

	default:
		/* Non-mapped EL2 registers are by definition in memory. */
		return SR_LOC_MEMORY;
	}
}

static void locate_mapped_el2_register(const struct kvm_vcpu *vcpu,
				       enum vcpu_sysreg reg,
				       enum vcpu_sysreg map_reg,
				       u64 (*xlate)(u64),
				       struct sr_loc *loc)
{
	if (!is_hyp_ctxt(vcpu)) {
		loc->loc = SR_LOC_MEMORY;
		return;
	}

	loc->loc = SR_LOC_LOADED | SR_LOC_MAPPED;
	loc->map_reg = map_reg;

	WARN_ON(locate_direct_register(vcpu, map_reg) != SR_LOC_MEMORY);

	if (xlate != NULL && !vcpu_el2_e2h_is_set(vcpu)) {
		loc->loc |= SR_LOC_XLATED;
		loc->xlate = xlate;
	}
}

#define MAPPED_EL2_SYSREG(r, m, t)					\
	case r:	{							\
		locate_mapped_el2_register(vcpu, r, m, t, loc);		\
		break;							\
	}

static void locate_register(const struct kvm_vcpu *vcpu, enum vcpu_sysreg reg,
			    struct sr_loc *loc)
{
	if (!vcpu_get_flag(vcpu, SYSREGS_ON_CPU)) {
		loc->loc = SR_LOC_MEMORY;
		return;
	}

Annotation

Implementation Notes