Re: riscv disassembler error with pmpcfg0

2024-05-16 Thread Eric DeVolder
Thank you!
Eric






On Tuesday, May 14, 2024 at 12:19:55 AM CDT, Alistair Francis 
 wrote: 





On Thu, Apr 4, 2024 at 5:02 AM Eric DeVolder  wrote:
>
> I've been using QEMU8 to collect instruction information on U-Boot + OpenSBI.
>
> I'm running QEMU in this fashion to collect the information:
>
> # qemu-system-riscv64 -plugin file=qemu/build/contrib/plugins/libexeclog.so 
> -singlestep -d plugin,nochain -D execlog.txt ...
>
> When examining the instruction trace in execlog, I've noticed that the 
> disassembly for pmpcfg0 is erroneous, for example:
>
> 0, 0x5456, 0x3a002573, "csrrs                  a0,pmpcfg3,zero"
>
> the CSR encoded in the instruction above is 0x3a0, which is pmpcfg0 (which 
> also matches the code I'm examining).
>
> For the Uboot+OpenSBI code I'm examining, pmpcfg0/3 is the only one that 
> appears to have a problem.
>
> I also checked QEMU9 and it behaves as described above as well.
>
> I'm willing to provide a fix if I can get some advice/pointers on how this 
> disassembly statement is generated...I did take a quick look but it didn't 
> appear obvious how...

Thanks for pointing this out. This should fix the issue for you:
https://patchew.org/QEMU/20240514051615.330979-1-alistair.fran...@wdc.com/

Alistair


>
> Thanks,
> eric
>



riscv disassembler error with pmpcfg0

2024-04-03 Thread Eric DeVolder
I've been using QEMU8 to collect instruction information on U-Boot + OpenSBI.

I'm running QEMU in this fashion to collect the information:

# qemu-system-riscv64 -plugin file=qemu/build/contrib/plugins/libexeclog.so 
-singlestep -d plugin,nochain -D execlog.txt ...

When examining the instruction trace in execlog, I've noticed that the 
disassembly for pmpcfg0 is erroneous, for example:

0, 0x5456, 0x3a002573, "csrrs   a0,pmpcfg3,zero"

the CSR encoded in the instruction above is 0x3a0, which is pmpcfg0 (which also 
matches the code I'm examining).

For the Uboot+OpenSBI code I'm examining, pmpcfg0/3 is the only one that 
appears to have a problem.

I also checked QEMU9 and it behaves as described above as well.

I'm willing to provide a fix if I can get some advice/pointers on how this 
disassembly statement is generated...I did take a quick look but it didn't 
appear obvious how...

Thanks,
eric



[PATCH v2 1/3] ACPI: bios-tables-test.c step 2 (allowed-diff entries)

2023-05-17 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c,
set up bios-tables-test-allowed-diff.h to ignore the
imminent changes to the APIC tables, per step 2.

Signed-off-by: Eric DeVolder 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..66ae44e6b9 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,15 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/microvm/APIC",
+"tests/data/acpi/microvm/APIC.ioapic2",
+"tests/data/acpi/microvm/APIC.pcie",
+"tests/data/acpi/pc/APIC",
+"tests/data/acpi/pc/APIC.acpihmat",
+"tests/data/acpi/pc/APIC.cphp",
+"tests/data/acpi/pc/APIC.dimmpxm",
+"tests/data/acpi/q35/APIC",
+"tests/data/acpi/q35/APIC.acpihmat",
+"tests/data/acpi/q35/APIC.acpihmat-noinitiator",
+"tests/data/acpi/q35/APIC.core-count2",
+"tests/data/acpi/q35/APIC.cphp",
+"tests/data/acpi/q35/APIC.dimmpxm",
+"tests/data/acpi/q35/APIC.xapic",
-- 
2.31.1




[PATCH v2 2/3] ACPI: i386: bump to MADT to revision 3

2023-05-17 Thread Eric DeVolder
Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. Set .revision to 3 to match reality.

Link: https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devolder@ora
cle.com/T/#t
Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/i386/acpi-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..8a0932fe84 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -102,7 +102,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
 MachineClass *mc = MACHINE_GET_CLASS(x86ms);
 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = oem_id,
 .oem_table_id = oem_table_id };
 
 acpi_table_begin(, table_data);
-- 
2.31.1




[PATCH v2 3/3] ACPI: bios-tables-test.c step 5 (update expected table binaries)

2023-05-17 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
is step 5 and 6.

An examination of all the files impacted (as listed in
bios-tables-test-allowe-diff.h) shows only the MADT/APIC tables
bumping revision from 1 to 3, and a corresponding change to
the checksum. The below diff is typical:

 --- /tmp/asl-1F9641.dsl2023-05-16 15:18:31.292579156 -0400
 +++ /tmp/asl-GVD741.dsl2023-05-16 15:18:31.291579149 -0400
 @@ -1,32 +1,32 @@
  /*
   * Intel ACPI Component Architecture
   * AML/ASL+ Disassembler version 20230331 (64-bit version)
   * Copyright (c) 2000 - 2023 Intel Corporation
   *
 - * Disassembly of tests/data/acpi/pc/APIC, Tue May 16 15:18:31 2023
 + * Disassembly of /tmp/aml-R4D741, Tue May 16 15:18:31 2023
   *
   * ACPI Data Table [APIC]
   *
   * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue (in 
hex)
   */

  [000h  004h]   Signature : "APIC"[Multiple APIC 
Description Table (MADT)]
  [004h 0004 004h]Table Length : 0078
 -[008h 0008 001h]Revision : 01
 -[009h 0009 001h]Checksum : 8A
 +[008h 0008 001h]Revision : 03
 +[009h 0009 001h]Checksum : 88
  [00Ah 0010 006h]  Oem ID : "BOCHS "
  [010h 0016 008h]Oem Table ID : "BXPC"
  [018h 0024 004h]Oem Revision : 0001
  [01Ch 0028 004h] Asl Compiler ID : "BXPC"
  [020h 0032 004h]   Asl Compiler Revision : 0001

  [024h 0036 004h]  Local Apic Address : FEE0
  [028h 0040 004h]   Flags (decoded below) : 0001
   PC-AT Compatibility : 1

  [02Ch 0044 001h]   Subtable Type : 00 [Processor Local APIC]
  [02Dh 0045 001h]  Length : 08
  [02Eh 0046 001h]Processor ID : 00
  [02Fh 0047 001h]   Local Apic ID : 00
  [030h 0048 004h]   Flags (decoded below) : 0001
 Processor Enabled : 1
 @@ -81,24 +81,24 @@
  [06Bh 0107 001h]  Source : 0B
  [06Ch 0108 004h]   Interrupt : 000B
  [070h 0112 002h]   Flags (decoded below) : 000D
  Polarity : 1
  Trigger Mode : 3

  [072h 0114 001h]   Subtable Type : 04 [Local APIC NMI]
  [073h 0115 001h]  Length : 06
  [074h 0116 001h]Processor ID : FF
  [075h 0117 002h]   Flags (decoded below) : 
  Polarity : 0
  Trigger Mode : 0
  [077h 0119 001h]Interrupt Input LINT : 01

  Raw Table Data: Length 120 (0x78)

 -: 41 50 49 43 78 00 00 00 01 8A 42 4F 43 48 53 20  // APICx.BOCHS
 +: 41 50 49 43 78 00 00 00 03 88 42 4F 43 48 53 20  // APICx.BOCHS
  0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43  // BXPCBXPC
  0020: 01 00 00 00 00 00 E0 FE 01 00 00 00 00 08 00 00  // 
  0030: 01 00 00 00 01 0C 00 00 00 00 C0 FE 00 00 00 00  // 
  0040: 02 0A 00 00 02 00 00 00 00 00 02 0A 00 05 05 00  // 
  0050: 00 00 0D 00 02 0A 00 09 09 00 00 00 0D 00 02 0A  // 
  0060: 00 0A 0A 00 00 00 0D 00 02 0A 00 0B 0B 00 00 00  // 
  0070: 0D 00 04 06 FF 00 00 01      // 

Signed-off-by: Eric DeVolder 
---
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 tests/qtest/bios-tables-test-allowed-diff.h   |  14 --
 15 files changed, 14 deletions(-)

diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC
index 
68dbd44a7e35a356083f086df60f70e424c4249f..672764e711d80402890902ba9ded10915770e84c
 100644
GIT binary patch
delta 16
XcmZ>B<8ln}barE4U|=qq$Ylcn95e$)

delta 16
XcmZ>B<8ln}barE4U|=kn$Ylcn95Mq&

[PATCH v2 0/3] ACPI: i386: bump MADT to revision 3

2023-05-17 Thread Eric DeVolder
The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

 e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be 
onlined for x2APIC")

Discussion on this topic can be located here:

 
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t

