Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 616dff86 authored by Alexander Graf's avatar Alexander Graf
Browse files

KVM: PPC: Book3S PR: Handle Facility interrupt and FSCR



POWER8 introduced a new interrupt type called "Facility unavailable interrupt"
which contains its status message in a new register called FSCR.

Handle these exits and try to emulate instructions for unhandled facilities.
Follow-on patches enable KVM to expose specific facilities into the guest.

Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent a5948fa0
Loading
Loading
Loading
Loading
+10 −8
Original line number Original line Diff line number Diff line
@@ -102,6 +102,7 @@
#define BOOK3S_INTERRUPT_PERFMON	0xf00
#define BOOK3S_INTERRUPT_PERFMON	0xf00
#define BOOK3S_INTERRUPT_ALTIVEC	0xf20
#define BOOK3S_INTERRUPT_ALTIVEC	0xf20
#define BOOK3S_INTERRUPT_VSX		0xf40
#define BOOK3S_INTERRUPT_VSX		0xf40
#define BOOK3S_INTERRUPT_FAC_UNAVAIL	0xf60
#define BOOK3S_INTERRUPT_H_FAC_UNAVAIL	0xf80
#define BOOK3S_INTERRUPT_H_FAC_UNAVAIL	0xf80


#define BOOK3S_IRQPRIO_SYSTEM_RESET		0
#define BOOK3S_IRQPRIO_SYSTEM_RESET		0
@@ -114,14 +115,15 @@
#define BOOK3S_IRQPRIO_FP_UNAVAIL		7
#define BOOK3S_IRQPRIO_FP_UNAVAIL		7
#define BOOK3S_IRQPRIO_ALTIVEC			8
#define BOOK3S_IRQPRIO_ALTIVEC			8
#define BOOK3S_IRQPRIO_VSX			9
#define BOOK3S_IRQPRIO_VSX			9
#define BOOK3S_IRQPRIO_SYSCALL			10
#define BOOK3S_IRQPRIO_FAC_UNAVAIL		10
#define BOOK3S_IRQPRIO_MACHINE_CHECK		11
#define BOOK3S_IRQPRIO_SYSCALL			11
#define BOOK3S_IRQPRIO_DEBUG			12
#define BOOK3S_IRQPRIO_MACHINE_CHECK		12
#define BOOK3S_IRQPRIO_EXTERNAL			13
#define BOOK3S_IRQPRIO_DEBUG			13
#define BOOK3S_IRQPRIO_DECREMENTER		14
#define BOOK3S_IRQPRIO_EXTERNAL			14
#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR	15
#define BOOK3S_IRQPRIO_DECREMENTER		15
#define BOOK3S_IRQPRIO_EXTERNAL_LEVEL		16
#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR	16
#define BOOK3S_IRQPRIO_MAX			17
#define BOOK3S_IRQPRIO_EXTERNAL_LEVEL		17
#define BOOK3S_IRQPRIO_MAX			18


#define BOOK3S_HFLAG_DCBZ32			0x1
#define BOOK3S_HFLAG_DCBZ32			0x1
#define BOOK3S_HFLAG_SLB			0x2
#define BOOK3S_HFLAG_SLB			0x2
+2 −0
Original line number Original line Diff line number Diff line
@@ -104,6 +104,7 @@ struct kvmppc_host_state {
#ifdef CONFIG_PPC_BOOK3S_64
#ifdef CONFIG_PPC_BOOK3S_64
	u64 cfar;
	u64 cfar;
	u64 ppr;
	u64 ppr;
	u64 host_fscr;
#endif
#endif
};
};


@@ -133,6 +134,7 @@ struct kvmppc_book3s_shadow_vcpu {
		u64     esid;
		u64     esid;
		u64     vsid;
		u64     vsid;
	} slb[64];			/* guest SLB */
	} slb[64];			/* guest SLB */
	u64 shadow_fscr;
#endif
#endif
};
};


