qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Huth <thuth@redhat.com>
To: Pierre Morel <pmorel@linux.ibm.com>, qemu-s390x@nongnu.org
Cc: frankja@linux.ibm.com, david@redhat.com, cohuck@redhat.com,
	qemu-devel@nongnu.org, borntraeger@de.ibm.com,
	mihajlov@linux.ibm.com
Subject: Re: [PATCH v1 1/1] s390x: protvirt: SCLP interpretation
Date: Thu, 28 Nov 2019 13:10:45 +0100	[thread overview]
Message-ID: <e73fcc10-14cd-512e-56c7-ca17bcbefff8@redhat.com> (raw)
In-Reply-To: <1574935984-16910-2-git-send-email-pmorel@linux.ibm.com>

On 28/11/2019 11.13, Pierre Morel wrote:
> The SCLP protection handle some of the exceptions due to
> mis-constructions of the SCLP Control Block (SCCB) by the guest and
> provides notifications to the host when something gets wrong.
> We currently do not handle these exceptions, letting all the work to the
> firmware therefor, we only need to inject an external interrupt to the
> guest.
> 
> When the SCCB is correct, the S390x virtualisation protection copies
> the SCLP Control Block (SCCB) from the guest inside the kernel to avoid
> opening a direct access to the guest memory.
> When accessing the kernel memory with standard s390_cpu_virt_mem_*
> functions the host opens access to the SCCB shadow at address 0.
> 
> Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
> ---
>   hw/s390x/sclp.c         | 18 +++++++++++++
>   include/hw/s390x/sclp.h |  2 ++
>   target/s390x/kvm.c      | 56 ++++++++++++++++++++++++++++++++++++++++-
>   3 files changed, 75 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
> index f57ce7b739..02e4e0146f 100644
> --- a/hw/s390x/sclp.c
> +++ b/hw/s390x/sclp.c
> @@ -193,6 +193,24 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
>       }
>   }
>   
> +int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
> +                                uint32_t code)
> +{
> +    SCLPDevice *sclp = get_sclp_device();
> +    SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
> +    SCCB work_sccb;
> +    hwaddr sccb_len = sizeof(SCCB);
> +
> +    /* Protected guest SCCB is always seen at address 0 */

Well, as far as I've understood it, the address is rather ignored (and 
you can only specify an offset into the 4k page)?

> +    s390_cpu_virt_mem_read(env_archcpu(env), 0, 0, &work_sccb, sccb_len);
> +    sclp_c->execute(sclp, &work_sccb, code);
> +    s390_cpu_virt_mem_write(env_archcpu(env), 0, 0, &work_sccb,
> +                            be16_to_cpu(work_sccb.h.length));
> +
> +    sclp_c->service_interrupt(sclp, (uint64_t)&work_sccb);
> +    return 0;
> +}
> +
>   int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
>   {
>       SCLPDevice *sclp = get_sclp_device();
> diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
> index c54413b78c..c0a3faa37d 100644
> --- a/include/hw/s390x/sclp.h
> +++ b/include/hw/s390x/sclp.h
> @@ -217,5 +217,7 @@ void s390_sclp_init(void);
>   void sclp_service_interrupt(uint32_t sccb);
>   void raise_irq_cpu_hotplug(void);
>   int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
> +int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
> +                                uint32_t code);
>   
>   #endif
> diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
> index 0c9d14b4b1..559f470f51 100644
> --- a/target/s390x/kvm.c
> +++ b/target/s390x/kvm.c
> @@ -1170,7 +1170,14 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
>       sccb = env->regs[ipbh0 & 0xf];
>       code = env->regs[(ipbh0 & 0xf0) >> 4];
>   
> -    r = sclp_service_call(env, sccb, code);
> +    switch (run->s390_sieic.icptcode) {
> +    case ICPT_PV_INSTR:
> +        r = sclp_service_call_protected(env, sccb, code);
> +        break;
> +    default:
> +        r = sclp_service_call(env, sccb, code);
> +        break;
> +    }

Why not simply

     if (run->s390_sieic.icptcode == ICPT_PV_INSTR) {
         r = sclp_service_call_protected(env, sccb, code);
     } else {
         r = sclp_service_call(env, sccb, code);
     }

... that's way short and easier to read. Or do you expect other 
icptcodes in the near future?

>       if (r < 0) {
>           kvm_s390_program_interrupt(cpu, -r);
>       } else {
> @@ -1575,6 +1582,47 @@ static int kvm_s390_handle_sigp(S390CPU *cpu, uint8_t ipa1, uint32_t ipb)
>       return 0;
>   }
>   
> +static int handle_secure_notification(S390CPU *cpu, struct kvm_run *run)
> +{
> +    unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
> +    uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
> +
> +    switch (ipa0) {
> +    case IPA0_SIGP: /* We get the notification that the guest stop */
> +        kvm_s390_handle_sigp(cpu, ipa1, run->s390_sieic.ipb);
> +        break;
> +    case IPA0_B2: /* We accept but do nothing for B2 notifications */
> +        break;
> +    default: /* We do not expect other instruction's notification */
> +        kvm_s390_program_interrupt(cpu, PGM_OPERATION);

Maybe add a tracepoint or qemu_log_mask(LOG_UNIMP, ...) or CPU_LOG_INT 
here, so we can spot this condition more easily?

> +        break;
> +    }
> +    return 0;
> +}
> +
> +static int handle_secure_instruction(S390CPU *cpu, struct kvm_run *run)
> +{
> +    unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
> +    uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
> +    int r = -1;
> +
> +    switch (ipa0) {
> +    case IPA0_B2:
> +        r = handle_b2(cpu, run, ipa1);
> +        break;
> +    case IPA0_DIAG:
> +        r = handle_diag(cpu, run, run->s390_sieic.ipb);
> +        break;
> +    }
> +
> +    if (r < 0) {
> +        r = 0;
> +        kvm_s390_program_interrupt(cpu, PGM_OPERATION);
> +    }
> +
> +    return r;
> +}
> +
>   static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
>   {
>       unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
> @@ -1665,6 +1713,12 @@ static int handle_intercept(S390CPU *cpu)
>       DPRINTF("intercept: 0x%x (at 0x%lx)\n", icpt_code,
>               (long)cs->kvm_run->psw_addr);
>       switch (icpt_code) {
> +         case ICPT_PV_INSTR_NOT:
> +            r = handle_secure_notification(cpu, run);
> +            break;
> +        case ICPT_PV_INSTR:
> +            r = handle_secure_instruction(cpu, run);
> +            break;
>           case ICPT_INSTRUCTION:
>               r = handle_instruction(cpu, run);
>               break;
> 

  Thomas



  reply	other threads:[~2019-11-28 12:15 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-28 10:13 [PATCH v1 0/1] s390x: protvirt: SCLP interpretation Pierre Morel
2019-11-28 10:13 ` [PATCH v1 1/1] " Pierre Morel
2019-11-28 12:10   ` Thomas Huth [this message]
2019-11-28 13:05     ` Pierre Morel
2019-11-28 12:28 ` [PATCH v1 0/1] " Janosch Frank
2019-11-28 13:15   ` Pierre Morel
2019-11-28 23:09 ` no-reply

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=e73fcc10-14cd-512e-56c7-ca17bcbefff8@redhat.com \
    --to=thuth@redhat.com \
    --cc=borntraeger@de.ibm.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=frankja@linux.ibm.com \
    --cc=mihajlov@linux.ibm.com \
    --cc=pmorel@linux.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-s390x@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).