qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Igor Mammedov <imammedo@redhat.com>
To: Gavin Shan <gshan@redhat.com>
Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, mst@redhat.com,
	anisinha@redhat.com, gengdongjiu1@gmail.com,
	peter.maydell@linaro.org, pbonzini@redhat.com,
	mchehab+huawei@kernel.org, Jonathan.Cameron@huawei.com,
	shan.gavin@gmail.com
Subject: Re: [PATCH RESEND v2 3/3] target/arm/kvm: Support multiple memory CPERs injection
Date: Mon, 3 Nov 2025 10:52:16 +0100	[thread overview]
Message-ID: <20251103105216.1f4241d7@fedora> (raw)
In-Reply-To: <88a41137-d5fb-4b61-a3f2-dd73133c17ec@redhat.com>

On Mon, 3 Nov 2025 09:02:54 +1000
Gavin Shan <gshan@redhat.com> wrote:

> On 10/31/25 11:55 PM, Igor Mammedov wrote:
> > On Sun, 19 Oct 2025 10:36:16 +1000
> > Gavin Shan <gshan@redhat.com> wrote:  
> >> On 10/18/25 12:27 AM, Igor Mammedov wrote:  
> >>> On Tue,  7 Oct 2025 16:08:10 +1000
> >>> Gavin Shan <gshan@redhat.com> wrote:
> >>>      
> >>>> In the combination of 64KB host and 4KB guest, a problematic host page
> >>>> affects 16x guest pages. In this specific case, it's reasonable to
> >>>> push 16 consecutive memory CPERs. Otherwise, QEMU can run into core
> >>>> dump due to the current error can't be delivered as the previous error
> >>>> isn't acknoledges. It's caused by the nature the host page can be
> >>>> accessed in parallel due to the mismatched host and guest page sizes.  
> >>>
> >>> can you explain a bit more what goes wrong?
> >>>
> >>> I'm especially interested in parallel access you've mentioned
> >>> and why batch adding error records is needed
> >>> as opposed to adding records every time invalid access happens?
> >>>
> >>> PS:
> >>> Assume I don't remember details on how HEST works,
> >>> Answering it in this format also should improve commit message
> >>> making it more digestible for uninitiated.
> >>>      
> >>
> >> Thanks for your review and I'm trying to answer your question below. Please let
> >> me know if there are more questions.
> >>
> >> There are two signals (BUS_MCEERR_AR and BUS_MCEERR_AO) and BUS_MCEERR_AR is
> >> concerned here. This signal BUS_MCEERR_AR is sent by host's stage2 page fault
> >> handler when the resolved host page has been marked as marked as poisoned.
> >> The stage2 page fault handler is invoked on every access to the host page.
> >>
> >> In the combination where host and guest has 64KB and 4KB separately, A 64KB
> >> host page corresponds to 16x consecutive 4KB guest pages. It means we're
> >> accessing the 64KB host page when any of those 16x consecutive 4KB guest pages
> >> is accessed. In other words, a problematic 64KB host page affects the accesses
> >> on 16x 4KB guest pages. Those 16x 4KB guest pages can be owned by different
> >> threads on the guest and they run in parallel, potentially to access those
> >> 16x 4KB guest pages in parallel. It potentially leading to 16x BUS_MCEERR_AR
> >> signals at one point.
> >>
> >> In current implementation, the error record is built as the following calltrace
> >> indicates. There are 16 error records in the extreme case (parallel accesses on
> >> 16x 4KB guest pages, mapped to one 64KB host page). However, we can't handle
> >> multiple error records at once due to the acknowledgement mechanism in
> >> ghes_record_cper_errors(). For example, the first error record has been sent,
> >> but not consumed by the guest yet. We fail to send the second error record.
> >>
> >> kvm_arch_on_sigbus_vcpu
> >>     acpi_ghes_memory_errors
> >>       ghes_gen_err_data_uncorrectable_recoverable      // Generic Error Data Entry
> >>       acpi_ghes_build_append_mem_cper                  // Memory Error
> >>       ghes_record_cper_errors
> >>         
> >> So this series improves this situation by simply sending 16x error records in
> >> one shot for the combination of 64KB host + 4KB guest.  
> > 
> > 1) What I'm concerned about is that it target one specific case only.
> > Imagine if 1st cpu get error on page1 and another on page2=(page1+host_page_size)
> > and so on for other CPUs. Then we are back where we were before this series.
> > 
> > Also in abstract future when ARM gets 1Gb pages, that won't scale well.
> > 
> > Can we instead of making up CPERs to cover whole host page,
> > create 1/vcpu GHES source?
> > That way when vcpu trips over bad page, it would have its own
> > error status block to put errors in.
> > That would address [1] and deterministically scale
> > (well assuming that multiple SEA error sources are possible in theory)
> >   
> 
> I think it's a good idea to have individual error source for each vCPU. In this
> way, the read_ack_reg won't be a limitation. I hope Jonathan is ok to this scheme.
> 
> Currently, we have two (fixed) error sources like below. I assume the index of
> the error source per vCPU will starts from (ACPI_HEST_SRC_ID_QMP + 1) based on
> CPUState::cpu_index.

