All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v14 0/9] Add ARMv8 RAS virtualization support in QEMU
@ 2017-12-28  5:54 ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

From: gengdongjiu <gengdongjiu@huawei.com>

In the ARMv8 platform, the CPU error type are synchronous external
abort(SEA) and SError Interrupt (SEI). If exception happens to guest,
sometimes  guest itself do the recovery is better, because host 
does not know guest's detailed information. For example, if a guest
user-space application happen exception, host doe not which application
encounter errors.

For the ARMv8 SEA/SEI, KVM or host kernel will deliver SIGBUS or
use other interface to notify user space. After user space gets 
the notification, it will record the CPER to guest GHES buffer
for guest and inject a exception or IRQ to KVM.

In the current implement, if the SIGBUS is BUS_MCEERR_AR, we will
treat it as synchronous exception, and use ARMv8 SEA notification type
to notify guest after recording CPER for guest; If the SIGBUS is
BUS_MCEERR_AO, we will treat it as asynchronous exception, and use
GPIO-Signal to notify guest after recording CPER for guest.

This series patches are based on Qemu 2.10, which have two parts:
1. Generate APEI/GHES table and record CPER for guest in runtime.
2. Handle the SIGBUS signal, record the CPER and fill into guest memory,
   then according to SIGBUS type(BUS_MCEERR_AR or BUS_MCEERR_AO), using
   different ACPI notification type to notify guest.

Whole solution was suggested by James(james.morse@arm.com); inject RAS SEA abort and specify guest ESR
in user space are suggested by Marc(marc.zyngier@arm.com), APEI part solution is suggested by
Laszlo(lersek@redhat.com). Shown some discussion in [1].


This series patches have already tested on ARM64 platform with RAS feature enabled:
Show the APEI part verification result in [2]
Show the BUS_MCEERR_AR and BUS_MCEERR_AO SIGBUS handling verification result in [3]

---
Change since v13:
1. Move the patches that set guest ESR and inject virtual SError out of this series
2. Clean and optimize the APEI part patches 
3. Update the commit messages and add some comments for the code

Change since v12:
1. Address Paolo's comments to move HWPoisonPage definition to accel/kvm/kvm-all.c
2. Only call kvm_cpu_synchronize_state() when get the BUS_MCEERR_AR signal
3. Only add and enable GPIO-Signal and ARMv8 SEA two hardware error sources
4. Address Michael's comments to not sync SPDX from Linux kernel header file 

Change since v11:
Address James's comments(james.morse@arm.com)
1. Check whether KVM has the capability to to set ESR instead of detecting host CPU RAS capability
2. For SIGBUS_MCEERR_AR SIGBUS, use Synchronous-External-Abort(SEA) notification type
   for SIGBUS_MCEERR_AO SIGBUS, use GPIO-Signal notification


Address Shannon's comments(for ACPI part):
1. Unify hest_ghes.c and hest_ghes.h license declaration
2. Remove unnecessary including "qmp-commands.h" in hest_ghes.c
3. Unconditionally add guest APEI table based on James's comments(james.morse@arm.com) 
4. Add a option to virt machine for migration compatibility. On new virt machine it's on
   by default while off for old ones, we enabled it since 2.10
5. Refer to the ACPI spec version which introduces Hardware Error Notification first time
6. Add ACPI_HEST_NOTIFY_RESERVED notification type

Address Igor's comments(for ACPI part):
1. Add doc patch first which will describe how it's supposed to work between QEMU/firmware/guest
   OS with expected flows.
2. Move APEI diagrams into doc/spec patch
3. Remove redundant g_malloc in ghes_record_cper()
4. Use build_append_int_noprefix() API to compose whole error status block and whole APEI table, 
   and try to get rid of most structures in patch 1, as they will be left unused after that
5. Reuse something like https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c
   to build GAS
6. Remove much offsetof() in the function
7. Build independent tables first and only then build dependent tables passing to it pointers
   to previously build table if necessary.
8. Redefine macro GHES_ACPI_HEST_NOTIFY_RESERVED to ACPI_HEST_ERROR_SOURCE_COUNT to avoid confusion


Address Peter Maydell's comments
1. linux-headers is done as a patch of their own created using scripts/update-linux-headers.sh run against a
   mainline kernel tree 
2. Tested whether this patchset builds OK on aarch32  
3. Abstract Hwpoison page adding code  out properly into a cpu-independent source file from target/i386/kvm.c,
   such as kvm-all.c
4. Add doc-comment formatted documentation comment for new globally-visible function prototype in a header

---
[1]:
https://lkml.org/lkml/2017/2/27/246
https://patchwork.kernel.org/patch/9633105/
https://patchwork.kernel.org/patch/9925227/

[2]:
Note: the UEFI(QEMU_EFI.fd) is needed if guest want to use ACPI table.

After guest boot up, dump the APEI table, then can see the initialized table
(1) # iasl -p ./HEST -d /sys/firmware/acpi/tables/HEST
(2) # cat HEST.dsl
    /*
     * Intel ACPI Component Architecture
     * AML/ASL+ Disassembler version 20170728 (64-bit version)
     * Copyright (c) 2000 - 2017 Intel Corporation
     *
     * Disassembly of /sys/firmware/acpi/tables/HEST, Mon Sep  5 07:59:17 2016
     *
     * ACPI Data Table [HEST]
     *
     * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue
     */

    ..................................................................................
    [308h 0776   2]                Subtable Type : 000A [Generic Hardware Error Source V2]
    [30Ah 0778   2]                    Source Id : 0008
    [30Ch 0780   2]            Related Source Id : FFFF
    [30Eh 0782   1]                     Reserved : 00
    [30Fh 0783   1]                      Enabled : 01
    [310h 0784   4]       Records To Preallocate : 00000001
    [314h 0788   4]      Max Sections Per Record : 00000001
    [318h 0792   4]          Max Raw Data Length : 00001000

    [31Ch 0796  12]         Error Status Address : [Generic Address Structure]
    [31Ch 0796   1]                     Space ID : 00 [SystemMemory]
    [31Dh 0797   1]                    Bit Width : 40
    [31Eh 0798   1]                   Bit Offset : 00
    [31Fh 0799   1]         Encoded Access Width : 04 [QWord Access:64]
    [320h 0800   8]                      Address : 00000000785D0040

    [328h 0808  28]                       Notify : [Hardware Error Notification Structure]
    [328h 0808   1]                  Notify Type : 08 [SEA]
    [329h 0809   1]                Notify Length : 1C
    [32Ah 0810   2]   Configuration Write Enable : 0000
    [32Ch 0812   4]                 PollInterval : 00000000
    [330h 0816   4]                       Vector : 00000000
    [334h 0820   4]      Polling Threshold Value : 00000000
    [338h 0824   4]     Polling Threshold Window : 00000000
    [33Ch 0828   4]        Error Threshold Value : 00000000
    [340h 0832   4]       Error Threshold Window : 00000000

    [344h 0836   4]    Error Status Block Length : 00001000
    [348h 0840  12]            Read Ack Register : [Generic Address Structure]
    [348h 0840   1]                     Space ID : 00 [SystemMemory]
    [349h 0841   1]                    Bit Width : 40
    [34Ah 0842   1]                   Bit Offset : 00
    [34Bh 0843   1]         Encoded Access Width : 04 [QWord Access:64]
    [34Ch 0844   8]                      Address : 00000000785D0098

    [354h 0852   8]            Read Ack Preserve : 00000000FFFFFFFE
    [35Ch 0860   8]               Read Ack Write : 0000000000000001

    .....................................................................................

(3) After a synchronous external abort(SEA) happen, Qemu receive a SIGBUS and 
    filled the CPER into guest GHES memory.  For example, according to above table,
    the address that contains the physical address of a block of memory that holds
    the error status data for this abort is 0x00000000785D0040
(4) the address for SEA notification error source is 0x785d80b0
    (qemu) xp /1 0x00000000785D0040
    00000000785d0040: 0x785d80b0

(5) check the content of generic error status block and generic error data entry
    (qemu) xp /100x 0x785d80b0
    00000000785d80b0: 0x00000001 0x00000000 0x00000000 0x00000098
    00000000785d80c0: 0x00000000 0xa5bc1114 0x4ede6f64 0x833e63b8
    00000000785d80d0: 0xb1837ced 0x00000000 0x00000300 0x00000050
    00000000785d80e0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d80f0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8100: 0x00000000 0x00000000 0x00000000 0x00004002
(6) check the OSPM's ACK value(for example SEA)
    /* Before OSPM acknowledges the error, check the ACK value */
    (qemu) xp /1 0x00000000785D0098
    00000000785d00f0: 0x00000000

    /* After OSPM acknowledges the error, check the ACK value, it change to 1 from 0 */
    (qemu) xp /1 0x00000000785D0098
    00000000785d00f0: 0x00000001

[2] host memory error hander deliver "BUS_MCEERR_AO" to Qemu, Qemu record the
    guest CPER and notify guest by IRQ, then guest do the recovery.

[ 4895.040340] {2}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
[ 4895.367779] {2}[Hardware Error]: event severity: recoverable
[ 4896.536868] {2}[Hardware Error]:  Error 0, type: recoverable
[ 4896.753032] {2}[Hardware Error]:   section_type: memory error
[ 4896.969088] {2}[Hardware Error]:   physical_address: 0x0000000040a08000
[ 4897.211532] {2}[Hardware Error]:   error_type: 3, multi-bit ECC
[ 4900.666650] Memory failure: 0x40600: already hardware poisoned
[ 4902.744432] Memory failure: 0x40a08: Killing mca-recover:42 due to hardware memory corruption
[ 4903.448544] Memory failure: 0x40a08: recovery action for dirty LRU page: RecoVered

[3] KVM deliver "BUS_MCEERR_AR" to Qemu, Qemu record the guest CPER and inject
    synchronous external abort to notify guest, then guest do the recovery.

[ 1552.516170] Synchronous External Abort: synchronous external abort (0x92000410) at 0x000000003751c6b4
[ 1553.074073] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 8
[ 1553.081654] {1}[Hardware Error]: event severity: recoverable
[ 1554.034191] {1}[Hardware Error]:  Error 0, type: recoverable
[ 1554.037934] {1}[Hardware Error]:   section_type: memory error
[ 1554.513261] {1}[Hardware Error]:   physical_address: 0x0000000040fa6000
[ 1554.513944] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
[ 1555.041451] Memory failure: 0x40fa6: Killing mca-recover:1296 due to hardware memory corruption
[ 1555.373116] Memory failure: 0x40fa6: recovery action for dirty LRU page: Recovered

Dongjiu Geng (9):
  ACPI: add some GHES structures and macros definition
  ACPI: Add APEI GHES table generation and CPER record support
  docs: APEI GHES generation and CPER record description
  ACPI: enable APEI GHES in the configure file
  target-arm: kvm64: inject synchronous External Abort
  Move related hwpoison page functions to accel/kvm/ folder
  ARM: ACPI: Add GPIO notification type for hardware RAS error
  hw/arm/virt: Add RAS platform version for migration
  target-arm: kvm64: handle SIGBUS signal from kernel or KVM

 accel/kvm/kvm-all.c             |  33 ++++
 default-configs/arm-softmmu.mak |   1 +
 docs/specs/acpi_hest_ghes.txt   |  97 ++++++++++
 hw/acpi/Makefile.objs           |   1 +
 hw/acpi/aml-build.c             |   2 +
 hw/acpi/hest_ghes.c             | 390 ++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c        |  43 ++++-
 hw/arm/virt.c                   |  22 +++
 include/exec/ram_addr.h         |   5 +
 include/hw/acpi/acpi-defs.h     |  52 ++++++
 include/hw/acpi/aml-build.h     |   1 +
 include/hw/acpi/hest_ghes.h     |  82 +++++++++
 include/hw/arm/virt.h           |   1 +
 include/sysemu/kvm.h            |   2 +-
 include/sysemu/sysemu.h         |   3 +
 target/arm/kvm.c                |   2 +
 target/arm/kvm64.c              |  99 ++++++++++
 target/i386/kvm.c               |  33 ----
 vl.c                            |  12 ++
 19 files changed, 846 insertions(+), 35 deletions(-)
 create mode 100644 docs/specs/acpi_hest_ghes.txt
 create mode 100644 hw/acpi/hest_ghes.c
 create mode 100644 include/hw/acpi/hest_ghes.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 0/9] Add ARMv8 RAS virtualization support in QEMU
@ 2017-12-28  5:54 ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

From: gengdongjiu <gengdongjiu@huawei.com>

In the ARMv8 platform, the CPU error type are synchronous external
abort(SEA) and SError Interrupt (SEI). If exception happens to guest,
sometimes  guest itself do the recovery is better, because host 
does not know guest's detailed information. For example, if a guest
user-space application happen exception, host doe not which application
encounter errors.

For the ARMv8 SEA/SEI, KVM or host kernel will deliver SIGBUS or
use other interface to notify user space. After user space gets 
the notification, it will record the CPER to guest GHES buffer
for guest and inject a exception or IRQ to KVM.

In the current implement, if the SIGBUS is BUS_MCEERR_AR, we will
treat it as synchronous exception, and use ARMv8 SEA notification type
to notify guest after recording CPER for guest; If the SIGBUS is
BUS_MCEERR_AO, we will treat it as asynchronous exception, and use
GPIO-Signal to notify guest after recording CPER for guest.

This series patches are based on Qemu 2.10, which have two parts:
1. Generate APEI/GHES table and record CPER for guest in runtime.
2. Handle the SIGBUS signal, record the CPER and fill into guest memory,
   then according to SIGBUS type(BUS_MCEERR_AR or BUS_MCEERR_AO), using
   different ACPI notification type to notify guest.

Whole solution was suggested by James(james.morse@arm.com); inject RAS SEA abort and specify guest ESR
in user space are suggested by Marc(marc.zyngier@arm.com), APEI part solution is suggested by
Laszlo(lersek@redhat.com). Shown some discussion in [1].


This series patches have already tested on ARM64 platform with RAS feature enabled:
Show the APEI part verification result in [2]
Show the BUS_MCEERR_AR and BUS_MCEERR_AO SIGBUS handling verification result in [3]

---
Change since v13:
1. Move the patches that set guest ESR and inject virtual SError out of this series
2. Clean and optimize the APEI part patches 
3. Update the commit messages and add some comments for the code

Change since v12:
1. Address Paolo's comments to move HWPoisonPage definition to accel/kvm/kvm-all.c
2. Only call kvm_cpu_synchronize_state() when get the BUS_MCEERR_AR signal
3. Only add and enable GPIO-Signal and ARMv8 SEA two hardware error sources
4. Address Michael's comments to not sync SPDX from Linux kernel header file 

Change since v11:
Address James's comments(james.morse@arm.com)
1. Check whether KVM has the capability to to set ESR instead of detecting host CPU RAS capability
2. For SIGBUS_MCEERR_AR SIGBUS, use Synchronous-External-Abort(SEA) notification type
   for SIGBUS_MCEERR_AO SIGBUS, use GPIO-Signal notification


Address Shannon's comments(for ACPI part):
1. Unify hest_ghes.c and hest_ghes.h license declaration
2. Remove unnecessary including "qmp-commands.h" in hest_ghes.c
3. Unconditionally add guest APEI table based on James's comments(james.morse@arm.com) 
4. Add a option to virt machine for migration compatibility. On new virt machine it's on
   by default while off for old ones, we enabled it since 2.10
5. Refer to the ACPI spec version which introduces Hardware Error Notification first time
6. Add ACPI_HEST_NOTIFY_RESERVED notification type

Address Igor's comments(for ACPI part):
1. Add doc patch first which will describe how it's supposed to work between QEMU/firmware/guest
   OS with expected flows.
2. Move APEI diagrams into doc/spec patch
3. Remove redundant g_malloc in ghes_record_cper()
4. Use build_append_int_noprefix() API to compose whole error status block and whole APEI table, 
   and try to get rid of most structures in patch 1, as they will be left unused after that
5. Reuse something like https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c
   to build GAS
6. Remove much offsetof() in the function
7. Build independent tables first and only then build dependent tables passing to it pointers
   to previously build table if necessary.
8. Redefine macro GHES_ACPI_HEST_NOTIFY_RESERVED to ACPI_HEST_ERROR_SOURCE_COUNT to avoid confusion


Address Peter Maydell's comments
1. linux-headers is done as a patch of their own created using scripts/update-linux-headers.sh run against a
   mainline kernel tree 
2. Tested whether this patchset builds OK on aarch32  
3. Abstract Hwpoison page adding code  out properly into a cpu-independent source file from target/i386/kvm.c,
   such as kvm-all.c
4. Add doc-comment formatted documentation comment for new globally-visible function prototype in a header

---
[1]:
https://lkml.org/lkml/2017/2/27/246
https://patchwork.kernel.org/patch/9633105/
https://patchwork.kernel.org/patch/9925227/

[2]:
Note: the UEFI(QEMU_EFI.fd) is needed if guest want to use ACPI table.

After guest boot up, dump the APEI table, then can see the initialized table
(1) # iasl -p ./HEST -d /sys/firmware/acpi/tables/HEST
(2) # cat HEST.dsl
    /*
     * Intel ACPI Component Architecture
     * AML/ASL+ Disassembler version 20170728 (64-bit version)
     * Copyright (c) 2000 - 2017 Intel Corporation
     *
     * Disassembly of /sys/firmware/acpi/tables/HEST, Mon Sep  5 07:59:17 2016
     *
     * ACPI Data Table [HEST]
     *
     * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue
     */

    ..................................................................................
    [308h 0776   2]                Subtable Type : 000A [Generic Hardware Error Source V2]
    [30Ah 0778   2]                    Source Id : 0008
    [30Ch 0780   2]            Related Source Id : FFFF
    [30Eh 0782   1]                     Reserved : 00
    [30Fh 0783   1]                      Enabled : 01
    [310h 0784   4]       Records To Preallocate : 00000001
    [314h 0788   4]      Max Sections Per Record : 00000001
    [318h 0792   4]          Max Raw Data Length : 00001000

    [31Ch 0796  12]         Error Status Address : [Generic Address Structure]
    [31Ch 0796   1]                     Space ID : 00 [SystemMemory]
    [31Dh 0797   1]                    Bit Width : 40
    [31Eh 0798   1]                   Bit Offset : 00
    [31Fh 0799   1]         Encoded Access Width : 04 [QWord Access:64]
    [320h 0800   8]                      Address : 00000000785D0040

    [328h 0808  28]                       Notify : [Hardware Error Notification Structure]
    [328h 0808   1]                  Notify Type : 08 [SEA]
    [329h 0809   1]                Notify Length : 1C
    [32Ah 0810   2]   Configuration Write Enable : 0000
    [32Ch 0812   4]                 PollInterval : 00000000
    [330h 0816   4]                       Vector : 00000000
    [334h 0820   4]      Polling Threshold Value : 00000000
    [338h 0824   4]     Polling Threshold Window : 00000000
    [33Ch 0828   4]        Error Threshold Value : 00000000
    [340h 0832   4]       Error Threshold Window : 00000000

    [344h 0836   4]    Error Status Block Length : 00001000
    [348h 0840  12]            Read Ack Register : [Generic Address Structure]
    [348h 0840   1]                     Space ID : 00 [SystemMemory]
    [349h 0841   1]                    Bit Width : 40
    [34Ah 0842   1]                   Bit Offset : 00
    [34Bh 0843   1]         Encoded Access Width : 04 [QWord Access:64]
    [34Ch 0844   8]                      Address : 00000000785D0098

    [354h 0852   8]            Read Ack Preserve : 00000000FFFFFFFE
    [35Ch 0860   8]               Read Ack Write : 0000000000000001

    .....................................................................................

(3) After a synchronous external abort(SEA) happen, Qemu receive a SIGBUS and 
    filled the CPER into guest GHES memory.  For example, according to above table,
    the address that contains the physical address of a block of memory that holds
    the error status data for this abort is 0x00000000785D0040
(4) the address for SEA notification error source is 0x785d80b0
    (qemu) xp /1 0x00000000785D0040
    00000000785d0040: 0x785d80b0

(5) check the content of generic error status block and generic error data entry
    (qemu) xp /100x 0x785d80b0
    00000000785d80b0: 0x00000001 0x00000000 0x00000000 0x00000098
    00000000785d80c0: 0x00000000 0xa5bc1114 0x4ede6f64 0x833e63b8
    00000000785d80d0: 0xb1837ced 0x00000000 0x00000300 0x00000050
    00000000785d80e0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d80f0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8100: 0x00000000 0x00000000 0x00000000 0x00004002
(6) check the OSPM's ACK value(for example SEA)
    /* Before OSPM acknowledges the error, check the ACK value */
    (qemu) xp /1 0x00000000785D0098
    00000000785d00f0: 0x00000000

    /* After OSPM acknowledges the error, check the ACK value, it change to 1 from 0 */
    (qemu) xp /1 0x00000000785D0098
    00000000785d00f0: 0x00000001

[2] host memory error hander deliver "BUS_MCEERR_AO" to Qemu, Qemu record the
    guest CPER and notify guest by IRQ, then guest do the recovery.

[ 4895.040340] {2}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
[ 4895.367779] {2}[Hardware Error]: event severity: recoverable
[ 4896.536868] {2}[Hardware Error]:  Error 0, type: recoverable
[ 4896.753032] {2}[Hardware Error]:   section_type: memory error
[ 4896.969088] {2}[Hardware Error]:   physical_address: 0x0000000040a08000
[ 4897.211532] {2}[Hardware Error]:   error_type: 3, multi-bit ECC
[ 4900.666650] Memory failure: 0x40600: already hardware poisoned
[ 4902.744432] Memory failure: 0x40a08: Killing mca-recover:42 due to hardware memory corruption
[ 4903.448544] Memory failure: 0x40a08: recovery action for dirty LRU page: RecoVered

[3] KVM deliver "BUS_MCEERR_AR" to Qemu, Qemu record the guest CPER and inject
    synchronous external abort to notify guest, then guest do the recovery.

[ 1552.516170] Synchronous External Abort: synchronous external abort (0x92000410) at 0x000000003751c6b4
[ 1553.074073] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 8
[ 1553.081654] {1}[Hardware Error]: event severity: recoverable
[ 1554.034191] {1}[Hardware Error]:  Error 0, type: recoverable
[ 1554.037934] {1}[Hardware Error]:   section_type: memory error
[ 1554.513261] {1}[Hardware Error]:   physical_address: 0x0000000040fa6000
[ 1554.513944] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
[ 1555.041451] Memory failure: 0x40fa6: Killing mca-recover:1296 due to hardware memory corruption
[ 1555.373116] Memory failure: 0x40fa6: recovery action for dirty LRU page: Recovered

Dongjiu Geng (9):
  ACPI: add some GHES structures and macros definition
  ACPI: Add APEI GHES table generation and CPER record support
  docs: APEI GHES generation and CPER record description
  ACPI: enable APEI GHES in the configure file
  target-arm: kvm64: inject synchronous External Abort
  Move related hwpoison page functions to accel/kvm/ folder
  ARM: ACPI: Add GPIO notification type for hardware RAS error
  hw/arm/virt: Add RAS platform version for migration
  target-arm: kvm64: handle SIGBUS signal from kernel or KVM

 accel/kvm/kvm-all.c             |  33 ++++
 default-configs/arm-softmmu.mak |   1 +
 docs/specs/acpi_hest_ghes.txt   |  97 ++++++++++
 hw/acpi/Makefile.objs           |   1 +
 hw/acpi/aml-build.c             |   2 +
 hw/acpi/hest_ghes.c             | 390 ++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c        |  43 ++++-
 hw/arm/virt.c                   |  22 +++
 include/exec/ram_addr.h         |   5 +
 include/hw/acpi/acpi-defs.h     |  52 ++++++
 include/hw/acpi/aml-build.h     |   1 +
 include/hw/acpi/hest_ghes.h     |  82 +++++++++
 include/hw/arm/virt.h           |   1 +
 include/sysemu/kvm.h            |   2 +-
 include/sysemu/sysemu.h         |   3 +
 target/arm/kvm.c                |   2 +
 target/arm/kvm64.c              |  99 ++++++++++
 target/i386/kvm.c               |  33 ----
 vl.c                            |  12 ++
 19 files changed, 846 insertions(+), 35 deletions(-)
 create mode 100644 docs/specs/acpi_hest_ghes.txt
 create mode 100644 hw/acpi/hest_ghes.c
 create mode 100644 include/hw/acpi/hest_ghes.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 83+ messages in thread

* [PATCH v14 1/9] ACPI: add some GHES structures and macros definition
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add Generic Error Status Block structures and some macros
definitions, which is referred to the ACPI 4.0 or ACPI 6.1. The
HEST table generation and CPER record will use them.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Change since v13:
1. Clean the new added structures and macros definition

Change since v12:
1. Address Igor's comments to to get rid of most structures and use
build_append_int_noprefix() API to compose whole error status block
and APEI table in [1]

[1]: https://lkml.org/lkml/2017/8/29/187
---
 include/hw/acpi/acpi-defs.h | 52 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 72be675..fb2110c 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -298,6 +298,25 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
 #define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
 
 /*
+ * Hardware Error Notification
+ */
+enum AcpiHestNotifyType {
+    ACPI_HEST_NOTIFY_POLLED = 0,
+    ACPI_HEST_NOTIFY_EXTERNAL = 1,
+    ACPI_HEST_NOTIFY_LOCAL = 2,
+    ACPI_HEST_NOTIFY_SCI = 3,
+    ACPI_HEST_NOTIFY_NMI = 4,
+    ACPI_HEST_NOTIFY_CMCI = 5,  /* ACPI 5.0 */
+    ACPI_HEST_NOTIFY_MCE = 6,   /* ACPI 5.0 */
+    ACPI_HEST_NOTIFY_GPIO = 7,  /* ACPI 6.0 */
+    ACPI_HEST_NOTIFY_SEA = 8,   /* ACPI 6.1 */
+    ACPI_HEST_NOTIFY_SEI = 9,   /* ACPI 6.1 */
+    ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */
+    ACPI_HEST_NOTIFY_SDEI = 11, /* ACPI 6.2 */
+    ACPI_HEST_NOTIFY_RESERVED = 12 /* 12 and greater are reserved */
+};
+
+/*
  * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
  */
 #define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
@@ -474,6 +493,39 @@ struct AcpiSystemResourceAffinityTable {
 } QEMU_PACKED;
 typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
 
+/*
+ * Generic Error Status Block
+ */
+struct AcpiGenericErrorStatus {
+    /* It is a bitmask composed of ACPI_GEBS_xxx macros */
+    uint32_t block_status;
+    uint32_t raw_data_offset;
+    uint32_t raw_data_length;
+    uint32_t data_length;
+    uint32_t error_severity;
+} QEMU_PACKED;
+typedef struct AcpiGenericErrorStatus AcpiGenericErrorStatus;
+
+/*
+ * Masks for Block Status field above
+ */
+#define ACPI_GEBS_UNCORRECTABLE          (1)
+
+/*
+ * Value for Error Severity field above
+ */
+enum AcpiGenericErrorSeverity {
+    ACPI_CPER_SEV_RECOVERABLE,
+    ACPI_CPER_SEV_FATAL,
+    ACPI_CPER_SEV_CORRECTED,
+    ACPI_CPER_SEV_NONE,
+};
+
+/*
+ * Generic Hardware Error Source version 2
+ */
+#define ACPI_HEST_SOURCE_GENERIC_ERROR_V2    (10)
+
 #define ACPI_SRAT_PROCESSOR_APIC     0
 #define ACPI_SRAT_MEMORY             1
 #define ACPI_SRAT_PROCESSOR_x2APIC   2
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 1/9] ACPI: add some GHES structures and macros definition
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add Generic Error Status Block structures and some macros
definitions, which is referred to the ACPI 4.0 or ACPI 6.1. The
HEST table generation and CPER record will use them.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Change since v13:
1. Clean the new added structures and macros definition

Change since v12:
1. Address Igor's comments to to get rid of most structures and use
build_append_int_noprefix() API to compose whole error status block
and APEI table in [1]

[1]: https://lkml.org/lkml/2017/8/29/187
---
 include/hw/acpi/acpi-defs.h | 52 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 72be675..fb2110c 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -298,6 +298,25 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
 #define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
 
 /*
+ * Hardware Error Notification
+ */
+enum AcpiHestNotifyType {
+    ACPI_HEST_NOTIFY_POLLED = 0,
+    ACPI_HEST_NOTIFY_EXTERNAL = 1,
+    ACPI_HEST_NOTIFY_LOCAL = 2,
+    ACPI_HEST_NOTIFY_SCI = 3,
+    ACPI_HEST_NOTIFY_NMI = 4,
+    ACPI_HEST_NOTIFY_CMCI = 5,  /* ACPI 5.0 */
+    ACPI_HEST_NOTIFY_MCE = 6,   /* ACPI 5.0 */
+    ACPI_HEST_NOTIFY_GPIO = 7,  /* ACPI 6.0 */
+    ACPI_HEST_NOTIFY_SEA = 8,   /* ACPI 6.1 */
+    ACPI_HEST_NOTIFY_SEI = 9,   /* ACPI 6.1 */
+    ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */
+    ACPI_HEST_NOTIFY_SDEI = 11, /* ACPI 6.2 */
+    ACPI_HEST_NOTIFY_RESERVED = 12 /* 12 and greater are reserved */
+};
+
+/*
  * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
  */
 #define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
@@ -474,6 +493,39 @@ struct AcpiSystemResourceAffinityTable {
 } QEMU_PACKED;
 typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
 
+/*
+ * Generic Error Status Block
+ */
+struct AcpiGenericErrorStatus {
+    /* It is a bitmask composed of ACPI_GEBS_xxx macros */
+    uint32_t block_status;
+    uint32_t raw_data_offset;
+    uint32_t raw_data_length;
+    uint32_t data_length;
+    uint32_t error_severity;
+} QEMU_PACKED;
+typedef struct AcpiGenericErrorStatus AcpiGenericErrorStatus;
+
+/*
+ * Masks for Block Status field above
+ */
+#define ACPI_GEBS_UNCORRECTABLE          (1)
+
+/*
+ * Value for Error Severity field above
+ */
+enum AcpiGenericErrorSeverity {
+    ACPI_CPER_SEV_RECOVERABLE,
+    ACPI_CPER_SEV_FATAL,
+    ACPI_CPER_SEV_CORRECTED,
+    ACPI_CPER_SEV_NONE,
+};
+
+/*
+ * Generic Hardware Error Source version 2
+ */
+#define ACPI_HEST_SOURCE_GENERIC_ERROR_V2    (10)
+
 #define ACPI_SRAT_PROCESSOR_APIC     0
 #define ACPI_SRAT_MEMORY             1
 #define ACPI_SRAT_PROCESSOR_x2APIC   2
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

This implements APEI GHES Table generation and record CPER in
runtime via fw_cfg blobs.Now we only support two types of GHESv2,
which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
supported type if needed. For the CPER section type, currently it
is memory section because kernel manly wants userspace to handle
the memory errors. In order to simulation, we hard code the error
type to Multi-bit ECC.

For GHESv2 error source, the OSPM must acknowledges the error via
Read ACK register. So user space must check the ACK value before
recording a new CPER to avoid read-write race condition.

Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
The basic solution is suggested by Laszlo in [1]
[1]: https://lkml.org/lkml/2017/3/29/342
---
 hw/acpi/aml-build.c         |   2 +
 hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c    |   8 +
 include/hw/acpi/aml-build.h |   1 +
 include/hw/acpi/hest_ghes.h |  82 ++++++++++
 5 files changed, 483 insertions(+)
 create mode 100644 hw/acpi/hest_ghes.c
 create mode 100644 include/hw/acpi/hest_ghes.h

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 36a6cc4..6849e5f 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
     tables->table_data = g_array_new(false, true /* clear */, 1);
     tables->tcpalog = g_array_new(false, true /* clear */, 1);
     tables->vmgenid = g_array_new(false, true /* clear */, 1);
+    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
     tables->linker = bios_linker_loader_init();
 }
 
@@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->table_data, true);
     g_array_free(tables->tcpalog, mfre);
     g_array_free(tables->vmgenid, mfre);
+    g_array_free(tables->hardware_errors, mfre);
 }
 
 /* Build rsdt table */
diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
new file mode 100644
index 0000000..86ec99e
--- /dev/null
+++ b/hw/acpi/hest_ghes.c
@@ -0,0 +1,390 @@
+/* Support for generating APEI tables and record CPER for Guests
+ *
+ * Copyright (C) 2017 HuaWei Corporation.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/hest_ghes.h"
+#include "hw/nvram/fw_cfg.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+/* Generic Address Structure (GAS)
+ * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
+ * 2.0 compat note:
+ *    @access_width must be 0, see ACPI 2.0:Table 5-1
+ */
+static void build_append_gas(GArray *table, AmlRegionSpace as,
+                      uint8_t bit_width, uint8_t bit_offset,
+                      uint8_t access_width, uint64_t address)
+{
+    build_append_int_noprefix(table, as, 1);
+    build_append_int_noprefix(table, bit_width, 1);
+    build_append_int_noprefix(table, bit_offset, 1);
+    build_append_int_noprefix(table, access_width, 1);
+    build_append_int_noprefix(table, address, 8);
+}
+
+/* Hardware Error Notification
+ * ACPI 4.0: 17.3.2.7 Hardware Error Notification
+ */
+static void build_append_notify(GArray *table, const uint8_t type,
+                                uint8_t length)
+{
+        build_append_int_noprefix(table, type, 1); /* type */
+        build_append_int_noprefix(table, length, 1);
+        build_append_int_noprefix(table, 0, 26);
+}
+
+/* Generic Error Status Block
+ * ACPI 4.0: 17.3.2.6.1 Generic Error Data
+ */
+static void build_append_gesb_header(GArray *table, uint32_t block_status,
+                      uint32_t raw_data_offset, uint32_t raw_data_length,
+                      uint32_t data_length, uint32_t error_severity)
+{
+    build_append_int_noprefix(table, block_status, 4);
+    build_append_int_noprefix(table, raw_data_offset, 4);
+    build_append_int_noprefix(table, raw_data_length, 4);
+    build_append_int_noprefix(table, data_length, 4);
+    build_append_int_noprefix(table, error_severity, 4);
+}
+
+/* Generic Error Data Entry
+ * ACPI 4.0: 17.3.2.6.1 Generic Error Data
+ */
+static void build_append_gede_header(GArray *table, const char *section_type,
+                      const uint32_t error_severity, const uint16_t revision,
+                      const uint32_t error_data_length)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        build_append_int_noprefix(table, section_type[i], 1);
+    }
+
+    build_append_int_noprefix(table, error_severity, 4);
+    build_append_int_noprefix(table, revision, 2);
+    build_append_int_noprefix(table, 0, 2);
+    build_append_int_noprefix(table, error_data_length, 4);
+    build_append_int_noprefix(table, 0, 44);
+}
+
+/* Memory section CPER record */
+static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
+{
+    /*
+     * Memory Error Record
+     */
+    build_append_int_noprefix(table,
+                 (1UL << 14) | /* Type Valid */
+                 (1UL << 1) /* Physical Address Valid */,
+                 8);
+    /* Memory error status information */
+    build_append_int_noprefix(table, 0, 8);
+    /* The physical address at which the memory error occurred */
+    build_append_int_noprefix(table, error_physical_addr, 8);
+    build_append_int_noprefix(table, 0, 48);
+    /* Hard code to Multi-bit ECC error */
+    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
+    build_append_int_noprefix(table, 0, 7);
+}
+
+static int ghes_record_mem_error(uint64_t error_block_address,
+                                    uint64_t error_physical_addr)
+{
+    GArray *block;
+    uint64_t current_block_length;
+    uint32_t data_length;
+    /* Memory section */
+    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
+                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
+                                0x83, 0xB1};
+
+    block = g_array_new(false, true /* clear */, 1);
+
+    /* Read the current length in bytes of the generic error data */
+    cpu_physical_memory_read(error_block_address +
+        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
+
+    /* The current whole length in bytes of the generic error status block */
+    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
+
+    /* Add a new generic error data entry*/
+    data_length += GHES_DATA_LENGTH;
+    data_length += GHES_CPER_LENGTH;
+
+    /* Check whether it will run out of the preallocated memory if adding a new
+     * generic error data entry
+     */
+    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
+        error_report("Record CPER out of boundary!!!");
+        return GHES_CPER_FAIL;
+    }
+    /* Build the new generic error status block header */
+    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
+        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
+
+    /* Write back above generic error status block header to guest memory */
+    cpu_physical_memory_write(error_block_address, block->data,
+                              block->len);
+
+    /* Build the generic error data entries */
+
+    data_length = block->len;
+    /* Build the new generic error data entry header */
+    build_append_gede_header(block, mem_section_id_le,
+                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
+                    cpu_to_le32(80)/* the total size of Memory Error Record */);
+
+    /* Build the memory section CPER */
+    build_append_mem_cper(block, error_physical_addr);
+
+    /* Write back above whole new generic error data entry to guest memory */
+    cpu_physical_memory_write(error_block_address + current_block_length,
+                    block->data + data_length, block->len - data_length);
+
+    g_array_free(block, true);
+
+    return GHES_CPER_OK;
+}
+
+/* Build table for the hardware error fw_cfg blob */
+void build_hardware_error_table(GArray *hardware_errors, BIOSLinker *linker)
+{
+    int i;
+
+    /*
+     * | +--------------------------+
+     * | |    error_block_addressN   |
+     * | |      ..........          |
+     * | +--------------------------+
+     * | |    read_ack_registerN    |
+     * | |     ...........          |
+     * | +--------------------------+
+     * | |Generic Error Status Block|
+     * | |      ........            |
+     * | +--------------------------+
+     */
+
+    /* Build error block address */
+    build_append_int_noprefix((void *)hardware_errors, 0,
+                    GHES_ADDRESS_SIZE * ACPI_HEST_ERROR_SOURCE_COUNT);
+
+    for (i = 0; i < ACPI_HEST_ERROR_SOURCE_COUNT; i++)
+        /* Build Read ACK registes and initialize them to 1, so GHES can be
+         * writeable in the first time
+         */
+        build_append_int_noprefix((void *)hardware_errors, 1, GHES_ADDRESS_SIZE);
+
+     /* Build generic error status blocks */
+    build_append_int_noprefix((void *)hardware_errors, 0,
+                    GHES_MAX_RAW_DATA_LENGTH * ACPI_HEST_ERROR_SOURCE_COUNT);
+
+    /* Allocate guest memory for the hardware error fw_cfg blob */
+    bios_linker_loader_alloc(linker, GHES_ERRORS_FW_CFG_FILE, hardware_errors,
+                            1, false);
+}
+
+void build_apei_ghes(GArray *table_data, GArray *hardware_errors,
+                                            BIOSLinker *linker)
+{
+    uint32_t i, error_status_block_offset, length = table_data->len;
+
+    /* Reserve table header size */
+    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+
+    /* Set the error source counts */
+    build_append_int_noprefix(table_data, ACPI_HEST_ERROR_SOURCE_COUNT, 4);
+
+    for (i = 0; i < ACPI_HEST_ERROR_SOURCE_COUNT; i++) {
+        /* Generic Hardware Error Source version 2(GHESv2 - Type 10)
+         */
+        build_append_int_noprefix(table_data,
+            ACPI_HEST_SOURCE_GENERIC_ERROR_V2, 2); /* type */
+        build_append_int_noprefix(table_data, cpu_to_le16(i), 2); /* source id */
+        build_append_int_noprefix(table_data, 0xffff, 2); /* related source id */
+        build_append_int_noprefix(table_data, 0, 1); /* flags */
+
+        build_append_int_noprefix(table_data, 1, 1); /* enabled */
+
+        /* Number of Records To Pre-allocate */
+        build_append_int_noprefix(table_data, 1, 4);
+        /* Max Sections Per Record */
+        build_append_int_noprefix(table_data, 1, 4);
+        /* Max Raw Data Length */
+        build_append_int_noprefix(table_data, GHES_MAX_RAW_DATA_LENGTH, 4);
+
+        /* Build error status address*/
+        build_append_gas(table_data, AML_SYSTEM_MEMORY, 0x40, 0, 4 /* QWord access */, 0);
+        bios_linker_loader_add_pointer(linker,
+            ACPI_BUILD_TABLE_FILE, ERROR_STATUS_ADDRESS_OFFSET(length, i),
+            GHES_ADDRESS_SIZE, GHES_ERRORS_FW_CFG_FILE, i * GHES_ADDRESS_SIZE);
+
+        /* Hardware Error Notification
+         * Now only enable GPIO-Signal and ARMv8 SEA notification types
+         */
+        if (i == 0) {
+            build_append_notify(table_data, ACPI_HEST_NOTIFY_GPIO, 28);
+        } else if (i == 1) {
+            build_append_notify(table_data, ACPI_HEST_NOTIFY_SEA, 28);
+        }
+
+        /* Error Status Block Length */
+        build_append_int_noprefix(table_data,
+            cpu_to_le32(GHES_MAX_RAW_DATA_LENGTH), 4);
+
+        /* Build Read ACK register
+         * ACPI 6.1/6.2: 18.3.2.8 Generic Hardware Error Source
+         * version 2 (GHESv2 - Type 10)
+         */
+        build_append_gas(table_data, AML_SYSTEM_MEMORY, 0x40, 0, 4 /* QWord access */, 0);
+        bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+            READ_ACK_REGISTER_ADDRESS_OFFSET(length, i), GHES_ADDRESS_SIZE,
+            GHES_ERRORS_FW_CFG_FILE,
+            (ACPI_HEST_ERROR_SOURCE_COUNT + i) * GHES_ADDRESS_SIZE);
+
+        /* Build Read Ack Preserve and Read Ack Writer */
+        build_append_int_noprefix(table_data, cpu_to_le64(ReadAckPreserve), 8);
+        build_append_int_noprefix(table_data, cpu_to_le64(ReadAckWrite), 8);
+    }
+
+    /* Generic Error Status Block offset in the hardware error fw_cfg blob */
+    error_status_block_offset = GHES_ADDRESS_SIZE * 2 *
+                                ACPI_HEST_ERROR_SOURCE_COUNT;
+
+    for (i = 0; i < ACPI_HEST_ERROR_SOURCE_COUNT; i++)
+        /* Patch address of generic error status block into
+         * the error block address register of hardware_errors fw_cfg blob
+         */
+        bios_linker_loader_add_pointer(linker,
+            GHES_ERRORS_FW_CFG_FILE, GHES_ADDRESS_SIZE * i, GHES_ADDRESS_SIZE,
+            GHES_ERRORS_FW_CFG_FILE,
+            error_status_block_offset + i * GHES_MAX_RAW_DATA_LENGTH);
+
+    /* write address of hardware_errors fw_cfg blob into the
+     * hardware_errors_addr fw_cfg blob.
+     */
+    bios_linker_loader_write_pointer(linker, GHES_DATA_ADDR_FW_CFG_FILE,
+        0, GHES_ADDRESS_SIZE, GHES_ERRORS_FW_CFG_FILE, 0);
+
+    build_header(linker, table_data,
+        (void *)(table_data->data + length), "HEST",
+        table_data->len - length, 1, NULL, "GHES");
+}
+
+static GhesState ges;
+void ghes_add_fw_cfg(FWCfgState *s, GArray *hardware_error)
+{
+
+    size_t size = 2 * GHES_ADDRESS_SIZE + GHES_MAX_RAW_DATA_LENGTH;
+    size_t request_block_size = ACPI_HEST_ERROR_SOURCE_COUNT * size;
+
+    /* Create a read-only fw_cfg file for GHES */
+    fw_cfg_add_file(s, GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
+                    request_block_size);
+
+    /* Create a read-write fw_cfg file for Address */
+    fw_cfg_add_file_callback(s, GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
+        &ges.ghes_addr_le, sizeof(ges.ghes_addr_le), false);
+}
+
+bool ghes_record_errors(uint32_t notify, uint64_t physical_address)
+{
+    uint64_t error_block_addr, read_ack_register_addr;
+    int read_ack_register = 0, loop = 0;
+    uint64_t start_addr = le32_to_cpu(ges.ghes_addr_le);
+    bool ret = GHES_CPER_FAIL;
+    const uint8_t error_source_id[] = { 0xff, 0xff, 0xff, 0xff,
+                                        0xff, 0xff, 0xff, 0, 1};
+
+    /*
+     * | +---------------------+ ges.ghes_addr_le
+     * | |error_block_address0|
+     * | +---------------------+
+     * | |error_block_address1|
+     * | +---------------------+ --+--
+     * | |    .............    | GHES_ADDRESS_SIZE
+     * | +---------------------+ --+--
+     * | |error_block_addressN|
+     * | +---------------------+
+     * | | read_ack_register0  |
+     * | +---------------------+ --+--
+     * | | read_ack_register1  | GHES_ADDRESS_SIZE
+     * | +---------------------+ --+--
+     * | |   .............     |
+     * | +---------------------+
+     * | | read_ack_registerN  |
+     * | +---------------------+ --+--
+     * | |      CPER           |   |
+     * | |      ....           | GHES_MAX_RAW_DATA_LENGT
+     * | |      CPER           |   |
+     * | +---------------------+ --+--
+     * | |    ..........       |
+     * | +---------------------+
+     * | |      CPER           |
+     * | |      ....           |
+     * | |      CPER           |
+     * | +---------------------+
+     */
+    if (physical_address && notify < ACPI_HEST_NOTIFY_RESERVED) {
+        /* Find and check the source id for this new CPER */
+        if (error_source_id[notify] != 0xff) {
+            start_addr += error_source_id[notify] * GHES_ADDRESS_SIZE;
+        } else {
+            goto out;
+        }
+
+        cpu_physical_memory_read(start_addr, &error_block_addr,
+                                    GHES_ADDRESS_SIZE);
+
+        read_ack_register_addr = start_addr +
+                        ACPI_HEST_ERROR_SOURCE_COUNT * GHES_ADDRESS_SIZE;
+retry:
+        cpu_physical_memory_read(read_ack_register_addr,
+                                 &read_ack_register, GHES_ADDRESS_SIZE);
+
+        /* zero means OSPM does not acknowledge the error */
+        if (!read_ack_register) {
+            if (loop < 3) {
+                usleep(100 * 1000);
+                loop++;
+                goto retry;
+            } else {
+                error_report("Last time OSPM does not acknowledge the error,"
+                    " record CPER failed this time, set the ack value to"
+                    " avoid blocking next time CPER record! exit");
+                read_ack_register = 1;
+                cpu_physical_memory_write(read_ack_register_addr,
+                    &read_ack_register, GHES_ADDRESS_SIZE);
+            }
+        } else {
+            if (error_block_addr) {
+                read_ack_register = 0;
+                cpu_physical_memory_write(read_ack_register_addr,
+                    &read_ack_register, GHES_ADDRESS_SIZE);
+                ret = ghes_record_mem_error(error_block_addr, physical_address);
+            }
+        }
+    }
+
+out:
+    return ret;
+}
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 3d78ff6..b7d45cd 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -45,6 +45,7 @@
 #include "hw/arm/virt.h"
 #include "sysemu/numa.h"
 #include "kvm_arm.h"
+#include "hw/acpi/hest_ghes.h"
 
 #define ARM_SPI_BASE 32
 #define ACPI_POWER_BUTTON_DEVICE "PWRB"
@@ -771,6 +772,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     acpi_add_table(table_offsets, tables_blob);
     build_spcr(tables_blob, tables->linker, vms);
 
+    acpi_add_table(table_offsets, tables_blob);
+    build_hardware_error_table(tables->hardware_errors, tables->linker);
+    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
+
+
     if (nb_numa_nodes > 0) {
         acpi_add_table(table_offsets, tables_blob);
         build_srat(tables_blob, tables->linker, vms);
@@ -887,6 +893,8 @@ void virt_acpi_setup(VirtMachineState *vms)
     fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
                     acpi_data_len(tables.tcpalog));
 
+    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
+
     build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
                                               ACPI_BUILD_RSDP_FILE, 0);
 
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 88d0738..7f7b55c 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -211,6 +211,7 @@ struct AcpiBuildTables {
     GArray *rsdp;
     GArray *tcpalog;
     GArray *vmgenid;
+    GArray *hardware_errors;
     BIOSLinker *linker;
 } AcpiBuildTables;
 
diff --git a/include/hw/acpi/hest_ghes.h b/include/hw/acpi/hest_ghes.h
new file mode 100644
index 0000000..420e825
--- /dev/null
+++ b/include/hw/acpi/hest_ghes.h
@@ -0,0 +1,82 @@
+/* Support for generating APEI tables and record CPER for Guests
+ *
+ * Copyright (C) 2017 HuaWei Corporation.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACPI_GHES_H
+#define ACPI_GHES_H
+
+#include "hw/acpi/bios-linker-loader.h"
+
+#define GHES_ERRORS_FW_CFG_FILE         "etc/hardware_errors"
+#define GHES_DATA_ADDR_FW_CFG_FILE      "etc/hardware_errors_addr"
+
+#define GHES_CPER_OK            1
+#define GHES_CPER_FAIL          0
+
+/* The Address field is 64-bit size, ACPI 2.0/3.0: 5.2.3.1 Generic Address
+ * Structure
+ */
+#define GHES_ADDRESS_SIZE           8
+
+#define GHES_DATA_LENGTH            72
+#define GHES_CPER_LENGTH            80
+
+#define ReadAckPreserve             0xfffffffe
+#define ReadAckWrite                0x1
+
+/* The max size in bytes for one error block */
+#define GHES_MAX_RAW_DATA_LENGTH        0x1000
+/* Now only have GPIO-Signal and ARMv8 SEA notification types error sources
+ */
+#define ACPI_HEST_ERROR_SOURCE_COUNT    2
+
+/*
+ * | +--------------------------+ 0
+ * | |        Header            |
+ * | +--------------------------+ 40---+-
+ * | | .................        |      |
+ * | | error_status_address-----+ 60   |
+ * | | .................        |      |
+ * | | read_ack_register--------+ 104  92
+ * | | read_ack_preserve        |      |
+ * | | read_ack_write           |      |
+ * + +--------------------------+ 132--+-
+ *
+ * From above GHES definition, the error status address offset is 60;
+ * the Read ack register offset is 104, the whole size of GHESv2 is 92
+ */
+
+/* The error status address offset in GHES */
+#define ERROR_STATUS_ADDRESS_OFFSET(start_addr, n)     (start_addr + 60 + \
+                    offsetof(struct AcpiGenericAddress, address) + n * 92)
+
+/* The read Ack register offset in GHES */
+#define READ_ACK_REGISTER_ADDRESS_OFFSET(start_addr, n) (start_addr + 104 + \
+                    offsetof(struct AcpiGenericAddress, address) + n * 92)
+
+typedef struct GhesState {
+    uint64_t ghes_addr_le;
+} GhesState;
+
+void build_apei_ghes(GArray *table_data, GArray *hardware_error,
+                    BIOSLinker *linker);
+void build_hardware_error_table(GArray *hardware_errors, BIOSLinker *linker);
+void ghes_add_fw_cfg(FWCfgState *s, GArray *hardware_errors);
+bool ghes_record_errors(uint32_t notify, uint64_t error_physical_addr);
+#endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

This implements APEI GHES Table generation and record CPER in
runtime via fw_cfg blobs.Now we only support two types of GHESv2,
which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
supported type if needed. For the CPER section type, currently it
is memory section because kernel manly wants userspace to handle
the memory errors. In order to simulation, we hard code the error
type to Multi-bit ECC.

For GHESv2 error source, the OSPM must acknowledges the error via
Read ACK register. So user space must check the ACK value before
recording a new CPER to avoid read-write race condition.

Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
The basic solution is suggested by Laszlo in [1]
[1]: https://lkml.org/lkml/2017/3/29/342
---
 hw/acpi/aml-build.c         |   2 +
 hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c    |   8 +
 include/hw/acpi/aml-build.h |   1 +
 include/hw/acpi/hest_ghes.h |  82 ++++++++++
 5 files changed, 483 insertions(+)
 create mode 100644 hw/acpi/hest_ghes.c
 create mode 100644 include/hw/acpi/hest_ghes.h

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 36a6cc4..6849e5f 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
     tables->table_data = g_array_new(false, true /* clear */, 1);
     tables->tcpalog = g_array_new(false, true /* clear */, 1);
     tables->vmgenid = g_array_new(false, true /* clear */, 1);
+    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
     tables->linker = bios_linker_loader_init();
 }
 
@@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->table_data, true);
     g_array_free(tables->tcpalog, mfre);
     g_array_free(tables->vmgenid, mfre);
+    g_array_free(tables->hardware_errors, mfre);
 }
 
 /* Build rsdt table */
diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
new file mode 100644
index 0000000..86ec99e
--- /dev/null
+++ b/hw/acpi/hest_ghes.c
@@ -0,0 +1,390 @@
+/* Support for generating APEI tables and record CPER for Guests
+ *
+ * Copyright (C) 2017 HuaWei Corporation.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/hest_ghes.h"
+#include "hw/nvram/fw_cfg.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+/* Generic Address Structure (GAS)
+ * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
+ * 2.0 compat note:
+ *    @access_width must be 0, see ACPI 2.0:Table 5-1
+ */
+static void build_append_gas(GArray *table, AmlRegionSpace as,
+                      uint8_t bit_width, uint8_t bit_offset,
+                      uint8_t access_width, uint64_t address)
+{
+    build_append_int_noprefix(table, as, 1);
+    build_append_int_noprefix(table, bit_width, 1);
+    build_append_int_noprefix(table, bit_offset, 1);
+    build_append_int_noprefix(table, access_width, 1);
+    build_append_int_noprefix(table, address, 8);
+}
+
+/* Hardware Error Notification
+ * ACPI 4.0: 17.3.2.7 Hardware Error Notification
+ */
+static void build_append_notify(GArray *table, const uint8_t type,
+                                uint8_t length)
+{
+        build_append_int_noprefix(table, type, 1); /* type */
+        build_append_int_noprefix(table, length, 1);
+        build_append_int_noprefix(table, 0, 26);
+}
+
+/* Generic Error Status Block
+ * ACPI 4.0: 17.3.2.6.1 Generic Error Data
+ */
+static void build_append_gesb_header(GArray *table, uint32_t block_status,
+                      uint32_t raw_data_offset, uint32_t raw_data_length,
+                      uint32_t data_length, uint32_t error_severity)
+{
+    build_append_int_noprefix(table, block_status, 4);
+    build_append_int_noprefix(table, raw_data_offset, 4);
+    build_append_int_noprefix(table, raw_data_length, 4);
+    build_append_int_noprefix(table, data_length, 4);
+    build_append_int_noprefix(table, error_severity, 4);
+}
+
+/* Generic Error Data Entry
+ * ACPI 4.0: 17.3.2.6.1 Generic Error Data
+ */
+static void build_append_gede_header(GArray *table, const char *section_type,
+                      const uint32_t error_severity, const uint16_t revision,
+                      const uint32_t error_data_length)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        build_append_int_noprefix(table, section_type[i], 1);
+    }
+
+    build_append_int_noprefix(table, error_severity, 4);
+    build_append_int_noprefix(table, revision, 2);
+    build_append_int_noprefix(table, 0, 2);
+    build_append_int_noprefix(table, error_data_length, 4);
+    build_append_int_noprefix(table, 0, 44);
+}
+
+/* Memory section CPER record */
+static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
+{
+    /*
+     * Memory Error Record
+     */
+    build_append_int_noprefix(table,
+                 (1UL << 14) | /* Type Valid */
+                 (1UL << 1) /* Physical Address Valid */,
+                 8);
+    /* Memory error status information */
+    build_append_int_noprefix(table, 0, 8);
+    /* The physical address at which the memory error occurred */
+    build_append_int_noprefix(table, error_physical_addr, 8);
+    build_append_int_noprefix(table, 0, 48);
+    /* Hard code to Multi-bit ECC error */
+    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
+    build_append_int_noprefix(table, 0, 7);
+}
+
+static int ghes_record_mem_error(uint64_t error_block_address,
+                                    uint64_t error_physical_addr)
+{
+    GArray *block;
+    uint64_t current_block_length;
+    uint32_t data_length;
+    /* Memory section */
+    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
+                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
+                                0x83, 0xB1};
+
+    block = g_array_new(false, true /* clear */, 1);
+
+    /* Read the current length in bytes of the generic error data */
+    cpu_physical_memory_read(error_block_address +
+        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
+
+    /* The current whole length in bytes of the generic error status block */
+    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
+
+    /* Add a new generic error data entry*/
+    data_length += GHES_DATA_LENGTH;
+    data_length += GHES_CPER_LENGTH;
+
+    /* Check whether it will run out of the preallocated memory if adding a new
+     * generic error data entry
+     */
+    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
+        error_report("Record CPER out of boundary!!!");
+        return GHES_CPER_FAIL;
+    }
+    /* Build the new generic error status block header */
+    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
+        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
+
+    /* Write back above generic error status block header to guest memory */
+    cpu_physical_memory_write(error_block_address, block->data,
+                              block->len);
+
+    /* Build the generic error data entries */
+
+    data_length = block->len;
+    /* Build the new generic error data entry header */
+    build_append_gede_header(block, mem_section_id_le,
+                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
+                    cpu_to_le32(80)/* the total size of Memory Error Record */);
+
+    /* Build the memory section CPER */
+    build_append_mem_cper(block, error_physical_addr);
+
+    /* Write back above whole new generic error data entry to guest memory */
+    cpu_physical_memory_write(error_block_address + current_block_length,
+                    block->data + data_length, block->len - data_length);
+
+    g_array_free(block, true);
+
+    return GHES_CPER_OK;
+}
+
+/* Build table for the hardware error fw_cfg blob */
+void build_hardware_error_table(GArray *hardware_errors, BIOSLinker *linker)
+{
+    int i;
+
+    /*
+     * | +--------------------------+
+     * | |    error_block_addressN   |
+     * | |      ..........          |
+     * | +--------------------------+
+     * | |    read_ack_registerN    |
+     * | |     ...........          |
+     * | +--------------------------+
+     * | |Generic Error Status Block|
+     * | |      ........            |
+     * | +--------------------------+
+     */
+
+    /* Build error block address */
+    build_append_int_noprefix((void *)hardware_errors, 0,
+                    GHES_ADDRESS_SIZE * ACPI_HEST_ERROR_SOURCE_COUNT);
+
+    for (i = 0; i < ACPI_HEST_ERROR_SOURCE_COUNT; i++)
+        /* Build Read ACK registes and initialize them to 1, so GHES can be
+         * writeable in the first time
+         */
+        build_append_int_noprefix((void *)hardware_errors, 1, GHES_ADDRESS_SIZE);
+
+     /* Build generic error status blocks */
+    build_append_int_noprefix((void *)hardware_errors, 0,
+                    GHES_MAX_RAW_DATA_LENGTH * ACPI_HEST_ERROR_SOURCE_COUNT);
+
+    /* Allocate guest memory for the hardware error fw_cfg blob */
+    bios_linker_loader_alloc(linker, GHES_ERRORS_FW_CFG_FILE, hardware_errors,
+                            1, false);
+}
+
+void build_apei_ghes(GArray *table_data, GArray *hardware_errors,
+                                            BIOSLinker *linker)
+{
+    uint32_t i, error_status_block_offset, length = table_data->len;
+
+    /* Reserve table header size */
+    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+
+    /* Set the error source counts */
+    build_append_int_noprefix(table_data, ACPI_HEST_ERROR_SOURCE_COUNT, 4);
+
+    for (i = 0; i < ACPI_HEST_ERROR_SOURCE_COUNT; i++) {
+        /* Generic Hardware Error Source version 2(GHESv2 - Type 10)
+         */
+        build_append_int_noprefix(table_data,
+            ACPI_HEST_SOURCE_GENERIC_ERROR_V2, 2); /* type */
+        build_append_int_noprefix(table_data, cpu_to_le16(i), 2); /* source id */
+        build_append_int_noprefix(table_data, 0xffff, 2); /* related source id */
+        build_append_int_noprefix(table_data, 0, 1); /* flags */
+
+        build_append_int_noprefix(table_data, 1, 1); /* enabled */
+
+        /* Number of Records To Pre-allocate */
+        build_append_int_noprefix(table_data, 1, 4);
+        /* Max Sections Per Record */
+        build_append_int_noprefix(table_data, 1, 4);
+        /* Max Raw Data Length */
+        build_append_int_noprefix(table_data, GHES_MAX_RAW_DATA_LENGTH, 4);
+
+        /* Build error status address*/
+        build_append_gas(table_data, AML_SYSTEM_MEMORY, 0x40, 0, 4 /* QWord access */, 0);
+        bios_linker_loader_add_pointer(linker,
+            ACPI_BUILD_TABLE_FILE, ERROR_STATUS_ADDRESS_OFFSET(length, i),
+            GHES_ADDRESS_SIZE, GHES_ERRORS_FW_CFG_FILE, i * GHES_ADDRESS_SIZE);
+
+        /* Hardware Error Notification
+         * Now only enable GPIO-Signal and ARMv8 SEA notification types
+         */
+        if (i == 0) {
+            build_append_notify(table_data, ACPI_HEST_NOTIFY_GPIO, 28);
+        } else if (i == 1) {
+            build_append_notify(table_data, ACPI_HEST_NOTIFY_SEA, 28);
+        }
+
+        /* Error Status Block Length */
+        build_append_int_noprefix(table_data,
+            cpu_to_le32(GHES_MAX_RAW_DATA_LENGTH), 4);
+
+        /* Build Read ACK register
+         * ACPI 6.1/6.2: 18.3.2.8 Generic Hardware Error Source
+         * version 2 (GHESv2 - Type 10)
+         */
+        build_append_gas(table_data, AML_SYSTEM_MEMORY, 0x40, 0, 4 /* QWord access */, 0);
+        bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+            READ_ACK_REGISTER_ADDRESS_OFFSET(length, i), GHES_ADDRESS_SIZE,
+            GHES_ERRORS_FW_CFG_FILE,
+            (ACPI_HEST_ERROR_SOURCE_COUNT + i) * GHES_ADDRESS_SIZE);
+
+        /* Build Read Ack Preserve and Read Ack Writer */
+        build_append_int_noprefix(table_data, cpu_to_le64(ReadAckPreserve), 8);
+        build_append_int_noprefix(table_data, cpu_to_le64(ReadAckWrite), 8);
+    }
+
+    /* Generic Error Status Block offset in the hardware error fw_cfg blob */
+    error_status_block_offset = GHES_ADDRESS_SIZE * 2 *
+                                ACPI_HEST_ERROR_SOURCE_COUNT;
+
+    for (i = 0; i < ACPI_HEST_ERROR_SOURCE_COUNT; i++)
+        /* Patch address of generic error status block into
+         * the error block address register of hardware_errors fw_cfg blob
+         */
+        bios_linker_loader_add_pointer(linker,
+            GHES_ERRORS_FW_CFG_FILE, GHES_ADDRESS_SIZE * i, GHES_ADDRESS_SIZE,
+            GHES_ERRORS_FW_CFG_FILE,
+            error_status_block_offset + i * GHES_MAX_RAW_DATA_LENGTH);
+
+    /* write address of hardware_errors fw_cfg blob into the
+     * hardware_errors_addr fw_cfg blob.
+     */
+    bios_linker_loader_write_pointer(linker, GHES_DATA_ADDR_FW_CFG_FILE,
+        0, GHES_ADDRESS_SIZE, GHES_ERRORS_FW_CFG_FILE, 0);
+
+    build_header(linker, table_data,
+        (void *)(table_data->data + length), "HEST",
+        table_data->len - length, 1, NULL, "GHES");
+}
+
+static GhesState ges;
+void ghes_add_fw_cfg(FWCfgState *s, GArray *hardware_error)
+{
+
+    size_t size = 2 * GHES_ADDRESS_SIZE + GHES_MAX_RAW_DATA_LENGTH;
+    size_t request_block_size = ACPI_HEST_ERROR_SOURCE_COUNT * size;
+
+    /* Create a read-only fw_cfg file for GHES */
+    fw_cfg_add_file(s, GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
+                    request_block_size);
+
+    /* Create a read-write fw_cfg file for Address */
+    fw_cfg_add_file_callback(s, GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
+        &ges.ghes_addr_le, sizeof(ges.ghes_addr_le), false);
+}
+
+bool ghes_record_errors(uint32_t notify, uint64_t physical_address)
+{
+    uint64_t error_block_addr, read_ack_register_addr;
+    int read_ack_register = 0, loop = 0;
+    uint64_t start_addr = le32_to_cpu(ges.ghes_addr_le);
+    bool ret = GHES_CPER_FAIL;
+    const uint8_t error_source_id[] = { 0xff, 0xff, 0xff, 0xff,
+                                        0xff, 0xff, 0xff, 0, 1};
+
+    /*
+     * | +---------------------+ ges.ghes_addr_le
+     * | |error_block_address0|
+     * | +---------------------+
+     * | |error_block_address1|
+     * | +---------------------+ --+--
+     * | |    .............    | GHES_ADDRESS_SIZE
+     * | +---------------------+ --+--
+     * | |error_block_addressN|
+     * | +---------------------+
+     * | | read_ack_register0  |
+     * | +---------------------+ --+--
+     * | | read_ack_register1  | GHES_ADDRESS_SIZE
+     * | +---------------------+ --+--
+     * | |   .............     |
+     * | +---------------------+
+     * | | read_ack_registerN  |
+     * | +---------------------+ --+--
+     * | |      CPER           |   |
+     * | |      ....           | GHES_MAX_RAW_DATA_LENGT
+     * | |      CPER           |   |
+     * | +---------------------+ --+--
+     * | |    ..........       |
+     * | +---------------------+
+     * | |      CPER           |
+     * | |      ....           |
+     * | |      CPER           |
+     * | +---------------------+
+     */
+    if (physical_address && notify < ACPI_HEST_NOTIFY_RESERVED) {
+        /* Find and check the source id for this new CPER */
+        if (error_source_id[notify] != 0xff) {
+            start_addr += error_source_id[notify] * GHES_ADDRESS_SIZE;
+        } else {
+            goto out;
+        }
+
+        cpu_physical_memory_read(start_addr, &error_block_addr,
+                                    GHES_ADDRESS_SIZE);
+
+        read_ack_register_addr = start_addr +
+                        ACPI_HEST_ERROR_SOURCE_COUNT * GHES_ADDRESS_SIZE;
+retry:
+        cpu_physical_memory_read(read_ack_register_addr,
+                                 &read_ack_register, GHES_ADDRESS_SIZE);
+
+        /* zero means OSPM does not acknowledge the error */
+        if (!read_ack_register) {
+            if (loop < 3) {
+                usleep(100 * 1000);
+                loop++;
+                goto retry;
+            } else {
+                error_report("Last time OSPM does not acknowledge the error,"
+                    " record CPER failed this time, set the ack value to"
+                    " avoid blocking next time CPER record! exit");
+                read_ack_register = 1;
+                cpu_physical_memory_write(read_ack_register_addr,
+                    &read_ack_register, GHES_ADDRESS_SIZE);
+            }
+        } else {
+            if (error_block_addr) {
+                read_ack_register = 0;
+                cpu_physical_memory_write(read_ack_register_addr,
+                    &read_ack_register, GHES_ADDRESS_SIZE);
+                ret = ghes_record_mem_error(error_block_addr, physical_address);
+            }
+        }
+    }
+
+out:
+    return ret;
+}
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 3d78ff6..b7d45cd 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -45,6 +45,7 @@
 #include "hw/arm/virt.h"
 #include "sysemu/numa.h"
 #include "kvm_arm.h"
+#include "hw/acpi/hest_ghes.h"
 
 #define ARM_SPI_BASE 32
 #define ACPI_POWER_BUTTON_DEVICE "PWRB"
@@ -771,6 +772,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     acpi_add_table(table_offsets, tables_blob);
     build_spcr(tables_blob, tables->linker, vms);
 
+    acpi_add_table(table_offsets, tables_blob);
+    build_hardware_error_table(tables->hardware_errors, tables->linker);
+    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
+
+
     if (nb_numa_nodes > 0) {
         acpi_add_table(table_offsets, tables_blob);
         build_srat(tables_blob, tables->linker, vms);
@@ -887,6 +893,8 @@ void virt_acpi_setup(VirtMachineState *vms)
     fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
                     acpi_data_len(tables.tcpalog));
 
+    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
+
     build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
                                               ACPI_BUILD_RSDP_FILE, 0);
 
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 88d0738..7f7b55c 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -211,6 +211,7 @@ struct AcpiBuildTables {
     GArray *rsdp;
     GArray *tcpalog;
     GArray *vmgenid;
+    GArray *hardware_errors;
     BIOSLinker *linker;
 } AcpiBuildTables;
 
diff --git a/include/hw/acpi/hest_ghes.h b/include/hw/acpi/hest_ghes.h
new file mode 100644
index 0000000..420e825
--- /dev/null
+++ b/include/hw/acpi/hest_ghes.h
@@ -0,0 +1,82 @@
+/* Support for generating APEI tables and record CPER for Guests
+ *
+ * Copyright (C) 2017 HuaWei Corporation.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACPI_GHES_H
+#define ACPI_GHES_H
+
+#include "hw/acpi/bios-linker-loader.h"
+
+#define GHES_ERRORS_FW_CFG_FILE         "etc/hardware_errors"
+#define GHES_DATA_ADDR_FW_CFG_FILE      "etc/hardware_errors_addr"
+
+#define GHES_CPER_OK            1
+#define GHES_CPER_FAIL          0
+
+/* The Address field is 64-bit size, ACPI 2.0/3.0: 5.2.3.1 Generic Address
+ * Structure
+ */
+#define GHES_ADDRESS_SIZE           8
+
+#define GHES_DATA_LENGTH            72
+#define GHES_CPER_LENGTH            80
+
+#define ReadAckPreserve             0xfffffffe
+#define ReadAckWrite                0x1
+
+/* The max size in bytes for one error block */
+#define GHES_MAX_RAW_DATA_LENGTH        0x1000
+/* Now only have GPIO-Signal and ARMv8 SEA notification types error sources
+ */
+#define ACPI_HEST_ERROR_SOURCE_COUNT    2
+
+/*
+ * | +--------------------------+ 0
+ * | |        Header            |
+ * | +--------------------------+ 40---+-
+ * | | .................        |      |
+ * | | error_status_address-----+ 60   |
+ * | | .................        |      |
+ * | | read_ack_register--------+ 104  92
+ * | | read_ack_preserve        |      |
+ * | | read_ack_write           |      |
+ * + +--------------------------+ 132--+-
+ *
+ * From above GHES definition, the error status address offset is 60;
+ * the Read ack register offset is 104, the whole size of GHESv2 is 92
+ */
+
+/* The error status address offset in GHES */
+#define ERROR_STATUS_ADDRESS_OFFSET(start_addr, n)     (start_addr + 60 + \
+                    offsetof(struct AcpiGenericAddress, address) + n * 92)
+
+/* The read Ack register offset in GHES */
+#define READ_ACK_REGISTER_ADDRESS_OFFSET(start_addr, n) (start_addr + 104 + \
+                    offsetof(struct AcpiGenericAddress, address) + n * 92)
+
+typedef struct GhesState {
+    uint64_t ghes_addr_le;
+} GhesState;
+
+void build_apei_ghes(GArray *table_data, GArray *hardware_error,
+                    BIOSLinker *linker);
+void build_hardware_error_table(GArray *hardware_errors, BIOSLinker *linker);
+void ghes_add_fw_cfg(FWCfgState *s, GArray *hardware_errors);
+bool ghes_record_errors(uint32_t notify, uint64_t error_physical_addr);
+#endif
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 3/9] docs: APEI GHES generation and CPER record description
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add APEI/GHES detailed design document

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address Igor's comments to add a doc
---
 docs/specs/acpi_hest_ghes.txt | 97 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 docs/specs/acpi_hest_ghes.txt

diff --git a/docs/specs/acpi_hest_ghes.txt b/docs/specs/acpi_hest_ghes.txt
new file mode 100644
index 0000000..fbfc787
--- /dev/null
+++ b/docs/specs/acpi_hest_ghes.txt
@@ -0,0 +1,97 @@
+APEI tables generating and CPER record
+=============================
+
+Copyright (C) 2017 HuaWei Corporation.
+
+Design Details:
+-------------------
+
+       etc/acpi/tables                                 etc/hardware_errors
+    ====================                      ==========================================
++ +--------------------------+            +-----------------------+
+| | HEST                     |            |    address            |            +--------------+
+| +--------------------------+            |    registers          |            | Error Status |
+| | GHES1                    |            | +---------------------+            | Data Block 1 |
+| +--------------------------+ +--------->| |error_block_address1 |----------->| +------------+
+| | .................        | |          | +---------------------+            | |  CPER      |
+| | error_status_address-----+-+ +------->| |error_block_address2 |--------+   | |  CPER      |
+| | .................        |   |        | +---------------------+        |   | |  ....      |
+| | read_ack_register--------+-+ |        | |    ..............   |        |   | |  CPER      |
+| | read_ack_preserve        | | |        +-----------------------+        |   | +------------+
+| | read_ack_write           | | | +----->| |error_block_addressN |------+ |   | Error Status |
++ +--------------------------+ | | |      | +---------------------+      | |   | Data Block 2 |
+| | GHES2                    | +-+-+----->| |read_ack_register1   |      | +-->| +------------+
++ +--------------------------+   | |      | +---------------------+      |     | |  CPER      |
+| | .................        |   | | +--->| |read_ack_register2   |      |     | |  CPER      |
+| | error_status_address-----+---+ | |    | +---------------------+      |     | |  ....      |
+| | .................        |     | |    | |  .............      |      |     | |  CPER      |
+| | read_ack_register--------+-----+-+    | +---------------------+      |     +-+------------+
+| | read_ack_preserve        |     |   +->| |read_ack_registerN   |      |     | |..........  |
+| | read_ack_write           |     |   |  | +---------------------+      |     | +------------+
++ +--------------------------|     |   |                                 |     | Error Status |
+| | ...............          |     |   |                                 |     | Data Block N |
++ +--------------------------+     |   |                                 +---->| +------------+
+| | GHESN                    |     |   |                                       | |  CPER      |
++ +--------------------------+     |   |                                       | |  CPER      |
+| | .................        |     |   |                                       | |  ....      |
+| | error_status_address-----+-----+   |                                       | |  CPER      |
+| | .................        |         |                                       +-+------------+
+| | read_ack_register--------+---------+
+| | read_ack_preserve        |
+| | read_ack_write           |
++ +--------------------------+
+
+(1) QEMU generates the ACPI HEST table. This table goes in the current
+    "etc/acpi/tables" fw_cfg blob. Each error source has different
+    notification type.
+
+(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
+    also need to populate this blob. The "etc/hardwre_errors" fw_cfg blob
+    contains one address registers table and one Error Status Data Block
+    table, all of which are pre-allocated.
+
+(3) The address registers table contains N Error Block Address entries
+    and N Read Ack Address entries, the size for each entry is 8-byte.
+    The Error Status Data Block table contains N Error Status Data Block
+    entries, the size for each entry is 4096(0x1000) bytes. The total size
+    for "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
+
+(4) QEMU generates the ACPI linker/loader script for the firmware
+
+(4a) The HEST table is part of "etc/acpi/tables", the firmware already
+    allocates the memory for it, because QEMU already generates an ALLOCATE
+    linker/loader command for it
+
+(4b) QEMU creates another ALLOCATE command for the "etc/hardware_errors"
+    blob. The firmware allocates memory for this blob and downloads it.
+
+(5) QEMU generates N ADD_POINTER commands, which patch address in the
+    "error_status_address" fields of the HEST table with a pointer to the
+    corresponding "address registers" in the downloaded "etc/hardware_errors"
+    blob.
+
+(6) QEMU generates N ADD_POINTER commands, which patch address in the
+    "read_ack_register" fields of the HEST table with a pointer to the
+    corresponding "address registers" in the downloaded "etc/hardware_errors" blob.
+
+(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
+    address in the " error_block_address" fields with a pointer to the
+    respective "Error Status Data Block" in the downloaded "etc/hardware_errors"
+    blob.
+
+(8) QEMU Defines a third and write-only fw_cfg blob which is called
+    "etc/hardware_errors_addr". Through that blob, the firmware can send back
+    the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
+    blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER commands
+    for the firmware, the firmware will write back the start address of
+    "etc/hardware_errors" blob to fw_cfg file "etc/hardware_errors_addr". Then
+    Qemu will know the Error Status Data Block for every error source. Each of
+    Error Status Data Block has fixed size which is 4096(0x1000).
+
+(9) When QEMU gets SIGBUS from the kernel, QEMU formats the CPER right into
+    guest memory, and then injects whatever interrupt (or assert whatever GPIO line)
+    as a notification which is necessary for notifying the guest.
+
+(10) This notification (in virtual hardware) will be handled by guest kernel,
+    guest APEI driver will read the CPER which is recorded by QEMU and do the
+    recovery.
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 3/9] docs: APEI GHES generation and CPER record description
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add APEI/GHES detailed design document

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address Igor's comments to add a doc
---
 docs/specs/acpi_hest_ghes.txt | 97 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
 create mode 100644 docs/specs/acpi_hest_ghes.txt

diff --git a/docs/specs/acpi_hest_ghes.txt b/docs/specs/acpi_hest_ghes.txt
new file mode 100644
index 0000000..fbfc787
--- /dev/null
+++ b/docs/specs/acpi_hest_ghes.txt
@@ -0,0 +1,97 @@
+APEI tables generating and CPER record
+=============================
+
+Copyright (C) 2017 HuaWei Corporation.
+
+Design Details:
+-------------------
+
+       etc/acpi/tables                                 etc/hardware_errors
+    ====================                      ==========================================
++ +--------------------------+            +-----------------------+
+| | HEST                     |            |    address            |            +--------------+
+| +--------------------------+            |    registers          |            | Error Status |
+| | GHES1                    |            | +---------------------+            | Data Block 1 |
+| +--------------------------+ +--------->| |error_block_address1 |----------->| +------------+
+| | .................        | |          | +---------------------+            | |  CPER      |
+| | error_status_address-----+-+ +------->| |error_block_address2 |--------+   | |  CPER      |
+| | .................        |   |        | +---------------------+        |   | |  ....      |
+| | read_ack_register--------+-+ |        | |    ..............   |        |   | |  CPER      |
+| | read_ack_preserve        | | |        +-----------------------+        |   | +------------+
+| | read_ack_write           | | | +----->| |error_block_addressN |------+ |   | Error Status |
++ +--------------------------+ | | |      | +---------------------+      | |   | Data Block 2 |
+| | GHES2                    | +-+-+----->| |read_ack_register1   |      | +-->| +------------+
++ +--------------------------+   | |      | +---------------------+      |     | |  CPER      |
+| | .................        |   | | +--->| |read_ack_register2   |      |     | |  CPER      |
+| | error_status_address-----+---+ | |    | +---------------------+      |     | |  ....      |
+| | .................        |     | |    | |  .............      |      |     | |  CPER      |
+| | read_ack_register--------+-----+-+    | +---------------------+      |     +-+------------+
+| | read_ack_preserve        |     |   +->| |read_ack_registerN   |      |     | |..........  |
+| | read_ack_write           |     |   |  | +---------------------+      |     | +------------+
++ +--------------------------|     |   |                                 |     | Error Status |
+| | ...............          |     |   |                                 |     | Data Block N |
++ +--------------------------+     |   |                                 +---->| +------------+
+| | GHESN                    |     |   |                                       | |  CPER      |
++ +--------------------------+     |   |                                       | |  CPER      |
+| | .................        |     |   |                                       | |  ....      |
+| | error_status_address-----+-----+   |                                       | |  CPER      |
+| | .................        |         |                                       +-+------------+
+| | read_ack_register--------+---------+
+| | read_ack_preserve        |
+| | read_ack_write           |
++ +--------------------------+
+
+(1) QEMU generates the ACPI HEST table. This table goes in the current
+    "etc/acpi/tables" fw_cfg blob. Each error source has different
+    notification type.
+
+(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
+    also need to populate this blob. The "etc/hardwre_errors" fw_cfg blob
+    contains one address registers table and one Error Status Data Block
+    table, all of which are pre-allocated.
+
+(3) The address registers table contains N Error Block Address entries
+    and N Read Ack Address entries, the size for each entry is 8-byte.
+    The Error Status Data Block table contains N Error Status Data Block
+    entries, the size for each entry is 4096(0x1000) bytes. The total size
+    for "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
+
+(4) QEMU generates the ACPI linker/loader script for the firmware
+
+(4a) The HEST table is part of "etc/acpi/tables", the firmware already
+    allocates the memory for it, because QEMU already generates an ALLOCATE
+    linker/loader command for it
+
+(4b) QEMU creates another ALLOCATE command for the "etc/hardware_errors"
+    blob. The firmware allocates memory for this blob and downloads it.
+
+(5) QEMU generates N ADD_POINTER commands, which patch address in the
+    "error_status_address" fields of the HEST table with a pointer to the
+    corresponding "address registers" in the downloaded "etc/hardware_errors"
+    blob.
+
+(6) QEMU generates N ADD_POINTER commands, which patch address in the
+    "read_ack_register" fields of the HEST table with a pointer to the
+    corresponding "address registers" in the downloaded "etc/hardware_errors" blob.
+
+(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
+    address in the " error_block_address" fields with a pointer to the
+    respective "Error Status Data Block" in the downloaded "etc/hardware_errors"
+    blob.
+
+(8) QEMU Defines a third and write-only fw_cfg blob which is called
+    "etc/hardware_errors_addr". Through that blob, the firmware can send back
+    the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
+    blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER commands
+    for the firmware, the firmware will write back the start address of
+    "etc/hardware_errors" blob to fw_cfg file "etc/hardware_errors_addr". Then
+    Qemu will know the Error Status Data Block for every error source. Each of
+    Error Status Data Block has fixed size which is 4096(0x1000).
+
+(9) When QEMU gets SIGBUS from the kernel, QEMU formats the CPER right into
+    guest memory, and then injects whatever interrupt (or assert whatever GPIO line)
+    as a notification which is necessary for notifying the guest.
+
+(10) This notification (in virtual hardware) will be handled by guest kernel,
+    guest APEI driver will read the CPER which is recorded by QEMU and do the
+    recovery.
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add CONFIG_ACPI_APEI configuration in the arm-softmmu.mak
and add build choice in the Makefile.objs.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
 default-configs/arm-softmmu.mak | 1 +
 hw/acpi/Makefile.objs           | 1 +
 2 files changed, 2 insertions(+)

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index bbdd3c1..c362113 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -129,3 +129,4 @@ CONFIG_ACPI=y
 CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_GPIO_KEY=y
+CONFIG_ACPI_APEI=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 11c35bc..bafb148 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
 common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
 common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
+common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o
 common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
 
 common-obj-y += acpi_interface.o
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add CONFIG_ACPI_APEI configuration in the arm-softmmu.mak
and add build choice in the Makefile.objs.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
 default-configs/arm-softmmu.mak | 1 +
 hw/acpi/Makefile.objs           | 1 +
 2 files changed, 2 insertions(+)

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index bbdd3c1..c362113 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -129,3 +129,4 @@ CONFIG_ACPI=y
 CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_GPIO_KEY=y
+CONFIG_ACPI_APEI=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 11c35bc..bafb148 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
 common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
 common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
+common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o
 common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
 
 common-obj-y += acpi_interface.o
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add synchronous external abort injection logic, setup
exception type and syndrome value. When switch to guest,
guest will jump to the synchronous external abort vector
table entry.

The ESR_ELx.DFSC is set to synchronous external abort(0x10),
and ESR_ELx.FnV is set to not valid(0x1), which will tell
guest that FAR is not valid and holds an UNKNOWN value.
These value will be set to KVM register structures through
KVM_SET_ONE_REG IOCTL.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Marc is against that KVM inject the synchronous external abort(SEA) in [1],
so user space how to inject it. The test result that injection SEA to guest by Qemu
is shown in [2].

[1]: https://lkml.org/lkml/2017/3/2/110
[2]:
Taking exception 4 [Data Abort]
...from EL0 to EL1
...with ESR 0x24/0x92000410
...with FAR 0x0
...with ELR 0x40cf04
...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
after kvm_inject_arm_sea
Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
Hardware name: linux,dummy-virt (DT)
task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
PC is at 0x40cf04
LR is at 0x40cdec
pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
sp : 0000007ff7b24130
x29: 0000007ff7b24260 x28: 0000000000000000
x27: 00000000000000ad x26: 000000000049c000
x25: 000000000048904b x24: 000000000049c000
x23: 0000000040600000 x22: 0000007ff7b243a0
x21: 0000000000000002 x20: 0000000000000000
x19: 0000000000000020 x18: 0000000000000000
x17: 000000000049c6d0 x16: 0000007fa22c85c0
x15: 0000000000005798 x14: 0000007fa2205f1c
x13: 0000007fa241ccb0 x12: 0000000000000137
x11: 0000000000000000 x10: 0000000000000000
x9 : 0000000000000000 x8 : 00000000000000de
x7 : 0000000000000000 x6 : 0000000000002000
x5 : 0000000040600000 x4 : 0000000000000003
x3 : 0000000000000001 x2 : 0000000000000000
x1 : 0000000000000000 x0 : 0000007fa2418000
---
 target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index a16abc8..c00450d 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
     return KVM_PUT_RUNTIME_STATE;
 }
 
+static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
+{
+    int i;
+
+    for (i = 0; i < cpu->cpreg_array_len; i++) {
+        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
+        const ARMCPRegInfo *ri;
+        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
+        if (!ri) {
+            continue;
+        }
+
+        if (ri->type & ARM_CP_NO_RAW) {
+            continue;
+        }
+
+        if (ri->fieldoffset == fieldoffset) {
+            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
+            return 0;
+        }
+    }
+    return -EINVAL;
+}
+
+/* Inject synchronous external abort */
+static void kvm_inject_arm_sea(CPUState *c)
+{
+    ARMCPU *cpu = ARM_CPU(c);
+    CPUARMState *env = &cpu->env;
+    unsigned long cpsr = pstate_read(env);
+    uint32_t esr, ret;
+
+    /* This exception is synchronous data abort*/
+    c->exception_index = EXCP_DATA_ABORT;
+    /* Inject the exception to guest El1 */
+    env->exception.target_el = 1;
+    CPUClass *cc = CPU_GET_CLASS(c);
+
+    /* Set the DFSC to synchronous external abort and set FnV to not valid,
+     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
+     */
+    esr = (0x10 | (1 << 10));
+
+    /* This exception comes from lower or current exception level. */
+    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
+        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
+    } else {
+        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
+    }
+
+    /* For the AArch64, instruction length is 32-bit */
+    esr |= ARM_EL_IL;
+    env->exception.syndrome = esr;
+
+    cc->do_interrupt(c);
+
+    /* set ESR_EL1 */
+    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
+
+    if (ret) {
+        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
+        abort();
+    }
+}
+
 #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
                  KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add synchronous external abort injection logic, setup
exception type and syndrome value. When switch to guest,
guest will jump to the synchronous external abort vector
table entry.

The ESR_ELx.DFSC is set to synchronous external abort(0x10),
and ESR_ELx.FnV is set to not valid(0x1), which will tell
guest that FAR is not valid and holds an UNKNOWN value.
These value will be set to KVM register structures through
KVM_SET_ONE_REG IOCTL.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Marc is against that KVM inject the synchronous external abort(SEA) in [1],
so user space how to inject it. The test result that injection SEA to guest by Qemu
is shown in [2].

[1]: https://lkml.org/lkml/2017/3/2/110
[2]:
Taking exception 4 [Data Abort]
...from EL0 to EL1
...with ESR 0x24/0x92000410
...with FAR 0x0
...with ELR 0x40cf04
...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
after kvm_inject_arm_sea
Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
Hardware name: linux,dummy-virt (DT)
task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
PC is at 0x40cf04
LR is at 0x40cdec
pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
sp : 0000007ff7b24130
x29: 0000007ff7b24260 x28: 0000000000000000
x27: 00000000000000ad x26: 000000000049c000
x25: 000000000048904b x24: 000000000049c000
x23: 0000000040600000 x22: 0000007ff7b243a0
x21: 0000000000000002 x20: 0000000000000000
x19: 0000000000000020 x18: 0000000000000000
x17: 000000000049c6d0 x16: 0000007fa22c85c0
x15: 0000000000005798 x14: 0000007fa2205f1c
x13: 0000007fa241ccb0 x12: 0000000000000137
x11: 0000000000000000 x10: 0000000000000000
x9 : 0000000000000000 x8 : 00000000000000de
x7 : 0000000000000000 x6 : 0000000000002000
x5 : 0000000040600000 x4 : 0000000000000003
x3 : 0000000000000001 x2 : 0000000000000000
x1 : 0000000000000000 x0 : 0000007fa2418000
---
 target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index a16abc8..c00450d 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
     return KVM_PUT_RUNTIME_STATE;
 }
 
+static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
+{
+    int i;
+
+    for (i = 0; i < cpu->cpreg_array_len; i++) {
+        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
+        const ARMCPRegInfo *ri;
+        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
+        if (!ri) {
+            continue;
+        }
+
+        if (ri->type & ARM_CP_NO_RAW) {
+            continue;
+        }
+
+        if (ri->fieldoffset == fieldoffset) {
+            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
+            return 0;
+        }
+    }
+    return -EINVAL;
+}
+
+/* Inject synchronous external abort */
+static void kvm_inject_arm_sea(CPUState *c)
+{
+    ARMCPU *cpu = ARM_CPU(c);
+    CPUARMState *env = &cpu->env;
+    unsigned long cpsr = pstate_read(env);
+    uint32_t esr, ret;
+
+    /* This exception is synchronous data abort*/
+    c->exception_index = EXCP_DATA_ABORT;
+    /* Inject the exception to guest El1 */
+    env->exception.target_el = 1;
+    CPUClass *cc = CPU_GET_CLASS(c);
+
+    /* Set the DFSC to synchronous external abort and set FnV to not valid,
+     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
+     */
+    esr = (0x10 | (1 << 10));
+
+    /* This exception comes from lower or current exception level. */
+    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
+        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
+    } else {
+        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
+    }
+
+    /* For the AArch64, instruction length is 32-bit */
+    esr |= ARM_EL_IL;
+    env->exception.syndrome = esr;
+
+    cc->do_interrupt(c);
+
+    /* set ESR_EL1 */
+    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
+
+    if (ret) {
+        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
+        abort();
+    }
+}
+
 #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
                  KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 6/9] Move related hwpoison page functions to accel/kvm/ folder
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

kvm_hwpoison_page_add() and kvm_unpoison_all() will be used both
by X86 and ARM platforms, so move these functions to a common
accel/kvm/ folder to avoid duplicate code.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address Peter's comments to move related hwpoison page function to accel/kvm folder in [1]
Address Paolo's comments to move HWPoisonPage definition back to accel/kvm/kvm-all.c

[1]:
https://lists.gnu.org/archive/html/qemu-arm/2017-09/msg00077.html
https://lists.gnu.org/archive/html/qemu-arm/2017-09/msg00152.html
---
 accel/kvm/kvm-all.c     | 33 +++++++++++++++++++++++++++++++++
 include/exec/ram_addr.h |  5 +++++
 target/i386/kvm.c       | 33 ---------------------------------
 3 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 46ce479..2412ea6 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -564,6 +564,39 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
+typedef struct HWPoisonPage {
+    ram_addr_t ram_addr;
+    QLIST_ENTRY(HWPoisonPage) list;
+} HWPoisonPage;
+
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
+    QLIST_HEAD_INITIALIZER(hwpoison_page_list);
+
+void kvm_unpoison_all(void *param)
+{
+    HWPoisonPage *page, *next_page;
+
+    QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
+        QLIST_REMOVE(page, list);
+        qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
+        g_free(page);
+    }
+}
+
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
+{
+    HWPoisonPage *page;
+
+    QLIST_FOREACH(page, &hwpoison_page_list, list) {
+        if (page->ram_addr == ram_addr) {
+            return;
+        }
+    }
+    page = g_new(HWPoisonPage, 1);
+    page->ram_addr = ram_addr;
+    QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
+}
+
 static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
 {
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index d017639..41d9c37 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -80,6 +80,11 @@ void qemu_ram_free(RAMBlock *block);
 
 int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp);
 
+/* Add a poisoned page to the list */
+void kvm_hwpoison_page_add(ram_addr_t ram_addr);
+/* Free and remove all the poisoned pages in the list */
+void kvm_unpoison_all(void *param);
+
 #define DIRTY_CLIENTS_ALL     ((1 << DIRTY_MEMORY_NUM) - 1)
 #define DIRTY_CLIENTS_NOCODE  (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
 
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 6db7783..3e1afb6 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -390,39 +390,6 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
     return ret;
 }
 
-typedef struct HWPoisonPage {
-    ram_addr_t ram_addr;
-    QLIST_ENTRY(HWPoisonPage) list;
-} HWPoisonPage;
-
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
-    QLIST_HEAD_INITIALIZER(hwpoison_page_list);
-
-static void kvm_unpoison_all(void *param)
-{
-    HWPoisonPage *page, *next_page;
-
-    QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
-        QLIST_REMOVE(page, list);
-        qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
-        g_free(page);
-    }
-}
-
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
-{
-    HWPoisonPage *page;
-
-    QLIST_FOREACH(page, &hwpoison_page_list, list) {
-        if (page->ram_addr == ram_addr) {
-            return;
-        }
-    }
-    page = g_new(HWPoisonPage, 1);
-    page->ram_addr = ram_addr;
-    QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
-}
-
 static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
                                      int *max_banks)
 {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 6/9] Move related hwpoison page functions to accel/kvm/ folder
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

kvm_hwpoison_page_add() and kvm_unpoison_all() will be used both
by X86 and ARM platforms, so move these functions to a common
accel/kvm/ folder to avoid duplicate code.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address Peter's comments to move related hwpoison page function to accel/kvm folder in [1]
Address Paolo's comments to move HWPoisonPage definition back to accel/kvm/kvm-all.c

[1]:
https://lists.gnu.org/archive/html/qemu-arm/2017-09/msg00077.html
https://lists.gnu.org/archive/html/qemu-arm/2017-09/msg00152.html
---
 accel/kvm/kvm-all.c     | 33 +++++++++++++++++++++++++++++++++
 include/exec/ram_addr.h |  5 +++++
 target/i386/kvm.c       | 33 ---------------------------------
 3 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 46ce479..2412ea6 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -564,6 +564,39 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
+typedef struct HWPoisonPage {
+    ram_addr_t ram_addr;
+    QLIST_ENTRY(HWPoisonPage) list;
+} HWPoisonPage;
+
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
+    QLIST_HEAD_INITIALIZER(hwpoison_page_list);
+
+void kvm_unpoison_all(void *param)
+{
+    HWPoisonPage *page, *next_page;
+
+    QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
+        QLIST_REMOVE(page, list);
+        qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
+        g_free(page);
+    }
+}
+
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
+{
+    HWPoisonPage *page;
+
+    QLIST_FOREACH(page, &hwpoison_page_list, list) {
+        if (page->ram_addr == ram_addr) {
+            return;
+        }
+    }
+    page = g_new(HWPoisonPage, 1);
+    page->ram_addr = ram_addr;
+    QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
+}
+
 static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
 {
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index d017639..41d9c37 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -80,6 +80,11 @@ void qemu_ram_free(RAMBlock *block);
 
 int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp);
 
+/* Add a poisoned page to the list */
+void kvm_hwpoison_page_add(ram_addr_t ram_addr);
+/* Free and remove all the poisoned pages in the list */
+void kvm_unpoison_all(void *param);
+
 #define DIRTY_CLIENTS_ALL     ((1 << DIRTY_MEMORY_NUM) - 1)
 #define DIRTY_CLIENTS_NOCODE  (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
 
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 6db7783..3e1afb6 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -390,39 +390,6 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
     return ret;
 }
 
-typedef struct HWPoisonPage {
-    ram_addr_t ram_addr;
-    QLIST_ENTRY(HWPoisonPage) list;
-} HWPoisonPage;
-
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
-    QLIST_HEAD_INITIALIZER(hwpoison_page_list);
-
-static void kvm_unpoison_all(void *param)
-{
-    HWPoisonPage *page, *next_page;
-
-    QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
-        QLIST_REMOVE(page, list);
-        qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
-        g_free(page);
-    }
-}
-
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
-{
-    HWPoisonPage *page;
-
-    QLIST_FOREACH(page, &hwpoison_page_list, list) {
-        if (page->ram_addr == ram_addr) {
-            return;
-        }
-    }
-    page = g_new(HWPoisonPage, 1);
-    page->ram_addr = ram_addr;
-    QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
-}
-
 static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
                                      int *max_banks)
 {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

In ARM platform we implements a notification of error events
via a GPIO pin. For this GPIO-signaled events, we choose GPIO
pin 4 for hardware error device (PNP0C33), So _E04 should be
added to ACPI DSDT table. When GPIO-pin 4 signaled a events,
the guest ACPI driver will receive this notification and
handing the error.

In order to better trigger the GPIO IRQ, we defined a notifier
hardware_error_notifiers. If Qemu wants to deliver a GPIO-Signal
notification, will call it.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
1. Address discussion result about guest APEI notification type for SIGBUS_MCEERR_AO SIGBUS in [1],
   the discussion conclusion is using GPIO-Signal

[1]:
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03397.html
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03467.html
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03601.html
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03775.html

2. The ASL dump for the GPIO and hardware error device

................
Device (GPO0)
{
    Name (_AEI, ResourceTemplate ()  // _AEI: ACPI Event Interrupts
    {
        .............
        GpioInt (Edge, ActiveHigh, Exclusive, PullUp, 0x0000,
            "GPO0", 0x00, ResourceConsumer, ,
            )
            {   // Pin list
                0x0004
            }
    })
    Method (_E04, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
    {
        Notify (ERRD, 0x80) // Status Change
    }
}
Device (ERRD)
{
    Name (_HID, EisaId ("PNP0C33") /* Error Device */)  // _HID: Hardware ID
    Name (_UID, Zero)  // _UID: Unique ID
    Method (_STA, 0, NotSerialized)  // _STA: Status
    {
        Return (0x0F)
    }
}

3. Below is the guest log when Qemu notifies guest using GPIO-signal after record a CPER
[  504.164899] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
[  504.166970] {1}[Hardware Error]: event severity: recoverable
[  504.251650] {1}[Hardware Error]:  Error 0, type: recoverable
[  504.252974] {1}[Hardware Error]:   section_type: memory error
[  504.254380] {1}[Hardware Error]:   physical_address: 0x00000000000003ec
[  504.255879] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
---
 hw/arm/virt-acpi-build.c | 31 ++++++++++++++++++++++++++++++-
 hw/arm/virt.c            | 18 ++++++++++++++++++
 include/sysemu/sysemu.h  |  3 +++
 vl.c                     | 12 ++++++++++++
 4 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index b7d45cd..06c14b3 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,7 @@
 
 #define ARM_SPI_BASE 32
 #define ACPI_POWER_BUTTON_DEVICE "PWRB"
+#define ACPI_HARDWARE_ERROR_DEVICE "ERRD"
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 {
@@ -340,7 +341,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
 
     Aml *aei = aml_resource_template();
     /* Pin 3 for power button */
-    const uint32_t pin_list[1] = {3};
+    uint32_t pin_list[1] = {3};
+    aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
+                                 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
+                                 "GPO0", NULL, 0));
+
+    /* Pin 4 for hardware error device */
+    pin_list[0] = 4;
     aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
                                  AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
                                  "GPO0", NULL, 0));
@@ -351,6 +358,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
     aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
                                   aml_int(0x80)));
     aml_append(dev, method);
+
+    /* _E04 is handle for hardware error */
+    method = aml_method("_E04", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_notify(aml_name(ACPI_HARDWARE_ERROR_DEVICE),
+                                  aml_int(0x80)));
+    aml_append(dev, method);
+
     aml_append(scope, dev);
 }
 
@@ -363,6 +377,20 @@ static void acpi_dsdt_add_power_button(Aml *scope)
     aml_append(scope, dev);
 }
 
+static void acpi_dsdt_add_error_device(Aml *scope)
+{
+    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
+    Aml *method;
+
+    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
+    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
+
+    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_return(aml_int(0x0f)));
+    aml_append(dev, method);
+    aml_append(scope, dev);
+}
+
 /* RSDP */
 static GArray *
 build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
@@ -716,6 +744,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
                        (irqmap[VIRT_GPIO] + ARM_SPI_BASE));
     acpi_dsdt_add_power_button(scope);
+    acpi_dsdt_add_error_device(scope);
 
     aml_append(dsdt, scope);
 
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 6b7a0fe..68495c2 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -701,16 +701,27 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
 }
 
 static DeviceState *gpio_key_dev;
+static DeviceState *gpio_err_dev;
 static void virt_powerdown_req(Notifier *n, void *opaque)
 {
     /* use gpio Pin 3 for power button event */
     qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
 }
 
+static void virt_error_notify_req(Notifier *n, void *opaque)
+{
+    /* use gpio Pin 4 for hardware error event */
+    qemu_set_irq(qdev_get_gpio_in(gpio_err_dev, 0), 1);
+}
+
 static Notifier virt_system_powerdown_notifier = {
     .notify = virt_powerdown_req
 };
 
+static Notifier virt_hardware_error_notifier = {
+    .notify = virt_error_notify_req
+};
+
 static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
 {
     char *nodename;
@@ -739,6 +750,10 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
 
     gpio_key_dev = sysbus_create_simple("gpio-key", -1,
                                         qdev_get_gpio_in(pl061_dev, 3));
+
+    gpio_err_dev = sysbus_create_simple("gpio-key", -1,
+                                        qdev_get_gpio_in(pl061_dev, 4));
+
     qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
     qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
     qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
@@ -755,6 +770,9 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
     /* connect powerdown request */
     qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
 
+    /* connect hardware error notify request */
+    qemu_register_hardware_error_notifier(&virt_hardware_error_notifier);
+
     g_free(nodename);
 }
 
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index b213696..86931cf 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -75,6 +75,7 @@ void qemu_register_wakeup_notifier(Notifier *notifier);
 void qemu_system_shutdown_request(ShutdownCause reason);
 void qemu_system_powerdown_request(void);
 void qemu_register_powerdown_notifier(Notifier *notifier);
+void qemu_register_hardware_error_notifier(Notifier *notifier);
 void qemu_system_debug_request(void);
 void qemu_system_vmstop_request(RunState reason);
 void qemu_system_vmstop_request_prepare(void);
@@ -93,6 +94,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
 
 void qemu_announce_self(void);
 
+void qemu_hardware_error_notify(void);
+
 extern int autostart;
 
 typedef enum {
diff --git a/vl.c b/vl.c
index d632693..3552f7d 100644
--- a/vl.c
+++ b/vl.c
@@ -1614,6 +1614,8 @@ static int suspend_requested;
 static WakeupReason wakeup_reason;
 static NotifierList powerdown_notifiers =
     NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
+static NotifierList hardware_error_notifiers =
+    NOTIFIER_LIST_INITIALIZER(hardware_error_notifiers);
 static NotifierList suspend_notifiers =
     NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
 static NotifierList wakeup_notifiers =
@@ -1850,12 +1852,22 @@ void qemu_register_powerdown_notifier(Notifier *notifier)
     notifier_list_add(&powerdown_notifiers, notifier);
 }
 
+void qemu_register_hardware_error_notifier(Notifier *notifier)
+{
+    notifier_list_add(&hardware_error_notifiers, notifier);
+}
+
 void qemu_system_debug_request(void)
 {
     debug_requested = 1;
     qemu_notify_event();
 }
 
+void qemu_hardware_error_notify(void)
+{
+    notifier_list_notify(&hardware_error_notifiers, NULL);
+}
+
 static bool main_loop_should_exit(void)
 {
     RunState r;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

In ARM platform we implements a notification of error events
via a GPIO pin. For this GPIO-signaled events, we choose GPIO
pin 4 for hardware error device (PNP0C33), So _E04 should be
added to ACPI DSDT table. When GPIO-pin 4 signaled a events,
the guest ACPI driver will receive this notification and
handing the error.

In order to better trigger the GPIO IRQ, we defined a notifier
hardware_error_notifiers. If Qemu wants to deliver a GPIO-Signal
notification, will call it.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
1. Address discussion result about guest APEI notification type for SIGBUS_MCEERR_AO SIGBUS in [1],
   the discussion conclusion is using GPIO-Signal

[1]:
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03397.html
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03467.html
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03601.html
https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03775.html

2. The ASL dump for the GPIO and hardware error device

................
Device (GPO0)
{
    Name (_AEI, ResourceTemplate ()  // _AEI: ACPI Event Interrupts
    {
        .............
        GpioInt (Edge, ActiveHigh, Exclusive, PullUp, 0x0000,
            "GPO0", 0x00, ResourceConsumer, ,
            )
            {   // Pin list
                0x0004
            }
    })
    Method (_E04, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
    {
        Notify (ERRD, 0x80) // Status Change
    }
}
Device (ERRD)
{
    Name (_HID, EisaId ("PNP0C33") /* Error Device */)  // _HID: Hardware ID
    Name (_UID, Zero)  // _UID: Unique ID
    Method (_STA, 0, NotSerialized)  // _STA: Status
    {
        Return (0x0F)
    }
}

3. Below is the guest log when Qemu notifies guest using GPIO-signal after record a CPER
[  504.164899] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
[  504.166970] {1}[Hardware Error]: event severity: recoverable
[  504.251650] {1}[Hardware Error]:  Error 0, type: recoverable
[  504.252974] {1}[Hardware Error]:   section_type: memory error
[  504.254380] {1}[Hardware Error]:   physical_address: 0x00000000000003ec
[  504.255879] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
---
 hw/arm/virt-acpi-build.c | 31 ++++++++++++++++++++++++++++++-
 hw/arm/virt.c            | 18 ++++++++++++++++++
 include/sysemu/sysemu.h  |  3 +++
 vl.c                     | 12 ++++++++++++
 4 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index b7d45cd..06c14b3 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,7 @@
 
 #define ARM_SPI_BASE 32
 #define ACPI_POWER_BUTTON_DEVICE "PWRB"
+#define ACPI_HARDWARE_ERROR_DEVICE "ERRD"
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 {
@@ -340,7 +341,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
 
     Aml *aei = aml_resource_template();
     /* Pin 3 for power button */
-    const uint32_t pin_list[1] = {3};
+    uint32_t pin_list[1] = {3};
+    aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
+                                 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
+                                 "GPO0", NULL, 0));
+
+    /* Pin 4 for hardware error device */
+    pin_list[0] = 4;
     aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
                                  AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
                                  "GPO0", NULL, 0));
@@ -351,6 +358,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
     aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
                                   aml_int(0x80)));
     aml_append(dev, method);
+
+    /* _E04 is handle for hardware error */
+    method = aml_method("_E04", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_notify(aml_name(ACPI_HARDWARE_ERROR_DEVICE),
+                                  aml_int(0x80)));
+    aml_append(dev, method);
+
     aml_append(scope, dev);
 }
 
@@ -363,6 +377,20 @@ static void acpi_dsdt_add_power_button(Aml *scope)
     aml_append(scope, dev);
 }
 
+static void acpi_dsdt_add_error_device(Aml *scope)
+{
+    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
+    Aml *method;
+
+    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
+    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
+
+    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_return(aml_int(0x0f)));
+    aml_append(dev, method);
+    aml_append(scope, dev);
+}
+
 /* RSDP */
 static GArray *
 build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
@@ -716,6 +744,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
                        (irqmap[VIRT_GPIO] + ARM_SPI_BASE));
     acpi_dsdt_add_power_button(scope);
+    acpi_dsdt_add_error_device(scope);
 
     aml_append(dsdt, scope);
 
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 6b7a0fe..68495c2 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -701,16 +701,27 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
 }
 
 static DeviceState *gpio_key_dev;
+static DeviceState *gpio_err_dev;
 static void virt_powerdown_req(Notifier *n, void *opaque)
 {
     /* use gpio Pin 3 for power button event */
     qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
 }
 
+static void virt_error_notify_req(Notifier *n, void *opaque)
+{
+    /* use gpio Pin 4 for hardware error event */
+    qemu_set_irq(qdev_get_gpio_in(gpio_err_dev, 0), 1);
+}
+
 static Notifier virt_system_powerdown_notifier = {
     .notify = virt_powerdown_req
 };
 
+static Notifier virt_hardware_error_notifier = {
+    .notify = virt_error_notify_req
+};
+
 static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
 {
     char *nodename;
@@ -739,6 +750,10 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
 
     gpio_key_dev = sysbus_create_simple("gpio-key", -1,
                                         qdev_get_gpio_in(pl061_dev, 3));
+
+    gpio_err_dev = sysbus_create_simple("gpio-key", -1,
+                                        qdev_get_gpio_in(pl061_dev, 4));
+
     qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
     qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
     qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
@@ -755,6 +770,9 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
     /* connect powerdown request */
     qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
 
+    /* connect hardware error notify request */
+    qemu_register_hardware_error_notifier(&virt_hardware_error_notifier);
+
     g_free(nodename);
 }
 
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index b213696..86931cf 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -75,6 +75,7 @@ void qemu_register_wakeup_notifier(Notifier *notifier);
 void qemu_system_shutdown_request(ShutdownCause reason);
 void qemu_system_powerdown_request(void);
 void qemu_register_powerdown_notifier(Notifier *notifier);
+void qemu_register_hardware_error_notifier(Notifier *notifier);
 void qemu_system_debug_request(void);
 void qemu_system_vmstop_request(RunState reason);
 void qemu_system_vmstop_request_prepare(void);
@@ -93,6 +94,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
 
 void qemu_announce_self(void);
 
+void qemu_hardware_error_notify(void);
+
 extern int autostart;
 
 typedef enum {
diff --git a/vl.c b/vl.c
index d632693..3552f7d 100644
--- a/vl.c
+++ b/vl.c
@@ -1614,6 +1614,8 @@ static int suspend_requested;
 static WakeupReason wakeup_reason;
 static NotifierList powerdown_notifiers =
     NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
+static NotifierList hardware_error_notifiers =
+    NOTIFIER_LIST_INITIALIZER(hardware_error_notifiers);
 static NotifierList suspend_notifiers =
     NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
 static NotifierList wakeup_notifiers =
@@ -1850,12 +1852,22 @@ void qemu_register_powerdown_notifier(Notifier *notifier)
     notifier_list_add(&powerdown_notifiers, notifier);
 }
 
+void qemu_register_hardware_error_notifier(Notifier *notifier)
+{
+    notifier_list_add(&hardware_error_notifiers, notifier);
+}
+
 void qemu_system_debug_request(void)
 {
     debug_requested = 1;
     qemu_notify_event();
 }
 
+void qemu_hardware_error_notify(void)
+{
+    notifier_list_notify(&hardware_error_notifiers, NULL);
+}
+
 static bool main_loop_should_exit(void)
 {
     RunState r;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Support this feature since version 2.10, disable it by
default in the old version.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address Shannon's comments to add platform version in [1].

[1]: https://lkml.org/lkml/2017/8/25/821

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
 hw/arm/virt-acpi-build.c | 14 +++++++++-----
 hw/arm/virt.c            |  4 ++++
 include/hw/arm/virt.h    |  1 +
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 06c14b3..b6974ef 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     acpi_add_table(table_offsets, tables_blob);
     build_spcr(tables_blob, tables->linker, vms);
 
-    acpi_add_table(table_offsets, tables_blob);
-    build_hardware_error_table(tables->hardware_errors, tables->linker);
-    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
-
+    if (!vmc->no_ras) {
+        acpi_add_table(table_offsets, tables_blob);
+        build_hardware_error_table(tables->hardware_errors, tables->linker);
+        build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
+    }
 
     if (nb_numa_nodes > 0) {
         acpi_add_table(table_offsets, tables_blob);
@@ -891,6 +892,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
 
 void virt_acpi_setup(VirtMachineState *vms)
 {
+    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
     AcpiBuildTables tables;
     AcpiBuildState *build_state;
 
@@ -922,7 +924,9 @@ void virt_acpi_setup(VirtMachineState *vms)
     fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
                     acpi_data_len(tables.tcpalog));
 
-    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
+    if (!vmc->no_ras) {
+        ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
+    }
 
     build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
                                               ACPI_BUILD_RSDP_FILE, 0);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 68495c2..ab79988 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1732,8 +1732,12 @@ static void virt_2_9_instance_init(Object *obj)
 
 static void virt_machine_2_9_options(MachineClass *mc)
 {
+    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
     virt_machine_2_10_options(mc);
     SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_9);
+    /* memory recovery feature was introduced with 2.10 */
+    vmc->no_ras = true;
 }
 DEFINE_VIRT_MACHINE(2, 9)
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 33b0ff3..8fbd664 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -84,6 +84,7 @@ typedef struct {
     bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
+    bool no_ras;
     bool claim_edge_triggered_timers;
 } VirtMachineClass;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Support this feature since version 2.10, disable it by
default in the old version.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address Shannon's comments to add platform version in [1].

[1]: https://lkml.org/lkml/2017/8/25/821

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
 hw/arm/virt-acpi-build.c | 14 +++++++++-----
 hw/arm/virt.c            |  4 ++++
 include/hw/arm/virt.h    |  1 +
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 06c14b3..b6974ef 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
     acpi_add_table(table_offsets, tables_blob);
     build_spcr(tables_blob, tables->linker, vms);
 
-    acpi_add_table(table_offsets, tables_blob);
-    build_hardware_error_table(tables->hardware_errors, tables->linker);
-    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
-
+    if (!vmc->no_ras) {
+        acpi_add_table(table_offsets, tables_blob);
+        build_hardware_error_table(tables->hardware_errors, tables->linker);
+        build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
+    }
 
     if (nb_numa_nodes > 0) {
         acpi_add_table(table_offsets, tables_blob);
@@ -891,6 +892,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
 
 void virt_acpi_setup(VirtMachineState *vms)
 {
+    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
     AcpiBuildTables tables;
     AcpiBuildState *build_state;
 
@@ -922,7 +924,9 @@ void virt_acpi_setup(VirtMachineState *vms)
     fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
                     acpi_data_len(tables.tcpalog));
 
-    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
+    if (!vmc->no_ras) {
+        ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
+    }
 
     build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
                                               ACPI_BUILD_RSDP_FILE, 0);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 68495c2..ab79988 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1732,8 +1732,12 @@ static void virt_2_9_instance_init(Object *obj)
 
 static void virt_machine_2_9_options(MachineClass *mc)
 {
+    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
     virt_machine_2_10_options(mc);
     SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_9);
+    /* memory recovery feature was introduced with 2.10 */
+    vmc->no_ras = true;
 }
 DEFINE_VIRT_MACHINE(2, 9)
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 33b0ff3..8fbd664 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -84,6 +84,7 @@ typedef struct {
     bool disallow_affinity_adjustment;
     bool no_its;
     bool no_pmu;
+    bool no_ras;
     bool claim_edge_triggered_timers;
 } VirtMachineClass;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28  5:54   ` Dongjiu Geng
  -1 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
translates the host VA which is delivered by host to guest PA, then fill
this PA to CPER and fill the CPER to guest APEI GHES memory, finally
notify guest according to the SIGBUS type. There are two kinds of SIGBUS
that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.

If guest accesses the poisoned memory, it generates Synchronous External
Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
create a new CPER and add it to guest APEI GHES memory, then notify the
guest with a GPIO-Signal notification.

When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).

Suggested-by: James Morse <james.morse@arm.com>
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address James's comments to record CPER and notify guest for SIGBUS signal handling.
Shown some discussion in [1].

[1]:
https://lkml.org/lkml/2017/2/27/246
https://lkml.org/lkml/2017/9/14/241
https://lkml.org/lkml/2017/9/22/499
---
 include/sysemu/kvm.h |  2 +-
 target/arm/kvm.c     |  2 ++
 target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 3a458f5..90c1605 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
 /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
 unsigned long kvm_arch_vcpu_id(CPUState *cpu);
 
-#ifdef TARGET_I386
+#if defined(TARGET_I386) || defined(TARGET_AARCH64)
 #define KVM_HAVE_MCE_INJECTION 1
 void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
 #endif
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 7c17f0d..9d25f51 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -26,6 +26,7 @@
 #include "exec/address-spaces.h"
 #include "hw/boards.h"
 #include "qemu/log.h"
+#include "exec/ram_addr.h"
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
@@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 
     cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
 
+    qemu_register_reset(kvm_unpoison_all, NULL);
     type_register_static(&host_arm_cpu_type_info);
 
     return 0;
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index c00450d..6955d85 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -27,6 +27,9 @@
 #include "kvm_arm.h"
 #include "internals.h"
 #include "hw/arm/arm.h"
+#include "exec/ram_addr.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/hest_ghes.h"
 
 static bool have_guest_debug;
 
@@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
     return ret;
 }
 
+void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
+{
+    ram_addr_t ram_addr;
+    hwaddr paddr;
+
+    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
+    if (addr) {
+        ram_addr = qemu_ram_addr_from_host(addr);
+        if (ram_addr != RAM_ADDR_INVALID &&
+            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
+            kvm_hwpoison_page_add(ram_addr);
+            if (code == BUS_MCEERR_AR) {
+                kvm_cpu_synchronize_state(c);
+                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
+                kvm_inject_arm_sea(c);
+            } else if (code == BUS_MCEERR_AO) {
+                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
+                qemu_hardware_error_notify();
+            }
+            return;
+        }
+        fprintf(stderr, "Hardware memory error for memory used by "
+                "QEMU itself instead of guest system!\n");
+    }
+
+    if (code == BUS_MCEERR_AR) {
+        fprintf(stderr, "Hardware memory error!\n");
+        exit(1);
+    }
+}
+
 /* C6.6.29 BRK instruction */
 static const uint32_t brk_insn = 0xd4200000;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2017-12-28  5:54   ` Dongjiu Geng
  0 siblings, 0 replies; 83+ messages in thread
From: Dongjiu Geng @ 2017-12-28  5:54 UTC (permalink / raw)
  To: pbonzini, mst, imammedo, zhaoshenglong, peter.maydell, mtosatti,
	rth, ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm
  Cc: gengdongjiu, huangshaoyu, zhengqiang10, xuwei5

Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
translates the host VA which is delivered by host to guest PA, then fill
this PA to CPER and fill the CPER to guest APEI GHES memory, finally
notify guest according to the SIGBUS type. There are two kinds of SIGBUS
that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.

If guest accesses the poisoned memory, it generates Synchronous External
Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
create a new CPER and add it to guest APEI GHES memory, then notify the
guest with a GPIO-Signal notification.

When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).

Suggested-by: James Morse <james.morse@arm.com>
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
---
Address James's comments to record CPER and notify guest for SIGBUS signal handling.
Shown some discussion in [1].

[1]:
https://lkml.org/lkml/2017/2/27/246
https://lkml.org/lkml/2017/9/14/241
https://lkml.org/lkml/2017/9/22/499
---
 include/sysemu/kvm.h |  2 +-
 target/arm/kvm.c     |  2 ++
 target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 3a458f5..90c1605 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
 /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
 unsigned long kvm_arch_vcpu_id(CPUState *cpu);
 
-#ifdef TARGET_I386
+#if defined(TARGET_I386) || defined(TARGET_AARCH64)
 #define KVM_HAVE_MCE_INJECTION 1
 void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
 #endif
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 7c17f0d..9d25f51 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -26,6 +26,7 @@
 #include "exec/address-spaces.h"
 #include "hw/boards.h"
 #include "qemu/log.h"
+#include "exec/ram_addr.h"
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
@@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 
     cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
 
+    qemu_register_reset(kvm_unpoison_all, NULL);
     type_register_static(&host_arm_cpu_type_info);
 
     return 0;
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index c00450d..6955d85 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -27,6 +27,9 @@
 #include "kvm_arm.h"
 #include "internals.h"
 #include "hw/arm/arm.h"
+#include "exec/ram_addr.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/hest_ghes.h"
 
 static bool have_guest_debug;
 
@@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
     return ret;
 }
 
+void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
+{
+    ram_addr_t ram_addr;
+    hwaddr paddr;
+
+    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
+    if (addr) {
+        ram_addr = qemu_ram_addr_from_host(addr);
+        if (ram_addr != RAM_ADDR_INVALID &&
+            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
+            kvm_hwpoison_page_add(ram_addr);
+            if (code == BUS_MCEERR_AR) {
+                kvm_cpu_synchronize_state(c);
+                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
+                kvm_inject_arm_sea(c);
+            } else if (code == BUS_MCEERR_AO) {
+                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
+                qemu_hardware_error_notify();
+            }
+            return;
+        }
+        fprintf(stderr, "Hardware memory error for memory used by "
+                "QEMU itself instead of guest system!\n");
+    }
+
+    if (code == BUS_MCEERR_AR) {
+        fprintf(stderr, "Hardware memory error!\n");
+        exit(1);
+    }
+}
+
 /* C6.6.29 BRK instruction */
 static const uint32_t brk_insn = 0xd4200000;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 1/9] ACPI: add some GHES structures and macros definition
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28 12:29     ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 12:29 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:10 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Add Generic Error Status Block structures and some macros
> definitions, which is referred to the ACPI 4.0 or ACPI 6.1. The
> HEST table generation and CPER record will use them.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Change since v13:
> 1. Clean the new added structures and macros definition
> 
> Change since v12:
> 1. Address Igor's comments to to get rid of most structures and use
> build_append_int_noprefix() API to compose whole error status block
> and APEI table in [1]
> 
> [1]: https://lkml.org/lkml/2017/8/29/187
> ---
>  include/hw/acpi/acpi-defs.h | 52 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 72be675..fb2110c 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -298,6 +298,25 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
>  #define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
>  
>  /*
> + * Hardware Error Notification
> + */
> +enum AcpiHestNotifyType {
> +    ACPI_HEST_NOTIFY_POLLED = 0,
> +    ACPI_HEST_NOTIFY_EXTERNAL = 1,
> +    ACPI_HEST_NOTIFY_LOCAL = 2,
> +    ACPI_HEST_NOTIFY_SCI = 3,
> +    ACPI_HEST_NOTIFY_NMI = 4,
> +    ACPI_HEST_NOTIFY_CMCI = 5,  /* ACPI 5.0 */
for stuff coming from spec comment should be something like this
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */

i.e. concrete version, chapter/table
otherwise it could be hard to find definition in huge spec 

> +    ACPI_HEST_NOTIFY_MCE = 6,   /* ACPI 5.0 */
> +    ACPI_HEST_NOTIFY_GPIO = 7,  /* ACPI 6.0 */
> +    ACPI_HEST_NOTIFY_SEA = 8,   /* ACPI 6.1 */
> +    ACPI_HEST_NOTIFY_SEI = 9,   /* ACPI 6.1 */
> +    ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */
> +    ACPI_HEST_NOTIFY_SDEI = 11, /* ACPI 6.2 */
> +    ACPI_HEST_NOTIFY_RESERVED = 12 /* 12 and greater are reserved */
> +};
> +
> +/*
>   * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
>   */
>  #define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
> @@ -474,6 +493,39 @@ struct AcpiSystemResourceAffinityTable {
>  } QEMU_PACKED;
>  typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
>  
> +/*
> + * Generic Error Status Block
> + */
> +struct AcpiGenericErrorStatus {
> +    /* It is a bitmask composed of ACPI_GEBS_xxx macros */
> +    uint32_t block_status;
> +    uint32_t raw_data_offset;
> +    uint32_t raw_data_length;
> +    uint32_t data_length;
> +    uint32_t error_severity;
> +} QEMU_PACKED;
> +typedef struct AcpiGenericErrorStatus AcpiGenericErrorStatus;
> +
> +/*
> + * Masks for Block Status field above
> + */
> +#define ACPI_GEBS_UNCORRECTABLE          (1)
() are usually used with an expression and not with single value,
so drop that to be consistent with style of the header

> +
> +/*
> + * Value for Error Severity field above
> + */
> +enum AcpiGenericErrorSeverity {
> +    ACPI_CPER_SEV_RECOVERABLE,
> +    ACPI_CPER_SEV_FATAL,
> +    ACPI_CPER_SEV_CORRECTED,
> +    ACPI_CPER_SEV_NONE,
> +};
> +
> +/*
> + * Generic Hardware Error Source version 2
> + */
> +#define ACPI_HEST_SOURCE_GENERIC_ERROR_V2    (10)
ditto

> +
>  #define ACPI_SRAT_PROCESSOR_APIC     0
>  #define ACPI_SRAT_MEMORY             1
>  #define ACPI_SRAT_PROCESSOR_x2APIC   2

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 1/9] ACPI: add some GHES structures and macros definition
@ 2017-12-28 12:29     ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 12:29 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:10 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Add Generic Error Status Block structures and some macros
> definitions, which is referred to the ACPI 4.0 or ACPI 6.1. The
> HEST table generation and CPER record will use them.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Change since v13:
> 1. Clean the new added structures and macros definition
> 
> Change since v12:
> 1. Address Igor's comments to to get rid of most structures and use
> build_append_int_noprefix() API to compose whole error status block
> and APEI table in [1]
> 
> [1]: https://lkml.org/lkml/2017/8/29/187
> ---
>  include/hw/acpi/acpi-defs.h | 52 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 72be675..fb2110c 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -298,6 +298,25 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
>  #define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
>  
>  /*
> + * Hardware Error Notification
> + */
> +enum AcpiHestNotifyType {
> +    ACPI_HEST_NOTIFY_POLLED = 0,
> +    ACPI_HEST_NOTIFY_EXTERNAL = 1,
> +    ACPI_HEST_NOTIFY_LOCAL = 2,
> +    ACPI_HEST_NOTIFY_SCI = 3,
> +    ACPI_HEST_NOTIFY_NMI = 4,
> +    ACPI_HEST_NOTIFY_CMCI = 5,  /* ACPI 5.0 */
for stuff coming from spec comment should be something like this
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */

i.e. concrete version, chapter/table
otherwise it could be hard to find definition in huge spec 

> +    ACPI_HEST_NOTIFY_MCE = 6,   /* ACPI 5.0 */
> +    ACPI_HEST_NOTIFY_GPIO = 7,  /* ACPI 6.0 */
> +    ACPI_HEST_NOTIFY_SEA = 8,   /* ACPI 6.1 */
> +    ACPI_HEST_NOTIFY_SEI = 9,   /* ACPI 6.1 */
> +    ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */
> +    ACPI_HEST_NOTIFY_SDEI = 11, /* ACPI 6.2 */
> +    ACPI_HEST_NOTIFY_RESERVED = 12 /* 12 and greater are reserved */
> +};
> +
> +/*
>   * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
>   */
>  #define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
> @@ -474,6 +493,39 @@ struct AcpiSystemResourceAffinityTable {
>  } QEMU_PACKED;
>  typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
>  
> +/*
> + * Generic Error Status Block
> + */
> +struct AcpiGenericErrorStatus {
> +    /* It is a bitmask composed of ACPI_GEBS_xxx macros */
> +    uint32_t block_status;
> +    uint32_t raw_data_offset;
> +    uint32_t raw_data_length;
> +    uint32_t data_length;
> +    uint32_t error_severity;
> +} QEMU_PACKED;
> +typedef struct AcpiGenericErrorStatus AcpiGenericErrorStatus;
> +
> +/*
> + * Masks for Block Status field above
> + */
> +#define ACPI_GEBS_UNCORRECTABLE          (1)
() are usually used with an expression and not with single value,
so drop that to be consistent with style of the header

> +
> +/*
> + * Value for Error Severity field above
> + */
> +enum AcpiGenericErrorSeverity {
> +    ACPI_CPER_SEV_RECOVERABLE,
> +    ACPI_CPER_SEV_FATAL,
> +    ACPI_CPER_SEV_CORRECTED,
> +    ACPI_CPER_SEV_NONE,
> +};
> +
> +/*
> + * Generic Hardware Error Source version 2
> + */
> +#define ACPI_HEST_SOURCE_GENERIC_ERROR_V2    (10)
ditto

> +
>  #define ACPI_SRAT_PROCESSOR_APIC     0
>  #define ACPI_SRAT_MEMORY             1
>  #define ACPI_SRAT_PROCESSOR_x2APIC   2

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28 13:49     ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 13:49 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:14 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Add synchronous external abort injection logic, setup
> exception type and syndrome value. When switch to guest,
> guest will jump to the synchronous external abort vector
> table entry.
> 
> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
> and ESR_ELx.FnV is set to not valid(0x1), which will tell
> guest that FAR is not valid and holds an UNKNOWN value.
> These value will be set to KVM register structures through
> KVM_SET_ONE_REG IOCTL.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
> so user space how to inject it. The test result that injection SEA to guest by Qemu
> is shown in [2].
is it possible to inject SEA when running in TCG mode?

it would be useful from testing/verification point of view
(i.e. we could test logic on non ARM host during 'make check')


> [1]: https://lkml.org/lkml/2017/3/2/110
> [2]:
> Taking exception 4 [Data Abort]
> ...from EL0 to EL1
> ...with ESR 0x24/0x92000410
> ...with FAR 0x0
> ...with ELR 0x40cf04
> ...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
> after kvm_inject_arm_sea
> Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
> Hardware name: linux,dummy-virt (DT)
> task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
> PC is at 0x40cf04
> LR is at 0x40cdec
> pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
> sp : 0000007ff7b24130
> x29: 0000007ff7b24260 x28: 0000000000000000
> x27: 00000000000000ad x26: 000000000049c000
> x25: 000000000048904b x24: 000000000049c000
> x23: 0000000040600000 x22: 0000007ff7b243a0
> x21: 0000000000000002 x20: 0000000000000000
> x19: 0000000000000020 x18: 0000000000000000
> x17: 000000000049c6d0 x16: 0000007fa22c85c0
> x15: 0000000000005798 x14: 0000007fa2205f1c
> x13: 0000007fa241ccb0 x12: 0000000000000137
> x11: 0000000000000000 x10: 0000000000000000
> x9 : 0000000000000000 x8 : 00000000000000de
> x7 : 0000000000000000 x6 : 0000000000002000
> x5 : 0000000040600000 x4 : 0000000000000003
> x3 : 0000000000000001 x2 : 0000000000000000
> x1 : 0000000000000000 x0 : 0000007fa2418000
> ---
>  target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
> 
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index a16abc8..c00450d 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>      return KVM_PUT_RUNTIME_STATE;
>  }
>  
> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
> +{
> +    int i;
> +
> +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
> +        const ARMCPRegInfo *ri;
> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
> +        if (!ri) {
> +            continue;
> +        }
> +
> +        if (ri->type & ARM_CP_NO_RAW) {
> +            continue;
> +        }
> +
> +        if (ri->fieldoffset == fieldoffset) {
> +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
> +            return 0;
> +        }
> +    }
> +    return -EINVAL;
> +}
> +
> +/* Inject synchronous external abort */
> +static void kvm_inject_arm_sea(CPUState *c)
> +{
> +    ARMCPU *cpu = ARM_CPU(c);
> +    CPUARMState *env = &cpu->env;
> +    unsigned long cpsr = pstate_read(env);
> +    uint32_t esr, ret;
> +
> +    /* This exception is synchronous data abort*/
> +    c->exception_index = EXCP_DATA_ABORT;
> +    /* Inject the exception to guest El1 */
> +    env->exception.target_el = 1;
> +    CPUClass *cc = CPU_GET_CLASS(c);
> +
> +    /* Set the DFSC to synchronous external abort and set FnV to not valid,
> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
> +     */
> +    esr = (0x10 | (1 << 10));
> +
> +    /* This exception comes from lower or current exception level. */
> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
> +        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
> +    } else {
> +        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
> +    }
> +
> +    /* For the AArch64, instruction length is 32-bit */
> +    esr |= ARM_EL_IL;
> +    env->exception.syndrome = esr;
> +
> +    cc->do_interrupt(c);
> +
> +    /* set ESR_EL1 */
> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
> +
> +    if (ret) {
> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
> +        abort();
> +    }
> +}
> +
>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>  

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2017-12-28 13:49     ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 13:49 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:14 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Add synchronous external abort injection logic, setup
> exception type and syndrome value. When switch to guest,
> guest will jump to the synchronous external abort vector
> table entry.
> 
> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
> and ESR_ELx.FnV is set to not valid(0x1), which will tell
> guest that FAR is not valid and holds an UNKNOWN value.
> These value will be set to KVM register structures through
> KVM_SET_ONE_REG IOCTL.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
> so user space how to inject it. The test result that injection SEA to guest by Qemu
> is shown in [2].
is it possible to inject SEA when running in TCG mode?

it would be useful from testing/verification point of view
(i.e. we could test logic on non ARM host during 'make check')


> [1]: https://lkml.org/lkml/2017/3/2/110
> [2]:
> Taking exception 4 [Data Abort]
> ...from EL0 to EL1
> ...with ESR 0x24/0x92000410
> ...with FAR 0x0
> ...with ELR 0x40cf04
> ...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
> after kvm_inject_arm_sea
> Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
> Hardware name: linux,dummy-virt (DT)
> task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
> PC is at 0x40cf04
> LR is at 0x40cdec
> pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
> sp : 0000007ff7b24130
> x29: 0000007ff7b24260 x28: 0000000000000000
> x27: 00000000000000ad x26: 000000000049c000
> x25: 000000000048904b x24: 000000000049c000
> x23: 0000000040600000 x22: 0000007ff7b243a0
> x21: 0000000000000002 x20: 0000000000000000
> x19: 0000000000000020 x18: 0000000000000000
> x17: 000000000049c6d0 x16: 0000007fa22c85c0
> x15: 0000000000005798 x14: 0000007fa2205f1c
> x13: 0000007fa241ccb0 x12: 0000000000000137
> x11: 0000000000000000 x10: 0000000000000000
> x9 : 0000000000000000 x8 : 00000000000000de
> x7 : 0000000000000000 x6 : 0000000000002000
> x5 : 0000000040600000 x4 : 0000000000000003
> x3 : 0000000000000001 x2 : 0000000000000000
> x1 : 0000000000000000 x0 : 0000007fa2418000
> ---
>  target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
> 
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index a16abc8..c00450d 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>      return KVM_PUT_RUNTIME_STATE;
>  }
>  
> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
> +{
> +    int i;
> +
> +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
> +        const ARMCPRegInfo *ri;
> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
> +        if (!ri) {
> +            continue;
> +        }
> +
> +        if (ri->type & ARM_CP_NO_RAW) {
> +            continue;
> +        }
> +
> +        if (ri->fieldoffset == fieldoffset) {
> +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
> +            return 0;
> +        }
> +    }
> +    return -EINVAL;
> +}
> +
> +/* Inject synchronous external abort */
> +static void kvm_inject_arm_sea(CPUState *c)
> +{
> +    ARMCPU *cpu = ARM_CPU(c);
> +    CPUARMState *env = &cpu->env;
> +    unsigned long cpsr = pstate_read(env);
> +    uint32_t esr, ret;
> +
> +    /* This exception is synchronous data abort*/
> +    c->exception_index = EXCP_DATA_ABORT;
> +    /* Inject the exception to guest El1 */
> +    env->exception.target_el = 1;
> +    CPUClass *cc = CPU_GET_CLASS(c);
> +
> +    /* Set the DFSC to synchronous external abort and set FnV to not valid,
> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
> +     */
> +    esr = (0x10 | (1 << 10));
> +
> +    /* This exception comes from lower or current exception level. */
> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
> +        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
> +    } else {
> +        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
> +    }
> +
> +    /* For the AArch64, instruction length is 32-bit */
> +    esr |= ARM_EL_IL;
> +    env->exception.syndrome = esr;
> +
> +    cc->do_interrupt(c);
> +
> +    /* set ESR_EL1 */
> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
> +
> +    if (ret) {
> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
> +        abort();
> +    }
> +}
> +
>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>  

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28 14:18     ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 14:18 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:11 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> This implements APEI GHES Table generation and record CPER in
> runtime via fw_cfg blobs.Now we only support two types of GHESv2,
> which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
> supported type if needed. For the CPER section type, currently it
s/type/types/

> is memory section because kernel manly wants userspace to handle
s/manly/mainly/

> the memory errors. 

>In order to simulation, we hard code the error
> type to Multi-bit ECC.
Not sure what this is about, care to elaborate?


> For GHESv2 error source, the OSPM must acknowledges the error via
> Read ACK register. So user space must check the ACK value before
> recording a new CPER to avoid read-write race condition.
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> The basic solution is suggested by Laszlo in [1]
> [1]: https://lkml.org/lkml/2017/3/29/342


patch is too big, it would be better if it were split in several parts.

> ---
>  hw/acpi/aml-build.c         |   2 +
>  hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
>  hw/arm/virt-acpi-build.c    |   8 +
>  include/hw/acpi/aml-build.h |   1 +
>  include/hw/acpi/hest_ghes.h |  82 ++++++++++
>  5 files changed, 483 insertions(+)
>  create mode 100644 hw/acpi/hest_ghes.c
>  create mode 100644 include/hw/acpi/hest_ghes.h
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 36a6cc4..6849e5f 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
>      tables->table_data = g_array_new(false, true /* clear */, 1);
>      tables->tcpalog = g_array_new(false, true /* clear */, 1);
>      tables->vmgenid = g_array_new(false, true /* clear */, 1);
> +    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
>      tables->linker = bios_linker_loader_init();
>  }
>  
> @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>      g_array_free(tables->table_data, true);
>      g_array_free(tables->tcpalog, mfre);
>      g_array_free(tables->vmgenid, mfre);
> +    g_array_free(tables->hardware_errors, mfre);
>  }
>  
>  /* Build rsdt table */
> diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
> new file mode 100644
> index 0000000..86ec99e
> --- /dev/null
> +++ b/hw/acpi/hest_ghes.c
> @@ -0,0 +1,390 @@
> +/* Support for generating APEI tables and record CPER for Guests
> + *
> + * Copyright (C) 2017 HuaWei Corporation.
> + *
> + * Author: Dongjiu Geng <gengdongjiu@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/acpi/acpi.h"
> +#include "hw/acpi/aml-build.h"
> +#include "hw/acpi/hest_ghes.h"
> +#include "hw/nvram/fw_cfg.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/error-report.h"
> +
> +/* Generic Address Structure (GAS)
> + * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
> + * 2.0 compat note:
> + *    @access_width must be 0, see ACPI 2.0:Table 5-1
> + */
> +static void build_append_gas(GArray *table, AmlRegionSpace as,
> +                      uint8_t bit_width, uint8_t bit_offset,
> +                      uint8_t access_width, uint64_t address)
> +{
> +    build_append_int_noprefix(table, as, 1);
> +    build_append_int_noprefix(table, bit_width, 1);
> +    build_append_int_noprefix(table, bit_offset, 1);
> +    build_append_int_noprefix(table, access_width, 1);
> +    build_append_int_noprefix(table, address, 8);
> +}
all build_append_foo() primitives should go into aml-build.c
you can reuse take following patches for build_append_gas() from my github repo
https://github.com/imammedo/qemu/commit/ff35b4ae1ec286f5f11830d504467f5ad243995b
https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c


> +/* Hardware Error Notification
> + * ACPI 4.0: 17.3.2.7 Hardware Error Notification
> + */
> +static void build_append_notify(GArray *table, const uint8_t type,
> +                                uint8_t length)
> +{
> +        build_append_int_noprefix(table, type, 1); /* type */
> +        build_append_int_noprefix(table, length, 1);
> +        build_append_int_noprefix(table, 0, 26);
> +}
split all build_append_foo() into separate patches /a patch per function/,

probably for GHES related primitives it would be better use 'ghes'
domain prefix in function names, like

  s/build_append_notify/build_append_ghes_notify/

the same applies to other build_append_foo() below


> +/* Generic Error Status Block
> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
> + */
> +static void build_append_gesb_header(GArray *table, uint32_t block_status,
> +                      uint32_t raw_data_offset, uint32_t raw_data_length,
> +                      uint32_t data_length, uint32_t error_severity)
> +{
> +    build_append_int_noprefix(table, block_status, 4);
> +    build_append_int_noprefix(table, raw_data_offset, 4);
> +    build_append_int_noprefix(table, raw_data_length, 4);
> +    build_append_int_noprefix(table, data_length, 4);
> +    build_append_int_noprefix(table, error_severity, 4);
> +}
> +
> +/* Generic Error Data Entry
> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
> + */
> +static void build_append_gede_header(GArray *table, const char *section_type,
> +                      const uint32_t error_severity, const uint16_t revision,
> +                      const uint32_t error_data_length)
> +{
> +    int i;
> +
> +    for (i = 0; i < 16; i++) {
> +        build_append_int_noprefix(table, section_type[i], 1);
> +    }
> +
> +    build_append_int_noprefix(table, error_severity, 4);
> +    build_append_int_noprefix(table, revision, 2);
> +    build_append_int_noprefix(table, 0, 2);
> +    build_append_int_noprefix(table, error_data_length, 4);
> +    build_append_int_noprefix(table, 0, 44);
> +}
> +
> +/* Memory section CPER record */
comment missing reference to related spec item

> +static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
> +{
> +    /*
> +     * Memory Error Record
> +     */
> +    build_append_int_noprefix(table,
> +                 (1UL << 14) | /* Type Valid */
> +                 (1UL << 1) /* Physical Address Valid */,
> +                 8);
> +    /* Memory error status information */
> +    build_append_int_noprefix(table, 0, 8);
> +    /* The physical address at which the memory error occurred */
> +    build_append_int_noprefix(table, error_physical_addr, 8);
> +    build_append_int_noprefix(table, 0, 48);
> +    /* Hard code to Multi-bit ECC error */
> +    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
> +    build_append_int_noprefix(table, 0, 7);
> +}
> +
> +static int ghes_record_mem_error(uint64_t error_block_address,
> +                                    uint64_t error_physical_addr)
probably function should be part of 9/9 patch, as the others that's called
only from ghes_record_errors().

i.e. split this patch into acpi tables generation and actual error generation patches.

> +{
> +    GArray *block;
> +    uint64_t current_block_length;
> +    uint32_t data_length;
> +    /* Memory section */
> +    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
> +                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
> +                                0x83, 0xB1};
> +
> +    block = g_array_new(false, true /* clear */, 1);
> +
> +    /* Read the current length in bytes of the generic error data */
> +    cpu_physical_memory_read(error_block_address +
> +        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
> +
> +    /* The current whole length in bytes of the generic error status block */
> +    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
missing le32_to_cpu() here

also check other sites where you call cpu_physical_memory_foo()

it would be good to have a 'make check' test case included in this series,
then when you can spot these errors during test on BE host, before posting patches.

> +
> +    /* Add a new generic error data entry*/
> +    data_length += GHES_DATA_LENGTH;
> +    data_length += GHES_CPER_LENGTH;
> +
> +    /* Check whether it will run out of the preallocated memory if adding a new
> +     * generic error data entry
> +     */
> +    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
> +        error_report("Record CPER out of boundary!!!");
> +        return GHES_CPER_FAIL;
you return values here and from ghes_record_errors() but not actually
handle them, so it's rather pointless thing to do,
more over it's called on nofail path so one should either abort on error o ignore it

> +    }
> +    /* Build the new generic error status block header */
> +    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
> +        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
> +
> +    /* Write back above generic error status block header to guest memory */
> +    cpu_physical_memory_write(error_block_address, block->data,
> +                              block->len);
> +
> +    /* Build the generic error data entries */
> +
> +    data_length = block->len;
> +    /* Build the new generic error data entry header */
> +    build_append_gede_header(block, mem_section_id_le,
> +                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
> +                    cpu_to_le32(80)/* the total size of Memory Error Record */);
> +
> +    /* Build the memory section CPER */
> +    build_append_mem_cper(block, error_physical_addr);
> +
> +    /* Write back above whole new generic error data entry to guest memory */
> +    cpu_physical_memory_write(error_block_address + current_block_length,
> +                    block->data + data_length, block->len - data_length);
> +
> +    g_array_free(block, true);
> +
> +    return GHES_CPER_OK;
> +}
[...]

I'll try to make another round of review on this once patch is split

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2017-12-28 14:18     ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 14:18 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:11 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> This implements APEI GHES Table generation and record CPER in
> runtime via fw_cfg blobs.Now we only support two types of GHESv2,
> which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
> supported type if needed. For the CPER section type, currently it
s/type/types/

> is memory section because kernel manly wants userspace to handle
s/manly/mainly/

> the memory errors. 

>In order to simulation, we hard code the error
> type to Multi-bit ECC.
Not sure what this is about, care to elaborate?


> For GHESv2 error source, the OSPM must acknowledges the error via
> Read ACK register. So user space must check the ACK value before
> recording a new CPER to avoid read-write race condition.
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> The basic solution is suggested by Laszlo in [1]
> [1]: https://lkml.org/lkml/2017/3/29/342


patch is too big, it would be better if it were split in several parts.

> ---
>  hw/acpi/aml-build.c         |   2 +
>  hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
>  hw/arm/virt-acpi-build.c    |   8 +
>  include/hw/acpi/aml-build.h |   1 +
>  include/hw/acpi/hest_ghes.h |  82 ++++++++++
>  5 files changed, 483 insertions(+)
>  create mode 100644 hw/acpi/hest_ghes.c
>  create mode 100644 include/hw/acpi/hest_ghes.h
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 36a6cc4..6849e5f 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
>      tables->table_data = g_array_new(false, true /* clear */, 1);
>      tables->tcpalog = g_array_new(false, true /* clear */, 1);
>      tables->vmgenid = g_array_new(false, true /* clear */, 1);
> +    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
>      tables->linker = bios_linker_loader_init();
>  }
>  
> @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>      g_array_free(tables->table_data, true);
>      g_array_free(tables->tcpalog, mfre);
>      g_array_free(tables->vmgenid, mfre);
> +    g_array_free(tables->hardware_errors, mfre);
>  }
>  
>  /* Build rsdt table */
> diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
> new file mode 100644
> index 0000000..86ec99e
> --- /dev/null
> +++ b/hw/acpi/hest_ghes.c
> @@ -0,0 +1,390 @@
> +/* Support for generating APEI tables and record CPER for Guests
> + *
> + * Copyright (C) 2017 HuaWei Corporation.
> + *
> + * Author: Dongjiu Geng <gengdongjiu@huawei.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/acpi/acpi.h"
> +#include "hw/acpi/aml-build.h"
> +#include "hw/acpi/hest_ghes.h"
> +#include "hw/nvram/fw_cfg.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/error-report.h"
> +
> +/* Generic Address Structure (GAS)
> + * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
> + * 2.0 compat note:
> + *    @access_width must be 0, see ACPI 2.0:Table 5-1
> + */
> +static void build_append_gas(GArray *table, AmlRegionSpace as,
> +                      uint8_t bit_width, uint8_t bit_offset,
> +                      uint8_t access_width, uint64_t address)
> +{
> +    build_append_int_noprefix(table, as, 1);
> +    build_append_int_noprefix(table, bit_width, 1);
> +    build_append_int_noprefix(table, bit_offset, 1);
> +    build_append_int_noprefix(table, access_width, 1);
> +    build_append_int_noprefix(table, address, 8);
> +}
all build_append_foo() primitives should go into aml-build.c
you can reuse take following patches for build_append_gas() from my github repo
https://github.com/imammedo/qemu/commit/ff35b4ae1ec286f5f11830d504467f5ad243995b
https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c


> +/* Hardware Error Notification
> + * ACPI 4.0: 17.3.2.7 Hardware Error Notification
> + */
> +static void build_append_notify(GArray *table, const uint8_t type,
> +                                uint8_t length)
> +{
> +        build_append_int_noprefix(table, type, 1); /* type */
> +        build_append_int_noprefix(table, length, 1);
> +        build_append_int_noprefix(table, 0, 26);
> +}
split all build_append_foo() into separate patches /a patch per function/,

probably for GHES related primitives it would be better use 'ghes'
domain prefix in function names, like

  s/build_append_notify/build_append_ghes_notify/

the same applies to other build_append_foo() below


> +/* Generic Error Status Block
> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
> + */
> +static void build_append_gesb_header(GArray *table, uint32_t block_status,
> +                      uint32_t raw_data_offset, uint32_t raw_data_length,
> +                      uint32_t data_length, uint32_t error_severity)
> +{
> +    build_append_int_noprefix(table, block_status, 4);
> +    build_append_int_noprefix(table, raw_data_offset, 4);
> +    build_append_int_noprefix(table, raw_data_length, 4);
> +    build_append_int_noprefix(table, data_length, 4);
> +    build_append_int_noprefix(table, error_severity, 4);
> +}
> +
> +/* Generic Error Data Entry
> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
> + */
> +static void build_append_gede_header(GArray *table, const char *section_type,
> +                      const uint32_t error_severity, const uint16_t revision,
> +                      const uint32_t error_data_length)
> +{
> +    int i;
> +
> +    for (i = 0; i < 16; i++) {
> +        build_append_int_noprefix(table, section_type[i], 1);
> +    }
> +
> +    build_append_int_noprefix(table, error_severity, 4);
> +    build_append_int_noprefix(table, revision, 2);
> +    build_append_int_noprefix(table, 0, 2);
> +    build_append_int_noprefix(table, error_data_length, 4);
> +    build_append_int_noprefix(table, 0, 44);
> +}
> +
> +/* Memory section CPER record */
comment missing reference to related spec item

> +static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
> +{
> +    /*
> +     * Memory Error Record
> +     */
> +    build_append_int_noprefix(table,
> +                 (1UL << 14) | /* Type Valid */
> +                 (1UL << 1) /* Physical Address Valid */,
> +                 8);
> +    /* Memory error status information */
> +    build_append_int_noprefix(table, 0, 8);
> +    /* The physical address at which the memory error occurred */
> +    build_append_int_noprefix(table, error_physical_addr, 8);
> +    build_append_int_noprefix(table, 0, 48);
> +    /* Hard code to Multi-bit ECC error */
> +    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
> +    build_append_int_noprefix(table, 0, 7);
> +}
> +
> +static int ghes_record_mem_error(uint64_t error_block_address,
> +                                    uint64_t error_physical_addr)
probably function should be part of 9/9 patch, as the others that's called
only from ghes_record_errors().

i.e. split this patch into acpi tables generation and actual error generation patches.

> +{
> +    GArray *block;
> +    uint64_t current_block_length;
> +    uint32_t data_length;
> +    /* Memory section */
> +    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
> +                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
> +                                0x83, 0xB1};
> +
> +    block = g_array_new(false, true /* clear */, 1);
> +
> +    /* Read the current length in bytes of the generic error data */
> +    cpu_physical_memory_read(error_block_address +
> +        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
> +
> +    /* The current whole length in bytes of the generic error status block */
> +    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
missing le32_to_cpu() here

also check other sites where you call cpu_physical_memory_foo()

it would be good to have a 'make check' test case included in this series,
then when you can spot these errors during test on BE host, before posting patches.

> +
> +    /* Add a new generic error data entry*/
> +    data_length += GHES_DATA_LENGTH;
> +    data_length += GHES_CPER_LENGTH;
> +
> +    /* Check whether it will run out of the preallocated memory if adding a new
> +     * generic error data entry
> +     */
> +    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
> +        error_report("Record CPER out of boundary!!!");
> +        return GHES_CPER_FAIL;
you return values here and from ghes_record_errors() but not actually
handle them, so it's rather pointless thing to do,
more over it's called on nofail path so one should either abort on error o ignore it

> +    }
> +    /* Build the new generic error status block header */
> +    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
> +        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
> +
> +    /* Write back above generic error status block header to guest memory */
> +    cpu_physical_memory_write(error_block_address, block->data,
> +                              block->len);
> +
> +    /* Build the generic error data entries */
> +
> +    data_length = block->len;
> +    /* Build the new generic error data entry header */
> +    build_append_gede_header(block, mem_section_id_le,
> +                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
> +                    cpu_to_le32(80)/* the total size of Memory Error Record */);
> +
> +    /* Build the memory section CPER */
> +    build_append_mem_cper(block, error_physical_addr);
> +
> +    /* Write back above whole new generic error data entry to guest memory */
> +    cpu_physical_memory_write(error_block_address + current_block_length,
> +                    block->data + data_length, block->len - data_length);
> +
> +    g_array_free(block, true);
> +
> +    return GHES_CPER_OK;
> +}
[...]

I'll try to make another round of review on this once patch is split

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28 14:53     ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 14:53 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:16 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> In ARM platform we implements a notification of error events
> via a GPIO pin. For this GPIO-signaled events, we choose GPIO
> pin 4 for hardware error device (PNP0C33), So _E04 should be
> added to ACPI DSDT table. When GPIO-pin 4 signaled a events,
> the guest ACPI driver will receive this notification and
> handing the error.
> 
> In order to better trigger the GPIO IRQ, we defined a notifier
> hardware_error_notifiers. If Qemu wants to deliver a GPIO-Signal
> notification, will call it.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> 1. Address discussion result about guest APEI notification type for SIGBUS_MCEERR_AO SIGBUS in [1],
>    the discussion conclusion is using GPIO-Signal
> 
> [1]:
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03397.html
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03467.html
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03601.html
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03775.html
> 
> 2. The ASL dump for the GPIO and hardware error device
> 
> ................
> Device (GPO0)
> {
>     Name (_AEI, ResourceTemplate ()  // _AEI: ACPI Event Interrupts
>     {
>         .............
>         GpioInt (Edge, ActiveHigh, Exclusive, PullUp, 0x0000,
>             "GPO0", 0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x0004
>             }
>     })
>     Method (_E04, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
>     {
>         Notify (ERRD, 0x80) // Status Change
>     }
> }
> Device (ERRD)
> {
>     Name (_HID, EisaId ("PNP0C33") /* Error Device */)  // _HID: Hardware ID
>     Name (_UID, Zero)  // _UID: Unique ID
>     Method (_STA, 0, NotSerialized)  // _STA: Status
>     {
>         Return (0x0F)
>     }
> }
> 
> 3. Below is the guest log when Qemu notifies guest using GPIO-signal after record a CPER
> [  504.164899] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
> [  504.166970] {1}[Hardware Error]: event severity: recoverable
> [  504.251650] {1}[Hardware Error]:  Error 0, type: recoverable
> [  504.252974] {1}[Hardware Error]:   section_type: memory error
> [  504.254380] {1}[Hardware Error]:   physical_address: 0x00000000000003ec
> [  504.255879] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
> ---
>  hw/arm/virt-acpi-build.c | 31 ++++++++++++++++++++++++++++++-
>  hw/arm/virt.c            | 18 ++++++++++++++++++
>  include/sysemu/sysemu.h  |  3 +++
>  vl.c                     | 12 ++++++++++++
>  4 files changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index b7d45cd..06c14b3 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -49,6 +49,7 @@
>  
>  #define ARM_SPI_BASE 32
>  #define ACPI_POWER_BUTTON_DEVICE "PWRB"
> +#define ACPI_HARDWARE_ERROR_DEVICE "ERRD"
>  
>  static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
>  {
> @@ -340,7 +341,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>  
>      Aml *aei = aml_resource_template();
>      /* Pin 3 for power button */
> -    const uint32_t pin_list[1] = {3};
> +    uint32_t pin_list[1] = {3};
> +    aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
> +                                 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
> +                                 "GPO0", NULL, 0));
> +
> +    /* Pin 4 for hardware error device */
> +    pin_list[0] = 4;
>      aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
>                                   AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
>                                   "GPO0", NULL, 0));
> @@ -351,6 +358,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>      aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
>                                    aml_int(0x80)));
>      aml_append(dev, method);
> +
> +    /* _E04 is handle for hardware error */
> +    method = aml_method("_E04", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_notify(aml_name(ACPI_HARDWARE_ERROR_DEVICE),
> +                                  aml_int(0x80)));
aml_int(0x80) /* ACPI ... : Notification For Generic Error Sources */

> +    aml_append(dev, method);
> +
>      aml_append(scope, dev);
>  }
>  
> @@ -363,6 +377,20 @@ static void acpi_dsdt_add_power_button(Aml *scope)
>      aml_append(scope, dev);
>  }
>  
> +static void acpi_dsdt_add_error_device(Aml *scope)
> +{
> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
> +    Aml *method;
> +
> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> +
> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_return(aml_int(0x0f)));
no need for dummy _STA method, device is assumed to be present if there is no _STA 

> +    aml_append(dev, method);
> +    aml_append(scope, dev);
> +}
> +
>  /* RSDP */
>  static GArray *
>  build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
> @@ -716,6 +744,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>      acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
>                         (irqmap[VIRT_GPIO] + ARM_SPI_BASE));
>      acpi_dsdt_add_power_button(scope);
> +    acpi_dsdt_add_error_device(scope);
>  
>      aml_append(dsdt, scope);
>  
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 6b7a0fe..68495c2 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -701,16 +701,27 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
>  }
>  
>  static DeviceState *gpio_key_dev;
> +static DeviceState *gpio_err_dev;
>  static void virt_powerdown_req(Notifier *n, void *opaque)
>  {
>      /* use gpio Pin 3 for power button event */
>      qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
>  }
>  
> +static void virt_error_notify_req(Notifier *n, void *opaque)
> +{
> +    /* use gpio Pin 4 for hardware error event */
> +    qemu_set_irq(qdev_get_gpio_in(gpio_err_dev, 0), 1);
> +}
> +
>  static Notifier virt_system_powerdown_notifier = {
>      .notify = virt_powerdown_req
>  };
>  
> +static Notifier virt_hardware_error_notifier = {
> +    .notify = virt_error_notify_req
> +};
> +
>  static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>  {
>      char *nodename;
> @@ -739,6 +750,10 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>  
>      gpio_key_dev = sysbus_create_simple("gpio-key", -1,
>                                          qdev_get_gpio_in(pl061_dev, 3));
> +
> +    gpio_err_dev = sysbus_create_simple("gpio-key", -1,
> +                                        qdev_get_gpio_in(pl061_dev, 4));
> +
>      qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
>      qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
>      qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
> @@ -755,6 +770,9 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>      /* connect powerdown request */
>      qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
>  
> +    /* connect hardware error notify request */
> +    qemu_register_hardware_error_notifier(&virt_hardware_error_notifier);
> +
>      g_free(nodename);
>  }
>  
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index b213696..86931cf 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -75,6 +75,7 @@ void qemu_register_wakeup_notifier(Notifier *notifier);
>  void qemu_system_shutdown_request(ShutdownCause reason);
>  void qemu_system_powerdown_request(void);
>  void qemu_register_powerdown_notifier(Notifier *notifier);
> +void qemu_register_hardware_error_notifier(Notifier *notifier);
>  void qemu_system_debug_request(void);
>  void qemu_system_vmstop_request(RunState reason);
>  void qemu_system_vmstop_request_prepare(void);
> @@ -93,6 +94,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
>  
>  void qemu_announce_self(void);
>  
> +void qemu_hardware_error_notify(void);
> +
>  extern int autostart;
>  
>  typedef enum {
> diff --git a/vl.c b/vl.c
> index d632693..3552f7d 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1614,6 +1614,8 @@ static int suspend_requested;
>  static WakeupReason wakeup_reason;
>  static NotifierList powerdown_notifiers =
>      NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
> +static NotifierList hardware_error_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(hardware_error_notifiers);
>  static NotifierList suspend_notifiers =
>      NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
>  static NotifierList wakeup_notifiers =
> @@ -1850,12 +1852,22 @@ void qemu_register_powerdown_notifier(Notifier *notifier)
>      notifier_list_add(&powerdown_notifiers, notifier);
>  }
>  
> +void qemu_register_hardware_error_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&hardware_error_notifiers, notifier);
> +}
> +
>  void qemu_system_debug_request(void)
>  {
>      debug_requested = 1;
>      qemu_notify_event();
>  }
>  
> +void qemu_hardware_error_notify(void)
> +{
> +    notifier_list_notify(&hardware_error_notifiers, NULL);
> +}

I'd prefer if you'd replace all this Notifier code with a machine callback
and call it when needed.

>  static bool main_loop_should_exit(void)
>  {
>      RunState r;

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
@ 2017-12-28 14:53     ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 14:53 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:16 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> In ARM platform we implements a notification of error events
> via a GPIO pin. For this GPIO-signaled events, we choose GPIO
> pin 4 for hardware error device (PNP0C33), So _E04 should be
> added to ACPI DSDT table. When GPIO-pin 4 signaled a events,
> the guest ACPI driver will receive this notification and
> handing the error.
> 
> In order to better trigger the GPIO IRQ, we defined a notifier
> hardware_error_notifiers. If Qemu wants to deliver a GPIO-Signal
> notification, will call it.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> 1. Address discussion result about guest APEI notification type for SIGBUS_MCEERR_AO SIGBUS in [1],
>    the discussion conclusion is using GPIO-Signal
> 
> [1]:
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03397.html
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03467.html
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03601.html
> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03775.html
> 
> 2. The ASL dump for the GPIO and hardware error device
> 
> ................
> Device (GPO0)
> {
>     Name (_AEI, ResourceTemplate ()  // _AEI: ACPI Event Interrupts
>     {
>         .............
>         GpioInt (Edge, ActiveHigh, Exclusive, PullUp, 0x0000,
>             "GPO0", 0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x0004
>             }
>     })
>     Method (_E04, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
>     {
>         Notify (ERRD, 0x80) // Status Change
>     }
> }
> Device (ERRD)
> {
>     Name (_HID, EisaId ("PNP0C33") /* Error Device */)  // _HID: Hardware ID
>     Name (_UID, Zero)  // _UID: Unique ID
>     Method (_STA, 0, NotSerialized)  // _STA: Status
>     {
>         Return (0x0F)
>     }
> }
> 
> 3. Below is the guest log when Qemu notifies guest using GPIO-signal after record a CPER
> [  504.164899] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
> [  504.166970] {1}[Hardware Error]: event severity: recoverable
> [  504.251650] {1}[Hardware Error]:  Error 0, type: recoverable
> [  504.252974] {1}[Hardware Error]:   section_type: memory error
> [  504.254380] {1}[Hardware Error]:   physical_address: 0x00000000000003ec
> [  504.255879] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
> ---
>  hw/arm/virt-acpi-build.c | 31 ++++++++++++++++++++++++++++++-
>  hw/arm/virt.c            | 18 ++++++++++++++++++
>  include/sysemu/sysemu.h  |  3 +++
>  vl.c                     | 12 ++++++++++++
>  4 files changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index b7d45cd..06c14b3 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -49,6 +49,7 @@
>  
>  #define ARM_SPI_BASE 32
>  #define ACPI_POWER_BUTTON_DEVICE "PWRB"
> +#define ACPI_HARDWARE_ERROR_DEVICE "ERRD"
>  
>  static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
>  {
> @@ -340,7 +341,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>  
>      Aml *aei = aml_resource_template();
>      /* Pin 3 for power button */
> -    const uint32_t pin_list[1] = {3};
> +    uint32_t pin_list[1] = {3};
> +    aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
> +                                 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
> +                                 "GPO0", NULL, 0));
> +
> +    /* Pin 4 for hardware error device */
> +    pin_list[0] = 4;
>      aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
>                                   AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
>                                   "GPO0", NULL, 0));
> @@ -351,6 +358,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>      aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
>                                    aml_int(0x80)));
>      aml_append(dev, method);
> +
> +    /* _E04 is handle for hardware error */
> +    method = aml_method("_E04", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_notify(aml_name(ACPI_HARDWARE_ERROR_DEVICE),
> +                                  aml_int(0x80)));
aml_int(0x80) /* ACPI ... : Notification For Generic Error Sources */

> +    aml_append(dev, method);
> +
>      aml_append(scope, dev);
>  }
>  
> @@ -363,6 +377,20 @@ static void acpi_dsdt_add_power_button(Aml *scope)
>      aml_append(scope, dev);
>  }
>  
> +static void acpi_dsdt_add_error_device(Aml *scope)
> +{
> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
> +    Aml *method;
> +
> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> +
> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_return(aml_int(0x0f)));
no need for dummy _STA method, device is assumed to be present if there is no _STA 

> +    aml_append(dev, method);
> +    aml_append(scope, dev);
> +}
> +
>  /* RSDP */
>  static GArray *
>  build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
> @@ -716,6 +744,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>      acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
>                         (irqmap[VIRT_GPIO] + ARM_SPI_BASE));
>      acpi_dsdt_add_power_button(scope);
> +    acpi_dsdt_add_error_device(scope);
>  
>      aml_append(dsdt, scope);
>  
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 6b7a0fe..68495c2 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -701,16 +701,27 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
>  }
>  
>  static DeviceState *gpio_key_dev;
> +static DeviceState *gpio_err_dev;
>  static void virt_powerdown_req(Notifier *n, void *opaque)
>  {
>      /* use gpio Pin 3 for power button event */
>      qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
>  }
>  
> +static void virt_error_notify_req(Notifier *n, void *opaque)
> +{
> +    /* use gpio Pin 4 for hardware error event */
> +    qemu_set_irq(qdev_get_gpio_in(gpio_err_dev, 0), 1);
> +}
> +
>  static Notifier virt_system_powerdown_notifier = {
>      .notify = virt_powerdown_req
>  };
>  
> +static Notifier virt_hardware_error_notifier = {
> +    .notify = virt_error_notify_req
> +};
> +
>  static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>  {
>      char *nodename;
> @@ -739,6 +750,10 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>  
>      gpio_key_dev = sysbus_create_simple("gpio-key", -1,
>                                          qdev_get_gpio_in(pl061_dev, 3));
> +
> +    gpio_err_dev = sysbus_create_simple("gpio-key", -1,
> +                                        qdev_get_gpio_in(pl061_dev, 4));
> +
>      qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
>      qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
>      qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
> @@ -755,6 +770,9 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>      /* connect powerdown request */
>      qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
>  
> +    /* connect hardware error notify request */
> +    qemu_register_hardware_error_notifier(&virt_hardware_error_notifier);
> +
>      g_free(nodename);
>  }
>  
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index b213696..86931cf 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -75,6 +75,7 @@ void qemu_register_wakeup_notifier(Notifier *notifier);
>  void qemu_system_shutdown_request(ShutdownCause reason);
>  void qemu_system_powerdown_request(void);
>  void qemu_register_powerdown_notifier(Notifier *notifier);
> +void qemu_register_hardware_error_notifier(Notifier *notifier);
>  void qemu_system_debug_request(void);
>  void qemu_system_vmstop_request(RunState reason);
>  void qemu_system_vmstop_request_prepare(void);
> @@ -93,6 +94,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
>  
>  void qemu_announce_self(void);
>  
> +void qemu_hardware_error_notify(void);
> +
>  extern int autostart;
>  
>  typedef enum {
> diff --git a/vl.c b/vl.c
> index d632693..3552f7d 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1614,6 +1614,8 @@ static int suspend_requested;
>  static WakeupReason wakeup_reason;
>  static NotifierList powerdown_notifiers =
>      NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
> +static NotifierList hardware_error_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(hardware_error_notifiers);
>  static NotifierList suspend_notifiers =
>      NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
>  static NotifierList wakeup_notifiers =
> @@ -1850,12 +1852,22 @@ void qemu_register_powerdown_notifier(Notifier *notifier)
>      notifier_list_add(&powerdown_notifiers, notifier);
>  }
>  
> +void qemu_register_hardware_error_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&hardware_error_notifiers, notifier);
> +}
> +
>  void qemu_system_debug_request(void)
>  {
>      debug_requested = 1;
>      qemu_notify_event();
>  }
>  
> +void qemu_hardware_error_notify(void)
> +{
> +    notifier_list_notify(&hardware_error_notifiers, NULL);
> +}

I'd prefer if you'd replace all this Notifier code with a machine callback
and call it when needed.

>  static bool main_loop_should_exit(void)
>  {
>      RunState r;

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28 14:58     ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 14:58 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:17 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Support this feature since version 2.10, disable it by
> default in the old version.
patch should go before acpi tables are actually added,
otherwise it might break bisectability.

> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Address Shannon's comments to add platform version in [1].
> 
> [1]: https://lkml.org/lkml/2017/8/25/821
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
>  hw/arm/virt-acpi-build.c | 14 +++++++++-----
>  hw/arm/virt.c            |  4 ++++
>  include/hw/arm/virt.h    |  1 +
>  3 files changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 06c14b3..b6974ef 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>      acpi_add_table(table_offsets, tables_blob);
>      build_spcr(tables_blob, tables->linker, vms);
>  
> -    acpi_add_table(table_offsets, tables_blob);
> -    build_hardware_error_table(tables->hardware_errors, tables->linker);
> -    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
> -
> +    if (!vmc->no_ras) {

it's better to avoid no_foo, use something like

vmc->has_ras

instead

> +        acpi_add_table(table_offsets, tables_blob);
> +        build_hardware_error_table(tables->hardware_errors, tables->linker);
> +        build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
> +    }
>  
>      if (nb_numa_nodes > 0) {
>          acpi_add_table(table_offsets, tables_blob);
> @@ -891,6 +892,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
>  
>  void virt_acpi_setup(VirtMachineState *vms)
>  {
> +    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>      AcpiBuildTables tables;
>      AcpiBuildState *build_state;
>  
> @@ -922,7 +924,9 @@ void virt_acpi_setup(VirtMachineState *vms)
>      fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
>                      acpi_data_len(tables.tcpalog));
>  
> -    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
> +    if (!vmc->no_ras) {
> +        ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
> +    }
>  
>      build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
>                                                ACPI_BUILD_RSDP_FILE, 0);
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 68495c2..ab79988 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1732,8 +1732,12 @@ static void virt_2_9_instance_init(Object *obj)
>  
>  static void virt_machine_2_9_options(MachineClass *mc)
>  {
> +    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
> +
>      virt_machine_2_10_options(mc);
>      SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_9);
> +    /* memory recovery feature was introduced with 2.10 */
> +    vmc->no_ras = true;
>  }
>  DEFINE_VIRT_MACHINE(2, 9)
>  
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index 33b0ff3..8fbd664 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -84,6 +84,7 @@ typedef struct {
>      bool disallow_affinity_adjustment;
>      bool no_its;
>      bool no_pmu;
> +    bool no_ras;
>      bool claim_edge_triggered_timers;
>  } VirtMachineClass;
>  

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
@ 2017-12-28 14:58     ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 14:58 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:17 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Support this feature since version 2.10, disable it by
> default in the old version.
patch should go before acpi tables are actually added,
otherwise it might break bisectability.

> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Address Shannon's comments to add platform version in [1].
> 
> [1]: https://lkml.org/lkml/2017/8/25/821
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
>  hw/arm/virt-acpi-build.c | 14 +++++++++-----
>  hw/arm/virt.c            |  4 ++++
>  include/hw/arm/virt.h    |  1 +
>  3 files changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 06c14b3..b6974ef 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>      acpi_add_table(table_offsets, tables_blob);
>      build_spcr(tables_blob, tables->linker, vms);
>  
> -    acpi_add_table(table_offsets, tables_blob);
> -    build_hardware_error_table(tables->hardware_errors, tables->linker);
> -    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
> -
> +    if (!vmc->no_ras) {

it's better to avoid no_foo, use something like

vmc->has_ras

instead

> +        acpi_add_table(table_offsets, tables_blob);
> +        build_hardware_error_table(tables->hardware_errors, tables->linker);
> +        build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
> +    }
>  
>      if (nb_numa_nodes > 0) {
>          acpi_add_table(table_offsets, tables_blob);
> @@ -891,6 +892,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
>  
>  void virt_acpi_setup(VirtMachineState *vms)
>  {
> +    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>      AcpiBuildTables tables;
>      AcpiBuildState *build_state;
>  
> @@ -922,7 +924,9 @@ void virt_acpi_setup(VirtMachineState *vms)
>      fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
>                      acpi_data_len(tables.tcpalog));
>  
> -    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
> +    if (!vmc->no_ras) {
> +        ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
> +    }
>  
>      build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
>                                                ACPI_BUILD_RSDP_FILE, 0);
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 68495c2..ab79988 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1732,8 +1732,12 @@ static void virt_2_9_instance_init(Object *obj)
>  
>  static void virt_machine_2_9_options(MachineClass *mc)
>  {
> +    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
> +
>      virt_machine_2_10_options(mc);
>      SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_9);
> +    /* memory recovery feature was introduced with 2.10 */
> +    vmc->no_ras = true;
>  }
>  DEFINE_VIRT_MACHINE(2, 9)
>  
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index 33b0ff3..8fbd664 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -84,6 +84,7 @@ typedef struct {
>      bool disallow_affinity_adjustment;
>      bool no_its;
>      bool no_pmu;
> +    bool no_ras;
>      bool claim_edge_triggered_timers;
>  } VirtMachineClass;
>  

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2017-12-28 15:07     ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 15:07 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:18 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
> translates the host VA which is delivered by host to guest PA, then fill
> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
> 
> If guest accesses the poisoned memory, it generates Synchronous External
> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
s/unmapped/unmap/

> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
> create a new CPER and add it to guest APEI GHES memory, then notify the
> guest with a GPIO-Signal notification.
too long sentence, it's hard get what goes on here, pls split it in simple
sentences/rephrase so it would be easy to understand behavior.

> 
> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
> 
> Suggested-by: James Morse <james.morse@arm.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
> Shown some discussion in [1].
> 
> [1]:
> https://lkml.org/lkml/2017/2/27/246
> https://lkml.org/lkml/2017/9/14/241
> https://lkml.org/lkml/2017/9/22/499
> ---
>  include/sysemu/kvm.h |  2 +-
>  target/arm/kvm.c     |  2 ++
>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 3a458f5..90c1605 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>  
> -#ifdef TARGET_I386
> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
>  #define KVM_HAVE_MCE_INJECTION 1
>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>  #endif
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 7c17f0d..9d25f51 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -26,6 +26,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/boards.h"
>  #include "qemu/log.h"
> +#include "exec/ram_addr.h"
>  
>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>      KVM_CAP_LAST_INFO
> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>  
>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>  
> +    qemu_register_reset(kvm_unpoison_all, NULL);
>      type_register_static(&host_arm_cpu_type_info);
>  
>      return 0;
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index c00450d..6955d85 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -27,6 +27,9 @@
>  #include "kvm_arm.h"
>  #include "internals.h"
>  #include "hw/arm/arm.h"
> +#include "exec/ram_addr.h"
> +#include "hw/acpi/acpi-defs.h"
> +#include "hw/acpi/hest_ghes.h"
>  
>  static bool have_guest_debug;
>  
> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>      return ret;
>  }
>  
> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
> +{
> +    ram_addr_t ram_addr;
> +    hwaddr paddr;
> +
> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> +    if (addr) {
> +        ram_addr = qemu_ram_addr_from_host(addr);
> +        if (ram_addr != RAM_ADDR_INVALID &&
> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> +            kvm_hwpoison_page_add(ram_addr);
> +            if (code == BUS_MCEERR_AR) {
> +                kvm_cpu_synchronize_state(c);
> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
> +                kvm_inject_arm_sea(c);
> +            } else if (code == BUS_MCEERR_AO) {
> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
> +                qemu_hardware_error_notify();
> +            }
> +            return;
> +        }
> +        fprintf(stderr, "Hardware memory error for memory used by "
> +                "QEMU itself instead of guest system!\n");
not quite sure what above message means,

also fprintf() probably shouldn't be used by new code.

> +    }
> +
> +    if (code == BUS_MCEERR_AR) {
> +        fprintf(stderr, "Hardware memory error!\n");
> +        exit(1);
> +    }
> +}
> +
>  /* C6.6.29 BRK instruction */
>  static const uint32_t brk_insn = 0xd4200000;
>  

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2017-12-28 15:07     ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2017-12-28 15:07 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Thu, 28 Dec 2017 13:54:18 +0800
Dongjiu Geng <gengdongjiu@huawei.com> wrote:

> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
> translates the host VA which is delivered by host to guest PA, then fill
> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
> 
> If guest accesses the poisoned memory, it generates Synchronous External
> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
s/unmapped/unmap/

> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
> create a new CPER and add it to guest APEI GHES memory, then notify the
> guest with a GPIO-Signal notification.
too long sentence, it's hard get what goes on here, pls split it in simple
sentences/rephrase so it would be easy to understand behavior.

> 
> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
> 
> Suggested-by: James Morse <james.morse@arm.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
> Shown some discussion in [1].
> 
> [1]:
> https://lkml.org/lkml/2017/2/27/246
> https://lkml.org/lkml/2017/9/14/241
> https://lkml.org/lkml/2017/9/22/499
> ---
>  include/sysemu/kvm.h |  2 +-
>  target/arm/kvm.c     |  2 ++
>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 3a458f5..90c1605 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>  
> -#ifdef TARGET_I386
> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
>  #define KVM_HAVE_MCE_INJECTION 1
>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>  #endif
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 7c17f0d..9d25f51 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -26,6 +26,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/boards.h"
>  #include "qemu/log.h"
> +#include "exec/ram_addr.h"
>  
>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>      KVM_CAP_LAST_INFO
> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>  
>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>  
> +    qemu_register_reset(kvm_unpoison_all, NULL);
>      type_register_static(&host_arm_cpu_type_info);
>  
>      return 0;
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index c00450d..6955d85 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -27,6 +27,9 @@
>  #include "kvm_arm.h"
>  #include "internals.h"
>  #include "hw/arm/arm.h"
> +#include "exec/ram_addr.h"
> +#include "hw/acpi/acpi-defs.h"
> +#include "hw/acpi/hest_ghes.h"
>  
>  static bool have_guest_debug;
>  
> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>      return ret;
>  }
>  
> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
> +{
> +    ram_addr_t ram_addr;
> +    hwaddr paddr;
> +
> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> +    if (addr) {
> +        ram_addr = qemu_ram_addr_from_host(addr);
> +        if (ram_addr != RAM_ADDR_INVALID &&
> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> +            kvm_hwpoison_page_add(ram_addr);
> +            if (code == BUS_MCEERR_AR) {
> +                kvm_cpu_synchronize_state(c);
> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
> +                kvm_inject_arm_sea(c);
> +            } else if (code == BUS_MCEERR_AO) {
> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
> +                qemu_hardware_error_notify();
> +            }
> +            return;
> +        }
> +        fprintf(stderr, "Hardware memory error for memory used by "
> +                "QEMU itself instead of guest system!\n");
not quite sure what above message means,

also fprintf() probably shouldn't be used by new code.

> +    }
> +
> +    if (code == BUS_MCEERR_AR) {
> +        fprintf(stderr, "Hardware memory error!\n");
> +        exit(1);
> +    }
> +}
> +
>  /* C6.6.29 BRK instruction */
>  static const uint32_t brk_insn = 0xd4200000;
>  

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2017-12-28 13:49     ` [Qemu-devel] " Igor Mammedov
@ 2017-12-29  6:27       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2017-12-29  6:27 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Hi, Igor,

On 2017/12/28 21:49, Igor Mammedov wrote:
>> so user space how to inject it. The test result that injection SEA to guest by Qemu
>> is shown in [2].
> is it possible to inject SEA when running in TCG mode?
 I have tested it in TCG mode, It supports to inject SEA when running in TCG mode. Thanks

 Start vm commands:
 ./qemu-system-aarch64 -m 1024 -cpu cortex-a57 -machine virt,gic-version=2  -bios QEMU_EFI.fd -smp 4 -nographic -kernel Image -append "root=/dev/sda1 \
 console=ttyAMA0" -device virtio-scsi-device,id=scsi -drive file=./linaro.img,id=rootimg,cache=unsafe,if=none -device scsi-hd,drive=rootimg

> 
> it would be useful from testing/verification point of view
> (i.e. we could test logic on non ARM host during 'make check')>
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2017-12-29  6:27       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2017-12-29  6:27 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Hi, Igor,

On 2017/12/28 21:49, Igor Mammedov wrote:
>> so user space how to inject it. The test result that injection SEA to guest by Qemu
>> is shown in [2].
> is it possible to inject SEA when running in TCG mode?
 I have tested it in TCG mode, It supports to inject SEA when running in TCG mode. Thanks

 Start vm commands:
 ./qemu-system-aarch64 -m 1024 -cpu cortex-a57 -machine virt,gic-version=2  -bios QEMU_EFI.fd -smp 4 -nographic -kernel Image -append "root=/dev/sda1 \
 console=ttyAMA0" -device virtio-scsi-device,id=scsi -drive file=./linaro.img,id=rootimg,cache=unsafe,if=none -device scsi-hd,drive=rootimg

> 
> it would be useful from testing/verification point of view
> (i.e. we could test logic on non ARM host during 'make check')>
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2017-12-28 14:18     ` [Qemu-devel] " Igor Mammedov
@ 2017-12-29  6:33       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2017-12-29  6:33 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Igor,
  Thank you very much for your review and your time. I will check your comments in detail later.

On 2017/12/28 22:18, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:11 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> This implements APEI GHES Table generation and record CPER in
>> runtime via fw_cfg blobs.Now we only support two types of GHESv2,
>> which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
>> supported type if needed. For the CPER section type, currently it
> s/type/types/
> 
>> is memory section because kernel manly wants userspace to handle
> s/manly/mainly/
> 
>> the memory errors. 
> 
>> In order to simulation, we hard code the error
>> type to Multi-bit ECC.
> Not sure what this is about, care to elaborate?
> 
> 
>> For GHESv2 error source, the OSPM must acknowledges the error via
>> Read ACK register. So user space must check the ACK value before
>> recording a new CPER to avoid read-write race condition.
>>
>> Suggested-by: Laszlo Ersek <lersek@redhat.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> The basic solution is suggested by Laszlo in [1]
>> [1]: https://lkml.org/lkml/2017/3/29/342
> 
> 
> patch is too big, it would be better if it were split in several parts.
> 
>> ---
>>  hw/acpi/aml-build.c         |   2 +
>>  hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
>>  hw/arm/virt-acpi-build.c    |   8 +
>>  include/hw/acpi/aml-build.h |   1 +
>>  include/hw/acpi/hest_ghes.h |  82 ++++++++++
>>  5 files changed, 483 insertions(+)
>>  create mode 100644 hw/acpi/hest_ghes.c
>>  create mode 100644 include/hw/acpi/hest_ghes.h
>>
>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>> index 36a6cc4..6849e5f 100644
>> --- a/hw/acpi/aml-build.c
>> +++ b/hw/acpi/aml-build.c
>> @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
>>      tables->table_data = g_array_new(false, true /* clear */, 1);
>>      tables->tcpalog = g_array_new(false, true /* clear */, 1);
>>      tables->vmgenid = g_array_new(false, true /* clear */, 1);
>> +    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
>>      tables->linker = bios_linker_loader_init();
>>  }
>>  
>> @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>>      g_array_free(tables->table_data, true);
>>      g_array_free(tables->tcpalog, mfre);
>>      g_array_free(tables->vmgenid, mfre);
>> +    g_array_free(tables->hardware_errors, mfre);
>>  }
>>  
>>  /* Build rsdt table */
>> diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
>> new file mode 100644
>> index 0000000..86ec99e
>> --- /dev/null
>> +++ b/hw/acpi/hest_ghes.c
>> @@ -0,0 +1,390 @@
>> +/* Support for generating APEI tables and record CPER for Guests
>> + *
>> + * Copyright (C) 2017 HuaWei Corporation.
>> + *
>> + * Author: Dongjiu Geng <gengdongjiu@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/acpi/acpi.h"
>> +#include "hw/acpi/aml-build.h"
>> +#include "hw/acpi/hest_ghes.h"
>> +#include "hw/nvram/fw_cfg.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/error-report.h"
>> +
>> +/* Generic Address Structure (GAS)
>> + * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
>> + * 2.0 compat note:
>> + *    @access_width must be 0, see ACPI 2.0:Table 5-1
>> + */
>> +static void build_append_gas(GArray *table, AmlRegionSpace as,
>> +                      uint8_t bit_width, uint8_t bit_offset,
>> +                      uint8_t access_width, uint64_t address)
>> +{
>> +    build_append_int_noprefix(table, as, 1);
>> +    build_append_int_noprefix(table, bit_width, 1);
>> +    build_append_int_noprefix(table, bit_offset, 1);
>> +    build_append_int_noprefix(table, access_width, 1);
>> +    build_append_int_noprefix(table, address, 8);
>> +}
> all build_append_foo() primitives should go into aml-build.c
> you can reuse take following patches for build_append_gas() from my github repo
> https://github.com/imammedo/qemu/commit/ff35b4ae1ec286f5f11830d504467f5ad243995b
> https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c
> 
> 
>> +/* Hardware Error Notification
>> + * ACPI 4.0: 17.3.2.7 Hardware Error Notification
>> + */
>> +static void build_append_notify(GArray *table, const uint8_t type,
>> +                                uint8_t length)
>> +{
>> +        build_append_int_noprefix(table, type, 1); /* type */
>> +        build_append_int_noprefix(table, length, 1);
>> +        build_append_int_noprefix(table, 0, 26);
>> +}
> split all build_append_foo() into separate patches /a patch per function/,
> 
> probably for GHES related primitives it would be better use 'ghes'
> domain prefix in function names, like
> 
>   s/build_append_notify/build_append_ghes_notify/
> 
> the same applies to other build_append_foo() below
> 
> 
>> +/* Generic Error Status Block
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gesb_header(GArray *table, uint32_t block_status,
>> +                      uint32_t raw_data_offset, uint32_t raw_data_length,
>> +                      uint32_t data_length, uint32_t error_severity)
>> +{
>> +    build_append_int_noprefix(table, block_status, 4);
>> +    build_append_int_noprefix(table, raw_data_offset, 4);
>> +    build_append_int_noprefix(table, raw_data_length, 4);
>> +    build_append_int_noprefix(table, data_length, 4);
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +}
>> +
>> +/* Generic Error Data Entry
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gede_header(GArray *table, const char *section_type,
>> +                      const uint32_t error_severity, const uint16_t revision,
>> +                      const uint32_t error_data_length)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < 16; i++) {
>> +        build_append_int_noprefix(table, section_type[i], 1);
>> +    }
>> +
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +    build_append_int_noprefix(table, revision, 2);
>> +    build_append_int_noprefix(table, 0, 2);
>> +    build_append_int_noprefix(table, error_data_length, 4);
>> +    build_append_int_noprefix(table, 0, 44);
>> +}
>> +
>> +/* Memory section CPER record */
> comment missing reference to related spec item
> 
>> +static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
>> +{
>> +    /*
>> +     * Memory Error Record
>> +     */
>> +    build_append_int_noprefix(table,
>> +                 (1UL << 14) | /* Type Valid */
>> +                 (1UL << 1) /* Physical Address Valid */,
>> +                 8);
>> +    /* Memory error status information */
>> +    build_append_int_noprefix(table, 0, 8);
>> +    /* The physical address at which the memory error occurred */
>> +    build_append_int_noprefix(table, error_physical_addr, 8);
>> +    build_append_int_noprefix(table, 0, 48);
>> +    /* Hard code to Multi-bit ECC error */
>> +    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
>> +    build_append_int_noprefix(table, 0, 7);
>> +}
>> +
>> +static int ghes_record_mem_error(uint64_t error_block_address,
>> +                                    uint64_t error_physical_addr)
> probably function should be part of 9/9 patch, as the others that's called
> only from ghes_record_errors().
> 
> i.e. split this patch into acpi tables generation and actual error generation patches.
> 
>> +{
>> +    GArray *block;
>> +    uint64_t current_block_length;
>> +    uint32_t data_length;
>> +    /* Memory section */
>> +    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
>> +                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
>> +                                0x83, 0xB1};
>> +
>> +    block = g_array_new(false, true /* clear */, 1);
>> +
>> +    /* Read the current length in bytes of the generic error data */
>> +    cpu_physical_memory_read(error_block_address +
>> +        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
>> +
>> +    /* The current whole length in bytes of the generic error status block */
>> +    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
> missing le32_to_cpu() here
> 
> also check other sites where you call cpu_physical_memory_foo()
> 
> it would be good to have a 'make check' test case included in this series,
> then when you can spot these errors during test on BE host, before posting patches.
> 
>> +
>> +    /* Add a new generic error data entry*/
>> +    data_length += GHES_DATA_LENGTH;
>> +    data_length += GHES_CPER_LENGTH;
>> +
>> +    /* Check whether it will run out of the preallocated memory if adding a new
>> +     * generic error data entry
>> +     */
>> +    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
>> +        error_report("Record CPER out of boundary!!!");
>> +        return GHES_CPER_FAIL;
> you return values here and from ghes_record_errors() but not actually
> handle them, so it's rather pointless thing to do,
> more over it's called on nofail path so one should either abort on error o ignore it
> 
>> +    }
>> +    /* Build the new generic error status block header */
>> +    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
>> +        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
>> +
>> +    /* Write back above generic error status block header to guest memory */
>> +    cpu_physical_memory_write(error_block_address, block->data,
>> +                              block->len);
>> +
>> +    /* Build the generic error data entries */
>> +
>> +    data_length = block->len;
>> +    /* Build the new generic error data entry header */
>> +    build_append_gede_header(block, mem_section_id_le,
>> +                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
>> +                    cpu_to_le32(80)/* the total size of Memory Error Record */);
>> +
>> +    /* Build the memory section CPER */
>> +    build_append_mem_cper(block, error_physical_addr);
>> +
>> +    /* Write back above whole new generic error data entry to guest memory */
>> +    cpu_physical_memory_write(error_block_address + current_block_length,
>> +                    block->data + data_length, block->len - data_length);
>> +
>> +    g_array_free(block, true);
>> +
>> +    return GHES_CPER_OK;
>> +}
> [...]
> 
> I'll try to make another round of review on this once patch is split
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2017-12-29  6:33       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2017-12-29  6:33 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Igor,
  Thank you very much for your review and your time. I will check your comments in detail later.

On 2017/12/28 22:18, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:11 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> This implements APEI GHES Table generation and record CPER in
>> runtime via fw_cfg blobs.Now we only support two types of GHESv2,
>> which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
>> supported type if needed. For the CPER section type, currently it
> s/type/types/
> 
>> is memory section because kernel manly wants userspace to handle
> s/manly/mainly/
> 
>> the memory errors. 
> 
>> In order to simulation, we hard code the error
>> type to Multi-bit ECC.
> Not sure what this is about, care to elaborate?
> 
> 
>> For GHESv2 error source, the OSPM must acknowledges the error via
>> Read ACK register. So user space must check the ACK value before
>> recording a new CPER to avoid read-write race condition.
>>
>> Suggested-by: Laszlo Ersek <lersek@redhat.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> The basic solution is suggested by Laszlo in [1]
>> [1]: https://lkml.org/lkml/2017/3/29/342
> 
> 
> patch is too big, it would be better if it were split in several parts.
> 
>> ---
>>  hw/acpi/aml-build.c         |   2 +
>>  hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
>>  hw/arm/virt-acpi-build.c    |   8 +
>>  include/hw/acpi/aml-build.h |   1 +
>>  include/hw/acpi/hest_ghes.h |  82 ++++++++++
>>  5 files changed, 483 insertions(+)
>>  create mode 100644 hw/acpi/hest_ghes.c
>>  create mode 100644 include/hw/acpi/hest_ghes.h
>>
>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>> index 36a6cc4..6849e5f 100644
>> --- a/hw/acpi/aml-build.c
>> +++ b/hw/acpi/aml-build.c
>> @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
>>      tables->table_data = g_array_new(false, true /* clear */, 1);
>>      tables->tcpalog = g_array_new(false, true /* clear */, 1);
>>      tables->vmgenid = g_array_new(false, true /* clear */, 1);
>> +    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
>>      tables->linker = bios_linker_loader_init();
>>  }
>>  
>> @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>>      g_array_free(tables->table_data, true);
>>      g_array_free(tables->tcpalog, mfre);
>>      g_array_free(tables->vmgenid, mfre);
>> +    g_array_free(tables->hardware_errors, mfre);
>>  }
>>  
>>  /* Build rsdt table */
>> diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
>> new file mode 100644
>> index 0000000..86ec99e
>> --- /dev/null
>> +++ b/hw/acpi/hest_ghes.c
>> @@ -0,0 +1,390 @@
>> +/* Support for generating APEI tables and record CPER for Guests
>> + *
>> + * Copyright (C) 2017 HuaWei Corporation.
>> + *
>> + * Author: Dongjiu Geng <gengdongjiu@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/acpi/acpi.h"
>> +#include "hw/acpi/aml-build.h"
>> +#include "hw/acpi/hest_ghes.h"
>> +#include "hw/nvram/fw_cfg.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/error-report.h"
>> +
>> +/* Generic Address Structure (GAS)
>> + * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
>> + * 2.0 compat note:
>> + *    @access_width must be 0, see ACPI 2.0:Table 5-1
>> + */
>> +static void build_append_gas(GArray *table, AmlRegionSpace as,
>> +                      uint8_t bit_width, uint8_t bit_offset,
>> +                      uint8_t access_width, uint64_t address)
>> +{
>> +    build_append_int_noprefix(table, as, 1);
>> +    build_append_int_noprefix(table, bit_width, 1);
>> +    build_append_int_noprefix(table, bit_offset, 1);
>> +    build_append_int_noprefix(table, access_width, 1);
>> +    build_append_int_noprefix(table, address, 8);
>> +}
> all build_append_foo() primitives should go into aml-build.c
> you can reuse take following patches for build_append_gas() from my github repo
> https://github.com/imammedo/qemu/commit/ff35b4ae1ec286f5f11830d504467f5ad243995b
> https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c
> 
> 
>> +/* Hardware Error Notification
>> + * ACPI 4.0: 17.3.2.7 Hardware Error Notification
>> + */
>> +static void build_append_notify(GArray *table, const uint8_t type,
>> +                                uint8_t length)
>> +{
>> +        build_append_int_noprefix(table, type, 1); /* type */
>> +        build_append_int_noprefix(table, length, 1);
>> +        build_append_int_noprefix(table, 0, 26);
>> +}
> split all build_append_foo() into separate patches /a patch per function/,
> 
> probably for GHES related primitives it would be better use 'ghes'
> domain prefix in function names, like
> 
>   s/build_append_notify/build_append_ghes_notify/
> 
> the same applies to other build_append_foo() below
> 
> 
>> +/* Generic Error Status Block
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gesb_header(GArray *table, uint32_t block_status,
>> +                      uint32_t raw_data_offset, uint32_t raw_data_length,
>> +                      uint32_t data_length, uint32_t error_severity)
>> +{
>> +    build_append_int_noprefix(table, block_status, 4);
>> +    build_append_int_noprefix(table, raw_data_offset, 4);
>> +    build_append_int_noprefix(table, raw_data_length, 4);
>> +    build_append_int_noprefix(table, data_length, 4);
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +}
>> +
>> +/* Generic Error Data Entry
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gede_header(GArray *table, const char *section_type,
>> +                      const uint32_t error_severity, const uint16_t revision,
>> +                      const uint32_t error_data_length)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < 16; i++) {
>> +        build_append_int_noprefix(table, section_type[i], 1);
>> +    }
>> +
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +    build_append_int_noprefix(table, revision, 2);
>> +    build_append_int_noprefix(table, 0, 2);
>> +    build_append_int_noprefix(table, error_data_length, 4);
>> +    build_append_int_noprefix(table, 0, 44);
>> +}
>> +
>> +/* Memory section CPER record */
> comment missing reference to related spec item
> 
>> +static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
>> +{
>> +    /*
>> +     * Memory Error Record
>> +     */
>> +    build_append_int_noprefix(table,
>> +                 (1UL << 14) | /* Type Valid */
>> +                 (1UL << 1) /* Physical Address Valid */,
>> +                 8);
>> +    /* Memory error status information */
>> +    build_append_int_noprefix(table, 0, 8);
>> +    /* The physical address at which the memory error occurred */
>> +    build_append_int_noprefix(table, error_physical_addr, 8);
>> +    build_append_int_noprefix(table, 0, 48);
>> +    /* Hard code to Multi-bit ECC error */
>> +    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
>> +    build_append_int_noprefix(table, 0, 7);
>> +}
>> +
>> +static int ghes_record_mem_error(uint64_t error_block_address,
>> +                                    uint64_t error_physical_addr)
> probably function should be part of 9/9 patch, as the others that's called
> only from ghes_record_errors().
> 
> i.e. split this patch into acpi tables generation and actual error generation patches.
> 
>> +{
>> +    GArray *block;
>> +    uint64_t current_block_length;
>> +    uint32_t data_length;
>> +    /* Memory section */
>> +    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
>> +                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
>> +                                0x83, 0xB1};
>> +
>> +    block = g_array_new(false, true /* clear */, 1);
>> +
>> +    /* Read the current length in bytes of the generic error data */
>> +    cpu_physical_memory_read(error_block_address +
>> +        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
>> +
>> +    /* The current whole length in bytes of the generic error status block */
>> +    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
> missing le32_to_cpu() here
> 
> also check other sites where you call cpu_physical_memory_foo()
> 
> it would be good to have a 'make check' test case included in this series,
> then when you can spot these errors during test on BE host, before posting patches.
> 
>> +
>> +    /* Add a new generic error data entry*/
>> +    data_length += GHES_DATA_LENGTH;
>> +    data_length += GHES_CPER_LENGTH;
>> +
>> +    /* Check whether it will run out of the preallocated memory if adding a new
>> +     * generic error data entry
>> +     */
>> +    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
>> +        error_report("Record CPER out of boundary!!!");
>> +        return GHES_CPER_FAIL;
> you return values here and from ghes_record_errors() but not actually
> handle them, so it's rather pointless thing to do,
> more over it's called on nofail path so one should either abort on error o ignore it
> 
>> +    }
>> +    /* Build the new generic error status block header */
>> +    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
>> +        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
>> +
>> +    /* Write back above generic error status block header to guest memory */
>> +    cpu_physical_memory_write(error_block_address, block->data,
>> +                              block->len);
>> +
>> +    /* Build the generic error data entries */
>> +
>> +    data_length = block->len;
>> +    /* Build the new generic error data entry header */
>> +    build_append_gede_header(block, mem_section_id_le,
>> +                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
>> +                    cpu_to_le32(80)/* the total size of Memory Error Record */);
>> +
>> +    /* Build the memory section CPER */
>> +    build_append_mem_cper(block, error_physical_addr);
>> +
>> +    /* Write back above whole new generic error data entry to guest memory */
>> +    cpu_physical_memory_write(error_block_address + current_block_length,
>> +                    block->data + data_length, block->len - data_length);
>> +
>> +    g_array_free(block, true);
>> +
>> +    return GHES_CPER_OK;
>> +}
> [...]
> 
> I'll try to make another round of review on this once patch is split
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2017-12-28 14:18     ` [Qemu-devel] " Igor Mammedov
@ 2018-01-03  2:21       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  2:21 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Hi Igor,
   sorry for my late response due to new year holiday.

On 2017/12/28 22:18, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:11 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> This implements APEI GHES Table generation and record CPER in
>> runtime via fw_cfg blobs.Now we only support two types of GHESv2,
>> which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
>> supported type if needed. For the CPER section type, currently it
> s/type/types/
Ok

> 
>> is memory section because kernel manly wants userspace to handle
> s/manly/mainly/
Ok

> 
>> the memory errors. 
> 
>> In order to simulation, we hard code the error
>> type to Multi-bit ECC.
> Not sure what this is about, care to elaborate?

please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
the error type to Multi-bit ECC.

[1]:
UEFI Spec 2.6 Errata A:

"N.2.5 Memory Error Section"
-----------------+---------------+--------------+-------------------------------------------+
        Mnemonic |   Byte Offset |  Byte Length |        Description                        |
-----------------+---------------+--------------+-------------------------------------------+
        ........ |  ............ |  .........   |        ...........                        |
-----------------+---------------+--------------+-------------------------------------------+
Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
		 |		 |		| 0 – Unknown                              |
		 |		 |		| 1 – No error                             |
		 |		 |		| 2 – Single-bit ECC                       |
		 |		 |		| 3 – Multi-bit ECC                        |
		 |		 |		| 4 – Single-symbol ChipKill ECC           |
		 |		 |		| 5 – Multi-symbol ChipKill ECC            |
		 |		 |		| 6 – Master abort			    |
		 |		 |		| 7 – Target abort			    |
		 |		 |		| 8 – Parity Error			    |
		 |		 |		| 9 – Watchdog timeout			    |
		 |		 |		| 10 – Invalid address			    |
		 |		 |		| 11 – Mirror Broken			    |
		 |		 |		| 12 – Memory Sparing			    |
		 |		 |		| 13 - Scrub corrected error		    |
		 |		 |		| 14 - Scrub uncorrected error		    |
		 |		 |		| 15 - Physical Memory Map-out event	    |
		 |		 |		| All other values reserved.		    |
-----------------+---------------+--------------+-------------------------------------------+
        ........ |  ............ |  .........   |        ...........                        |
-----------------+---------------+--------------+-------------------------------------------+
> 
> 
>> For GHESv2 error source, the OSPM must acknowledges the error via
>> Read ACK register. So user space must check the ACK value before
>> recording a new CPER to avoid read-write race condition.
>>
>> Suggested-by: Laszlo Ersek <lersek@redhat.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> The basic solution is suggested by Laszlo in [1]
>> [1]: https://lkml.org/lkml/2017/3/29/342
> 
> 
> patch is too big, it would be better if it were split in several parts.
Ok, I will split it.

> 
>> ---
>>  hw/acpi/aml-build.c         |   2 +
>>  hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
>>  hw/arm/virt-acpi-build.c    |   8 +
>>  include/hw/acpi/aml-build.h |   1 +
>>  include/hw/acpi/hest_ghes.h |  82 ++++++++++
>>  5 files changed, 483 insertions(+)
>>  create mode 100644 hw/acpi/hest_ghes.c
>>  create mode 100644 include/hw/acpi/hest_ghes.h
>>
>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>> index 36a6cc4..6849e5f 100644
>> --- a/hw/acpi/aml-build.c
>> +++ b/hw/acpi/aml-build.c
>> @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
>>      tables->table_data = g_array_new(false, true /* clear */, 1);
>>      tables->tcpalog = g_array_new(false, true /* clear */, 1);
>>      tables->vmgenid = g_array_new(false, true /* clear */, 1);
>> +    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
>>      tables->linker = bios_linker_loader_init();
>>  }
>>  
>> @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>>      g_array_free(tables->table_data, true);
>>      g_array_free(tables->tcpalog, mfre);
>>      g_array_free(tables->vmgenid, mfre);
>> +    g_array_free(tables->hardware_errors, mfre);
>>  }
>>  
>>  /* Build rsdt table */
>> diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
>> new file mode 100644
>> index 0000000..86ec99e
>> --- /dev/null
>> +++ b/hw/acpi/hest_ghes.c
>> @@ -0,0 +1,390 @@
>> +/* Support for generating APEI tables and record CPER for Guests
>> + *
>> + * Copyright (C) 2017 HuaWei Corporation.
>> + *
>> + * Author: Dongjiu Geng <gengdongjiu@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/acpi/acpi.h"
>> +#include "hw/acpi/aml-build.h"
>> +#include "hw/acpi/hest_ghes.h"
>> +#include "hw/nvram/fw_cfg.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/error-report.h"
>> +
>> +/* Generic Address Structure (GAS)
>> + * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
>> + * 2.0 compat note:
>> + *    @access_width must be 0, see ACPI 2.0:Table 5-1
>> + */
>> +static void build_append_gas(GArray *table, AmlRegionSpace as,
>> +                      uint8_t bit_width, uint8_t bit_offset,
>> +                      uint8_t access_width, uint64_t address)
>> +{
>> +    build_append_int_noprefix(table, as, 1);
>> +    build_append_int_noprefix(table, bit_width, 1);
>> +    build_append_int_noprefix(table, bit_offset, 1);
>> +    build_append_int_noprefix(table, access_width, 1);
>> +    build_append_int_noprefix(table, address, 8);
>> +}
> all build_append_foo() primitives should go into aml-build.c
> you can reuse take following patches for build_append_gas() from my github repo
> https://github.com/imammedo/qemu/commit/ff35b4ae1ec286f5f11830d504467f5ad243995b
> https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c

Ok, got it, thanks Igor's comments.

> 
> 
>> +/* Hardware Error Notification
>> + * ACPI 4.0: 17.3.2.7 Hardware Error Notification
>> + */
>> +static void build_append_notify(GArray *table, const uint8_t type,
>> +                                uint8_t length)
>> +{
>> +        build_append_int_noprefix(table, type, 1); /* type */
>> +        build_append_int_noprefix(table, length, 1);
>> +        build_append_int_noprefix(table, 0, 26);
>> +}
> split all build_append_foo() into separate patches /a patch per function/,
> 
> probably for GHES related primitives it would be better use 'ghes'
> domain prefix in function names, like
> 
>   s/build_append_notify/build_append_ghes_notify/
> 
> the same applies to other build_append_foo() below
sure, thanks Igor's good suggestion.

> 
> 
>> +/* Generic Error Status Block
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gesb_header(GArray *table, uint32_t block_status,
>> +                      uint32_t raw_data_offset, uint32_t raw_data_length,
>> +                      uint32_t data_length, uint32_t error_severity)
>> +{
>> +    build_append_int_noprefix(table, block_status, 4);
>> +    build_append_int_noprefix(table, raw_data_offset, 4);
>> +    build_append_int_noprefix(table, raw_data_length, 4);
>> +    build_append_int_noprefix(table, data_length, 4);
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +}
>> +
>> +/* Generic Error Data Entry
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gede_header(GArray *table, const char *section_type,
>> +                      const uint32_t error_severity, const uint16_t revision,
>> +                      const uint32_t error_data_length)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < 16; i++) {
>> +        build_append_int_noprefix(table, section_type[i], 1);
>> +    }
>> +
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +    build_append_int_noprefix(table, revision, 2);
>> +    build_append_int_noprefix(table, 0, 2);
>> +    build_append_int_noprefix(table, error_data_length, 4);
>> +    build_append_int_noprefix(table, 0, 44);
>> +}
>> +
>> +/* Memory section CPER record */
> comment missing reference to related spec item
Ok, thanks for the reminder.

> 
>> +static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
>> +{
>> +    /*
>> +     * Memory Error Record
>> +     */
>> +    build_append_int_noprefix(table,
>> +                 (1UL << 14) | /* Type Valid */
>> +                 (1UL << 1) /* Physical Address Valid */,
>> +                 8);
>> +    /* Memory error status information */
>> +    build_append_int_noprefix(table, 0, 8);
>> +    /* The physical address at which the memory error occurred */
>> +    build_append_int_noprefix(table, error_physical_addr, 8);
>> +    build_append_int_noprefix(table, 0, 48);
>> +    /* Hard code to Multi-bit ECC error */
>> +    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
>> +    build_append_int_noprefix(table, 0, 7);
>> +}
>> +
>> +static int ghes_record_mem_error(uint64_t error_block_address,
>> +                                    uint64_t error_physical_addr)
> probably function should be part of 9/9 patch, as the others that's called
> only from ghes_record_errors().
> 
> i.e. split this patch into acpi tables generation and actual error generation patches.
Ok, thanks Igor's good suggestion and review comments.

> 
>> +{
>> +    GArray *block;
>> +    uint64_t current_block_length;
>> +    uint32_t data_length;
>> +    /* Memory section */
>> +    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
>> +                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
>> +                                0x83, 0xB1};
>> +
>> +    block = g_array_new(false, true /* clear */, 1);
>> +
>> +    /* Read the current length in bytes of the generic error data */
>> +    cpu_physical_memory_read(error_block_address +
>> +        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
>> +
>> +    /* The current whole length in bytes of the generic error status block */
>> +    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
> missing le32_to_cpu() here
> 
> also check other sites where you call cpu_physical_memory_foo()
> 
> it would be good to have a 'make check' test case included in this series,
> then when you can spot these errors during test on BE host, before posting patches.
Ok, sure, thanks.


> 
>> +
>> +    /* Add a new generic error data entry*/
>> +    data_length += GHES_DATA_LENGTH;
>> +    data_length += GHES_CPER_LENGTH;
>> +
>> +    /* Check whether it will run out of the preallocated memory if adding a new
>> +     * generic error data entry
>> +     */
>> +    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
>> +        error_report("Record CPER out of boundary!!!");
>> +        return GHES_CPER_FAIL;
> you return values here and from ghes_record_errors() but not actually
> handle them, so it's rather pointless thing to do,
> more over it's called on nofail path so one should either abort on error o ignore it
yes, it should, thanks for the point out. I will make it abort if it is failed.

> 
>> +    }
>> +    /* Build the new generic error status block header */
>> +    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
>> +        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
>> +
>> +    /* Write back above generic error status block header to guest memory */
>> +    cpu_physical_memory_write(error_block_address, block->data,
>> +                              block->len);
>> +
>> +    /* Build the generic error data entries */
>> +
>> +    data_length = block->len;
>> +    /* Build the new generic error data entry header */
>> +    build_append_gede_header(block, mem_section_id_le,
>> +                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
>> +                    cpu_to_le32(80)/* the total size of Memory Error Record */);
>> +
>> +    /* Build the memory section CPER */
>> +    build_append_mem_cper(block, error_physical_addr);
>> +
>> +    /* Write back above whole new generic error data entry to guest memory */
>> +    cpu_physical_memory_write(error_block_address + current_block_length,
>> +                    block->data + data_length, block->len - data_length);
>> +
>> +    g_array_free(block, true);
>> +
>> +    return GHES_CPER_OK;
>> +}
> [...]
> 
> I'll try to make another round of review on this once patch is split
Ok, thanks in advance.

> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2018-01-03  2:21       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  2:21 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Hi Igor,
   sorry for my late response due to new year holiday.

On 2017/12/28 22:18, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:11 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> This implements APEI GHES Table generation and record CPER in
>> runtime via fw_cfg blobs.Now we only support two types of GHESv2,
>> which are GPIO-Signal and ARMv8 SEA. Afterwards, we can extend the
>> supported type if needed. For the CPER section type, currently it
> s/type/types/
Ok

> 
>> is memory section because kernel manly wants userspace to handle
> s/manly/mainly/
Ok

> 
>> the memory errors. 
> 
>> In order to simulation, we hard code the error
>> type to Multi-bit ECC.
> Not sure what this is about, care to elaborate?

please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
the error type to Multi-bit ECC.

[1]:
UEFI Spec 2.6 Errata A:

"N.2.5 Memory Error Section"
-----------------+---------------+--------------+-------------------------------------------+
        Mnemonic |   Byte Offset |  Byte Length |        Description                        |
-----------------+---------------+--------------+-------------------------------------------+
        ........ |  ............ |  .........   |        ...........                        |
-----------------+---------------+--------------+-------------------------------------------+
Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
		 |		 |		| 0 – Unknown                              |
		 |		 |		| 1 – No error                             |
		 |		 |		| 2 – Single-bit ECC                       |
		 |		 |		| 3 – Multi-bit ECC                        |
		 |		 |		| 4 – Single-symbol ChipKill ECC           |
		 |		 |		| 5 – Multi-symbol ChipKill ECC            |
		 |		 |		| 6 – Master abort			    |
		 |		 |		| 7 – Target abort			    |
		 |		 |		| 8 – Parity Error			    |
		 |		 |		| 9 – Watchdog timeout			    |
		 |		 |		| 10 – Invalid address			    |
		 |		 |		| 11 – Mirror Broken			    |
		 |		 |		| 12 – Memory Sparing			    |
		 |		 |		| 13 - Scrub corrected error		    |
		 |		 |		| 14 - Scrub uncorrected error		    |
		 |		 |		| 15 - Physical Memory Map-out event	    |
		 |		 |		| All other values reserved.		    |
-----------------+---------------+--------------+-------------------------------------------+
        ........ |  ............ |  .........   |        ...........                        |
-----------------+---------------+--------------+-------------------------------------------+
> 
> 
>> For GHESv2 error source, the OSPM must acknowledges the error via
>> Read ACK register. So user space must check the ACK value before
>> recording a new CPER to avoid read-write race condition.
>>
>> Suggested-by: Laszlo Ersek <lersek@redhat.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> The basic solution is suggested by Laszlo in [1]
>> [1]: https://lkml.org/lkml/2017/3/29/342
> 
> 
> patch is too big, it would be better if it were split in several parts.
Ok, I will split it.

> 
>> ---
>>  hw/acpi/aml-build.c         |   2 +
>>  hw/acpi/hest_ghes.c         | 390 ++++++++++++++++++++++++++++++++++++++++++++
>>  hw/arm/virt-acpi-build.c    |   8 +
>>  include/hw/acpi/aml-build.h |   1 +
>>  include/hw/acpi/hest_ghes.h |  82 ++++++++++
>>  5 files changed, 483 insertions(+)
>>  create mode 100644 hw/acpi/hest_ghes.c
>>  create mode 100644 include/hw/acpi/hest_ghes.h
>>
>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>> index 36a6cc4..6849e5f 100644
>> --- a/hw/acpi/aml-build.c
>> +++ b/hw/acpi/aml-build.c
>> @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
>>      tables->table_data = g_array_new(false, true /* clear */, 1);
>>      tables->tcpalog = g_array_new(false, true /* clear */, 1);
>>      tables->vmgenid = g_array_new(false, true /* clear */, 1);
>> +    tables->hardware_errors = g_array_new(false, true /* clear */, 1);
>>      tables->linker = bios_linker_loader_init();
>>  }
>>  
>> @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
>>      g_array_free(tables->table_data, true);
>>      g_array_free(tables->tcpalog, mfre);
>>      g_array_free(tables->vmgenid, mfre);
>> +    g_array_free(tables->hardware_errors, mfre);
>>  }
>>  
>>  /* Build rsdt table */
>> diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c
>> new file mode 100644
>> index 0000000..86ec99e
>> --- /dev/null
>> +++ b/hw/acpi/hest_ghes.c
>> @@ -0,0 +1,390 @@
>> +/* Support for generating APEI tables and record CPER for Guests
>> + *
>> + * Copyright (C) 2017 HuaWei Corporation.
>> + *
>> + * Author: Dongjiu Geng <gengdongjiu@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/acpi/acpi.h"
>> +#include "hw/acpi/aml-build.h"
>> +#include "hw/acpi/hest_ghes.h"
>> +#include "hw/nvram/fw_cfg.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/error-report.h"
>> +
>> +/* Generic Address Structure (GAS)
>> + * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
>> + * 2.0 compat note:
>> + *    @access_width must be 0, see ACPI 2.0:Table 5-1
>> + */
>> +static void build_append_gas(GArray *table, AmlRegionSpace as,
>> +                      uint8_t bit_width, uint8_t bit_offset,
>> +                      uint8_t access_width, uint64_t address)
>> +{
>> +    build_append_int_noprefix(table, as, 1);
>> +    build_append_int_noprefix(table, bit_width, 1);
>> +    build_append_int_noprefix(table, bit_offset, 1);
>> +    build_append_int_noprefix(table, access_width, 1);
>> +    build_append_int_noprefix(table, address, 8);
>> +}
> all build_append_foo() primitives should go into aml-build.c
> you can reuse take following patches for build_append_gas() from my github repo
> https://github.com/imammedo/qemu/commit/ff35b4ae1ec286f5f11830d504467f5ad243995b
> https://github.com/imammedo/qemu/commit/3d2fd6d13a3ea298d2ee814835495ce6241d085c

Ok, got it, thanks Igor's comments.

> 
> 
>> +/* Hardware Error Notification
>> + * ACPI 4.0: 17.3.2.7 Hardware Error Notification
>> + */
>> +static void build_append_notify(GArray *table, const uint8_t type,
>> +                                uint8_t length)
>> +{
>> +        build_append_int_noprefix(table, type, 1); /* type */
>> +        build_append_int_noprefix(table, length, 1);
>> +        build_append_int_noprefix(table, 0, 26);
>> +}
> split all build_append_foo() into separate patches /a patch per function/,
> 
> probably for GHES related primitives it would be better use 'ghes'
> domain prefix in function names, like
> 
>   s/build_append_notify/build_append_ghes_notify/
> 
> the same applies to other build_append_foo() below
sure, thanks Igor's good suggestion.

> 
> 
>> +/* Generic Error Status Block
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gesb_header(GArray *table, uint32_t block_status,
>> +                      uint32_t raw_data_offset, uint32_t raw_data_length,
>> +                      uint32_t data_length, uint32_t error_severity)
>> +{
>> +    build_append_int_noprefix(table, block_status, 4);
>> +    build_append_int_noprefix(table, raw_data_offset, 4);
>> +    build_append_int_noprefix(table, raw_data_length, 4);
>> +    build_append_int_noprefix(table, data_length, 4);
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +}
>> +
>> +/* Generic Error Data Entry
>> + * ACPI 4.0: 17.3.2.6.1 Generic Error Data
>> + */
>> +static void build_append_gede_header(GArray *table, const char *section_type,
>> +                      const uint32_t error_severity, const uint16_t revision,
>> +                      const uint32_t error_data_length)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < 16; i++) {
>> +        build_append_int_noprefix(table, section_type[i], 1);
>> +    }
>> +
>> +    build_append_int_noprefix(table, error_severity, 4);
>> +    build_append_int_noprefix(table, revision, 2);
>> +    build_append_int_noprefix(table, 0, 2);
>> +    build_append_int_noprefix(table, error_data_length, 4);
>> +    build_append_int_noprefix(table, 0, 44);
>> +}
>> +
>> +/* Memory section CPER record */
> comment missing reference to related spec item
Ok, thanks for the reminder.

> 
>> +static void build_append_mem_cper(GArray *table, uint64_t error_physical_addr)
>> +{
>> +    /*
>> +     * Memory Error Record
>> +     */
>> +    build_append_int_noprefix(table,
>> +                 (1UL << 14) | /* Type Valid */
>> +                 (1UL << 1) /* Physical Address Valid */,
>> +                 8);
>> +    /* Memory error status information */
>> +    build_append_int_noprefix(table, 0, 8);
>> +    /* The physical address at which the memory error occurred */
>> +    build_append_int_noprefix(table, error_physical_addr, 8);
>> +    build_append_int_noprefix(table, 0, 48);
>> +    /* Hard code to Multi-bit ECC error */
>> +    build_append_int_noprefix(table, 3 /* Multi-bit ECC */, 1);
>> +    build_append_int_noprefix(table, 0, 7);
>> +}
>> +
>> +static int ghes_record_mem_error(uint64_t error_block_address,
>> +                                    uint64_t error_physical_addr)
> probably function should be part of 9/9 patch, as the others that's called
> only from ghes_record_errors().
> 
> i.e. split this patch into acpi tables generation and actual error generation patches.
Ok, thanks Igor's good suggestion and review comments.

> 
>> +{
>> +    GArray *block;
>> +    uint64_t current_block_length;
>> +    uint32_t data_length;
>> +    /* Memory section */
>> +    char mem_section_id_le[] = {0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE,
>> +                                0x4E, 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C,
>> +                                0x83, 0xB1};
>> +
>> +    block = g_array_new(false, true /* clear */, 1);
>> +
>> +    /* Read the current length in bytes of the generic error data */
>> +    cpu_physical_memory_read(error_block_address +
>> +        offsetof(AcpiGenericErrorStatus, data_length), &data_length, 4);
>> +
>> +    /* The current whole length in bytes of the generic error status block */
>> +    current_block_length = sizeof(AcpiGenericErrorStatus) + data_length;
> missing le32_to_cpu() here
> 
> also check other sites where you call cpu_physical_memory_foo()
> 
> it would be good to have a 'make check' test case included in this series,
> then when you can spot these errors during test on BE host, before posting patches.
Ok, sure, thanks.


> 
>> +
>> +    /* Add a new generic error data entry*/
>> +    data_length += GHES_DATA_LENGTH;
>> +    data_length += GHES_CPER_LENGTH;
>> +
>> +    /* Check whether it will run out of the preallocated memory if adding a new
>> +     * generic error data entry
>> +     */
>> +    if ((data_length + sizeof(AcpiGenericErrorStatus)) > GHES_MAX_RAW_DATA_LENGTH) {
>> +        error_report("Record CPER out of boundary!!!");
>> +        return GHES_CPER_FAIL;
> you return values here and from ghes_record_errors() but not actually
> handle them, so it's rather pointless thing to do,
> more over it's called on nofail path so one should either abort on error o ignore it
yes, it should, thanks for the point out. I will make it abort if it is failed.

> 
>> +    }
>> +    /* Build the new generic error status block header */
>> +    build_append_gesb_header(block, cpu_to_le32(ACPI_GEBS_UNCORRECTABLE), 0, 0,
>> +        cpu_to_le32(data_length), cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE));
>> +
>> +    /* Write back above generic error status block header to guest memory */
>> +    cpu_physical_memory_write(error_block_address, block->data,
>> +                              block->len);
>> +
>> +    /* Build the generic error data entries */
>> +
>> +    data_length = block->len;
>> +    /* Build the new generic error data entry header */
>> +    build_append_gede_header(block, mem_section_id_le,
>> +                    cpu_to_le32(ACPI_CPER_SEV_RECOVERABLE), cpu_to_le32(0x300),
>> +                    cpu_to_le32(80)/* the total size of Memory Error Record */);
>> +
>> +    /* Build the memory section CPER */
>> +    build_append_mem_cper(block, error_physical_addr);
>> +
>> +    /* Write back above whole new generic error data entry to guest memory */
>> +    cpu_physical_memory_write(error_block_address + current_block_length,
>> +                    block->data + data_length, block->len - data_length);
>> +
>> +    g_array_free(block, true);
>> +
>> +    return GHES_CPER_OK;
>> +}
> [...]
> 
> I'll try to make another round of review on this once patch is split
Ok, thanks in advance.

> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
  2017-12-28 14:53     ` [Qemu-devel] " Igor Mammedov
@ 2018-01-03  3:48       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  3:48 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On 2017/12/28 22:53, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:16 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> In ARM platform we implements a notification of error events
>> via a GPIO pin. For this GPIO-signaled events, we choose GPIO
>> pin 4 for hardware error device (PNP0C33), So _E04 should be
>> added to ACPI DSDT table. When GPIO-pin 4 signaled a events,
>> the guest ACPI driver will receive this notification and
>> handing the error.
>>
>> In order to better trigger the GPIO IRQ, we defined a notifier
>> hardware_error_notifiers. If Qemu wants to deliver a GPIO-Signal
>> notification, will call it.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> 1. Address discussion result about guest APEI notification type for SIGBUS_MCEERR_AO SIGBUS in [1],
>>    the discussion conclusion is using GPIO-Signal
>>
>> [1]:
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03397.html
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03467.html
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03601.html
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03775.html
>>
>> 2. The ASL dump for the GPIO and hardware error device
>>
>> ................
>> Device (GPO0)
>> {
>>     Name (_AEI, ResourceTemplate ()  // _AEI: ACPI Event Interrupts
>>     {
>>         .............
>>         GpioInt (Edge, ActiveHigh, Exclusive, PullUp, 0x0000,
>>             "GPO0", 0x00, ResourceConsumer, ,
>>             )
>>             {   // Pin list
>>                 0x0004
>>             }
>>     })
>>     Method (_E04, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
>>     {
>>         Notify (ERRD, 0x80) // Status Change
>>     }
>> }
>> Device (ERRD)
>> {
>>     Name (_HID, EisaId ("PNP0C33") /* Error Device */)  // _HID: Hardware ID
>>     Name (_UID, Zero)  // _UID: Unique ID
>>     Method (_STA, 0, NotSerialized)  // _STA: Status
>>     {
>>         Return (0x0F)
>>     }
>> }
>>
>> 3. Below is the guest log when Qemu notifies guest using GPIO-signal after record a CPER
>> [  504.164899] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
>> [  504.166970] {1}[Hardware Error]: event severity: recoverable
>> [  504.251650] {1}[Hardware Error]:  Error 0, type: recoverable
>> [  504.252974] {1}[Hardware Error]:   section_type: memory error
>> [  504.254380] {1}[Hardware Error]:   physical_address: 0x00000000000003ec
>> [  504.255879] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
>> ---
>>  hw/arm/virt-acpi-build.c | 31 ++++++++++++++++++++++++++++++-
>>  hw/arm/virt.c            | 18 ++++++++++++++++++
>>  include/sysemu/sysemu.h  |  3 +++
>>  vl.c                     | 12 ++++++++++++
>>  4 files changed, 63 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index b7d45cd..06c14b3 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -49,6 +49,7 @@
>>  
>>  #define ARM_SPI_BASE 32
>>  #define ACPI_POWER_BUTTON_DEVICE "PWRB"
>> +#define ACPI_HARDWARE_ERROR_DEVICE "ERRD"
>>  
>>  static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
>>  {
>> @@ -340,7 +341,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>>  
>>      Aml *aei = aml_resource_template();
>>      /* Pin 3 for power button */
>> -    const uint32_t pin_list[1] = {3};
>> +    uint32_t pin_list[1] = {3};
>> +    aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
>> +                                 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
>> +                                 "GPO0", NULL, 0));
>> +
>> +    /* Pin 4 for hardware error device */
>> +    pin_list[0] = 4;
>>      aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
>>                                   AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
>>                                   "GPO0", NULL, 0));
>> @@ -351,6 +358,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>>      aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
>>                                    aml_int(0x80)));
>>      aml_append(dev, method);
>> +
>> +    /* _E04 is handle for hardware error */
>> +    method = aml_method("_E04", 0, AML_NOTSERIALIZED);
>> +    aml_append(method, aml_notify(aml_name(ACPI_HARDWARE_ERROR_DEVICE),
>> +                                  aml_int(0x80)));
> aml_int(0x80) /* ACPI ... : Notification For Generic Error Sources */
sure. thanks

> 
>> +    aml_append(dev, method);
>> +
>>      aml_append(scope, dev);
>>  }
>>  
>> @@ -363,6 +377,20 @@ static void acpi_dsdt_add_power_button(Aml *scope)
>>      aml_append(scope, dev);
>>  }
>>  
>> +static void acpi_dsdt_add_error_device(Aml *scope)
>> +{
>> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
>> +    Aml *method;
>> +
>> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
>> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
>> +
>> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>> +    aml_append(method, aml_return(aml_int(0x0f)));
> no need for dummy _STA method, device is assumed to be present if there is no _STA 
Igor,
  do you mean remove above two line code as shown in [1]?
I dump the DSDT table in my host Ubuntu PC for the error device (PNP0C33), it has the _STA, as shown in [2].
do we not want to add the _STA for guest?

[1]
+    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_return(aml_int(0x0f)));

[2]:
        Device (WERR)
        {
            Name (_HID, EisaId ("PNP0C33"))  // _HID: Hardware ID
            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If (LGreaterEqual (OSYS, 0x07D9))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (Zero)
                }
            }
        }
> 
>> +    aml_append(dev, method);
>> +    aml_append(scope, dev);
>> +}
>> +
>>  /* RSDP */
>>  static GArray *
>>  build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
>> @@ -716,6 +744,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>      acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
>>                         (irqmap[VIRT_GPIO] + ARM_SPI_BASE));
>>      acpi_dsdt_add_power_button(scope);
>> +    acpi_dsdt_add_error_device(scope);
>>  
>>      aml_append(dsdt, scope);
>>  
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index 6b7a0fe..68495c2 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -701,16 +701,27 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
>>  }
>>  
>>  static DeviceState *gpio_key_dev;
>> +static DeviceState *gpio_err_dev;
>>  static void virt_powerdown_req(Notifier *n, void *opaque)
>>  {
>>      /* use gpio Pin 3 for power button event */
>>      qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
>>  }
>>  
>> +static void virt_error_notify_req(Notifier *n, void *opaque)
>> +{
>> +    /* use gpio Pin 4 for hardware error event */
>> +    qemu_set_irq(qdev_get_gpio_in(gpio_err_dev, 0), 1);
>> +}
>> +
>>  static Notifier virt_system_powerdown_notifier = {
>>      .notify = virt_powerdown_req
>>  };
>>  
>> +static Notifier virt_hardware_error_notifier = {
>> +    .notify = virt_error_notify_req
>> +};
>> +
>>  static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>>  {
>>      char *nodename;
>> @@ -739,6 +750,10 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>>  
>>      gpio_key_dev = sysbus_create_simple("gpio-key", -1,
>>                                          qdev_get_gpio_in(pl061_dev, 3));
>> +
>> +    gpio_err_dev = sysbus_create_simple("gpio-key", -1,
>> +                                        qdev_get_gpio_in(pl061_dev, 4));
>> +
>>      qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
>>      qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
>>      qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
>> @@ -755,6 +770,9 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>>      /* connect powerdown request */
>>      qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
>>  
>> +    /* connect hardware error notify request */
>> +    qemu_register_hardware_error_notifier(&virt_hardware_error_notifier);
>> +
>>      g_free(nodename);
>>  }
>>  
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index b213696..86931cf 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -75,6 +75,7 @@ void qemu_register_wakeup_notifier(Notifier *notifier);
>>  void qemu_system_shutdown_request(ShutdownCause reason);
>>  void qemu_system_powerdown_request(void);
>>  void qemu_register_powerdown_notifier(Notifier *notifier);
>> +void qemu_register_hardware_error_notifier(Notifier *notifier);
>>  void qemu_system_debug_request(void);
>>  void qemu_system_vmstop_request(RunState reason);
>>  void qemu_system_vmstop_request_prepare(void);
>> @@ -93,6 +94,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
>>  
>>  void qemu_announce_self(void);
>>  
>> +void qemu_hardware_error_notify(void);
>> +
>>  extern int autostart;
>>  
>>  typedef enum {
>> diff --git a/vl.c b/vl.c
>> index d632693..3552f7d 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -1614,6 +1614,8 @@ static int suspend_requested;
>>  static WakeupReason wakeup_reason;
>>  static NotifierList powerdown_notifiers =
>>      NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
>> +static NotifierList hardware_error_notifiers =
>> +    NOTIFIER_LIST_INITIALIZER(hardware_error_notifiers);
>>  static NotifierList suspend_notifiers =
>>      NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
>>  static NotifierList wakeup_notifiers =
>> @@ -1850,12 +1852,22 @@ void qemu_register_powerdown_notifier(Notifier *notifier)
>>      notifier_list_add(&powerdown_notifiers, notifier);
>>  }
>>  
>> +void qemu_register_hardware_error_notifier(Notifier *notifier)
>> +{
>> +    notifier_list_add(&hardware_error_notifiers, notifier);
>> +}
>> +
>>  void qemu_system_debug_request(void)
>>  {
>>      debug_requested = 1;
>>      qemu_notify_event();
>>  }
>>  
>> +void qemu_hardware_error_notify(void)
>> +{
>> +    notifier_list_notify(&hardware_error_notifiers, NULL);
>> +}
> 
> I'd prefer if you'd replace all this Notifier code with a machine callback
> and call it when needed.
Ok, thanks for this suggestion. I will check the code and see how to add a machine callback.


> 
>>  static bool main_loop_should_exit(void)
>>  {
>>      RunState r;
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
@ 2018-01-03  3:48       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  3:48 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On 2017/12/28 22:53, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:16 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> In ARM platform we implements a notification of error events
>> via a GPIO pin. For this GPIO-signaled events, we choose GPIO
>> pin 4 for hardware error device (PNP0C33), So _E04 should be
>> added to ACPI DSDT table. When GPIO-pin 4 signaled a events,
>> the guest ACPI driver will receive this notification and
>> handing the error.
>>
>> In order to better trigger the GPIO IRQ, we defined a notifier
>> hardware_error_notifiers. If Qemu wants to deliver a GPIO-Signal
>> notification, will call it.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> 1. Address discussion result about guest APEI notification type for SIGBUS_MCEERR_AO SIGBUS in [1],
>>    the discussion conclusion is using GPIO-Signal
>>
>> [1]:
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03397.html
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03467.html
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03601.html
>> https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03775.html
>>
>> 2. The ASL dump for the GPIO and hardware error device
>>
>> ................
>> Device (GPO0)
>> {
>>     Name (_AEI, ResourceTemplate ()  // _AEI: ACPI Event Interrupts
>>     {
>>         .............
>>         GpioInt (Edge, ActiveHigh, Exclusive, PullUp, 0x0000,
>>             "GPO0", 0x00, ResourceConsumer, ,
>>             )
>>             {   // Pin list
>>                 0x0004
>>             }
>>     })
>>     Method (_E04, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
>>     {
>>         Notify (ERRD, 0x80) // Status Change
>>     }
>> }
>> Device (ERRD)
>> {
>>     Name (_HID, EisaId ("PNP0C33") /* Error Device */)  // _HID: Hardware ID
>>     Name (_UID, Zero)  // _UID: Unique ID
>>     Method (_STA, 0, NotSerialized)  // _STA: Status
>>     {
>>         Return (0x0F)
>>     }
>> }
>>
>> 3. Below is the guest log when Qemu notifies guest using GPIO-signal after record a CPER
>> [  504.164899] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 7
>> [  504.166970] {1}[Hardware Error]: event severity: recoverable
>> [  504.251650] {1}[Hardware Error]:  Error 0, type: recoverable
>> [  504.252974] {1}[Hardware Error]:   section_type: memory error
>> [  504.254380] {1}[Hardware Error]:   physical_address: 0x00000000000003ec
>> [  504.255879] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
>> ---
>>  hw/arm/virt-acpi-build.c | 31 ++++++++++++++++++++++++++++++-
>>  hw/arm/virt.c            | 18 ++++++++++++++++++
>>  include/sysemu/sysemu.h  |  3 +++
>>  vl.c                     | 12 ++++++++++++
>>  4 files changed, 63 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index b7d45cd..06c14b3 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -49,6 +49,7 @@
>>  
>>  #define ARM_SPI_BASE 32
>>  #define ACPI_POWER_BUTTON_DEVICE "PWRB"
>> +#define ACPI_HARDWARE_ERROR_DEVICE "ERRD"
>>  
>>  static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
>>  {
>> @@ -340,7 +341,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>>  
>>      Aml *aei = aml_resource_template();
>>      /* Pin 3 for power button */
>> -    const uint32_t pin_list[1] = {3};
>> +    uint32_t pin_list[1] = {3};
>> +    aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
>> +                                 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
>> +                                 "GPO0", NULL, 0));
>> +
>> +    /* Pin 4 for hardware error device */
>> +    pin_list[0] = 4;
>>      aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
>>                                   AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
>>                                   "GPO0", NULL, 0));
>> @@ -351,6 +358,13 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>>      aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
>>                                    aml_int(0x80)));
>>      aml_append(dev, method);
>> +
>> +    /* _E04 is handle for hardware error */
>> +    method = aml_method("_E04", 0, AML_NOTSERIALIZED);
>> +    aml_append(method, aml_notify(aml_name(ACPI_HARDWARE_ERROR_DEVICE),
>> +                                  aml_int(0x80)));
> aml_int(0x80) /* ACPI ... : Notification For Generic Error Sources */
sure. thanks

> 
>> +    aml_append(dev, method);
>> +
>>      aml_append(scope, dev);
>>  }
>>  
>> @@ -363,6 +377,20 @@ static void acpi_dsdt_add_power_button(Aml *scope)
>>      aml_append(scope, dev);
>>  }
>>  
>> +static void acpi_dsdt_add_error_device(Aml *scope)
>> +{
>> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
>> +    Aml *method;
>> +
>> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
>> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
>> +
>> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>> +    aml_append(method, aml_return(aml_int(0x0f)));
> no need for dummy _STA method, device is assumed to be present if there is no _STA 
Igor,
  do you mean remove above two line code as shown in [1]?
I dump the DSDT table in my host Ubuntu PC for the error device (PNP0C33), it has the _STA, as shown in [2].
do we not want to add the _STA for guest?

[1]
+    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_return(aml_int(0x0f)));

[2]:
        Device (WERR)
        {
            Name (_HID, EisaId ("PNP0C33"))  // _HID: Hardware ID
            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If (LGreaterEqual (OSYS, 0x07D9))
                {
                    Return (0x0F)
                }
                Else
                {
                    Return (Zero)
                }
            }
        }
> 
>> +    aml_append(dev, method);
>> +    aml_append(scope, dev);
>> +}
>> +
>>  /* RSDP */
>>  static GArray *
>>  build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
>> @@ -716,6 +744,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>      acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
>>                         (irqmap[VIRT_GPIO] + ARM_SPI_BASE));
>>      acpi_dsdt_add_power_button(scope);
>> +    acpi_dsdt_add_error_device(scope);
>>  
>>      aml_append(dsdt, scope);
>>  
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index 6b7a0fe..68495c2 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -701,16 +701,27 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
>>  }
>>  
>>  static DeviceState *gpio_key_dev;
>> +static DeviceState *gpio_err_dev;
>>  static void virt_powerdown_req(Notifier *n, void *opaque)
>>  {
>>      /* use gpio Pin 3 for power button event */
>>      qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
>>  }
>>  
>> +static void virt_error_notify_req(Notifier *n, void *opaque)
>> +{
>> +    /* use gpio Pin 4 for hardware error event */
>> +    qemu_set_irq(qdev_get_gpio_in(gpio_err_dev, 0), 1);
>> +}
>> +
>>  static Notifier virt_system_powerdown_notifier = {
>>      .notify = virt_powerdown_req
>>  };
>>  
>> +static Notifier virt_hardware_error_notifier = {
>> +    .notify = virt_error_notify_req
>> +};
>> +
>>  static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>>  {
>>      char *nodename;
>> @@ -739,6 +750,10 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>>  
>>      gpio_key_dev = sysbus_create_simple("gpio-key", -1,
>>                                          qdev_get_gpio_in(pl061_dev, 3));
>> +
>> +    gpio_err_dev = sysbus_create_simple("gpio-key", -1,
>> +                                        qdev_get_gpio_in(pl061_dev, 4));
>> +
>>      qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
>>      qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
>>      qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
>> @@ -755,6 +770,9 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
>>      /* connect powerdown request */
>>      qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
>>  
>> +    /* connect hardware error notify request */
>> +    qemu_register_hardware_error_notifier(&virt_hardware_error_notifier);
>> +
>>      g_free(nodename);
>>  }
>>  
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index b213696..86931cf 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -75,6 +75,7 @@ void qemu_register_wakeup_notifier(Notifier *notifier);
>>  void qemu_system_shutdown_request(ShutdownCause reason);
>>  void qemu_system_powerdown_request(void);
>>  void qemu_register_powerdown_notifier(Notifier *notifier);
>> +void qemu_register_hardware_error_notifier(Notifier *notifier);
>>  void qemu_system_debug_request(void);
>>  void qemu_system_vmstop_request(RunState reason);
>>  void qemu_system_vmstop_request_prepare(void);
>> @@ -93,6 +94,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
>>  
>>  void qemu_announce_self(void);
>>  
>> +void qemu_hardware_error_notify(void);
>> +
>>  extern int autostart;
>>  
>>  typedef enum {
>> diff --git a/vl.c b/vl.c
>> index d632693..3552f7d 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -1614,6 +1614,8 @@ static int suspend_requested;
>>  static WakeupReason wakeup_reason;
>>  static NotifierList powerdown_notifiers =
>>      NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
>> +static NotifierList hardware_error_notifiers =
>> +    NOTIFIER_LIST_INITIALIZER(hardware_error_notifiers);
>>  static NotifierList suspend_notifiers =
>>      NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
>>  static NotifierList wakeup_notifiers =
>> @@ -1850,12 +1852,22 @@ void qemu_register_powerdown_notifier(Notifier *notifier)
>>      notifier_list_add(&powerdown_notifiers, notifier);
>>  }
>>  
>> +void qemu_register_hardware_error_notifier(Notifier *notifier)
>> +{
>> +    notifier_list_add(&hardware_error_notifiers, notifier);
>> +}
>> +
>>  void qemu_system_debug_request(void)
>>  {
>>      debug_requested = 1;
>>      qemu_notify_event();
>>  }
>>  
>> +void qemu_hardware_error_notify(void)
>> +{
>> +    notifier_list_notify(&hardware_error_notifiers, NULL);
>> +}
> 
> I'd prefer if you'd replace all this Notifier code with a machine callback
> and call it when needed.
Ok, thanks for this suggestion. I will check the code and see how to add a machine callback.


> 
>>  static bool main_loop_should_exit(void)
>>  {
>>      RunState r;
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
  2017-12-28 14:58     ` [Qemu-devel] " Igor Mammedov
@ 2018-01-03  4:02       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  4:02 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Igor,
   Thanks for the review and comments.

On 2017/12/28 22:58, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:17 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> Support this feature since version 2.10, disable it by
>> default in the old version.
> patch should go before acpi tables are actually added,
> otherwise it might break bisectability.
yes, it should. I will move this patch before APEI tables are added.
Thanks for the pointing out.

> 
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address Shannon's comments to add platform version in [1].
>>
>> [1]: https://lkml.org/lkml/2017/8/25/821
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>>  hw/arm/virt-acpi-build.c | 14 +++++++++-----
>>  hw/arm/virt.c            |  4 ++++
>>  include/hw/arm/virt.h    |  1 +
>>  3 files changed, 14 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index 06c14b3..b6974ef 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>>      acpi_add_table(table_offsets, tables_blob);
>>      build_spcr(tables_blob, tables->linker, vms);
>>  
>> -    acpi_add_table(table_offsets, tables_blob);
>> -    build_hardware_error_table(tables->hardware_errors, tables->linker);
>> -    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
>> -
>> +    if (!vmc->no_ras) {
> 
> it's better to avoid no_foo, use something like
> 
> vmc->has_ras
> 
> instead
Ok, I will rename it.

> 
>> +        acpi_add_table(table_offsets, tables_blob);
>> +        build_hardware_error_table(tables->hardware_errors, tables->linker);
>> +        build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
>> +    }
>>  
>>      if (nb_numa_nodes > 0) {
>>          acpi_add_table(table_offsets, tables_blob);
>> @@ -891,6 +892,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
>>  
>>  void virt_acpi_setup(VirtMachineState *vms)
>>  {
>> +    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>>      AcpiBuildTables tables;
>>      AcpiBuildState *build_state;
>>  
>> @@ -922,7 +924,9 @@ void virt_acpi_setup(VirtMachineState *vms)
>>      fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
>>                      acpi_data_len(tables.tcpalog));
>>  
>> -    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
>> +    if (!vmc->no_ras) {
>> +        ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
>> +    }
>>  
>>      build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
>>                                                ACPI_BUILD_RSDP_FILE, 0);
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index 68495c2..ab79988 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -1732,8 +1732,12 @@ static void virt_2_9_instance_init(Object *obj)
>>  
>>  static void virt_machine_2_9_options(MachineClass *mc)
>>  {
>> +    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
>> +
>>      virt_machine_2_10_options(mc);
>>      SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_9);
>> +    /* memory recovery feature was introduced with 2.10 */
>> +    vmc->no_ras = true;
>>  }
>>  DEFINE_VIRT_MACHINE(2, 9)
>>  
>> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
>> index 33b0ff3..8fbd664 100644
>> --- a/include/hw/arm/virt.h
>> +++ b/include/hw/arm/virt.h
>> @@ -84,6 +84,7 @@ typedef struct {
>>      bool disallow_affinity_adjustment;
>>      bool no_its;
>>      bool no_pmu;
>> +    bool no_ras;
>>      bool claim_edge_triggered_timers;
>>  } VirtMachineClass;
>>  
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
@ 2018-01-03  4:02       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  4:02 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Igor,
   Thanks for the review and comments.

On 2017/12/28 22:58, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:17 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> Support this feature since version 2.10, disable it by
>> default in the old version.
> patch should go before acpi tables are actually added,
> otherwise it might break bisectability.
yes, it should. I will move this patch before APEI tables are added.
Thanks for the pointing out.

> 
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address Shannon's comments to add platform version in [1].
>>
>> [1]: https://lkml.org/lkml/2017/8/25/821
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>>  hw/arm/virt-acpi-build.c | 14 +++++++++-----
>>  hw/arm/virt.c            |  4 ++++
>>  include/hw/arm/virt.h    |  1 +
>>  3 files changed, 14 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index 06c14b3..b6974ef 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>>      acpi_add_table(table_offsets, tables_blob);
>>      build_spcr(tables_blob, tables->linker, vms);
>>  
>> -    acpi_add_table(table_offsets, tables_blob);
>> -    build_hardware_error_table(tables->hardware_errors, tables->linker);
>> -    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
>> -
>> +    if (!vmc->no_ras) {
> 
> it's better to avoid no_foo, use something like
> 
> vmc->has_ras
> 
> instead
Ok, I will rename it.

> 
>> +        acpi_add_table(table_offsets, tables_blob);
>> +        build_hardware_error_table(tables->hardware_errors, tables->linker);
>> +        build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
>> +    }
>>  
>>      if (nb_numa_nodes > 0) {
>>          acpi_add_table(table_offsets, tables_blob);
>> @@ -891,6 +892,7 @@ static const VMStateDescription vmstate_virt_acpi_build = {
>>  
>>  void virt_acpi_setup(VirtMachineState *vms)
>>  {
>> +    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>>      AcpiBuildTables tables;
>>      AcpiBuildState *build_state;
>>  
>> @@ -922,7 +924,9 @@ void virt_acpi_setup(VirtMachineState *vms)
>>      fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
>>                      acpi_data_len(tables.tcpalog));
>>  
>> -    ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
>> +    if (!vmc->no_ras) {
>> +        ghes_add_fw_cfg(vms->fw_cfg, tables.hardware_errors);
>> +    }
>>  
>>      build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
>>                                                ACPI_BUILD_RSDP_FILE, 0);
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index 68495c2..ab79988 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -1732,8 +1732,12 @@ static void virt_2_9_instance_init(Object *obj)
>>  
>>  static void virt_machine_2_9_options(MachineClass *mc)
>>  {
>> +    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
>> +
>>      virt_machine_2_10_options(mc);
>>      SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_9);
>> +    /* memory recovery feature was introduced with 2.10 */
>> +    vmc->no_ras = true;
>>  }
>>  DEFINE_VIRT_MACHINE(2, 9)
>>  
>> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
>> index 33b0ff3..8fbd664 100644
>> --- a/include/hw/arm/virt.h
>> +++ b/include/hw/arm/virt.h
>> @@ -84,6 +84,7 @@ typedef struct {
>>      bool disallow_affinity_adjustment;
>>      bool no_its;
>>      bool no_pmu;
>> +    bool no_ras;
>>      bool claim_edge_triggered_timers;
>>  } VirtMachineClass;
>>  
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2017-12-28 15:07     ` [Qemu-devel] " Igor Mammedov
@ 2018-01-03  9:13       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  9:13 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5



On 2017/12/28 23:07, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:18 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
>> translates the host VA which is delivered by host to guest PA, then fill
>> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
>> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
>> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>>
>> If guest accesses the poisoned memory, it generates Synchronous External
>> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
>> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
> s/unmapped/unmap/
Thanks.

> 
>> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
>> create a new CPER and add it to guest APEI GHES memory, then notify the
>> guest with a GPIO-Signal notification.
> too long sentence, it's hard get what goes on here, pls split it in simple
> sentences/rephrase so it would be easy to understand behavior.
I will split it in simple sentences/rephrase.
Thanks for your detailed review.

> 
>>
>> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
>> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
>> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>>
>> Suggested-by: James Morse <james.morse@arm.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
>> Shown some discussion in [1].
>>
>> [1]:
>> https://lkml.org/lkml/2017/2/27/246
>> https://lkml.org/lkml/2017/9/14/241
>> https://lkml.org/lkml/2017/9/22/499
>> ---
>>  include/sysemu/kvm.h |  2 +-
>>  target/arm/kvm.c     |  2 ++
>>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 37 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
>> index 3a458f5..90c1605 100644
>> --- a/include/sysemu/kvm.h
>> +++ b/include/sysemu/kvm.h
>> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>>  
>> -#ifdef TARGET_I386
>> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
>>  #define KVM_HAVE_MCE_INJECTION 1
>>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>>  #endif
>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>> index 7c17f0d..9d25f51 100644
>> --- a/target/arm/kvm.c
>> +++ b/target/arm/kvm.c
>> @@ -26,6 +26,7 @@
>>  #include "exec/address-spaces.h"
>>  #include "hw/boards.h"
>>  #include "qemu/log.h"
>> +#include "exec/ram_addr.h"
>>  
>>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>>      KVM_CAP_LAST_INFO
>> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>>  
>>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>>  
>> +    qemu_register_reset(kvm_unpoison_all, NULL);
>>      type_register_static(&host_arm_cpu_type_info);
>>  
>>      return 0;
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index c00450d..6955d85 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -27,6 +27,9 @@
>>  #include "kvm_arm.h"
>>  #include "internals.h"
>>  #include "hw/arm/arm.h"
>> +#include "exec/ram_addr.h"
>> +#include "hw/acpi/acpi-defs.h"
>> +#include "hw/acpi/hest_ghes.h"
>>  
>>  static bool have_guest_debug;
>>  
>> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>>      return ret;
>>  }
>>  
>> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>> +{
>> +    ram_addr_t ram_addr;
>> +    hwaddr paddr;
>> +
>> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
>> +    if (addr) {
>> +        ram_addr = qemu_ram_addr_from_host(addr);
>> +        if (ram_addr != RAM_ADDR_INVALID &&
>> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
>> +            kvm_hwpoison_page_add(ram_addr);
>> +            if (code == BUS_MCEERR_AR) {
>> +                kvm_cpu_synchronize_state(c);
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
>> +                kvm_inject_arm_sea(c);
>> +            } else if (code == BUS_MCEERR_AO) {
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
>> +                qemu_hardware_error_notify();
>> +            }
>> +            return;
>> +        }
>> +        fprintf(stderr, "Hardware memory error for memory used by "
>> +                "QEMU itself instead of guest system!\n");
> not quite sure what above message means,
When the memory error address belong to QEMU itself, not belong to guest OS.
it will print above message.

Above message means this memory error happens in QEMU application instead of guest OS.

> 
> also fprintf() probably shouldn't be used by new code.
how about we use error_report()? thanks

> 
>> +    }
>> +
>> +    if (code == BUS_MCEERR_AR) {
>> +        fprintf(stderr, "Hardware memory error!\n");
>> +        exit(1);
>> +    }
>> +}
>> +
>>  /* C6.6.29 BRK instruction */
>>  static const uint32_t brk_insn = 0xd4200000;
>>  
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2018-01-03  9:13       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03  9:13 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5



On 2017/12/28 23:07, Igor Mammedov wrote:
> On Thu, 28 Dec 2017 13:54:18 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> 
>> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
>> translates the host VA which is delivered by host to guest PA, then fill
>> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
>> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
>> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>>
>> If guest accesses the poisoned memory, it generates Synchronous External
>> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
>> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
> s/unmapped/unmap/
Thanks.

> 
>> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
>> create a new CPER and add it to guest APEI GHES memory, then notify the
>> guest with a GPIO-Signal notification.
> too long sentence, it's hard get what goes on here, pls split it in simple
> sentences/rephrase so it would be easy to understand behavior.
I will split it in simple sentences/rephrase.
Thanks for your detailed review.

> 
>>
>> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
>> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
>> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>>
>> Suggested-by: James Morse <james.morse@arm.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
>> Shown some discussion in [1].
>>
>> [1]:
>> https://lkml.org/lkml/2017/2/27/246
>> https://lkml.org/lkml/2017/9/14/241
>> https://lkml.org/lkml/2017/9/22/499
>> ---
>>  include/sysemu/kvm.h |  2 +-
>>  target/arm/kvm.c     |  2 ++
>>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 37 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
>> index 3a458f5..90c1605 100644
>> --- a/include/sysemu/kvm.h
>> +++ b/include/sysemu/kvm.h
>> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>>  
>> -#ifdef TARGET_I386
>> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
>>  #define KVM_HAVE_MCE_INJECTION 1
>>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>>  #endif
>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>> index 7c17f0d..9d25f51 100644
>> --- a/target/arm/kvm.c
>> +++ b/target/arm/kvm.c
>> @@ -26,6 +26,7 @@
>>  #include "exec/address-spaces.h"
>>  #include "hw/boards.h"
>>  #include "qemu/log.h"
>> +#include "exec/ram_addr.h"
>>  
>>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>>      KVM_CAP_LAST_INFO
>> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>>  
>>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>>  
>> +    qemu_register_reset(kvm_unpoison_all, NULL);
>>      type_register_static(&host_arm_cpu_type_info);
>>  
>>      return 0;
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index c00450d..6955d85 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -27,6 +27,9 @@
>>  #include "kvm_arm.h"
>>  #include "internals.h"
>>  #include "hw/arm/arm.h"
>> +#include "exec/ram_addr.h"
>> +#include "hw/acpi/acpi-defs.h"
>> +#include "hw/acpi/hest_ghes.h"
>>  
>>  static bool have_guest_debug;
>>  
>> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>>      return ret;
>>  }
>>  
>> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>> +{
>> +    ram_addr_t ram_addr;
>> +    hwaddr paddr;
>> +
>> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
>> +    if (addr) {
>> +        ram_addr = qemu_ram_addr_from_host(addr);
>> +        if (ram_addr != RAM_ADDR_INVALID &&
>> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
>> +            kvm_hwpoison_page_add(ram_addr);
>> +            if (code == BUS_MCEERR_AR) {
>> +                kvm_cpu_synchronize_state(c);
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
>> +                kvm_inject_arm_sea(c);
>> +            } else if (code == BUS_MCEERR_AO) {
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
>> +                qemu_hardware_error_notify();
>> +            }
>> +            return;
>> +        }
>> +        fprintf(stderr, "Hardware memory error for memory used by "
>> +                "QEMU itself instead of guest system!\n");
> not quite sure what above message means,
When the memory error address belong to QEMU itself, not belong to guest OS.
it will print above message.

Above message means this memory error happens in QEMU application instead of guest OS.

> 
> also fprintf() probably shouldn't be used by new code.
how about we use error_report()? thanks

> 
>> +    }
>> +
>> +    if (code == BUS_MCEERR_AR) {
>> +        fprintf(stderr, "Hardware memory error!\n");
>> +        exit(1);
>> +    }
>> +}
>> +
>>  /* C6.6.29 BRK instruction */
>>  static const uint32_t brk_insn = 0xd4200000;
>>  
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 1/9] ACPI: add some GHES structures and macros definition
  2017-12-28 12:29     ` [Qemu-devel] " Igor Mammedov
@ 2018-01-03 10:29       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03 10:29 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Igor,
   sorry for my late response due to chines new year holiday.

On 2017/12/28 20:29, Igor Mammedov wrote:
>> +enum AcpiHestNotifyType {
>> +    ACPI_HEST_NOTIFY_POLLED = 0,
>> +    ACPI_HEST_NOTIFY_EXTERNAL = 1,
>> +    ACPI_HEST_NOTIFY_LOCAL = 2,
>> +    ACPI_HEST_NOTIFY_SCI = 3,
>> +    ACPI_HEST_NOTIFY_NMI = 4,
>> +    ACPI_HEST_NOTIFY_CMCI = 5,  /* ACPI 5.0 */
> for stuff coming from spec comment should be something like this
> /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */
> 
> i.e. concrete version, chapter/table
> otherwise it could be hard to find definition in huge spec 
Ok, got it. I am modifying it.
Appreciated for your detailed comments.
sure, it needs to be updated.

> 
>> +    ACPI_HEST_NOTIFY_MCE = 6,   /* ACPI 5.0 */
>> +    ACPI_HEST_NOTIFY_GPIO = 7,  /* ACPI 6.0 */
>> +    ACPI_HEST_NOTIFY_SEA = 8,   /* ACPI 6.1 */

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 1/9] ACPI: add some GHES structures and macros definition
@ 2018-01-03 10:29       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-03 10:29 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

Igor,
   sorry for my late response due to chines new year holiday.

On 2017/12/28 20:29, Igor Mammedov wrote:
>> +enum AcpiHestNotifyType {
>> +    ACPI_HEST_NOTIFY_POLLED = 0,
>> +    ACPI_HEST_NOTIFY_EXTERNAL = 1,
>> +    ACPI_HEST_NOTIFY_LOCAL = 2,
>> +    ACPI_HEST_NOTIFY_SCI = 3,
>> +    ACPI_HEST_NOTIFY_NMI = 4,
>> +    ACPI_HEST_NOTIFY_CMCI = 5,  /* ACPI 5.0 */
> for stuff coming from spec comment should be something like this
> /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */
> 
> i.e. concrete version, chapter/table
> otherwise it could be hard to find definition in huge spec 
Ok, got it. I am modifying it.
Appreciated for your detailed comments.
sure, it needs to be updated.

> 
>> +    ACPI_HEST_NOTIFY_MCE = 6,   /* ACPI 5.0 */
>> +    ACPI_HEST_NOTIFY_GPIO = 7,  /* ACPI 6.0 */
>> +    ACPI_HEST_NOTIFY_SEA = 8,   /* ACPI 6.1 */

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2018-01-03  2:21       ` [Qemu-devel] " gengdongjiu
@ 2018-01-03 13:31         ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2018-01-03 13:31 UTC (permalink / raw)
  To: gengdongjiu
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Wed, 3 Jan 2018 10:21:06 +0800
gengdongjiu <gengdongjiu@huawei.com> wrote:

[...]   
> >   
> >> In order to simulation, we hard code the error
> >> type to Multi-bit ECC.  
> > Not sure what this is about, care to elaborate?  
> 
> please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
> error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
> error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
> the error type to Multi-bit ECC.
Agreed that in case of TCG qemu won't likely have any way to get hw error from kernel
so it could be useful only for testing purposes (i.e. 'make check' and/or testing
how guest OS handles errors)

But with KVM in kernel it should be possible to fish error out from host kernel
and forward it to guest. If this are intended for handling HW errors,
I'm not sure that 'Multi-bit ECC' could replace all real errors reported by host
firmware.


> [1]:
> UEFI Spec 2.6 Errata A:
> 
> "N.2.5 Memory Error Section"
> -----------------+---------------+--------------+-------------------------------------------+
>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+
> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
> 		 |		 |		| 0 – Unknown                              |
> 		 |		 |		| 1 – No error                             |
> 		 |		 |		| 2 – Single-bit ECC                       |
> 		 |		 |		| 3 – Multi-bit ECC                        |
> 		 |		 |		| 4 – Single-symbol ChipKill ECC           |
> 		 |		 |		| 5 – Multi-symbol ChipKill ECC            |
> 		 |		 |		| 6 – Master abort			    |
> 		 |		 |		| 7 – Target abort			    |
> 		 |		 |		| 8 – Parity Error			    |
> 		 |		 |		| 9 – Watchdog timeout			    |
> 		 |		 |		| 10 – Invalid address			    |
> 		 |		 |		| 11 – Mirror Broken			    |
> 		 |		 |		| 12 – Memory Sparing			    |
> 		 |		 |		| 13 - Scrub corrected error		    |
> 		 |		 |		| 14 - Scrub uncorrected error		    |
> 		 |		 |		| 15 - Physical Memory Map-out event	    |
> 		 |		 |		| All other values reserved.		    |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+
[...]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2018-01-03 13:31         ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2018-01-03 13:31 UTC (permalink / raw)
  To: gengdongjiu
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Wed, 3 Jan 2018 10:21:06 +0800
gengdongjiu <gengdongjiu@huawei.com> wrote:

[...]   
> >   
> >> In order to simulation, we hard code the error
> >> type to Multi-bit ECC.  
> > Not sure what this is about, care to elaborate?  
> 
> please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
> error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
> error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
> the error type to Multi-bit ECC.
Agreed that in case of TCG qemu won't likely have any way to get hw error from kernel
so it could be useful only for testing purposes (i.e. 'make check' and/or testing
how guest OS handles errors)

But with KVM in kernel it should be possible to fish error out from host kernel
and forward it to guest. If this are intended for handling HW errors,
I'm not sure that 'Multi-bit ECC' could replace all real errors reported by host
firmware.


> [1]:
> UEFI Spec 2.6 Errata A:
> 
> "N.2.5 Memory Error Section"
> -----------------+---------------+--------------+-------------------------------------------+
>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+
> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
> 		 |		 |		| 0 – Unknown                              |
> 		 |		 |		| 1 – No error                             |
> 		 |		 |		| 2 – Single-bit ECC                       |
> 		 |		 |		| 3 – Multi-bit ECC                        |
> 		 |		 |		| 4 – Single-symbol ChipKill ECC           |
> 		 |		 |		| 5 – Multi-symbol ChipKill ECC            |
> 		 |		 |		| 6 – Master abort			    |
> 		 |		 |		| 7 – Target abort			    |
> 		 |		 |		| 8 – Parity Error			    |
> 		 |		 |		| 9 – Watchdog timeout			    |
> 		 |		 |		| 10 – Invalid address			    |
> 		 |		 |		| 11 – Mirror Broken			    |
> 		 |		 |		| 12 – Memory Sparing			    |
> 		 |		 |		| 13 - Scrub corrected error		    |
> 		 |		 |		| 14 - Scrub uncorrected error		    |
> 		 |		 |		| 15 - Physical Memory Map-out event	    |
> 		 |		 |		| All other values reserved.		    |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+
[...]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
  2018-01-03  3:48       ` [Qemu-devel] " gengdongjiu
@ 2018-01-03 13:36         ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2018-01-03 13:36 UTC (permalink / raw)
  To: gengdongjiu
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Wed, 3 Jan 2018 11:48:30 +0800
gengdongjiu <gengdongjiu@huawei.com> wrote:

> On 2017/12/28 22:53, Igor Mammedov wrote:
> > On Thu, 28 Dec 2017 13:54:16 +0800
> > Dongjiu Geng <gengdongjiu@huawei.com> wrote:
[...]
> >> +static void acpi_dsdt_add_error_device(Aml *scope)
> >> +{
> >> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
> >> +    Aml *method;
> >> +
> >> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
> >> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> >> +
> >> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> >> +    aml_append(method, aml_return(aml_int(0x0f)));  
> > no need for dummy _STA method, device is assumed to be present if there is no _STA   
> Igor,
>   do you mean remove above two line code as shown in [1]?
> I dump the DSDT table in my host Ubuntu PC for the error device (PNP0C33), it has the _STA, as shown in [2].
> do we not want to add the _STA for guest?
> 
> [1]
> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_return(aml_int(0x0f)));
compared to host, yours method does nothing,
read ACPI6.2 "6.3.7 _STA (Status)" one more time

> [2]:
>         Device (WERR)
>         {
>             Name (_HID, EisaId ("PNP0C33"))  // _HID: Hardware ID
>             Method (_STA, 0, NotSerialized)  // _STA: Status
>             {
>                 If (LGreaterEqual (OSYS, 0x07D9))
>                 {
>                     Return (0x0F)
>                 }
>                 Else
>                 {
>                     Return (Zero)
>                 }
>             }
>         }
> >   
> >> +    aml_append(dev, method);
> >> +    aml_append(scope, dev);
> >> +}
> >> +
[...]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
@ 2018-01-03 13:36         ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2018-01-03 13:36 UTC (permalink / raw)
  To: gengdongjiu
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Wed, 3 Jan 2018 11:48:30 +0800
gengdongjiu <gengdongjiu@huawei.com> wrote:

> On 2017/12/28 22:53, Igor Mammedov wrote:
> > On Thu, 28 Dec 2017 13:54:16 +0800
> > Dongjiu Geng <gengdongjiu@huawei.com> wrote:
[...]
> >> +static void acpi_dsdt_add_error_device(Aml *scope)
> >> +{
> >> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
> >> +    Aml *method;
> >> +
> >> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
> >> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> >> +
> >> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> >> +    aml_append(method, aml_return(aml_int(0x0f)));  
> > no need for dummy _STA method, device is assumed to be present if there is no _STA   
> Igor,
>   do you mean remove above two line code as shown in [1]?
> I dump the DSDT table in my host Ubuntu PC for the error device (PNP0C33), it has the _STA, as shown in [2].
> do we not want to add the _STA for guest?
> 
> [1]
> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_return(aml_int(0x0f)));
compared to host, yours method does nothing,
read ACPI6.2 "6.3.7 _STA (Status)" one more time

> [2]:
>         Device (WERR)
>         {
>             Name (_HID, EisaId ("PNP0C33"))  // _HID: Hardware ID
>             Method (_STA, 0, NotSerialized)  // _STA: Status
>             {
>                 If (LGreaterEqual (OSYS, 0x07D9))
>                 {
>                     Return (0x0F)
>                 }
>                 Else
>                 {
>                     Return (Zero)
>                 }
>             }
>         }
> >   
> >> +    aml_append(dev, method);
> >> +    aml_append(scope, dev);
> >> +}
> >> +
[...]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2018-01-03  9:13       ` [Qemu-devel] " gengdongjiu
@ 2018-01-03 13:44         ` Igor Mammedov
  -1 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2018-01-03 13:44 UTC (permalink / raw)
  To: gengdongjiu
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Wed, 3 Jan 2018 17:13:45 +0800
gengdongjiu <gengdongjiu@huawei.com> wrote:

> On 2017/12/28 23:07, Igor Mammedov wrote:
> > On Thu, 28 Dec 2017 13:54:18 +0800
> > Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> >   
> >> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
> >> translates the host VA which is delivered by host to guest PA, then fill
> >> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
> >> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
> >> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
> >>
> >> If guest accesses the poisoned memory, it generates Synchronous External
> >> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
> >> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO  
> > s/unmapped/unmap/  
> Thanks.
> 
> >   
> >> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
> >> create a new CPER and add it to guest APEI GHES memory, then notify the
> >> guest with a GPIO-Signal notification.  
> > too long sentence, it's hard get what goes on here, pls split it in simple
> > sentences/rephrase so it would be easy to understand behavior.  
> I will split it in simple sentences/rephrase.
> Thanks for your detailed review.
> 
> >   
> >>
> >> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
> >> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
> >> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
> >>
> >> Suggested-by: James Morse <james.morse@arm.com>
> >> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> >> ---
> >> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
> >> Shown some discussion in [1].
> >>
> >> [1]:
> >> https://lkml.org/lkml/2017/2/27/246
> >> https://lkml.org/lkml/2017/9/14/241
> >> https://lkml.org/lkml/2017/9/22/499
> >> ---
> >>  include/sysemu/kvm.h |  2 +-
> >>  target/arm/kvm.c     |  2 ++
> >>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
> >>  3 files changed, 37 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> >> index 3a458f5..90c1605 100644
> >> --- a/include/sysemu/kvm.h
> >> +++ b/include/sysemu/kvm.h
> >> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
> >>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
> >>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
> >>  
> >> -#ifdef TARGET_I386
> >> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
> >>  #define KVM_HAVE_MCE_INJECTION 1
> >>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
> >>  #endif
> >> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> >> index 7c17f0d..9d25f51 100644
> >> --- a/target/arm/kvm.c
> >> +++ b/target/arm/kvm.c
> >> @@ -26,6 +26,7 @@
> >>  #include "exec/address-spaces.h"
> >>  #include "hw/boards.h"
> >>  #include "qemu/log.h"
> >> +#include "exec/ram_addr.h"
> >>  
> >>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
> >>      KVM_CAP_LAST_INFO
> >> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
> >>  
> >>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
> >>  
> >> +    qemu_register_reset(kvm_unpoison_all, NULL);
> >>      type_register_static(&host_arm_cpu_type_info);
> >>  
> >>      return 0;
> >> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> >> index c00450d..6955d85 100644
> >> --- a/target/arm/kvm64.c
> >> +++ b/target/arm/kvm64.c
> >> @@ -27,6 +27,9 @@
> >>  #include "kvm_arm.h"
> >>  #include "internals.h"
> >>  #include "hw/arm/arm.h"
> >> +#include "exec/ram_addr.h"
> >> +#include "hw/acpi/acpi-defs.h"
> >> +#include "hw/acpi/hest_ghes.h"
> >>  
> >>  static bool have_guest_debug;
> >>  
> >> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
> >>      return ret;
> >>  }
> >>  
> >> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
> >> +{
> >> +    ram_addr_t ram_addr;
> >> +    hwaddr paddr;
> >> +
> >> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> >> +    if (addr) {
> >> +        ram_addr = qemu_ram_addr_from_host(addr);
> >> +        if (ram_addr != RAM_ADDR_INVALID &&
> >> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> >> +            kvm_hwpoison_page_add(ram_addr);
> >> +            if (code == BUS_MCEERR_AR) {
> >> +                kvm_cpu_synchronize_state(c);
> >> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
> >> +                kvm_inject_arm_sea(c);
> >> +            } else if (code == BUS_MCEERR_AO) {
> >> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
> >> +                qemu_hardware_error_notify();
> >> +            }
> >> +            return;
> >> +        }
> >> +        fprintf(stderr, "Hardware memory error for memory used by "
> >> +                "QEMU itself instead of guest system!\n");  
> > not quite sure what above message means,  
> When the memory error address belong to QEMU itself, not belong to guest OS.
> it will print above message.
> 
> Above message means this memory error happens in QEMU application instead of guest OS.
I'm not really understand what's going here and how it could happen,
so I can't suggest something. Perhaps someone else could comment on it.
 
> > also fprintf() probably shouldn't be used by new code.  
> how about we use error_report()? thanks
I'm not sure what current trend is, but I'd use error_report() vs fprintf()

Also series could benefit from trace-points (I haven't noticed any).

> >   
> >> +    }
> >> +
> >> +    if (code == BUS_MCEERR_AR) {
> >> +        fprintf(stderr, "Hardware memory error!\n");
> >> +        exit(1);
> >> +    }
> >> +}
> >> +
> >>  /* C6.6.29 BRK instruction */
> >>  static const uint32_t brk_insn = 0xd4200000;
> >>    
> > 
> > 
> > .
> >   
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2018-01-03 13:44         ` Igor Mammedov
  0 siblings, 0 replies; 83+ messages in thread
From: Igor Mammedov @ 2018-01-03 13:44 UTC (permalink / raw)
  To: gengdongjiu
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On Wed, 3 Jan 2018 17:13:45 +0800
gengdongjiu <gengdongjiu@huawei.com> wrote:

> On 2017/12/28 23:07, Igor Mammedov wrote:
> > On Thu, 28 Dec 2017 13:54:18 +0800
> > Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> >   
> >> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
> >> translates the host VA which is delivered by host to guest PA, then fill
> >> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
> >> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
> >> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
> >>
> >> If guest accesses the poisoned memory, it generates Synchronous External
> >> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
> >> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO  
> > s/unmapped/unmap/  
> Thanks.
> 
> >   
> >> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
> >> create a new CPER and add it to guest APEI GHES memory, then notify the
> >> guest with a GPIO-Signal notification.  
> > too long sentence, it's hard get what goes on here, pls split it in simple
> > sentences/rephrase so it would be easy to understand behavior.  
> I will split it in simple sentences/rephrase.
> Thanks for your detailed review.
> 
> >   
> >>
> >> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
> >> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
> >> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
> >>
> >> Suggested-by: James Morse <james.morse@arm.com>
> >> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> >> ---
> >> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
> >> Shown some discussion in [1].
> >>
> >> [1]:
> >> https://lkml.org/lkml/2017/2/27/246
> >> https://lkml.org/lkml/2017/9/14/241
> >> https://lkml.org/lkml/2017/9/22/499
> >> ---
> >>  include/sysemu/kvm.h |  2 +-
> >>  target/arm/kvm.c     |  2 ++
> >>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
> >>  3 files changed, 37 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> >> index 3a458f5..90c1605 100644
> >> --- a/include/sysemu/kvm.h
> >> +++ b/include/sysemu/kvm.h
> >> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
> >>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
> >>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
> >>  
> >> -#ifdef TARGET_I386
> >> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
> >>  #define KVM_HAVE_MCE_INJECTION 1
> >>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
> >>  #endif
> >> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> >> index 7c17f0d..9d25f51 100644
> >> --- a/target/arm/kvm.c
> >> +++ b/target/arm/kvm.c
> >> @@ -26,6 +26,7 @@
> >>  #include "exec/address-spaces.h"
> >>  #include "hw/boards.h"
> >>  #include "qemu/log.h"
> >> +#include "exec/ram_addr.h"
> >>  
> >>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
> >>      KVM_CAP_LAST_INFO
> >> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
> >>  
> >>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
> >>  
> >> +    qemu_register_reset(kvm_unpoison_all, NULL);
> >>      type_register_static(&host_arm_cpu_type_info);
> >>  
> >>      return 0;
> >> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> >> index c00450d..6955d85 100644
> >> --- a/target/arm/kvm64.c
> >> +++ b/target/arm/kvm64.c
> >> @@ -27,6 +27,9 @@
> >>  #include "kvm_arm.h"
> >>  #include "internals.h"
> >>  #include "hw/arm/arm.h"
> >> +#include "exec/ram_addr.h"
> >> +#include "hw/acpi/acpi-defs.h"
> >> +#include "hw/acpi/hest_ghes.h"
> >>  
> >>  static bool have_guest_debug;
> >>  
> >> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
> >>      return ret;
> >>  }
> >>  
> >> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
> >> +{
> >> +    ram_addr_t ram_addr;
> >> +    hwaddr paddr;
> >> +
> >> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> >> +    if (addr) {
> >> +        ram_addr = qemu_ram_addr_from_host(addr);
> >> +        if (ram_addr != RAM_ADDR_INVALID &&
> >> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> >> +            kvm_hwpoison_page_add(ram_addr);
> >> +            if (code == BUS_MCEERR_AR) {
> >> +                kvm_cpu_synchronize_state(c);
> >> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
> >> +                kvm_inject_arm_sea(c);
> >> +            } else if (code == BUS_MCEERR_AO) {
> >> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
> >> +                qemu_hardware_error_notify();
> >> +            }
> >> +            return;
> >> +        }
> >> +        fprintf(stderr, "Hardware memory error for memory used by "
> >> +                "QEMU itself instead of guest system!\n");  
> > not quite sure what above message means,  
> When the memory error address belong to QEMU itself, not belong to guest OS.
> it will print above message.
> 
> Above message means this memory error happens in QEMU application instead of guest OS.
I'm not really understand what's going here and how it could happen,
so I can't suggest something. Perhaps someone else could comment on it.
 
> > also fprintf() probably shouldn't be used by new code.  
> how about we use error_report()? thanks
I'm not sure what current trend is, but I'd use error_report() vs fprintf()

Also series could benefit from trace-points (I haven't noticed any).

> >   
> >> +    }
> >> +
> >> +    if (code == BUS_MCEERR_AR) {
> >> +        fprintf(stderr, "Hardware memory error!\n");
> >> +        exit(1);
> >> +    }
> >> +}
> >> +
> >>  /* C6.6.29 BRK instruction */
> >>  static const uint32_t brk_insn = 0xd4200000;
> >>    
> > 
> > 
> > .
> >   
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2018-01-03 13:31         ` [Qemu-devel] " Igor Mammedov
@ 2018-01-04  4:21           ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-04  4:21 UTC (permalink / raw)
  To: Igor Mammedov, James Morse
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, christoffer.dall, marc.zyngier, kvm, qemu-devel,
	qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On 2018/1/3 21:31, Igor Mammedov wrote:
> On Wed, 3 Jan 2018 10:21:06 +0800
> gengdongjiu <gengdongjiu@huawei.com> wrote:
> 
> [...]   
>>>   
>>>> In order to simulation, we hard code the error
>>>> type to Multi-bit ECC.  
>>> Not sure what this is about, care to elaborate?  
>>
>> please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
>> error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
>> error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
>> the error type to Multi-bit ECC.
> Agreed that in case of TCG qemu won't likely have any way to get hw error from kernel
> so it could be useful only for testing purposes (i.e. 'make check' and/or testing
> how guest OS handles errors)
> 
> But with KVM in kernel it should be possible to fish error out from host kernel
> and forward it to guest. If this are intended for handling HW errors,
> I'm not sure that 'Multi-bit ECC' could replace all real errors reported by host
> firmware.
Thanks for the mail.
I understand your meaning, I explain it more.

(1). In fact the Memory Error type is not important to guest OS, when the OS(such as guest OS) do memory recovery,
it does not uses the memory error type, OS(such as guest OS) mainly uses the memory_failure() function[1] to do recovery ,
In this function, it does not care what is the memory error type, It even does not know what is the memory error type.
(2). If KVM forward the error type to guest, it needs more efforts, may be not worth to do. The real memory error type exists in host
APEI table, only host APEI driver can get it, KVM can not directly get it. If forward it to guest, KVM needs to firstly get the error
type from APEI driver and forward it to guest, which may be opposed by James(james.morse@arm.com), I ever export more error information
to guest, but James does not agree that. In the ARM64 platform, we do not have implementation to get the error information from the
APEI driver to KVM or to other kernel modules.


[1]:
int memory_failure(unsigned long pfn, int trapno, int flags)
{
  ......
 }

> 
> 
>> [1]:
>> UEFI Spec 2.6 Errata A:
>>
>> "N.2.5 Memory Error Section"
>> -----------------+---------------+--------------+-------------------------------------------+
>>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
>> 		 |		 |		| 0 – Unknown                              |
>> 		 |		 |		| 1 – No error                             |
>> 		 |		 |		| 2 – Single-bit ECC                       |
>> 		 |		 |		| 3 – Multi-bit ECC                        |
>> 		 |		 |		| 4 – Single-symbol ChipKill ECC           |
>> 		 |		 |		| 5 – Multi-symbol ChipKill ECC            |
>> 		 |		 |		| 6 – Master abort			    |
>> 		 |		 |		| 7 – Target abort			    |
>> 		 |		 |		| 8 – Parity Error			    |
>> 		 |		 |		| 9 – Watchdog timeout			    |
>> 		 |		 |		| 10 – Invalid address			    |
>> 		 |		 |		| 11 – Mirror Broken			    |
>> 		 |		 |		| 12 – Memory Sparing			    |
>> 		 |		 |		| 13 - Scrub corrected error		    |
>> 		 |		 |		| 14 - Scrub uncorrected error		    |
>> 		 |		 |		| 15 - Physical Memory Map-out event	    |
>> 		 |		 |		| All other values reserved.		    |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
> [...]
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2018-01-04  4:21           ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-04  4:21 UTC (permalink / raw)
  To: Igor Mammedov, James Morse
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, christoffer.dall, marc.zyngier, kvm, qemu-devel,
	qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On 2018/1/3 21:31, Igor Mammedov wrote:
> On Wed, 3 Jan 2018 10:21:06 +0800
> gengdongjiu <gengdongjiu@huawei.com> wrote:
> 
> [...]   
>>>   
>>>> In order to simulation, we hard code the error
>>>> type to Multi-bit ECC.  
>>> Not sure what this is about, care to elaborate?  
>>
>> please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
>> error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
>> error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
>> the error type to Multi-bit ECC.
> Agreed that in case of TCG qemu won't likely have any way to get hw error from kernel
> so it could be useful only for testing purposes (i.e. 'make check' and/or testing
> how guest OS handles errors)
> 
> But with KVM in kernel it should be possible to fish error out from host kernel
> and forward it to guest. If this are intended for handling HW errors,
> I'm not sure that 'Multi-bit ECC' could replace all real errors reported by host
> firmware.
Thanks for the mail.
I understand your meaning, I explain it more.

(1). In fact the Memory Error type is not important to guest OS, when the OS(such as guest OS) do memory recovery,
it does not uses the memory error type, OS(such as guest OS) mainly uses the memory_failure() function[1] to do recovery ,
In this function, it does not care what is the memory error type, It even does not know what is the memory error type.
(2). If KVM forward the error type to guest, it needs more efforts, may be not worth to do. The real memory error type exists in host
APEI table, only host APEI driver can get it, KVM can not directly get it. If forward it to guest, KVM needs to firstly get the error
type from APEI driver and forward it to guest, which may be opposed by James(james.morse@arm.com), I ever export more error information
to guest, but James does not agree that. In the ARM64 platform, we do not have implementation to get the error information from the
APEI driver to KVM or to other kernel modules.


[1]:
int memory_failure(unsigned long pfn, int trapno, int flags)
{
  ......
 }

> 
> 
>> [1]:
>> UEFI Spec 2.6 Errata A:
>>
>> "N.2.5 Memory Error Section"
>> -----------------+---------------+--------------+-------------------------------------------+
>>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
>> 		 |		 |		| 0 – Unknown                              |
>> 		 |		 |		| 1 – No error                             |
>> 		 |		 |		| 2 – Single-bit ECC                       |
>> 		 |		 |		| 3 – Multi-bit ECC                        |
>> 		 |		 |		| 4 – Single-symbol ChipKill ECC           |
>> 		 |		 |		| 5 – Multi-symbol ChipKill ECC            |
>> 		 |		 |		| 6 – Master abort			    |
>> 		 |		 |		| 7 – Target abort			    |
>> 		 |		 |		| 8 – Parity Error			    |
>> 		 |		 |		| 9 – Watchdog timeout			    |
>> 		 |		 |		| 10 – Invalid address			    |
>> 		 |		 |		| 11 – Mirror Broken			    |
>> 		 |		 |		| 12 – Memory Sparing			    |
>> 		 |		 |		| 13 - Scrub corrected error		    |
>> 		 |		 |		| 14 - Scrub uncorrected error		    |
>> 		 |		 |		| 15 - Physical Memory Map-out event	    |
>> 		 |		 |		| All other values reserved.		    |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
> [...]
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error
  2018-01-03 13:36         ` [Qemu-devel] " Igor Mammedov
  (?)
@ 2018-01-04  4:55         ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-04  4:55 UTC (permalink / raw)
  To: qemu-devel

On 2018/1/3 21:36, Igor Mammedov wrote:
> On Wed, 3 Jan 2018 11:48:30 +0800
> gengdongjiu <gengdongjiu@huawei.com> wrote:
> 
>> On 2017/12/28 22:53, Igor Mammedov wrote:
>>> On Thu, 28 Dec 2017 13:54:16 +0800
>>> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> [...]
>>>> +static void acpi_dsdt_add_error_device(Aml *scope)
>>>> +{
>>>> +    Aml *dev = aml_device(ACPI_HARDWARE_ERROR_DEVICE);
>>>> +    Aml *method;
>>>> +
>>>> +    aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C33")));
>>>> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
>>>> +
>>>> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>>>> +    aml_append(method, aml_return(aml_int(0x0f)));  
>>> no need for dummy _STA method, device is assumed to be present if there is no _STA   
>> Igor,
>>   do you mean remove above two line code as shown in [1]?
>> I dump the DSDT table in my host Ubuntu PC for the error device (PNP0C33), it has the _STA, as shown in [2].
>> do we not want to add the _STA for guest?
>>
>> [1]
>> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>> +    aml_append(method, aml_return(aml_int(0x0f)));
> compared to host, yours method does nothing,
> read ACPI6.2 "6.3.7 _STA (Status)" one more time
Thanks for the pointing out.
yes, you are right. As the spec statement[1], Device is assumed to be present if there is no _STA.

[1]:
ACPI6.2 "6.3.7 _STA (Status), Return Value Information"
If a device object (including the processor object) does not have an _STA object, then OSPM
assumes that all of the above bits are set (i.e., the device is present, enabled, shown in the UI,
and functioning).

> 
>> [2]:
>>         Device (WERR)
>>         {
>>             Name (_HID, EisaId ("PNP0C33"))  // _HID: Hardware ID
>>             Method (_STA, 0, NotSerialized)  // _STA: Status
>>             {
>>                 If (LGreaterEqual (OSYS, 0x07D9))
>>                 {
>>                     Return (0x0F)
>>                 }
>>                 Else
>>                 {
>>                     Return (Zero)
>>                 }
>>             }
>>         }
>>>   
>>>> +    aml_append(dev, method);
>>>> +    aml_append(scope, dev);
>>>> +}
>>>> +
> [...]
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2018-01-03 13:44         ` [Qemu-devel] " Igor Mammedov
@ 2018-01-04  6:31           ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-04  6:31 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On 2018/1/3 21:44, Igor Mammedov wrote:
> On Wed, 3 Jan 2018 17:13:45 +0800
> gengdongjiu <gengdongjiu@huawei.com> wrote:
> 
>> On 2017/12/28 23:07, Igor Mammedov wrote:
>>> On Thu, 28 Dec 2017 13:54:18 +0800
>>> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>>>   
>>>> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
>>>> translates the host VA which is delivered by host to guest PA, then fill
>>>> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
>>>> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
>>>> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>>>>
>>>> If guest accesses the poisoned memory, it generates Synchronous External
>>>> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
>>>> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO  
>>> s/unmapped/unmap/  
>> Thanks.
>>
>>>   
>>>> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
>>>> create a new CPER and add it to guest APEI GHES memory, then notify the
>>>> guest with a GPIO-Signal notification.  
>>> too long sentence, it's hard get what goes on here, pls split it in simple
>>> sentences/rephrase so it would be easy to understand behavior.  
>> I will split it in simple sentences/rephrase.
>> Thanks for your detailed review.
>>
>>>   
>>>>
>>>> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
>>>> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
>>>> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>>>>
>>>> Suggested-by: James Morse <james.morse@arm.com>
>>>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>>>> ---
>>>> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
>>>> Shown some discussion in [1].
>>>>
>>>> [1]:
>>>> https://lkml.org/lkml/2017/2/27/246
>>>> https://lkml.org/lkml/2017/9/14/241
>>>> https://lkml.org/lkml/2017/9/22/499
>>>> ---
>>>>  include/sysemu/kvm.h |  2 +-
>>>>  target/arm/kvm.c     |  2 ++
>>>>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 37 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
>>>> index 3a458f5..90c1605 100644
>>>> --- a/include/sysemu/kvm.h
>>>> +++ b/include/sysemu/kvm.h
>>>> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>>>>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>>>>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>>>>  
>>>> -#ifdef TARGET_I386
>>>> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
>>>>  #define KVM_HAVE_MCE_INJECTION 1
>>>>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>>>>  #endif
>>>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>>>> index 7c17f0d..9d25f51 100644
>>>> --- a/target/arm/kvm.c
>>>> +++ b/target/arm/kvm.c
>>>> @@ -26,6 +26,7 @@
>>>>  #include "exec/address-spaces.h"
>>>>  #include "hw/boards.h"
>>>>  #include "qemu/log.h"
>>>> +#include "exec/ram_addr.h"
>>>>  
>>>>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>>>>      KVM_CAP_LAST_INFO
>>>> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>>>>  
>>>>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>>>>  
>>>> +    qemu_register_reset(kvm_unpoison_all, NULL);
>>>>      type_register_static(&host_arm_cpu_type_info);
>>>>  
>>>>      return 0;
>>>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>>>> index c00450d..6955d85 100644
>>>> --- a/target/arm/kvm64.c
>>>> +++ b/target/arm/kvm64.c
>>>> @@ -27,6 +27,9 @@
>>>>  #include "kvm_arm.h"
>>>>  #include "internals.h"
>>>>  #include "hw/arm/arm.h"
>>>> +#include "exec/ram_addr.h"
>>>> +#include "hw/acpi/acpi-defs.h"
>>>> +#include "hw/acpi/hest_ghes.h"
>>>>  
>>>>  static bool have_guest_debug;
>>>>  
>>>> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>>>>      return ret;
>>>>  }
>>>>  
>>>> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>>>> +{
>>>> +    ram_addr_t ram_addr;
>>>> +    hwaddr paddr;
>>>> +
>>>> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
>>>> +    if (addr) {
>>>> +        ram_addr = qemu_ram_addr_from_host(addr);
>>>> +        if (ram_addr != RAM_ADDR_INVALID &&
>>>> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
>>>> +            kvm_hwpoison_page_add(ram_addr);
>>>> +            if (code == BUS_MCEERR_AR) {
>>>> +                kvm_cpu_synchronize_state(c);
>>>> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
>>>> +                kvm_inject_arm_sea(c);
>>>> +            } else if (code == BUS_MCEERR_AO) {
>>>> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
>>>> +                qemu_hardware_error_notify();
>>>> +            }
>>>> +            return;
>>>> +        }
>>>> +        fprintf(stderr, "Hardware memory error for memory used by "
>>>> +                "QEMU itself instead of guest system!\n");  
>>> not quite sure what above message means,  
>> When the memory error address belong to QEMU itself, not belong to guest OS.
>> it will print above message.
>>
>> Above message means this memory error happens in QEMU application instead of guest OS.
> I'm not really understand what's going here and how it could happen,

Thanks, sorry for your confusion. I make a example:

As a general application, when QEMU does not run guest, if Qemu's thread touch a poison user space
memory, it will trap to host kernel, host kernel will call memory error handler(memory_failure())
to handle this error access, kernel memory error handler will deliver SIGBUS to QEMU, in this
process, KVM and guest are not involved. Because this address is not belong to guest(not match 'if'
condition in[1]), so it go to here and print above message.

[1]:
        if (ram_addr != RAM_ADDR_INVALID &&
             kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
	          .......
	     return;
         }
         fprintf(stderr, "Hardware memory error for memory used by "
                 "QEMU itself instead of guest system!\n");

> so I can't suggest something. Perhaps someone else could comment on it.
>  
>>> also fprintf() probably shouldn't be used by new code.  
>> how about we use error_report()? thanks
> I'm not sure what current trend is, but I'd use error_report() vs fprintf()
> 
> Also series could benefit from trace-points (I haven't noticed any).
I will add some trace-points, thanks.

> 
>>>   
>>>> +    }
>>>> +
>>>> +    if (code == BUS_MCEERR_AR) {
>>>> +        fprintf(stderr, "Hardware memory error!\n");
>>>> +        exit(1);
>>>> +    }
>>>> +}
>>>> +
>>>>  /* C6.6.29 BRK instruction */
>>>>  static const uint32_t brk_insn = 0xd4200000;
>>>>    
>>>
>>>
>>> .
>>>   
>>
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2018-01-04  6:31           ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-04  6:31 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: pbonzini, mst, zhaoshenglong, peter.maydell, mtosatti, rth,
	ehabkost, james.morse, christoffer.dall, marc.zyngier, kvm,
	qemu-devel, qemu-arm, huangshaoyu, zhengqiang10, xuwei5

On 2018/1/3 21:44, Igor Mammedov wrote:
> On Wed, 3 Jan 2018 17:13:45 +0800
> gengdongjiu <gengdongjiu@huawei.com> wrote:
> 
>> On 2017/12/28 23:07, Igor Mammedov wrote:
>>> On Thu, 28 Dec 2017 13:54:18 +0800
>>> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>>>   
>>>> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
>>>> translates the host VA which is delivered by host to guest PA, then fill
>>>> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
>>>> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
>>>> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>>>>
>>>> If guest accesses the poisoned memory, it generates Synchronous External
>>>> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
>>>> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO  
>>> s/unmapped/unmap/  
>> Thanks.
>>
>>>   
>>>> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
>>>> create a new CPER and add it to guest APEI GHES memory, then notify the
>>>> guest with a GPIO-Signal notification.  
>>> too long sentence, it's hard get what goes on here, pls split it in simple
>>> sentences/rephrase so it would be easy to understand behavior.  
>> I will split it in simple sentences/rephrase.
>> Thanks for your detailed review.
>>
>>>   
>>>>
>>>> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
>>>> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
>>>> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>>>>
>>>> Suggested-by: James Morse <james.morse@arm.com>
>>>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>>>> ---
>>>> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
>>>> Shown some discussion in [1].
>>>>
>>>> [1]:
>>>> https://lkml.org/lkml/2017/2/27/246
>>>> https://lkml.org/lkml/2017/9/14/241
>>>> https://lkml.org/lkml/2017/9/22/499
>>>> ---
>>>>  include/sysemu/kvm.h |  2 +-
>>>>  target/arm/kvm.c     |  2 ++
>>>>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 37 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
>>>> index 3a458f5..90c1605 100644
>>>> --- a/include/sysemu/kvm.h
>>>> +++ b/include/sysemu/kvm.h
>>>> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>>>>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>>>>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>>>>  
>>>> -#ifdef TARGET_I386
>>>> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
>>>>  #define KVM_HAVE_MCE_INJECTION 1
>>>>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>>>>  #endif
>>>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>>>> index 7c17f0d..9d25f51 100644
>>>> --- a/target/arm/kvm.c
>>>> +++ b/target/arm/kvm.c
>>>> @@ -26,6 +26,7 @@
>>>>  #include "exec/address-spaces.h"
>>>>  #include "hw/boards.h"
>>>>  #include "qemu/log.h"
>>>> +#include "exec/ram_addr.h"
>>>>  
>>>>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>>>>      KVM_CAP_LAST_INFO
>>>> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>>>>  
>>>>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>>>>  
>>>> +    qemu_register_reset(kvm_unpoison_all, NULL);
>>>>      type_register_static(&host_arm_cpu_type_info);
>>>>  
>>>>      return 0;
>>>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>>>> index c00450d..6955d85 100644
>>>> --- a/target/arm/kvm64.c
>>>> +++ b/target/arm/kvm64.c
>>>> @@ -27,6 +27,9 @@
>>>>  #include "kvm_arm.h"
>>>>  #include "internals.h"
>>>>  #include "hw/arm/arm.h"
>>>> +#include "exec/ram_addr.h"
>>>> +#include "hw/acpi/acpi-defs.h"
>>>> +#include "hw/acpi/hest_ghes.h"
>>>>  
>>>>  static bool have_guest_debug;
>>>>  
>>>> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>>>>      return ret;
>>>>  }
>>>>  
>>>> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>>>> +{
>>>> +    ram_addr_t ram_addr;
>>>> +    hwaddr paddr;
>>>> +
>>>> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
>>>> +    if (addr) {
>>>> +        ram_addr = qemu_ram_addr_from_host(addr);
>>>> +        if (ram_addr != RAM_ADDR_INVALID &&
>>>> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
>>>> +            kvm_hwpoison_page_add(ram_addr);
>>>> +            if (code == BUS_MCEERR_AR) {
>>>> +                kvm_cpu_synchronize_state(c);
>>>> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
>>>> +                kvm_inject_arm_sea(c);
>>>> +            } else if (code == BUS_MCEERR_AO) {
>>>> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
>>>> +                qemu_hardware_error_notify();
>>>> +            }
>>>> +            return;
>>>> +        }
>>>> +        fprintf(stderr, "Hardware memory error for memory used by "
>>>> +                "QEMU itself instead of guest system!\n");  
>>> not quite sure what above message means,  
>> When the memory error address belong to QEMU itself, not belong to guest OS.
>> it will print above message.
>>
>> Above message means this memory error happens in QEMU application instead of guest OS.
> I'm not really understand what's going here and how it could happen,

Thanks, sorry for your confusion. I make a example:

As a general application, when QEMU does not run guest, if Qemu's thread touch a poison user space
memory, it will trap to host kernel, host kernel will call memory error handler(memory_failure())
to handle this error access, kernel memory error handler will deliver SIGBUS to QEMU, in this
process, KVM and guest are not involved. Because this address is not belong to guest(not match 'if'
condition in[1]), so it go to here and print above message.

[1]:
        if (ram_addr != RAM_ADDR_INVALID &&
             kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
	          .......
	     return;
         }
         fprintf(stderr, "Hardware memory error for memory used by "
                 "QEMU itself instead of guest system!\n");

> so I can't suggest something. Perhaps someone else could comment on it.
>  
>>> also fprintf() probably shouldn't be used by new code.  
>> how about we use error_report()? thanks
> I'm not sure what current trend is, but I'd use error_report() vs fprintf()
> 
> Also series could benefit from trace-points (I haven't noticed any).
I will add some trace-points, thanks.

> 
>>>   
>>>> +    }
>>>> +
>>>> +    if (code == BUS_MCEERR_AR) {
>>>> +        fprintf(stderr, "Hardware memory error!\n");
>>>> +        exit(1);
>>>> +    }
>>>> +}
>>>> +
>>>>  /* C6.6.29 BRK instruction */
>>>>  static const uint32_t brk_insn = 0xd4200000;
>>>>    
>>>
>>>
>>> .
>>>   
>>
> 
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
  2017-12-28 14:58     ` [Qemu-devel] " Igor Mammedov
@ 2018-01-09 15:42       ` Peter Maydell
  -1 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 15:42 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: Dongjiu Geng, Paolo Bonzini, Michael S. Tsirkin, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 14:58, Igor Mammedov <imammedo@redhat.com> wrote:
> On Thu, 28 Dec 2017 13:54:17 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>
>> Support this feature since version 2.10, disable it by
>> default in the old version.
> patch should go before acpi tables are actually added,
> otherwise it might break bisectability.
>
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address Shannon's comments to add platform version in [1].
>>
>> [1]: https://lkml.org/lkml/2017/8/25/821
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>>  hw/arm/virt-acpi-build.c | 14 +++++++++-----
>>  hw/arm/virt.c            |  4 ++++
>>  include/hw/arm/virt.h    |  1 +
>>  3 files changed, 14 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index 06c14b3..b6974ef 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>>      acpi_add_table(table_offsets, tables_blob);
>>      build_spcr(tables_blob, tables->linker, vms);
>>
>> -    acpi_add_table(table_offsets, tables_blob);
>> -    build_hardware_error_table(tables->hardware_errors, tables->linker);
>> -    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
>> -
>> +    if (!vmc->no_ras) {
>
> it's better to avoid no_foo, use something like
>
> vmc->has_ras

Fields in VirtMachineClass for this kind of thing tend to
end up having to be no_foo, because the default (false) must
be the setting for the most up to date version of the
virt board, because of the way the virt_machine_X_XX_options()
functions chain together. So no_ras matches the sense used
for all the existing bools in VirtMachineClass.

(In contrast, bools in the VirtMachineState struct are the
conventional sense, so there we have highmem/its/virt/etc.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration
@ 2018-01-09 15:42       ` Peter Maydell
  0 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 15:42 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: Dongjiu Geng, Paolo Bonzini, Michael S. Tsirkin, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 14:58, Igor Mammedov <imammedo@redhat.com> wrote:
> On Thu, 28 Dec 2017 13:54:17 +0800
> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>
>> Support this feature since version 2.10, disable it by
>> default in the old version.
> patch should go before acpi tables are actually added,
> otherwise it might break bisectability.
>
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address Shannon's comments to add platform version in [1].
>>
>> [1]: https://lkml.org/lkml/2017/8/25/821
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>>  hw/arm/virt-acpi-build.c | 14 +++++++++-----
>>  hw/arm/virt.c            |  4 ++++
>>  include/hw/arm/virt.h    |  1 +
>>  3 files changed, 14 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index 06c14b3..b6974ef 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -801,10 +801,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
>>      acpi_add_table(table_offsets, tables_blob);
>>      build_spcr(tables_blob, tables->linker, vms);
>>
>> -    acpi_add_table(table_offsets, tables_blob);
>> -    build_hardware_error_table(tables->hardware_errors, tables->linker);
>> -    build_apei_ghes(tables_blob, tables->hardware_errors, tables->linker);
>> -
>> +    if (!vmc->no_ras) {
>
> it's better to avoid no_foo, use something like
>
> vmc->has_ras

Fields in VirtMachineClass for this kind of thing tend to
end up having to be no_foo, because the default (false) must
be the setting for the most up to date version of the
virt board, because of the way the virt_machine_X_XX_options()
functions chain together. So no_ras matches the sense used
for all the existing bools in VirtMachineClass.

(In contrast, bools in the VirtMachineState struct are the
conventional sense, so there we have highmem/its/virt/etc.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2018-01-03  2:21       ` [Qemu-devel] " gengdongjiu
@ 2018-01-09 16:51         ` Peter Maydell
  -1 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 16:51 UTC (permalink / raw)
  To: gengdongjiu
  Cc: Igor Mammedov, Paolo Bonzini, Michael S. Tsirkin, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 3 January 2018 at 02:21, gengdongjiu <gengdongjiu@huawei.com> wrote:
> On 2017/12/28 22:18, Igor Mammedov wrote:
>> On Thu, 28 Dec 2017 13:54:11 +0800
>> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>>> In order to simulation, we hard code the error
>>> type to Multi-bit ECC.
>> Not sure what this is about, care to elaborate?
>
> please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
> error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
> error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
> the error type to Multi-bit ECC.
>
> [1]:
> UEFI Spec 2.6 Errata A:
>
> "N.2.5 Memory Error Section"
> -----------------+---------------+--------------+-------------------------------------------+
>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+
> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
>                  |               |              | 0 – Unknown                              |
>                  |               |              | 1 – No error                             |
>                  |               |              | 2 – Single-bit ECC                       |
>                  |               |              | 3 – Multi-bit ECC                        |
>                  |               |              | 4 – Single-symbol ChipKill ECC           |
>                  |               |              | 5 – Multi-symbol ChipKill ECC            |
>                  |               |              | 6 – Master abort                          |
>                  |               |              | 7 – Target abort                          |
>                  |               |              | 8 – Parity Error                          |
>                  |               |              | 9 – Watchdog timeout                      |
>                  |               |              | 10 – Invalid address                      |
>                  |               |              | 11 – Mirror Broken                        |
>                  |               |              | 12 – Memory Sparing                       |
>                  |               |              | 13 - Scrub corrected error                |
>                  |               |              | 14 - Scrub uncorrected error              |
>                  |               |              | 15 - Physical Memory Map-out event        |
>                  |               |              | All other values reserved.                |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+

There's a value specified for "we don't know what the error type is",
which is "0 - Unknown". I think we should use that rather than claiming
that we have a particular type of error when we don't actually know that.

I agree with James that we don't want to report a particular type of
error to the guest anyway -- the VM is a virtual environment, and
the exact reason why the hardware/firmware/host kernel have decided
that a bit of RAM isn't usable any more doesn't matter to the guest.
We just want to report "this RAM has gone away, sorry" to it.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2018-01-09 16:51         ` Peter Maydell
  0 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 16:51 UTC (permalink / raw)
  To: gengdongjiu
  Cc: Igor Mammedov, Paolo Bonzini, Michael S. Tsirkin, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 3 January 2018 at 02:21, gengdongjiu <gengdongjiu@huawei.com> wrote:
> On 2017/12/28 22:18, Igor Mammedov wrote:
>> On Thu, 28 Dec 2017 13:54:11 +0800
>> Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>>> In order to simulation, we hard code the error
>>> type to Multi-bit ECC.
>> Not sure what this is about, care to elaborate?
>
> please see Memory Error Record in [1], in which the "Memory Error Type" field is used to describe the
> error type, such as  Multi-bit ECC or Parity Error etc. Because KVM or host does not pass the memory
> error type to Qemu, so Qemu does not know what is the error type for the memory section. Hence we let QEMU simulate
> the error type to Multi-bit ECC.
>
> [1]:
> UEFI Spec 2.6 Errata A:
>
> "N.2.5 Memory Error Section"
> -----------------+---------------+--------------+-------------------------------------------+
>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+
> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
>                  |               |              | 0 – Unknown                              |
>                  |               |              | 1 – No error                             |
>                  |               |              | 2 – Single-bit ECC                       |
>                  |               |              | 3 – Multi-bit ECC                        |
>                  |               |              | 4 – Single-symbol ChipKill ECC           |
>                  |               |              | 5 – Multi-symbol ChipKill ECC            |
>                  |               |              | 6 – Master abort                          |
>                  |               |              | 7 – Target abort                          |
>                  |               |              | 8 – Parity Error                          |
>                  |               |              | 9 – Watchdog timeout                      |
>                  |               |              | 10 – Invalid address                      |
>                  |               |              | 11 – Mirror Broken                        |
>                  |               |              | 12 – Memory Sparing                       |
>                  |               |              | 13 - Scrub corrected error                |
>                  |               |              | 14 - Scrub uncorrected error              |
>                  |               |              | 15 - Physical Memory Map-out event        |
>                  |               |              | All other values reserved.                |
> -----------------+---------------+--------------+-------------------------------------------+
>         ........ |  ............ |  .........   |        ...........                        |
> -----------------+---------------+--------------+-------------------------------------------+

There's a value specified for "we don't know what the error type is",
which is "0 - Unknown". I think we should use that rather than claiming
that we have a particular type of error when we don't actually know that.

I agree with James that we don't want to report a particular type of
error to the guest anyway -- the VM is a virtual environment, and
the exact reason why the hardware/firmware/host kernel have decided
that a bit of RAM isn't usable any more doesn't matter to the guest.
We just want to report "this RAM has gone away, sorry" to it.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2018-01-09 17:14     ` Peter Maydell
  -1 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 17:14 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
> translates the host VA which is delivered by host to guest PA, then fill
> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>
> If guest accesses the poisoned memory, it generates Synchronous External
> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
> create a new CPER and add it to guest APEI GHES memory, then notify the
> guest with a GPIO-Signal notification.
>
> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>
> Suggested-by: James Morse <james.morse@arm.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
> Shown some discussion in [1].
>
> [1]:
> https://lkml.org/lkml/2017/2/27/246
> https://lkml.org/lkml/2017/9/14/241
> https://lkml.org/lkml/2017/9/22/499
> ---
>  include/sysemu/kvm.h |  2 +-
>  target/arm/kvm.c     |  2 ++
>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 37 insertions(+), 1 deletion(-)
>
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 3a458f5..90c1605 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>
> -#ifdef TARGET_I386
> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)

As a general rule we should not introduce new ifdefs with
lists of architectures in them. Instead the targets which support
something should define something suitable in a per-target
header file.

In this case I think you should:
 * move the define KVM_HAVE_MCE_INJECTION to target/i386/cpu.h,
   and have this ifdef be #ifdef KVM_HAVE_MCE_INJECTION
   (that should be in a different patch)
 * have the target-arm patch then just define KVM_HAVE_MCE_INJECTION
   in target/arm/cpu.h (if TARGET_AARCH64) and provide
   kvm_arch_on_sigbus_vcpu()

>  #define KVM_HAVE_MCE_INJECTION 1
>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>  #endif
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 7c17f0d..9d25f51 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -26,6 +26,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/boards.h"
>  #include "qemu/log.h"
> +#include "exec/ram_addr.h"

Why this #include ?

>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>      KVM_CAP_LAST_INFO
> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>
>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>
> +    qemu_register_reset(kvm_unpoison_all, NULL);

Looking at this, I realised that we can do this generically in
kvm_init_vcpu() in kvm-all.c (guarded by #ifdef KVM_HAVE_MCE_INJECTION).
You can move the qemu_register_reset() call from target/i386 into
that common code in the patch where you move the unpoison functions.
Then you can make kvm_unpoison_all be static rather than global.

>      type_register_static(&host_arm_cpu_type_info);
>
>      return 0;
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index c00450d..6955d85 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -27,6 +27,9 @@
>  #include "kvm_arm.h"
>  #include "internals.h"
>  #include "hw/arm/arm.h"
> +#include "exec/ram_addr.h"
> +#include "hw/acpi/acpi-defs.h"
> +#include "hw/acpi/hest_ghes.h"
>
>  static bool have_guest_debug;
>
> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>      return ret;
>  }
>
> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
> +{
> +    ram_addr_t ram_addr;
> +    hwaddr paddr;
> +
> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> +    if (addr) {

The x86 equivalent of this code has a check that amounts to
"is the guest CPU actually able to accept MCE notifications?".
It looks wrong that we don't have one here.

It's also suspicious that our "send an MCE notification" is
ACPI specific, when not all our aarch64 boards have ACPI,
and even on virt it's optional.

> +        ram_addr = qemu_ram_addr_from_host(addr);
> +        if (ram_addr != RAM_ADDR_INVALID &&
> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> +            kvm_hwpoison_page_add(ram_addr);
> +            if (code == BUS_MCEERR_AR) {
> +                kvm_cpu_synchronize_state(c);

This is missing a comment that explains why it's necessary.

> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
> +                kvm_inject_arm_sea(c);
> +            } else if (code == BUS_MCEERR_AO) {
> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
> +                qemu_hardware_error_notify();
> +            }
> +            return;
> +        }
> +        fprintf(stderr, "Hardware memory error for memory used by "
> +                "QEMU itself instead of guest system!\n");
> +    }
> +
> +    if (code == BUS_MCEERR_AR) {
> +        fprintf(stderr, "Hardware memory error!\n");
> +        exit(1);
> +    }
> +}

I rather suspect we could have this function common, with
the per-architecture interface being "does this guest CPU support
reporting MCEs to it" and "report an MCE to the guest CPU". But
it's not that much code, so I can live with it not being shared for
now.

> +
>  /* C6.6.29 BRK instruction */
>  static const uint32_t brk_insn = 0xd4200000;
>
> --
> 1.8.3.1

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2018-01-09 17:14     ` Peter Maydell
  0 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 17:14 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
> translates the host VA which is delivered by host to guest PA, then fill
> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>
> If guest accesses the poisoned memory, it generates Synchronous External
> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
> create a new CPER and add it to guest APEI GHES memory, then notify the
> guest with a GPIO-Signal notification.
>
> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>
> Suggested-by: James Morse <james.morse@arm.com>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
> Shown some discussion in [1].
>
> [1]:
> https://lkml.org/lkml/2017/2/27/246
> https://lkml.org/lkml/2017/9/14/241
> https://lkml.org/lkml/2017/9/22/499
> ---
>  include/sysemu/kvm.h |  2 +-
>  target/arm/kvm.c     |  2 ++
>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 37 insertions(+), 1 deletion(-)
>
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 3a458f5..90c1605 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>
> -#ifdef TARGET_I386
> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)

As a general rule we should not introduce new ifdefs with
lists of architectures in them. Instead the targets which support
something should define something suitable in a per-target
header file.

In this case I think you should:
 * move the define KVM_HAVE_MCE_INJECTION to target/i386/cpu.h,
   and have this ifdef be #ifdef KVM_HAVE_MCE_INJECTION
   (that should be in a different patch)
 * have the target-arm patch then just define KVM_HAVE_MCE_INJECTION
   in target/arm/cpu.h (if TARGET_AARCH64) and provide
   kvm_arch_on_sigbus_vcpu()

>  #define KVM_HAVE_MCE_INJECTION 1
>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>  #endif
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 7c17f0d..9d25f51 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -26,6 +26,7 @@
>  #include "exec/address-spaces.h"
>  #include "hw/boards.h"
>  #include "qemu/log.h"
> +#include "exec/ram_addr.h"

Why this #include ?

>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>      KVM_CAP_LAST_INFO
> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>
>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>
> +    qemu_register_reset(kvm_unpoison_all, NULL);

Looking at this, I realised that we can do this generically in
kvm_init_vcpu() in kvm-all.c (guarded by #ifdef KVM_HAVE_MCE_INJECTION).
You can move the qemu_register_reset() call from target/i386 into
that common code in the patch where you move the unpoison functions.
Then you can make kvm_unpoison_all be static rather than global.

>      type_register_static(&host_arm_cpu_type_info);
>
>      return 0;
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index c00450d..6955d85 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -27,6 +27,9 @@
>  #include "kvm_arm.h"
>  #include "internals.h"
>  #include "hw/arm/arm.h"
> +#include "exec/ram_addr.h"
> +#include "hw/acpi/acpi-defs.h"
> +#include "hw/acpi/hest_ghes.h"
>
>  static bool have_guest_debug;
>
> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>      return ret;
>  }
>
> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
> +{
> +    ram_addr_t ram_addr;
> +    hwaddr paddr;
> +
> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> +    if (addr) {

The x86 equivalent of this code has a check that amounts to
"is the guest CPU actually able to accept MCE notifications?".
It looks wrong that we don't have one here.

It's also suspicious that our "send an MCE notification" is
ACPI specific, when not all our aarch64 boards have ACPI,
and even on virt it's optional.

> +        ram_addr = qemu_ram_addr_from_host(addr);
> +        if (ram_addr != RAM_ADDR_INVALID &&
> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> +            kvm_hwpoison_page_add(ram_addr);
> +            if (code == BUS_MCEERR_AR) {
> +                kvm_cpu_synchronize_state(c);

This is missing a comment that explains why it's necessary.

> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
> +                kvm_inject_arm_sea(c);
> +            } else if (code == BUS_MCEERR_AO) {
> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
> +                qemu_hardware_error_notify();
> +            }
> +            return;
> +        }
> +        fprintf(stderr, "Hardware memory error for memory used by "
> +                "QEMU itself instead of guest system!\n");
> +    }
> +
> +    if (code == BUS_MCEERR_AR) {
> +        fprintf(stderr, "Hardware memory error!\n");
> +        exit(1);
> +    }
> +}

I rather suspect we could have this function common, with
the per-architecture interface being "does this guest CPU support
reporting MCEs to it" and "report an MCE to the guest CPU". But
it's not that much code, so I can live with it not being shared for
now.

> +
>  /* C6.6.29 BRK instruction */
>  static const uint32_t brk_insn = 0xd4200000;
>
> --
> 1.8.3.1

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2018-01-09 17:16     ` Peter Maydell
  -1 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 17:16 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> Add CONFIG_ACPI_APEI configuration in the arm-softmmu.mak
> and add build choice in the Makefile.objs.
>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
>  default-configs/arm-softmmu.mak | 1 +
>  hw/acpi/Makefile.objs           | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index bbdd3c1..c362113 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -129,3 +129,4 @@ CONFIG_ACPI=y
>  CONFIG_SMBIOS=y
>  CONFIG_ASPEED_SOC=y
>  CONFIG_GPIO_KEY=y
> +CONFIG_ACPI_APEI=y
> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
> index 11c35bc..bafb148 100644
> --- a/hw/acpi/Makefile.objs
> +++ b/hw/acpi/Makefile.objs
> @@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
>  common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
>  common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
>  common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
> +common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o
>  common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o

You should include this in the patch which first adds the
new host_ghes.c file. Otherwise that patch won't compile.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file
@ 2018-01-09 17:16     ` Peter Maydell
  0 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 17:16 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> Add CONFIG_ACPI_APEI configuration in the arm-softmmu.mak
> and add build choice in the Makefile.objs.
>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
>  default-configs/arm-softmmu.mak | 1 +
>  hw/acpi/Makefile.objs           | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index bbdd3c1..c362113 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -129,3 +129,4 @@ CONFIG_ACPI=y
>  CONFIG_SMBIOS=y
>  CONFIG_ASPEED_SOC=y
>  CONFIG_GPIO_KEY=y
> +CONFIG_ACPI_APEI=y
> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
> index 11c35bc..bafb148 100644
> --- a/hw/acpi/Makefile.objs
> +++ b/hw/acpi/Makefile.objs
> @@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
>  common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
>  common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
>  common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
> +common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o
>  common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o

You should include this in the patch which first adds the
new host_ghes.c file. Otherwise that patch won't compile.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
@ 2018-01-09 17:30     ` Peter Maydell
  -1 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 17:30 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> Add synchronous external abort injection logic, setup
> exception type and syndrome value. When switch to guest,
> guest will jump to the synchronous external abort vector
> table entry.
>
> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
> and ESR_ELx.FnV is set to not valid(0x1), which will tell
> guest that FAR is not valid and holds an UNKNOWN value.
> These value will be set to KVM register structures through
> KVM_SET_ONE_REG IOCTL.
>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
> so user space how to inject it. The test result that injection SEA to guest by Qemu
> is shown in [2].
>
> [1]: https://lkml.org/lkml/2017/3/2/110
> [2]:
> Taking exception 4 [Data Abort]
> ...from EL0 to EL1
> ...with ESR 0x24/0x92000410
> ...with FAR 0x0
> ...with ELR 0x40cf04
> ...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
> after kvm_inject_arm_sea
> Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
> Hardware name: linux,dummy-virt (DT)
> task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
> PC is at 0x40cf04
> LR is at 0x40cdec
> pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
> sp : 0000007ff7b24130
> x29: 0000007ff7b24260 x28: 0000000000000000
> x27: 00000000000000ad x26: 000000000049c000
> x25: 000000000048904b x24: 000000000049c000
> x23: 0000000040600000 x22: 0000007ff7b243a0
> x21: 0000000000000002 x20: 0000000000000000
> x19: 0000000000000020 x18: 0000000000000000
> x17: 000000000049c6d0 x16: 0000007fa22c85c0
> x15: 0000000000005798 x14: 0000007fa2205f1c
> x13: 0000007fa241ccb0 x12: 0000000000000137
> x11: 0000000000000000 x10: 0000000000000000
> x9 : 0000000000000000 x8 : 00000000000000de
> x7 : 0000000000000000 x6 : 0000000000002000
> x5 : 0000000040600000 x4 : 0000000000000003
> x3 : 0000000000000001 x2 : 0000000000000000
> x1 : 0000000000000000 x0 : 0000007fa2418000
> ---
>  target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
>
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index a16abc8..c00450d 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>      return KVM_PUT_RUNTIME_STATE;
>  }
>
> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
> +{
> +    int i;
> +
> +    for (i = 0; i < cpu->cpreg_array_len; i++) {

This is still absolutely the wrong thing to do. Nothing should
need to scan this array like this.

> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
> +        const ARMCPRegInfo *ri;
> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
> +        if (!ri) {
> +            continue;
> +        }
> +
> +        if (ri->type & ARM_CP_NO_RAW) {
> +            continue;
> +        }
> +
> +        if (ri->fieldoffset == fieldoffset) {
> +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
> +            return 0;
> +        }
> +    }
> +    return -EINVAL;
> +}
> +
> +/* Inject synchronous external abort */
> +static void kvm_inject_arm_sea(CPUState *c)
> +{
> +    ARMCPU *cpu = ARM_CPU(c);
> +    CPUARMState *env = &cpu->env;
> +    unsigned long cpsr = pstate_read(env);
> +    uint32_t esr, ret;
> +
> +    /* This exception is synchronous data abort*/

Missing space before */

> +    c->exception_index = EXCP_DATA_ABORT;
> +    /* Inject the exception to guest El1 */

"EL1", all caps.

> +    env->exception.target_el = 1;
> +    CPUClass *cc = CPU_GET_CLASS(c);

Don't declare variables in the middle of the code -- check QEMU's
CODING_STYLE doc for more info.

> +
> +    /* Set the DFSC to synchronous external abort and set FnV to not valid,
> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
> +     */
> +    esr = (0x10 | (1 << 10));
> +
> +    /* This exception comes from lower or current exception level. */
> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {

This looks like it'll be wrong for AArch32 guests (which you can
still have with KVM with a 64-bit host), and even for AArch32
userspace in a 64-bit guest. The correct way to find out what the
current EL is is to use arm_current_el().

> +        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
> +    } else {
> +        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
> +    }

I'm pretty sure in a previous round of review I said you shouldn't
be manually constructing ESR values. We have helper functions for
those (syn_data_abort_*).

> +
> +    /* For the AArch64, instruction length is 32-bit */
> +    esr |= ARM_EL_IL;
> +    env->exception.syndrome = esr;
> +
> +    cc->do_interrupt(c);
> +
> +    /* set ESR_EL1 */
> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));

Breakpoint injection doesn't need to do this. Neither should this code.

> +    if (ret) {
> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
> +        abort();
> +    }
> +}
> +
>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>
> --
> 1.8.3.1

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2018-01-09 17:30     ` Peter Maydell
  0 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-09 17:30 UTC (permalink / raw)
  To: Dongjiu Geng
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> Add synchronous external abort injection logic, setup
> exception type and syndrome value. When switch to guest,
> guest will jump to the synchronous external abort vector
> table entry.
>
> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
> and ESR_ELx.FnV is set to not valid(0x1), which will tell
> guest that FAR is not valid and holds an UNKNOWN value.
> These value will be set to KVM register structures through
> KVM_SET_ONE_REG IOCTL.
>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> ---
> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
> so user space how to inject it. The test result that injection SEA to guest by Qemu
> is shown in [2].
>
> [1]: https://lkml.org/lkml/2017/3/2/110
> [2]:
> Taking exception 4 [Data Abort]
> ...from EL0 to EL1
> ...with ESR 0x24/0x92000410
> ...with FAR 0x0
> ...with ELR 0x40cf04
> ...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
> after kvm_inject_arm_sea
> Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
> Hardware name: linux,dummy-virt (DT)
> task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
> PC is at 0x40cf04
> LR is at 0x40cdec
> pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
> sp : 0000007ff7b24130
> x29: 0000007ff7b24260 x28: 0000000000000000
> x27: 00000000000000ad x26: 000000000049c000
> x25: 000000000048904b x24: 000000000049c000
> x23: 0000000040600000 x22: 0000007ff7b243a0
> x21: 0000000000000002 x20: 0000000000000000
> x19: 0000000000000020 x18: 0000000000000000
> x17: 000000000049c6d0 x16: 0000007fa22c85c0
> x15: 0000000000005798 x14: 0000007fa2205f1c
> x13: 0000007fa241ccb0 x12: 0000000000000137
> x11: 0000000000000000 x10: 0000000000000000
> x9 : 0000000000000000 x8 : 00000000000000de
> x7 : 0000000000000000 x6 : 0000000000002000
> x5 : 0000000040600000 x4 : 0000000000000003
> x3 : 0000000000000001 x2 : 0000000000000000
> x1 : 0000000000000000 x0 : 0000007fa2418000
> ---
>  target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
>
> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> index a16abc8..c00450d 100644
> --- a/target/arm/kvm64.c
> +++ b/target/arm/kvm64.c
> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>      return KVM_PUT_RUNTIME_STATE;
>  }
>
> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
> +{
> +    int i;
> +
> +    for (i = 0; i < cpu->cpreg_array_len; i++) {

This is still absolutely the wrong thing to do. Nothing should
need to scan this array like this.

> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
> +        const ARMCPRegInfo *ri;
> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
> +        if (!ri) {
> +            continue;
> +        }
> +
> +        if (ri->type & ARM_CP_NO_RAW) {
> +            continue;
> +        }
> +
> +        if (ri->fieldoffset == fieldoffset) {
> +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
> +            return 0;
> +        }
> +    }
> +    return -EINVAL;
> +}
> +
> +/* Inject synchronous external abort */
> +static void kvm_inject_arm_sea(CPUState *c)
> +{
> +    ARMCPU *cpu = ARM_CPU(c);
> +    CPUARMState *env = &cpu->env;
> +    unsigned long cpsr = pstate_read(env);
> +    uint32_t esr, ret;
> +
> +    /* This exception is synchronous data abort*/

Missing space before */

> +    c->exception_index = EXCP_DATA_ABORT;
> +    /* Inject the exception to guest El1 */

"EL1", all caps.

> +    env->exception.target_el = 1;
> +    CPUClass *cc = CPU_GET_CLASS(c);

Don't declare variables in the middle of the code -- check QEMU's
CODING_STYLE doc for more info.

> +
> +    /* Set the DFSC to synchronous external abort and set FnV to not valid,
> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
> +     */
> +    esr = (0x10 | (1 << 10));
> +
> +    /* This exception comes from lower or current exception level. */
> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {

This looks like it'll be wrong for AArch32 guests (which you can
still have with KVM with a 64-bit host), and even for AArch32
userspace in a 64-bit guest. The correct way to find out what the
current EL is is to use arm_current_el().

> +        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
> +    } else {
> +        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
> +    }

I'm pretty sure in a previous round of review I said you shouldn't
be manually constructing ESR values. We have helper functions for
those (syn_data_abort_*).

> +
> +    /* For the AArch64, instruction length is 32-bit */
> +    esr |= ARM_EL_IL;
> +    env->exception.syndrome = esr;
> +
> +    cc->do_interrupt(c);
> +
> +    /* set ESR_EL1 */
> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));

Breakpoint injection doesn't need to do this. Neither should this code.

> +    if (ret) {
> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
> +        abort();
> +    }
> +}
> +
>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>
> --
> 1.8.3.1

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
  2018-01-09 16:51         ` [Qemu-devel] " Peter Maydell
@ 2018-01-10  5:22           ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-10  5:22 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Igor Mammedov, Paolo Bonzini, Michael S. Tsirkin, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Peter,
  Thank you very much for your time to review it and give some comments.

On 2018/1/10 0:51, Peter Maydell wrote:
>> the error type to Multi-bit ECC.
>>
>> [1]:
>> UEFI Spec 2.6 Errata A:
>>
>> "N.2.5 Memory Error Section"
>> -----------------+---------------+--------------+-------------------------------------------+
>>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
>>                  |               |              | 0 – Unknown                              |
>>                  |               |              | 1 – No error                             |
>>                  |               |              | 2 – Single-bit ECC                       |
>>                  |               |              | 3 – Multi-bit ECC                        |
>>                  |               |              | 4 – Single-symbol ChipKill ECC           |
>>                  |               |              | 5 – Multi-symbol ChipKill ECC            |
>>                  |               |              | 6 – Master abort                          |
>>                  |               |              | 7 – Target abort                          |
>>                  |               |              | 8 – Parity Error                          |
>>                  |               |              | 9 – Watchdog timeout                      |
>>                  |               |              | 10 – Invalid address                      |
>>                  |               |              | 11 – Mirror Broken                        |
>>                  |               |              | 12 – Memory Sparing                       |
>>                  |               |              | 13 - Scrub corrected error                |
>>                  |               |              | 14 - Scrub uncorrected error              |
>>                  |               |              | 15 - Physical Memory Map-out event        |
>>                  |               |              | All other values reserved.                |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
> There's a value specified for "we don't know what the error type is",
> which is "0 - Unknown". I think we should use that rather than claiming
> that we have a particular type of error when we don't actually know that.
Agree peter's suggestion. It seems "0 - Unknown" makes sense.

> 
> I agree with James that we don't want to report a particular type of
> error to the guest anyway -- the VM is a virtual environment, and
> the exact reason why the hardware/firmware/host kernel have decided
> that a bit of RAM isn't usable any more doesn't matter to the guest.
> We just want to report "this RAM has gone away, sorry" to it.
Agree with peter, appreciate for the comments.

> 
> thanks
> -- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support
@ 2018-01-10  5:22           ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-10  5:22 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Igor Mammedov, Paolo Bonzini, Michael S. Tsirkin, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Peter,
  Thank you very much for your time to review it and give some comments.

On 2018/1/10 0:51, Peter Maydell wrote:
>> the error type to Multi-bit ECC.
>>
>> [1]:
>> UEFI Spec 2.6 Errata A:
>>
>> "N.2.5 Memory Error Section"
>> -----------------+---------------+--------------+-------------------------------------------+
>>         Mnemonic |   Byte Offset |  Byte Length |        Description                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
>> Memory Error Type|     72        |       1      |Identifies the type of error that occurred:|
>>                  |               |              | 0 – Unknown                              |
>>                  |               |              | 1 – No error                             |
>>                  |               |              | 2 – Single-bit ECC                       |
>>                  |               |              | 3 – Multi-bit ECC                        |
>>                  |               |              | 4 – Single-symbol ChipKill ECC           |
>>                  |               |              | 5 – Multi-symbol ChipKill ECC            |
>>                  |               |              | 6 – Master abort                          |
>>                  |               |              | 7 – Target abort                          |
>>                  |               |              | 8 – Parity Error                          |
>>                  |               |              | 9 – Watchdog timeout                      |
>>                  |               |              | 10 – Invalid address                      |
>>                  |               |              | 11 – Mirror Broken                        |
>>                  |               |              | 12 – Memory Sparing                       |
>>                  |               |              | 13 - Scrub corrected error                |
>>                  |               |              | 14 - Scrub uncorrected error              |
>>                  |               |              | 15 - Physical Memory Map-out event        |
>>                  |               |              | All other values reserved.                |
>> -----------------+---------------+--------------+-------------------------------------------+
>>         ........ |  ............ |  .........   |        ...........                        |
>> -----------------+---------------+--------------+-------------------------------------------+
> There's a value specified for "we don't know what the error type is",
> which is "0 - Unknown". I think we should use that rather than claiming
> that we have a particular type of error when we don't actually know that.
Agree peter's suggestion. It seems "0 - Unknown" makes sense.

> 
> I agree with James that we don't want to report a particular type of
> error to the guest anyway -- the VM is a virtual environment, and
> the exact reason why the hardware/firmware/host kernel have decided
> that a bit of RAM isn't usable any more doesn't matter to the guest.
> We just want to report "this RAM has gone away, sorry" to it.
Agree with peter, appreciate for the comments.

> 
> thanks
> -- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
  2018-01-09 17:14     ` [Qemu-devel] " Peter Maydell
@ 2018-01-10 11:56       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-10 11:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter,
  Thanks for the mail and comments.

On 2018/1/10 1:14, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
>> translates the host VA which is delivered by host to guest PA, then fill
>> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
>> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
>> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>>
>> If guest accesses the poisoned memory, it generates Synchronous External
>> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
>> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
>> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
>> create a new CPER and add it to guest APEI GHES memory, then notify the
>> guest with a GPIO-Signal notification.
>>
>> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
>> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
>> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>>
>> Suggested-by: James Morse <james.morse@arm.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
>> Shown some discussion in [1].
>>
>> [1]:
>> https://lkml.org/lkml/2017/2/27/246
>> https://lkml.org/lkml/2017/9/14/241
>> https://lkml.org/lkml/2017/9/22/499
>> ---
>>  include/sysemu/kvm.h |  2 +-
>>  target/arm/kvm.c     |  2 ++
>>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 37 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
>> index 3a458f5..90c1605 100644
>> --- a/include/sysemu/kvm.h
>> +++ b/include/sysemu/kvm.h
>> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>>
>> -#ifdef TARGET_I386
>> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
> 
> As a general rule we should not introduce new ifdefs with
> lists of architectures in them. Instead the targets which support
> something should define something suitable in a per-target
> header file.
> 
> In this case I think you should:
>  * move the define KVM_HAVE_MCE_INJECTION to target/i386/cpu.h,
>    and have this ifdef be #ifdef KVM_HAVE_MCE_INJECTION
>    (that should be in a different patch)
>  * have the target-arm patch then just define KVM_HAVE_MCE_INJECTION
>    in target/arm/cpu.h (if TARGET_AARCH64) and provide
>    kvm_arch_on_sigbus_vcpu()
Yes, this way is clean. thanks for the suggestion and detailed description.

>>  #define KVM_HAVE_MCE_INJECTION 1
>>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>>  #endif
>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>> index 7c17f0d..9d25f51 100644
>> --- a/target/arm/kvm.c
>> +++ b/target/arm/kvm.c
>> @@ -26,6 +26,7 @@
>>  #include "exec/address-spaces.h"
>>  #include "hw/boards.h"
>>  #include "qemu/log.h"
>> +#include "exec/ram_addr.h"
> 
> Why this #include ?
it needs to call the qemu_register_reset()

> 
>>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>>      KVM_CAP_LAST_INFO
>> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>>
>>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>>
>> +    qemu_register_reset(kvm_unpoison_all, NULL);
> 
> Looking at this, I realised that we can do this generically in
> kvm_init_vcpu() in kvm-all.c (guarded by #ifdef KVM_HAVE_MCE_INJECTION).
> You can move the qemu_register_reset() call from target/i386 into
> that common code in the patch where you move the unpoison functions.
> Then you can make kvm_unpoison_all be static rather than global.
Ok, thanks for the good suggestion and pointing out.

> 
>>      type_register_static(&host_arm_cpu_type_info);
>>
>>      return 0;
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index c00450d..6955d85 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -27,6 +27,9 @@
>>  #include "kvm_arm.h"
>>  #include "internals.h"
>>  #include "hw/arm/arm.h"
>> +#include "exec/ram_addr.h"
>> +#include "hw/acpi/acpi-defs.h"
>> +#include "hw/acpi/hest_ghes.h"
>>
>>  static bool have_guest_debug;
>>
>> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>>      return ret;
>>  }
>>
>> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>> +{
>> +    ram_addr_t ram_addr;
>> +    hwaddr paddr;
>> +
>> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
>> +    if (addr) {
> 
> The x86 equivalent of this code has a check that amounts to
> "is the guest CPU actually able to accept MCE notifications?".
> It looks wrong that we don't have one here.

In the x86 code[1], it checks the MCG_SER_P(software error recovery support present) flag,
this flag indicates that whether the processor supports software error recovery[2]. In arm64(now we
do not support arm32), we do not have such bit. If check, it may need to check that whether processor
supports RAS feature, Otherwise what we should check? James Morse <james.morse@arm.com> has some concern that Qemu checks whether
processor supports RAS feature. He thinks QEMU should record guest CPER and notify guest when receiving
SIGBUS signal even though processor does not support RAS. so I do not know what we should check, host(include QEMU and KVM)
should not know that whether guest can able to accept MCE notifications.

[1]: void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) {
     	if ((env->mcg_cap & MCG_SER_P) && addr) {
		.........
   	}
   }
[2]: https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-509.html


Hello James,
  As Peter mentioned, the x86 checks that whether the processor supports software error recovery before injecting MCE error in the user space.
For the ARM64, whether we should check something before recording guest CPER and inject SEA/IRQ? or nothing? I remember you are opposed to checking
processor RAS feature.

Below is user space code logic:
1. If kernel/KVM delivered host VA is not NULL and belonged to guest, then translate this host VA to guest PA.
2. if the SIBUS is BUS_MCEERR_AR, record the CPER for guest and inject SEA to notify guest
3. if the SIBUS is BUS_MCEERR_AO, record the CPER for guest and inject a GPIO IRQ to notify guest

In above logic, I do not check that processor support RAS feature.

> 
>> +        ram_addr = qemu_ram_addr_from_host(addr);
>> +        if (ram_addr != RAM_ADDR_INVALID &&
>> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
>> +            kvm_hwpoison_page_add(ram_addr);
>> +            if (code == BUS_MCEERR_AR) {
>> +                kvm_cpu_synchronize_state(c);
> 
> This is missing a comment that explains why it's necessary.
Ok, thanks very much for the careful review. sure, I will add it.

> 
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
>> +                kvm_inject_arm_sea(c);
>> +            } else if (code == BUS_MCEERR_AO) {
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
>> +                qemu_hardware_error_notify();
>> +            }
>> +            return;
>> +        }
>> +        fprintf(stderr, "Hardware memory error for memory used by "
>> +                "QEMU itself instead of guest system!\n");
>> +    }
>> +
>> +    if (code == BUS_MCEERR_AR) {
>> +        fprintf(stderr, "Hardware memory error!\n");
>> +        exit(1);
>> +    }
>> +}
> 
> I rather suspect we could have this function common, with
> the per-architecture interface being "does this guest CPU support
> reporting MCEs to it" and "report an MCE to the guest CPU". But
> it's not that much code, so I can live with it not being shared for
> now.
Thanks!
The x86 MCE mechanism and ARM64 RAS extension mechanism have some difference
include hardware and software. so the QEMU handling has some difference.

> 
>> +
>>  /* C6.6.29 BRK instruction */
>>  static const uint32_t brk_insn = 0xd4200000;
>>
>> --
>> 1.8.3.1
> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM
@ 2018-01-10 11:56       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-10 11:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter,
  Thanks for the mail and comments.

On 2018/1/10 1:14, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>> Add SIGBUS signal handler. In this handler, it checks the SIGBUS type,
>> translates the host VA which is delivered by host to guest PA, then fill
>> this PA to CPER and fill the CPER to guest APEI GHES memory, finally
>> notify guest according to the SIGBUS type. There are two kinds of SIGBUS
>> that QEMU needs to handle, which are BUS_MCEERR_AO and BUS_MCEERR_AR.
>>
>> If guest accesses the poisoned memory, it generates Synchronous External
>> Abort(SEA). Then host kernel gets an APEI notification and call memory_failure()
>> to unmapped the affected page from the guest's stage2, and SIGBUS_MCEERR_AO
>> is delivered to Qemu's main thread. If Qemu receives this SIGBUS, it will
>> create a new CPER and add it to guest APEI GHES memory, then notify the
>> guest with a GPIO-Signal notification.
>>
>> When guest hits a PG_hwpoison page, it will trap to KVM as stage2 fault, then a
>> SIGBUS_MCEERR_AR synchronous signal is delivered to Qemu, Qemu record this error
>> into guest APEI GHES memory and notify guest using Synchronous-External-Abort(SEA).
>>
>> Suggested-by: James Morse <james.morse@arm.com>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Address James's comments to record CPER and notify guest for SIGBUS signal handling.
>> Shown some discussion in [1].
>>
>> [1]:
>> https://lkml.org/lkml/2017/2/27/246
>> https://lkml.org/lkml/2017/9/14/241
>> https://lkml.org/lkml/2017/9/22/499
>> ---
>>  include/sysemu/kvm.h |  2 +-
>>  target/arm/kvm.c     |  2 ++
>>  target/arm/kvm64.c   | 34 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 37 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
>> index 3a458f5..90c1605 100644
>> --- a/include/sysemu/kvm.h
>> +++ b/include/sysemu/kvm.h
>> @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
>>  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
>>  unsigned long kvm_arch_vcpu_id(CPUState *cpu);
>>
>> -#ifdef TARGET_I386
>> +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
> 
> As a general rule we should not introduce new ifdefs with
> lists of architectures in them. Instead the targets which support
> something should define something suitable in a per-target
> header file.
> 
> In this case I think you should:
>  * move the define KVM_HAVE_MCE_INJECTION to target/i386/cpu.h,
>    and have this ifdef be #ifdef KVM_HAVE_MCE_INJECTION
>    (that should be in a different patch)
>  * have the target-arm patch then just define KVM_HAVE_MCE_INJECTION
>    in target/arm/cpu.h (if TARGET_AARCH64) and provide
>    kvm_arch_on_sigbus_vcpu()
Yes, this way is clean. thanks for the suggestion and detailed description.

>>  #define KVM_HAVE_MCE_INJECTION 1
>>  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
>>  #endif
>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>> index 7c17f0d..9d25f51 100644
>> --- a/target/arm/kvm.c
>> +++ b/target/arm/kvm.c
>> @@ -26,6 +26,7 @@
>>  #include "exec/address-spaces.h"
>>  #include "hw/boards.h"
>>  #include "qemu/log.h"
>> +#include "exec/ram_addr.h"
> 
> Why this #include ?
it needs to call the qemu_register_reset()

> 
>>  const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>>      KVM_CAP_LAST_INFO
>> @@ -182,6 +183,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>>
>>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
>>
>> +    qemu_register_reset(kvm_unpoison_all, NULL);
> 
> Looking at this, I realised that we can do this generically in
> kvm_init_vcpu() in kvm-all.c (guarded by #ifdef KVM_HAVE_MCE_INJECTION).
> You can move the qemu_register_reset() call from target/i386 into
> that common code in the patch where you move the unpoison functions.
> Then you can make kvm_unpoison_all be static rather than global.
Ok, thanks for the good suggestion and pointing out.

> 
>>      type_register_static(&host_arm_cpu_type_info);
>>
>>      return 0;
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index c00450d..6955d85 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -27,6 +27,9 @@
>>  #include "kvm_arm.h"
>>  #include "internals.h"
>>  #include "hw/arm/arm.h"
>> +#include "exec/ram_addr.h"
>> +#include "hw/acpi/acpi-defs.h"
>> +#include "hw/acpi/hest_ghes.h"
>>
>>  static bool have_guest_debug;
>>
>> @@ -944,6 +947,37 @@ int kvm_arch_get_registers(CPUState *cs)
>>      return ret;
>>  }
>>
>> +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>> +{
>> +    ram_addr_t ram_addr;
>> +    hwaddr paddr;
>> +
>> +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
>> +    if (addr) {
> 
> The x86 equivalent of this code has a check that amounts to
> "is the guest CPU actually able to accept MCE notifications?".
> It looks wrong that we don't have one here.

In the x86 code[1], it checks the MCG_SER_P(software error recovery support present) flag,
this flag indicates that whether the processor supports software error recovery[2]. In arm64(now we
do not support arm32), we do not have such bit. If check, it may need to check that whether processor
supports RAS feature, Otherwise what we should check? James Morse <james.morse@arm.com> has some concern that Qemu checks whether
processor supports RAS feature. He thinks QEMU should record guest CPER and notify guest when receiving
SIGBUS signal even though processor does not support RAS. so I do not know what we should check, host(include QEMU and KVM)
should not know that whether guest can able to accept MCE notifications.

[1]: void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) {
     	if ((env->mcg_cap & MCG_SER_P) && addr) {
		.........
   	}
   }
[2]: https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-509.html


Hello James,
  As Peter mentioned, the x86 checks that whether the processor supports software error recovery before injecting MCE error in the user space.
For the ARM64, whether we should check something before recording guest CPER and inject SEA/IRQ? or nothing? I remember you are opposed to checking
processor RAS feature.

Below is user space code logic:
1. If kernel/KVM delivered host VA is not NULL and belonged to guest, then translate this host VA to guest PA.
2. if the SIBUS is BUS_MCEERR_AR, record the CPER for guest and inject SEA to notify guest
3. if the SIBUS is BUS_MCEERR_AO, record the CPER for guest and inject a GPIO IRQ to notify guest

In above logic, I do not check that processor support RAS feature.

> 
>> +        ram_addr = qemu_ram_addr_from_host(addr);
>> +        if (ram_addr != RAM_ADDR_INVALID &&
>> +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
>> +            kvm_hwpoison_page_add(ram_addr);
>> +            if (code == BUS_MCEERR_AR) {
>> +                kvm_cpu_synchronize_state(c);
> 
> This is missing a comment that explains why it's necessary.
Ok, thanks very much for the careful review. sure, I will add it.

> 
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_SEA, paddr);
>> +                kvm_inject_arm_sea(c);
>> +            } else if (code == BUS_MCEERR_AO) {
>> +                ghes_record_errors(ACPI_HEST_NOTIFY_GPIO, paddr);
>> +                qemu_hardware_error_notify();
>> +            }
>> +            return;
>> +        }
>> +        fprintf(stderr, "Hardware memory error for memory used by "
>> +                "QEMU itself instead of guest system!\n");
>> +    }
>> +
>> +    if (code == BUS_MCEERR_AR) {
>> +        fprintf(stderr, "Hardware memory error!\n");
>> +        exit(1);
>> +    }
>> +}
> 
> I rather suspect we could have this function common, with
> the per-architecture interface being "does this guest CPU support
> reporting MCEs to it" and "report an MCE to the guest CPU". But
> it's not that much code, so I can live with it not being shared for
> now.
Thanks!
The x86 MCE mechanism and ARM64 RAS extension mechanism have some difference
include hardware and software. so the QEMU handling has some difference.

> 
>> +
>>  /* C6.6.29 BRK instruction */
>>  static const uint32_t brk_insn = 0xd4200000;
>>
>> --
>> 1.8.3.1
> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file
  2018-01-09 17:16     ` [Qemu-devel] " Peter Maydell
@ 2018-01-10 12:20       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-10 12:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 2018/1/10 1:16, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>> Add CONFIG_ACPI_APEI configuration in the arm-softmmu.mak
>> and add build choice in the Makefile.objs.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>>  default-configs/arm-softmmu.mak | 1 +
>>  hw/acpi/Makefile.objs           | 1 +
>>  2 files changed, 2 insertions(+)
>>
>> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
>> index bbdd3c1..c362113 100644
>> --- a/default-configs/arm-softmmu.mak
>> +++ b/default-configs/arm-softmmu.mak
>> @@ -129,3 +129,4 @@ CONFIG_ACPI=y
>>  CONFIG_SMBIOS=y
>>  CONFIG_ASPEED_SOC=y
>>  CONFIG_GPIO_KEY=y
>> +CONFIG_ACPI_APEI=y
>> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
>> index 11c35bc..bafb148 100644
>> --- a/hw/acpi/Makefile.objs
>> +++ b/hw/acpi/Makefile.objs
>> @@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
>>  common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
>>  common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
>>  common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
>> +common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o
>>  common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
> 
> You should include this in the patch which first adds the
> new host_ghes.c file. Otherwise that patch won't compile.

sure, will modify it.

> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file
@ 2018-01-10 12:20       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-10 12:20 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

On 2018/1/10 1:16, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>> Add CONFIG_ACPI_APEI configuration in the arm-softmmu.mak
>> and add build choice in the Makefile.objs.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>>  default-configs/arm-softmmu.mak | 1 +
>>  hw/acpi/Makefile.objs           | 1 +
>>  2 files changed, 2 insertions(+)
>>
>> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
>> index bbdd3c1..c362113 100644
>> --- a/default-configs/arm-softmmu.mak
>> +++ b/default-configs/arm-softmmu.mak
>> @@ -129,3 +129,4 @@ CONFIG_ACPI=y
>>  CONFIG_SMBIOS=y
>>  CONFIG_ASPEED_SOC=y
>>  CONFIG_GPIO_KEY=y
>> +CONFIG_ACPI_APEI=y
>> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
>> index 11c35bc..bafb148 100644
>> --- a/hw/acpi/Makefile.objs
>> +++ b/hw/acpi/Makefile.objs
>> @@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
>>  common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
>>  common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
>>  common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
>> +common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o
>>  common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
> 
> You should include this in the patch which first adds the
> new host_ghes.c file. Otherwise that patch won't compile.

sure, will modify it.

> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2018-01-09 17:30     ` [Qemu-devel] " Peter Maydell
@ 2018-01-11  5:59       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-11  5:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter.

On 2018/1/10 1:30, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>> Add synchronous external abort injection logic, setup
>> exception type and syndrome value. When switch to guest,
>> guest will jump to the synchronous external abort vector
>> table entry.
>>
>> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
>> and ESR_ELx.FnV is set to not valid(0x1), which will tell
>> guest that FAR is not valid and holds an UNKNOWN value.
>> These value will be set to KVM register structures through
>> KVM_SET_ONE_REG IOCTL.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
>> so user space how to inject it. The test result that injection SEA to guest by Qemu
>> is shown in [2].
>>
>> [1]: https://lkml.org/lkml/2017/3/2/110
>> [2]:
>> Taking exception 4 [Data Abort]
>> ...from EL0 to EL1
>> ...with ESR 0x24/0x92000410
>> ...with FAR 0x0
>> ...with ELR 0x40cf04
>> ...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
>> after kvm_inject_arm_sea
>> Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
>> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
>> Hardware name: linux,dummy-virt (DT)
>> task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
>> PC is at 0x40cf04
>> LR is at 0x40cdec
>> pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
>> sp : 0000007ff7b24130
>> x29: 0000007ff7b24260 x28: 0000000000000000
>> x27: 00000000000000ad x26: 000000000049c000
>> x25: 000000000048904b x24: 000000000049c000
>> x23: 0000000040600000 x22: 0000007ff7b243a0
>> x21: 0000000000000002 x20: 0000000000000000
>> x19: 0000000000000020 x18: 0000000000000000
>> x17: 000000000049c6d0 x16: 0000007fa22c85c0
>> x15: 0000000000005798 x14: 0000007fa2205f1c
>> x13: 0000007fa241ccb0 x12: 0000000000000137
>> x11: 0000000000000000 x10: 0000000000000000
>> x9 : 0000000000000000 x8 : 00000000000000de
>> x7 : 0000000000000000 x6 : 0000000000002000
>> x5 : 0000000040600000 x4 : 0000000000000003
>> x3 : 0000000000000001 x2 : 0000000000000000
>> x1 : 0000000000000000 x0 : 0000007fa2418000
>> ---
>>  target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 65 insertions(+)
>>
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index a16abc8..c00450d 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>>      return KVM_PUT_RUNTIME_STATE;
>>  }
>>
>> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> 
> This is still absolutely the wrong thing to do. Nothing should
> need to scan this array like this.
I will confirm that whether KVM mode will need this code, if not, I will remove this function.

> 
>> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
>> +        const ARMCPRegInfo *ri;
>> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
>> +        if (!ri) {
>> +            continue;
>> +        }
>> +
>> +        if (ri->type & ARM_CP_NO_RAW) {
>> +            continue;
>> +        }
>> +
>> +        if (ri->fieldoffset == fieldoffset) {
>> +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
>> +            return 0;
>> +        }
>> +    }
>> +    return -EINVAL;
>> +}
>> +
>> +/* Inject synchronous external abort */
>> +static void kvm_inject_arm_sea(CPUState *c)
>> +{
>> +    ARMCPU *cpu = ARM_CPU(c);
>> +    CPUARMState *env = &cpu->env;
>> +    unsigned long cpsr = pstate_read(env);
>> +    uint32_t esr, ret;
>> +
>> +    /* This exception is synchronous data abort*/
> 
> Missing space before */
will fix it.

> 
>> +    c->exception_index = EXCP_DATA_ABORT;
>> +    /* Inject the exception to guest El1 */
> 
> "EL1", all caps.
will fix it.

> 
>> +    env->exception.target_el = 1;
>> +    CPUClass *cc = CPU_GET_CLASS(c);
> 
> Don't declare variables in the middle of the code -- check QEMU's
> CODING_STYLE doc for more info.
will fix it.

> 
>> +
>> +    /* Set the DFSC to synchronous external abort and set FnV to not valid,
>> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
>> +     */
>> +    esr = (0x10 | (1 << 10));
>> +
>> +    /* This exception comes from lower or current exception level. */
>> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
> 
> This looks like it'll be wrong for AArch32 guests (which you can
> still have with KVM with a 64-bit host), and even for AArch32
> userspace in a 64-bit guest. The correct way to find out what the
> current EL is is to use arm_current_el().
 sorry, in the OS(include guest OS), for software error recovery, we only support AArch64 kernel, not support AArch32
 kernel or AArch32 user space.

> 
>> +        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
>> +    } else {
>> +        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
>> +    }
> 
> I'm pretty sure in a previous round of review I said you shouldn't
> be manually constructing ESR values. We have helper functions for
> those (syn_data_abort_*).
sorry, it is my mistake. I will use syn_data_abort_*.

> 
>> +
>> +    /* For the AArch64, instruction length is 32-bit */
>> +    esr |= ARM_EL_IL;
>> +    env->exception.syndrome = esr;
>> +
>> +    cc->do_interrupt(c);
>> +
>> +    /* set ESR_EL1 */
>> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
> 
> Breakpoint injection doesn't need to do this. Neither should this code.
Good point.
After I confirmed, in the TCG mode, it does not need this code. I am not sure whether KVM mode will need it.
I will test it in the KVM mode. If KVM mode also does not need it, I will remove this code.


> 
>> +    if (ret) {
>> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
>> +        abort();
>> +    }
>> +}
>> +
>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>
>> --
>> 1.8.3.1
> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2018-01-11  5:59       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-11  5:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter.

On 2018/1/10 1:30, Peter Maydell wrote:
> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
>> Add synchronous external abort injection logic, setup
>> exception type and syndrome value. When switch to guest,
>> guest will jump to the synchronous external abort vector
>> table entry.
>>
>> The ESR_ELx.DFSC is set to synchronous external abort(0x10),
>> and ESR_ELx.FnV is set to not valid(0x1), which will tell
>> guest that FAR is not valid and holds an UNKNOWN value.
>> These value will be set to KVM register structures through
>> KVM_SET_ONE_REG IOCTL.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> ---
>> Marc is against that KVM inject the synchronous external abort(SEA) in [1],
>> so user space how to inject it. The test result that injection SEA to guest by Qemu
>> is shown in [2].
>>
>> [1]: https://lkml.org/lkml/2017/3/2/110
>> [2]:
>> Taking exception 4 [Data Abort]
>> ...from EL0 to EL1
>> ...with ESR 0x24/0x92000410
>> ...with FAR 0x0
>> ...with ELR 0x40cf04
>> ...to EL1 PC 0xffffffc000084c00 PSTATE 0x3c5
>> after kvm_inject_arm_sea
>> Unhandled fault: synchronous external abort (0x92000410) at 0x0000007fa234c12c
>> CPU: 0 PID: 536 Comm: devmem Not tainted 4.1.0+ #20
>> Hardware name: linux,dummy-virt (DT)
>> task: ffffffc019ab2b00 ti: ffffffc008134000 task.ti: ffffffc008134000
>> PC is at 0x40cf04
>> LR is at 0x40cdec
>> pc : [<000000000040cf04>] lr : [<000000000040cdec>] pstate: 60000000
>> sp : 0000007ff7b24130
>> x29: 0000007ff7b24260 x28: 0000000000000000
>> x27: 00000000000000ad x26: 000000000049c000
>> x25: 000000000048904b x24: 000000000049c000
>> x23: 0000000040600000 x22: 0000007ff7b243a0
>> x21: 0000000000000002 x20: 0000000000000000
>> x19: 0000000000000020 x18: 0000000000000000
>> x17: 000000000049c6d0 x16: 0000007fa22c85c0
>> x15: 0000000000005798 x14: 0000007fa2205f1c
>> x13: 0000007fa241ccb0 x12: 0000000000000137
>> x11: 0000000000000000 x10: 0000000000000000
>> x9 : 0000000000000000 x8 : 00000000000000de
>> x7 : 0000000000000000 x6 : 0000000000002000
>> x5 : 0000000040600000 x4 : 0000000000000003
>> x3 : 0000000000000001 x2 : 0000000000000000
>> x1 : 0000000000000000 x0 : 0000007fa2418000
>> ---
>>  target/arm/kvm64.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 65 insertions(+)
>>
>> diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
>> index a16abc8..c00450d 100644
>> --- a/target/arm/kvm64.c
>> +++ b/target/arm/kvm64.c
>> @@ -582,6 +582,71 @@ int kvm_arm_cpreg_level(uint64_t regidx)
>>      return KVM_PUT_RUNTIME_STATE;
>>  }
>>
>> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> 
> This is still absolutely the wrong thing to do. Nothing should
> need to scan this array like this.
I will confirm that whether KVM mode will need this code, if not, I will remove this function.

> 
>> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
>> +        const ARMCPRegInfo *ri;
>> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
>> +        if (!ri) {
>> +            continue;
>> +        }
>> +
>> +        if (ri->type & ARM_CP_NO_RAW) {
>> +            continue;
>> +        }
>> +
>> +        if (ri->fieldoffset == fieldoffset) {
>> +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
>> +            return 0;
>> +        }
>> +    }
>> +    return -EINVAL;
>> +}
>> +
>> +/* Inject synchronous external abort */
>> +static void kvm_inject_arm_sea(CPUState *c)
>> +{
>> +    ARMCPU *cpu = ARM_CPU(c);
>> +    CPUARMState *env = &cpu->env;
>> +    unsigned long cpsr = pstate_read(env);
>> +    uint32_t esr, ret;
>> +
>> +    /* This exception is synchronous data abort*/
> 
> Missing space before */
will fix it.

> 
>> +    c->exception_index = EXCP_DATA_ABORT;
>> +    /* Inject the exception to guest El1 */
> 
> "EL1", all caps.
will fix it.

> 
>> +    env->exception.target_el = 1;
>> +    CPUClass *cc = CPU_GET_CLASS(c);
> 
> Don't declare variables in the middle of the code -- check QEMU's
> CODING_STYLE doc for more info.
will fix it.

> 
>> +
>> +    /* Set the DFSC to synchronous external abort and set FnV to not valid,
>> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
>> +     */
>> +    esr = (0x10 | (1 << 10));
>> +
>> +    /* This exception comes from lower or current exception level. */
>> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
> 
> This looks like it'll be wrong for AArch32 guests (which you can
> still have with KVM with a 64-bit host), and even for AArch32
> userspace in a 64-bit guest. The correct way to find out what the
> current EL is is to use arm_current_el().
 sorry, in the OS(include guest OS), for software error recovery, we only support AArch64 kernel, not support AArch32
 kernel or AArch32 user space.

> 
>> +        esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
>> +    } else {
>> +        esr |= (EC_DATAABORT_SAME_EL << ARM_EL_EC_SHIFT);
>> +    }
> 
> I'm pretty sure in a previous round of review I said you shouldn't
> be manually constructing ESR values. We have helper functions for
> those (syn_data_abort_*).
sorry, it is my mistake. I will use syn_data_abort_*.

> 
>> +
>> +    /* For the AArch64, instruction length is 32-bit */
>> +    esr |= ARM_EL_IL;
>> +    env->exception.syndrome = esr;
>> +
>> +    cc->do_interrupt(c);
>> +
>> +    /* set ESR_EL1 */
>> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
> 
> Breakpoint injection doesn't need to do this. Neither should this code.
Good point.
After I confirmed, in the TCG mode, it does not need this code. I am not sure whether KVM mode will need it.
I will test it in the KVM mode. If KVM mode also does not need it, I will remove this code.


> 
>> +    if (ret) {
>> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
>> +        abort();
>> +    }
>> +}
>> +
>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>
>> --
>> 1.8.3.1
> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-arm] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2018-01-11  5:59       ` [Qemu-devel] " gengdongjiu
@ 2018-01-11  9:53         ` Peter Maydell
  -1 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-11  9:53 UTC (permalink / raw)
  To: gengdongjiu
  Cc: Eduardo Habkost, kvm-devel, Michael S. Tsirkin, Marc Zyngier,
	Marcelo Tosatti, QEMU Developers, Xu Wei, qemu-arm, James Morse,
	Huangshaoyu, Igor Mammedov, Paolo Bonzini, Zhengqiang (turing),
	Shannon Zhao, Christoffer Dall, Richard Henderson

On 11 January 2018 at 05:59, gengdongjiu <gengdongjiu@huawei.com> wrote:
> Hi Peter.
>
> On 2018/1/10 1:30, Peter Maydell wrote:
>> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:

>>> +
>>> +    /* This exception comes from lower or current exception level. */
>>> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
>>
>> This looks like it'll be wrong for AArch32 guests (which you can
>> still have with KVM with a 64-bit host), and even for AArch32
>> userspace in a 64-bit guest. The correct way to find out what the
>> current EL is is to use arm_current_el().

>  sorry, in the OS(include guest OS), for software error recovery,
> we only support AArch64 kernel, not support AArch32
>  kernel or AArch32 user space.

Nope, you must handle AArch32 EL1 correctly in some way, even if that
is only "this guest CPU doesn't support RAS notification and we
will not notify it". And you must absolutely support AArch32 EL0,
that's a requirement for getting this merged. It's not difficult.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2018-01-11  9:53         ` Peter Maydell
  0 siblings, 0 replies; 83+ messages in thread
From: Peter Maydell @ 2018-01-11  9:53 UTC (permalink / raw)
  To: gengdongjiu
  Cc: Eduardo Habkost, kvm-devel, Michael S. Tsirkin, Marc Zyngier,
	Marcelo Tosatti, QEMU Developers, Xu Wei, qemu-arm, James Morse,
	Huangshaoyu, Igor Mammedov, Paolo Bonzini, Zhengqiang (turing),
	Shannon Zhao, Christoffer Dall, Richard Henderson

On 11 January 2018 at 05:59, gengdongjiu <gengdongjiu@huawei.com> wrote:
> Hi Peter.
>
> On 2018/1/10 1:30, Peter Maydell wrote:
>> On 28 December 2017 at 05:54, Dongjiu Geng <gengdongjiu@huawei.com> wrote:

>>> +
>>> +    /* This exception comes from lower or current exception level. */
>>> +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
>>
>> This looks like it'll be wrong for AArch32 guests (which you can
>> still have with KVM with a 64-bit host), and even for AArch32
>> userspace in a 64-bit guest. The correct way to find out what the
>> current EL is is to use arm_current_el().

>  sorry, in the OS(include guest OS), for software error recovery,
> we only support AArch64 kernel, not support AArch32
>  kernel or AArch32 user space.

Nope, you must handle AArch32 EL1 correctly in some way, even if that
is only "this guest CPU doesn't support RAS notification and we
will not notify it". And you must absolutely support AArch32 EL0,
that's a requirement for getting this merged. It's not difficult.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-arm] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2018-01-11  9:53         ` [Qemu-devel] " Peter Maydell
@ 2018-01-11 10:33           ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-11 10:33 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Eduardo Habkost, kvm-devel, Michael S. Tsirkin, Marc Zyngier,
	Marcelo Tosatti, QEMU Developers, Xu Wei, qemu-arm, James Morse,
	Huangshaoyu, Igor Mammedov, Paolo Bonzini, Zhengqiang (turing),
	Shannon Zhao, Christoffer Dall, Richard Henderson

On 2018/1/11 17:53, Peter Maydell wrote:
>> we only support AArch64 kernel, not support AArch32
>>  kernel or AArch32 user space.
> Nope, you must handle AArch32 EL1 correctly in some way, even if that
> is only "this guest CPU doesn't support RAS notification and we
> will not notify it". And you must absolutely support AArch32 EL0,
> that's a requirement for getting this merged. It's not difficult.
sure, it needed. I absolutely follow your suggestion and handle AArch32
EL1 correctly in some way. it is not difficult.

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [Qemu-arm] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2018-01-11 10:33           ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-11 10:33 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Eduardo Habkost, kvm-devel, Michael S. Tsirkin, Marc Zyngier,
	Marcelo Tosatti, QEMU Developers, Xu Wei, qemu-arm, James Morse,
	Huangshaoyu, Igor Mammedov, Paolo Bonzini, Zhengqiang (turing),
	Shannon Zhao, Christoffer Dall, Richard Henderson

On 2018/1/11 17:53, Peter Maydell wrote:
>> we only support AArch64 kernel, not support AArch32
>>  kernel or AArch32 user space.
> Nope, you must handle AArch32 EL1 correctly in some way, even if that
> is only "this guest CPU doesn't support RAS notification and we
> will not notify it". And you must absolutely support AArch32 EL0,
> that's a requirement for getting this merged. It's not difficult.
sure, it needed. I absolutely follow your suggestion and handle AArch32
EL1 correctly in some way. it is not difficult.

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2018-01-09 17:30     ` [Qemu-devel] " Peter Maydell
@ 2018-01-13  5:24       ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-13  5:24 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter,

>> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> 
> This is still absolutely the wrong thing to do. Nothing should
> need to scan this array like this.

For the KVM mode, I use this function to set the ESR_ELx's value. If not set it using this way, do you have better method? Thanks!
>From my test, if kvm_inject_arm_sea() does not call this function kvm_arm_cpreg_value() to set the ESR_ELx's register, the guest
will have wrong ESR value. As shown the log in [1], QEMU sets the ESR to  0x96000414, but the guest's ESR value is 0x56000000 instead of 0x96000414.

[1]:
Taking exception 4 [Data Abort]
...from EL1 to EL1
...with ESR 0x25/0x96000414
...with FAR 0x0
...with ELR 0xffffff8008081a80
...to EL1 PC 0xffffff8008081a00 PSTATE 0x3c5

[   16.974756] Bad mode in Synchronous Abort handler detected on CPU0, code 0x56000000 -- SVC (AArch64)
[   16.989504] Internal error: Oops - bad mode: 0 [#1] SMP
[   16.990753] Modules linked in:
[   16.991462] CPU: 0 PID: 204 Comm: sh Tainted: G        W       4.13.0-rc4ajb-00005-g1353b1e-dirty #40
[   16.993533] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
[   16.995083] task: ffffffc03d3c2b00 task.stack: ffffffc03d2b0000
[   16.996448] PC is at vectors+0x280/0x784
[   16.997340] LR is at pl011_tx_empty+0x18/0x40


> 
>> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
>> +        const ARMCPRegInfo *ri;
>> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
>> +        if (!ri) {
>> +            continue;
>> +        }

[...]

> 
>> +
>> +    /* For the AArch64, instruction length is 32-bit */
>> +    esr |= ARM_EL_IL;
>> +    env->exception.syndrome = esr;
>> +
>> +    cc->do_interrupt(c);
>> +
>> +    /* set ESR_EL1 */
>> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
> 
> Breakpoint injection doesn't need to do this. Neither should this code.
As my above explanation, in the KVM mode, it needs to set the ESR_ELx in extra method.
the cc->do_interrupt(c) does not set ESR_ELx. so I use kvm_arm_cpreg_value()
to set it. whether you have better method to set the ESR_Elx except for my method?  Thanks.


> 
>> +    if (ret) {
>> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
>> +        abort();
>> +    }
>> +}
>> +
>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>
>> --
>> 1.8.3.1
> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2018-01-13  5:24       ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-13  5:24 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter,

>> +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> 
> This is still absolutely the wrong thing to do. Nothing should
> need to scan this array like this.

For the KVM mode, I use this function to set the ESR_ELx's value. If not set it using this way, do you have better method? Thanks!
>From my test, if kvm_inject_arm_sea() does not call this function kvm_arm_cpreg_value() to set the ESR_ELx's register, the guest
will have wrong ESR value. As shown the log in [1], QEMU sets the ESR to  0x96000414, but the guest's ESR value is 0x56000000 instead of 0x96000414.

[1]:
Taking exception 4 [Data Abort]
...from EL1 to EL1
...with ESR 0x25/0x96000414
...with FAR 0x0
...with ELR 0xffffff8008081a80
...to EL1 PC 0xffffff8008081a00 PSTATE 0x3c5

[   16.974756] Bad mode in Synchronous Abort handler detected on CPU0, code 0x56000000 -- SVC (AArch64)
[   16.989504] Internal error: Oops - bad mode: 0 [#1] SMP
[   16.990753] Modules linked in:
[   16.991462] CPU: 0 PID: 204 Comm: sh Tainted: G        W       4.13.0-rc4ajb-00005-g1353b1e-dirty #40
[   16.993533] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
[   16.995083] task: ffffffc03d3c2b00 task.stack: ffffffc03d2b0000
[   16.996448] PC is at vectors+0x280/0x784
[   16.997340] LR is at pl011_tx_empty+0x18/0x40


> 
>> +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
>> +        const ARMCPRegInfo *ri;
>> +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
>> +        if (!ri) {
>> +            continue;
>> +        }

[...]

> 
>> +
>> +    /* For the AArch64, instruction length is 32-bit */
>> +    esr |= ARM_EL_IL;
>> +    env->exception.syndrome = esr;
>> +
>> +    cc->do_interrupt(c);
>> +
>> +    /* set ESR_EL1 */
>> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
> 
> Breakpoint injection doesn't need to do this. Neither should this code.
As my above explanation, in the KVM mode, it needs to set the ESR_ELx in extra method.
the cc->do_interrupt(c) does not set ESR_ELx. so I use kvm_arm_cpreg_value()
to set it. whether you have better method to set the ESR_Elx except for my method?  Thanks.


> 
>> +    if (ret) {
>> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
>> +        abort();
>> +    }
>> +}
>> +
>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>
>> --
>> 1.8.3.1
> 
> thanks
> -- PMM
> 
> .
> 

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
  2018-01-13  5:24       ` [Qemu-devel] " gengdongjiu
@ 2018-01-13  8:27         ` gengdongjiu
  -1 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-13  8:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter,

On 2018/1/13 13:24, gengdongjiu wrote:
>>> +
>>> +    /* For the AArch64, instruction length is 32-bit */
>>> +    esr |= ARM_EL_IL;
>>> +    env->exception.syndrome = esr;
>>> +
>>> +    cc->do_interrupt(c);
>>> +
>>> +    /* set ESR_EL1 */
>>> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
>> Breakpoint injection doesn't need to do this. Neither should this code.
> As my above explanation, in the KVM mode, it needs to set the ESR_ELx in extra method.
> the cc->do_interrupt(c) does not set ESR_ELx. so I use kvm_arm_cpreg_value()
> to set it. whether you have better method to set the ESR_Elx except for my method?  Thanks.

If QEMU changes the KVM's registers, it needs to call write_list_to_kvmstate() to write the cpu->cpreg_values[] list
to KVM through KVM_SET_ONE_REG IOCTL[1]. In Qemu, now it should not have software path to change the cpu->cpreg_values[] list
except write_cpustate_to_list(). Here I can also call write_cpustate_to_list() instead of kvm_arm_cpreg_value() to change
cpu->cpreg_values[] list, but the write_cpustate_to_list() will write all the coprocessor state to the cpu->cpreg_values[] list,
we can not sure all the coprocessor states are right, so here I only change corresponding index value in this list using kvm_arm_cpreg_value().

Breakpoint injection that you mentioned should not change KVM register or not in the KVM mode.

[1]:
 kvm_arch_put_registers()
  -> write_list_to_kvmstate()
    -> write cpu->cpreg_values[] to the kernel KVM through KVM_SET_ONE_REG

> 
> 
>>> +    if (ret) {
>>> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
>>> +        abort();
>>> +    }
>>> +}
>>> +
>>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>>
>>> --
>>> 1.8.3.1

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [Qemu-devel] [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort
@ 2018-01-13  8:27         ` gengdongjiu
  0 siblings, 0 replies; 83+ messages in thread
From: gengdongjiu @ 2018-01-13  8:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Paolo Bonzini, Michael S. Tsirkin, Igor Mammedov, Shannon Zhao,
	Marcelo Tosatti, Richard Henderson, Eduardo Habkost, James Morse,
	Christoffer Dall, Marc Zyngier, kvm-devel, QEMU Developers,
	qemu-arm, Huangshaoyu, Zhengqiang (turing),
	Xu Wei

Hi Peter,

On 2018/1/13 13:24, gengdongjiu wrote:
>>> +
>>> +    /* For the AArch64, instruction length is 32-bit */
>>> +    esr |= ARM_EL_IL;
>>> +    env->exception.syndrome = esr;
>>> +
>>> +    cc->do_interrupt(c);
>>> +
>>> +    /* set ESR_EL1 */
>>> +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));
>> Breakpoint injection doesn't need to do this. Neither should this code.
> As my above explanation, in the KVM mode, it needs to set the ESR_ELx in extra method.
> the cc->do_interrupt(c) does not set ESR_ELx. so I use kvm_arm_cpreg_value()
> to set it. whether you have better method to set the ESR_Elx except for my method?  Thanks.

If QEMU changes the KVM's registers, it needs to call write_list_to_kvmstate() to write the cpu->cpreg_values[] list
to KVM through KVM_SET_ONE_REG IOCTL[1]. In Qemu, now it should not have software path to change the cpu->cpreg_values[] list
except write_cpustate_to_list(). Here I can also call write_cpustate_to_list() instead of kvm_arm_cpreg_value() to change
cpu->cpreg_values[] list, but the write_cpustate_to_list() will write all the coprocessor state to the cpu->cpreg_values[] list,
we can not sure all the coprocessor states are right, so here I only change corresponding index value in this list using kvm_arm_cpreg_value().

Breakpoint injection that you mentioned should not change KVM register or not in the KVM mode.

[1]:
 kvm_arch_put_registers()
  -> write_list_to_kvmstate()
    -> write cpu->cpreg_values[] to the kernel KVM through KVM_SET_ONE_REG

> 
> 
>>> +    if (ret) {
>>> +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
>>> +        abort();
>>> +    }
>>> +}
>>> +
>>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>>
>>> --
>>> 1.8.3.1

^ permalink raw reply	[flat|nested] 83+ messages in thread

end of thread, other threads:[~2018-01-13  8:30 UTC | newest]

Thread overview: 83+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-28  5:54 [PATCH v14 0/9] Add ARMv8 RAS virtualization support in QEMU Dongjiu Geng
2017-12-28  5:54 ` [Qemu-devel] " Dongjiu Geng
2017-12-28  5:54 ` [PATCH v14 1/9] ACPI: add some GHES structures and macros definition Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28 12:29   ` Igor Mammedov
2017-12-28 12:29     ` [Qemu-devel] " Igor Mammedov
2018-01-03 10:29     ` gengdongjiu
2018-01-03 10:29       ` [Qemu-devel] " gengdongjiu
2017-12-28  5:54 ` [PATCH v14 2/9] ACPI: Add APEI GHES table generation and CPER record support Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28 14:18   ` Igor Mammedov
2017-12-28 14:18     ` [Qemu-devel] " Igor Mammedov
2017-12-29  6:33     ` gengdongjiu
2017-12-29  6:33       ` [Qemu-devel] " gengdongjiu
2018-01-03  2:21     ` gengdongjiu
2018-01-03  2:21       ` [Qemu-devel] " gengdongjiu
2018-01-03 13:31       ` Igor Mammedov
2018-01-03 13:31         ` [Qemu-devel] " Igor Mammedov
2018-01-04  4:21         ` gengdongjiu
2018-01-04  4:21           ` [Qemu-devel] " gengdongjiu
2018-01-09 16:51       ` Peter Maydell
2018-01-09 16:51         ` [Qemu-devel] " Peter Maydell
2018-01-10  5:22         ` gengdongjiu
2018-01-10  5:22           ` [Qemu-devel] " gengdongjiu
2017-12-28  5:54 ` [PATCH v14 3/9] docs: APEI GHES generation and CPER record description Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28  5:54 ` [PATCH v14 4/9] ACPI: enable APEI GHES in the configure file Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2018-01-09 17:16   ` Peter Maydell
2018-01-09 17:16     ` [Qemu-devel] " Peter Maydell
2018-01-10 12:20     ` gengdongjiu
2018-01-10 12:20       ` [Qemu-devel] " gengdongjiu
2017-12-28  5:54 ` [PATCH v14 5/9] target-arm: kvm64: inject synchronous External Abort Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28 13:49   ` Igor Mammedov
2017-12-28 13:49     ` [Qemu-devel] " Igor Mammedov
2017-12-29  6:27     ` gengdongjiu
2017-12-29  6:27       ` [Qemu-devel] " gengdongjiu
2018-01-09 17:30   ` Peter Maydell
2018-01-09 17:30     ` [Qemu-devel] " Peter Maydell
2018-01-11  5:59     ` gengdongjiu
2018-01-11  5:59       ` [Qemu-devel] " gengdongjiu
2018-01-11  9:53       ` [Qemu-arm] " Peter Maydell
2018-01-11  9:53         ` [Qemu-devel] " Peter Maydell
2018-01-11 10:33         ` gengdongjiu
2018-01-11 10:33           ` [Qemu-devel] " gengdongjiu
2018-01-13  5:24     ` gengdongjiu
2018-01-13  5:24       ` [Qemu-devel] " gengdongjiu
2018-01-13  8:27       ` gengdongjiu
2018-01-13  8:27         ` [Qemu-devel] " gengdongjiu
2017-12-28  5:54 ` [PATCH v14 6/9] Move related hwpoison page functions to accel/kvm/ folder Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28  5:54 ` [PATCH v14 7/9] ARM: ACPI: Add GPIO notification type for hardware RAS error Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28 14:53   ` Igor Mammedov
2017-12-28 14:53     ` [Qemu-devel] " Igor Mammedov
2018-01-03  3:48     ` gengdongjiu
2018-01-03  3:48       ` [Qemu-devel] " gengdongjiu
2018-01-03 13:36       ` Igor Mammedov
2018-01-03 13:36         ` [Qemu-devel] " Igor Mammedov
2018-01-04  4:55         ` gengdongjiu
2017-12-28  5:54 ` [PATCH v14 8/9] hw/arm/virt: Add RAS platform version for migration Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28 14:58   ` Igor Mammedov
2017-12-28 14:58     ` [Qemu-devel] " Igor Mammedov
2018-01-03  4:02     ` gengdongjiu
2018-01-03  4:02       ` [Qemu-devel] " gengdongjiu
2018-01-09 15:42     ` Peter Maydell
2018-01-09 15:42       ` [Qemu-devel] " Peter Maydell
2017-12-28  5:54 ` [PATCH v14 9/9] target-arm: kvm64: handle SIGBUS signal from kernel or KVM Dongjiu Geng
2017-12-28  5:54   ` [Qemu-devel] " Dongjiu Geng
2017-12-28 15:07   ` Igor Mammedov
2017-12-28 15:07     ` [Qemu-devel] " Igor Mammedov
2018-01-03  9:13     ` gengdongjiu
2018-01-03  9:13       ` [Qemu-devel] " gengdongjiu
2018-01-03 13:44       ` Igor Mammedov
2018-01-03 13:44         ` [Qemu-devel] " Igor Mammedov
2018-01-04  6:31         ` gengdongjiu
2018-01-04  6:31           ` [Qemu-devel] " gengdongjiu
2018-01-09 17:14   ` Peter Maydell
2018-01-09 17:14     ` [Qemu-devel] " Peter Maydell
2018-01-10 11:56     ` gengdongjiu
2018-01-10 11:56       ` [Qemu-devel] " gengdongjiu

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.