Commit c760f5e2 authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvm-s390-20140117' of...

Merge tag 'kvm-s390-20140117' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into kvm-queue

This deals with 2 guest features that need enablement in the kvm host:
- transactional execution
- lpp sampling support

In addition there is also a fix to the virtio-ccw guest driver. This will
enable future features
parents 0dc3fd02 19e4735b
...@@ -106,9 +106,22 @@ struct kvm_s390_sie_block { ...@@ -106,9 +106,22 @@ struct kvm_s390_sie_block {
__u64 gbea; /* 0x0180 */ __u64 gbea; /* 0x0180 */
__u8 reserved188[24]; /* 0x0188 */ __u8 reserved188[24]; /* 0x0188 */
__u32 fac; /* 0x01a0 */ __u32 fac; /* 0x01a0 */
__u8 reserved1a4[92]; /* 0x01a4 */ __u8 reserved1a4[68]; /* 0x01a4 */
__u64 itdba; /* 0x01e8 */
__u8 reserved1f0[16]; /* 0x01f0 */
} __attribute__((packed)); } __attribute__((packed));
struct kvm_s390_itdb {
__u8 data[256];
} __packed;
struct sie_page {
struct kvm_s390_sie_block sie_block;
__u8 reserved200[1024]; /* 0x0200 */
struct kvm_s390_itdb itdb; /* 0x0600 */
__u8 reserved700[2304]; /* 0x0700 */
} __packed;
struct kvm_vcpu_stat { struct kvm_vcpu_stat {
u32 exit_userspace; u32 exit_userspace;
u32 exit_null; u32 exit_null;
......
...@@ -112,6 +112,17 @@ static int handle_instruction(struct kvm_vcpu *vcpu) ...@@ -112,6 +112,17 @@ static int handle_instruction(struct kvm_vcpu *vcpu)
static int handle_prog(struct kvm_vcpu *vcpu) static int handle_prog(struct kvm_vcpu *vcpu)
{ {
vcpu->stat.exit_program_interruption++; vcpu->stat.exit_program_interruption++;
/* Restore ITDB to Program-Interruption TDB in guest memory */
if (IS_TE_ENABLED(vcpu) &&
!(current->thread.per_flags & PER_FLAG_NO_TE) &&
IS_ITDB_VALID(vcpu)) {
copy_to_guest(vcpu, TDB_ADDR, vcpu->arch.sie_block->itdba,
sizeof(struct kvm_s390_itdb));
memset((void *) vcpu->arch.sie_block->itdba, 0,
sizeof(struct kvm_s390_itdb));
}
trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc); trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc);
return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc); return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc);
} }
......
...@@ -395,6 +395,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) ...@@ -395,6 +395,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
CPUSTAT_STOPPED | CPUSTAT_STOPPED |
CPUSTAT_GED); CPUSTAT_GED);
vcpu->arch.sie_block->ecb = 6; vcpu->arch.sie_block->ecb = 6;
if (test_vfacility(50) && test_vfacility(73))
vcpu->arch.sie_block->ecb |= 0x10;
vcpu->arch.sie_block->ecb2 = 8; vcpu->arch.sie_block->ecb2 = 8;
vcpu->arch.sie_block->eca = 0xC1002001U; vcpu->arch.sie_block->eca = 0xC1002001U;
vcpu->arch.sie_block->fac = (int) (long) vfacilities; vcpu->arch.sie_block->fac = (int) (long) vfacilities;
...@@ -411,6 +414,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, ...@@ -411,6 +414,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
unsigned int id) unsigned int id)
{ {
struct kvm_vcpu *vcpu; struct kvm_vcpu *vcpu;
struct sie_page *sie_page;
int rc = -EINVAL; int rc = -EINVAL;
if (id >= KVM_MAX_VCPUS) if (id >= KVM_MAX_VCPUS)
...@@ -422,12 +426,13 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, ...@@ -422,12 +426,13 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
if (!vcpu) if (!vcpu)
goto out; goto out;
vcpu->arch.sie_block = (struct kvm_s390_sie_block *) sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL);
get_zeroed_page(GFP_KERNEL); if (!sie_page)
if (!vcpu->arch.sie_block)
goto out_free_cpu; goto out_free_cpu;
vcpu->arch.sie_block = &sie_page->sie_block;
vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
vcpu->arch.sie_block->icpua = id; vcpu->arch.sie_block->icpua = id;
if (!kvm_is_ucontrol(kvm)) { if (!kvm_is_ucontrol(kvm)) {
if (!kvm->arch.sca) { if (!kvm->arch.sca) {
...@@ -1182,8 +1187,8 @@ static int __init kvm_s390_init(void) ...@@ -1182,8 +1187,8 @@ static int __init kvm_s390_init(void)
return -ENOMEM; return -ENOMEM;
} }
memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16);
vfacilities[0] &= 0xff82fff3f47c0000UL; vfacilities[0] &= 0xff82fff3f4fc2000UL;
vfacilities[1] &= 0x001c000000000000UL; vfacilities[1] &= 0x005c000000000000UL;
return 0; return 0;
} }
......
...@@ -26,6 +26,12 @@ extern unsigned long *vfacilities; ...@@ -26,6 +26,12 @@ extern unsigned long *vfacilities;
int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
/* Transactional Memory Execution related macros */
#define IS_TE_ENABLED(vcpu) ((vcpu->arch.sie_block->ecb & 0x10))
#define TDB_ADDR 0x1800UL
#define TDB_FORMAT1 1
#define IS_ITDB_VALID(vcpu) ((*(char *)vcpu->arch.sie_block->itdba == TDB_FORMAT1))
#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
do { \ do { \
debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \ debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \
......
...@@ -642,8 +642,15 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, ...@@ -642,8 +642,15 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) { (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) {
/* OK */ /* OK */
} }
if (irb_is_error(irb)) if (irb_is_error(irb)) {
vcdev->err = -EIO; /* XXX - use real error */ /* Command reject? */
if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
(irb->ecw[0] & SNS0_CMD_REJECT))
vcdev->err = -EOPNOTSUPP;
else
/* Map everything else to -EIO. */
vcdev->err = -EIO;
}
if (vcdev->curr_io & activity) { if (vcdev->curr_io & activity) {
switch (activity) { switch (activity) {
case VIRTIO_CCW_DOING_READ_FEAT: case VIRTIO_CCW_DOING_READ_FEAT:
......
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