Skip to content

Commit

Permalink
[S390] s390-kvm: leave sie context on work. Removes preemption requir…
Browse files Browse the repository at this point in the history
…ement

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

This patch fixes a bug with cpu bound guest on kvm-s390. Sometimes it
was impossible to deliver a signal to a spinning guest. We used
preemption as a circumvention. The preemption notifiers called
vcpu_load, which checked for pending signals and triggered a host
intercept. But even with preemption, a sigkill was not delivered
immediately.

This patch changes the low level host interrupt handler to check for the
SIE  instruction, if TIF_WORK is set. In that case we change the
instruction pointer of the return PSW to rerun the vcpu_run loop. The kvm
code sees an intercept reason 0 if that happens. This patch adds accounting
for these types of intercept as well.

The advantages:
- works with and without preemption
- signals are delivered immediately
- much better host latencies without preemption

Acked-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Christian Borntraeger authored and Martin Schwidefsky committed May 7, 2008
1 parent 2688905 commit 0eaeafa
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 6 deletions.
30 changes: 29 additions & 1 deletion arch/s390/kernel/entry64.S
Original file line number Diff line number Diff line change
Expand Up @@ -607,14 +607,37 @@ io_restore_trace_psw:
#endif

#
# switch to kernel stack, then check TIF bits
# There is work todo, we need to check if we return to userspace, then
# check, if we are in SIE, if yes leave it
#
io_work:
tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifndef CONFIG_PREEMPT
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
jnz io_work_user # yes -> no need to check for SIE
la %r1, BASED(sie_opcode) # we return to kernel here
lg %r2, SP_PSW+8(%r15)
clc 0(2,%r1), 0(%r2) # is current instruction = SIE?
jne io_restore # no-> return to kernel
lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE
aghi %r1, 4
stg %r1, SP_PSW+8(%r15)
j io_restore # return to kernel
#else
jno io_restore # no-> skip resched & signal
#endif
#else
jnz io_work_user # yes -> do resched & signal
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
la %r1, BASED(sie_opcode)
lg %r2, SP_PSW+8(%r15)
clc 0(2,%r1), 0(%r2) # is current instruction = SIE?
jne 0f # no -> leave PSW alone
lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE
aghi %r1, 4
stg %r1, SP_PSW+8(%r15)
0:
#endif
# check for preemptive scheduling
icm %r0,15,__TI_precount(%r9)
jnz io_restore # preemption is disabled
Expand Down Expand Up @@ -652,6 +675,11 @@ io_work_loop:
j io_restore
io_work_done:

#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
sie_opcode:
.long 0xb2140000
#endif

#
# _TIF_MCCK_PENDING is set, call handler
#
Expand Down
1 change: 0 additions & 1 deletion arch/s390/kvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ config KVM
select PREEMPT_NOTIFIERS
select ANON_INODES
select S390_SWITCH_AMODE
select PREEMPT
---help---
Support hosting paravirtualized guest machines using the SIE
virtualization capability on the mainframe. This should work
Expand Down
3 changes: 3 additions & 0 deletions arch/s390/kvm/intercept.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = {
static int handle_noop(struct kvm_vcpu *vcpu)
{
switch (vcpu->arch.sie_block->icptcode) {
case 0x0:
vcpu->stat.exit_null++;
break;
case 0x10:
vcpu->stat.exit_external_request++;
break;
Expand Down
5 changes: 1 addition & 4 deletions arch/s390/kvm/kvm-s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "userspace_handled", VCPU_STAT(exit_userspace) },
{ "exit_null", VCPU_STAT(exit_null) },
{ "exit_validity", VCPU_STAT(exit_validity) },
{ "exit_stop_request", VCPU_STAT(exit_stop_request) },
{ "exit_external_request", VCPU_STAT(exit_external_request) },
Expand Down Expand Up @@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
restore_fp_regs(&vcpu->arch.guest_fpregs);
restore_access_regs(vcpu->arch.guest_acrs);

if (signal_pending(current))
atomic_set_mask(CPUSTAT_STOP_INT,
&vcpu->arch.sie_block->cpuflags);
}

void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
Expand Down
1 change: 1 addition & 0 deletions include/asm-s390/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ struct sie_block {

struct kvm_vcpu_stat {
u32 exit_userspace;
u32 exit_null;
u32 exit_external_request;
u32 exit_external_interrupt;
u32 exit_stop_request;
Expand Down

0 comments on commit 0eaeafa

Please sign in to comment.