+1 −0
Original line number Original line Diff line number Diff line
@@ -475,6 +475,7 @@ struct kvm_vcpu_arch {
	ulong ppr;
	ulong ppr;
	ulong pspb;
	ulong pspb;
	ulong fscr;
	ulong fscr;
	ulong shadow_fscr;
	ulong ebbhr;
	ulong ebbhr;
	ulong ebbrr;
	ulong ebbrr;
	ulong bescr;
	ulong bescr;
+3 −0
Original line number Original line Diff line number Diff line
@@ -537,6 +537,7 @@ int main(void)
	DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar));
	DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar));
	DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
	DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
	DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
	DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
	DEFINE(VCPU_SHADOW_FSCR, offsetof(struct kvm_vcpu, arch.shadow_fscr));
	DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
	DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
	DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
	DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
	DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
	DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
@@ -618,6 +619,7 @@ int main(void)
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
	SVCPU_FIELD(SVCPU_SLB, slb);
	SVCPU_FIELD(SVCPU_SLB, slb);
	SVCPU_FIELD(SVCPU_SLB_MAX, slb_max);
	SVCPU_FIELD(SVCPU_SLB_MAX, slb_max);
	SVCPU_FIELD(SVCPU_SHADOW_FSCR, shadow_fscr);
#endif
#endif


	HSTATE_FIELD(HSTATE_HOST_R1, host_r1);
	HSTATE_FIELD(HSTATE_HOST_R1, host_r1);
@@ -653,6 +655,7 @@ int main(void)
#ifdef CONFIG_PPC_BOOK3S_64
#ifdef CONFIG_PPC_BOOK3S_64
	HSTATE_FIELD(HSTATE_CFAR, cfar);
	HSTATE_FIELD(HSTATE_CFAR, cfar);
	HSTATE_FIELD(HSTATE_PPR, ppr);
	HSTATE_FIELD(HSTATE_PPR, ppr);
	HSTATE_FIELD(HSTATE_HOST_FSCR, host_fscr);
#endif /* CONFIG_PPC_BOOK3S_64 */
#endif /* CONFIG_PPC_BOOK3S_64 */


#else /* CONFIG_PPC_BOOK3S */
#else /* CONFIG_PPC_BOOK3S */
+10 −0
Original line number Original line Diff line number Diff line
@@ -145,6 +145,7 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
	case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG;		break;
	case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG;		break;
	case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC;		break;
	case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC;		break;
	case 0xf40: prio = BOOK3S_IRQPRIO_VSX;			break;
	case 0xf40: prio = BOOK3S_IRQPRIO_VSX;			break;
	case 0xf60: prio = BOOK3S_IRQPRIO_FAC_UNAVAIL;		break;
	default:    prio = BOOK3S_IRQPRIO_MAX;			break;
	default:    prio = BOOK3S_IRQPRIO_MAX;			break;
	}
	}


@@ -275,6 +276,9 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
	case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR:
	case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR:
		vec = BOOK3S_INTERRUPT_PERFMON;
		vec = BOOK3S_INTERRUPT_PERFMON;
		break;
		break;
	case BOOK3S_IRQPRIO_FAC_UNAVAIL:
		vec = BOOK3S_INTERRUPT_FAC_UNAVAIL;
		break;
	default:
	default:
		deliver = 0;
		deliver = 0;
		printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority);
		printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority);
@@ -627,6 +631,9 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
			val = get_reg_val(reg->id, kvmppc_xics_get_icp(vcpu));
			val = get_reg_val(reg->id, kvmppc_xics_get_icp(vcpu));
			break;
			break;
#endif /* CONFIG_KVM_XICS */
#endif /* CONFIG_KVM_XICS */
		case KVM_REG_PPC_FSCR:
			val = get_reg_val(reg->id, vcpu->arch.fscr);
			break;
		default:
		default:
			r = -EINVAL;
			r = -EINVAL;
			break;
			break;
@@ -716,6 +723,9 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
						set_reg_val(reg->id, val));
						set_reg_val(reg->id, val));
			break;
			break;
#endif /* CONFIG_KVM_XICS */
#endif /* CONFIG_KVM_XICS */
		case KVM_REG_PPC_FSCR:
			vcpu->arch.fscr = set_reg_val(reg->id, val);
			break;
		default:
		default:
			r = -EINVAL;
			r = -EINVAL;
			break;
			break;
Loading