Commit 77cb7a3e authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvm-s390-next-4.8-3' of...

Merge tag 'kvm-s390-next-4.8-3' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: Fix for kvm/next (4.8) part 3

This contains a fix for PER ifetch events. As we now have a handler
for a problem state instruction (sthyi) that could be stepped with a
debugger we should try to do the right thing regarding PER in our
instruction handlers.  With this fix the handling for intercepted
instructions is fixed in general, thus fixing other oddball cases as
well (e.g. kprobes single stepping)
parents 03f6a22a 5ffe466c
...@@ -439,6 +439,23 @@ static int debug_exit_required(struct kvm_vcpu *vcpu) ...@@ -439,6 +439,23 @@ static int debug_exit_required(struct kvm_vcpu *vcpu)
#define guest_per_enabled(vcpu) \ #define guest_per_enabled(vcpu) \
(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER)
int kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu)
{
const u8 ilen = kvm_s390_get_ilen(vcpu);
struct kvm_s390_pgm_info pgm_info = {
.code = PGM_PER,
.per_code = PER_EVENT_IFETCH >> 24,
.per_address = __rewind_psw(vcpu->arch.sie_block->gpsw, ilen),
};
/*
* The PSW points to the next instruction, therefore the intercepted
* instruction generated a PER i-fetch event. PER address therefore
* points at the previous PSW address (could be an EXECUTE function).
*/
return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
}
static void filter_guest_per_event(struct kvm_vcpu *vcpu) static void filter_guest_per_event(struct kvm_vcpu *vcpu)
{ {
u32 perc = vcpu->arch.sie_block->perc << 24; u32 perc = vcpu->arch.sie_block->perc << 24;
......
...@@ -364,6 +364,8 @@ static int handle_operexc(struct kvm_vcpu *vcpu) ...@@ -364,6 +364,8 @@ static int handle_operexc(struct kvm_vcpu *vcpu)
int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
{ {
int rc, per_rc = 0;
if (kvm_is_ucontrol(vcpu->kvm)) if (kvm_is_ucontrol(vcpu->kvm))
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -372,7 +374,8 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) ...@@ -372,7 +374,8 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
case 0x18: case 0x18:
return handle_noop(vcpu); return handle_noop(vcpu);
case 0x04: case 0x04:
return handle_instruction(vcpu); rc = handle_instruction(vcpu);
break;
case 0x08: case 0x08:
return handle_prog(vcpu); return handle_prog(vcpu);
case 0x14: case 0x14:
...@@ -384,10 +387,18 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) ...@@ -384,10 +387,18 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
case 0x28: case 0x28:
return handle_stop(vcpu); return handle_stop(vcpu);
case 0x2c: case 0x2c:
return handle_operexc(vcpu); rc = handle_operexc(vcpu);
break;
case 0x38: case 0x38:
return handle_partial_execution(vcpu); rc = handle_partial_execution(vcpu);
break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
/* process PER, also if the instrution is processed in user space */
if (vcpu->arch.sie_block->icptstatus & 0x02 &&
(!rc || rc == -EOPNOTSUPP))
per_rc = kvm_s390_handle_per_ifetch_icpt(vcpu);
return per_rc ? per_rc : rc;
} }
...@@ -238,6 +238,8 @@ static inline void kvm_s390_forward_psw(struct kvm_vcpu *vcpu, int ilen) ...@@ -238,6 +238,8 @@ static inline void kvm_s390_forward_psw(struct kvm_vcpu *vcpu, int ilen)
} }
static inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu) static inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu)
{ {
/* don't inject PER events if we re-execute the instruction */
vcpu->arch.sie_block->icptstatus &= ~0x02;
kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu)); kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu));
} }
...@@ -377,6 +379,7 @@ int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu, ...@@ -377,6 +379,7 @@ int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg); struct kvm_guest_debug *dbg);
void kvm_s390_clear_bp_data(struct kvm_vcpu *vcpu); void kvm_s390_clear_bp_data(struct kvm_vcpu *vcpu);
void kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu); void kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu);
int kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu);
void kvm_s390_handle_per_event(struct kvm_vcpu *vcpu); void kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
/* support for Basic/Extended SCA handling */ /* support for Basic/Extended SCA handling */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment