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
This commit is contained in:
@@ -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 {
|
|||||||
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 {
|
|||||||
__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 {
|
|||||||
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 @@
|
|||||||
|
|
||||||
/* 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[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
/* 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)
|
|||||||
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,
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user