mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iQIcBAABAgAGBQJXMID5AAoJEBF7vIC1phx8CfIP/1HVUvuD1mKTQVXMNEaC0CVK hi31MqFXe2/PQRX+s6T25XYHtKyDKnVoZeXl94iVvHOB0lmz8AgfwBOuWewr4beM NF73TVhWYq3QidIEg0usFKrVt08SDvZoyBNTH0kGeplQpDhaRC233/oTl6fFO/UQ 5YUK9wnUXHuovYHbqvST0xRkRu8xjxEa7JgJCQqPHQLLmbDTe88XyTSSWDfe+xUe COcgVJgyKOJDDqgrEcYwcsoOxfKKapRSeKq7nq6IJYEGB2JrwyVtb9JRIIHMnXYl 1tYVy4gtIP64UeyXJ3IM1OfU3fjKJYVHBIRZONGSo2P60XqVsqQ9z8OstGwbHoPM XOEga5X54ir+Im9sJfJK4vDBzBjnFagQnhohUgs2dPg/S4uxuulSU9hdr9iQhuhy 179uDZjwpOAMSo4qv8Mupa1WDhy4UeM9nsQICGrfmQPcyoJ/+2lQtTgkWYpbkr30 P3i+Yh0+aKEqdbb7Qog9Y8pAJyNSgy5++xR+5IeVcMfhtdl2YbsLH3WoKTanxPYB g28xsvhwsBF92DXAIrWq/gQcZIZr0z+U+ggwmZDXJ1xipIP1rME7wWZj3mXEo+2Z 0pWxTSsZO0HS9niJ1RFfJkkHuQ8X/hR9hzz3Lsy6NkfyqgcZVtVrkFkiuJ7OGAw/ Gcn4bkyYKkrICcpU5CeV =eTE9 -----END PGP SIGNATURE----- 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:
commit
6ac0f61f47
@ -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
|
||||
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.
|
||||
----------------------
|
||||
|
@ -544,10 +544,6 @@ struct kvm_vcpu_arch {
|
||||
struct kvm_s390_local_interrupt local_int;
|
||||
struct hrtimer ckc_timer;
|
||||
struct kvm_s390_pgm_info pgm;
|
||||
union {
|
||||
struct cpuid cpu_id;
|
||||
u64 stidp_data;
|
||||
};
|
||||
struct gmap *gmap;
|
||||
struct kvm_guestdbg_info_arch guestdbg;
|
||||
unsigned long pfault_token;
|
||||
@ -605,7 +601,7 @@ struct kvm_s390_cpu_model {
|
||||
__u64 fac_mask[S390_ARCH_FAC_LIST_SIZE_U64];
|
||||
/* facility list requested by guest (in dma page) */
|
||||
__u64 *fac_list;
|
||||
struct cpuid cpu_id;
|
||||
u64 cpuid;
|
||||
unsigned short ibc;
|
||||
};
|
||||
|
||||
|
@ -69,6 +69,7 @@ struct sclp_info {
|
||||
unsigned int max_cores;
|
||||
unsigned long hsa_size;
|
||||
unsigned long facilities;
|
||||
unsigned int hmfai;
|
||||
};
|
||||
extern struct sclp_info sclp;
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
/* SIGP cpu status bits */
|
||||
|
||||
#define SIGP_STATUS_INVALID_ORDER 0x00000002UL
|
||||
#define SIGP_STATUS_CHECK_STOP 0x00000010UL
|
||||
#define SIGP_STATUS_STOPPED 0x00000040UL
|
||||
#define SIGP_STATUS_EXT_CALL_PENDING 0x00000080UL
|
||||
|
@ -118,9 +118,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
|
||||
};
|
||||
|
||||
/* upper facilities limit for kvm */
|
||||
unsigned long kvm_s390_fac_list_mask[] = {
|
||||
0xffe6fffbfcfdfc40UL,
|
||||
0x005e800000000000UL,
|
||||
unsigned long kvm_s390_fac_list_mask[16] = {
|
||||
0xffe6000000000000UL,
|
||||
0x005e000000000000UL,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
struct kvm_s390_vm_cpu_processor *proc;
|
||||
u16 lowest_ibc, unblocked_ibc;
|
||||
int ret = 0;
|
||||
|
||||
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,
|
||||
sizeof(*proc))) {
|
||||
memcpy(&kvm->arch.model.cpu_id, &proc->cpuid,
|
||||
sizeof(struct cpuid));
|
||||
kvm->arch.model.ibc = proc->ibc;
|
||||
kvm->arch.model.cpuid = proc->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;
|
||||
}
|
||||
memcpy(kvm->arch.model.fac_list, proc->fac_list,
|
||||
S390_ARCH_FAC_LIST_SIZE_BYTE);
|
||||
} else
|
||||
@ -687,7 +696,7 @@ static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
ret = -ENOMEM;
|
||||
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;
|
||||
memcpy(&proc->fac_list, kvm->arch.model.fac_list,
|
||||
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;
|
||||
}
|
||||
|
||||
static void kvm_s390_get_cpu_id(struct cpuid *cpu_id)
|
||||
static u64 kvm_s390_get_initial_cpuid(void)
|
||||
{
|
||||
get_cpu_id(cpu_id);
|
||||
cpu_id->version = 0xff;
|
||||
struct cpuid cpuid;
|
||||
|
||||
get_cpu_id(&cpuid);
|
||||
cpuid.version = 0xff;
|
||||
return *((u64 *) &cpuid);
|
||||
}
|
||||
|
||||
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,
|
||||
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_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;
|
||||
|
||||
vcpu->arch.cpu_id = model->cpu_id;
|
||||
vcpu->arch.sie_block->ibc = model->ibc;
|
||||
if (test_kvm_facility(vcpu->kvm, 7))
|
||||
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);
|
||||
|
||||
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))
|
||||
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;
|
||||
if (sclp.has_siif)
|
||||
vcpu->arch.sie_block->eca |= 1;
|
||||
@ -2971,13 +2985,26 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!sclp.has_sief2) {
|
||||
pr_info("SIE not available\n");
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ static int handle_lpswe(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;
|
||||
int rc;
|
||||
ar_t ar;
|
||||
@ -670,8 +670,9 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
|
||||
if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||
|
||||
/* Only provide non-quiescing support if the host supports it */
|
||||
if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && !test_facility(14))
|
||||
/* Only provide non-quiescing support if enabled for the guest */
|
||||
if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ &&
|
||||
!test_kvm_facility(vcpu->kvm, 14))
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||
|
||||
/* No support for conditional-SSKE */
|
||||
@ -744,7 +745,7 @@ static int handle_essa(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/* entries expected to be 1FF */
|
||||
int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
|
||||
unsigned long *cbrlo, cbrle;
|
||||
unsigned long *cbrlo;
|
||||
struct gmap *gmap;
|
||||
int i;
|
||||
|
||||
@ -765,17 +766,9 @@ static int handle_essa(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.sie_block->cbrlo &= PAGE_MASK; /* reset nceo */
|
||||
cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
|
||||
down_read(&gmap->mm->mmap_sem);
|
||||
for (i = 0; i < entries; ++i) {
|
||||
cbrle = cbrlo[i];
|
||||
if (unlikely(cbrle & ~PAGE_MASK || cbrle < 2 * PAGE_SIZE))
|
||||
/* invalid entry */
|
||||
break;
|
||||
/* try to free backing */
|
||||
__gmap_zap(gmap, cbrle);
|
||||
}
|
||||
for (i = 0; i < entries; ++i)
|
||||
__gmap_zap(gmap, cbrlo[i]);
|
||||
up_read(&gmap->mm->mmap_sem);
|
||||
if (i < entries)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -240,6 +240,12 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu,
|
||||
struct kvm_s390_local_interrupt *li;
|
||||
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;
|
||||
if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
|
||||
/* running */
|
||||
|
@ -49,7 +49,9 @@ struct read_info_sccb {
|
||||
u8 _pad_117[119 - 117]; /* 117-118 */
|
||||
u8 fac119; /* 119 */
|
||||
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);
|
||||
|
||||
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_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0;
|
||||
sclp.mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0;
|
||||
|
||||
sclp.hmfai = sccb->hmfai;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user