qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [qemu-s390x] [PATCH v5 11/12] s390-ccw: clear pending i


From: David Hildenbrand
Subject: Re: [Qemu-devel] [qemu-s390x] [PATCH v5 11/12] s390-ccw: clear pending irqs
Date: Wed, 14 Feb 2018 11:57:06 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2

On 05.02.2018 21:57, Collin L. Walling wrote:
> It is possible while waiting for multiple types of external
> interrupts that we might have pending irqs remaining between
> irq consumption and irq disabling. Those interrupts could
> propagate to the guest after IPL completes and cause unwanted
> behavior.
> 
> To avoid this, we clear the write event mask to prevent further
> service interrupts from ASCII events and then consume all pending
> irqs for a miniscule duration. Once finished, we reset the write
> event mask and resume business as usual.
> 
> Signed-off-by: Collin L. Walling <address@hidden>
> ---
>  pc-bios/s390-ccw/menu.c | 16 ++++++++++++++++
>  pc-bios/s390-ccw/sclp.c | 12 ++++++++++++
>  2 files changed, 28 insertions(+)
> 
> diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
> index 85d285f..971f6b6 100644
> --- a/pc-bios/s390-ccw/menu.c
> +++ b/pc-bios/s390-ccw/menu.c
> @@ -64,6 +64,20 @@ static inline bool check_clock_int(void)
>      return *code == 0x1004;
>  }
>  
> +static void clear_pending_irqs(void)
> +{
> +    uint64_t time = 50 * TOD_CLOCK_SECOND / 0x3e8;
> +
> +    sclp_clear_write_mask();
> +
> +    set_clock_comparator(get_clock() + time);
> +    enable_clock_int();
> +    consume_sclp_int();
> +    disable_clock_int();
> +
> +    sclp_setup(); /* re-enable write mask */
> +}
> +
>  static int read_prompt(char *buf, size_t len)
>  {
>      char inp[2] = {};
> @@ -165,6 +179,8 @@ static int get_boot_index(int entries)
>      sclp_print("\nBooting entry #");
>      sclp_print(itostr(boot_index, tmp, sizeof(tmp)));
>  
> +    clear_pending_irqs();
> +
>      return boot_index;
>  }
>  
> diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
> index 5902d5b..025eb2d 100644
> --- a/pc-bios/s390-ccw/sclp.c
> +++ b/pc-bios/s390-ccw/sclp.c
> @@ -46,6 +46,18 @@ static int sclp_service_call(unsigned int command, void 
> *sccb)
>          return 0;
>  }
>  
> +void sclp_clear_write_mask(void)
> +{
> +    WriteEventMask *sccb = (void *)_sccb;
> +
> +    sccb->h.length = sizeof(WriteEventMask);
> +    sccb->mask_length = sizeof(unsigned int);
> +    sccb->cp_receive_mask = 0;
> +    sccb->cp_send_mask = 0;
> +
> +    sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
> +}
> +
>  static void sclp_set_write_mask(void)
>  {
>      WriteEventMask *sccb = (void *)_sccb;
> 

1. CKC interrupts can be cleared by resetting the CKC
2. SCLP interrupts can be cleared only via delivery (apart from CPU reset)

So if you have CKC and SCLP pending at the same time, you get the CKC
delivered first and the SCLP remains pending.

Now, the easiest way to clear that (if you don't know if any is
pending!) is to simply print a string. Then you know that you have
exactly one SCLP interrupt pending.

So simply printing a string after potentially reading should be
sufficient to clear the SCLP interrupt deterministically :)

-- 

Thanks,

David / dhildenb



reply via email to

[Prev in Thread] Current Thread [Next in Thread]