Commit 78c4b59f authored by Michael Mueller's avatar Michael Mueller Committed by Paolo Bonzini

KVM: s390: declare virtual HW facilities

The patch renames the array holding the HW facility bitmaps.
This allows to interprete the variable as set of virtual
machine specific "virtual" facilities. The basic idea is
to make virtual facilities externally managable in future.
An availability test for virtual facilites has been added
as well.
Signed-off-by: default avatarMichael Mueller <mimu@linux.vnet.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent ee6ee55b
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/facility.h>
#include <asm/sclp.h> #include <asm/sclp.h>
#include "kvm-s390.h" #include "kvm-s390.h"
#include "gaccess.h" #include "gaccess.h"
...@@ -84,9 +85,15 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { ...@@ -84,9 +85,15 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL } { NULL }
}; };
static unsigned long long *facilities; unsigned long *vfacilities;
static struct gmap_notifier gmap_notifier; static struct gmap_notifier gmap_notifier;
/* test availability of vfacility */
static inline int test_vfacility(unsigned long nr)
{
return __test_facility(nr, (void *) vfacilities);
}
/* Section: not file related */ /* Section: not file related */
int kvm_arch_hardware_enable(void *garbage) int kvm_arch_hardware_enable(void *garbage)
{ {
...@@ -387,7 +394,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) ...@@ -387,7 +394,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->ecb = 6; vcpu->arch.sie_block->ecb = 6;
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) facilities; vcpu->arch.sie_block->fac = (int) (long) vfacilities;
hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
(unsigned long) vcpu); (unsigned long) vcpu);
...@@ -1126,20 +1133,20 @@ static int __init kvm_s390_init(void) ...@@ -1126,20 +1133,20 @@ static int __init kvm_s390_init(void)
* to hold the maximum amount of facilities. On the other hand, we * to hold the maximum amount of facilities. On the other hand, we
* only set facilities that are known to work in KVM. * only set facilities that are known to work in KVM.
*/ */
facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); vfacilities = (unsigned long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
if (!facilities) { if (!vfacilities) {
kvm_exit(); kvm_exit();
return -ENOMEM; return -ENOMEM;
} }
memcpy(facilities, S390_lowcore.stfle_fac_list, 16); memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16);
facilities[0] &= 0xff82fff3f47c0000ULL; vfacilities[0] &= 0xff82fff3f47c0000UL;
facilities[1] &= 0x001c000000000000ULL; vfacilities[1] &= 0x001c000000000000UL;
return 0; return 0;
} }
static void __exit kvm_s390_exit(void) static void __exit kvm_s390_exit(void)
{ {
free_page((unsigned long) facilities); free_page((unsigned long) vfacilities);
kvm_exit(); kvm_exit();
} }
......
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu); typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
/* declare vfacilities extern */
extern unsigned long *vfacilities;
/* negativ values are error codes, positive values for internal conditions */ /* negativ values are error codes, positive values for internal conditions */
#define SIE_INTERCEPT_RERUNVCPU (1<<0) #define SIE_INTERCEPT_RERUNVCPU (1<<0)
#define SIE_INTERCEPT_UCONTROL (1<<1) #define SIE_INTERCEPT_UCONTROL (1<<1)
......
...@@ -227,7 +227,6 @@ static int handle_io_inst(struct kvm_vcpu *vcpu) ...@@ -227,7 +227,6 @@ static int handle_io_inst(struct kvm_vcpu *vcpu)
static int handle_stfl(struct kvm_vcpu *vcpu) static int handle_stfl(struct kvm_vcpu *vcpu)
{ {
unsigned int facility_list;
int rc; int rc;
vcpu->stat.instruction_stfl++; vcpu->stat.instruction_stfl++;
...@@ -235,15 +234,13 @@ static int handle_stfl(struct kvm_vcpu *vcpu) ...@@ -235,15 +234,13 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
/* only pass the facility bits, which we can handle */
facility_list = S390_lowcore.stfl_fac_list & 0xff82fff3;
rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
&facility_list, sizeof(facility_list)); vfacilities, 4);
if (rc) if (rc)
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
VCPU_EVENT(vcpu, 5, "store facility list value %x", facility_list); VCPU_EVENT(vcpu, 5, "store facility list value %x",
trace_kvm_s390_handle_stfl(vcpu, facility_list); *(unsigned int *) vfacilities);
trace_kvm_s390_handle_stfl(vcpu, *(unsigned int *) vfacilities);
return 0; return 0;
} }
......
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