Fix port IO in fw_cfg device for x86 - #190
Open
scholzp wants to merge 8 commits into
Open
Conversation
The DMA interface in `fw_cfg` in the CHV implementation is broken and needs some overhaul. We deactivate it to force a guest to use the traditional interface instead and ignore the DMA interface.[0] We make DMA transfers no-ops for now and alter the test to verify this instead until we do a rework of the DMA path. [0] https://www.qemu.org/docs/master/specs/fw_cfg.html#guest-side-dma-interface On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
The selector 0x0000 has to contain the bytes "QEMU" in the traditional interface.[0] Using the DMA signature in a way currently done returns the wrong signature if a guest reads more than 4 bytes from the selector 0x0000. [0] https://www.qemu.org/docs/master/specs/fw_cfg.html#signature-key-0x0000-fw-cfg-signature On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
In the traditional/POI interface the DATA register has a width of one byte on x86.[0] We therefore do not allow reads with higher widths. Currently, all tests assume a read with of 1 byte too. We reject `fw_cfg` in aarch64 builds for now as these changes introduce an incompatibility that adds to the incomplete implementation of it. Aarch64 support is a task to be solved in followups, as this also includes making corrections to the MMIO transport implementation and FDT corrections. [0] https://www.qemu.org/docs/master/specs/fw_cfg.html#data-register On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
QEMU checks if the read has an allowed width.[0] If it detects an invalid read, then QEMU will treat the register reads as an read to unassigned memory.[1] As a result, it will return 0x0 for the whole buffer. We mimic this behavior for CHV's `fw_cfg` design for improved compatibility. [0] https://github.com/qemu/qemu/blob/6e9a825c1d4e7b62d072e99a89ecd1a74c7f0d55/hw/nvram/fw_cfg.c#L533 [1] https://github.com/qemu/qemu/blob/6e9a825c1d4e7b62d072e99a89ecd1a74c7f0d55/system/memory.c#L1480 On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
While the documentation states that the SELECTOR register is write-only, QEMU actually allows reading the SELECTOR register. This is because QEMU uses a contiguous mapping for the SELECTOR and DATA registers to allow the 16-bit width of the SELECTOR register.[0] As a consequence a read from SELECTOR is delegated to the same callback as a read from DATA. We mimic this for maximal compatibility. [0] https://github.com/qemu/qemu/blob/6e9a825c1d4e7b62d072e99a89ecd1a74c7f0d55/hw/nvram/fw_cfg.c#L539 On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
Currently, the read implementation isn't complete and doesn't handle some error cases gracefully. We rework it with the aim of maximal compatibility to QEMU and add tests for it. Problem of the old implementation include: * Reads beyond EOF should yield 0x0 [0]. These currently panic. * Register reads with invalid SELECTOR should also yield 0x0 [1] * If provided with a buffer larger than an item, then the reamining buffer bytes should be set to zero.[1] [0] https://www.qemu.org/docs/master/specs/fw_cfg.html#data-register [1] https://github.com/qemu/qemu/blob/6e9a825c1d4e7b62d072e99a89ecd1a74c7f0d55/hw/nvram/fw_cfg.c#L382 On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
This is a fix to allow string reads that map to `rep ins`. KVM returns an IO exit with the respective port, the width of `x` bytes and the number of `n` bytes in `count`. `kvm_ioctls` creates a buffer from this with the size of `x * n` bytes.[0] This makes it impossible to decide if the buffer was a single n-byte-width read of the kind `insd` or `rep ins` with EDX set to 4, for example. While the first would be invalid according to QEMU semantics, the second is a valid repeated access with one byte width. We therefore accept reads of any size until we can solve this issue. [0] https://github.com/rust-vmm/kvm/blob/b4c9ed8df95a9e10a68f50f5ef5e7d04108759ba/kvm-ioctls/src/ioctls/vcpu.rs#L1549 Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de> On-behalf-of: SAP pascal.scholz@sap.com
scholzp
force-pushed
the
fw_cfg_fix_pio
branch
2 times, most recently
from
August 5, 2026 13:39
f2df444 to
2a7766b
Compare
I'm unsure what that means, could you elaborate on what the current state of upstream is and how we get to using upstream? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is the starting ground for the
fw_cfgrework in CHV by reworking the port IO transportation path. The current implementation has many issues such as panicking when reading beyond item lengths. Moreover, the current implementation doesn't follow QEMU semantics, which is addressed in this PR. The next followup will introduce compatibility for well-known legacy items. After that, we can safely merge thebootorderfeature, as thefw_cfgdevice will than semantically act similar to the QEMU implementation from the guest's perspective.The DMA path is broken. Therefore it is deactivated in this patch series. For our fork we decided to use the Port IO interface only. This doesn't has any implication to the
bootorderfeature.We reject building for aarch64, because the MMIO mapped register based transportation layer for aarch64 is broken and doesn't follow QEMU semantics either. This, similar to other cleanup, is left for followups. The entire rework of
fw_cfgwill target upstream and we can sooner or later replace this version with the upstream one.This is also includes the fix for the DATA register read handling, which accepts arbitrary length at the moment. This needs to be fixed in
kvm_ioctlscrate and then globally in CHV.I tested locally that the
bootorderfeature still works. This commit series contains a commit that activates thefw_cfgfeature. I'll remove it once the pipeline finished. It's only purpose is to run the pipeline withfw_cfgactivated. Find a pipeline here: https://gitlab.cyberus-technology.de/cyberus/cloud/libvirt/-/merge_requests/268