Skip to content

Commit

Permalink
Merge tag 'kvm-s390-20131211' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/kvms390/linux into kvm-next

Some further s390 patches for kvm-next.

Various improvements and bugfixes in the signal processor handling.
Document kvm support for diagnose (s390 hypercalls). And last but
not least, fix a bug in the s390 ioeventfd backend that was causing
us grief in scenarios with 4G+ memory.
  • Loading branch information
bonzini committed Dec 12, 2013
2 parents 6dfacad + ff1f3cb commit 6bb05ef
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Documentation/virtual/kvm/hypercalls.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ S390:
S390 uses diagnose instruction as hypercall (0x500) along with hypercall
number in R1.

For further information on the S390 diagnose call as supported by KVM,
refer to Documentation/virtual/kvm/s390-diag.txt.

PowerPC:
It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers.
Return value is placed in R3.
Expand Down
80 changes: 80 additions & 0 deletions Documentation/virtual/kvm/s390-diag.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
The s390 DIAGNOSE call on KVM
=============================

KVM on s390 supports the DIAGNOSE call for making hypercalls, both for
native hypercalls and for selected hypercalls found on other s390
hypervisors.

Note that bits are numbered as by the usual s390 convention (most significant
bit on the left).


General remarks
---------------

DIAGNOSE calls by the guest cause a mandatory intercept. This implies
all supported DIAGNOSE calls need to be handled by either KVM or its
userspace.

All DIAGNOSE calls supported by KVM use the RS-a format:

--------------------------------------
| '83' | R1 | R3 | B2 | D2 |
--------------------------------------
0 8 12 16 20 31

The second-operand address (obtained by the base/displacement calculation)
is not used to address data. Instead, bits 48-63 of this address specify
the function code, and bits 0-47 are ignored.

The supported DIAGNOSE function codes vary by the userspace used. For
DIAGNOSE function codes not specific to KVM, please refer to the
documentation for the s390 hypervisors defining them.


DIAGNOSE function code 'X'500' - KVM virtio functions
-----------------------------------------------------

If the function code specifies 0x500, various virtio-related functions
are performed.

General register 1 contains the virtio subfunction code. Supported
virtio subfunctions depend on KVM's userspace. Generally, userspace
provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).

Upon completion of the DIAGNOSE instruction, general register 2 contains
the function's return code, which is either a return code or a subcode
specific value.

Subcode 0 - s390-virtio notification and early console printk
Handled by userspace.

Subcode 1 - s390-virtio reset
Handled by userspace.

Subcode 2 - s390-virtio set status
Handled by userspace.

Subcode 3 - virtio-ccw notification
Handled by either userspace or KVM (ioeventfd case).

General register 2 contains a subchannel-identification word denoting
the subchannel of the virtio-ccw proxy device to be notified.

General register 3 contains the number of the virtqueue to be notified.

General register 4 contains a 64bit identifier for KVM usage (the
kvm_io_bus cookie). If general register 4 does not contain a valid
identifier, it is ignored.

After completion of the DIAGNOSE call, general register 2 may contain
a 64bit identifier (in the kvm_io_bus cookie case).

See also the virtio standard for a discussion of this hypercall.


DIAGNOSE function code 'X'501 - KVM breakpoint
----------------------------------------------

If the function code specifies 0x501, breakpoint functions may be performed.
This function code is handled by userspace.
2 changes: 2 additions & 0 deletions arch/s390/include/asm/sigp.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
#define SIGP_SENSE 1
#define SIGP_EXTERNAL_CALL 2
#define SIGP_EMERGENCY_SIGNAL 3
#define SIGP_START 4
#define SIGP_STOP 5
#define SIGP_RESTART 6
#define SIGP_STOP_AND_STORE_STATUS 9
#define SIGP_INITIAL_CPU_RESET 11
#define SIGP_SET_PREFIX 13
#define SIGP_STORE_STATUS_AT_ADDRESS 14
#define SIGP_SET_ARCHITECTURE 18
#define SIGP_COND_EMERGENCY_SIGNAL 19
#define SIGP_SENSE_RUNNING 21

