All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cornelia Huck <cornelia.huck@de.ibm.com>
To: Alexander Graf <agraf@suse.de>
Cc: qemu-devel <qemu-devel@nongnu.org>, KVM <kvm@vger.kernel.org>,
	linux-s390 <linux-s390@vger.kernel.org>,
	Marcelo Tosatti <mtosatti@redhat.com>,
	Gleb Natapov <gleb@redhat.com>,
	Anthony Liguori <aliguori@us.ibm.com>,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	Carsten Otte <cotte@de.ibm.com>,
	Heiko Carstens <heiko.carstens@de.ibm.com>,
	Martin Schwidefsky <schwidefsky@de.ibm.com>,
	Sebastian Ott <sebott@linux.vnet.ibm.com>
Subject: Re: [PATCH 6/8] s390: Wire up channel I/O in kvm.
Date: Mon, 10 Dec 2012 11:29:28 +0100	[thread overview]
Message-ID: <20121210112928.660d3d5b@BR9GNB5Z> (raw)
In-Reply-To: <F8BFFCBB-8137-4C48-BE74-43A9CE6387FA@suse.de>

On Mon, 10 Dec 2012 10:40:15 +0100
Alexander Graf <agraf@suse.de> wrote:

> 
> 
> On 07.12.2012, at 13:50, Cornelia Huck <cornelia.huck@de.ibm.com> wrote:
> 
> > Trigger the code for our virtual css in case of instruction
> > intercepts for I/O instructions.
> > 
> > Handle the tsch exit for the subchannel-related part of tsch.
> > 
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > ---
> > target-s390x/cpu.h |  11 +++
> > target-s390x/kvm.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++---
> > 2 files changed, 244 insertions(+), 13 deletions(-)
> > 
> > diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
> > index eb24c6b..1d21ca8 100644
> > --- a/target-s390x/cpu.h
> > +++ b/target-s390x/cpu.h
> > @@ -1178,6 +1178,13 @@ uint32_t set_cc_nz_f64(float64 v);
> > /* misc_helper.c */
> > void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
> > 
> > +#ifdef CONFIG_KVM
> > +int kvm_s390_io_interrupt(CPUS390XState *env, uint16_t subchannel_id,
> > +                          uint16_t subchannel_nr, uint32_t io_int_parm,
> > +                          uint32_t io_int_word);
> > +int kvm_s390_crw_mchk(CPUS390XState *env);
> > +void kvm_s390_enable_css_support(CPUS390XState *env);
> > +#else
> > static inline int kvm_s390_io_interrupt(CPUS390XState *env,
> >                                         uint16_t subchannel_id,
> >                                         uint16_t subchannel_nr,
> > @@ -1190,6 +1197,10 @@ static inline int kvm_s390_crw_mchk(CPUS390XState *env)
> > {
> >     return -EOPNOTSUPP;
> > }
> > +static inline void kvm_s390_enable_css_support(CPUS390XState *env)
> > +{
> > +}
> > +#endif
> > 
> > static inline void s390_io_interrupt(CPUS390XState *env,
> >                                      uint16_t subchannel_id,
> > diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
> > index 94de764..c9a4a7d 100644
> > --- a/target-s390x/kvm.c
> > +++ b/target-s390x/kvm.c
> > @@ -30,6 +30,7 @@
> > #include "kvm.h"
> > #include "cpu.h"
> > #include "device_tree.h"
> > +#include "ioinst.h"
> > 
> > /* #define DEBUG_KVM */
> > 
> > @@ -43,9 +44,27 @@
> > 
> > #define IPA0_DIAG                       0x8300
> > #define IPA0_SIGP                       0xae00
> > -#define IPA0_PRIV                       0xb200
> > +#define IPA0_B2                         0xb200
> > +#define IPA0_B9                         0xb900
> > +#define IPA0_EB                         0xeb00
> > 
> > #define PRIV_SCLP_CALL                  0x20
> > +#define PRIV_CSCH                       0x30
> > +#define PRIV_HSCH                       0x31
> > +#define PRIV_MSCH                       0x32
> > +#define PRIV_SSCH                       0x33
> > +#define PRIV_STSCH                      0x34
> > +#define PRIV_TSCH                       0x35
> > +#define PRIV_TPI                        0x36
> > +#define PRIV_SAL                        0x37
> > +#define PRIV_RSCH                       0x38
> > +#define PRIV_STCRW                      0x39
> > +#define PRIV_STCPS                      0x3a
> > +#define PRIV_RCHP                       0x3b
> > +#define PRIV_SCHM                       0x3c
> > +#define PRIV_CHSC                       0x5f
> > +#define PRIV_SIGA                       0x74
> > +#define PRIV_XSCH                       0x76
> > #define DIAG_KVM_HYPERCALL              0x500
> > #define DIAG_KVM_BREAKPOINT             0x501
> > 
> > @@ -350,10 +369,120 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
> >     return 0;
> > }
> > 
> > -static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
> > +static int kvm_handle_css_inst(CPUS390XState *env, struct kvm_run *run,
> > +                               uint8_t ipa0, uint8_t ipa1, uint8_t ipb)
> > +{
> > +    int r = 0;
> > +    int no_cc = 0;
> > +
> > +    if (ipa0 != 0xb2) {
> > +        /* Not handled for now. */
> > +        return -1;
> > +    }
> > +    cpu_synchronize_state(env);
> > +    switch (ipa1) {
> > +    case PRIV_XSCH:
> > +        r = ioinst_handle_xsch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_CSCH:
> > +        r = ioinst_handle_csch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_HSCH:
> > +        r = ioinst_handle_hsch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_MSCH:
> > +        r = ioinst_handle_msch(env, env->regs[1], run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_SSCH:
> > +        r = ioinst_handle_ssch(env, env->regs[1], run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_STCRW:
> > +        r = ioinst_handle_stcrw(env, run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_STSCH:
> > +        r = ioinst_handle_stsch(env, env->regs[1], run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_TSCH:
> > +        /* We should only get tsch via KVM_EXIT_S390_TSCH. */
> > +        fprintf(stderr, "Spurious tsch intercept\n");
> > +        break;
> > +    case PRIV_CHSC:
> > +        r = ioinst_handle_chsc(env, run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_TPI:
> > +        /* This should have been handled by kvm already. */
> > +        fprintf(stderr, "Spurious tpi intercept\n");
> > +        break;
> > +    case PRIV_SCHM:
> > +        no_cc = 1;
> > +        r = ioinst_handle_schm(env, env->regs[1], env->regs[2],
> > +                               run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_RSCH:
> > +        r = ioinst_handle_rsch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_RCHP:
> > +        r = ioinst_handle_rchp(env, env->regs[1]);
> > +        break;
> > +    case PRIV_STCPS:
> > +        /* We do not provide this instruction, it is suppressed. */
> > +        no_cc = 1;
> > +        r = 0;
> > +        break;
> > +    case PRIV_SAL:
> > +        no_cc = 1;
> > +        r = ioinst_handle_sal(env, env->regs[1]);
> > +        break;
> > +    default:
> > +        r = -1;
> > +        break;
> > +    }
> > +
> > +    if (r >= 0) {
> > +        if (!no_cc) {
> > +            setcc(env, r);
> > +        }
> > +        r = 0;
> > +    } else if (r < -1) {
> > +        r = 0;
> > +    }
> > +    return r;
> > +}
> > +
> > +static int is_ioinst(uint8_t ipa0, uint8_t ipa1, uint8_t ipb)
> > +{
> > +    int ret = 0;
> > +
> > +    switch (ipa0) {
> > +    case 0xb2:
> > +        if (((ipa1 >= 0x30) && (ipa1 <= 0x3c)) ||
> > +            (ipa1 == 0x5f) ||
> > +            (ipa1 == 0x74) ||
> > +            (ipa1 == 0x76)) {
> 
> Just make this a switch. You can the also use defines for the instruction names :).

I thought I could get away with ranges, but the I/O instructions are
unfortunately too dispersed. I'll change that to a switch and see how
that looks.

> 
> Alex
> 
> > +            ret = 1;
> > +        }
> > +        break;
> > +    case 0xb9:
> > +        if (ipa1 == 0x9c) {
> > +            ret = 1;
> > +        }
> > +        break;
> > +    case 0xeb:
> > +        if (ipb == 0x8a) {
> > +            ret = 1;
> > +        }
> > +        break;
> > +    }
> > +
> > +    return ret;
> > +}
> > +
> > +static int handle_priv(CPUS390XState *env, struct kvm_run *run,
> > +                       uint8_t ipa0, uint8_t ipa1)
> > {
> >     int r = 0;
> >     uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
> > +    uint8_t ipb = run->s390_sieic.ipb & 0xff;
> > 
> >     dprintf("KVM: PRIV: %d\n", ipa1);
> >     switch (ipa1) {
> > @@ -361,8 +490,16 @@ static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
> >             r = kvm_sclp_service_call(env, run, ipbh0);
> >             break;
> >         default:
> > -            dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
> > -            r = -1;
> > +            if (is_ioinst(ipa0, ipa1, ipb)) {
> > +                r = kvm_handle_css_inst(env, run, ipa0, ipa1, ipb);
> > +                if (r == -1) {
> > +                    setcc(env, 3);
> > +                    r = 0;
> > +                }
> > +            } else {
> > +                dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
> > +                r = -1;
> > +            }
> >             break;
> >     }
> > 
> > @@ -500,15 +637,17 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run)
> > 
> >     dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
> >     switch (ipa0) {
> > -        case IPA0_PRIV:
> > -            r = handle_priv(env, run, ipa1);
> > -            break;
> > -        case IPA0_DIAG:
> > -            r = handle_diag(env, run, ipb_code);
> > -            break;
> > -        case IPA0_SIGP:
> > -            r = handle_sigp(env, run, ipa1);
> > -            break;
> > +    case IPA0_B2:
> > +    case IPA0_B9:
> > +    case IPA0_EB:
> > +        r = handle_priv(env, run, ipa0 >> 8, ipa1);
> > +        break;
> > +    case IPA0_DIAG:
> > +        r = handle_diag(env, run, ipb_code);
> > +        break;
> > +    case IPA0_SIGP:
> > +        r = handle_sigp(env, run, ipa1);
> > +        break;
> >     }
> > 
> >     if (r < 0) {
> > @@ -565,6 +704,38 @@ static int handle_intercept(CPUS390XState *env)
> >     return r;
> > }
> > 
> > +static int handle_tsch(CPUS390XState *env, struct kvm_run *run, int dequeued,
> > +                       uint16_t subchannel_id, uint16_t subchannel_nr,
> > +                       uint32_t io_int_parm, uint32_t io_int_word)
> > +{
> > +    int ret;
> > +
> > +    cpu_synchronize_state(env);
> > +    ret = ioinst_handle_tsch(env, env->regs[1], run->s390_tsch.ipb);
> > +    if (ret >= 0) {
> > +        /* Success; set condition code. */
> > +        setcc(env, ret);
> > +        ret = 0;
> > +    } else if (ret < -1) {
> > +        /*
> > +         * Failure.
> > +         * If an I/O interrupt had been dequeued, we have to reinject it.
> > +         */
> > +        if (dequeued) {
> > +            uint32_t type = ((subchannel_id & 0xff00) << 24) |
> > +                ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16);
> > +
> > +            kvm_s390_interrupt_internal(env, type,
> > +                                        ((uint32_t)subchannel_id << 16)
> > +                                        | subchannel_nr,
> > +                                        ((uint64_t)io_int_parm << 32)
> > +                                        | io_int_word, 1);
> > +        }
> > +        ret = 0;
> > +    }
> > +    return ret;
> > +}
> > +
> > int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
> > {
> >     int ret = 0;
> > @@ -576,6 +747,13 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
> >         case KVM_EXIT_S390_RESET:
> >             qemu_system_reset_request();
> >             break;
> > +        case KVM_EXIT_S390_TSCH:
> > +            ret = handle_tsch(env, run, run->s390_tsch.dequeued,
> > +                              run->s390_tsch.subchannel_id,
> > +                              run->s390_tsch.subchannel_nr,
> > +                              run->s390_tsch.io_int_parm,
> > +                              run->s390_tsch.io_int_word);
> > +            break;
> >         default:
> >             fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
> >             break;
> > @@ -601,3 +779,45 @@ int kvm_arch_on_sigbus(int code, void *addr)
> > {
> >     return 1;
> > }
> > +
> > +int kvm_s390_io_interrupt(CPUS390XState *env, uint16_t subchannel_id,
> > +                          uint16_t subchannel_nr, uint32_t io_int_parm,
> > +                          uint32_t io_int_word)
> > +{
> > +    uint32_t type;
> > +
> > +    if (!kvm_enabled()) {
> > +        return -EOPNOTSUPP;
> > +    }
> > +
> > +    type = ((subchannel_id & 0xff00) << 24) |
> > +        ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16);
> > +    kvm_s390_interrupt_internal(env, type,
> > +                                ((uint32_t)subchannel_id << 16) | subchannel_nr,
> > +                                ((uint64_t)io_int_parm << 32) | io_int_word, 1);
> > +    return 0;
> > +}
> > +
> > +int kvm_s390_crw_mchk(CPUS390XState *env)
> > +{
> > +    if (!kvm_enabled()) {
> > +        return -EOPNOTSUPP;
> > +    }
> > +
> > +    kvm_s390_interrupt_internal(env, KVM_S390_MCHK, 1 << 28,
> > +                                0x00400f1d40330000, 1);
> > +    return 0;
> > +}
> > +
> > +void kvm_s390_enable_css_support(CPUS390XState *env)
> > +{
> > +    struct kvm_enable_cap cap = {};
> > +    int r;
> > +
> > +    /* Activate host kernel channel subsystem support. */
> > +    if (kvm_enabled()) {
> > +        cap.cap = KVM_CAP_S390_CSS_SUPPORT;
> > +        r = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
> > +        assert(r == 0);
> > +    }
> > +}
> > -- 
> > 1.7.12.4
> > 
> 

WARNING: multiple messages have this Message-ID (diff)
From: Cornelia Huck <cornelia.huck@de.ibm.com>
To: Alexander Graf <agraf@suse.de>
Cc: linux-s390 <linux-s390@vger.kernel.org>,
	Anthony Liguori <aliguori@us.ibm.com>, KVM <kvm@vger.kernel.org>,
	Gleb Natapov <gleb@redhat.com>, Carsten Otte <cotte@de.ibm.com>,
	Sebastian Ott <sebott@linux.vnet.ibm.com>,
	Marcelo Tosatti <mtosatti@redhat.com>,
	Heiko Carstens <heiko.carstens@de.ibm.com>,
	qemu-devel <qemu-devel@nongnu.org>,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	Martin Schwidefsky <schwidefsky@de.ibm.com>
Subject: Re: [Qemu-devel] [PATCH 6/8] s390: Wire up channel I/O in kvm.
Date: Mon, 10 Dec 2012 11:29:28 +0100	[thread overview]
Message-ID: <20121210112928.660d3d5b@BR9GNB5Z> (raw)
In-Reply-To: <F8BFFCBB-8137-4C48-BE74-43A9CE6387FA@suse.de>

On Mon, 10 Dec 2012 10:40:15 +0100
Alexander Graf <agraf@suse.de> wrote:

> 
> 
> On 07.12.2012, at 13:50, Cornelia Huck <cornelia.huck@de.ibm.com> wrote:
> 
> > Trigger the code for our virtual css in case of instruction
> > intercepts for I/O instructions.
> > 
> > Handle the tsch exit for the subchannel-related part of tsch.
> > 
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > ---
> > target-s390x/cpu.h |  11 +++
> > target-s390x/kvm.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++---
> > 2 files changed, 244 insertions(+), 13 deletions(-)
> > 
> > diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
> > index eb24c6b..1d21ca8 100644
> > --- a/target-s390x/cpu.h
> > +++ b/target-s390x/cpu.h
> > @@ -1178,6 +1178,13 @@ uint32_t set_cc_nz_f64(float64 v);
> > /* misc_helper.c */
> > void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
> > 
> > +#ifdef CONFIG_KVM
> > +int kvm_s390_io_interrupt(CPUS390XState *env, uint16_t subchannel_id,
> > +                          uint16_t subchannel_nr, uint32_t io_int_parm,
> > +                          uint32_t io_int_word);
> > +int kvm_s390_crw_mchk(CPUS390XState *env);
> > +void kvm_s390_enable_css_support(CPUS390XState *env);
> > +#else
> > static inline int kvm_s390_io_interrupt(CPUS390XState *env,
> >                                         uint16_t subchannel_id,
> >                                         uint16_t subchannel_nr,
> > @@ -1190,6 +1197,10 @@ static inline int kvm_s390_crw_mchk(CPUS390XState *env)
> > {
> >     return -EOPNOTSUPP;
> > }
> > +static inline void kvm_s390_enable_css_support(CPUS390XState *env)
> > +{
> > +}
> > +#endif
> > 
> > static inline void s390_io_interrupt(CPUS390XState *env,
> >                                      uint16_t subchannel_id,
> > diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
> > index 94de764..c9a4a7d 100644
> > --- a/target-s390x/kvm.c
> > +++ b/target-s390x/kvm.c
> > @@ -30,6 +30,7 @@
> > #include "kvm.h"
> > #include "cpu.h"
> > #include "device_tree.h"
> > +#include "ioinst.h"
> > 
> > /* #define DEBUG_KVM */
> > 
> > @@ -43,9 +44,27 @@
> > 
> > #define IPA0_DIAG                       0x8300
> > #define IPA0_SIGP                       0xae00
> > -#define IPA0_PRIV                       0xb200
> > +#define IPA0_B2                         0xb200
> > +#define IPA0_B9                         0xb900
> > +#define IPA0_EB                         0xeb00
> > 
> > #define PRIV_SCLP_CALL                  0x20
> > +#define PRIV_CSCH                       0x30
> > +#define PRIV_HSCH                       0x31
> > +#define PRIV_MSCH                       0x32
> > +#define PRIV_SSCH                       0x33
> > +#define PRIV_STSCH                      0x34
> > +#define PRIV_TSCH                       0x35
> > +#define PRIV_TPI                        0x36
> > +#define PRIV_SAL                        0x37
> > +#define PRIV_RSCH                       0x38
> > +#define PRIV_STCRW                      0x39
> > +#define PRIV_STCPS                      0x3a
> > +#define PRIV_RCHP                       0x3b
> > +#define PRIV_SCHM                       0x3c
> > +#define PRIV_CHSC                       0x5f
> > +#define PRIV_SIGA                       0x74
> > +#define PRIV_XSCH                       0x76
> > #define DIAG_KVM_HYPERCALL              0x500
> > #define DIAG_KVM_BREAKPOINT             0x501
> > 
> > @@ -350,10 +369,120 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
> >     return 0;
> > }
> > 
> > -static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
> > +static int kvm_handle_css_inst(CPUS390XState *env, struct kvm_run *run,
> > +                               uint8_t ipa0, uint8_t ipa1, uint8_t ipb)
> > +{
> > +    int r = 0;
> > +    int no_cc = 0;
> > +
> > +    if (ipa0 != 0xb2) {
> > +        /* Not handled for now. */
> > +        return -1;
> > +    }
> > +    cpu_synchronize_state(env);
> > +    switch (ipa1) {
> > +    case PRIV_XSCH:
> > +        r = ioinst_handle_xsch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_CSCH:
> > +        r = ioinst_handle_csch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_HSCH:
> > +        r = ioinst_handle_hsch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_MSCH:
> > +        r = ioinst_handle_msch(env, env->regs[1], run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_SSCH:
> > +        r = ioinst_handle_ssch(env, env->regs[1], run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_STCRW:
> > +        r = ioinst_handle_stcrw(env, run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_STSCH:
> > +        r = ioinst_handle_stsch(env, env->regs[1], run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_TSCH:
> > +        /* We should only get tsch via KVM_EXIT_S390_TSCH. */
> > +        fprintf(stderr, "Spurious tsch intercept\n");
> > +        break;
> > +    case PRIV_CHSC:
> > +        r = ioinst_handle_chsc(env, run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_TPI:
> > +        /* This should have been handled by kvm already. */
> > +        fprintf(stderr, "Spurious tpi intercept\n");
> > +        break;
> > +    case PRIV_SCHM:
> > +        no_cc = 1;
> > +        r = ioinst_handle_schm(env, env->regs[1], env->regs[2],
> > +                               run->s390_sieic.ipb);
> > +        break;
> > +    case PRIV_RSCH:
> > +        r = ioinst_handle_rsch(env, env->regs[1]);
> > +        break;
> > +    case PRIV_RCHP:
> > +        r = ioinst_handle_rchp(env, env->regs[1]);
> > +        break;
> > +    case PRIV_STCPS:
> > +        /* We do not provide this instruction, it is suppressed. */
> > +        no_cc = 1;
> > +        r = 0;
> > +        break;
> > +    case PRIV_SAL:
> > +        no_cc = 1;
> > +        r = ioinst_handle_sal(env, env->regs[1]);
> > +        break;
> > +    default:
> > +        r = -1;
> > +        break;
> > +    }
> > +
> > +    if (r >= 0) {
> > +        if (!no_cc) {
> > +            setcc(env, r);
> > +        }
> > +        r = 0;
> > +    } else if (r < -1) {
> > +        r = 0;
> > +    }
> > +    return r;
> > +}
> > +
> > +static int is_ioinst(uint8_t ipa0, uint8_t ipa1, uint8_t ipb)
> > +{
> > +    int ret = 0;
> > +
> > +    switch (ipa0) {
> > +    case 0xb2:
> > +        if (((ipa1 >= 0x30) && (ipa1 <= 0x3c)) ||
> > +            (ipa1 == 0x5f) ||
> > +            (ipa1 == 0x74) ||
> > +            (ipa1 == 0x76)) {
> 
> Just make this a switch. You can the also use defines for the instruction names :).

I thought I could get away with ranges, but the I/O instructions are
unfortunately too dispersed. I'll change that to a switch and see how
that looks.

> 
> Alex
> 
> > +            ret = 1;
> > +        }
> > +        break;
> > +    case 0xb9:
> > +        if (ipa1 == 0x9c) {
> > +            ret = 1;
> > +        }
> > +        break;
> > +    case 0xeb:
> > +        if (ipb == 0x8a) {
> > +            ret = 1;
> > +        }
> > +        break;
> > +    }
> > +
> > +    return ret;
> > +}
> > +
> > +static int handle_priv(CPUS390XState *env, struct kvm_run *run,
> > +                       uint8_t ipa0, uint8_t ipa1)
> > {
> >     int r = 0;
> >     uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
> > +    uint8_t ipb = run->s390_sieic.ipb & 0xff;
> > 
> >     dprintf("KVM: PRIV: %d\n", ipa1);
> >     switch (ipa1) {
> > @@ -361,8 +490,16 @@ static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
> >             r = kvm_sclp_service_call(env, run, ipbh0);
> >             break;
> >         default:
> > -            dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
> > -            r = -1;
> > +            if (is_ioinst(ipa0, ipa1, ipb)) {
> > +                r = kvm_handle_css_inst(env, run, ipa0, ipa1, ipb);
> > +                if (r == -1) {
> > +                    setcc(env, 3);
> > +                    r = 0;
> > +                }
> > +            } else {
> > +                dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
> > +                r = -1;
> > +            }
> >             break;
> >     }
> > 
> > @@ -500,15 +637,17 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run)
> > 
> >     dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
> >     switch (ipa0) {
> > -        case IPA0_PRIV:
> > -            r = handle_priv(env, run, ipa1);
> > -            break;
> > -        case IPA0_DIAG:
> > -            r = handle_diag(env, run, ipb_code);
> > -            break;
> > -        case IPA0_SIGP:
> > -            r = handle_sigp(env, run, ipa1);
> > -            break;
> > +    case IPA0_B2:
> > +    case IPA0_B9:
> > +    case IPA0_EB:
> > +        r = handle_priv(env, run, ipa0 >> 8, ipa1);
> > +        break;
> > +    case IPA0_DIAG:
> > +        r = handle_diag(env, run, ipb_code);
> > +        break;
> > +    case IPA0_SIGP:
> > +        r = handle_sigp(env, run, ipa1);
> > +        break;
> >     }
> > 
> >     if (r < 0) {
> > @@ -565,6 +704,38 @@ static int handle_intercept(CPUS390XState *env)
> >     return r;
> > }
> > 
> > +static int handle_tsch(CPUS390XState *env, struct kvm_run *run, int dequeued,
> > +                       uint16_t subchannel_id, uint16_t subchannel_nr,
> > +                       uint32_t io_int_parm, uint32_t io_int_word)
> > +{
> > +    int ret;
> > +
> > +    cpu_synchronize_state(env);
> > +    ret = ioinst_handle_tsch(env, env->regs[1], run->s390_tsch.ipb);
> > +    if (ret >= 0) {
> > +        /* Success; set condition code. */
> > +        setcc(env, ret);
> > +        ret = 0;
> > +    } else if (ret < -1) {
> > +        /*
> > +         * Failure.
> > +         * If an I/O interrupt had been dequeued, we have to reinject it.
> > +         */
> > +        if (dequeued) {
> > +            uint32_t type = ((subchannel_id & 0xff00) << 24) |
> > +                ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16);
> > +
> > +            kvm_s390_interrupt_internal(env, type,
> > +                                        ((uint32_t)subchannel_id << 16)
> > +                                        | subchannel_nr,
> > +                                        ((uint64_t)io_int_parm << 32)
> > +                                        | io_int_word, 1);
> > +        }
> > +        ret = 0;
> > +    }
> > +    return ret;
> > +}
> > +
> > int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
> > {
> >     int ret = 0;
> > @@ -576,6 +747,13 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
> >         case KVM_EXIT_S390_RESET:
> >             qemu_system_reset_request();
> >             break;
> > +        case KVM_EXIT_S390_TSCH:
> > +            ret = handle_tsch(env, run, run->s390_tsch.dequeued,
> > +                              run->s390_tsch.subchannel_id,
> > +                              run->s390_tsch.subchannel_nr,
> > +                              run->s390_tsch.io_int_parm,
> > +                              run->s390_tsch.io_int_word);
> > +            break;
> >         default:
> >             fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
> >             break;
> > @@ -601,3 +779,45 @@ int kvm_arch_on_sigbus(int code, void *addr)
> > {
> >     return 1;
> > }
> > +
> > +int kvm_s390_io_interrupt(CPUS390XState *env, uint16_t subchannel_id,
> > +                          uint16_t subchannel_nr, uint32_t io_int_parm,
> > +                          uint32_t io_int_word)
> > +{
> > +    uint32_t type;
> > +
> > +    if (!kvm_enabled()) {
> > +        return -EOPNOTSUPP;
> > +    }
> > +
> > +    type = ((subchannel_id & 0xff00) << 24) |
> > +        ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16);
> > +    kvm_s390_interrupt_internal(env, type,
> > +                                ((uint32_t)subchannel_id << 16) | subchannel_nr,
> > +                                ((uint64_t)io_int_parm << 32) | io_int_word, 1);
> > +    return 0;
> > +}
> > +
> > +int kvm_s390_crw_mchk(CPUS390XState *env)
> > +{
> > +    if (!kvm_enabled()) {
> > +        return -EOPNOTSUPP;
> > +    }
> > +
> > +    kvm_s390_interrupt_internal(env, KVM_S390_MCHK, 1 << 28,
> > +                                0x00400f1d40330000, 1);
> > +    return 0;
> > +}
> > +
> > +void kvm_s390_enable_css_support(CPUS390XState *env)
> > +{
> > +    struct kvm_enable_cap cap = {};
> > +    int r;
> > +
> > +    /* Activate host kernel channel subsystem support. */
> > +    if (kvm_enabled()) {
> > +        cap.cap = KVM_CAP_S390_CSS_SUPPORT;
> > +        r = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
> > +        assert(r == 0);
> > +    }
> > +}
> > -- 
> > 1.7.12.4
> > 
> 

  reply	other threads:[~2012-12-10 10:29 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-07 12:50 [RFC PATCH v4 0/8] s390: channel I/O support in qemu Cornelia Huck
2012-12-07 12:50 ` [Qemu-devel] " Cornelia Huck
2012-12-07 12:50 ` [PATCH 1/8] Update linux headers Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-07 13:01   ` Peter Maydell
2012-12-07 13:01     ` Peter Maydell
2012-12-07 14:08     ` Cornelia Huck
2012-12-07 14:08       ` Cornelia Huck
2012-12-07 12:50 ` [PATCH 2/8] s390: Channel I/O basic defintions Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-10  8:07   ` Alexander Graf
2012-12-10  8:07     ` [Qemu-devel] " Alexander Graf
2012-12-10 10:18     ` Cornelia Huck
2012-12-10 10:18       ` [Qemu-devel] " Cornelia Huck
2012-12-11 10:27       ` Alexander Graf
2012-12-11 10:27         ` [Qemu-devel] " Alexander Graf
2012-12-11 12:48         ` Cornelia Huck
2012-12-11 12:48           ` [Qemu-devel] " Cornelia Huck
2012-12-07 12:50 ` [PATCH 3/8] s390: I/O interrupt and machine check injection Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-10  8:20   ` Alexander Graf
2012-12-10  8:20     ` [Qemu-devel] " Alexander Graf
2012-12-10 10:27     ` Cornelia Huck
2012-12-10 10:27       ` [Qemu-devel] " Cornelia Huck
2012-12-11  0:26       ` Rob Landley
2012-12-11  0:26         ` [Qemu-devel] " Rob Landley
2012-12-11 12:17         ` Cornelia Huck
2012-12-11 12:17           ` Cornelia Huck
2012-12-11 10:29       ` Alexander Graf
2012-12-11 10:29         ` [Qemu-devel] " Alexander Graf
2012-12-11 12:50         ` Cornelia Huck
2012-12-11 12:50           ` [Qemu-devel] " Cornelia Huck
2012-12-07 12:50 ` [PATCH 4/8] s390: Add channel I/O instructions Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-10  9:00   ` Alexander Graf
2012-12-10  9:00     ` [Qemu-devel] " Alexander Graf
2012-12-10  9:18     ` Cornelia Huck
2012-12-10  9:18       ` [Qemu-devel] " Cornelia Huck
2012-12-11 10:18       ` Alexander Graf
2012-12-11 10:18         ` [Qemu-devel] " Alexander Graf
2012-12-11 12:53         ` Cornelia Huck
2012-12-11 12:53           ` [Qemu-devel] " Cornelia Huck
2012-12-07 12:50 ` [PATCH 5/8] s390: Virtual channel subsystem support Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-07 12:50 ` [PATCH 6/8] s390: Wire up channel I/O in kvm Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-10  9:40   ` Alexander Graf
2012-12-10  9:40     ` [Qemu-devel] " Alexander Graf
2012-12-10 10:29     ` Cornelia Huck [this message]
2012-12-10 10:29       ` Cornelia Huck
2012-12-07 12:50 ` [PATCH 7/8] s390-virtio: Factor out some initialization code Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-07 12:50 ` [PATCH 8/8] s390: Add new channel I/O based virtio transport Cornelia Huck
2012-12-07 12:50   ` [Qemu-devel] " Cornelia Huck
2012-12-11 10:53   ` Alexander Graf
2012-12-11 10:53     ` [Qemu-devel] " Alexander Graf
2012-12-11 12:06     ` Christian Borntraeger
2012-12-11 12:06       ` [Qemu-devel] " Christian Borntraeger
2012-12-12  0:38       ` Alexander Graf
2012-12-12  0:38         ` [Qemu-devel] " Alexander Graf
2012-12-11 13:03     ` Cornelia Huck
2012-12-11 13:03       ` [Qemu-devel] " Cornelia Huck
2012-12-12  0:39       ` Alexander Graf
2012-12-12  0:39         ` [Qemu-devel] " Alexander Graf
2013-01-16 13:24   ` Alexander Graf
2013-01-16 13:24     ` [Qemu-devel] " Alexander Graf
2013-01-16 13:53     ` Alexander Graf
2013-01-16 13:53       ` Alexander Graf
2013-01-16 13:58       ` Cornelia Huck
2013-01-16 13:58         ` Cornelia Huck
2013-01-16 16:46     ` Richard Henderson
2013-01-16 16:46       ` Richard Henderson
2013-01-16 17:05       ` Alexander Graf
2013-01-16 17:05         ` Alexander Graf
2012-12-10  8:02 ` [RFC PATCH v4 0/8] s390: channel I/O support in qemu Alexander Graf
2012-12-10  8:02   ` [Qemu-devel] " Alexander Graf
2012-12-10 10:34   ` Cornelia Huck
2012-12-10 10:34     ` [Qemu-devel] " Cornelia Huck

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=20121210112928.660d3d5b@BR9GNB5Z \
    --to=cornelia.huck@de.ibm.com \
    --cc=agraf@suse.de \
    --cc=aliguori@us.ibm.com \
    --cc=borntraeger@de.ibm.com \
    --cc=cotte@de.ibm.com \
    --cc=gleb@redhat.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=schwidefsky@de.ibm.com \
    --cc=sebott@linux.vnet.ibm.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.