Commit 6ac0f61f authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvm-s390-next-4.7-2' of...

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

KVM: s390: features and fixes for 4.7 part2

- Use hardware provided information about facility bits that do not
  need any hypervisor activitiy
- Add missing documentation for KVM_CAP_S390_RI
- Some updates/fixes for handling cpu models and facilities
parents 4ac33429 60a37709
...@@ -3788,6 +3788,14 @@ a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace. ...@@ -3788,6 +3788,14 @@ a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
Fails if VCPU has already been created, or if the irqchip is already in the Fails if VCPU has already been created, or if the irqchip is already in the
kernel (i.e. KVM_CREATE_IRQCHIP has already been called). kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
7.6 KVM_CAP_S390_RI
Architectures: s390
Parameters: none
Allows use of runtime-instrumentation introduced with zEC12 processor.
Will return -EINVAL if the machine does not support runtime-instrumentation.
Will return -EBUSY if a VCPU has already been created.
8. Other capabilities. 8. Other capabilities.
---------------------- ----------------------
......
...@@ -544,10 +544,6 @@ struct kvm_vcpu_arch { ...@@ -544,10 +544,6 @@ struct kvm_vcpu_arch {
struct kvm_s390_local_interrupt local_int; struct kvm_s390_local_interrupt local_int;
struct hrtimer ckc_timer; struct hrtimer ckc_timer;
struct kvm_s390_pgm_info pgm; struct kvm_s390_pgm_info pgm;
union {
struct cpuid cpu_id;
u64 stidp_data;
};
struct gmap *gmap; struct gmap *gmap;
struct kvm_guestdbg_info_arch guestdbg; struct kvm_guestdbg_info_arch guestdbg;
unsigned long pfault_token; unsigned long pfault_token;
...@@ -605,7 +601,7 @@ struct kvm_s390_cpu_model { ...@@ -605,7 +601,7 @@ struct kvm_s390_cpu_model {
__u64 fac_mask[S390_ARCH_FAC_LIST_SIZE_U64]; __u64 fac_mask[S390_ARCH_FAC_LIST_SIZE_U64];
/* facility list requested by guest (in dma page) */ /* facility list requested by guest (in dma page) */
__u64 *fac_list; __u64 *fac_list;
struct cpuid cpu_id; u64 cpuid;
unsigned short ibc; unsigned short ibc;
}; };
......
...@@ -69,6 +69,7 @@ struct sclp_info { ...@@ -69,6 +69,7 @@ struct sclp_info {
unsigned int max_cores; unsigned int max_cores;
unsigned long hsa_size; unsigned long hsa_size;
unsigned long facilities; unsigned long facilities;
unsigned int hmfai;
}; };
extern struct sclp_info sclp; extern struct sclp_info sclp;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
/* SIGP cpu status bits */ /* SIGP cpu status bits */
#define SIGP_STATUS_INVALID_ORDER 0x00000002UL
#define SIGP_STATUS_CHECK_STOP 0x00000010UL #define SIGP_STATUS_CHECK_STOP 0x00000010UL
#define SIGP_STATUS_STOPPED 0x00000040UL #define SIGP_STATUS_STOPPED 0x00000040UL
#define SIGP_STATUS_EXT_CALL_PENDING 0x00000080UL #define SIGP_STATUS_EXT_CALL_PENDING 0x00000080UL
......
...@@ -118,9 +118,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { ...@@ -118,9 +118,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
}; };
/* upper facilities limit for kvm */ /* upper facilities limit for kvm */
unsigned long kvm_s390_fac_list_mask[] = { unsigned long kvm_s390_fac_list_mask[16] = {
0xffe6fffbfcfdfc40UL, 0xffe6000000000000UL,
0x005e800000000000UL, 0x005e000000000000UL,
}; };
unsigned long kvm_s390_fac_list_mask_size(void) unsigned long kvm_s390_fac_list_mask_size(void)
...@@ -638,6 +638,7 @@ static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr) ...@@ -638,6 +638,7 @@ static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr)
static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr) static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
{ {
struct kvm_s390_vm_cpu_processor *proc; struct kvm_s390_vm_cpu_processor *proc;
u16 lowest_ibc, unblocked_ibc;
int ret = 0; int ret = 0;
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
...@@ -652,9 +653,17 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr) ...@@ -652,9 +653,17 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
} }
if (!copy_from_user(proc, (void __user *)attr->addr, if (!copy_from_user(proc, (void __user *)attr->addr,
sizeof(*proc))) { sizeof(*proc))) {
memcpy(&kvm->arch.model.cpu_id, &proc->cpuid, kvm->arch.model.cpuid = proc->cpuid;
sizeof(struct cpuid)); lowest_ibc = sclp.ibc >> 16 & 0xfff;
unblocked_ibc = sclp.ibc & 0xfff;
if (lowest_ibc) {
if (proc->ibc > unblocked_ibc)
kvm->arch.model.ibc = unblocked_ibc;
else if (proc->ibc < lowest_ibc)
kvm->arch.model.ibc = lowest_ibc;
else
kvm->arch.model.ibc = proc->ibc; kvm->arch.model.ibc = proc->ibc;
}
memcpy(kvm->arch.model.fac_list, proc->fac_list, memcpy(kvm->arch.model.fac_list, proc->fac_list,
S390_ARCH_FAC_LIST_SIZE_BYTE); S390_ARCH_FAC_LIST_SIZE_BYTE);
} else } else
...@@ -687,7 +696,7 @@ static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr) ...@@ -687,7 +696,7 @@ static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr)
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
memcpy(&proc->cpuid, &kvm->arch.model.cpu_id, sizeof(struct cpuid)); proc->cpuid = kvm->arch.model.cpuid;
proc->ibc = kvm->arch.model.ibc; proc->ibc = kvm->arch.model.ibc;
memcpy(&proc->fac_list, kvm->arch.model.fac_list, memcpy(&proc->fac_list, kvm->arch.model.fac_list,
S390_ARCH_FAC_LIST_SIZE_BYTE); S390_ARCH_FAC_LIST_SIZE_BYTE);
...@@ -1081,10 +1090,13 @@ static void kvm_s390_set_crycb_format(struct kvm *kvm) ...@@ -1081,10 +1090,13 @@ static void kvm_s390_set_crycb_format(struct kvm *kvm)
kvm->arch.crypto.crycbd |= CRYCB_FORMAT1; kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
} }
static void kvm_s390_get_cpu_id(struct cpuid *cpu_id) static u64 kvm_s390_get_initial_cpuid(void)
{ {
get_cpu_id(cpu_id); struct cpuid cpuid;
cpu_id->version = 0xff;
get_cpu_id(&cpuid);
cpuid.version = 0xff;
return *((u64 *) &cpuid);
} }
static void kvm_s390_crypto_init(struct kvm *kvm) static void kvm_s390_crypto_init(struct kvm *kvm)
...@@ -1175,7 +1187,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) ...@@ -1175,7 +1187,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask, memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask,
S390_ARCH_FAC_LIST_SIZE_BYTE); S390_ARCH_FAC_LIST_SIZE_BYTE);
kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id); kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid();
kvm->arch.model.ibc = sclp.ibc & 0x0fff; kvm->arch.model.ibc = sclp.ibc & 0x0fff;
kvm_s390_crypto_init(kvm); kvm_s390_crypto_init(kvm);
...@@ -1624,7 +1636,6 @@ static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu) ...@@ -1624,7 +1636,6 @@ static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu)
{ {
struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model; struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model;
vcpu->arch.cpu_id = model->cpu_id;
vcpu->arch.sie_block->ibc = model->ibc; vcpu->arch.sie_block->ibc = model->ibc;
if (test_kvm_facility(vcpu->kvm, 7)) if (test_kvm_facility(vcpu->kvm, 7))
vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list; vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list;
...@@ -1645,11 +1656,14 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) ...@@ -1645,11 +1656,14 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
kvm_s390_vcpu_setup_model(vcpu); kvm_s390_vcpu_setup_model(vcpu);
vcpu->arch.sie_block->ecb = 6; vcpu->arch.sie_block->ecb = 0x02;
if (test_kvm_facility(vcpu->kvm, 9))
vcpu->arch.sie_block->ecb |= 0x04;
if (test_kvm_facility(vcpu->kvm, 50) && test_kvm_facility(vcpu->kvm, 73)) if (test_kvm_facility(vcpu->kvm, 50) && test_kvm_facility(vcpu->kvm, 73))
vcpu->arch.sie_block->ecb |= 0x10; vcpu->arch.sie_block->ecb |= 0x10;
vcpu->arch.sie_block->ecb2 = 8; if (test_kvm_facility(vcpu->kvm, 8))
vcpu->arch.sie_block->ecb2 |= 0x08;
vcpu->arch.sie_block->eca = 0xC1002000U; vcpu->arch.sie_block->eca = 0xC1002000U;
if (sclp.has_siif) if (sclp.has_siif)
vcpu->arch.sie_block->eca |= 1; vcpu->arch.sie_block->eca |= 1;
...@@ -2971,13 +2985,26 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, ...@@ -2971,13 +2985,26 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
return; return;
} }
static inline unsigned long nonhyp_mask(int i)
{
unsigned int nonhyp_fai = (sclp.hmfai << i * 2) >> 30;
return 0x0000ffffffffffffUL >> (nonhyp_fai << 4);
}
static int __init kvm_s390_init(void) static int __init kvm_s390_init(void)
{ {
int i;
if (!sclp.has_sief2) { if (!sclp.has_sief2) {
pr_info("SIE not available\n"); pr_info("SIE not available\n");
return -ENODEV; return -ENODEV;
} }
for (i = 0; i < 16; i++)
kvm_s390_fac_list_mask[i] |=
S390_lowcore.stfle_fac_list[i] & nonhyp_mask(i);
return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
} }
......
...@@ -439,7 +439,7 @@ static int handle_lpswe(struct kvm_vcpu *vcpu) ...@@ -439,7 +439,7 @@ static int handle_lpswe(struct kvm_vcpu *vcpu)
static int handle_stidp(struct kvm_vcpu *vcpu) static int handle_stidp(struct kvm_vcpu *vcpu)
{ {
u64 stidp_data = vcpu->arch.stidp_data; u64 stidp_data = vcpu->kvm->arch.model.cpuid;
u64 operand2; u64 operand2;
int rc; int rc;
ar_t ar; ar_t ar;
...@@ -670,8 +670,9 @@ static int handle_pfmf(struct kvm_vcpu *vcpu) ...@@ -670,8 +670,9 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED) if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
/* Only provide non-quiescing support if the host supports it */ /* Only provide non-quiescing support if enabled for the guest */
if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && !test_facility(14)) if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ &&
!test_kvm_facility(vcpu->kvm, 14))
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
/* No support for conditional-SSKE */ /* No support for conditional-SSKE */
...@@ -744,7 +745,7 @@ static int handle_essa(struct kvm_vcpu *vcpu) ...@@ -744,7 +745,7 @@ static int handle_essa(struct kvm_vcpu *vcpu)
{ {
/* entries expected to be 1FF */ /* entries expected to be 1FF */
int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3; int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
unsigned long *cbrlo, cbrle; unsigned long *cbrlo;
struct gmap *gmap; struct gmap *gmap;
int i; int i;
...@@ -765,17 +766,9 @@ static int handle_essa(struct kvm_vcpu *vcpu) ...@@ -765,17 +766,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->cbrlo &= PAGE_MASK; /* reset nceo */ vcpu->arch.sie_block->cbrlo &= PAGE_MASK; /* reset nceo */
cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo); cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
down_read(&gmap->mm->mmap_sem); down_read(&gmap->mm->mmap_sem);
for (i = 0; i < entries; ++i) { for (i = 0; i < entries; ++i)
cbrle = cbrlo[i]; __gmap_zap(gmap, cbrlo[i]);
if (unlikely(cbrle & ~PAGE_MASK || cbrle < 2 * PAGE_SIZE))
/* invalid entry */
break;
/* try to free backing */
__gmap_zap(gmap, cbrle);
}
up_read(&gmap->mm->mmap_sem); up_read(&gmap->mm->mmap_sem);
if (i < entries)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
return 0; return 0;
} }
......
...@@ -240,6 +240,12 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, ...@@ -240,6 +240,12 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu,
struct kvm_s390_local_interrupt *li; struct kvm_s390_local_interrupt *li;
int rc; int rc;
if (!test_kvm_facility(vcpu->kvm, 9)) {
*reg &= 0xffffffff00000000UL;
*reg |= SIGP_STATUS_INVALID_ORDER;
return SIGP_CC_STATUS_STORED;
}
li = &dst_vcpu->arch.local_int; li = &dst_vcpu->arch.local_int;
if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) { if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
/* running */ /* running */
......
...@@ -49,7 +49,9 @@ struct read_info_sccb { ...@@ -49,7 +49,9 @@ struct read_info_sccb {
u8 _pad_117[119 - 117]; /* 117-118 */ u8 _pad_117[119 - 117]; /* 117-118 */
u8 fac119; /* 119 */ u8 fac119; /* 119 */
u16 hcpua; /* 120-121 */ u16 hcpua; /* 120-121 */
u8 _pad_122[4096 - 122]; /* 122-4095 */ u8 _pad_122[124 - 122]; /* 122-123 */
u32 hmfai; /* 124-127 */
u8 _pad_128[4096 - 128]; /* 128-4095 */
} __packed __aligned(PAGE_SIZE); } __packed __aligned(PAGE_SIZE);
static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata;
...@@ -155,6 +157,8 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb) ...@@ -155,6 +157,8 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
sclp.mtid = (sccb->fac42 & 0x80) ? (sccb->fac42 & 31) : 0; sclp.mtid = (sccb->fac42 & 0x80) ? (sccb->fac42 & 31) : 0;
sclp.mtid_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0; sclp.mtid_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0;
sclp.mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0; sclp.mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0;
sclp.hmfai = sccb->hmfai;
} }
/* /*
......
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