KVM: PPC: Emulate trap SRR1 flags properly
Book3S needs some flags in SRR1 to get to know details about an interrupt. One such example is the trap instruction. It tells the guest kernel that a program interrupt is due to a trap using a bit in SRR1. This patch implements above behavior, making WARN_ON behave like WARN_ON. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
021ec9c69f
commit
25a8a02d26
|
@ -91,6 +91,7 @@ struct kvmppc_vcpu_book3s {
|
|||
u64 vsid_next;
|
||||
u64 vsid_max;
|
||||
int context_id;
|
||||
ulong prog_flags; /* flags to inject when giving a 700 trap */
|
||||
};
|
||||
|
||||
#define CONTEXT_HOST 0
|
||||
|
|
|
@ -80,7 +80,7 @@ extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);
|
|||
|
||||
extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
|
||||
extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
|
||||
extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu);
|
||||
extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong 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,
|
||||
|
|
|
@ -426,6 +426,10 @@
|
|||
#define SRR1_WAKEMT 0x00280000 /* mtctrl */
|
||||
#define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */
|
||||
#define SRR1_WAKETHERM 0x00100000 /* Thermal management interrupt */
|
||||
#define SRR1_PROGFPE 0x00100000 /* Floating Point Enabled */
|
||||
#define SRR1_PROGPRIV 0x00040000 /* Privileged instruction */
|
||||
#define SRR1_PROGTRAP 0x00020000 /* Trap */
|
||||
#define SRR1_PROGADDR 0x00010000 /* SRR0 contains subsequent addr */
|
||||
#define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */
|
||||
#define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */
|
||||
|
||||
|
|
|
@ -168,8 +168,9 @@ void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
|
|||
}
|
||||
|
||||
|
||||
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
|
||||
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
|
||||
{
|
||||
to_book3s(vcpu)->prog_flags = flags;
|
||||
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM);
|
||||
}
|
||||
|
||||
|
@ -198,6 +199,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
|||
{
|
||||
int deliver = 1;
|
||||
int vec = 0;
|
||||
ulong flags = 0ULL;
|
||||
|
||||
switch (priority) {
|
||||
case BOOK3S_IRQPRIO_DECREMENTER:
|
||||
|
@ -231,6 +233,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
|||
break;
|
||||
case BOOK3S_IRQPRIO_PROGRAM:
|
||||
vec = BOOK3S_INTERRUPT_PROGRAM;
|
||||
flags = to_book3s(vcpu)->prog_flags;
|
||||
break;
|
||||
case BOOK3S_IRQPRIO_VSX:
|
||||
vec = BOOK3S_INTERRUPT_VSX;
|
||||
|
@ -261,7 +264,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
|||
#endif
|
||||
|
||||
if (deliver)
|
||||
kvmppc_inject_interrupt(vcpu, vec, 0ULL);
|
||||
kvmppc_inject_interrupt(vcpu, vec, flags);
|
||||
|
||||
return deliver;
|
||||
}
|
||||
|
|
|
@ -82,8 +82,9 @@ static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
|
|||
set_bit(priority, &vcpu->arch.pending_exceptions);
|
||||
}
|
||||
|
||||
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
|
||||
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
|
||||
{
|
||||
/* BookE does flags in ESR, so ignore those we get here */
|
||||
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
|
|||
#else
|
||||
vcpu->arch.esr |= ESR_PTR;
|
||||
#endif
|
||||
kvmppc_core_queue_program(vcpu);
|
||||
kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
|
||||
advance = 0;
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue