Commit 61db97cc authored by Alexander Graf's avatar Alexander Graf Committed by Avi Kivity
Browse files

KVM: PPC: Emulate segment fault



Book3S_32 doesn't know about segment faults. It only knows about page faults.
So in order to know that we didn't map a segment, we need to fake segment
faults.

We do this by setting invalid segment registers to an invalid VSID and then
check for that VSID on normal page faults.

Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 97e49255
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -775,6 +775,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
	switch (exit_nr) {
	case BOOK3S_INTERRUPT_INST_STORAGE:
		vcpu->stat.pf_instruc++;

#ifdef CONFIG_PPC_BOOK3S_32
		/* We set segments as unused segments when invalidating them. So
		 * treat the respective fault as segment fault. */
		if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
		    == SR_INVALID) {
			kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
			r = RESUME_GUEST;
			break;
		}
#endif

		/* only care about PTEG not found errors, but leave NX alone */
		if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
			r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
@@ -799,6 +811,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
	{
		ulong dar = kvmppc_get_fault_dar(vcpu);
		vcpu->stat.pf_storage++;

#ifdef CONFIG_PPC_BOOK3S_32
		/* We set segments as unused segments when invalidating them. So
		 * treat the respective fault as segment fault. */
		if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
			kvmppc_mmu_map_segment(vcpu, dar);
			r = RESUME_GUEST;
			break;
		}
#endif

		/* The only case we need to handle is missing shadow PTEs */
		if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
			r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);