I'd suggest ditch cpu index and use arch_id instead.

> 
> enum AcpiGhesSourceID {
>      ACPI_HEST_SRC_ID_SYNC,
>      ACPI_HEST_SRC_ID_QMP,       /* Use it only for QMP injected errors */
> };
> 
> 
> > PS:
> > I also wonder what real HW does when it gets in similar situation
> > (i.e. error status block is not yet acknowledged but another async
> > error arrived for the same error source)?
> >   
> 
> I believe real HW also have this specific issue. As to ARM64, I ever did some
> google search and was told the error follows the firmware-first policy and
> handled by a component of trustfirmware-a. However, I was unable to get the
> source code. So it's hard for me to know how this specific issue is handled
> there.

Perhaps Jonathan can help with finding how real hw works around it?

My idea using per cpu source is just a speculation based on spec
on how workaround the problem,
I don't really know if guest OS will be able to handle it (aka,
need to be tested is it's viable). That also probably was a reason
in previous review, why should've waited for multiple sources
support be be merged first before this series.

 
> Thanks,
> Gavin
> 
> >>>> Imporve push_ghes_memory_errors() to push 16x consecutive memory CPERs
> >>>> for this specific case. The maximal error block size is bumped to 4KB,
> >>>> providing enough storage space for those 16x memory CPERs.
> >>>>
> >>>> Signed-off-by: Gavin Shan <gshan@redhat.com>
> >>>> ---
> >>>>    hw/acpi/ghes.c   |  2 +-
> >>>>    target/arm/kvm.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
> >>>>    2 files changed, 46 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
> >>>> index 045b77715f..5c87b3a027 100644
> >>>> --- a/hw/acpi/ghes.c
> >>>> +++ b/hw/acpi/ghes.c
> >>>> @@ -33,7 +33,7 @@
> >>>>    #define ACPI_HEST_ADDR_FW_CFG_FILE          "etc/acpi_table_hest_addr"
> >>>>    
> >>>>    /* The max size in bytes for one error block */
> >>>> -#define ACPI_GHES_MAX_RAW_DATA_LENGTH   (1 * KiB)
> >>>> +#define ACPI_GHES_MAX_RAW_DATA_LENGTH   (4 * KiB)
> >>>>    
> >>>>    /* Generic Hardware Error Source version 2 */
> >>>>    #define ACPI_GHES_SOURCE_GENERIC_ERROR_V2   10
> >>>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> >>>> index c5d5b3b16e..3ecb85e4b7 100644
> >>>> --- a/target/arm/kvm.c
> >>>> +++ b/target/arm/kvm.c
> >>>> @@ -11,6 +11,7 @@
> >>>>     */
> >>>>    
> >>>>    #include "qemu/osdep.h"
> >>>> +#include "qemu/units.h"
> >>>>    #include <sys/ioctl.h>
> >>>>    
> >>>>    #include <linux/kvm.h>
> >>>> @@ -2433,10 +2434,53 @@ static void push_ghes_memory_errors(CPUState *c, AcpiGhesState *ags,
> >>>>                                        uint64_t paddr)
> >>>>    {
> >>>>        GArray *addresses = g_array_new(false, false, sizeof(paddr));
> >>>> +    uint64_t val, start, end, guest_pgsz, host_pgsz;
> >>>>        int ret;
> >>>>    
> >>>>        kvm_cpu_synchronize_state(c);
> >>>> -    g_array_append_vals(addresses, &paddr, 1);
> >>>> +
> >>>> +    /*
> >>>> +     * Sort out the guest page size from TCR_EL1, which can be modified
> >>>> +     * by the guest from time to time. So we have to sort it out dynamically.
> >>>> +     */
> >>>> +    ret = read_sys_reg64(c->kvm_fd, &val, ARM64_SYS_REG(3, 0, 2, 0, 2));
> >>>> +    if (ret) {
> >>>> +        goto error;
> >>>> +    }
> >>>> +
> >>>> +    switch (extract64(val, 14, 2)) {
> >>>> +    case 0:
> >>>> +        guest_pgsz = 4 * KiB;
> >>>> +        break;
> >>>> +    case 1:
> >>>> +        guest_pgsz = 64 * KiB;
> >>>> +        break;
> >>>> +    case 2:
> >>>> +        guest_pgsz = 16 * KiB;
> >>>> +        break;
> >>>> +    default:
> >>>> +        error_report("unknown page size from TCR_EL1 (0x%" PRIx64 ")", val);
> >>>> +        goto error;
> >>>> +    }
> >>>> +
> >>>> +    host_pgsz = qemu_real_host_page_size();
> >>>> +    start = paddr & ~(host_pgsz - 1);
> >>>> +    end = start + host_pgsz;
> >>>> +    while (start < end) {
> >>>> +        /*
> >>>> +         * The precise physical address is provided for the affected
> >>>> +         * guest page that contains @paddr. Otherwise, the starting
> >>>> +         * address of the guest page is provided.
> >>>> +         */
> >>>> +        if (paddr >= start && paddr < (start + guest_pgsz)) {
> >>>> +            g_array_append_vals(addresses, &paddr, 1);
> >>>> +        } else {
> >>>> +            g_array_append_vals(addresses, &start, 1);
> >>>> +        }
> >>>> +
> >>>> +        start += guest_pgsz;
> >>>> +    }
> >>>> +
> >>>>        ret = acpi_ghes_memory_errors(ags, ACPI_HEST_SRC_ID_SYNC, addresses);
> >>>>        if (ret) {
> >>>>            goto error;  
> >>>      
> >>  
> >   
> 



  reply	other threads:[~2025-11-03  9:53 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-07  6:08 [PATCH RESEND v2 0/3] target/arm/kvm: Improve memory error handling Gavin Shan
2025-10-07  6:08 ` [PATCH RESEND v2 1/3] acpi/ghes: Extend acpi_ghes_memory_errors() to support multiple CPERs Gavin Shan
2025-10-31  9:58   ` Jonathan Cameron via
2025-10-31 10:08     ` Jonathan Cameron via
2025-11-02 22:45       ` Gavin Shan
2025-10-31 13:17   ` Igor Mammedov
2025-11-02 22:51     ` Gavin Shan
2025-10-07  6:08 ` [PATCH RESEND v2 2/3] kvm/arm/kvm: Introduce helper push_ghes_memory_errors() Gavin Shan
2025-10-31 10:09   ` Jonathan Cameron via
2025-11-02 23:39     ` Gavin Shan
2025-11-03  9:45       ` Igor Mammedov
2025-10-31 13:25   ` Igor Mammedov
2025-11-02 23:35     ` Gavin Shan
2025-10-07  6:08 ` [PATCH RESEND v2 3/3] target/arm/kvm: Support multiple memory CPERs injection Gavin Shan
2025-10-07 10:57   ` Mauro Carvalho Chehab
2025-10-08  3:57     ` Gavin Shan
2025-10-17 14:27   ` Igor Mammedov
2025-10-19  0:36     ` Gavin Shan
2025-10-31 13:55       ` Igor Mammedov
2025-11-02 23:02         ` Gavin Shan
2025-11-03  9:52           ` Igor Mammedov [this message]
2025-11-03 23:51             ` Gavin Shan
2025-11-06  7:57               ` Igor Mammedov
2025-11-04 12:21             ` Jonathan Cameron via
2025-11-05  0:40               ` Gavin Shan
2025-11-05  9:02                 ` Jonathan Cameron via
2025-10-31 10:10   ` Jonathan Cameron via
2025-11-02 23:03     ` Gavin Shan

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=20251103105216.1f4241d7@fedora \
    --to=imammedo@redhat.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=anisinha@redhat.com \
    --cc=gengdongjiu1@gmail.com \
    --cc=gshan@redhat.com \
    --cc=mchehab+huawei@kernel.org \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=shan.gavin@gmail.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 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).