From: frank.blaschka@de.ibm.com
To: qemu-devel@nongnu.org, linux-s390@vger.kernel.org, kvm@vger.kernel.org
Cc: aik@ozlabs.ru, pbonzini@redhat.com, agraf@suse.de
Subject: [Qemu-devel] [RFC][patch 3/6] KVM: s390: Add GISA support
Date: Thu, 04 Sep 2014 12:52:26 +0200 [thread overview]
Message-ID: <20140904105337.081387456@de.ibm.com> (raw)
In-Reply-To: 20140904105223.336503578@de.ibm.com
[-- Attachment #1: 004-s390_kvm_gisa-3.16.patch --]
[-- Type: text/plain, Size: 10151 bytes --]
From: Frank Blaschka <frank.blaschka@de.ibm.com>
This patch adds GISA (Guest Interrupt State Area) support
to s390 kvm. GISA can be used for exitless interrupts. The
patch provides a set of functions for GISA related operations
like accessing GISA fields or registering ISCs for alert.
Exploiters of GISA will follow with additional patches.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
arch/s390/include/asm/kvm_host.h | 72 ++++++++++++++++
arch/s390/kvm/kvm-s390.c | 167 +++++++++++++++++++++++++++++++++++++++
arch/s390/kvm/kvm-s390.h | 28 ++++++
3 files changed, 265 insertions(+), 2 deletions(-)
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -129,11 +129,12 @@ struct kvm_s390_sie_block {
__u8 reserved60; /* 0x0060 */
__u8 ecb; /* 0x0061 */
__u8 ecb2; /* 0x0062 */
- __u8 reserved63[1]; /* 0x0063 */
+ __u8 ecb3; /* 0x0063 */
__u32 scaol; /* 0x0064 */
__u8 reserved68[4]; /* 0x0068 */
__u32 todpr; /* 0x006c */
- __u8 reserved70[32]; /* 0x0070 */
+ __u32 gd; /* 0x0070 */
+ __u8 reserved74[28]; /* 0x0074 */
psw_t gpsw; /* 0x0090 */
__u64 gg14; /* 0x00a0 */
__u64 gg15; /* 0x00a8 */
@@ -300,6 +301,70 @@ struct kvm_s390_interrupt_info {
#define ACTION_STORE_ON_STOP (1<<0)
#define ACTION_STOP_ON_STOP (1<<1)
+#define KVM_S390_GISA_FORMAT_0 0
+#define KVM_S390_GISA_FORMAT_1 1
+
+struct kvm_s390_gisa_f0 {
+ u32 next_alert;
+ u8 ipm;
+ u16 rsv0:14;
+ u16 g:1;
+ u16 c:1;
+ u8 iam;
+ u32 rsv1;
+ u32 count;
+} __packed;
+
+struct kvm_s390_gisa_f1 {
+ u32 next_alert;
+ u8 ipm;
+ u8 simm;
+ u8 nimm;
+ u8 iam;
+ u64 aisma;
+ u32 rsv0:6;
+ u32 g:1;
+ u32 c:1;
+ u32 rsv1:24;
+ u64 rsv2;
+ u32 count;
+} __packed;
+
+union kvm_s390_gisa {
+ struct kvm_s390_gisa_f0 f0;
+ struct kvm_s390_gisa_f1 f1;
+};
+
+struct kvm_s390_gait {
+ u32 gd;
+ u16 : 5;
+ u16 gisc : 3;
+ u16 rpu : 8;
+ u16 : 10;
+ u16 gaisbo : 6;
+ u64 gaisba;
+} __packed;
+
+struct kvm_s390_aifte {
+ u64 faisba;
+ u64 gaita;
+ u16 simm : 8;
+ u16 : 5;
+ u16 afi : 3;
+ u16 reserved1;
+ u16 reserved2;
+ u16 faal;
+} __packed;
+
+struct kvm_s390_gib {
+ u32 alo;
+ u32 reserved1;
+ u32 : 5;
+ u32 nisc : 3;
+ u32 : 24;
+ u8 reserverd2[20];
+} __packed;
+
struct kvm_s390_local_interrupt {
spinlock_t lock;
struct list_head list;
@@ -420,6 +485,9 @@ struct kvm_arch{
struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
wait_queue_head_t ipte_wq;
spinlock_t start_stop_lock;
+ union kvm_s390_gisa *gisa;
+ unsigned long iam;
+ atomic_t in_sie;
};
#define KVM_HVA_ERR_BAD (-1UL)
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -404,6 +404,16 @@ long kvm_arch_vm_ioctl(struct file *filp
return r;
}
+static u8 kvm_s390_gisa_get_alert_mask(struct kvm *kvm)
+{
+ return (u8)ACCESS_ONCE(kvm->arch.iam);
+}
+
+static void kvm_s390_gisa_set_alert_mask(struct kvm *kvm, u8 iam)
+{
+ xchg(&kvm->arch.iam, iam);
+}
+
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
int rc;
@@ -461,6 +471,14 @@ int kvm_arch_init_vm(struct kvm *kvm, un
kvm->arch.css_support = 0;
kvm->arch.use_irqchip = 0;
+ kvm->arch.gisa = (union kvm_s390_gisa *)get_zeroed_page(
+ GFP_KERNEL | GFP_DMA);
+ if (!kvm->arch.gisa)
+ goto out_nogmap;
+ kvm_s390_gisa_set_next_alert(kvm, (u32)(unsigned long)kvm->arch.gisa);
+ kvm_s390_gisa_set_alert_mask(kvm, 0);
+ atomic_set(&kvm->arch.in_sie, 0);
+
spin_lock_init(&kvm->arch.start_stop_lock);
return 0;
@@ -520,6 +538,7 @@ void kvm_arch_sync_events(struct kvm *kv
void kvm_arch_destroy_vm(struct kvm *kvm)
{
+ free_page((unsigned long)kvm->arch.gisa);
kvm_free_vcpus(kvm);
free_page((unsigned long)(kvm->arch.sca));
debug_unregister(kvm->arch.dbf);
@@ -656,6 +675,19 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
return rc;
}
+u32 kvm_s390_gisa_get_fmt(void)
+{
+ if (test_facility(70) || test_facility(72))
+ return KVM_S390_GISA_FORMAT_1;
+ else
+ return KVM_S390_GISA_FORMAT_0;
+}
+
+static u32 kvm_s390_build_gd(struct kvm *kvm)
+{
+ return (u32)(unsigned long)kvm->arch.gisa | kvm_s390_gisa_get_fmt();
+}
+
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
unsigned int id)
{
@@ -699,6 +731,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
vcpu->arch.local_int.float_int = &kvm->arch.float_int;
vcpu->arch.local_int.wq = &vcpu->wq;
vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
+ vcpu->arch.sie_block->gd = kvm_s390_build_gd(kvm);
rc = kvm_vcpu_init(vcpu, kvm, id);
if (rc)
@@ -749,6 +782,132 @@ void exit_sie_sync(struct kvm_vcpu *vcpu
exit_sie(vcpu);
}
+void kvm_s390_gisa_register_alert(struct kvm *kvm, u32 gisc)
+{
+ int bito = BITS_PER_BYTE * 7 + gisc;
+
+ set_bit(bito ^ (BITS_PER_LONG - 1), &kvm->arch.iam);
+}
+
+void kvm_s390_gisa_unregister_alert(struct kvm *kvm, u32 gisc)
+{
+ int bito = BITS_PER_BYTE * 7 + gisc;
+
+ clear_bit(bito ^ (BITS_PER_LONG - 1), &kvm->arch.iam);
+}
+
+u32 __kvm_s390_gisa_get_next_alert(union kvm_s390_gisa *gisa)
+{
+ return ACCESS_ONCE(gisa->f0.next_alert);
+}
+
+u32 kvm_s390_gisa_get_next_alert(struct kvm *kvm)
+{
+ return __kvm_s390_gisa_get_next_alert(
+ (union kvm_s390_gisa *)kvm->arch.gisa);
+}
+
+void __kvm_s390_gisa_set_next_alert(union kvm_s390_gisa *gisa, u32 val)
+{
+ xchg(&gisa->f0.next_alert, val);
+}
+
+void kvm_s390_gisa_set_next_alert(struct kvm *kvm, u32 val)
+{
+ __kvm_s390_gisa_set_next_alert(kvm->arch.gisa, val);
+}
+
+u8 kvm_s390_gisa_get_iam(struct kvm *kvm)
+{
+ return ACCESS_ONCE(kvm->arch.gisa->f0.iam);
+}
+
+void kvm_s390_gisa_set_iam(struct kvm *kvm, u8 iam)
+{
+ xchg(&kvm->arch.gisa->f0.iam, iam);
+}
+
+int kvm_s390_gisa_test_iam_gisc(struct kvm *kvm, u32 gisc)
+{
+ int bito = BITS_PER_BYTE * 7 + gisc;
+ unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+ return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u8 kvm_s390_gisa_get_ipm(struct kvm *kvm)
+{
+ return ACCESS_ONCE(kvm->arch.gisa->f0.ipm);
+}
+
+void kvm_s390_gisa_set_ipm(struct kvm *kvm, u8 ipm)
+{
+ xchg(&kvm->arch.gisa->f0.ipm, ipm);
+}
+
+int kvm_s390_gisa_test_ipm_gisc(struct kvm *kvm, u32 gisc)
+{
+ int bito = BITS_PER_BYTE * 4 + gisc;
+ unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+ return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+void kvm_s390_gisa_set_ipm_gisc(struct kvm *kvm, u32 gisc)
+{
+ int bito = gisc + 32;
+ unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+ set_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_g(struct kvm *kvm)
+{
+ u32 fmt, bito;
+ unsigned long *addr;
+
+ fmt = kvm_s390_gisa_get_fmt();
+ if (fmt == KVM_S390_GISA_FORMAT_0) {
+ addr = (unsigned long *)kvm->arch.gisa;
+ bito = BITS_PER_BYTE * 6 + 6;
+ } else {
+ addr = (unsigned long *)((u8 *)kvm->arch.gisa + 16);
+ bito = 6;
+ }
+
+ return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_c(struct kvm *kvm)
+{
+ u32 fmt, bito;
+ unsigned long *addr;
+
+ fmt = kvm_s390_gisa_get_fmt();
+ if (fmt == KVM_S390_GISA_FORMAT_0) {
+ addr = (unsigned long *)kvm->arch.gisa;
+ bito = BITS_PER_BYTE * 6 + 7;
+ } else {
+ addr = (unsigned long *)((u8 *)kvm->arch.gisa + 16);
+ bito = 7;
+ }
+
+ return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_count(struct kvm *kvm)
+{
+ u32 fmt, cnt;
+
+ fmt = kvm_s390_gisa_get_fmt();
+ if (fmt == KVM_S390_GISA_FORMAT_0)
+ cnt = ACCESS_ONCE(kvm->arch.gisa->f0.count);
+ else
+ cnt = ACCESS_ONCE(kvm->arch.gisa->f1.count);
+
+ return cnt;
+}
+
static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address)
{
int i;
@@ -1284,8 +1443,16 @@ static int __vcpu_run(struct kvm_vcpu *v
preempt_disable();
kvm_guest_enter();
preempt_enable();
+
+ atomic_inc(&vcpu->kvm->arch.in_sie);
+ kvm_s390_gisa_set_iam(vcpu->kvm, 0);
+
exit_reason = sie64a(vcpu->arch.sie_block,
vcpu->run->s.regs.gprs);
+ if (atomic_dec_and_test(&vcpu->kvm->arch.in_sie))
+ kvm_s390_gisa_set_iam(vcpu->kvm,
+ kvm_s390_gisa_get_alert_mask(vcpu->kvm));
+
kvm_guest_exit();
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -122,6 +122,17 @@ static inline u64 kvm_s390_get_base_disp
return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
}
+static inline u64 kvm_s390_get_base_disp_rxy(struct kvm_vcpu *vcpu)
+{
+ u32 x2 = (vcpu->arch.sie_block->ipa & 0x000f);
+ u32 base2 = vcpu->arch.sie_block->ipb >> 28;
+ u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
+ ((vcpu->arch.sie_block->ipb & 0xff00) << 4);
+
+ return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) +
+ (x2 ? vcpu->run->s.regs.gprs[x2] : 0) + (u64)disp2;
+}
+
/* Set the condition code in the guest program status word */
static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
{
@@ -180,6 +191,23 @@ void exit_sie(struct kvm_vcpu *vcpu);
void exit_sie_sync(struct kvm_vcpu *vcpu);
int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
+u32 kvm_s390_gisa_get_fmt(void);
+void kvm_s390_gisa_register_alert(struct kvm *kvm, u32 gisc);
+void kvm_s390_gisa_unregister_alert(struct kvm *kvm, u32 gisc);
+u32 __kvm_s390_gisa_get_next_alert(union kvm_s390_gisa *gisa);
+u32 kvm_s390_gisa_get_next_alert(struct kvm *kvm);
+void __kvm_s390_gisa_set_next_alert(union kvm_s390_gisa *gisa, u32 val);
+void kvm_s390_gisa_set_next_alert(struct kvm *kvm, u32 val);
+u8 kvm_s390_gisa_get_iam(struct kvm *kvm);
+void kvm_s390_gisa_set_iam(struct kvm *kvm, u8 value);
+int kvm_s390_gisa_test_iam_gisc(struct kvm *kvm, u32 gisc);
+u8 kvm_s390_gisa_get_ipm(struct kvm *kvm);
+void kvm_s390_gisa_set_ipm(struct kvm *kvm, u8 value);
+int kvm_s390_gisa_test_ipm_gisc(struct kvm *kvm, u32 gisc);
+void kvm_s390_gisa_set_ipm_gisc(struct kvm *kvm, u32 gisc);
+u32 kvm_s390_gisa_get_g(struct kvm *kvm);
+u32 kvm_s390_gisa_get_c(struct kvm *kvm);
+u32 kvm_s390_gisa_get_count(struct kvm *kvm);
/* is cmma enabled */
bool kvm_s390_cmma_enabled(struct kvm *kvm);
int test_vfacility(unsigned long nr);
next prev parent reply other threads:[~2014-09-04 10:54 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-04 10:52 [Qemu-devel] [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390 frank.blaschka
2014-09-04 10:52 ` [Qemu-devel] [RFC][patch 1/6] s390: cio: chsc function to register GIB frank.blaschka
2014-09-04 10:52 ` [Qemu-devel] [RFC][patch 2/6] s390: pci: export pci functions for pass-through usage frank.blaschka
2014-09-04 10:52 ` frank.blaschka [this message]
2014-09-04 14:19 ` [Qemu-devel] [RFC][patch 3/6] KVM: s390: Add GISA support Heiko Carstens
2014-09-05 8:29 ` Alexander Graf
2014-09-05 10:52 ` Frank Blaschka
2014-09-04 10:52 ` [Qemu-devel] [RFC][patch 4/6] KVM: s390: Add PCI pass-through support frank.blaschka
2014-09-05 8:37 ` Alexander Graf
2014-09-04 10:52 ` [Qemu-devel] [RFC][patch 5/6] s390: Add PCI bus support frank.blaschka
2014-09-04 10:52 ` [Qemu-devel] [RFC][patch 6/6] s390: Add PCI pass-through device support frank.blaschka
2014-09-04 13:16 ` [Qemu-devel] [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390 Alex Williamson
2014-09-05 7:46 ` Frank Blaschka
2014-09-05 8:35 ` Alexander Graf
2014-09-05 11:55 ` Frank Blaschka
2014-09-05 23:03 ` Alexander Graf
2014-09-05 8:21 ` Alexander Graf
2014-09-05 11:39 ` Frank Blaschka
2014-09-05 23:19 ` Alexander Graf
2014-09-08 9:20 ` Paolo Bonzini
2014-09-08 14:19 ` Alex Williamson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140904105337.081387456@de.ibm.com \
--to=frank.blaschka@de.ibm.com \
--cc=agraf@suse.de \
--cc=aik@ozlabs.ru \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).