Commit 95ca2cb5 authored by Janosch Frank's avatar Janosch Frank Committed by Christian Borntraeger

KVM: s390: Add sthyi emulation

Store Hypervisor Information is an emulated z/VM instruction that
provides a guest with basic information about the layers it is running
on. This includes information about the cpu configuration of both the
machine and the lpar, as well as their names, machine model and
machine type. This information enables an application to determine the
maximum capacity of CPs and IFLs available to software.

The instruction is available whenever the facility bit 74 is set,
otherwise executing it results in an operation exception.

It is important to check the validity flags in the sections before
using data from any structure member. It is not guaranteed that all
members will be valid on all machines / machine configurations.
Signed-off-by: default avatarJanosch Frank <frankja@linux.vnet.ibm.com>
Reviewed-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent a2d57b35
...@@ -215,6 +215,16 @@ struct diag204_x_phys_cpu { ...@@ -215,6 +215,16 @@ struct diag204_x_phys_cpu {
char reserved3[80]; char reserved3[80];
} __packed; } __packed;
struct diag204_x_part_block {
struct diag204_x_part_hdr hdr;
struct diag204_x_cpu_info cpus[];
} __packed;
struct diag204_x_phys_block {
struct diag204_x_phys_hdr hdr;
struct diag204_x_phys_cpu cpus[];
} __packed;
int diag204(unsigned long subcode, unsigned long size, void *addr); int diag204(unsigned long subcode, unsigned long size, void *addr);
int diag224(void *ptr); int diag224(void *ptr);
#endif /* _ASM_S390_DIAG_H */ #endif /* _ASM_S390_DIAG_H */
...@@ -154,6 +154,7 @@ struct kvm_s390_sie_block { ...@@ -154,6 +154,7 @@ struct kvm_s390_sie_block {
#define LCTL_CR14 0x0002 #define LCTL_CR14 0x0002
__u16 lctl; /* 0x0044 */ __u16 lctl; /* 0x0044 */
__s16 icpua; /* 0x0046 */ __s16 icpua; /* 0x0046 */
#define ICTL_OPEREXC 0x80000000
#define ICTL_PINT 0x20000000 #define ICTL_PINT 0x20000000
#define ICTL_LPSW 0x00400000 #define ICTL_LPSW 0x00400000
#define ICTL_STCTL 0x00040000 #define ICTL_STCTL 0x00040000
...@@ -279,6 +280,7 @@ struct kvm_vcpu_stat { ...@@ -279,6 +280,7 @@ struct kvm_vcpu_stat {
u32 instruction_stfl; u32 instruction_stfl;
u32 instruction_tprot; u32 instruction_tprot;
u32 instruction_essa; u32 instruction_essa;
u32 instruction_sthyi;
u32 instruction_sigp_sense; u32 instruction_sigp_sense;
u32 instruction_sigp_sense_running; u32 instruction_sigp_sense_running;
u32 instruction_sigp_external_call; u32 instruction_sigp_external_call;
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
exit_code_ipa0(0xB2, 0x4c, "TAR"), \ exit_code_ipa0(0xB2, 0x4c, "TAR"), \
exit_code_ipa0(0xB2, 0x50, "CSP"), \ exit_code_ipa0(0xB2, 0x50, "CSP"), \
exit_code_ipa0(0xB2, 0x54, "MVPG"), \ exit_code_ipa0(0xB2, 0x54, "MVPG"), \
exit_code_ipa0(0xB2, 0x56, "STHYI"), \
exit_code_ipa0(0xB2, 0x58, "BSG"), \ exit_code_ipa0(0xB2, 0x58, "BSG"), \
exit_code_ipa0(0xB2, 0x5a, "BSA"), \ exit_code_ipa0(0xB2, 0x5a, "BSA"), \
exit_code_ipa0(0xB2, 0x5f, "CHSC"), \ exit_code_ipa0(0xB2, 0x5f, "CHSC"), \
......
...@@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch ...@@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch
ccflags-y := -Ivirt/kvm -Iarch/s390/kvm ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o
kvm-objs += diag.o gaccess.o guestdbg.o kvm-objs += diag.o gaccess.o guestdbg.o sthyi.o
obj-$(CONFIG_KVM) += kvm.o obj-$(CONFIG_KVM) += kvm.o
...@@ -355,6 +355,10 @@ static int handle_operexc(struct kvm_vcpu *vcpu) ...@@ -355,6 +355,10 @@ static int handle_operexc(struct kvm_vcpu *vcpu)
trace_kvm_s390_handle_operexc(vcpu, vcpu->arch.sie_block->ipa, trace_kvm_s390_handle_operexc(vcpu, vcpu->arch.sie_block->ipa,
vcpu->arch.sie_block->ipb); vcpu->arch.sie_block->ipb);
if (vcpu->arch.sie_block->ipa == 0xb256 &&
test_kvm_facility(vcpu->kvm, 74))
return handle_sthyi(vcpu);
return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
} }
......
...@@ -94,6 +94,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { ...@@ -94,6 +94,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "instruction_stsi", VCPU_STAT(instruction_stsi) }, { "instruction_stsi", VCPU_STAT(instruction_stsi) },
{ "instruction_stfl", VCPU_STAT(instruction_stfl) }, { "instruction_stfl", VCPU_STAT(instruction_stfl) },
{ "instruction_tprot", VCPU_STAT(instruction_tprot) }, { "instruction_tprot", VCPU_STAT(instruction_tprot) },
{ "instruction_sthyi", VCPU_STAT(instruction_sthyi) },
{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) }, { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
{ "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) }, { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
{ "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) }, { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
...@@ -1189,6 +1190,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) ...@@ -1189,6 +1190,9 @@ 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);
set_kvm_facility(kvm->arch.model.fac_mask, 74);
set_kvm_facility(kvm->arch.model.fac_list, 74);
kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid(); kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid();
kvm->arch.model.ibc = sclp.ibc & 0x0fff; kvm->arch.model.ibc = sclp.ibc & 0x0fff;
...@@ -1679,6 +1683,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) ...@@ -1679,6 +1683,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
} }
vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb; vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb;
vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE; vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
if (test_kvm_facility(vcpu->kvm, 74))
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
if (vcpu->kvm->arch.use_cmma) { if (vcpu->kvm->arch.use_cmma) {
rc = kvm_s390_vcpu_setup_cmma(vcpu); rc = kvm_s390_vcpu_setup_cmma(vcpu);
......
...@@ -250,6 +250,9 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); ...@@ -250,6 +250,9 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
/* implemented in sthyi.c */
int handle_sthyi(struct kvm_vcpu *vcpu);
/* implemented in kvm-s390.c */ /* implemented in kvm-s390.c */
void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod); void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod);
long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable); long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
......
This diff is collapsed.
...@@ -433,6 +433,26 @@ TRACE_EVENT(kvm_s390_handle_operexc, ...@@ -433,6 +433,26 @@ TRACE_EVENT(kvm_s390_handle_operexc,
icpt_insn_codes)) icpt_insn_codes))
); );
TRACE_EVENT(kvm_s390_handle_sthyi,
TP_PROTO(VCPU_PROTO_COMMON, u64 code, u64 addr),
TP_ARGS(VCPU_ARGS_COMMON, code, addr),
TP_STRUCT__entry(
VCPU_FIELD_COMMON
__field(u64, code)
__field(u64, addr)
),
TP_fast_assign(
VCPU_ASSIGN_COMMON
__entry->code = code;
__entry->addr = addr;
),
VCPU_TP_PRINTK("STHYI fc: %llu addr: %016llx",
__entry->code, __entry->addr)
);
#endif /* _TRACE_KVM_H */ #endif /* _TRACE_KVM_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
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