From: Gavin Shan <gshan@redhat.com>
To: Igor Mammedov <imammedo@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 09:02:54 +1000 [thread overview]
Message-ID: <88a41137-d5fb-4b61-a3f2-dd73133c17ec@redhat.com> (raw)
In-Reply-To: <20251031145539.3551b0a5@fedora>
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.
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.
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;
>>>
>>
>
next prev parent reply other threads:[~2025-11-02 23:03 UTC|newest]
Thread overview: 30+ 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 [this message]
2025-11-03 9:52 ` Igor Mammedov
2025-11-03 23:51 ` Gavin Shan
2025-11-06 7:57 ` Igor Mammedov
2025-11-06 21:43 ` Gavin Shan
2025-11-04 12:21 ` Jonathan Cameron via
2025-11-05 0:40 ` Gavin Shan
2025-11-05 9:02 ` Jonathan Cameron via
2025-11-07 5:11 ` Gavin Shan
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=88a41137-d5fb-4b61-a3f2-dd73133c17ec@redhat.com \
--to=gshan@redhat.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=anisinha@redhat.com \
--cc=gengdongjiu1@gmail.com \
--cc=imammedo@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).