/* SIGP condition codes */
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kvm/diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
* - gpr 4 contains the index on the bus (optionally)
*/
ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
vcpu->run->s.regs.gprs[2],
vcpu->run->s.regs.gprs[2] & 0xffffffff,
8, &vcpu->run->s.regs.gprs[3],
vcpu->run->s.regs.gprs[4]);

Expand Down
64 changes: 53 additions & 11 deletions arch/s390/kvm/sigp.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* handling interprocessor communication
*
* Copyright IBM Corp. 2008, 2009
* Copyright IBM Corp. 2008, 2013
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (version 2 only)
Expand Down Expand Up @@ -89,6 +89,37 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
return rc;
}

static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr,
u16 asn, u64 *reg)
{
struct kvm_vcpu *dst_vcpu = NULL;
const u64 psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT;
u16 p_asn, s_asn;
psw_t *psw;
u32 flags;

if (cpu_addr < KVM_MAX_VCPUS)
dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
if (!dst_vcpu)
return SIGP_CC_NOT_OPERATIONAL;
flags = atomic_read(&dst_vcpu->arch.sie_block->cpuflags);
psw = &dst_vcpu->arch.sie_block->gpsw;
p_asn = dst_vcpu->arch.sie_block->gcr[4] & 0xffff; /* Primary ASN */
s_asn = dst_vcpu->arch.sie_block->gcr[3] & 0xffff; /* Secondary ASN */

/* Deliver the emergency signal? */
if (!(flags & CPUSTAT_STOPPED)
|| (psw->mask & psw_int_mask) != psw_int_mask
|| ((flags & CPUSTAT_WAIT) && psw->addr != 0)
|| (!(flags & CPUSTAT_WAIT) && (asn == p_asn || asn == s_asn))) {
return __sigp_emergency(vcpu, cpu_addr);
} else {
*reg &= 0xffffffff00000000UL;
*reg |= SIGP_STATUS_INCORRECT_STATE;
return SIGP_CC_STATUS_STORED;
}
}

static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
{
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
Expand Down Expand Up @@ -332,7 +363,8 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
return rc;
}

static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
/* Test whether the destination CPU is available and not busy */
static int sigp_check_callable(struct kvm_vcpu *vcpu, u16 cpu_addr)
{
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
struct kvm_s390_local_interrupt *li;
Expand All @@ -351,9 +383,6 @@ static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
spin_lock_bh(&li->lock);
if (li->action_bits & ACTION_STOP_ON_STOP)
rc = SIGP_CC_BUSY;
else
VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
cpu_addr);
spin_unlock_bh(&li->lock);
out:
spin_unlock(&fi->lock);
Expand Down Expand Up @@ -417,25 +446,38 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
&vcpu->run->s.regs.gprs[r1]);
break;
case SIGP_COND_EMERGENCY_SIGNAL:
rc = __sigp_conditional_emergency(vcpu, cpu_addr, parameter,
&vcpu->run->s.regs.gprs[r1]);
break;
case SIGP_SENSE_RUNNING:
vcpu->stat.instruction_sigp_sense_running++;
rc = __sigp_sense_running(vcpu, cpu_addr,
&vcpu->run->s.regs.gprs[r1]);
break;
case SIGP_START:
rc = sigp_check_callable(vcpu, cpu_addr);
if (rc == SIGP_CC_ORDER_CODE_ACCEPTED)
rc = -EOPNOTSUPP; /* Handle START in user space */
break;
case SIGP_RESTART:
vcpu->stat.instruction_sigp_restart++;
rc = __sigp_restart(vcpu, cpu_addr);
if (rc == SIGP_CC_BUSY)
break;
/* user space must know about restart */
rc = sigp_check_callable(vcpu, cpu_addr);
if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) {
VCPU_EVENT(vcpu, 4,
"sigp restart %x to handle userspace",
cpu_addr);
/* user space must know about restart */
rc = -EOPNOTSUPP;
}
break;
default:
return -EOPNOTSUPP;
}

if (rc < 0)
return rc;

vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44;
kvm_s390_set_psw_cc(vcpu, rc);
return 0;
}

0 comments on commit 6bb05ef

Please sign in to comment.