 120f765e03
			
		
	
	
		120f765e03
		
	
	
	
	
		
			
			Signed-off-by: Stefan Weil <sw@weilnetz.de> Reviewed-by: Hongren (Zenithal) Zheng <i@zenithal.me> Message-id: 20220812075642.1200578-1-sw@weilnetz.de Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
		
			
				
	
	
		
			201 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| 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=0x10000,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 to be a part of the slot 0 header. For example, at 8KiB,
 | |
| the slot 0 header can accommodate 1021 records. Thus a storage size
 | |
| of 8MiB (8KiB * 1024) requires an additional slot for use by the
 | |
| header. In this scenario, slot 0 and slot 1 form the backend storage
 | |
| header, and records can be stored starting at slot 2.
 | |
| 
 | |
| Below is an example layout of the backend storage format (for storage
 | |
| size less than 8MiB). The size of the storage is a multiple of 8KiB,
 | |
| and contains N number of slots to store records. The example below
 | |
| shows two records (in CPER format) in the backend storage, while the
 | |
| remaining slots are empty/available.
 | |
| 
 | |
| ::
 | |
| 
 | |
|  Slot   Record
 | |
|         <------------------ 8KiB -------------------->
 | |
|         +--------------------------------------------+
 | |
|     0   | storage header                             |
 | |
|         +--------------------------------------------+
 | |
|     1   | empty/available                            |
 | |
|         +--------------------------------------------+
 | |
|     2   | CPER                                       |
 | |
|         +--------------------------------------------+
 | |
|     3   | CPER                                       |
 | |
|         +--------------------------------------------+
 | |
|   ...   |                                            |
 | |
|         +--------------------------------------------+
 | |
|     N   | empty/available                            |
 | |
|         +--------------------------------------------+
 | |
| 
 | |
| The storage header consists of some basic information and an array
 | |
| of CPER record_id's to efficiently access records in the backend
 | |
| storage.
 | |
| 
 | |
| All fields in the header are stored in little endian format.
 | |
| 
 | |
| ::
 | |
| 
 | |
|   +--------------------------------------------+
 | |
|   | magic                                      | 0x0000
 | |
|   +--------------------------------------------+
 | |
|   | record_offset        | record_size         | 0x0008
 | |
|   +--------------------------------------------+
 | |
|   | record_count         | reserved | version  | 0x0010
 | |
|   +--------------------------------------------+
 | |
|   | record_id[0]                               | 0x0018
 | |
|   +--------------------------------------------+
 | |
|   | record_id[1]                               | 0x0020
 | |
|   +--------------------------------------------+
 | |
|   | record_id[...]                             |
 | |
|   +--------------------------------------------+
 | |
|   | record_id[N]                               | 0x1FF8
 | |
|   +--------------------------------------------+
 | |
| 
 | |
| The 'magic' field contains the value 0x524F545354535245.
 | |
| 
 | |
| The 'record_size' field contains the value 0x2000, 8KiB.
 | |
| 
 | |
| The 'record_offset' field points to the first record_id in the array,
 | |
| 0x0018.
 | |
| 
 | |
| The 'version' field contains 0x0100, the first version.
 | |
| 
 | |
| The 'record_count' field contains the number of valid records in the
 | |
| backend storage.
 | |
| 
 | |
| The 'record_id' array fields are the 64-bit record identifiers of the
 | |
| CPER record in the corresponding slot. Stated differently, the
 | |
| location of a CPER record_id in the record_id[] array provides the
 | |
| slot index for the corresponding record in the backend storage.
 | |
| 
 | |
| Note that, for example, with a backend storage less than 8MiB, slot 0
 | |
| contains the header, so the record_id[0] will never contain a valid
 | |
| CPER record_id. Instead slot 1 is the first available slot and thus
 | |
| record_id_[1] may contain a CPER.
 | |
| 
 | |
| A 'record_id' of all 0s or all 1s indicates an invalid record (ie. the
 | |
| slot is available).
 | |
| 
 | |
| 
 | |
| References
 | |
| ----------
 | |
| 
 | |
| [1] "Advanced Configuration and Power Interface Specification",
 | |
|     version 4.0, June 2009.
 | |
| 
 | |
| [2] "Unified Extensible Firmware Interface Specification",
 | |
|     version 2.1, October 2008.
 | |
| 
 | |
| [3] "Windows Hardware Error Architecture", specifically
 | |
|     "Error Record Persistence Mechanism".
 |