which resulted in the following fixes in Linux 6.3-rc5:

 a74fabfbd1b7: ("x86/ACPI/boot: Use FADT version to check support for online 
capable")
 fed8d8773b8e: ("x86/acpi/boot: Correct acpi_is_processor_usable() check")

However, as part of the investigation into resolving this breakage, I
learned that i386 QEMU reports revision 1, while technically it
generates revision 3.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
 5.2.11.13 Local SAPIC Structure added two new fields:
  ACPI Processor UID Value
  ACPI Processor UID String
 5.2.10.14 Platform Interrupt Sources Structure:
  Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
 Added a section describing guidelines for the ordering of
 processors in the MADT to support proper boot processor
 and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
 Adds Processor Local x2APIC structure type 9
 Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
 Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- version 45, is indeed accurate!
6.2b5   Section 5.2.12
 GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
 Adds Local APIC Flags Online Capable!
 Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
 Adds Multiprocessor Wakeup Structure type 0x10
 (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures.
So the QEMU i386 MADT revision can safely be moved to 3.

So, set the MADT revision to 3.

Regards,
Eric
---
v2: 17may2023
 - Fix problems with the binary tables for the bios-tables-test.c
   and make check.

v1: 15may2023
 - initial
---
Eric DeVolder (3):
  ACPI: bios-tables-test.c step 2 (allowed-diff entries)
  ACPI: i386: bump to MADT to revision 3
  ACPI: bios-tables-test.c step 5 (update expected table binaries)

 hw/i386/acpi-common.c |   2 +-
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 15 files changed, 1 insertion(+), 1 deletion(-)

-- 
2.31.1




Re: [PATCH 2/3] ACPI: i386: bump to MADT to revision 3

2023-05-16 Thread Eric DeVolder




On 5/16/23 07:51, Ani Sinha wrote:

On Tue, May 16, 2023 at 6:01 PM Igor Mammedov  wrote:


On Mon, 15 May 2023 16:33:10 -0400
Eric DeVolder  wrote:


Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. Set .revision to 3 to match reality.

Link: https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devolder@ora
cle.com/T/#t
Signed-off-by: Eric DeVolder 
---
  hw/i386/acpi-common.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..8a0932fe84 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -102,7 +102,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
  MachineClass *mc = MACHINE_GET_CLASS(x86ms);
  const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
  AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = oem_id,
  .oem_table_id = oem_table_id };

  acpi_table_begin(, table_data);


make check fails for me at this point
(my guess is that not all APIC tables are whitelisted)


I think the patchset needs to be rebased and the blobs regenerated.


So I've been trying to overcome this today and not having much luck.

When I run "make check V=2", I see at the end:

Summary of Failures:

 45/786 qemu:qtest+qtest-i386 / qtest-i386/bios-tables-test
 68/786 qemu:qtest+qtest-x86_64 / qtest-x86_64/bios-tables-test

If I go look at 45/786, for example, I see:

Looking for expected file 'tests/data/acpi/pc/FACP'
Using expected file 'tests/data/acpi/pc/FACP'
Looking for expected file 'tests/data/acpi/pc/APIC'
Using expected file 'tests/data/acpi/pc/APIC'
Looking for expected file 'tests/data/acpi/pc/HPET'
Using expected file 'tests/data/acpi/pc/HPET'
Looking for expected file 'tests/data/acpi/pc/WAET'
Using expected file 'tests/data/acpi/pc/WAET'
Looking for expected file 'tests/data/acpi/pc/FACS'
Using expected file 'tests/data/acpi/pc/FACS'
Looking for expected file 'tests/data/acpi/pc/DSDT'
Using expected file 'tests/data/acpi/pc/DSDT'
acpi-test: Warning! APIC binary file mismatch. Actual [aml:/tmp/aml-R4D741], Expected 
[aml:tests/data/acpi/pc/APIC].

See source file tests/qtest/bios-tables-test.c for instructions on how to 
update expected files.
acpi-test: Warning! APIC mismatch. Actual [asl:/tmp/asl-GVD741.dsl, aml:/tmp/aml-R4D741], Expected 
[asl:/tmp/asl-1F9641.dsl, aml:tests/data/acpi/pc/APIC].

--- /tmp/asl-1F9641.dsl 2023-05-16 15:18:31.292579156 -0400
+++ /tmp/asl-GVD741.dsl 2023-05-16 15:18:31.291579149 -0400
@@ -1,32 +1,32 @@
 /*
  * Intel ACPI Component Architecture
  * AML/ASL+ Disassembler version 20230331 (64-bit version)
  * Copyright (c) 2000 - 2023 Intel Corporation
  *
- * Disassembly of tests/data/acpi/pc/APIC, Tue May 16 15:18:31 2023
+ * Disassembly of /tmp/aml-R4D741, Tue May 16 15:18:31 2023
  *
  * ACPI Data Table [APIC]
  *
  * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue (in 
hex)
  */

 [000h  004h]   Signature : "APIC"[Multiple APIC 
Description Table (MADT)]
 [004h 0004 004h]Table Length : 0078
-[008h 0008 001h]Revision : 01
-[009h 0009 001h]Checksum : 8A
+[008h 0008 001h]Revision : 03
+[009h 0009 001h]Checksum : 88
 [00Ah 0010 006h]  Oem ID : "BOCHS "
 [010h 0016 008h]Oem Table ID : "BXPC"
 [018h 0024 004h]Oem Revision : 0001
 [01Ch 0028 004h] Asl Compiler ID : "BXPC"
 [020h 0032 004h]   Asl Compiler Revision : 0001
[...]

And the q35 looks very very similar.

It suggests that I need to list tests/data/acpi/pc/APIC, which I have done
in bios-tables-test-allowed-diff.h:

/* List of comma-separated changed AML files to ignore */
"tests/data/acpi/pc/APIC",
"tests/data/acpi/q35/APIC",
"tests/data/acpi/microvm/APIC",
"tests/data/acpi/virt/APIC",

But as I looked closer at the files that changed in the last step
of the previous post, there are a bunch of them:

 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/a

[PATCH 3/3] ACPI: bios-tables-test.c step 5 (update expected table binaries)

2023-05-15 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
is step 5 and 6.

The MADT/APIC table diffs show (for pc, q35 and microvm) bumping
revision from 1 to 3 (and checksum changing accordingly):

 Using expected file 'tests/data/acpi/pc/DSDT'
 acpi-test: Warning! APIC binary file mismatch. Actual [aml:/tmp/aml-9UKC51], 
Expected [aml:tests/data/acpi/pc/APIC].
 See source file tests/qtest/bios-tables-test.c for instructions on how to 
update expected files.
 acpi-test: Warning! APIC mismatch. Actual [asl:/tmp/asl-CFKC51.dsl, 
aml:/tmp/aml-9UKC51], Expected [asl:/tmp/asl-TMFC51.dsl, 
aml:tests/data/acpi/pc/APIC].
 --- /tmp/asl-TMFC51.dsl2023-05-15 14:15:26.599183824 -0400
 +++ /tmp/asl-CFKC51.dsl2023-05-15 14:15:26.598183818 -0400
 @@ -1,32 +1,32 @@
  /*
   * Intel ACPI Component Architecture
   * AML/ASL+ Disassembler version 20230331 (64-bit version)
   * Copyright (c) 2000 - 2023 Intel Corporation
   *
 - * Disassembly of tests/data/acpi/pc/APIC, Mon May 15 14:15:26 2023
 + * Disassembly of /tmp/aml-9UKC51, Mon May 15 14:15:26 2023
   *
   * ACPI Data Table [APIC]
   *
   * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue (in 
hex)
   */

  [000h  004h]   Signature : "APIC"[Multiple APIC 
Description Table (MADT)]
  [004h 0004 004h]Table Length : 0078
 -[008h 0008 001h]Revision : 01
 -[009h 0009 001h]Checksum : 8A
 +[008h 0008 001h]Revision : 03
 +[009h 0009 001h]Checksum : 88
  [00Ah 0010 006h]  Oem ID : "BOCHS "
  [010h 0016 008h]Oem Table ID : "BXPC"
  [018h 0024 004h]Oem Revision : 0001
  [01Ch 0028 004h] Asl Compiler ID : "BXPC"
  [020h 0032 004h]   Asl Compiler Revision : 0001

  [024h 0036 004h]  Local Apic Address : FEE0
  [028h 0040 004h]   Flags (decoded below) : 0001
   PC-AT Compatibility : 1

  [02Ch 0044 001h]   Subtable Type : 00 [Processor Local APIC]
  [02Dh 0045 001h]  Length : 08
  [02Eh 0046 001h]Processor ID : 00
  [02Fh 0047 001h]   Local Apic ID : 00
  [030h 0048 004h]   Flags (decoded below) : 0001
 Processor Enabled : 1
 @@ -81,24 +81,24 @@
  [06Bh 0107 001h]  Source : 0B
  [06Ch 0108 004h]   Interrupt : 000B
  [070h 0112 002h]   Flags (decoded below) : 000D
  Polarity : 1
  Trigger Mode : 3

  [072h 0114 001h]   Subtable Type : 04 [Local APIC NMI]
  [073h 0115 001h]  Length : 06
  [074h 0116 001h]Processor ID : FF
  [075h 0117 002h]   Flags (decoded below) : 
  Polarity : 0
  Trigger Mode : 0
  [077h 0119 001h]Interrupt Input LINT : 01

  Raw Table Data: Length 120 (0x78)

 -: 41 50 49 43 78 00 00 00 01 8A 42 4F 43 48 53 20  // APICx.BOCHS
 +: 41 50 49 43 78 00 00 00 03 88 42 4F 43 48 53 20  // APICx.BOCHS
  0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43  // BXPCBXPC
  0020: 01 00 00 00 00 00 E0 FE 01 00 00 00 00 08 00 00  // 
  0030: 01 00 00 00 01 0C 00 00 00 00 C0 FE 00 00 00 00  // 
  0040: 02 0A 00 00 02 00 00 00 00 00 02 0A 00 05 05 00  // 
  0050: 00 00 0D 00 02 0A 00 09 09 00 00 00 0D 00 02 0A  // 
  0060: 00 0A 0A 00 00 00 0D 00 02 0A 00 0B 0B 00 00 00  // 
  0070: 0D 00 04 06 FF 00 00 01      // 

Signed-off-by: Eric DeVolder 
---
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 tests/qtest/bios-tables-test-allowed-diff.h   |   4 
 15 files changed, 4 deletions(

[PATCH 0/3] ACPI: i386: bump MADT to revision 3

2023-05-15 Thread Eric DeVolder
The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

 e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be 
onlined for x2APIC")

Discussion on this topic can be located here:

 
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t

which resulted in the following fixes in Linux 6.3-rc5:

 a74fabfbd1b7: ("x86/ACPI/boot: Use FADT version to check support for online 
capable")
 fed8d8773b8e: ("x86/acpi/boot: Correct acpi_is_processor_usable() check")

However, as part of the investigation into resolving this breakage, I
learned that i386 QEMU reports revision 1, while technically it
generates revision 3.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
 5.2.11.13 Local SAPIC Structure added two new fields:
  ACPI Processor UID Value
  ACPI Processor UID String
 5.2.10.14 Platform Interrupt Sources Structure:
  Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
 Added a section describing guidelines for the ordering of
 processors in the MADT to support proper boot processor
 and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
 Adds Processor Local x2APIC structure type 9
 Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
 Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- version 45, is indeed accurate!
6.2b5   Section 5.2.12
 GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
 Adds Local APIC Flags Online Capable!
 Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
 Adds Multiprocessor Wakeup Structure type 0x10
 (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures.
So the QEMU i386 MADT revision can safely be moved to 3.

So, set the MADT revision to 3.

Regards,
Eric
---
Eric DeVolder (3):
  ACPI: bios-tables-test.c step 2 (allowed-diff entries)
  ACPI: i386: bump to MADT to revision 3
  ACPI: bios-tables-test.c step 5 (update expected table binaries)

 hw/i386/acpi-common.c |   2 +-
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 15 files changed, 1 insertion(+), 1 deletion(-)

-- 
2.31.1




[PATCH 1/3] ACPI: bios-tables-test.c step 2 (allowed-diff entries)

2023-05-15 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c,
set up bios-tables-test-allowed-diff.h to exclude the
imminent changes to the APIC tables, per step 2.

Signed-off-by: Eric DeVolder 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..1e5e354ecf 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/APIC",
+"tests/data/acpi/q35/APIC",
+"tests/data/acpi/microvm/APIC",
+"tests/data/acpi/virt/APIC",
-- 
2.31.1




[PATCH 2/3] ACPI: i386: bump to MADT to revision 3

2023-05-15 Thread Eric DeVolder
Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. Set .revision to 3 to match reality.

Link: https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devolder@ora
cle.com/T/#t
Signed-off-by: Eric DeVolder 
---
 hw/i386/acpi-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..8a0932fe84 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -102,7 +102,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
 MachineClass *mc = MACHINE_GET_CLASS(x86ms);
 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = oem_id,
 .oem_table_id = oem_table_id };
 
 acpi_table_begin(, table_data);
-- 
2.31.1




Re: [PATCH v3 0/3] ACPI: i386: bump MADT to revision 5

2023-05-10 Thread Eric DeVolder




On 5/10/23 10:45, Igor Mammedov wrote:

On Wed, 10 May 2023 10:08:50 -0500
Eric DeVolder  wrote:


On 5/10/23 03:14, Igor Mammedov wrote:

On Fri, 5 May 2023 16:53:22 -0500
Eric DeVolder  wrote:
   

Thoughts?


I still don't think we need to bump x86 to rev 5 in QEMU.


Linux v6.3 has the fix merged (so crisis averted 8).
The investigation allowed me to opportunistically provide this patch.
I think this should receive serious consideration for merging,
more so because generating MADT .revision 3 and reporting .revision 1
seems wrong to me.


It's a way much simpler to bump revision to 3 without introducing
OnlineCapable handling. So if you post rev3 patch, I'll gladly
ack it.
(+include kernel commit ids of kernel side fix, so if someone
stumbles upon it, one can easily find what to backport)


OK, I'll do that. It'll be next week as I'm on a short week this week.


This patch seems really straight forward, and low risk, now.

   

eric

On 4/21/23 16:48, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be onlined 
for x2APIC")

Discussion on this topic can be located here:


https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t


have your kernel fix landed up upstream?
   

Yes, merged and available in v6.3.



which resulted in the following fixes Linux in 6.3-rc5:

a74fabfbd1b7: ("x86/ACPI/boot: Use FADT version to check support for online 
capable")
fed8d8773b8e: ("x86/acpi/boot: Correct acpi_is_processor_usable() check")

However, as part of the investigation into resolving this breakage, I
learned that i386 QEMU reports revision 1, while technically it
generates revision 3. Aarch64 generates and reports revision 4.

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
5.2.11.13 Local SAPIC Structure added two new fields:
 ACPI Processor UID Value
 ACPI Processor UID String
5.2.10.14 Platform Interrupt Sources Structure:
 Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
Added a section describing guidelines for the ordering of
processors in the MADT to support proper boot processor
and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
Adds Processor Local x2APIC structure type 9
Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- version 45, is indeed accurate!
6.2b5   Section 5.2.12
GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
Adds Local APIC Flags Online Capable!
Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
Adds Multiprocessor Wakeup Structure type 0x10
(change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures. A simple
search of x2apic within QEMU source and hw/i386/acpi-common.c
specifically reveals this. So the QEMU i386 MADT revision can safely
be moved to 3.

For the MADT revision change 3 -> 4, the spec adds support for the ARM
GIC structures. QEMU ARM does in fact generate and report revision 4.
As these will not be used by i386 QEMU, so then the QEMU i386 MADT
revision can safely be moved to 4 as well.

Now for the MADT revision change 4 -> 5, the spec adds the Online
Capable flag to the Local APIC structure, and the ARM GICC SPE
Overflow Interrupt field.


All ARM stuff is irrelevant in x86 patch
   

sure


For i386, the ARM SPE is not applicable.

For the i386 Local APIC flag Online Capable, the spec has certain rules
about this value. And in particuar setting this value now explicitly
indicates a hotpluggable CPU.

So this patch makes the needed chan

Re: [PATCH v3 0/3] ACPI: i386: bump MADT to revision 5

2023-05-10 Thread Eric DeVolder




On 5/10/23 03:14, Igor Mammedov wrote:

On Fri, 5 May 2023 16:53:22 -0500
Eric DeVolder  wrote:


Thoughts?


I still don't think we need to bump x86 to rev 5 in QEMU.


Linux v6.3 has the fix merged (so crisis averted 8).
The investigation allowed me to opportunistically provide this patch.
I think this should receive serious consideration for merging,
more so because generating MADT .revision 3 and reporting .revision 1
seems wrong to me.

This patch seems really straight forward, and low risk, now.




eric

On 4/21/23 16:48, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

   e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be onlined 
for x2APIC")

Discussion on this topic can be located here:

   
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t


have your kernel fix landed up upstream?


Yes, merged and available in v6.3.



which resulted in the following fixes Linux in 6.3-rc5:

   a74fabfbd1b7: ("x86/ACPI/boot: Use FADT version to check support for online 
capable")
   fed8d8773b8e: ("x86/acpi/boot: Correct acpi_is_processor_usable() check")

However, as part of the investigation into resolving this breakage, I
learned that i386 QEMU reports revision 1, while technically it
generates revision 3. Aarch64 generates and reports revision 4.

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
   5.2.11.13 Local SAPIC Structure added two new fields:
ACPI Processor UID Value
ACPI Processor UID String
   5.2.10.14 Platform Interrupt Sources Structure:
Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
   Added a section describing guidelines for the ordering of
   processors in the MADT to support proper boot processor
   and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
   Adds Processor Local x2APIC structure type 9
   Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
   Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- version 45, is indeed accurate!
6.2b5   Section 5.2.12
   GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
   Adds Local APIC Flags Online Capable!
   Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
   Adds Multiprocessor Wakeup Structure type 0x10
   (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures. A simple
search of x2apic within QEMU source and hw/i386/acpi-common.c
specifically reveals this. So the QEMU i386 MADT revision can safely
be moved to 3.

For the MADT revision change 3 -> 4, the spec adds support for the ARM
GIC structures. QEMU ARM does in fact generate and report revision 4.
As these will not be used by i386 QEMU, so then the QEMU i386 MADT
revision can safely be moved to 4 as well.

Now for the MADT revision change 4 -> 5, the spec adds the Online
Capable flag to the Local APIC structure, and the ARM GICC SPE
Overflow Interrupt field.


All ARM stuff is irrelevant in x86 patch


sure


For i386, the ARM SPE is not applicable.

For the i386 Local APIC flag Online Capable, the spec has certain rules
about this value. And in particuar setting this value now explicitly
indicates a hotpluggable CPU.

So this patch makes the needed changes to move i386 MADT to
revision 5.

Without these changes, the information below shows "how" CPU hotplug
breaks with the current upstream Linux kernel 6.3.  For example, a Linux
guest started with:


what's the status wrt current upstream kernel?
  

qemu cpu hotplug works with upstream kernel ( >= v6.3) but only because the
kernel fix allows the legacy fallback assumption that the non Enabled
cpus specified in MADT are online capable.

with this patch

Re: [PATCH v3 0/3] ACPI: i386: bump MADT to revision 5

2023-05-05 Thread Eric DeVolder

Thoughts?
eric

On 4/21/23 16:48, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

  e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be onlined 
for x2APIC")

Discussion on this topic can be located here:

  
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t

which resulted in the following fixes Linux in 6.3-rc5:

  a74fabfbd1b7: ("x86/ACPI/boot: Use FADT version to check support for online 
capable")
  fed8d8773b8e: ("x86/acpi/boot: Correct acpi_is_processor_usable() check")

However, as part of the investigation into resolving this breakage, I
learned that i386 QEMU reports revision 1, while technically it
generates revision 3. Aarch64 generates and reports revision 4.

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
  5.2.11.13 Local SAPIC Structure added two new fields:
   ACPI Processor UID Value
   ACPI Processor UID String
  5.2.10.14 Platform Interrupt Sources Structure:
   Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
  Added a section describing guidelines for the ordering of
  processors in the MADT to support proper boot processor
  and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
  Adds Processor Local x2APIC structure type 9
  Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
  Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- version 45, is indeed accurate!
6.2b5   Section 5.2.12
  GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
  Adds Local APIC Flags Online Capable!
  Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
  Adds Multiprocessor Wakeup Structure type 0x10
  (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures. A simple
search of x2apic within QEMU source and hw/i386/acpi-common.c
specifically reveals this. So the QEMU i386 MADT revision can safely
be moved to 3.

For the MADT revision change 3 -> 4, the spec adds support for the ARM
GIC structures. QEMU ARM does in fact generate and report revision 4.
As these will not be used by i386 QEMU, so then the QEMU i386 MADT
revision can safely be moved to 4 as well.

Now for the MADT revision change 4 -> 5, the spec adds the Online
Capable flag to the Local APIC structure, and the ARM GICC SPE
Overflow Interrupt field.

For i386, the ARM SPE is not applicable.

For the i386 Local APIC flag Online Capable, the spec has certain rules
about this value. And in particuar setting this value now explicitly
indicates a hotpluggable CPU.

So this patch makes the needed changes to move i386 MADT to
revision 5.

Without these changes, the information below shows "how" CPU hotplug
breaks with the current upstream Linux kernel 6.3.  For example, a Linux
guest started with:

  qemu-system-x86_64 -smp 30,maxcpus=32 ...

and then attempting to hotplug a CPU:

   (QEMU) device_add id=cpu30 driver=host-x86_64-cpu socket-id=0 core-id=30 
thread-id=0

fails with the following:

   APIC: NR_CPUS/possible_cpus limit of 30 reached. Processor 30/0x.
   ACPI: Unable to map lapic to logical cpu number
   acpi LNXCPU:1e: Enumeration failure

   # dmesg | grep smpboot
   smpboot: Allowing 30 CPUs, 0 hotplug CPUs
   smpboot: CPU0: Intel(R) Xeon(R) CPU D-1533 @ 2.10GHz (family: 0x)
   smpboot: Max logical packages: 1
   smpboot: Total of 30 processors activated (125708.76 BogoMIPS)

   # iasl -d /sys/firmware/tables/acpi/APIC
   [000h    4]Signature : "APIC"[Multiple APIC 
Descript
   [004h 0004   4] Table Length : 0170
   [008h 0008   1] Revision : 01  <=
   [009h 0009   1] Ch

[PATCH v3 0/3] ACPI: i386: bump MADT to revision 5

2023-04-21 Thread Eric DeVolder
form microcode: firmware: requesting intel-ucode/06-56-03

 # cat /sys/devices/system/cpu/online
 0-8

 (QEMU) device_del id=cpu8

 Broke affinity for irq 24
 CPU 8 is now offline

 # cat /sys/devices/system/cpu/online
 0-7

 RHEL 6.9
 kernel 2.6.32-696.el6.x86_64
 build Feb 21 2017 

Both of the above 'legacy' operating systems behaved as expected.

Regards,
Eric

---
v3: 21apr2023
 - Dropped ARM patch as there is no compelling need to move to
   MADT revision 5, per Michael Tsirkin.
 - Recoded the flags to be simpler, per Michael, Ani Sinha and
   Miguel Luis.
 - Regenerated the binary tables, as per bios-tables-test.c
   instructions.

v2: 18apr2023
 https://lists.gnu.org/archive/html/qemu-devel/2023-04/msg02576.html
 - Code formatting changes per Igor Mammedov
 - Included the steps in bios-tables-test.

v1: 28mar2023
 https://lists.gnu.org/archive/html/qemu-devel/2023-03/msg06705.html
 - Initial series for ARM and i386 MADT revision bump to 5.
Eric DeVolder (3):
  ACPI: bios-tables-test.c step 2 (allowed-diff entries)
  hw/acpi: i386: bump MADT to revision 5
  ACPI: bios-tables-test.c step 5 (updated expected table binaries)

 hw/i386/acpi-common.c |   4 ++--
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 15 files changed, 2 insertions(+), 2 deletions(-)

-- 
2.31.1




[PATCH v3 1/3] ACPI: bios-tables-test.c step 2 (allowed-diff entries)

2023-04-21 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change sets-up bios-tables-test-allowed-diff.h to exclude the
imminent changes to the APIC tables, per step 2.

Signed-off-by: Eric DeVolder 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..1e5e354ecf 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/APIC",
+"tests/data/acpi/q35/APIC",
+"tests/data/acpi/microvm/APIC",
+"tests/data/acpi/virt/APIC",
-- 
2.31.1




[PATCH v3 2/3] ACPI: i386: bump MADT to revision 5

2023-04-21 Thread Eric DeVolder
Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Link: https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devolder@ora
cle.com/T/#t
Signed-off-by: Eric DeVolder 
---
 hw/i386/acpi-common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..5a5e73c399 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -39,7 +39,7 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList *apic_ids,
 uint32_t apic_id = apic_ids->cpus[uid].arch_id;
 /* Flags – Local APIC Flags */
 uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+ 1 /* Enabled */ : 2 /* Online Capable */;
 
 /* ACPI spec says that LAPIC entry for non present
  * CPU may be omitted from MADT or it must be marked
@@ -102,7 +102,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
 MachineClass *mc = MACHINE_GET_CLASS(x86ms);
 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
 .oem_table_id = oem_table_id };
 
 acpi_table_begin(, table_data);
-- 
2.31.1




[PATCH v3 3/3] ACPI: bios-tables-test.c step 5 (updated expected table binaries)

2023-04-21 Thread Eric DeVolder
   Subtable Type : 02 [Interrupt Source Override]
  [069h 0105 001h]  Length : 0A
  [06Ah 0106 001h] Bus : 00
  [06Bh 0107 001h]  Source : 00
  [06Ch 0108 004h]   Interrupt : 0002
  [070h 0112 002h]   Flags (decoded below) : 
  Polarity : 0
  Trigger Mode : 0
 @@ -121,26 +121,26 @@
  [093h 0147 001h]  Source : 0B
  [094h 0148 004h]   Interrupt : 000B
  [098h 0152 002h]   Flags (decoded below) : 000D
  Polarity : 1
  Trigger Mode : 3

  [09Ah 0154 001h]   Subtable Type : 04 [Local APIC NMI]
  [09Bh 0155 001h]  Length : 06
  [09Ch 0156 001h]Processor ID : FF
  [09Dh 0157 002h]   Flags (decoded below) : 
  Polarity : 0
  Trigger Mode : 0
  [09Fh 0159 001h]Interrupt Input LINT : 01

  Raw Table Data: Length 160 (0xA0)

 -: 41 50 49 43 A0 00 00 00 01 18 42 4F 43 48 53 20  // APIC..BOCHS
 +: 41 50 49 43 A0 00 00 00 05 0C 42 4F 43 48 53 20  // APIC..BOCHS
  0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43  // BXPCBXPC
  0020: 01 00 00 00 00 00 E0 FE 01 00 00 00 00 08 00 00  // 
  0030: 01 00 00 00 00 08 01 01 01 00 00 00 00 08 02 02  // 
 -0040: 00 00 00 00 00 08 03 04 00 00 00 00 00 08 04 05  // 
 -0050: 00 00 00 00 00 08 05 06 00 00 00 00 01 0C 00 00  // 
 +0040: 02 00 00 00 00 08 03 04 02 00 00 00 00 08 04 05  // 
 +0050: 02 00 00 00 00 08 05 06 02 00 00 00 01 0C 00 00  // 
  0060: 00 00 C0 FE 00 00 00 00 02 0A 00 00 02 00 00 00  // 
  0070: 00 00 02 0A 00 05 05 00 00 00 0D 00 02 0A 00 09  // 
  0080: 09 00 00 00 0D 00 02 0A 00 0A 0A 00 00 00 0D 00  // 
  0090: 02 0A 00 0B 0B 00 00 00 0D 00 04 06 FF 00 00 01  // ....
 **
Signed-off-by: Eric DeVolder 
---
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 tests/data/acpi/virt/APIC | Bin 172 -> 172 bytes
 tests/data/acpi/virt/APIC.acpihmatvirt| Bin 412 -> 412 bytes
 tests/data/acpi/virt/APIC.topology| Bin 732 -> 732 bytes
 tests/qtest/bios-tables-test-allowed-diff.h   |   4 
 18 files changed, 4 deletions(-)

diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC
index 
68dbd44a7e35a356083f086df60f70e424c4249f..e1c72bd3e60e46acc2c8b3de14f5992946cd55a3
 100644
GIT binary patch
delta 16
XcmZ>B<8ln}barE4U|=nn$Ylcn95w?+

delta 16
XcmZ>B<8ln}barE4U|=kn$Ylcn95Mq&

diff --git a/tests/data/acpi/microvm/APIC.ioapic2 
b/tests/data/acpi/microvm/APIC.ioapic2
index 
3063c52cd3e9bbed29c06031b375900f4a49b9e0..7c4f1b61d6c37f893d0d46be44a00e3f54a27a75
 100644
GIT binary patch
delta 16
XcmWFv;|bPi%*U|_AE$mIb59$o{5

delta 16
XcmWFv;|bPi%*U|?*X$mIb59$Ev1

diff --git a/tests/data/acpi/microvm/APIC.pcie 
b/tests/data/acpi/microvm/APIC.pcie
index 
4e8f6ed8d6a866429fc17aecdeafc3fb5ef65fa3..23956151765cae221853d92448a619d5576119b5
 100644
GIT binary patch
delta 16
Xcmd1H<8ln}bk1X7U|_A7$dv*BBEAFe

delta 16
Xcmd1H<8ln}bk1X7U|_77$dv*BBDw?a

diff --git a/tests/data/acpi/pc/APIC b/tests/data/acpi/pc/APIC
index 
208331db53b7dd5c6205cce0e95427636b86dd64..48bdab41959d7895b01491c6136d7403df284f98
 100644
GIT binary patch
delta 16
Xcmb=Z;BpM`bgp1vU|?;V$dv~GB#;Co

delta 16
Xcmb=Z;BpM`bgp1vU|{T;$dv~GB#Z

delta 18
ZcmbQhIDwJNF~HM#0s{jBqxVFvHUKF)1V;b>

diff --git a/tests/data/acpi/q35/APIC b/tests/data/acpi/q35/APIC
index 
208331db53b7dd5c6205cce0e95427636b86dd64..48bdab41959d7895b01491c6136d7403df284f98
 100644
GIT binary patch
delta 16
Xcmb=Z;BpM`bgp1vU|?;V$dv~GB#;Co

delta 16
Xcmb=Z;BpM`bgp1vU|{T;$dv~GB#Z

del

Re: [PATCH v2 3/4] hw/acpi: i386: bump MADT to revision 5

2023-04-20 Thread Eric DeVolder




On 4/20/23 03:05, Ani Sinha wrote:

On Tue, Apr 18, 2023 at 10:22 PM Eric DeVolder  wrote:


Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Link: 
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t
Signed-off-by: Eric DeVolder 
---
  hw/i386/acpi-common.c | 13 ++---
  1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..286c1c5c32 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
  {
  uint32_t apic_id = apic_ids->cpus[uid].arch_id;
  /* Flags – Local APIC Flags */
-uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true : false;


how about "processor_enabled" instead of just "enabled" as the variable name.


+/*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+bool onlinecapable = enabled ? false : true;


ugh, how about uint32 onlinecapable = enabled? 0x0 : 0x2 ?


+uint32_t flags = onlinecapable ? 0x2 : 0x0 | /* Online Capable */
+ enabled ? 0x1 : 0x0; /* Enabled */


then here, flags = onlinecapable | processor_enabled? 0x1 : 0x0;



Colleague Miguel Luis pointed out that this is simpler and equivalent:

uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ? 1 /* Enabled */ : 2 /* Online 
Capable */;


Is that acceptable?
eric



  /* ACPI spec says that LAPIC entry for non present
   * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
  MachineClass *mc = MACHINE_GET_CLASS(x86ms);
  const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
  AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
  .oem_table_id = oem_table_id };

  acpi_table_begin(, table_data);
--
2.31.1





Re: [PATCH v2 3/4] hw/acpi: i386: bump MADT to revision 5

2023-04-19 Thread Eric DeVolder




On 4/19/23 09:56, Michael S. Tsirkin wrote:

On Tue, Apr 18, 2023 at 12:52:18PM -0400, Eric DeVolder wrote:

Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Link: 
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t
Signed-off-by: Eric DeVolder 
---
  hw/i386/acpi-common.c | 13 ++---
  1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..286c1c5c32 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
  {
  uint32_t apic_id = apic_ids->cpus[uid].arch_id;
  /* Flags – Local APIC Flags */
-uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true : false;
+/*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+bool onlinecapable = enabled ? false : true;


Pls write this as onlinecapable = !enabled or just open-code on the next
line - does not look like this variable adds  a lot of value.


Will do!


+uint32_t flags = onlinecapable ? 0x2 : 0x0 | /* Online Capable */
+ enabled ? 0x1 : 0x0; /* Enabled */
  
  /* ACPI spec says that LAPIC entry for non present

   * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
  MachineClass *mc = MACHINE_GET_CLASS(x86ms);
  const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
  AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
  .oem_table_id = oem_table_id };
  
  acpi_table_begin(, table_data);

--
2.31.1






Re: [PATCH v2 2/4] hw/acpi: arm: bump MADT to revision 5

2023-04-19 Thread Eric DeVolder




On 4/19/23 00:30, Michael S. Tsirkin wrote:

On Tue, Apr 18, 2023 at 12:52:17PM -0400, Eric DeVolder wrote:

Currently ARM QEMU generates, and reports, MADT revision 4. ACPI 6.3
introduces MADT revision 5.

For MADT revision 5, the GICC structure adds an SPE Overflow Interrupt
field. This new 2-byte field is created from the existing 3-byte
Reserved field. The spec indicates if the SPE overflow interrupt is
not supported, to zero the field.

Signed-off-by: Eric DeVolder 


So why do we bother changing this? I'd rather defer until
we actually intend to fill this field.


Perfectly reasonable to me. I'll drop the ARM change going forward.
eric




---
  hw/arm/virt-acpi-build.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 4156111d49..23268dd981 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -705,7 +705,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
  int i;
  VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
  const MemMapEntry *memmap = vms->memmap;
-AcpiTable table = { .sig = "APIC", .rev = 4, .oem_id = vms->oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = vms->oem_id,
  .oem_table_id = vms->oem_table_id };
  
  acpi_table_begin(, table_data);

@@ -763,7 +763,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
  /* Processor Power Efficiency Class */
  build_append_int_noprefix(table_data, 0, 1);
  /* Reserved */
-build_append_int_noprefix(table_data, 0, 3);
+build_append_int_noprefix(table_data, 0, 1);
+/* SPE overflow Interrupt */
+build_append_int_noprefix(table_data, 0, 2);
  }
  
  if (vms->gic_version != VIRT_GIC_VERSION_2) {

--
2.31.1






Re: [PATCH 2/2] hw/acpi: i386: bump MADT to revision 5

2023-04-18 Thread Eric DeVolder




On 4/12/23 02:58, Igor Mammedov wrote:

On Tue, 11 Apr 2023 18:00:49 +0200
Igor Mammedov  wrote:


On Tue, 28 Mar 2023 11:59:26 -0400
Eric DeVolder  wrote:


Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).


So spec mandates 3 possible states
   00t - not present and not can't be added later ever
   01t - present
   10t - not present but might be added later
and outlawed 11t combination

00t - doesn't make much sense (i.e. why put such entry in MADT in the 1st place)

but looking at kernel commit aa06e20f1be, it looks like
ACPI_MADT_ONLINE_CAPABLE was introduced to accommodate
firmware/hw folks who would stuff MADT with LAPIC entries
for all possible CPU models, and then patch it depending on
actually used CPU model instead of dynamically creating LAPIC
entries. (insane)


on second thought, QEMU doesn't need rev 5 MADT with this flag complications.
Also I see that kernel side fix ended up in checking ACPI spec version instead
of dealing with MADT revisions mess.

So for x86 lets bump revision to 3 or 4 to be in sync with
what QEMU actually uses.


If bumping to only 3 or 4, then there is no need for this patch series.

   


  

Signed-off-by: Eric DeVolder 
---
  hw/i386/acpi-common.c | 13 ++---
  1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..1e3a13a36c 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
  {
  uint32_t apic_id = apic_ids->cpus[uid].arch_id;
  /* Flags – Local APIC Flags */
-uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true /* Enabled */ : false;
+/*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+bool onlinecapable = enabled ? false : true; /* Online Capable */



+uint32_t flags = onlinecapable ? 0x2 : 0x0 |
+enabled ? 0x1 : 0x0;

align the last line with onlinecapable '

move /* Enabled */ and /* Online Capable */ comments right to magic values
i.e. onlinecapable ? 0x2 : 0x0 | /* Online Capable */ ...



Done.

I've gone ahead and posted a v2 with these changes; keeping MADT.revision at 5.
eric


  
  /* ACPI spec says that LAPIC entry for non present

   * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
  MachineClass *mc = MACHINE_GET_CLASS(x86ms);
  const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
  AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
  .oem_table_id = oem_table_id };
  
  acpi_table_begin(, table_data);








[PATCH v2 1/4] ACPI: bios-tables-test.c step 2 (allowed-diff entries)

2023-04-18 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change sets-up bios-tables-test-allowed-diff.h to exclude the
imminent changes to the APIC tables, per step 2.

Signed-off-by: Eric DeVolder 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..1e5e354ecf 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/APIC",
+"tests/data/acpi/q35/APIC",
+"tests/data/acpi/microvm/APIC",
+"tests/data/acpi/virt/APIC",
-- 
2.31.1




[PATCH v2 0/4] hw/acpi: bump MADT to revision 5

2023-04-18 Thread Eric DeVolder
r 8 APIC 0x8
 kvm-clock: cpu 8, msr 2830ed00
 Will online and init hotplugged CPU: 8
 microcode: CPU8 sig=0x50663, pf=0x1, revision=0x71c
 platform microcode: firmware: requesting intel-ucode/06-56-03

 # cat /sys/devices/system/cpu/online
 0-8

 (QEMU) device_del id=cpu8

 Broke affinity for irq 24
 CPU 8 is now offline

 # cat /sys/devices/system/cpu/online
 0-7

 RHEL 6.9
 kernel 2.6.32-696.el6.x86_64
 build Feb 21 2017 

Both of the above 'legacy' operating systems behaved as expected.

Regards,
Eric

---
v2: 18apr2023
 - Code formatting changes per Igor Mammedov
 - Included the steps in bios-tables-test.

v1: 28mar2023
 https://lists.gnu.org/archive/html/qemu-devel/2023-03/msg06705.html
 - Initial series for ARM and i386 MADT revision bump to 5.

Eric DeVolder (4):
  ACPI: bios-tables-test.c step 2 (allowed-diff entries)
  hw/acpi: arm: bump MADT to revision 5
  hw/acpi: i386: bump MADT to revision 5
  ACPI: bios-tables-test.c step 5 (updated expected table binaries)

 hw/arm/virt-acpi-build.c  |   6 --
 hw/i386/acpi-common.c |  13 ++---
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.xapic| Bin 2686 -> 2686 bytes
 tests/data/acpi/virt/APIC | Bin 172 -> 172 bytes
 tests/data/acpi/virt/APIC.acpihmatvirt| Bin 412 -> 412 bytes
 tests/data/acpi/virt/APIC.topology| Bin 732 -> 732 bytes
 19 files changed, 14 insertions(+), 5 deletions(-)

-- 
2.31.1




[PATCH v2 3/4] hw/acpi: i386: bump MADT to revision 5

2023-04-18 Thread Eric DeVolder
Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Link: 
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t
Signed-off-by: Eric DeVolder 
---
 hw/i386/acpi-common.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..286c1c5c32 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
 {
 uint32_t apic_id = apic_ids->cpus[uid].arch_id;
 /* Flags – Local APIC Flags */
-uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true : false;
+/*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+bool onlinecapable = enabled ? false : true;
+uint32_t flags = onlinecapable ? 0x2 : 0x0 | /* Online Capable */
+ enabled ? 0x1 : 0x0; /* Enabled */
 
 /* ACPI spec says that LAPIC entry for non present
  * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
 MachineClass *mc = MACHINE_GET_CLASS(x86ms);
 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
 .oem_table_id = oem_table_id };
 
 acpi_table_begin(, table_data);
-- 
2.31.1




[PATCH v2 4/4] ACPI: bios-tables-test.c step 5 (updated expected table binaries)

2023-04-18 Thread Eric DeVolder
FE 01 00 00 00 00 08 00 00  // 
  0030: 01 00 00 00 01 0C 00 00 00 00 C0 FE 00 00 00 00  // 
  0040: 02 0A 00 00 02 00 00 00 00 00 02 0A 00 05 05 00  // 
  0050: 00 00 0D 00 02 0A 00 09 09 00 00 00 0D 00 02 0A  // 
  0060: 00 0A 0A 00 00 00 0D 00 02 0A 00 0B 0B 00 00 00  // 
  0070: 0D 00 04 06 FF 00 00 01  // 

The diff below show ARM MADT revision change to 5.

 --- /tmp/asl-O2P921.dsl2023-04-18 10:41:56.560930849 -0400
 +++ /tmp/asl-XJR921.dsl2023-04-18 10:41:56.558930836 -0400
 @@ -1,32 +1,32 @@
  /*
   * Intel ACPI Component Architecture
   * AML/ASL+ Disassembler version 20230331 (64-bit version)
   * Copyright (c) 2000 - 2023 Intel Corporation
   *
 - * Disassembly of tests/data/acpi/virt/APIC, Tue Apr 18 10:41:56 2023
 + * Disassembly of /tmp/aml-ACR921, Tue Apr 18 10:41:56 2023
   *
   * ACPI Data Table [APIC]
   *
   * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue (in 
hex)
   */

  [000h  004h]   Signature : "APIC"[Multiple APIC 
Description Table (MADT)]
  [004h 0004 004h]Table Length : 00AC
 -[008h 0008 001h]Revision : 04
 -[009h 0009 001h]Checksum : 47
 +[008h 0008 001h]Revision : 05
 +[009h 0009 001h]Checksum : 46
  [00Ah 0010 006h]  Oem ID : "BOCHS "
  [010h 0016 008h]Oem Table ID : "BXPC"
  [018h 0024 004h]Oem Revision : 0001
  [01Ch 0028 004h] Asl Compiler ID : "BXPC"
  [020h 0032 004h]   Asl Compiler Revision : 0001

  [024h 0036 004h]  Local Apic Address : 
  [028h 0040 004h]   Flags (decoded below) : 
   PC-AT Compatibility : 0

  [02Ch 0044 001h]   Subtable Type : 0C [Generic Interrupt 
Distributor]
  [02Dh 0045 001h]  Length : 18
  [02Eh 0046 002h]Reserved : 
  [030h 0048 004h]   Local GIC Hardware ID : 
  [034h 0052 008h]Base Address : 0800
  [03Ch 0060 004h]  Interrupt Base : 
 @@ -55,27 +55,27 @@
  [091h 0145 001h]Reserved : 00
  [092h 0146 002h]  SPE Overflow Interrupt : 
  [094h 0148 002h]  TRBE Interrupt : 180D

  [094h 0148 001h]   Subtable Type : 0D [Generic MSI Frame]
  [095h 0149 001h]  Length : 18
  [096h 0150 002h]Reserved : 
  [098h 0152 004h]MSI Frame ID : 
  [09Ch 0156 008h]Base Address : 0802
  [0A4h 0164 004h]   Flags (decoded below) : 0001
Select SPI : 1
  [0A8h 0168 002h]   SPI Count : 0040
  [0AAh 0170 002h]SPI Base : 0050

  Raw Table Data: Length 172 (0xAC)

 -: 41 50 49 43 AC 00 00 00 04 47 42 4F 43 48 53 20  // APIC.GBOCHS
 +: 41 50 49 43 AC 00 00 00 05 46 42 4F 43 48 53 20  // APIC.FBOCHS
  0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43  // BXPCBXPC
  0020: 01 00 00 00 00 00 00 00 00 00 00 00 0C 18 00 00  // 
  0030: 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00  // 
  0040: 02 00 00 00 0B 50 00 00 00 00 00 00 00 00 00 00  // .P..
  0050: 01 00 00 00 00 00 00 00 17 00 00 00 00 00 00 00  // 
  0060: 00 00 00 00 00 00 01 08 00 00 00 00 00 00 04 08  // 
  0070: 00 00 00 00 00 00 03 08 00 00 00 00 00 00 00 00  // 
  0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  // 
  0090: 00 00 00 00 0D 18 00 00 00 00 00 00 00 00 02 08  // ....
  00A0: 00 00 00 00 01 00 00 00 40 00 50 00  // @.P.

Signed-off-by: Eric DeVolder 
---
 tests/data/acpi/microvm/APIC  | Bin 70 -> 70 bytes
 tests/data/acpi/microvm/APIC.ioapic2  | Bin 82 -> 82 bytes
 tests/data/acpi/microvm/APIC.pcie | Bin 110 -> 110 bytes
 tests/data/acpi/pc/APIC   | Bin 120 -> 120 bytes
 tests/data/acpi/pc/APIC.acpihmat  | Bin 128 -> 128 bytes
 tests/data/acpi/pc/APIC.cphp  | Bin 160 -> 160 bytes
 tests/data/acpi/pc/APIC.dimmpxm   | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC  | Bin 120 -> 120 bytes
 tests/data/acpi/q35/APIC.acpihmat | Bin 128 -> 128 bytes
 tests/data/acpi/q35/APIC.acpihmat-noinitiator | Bin 144 -> 144 bytes
 tests/data/acpi/q35/APIC.core-count2  | Bin 2478 -> 2478 bytes
 tests/data/acpi/q35/APIC.cphp | Bin 160 -> 160 bytes
 tests/data/acpi/q35/APIC.dimmpxm  | Bin 144 -> 144 bytes

[PATCH v2 2/4] hw/acpi: arm: bump MADT to revision 5

2023-04-18 Thread Eric DeVolder
Currently ARM QEMU generates, and reports, MADT revision 4. ACPI 6.3
introduces MADT revision 5.

For MADT revision 5, the GICC structure adds an SPE Overflow Interrupt
field. This new 2-byte field is created from the existing 3-byte
Reserved field. The spec indicates if the SPE overflow interrupt is
not supported, to zero the field.

Signed-off-by: Eric DeVolder 
---
 hw/arm/virt-acpi-build.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 4156111d49..23268dd981 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -705,7 +705,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 int i;
 VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
 const MemMapEntry *memmap = vms->memmap;
-AcpiTable table = { .sig = "APIC", .rev = 4, .oem_id = vms->oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = vms->oem_id,
 .oem_table_id = vms->oem_table_id };
 
 acpi_table_begin(, table_data);
@@ -763,7 +763,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 /* Processor Power Efficiency Class */
 build_append_int_noprefix(table_data, 0, 1);
 /* Reserved */
-build_append_int_noprefix(table_data, 0, 3);
+build_append_int_noprefix(table_data, 0, 1);
+/* SPE overflow Interrupt */
+build_append_int_noprefix(table_data, 0, 2);
 }
 
 if (vms->gic_version != VIRT_GIC_VERSION_2) {
-- 
2.31.1




Re: [PATCH 0/2] hw/acpi: bump MADT to revision 5

2023-04-04 Thread Eric DeVolder

I'm back from travel and catching up. More info below.
eric


On 3/31/23 11:25, Igor Mammedov wrote:

On Wed, 29 Mar 2023 12:47:05 -0400
"Michael S. Tsirkin"  wrote:


On Wed, Mar 29, 2023 at 08:14:37AM -0500, Eric DeVolder wrote:



On 3/29/23 00:19, Michael S. Tsirkin wrote:

Hmm I don't think we can reasonably make such a change for 8.0.
Seems too risky.
Also, I feel we want to have an internal (with "x-" prefix") flag to
revert to old behaviour, in case of breakage on some guests.  and maybe
we want to keep old revision for old machine types.

Ok, what option name, for keeping old behavior, would you like?


Don't much care. x-madt-rev?


if it works fine (cold & hot-plug) with older linux/windows guests
I'd rather avoid adding compat knob (we typically do that in ACPI tables
only when change breaks something).

(as old guest I'd define WinXP sp3 (/me wonders if we  still care about
dead EOLed OS) perhaps WS2008 would be a better minimum target these days
and RHEL6 (or some older ACPI enabled kernel with hotplug support))


Thus far I've tested this patch series with the following guests. In both cases 
below,
the guest started with -smp 8,maxcpus=16, and I simply attempted to hot plug 
and unplug
cpu8, with: device_add id=cpu8 driver=host-x86_64-cpu socket-id=0 core-id=8 
thread-id=0.

1) Windows Server 2008.
 In Windows, after logging-in, I close the first full-screen window
 and then "Server Manager" window pops up. I navigate to left hand
 pane and choose Diagnostics -> Device Manager -> Processors.
 I count them before and after.
 When hotplugging a cpu, you can see the new processor show up in the
 processor list. That is, it goes from 8 to 9.
 When hot unplugging the CPU, Windows refuses:

  The 'Intel(R) Xeon(R) CPU D-1533 @ 2.10GHz' device is not
  removable and cannot be ejected or unplugged.

2) RHEL 6.9
 From dmesg:
 ACPI: APIC 7ffe32f0 000F0 (v05 BOCHS  BXPC0001 BXPC 0001)
 SMP: Allowing 16 CPUs, 8 hotplug CPUs

 # cat /sys/devices/system/cpu/online
 0-7

 (QEMU) device_add ...

 CPU 8 got hotplugged
 Booting Node 0 Processor 8 APIC 0x8
 kvm-clock: cpu 8, msr 2830ed00
 Will online and init hotplugged CPU: 8
 microcode: CPU8 sig=0x50663, pf=0x1, revision=0x71c
 platform microcode: firmware: requesting intel-ucode/06-56-03

 # cat /sys/devices/system/cpu/online
 0-8

 (QEMU) device_del ...

 Broke affinity for irq 24
 CPU 8 is now offline

 # cat /sys/devices/system/cpu/online
 0-7

 RHEL 6.9
 kernel 2.6.32-696.el6.x86_64
 build Feb 21 2017


So with these two older guest OS, it appears to still work. If there are others to be tested, let me 
know.










On Tue, Mar 28, 2023 at 11:59:24AM -0400, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

   commit e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be 
onlined for x2APIC")


Presumably it's being fixed? Link to discussion? Patch fixing that in
Linux?


https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t


Great! Maybe stick a Link: tag in the commit log.


Sure, will include that with v2.



So it's guest bug which is in process of being fixed.
(i.e. QEMU technically correct as long as MADT revision < 5)


Iiuc, if QEMU generates x2apic tables with .revision = 1, that is not correct
(as x2APIC shows up in .revision=3).
But if QEMU generates, apic, sapic, or x2apic tables with .revision = 5, that
is correct (as all are valid options thru .revision 5).



In this case I'd not touch x86 MADT at all (It should be upto
downstream distros to fix guest kernel).


Fwiw, this has been fixed and should show up in 6.3-rc6 this weekend.



Probably the same applies to ARM variant
i.e. we should bump rev only when current one gets in the way
(aka we are pulling in new fields/definitions from new version)



As part of the investigation into resolving this breakage, I learned
that i386 QEMU reports revision 1, while technically it is at revision 3.
(Arm QEMU reports revision 4, and that is valid/correct.)

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
   5.2.11.13 Local SAPIC Structure added two new fields:
ACPI Processor UID Value
ACPI Processor UID String
   5.2.10.14 Platform Interrupt Sources Structure:
Reserved changed to Platform Interrupt Sources Flags
3.0b2   Sect

Re: [PATCH 2/2] hw/acpi: i386: bump MADT to revision 5

2023-03-29 Thread Eric DeVolder




On 3/29/23 08:16, Eric DeVolder wrote:



On 3/29/23 00:03, Michael S. Tsirkin wrote:

On Tue, Mar 28, 2023 at 11:59:26AM -0400, Eric DeVolder wrote:

Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Signed-off-by: Eric DeVolder 


I am looking for ways to reduce risk of breakage with this.
We don't currently have a reason to change it if cpu
hotplug is off, do we? Maybe make it conditional on that.


By "cpu hotplug off", do you mean, for example, no maxcpus= option?
In other words, how should I detect "cpu hotplug off"?
eric



Actually, if, for example, one had -smp 30,maxcpus=32, then there would be two hotpluggable cpus 
reported, the last two with the Enabled=0 and Online Capable=1. If one had -smp 32 (ie "cpu hotplug 
off"), then all cpus would be reported as Enabled and no cpu would have its Online Capable flag set.


Granted in both cases, MADT.revision would report 5, but it would still be 
accurate.

eric








---
  hw/i386/acpi-common.c | 13 ++---
  1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..1e3a13a36c 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
  {
  uint32_t apic_id = apic_ids->cpus[uid].arch_id;
  /* Flags – Local APIC Flags */
-    uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+    bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true /* Enabled */ : false;
+    /*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+    bool onlinecapable = enabled ? false : true; /* Online Capable */
+    uint32_t flags = onlinecapable ? 0x2 : 0x0 |
+    enabled ? 0x1 : 0x0;
  /* ACPI spec says that LAPIC entry for non present
   * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
  MachineClass *mc = MACHINE_GET_CLASS(x86ms);
  const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
  AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-    AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+    AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
  .oem_table_id = oem_table_id };
  acpi_table_begin(, table_data);
--
2.31.1









Re: [PATCH 2/2] hw/acpi: i386: bump MADT to revision 5

2023-03-29 Thread Eric DeVolder




On 3/29/23 00:03, Michael S. Tsirkin wrote:

On Tue, Mar 28, 2023 at 11:59:26AM -0400, Eric DeVolder wrote:

Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Signed-off-by: Eric DeVolder 


I am looking for ways to reduce risk of breakage with this.
We don't currently have a reason to change it if cpu
hotplug is off, do we? Maybe make it conditional on that.


By "cpu hotplug off", do you mean, for example, no maxcpus= option?
In other words, how should I detect "cpu hotplug off"?
eric








---
  hw/i386/acpi-common.c | 13 ++---
  1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..1e3a13a36c 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
  {
  uint32_t apic_id = apic_ids->cpus[uid].arch_id;
  /* Flags – Local APIC Flags */
-uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true /* Enabled */ : false;
+/*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+bool onlinecapable = enabled ? false : true; /* Online Capable */
+uint32_t flags = onlinecapable ? 0x2 : 0x0 |
+enabled ? 0x1 : 0x0;
  
  /* ACPI spec says that LAPIC entry for non present

   * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
  MachineClass *mc = MACHINE_GET_CLASS(x86ms);
  const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
  AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
  .oem_table_id = oem_table_id };
  
  acpi_table_begin(, table_data);

--
2.31.1









Re: [PATCH 0/2] hw/acpi: bump MADT to revision 5

2023-03-29 Thread Eric DeVolder




On 3/29/23 00:19, Michael S. Tsirkin wrote:

Hmm I don't think we can reasonably make such a change for 8.0.
Seems too risky.
Also, I feel we want to have an internal (with "x-" prefix") flag to
revert to old behaviour, in case of breakage on some guests.  and maybe
we want to keep old revision for old machine types.

Ok, what option name, for keeping old behavior, would you like?




On Tue, Mar 28, 2023 at 11:59:24AM -0400, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

  commit e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be 
onlined for x2APIC")


Presumably it's being fixed? Link to discussion? Patch fixing that in
Linux?


https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t





As part of the investigation into resolving this breakage, I learned
that i386 QEMU reports revision 1, while technically it is at revision 3.
(Arm QEMU reports revision 4, and that is valid/correct.)

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
  5.2.11.13 Local SAPIC Structure added two new fields:
   ACPI Processor UID Value
   ACPI Processor UID String
  5.2.10.14 Platform Interrupt Sources Structure:
   Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
  Added a section describing guidelines for the ordering of
  processors in the MADT to support proper boot processor
  and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
  Adds Processor Local x2APIC structure type 9
  Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
  Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- yep it says version 45!
6.2b5   Section 5.2.12
  GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
  Adds Local APIC Flags Online Capable!
  Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
  Adds Multiprocessor Wakeup Structure type 0x10
  (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures. A simple
search of x2apic within QEMU source and hw/i386/acpi-common.c
specifically reveals this.


But not unconditionally.


I don't think that reporting revision 3 requires that generation of x2apic; one could still see 
apic, x2apic, or sapic in theory. I realize qemu doesn't do sapic...





So the QEMU i386 MADT revision can safely
be moved to 3.

For the MADT revision change 3 -> 4, the spec adds support for the ARM
GIC structures. QEMU ARM does in fact generate and report revision 4.
As these will not be used by i386 QEMU, so then the QEMU i386 MADT
revision can safely be moved to 4 as well.

Now for the MADT revision change 4 -> 5, the spec adds the Online
Capable flag to the Local APIC structure, and the ARM GICC SPE
Overflow Interrupt field.

For the ARM SPE, an existing 3-byte Reserved field is broken into a 1-
byte Reserved field and a 2-byte SPE field.  The spec says that is SPE
Overflow is not supported, it should be zero.

For the i386 Local APIC flag Online Capable, the spec has certain rules
about this value. And in particuar setting this value now explicitly
indicates a hotpluggable CPU.

So this patch makes the needed changes to move both ARM and i386 MADT
to revision 5. These are not complicated, thankfully.

Without these changes, the information below shows "how" CPU hotplug
breaks with the current upstream Linux kernel 6.3.  For example, a Linux
guest started with:

  qemu-system-x86_64 -smp 30,maxcpus=32 ...

and then attempting to hotplug a CPU:

   (QEMU) device_add id=cpu30 driver=host-x86_64-cpu socket-id=0 core-id=30 
thread-id=0

fails with the following:

   APIC: NR_CPUS/possible_cpus limit of 30 reached. Processor 30/0x.
   ACPI: Unable to map lapic to logical

Re: [PATCH 0/2] hw/acpi: bump MADT to revision 5

2023-03-28 Thread Eric DeVolder

I forgot to include the updated ACPI tables. I will do that as part of v2.
In the meantime, I appreciate any feedback...
eric

On 3/28/23 10:59, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

  commit e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be 
onlined for x2APIC")

As part of the investigation into resolving this breakage, I learned
that i386 QEMU reports revision 1, while technically it is at revision 3.
(Arm QEMU reports revision 4, and that is valid/correct.)

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
  5.2.11.13 Local SAPIC Structure added two new fields:
   ACPI Processor UID Value
   ACPI Processor UID String
  5.2.10.14 Platform Interrupt Sources Structure:
   Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
  Added a section describing guidelines for the ordering of
  processors in the MADT to support proper boot processor
  and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
  Adds Processor Local x2APIC structure type 9
  Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
  Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- yep it says version 45!
6.2b5   Section 5.2.12
  GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
  Adds Local APIC Flags Online Capable!
  Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
  Adds Multiprocessor Wakeup Structure type 0x10
  (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures. A simple
search of x2apic within QEMU source and hw/i386/acpi-common.c
specifically reveals this. So the QEMU i386 MADT revision can safely
be moved to 3.

For the MADT revision change 3 -> 4, the spec adds support for the ARM
GIC structures. QEMU ARM does in fact generate and report revision 4.
As these will not be used by i386 QEMU, so then the QEMU i386 MADT
revision can safely be moved to 4 as well.

Now for the MADT revision change 4 -> 5, the spec adds the Online
Capable flag to the Local APIC structure, and the ARM GICC SPE
Overflow Interrupt field.

For the ARM SPE, an existing 3-byte Reserved field is broken into a 1-
byte Reserved field and a 2-byte SPE field.  The spec says that is SPE
Overflow is not supported, it should be zero.

For the i386 Local APIC flag Online Capable, the spec has certain rules
about this value. And in particuar setting this value now explicitly
indicates a hotpluggable CPU.

So this patch makes the needed changes to move both ARM and i386 MADT
to revision 5. These are not complicated, thankfully.

Without these changes, the information below shows "how" CPU hotplug
breaks with the current upstream Linux kernel 6.3.  For example, a Linux
guest started with:

  qemu-system-x86_64 -smp 30,maxcpus=32 ...

and then attempting to hotplug a CPU:

   (QEMU) device_add id=cpu30 driver=host-x86_64-cpu socket-id=0 core-id=30 
thread-id=0

fails with the following:

   APIC: NR_CPUS/possible_cpus limit of 30 reached. Processor 30/0x.
   ACPI: Unable to map lapic to logical cpu number
   acpi LNXCPU:1e: Enumeration failure

   # dmesg | grep smpboot
   smpboot: Allowing 30 CPUs, 0 hotplug CPUs
   smpboot: CPU0: Intel(R) Xeon(R) CPU D-1533 @ 2.10GHz (family: 0x)
   smpboot: Max logical packages: 1
   smpboot: Total of 30 processors activated (125708.76 BogoMIPS)

   # iasl -d /sys/firmware/tables/acpi/APIC
   [000h    4]Signature : "APIC"[Multiple APIC 
Descript
   [004h 0004   4] Table Length : 0170
   [008h 0008   1] Revision : 01  <=
   [009h 0009   1] Checksum : 9C
   [00Ah 0010   6]   Oem ID : "BO

[PATCH 1/2] hw/acpi: arm: bump MADT to revision 5

2023-03-28 Thread Eric DeVolder
Currently ARM QEMU generates, and reports, MADT revision 4. ACPI 6.3
introduces MADT revision 5.

For MADT revision 5, the GICC structure adds an SPE Overflow Interrupt
field. This new 2-byte field is created from the existing 3-byte
Reserved field. The spec indicates if the SPE overflow interrupt is
not supported, to zero the field.

Signed-off-by: Eric DeVolder 
---
 hw/arm/virt-acpi-build.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 4156111d49..23268dd981 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -705,7 +705,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 int i;
 VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
 const MemMapEntry *memmap = vms->memmap;
-AcpiTable table = { .sig = "APIC", .rev = 4, .oem_id = vms->oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = vms->oem_id,
 .oem_table_id = vms->oem_table_id };
 
 acpi_table_begin(, table_data);
@@ -763,7 +763,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 /* Processor Power Efficiency Class */
 build_append_int_noprefix(table_data, 0, 1);
 /* Reserved */
-build_append_int_noprefix(table_data, 0, 3);
+build_append_int_noprefix(table_data, 0, 1);
+/* SPE overflow Interrupt */
+build_append_int_noprefix(table_data, 0, 2);
 }
 
 if (vms->gic_version != VIRT_GIC_VERSION_2) {
-- 
2.31.1




[PATCH 0/2] hw/acpi: bump MADT to revision 5

2023-03-28 Thread Eric DeVolder
  [020h 0032   4]Asl Compiler Revision : 0001

  ...

  [114h 0276   1]Subtable Type : 00 [Processor Local APIC]
  [115h 0277   1]   Length : 08
  [116h 0278   1] Processor ID : 1D
  [117h 0279   1]Local Apic ID : 1D
  [118h 0280   4]Flags (decoded below) : 0001
 Processor Enabled : 1  <=

  [11Ch 0284   1]Subtable Type : 00 [Processor Local APIC]
  [11Dh 0285   1]   Length : 08
  [11Eh 0286   1] Processor ID : 1E
  [11Fh 0287   1]Local Apic ID : 1E
  [120h 0288   4]Flags (decoded below) : 
 Processor Enabled : 0  <=

  [124h 0292   1]Subtable Type : 00 [Processor Local APIC]
  [125h 0293   1]   Length : 08
  [126h 0294   1] Processor ID : 1F
  [127h 0295   1]Local Apic ID : 1F
  [128h 0296   4]Flags (decoded below) : 
 Processor Enabled : 0  <=

The (latest upstream) Linux kernel sees 30 Enabled processors, and
does not consider processors 31 and 32 to be hotpluggable.

With this patch series applied, by bumping MADT to revision 5, the
latest upstream Linux kernel correctly identifies 30 CPUs plus 2
hotpluggable CPUS.

  CPU30 has been hot-added
  smpboot: Booting Node 0 Processor 30 APIC 0x1e
  Will online and init hotplugged CPU: 30

  # dmesg | grep smpboot
  smpboot: Allowing 32 CPUs, 2 hotplug CPUs
  smpboot: CPU0: Intel(R) Xeon(R) CPU D-1533 @ 2.10GHz (family: 0x6, model: 
0x56, stepping: 0x3)
  smpboot: Max logical packages: 2
  smpboot: Total of 30 processors activated (125708.76 BogoMIPS)

  # iasl -d /sys/firmware/tables/acpi/APIC
  [000h  004h]   Signature : "APIC"[Multiple APIC 
Descript
  [004h 0004 004h]Table Length : 0170
  [008h 0008 001h]Revision : 05  <=
  [009h 0009 001h]Checksum : 94
  [00Ah 0010 006h]  Oem ID : "BOCHS "
  [010h 0016 008h]Oem Table ID : "BXPC"
  [018h 0024 004h]Oem Revision : 0001
  [01Ch 0028 004h] Asl Compiler ID : "BXPC"
  [020h 0032 004h]   Asl Compiler Revision : 0001

  ...

  [114h 0276 001h]   Subtable Type : 00 [Processor Local APIC]
  [115h 0277 001h]  Length : 08
  [116h 0278 001h]Processor ID : 1D
  [117h 0279 001h]   Local Apic ID : 1D
  [118h 0280 004h]   Flags (decoded below) : 0001
 Processor Enabled : 1  <=
Runtime Online Capable : 0  <=

  [11Ch 0284 001h]   Subtable Type : 00 [Processor Local APIC]
  [11Dh 0285 001h]  Length : 08
  [11Eh 0286 001h]Processor ID : 1E
  [11Fh 0287 001h]   Local Apic ID : 1E
  [120h 0288 004h]   Flags (decoded below) : 0002
 Processor Enabled : 0  <=
Runtime Online Capable : 1  <=

  [124h 0292 001h]   Subtable Type : 00 [Processor Local APIC]
  [125h 0293 001h]  Length : 08
  [126h 0294 001h]Processor ID : 1F
  [127h 0295 001h]   Local Apic ID : 1F
  [128h 0296 004h]   Flags (decoded below) : 0002
     Processor Enabled : 0  <=
Runtime Online Capable : 1  <=

Regards,
Eric


Eric DeVolder (2):
  hw/acpi: arm: bump MADT to revision 5
  hw/acpi: i386: bump MADT to revision 5

 hw/arm/virt-acpi-build.c |  6 --
 hw/i386/acpi-common.c| 13 ++---
 2 files changed, 14 insertions(+), 5 deletions(-)

-- 
2.31.1




[PATCH 2/2] hw/acpi: i386: bump MADT to revision 5

2023-03-28 Thread Eric DeVolder
Currently i386 QEMU generates MADT revision 3, and reports
MADT revision 1. ACPI 6.3 introduces MADT revision 5.

For MADT revision 4, that introduces ARM GIC structures, which do
not apply to i386.

For MADT revision 5, the Local APIC flags introduces the Online
Capable bitfield.

Making MADT generate and report revision 5 will solve problems with
CPU hotplug (the Online Capable flag indicates hotpluggable CPUs).

Signed-off-by: Eric DeVolder 
---
 hw/i386/acpi-common.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 52e5c1439a..1e3a13a36c 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,8 +38,15 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList 
*apic_ids,
 {
 uint32_t apic_id = apic_ids->cpus[uid].arch_id;
 /* Flags – Local APIC Flags */
-uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
- 1 /* Enabled */ : 0;
+bool enabled = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ true /* Enabled */ : false;
+/*
+ * ACPI 6.3 5.2.12.2 Local APIC Flags: OnlineCapable must be 0
+ * if Enabled is set.
+ */
+bool onlinecapable = enabled ? false : true; /* Online Capable */
+uint32_t flags = onlinecapable ? 0x2 : 0x0 |
+enabled ? 0x1 : 0x0;
 
 /* ACPI spec says that LAPIC entry for non present
  * CPU may be omitted from MADT or it must be marked
@@ -102,7 +109,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
 MachineClass *mc = MACHINE_GET_CLASS(x86ms);
 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+AcpiTable table = { .sig = "APIC", .rev = 5, .oem_id = oem_id,
 .oem_table_id = oem_table_id };
 
 acpi_table_begin(, table_data);
-- 
2.31.1




Re: [PATCH v2] hw/acpi/erst.c: Fix memory handling issues

2022-10-24 Thread Eric DeVolder




On 10/24/22 10:42, Christian A. Ehrhardt wrote:

- Fix memset argument order: The second argument is
   the value, the length goes last.
- Fix an integer overflow reported by Alexander Bulekov.

Both issues allow the guest to overrun the host buffer
allocated for the ERST memory device.

Cc: Eric DeVolder 
Cc: qemu-sta...@nongnu.org
Fixes: f7e26ffa590 ("ACPI ERST: support for ACPI ERST feature")
Tested-by: Alexander Bulekov 
Signed-off-by: Christian A. Ehrhardt 


Reviewed-by: Eric DeVolder 

Thanks Christian!
eric


---
  hw/acpi/erst.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index df856b2669..aefcc03ad6 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -635,7 +635,7 @@ static unsigned read_erst_record(ERSTDeviceState *s)
  if (record_length < UEFI_CPER_RECORD_MIN_SIZE) {
  rc = STATUS_FAILED;
  }
-if ((s->record_offset + record_length) > exchange_length) {
+if (record_length > exchange_length - s->record_offset) {
  rc = STATUS_FAILED;
  }
  /* If all is ok, copy the record to the exchange buffer */
@@ -684,7 +684,7 @@ static unsigned write_erst_record(ERSTDeviceState *s)
  if (record_length < UEFI_CPER_RECORD_MIN_SIZE) {
  return STATUS_FAILED;
  }
-if ((s->record_offset + record_length) > exchange_length) {
+if (record_length > exchange_length - s->record_offset) {
  return STATUS_FAILED;
  }
  
@@ -716,7 +716,7 @@ static unsigned write_erst_record(ERSTDeviceState *s)

  if (nvram) {
  /* Write the record into the slot */
  memcpy(nvram, exchange, record_length);
-memset(nvram + record_length, exchange_length - record_length, 0xFF);
+memset(nvram + record_length, 0xFF, exchange_length - record_length);
  /* If a new record, increment the record_count */
  if (!record_found) {
  uint32_t record_count;





Re: [PATCH] hw/acpi/erst.c: Fix memset argument order

2022-10-21 Thread Eric DeVolder




On 10/20/22 01:14, Markus Armbruster wrote:

"Christian A. Ehrhardt"  writes:


Fix memset argument order: The second argument is
the value, the length goes last.


Impact of the bug?


Cc: Eric DeVolder 
Cc: qemu-sta...@nongnu.org
Fixes: f7e26ffa590 ("ACPI ERST: support for ACPI ERST feature")
Signed-off-by: Christian A. Ehrhardt 
---
  hw/acpi/erst.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index df856b2669..26391f93ca 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -716,7 +716,7 @@ static unsigned write_erst_record(ERSTDeviceState *s)

exchange_length = memory_region_size(>exchange_mr);

This is the size of the exchange buffer.

Aside: it's unsigned int, but memory_region_size() returns uint64_t.
Unclean if it fits, bug if it doesn't.

/* Validate record_offset */
if (s->record_offset > (exchange_length - UEFI_CPER_RECORD_MIN_SIZE)) {
return STATUS_FAILED;
}

/* Obtain pointer to record in the exchange buffer */
exchange = memory_region_get_ram_ptr(>exchange_mr);
exchange += s->record_offset;

/* Validate CPER record_length */
memcpy((uint8_t *)_length, 
[UEFI_CPER_RECORD_LENGTH_OFFSET],
sizeof(uint32_t));

Aside: record_length = *(uint32_t *)exchange[UEFI_CPER_RECORD_LENGTH_OFFSET]
would do, since UEFI_CPER_RECORD_LENGTH_OFFSET is a multiple of 4.


Igor requested I use memcpy() so that this would work on EB and EL hosts.



record_length = le32_to_cpu(record_length);
if (record_length < UEFI_CPER_RECORD_MIN_SIZE) {
return STATUS_FAILED;
}
if ((s->record_offset + record_length) > exchange_length) {
return STATUS_FAILED;
}

This ensures there are at least @record_length bytes of space left in
the exchange buffer.  Good.

[...]

  if (nvram) {
  /* Write the record into the slot */
  memcpy(nvram, exchange, record_length);


This first copies @record_length bytes into the exchange buffer.


-memset(nvram + record_length, exchange_length - record_length, 0xFF);
+memset(nvram + record_length, 0xFF, exchange_length - record_length);


The new code pads it to the full exchange buffer size.

The old code writes 0xFF bytes.

If 0xFF < exchange_length - record_length, the padding doesn't extend to
the end of the buffer.  Impact?


The purpose of the memset() is to ensure the slot does not contain any remnants of a previous 
record. There is no functional requirement for this; other than it was intended to prevent the 
possibility of leaking data.


If there were a previously deleted/overwritten record in that slot, then the tail of that record 
would remain. However, it still isn't visible upon the record read; it would only be visible by 
directly accessing the backing file/memory.




If 0xFF > exchange_length - record_length, we write beyond the end of
the buffer.  Impact?


There are two cases here, if the record is stored in any slot but the last, then it has the 
opportunity to corrupt the next adjacent slot/record. Given that the CPER format places the magic 
'CPER' as the first 4 bytes, then I believe that upon next read of this corrupted record, it will be 
rejected as it does not have a valid CPER header.


If the record is the last in the backing storage, then it would attempt to write beyond the end. The 
backing store is memory mapped into the guest, so I believe that an attempt to write beyond the end 
will result in a segfault.


Previously stated: "Well, this is a memory error, i.e. the potential impact is
anything from silent data corruption to arbitrary code execution.
Phillipe described this accurately as "Ouch".

Yes, ouch. I had it correct until patch series v7 (of v15); not that that is 
helpful.

However, I do not see a path to arbitrary code execution. The erroneous memset() will write out a 
constant value (exchange_length - record_length) for 0xFF bytes.


In terms of current Linux real world impact, ERST is used as pstore backend and writes to pstore 
typically only happen on kernel panic, if configured. Furthermore, the systemd-pstore service 
attempts to keep the pstore empty, so that reduces the chances of pstore/ERST filling up and 
reaching that last slot that could cause a segfault.


ERST can be written by MCE, I think; not sure how relevant that is to guests.

eric




  /* If a new record, increment the record_count */
  if (!record_found) {
  uint32_t record_count;






Re: [PATCH] hw/acpi/erst.c: Fix memset argument order

2022-10-19 Thread Eric DeVolder




On 10/19/22 14:37, Philippe Mathieu-Daudé wrote:

On 19/10/22 21:15, Christian A. Ehrhardt wrote:

Fix memset argument order: The second argument is
the value, the length goes last.

Cc: Eric DeVolder 
Cc: qemu-sta...@nongnu.org
Fixes: f7e26ffa590 ("ACPI ERST: support for ACPI ERST feature")
Signed-off-by: Christian A. Ehrhardt 
---
  hw/acpi/erst.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index df856b2669..26391f93ca 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -716,7 +716,7 @@ static unsigned write_erst_record(ERSTDeviceState *s)
  if (nvram) {
  /* Write the record into the slot */
  memcpy(nvram, exchange, record_length);
-    memset(nvram + record_length, exchange_length - record_length, 0xFF);
+    memset(nvram + record_length, 0xFF, exchange_length - record_length);

Ouch

Sheesh, I'd hate to be that guy...

Reviewed-by: Eric DeVolder 


Reviewed-by: Philippe Mathieu-Daudé 





Re: [PATCH] acpi/erst: fix fallthrough code upon validation failure

2022-05-19 Thread Eric DeVolder




On 5/13/22 09:10, Ani Sinha wrote:

At any step when any validation fail in check_erst_backend_storage(), there is
no need to continue further through other validation checks. Further, by
continuing even when record_size is 0, we run the risk of triggering a divide
by zero error if we continued with other validation checks. Hence, we should
simply return from this function upon validation failure.

CC: Peter Maydell 
CC: Eric DeVolder 
Signed-off-by: Ani Sinha 


Reviewed-by: Eric DeVolder 

My apologies, I've been away for the past week.
Thank you for taking the time to correct this issue!
eric


---
  hw/acpi/erst.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index de509c2b48..df856b2669 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -440,6 +440,7 @@ static void check_erst_backend_storage(ERSTDeviceState *s, 
Error **errp)
  (record_size >= 4096) /* PAGE_SIZE */
  )) {
  error_setg(errp, "ERST record_size %u is invalid", record_size);
+return;
  }
  
  /* Validity check header */

@@ -450,6 +451,7 @@ static void check_erst_backend_storage(ERSTDeviceState *s, 
Error **errp)
  (le16_to_cpu(header->reserved) == 0)
  )) {
  error_setg(errp, "ERST backend storage header is invalid");
+return;
  }
  
  /* Check storage_size against record_size */

@@ -457,6 +459,7 @@ static void check_erst_backend_storage(ERSTDeviceState *s, 
Error **errp)
   (record_size > s->storage_size)) {
  error_setg(errp, "ACPI ERST requires storage size be multiple of "
  "record size (%uKiB)", record_size);
+return;
  }
  
  /* Compute offset of first and last record storage slot */






Re: [PATCH v16] ACPI ERST: specification for ERST support

2022-03-01 Thread Eric DeVolder

Hi, just wondering when this is targeted for merge?
Thanks,
eric

On 2/7/22 01:02, Ani Sinha wrote:

From: Eric DeVolder 

Information on the implementation of the ACPI ERST support.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
  docs/specs/acpi_erst.rst | 200 +++
  docs/specs/index.rst |   1 +
  2 files changed, 201 insertions(+)
  create mode 100644 docs/specs/acpi_erst.rst

diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 00..a8a9d22d25
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+-
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
+independent of, and runs before, kdump.  In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+---
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object 
memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x1,share=on
 \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+   this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+   required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+   parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+   ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+   backend storage. Must be a power of two value greater than or
+   equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers.  All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION.  Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+--
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record.  Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that ident

Re: [PATCH] hw/acpi/erst: clean up unused IS_UEFI_CPER_RECORD macro

2022-02-15 Thread Eric DeVolder




On 2/15/22 09:31, Ani Sinha wrote:

This change is cosmetic. IS_UEFI_CPER_RECORD macro definition that was added
as a part of the ERST implementation seems to be unused. Remove it.

CC: Eric DeVolder 
Signed-off-by: Ani Sinha 


Thanks!
Reviewed-by: Eric DeVolder 


---
  hw/acpi/erst.c | 5 -
  1 file changed, 5 deletions(-)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index c0a23cf467..de509c2b48 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -80,11 +80,6 @@
  #define UEFI_CPER_RECORD_MIN_SIZE 128U
  #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
  #define UEFI_CPER_RECORD_ID_OFFSET 96U
-#define IS_UEFI_CPER_RECORD(ptr) \
-(((ptr)[0] == 'C') && \
- ((ptr)[1] == 'P') && \
- ((ptr)[2] == 'E') && \
- ((ptr)[3] == 'R'))
  
  /*

   * NOTE that when accessing CPER fields within a record, memcpy()





Re: [PATCH] docs/acpi/erst: add device id for ACPI ERST device in pci-ids.txt

2022-02-15 Thread Eric DeVolder




On 2/15/22 09:23, Ani Sinha wrote:

Adding device ID for ERST device in pci-ids.txt. It was missed when ERST
related patches were reviewed.

CC: Eric DeVolder 
Signed-off-by: Ani Sinha 


Thanks!
Reviewed-by: Eric DeVolder 


---
  docs/specs/pci-ids.txt | 1 +
  1 file changed, 1 insertion(+)

diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt
index 5e407a6f32..dd6859d039 100644
--- a/docs/specs/pci-ids.txt
+++ b/docs/specs/pci-ids.txt
@@ -65,6 +65,7 @@ PCI devices (other than virtio):
  1b36:000f  mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
  1b36:0010  PCIe NVMe device (-device nvme)
  1b36:0011  PCI PVPanic device (-device pvpanic-pci)
+1b36:0012  PCI ACPI ERST device (-device acpi-erst)
  
  All these devices are documented in docs/specs.
  





[PATCH v15 00/10] acpi: Error Record Serialization Table, ERST, support for QEMU

2022-01-28 Thread Eric DeVolder
This patchset introduces support for the ACPI Error Record
Serialization Table, ERST.

For background and implementation information, please see
docs/specs/acpi_erst.rst, which is patch 2/10.

Suggested-by: Konrad Wilk 
Signed-off-by: Eric DeVolder 

---
v15: 28jan2022
 - Changes to build_erst() and ACTION/VALUE context struct
   setup, per Michael.

v14: 26jan2022
 - Changed build_erst() to utilize a context structure for
   generating accesses to ACTION and VALUE, per Michael Tsirkin.
 - Other simplification per Ani Sinha.

v13: 24jan2022
 - v12 erroneously omitted step 6 of bios-tables-test.c, this
   has step 6 included.
 - No other changes to v12.

v12: 10jan2022
 - Converted macros in build_erst() to uppert to follow coding
   style, as pointed out by Michael Tsirkin.
 - And few items to help further simplify build_erst().

v11: 15dec2021
 - Simplified build_erst() via feedback from Michael Tsirkin
 - Addressed additional feedback from Ani Sinha

v10: 9dec2021
 - Addressed additional feedback from Ani Sinha

v9: 2dec2021
 - Addressed feedback from Ani Sinha

v8: 15oct2021
 - Added Kconfig option for ERST, per Ani Sinha
 - Fixed patch ordering, per Ani

v7: 7oct2021
 - style improvements, per Igor
 - use of endian accessors for storage header, per Igor
 - a number of optimizations and improvements, per Igor
 - updated spec for header, per Igor
 - updated spec for rst format, per Michael Tsirkin
 - updated spec for new record_size parameter
   Due to changes in the spec, I am not carrying the
   Acked-by from Ani Sinha.
 - changes for and testing of migration to systems with
   differing ERST_RECORD_SIZE

v6: 5aug2021
 - Fixed compile warning/error, per Michael Tsirkin
 - Fixed mingw32 build error, per Michael
 - Converted exchange buffer to MemoryBackend, per Igor
 - Migrated test to PCI, per Igor
 - Significantly reduced amount of copying, per Igor
 - Corrections/enhancements to acpi_erst.txt, per Igor
 - Many misc/other small items, per Igor

v5: 30jun2021
 - Create docs/specs/acpi_erst.txt, per Igor
 - Separate PCI BARs for registers and memory, per Igor
 - Convert debugging to use trace infrastructure, per Igor
 - Various other fixups, per Igor

v4: 11jun2021
 - Converted to a PCI device, per Igor.
 - Updated qtest.
 - Rearranged patches, per Igor.

v3: 28may2021
 - Converted to using a TYPE_MEMORY_BACKEND_FILE object rather than
   internal array with explicit file operations, per Igor.
 - Changed the way the qdev and base address are handled, allowing
   ERST to be disabled at run-time. Also aligns better with other
   existing code.

v2: 8feb2021
 - Added qtest/smoke test per Paolo Bonzini
 - Split patch into smaller chunks, per Igor Mammedov
 - Did away with use of ACPI packed structures, per Igor Mammedov

v1: 26oct2020
 - initial post

---
Eric DeVolder (10):
  ACPI ERST: bios-tables-test.c steps 1 and 2
  ACPI ERST: specification for ERST support
  ACPI ERST: PCI device_id for ERST
  ACPI ERST: header file for ERST
  ACPI ERST: support for ACPI ERST feature
  ACPI ERST: build the ACPI ERST table
  ACPI ERST: create ACPI ERST table for pc/x86 machines
  ACPI ERST: qtest for ERST
  ACPI ERST: bios-tables-test testcase
  ACPI ERST: step 6 of bios-tables-test.c

 docs/specs/acpi_erst.rst  |  200 +++
 hw/acpi/Kconfig   |6 +
 hw/acpi/erst.c| 1055 +
 hw/acpi/meson.build   |1 +
 hw/acpi/trace-events  |   15 +
 hw/i386/acpi-build.c  |   15 +
 hw/i386/acpi-microvm.c|   15 +
 include/hw/acpi/erst.h|   24 +
 include/hw/pci/pci.h  |1 +
 tests/data/acpi/microvm/ERST.pcie |  Bin 0 -> 912 bytes
 tests/data/acpi/pc/DSDT.acpierst  |  Bin 0 -> 5969 bytes
 tests/data/acpi/pc/ERST.acpierst  |  Bin 0 -> 912 bytes
 tests/data/acpi/q35/DSDT.acpierst |  Bin 0 -> 8306 bytes
 tests/data/acpi/q35/ERST.acpierst |  Bin 0 -> 912 bytes
 tests/qtest/bios-tables-test.c|   54 ++
 tests/qtest/erst-test.c   |  172 ++
 tests/qtest/meson.build   |2 +
 17 files changed, 1560 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst
 create mode 100644 hw/acpi/erst.c
 create mode 100644 include/hw/acpi/erst.h
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst
 create mode 100644 tests/qtest/erst-test.c

-- 
1.8.3.1




[PATCH v15 08/10] ACPI ERST: qtest for ERST

2022-01-28 Thread Eric DeVolder
This change provides a qtest that locates and then does a simple
interrogation of the ERST feature within the guest.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/erst-test.c | 172 
 tests/qtest/meson.build |   2 +
 2 files changed, 174 insertions(+)
 create mode 100644 tests/qtest/erst-test.c

diff --git a/tests/qtest/erst-test.c b/tests/qtest/erst-test.c
new file mode 100644
index 000..f9ad3c9
--- /dev/null
+++ b/tests/qtest/erst-test.c
@@ -0,0 +1,172 @@
+/*
+ * QTest testcase for acpi-erst
+ *
+ * Copyright (c) 2021 Oracle
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "libqos/libqos-pc.h"
+#include "libqos/libqtest.h"
+#include "qemu-common.h"
+
+#include "hw/pci/pci.h"
+
+static void save_fn(QPCIDevice *dev, int devfn, void *data)
+{
+QPCIDevice **pdev = (QPCIDevice **) data;
+
+*pdev = dev;
+}
+
+static QPCIDevice *get_erst_device(QPCIBus *pcibus)
+{
+QPCIDevice *dev;
+
+dev = NULL;
+qpci_device_foreach(pcibus,
+PCI_VENDOR_ID_REDHAT,
+PCI_DEVICE_ID_REDHAT_ACPI_ERST,
+save_fn, );
+g_assert(dev != NULL);
+
+return dev;
+}
+
+typedef struct _ERSTState {
+QOSState *qs;
+QPCIBar reg_bar, mem_bar;
+uint64_t reg_barsize, mem_barsize;
+QPCIDevice *dev;
+} ERSTState;
+
+#define ACTION 0
+#define VALUE 8
+
+static const char *reg2str(unsigned reg)
+{
+switch (reg) {
+case 0:
+return "ACTION";
+case 8:
+return "VALUE";
+default:
+return NULL;
+}
+}
+
+static inline uint32_t in_reg32(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint32_t res;
+
+res = qpci_io_readl(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %08x", name, res);
+
+return res;
+}
+
+static inline uint64_t in_reg64(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint64_t res;
+
+res = qpci_io_readq(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %016llx", name, (unsigned long long)res);
+
+return res;
+}
+
+static inline void out_reg32(ERSTState *s, unsigned reg, uint32_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%08x -> *%s", v, name);
+qpci_io_writel(s->dev, s->reg_bar, reg, v);
+}
+
+static inline void out_reg64(ERSTState *s, unsigned reg, uint64_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%016llx -> *%s", (unsigned long long)v, name);
+qpci_io_writeq(s->dev, s->reg_bar, reg, v);
+}
+
+static void cleanup_vm(ERSTState *s)
+{
+g_free(s->dev);
+qtest_shutdown(s->qs);
+}
+
+static void setup_vm_cmd(ERSTState *s, const char *cmd)
+{
+const char *arch = qtest_get_arch();
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+s->qs = qtest_pc_boot(cmd);
+} else {
+g_printerr("erst-test tests are only available on x86\n");
+exit(EXIT_FAILURE);
+}
+s->dev = get_erst_device(s->qs->pcibus);
+
+s->reg_bar = qpci_iomap(s->dev, 0, >reg_barsize);
+g_assert_cmpuint(s->reg_barsize, ==, 16);
+
+s->mem_bar = qpci_iomap(s->dev, 1, >mem_barsize);
+g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
+
+qpci_device_enable(s->dev);
+}
+
+static void test_acpi_erst_basic(void)
+{
+ERSTState state;
+uint64_t log_address_range;
+uint64_t log_address_length;
+uint32_t log_address_attr;
+
+setup_vm_cmd(,
+"-object memory-backend-file,"
+"mem-path=acpi-erst.XX,"
+"size=64K,"
+"share=on,"
+"id=nvram "
+"-device acpi-erst,"
+"memdev=nvram");
+
+out_reg32(, ACTION, 0xD);
+log_address_range = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xE);
+log_address_length = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xF);
+log_address_attr = in_reg32(, VALUE);
+
+/* Check log_address_range is not 0, ~0 or base */
+g_assert_cmpuint(log_address_range, !=,  0ULL);
+g_assert_cmpuint(log_address_range, !=, ~0ULL);
+g_assert_cmpuint(log_address_range, !=, state.reg_bar.addr);
+g_assert_cmpuint(log_address_range, ==, state.mem_bar.addr);
+
+/* Check log_address_length is bar1_size */
+g_assert_cmpuint(log_address_length, ==, state.mem_barsize);
+
+/* Check log_address_attr is 0 */
+g_assert_cmpuint(log_address_attr, ==, 0);
+
+cleanup_vm();
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+
+g_test_init(, , NULL);
+qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);

[PATCH v15 09/10] ACPI ERST: bios-tables-test testcase

2022-01-28 Thread Eric DeVolder
This change implements the test suite checks for the ERST table.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/bios-tables-test.c | 54 ++
 1 file changed, 54 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index e6b72d9..266b215 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1446,6 +1446,57 @@ static void test_acpi_piix4_tcg_acpi_hmat(void)
 test_acpi_tcg_acpi_hmat(MACHINE_PC);
 }
 
+static void test_acpi_erst(const char *machine)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+memset(, 0, sizeof(data));
+data.machine = machine;
+data.variant = ".acpierst";
+params = g_strdup_printf(
+" -object memory-backend-file,id=erstnvram,"
+"mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+free_test_data();
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+}
+
+static void test_acpi_piix4_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_PC);
+}
+
+static void test_acpi_q35_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_Q35);
+}
+
+static void test_acpi_microvm_acpi_erst(void)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+test_acpi_microvm_prepare();
+data.variant = ".pcie";
+data.tcg_only = true; /* need constant host-phys-bits */
+params = g_strdup_printf(" -machine microvm,"
+"acpi=on,ioapic2=off,rtc=off,pcie=on"
+" -object memory-backend-file,id=erstnvram,"
+   "mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+free_test_data();
+}
+
 static void test_acpi_virt_tcg(void)
 {
 test_data data = {
@@ -1675,6 +1726,8 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
 qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
 qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
+qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst);
+qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst);
 qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
 qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg);
 qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg);
@@ -1684,6 +1737,7 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs);
 if (strcmp(arch, "x86_64") == 0) {
 qtest_add_func("acpi/microvm/pcie", 
test_acpi_microvm_pcie_tcg);
+qtest_add_func("acpi/microvm/acpierst", 
test_acpi_microvm_acpi_erst);
 }
 }
 if (has_kvm) {
-- 
1.8.3.1




[PATCH v15 07/10] ACPI ERST: create ACPI ERST table for pc/x86 machines

2022-01-28 Thread Eric DeVolder
This change exposes ACPI ERST support for x86 guests.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/i386/acpi-build.c   | 15 +++
 hw/i386/acpi-microvm.c | 15 +++
 include/hw/acpi/erst.h |  5 +
 3 files changed, 35 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ce823e8..ebd47aa 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -43,6 +43,7 @@
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
 #include "hw/acpi/vmgenid.h"
+#include "hw/acpi/erst.h"
 #include "sysemu/tpm_backend.h"
 #include "hw/rtc/mc146818rtc_regs.h"
 #include "migration/vmstate.h"
@@ -74,6 +75,8 @@
 #include "hw/acpi/hmat.h"
 #include "hw/acpi/viot.h"
 
+#include CONFIG_DEVICES
+
 /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
  * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
  * a little bit, there should be plenty of free space since the DSDT
@@ -2575,6 +2578,18 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 vmgenid_dev = find_vmgenid_dev();
 if (vmgenid_dev) {
 acpi_add_table(table_offsets, tables_blob);
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index 196d318..68ca7e7 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -30,6 +30,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/acpi/utils.h"
+#include "hw/acpi/erst.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/i386/microvm.h"
 #include "hw/pci/pci.h"
@@ -40,6 +41,8 @@
 #include "acpi-common.h"
 #include "acpi-microvm.h"
 
+#include CONFIG_DEVICES
+
 static void acpi_dsdt_add_virtio(Aml *scope,
  MicrovmMachineState *mms)
 {
@@ -207,6 +210,18 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 xsdt = tables_blob->len;
 build_xsdt(tables_blob, tables->linker, table_offsets, x86ms->oem_id,
x86ms->oem_table_id);
diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
index 9d63717..b747fe7 100644
--- a/include/hw/acpi/erst.h
+++ b/include/hw/acpi/erst.h
@@ -16,4 +16,9 @@ void build_erst(GArray *table_data, BIOSLinker *linker, 
Object *erst_dev,
 
 #define TYPE_ACPI_ERST "acpi-erst"
 
+/* returns NULL unless there is exactly one device */
+static inline Object *find_erst_dev(void)
+{
+return object_resolve_path_type("", TYPE_ACPI_ERST, NULL);
+}
 #endif
-- 
1.8.3.1




[PATCH v15 06/10] ACPI ERST: build the ACPI ERST table

2022-01-28 Thread Eric DeVolder
This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/acpi/erst.c | 211 +
 1 file changed, 211 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..cd32aa7 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
 #define STATUS_RECORD_STORE_EMPTY 0x04
 #define STATUS_RECORD_NOT_FOUND   0x05
 
+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
 /* UEFI 2.1: Appendix N Common Platform Error Record */
 #define UEFI_CPER_RECORD_MIN_SIZE 128U
 #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,196 @@ typedef struct {
 
 /***/
 /***/
+typedef struct {
+GArray *table_data;
+pcibus_t bar;
+uint8_t instruction;
+uint8_t flags;
+uint8_t register_bit_width;
+pcibus_t register_offset;
+} BuildSerializationInstructionEntry;
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction(
+BuildSerializationInstructionEntry *e,
+uint8_t serialization_action,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(e->table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(e->table_data, e->instruction, 1);
+/* Flags */
+build_append_int_noprefix(e->table_data, e->flags, 1);
+/* Reserved */
+build_append_int_noprefix(e->table_data, 0, 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = e->register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = (uint8_t)ctz32(e->register_bit_width) - 2;
+gas.address = (uint64_t)(e->bar + e->register_offset);
+build_append_gas_from_struct(e->table_data, );
+/* Value */
+build_append_int_noprefix(e->table_data, value, 8);
+/* Mask */
+mask = (1ULL << (e->register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(e->table_data, mask, 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+unsigned action;
+GArray *table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+/* Contexts for the different ways ACTION and VALUE are accessed */
+BuildSerializationInstructionEntry rd_value_32_val = {
+.table_data = table_instruction_data, .bar = bar0, .flags = 0,
+.instruction = INST_READ_REGISTER_VALUE,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry rd_value_32 = {
+.table_data = table_instruction_data, .bar = bar0, .flags = 0,
+.instruction = INST_READ_REGISTER,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry rd_value_64 = {
+.table_data = table_instruction_data, .bar = bar0, .flags = 0,
+.instruction = INST_READ_REGISTER,
+.register_bit_width = 64,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry wr_value_32_val = {
+.table_data = table_instruction_data, .bar = bar0, .flags = 0,
+.instructio

[PATCH v15 04/10] ACPI ERST: header file for ERST

2022-01-28 Thread Eric DeVolder
This change introduces the public defintions for ACPI ERST.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 include/hw/acpi/erst.h | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 include/hw/acpi/erst.h

diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
new file mode 100644
index 000..9d63717
--- /dev/null
+++ b/include/hw/acpi/erst.h
@@ -0,0 +1,19 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_ACPI_ERST_H
+#define HW_ACPI_ERST_H
+
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id);
+
+#define TYPE_ACPI_ERST "acpi-erst"
+
+#endif
-- 
1.8.3.1




[PATCH v15 05/10] ACPI ERST: support for ACPI ERST feature

2022-01-28 Thread Eric DeVolder
This implements a PCI device for ACPI ERST. This implements the
non-NVRAM "mode" of operation for ERST as it is supported by
Linux and Windows.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/acpi/Kconfig  |   6 +
 hw/acpi/erst.c   | 844 +++
 hw/acpi/meson.build  |   1 +
 hw/acpi/trace-events |  15 +
 4 files changed, 866 insertions(+)
 create mode 100644 hw/acpi/erst.c

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b5..19caebd 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -10,6 +10,7 @@ config ACPI_X86
 select ACPI_HMAT
 select ACPI_PIIX4
 select ACPI_PCIHP
+select ACPI_ERST
 
 config ACPI_X86_ICH
 bool
@@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
 select ACPI
 select ACPI_MEMORY_HOTPLUG
 select ACPI_NVDIMM
+
+config ACPI_ERST
+bool
+default y
+depends on ACPI && PCI
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
new file mode 100644
index 000..fe9ba51
--- /dev/null
+++ b/hw/acpi/erst.c
@@ -0,0 +1,844 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+#include 
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-core.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/pci/pci.h"
+#include "qom/object_interfaces.h"
+#include "qemu/error-report.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/hostmem.h"
+#include "hw/acpi/erst.h"
+#include "trace.h"
+
+/* ACPI 4.0: Table 17-16 Serialization Actions */
+#define ACTION_BEGIN_WRITE_OPERATION 0x0
+#define ACTION_BEGIN_READ_OPERATION  0x1
+#define ACTION_BEGIN_CLEAR_OPERATION 0x2
+#define ACTION_END_OPERATION 0x3
+#define ACTION_SET_RECORD_OFFSET 0x4
+#define ACTION_EXECUTE_OPERATION 0x5
+#define ACTION_CHECK_BUSY_STATUS 0x6
+#define ACTION_GET_COMMAND_STATUS0x7
+#define ACTION_GET_RECORD_IDENTIFIER 0x8
+#define ACTION_SET_RECORD_IDENTIFIER 0x9
+#define ACTION_GET_RECORD_COUNT  0xA
+#define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
+#define ACTION_RESERVED  0xC
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
+#define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
+#define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10 /* ACPI 6.3 */
+
+/* ACPI 4.0: Table 17-17 Command Status Definitions */
+#define STATUS_SUCCESS0x00
+#define STATUS_NOT_ENOUGH_SPACE   0x01
+#define STATUS_HARDWARE_NOT_AVAILABLE 0x02
+#define STATUS_FAILED 0x03
+#define STATUS_RECORD_STORE_EMPTY 0x04
+#define STATUS_RECORD_NOT_FOUND   0x05
+
+/* UEFI 2.1: Appendix N Common Platform Error Record */
+#define UEFI_CPER_RECORD_MIN_SIZE 128U
+#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
+#define UEFI_CPER_RECORD_ID_OFFSET 96U
+#define IS_UEFI_CPER_RECORD(ptr) \
+(((ptr)[0] == 'C') && \
+ ((ptr)[1] == 'P') && \
+ ((ptr)[2] == 'E') && \
+ ((ptr)[3] == 'R'))
+
+/*
+ * NOTE that when accessing CPER fields within a record, memcpy()
+ * is utilized to avoid a possible misaligned access on the host.
+ */
+
+/*
+ * This implementation is an ACTION (cmd) and VALUE (data)
+ * interface consisting of just two 64-bit registers.
+ */
+#define ERST_REG_SIZE (16UL)
+#define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
+#define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
+
+/*
+ * ERST_RECORD_SIZE is the buffer size for exchanging ERST
+ * record contents. Thus, it defines the maximum record size.
+ * As this is mapped through a PCI BAR, it must be a power of
+ * two and larger than UEFI_CPER_RECORD_MIN_SIZE.
+ * The backing storage is divided into fixed size "slots",
+ * each ERST_RECORD_SIZE in length, and each "slot"
+ * storing a single record. No attempt at optimizing storage
+ * through compression, compaction, etc is attempted.
+ * NOTE that slot 0 is reserved for the backing storage header.
+ * Depending upon the size of the backing storage, additional
+ * slots will be part of the slot 0 header in order to account
+ * for a record_id for each available remaining slot.
+ */
+/* 8KiB records, not too small, not too big */
+#define ERST_RECORD_SIZE (8192UL)
+
+#define ACPI_ERST_MEMDEV_PROP "

[PATCH v15 10/10] ACPI ERST: step 6 of bios-tables-test.c

2022-01-28 Thread Eric DeVolder
 }

 @@ -1399,11 +1394,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS "

  Method (DVNT, 2, NotSerialized)
  {
 -If ((Arg0 & 0x08))
 -{
 -Notify (S18, Arg1)
 -}
 -
  If ((Arg0 & 0x10))
  {
  Notify (S20, Arg1)

diff q35/DSDT and q35/DSDT.acpierst:
 @@ -5,13 +5,13 @@
   *
   * Disassembling to symbolic ASL+ operators
   *
 - * Disassembly of tests/data/acpi/q35/DSDT, Thu Dec  2 10:10:13 2021
 + * Disassembly of tests/data/acpi/q35/DSDT.acpierst, Thu Dec  2 12:59:36 2021
   *
   * Original Table Header:
   * Signature"DSDT"
 - * Length   0x2061 (8289)
 + * Length   0x2072 (8306)
   * Revision 0x01  32-bit table (V1), no 64-bit math support
 - * Checksum 0xFA
 + * Checksum 0x9A
   * OEM ID   "BOCHS "
   * OEM Table ID "BXPC"
   * OEM Revision 0x0001 (1)
 @@ -3278,6 +3278,11 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS "
  }
  }

 +Device (S10)
 +{
 +Name (_ADR, 0x0002)  // _ADR: Address
 +}
 +
  Method (PCNT, 0, NotSerialized)
  {
  }

For both pc and q35, there is but a small difference between this
DSDT.acpierst and the corresponding DSDT. In both cases, the changes
occur under the hiearchy:

Scope (\_SB)
{
Scope (PCI0)
{

which leads me to believe that the change to the DSDT was needed
due to the introduction of the ERST PCI device.

And is explained in detail by Ani Sinha:
I have convinced myself of the changes we see in the DSDT tables.
On i440fx side, we are adding a non-hotpluggable pci device on slot 3.
So the changes we see are basically replacing an empty hotpluggable
slot on the pci root port with a non-hotplugggable device.
On q35, bsel on pcie root bus is not set (its not hotpluggable bus),
so the change basically adds the address enumeration for the device.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 tests/data/acpi/microvm/ERST.pcie   | Bin 0 -> 912 bytes
 tests/data/acpi/pc/DSDT.acpierst| Bin 0 -> 5969 bytes
 tests/data/acpi/pc/ERST.acpierst| Bin 0 -> 912 bytes
 tests/data/acpi/q35/DSDT.acpierst   | Bin 0 -> 8306 bytes
 tests/data/acpi/q35/ERST.acpierst   | Bin 0 -> 912 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   5 -
 6 files changed, 5 deletions(-)

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a6d0cb783831ebc18972ec57bb6c624438ff150d
 100644
GIT binary patch
literal 912
zcmaKoTMmLS5Jd;doACJehb6cK12OSWBYwCn7ocm^-rA|;CUz1YmosPDa=fm$hY?9$
z^LaU~(|o@yldVKV@Q+UZ@>zwpS)GZ(sO?Lc}v64j-jFC7yn9;D$INO8pFiUB7f+
zf49KN+;jDxe>nP4Iq`z#7tC?s!tc6i7Z+t!@(t>{e2`4%
zZhiFB_p5lnFb*Ui&1$pT3_)pk?J?$-jLiezjJ$6`=r)uYry0Rn7KuJIp)|!
zckaizM=~sYzU*-I~PkUtAn>Dr`~u=;o(_O$t$PK8~R}U#`{0u*{
zz`m8fl|Wu#ucTKJu-TjNQ`rN~%rBccG0yWwF_}_zQl+X71|-_g)Pr`x1*Xgb!>QealcAR5Lj8F@vR~_hFrfVBOumUtb3<
zL8GI#8|W0leXv|!GGL=~vE5*uM7z%Af!czNXYqlQL#IT$!9xR0zORu68XY#=M-SGy
z3b+$tZv(*Hu4BBt4F>MUo>Padde^ZZU%V_4TiQ&6ruaomTLcp<9-2bBZ=qyp40+
ziEQ&$6L)c>%cI)0;%@F~Or>jX}g)!VlmH>3A6L#ZGj;i8(jvxl3w$XL%gc
z#4Y0Q*ces>sy7Obm6bTnr@oqih!n=P&+!w*9R95=2i+)QqA9kLa1VJk2ES
zOh6C4;>puBt75SyO`ippr%I9Z{pk6j=(st4aP-WP=ov412KgP0p3z1}&)7R9%3U9d
z!>df~G};j<@%&-TL`!{M=J{^0EAj)b4{!p{wbpF1J^oV~LmWA@f?c-apx
zmJl5aIOP$4%5j~Id6TV0{V^u0sG`|bSAOB2V2gb1@Ki7>g+T~D<}I$cZmy;lKl#kP
zxAm*k{f|HWWb1z8<4?h6y1Bg6FLiOw7Z@DC0gGYf$3^AUwgVosAOD1e9Hex!P-c3u
zY%#r3y2G$SrRg@$K+^S+fmJX`o|0}AmQ(0%hN|GcJ*{Ry{RpZVR_9(>4G!#sMm9K*-Kb2oqvI?7dL24<1WVww+F6k
zrAwi@3blP`ov2|RQA!4yn|HMt+|rp;ky|p}*s4Bhi{tS7b7IwWYtO
z($_%y0DUt+12O0t{g!qm$i(>FX+UGsM;osE9mca!r!@5Ld6Jt2$-nabyyC?4*zT@l2
z4LgzF3U^-%E&8T*RhMxH{B|{Nmd$hyhrlm@q(4{QfcO=jBztZw|gWU^0Q+lFdc4
z;t%ATAUG5ws_1bncmXfi8SEC{UBmF!TrD{!GvtiVS87Q`#ts;JTa>Png~+QvKOAg(
z=l%H)^?9Gb?Lui47fY7Bv8_MKSPiRTs@3YkU)Q{@YvnKAT;;J8U>fgQ>9qeF0+gJ!
zS_V9pumOy9sSU)%^lS1X17`o1`MA>W^ePI^H@E*S%`|HOx^c$lLHVkhwcpCba771jDZ#SdZmhM`3K=q{%
zNdudV5*`|Tn?lmSM!~R<_iYsI+Q3HPu(0YhlR~GImZVAKI~h
z+O@D02|KpVC?DEYlCeYxd&-j!?Kerrtt;#;Pd>DJ8RM1`cI=OKE{vc{!8uv6Z~
u5j$m$OK@OMk$l8{6J=Z)1AB{Pv}@<7F~|QN>AydkHSF$IS^vS{(*FTuhT2R3

literal 0
HcmV?d1

diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7965ac2562e7b23bf1dc2caaf00ef66453c4f47a
 100644
GIT binary patch
literal 912
zcmaKoOAdlC6h$9Upg{N}4xO+BmS7+z{Ww`+N;?C6GO0l^KeF>#Er>E`f@jBlg
ziAb~?&(mq{$NOdKO+_MtIsSwBP(BS`
zh6Ua)#A*M6_AiN-%#j24ugI^+uZh>pkpuT{$ZyEEIpDYCx8#=`Con^
B

[PATCH v15 01/10] ACPI ERST: bios-tables-test.c steps 1 and 2

2022-01-28 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change adds empty placeholder files per step 1 for the new ERST
table, and excludes resulting changed files in bios-tables-test-allowed-diff.h
per step 2.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/microvm/ERST.pcie   | 0
 tests/data/acpi/pc/DSDT.acpierst| 0
 tests/data/acpi/pc/ERST.acpierst| 0
 tests/data/acpi/q35/DSDT.acpierst   | 0
 tests/data/acpi/q35/ERST.acpierst   | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 5 +
 6 files changed, 5 insertions(+)
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/DSDT.acpierst 
b/tests/data/acpi/q35/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/ERST.acpierst 
b/tests/data/acpi/q35/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523..603db07 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,6 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/DSDT.acpierst",
+"tests/data/acpi/pc/ERST.acpierst",
+"tests/data/acpi/q35/DSDT.acpierst",
+"tests/data/acpi/q35/ERST.acpierst",
+"tests/data/acpi/microvm/ERST.pcie",
-- 
1.8.3.1




[PATCH v15 02/10] ACPI ERST: specification for ERST support

2022-01-28 Thread Eric DeVolder
Information on the implementation of the ACPI ERST support.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 docs/specs/acpi_erst.rst | 200 +++
 1 file changed, 200 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst

diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 000..a8a9d22
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+-
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
+independent of, and runs before, kdump.  In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+---
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object 
memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x1,share=on
 \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+   this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+   required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+   parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+   ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+   backend storage. Must be a power of two value greater than or
+   equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers.  All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION.  Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+--
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record.  Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that identifies the contents
+as ERST and also facilitates efficient access to the records.
+Depending upon the size of the backend storage, additional slots will
+be designated

[PATCH v15 03/10] ACPI ERST: PCI device_id for ERST

2022-01-28 Thread Eric DeVolder
This change reserves the PCI device_id for the new ACPI ERST
device.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
Acked-by: Ani Sinha 
---
 include/hw/pci/pci.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 023abc0..c3f3c90 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -108,6 +108,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_MDPY0x000f
 #define PCI_DEVICE_ID_REDHAT_NVME0x0010
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
+#define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
1.8.3.1




Re: [PATCH v14 06/10] ACPI ERST: build the ACPI ERST table

2022-01-28 Thread Eric DeVolder




On 1/28/22 11:25, Ani Sinha wrote:


[snip]
On Fri, Jan 28, 2022 at 9:44 PM Michael S. Tsirkin mailto:m...@redhat.com>> wrote:




 > > > OK, here is the equivalent using struct assignment, is this what you 
were after?
 > > >
 > > >      BuildSerializationInstructionEntry base = {
 > > >          .table_data = table_instruction_data,
 > > >          .bar = bar0,
 > > >          .instruction = INST_WRITE_REGISTER,
 > > >          .flags = 0,
 > > >          .register_bit_width = 32,
 > > >          .register_offset = ERST_VALUE_OFFSET,
 > > >      };
 > > >      BuildSerializationInstructionEntry rd_value_32_val = base;
 > > >      rd_value_32_val.instruction = INST_READ_REGISTER_VALUE;
 > > >      BuildSerializationInstructionEntry rd_value_32 = base;
 > > >      rd_value_32.instruction = INST_READ_REGISTER;
 > > >      BuildSerializationInstructionEntry rd_value_64 = base;
 > > >      rd_value_64.instruction = INST_READ_REGISTER;
 > > >      rd_value_64.register_bit_width = 64;
 > > >      BuildSerializationInstructionEntry wr_value_32_val = base;
 > > >      wr_value_32_val.instruction = INST_WRITE_REGISTER_VALUE;
 > > >      BuildSerializationInstructionEntry wr_value_32 = base;
 > > >      BuildSerializationInstructionEntry wr_value_64 = base;
 > > >      wr_value_64.register_bit_width = 64;
 > > >      BuildSerializationInstructionEntry wr_action = base;
 > > >      wr_action.instruction = INST_WRITE_REGISTER_VALUE;
 > > >      wr_action.register_offset = ERST_ACTION_OFFSET;
 > > >
 > >
 > > That's what I described, yes. We should have some empty lines here I
 > > guess. I'm ok with the original one too, there's not too much
 > > duplication.
 >
 > Are the blank lines referring to spacing out the setup of each of the 7 
accesors?
 > If so, I could put a one line comment between each setup? Or is a blank 
line also
 > needed?

A blank line between declarations and code is usually a good idea.


 > Is it OK to post v15 with the struct assignment approach? Or would you 
prefer the
 > explicit structs (which is what I think you mean by 'the original one')?


I prefer the explicit structs as you had posted before.


Ok, as Michael does not have a preference, so let's go with your preference of 
the
explicit structs!
Thank you!
eric




 >
 > Thanks!
 > eric

I don't care either way.

 > >
 > >
 > > >
 > > > >
 > > > >
 > > > > > #define SERIALIZATIONINSTRUCTIONCTX(name, \
 > > > > >       inst, bit_width, offset) \
 > > > > >       BuildSerializationInstructionEntry name = { \
 > > > > >           .table_data = table_instruction_data, \
 > > > > >           .bar = bar0, \
 > > > > >           .instruction = inst, \
 > > > > >           .flags = 0, \
 > > > > >           .register_bit_width = bit_width, \
 > > > > >           .register_offset = offset, \
 > > > > >       }
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(rd_value_32_val,
 > > > > >           INST_READ_REGISTER_VALUE, 32, ERST_VALUE_OFFSET);
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(rd_value_32,
 > > > > >           INST_READ_REGISTER, 32, ERST_VALUE_OFFSET);
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(rd_value_64,
 > > > > >           INST_READ_REGISTER, 64, ERST_VALUE_OFFSET);
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(wr_value_32_val,
 > > > > >           INST_WRITE_REGISTER_VALUE, 32, ERST_VALUE_OFFSET);
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(wr_value_32,
 > > > > >           INST_WRITE_REGISTER, 32, ERST_VALUE_OFFSET);
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(wr_value_64,
 > > > > >           INST_WRITE_REGISTER, 64, ERST_VALUE_OFFSET);
 > > > > >       SERIALIZATIONINSTRUCTIONCTX(wr_action,
 > > > > >           INST_WRITE_REGISTER_VALUE, 32, ERST_ACTION_OFFSET);
 > > > > >
 > > > > > These are the 7 accessors needed.
 > > > >
 > > > > not at all sure this one is worth the macro mess.
 > > >
 > > > I'm hoping to produce a v15 with the style you want.
 > > > eric
 > > >
 > > > >
 > > > > > >
 > > > > > > > +    unsigned action;
 > > > > > > > +
 > > > > > > > +    trace_acpi_erst_pci_bar_0(bar0);
 > > > > > > > +
 > > > > > > > +    /* Serialization Instruction Entries */
 > > > > > > > +    action = ACTION_BEGIN_WRITE_OPERATION;
 > > > > > > > +    build_serialization_instruction(_action, action, 
action);
 > > > > > > > +
 > > > > > > > +    action = ACTION_BEGIN_READ_OPERATION;
 > > > > > > > +    build_serialization_instruction(_action, action, 
action);
 > > > > > > > +
 > > > > > > > +    action = ACTION_BEGIN_CLEAR_OPERATION;
 > > > > > > > +    build_serialization_instruction(_action, action, 
action);
 > > > > > > > +
 > > > > > > > +    

Re: [PATCH v14 06/10] ACPI ERST: build the ACPI ERST table

2022-01-28 Thread Eric DeVolder

Michael, thanks! See inline response below, please.
eric

On 1/28/22 09:54, Michael S. Tsirkin wrote:

On Fri, Jan 28, 2022 at 09:11:41AM -0600, Eric DeVolder wrote:

Michael,
Thanks for examining this. Inline response below.
eric

On 1/27/22 18:37, Michael S. Tsirkin wrote:

On Thu, Jan 27, 2022 at 04:02:07PM -0600, Eric DeVolder wrote:

Ani,
Thanks for the RB! Inline responses below.
eric

On 1/27/22 02:36, Ani Sinha wrote:



On Wed, 26 Jan 2022, Eric DeVolder wrote:


This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.


There might be more optimizations possible but I think we have messaged
this code enough. We can further rework the code if needed in subsequent
patches once this is pushed.



Signed-off-by: Eric DeVolder 


with some minor comments,

Reviewed-by: Ani Sinha 


hw/acpi/erst.c | 225 
+
1 file changed, 225 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..5d5a639 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
#define STATUS_RECORD_STORE_EMPTY 0x04
#define STATUS_RECORD_NOT_FOUND   0x05

+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
/* UEFI 2.1: Appendix N Common Platform Error Record */
#define UEFI_CPER_RECORD_MIN_SIZE 128U
#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,210 @@ typedef struct {

/***/
/***/
+typedef struct {
+GArray *table_data;
+pcibus_t bar;
+uint8_t instruction;
+uint8_t flags;
+uint8_t register_bit_width;
+pcibus_t register_offset;
+} BuildSerializationInstructionEntry;
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction(
+BuildSerializationInstructionEntry *e,
+uint8_t serialization_action,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(e->table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(e->table_data, e->instruction, 1);
+/* Flags */
+build_append_int_noprefix(e->table_data, e->flags, 1);
+/* Reserved */
+build_append_int_noprefix(e->table_data, 0, 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = e->register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(e->register_bit_width) - 2;


Should this be casted as unit8_t?

OK, done.




+gas.address = (uint64_t)(e->bar + e->register_offset);
+build_append_gas_from_struct(e->table_data, );
+/* Value */
+build_append_int_noprefix(e->table_data, value, 8);
+/* Mask */
+mask = (1ULL << (e->register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(e->table_data, mask, 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+GArray *table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+/* Contexts for the different ways ACTION and VALUE are accessed */
+BuildSerializationInstructionEntry rd_value_32_val = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER_VALUE,
+.flags = 0,
+.regist

Re: [PATCH v14 06/10] ACPI ERST: build the ACPI ERST table

2022-01-28 Thread Eric DeVolder

Michael,
Thanks for examining this. Inline response below.
eric

On 1/27/22 18:37, Michael S. Tsirkin wrote:

On Thu, Jan 27, 2022 at 04:02:07PM -0600, Eric DeVolder wrote:

Ani,
Thanks for the RB! Inline responses below.
eric

On 1/27/22 02:36, Ani Sinha wrote:



On Wed, 26 Jan 2022, Eric DeVolder wrote:


This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.


There might be more optimizations possible but I think we have messaged
this code enough. We can further rework the code if needed in subsequent
patches once this is pushed.



Signed-off-by: Eric DeVolder 


with some minor comments,

Reviewed-by: Ani Sinha 


   hw/acpi/erst.c | 225 
+
   1 file changed, 225 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..5d5a639 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
   #define STATUS_RECORD_STORE_EMPTY 0x04
   #define STATUS_RECORD_NOT_FOUND   0x05

+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
   /* UEFI 2.1: Appendix N Common Platform Error Record */
   #define UEFI_CPER_RECORD_MIN_SIZE 128U
   #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,210 @@ typedef struct {

   /***/
   /***/
+typedef struct {
+GArray *table_data;
+pcibus_t bar;
+uint8_t instruction;
+uint8_t flags;
+uint8_t register_bit_width;
+pcibus_t register_offset;
+} BuildSerializationInstructionEntry;
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction(
+BuildSerializationInstructionEntry *e,
+uint8_t serialization_action,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(e->table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(e->table_data, e->instruction, 1);
+/* Flags */
+build_append_int_noprefix(e->table_data, e->flags, 1);
+/* Reserved */
+build_append_int_noprefix(e->table_data, 0, 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = e->register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(e->register_bit_width) - 2;


Should this be casted as unit8_t?

OK, done.




+gas.address = (uint64_t)(e->bar + e->register_offset);
+build_append_gas_from_struct(e->table_data, );
+/* Value */
+build_append_int_noprefix(e->table_data, value, 8);
+/* Mask */
+mask = (1ULL << (e->register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(e->table_data, mask, 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+GArray *table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+/* Contexts for the different ways ACTION and VALUE are accessed */
+BuildSerializationInstructionEntry rd_value_32_val = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER_VALUE,
+.flags = 0,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry rd_value_32 = {
+.table_data = table_instruction_data,

Re: [PATCH v14 06/10] ACPI ERST: build the ACPI ERST table

2022-01-27 Thread Eric DeVolder

Ani,
Thanks for the RB! Inline responses below.
eric

On 1/27/22 02:36, Ani Sinha wrote:



On Wed, 26 Jan 2022, Eric DeVolder wrote:


This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.


There might be more optimizations possible but I think we have messaged
this code enough. We can further rework the code if needed in subsequent
patches once this is pushed.



Signed-off-by: Eric DeVolder 


with some minor comments,

Reviewed-by: Ani Sinha 


  hw/acpi/erst.c | 225 +
  1 file changed, 225 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..5d5a639 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
  #define STATUS_RECORD_STORE_EMPTY 0x04
  #define STATUS_RECORD_NOT_FOUND   0x05

+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
  /* UEFI 2.1: Appendix N Common Platform Error Record */
  #define UEFI_CPER_RECORD_MIN_SIZE 128U
  #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,210 @@ typedef struct {

  /***/
  /***/
+typedef struct {
+GArray *table_data;
+pcibus_t bar;
+uint8_t instruction;
+uint8_t flags;
+uint8_t register_bit_width;
+pcibus_t register_offset;
+} BuildSerializationInstructionEntry;
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction(
+BuildSerializationInstructionEntry *e,
+uint8_t serialization_action,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(e->table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(e->table_data, e->instruction, 1);
+/* Flags */
+build_append_int_noprefix(e->table_data, e->flags, 1);
+/* Reserved */
+build_append_int_noprefix(e->table_data, 0, 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = e->register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(e->register_bit_width) - 2;


Should this be casted as unit8_t?

OK, done.




+gas.address = (uint64_t)(e->bar + e->register_offset);
+build_append_gas_from_struct(e->table_data, );
+/* Value */
+build_append_int_noprefix(e->table_data, value, 8);
+/* Mask */
+mask = (1ULL << (e->register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(e->table_data, mask, 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+GArray *table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+/* Contexts for the different ways ACTION and VALUE are accessed */
+BuildSerializationInstructionEntry rd_value_32_val = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER_VALUE,
+.flags = 0,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry rd_value_32 = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER,
+.flags = 0,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSe

[PATCH v14 10/10] ACPI ERST: step 6 of bios-tables-test.c

2022-01-26 Thread Eric DeVolder
 }

 @@ -1399,11 +1394,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS "

  Method (DVNT, 2, NotSerialized)
  {
 -If ((Arg0 & 0x08))
 -{
 -Notify (S18, Arg1)
 -}
 -
  If ((Arg0 & 0x10))
  {
  Notify (S20, Arg1)

diff q35/DSDT and q35/DSDT.acpierst:
 @@ -5,13 +5,13 @@
   *
   * Disassembling to symbolic ASL+ operators
   *
 - * Disassembly of tests/data/acpi/q35/DSDT, Thu Dec  2 10:10:13 2021
 + * Disassembly of tests/data/acpi/q35/DSDT.acpierst, Thu Dec  2 12:59:36 2021
   *
   * Original Table Header:
   * Signature"DSDT"
 - * Length   0x2061 (8289)
 + * Length   0x2072 (8306)
   * Revision 0x01  32-bit table (V1), no 64-bit math support
 - * Checksum 0xFA
 + * Checksum 0x9A
   * OEM ID   "BOCHS "
   * OEM Table ID "BXPC"
   * OEM Revision 0x0001 (1)
 @@ -3278,6 +3278,11 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS "
  }
  }

 +Device (S10)
 +{
 +Name (_ADR, 0x0002)  // _ADR: Address
 +}
 +
  Method (PCNT, 0, NotSerialized)
  {
  }

For both pc and q35, there is but a small difference between this
DSDT.acpierst and the corresponding DSDT. In both cases, the changes
occur under the hiearchy:

Scope (\_SB)
{
Scope (PCI0)
{

which leads me to believe that the change to the DSDT was needed
due to the introduction of the ERST PCI device.

And is explained in detail by Ani Sinha:
I have convinced myself of the changes we see in the DSDT tables.
On i440fx side, we are adding a non-hotpluggable pci device on slot 3.
So the changes we see are basically replacing an empty hotpluggable
slot on the pci root port with a non-hotplugggable device.
On q35, bsel on pcie root bus is not set (its not hotpluggable bus),
so the change basically adds the address enumeration for the device.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 tests/data/acpi/microvm/ERST.pcie   | Bin 0 -> 912 bytes
 tests/data/acpi/pc/DSDT.acpierst| Bin 0 -> 5969 bytes
 tests/data/acpi/pc/ERST.acpierst| Bin 0 -> 912 bytes
 tests/data/acpi/q35/DSDT.acpierst   | Bin 0 -> 8306 bytes
 tests/data/acpi/q35/ERST.acpierst   | Bin 0 -> 912 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   5 -
 6 files changed, 5 deletions(-)

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a6d0cb783831ebc18972ec57bb6c624438ff150d
 100644
GIT binary patch
literal 912
zcmaKoTMmLS5Jd;doACJehb6cK12OSWBYwCn7ocm^-rA|;CUz1YmosPDa=fm$hY?9$
z^LaU~(|o@yldVKV@Q+UZ@>zwpS)GZ(sO?Lc}v64j-jFC7yn9;D$INO8pFiUB7f+
zf49KN+;jDxe>nP4Iq`z#7tC?s!tc6i7Z+t!@(t>{e2`4%
zZhiFB_p5lnFb*Ui&1$pT3_)pk?J?$-jLiezjJ$6`=r)uYry0Rn7KuJIp)|!
zckaizM=~sYzU*-I~PkUtAn>Dr`~u=;o(_O$t$PK8~R}U#`{0u*{
zz`m8fl|Wu#ucTKJu-TjNQ`rN~%rBccG0yWwF_}_zQl+X71|-_g)Pr`x1*Xgb!>QealcAR5Lj8F@vR~_hFrfVBOumUtb3<
zL8GI#8|W0leXv|!GGL=~vE5*uM7z%Af!czNXYqlQL#IT$!9xR0zORu68XY#=M-SGy
z3b+$tZv(*Hu4BBt4F>MUo>Padde^ZZU%V_4TiQ&6ruaomTLcp<9-2bBZ=qyp40+
ziEQ&$6L)c>%cI)0;%@F~Or>jX}g)!VlmH>3A6L#ZGj;i8(jvxl3w$XL%gc
z#4Y0Q*ces>sy7Obm6bTnr@oqih!n=P&+!w*9R95=2i+)QqA9kLa1VJk2ES
zOh6C4;>puBt75SyO`ippr%I9Z{pk6j=(st4aP-WP=ov412KgP0p3z1}&)7R9%3U9d
z!>df~G};j<@%&-TL`!{M=J{^0EAj)b4{!p{wbpF1J^oV~LmWA@f?c-apx
zmJl5aIOP$4%5j~Id6TV0{V^u0sG`|bSAOB2V2gb1@Ki7>g+T~D<}I$cZmy;lKl#kP
zxAm*k{f|HWWb1z8<4?h6y1Bg6FLiOw7Z@DC0gGYf$3^AUwgVosAOD1e9Hex!P-c3u
zY%#r3y2G$SrRg@$K+^S+fmJX`o|0}AmQ(0%hN|GcJ*{Ry{RpZVR_9(>4G!#sMm9K*-Kb2oqvI?7dL24<1WVww+F6k
zrAwi@3blP`ov2|RQA!4yn|HMt+|rp;ky|p}*s4Bhi{tS7b7IwWYtO
z($_%y0DUt+12O0t{g!qm$i(>FX+UGsM;osE9mca!r!@5Ld6Jt2$-nabyyC?4*zT@l2
z4LgzF3U^-%E&8T*RhMxH{B|{Nmd$hyhrlm@q(4{QfcO=jBztZw|gWU^0Q+lFdc4
z;t%ATAUG5ws_1bncmXfi8SEC{UBmF!TrD{!GvtiVS87Q`#ts;JTa>Png~+QvKOAg(
z=l%H)^?9Gb?Lui47fY7Bv8_MKSPiRTs@3YkU)Q{@YvnKAT;;J8U>fgQ>9qeF0+gJ!
zS_V9pumOy9sSU)%^lS1X17`o1`MA>W^ePI^H@E*S%`|HOx^c$lLHVkhwcpCba771jDZ#SdZmhM`3K=q{%
zNdudV5*`|Tn?lmSM!~R<_iYsI+Q3HPu(0YhlR~GImZVAKI~h
z+O@D02|KpVC?DEYlCeYxd&-j!?Kerrtt;#;Pd>DJ8RM1`cI=OKE{vc{!8uv6Z~
u5j$m$OK@OMk$l8{6J=Z)1AB{Pv}@<7F~|QN>AydkHSF$IS^vS{(*FTuhT2R3

literal 0
HcmV?d1

diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7965ac2562e7b23bf1dc2caaf00ef66453c4f47a
 100644
GIT binary patch
literal 912
zcmaKoOAdlC6h$9Upg{N}4xO+BmS7+z{Ww`+N;?C6GO0l^KeF>#Er>E`f@jBlg
ziAb~?&(mq{$NOdKO+_MtIsSwBP(BS`
zh6Ua)#A*M6_AiN-%#j24ugI^+uZh>pkpuT{$ZyEEIpDYCx8#=`Con^
B

[PATCH v14 08/10] ACPI ERST: qtest for ERST

2022-01-26 Thread Eric DeVolder
This change provides a qtest that locates and then does a simple
interrogation of the ERST feature within the guest.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/erst-test.c | 172 
 tests/qtest/meson.build |   2 +
 2 files changed, 174 insertions(+)
 create mode 100644 tests/qtest/erst-test.c

diff --git a/tests/qtest/erst-test.c b/tests/qtest/erst-test.c
new file mode 100644
index 000..f9ad3c9
--- /dev/null
+++ b/tests/qtest/erst-test.c
@@ -0,0 +1,172 @@
+/*
+ * QTest testcase for acpi-erst
+ *
+ * Copyright (c) 2021 Oracle
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "libqos/libqos-pc.h"
+#include "libqos/libqtest.h"
+#include "qemu-common.h"
+
+#include "hw/pci/pci.h"
+
+static void save_fn(QPCIDevice *dev, int devfn, void *data)
+{
+QPCIDevice **pdev = (QPCIDevice **) data;
+
+*pdev = dev;
+}
+
+static QPCIDevice *get_erst_device(QPCIBus *pcibus)
+{
+QPCIDevice *dev;
+
+dev = NULL;
+qpci_device_foreach(pcibus,
+PCI_VENDOR_ID_REDHAT,
+PCI_DEVICE_ID_REDHAT_ACPI_ERST,
+save_fn, );
+g_assert(dev != NULL);
+
+return dev;
+}
+
+typedef struct _ERSTState {
+QOSState *qs;
+QPCIBar reg_bar, mem_bar;
+uint64_t reg_barsize, mem_barsize;
+QPCIDevice *dev;
+} ERSTState;
+
+#define ACTION 0
+#define VALUE 8
+
+static const char *reg2str(unsigned reg)
+{
+switch (reg) {
+case 0:
+return "ACTION";
+case 8:
+return "VALUE";
+default:
+return NULL;
+}
+}
+
+static inline uint32_t in_reg32(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint32_t res;
+
+res = qpci_io_readl(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %08x", name, res);
+
+return res;
+}
+
+static inline uint64_t in_reg64(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint64_t res;
+
+res = qpci_io_readq(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %016llx", name, (unsigned long long)res);
+
+return res;
+}
+
+static inline void out_reg32(ERSTState *s, unsigned reg, uint32_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%08x -> *%s", v, name);
+qpci_io_writel(s->dev, s->reg_bar, reg, v);
+}
+
+static inline void out_reg64(ERSTState *s, unsigned reg, uint64_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%016llx -> *%s", (unsigned long long)v, name);
+qpci_io_writeq(s->dev, s->reg_bar, reg, v);
+}
+
+static void cleanup_vm(ERSTState *s)
+{
+g_free(s->dev);
+qtest_shutdown(s->qs);
+}
+
+static void setup_vm_cmd(ERSTState *s, const char *cmd)
+{
+const char *arch = qtest_get_arch();
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+s->qs = qtest_pc_boot(cmd);
+} else {
+g_printerr("erst-test tests are only available on x86\n");
+exit(EXIT_FAILURE);
+}
+s->dev = get_erst_device(s->qs->pcibus);
+
+s->reg_bar = qpci_iomap(s->dev, 0, >reg_barsize);
+g_assert_cmpuint(s->reg_barsize, ==, 16);
+
+s->mem_bar = qpci_iomap(s->dev, 1, >mem_barsize);
+g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
+
+qpci_device_enable(s->dev);
+}
+
+static void test_acpi_erst_basic(void)
+{
+ERSTState state;
+uint64_t log_address_range;
+uint64_t log_address_length;
+uint32_t log_address_attr;
+
+setup_vm_cmd(,
+"-object memory-backend-file,"
+"mem-path=acpi-erst.XX,"
+"size=64K,"
+"share=on,"
+"id=nvram "
+"-device acpi-erst,"
+"memdev=nvram");
+
+out_reg32(, ACTION, 0xD);
+log_address_range = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xE);
+log_address_length = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xF);
+log_address_attr = in_reg32(, VALUE);
+
+/* Check log_address_range is not 0, ~0 or base */
+g_assert_cmpuint(log_address_range, !=,  0ULL);
+g_assert_cmpuint(log_address_range, !=, ~0ULL);
+g_assert_cmpuint(log_address_range, !=, state.reg_bar.addr);
+g_assert_cmpuint(log_address_range, ==, state.mem_bar.addr);
+
+/* Check log_address_length is bar1_size */
+g_assert_cmpuint(log_address_length, ==, state.mem_barsize);
+
+/* Check log_address_attr is 0 */
+g_assert_cmpuint(log_address_attr, ==, 0);
+
+cleanup_vm();
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+
+g_test_init(, , NULL);
+qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);

[PATCH v14 05/10] ACPI ERST: support for ACPI ERST feature

2022-01-26 Thread Eric DeVolder
This implements a PCI device for ACPI ERST. This implements the
non-NVRAM "mode" of operation for ERST as it is supported by
Linux and Windows.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/acpi/Kconfig  |   6 +
 hw/acpi/erst.c   | 844 +++
 hw/acpi/meson.build  |   1 +
 hw/acpi/trace-events |  15 +
 4 files changed, 866 insertions(+)
 create mode 100644 hw/acpi/erst.c

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b5..19caebd 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -10,6 +10,7 @@ config ACPI_X86
 select ACPI_HMAT
 select ACPI_PIIX4
 select ACPI_PCIHP
+select ACPI_ERST
 
 config ACPI_X86_ICH
 bool
@@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
 select ACPI
 select ACPI_MEMORY_HOTPLUG
 select ACPI_NVDIMM
+
+config ACPI_ERST
+bool
+default y
+depends on ACPI && PCI
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
new file mode 100644
index 000..fe9ba51
--- /dev/null
+++ b/hw/acpi/erst.c
@@ -0,0 +1,844 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+#include 
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-core.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/pci/pci.h"
+#include "qom/object_interfaces.h"
+#include "qemu/error-report.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/hostmem.h"
+#include "hw/acpi/erst.h"
+#include "trace.h"
+
+/* ACPI 4.0: Table 17-16 Serialization Actions */
+#define ACTION_BEGIN_WRITE_OPERATION 0x0
+#define ACTION_BEGIN_READ_OPERATION  0x1
+#define ACTION_BEGIN_CLEAR_OPERATION 0x2
+#define ACTION_END_OPERATION 0x3
+#define ACTION_SET_RECORD_OFFSET 0x4
+#define ACTION_EXECUTE_OPERATION 0x5
+#define ACTION_CHECK_BUSY_STATUS 0x6
+#define ACTION_GET_COMMAND_STATUS0x7
+#define ACTION_GET_RECORD_IDENTIFIER 0x8
+#define ACTION_SET_RECORD_IDENTIFIER 0x9
+#define ACTION_GET_RECORD_COUNT  0xA
+#define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
+#define ACTION_RESERVED  0xC
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
+#define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
+#define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10 /* ACPI 6.3 */
+
+/* ACPI 4.0: Table 17-17 Command Status Definitions */
+#define STATUS_SUCCESS0x00
+#define STATUS_NOT_ENOUGH_SPACE   0x01
+#define STATUS_HARDWARE_NOT_AVAILABLE 0x02
+#define STATUS_FAILED 0x03
+#define STATUS_RECORD_STORE_EMPTY 0x04
+#define STATUS_RECORD_NOT_FOUND   0x05
+
+/* UEFI 2.1: Appendix N Common Platform Error Record */
+#define UEFI_CPER_RECORD_MIN_SIZE 128U
+#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
+#define UEFI_CPER_RECORD_ID_OFFSET 96U
+#define IS_UEFI_CPER_RECORD(ptr) \
+(((ptr)[0] == 'C') && \
+ ((ptr)[1] == 'P') && \
+ ((ptr)[2] == 'E') && \
+ ((ptr)[3] == 'R'))
+
+/*
+ * NOTE that when accessing CPER fields within a record, memcpy()
+ * is utilized to avoid a possible misaligned access on the host.
+ */
+
+/*
+ * This implementation is an ACTION (cmd) and VALUE (data)
+ * interface consisting of just two 64-bit registers.
+ */
+#define ERST_REG_SIZE (16UL)
+#define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
+#define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
+
+/*
+ * ERST_RECORD_SIZE is the buffer size for exchanging ERST
+ * record contents. Thus, it defines the maximum record size.
+ * As this is mapped through a PCI BAR, it must be a power of
+ * two and larger than UEFI_CPER_RECORD_MIN_SIZE.
+ * The backing storage is divided into fixed size "slots",
+ * each ERST_RECORD_SIZE in length, and each "slot"
+ * storing a single record. No attempt at optimizing storage
+ * through compression, compaction, etc is attempted.
+ * NOTE that slot 0 is reserved for the backing storage header.
+ * Depending upon the size of the backing storage, additional
+ * slots will be part of the slot 0 header in order to account
+ * for a record_id for each available remaining slot.
+ */
+/* 8KiB records, not too small, not too big */
+#define ERST_RECORD_SIZE (8192UL)
+
+#define ACPI_ERST_MEMDEV_PROP "

[PATCH v14 06/10] ACPI ERST: build the ACPI ERST table

2022-01-26 Thread Eric DeVolder
This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
 hw/acpi/erst.c | 225 +
 1 file changed, 225 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..5d5a639 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
 #define STATUS_RECORD_STORE_EMPTY 0x04
 #define STATUS_RECORD_NOT_FOUND   0x05
 
+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
 /* UEFI 2.1: Appendix N Common Platform Error Record */
 #define UEFI_CPER_RECORD_MIN_SIZE 128U
 #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,210 @@ typedef struct {
 
 /***/
 /***/
+typedef struct {
+GArray *table_data;
+pcibus_t bar;
+uint8_t instruction;
+uint8_t flags;
+uint8_t register_bit_width;
+pcibus_t register_offset;
+} BuildSerializationInstructionEntry;
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction(
+BuildSerializationInstructionEntry *e,
+uint8_t serialization_action,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(e->table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(e->table_data, e->instruction, 1);
+/* Flags */
+build_append_int_noprefix(e->table_data, e->flags, 1);
+/* Reserved */
+build_append_int_noprefix(e->table_data, 0, 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = e->register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(e->register_bit_width) - 2;
+gas.address = (uint64_t)(e->bar + e->register_offset);
+build_append_gas_from_struct(e->table_data, );
+/* Value */
+build_append_int_noprefix(e->table_data, value, 8);
+/* Mask */
+mask = (1ULL << (e->register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(e->table_data, mask, 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+GArray *table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+/* Contexts for the different ways ACTION and VALUE are accessed */
+BuildSerializationInstructionEntry rd_value_32_val = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER_VALUE,
+.flags = 0,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry rd_value_32 = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER,
+.flags = 0,
+.register_bit_width = 32,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry rd_value_64 = {
+.table_data = table_instruction_data,
+.bar = bar0,
+.instruction = INST_READ_REGISTER,
+.flags = 0,
+.register_bit_width = 64,
+.register_offset = ERST_VALUE_OFFSET,
+};
+BuildSerializationInstructionEntry wr_value_32_val = {
+.table_data = table_instruction_data,
+.bar = bar0,
+ 

[PATCH v14 09/10] ACPI ERST: bios-tables-test testcase

2022-01-26 Thread Eric DeVolder
This change implements the test suite checks for the ERST table.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/bios-tables-test.c | 54 ++
 1 file changed, 54 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index e6b72d9..266b215 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1446,6 +1446,57 @@ static void test_acpi_piix4_tcg_acpi_hmat(void)
 test_acpi_tcg_acpi_hmat(MACHINE_PC);
 }
 
+static void test_acpi_erst(const char *machine)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+memset(, 0, sizeof(data));
+data.machine = machine;
+data.variant = ".acpierst";
+params = g_strdup_printf(
+" -object memory-backend-file,id=erstnvram,"
+"mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+free_test_data();
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+}
+
+static void test_acpi_piix4_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_PC);
+}
+
+static void test_acpi_q35_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_Q35);
+}
+
+static void test_acpi_microvm_acpi_erst(void)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+test_acpi_microvm_prepare();
+data.variant = ".pcie";
+data.tcg_only = true; /* need constant host-phys-bits */
+params = g_strdup_printf(" -machine microvm,"
+"acpi=on,ioapic2=off,rtc=off,pcie=on"
+" -object memory-backend-file,id=erstnvram,"
+   "mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+free_test_data();
+}
+
 static void test_acpi_virt_tcg(void)
 {
 test_data data = {
@@ -1675,6 +1726,8 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
 qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
 qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
+qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst);
+qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst);
 qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
 qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg);
 qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg);
@@ -1684,6 +1737,7 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs);
 if (strcmp(arch, "x86_64") == 0) {
 qtest_add_func("acpi/microvm/pcie", 
test_acpi_microvm_pcie_tcg);
+qtest_add_func("acpi/microvm/acpierst", 
test_acpi_microvm_acpi_erst);
 }
 }
 if (has_kvm) {
-- 
1.8.3.1




[PATCH v14 04/10] ACPI ERST: header file for ERST

2022-01-26 Thread Eric DeVolder
This change introduces the public defintions for ACPI ERST.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 include/hw/acpi/erst.h | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 include/hw/acpi/erst.h

diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
new file mode 100644
index 000..9d63717
--- /dev/null
+++ b/include/hw/acpi/erst.h
@@ -0,0 +1,19 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_ACPI_ERST_H
+#define HW_ACPI_ERST_H
+
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id);
+
+#define TYPE_ACPI_ERST "acpi-erst"
+
+#endif
-- 
1.8.3.1




[PATCH v14 07/10] ACPI ERST: create ACPI ERST table for pc/x86 machines

2022-01-26 Thread Eric DeVolder
This change exposes ACPI ERST support for x86 guests.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/i386/acpi-build.c   | 15 +++
 hw/i386/acpi-microvm.c | 15 +++
 include/hw/acpi/erst.h |  5 +
 3 files changed, 35 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ce823e8..ebd47aa 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -43,6 +43,7 @@
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
 #include "hw/acpi/vmgenid.h"
+#include "hw/acpi/erst.h"
 #include "sysemu/tpm_backend.h"
 #include "hw/rtc/mc146818rtc_regs.h"
 #include "migration/vmstate.h"
@@ -74,6 +75,8 @@
 #include "hw/acpi/hmat.h"
 #include "hw/acpi/viot.h"
 
+#include CONFIG_DEVICES
+
 /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
  * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
  * a little bit, there should be plenty of free space since the DSDT
@@ -2575,6 +2578,18 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 vmgenid_dev = find_vmgenid_dev();
 if (vmgenid_dev) {
 acpi_add_table(table_offsets, tables_blob);
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index 196d318..68ca7e7 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -30,6 +30,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/acpi/utils.h"
+#include "hw/acpi/erst.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/i386/microvm.h"
 #include "hw/pci/pci.h"
@@ -40,6 +41,8 @@
 #include "acpi-common.h"
 #include "acpi-microvm.h"
 
+#include CONFIG_DEVICES
+
 static void acpi_dsdt_add_virtio(Aml *scope,
  MicrovmMachineState *mms)
 {
@@ -207,6 +210,18 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 xsdt = tables_blob->len;
 build_xsdt(tables_blob, tables->linker, table_offsets, x86ms->oem_id,
x86ms->oem_table_id);
diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
index 9d63717..b747fe7 100644
--- a/include/hw/acpi/erst.h
+++ b/include/hw/acpi/erst.h
@@ -16,4 +16,9 @@ void build_erst(GArray *table_data, BIOSLinker *linker, 
Object *erst_dev,
 
 #define TYPE_ACPI_ERST "acpi-erst"
 
+/* returns NULL unless there is exactly one device */
+static inline Object *find_erst_dev(void)
+{
+return object_resolve_path_type("", TYPE_ACPI_ERST, NULL);
+}
 #endif
-- 
1.8.3.1




[PATCH v14 02/10] ACPI ERST: specification for ERST support

2022-01-26 Thread Eric DeVolder
Information on the implementation of the ACPI ERST support.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 docs/specs/acpi_erst.rst | 200 +++
 1 file changed, 200 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst

diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 000..a8a9d22
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+-
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
+independent of, and runs before, kdump.  In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+---
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object 
memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x1,share=on
 \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+   this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+   required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+   parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+   ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+   backend storage. Must be a power of two value greater than or
+   equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers.  All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION.  Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+--
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record.  Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that identifies the contents
+as ERST and also facilitates efficient access to the records.
+Depending upon the size of the backend storage, additional slots will
+be designated

[PATCH v14 01/10] ACPI ERST: bios-tables-test.c steps 1 and 2

2022-01-26 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change adds empty placeholder files per step 1 for the new ERST
table, and excludes resulting changed files in bios-tables-test-allowed-diff.h
per step 2.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/microvm/ERST.pcie   | 0
 tests/data/acpi/pc/DSDT.acpierst| 0
 tests/data/acpi/pc/ERST.acpierst| 0
 tests/data/acpi/q35/DSDT.acpierst   | 0
 tests/data/acpi/q35/ERST.acpierst   | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 5 +
 6 files changed, 5 insertions(+)
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/DSDT.acpierst 
b/tests/data/acpi/q35/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/ERST.acpierst 
b/tests/data/acpi/q35/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523..603db07 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,6 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/DSDT.acpierst",
+"tests/data/acpi/pc/ERST.acpierst",
+"tests/data/acpi/q35/DSDT.acpierst",
+"tests/data/acpi/q35/ERST.acpierst",
+"tests/data/acpi/microvm/ERST.pcie",
-- 
1.8.3.1




[PATCH v14 03/10] ACPI ERST: PCI device_id for ERST

2022-01-26 Thread Eric DeVolder
This change reserves the PCI device_id for the new ACPI ERST
device.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
Acked-by: Ani Sinha 
---
 include/hw/pci/pci.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 023abc0..c3f3c90 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -108,6 +108,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_MDPY0x000f
 #define PCI_DEVICE_ID_REDHAT_NVME0x0010
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
+#define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
1.8.3.1




[PATCH v14 00/10] acpi: Error Record Serialization Table, ERST, support for QEMU

2022-01-26 Thread Eric DeVolder
This patchset introduces support for the ACPI Error Record
Serialization Table, ERST.

For background and implementation information, please see
docs/specs/acpi_erst.rst, which is patch 2/10.

Suggested-by: Konrad Wilk 
Signed-off-by: Eric DeVolder 

---
v14: 26jan2022
 - Changed build_erst() to utilize a context structure for
   generating accesses to ACTION and VALUE, per Michael Tsirkin.
 - Other simplification per Ani Sinha.

v13: 24jan2022
 - v12 erroneously omitted step 6 of bios-tables-test.c, this
   has step 6 included.
 - No other changes to v12.

v12: 10jan2022
 - Converted macros in build_erst() to uppert to follow coding
   style, as pointed out by Michael Tsirkin.
 - And few items to help further simplify build_erst().

v11: 15dec2021
 - Simplified build_erst() via feedback from Michael Tsirkin
 - Addressed additional feedback from Ani Sinha

v10: 9dec2021
 - Addressed additional feedback from Ani Sinha

v9: 2dec2021
 - Addressed feedback from Ani Sinha

v8: 15oct2021
 - Added Kconfig option for ERST, per Ani Sinha
 - Fixed patch ordering, per Ani

v7: 7oct2021
 - style improvements, per Igor
 - use of endian accessors for storage header, per Igor
 - a number of optimizations and improvements, per Igor
 - updated spec for header, per Igor
 - updated spec for rst format, per Michael Tsirkin
 - updated spec for new record_size parameter
   Due to changes in the spec, I am not carrying the
   Acked-by from Ani Sinha.
 - changes for and testing of migration to systems with
   differing ERST_RECORD_SIZE

v6: 5aug2021
 - Fixed compile warning/error, per Michael Tsirkin
 - Fixed mingw32 build error, per Michael
 - Converted exchange buffer to MemoryBackend, per Igor
 - Migrated test to PCI, per Igor
 - Significantly reduced amount of copying, per Igor
 - Corrections/enhancements to acpi_erst.txt, per Igor
 - Many misc/other small items, per Igor

v5: 30jun2021
 - Create docs/specs/acpi_erst.txt, per Igor
 - Separate PCI BARs for registers and memory, per Igor
 - Convert debugging to use trace infrastructure, per Igor
 - Various other fixups, per Igor

v4: 11jun2021
 - Converted to a PCI device, per Igor.
 - Updated qtest.
 - Rearranged patches, per Igor.

v3: 28may2021
 - Converted to using a TYPE_MEMORY_BACKEND_FILE object rather than
   internal array with explicit file operations, per Igor.
 - Changed the way the qdev and base address are handled, allowing
   ERST to be disabled at run-time. Also aligns better with other
   existing code.

v2: 8feb2021
 - Added qtest/smoke test per Paolo Bonzini
 - Split patch into smaller chunks, per Igor Mammedov
 - Did away with use of ACPI packed structures, per Igor Mammedov

v1: 26oct2020
 - initial post

---

Eric DeVolder (10):
  ACPI ERST: bios-tables-test.c steps 1 and 2
  ACPI ERST: specification for ERST support
  ACPI ERST: PCI device_id for ERST
  ACPI ERST: header file for ERST
  ACPI ERST: support for ACPI ERST feature
  ACPI ERST: build the ACPI ERST table
  ACPI ERST: create ACPI ERST table for pc/x86 machines
  ACPI ERST: qtest for ERST
  ACPI ERST: bios-tables-test testcase
  ACPI ERST: step 6 of bios-tables-test.c

 docs/specs/acpi_erst.rst  |  200 +++
 hw/acpi/Kconfig   |6 +
 hw/acpi/erst.c| 1069 +
 hw/acpi/meson.build   |1 +
 hw/acpi/trace-events  |   15 +
 hw/i386/acpi-build.c  |   15 +
 hw/i386/acpi-microvm.c|   15 +
 include/hw/acpi/erst.h|   24 +
 include/hw/pci/pci.h  |1 +
 tests/data/acpi/microvm/ERST.pcie |  Bin 0 -> 912 bytes
 tests/data/acpi/pc/DSDT.acpierst  |  Bin 0 -> 5969 bytes
 tests/data/acpi/pc/ERST.acpierst  |  Bin 0 -> 912 bytes
 tests/data/acpi/q35/DSDT.acpierst |  Bin 0 -> 8306 bytes
 tests/data/acpi/q35/ERST.acpierst |  Bin 0 -> 912 bytes
 tests/qtest/bios-tables-test.c|   54 ++
 tests/qtest/erst-test.c   |  172 ++
 tests/qtest/meson.build   |2 +
 17 files changed, 1574 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst
 create mode 100644 hw/acpi/erst.c
 create mode 100644 include/hw/acpi/erst.h
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst
 create mode 100644 tests/qtest/erst-test.c

-- 
1.8.3.1




Re: [PATCH v13 06/10] ACPI ERST: build the ACPI ERST table

2022-01-26 Thread Eric DeVolder

Ani, Michael,
An inline response at the bottom.
Thanks!
eric

On 1/26/22 01:05, Ani Sinha wrote:



On Tue, 25 Jan 2022, Eric DeVolder wrote:


Ani,
Thanks for the feedback! Inline responses below.
eric

On 1/25/22 04:53, Ani Sinha wrote:




+
+action = ACTION_BEGIN_CLEAR_OPERATION;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTION_END_OPERATION;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTION_SET_RECORD_OFFSET;
+BUILD_WRITE_REGISTER(32, ERST_VALUE_OFFSET, 0);
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTION_EXECUTE_OPERATION;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_VALUE_OFFSET,
+ERST_EXECUTE_OPERATION_MAGIC);


except here, on all cases we have
BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);

We should treat the above as special case and simplify the rest of the
calls (eliminate repeated common arguments).


OK, I created BUILD_WRITE_ACTION() to replace this occurrence. I've provided
what this section of code looks like with this and the other below change at
the end.

I have seen the comment from Michael and you about using inline functions, I
will respond to that in the other message.




+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTION_CHECK_BUSY_STATUS;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER_VALUE(32, ERST_VALUE_OFFSET, 0x01);
+
+action = ACTION_GET_COMMAND_STATUS;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(32, ERST_VALUE_OFFSET);
+
+action = ACTION_GET_RECORD_IDENTIFIER;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(64, ERST_VALUE_OFFSET);
+
+action = ACTION_SET_RECORD_IDENTIFIER;
+BUILD_WRITE_REGISTER(64, ERST_VALUE_OFFSET, 0);
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);


This one seems reverted. Should this be
BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
BUILD_WRITE_REGISTER(64, ERST_VALUE_OFFSET, 0);

like others?


This is a SET operation, so the data is provided in VALUE register, then
the ACTION is written to perform the command, ie record the value.



Ok I see. makes sense.




+
+action = ACTION_GET_RECORD_COUNT;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(32, ERST_VALUE_OFFSET);
+
+action = ACTION_BEGIN_DUMMY_WRITE_OPERATION;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTION_GET_ERROR_LOG_ADDRESS_RANGE;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(64, ERST_VALUE_OFFSET);
+
+action = ACTION_GET_ERROR_LOG_ADDRESS_LENGTH;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(64, ERST_VALUE_OFFSET);
+
+action = ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(32, ERST_VALUE_OFFSET);
+
+action = ACTION_GET_EXECUTE_OPERATION_TIMINGS;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+BUILD_READ_REGISTER(64, ERST_VALUE_OFFSET);
+


BUILD_READ_REGISTER() is always called with ERST_VALUE_OFFSET as second
argument. WE should eliminate this repeated passing of same argument.


The BUILD_READ_REGISTER is always against the VALUE register, as you point
out,
so I've s/BUILD_READ_REGISTER/BUILD_READ_VALUE/ and embedded the offset in the
macro now. You can see this below.




And here is what the main snippet looks like with the above changes (a diff
is quite messy):

 /*
  * Macros for use with construction of the action instructions
  */
#define BUILD_READ_VALUE(width_in_bits) \
 build_serialization_instruction_entry(table_instruction_data, \
 action, INST_READ_REGISTER, 0, width_in_bits, \
 bar0 + ERST_VALUE_OFFSET, 0)

#define BUILD_READ_VALUE_VALUE(width_in_bits, value) \
 build_serialization_instruction_entry(table_instruction_data, \
 action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
 bar0 + ERST_VALUE_OFFSET, value)

#define BUILD_WRITE_REGISTER(width_in_bits, reg, value) \
 build_serialization_instruction_entry(table_instruction_data, \
 action, INST_WRITE_REGISTER, 0, width_in_bits, \
 bar0 + reg, value)

#define BUILD_WRITE_REGISTER_VALUE(width_in_bits, reg, value) \
 build_serialization_instruction_entry(table_instruction_data, \
 action, INST_WRITE_REGISTER_VALUE, 0, width_in_bits, \
 bar0 + reg, value)

#define BUILD_WRITE_ACTION() \
 BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action)

 /* Serialization Instruction Entries */
 action = ACTION_BEGIN_WRITE_OPERATION;
 BUILD_WRITE_ACTION();

 action = ACTION_BEGIN_READ_OPERATION;
 BUILD_WRITE_ACTION();

 action = ACTION_BEGIN_CLEAR_OPERATION

Re: [PATCH v13 06/10] ACPI ERST: build the ACPI ERST table

2022-01-25 Thread Eric DeVolder

Hi Michael,
Thanks for examining this! Inline response below.
eric

On 1/25/22 06:05, Michael S. Tsirkin wrote:

On Tue, Jan 25, 2022 at 04:23:49PM +0530, Ani Sinha wrote:



On Mon, 24 Jan 2022, Eric DeVolder wrote:


This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
  hw/acpi/erst.c | 188 +
  1 file changed, 188 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..b0c7539 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
  #define STATUS_RECORD_STORE_EMPTY 0x04
  #define STATUS_RECORD_NOT_FOUND   0x05

+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
  /* UEFI 2.1: Appendix N Common Platform Error Record */
  #define UEFI_CPER_RECORD_MIN_SIZE 128U
  #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,173 @@ typedef struct {

  /***/
  /***/
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+uint8_t serialization_action,
+uint8_t instruction,
+uint8_t flags,
+uint8_t register_bit_width,
+uint64_t register_address,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(table_data, instruction , 1);
+/* Flags */
+build_append_int_noprefix(table_data, flags   , 1);
+/* Reserved */
+build_append_int_noprefix(table_data, 0   , 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(register_bit_width) - 2;
+gas.address = register_address;
+build_append_gas_from_struct(table_data, );
+/* Value */
+build_append_int_noprefix(table_data, value  , 8);
+/* Mask */
+mask = (1ULL << (register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(table_data, mask  , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+GArray *table_instruction_data;
+unsigned action;
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+
+trace_acpi_erst_pci_bar_0(bar0);
+
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+
+/*
+ * Macros for use with construction of the action instructions
+ */
+#define BUILD_READ_REGISTER(width_in_bits, reg) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER, 0, width_in_bits, \
+bar0 + reg, 0)
+
+#define BUILD_READ_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER_VALUE, 0, width_in_bits, \
+   

Re: [PATCH v13 06/10] ACPI ERST: build the ACPI ERST table

2022-01-25 Thread Eric DeVolder

Ani,
Thanks for the feedback! Inline responses below.
eric

On 1/25/22 04:53, Ani Sinha wrote:



On Mon, 24 Jan 2022, Eric DeVolder wrote:


This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
  hw/acpi/erst.c | 188 +
  1 file changed, 188 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..b0c7539 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
  #define STATUS_RECORD_STORE_EMPTY 0x04
  #define STATUS_RECORD_NOT_FOUND   0x05

+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
  /* UEFI 2.1: Appendix N Common Platform Error Record */
  #define UEFI_CPER_RECORD_MIN_SIZE 128U
  #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,173 @@ typedef struct {

  /***/
  /***/
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+uint8_t serialization_action,
+uint8_t instruction,
+uint8_t flags,
+uint8_t register_bit_width,
+uint64_t register_address,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(table_data, instruction , 1);
+/* Flags */
+build_append_int_noprefix(table_data, flags   , 1);
+/* Reserved */
+build_append_int_noprefix(table_data, 0   , 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(register_bit_width) - 2;
+gas.address = register_address;
+build_append_gas_from_struct(table_data, );
+/* Value */
+build_append_int_noprefix(table_data, value  , 8);
+/* Mask */
+mask = (1ULL << (register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(table_data, mask  , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+GArray *table_instruction_data;
+unsigned action;
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+
+trace_acpi_erst_pci_bar_0(bar0);
+
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+
+/*
+ * Macros for use with construction of the action instructions
+ */
+#define BUILD_READ_REGISTER(width_in_bits, reg) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER, 0, width_in_bits, \
+bar0 + reg, 0)
+
+#define BUILD_READ_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+/* Serialization Instruction 

[PATCH v13 05/10] ACPI ERST: support for ACPI ERST feature

2022-01-24 Thread Eric DeVolder
This implements a PCI device for ACPI ERST. This implements the
non-NVRAM "mode" of operation for ERST as it is supported by
Linux and Windows.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/acpi/Kconfig  |   6 +
 hw/acpi/erst.c   | 844 +++
 hw/acpi/meson.build  |   1 +
 hw/acpi/trace-events |  15 +
 4 files changed, 866 insertions(+)
 create mode 100644 hw/acpi/erst.c

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b5..19caebd 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -10,6 +10,7 @@ config ACPI_X86
 select ACPI_HMAT
 select ACPI_PIIX4
 select ACPI_PCIHP
+select ACPI_ERST
 
 config ACPI_X86_ICH
 bool
@@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
 select ACPI
 select ACPI_MEMORY_HOTPLUG
 select ACPI_NVDIMM
+
+config ACPI_ERST
+bool
+default y
+depends on ACPI && PCI
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
new file mode 100644
index 000..fe9ba51
--- /dev/null
+++ b/hw/acpi/erst.c
@@ -0,0 +1,844 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+#include 
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-core.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/pci/pci.h"
+#include "qom/object_interfaces.h"
+#include "qemu/error-report.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/hostmem.h"
+#include "hw/acpi/erst.h"
+#include "trace.h"
+
+/* ACPI 4.0: Table 17-16 Serialization Actions */
+#define ACTION_BEGIN_WRITE_OPERATION 0x0
+#define ACTION_BEGIN_READ_OPERATION  0x1
+#define ACTION_BEGIN_CLEAR_OPERATION 0x2
+#define ACTION_END_OPERATION 0x3
+#define ACTION_SET_RECORD_OFFSET 0x4
+#define ACTION_EXECUTE_OPERATION 0x5
+#define ACTION_CHECK_BUSY_STATUS 0x6
+#define ACTION_GET_COMMAND_STATUS0x7
+#define ACTION_GET_RECORD_IDENTIFIER 0x8
+#define ACTION_SET_RECORD_IDENTIFIER 0x9
+#define ACTION_GET_RECORD_COUNT  0xA
+#define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
+#define ACTION_RESERVED  0xC
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
+#define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
+#define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10 /* ACPI 6.3 */
+
+/* ACPI 4.0: Table 17-17 Command Status Definitions */
+#define STATUS_SUCCESS0x00
+#define STATUS_NOT_ENOUGH_SPACE   0x01
+#define STATUS_HARDWARE_NOT_AVAILABLE 0x02
+#define STATUS_FAILED 0x03
+#define STATUS_RECORD_STORE_EMPTY 0x04
+#define STATUS_RECORD_NOT_FOUND   0x05
+
+/* UEFI 2.1: Appendix N Common Platform Error Record */
+#define UEFI_CPER_RECORD_MIN_SIZE 128U
+#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
+#define UEFI_CPER_RECORD_ID_OFFSET 96U
+#define IS_UEFI_CPER_RECORD(ptr) \
+(((ptr)[0] == 'C') && \
+ ((ptr)[1] == 'P') && \
+ ((ptr)[2] == 'E') && \
+ ((ptr)[3] == 'R'))
+
+/*
+ * NOTE that when accessing CPER fields within a record, memcpy()
+ * is utilized to avoid a possible misaligned access on the host.
+ */
+
+/*
+ * This implementation is an ACTION (cmd) and VALUE (data)
+ * interface consisting of just two 64-bit registers.
+ */
+#define ERST_REG_SIZE (16UL)
+#define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
+#define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
+
+/*
+ * ERST_RECORD_SIZE is the buffer size for exchanging ERST
+ * record contents. Thus, it defines the maximum record size.
+ * As this is mapped through a PCI BAR, it must be a power of
+ * two and larger than UEFI_CPER_RECORD_MIN_SIZE.
+ * The backing storage is divided into fixed size "slots",
+ * each ERST_RECORD_SIZE in length, and each "slot"
+ * storing a single record. No attempt at optimizing storage
+ * through compression, compaction, etc is attempted.
+ * NOTE that slot 0 is reserved for the backing storage header.
+ * Depending upon the size of the backing storage, additional
+ * slots will be part of the slot 0 header in order to account
+ * for a record_id for each available remaining slot.
+ */
+/* 8KiB records, not too small, not too big */
+#define ERST_RECORD_SIZE (8192UL)
+
+#define ACPI_ERST_MEMDEV_PROP "

[PATCH v13 09/10] ACPI ERST: bios-tables-test testcase

2022-01-24 Thread Eric DeVolder
This change implements the test suite checks for the ERST table.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/bios-tables-test.c | 54 ++
 1 file changed, 54 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index e6b72d9..266b215 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1446,6 +1446,57 @@ static void test_acpi_piix4_tcg_acpi_hmat(void)
 test_acpi_tcg_acpi_hmat(MACHINE_PC);
 }
 
+static void test_acpi_erst(const char *machine)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+memset(, 0, sizeof(data));
+data.machine = machine;
+data.variant = ".acpierst";
+params = g_strdup_printf(
+" -object memory-backend-file,id=erstnvram,"
+"mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+free_test_data();
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+}
+
+static void test_acpi_piix4_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_PC);
+}
+
+static void test_acpi_q35_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_Q35);
+}
+
+static void test_acpi_microvm_acpi_erst(void)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+test_acpi_microvm_prepare();
+data.variant = ".pcie";
+data.tcg_only = true; /* need constant host-phys-bits */
+params = g_strdup_printf(" -machine microvm,"
+"acpi=on,ioapic2=off,rtc=off,pcie=on"
+" -object memory-backend-file,id=erstnvram,"
+   "mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+free_test_data();
+}
+
 static void test_acpi_virt_tcg(void)
 {
 test_data data = {
@@ -1675,6 +1726,8 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
 qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
 qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
+qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst);
+qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst);
 qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
 qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg);
 qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg);
@@ -1684,6 +1737,7 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs);
 if (strcmp(arch, "x86_64") == 0) {
 qtest_add_func("acpi/microvm/pcie", 
test_acpi_microvm_pcie_tcg);
+qtest_add_func("acpi/microvm/acpierst", 
test_acpi_microvm_acpi_erst);
 }
 }
 if (has_kvm) {
-- 
1.8.3.1




[PATCH v13 08/10] ACPI ERST: qtest for ERST

2022-01-24 Thread Eric DeVolder
This change provides a qtest that locates and then does a simple
interrogation of the ERST feature within the guest.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/erst-test.c | 172 
 tests/qtest/meson.build |   2 +
 2 files changed, 174 insertions(+)
 create mode 100644 tests/qtest/erst-test.c

diff --git a/tests/qtest/erst-test.c b/tests/qtest/erst-test.c
new file mode 100644
index 000..f9ad3c9
--- /dev/null
+++ b/tests/qtest/erst-test.c
@@ -0,0 +1,172 @@
+/*
+ * QTest testcase for acpi-erst
+ *
+ * Copyright (c) 2021 Oracle
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "libqos/libqos-pc.h"
+#include "libqos/libqtest.h"
+#include "qemu-common.h"
+
+#include "hw/pci/pci.h"
+
+static void save_fn(QPCIDevice *dev, int devfn, void *data)
+{
+QPCIDevice **pdev = (QPCIDevice **) data;
+
+*pdev = dev;
+}
+
+static QPCIDevice *get_erst_device(QPCIBus *pcibus)
+{
+QPCIDevice *dev;
+
+dev = NULL;
+qpci_device_foreach(pcibus,
+PCI_VENDOR_ID_REDHAT,
+PCI_DEVICE_ID_REDHAT_ACPI_ERST,
+save_fn, );
+g_assert(dev != NULL);
+
+return dev;
+}
+
+typedef struct _ERSTState {
+QOSState *qs;
+QPCIBar reg_bar, mem_bar;
+uint64_t reg_barsize, mem_barsize;
+QPCIDevice *dev;
+} ERSTState;
+
+#define ACTION 0
+#define VALUE 8
+
+static const char *reg2str(unsigned reg)
+{
+switch (reg) {
+case 0:
+return "ACTION";
+case 8:
+return "VALUE";
+default:
+return NULL;
+}
+}
+
+static inline uint32_t in_reg32(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint32_t res;
+
+res = qpci_io_readl(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %08x", name, res);
+
+return res;
+}
+
+static inline uint64_t in_reg64(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint64_t res;
+
+res = qpci_io_readq(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %016llx", name, (unsigned long long)res);
+
+return res;
+}
+
+static inline void out_reg32(ERSTState *s, unsigned reg, uint32_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%08x -> *%s", v, name);
+qpci_io_writel(s->dev, s->reg_bar, reg, v);
+}
+
+static inline void out_reg64(ERSTState *s, unsigned reg, uint64_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%016llx -> *%s", (unsigned long long)v, name);
+qpci_io_writeq(s->dev, s->reg_bar, reg, v);
+}
+
+static void cleanup_vm(ERSTState *s)
+{
+g_free(s->dev);
+qtest_shutdown(s->qs);
+}
+
+static void setup_vm_cmd(ERSTState *s, const char *cmd)
+{
+const char *arch = qtest_get_arch();
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+s->qs = qtest_pc_boot(cmd);
+} else {
+g_printerr("erst-test tests are only available on x86\n");
+exit(EXIT_FAILURE);
+}
+s->dev = get_erst_device(s->qs->pcibus);
+
+s->reg_bar = qpci_iomap(s->dev, 0, >reg_barsize);
+g_assert_cmpuint(s->reg_barsize, ==, 16);
+
+s->mem_bar = qpci_iomap(s->dev, 1, >mem_barsize);
+g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
+
+qpci_device_enable(s->dev);
+}
+
+static void test_acpi_erst_basic(void)
+{
+ERSTState state;
+uint64_t log_address_range;
+uint64_t log_address_length;
+uint32_t log_address_attr;
+
+setup_vm_cmd(,
+"-object memory-backend-file,"
+"mem-path=acpi-erst.XX,"
+"size=64K,"
+"share=on,"
+"id=nvram "
+"-device acpi-erst,"
+"memdev=nvram");
+
+out_reg32(, ACTION, 0xD);
+log_address_range = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xE);
+log_address_length = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xF);
+log_address_attr = in_reg32(, VALUE);
+
+/* Check log_address_range is not 0, ~0 or base */
+g_assert_cmpuint(log_address_range, !=,  0ULL);
+g_assert_cmpuint(log_address_range, !=, ~0ULL);
+g_assert_cmpuint(log_address_range, !=, state.reg_bar.addr);
+g_assert_cmpuint(log_address_range, ==, state.mem_bar.addr);
+
+/* Check log_address_length is bar1_size */
+g_assert_cmpuint(log_address_length, ==, state.mem_barsize);
+
+/* Check log_address_attr is 0 */
+g_assert_cmpuint(log_address_attr, ==, 0);
+
+cleanup_vm();
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+
+g_test_init(, , NULL);
+qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);

[PATCH v13 07/10] ACPI ERST: create ACPI ERST table for pc/x86 machines

2022-01-24 Thread Eric DeVolder
This change exposes ACPI ERST support for x86 guests.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/i386/acpi-build.c   | 15 +++
 hw/i386/acpi-microvm.c | 15 +++
 include/hw/acpi/erst.h |  5 +
 3 files changed, 35 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ce823e8..ebd47aa 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -43,6 +43,7 @@
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
 #include "hw/acpi/vmgenid.h"
+#include "hw/acpi/erst.h"
 #include "sysemu/tpm_backend.h"
 #include "hw/rtc/mc146818rtc_regs.h"
 #include "migration/vmstate.h"
@@ -74,6 +75,8 @@
 #include "hw/acpi/hmat.h"
 #include "hw/acpi/viot.h"
 
+#include CONFIG_DEVICES
+
 /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
  * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
  * a little bit, there should be plenty of free space since the DSDT
@@ -2575,6 +2578,18 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 vmgenid_dev = find_vmgenid_dev();
 if (vmgenid_dev) {
 acpi_add_table(table_offsets, tables_blob);
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index 196d318..68ca7e7 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -30,6 +30,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/acpi/utils.h"
+#include "hw/acpi/erst.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/i386/microvm.h"
 #include "hw/pci/pci.h"
@@ -40,6 +41,8 @@
 #include "acpi-common.h"
 #include "acpi-microvm.h"
 
+#include CONFIG_DEVICES
+
 static void acpi_dsdt_add_virtio(Aml *scope,
  MicrovmMachineState *mms)
 {
@@ -207,6 +210,18 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 xsdt = tables_blob->len;
 build_xsdt(tables_blob, tables->linker, table_offsets, x86ms->oem_id,
x86ms->oem_table_id);
diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
index 9d63717..b747fe7 100644
--- a/include/hw/acpi/erst.h
+++ b/include/hw/acpi/erst.h
@@ -16,4 +16,9 @@ void build_erst(GArray *table_data, BIOSLinker *linker, 
Object *erst_dev,
 
 #define TYPE_ACPI_ERST "acpi-erst"
 
+/* returns NULL unless there is exactly one device */
+static inline Object *find_erst_dev(void)
+{
+return object_resolve_path_type("", TYPE_ACPI_ERST, NULL);
+}
 #endif
-- 
1.8.3.1




[PATCH v13 01/10] ACPI ERST: bios-tables-test.c steps 1 and 2

2022-01-24 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change adds empty placeholder files per step 1 for the new ERST
table, and excludes resulting changed files in bios-tables-test-allowed-diff.h
per step 2.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/microvm/ERST.pcie   | 0
 tests/data/acpi/pc/DSDT.acpierst| 0
 tests/data/acpi/pc/ERST.acpierst| 0
 tests/data/acpi/q35/DSDT.acpierst   | 0
 tests/data/acpi/q35/ERST.acpierst   | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 5 +
 6 files changed, 5 insertions(+)
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/DSDT.acpierst 
b/tests/data/acpi/q35/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/ERST.acpierst 
b/tests/data/acpi/q35/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523..603db07 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,6 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/DSDT.acpierst",
+"tests/data/acpi/pc/ERST.acpierst",
+"tests/data/acpi/q35/DSDT.acpierst",
+"tests/data/acpi/q35/ERST.acpierst",
+"tests/data/acpi/microvm/ERST.pcie",
-- 
1.8.3.1




[PATCH v13 04/10] ACPI ERST: header file for ERST

2022-01-24 Thread Eric DeVolder
This change introduces the public defintions for ACPI ERST.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 include/hw/acpi/erst.h | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 include/hw/acpi/erst.h

diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
new file mode 100644
index 000..9d63717
--- /dev/null
+++ b/include/hw/acpi/erst.h
@@ -0,0 +1,19 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_ACPI_ERST_H
+#define HW_ACPI_ERST_H
+
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id);
+
+#define TYPE_ACPI_ERST "acpi-erst"
+
+#endif
-- 
1.8.3.1




[PATCH v13 02/10] ACPI ERST: specification for ERST support

2022-01-24 Thread Eric DeVolder
Information on the implementation of the ACPI ERST support.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 docs/specs/acpi_erst.rst | 200 +++
 1 file changed, 200 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst

diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 000..a8a9d22
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+-
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
+independent of, and runs before, kdump.  In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+---
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object 
memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x1,share=on
 \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+   this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+   required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+   parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+   ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+   backend storage. Must be a power of two value greater than or
+   equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers.  All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION.  Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+--
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record.  Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that identifies the contents
+as ERST and also facilitates efficient access to the records.
+Depending upon the size of the backend storage, additional slots will
+be designated

[PATCH v13 10/10] ACPI ERST: step 6 of bios-tables-test.c

2022-01-24 Thread Eric DeVolder
 }

 @@ -1399,11 +1394,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS "

  Method (DVNT, 2, NotSerialized)
  {
 -If ((Arg0 & 0x08))
 -{
 -Notify (S18, Arg1)
 -}
 -
  If ((Arg0 & 0x10))
  {
  Notify (S20, Arg1)

diff q35/DSDT and q35/DSDT.acpierst:
 @@ -5,13 +5,13 @@
   *
   * Disassembling to symbolic ASL+ operators
   *
 - * Disassembly of tests/data/acpi/q35/DSDT, Thu Dec  2 10:10:13 2021
 + * Disassembly of tests/data/acpi/q35/DSDT.acpierst, Thu Dec  2 12:59:36 2021
   *
   * Original Table Header:
   * Signature"DSDT"
 - * Length   0x2061 (8289)
 + * Length   0x2072 (8306)
   * Revision 0x01  32-bit table (V1), no 64-bit math support
 - * Checksum 0xFA
 + * Checksum 0x9A
   * OEM ID   "BOCHS "
   * OEM Table ID "BXPC"
   * OEM Revision 0x0001 (1)
 @@ -3278,6 +3278,11 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS "
  }
  }

 +Device (S10)
 +{
 +Name (_ADR, 0x0002)  // _ADR: Address
 +}
 +
  Method (PCNT, 0, NotSerialized)
  {
  }

For both pc and q35, there is but a small difference between this
DSDT.acpierst and the corresponding DSDT. In both cases, the changes
occur under the hiearchy:

Scope (\_SB)
{
Scope (PCI0)
{

which leads me to believe that the change to the DSDT was needed
due to the introduction of the ERST PCI device.

And is explained in detail by Ani Sinha:
I have convinced myself of the changes we see in the DSDT tables.
On i440fx side, we are adding a non-hotpluggable pci device on slot 3.
So the changes we see are basically replacing an empty hotpluggable
slot on the pci root port with a non-hotplugggable device.
On q35, bsel on pcie root bus is not set (its not hotpluggable bus),
so the change basically adds the address enumeration for the device.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 tests/data/acpi/microvm/ERST.pcie   | Bin 0 -> 912 bytes
 tests/data/acpi/pc/DSDT.acpierst| Bin 0 -> 5969 bytes
 tests/data/acpi/pc/ERST.acpierst| Bin 0 -> 912 bytes
 tests/data/acpi/q35/DSDT.acpierst   | Bin 0 -> 8306 bytes
 tests/data/acpi/q35/ERST.acpierst   | Bin 0 -> 912 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   5 -
 6 files changed, 5 deletions(-)

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a6d0cb783831ebc18972ec57bb6c624438ff150d
 100644
GIT binary patch
literal 912
zcmaKoTMmLS5Jd;doACJehb6cK12OSWBYwCn7ocm^-rA|;CUz1YmosPDa=fm$hY?9$
z^LaU~(|o@yldVKV@Q+UZ@>zwpS)GZ(sO?Lc}v64j-jFC7yn9;D$INO8pFiUB7f+
zf49KN+;jDxe>nP4Iq`z#7tC?s!tc6i7Z+t!@(t>{e2`4%
zZhiFB_p5lnFb*Ui&1$pT3_)pk?J?$-jLiezjJ$6`=r)uYry0Rn7KuJIp)|!
zckaizM=~sYzU*-I~PkUtAn>Dr`~u=;o(_O$t$PK8~R}U#`{0u*{
zz`m8fl|Wu#ucTKJu-TjNQ`rN~%rBccG0yWwF_}_zQl+X71|-_g)Pr`x1*Xgb!>QealcAR5Lj8F@vR~_hFrfVBOumUtb3<
zL8GI#8|W0leXv|!GGL=~vE5*uM7z%Af!czNXYqlQL#IT$!9xR0zORu68XY#=M-SGy
z3b+$tZv(*Hu4BBt4F>MUo>Padde^ZZU%V_4TiQ&6ruaomTLcp<9-2bBZ=qyp40+
ziEQ&$6L)c>%cI)0;%@F~Or>jX}g)!VlmH>3A6L#ZGj;i8(jvxl3w$XL%gc
z#4Y0Q*ces>sy7Obm6bTnr@oqih!n=P&+!w*9R95=2i+)QqA9kLa1VJk2ES
zOh6C4;>puBt75SyO`ippr%I9Z{pk6j=(st4aP-WP=ov412KgP0p3z1}&)7R9%3U9d
z!>df~G};j<@%&-TL`!{M=J{^0EAj)b4{!p{wbpF1J^oV~LmWA@f?c-apx
zmJl5aIOP$4%5j~Id6TV0{V^u0sG`|bSAOB2V2gb1@Ki7>g+T~D<}I$cZmy;lKl#kP
zxAm*k{f|HWWb1z8<4?h6y1Bg6FLiOw7Z@DC0gGYf$3^AUwgVosAOD1e9Hex!P-c3u
zY%#r3y2G$SrRg@$K+^S+fmJX`o|0}AmQ(0%hN|GcJ*{Ry{RpZVR_9(>4G!#sMm9K*-Kb2oqvI?7dL24<1WVww+F6k
zrAwi@3blP`ov2|RQA!4yn|HMt+|rp;ky|p}*s4Bhi{tS7b7IwWYtO
z($_%y0DUt+12O0t{g!qm$i(>FX+UGsM;osE9mca!r!@5Ld6Jt2$-nabyyC?4*zT@l2
z4LgzF3U^-%E&8T*RhMxH{B|{Nmd$hyhrlm@q(4{QfcO=jBztZw|gWU^0Q+lFdc4
z;t%ATAUG5ws_1bncmXfi8SEC{UBmF!TrD{!GvtiVS87Q`#ts;JTa>Png~+QvKOAg(
z=l%H)^?9Gb?Lui47fY7Bv8_MKSPiRTs@3YkU)Q{@YvnKAT;;J8U>fgQ>9qeF0+gJ!
zS_V9pumOy9sSU)%^lS1X17`o1`MA>W^ePI^H@E*S%`|HOx^c$lLHVkhwcpCba771jDZ#SdZmhM`3K=q{%
zNdudV5*`|Tn?lmSM!~R<_iYsI+Q3HPu(0YhlR~GImZVAKI~h
z+O@D02|KpVC?DEYlCeYxd&-j!?Kerrtt;#;Pd>DJ8RM1`cI=OKE{vc{!8uv6Z~
u5j$m$OK@OMk$l8{6J=Z)1AB{Pv}@<7F~|QN>AydkHSF$IS^vS{(*FTuhT2R3

literal 0
HcmV?d1

diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7965ac2562e7b23bf1dc2caaf00ef66453c4f47a
 100644
GIT binary patch
literal 912
zcmaKoOAdlC6h$9Upg{N}4xO+BmS7+z{Ww`+N;?C6GO0l^KeF>#Er>E`f@jBlg
ziAb~?&(mq{$NOdKO+_MtIsSwBP(BS`
zh6Ua)#A*M6_AiN-%#j24ugI^+uZh>pkpuT{$ZyEEIpDYCx8#=`Con^
B

[PATCH v13 03/10] ACPI ERST: PCI device_id for ERST

2022-01-24 Thread Eric DeVolder
This change reserves the PCI device_id for the new ACPI ERST
device.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
Acked-by: Ani Sinha 
---
 include/hw/pci/pci.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 023abc0..c3f3c90 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -108,6 +108,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_MDPY0x000f
 #define PCI_DEVICE_ID_REDHAT_NVME0x0010
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
+#define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
1.8.3.1




[PATCH v13 00/10] acpi: Error Record Serialization Table, ERST, support for QEMU

2022-01-24 Thread Eric DeVolder
This patchset introduces support for the ACPI Error Record
Serialization Table, ERST.

For background and implementation information, please see
docs/specs/acpi_erst.rst, which is patch 2/10.

Suggested-by: Konrad Wilk 
Signed-off-by: Eric DeVolder 

---
v13: 24jan2022
 - v12 erroneously omitted step 6 of bios-tables-test.c, this
   has step 6 included.
 - No other changes to v12.

v12: 10jan2022
 - Converted macros in build_erst() to uppert to follow coding
   style, as pointed out by Michael Tsirkin.
 - And few items to help further simplify build_erst().

v11: 15dec2021
 - Simplified build_erst() via feedback from Michael Tsirkin
 - Addressed additional feedback from Ani Sinha

v10: 9dec2021
 - Addressed additional feedback from Ani Sinha

v9: 2dec2021
 - Addressed feedback from Ani Sinha

v8: 15oct2021
 - Added Kconfig option for ERST, per Ani Sinha
 - Fixed patch ordering, per Ani

v7: 7oct2021
 - style improvements, per Igor
 - use of endian accessors for storage header, per Igor
 - a number of optimizations and improvements, per Igor
 - updated spec for header, per Igor
 - updated spec for rst format, per Michael Tsirkin
 - updated spec for new record_size parameter
   Due to changes in the spec, I am not carrying the
   Acked-by from Ani Sinha.
 - changes for and testing of migration to systems with
   differing ERST_RECORD_SIZE

v6: 5aug2021
 - Fixed compile warning/error, per Michael Tsirkin
 - Fixed mingw32 build error, per Michael
 - Converted exchange buffer to MemoryBackend, per Igor
 - Migrated test to PCI, per Igor
 - Significantly reduced amount of copying, per Igor
 - Corrections/enhancements to acpi_erst.txt, per Igor
 - Many misc/other small items, per Igor

v5: 30jun2021
 - Create docs/specs/acpi_erst.txt, per Igor
 - Separate PCI BARs for registers and memory, per Igor
 - Convert debugging to use trace infrastructure, per Igor
 - Various other fixups, per Igor

v4: 11jun2021
 - Converted to a PCI device, per Igor.
 - Updated qtest.
 - Rearranged patches, per Igor.

v3: 28may2021
 - Converted to using a TYPE_MEMORY_BACKEND_FILE object rather than
   internal array with explicit file operations, per Igor.
 - Changed the way the qdev and base address are handled, allowing
   ERST to be disabled at run-time. Also aligns better with other
   existing code.

v2: 8feb2021
 - Added qtest/smoke test per Paolo Bonzini
 - Split patch into smaller chunks, per Igor Mammedov
 - Did away with use of ACPI packed structures, per Igor Mammedov

v1: 26oct2020
 - initial post

---
Eric DeVolder (10):
  ACPI ERST: bios-tables-test.c steps 1 and 2
  ACPI ERST: specification for ERST support
  ACPI ERST: PCI device_id for ERST
  ACPI ERST: header file for ERST
  ACPI ERST: support for ACPI ERST feature
  ACPI ERST: build the ACPI ERST table
  ACPI ERST: create ACPI ERST table for pc/x86 machines
  ACPI ERST: qtest for ERST
  ACPI ERST: bios-tables-test testcase
  ACPI ERST: step 6 of bios-tables-test.c

 docs/specs/acpi_erst.rst  |  200 +++
 hw/acpi/Kconfig   |6 +
 hw/acpi/erst.c| 1032 +
 hw/acpi/meson.build   |1 +
 hw/acpi/trace-events  |   15 +
 hw/i386/acpi-build.c  |   15 +
 hw/i386/acpi-microvm.c|   15 +
 include/hw/acpi/erst.h|   24 +
 include/hw/pci/pci.h  |1 +
 tests/data/acpi/microvm/ERST.pcie |  Bin 0 -> 912 bytes
 tests/data/acpi/pc/DSDT.acpierst  |  Bin 0 -> 5969 bytes
 tests/data/acpi/pc/ERST.acpierst  |  Bin 0 -> 912 bytes
 tests/data/acpi/q35/DSDT.acpierst |  Bin 0 -> 8306 bytes
 tests/data/acpi/q35/ERST.acpierst |  Bin 0 -> 912 bytes
 tests/qtest/bios-tables-test.c|   54 ++
 tests/qtest/erst-test.c   |  172 +++
 tests/qtest/meson.build   |2 +
 17 files changed, 1537 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst
 create mode 100644 hw/acpi/erst.c
 create mode 100644 include/hw/acpi/erst.h
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst
 create mode 100644 tests/qtest/erst-test.c

-- 
1.8.3.1




[PATCH v13 06/10] ACPI ERST: build the ACPI ERST table

2022-01-24 Thread Eric DeVolder
This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
 hw/acpi/erst.c | 188 +
 1 file changed, 188 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index fe9ba51..b0c7539 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
 #define STATUS_RECORD_STORE_EMPTY 0x04
 #define STATUS_RECORD_NOT_FOUND   0x05
 
+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
 /* UEFI 2.1: Appendix N Common Platform Error Record */
 #define UEFI_CPER_RECORD_MIN_SIZE 128U
 #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,173 @@ typedef struct {
 
 /***/
 /***/
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+uint8_t serialization_action,
+uint8_t instruction,
+uint8_t flags,
+uint8_t register_bit_width,
+uint64_t register_address,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(table_data, instruction , 1);
+/* Flags */
+build_append_int_noprefix(table_data, flags   , 1);
+/* Reserved */
+build_append_int_noprefix(table_data, 0   , 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(register_bit_width) - 2;
+gas.address = register_address;
+build_append_gas_from_struct(table_data, );
+/* Value */
+build_append_int_noprefix(table_data, value  , 8);
+/* Mask */
+mask = (1ULL << (register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(table_data, mask  , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+GArray *table_instruction_data;
+unsigned action;
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+
+trace_acpi_erst_pci_bar_0(bar0);
+
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+
+/*
+ * Macros for use with construction of the action instructions
+ */
+#define BUILD_READ_REGISTER(width_in_bits, reg) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER, 0, width_in_bits, \
+bar0 + reg, 0)
+
+#define BUILD_READ_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+/* Serialization Instruction Entries */
+action = ACTION_BEGIN_WRITE_OPERATION;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTIO

Re: [PATCH v9 05/10] ACPI ERST: support for ACPI ERST feature

2022-01-11 Thread Eric DeVolder

Ani,
I'll change this from the g_assert_not_reached() back to STATUS_FAILED.
Alas I realized I didn't do the last step in producing the new ACPI tables in the patchset, so even 
though I just put out v12, I'll need to do a followup v13 with the missing tables.

Thanks!
eric

On 1/11/22 02:35, Ani Sinha wrote:

On Tue, Dec 14, 2021 at 2:33 AM Eric DeVolder  wrote:


Ani, an inline response below.
Thanks!
eric

On 12/10/21 08:09, Ani Sinha wrote:

On Thu, Dec 9, 2021 at 11:24 PM Eric DeVolder  wrote:


Ani, inline responses below. eric

On 12/9/21 00:29, Ani Sinha wrote:

On Fri, Dec 3, 2021 at 12:39 AM Eric DeVolder  wrote:


This implements a PCI device for ACPI ERST. This implements the
non-NVRAM "mode" of operation for ERST as it is supported by
Linux and Windows.


Few more comments on this patch ...



Signed-off-by: Eric DeVolder 
---
hw/acpi/Kconfig  |   6 +
hw/acpi/erst.c   | 836 
+++
hw/acpi/meson.build  |   1 +
hw/acpi/trace-events |  15 +
4 files changed, 858 insertions(+)
create mode 100644 hw/acpi/erst.c

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b5..19caebd 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -10,6 +10,7 @@ config ACPI_X86
select ACPI_HMAT
select ACPI_PIIX4
select ACPI_PCIHP
+select ACPI_ERST

config ACPI_X86_ICH
bool
@@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
select ACPI
select ACPI_MEMORY_HOTPLUG
select ACPI_NVDIMM
+
+config ACPI_ERST
+bool
+default y
+depends on ACPI && PCI
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
new file mode 100644
index 000..4304f55
--- /dev/null
+++ b/hw/acpi/erst.c
@@ -0,0 +1,836 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+#include 
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-core.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/pci/pci.h"
+#include "qom/object_interfaces.h"
+#include "qemu/error-report.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/hostmem.h"
+#include "hw/acpi/erst.h"
+#include "trace.h"
+
+/* ACPI 4.0: Table 17-16 Serialization Actions */
+#define ACTION_BEGIN_WRITE_OPERATION 0x0
+#define ACTION_BEGIN_READ_OPERATION  0x1
+#define ACTION_BEGIN_CLEAR_OPERATION 0x2
+#define ACTION_END_OPERATION 0x3
+#define ACTION_SET_RECORD_OFFSET 0x4
+#define ACTION_EXECUTE_OPERATION 0x5
+#define ACTION_CHECK_BUSY_STATUS 0x6
+#define ACTION_GET_COMMAND_STATUS0x7
+#define ACTION_GET_RECORD_IDENTIFIER 0x8
+#define ACTION_SET_RECORD_IDENTIFIER 0x9
+#define ACTION_GET_RECORD_COUNT  0xA
+#define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
+#define ACTION_RESERVED  0xC
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
+#define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
+#define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10
+
+/* ACPI 4.0: Table 17-17 Command Status Definitions */
+#define STATUS_SUCCESS0x00
+#define STATUS_NOT_ENOUGH_SPACE   0x01
+#define STATUS_HARDWARE_NOT_AVAILABLE 0x02
+#define STATUS_FAILED 0x03
+#define STATUS_RECORD_STORE_EMPTY 0x04
+#define STATUS_RECORD_NOT_FOUND   0x05
+
+
+/* UEFI 2.1: Appendix N Common Platform Error Record */
+#define UEFI_CPER_RECORD_MIN_SIZE 128U
+#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
+#define UEFI_CPER_RECORD_ID_OFFSET 96U
+#define IS_UEFI_CPER_RECORD(ptr) \
+(((ptr)[0] == 'C') && \
+ ((ptr)[1] == 'P') && \
+ ((ptr)[2] == 'E') && \
+ ((ptr)[3] == 'R'))
+
+/*
+ * NOTE that when accessing CPER fields within a record, memcpy()
+ * is utilized to avoid a possible misaligned access on the host.
+ */
+
+/*
+ * This implementation is an ACTION (cmd) and VALUE (data)
+ * interface consisting of just two 64-bit registers.
+ */
+#define ERST_REG_SIZE (16UL)
+#define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
+#define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
+
+/*
+ * ERST_RECORD_SIZE is the buffer size for exchanging ERST
+ * record contents. Thus, it defines the maximum record size.
+ * As this is mapped through a PCI BAR, it must be a powe

Re: [PATCH v11 06/10] ACPI ERST: build the ACPI ERST table

2022-01-10 Thread Eric DeVolder

Thanks for looking at this Michael, I've an inline response below.
eric

On 1/6/22 04:45, Michael S. Tsirkin wrote:

On Wed, Dec 15, 2021 at 10:38:11AM -0500, Eric DeVolder wrote:

This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
  hw/acpi/erst.c | 188 +
  1 file changed, 188 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index bb6cad4..05177b3 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
  #define STATUS_RECORD_STORE_EMPTY 0x04
  #define STATUS_RECORD_NOT_FOUND   0x05
  
+/* ACPI 4.0: Table 17-19 Serialization Instructions */

+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
  /* UEFI 2.1: Appendix N Common Platform Error Record */
  #define UEFI_CPER_RECORD_MIN_SIZE 128U
  #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,173 @@ typedef struct {
  
  /***/

  /***/
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+uint8_t serialization_action,
+uint8_t instruction,
+uint8_t flags,
+uint8_t register_bit_width,
+uint64_t register_address,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(table_data, instruction , 1);
+/* Flags */
+build_append_int_noprefix(table_data, flags   , 1);
+/* Reserved */
+build_append_int_noprefix(table_data, 0   , 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(register_bit_width) - 2;
+gas.address = register_address;
+build_append_gas_from_struct(table_data, );
+/* Value */
+build_append_int_noprefix(table_data, value  , 8);
+/* Mask */
+mask = (1ULL << (register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(table_data, mask  , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+GArray *table_instruction_data;
+unsigned action;
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+
+trace_acpi_erst_pci_bar_0(bar0);
+
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+
+/*
+ * Macros for use with construction of the action instructions
+ */
+#define build_read_register(action, width_in_bits, reg) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER, 0, width_in_bits, \
+bar0 + reg, 0)
+
+#define build_read_register_value(action, width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define build_write_register(action, width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define build_write_register_value(action, width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER_VALUE, 0, width_in_bits, \
+   

[PATCH v12 6/9] ACPI ERST: build the ACPI ERST table

2022-01-10 Thread Eric DeVolder
This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
 hw/acpi/erst.c | 188 +
 1 file changed, 188 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index bb6cad4..00dbd8be 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
 #define STATUS_RECORD_STORE_EMPTY 0x04
 #define STATUS_RECORD_NOT_FOUND   0x05
 
+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
 /* UEFI 2.1: Appendix N Common Platform Error Record */
 #define UEFI_CPER_RECORD_MIN_SIZE 128U
 #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,173 @@ typedef struct {
 
 /***/
 /***/
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+uint8_t serialization_action,
+uint8_t instruction,
+uint8_t flags,
+uint8_t register_bit_width,
+uint64_t register_address,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(table_data, instruction , 1);
+/* Flags */
+build_append_int_noprefix(table_data, flags   , 1);
+/* Reserved */
+build_append_int_noprefix(table_data, 0   , 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(register_bit_width) - 2;
+gas.address = register_address;
+build_append_gas_from_struct(table_data, );
+/* Value */
+build_append_int_noprefix(table_data, value  , 8);
+/* Mask */
+mask = (1ULL << (register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(table_data, mask  , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+GArray *table_instruction_data;
+unsigned action;
+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+
+trace_acpi_erst_pci_bar_0(bar0);
+
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+
+/*
+ * Macros for use with construction of the action instructions
+ */
+#define BUILD_READ_REGISTER(width_in_bits, reg) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER, 0, width_in_bits, \
+bar0 + reg, 0)
+
+#define BUILD_READ_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define BUILD_WRITE_REGISTER_VALUE(width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+/* Serialization Instruction Entries */
+action = ACTION_BEGIN_WRITE_OPERATION;
+BUILD_WRITE_REGISTER_VALUE(32, ERST_ACTION_OFFSET, action);
+
+action = ACTIO

[PATCH v12 5/9] ACPI ERST: support for ACPI ERST feature

2022-01-10 Thread Eric DeVolder
This implements a PCI device for ACPI ERST. This implements the
non-NVRAM "mode" of operation for ERST as it is supported by
Linux and Windows.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/acpi/Kconfig  |   6 +
 hw/acpi/erst.c   | 845 +++
 hw/acpi/meson.build  |   1 +
 hw/acpi/trace-events |  15 +
 4 files changed, 867 insertions(+)
 create mode 100644 hw/acpi/erst.c

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b5..19caebd 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -10,6 +10,7 @@ config ACPI_X86
 select ACPI_HMAT
 select ACPI_PIIX4
 select ACPI_PCIHP
+select ACPI_ERST
 
 config ACPI_X86_ICH
 bool
@@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
 select ACPI
 select ACPI_MEMORY_HOTPLUG
 select ACPI_NVDIMM
+
+config ACPI_ERST
+bool
+default y
+depends on ACPI && PCI
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
new file mode 100644
index 000..bb6cad4
--- /dev/null
+++ b/hw/acpi/erst.c
@@ -0,0 +1,845 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+#include 
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-core.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/pci/pci.h"
+#include "qom/object_interfaces.h"
+#include "qemu/error-report.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/hostmem.h"
+#include "hw/acpi/erst.h"
+#include "trace.h"
+
+/* ACPI 4.0: Table 17-16 Serialization Actions */
+#define ACTION_BEGIN_WRITE_OPERATION 0x0
+#define ACTION_BEGIN_READ_OPERATION  0x1
+#define ACTION_BEGIN_CLEAR_OPERATION 0x2
+#define ACTION_END_OPERATION 0x3
+#define ACTION_SET_RECORD_OFFSET 0x4
+#define ACTION_EXECUTE_OPERATION 0x5
+#define ACTION_CHECK_BUSY_STATUS 0x6
+#define ACTION_GET_COMMAND_STATUS0x7
+#define ACTION_GET_RECORD_IDENTIFIER 0x8
+#define ACTION_SET_RECORD_IDENTIFIER 0x9
+#define ACTION_GET_RECORD_COUNT  0xA
+#define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
+#define ACTION_RESERVED  0xC
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
+#define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
+#define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10 /* ACPI 6.3 */
+
+/* ACPI 4.0: Table 17-17 Command Status Definitions */
+#define STATUS_SUCCESS0x00
+#define STATUS_NOT_ENOUGH_SPACE   0x01
+#define STATUS_HARDWARE_NOT_AVAILABLE 0x02
+#define STATUS_FAILED 0x03
+#define STATUS_RECORD_STORE_EMPTY 0x04
+#define STATUS_RECORD_NOT_FOUND   0x05
+
+/* UEFI 2.1: Appendix N Common Platform Error Record */
+#define UEFI_CPER_RECORD_MIN_SIZE 128U
+#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
+#define UEFI_CPER_RECORD_ID_OFFSET 96U
+#define IS_UEFI_CPER_RECORD(ptr) \
+(((ptr)[0] == 'C') && \
+ ((ptr)[1] == 'P') && \
+ ((ptr)[2] == 'E') && \
+ ((ptr)[3] == 'R'))
+
+/*
+ * NOTE that when accessing CPER fields within a record, memcpy()
+ * is utilized to avoid a possible misaligned access on the host.
+ */
+
+/*
+ * This implementation is an ACTION (cmd) and VALUE (data)
+ * interface consisting of just two 64-bit registers.
+ */
+#define ERST_REG_SIZE (16UL)
+#define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
+#define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
+
+/*
+ * ERST_RECORD_SIZE is the buffer size for exchanging ERST
+ * record contents. Thus, it defines the maximum record size.
+ * As this is mapped through a PCI BAR, it must be a power of
+ * two and larger than UEFI_CPER_RECORD_MIN_SIZE.
+ * The backing storage is divided into fixed size "slots",
+ * each ERST_RECORD_SIZE in length, and each "slot"
+ * storing a single record. No attempt at optimizing storage
+ * through compression, compaction, etc is attempted.
+ * NOTE that slot 0 is reserved for the backing storage header.
+ * Depending upon the size of the backing storage, additional
+ * slots will be part of the slot 0 header in order to account
+ * for a record_id for each available remaining slot.
+ */
+/* 8KiB records, not too small, not too big */
+#define ERST_RECORD_SIZE (8192UL)
+
+#define ACPI_ERST_MEMDEV_PROP "

[PATCH v12 4/9] ACPI ERST: header file for ERST

2022-01-10 Thread Eric DeVolder
This change introduces the public defintions for ACPI ERST.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 include/hw/acpi/erst.h | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 include/hw/acpi/erst.h

diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
new file mode 100644
index 000..9d63717
--- /dev/null
+++ b/include/hw/acpi/erst.h
@@ -0,0 +1,19 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_ACPI_ERST_H
+#define HW_ACPI_ERST_H
+
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id);
+
+#define TYPE_ACPI_ERST "acpi-erst"
+
+#endif
-- 
1.8.3.1




[PATCH v12 9/9] ACPI ERST: bios-tables-test testcase

2022-01-10 Thread Eric DeVolder
This change implements the test suite checks for the ERST table.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/bios-tables-test.c | 54 ++
 1 file changed, 54 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index e6b72d9..266b215 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1446,6 +1446,57 @@ static void test_acpi_piix4_tcg_acpi_hmat(void)
 test_acpi_tcg_acpi_hmat(MACHINE_PC);
 }
 
+static void test_acpi_erst(const char *machine)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+memset(, 0, sizeof(data));
+data.machine = machine;
+data.variant = ".acpierst";
+params = g_strdup_printf(
+" -object memory-backend-file,id=erstnvram,"
+"mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+free_test_data();
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+}
+
+static void test_acpi_piix4_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_PC);
+}
+
+static void test_acpi_q35_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_Q35);
+}
+
+static void test_acpi_microvm_acpi_erst(void)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+test_acpi_microvm_prepare();
+data.variant = ".pcie";
+data.tcg_only = true; /* need constant host-phys-bits */
+params = g_strdup_printf(" -machine microvm,"
+"acpi=on,ioapic2=off,rtc=off,pcie=on"
+" -object memory-backend-file,id=erstnvram,"
+   "mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+free_test_data();
+}
+
 static void test_acpi_virt_tcg(void)
 {
 test_data data = {
@@ -1675,6 +1726,8 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
 qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
 qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
+qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst);
+qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst);
 qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
 qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg);
 qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg);
@@ -1684,6 +1737,7 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs);
 if (strcmp(arch, "x86_64") == 0) {
 qtest_add_func("acpi/microvm/pcie", 
test_acpi_microvm_pcie_tcg);
+qtest_add_func("acpi/microvm/acpierst", 
test_acpi_microvm_acpi_erst);
 }
 }
 if (has_kvm) {
-- 
1.8.3.1




[PATCH v12 1/9] ACPI ERST: bios-tables-test.c steps 1 and 2

2022-01-10 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change adds empty placeholder files per step 1 for the new ERST
table, and excludes resulting changed files in bios-tables-test-allowed-diff.h
per step 2.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/microvm/ERST.pcie   | 0
 tests/data/acpi/pc/DSDT.acpierst| 0
 tests/data/acpi/pc/ERST.acpierst| 0
 tests/data/acpi/q35/DSDT.acpierst   | 0
 tests/data/acpi/q35/ERST.acpierst   | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 5 +
 6 files changed, 5 insertions(+)
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/DSDT.acpierst 
b/tests/data/acpi/q35/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/ERST.acpierst 
b/tests/data/acpi/q35/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523..603db07 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,6 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/DSDT.acpierst",
+"tests/data/acpi/pc/ERST.acpierst",
+"tests/data/acpi/q35/DSDT.acpierst",
+"tests/data/acpi/q35/ERST.acpierst",
+"tests/data/acpi/microvm/ERST.pcie",
-- 
1.8.3.1




[PATCH v12 7/9] ACPI ERST: create ACPI ERST table for pc/x86 machines

2022-01-10 Thread Eric DeVolder
This change exposes ACPI ERST support for x86 guests.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/i386/acpi-build.c   | 15 +++
 hw/i386/acpi-microvm.c | 15 +++
 include/hw/acpi/erst.h |  5 +
 3 files changed, 35 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ce823e8..ebd47aa 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -43,6 +43,7 @@
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
 #include "hw/acpi/vmgenid.h"
+#include "hw/acpi/erst.h"
 #include "sysemu/tpm_backend.h"
 #include "hw/rtc/mc146818rtc_regs.h"
 #include "migration/vmstate.h"
@@ -74,6 +75,8 @@
 #include "hw/acpi/hmat.h"
 #include "hw/acpi/viot.h"
 
+#include CONFIG_DEVICES
+
 /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
  * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
  * a little bit, there should be plenty of free space since the DSDT
@@ -2575,6 +2578,18 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 vmgenid_dev = find_vmgenid_dev();
 if (vmgenid_dev) {
 acpi_add_table(table_offsets, tables_blob);
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index 196d318..68ca7e7 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -30,6 +30,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/acpi/utils.h"
+#include "hw/acpi/erst.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/i386/microvm.h"
 #include "hw/pci/pci.h"
@@ -40,6 +41,8 @@
 #include "acpi-common.h"
 #include "acpi-microvm.h"
 
+#include CONFIG_DEVICES
+
 static void acpi_dsdt_add_virtio(Aml *scope,
  MicrovmMachineState *mms)
 {
@@ -207,6 +210,18 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
 ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
 x86ms->oem_table_id);
 
+#ifdef CONFIG_ACPI_ERST
+{
+Object *erst_dev;
+erst_dev = find_erst_dev();
+if (erst_dev) {
+acpi_add_table(table_offsets, tables_blob);
+build_erst(tables_blob, tables->linker, erst_dev,
+   x86ms->oem_id, x86ms->oem_table_id);
+}
+}
+#endif
+
 xsdt = tables_blob->len;
 build_xsdt(tables_blob, tables->linker, table_offsets, x86ms->oem_id,
x86ms->oem_table_id);
diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
index 9d63717..b747fe7 100644
--- a/include/hw/acpi/erst.h
+++ b/include/hw/acpi/erst.h
@@ -16,4 +16,9 @@ void build_erst(GArray *table_data, BIOSLinker *linker, 
Object *erst_dev,
 
 #define TYPE_ACPI_ERST "acpi-erst"
 
+/* returns NULL unless there is exactly one device */
+static inline Object *find_erst_dev(void)
+{
+return object_resolve_path_type("", TYPE_ACPI_ERST, NULL);
+}
 #endif
-- 
1.8.3.1




[PATCH v12 8/9] ACPI ERST: qtest for ERST

2022-01-10 Thread Eric DeVolder
This change provides a qtest that locates and then does a simple
interrogation of the ERST feature within the guest.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/erst-test.c | 172 
 tests/qtest/meson.build |   2 +
 2 files changed, 174 insertions(+)
 create mode 100644 tests/qtest/erst-test.c

diff --git a/tests/qtest/erst-test.c b/tests/qtest/erst-test.c
new file mode 100644
index 000..f9ad3c9
--- /dev/null
+++ b/tests/qtest/erst-test.c
@@ -0,0 +1,172 @@
+/*
+ * QTest testcase for acpi-erst
+ *
+ * Copyright (c) 2021 Oracle
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "libqos/libqos-pc.h"
+#include "libqos/libqtest.h"
+#include "qemu-common.h"
+
+#include "hw/pci/pci.h"
+
+static void save_fn(QPCIDevice *dev, int devfn, void *data)
+{
+QPCIDevice **pdev = (QPCIDevice **) data;
+
+*pdev = dev;
+}
+
+static QPCIDevice *get_erst_device(QPCIBus *pcibus)
+{
+QPCIDevice *dev;
+
+dev = NULL;
+qpci_device_foreach(pcibus,
+PCI_VENDOR_ID_REDHAT,
+PCI_DEVICE_ID_REDHAT_ACPI_ERST,
+save_fn, );
+g_assert(dev != NULL);
+
+return dev;
+}
+
+typedef struct _ERSTState {
+QOSState *qs;
+QPCIBar reg_bar, mem_bar;
+uint64_t reg_barsize, mem_barsize;
+QPCIDevice *dev;
+} ERSTState;
+
+#define ACTION 0
+#define VALUE 8
+
+static const char *reg2str(unsigned reg)
+{
+switch (reg) {
+case 0:
+return "ACTION";
+case 8:
+return "VALUE";
+default:
+return NULL;
+}
+}
+
+static inline uint32_t in_reg32(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint32_t res;
+
+res = qpci_io_readl(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %08x", name, res);
+
+return res;
+}
+
+static inline uint64_t in_reg64(ERSTState *s, unsigned reg)
+{
+const char *name = reg2str(reg);
+uint64_t res;
+
+res = qpci_io_readq(s->dev, s->reg_bar, reg);
+g_test_message("*%s -> %016llx", name, (unsigned long long)res);
+
+return res;
+}
+
+static inline void out_reg32(ERSTState *s, unsigned reg, uint32_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%08x -> *%s", v, name);
+qpci_io_writel(s->dev, s->reg_bar, reg, v);
+}
+
+static inline void out_reg64(ERSTState *s, unsigned reg, uint64_t v)
+{
+const char *name = reg2str(reg);
+
+g_test_message("%016llx -> *%s", (unsigned long long)v, name);
+qpci_io_writeq(s->dev, s->reg_bar, reg, v);
+}
+
+static void cleanup_vm(ERSTState *s)
+{
+g_free(s->dev);
+qtest_shutdown(s->qs);
+}
+
+static void setup_vm_cmd(ERSTState *s, const char *cmd)
+{
+const char *arch = qtest_get_arch();
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+s->qs = qtest_pc_boot(cmd);
+} else {
+g_printerr("erst-test tests are only available on x86\n");
+exit(EXIT_FAILURE);
+}
+s->dev = get_erst_device(s->qs->pcibus);
+
+s->reg_bar = qpci_iomap(s->dev, 0, >reg_barsize);
+g_assert_cmpuint(s->reg_barsize, ==, 16);
+
+s->mem_bar = qpci_iomap(s->dev, 1, >mem_barsize);
+g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
+
+qpci_device_enable(s->dev);
+}
+
+static void test_acpi_erst_basic(void)
+{
+ERSTState state;
+uint64_t log_address_range;
+uint64_t log_address_length;
+uint32_t log_address_attr;
+
+setup_vm_cmd(,
+"-object memory-backend-file,"
+"mem-path=acpi-erst.XX,"
+"size=64K,"
+"share=on,"
+"id=nvram "
+"-device acpi-erst,"
+"memdev=nvram");
+
+out_reg32(, ACTION, 0xD);
+log_address_range = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xE);
+log_address_length = in_reg64(, VALUE);
+out_reg32(, ACTION, 0xF);
+log_address_attr = in_reg32(, VALUE);
+
+/* Check log_address_range is not 0, ~0 or base */
+g_assert_cmpuint(log_address_range, !=,  0ULL);
+g_assert_cmpuint(log_address_range, !=, ~0ULL);
+g_assert_cmpuint(log_address_range, !=, state.reg_bar.addr);
+g_assert_cmpuint(log_address_range, ==, state.mem_bar.addr);
+
+/* Check log_address_length is bar1_size */
+g_assert_cmpuint(log_address_length, ==, state.mem_barsize);
+
+/* Check log_address_attr is 0 */
+g_assert_cmpuint(log_address_attr, ==, 0);
+
+cleanup_vm();
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+
+g_test_init(, , NULL);
+qtest_add_func("/acpi-erst/basic", test_acpi_erst_basic);

[PATCH v12 3/9] ACPI ERST: PCI device_id for ERST

2022-01-10 Thread Eric DeVolder
This change reserves the PCI device_id for the new ACPI ERST
device.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
Acked-by: Ani Sinha 
---
 include/hw/pci/pci.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 483d5c7..19db80e 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -108,6 +108,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_MDPY0x000f
 #define PCI_DEVICE_ID_REDHAT_NVME0x0010
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
+#define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
1.8.3.1




[PATCH v12 0/9] acpi: Error Record Serialization Table, ERST, support for QEMU

2022-01-10 Thread Eric DeVolder
This patchset introduces support for the ACPI Error Record
Serialization Table, ERST.

For background and implementation information, please see
docs/specs/acpi_erst.rst, which is patch 2/10.

Suggested-by: Konrad Wilk 
Signed-off-by: Eric DeVolder 

---
v12: 10jan2022
 - Converted macros in build_erst() to uppert to follow coding
   style, as pointed out by Michael Tsirkin.
 - And few items to help further simplify build_erst().

v11: 15dec2021
 - Simplified build_erst() via feedback from Michael Tsirkin
 - Addressed additional feedback from Ani Sinha

v10: 9dec2021
 - Addressed additional feedback from Ani Sinha

v9: 2dec2021
 - Addressed feedback from Ani Sinha

v8: 15oct2021
 - Added Kconfig option for ERST, per Ani Sinha
 - Fixed patch ordering, per Ani

v7: 7oct2021
 - style improvements, per Igor
 - use of endian accessors for storage header, per Igor
 - a number of optimizations and improvements, per Igor
 - updated spec for header, per Igor
 - updated spec for rst format, per Michael Tsirkin
 - updated spec for new record_size parameter
   Due to changes in the spec, I am not carrying the
   Acked-by from Ani Sinha.
 - changes for and testing of migration to systems with
   differing ERST_RECORD_SIZE

v6: 5aug2021
 - Fixed compile warning/error, per Michael Tsirkin
 - Fixed mingw32 build error, per Michael
 - Converted exchange buffer to MemoryBackend, per Igor
 - Migrated test to PCI, per Igor
 - Significantly reduced amount of copying, per Igor
 - Corrections/enhancements to acpi_erst.txt, per Igor
 - Many misc/other small items, per Igor

v5: 30jun2021
 - Create docs/specs/acpi_erst.txt, per Igor
 - Separate PCI BARs for registers and memory, per Igor
 - Convert debugging to use trace infrastructure, per Igor
 - Various other fixups, per Igor

v4: 11jun2021
 - Converted to a PCI device, per Igor.
 - Updated qtest.
 - Rearranged patches, per Igor.

v3: 28may2021
 - Converted to using a TYPE_MEMORY_BACKEND_FILE object rather than
   internal array with explicit file operations, per Igor.
 - Changed the way the qdev and base address are handled, allowing
   ERST to be disabled at run-time. Also aligns better with other
   existing code.

v2: 8feb2021
 - Added qtest/smoke test per Paolo Bonzini
 - Split patch into smaller chunks, per Igor Mammedov
 - Did away with use of ACPI packed structures, per Igor Mammedov

v1: 26oct2020
 - initial post

---
Eric DeVolder (9):
  ACPI ERST: bios-tables-test.c steps 1 and 2
  ACPI ERST: specification for ERST support
  ACPI ERST: PCI device_id for ERST
  ACPI ERST: header file for ERST
  ACPI ERST: support for ACPI ERST feature
  ACPI ERST: build the ACPI ERST table
  ACPI ERST: create ACPI ERST table for pc/x86 machines
  ACPI ERST: qtest for ERST
  ACPI ERST: bios-tables-test testcase

 docs/specs/acpi_erst.rst|  200 ++
 hw/acpi/Kconfig |6 +
 hw/acpi/erst.c  | 1033 +++
 hw/acpi/meson.build |1 +
 hw/acpi/trace-events|   15 +
 hw/i386/acpi-build.c|   15 +
 hw/i386/acpi-microvm.c  |   15 +
 include/hw/acpi/erst.h  |   24 +
 include/hw/pci/pci.h|1 +
 tests/data/acpi/microvm/ERST.pcie   |0
 tests/data/acpi/pc/DSDT.acpierst|0
 tests/data/acpi/pc/ERST.acpierst|0
 tests/data/acpi/q35/DSDT.acpierst   |0
 tests/data/acpi/q35/ERST.acpierst   |0
 tests/qtest/bios-tables-test-allowed-diff.h |5 +
 tests/qtest/bios-tables-test.c  |   54 ++
 tests/qtest/erst-test.c |  172 +
 tests/qtest/meson.build |2 +
 18 files changed, 1543 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst
 create mode 100644 hw/acpi/erst.c
 create mode 100644 include/hw/acpi/erst.h
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst
 create mode 100644 tests/qtest/erst-test.c

-- 
1.8.3.1




[PATCH v12 2/9] ACPI ERST: specification for ERST support

2022-01-10 Thread Eric DeVolder
Information on the implementation of the ACPI ERST support.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 docs/specs/acpi_erst.rst | 200 +++
 1 file changed, 200 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst

diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 000..a8a9d22
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+-
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
+independent of, and runs before, kdump.  In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+---
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object 
memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x1,share=on
 \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+   this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+   required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+   parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+   ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+   backend storage. Must be a power of two value greater than or
+   equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers.  All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION.  Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+--
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record.  Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that identifies the contents
+as ERST and also facilitates efficient access to the records.
+Depending upon the size of the backend storage, additional slots will
+be designated

Re: [PATCH v11 06/10] ACPI ERST: build the ACPI ERST table

2021-12-15 Thread Eric DeVolder

Hi Ani,
Thanks for such quick feedback! One inline response below.
eric

On 12/15/21 10:33, Ani Sinha wrote:

On Wed, Dec 15, 2021 at 9:08 PM Eric DeVolder  wrote:


This builds the ACPI ERST table to inform OSPM how to communicate
with the acpi-erst device.

Signed-off-by: Eric DeVolder 
---
  hw/acpi/erst.c | 188 +
  1 file changed, 188 insertions(+)

diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index bb6cad4..05177b3 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -59,6 +59,27 @@
  #define STATUS_RECORD_STORE_EMPTY 0x04
  #define STATUS_RECORD_NOT_FOUND   0x05

+/* ACPI 4.0: Table 17-19 Serialization Instructions */
+#define INST_READ_REGISTER 0x00
+#define INST_READ_REGISTER_VALUE   0x01
+#define INST_WRITE_REGISTER0x02
+#define INST_WRITE_REGISTER_VALUE  0x03
+#define INST_NOOP  0x04
+#define INST_LOAD_VAR1 0x05
+#define INST_LOAD_VAR2 0x06
+#define INST_STORE_VAR10x07
+#define INST_ADD   0x08
+#define INST_SUBTRACT  0x09
+#define INST_ADD_VALUE 0x0A
+#define INST_SUBTRACT_VALUE0x0B
+#define INST_STALL 0x0C
+#define INST_STALL_WHILE_TRUE  0x0D
+#define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
+#define INST_GOTO  0x0F
+#define INST_SET_SRC_ADDRESS_BASE  0x10
+#define INST_SET_DST_ADDRESS_BASE  0x11
+#define INST_MOVE_DATA 0x12
+
  /* UEFI 2.1: Appendix N Common Platform Error Record */
  #define UEFI_CPER_RECORD_MIN_SIZE 128U
  #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
@@ -172,6 +193,173 @@ typedef struct {

  /***/
  /***/
+
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+uint8_t serialization_action,
+uint8_t instruction,
+uint8_t flags,
+uint8_t register_bit_width,
+uint64_t register_address,
+uint64_t value)
+{
+/* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+struct AcpiGenericAddress gas;
+uint64_t mask;
+
+/* Serialization Action */
+build_append_int_noprefix(table_data, serialization_action, 1);
+/* Instruction */
+build_append_int_noprefix(table_data, instruction , 1);
+/* Flags */
+build_append_int_noprefix(table_data, flags   , 1);
+/* Reserved */
+build_append_int_noprefix(table_data, 0   , 1);
+/* Register Region */
+gas.space_id = AML_SYSTEM_MEMORY;
+gas.bit_width = register_bit_width;
+gas.bit_offset = 0;
+gas.access_width = ctz32(register_bit_width) - 2;
+gas.address = register_address;
+build_append_gas_from_struct(table_data, );
+/* Value */
+build_append_int_noprefix(table_data, value  , 8);
+/* Mask */
+mask = (1ULL << (register_bit_width - 1) << 1) - 1;
+build_append_int_noprefix(table_data, mask  , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+const char *oem_id, const char *oem_table_id)
+{
+GArray *table_instruction_data;
+unsigned action;


This variable can be eliminated (see below).


+pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
+.oem_table_id = oem_table_id };
+
+trace_acpi_erst_pci_bar_0(bar0);
+
+/*
+ * Serialization Action Table
+ * The serialization action table must be generated first
+ * so that its size can be known in order to populate the
+ * Instruction Entry Count field.
+ */
+table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
+
+/*
+ * Macros for use with construction of the action instructions
+ */
+#define build_read_register(action, width_in_bits, reg) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER, 0, width_in_bits, \
+bar0 + reg, 0)
+
+#define build_read_register_value(action, width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_READ_REGISTER_VALUE, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define build_write_register(action, width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER, 0, width_in_bits, \
+bar0 + reg, value)
+
+#define build_write_register_value(action, width_in_bits, reg, value) \
+build_serialization_instruction_entry(table_instruction_data, \
+action, INST_WRITE_REGISTER_V

[PATCH v11 02/10] ACPI ERST: specification for ERST support

2021-12-15 Thread Eric DeVolder
Information on the implementation of the ACPI ERST support.

Signed-off-by: Eric DeVolder 
Acked-by: Ani Sinha 
---
 docs/specs/acpi_erst.rst | 200 +++
 1 file changed, 200 insertions(+)
 create mode 100644 docs/specs/acpi_erst.rst

diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 000..a8a9d22
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+-
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns.  Pstore is
+independent of, and runs before, kdump.  In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+---
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object 
memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x1,share=on
 \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+   this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+   required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+   parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+   ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+   backend storage. Must be a power of two value greater than or
+   equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers.  All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION.  Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+--
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record.  Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that identifies the contents
+as ERST and also facilitates efficient access to the records.
+Depending upon the size of the backend storage, additional slots will
+be designated

[PATCH v11 09/10] ACPI ERST: bios-tables-test testcase

2021-12-15 Thread Eric DeVolder
This change implements the test suite checks for the ERST table.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 tests/qtest/bios-tables-test.c | 56 ++
 1 file changed, 56 insertions(+)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 2588741..2f073e6 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1446,6 +1446,57 @@ static void test_acpi_piix4_tcg_acpi_hmat(void)
 test_acpi_tcg_acpi_hmat(MACHINE_PC);
 }
 
+static void test_acpi_erst(const char *machine)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+memset(, 0, sizeof(data));
+data.machine = machine;
+data.variant = ".acpierst";
+params = g_strdup_printf(
+" -object memory-backend-file,id=erstnvram,"
+"mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+free_test_data();
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+}
+
+static void test_acpi_piix4_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_PC);
+}
+
+static void test_acpi_q35_acpi_erst(void)
+{
+test_acpi_erst(MACHINE_Q35);
+}
+
+static void test_acpi_microvm_acpi_erst(void)
+{
+gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XX", NULL);
+gchar *params;
+test_data data;
+
+test_acpi_microvm_prepare();
+data.variant = ".pcie";
+data.tcg_only = true; /* need constant host-phys-bits */
+params = g_strdup_printf(" -machine microvm,"
+"acpi=on,ioapic2=off,rtc=off,pcie=on"
+" -object memory-backend-file,id=erstnvram,"
+   "mem-path=%s,size=0x1,share=on"
+" -device acpi-erst,memdev=erstnvram", tmp_path);
+test_acpi_one(params, );
+g_free(params);
+g_assert(g_rmdir(tmp_path) == 0);
+g_free(tmp_path);
+free_test_data();
+}
+
 static void test_acpi_virt_tcg(void)
 {
 test_data data = {
@@ -1624,6 +1675,8 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
 qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
 qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
+qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst);
+qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst);
 qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
 qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg);
 qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg);
@@ -1639,6 +1692,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/kvm/xapic", test_acpi_q35_kvm_xapic);
 qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar);
 }
+if (strcmp(arch, "x86_64") == 0) {
+qtest_add_func("acpi/microvm/acpierst", 
test_acpi_microvm_acpi_erst);
+}
 } else if (strcmp(arch, "aarch64") == 0) {
 if (has_tcg) {
 qtest_add_func("acpi/virt", test_acpi_virt_tcg);
-- 
1.8.3.1




[PATCH v11 03/10] ACPI ERST: PCI device_id for ERST

2021-12-15 Thread Eric DeVolder
This change reserves the PCI device_id for the new ACPI ERST
device.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
Acked-by: Ani Sinha 
---
 include/hw/pci/pci.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index e7cdf2d..d3734b9 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -108,6 +108,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_MDPY0x000f
 #define PCI_DEVICE_ID_REDHAT_NVME0x0010
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
+#define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
1.8.3.1




[PATCH v11 01/10] ACPI ERST: bios-tables-test.c steps 1 and 2

2021-12-15 Thread Eric DeVolder
Following the guidelines in tests/qtest/bios-tables-test.c, this
change adds empty placeholder files per step 1 for the new ERST
table, and excludes resulting changed files in bios-tables-test-allowed-diff.h
per step 2.

Signed-off-by: Eric DeVolder 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/microvm/ERST.pcie   | 0
 tests/data/acpi/pc/DSDT.acpierst| 0
 tests/data/acpi/pc/ERST.acpierst| 0
 tests/data/acpi/q35/DSDT.acpierst   | 0
 tests/data/acpi/q35/ERST.acpierst   | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 5 +
 6 files changed, 5 insertions(+)
 create mode 100644 tests/data/acpi/microvm/ERST.pcie
 create mode 100644 tests/data/acpi/pc/DSDT.acpierst
 create mode 100644 tests/data/acpi/pc/ERST.acpierst
 create mode 100644 tests/data/acpi/q35/DSDT.acpierst
 create mode 100644 tests/data/acpi/q35/ERST.acpierst

diff --git a/tests/data/acpi/microvm/ERST.pcie 
b/tests/data/acpi/microvm/ERST.pcie
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/pc/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/DSDT.acpierst 
b/tests/data/acpi/q35/DSDT.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/data/acpi/q35/ERST.acpierst 
b/tests/data/acpi/q35/ERST.acpierst
new file mode 100644
index 000..e69de29
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523..603db07 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,6 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/pc/DSDT.acpierst",
+"tests/data/acpi/pc/ERST.acpierst",
+"tests/data/acpi/q35/DSDT.acpierst",
+"tests/data/acpi/q35/ERST.acpierst",
+"tests/data/acpi/microvm/ERST.pcie",
-- 
1.8.3.1




[PATCH v11 05/10] ACPI ERST: support for ACPI ERST feature

2021-12-15 Thread Eric DeVolder
This implements a PCI device for ACPI ERST. This implements the
non-NVRAM "mode" of operation for ERST as it is supported by
Linux and Windows.

Signed-off-by: Eric DeVolder 
Reviewed-by: Ani Sinha 
---
 hw/acpi/Kconfig  |   6 +
 hw/acpi/erst.c   | 845 +++
 hw/acpi/meson.build  |   1 +
 hw/acpi/trace-events |  15 +
 4 files changed, 867 insertions(+)
 create mode 100644 hw/acpi/erst.c

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b5..19caebd 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -10,6 +10,7 @@ config ACPI_X86
 select ACPI_HMAT
 select ACPI_PIIX4
 select ACPI_PCIHP
+select ACPI_ERST
 
 config ACPI_X86_ICH
 bool
@@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
 select ACPI
 select ACPI_MEMORY_HOTPLUG
 select ACPI_NVDIMM
+
+config ACPI_ERST
+bool
+default y
+depends on ACPI && PCI
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
new file mode 100644
index 000..bb6cad4
--- /dev/null
+++ b/hw/acpi/erst.c
@@ -0,0 +1,845 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+#include 
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-core.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+#include "hw/pci/pci.h"
+#include "qom/object_interfaces.h"
+#include "qemu/error-report.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/hostmem.h"
+#include "hw/acpi/erst.h"
+#include "trace.h"
+
+/* ACPI 4.0: Table 17-16 Serialization Actions */
+#define ACTION_BEGIN_WRITE_OPERATION 0x0
+#define ACTION_BEGIN_READ_OPERATION  0x1
+#define ACTION_BEGIN_CLEAR_OPERATION 0x2
+#define ACTION_END_OPERATION 0x3
+#define ACTION_SET_RECORD_OFFSET 0x4
+#define ACTION_EXECUTE_OPERATION 0x5
+#define ACTION_CHECK_BUSY_STATUS 0x6
+#define ACTION_GET_COMMAND_STATUS0x7
+#define ACTION_GET_RECORD_IDENTIFIER 0x8
+#define ACTION_SET_RECORD_IDENTIFIER 0x9
+#define ACTION_GET_RECORD_COUNT  0xA
+#define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
+#define ACTION_RESERVED  0xC
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
+#define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
+#define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
+#define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10 /* ACPI 6.3 */
+
+/* ACPI 4.0: Table 17-17 Command Status Definitions */
+#define STATUS_SUCCESS0x00
+#define STATUS_NOT_ENOUGH_SPACE   0x01
+#define STATUS_HARDWARE_NOT_AVAILABLE 0x02
+#define STATUS_FAILED 0x03
+#define STATUS_RECORD_STORE_EMPTY 0x04
+#define STATUS_RECORD_NOT_FOUND   0x05
+
+/* UEFI 2.1: Appendix N Common Platform Error Record */
+#define UEFI_CPER_RECORD_MIN_SIZE 128U
+#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
+#define UEFI_CPER_RECORD_ID_OFFSET 96U
+#define IS_UEFI_CPER_RECORD(ptr) \
+(((ptr)[0] == 'C') && \
+ ((ptr)[1] == 'P') && \
+ ((ptr)[2] == 'E') && \
+ ((ptr)[3] == 'R'))
+
+/*
+ * NOTE that when accessing CPER fields within a record, memcpy()
+ * is utilized to avoid a possible misaligned access on the host.
+ */
+
+/*
+ * This implementation is an ACTION (cmd) and VALUE (data)
+ * interface consisting of just two 64-bit registers.
+ */
+#define ERST_REG_SIZE (16UL)
+#define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
+#define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
+
+/*
+ * ERST_RECORD_SIZE is the buffer size for exchanging ERST
+ * record contents. Thus, it defines the maximum record size.
+ * As this is mapped through a PCI BAR, it must be a power of
+ * two and larger than UEFI_CPER_RECORD_MIN_SIZE.
+ * The backing storage is divided into fixed size "slots",
+ * each ERST_RECORD_SIZE in length, and each "slot"
+ * storing a single record. No attempt at optimizing storage
+ * through compression, compaction, etc is attempted.
+ * NOTE that slot 0 is reserved for the backing storage header.
+ * Depending upon the size of the backing storage, additional
+ * slots will be part of the slot 0 header in order to account
+ * for a record_id for each available remaining slot.
+ */
+/* 8KiB records, not too small, not too big */
+#define ERST_RECORD_SIZE (8192UL)
+
+#define ACPI_ERST_MEMDEV_PROP "

  1   2   3   >