arch/arm64/kvm/reset.c

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

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/reset.c
Extension
.c
Size
9057 bytes
Lines
328
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 (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
			target_pc &= ~1UL;
			vcpu_set_thumb(vcpu);
		}

		/* Propagate caller endianness */
		if (reset_state.be)
			kvm_vcpu_set_be(vcpu);

		*vcpu_pc(vcpu) = target_pc;

		/*
		 * We may come from a state where either a PC update was
		 * pending (SMC call resulting in PC being increpented to
		 * skip the SMC) or a pending exception. Make sure we get
		 * rid of all that, as this cannot be valid out of reset.
		 *
		 * Note that clearing the exception mask also clears PC
		 * updates, but that's an implementation detail, and we
		 * really want to make it explicit.
		 */
		vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
		vcpu_clear_flag(vcpu, EXCEPT_MASK);
		vcpu_clear_flag(vcpu, INCREMENT_PC);
		vcpu_set_reg(vcpu, 0, reset_state.r0);
	}

	/* Reset timer */
	kvm_timer_vcpu_reset(vcpu);

	if (loaded)
		kvm_arch_vcpu_load(vcpu, smp_processor_id());
	preempt_enable();
}

u32 kvm_get_pa_bits(struct kvm *kvm)
{
	/* Fixed limit until we can configure ID_AA64MMFR0.PARange */
	return kvm_ipa_limit;
}

u32 get_kvm_ipa_limit(void)
{
	return kvm_ipa_limit;
}

int __init kvm_set_ipa_limit(void)
{
	unsigned int parange;
	u64 mmfr0;

	mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
	parange = cpuid_feature_extract_unsigned_field(mmfr0,
				ID_AA64MMFR0_EL1_PARANGE_SHIFT);
	/*
	 * IPA size beyond 48 bits for 4K and 16K page size is only supported
	 * when LPA2 is available. So if we have LPA2, enable it, else cap to 48
	 * bits, in case it's reported as larger on the system.
	 */
	if (!kvm_lpa2_is_enabled() && PAGE_SIZE != SZ_64K)
		parange = min(parange, (unsigned int)ID_AA64MMFR0_EL1_PARANGE_48);

	/*
	 * Check with ARMv8.5-GTG that our PAGE_SIZE is supported at
	 * Stage-2. If not, things will stop very quickly.
	 */
	switch (cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_EL1_TGRAN_2_SHIFT)) {
	case ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_NONE:
		kvm_err("PAGE_SIZE not supported at Stage-2, giving up\n");
		return -EINVAL;
	case ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_DEFAULT:
		kvm_debug("PAGE_SIZE supported at Stage-2 (default)\n");
		break;
	case ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MIN ... ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MAX:
		kvm_debug("PAGE_SIZE supported at Stage-2 (advertised)\n");
		break;
	default:
		kvm_err("Unsupported value for TGRAN_2, giving up\n");
		return -EINVAL;
	}

	kvm_ipa_limit = id_aa64mmfr0_parange_to_phys_shift(parange);
	kvm_info("IPA Size Limit: %d bits%s\n", kvm_ipa_limit,
		 ((kvm_ipa_limit < KVM_PHYS_SHIFT) ?
		  " (Reduced IPA size, limited VM/VMM compatibility)" : ""));

	return 0;
}

Annotation

Implementation Notes