arch/powerpc/kvm/book3s_hv_ras.c

Source file repositories/reference/linux-study-clean/arch/powerpc/kvm/book3s_hv_ras.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kvm/book3s_hv_ras.c
Extension
.c
Size
11926 bytes
Lines
378
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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 (dsisr & DSISR_MC_TLB_MULTI) {
			tlbiel_all_lpid(vcpu->kvm->arch.radix);
			dsisr &= ~DSISR_MC_TLB_MULTI;
		}
		/* Any other errors we don't understand? */
		if (dsisr & 0xffffffffUL)
			handled = 0;
	}

	switch ((srr1 >> SRR1_MC_IFETCH_SH) & SRR1_MC_IFETCH_MASK) {
	case 0:
		break;
	case SRR1_MC_IFETCH_SLBPAR:
	case SRR1_MC_IFETCH_SLBMULTI:
	case SRR1_MC_IFETCH_SLBPARMULTI:
		reload_slb(vcpu);
		break;
	case SRR1_MC_IFETCH_TLBMULTI:
		tlbiel_all_lpid(vcpu->kvm->arch.radix);
		break;
	default:
		handled = 0;
	}

	return handled;
}

void kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
{
	struct machine_check_event mce_evt;
	long handled;

	if (vcpu->kvm->arch.fwnmi_enabled) {
		/* FWNMI guests handle their own recovery */
		handled = 0;
	} else {
		handled = kvmppc_realmode_mc_power7(vcpu);
	}

	/*
	 * Now get the event and stash it in the vcpu struct so it can
	 * be handled by the primary thread in virtual mode.  We can't
	 * call machine_check_queue_event() here if we are running on
	 * an offline secondary thread.
	 */
	if (get_mce_event(&mce_evt, MCE_EVENT_RELEASE)) {
		if (handled && mce_evt.version == MCE_V1)
			mce_evt.disposition = MCE_DISPOSITION_RECOVERED;
	} else {
		memset(&mce_evt, 0, sizeof(mce_evt));
	}

	vcpu->arch.mce_evt = mce_evt;
}


long kvmppc_p9_realmode_hmi_handler(struct kvm_vcpu *vcpu)
{
	struct kvmppc_vcore *vc = vcpu->arch.vcore;
	long ret = 0;

	/*
	 * Unapply and clear the offset first. That way, if the TB was not
	 * resynced then it will remain in host-offset, and if it was resynced
	 * then it is brought into host-offset. Then the tb offset is
	 * re-applied before continuing with the KVM exit.
	 *
	 * This way, we don't need to actually know whether not OPAL resynced
	 * the timebase or do any of the complicated dance that the P7/8
	 * path requires.
	 */
	if (vc->tb_offset_applied) {
		u64 new_tb = mftb() - vc->tb_offset_applied;
		mtspr(SPRN_TBU40, new_tb);
		if ((mftb() & 0xffffff) < (new_tb & 0xffffff)) {
			new_tb += 0x1000000;
			mtspr(SPRN_TBU40, new_tb);
		}
		vc->tb_offset_applied = 0;
	}

	local_paca->hmi_irqs++;

	if (hmi_handle_debugtrig(NULL) >= 0) {
		ret = 1;
		goto out;
	}

	if (ppc_md.hmi_exception_early)
		ppc_md.hmi_exception_early(NULL);

Annotation

Implementation Notes