Commit 460ba21d authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

KVM: PPC: Permit SRR1 flags in more injected interrupt types



The prefix architecture in ISA v3.1 introduces a prefixed bit in SRR1
for many types of synchronous interrupts which is set when the interrupt
is caused by a prefixed instruction.

This requires KVM to be able to set this bit when injecting interrupts
into a guest. Plumb through the SRR1 "flags" argument to the core_queue
APIs where it's missing for this. For now they are set to 0, which is
no change.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
[mpe: Fixup kvmppc_core_queue_alignment() in booke.c]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230330103224.3589928-2-npiggin@gmail.com
parent 43d05c61
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -126,25 +126,34 @@ extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);

extern int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu);
extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu, ulong flags);

extern void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu,
					    ulong srr1_flags);
extern void kvmppc_core_queue_syscall(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags);
extern void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu,
				      ulong srr1_flags);
extern void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu,
					ulong srr1_flags);
extern void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu,
					  ulong srr1_flags);
extern void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu,
					  ulong srr1_flags);
extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                       struct kvm_interrupt *irq);
extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, ulong dear_flags,
					ulong esr_flags);
extern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
					ulong dear_flags,
					ulong esr_flags);
extern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
					   ulong srr1_flags,
					   ulong dar,
					   ulong dsisr);
extern void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
					   ulong esr_flags);
					   ulong srr1_flags);

extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);

+16 −16
Original line number Diff line number Diff line
@@ -188,10 +188,10 @@ void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
}
EXPORT_SYMBOL_GPL(kvmppc_book3s_queue_irqprio);

void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu, ulong flags)
void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu, ulong srr1_flags)
{
	/* might as well deliver this straight away */
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_MACHINE_CHECK, flags);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_MACHINE_CHECK, srr1_flags);
}
EXPORT_SYMBOL_GPL(kvmppc_core_queue_machine_check);

@@ -201,29 +201,29 @@ void kvmppc_core_queue_syscall(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL(kvmppc_core_queue_syscall);

void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong srr1_flags)
{
	/* might as well deliver this straight away */
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, flags);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, srr1_flags);
}
EXPORT_SYMBOL_GPL(kvmppc_core_queue_program);

void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu)
void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu, ulong srr1_flags)
{
	/* might as well deliver this straight away */
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, 0);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, srr1_flags);
}

void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu)
void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu, ulong srr1_flags)
{
	/* might as well deliver this straight away */
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_ALTIVEC, 0);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_ALTIVEC, srr1_flags);
}

void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu)
void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu, ulong srr1_flags)
{
	/* might as well deliver this straight away */
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_VSX, 0);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_VSX, srr1_flags);
}

void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
@@ -278,18 +278,18 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu)
	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL);
}

void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar,
				    ulong flags)
void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong srr1_flags,
				    ulong dar, ulong dsisr)
{
	kvmppc_set_dar(vcpu, dar);
	kvmppc_set_dsisr(vcpu, flags);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
	kvmppc_set_dsisr(vcpu, dsisr);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, srr1_flags);
}
EXPORT_SYMBOL_GPL(kvmppc_core_queue_data_storage);

void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong flags)
void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong srr1_flags)
{
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE, flags);
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE, srr1_flags);
}
EXPORT_SYMBOL_GPL(kvmppc_core_queue_inst_storage);

+4 −4
Original line number Diff line number Diff line
@@ -954,7 +954,7 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
	if (dsisr & DSISR_BADACCESS) {
		/* Reflect to the guest as DSI */
		pr_err("KVM: Got radix HV page fault with DSISR=%lx\n", dsisr);
		kvmppc_core_queue_data_storage(vcpu, ea, dsisr);
		kvmppc_core_queue_data_storage(vcpu, 0, ea, dsisr);
		return RESUME_GUEST;
	}

@@ -979,7 +979,7 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
			 * Bad address in guest page table tree, or other
			 * unusual error - reflect it to the guest as DSI.
			 */
			kvmppc_core_queue_data_storage(vcpu, ea, dsisr);
			kvmppc_core_queue_data_storage(vcpu, 0, ea, dsisr);
			return RESUME_GUEST;
		}
		return kvmppc_hv_emulate_mmio(vcpu, gpa, ea, writing);
@@ -988,8 +988,8 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
	if (memslot->flags & KVM_MEM_READONLY) {
		if (writing) {
			/* give the guest a DSI */
			kvmppc_core_queue_data_storage(vcpu, ea, DSISR_ISSTORE |
						       DSISR_PROTFAULT);
			kvmppc_core_queue_data_storage(vcpu, 0, ea,
					DSISR_ISSTORE | DSISR_PROTFAULT);
			return RESUME_GUEST;
		}
		kvm_ro = true;
+2 −2
Original line number Diff line number Diff line
@@ -1739,7 +1739,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
		}

		if (!(vcpu->arch.fault_dsisr & (DSISR_NOHPTE | DSISR_PROTFAULT))) {
			kvmppc_core_queue_data_storage(vcpu,
			kvmppc_core_queue_data_storage(vcpu, 0,
				vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
			r = RESUME_GUEST;
			break;
@@ -1757,7 +1757,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
		} else if (err == -1 || err == -2) {
			r = RESUME_PAGE_FAULT;
		} else {
			kvmppc_core_queue_data_storage(vcpu,
			kvmppc_core_queue_data_storage(vcpu, 0,
				vcpu->arch.fault_dar, err);
			r = RESUME_GUEST;
		}
+2 −2
Original line number Diff line number Diff line
@@ -1560,7 +1560,7 @@ static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu,
	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
		if (dsisr & (DSISR_PRTABLE_FAULT | DSISR_BADACCESS)) {
			/* unusual error -> reflect to the guest as a DSI */
			kvmppc_core_queue_data_storage(vcpu, ea, dsisr);
			kvmppc_core_queue_data_storage(vcpu, 0, ea, dsisr);
			return RESUME_GUEST;
		}

@@ -1570,7 +1570,7 @@ static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu,
	if (memslot->flags & KVM_MEM_READONLY) {
		if (writing) {
			/* Give the guest a DSI */
			kvmppc_core_queue_data_storage(vcpu, ea,
			kvmppc_core_queue_data_storage(vcpu, 0, ea,
					DSISR_ISSTORE | DSISR_PROTFAULT);
			return RESUME_GUEST;
		}
Loading