mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-05 05:42:36 +00:00
[S390] s390-kvm: leave sie context on work. Removes preemption requirement
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>
This commit is contained in:
parent
2688905e6a
commit
0eaeafa10f
5 changed files with 34 additions and 6 deletions
|
@ -607,14 +607,37 @@ io_restore_trace_psw:
|
||||||
#endif
|
#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:
|
io_work:
|
||||||
tm SP_PSW+1(%r15),0x01 # returning to user ?
|
tm SP_PSW+1(%r15),0x01 # returning to user ?
|
||||||
#ifndef CONFIG_PREEMPT
|
#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
|
jno io_restore # no-> skip resched & signal
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
jnz io_work_user # yes -> do resched & signal
|
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
|
# check for preemptive scheduling
|
||||||
icm %r0,15,__TI_precount(%r9)
|
icm %r0,15,__TI_precount(%r9)
|
||||||
jnz io_restore # preemption is disabled
|
jnz io_restore # preemption is disabled
|
||||||
|
@ -652,6 +675,11 @@ io_work_loop:
|
||||||
j io_restore
|
j io_restore
|
||||||
io_work_done:
|
io_work_done:
|
||||||
|
|
||||||
|
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
|
||||||
|
sie_opcode:
|
||||||
|
.long 0xb2140000
|
||||||
|
#endif
|
||||||
|
|
||||||
#
|
#
|
||||||
# _TIF_MCCK_PENDING is set, call handler
|
# _TIF_MCCK_PENDING is set, call handler
|
||||||
#
|
#
|
||||||
|
|
|
@ -22,7 +22,6 @@ config KVM
|
||||||
select PREEMPT_NOTIFIERS
|
select PREEMPT_NOTIFIERS
|
||||||
select ANON_INODES
|
select ANON_INODES
|
||||||
select S390_SWITCH_AMODE
|
select S390_SWITCH_AMODE
|
||||||
select PREEMPT
|
|
||||||
---help---
|
---help---
|
||||||
Support hosting paravirtualized guest machines using the SIE
|
Support hosting paravirtualized guest machines using the SIE
|
||||||
virtualization capability on the mainframe. This should work
|
virtualization capability on the mainframe. This should work
|
||||||
|
|
|
@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = {
|
||||||
static int handle_noop(struct kvm_vcpu *vcpu)
|
static int handle_noop(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
switch (vcpu->arch.sie_block->icptcode) {
|
switch (vcpu->arch.sie_block->icptcode) {
|
||||||
|
case 0x0:
|
||||||
|
vcpu->stat.exit_null++;
|
||||||
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
vcpu->stat.exit_external_request++;
|
vcpu->stat.exit_external_request++;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
struct kvm_stats_debugfs_item debugfs_entries[] = {
|
struct kvm_stats_debugfs_item debugfs_entries[] = {
|
||||||
{ "userspace_handled", VCPU_STAT(exit_userspace) },
|
{ "userspace_handled", VCPU_STAT(exit_userspace) },
|
||||||
|
{ "exit_null", VCPU_STAT(exit_null) },
|
||||||
{ "exit_validity", VCPU_STAT(exit_validity) },
|
{ "exit_validity", VCPU_STAT(exit_validity) },
|
||||||
{ "exit_stop_request", VCPU_STAT(exit_stop_request) },
|
{ "exit_stop_request", VCPU_STAT(exit_stop_request) },
|
||||||
{ "exit_external_request", VCPU_STAT(exit_external_request) },
|
{ "exit_external_request", VCPU_STAT(exit_external_request) },
|
||||||
|
@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||||
vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
|
vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
|
||||||
restore_fp_regs(&vcpu->arch.guest_fpregs);
|
restore_fp_regs(&vcpu->arch.guest_fpregs);
|
||||||
restore_access_regs(vcpu->arch.guest_acrs);
|
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)
|
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||||
|
|
|
@ -104,6 +104,7 @@ struct sie_block {
|
||||||
|
|
||||||
struct kvm_vcpu_stat {
|
struct kvm_vcpu_stat {
|
||||||
u32 exit_userspace;
|
u32 exit_userspace;
|
||||||
|
u32 exit_null;
|
||||||
u32 exit_external_request;
|
u32 exit_external_request;
|
||||||
u32 exit_external_interrupt;
|
u32 exit_external_interrupt;
|
||||||
u32 exit_stop_request;
|
u32 exit_stop_request;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue