* [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations @ 2023-10-31 23:24 Joe L 2023-11-01 2:09 ` Pedro Falcato 0 siblings, 1 reply; 10+ messages in thread From: Joe L @ 2023-10-31 23:24 UTC (permalink / raw) To: devel [-- Attachment #1: Type: text/plain, Size: 5066 bytes --] Hello, During experimentation on an AARCH64 platform with a PCIe endpoint that supports option ROM, it was found that the ordering of transactions between ECAM (Cfg-Write) and MMIO (Mem-Read) is not preserved by the CHI HN-I node. The observed sequence is as follows: 1. EFI issues a Cfg-Write to endpoint Memory Space Enable bit to enable memory access 2. EFI issues a Mem-Read to the endpoint Option ROM memory space and receives back 0xFFFF (unsupported request) If the memory ordering between the two accesses is explicitly preserved via memory barrier (DMB instruction), 2. will return back valid data instead of UR. Analyzing the transactions with a protocol analyzer, we found that the Mem-Read was being issued before the completion for the Cfg-Write is received. On this system, the HN-I node is configured to separate the ECAM and MMIO into different SAM regions. Both regions are assigned Decice-nGnRnE attributes. According to this snippet from Arm "DEN0114 PCIe AMBA Integration Guide", the ordering of even Device-nGnRnE memory regions cannot be guaranteed if they belong to separate PCIe address spaces > > > > *4.8.2* > > Multiple PCIe address spaces mapped as Device-nGnRnE or Device-nGnRE Arm > memory model does not give any ordering guarantees between accesses to > different Device-nGnRnE or Device-nGnRE peripherals. Additionally, there > is no restriction on mapping various PCIe address spaces of the same PCIe > function as different Device-nGnRnE or Device-nGnRE peripherals. > Consequently, software cannot assume that program order will be maintained > between accesses to two different PCIe address spaces, even though both > spaces are mapped as Device-nGnRnE or Device-nGnRE. Therefore, for maximum > software portability, ordering requirements between accesses to different > PCIe address spaces must be handled explicitly in software using > appropriate ordering instructions." We requested a comment from an Arm representative and received a similar response, confirming that a memory barrier is needed to ensure ordering between accesses to ECAM and MMIO regions (or between any two ranges that are assigned to a separate SAM address region) > > > > When they are to two different order regions, the read will not wait for > the write to complete, and can return data before the write does anything. > The HN-I only preserves ordering between reads and writes to the same > Order Region (which implies the same Address Region). Likewise, the HN-I > will only preserve ordering between multiple reads and between multiple > writes within the same Order Region, and it accomplishes this by issuing > the reads with the same ARID and the writes with the same AWID (i.e. it > relies on the downstream device to follow AXI ordering rules). Issuing a > CHI request with REQ.Order=EndpointOrder only guarantees ordering to the > same “endpoint address range,” which the HN-I defines as an Order Region > (within an Address Region). > > Our CMN TRM showcases an example where ECAM and MMIO are two different > regions in the HN-I SAM. The implication is that we would expect a DSB > between the ECAM write and MMIO read. I'm asking our Open Source Software > group to confirm that standard PCIe software is generally expected to be > aware of the need for a DSB--but my impression from talking to some of our > hardware engineers is that that is indeed the expectation. > > > I am requesting that EDK2 consumes or produces a change to the current PciExpressLib that will ensure ordering on Arm architectures after Cfg-Writes which may or may not have side effects. For example, in MdePkg/Library/BasePciExpressLib/PciExpressLib.c, UINT8 EFIAPI PciExpressWrite8 ( IN UINTN Address, IN UINT8 Value ) { ASSERT_INVALID_PCI_ADDRESS (Address); if (Address >= PcdPciExpressBaseSize ()) { return (UINT8)-1; } return MmioWrite8 ((UINTN)GetPciExpressBaseAddress () + Address, Value); } should become UINT8 EFIAPI PciExpressWrite8 ( IN UINTN Address, IN UINT8 Value ) { ASSERT_INVALID_PCI_ADDRESS (Address); if (Address >= PcdPciExpressBaseSize ()) { return (UINT8)-1; } UINT8 ReturnValue = MmioWrite8 ((UINTN)GetPciExpressBaseAddress () + Address, Value); #if defined (MDE_CPU_AARCH64) MemoryFence (); // DMB sy or DSB #endif return ReturnValue; } Please let me know your thoughts and if this is the correct implementation change needed to enforce memory ordering between separate address regions. I would also like to know the preferred memory barrier instruction in this case (DMB or DSB). Thanks, Joe -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110456): https://edk2.groups.io/g/devel/message/110456 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- [-- Attachment #2: Type: text/html, Size: 6051 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-10-31 23:24 [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations Joe L @ 2023-11-01 2:09 ` Pedro Falcato 2023-11-01 9:56 ` Ard Biesheuvel 0 siblings, 1 reply; 10+ messages in thread From: Pedro Falcato @ 2023-11-01 2:09 UTC (permalink / raw) To: devel, jlotwo; +Cc: Leif Lindholm, Ard Biesheuvel, Sami Mujawar +CC ARM maintainers On Wed, Nov 1, 2023 at 12:40 AM Joe L <jlotwo@gmail.com> wrote: > > Hello, > > During experimentation on an AARCH64 platform with a PCIe endpoint that supports option ROM, it was found that the ordering of transactions between ECAM (Cfg-Write) and MMIO (Mem-Read) is not preserved by the CHI HN-I node. The observed sequence is as follows: > 1. EFI issues a Cfg-Write to endpoint Memory Space Enable bit to enable memory access > 2. EFI issues a Mem-Read to the endpoint Option ROM memory space and receives back 0xFFFF (unsupported request) > If the memory ordering between the two accesses is explicitly preserved via memory barrier (DMB instruction), 2. will return back valid data instead of UR. Analyzing the transactions with a protocol analyzer, we found that the Mem-Read was being issued before the completion for the Cfg-Write is received. > > On this system, the HN-I node is configured to separate the ECAM and MMIO into different SAM regions. Both regions are assigned Decice-nGnRnE attributes. According to this snippet from Arm "DEN0114 PCIe AMBA Integration Guide", the ordering of even Device-nGnRnE memory regions cannot be guaranteed if they belong to separate PCIe address spaces > > 4.8.2 > > Multiple PCIe address spaces mapped as Device-nGnRnE or Device-nGnRE Arm memory model does not give any ordering guarantees between accesses to different Device-nGnRnE or Device-nGnRE peripherals. Additionally, there is no restriction on mapping various PCIe address spaces of the same PCIe function as different Device-nGnRnE or Device-nGnRE peripherals. Consequently, software cannot assume that program order will be maintained between accesses to two different PCIe address spaces, even though both spaces are mapped as Device-nGnRnE or Device-nGnRE. Therefore, for maximum software portability, ordering requirements between accesses to different PCIe address spaces must be handled explicitly in software using appropriate ordering instructions." > > We requested a comment from an Arm representative and received a similar response, confirming that a memory barrier is needed to ensure ordering between accesses to ECAM and MMIO regions (or between any two ranges that are assigned to a separate SAM address region) > > When they are to two different order regions, the read will not wait for the write to complete, and can return data before the write does anything. The HN-I only preserves ordering between reads and writes to the same Order Region (which implies the same Address Region). Likewise, the HN-I will only preserve ordering between multiple reads and between multiple writes within the same Order Region, and it accomplishes this by issuing the reads with the same ARID and the writes with the same AWID (i.e. it relies on the downstream device to follow AXI ordering rules). Issuing a CHI request with REQ.Order=EndpointOrder only guarantees ordering to the same “endpoint address range,” which the HN-I defines as an Order Region (within an Address Region). > > Our CMN TRM showcases an example where ECAM and MMIO are two different regions in the HN-I SAM. The implication is that we would expect a DSB between the ECAM write and MMIO read. I'm asking our Open Source Software group to confirm that standard PCIe software is generally expected to be aware of the need for a DSB--but my impression from talking to some of our hardware engineers is that that is indeed the expectation. > > > I am requesting that EDK2 consumes or produces a change to the current PciExpressLib that will ensure ordering on Arm architectures after Cfg-Writes which may or may not have side effects. For example, in MdePkg/Library/BasePciExpressLib/PciExpressLib.c, > > UINT8 > EFIAPI > PciExpressWrite8 ( > IN UINTN Address, > IN UINT8 Value > ) > { > ASSERT_INVALID_PCI_ADDRESS (Address); > if (Address >= PcdPciExpressBaseSize ()) { > return (UINT8)-1; > } > > return MmioWrite8 ((UINTN)GetPciExpressBaseAddress () + Address, Value); > } > > should become > > > > UINT8 > EFIAPI > PciExpressWrite8 ( > IN UINTN Address, > IN UINT8 Value > ) > { > ASSERT_INVALID_PCI_ADDRESS (Address); > if (Address >= PcdPciExpressBaseSize ()) { > return (UINT8)-1; > } > > UINT8 ReturnValue = MmioWrite8 ((UINTN)GetPciExpressBaseAddress () + Address, Value); > #if defined (MDE_CPU_AARCH64) > MemoryFence (); // DMB sy or DSB > #endif > > return ReturnValue; > } > > Please let me know your thoughts and if this is the correct implementation change needed to enforce memory ordering between separate address regions. I would also like to know the preferred memory barrier instruction in this case (DMB or DSB). Hrmmm, I think the current implementation of MmioRead/Write only offers TSO instead of "full serialization". For instance: // // Reads an 8-bit MMIO register. // // Reads the 8-bit MMIO register specified by Address. The 8-bit read value is // returned. This function must guarantee that all MMIO read and write // operations are serialized. // // @param Address The MMIO register to read. // // @return The value read. // ASM_PFX(MmioRead8Internal): AARCH64_BTI(c) ldrb w0, [x0] dmb ld ret // // Writes an 8-bit MMIO register. // // Writes the 8-bit MMIO register specified by Address with the value specified // by Value and returns Value. This function must guarantee that all MMIO read // and write operations are serialized. // // @param Address The MMIO register to write. // @param Value The value to write to the MMIO register. // ASM_PFX(MmioWrite8Internal): AARCH64_BTI(c) dmb st strb w1, [x0] ret So prior reads are ordered against reads/stores (through dmb ld after the load). Prior writes are ordered against writes only (through dmb st before the store). So one can easily devise a problem here where dmb st /* orders against prior writes */ strb w1, [x0] /* write */ [...] ldrb w0, [x0] /* load */ dmb ld /* orders this load against later reads/stores, but not against prior writes (!!) */ where the CPU can (AFAIK) freely reorder the write after the load in the ARM64 case. Do we want dmb st after the store instead? -- Pedro -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110462): https://edk2.groups.io/g/devel/message/110462 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 2:09 ` Pedro Falcato @ 2023-11-01 9:56 ` Ard Biesheuvel 2023-11-01 12:25 ` Michael Brown 0 siblings, 1 reply; 10+ messages in thread From: Ard Biesheuvel @ 2023-11-01 9:56 UTC (permalink / raw) To: devel, pedro.falcato; +Cc: jlotwo, Leif Lindholm, Sami Mujawar, Ray Ni (cc Ray) On Wed, 1 Nov 2023 at 03:09, Pedro Falcato <pedro.falcato@gmail.com> wrote: > > +CC ARM maintainers > > On Wed, Nov 1, 2023 at 12:40 AM Joe L <jlotwo@gmail.com> wrote: > > > > Hello, > > > > During experimentation on an AARCH64 platform with a PCIe endpoint that supports option ROM, it was found that the ordering of transactions between ECAM (Cfg-Write) and MMIO (Mem-Read) is not preserved by the CHI HN-I node. The observed sequence is as follows: > > 1. EFI issues a Cfg-Write to endpoint Memory Space Enable bit to enable memory access > > 2. EFI issues a Mem-Read to the endpoint Option ROM memory space and receives back 0xFFFF (unsupported request) > > If the memory ordering between the two accesses is explicitly preserved via memory barrier (DMB instruction), 2. will return back valid data instead of UR. Analyzing the transactions with a protocol analyzer, we found that the Mem-Read was being issued before the completion for the Cfg-Write is received. > > > > On this system, the HN-I node is configured to separate the ECAM and MMIO into different SAM regions. Both regions are assigned Decice-nGnRnE attributes. According to this snippet from Arm "DEN0114 PCIe AMBA Integration Guide", the ordering of even Device-nGnRnE memory regions cannot be guaranteed if they belong to separate PCIe address spaces > > > > 4.8.2 > > > > Multiple PCIe address spaces mapped as Device-nGnRnE or Device-nGnRE Arm memory model does not give any ordering guarantees between accesses to different Device-nGnRnE or Device-nGnRE peripherals. Additionally, there is no restriction on mapping various PCIe address spaces of the same PCIe function as different Device-nGnRnE or Device-nGnRE peripherals. Consequently, software cannot assume that program order will be maintained between accesses to two different PCIe address spaces, even though both spaces are mapped as Device-nGnRnE or Device-nGnRE. Therefore, for maximum software portability, ordering requirements between accesses to different PCIe address spaces must be handled explicitly in software using appropriate ordering instructions." > > > > We requested a comment from an Arm representative and received a similar response, confirming that a memory barrier is needed to ensure ordering between accesses to ECAM and MMIO regions (or between any two ranges that are assigned to a separate SAM address region) > > > > When they are to two different order regions, the read will not wait for the write to complete, and can return data before the write does anything. The HN-I only preserves ordering between reads and writes to the same Order Region (which implies the same Address Region). Likewise, the HN-I will only preserve ordering between multiple reads and between multiple writes within the same Order Region, and it accomplishes this by issuing the reads with the same ARID and the writes with the same AWID (i.e. it relies on the downstream device to follow AXI ordering rules). Issuing a CHI request with REQ.Order=EndpointOrder only guarantees ordering to the same “endpoint address range,” which the HN-I defines as an Order Region (within an Address Region). > > > > Our CMN TRM showcases an example where ECAM and MMIO are two different regions in the HN-I SAM. The implication is that we would expect a DSB between the ECAM write and MMIO read. I'm asking our Open Source Software group to confirm that standard PCIe software is generally expected to be aware of the need for a DSB--but my impression from talking to some of our hardware engineers is that that is indeed the expectation. > > > > > > I am requesting that EDK2 consumes or produces a change to the current PciExpressLib that will ensure ordering on Arm architectures after Cfg-Writes which may or may not have side effects. For example, in MdePkg/Library/BasePciExpressLib/PciExpressLib.c, > > > > UINT8 > > EFIAPI > > PciExpressWrite8 ( > > IN UINTN Address, > > IN UINT8 Value > > ) > > { > > ASSERT_INVALID_PCI_ADDRESS (Address); > > if (Address >= PcdPciExpressBaseSize ()) { > > return (UINT8)-1; > > } > > > > return MmioWrite8 ((UINTN)GetPciExpressBaseAddress () + Address, Value); > > } > > > > should become > > > > > > > > UINT8 > > EFIAPI > > PciExpressWrite8 ( > > IN UINTN Address, > > IN UINT8 Value > > ) > > { > > ASSERT_INVALID_PCI_ADDRESS (Address); > > if (Address >= PcdPciExpressBaseSize ()) { > > return (UINT8)-1; > > } > > > > UINT8 ReturnValue = MmioWrite8 ((UINTN)GetPciExpressBaseAddress () + Address, Value); > > #if defined (MDE_CPU_AARCH64) > > MemoryFence (); // DMB sy or DSB > > #endif > > > > return ReturnValue; > > } > > > > Please let me know your thoughts and if this is the correct implementation change needed to enforce memory ordering between separate address regions. I would also like to know the preferred memory barrier instruction in this case (DMB or DSB). > > Hrmmm, I think the current implementation of MmioRead/Write only > offers TSO instead of "full serialization". For instance: > > // > // Reads an 8-bit MMIO register. > // > // Reads the 8-bit MMIO register specified by Address. The 8-bit read value is > // returned. This function must guarantee that all MMIO read and write > // operations are serialized. > // > // @param Address The MMIO register to read. > // > // @return The value read. > // > ASM_PFX(MmioRead8Internal): > AARCH64_BTI(c) > ldrb w0, [x0] > dmb ld > ret > > // > // Writes an 8-bit MMIO register. > // > // Writes the 8-bit MMIO register specified by Address with the value specified > // by Value and returns Value. This function must guarantee that all MMIO read > // and write operations are serialized. > // > // @param Address The MMIO register to write. > // @param Value The value to write to the MMIO register. > // > ASM_PFX(MmioWrite8Internal): > AARCH64_BTI(c) > dmb st > strb w1, [x0] > ret > > > So prior reads are ordered against reads/stores (through dmb ld after > the load). Prior writes are ordered against writes only (through dmb > st before the store). So one can easily devise a problem here where > > dmb st /* orders against prior writes */ > strb w1, [x0] /* write */ > [...] > > ldrb w0, [x0] /* load */ > dmb ld /* orders this load against later reads/stores, but not > against prior writes (!!) */ > > where the CPU can (AFAIK) freely reorder the write after the load in > the ARM64 case. > Not if the memory type is device/strongly ordered, which is the assumption for regions these accessors operate on. And even with cached normal memory, only /other/ observers might see these take effect in a different order. The barriers here are supposed to manage concurrent accesses, which are mostly from coherent masters other than secondary CPUs in the context that EDK2 typically operates in. For instance, the DMB ST in MmioWrite8Internal() is supposed to ensure that any prior writes to a DMA buffer are not reordered with the MMIO write that kicks of the DMA transaction. > Do we want dmb st after the store instead? > I think we should separate the two cases here: 1) as per the architecture (as interpreted by the ARM architects), a DSB is required to ensure that the side effects of enabling a MMIO BAR in the PCI config space are sufficiently observable to memory accesses to that BAR that appear after the PCI config space access in the program. 2) the MMIO accessors are completely undocumented, and it would make sense to put some of the (alleged) rationale in the source code for posterity. As for 1), I don't think dropping a MemoryFence() (which issues a DBM not a DSB on arm64) in a shared source file somewhere is the right approach here. I'd much prefer handling this in RootBridgeIoPciAccess(), and using/introducing a generic helper other than MemoryFence() to convey the existence of a potential side effect that may turn entire regions of memory on or off (including ones that the program/compiler may consider 'ordinary' memory) On ARM/AARCH64, we already have DataSynchronizationBarrier () for this purpose. Alternatively, we might introduce a PciExpressLib instance in ArmPkg that uses this. -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110473): https://edk2.groups.io/g/devel/message/110473 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 9:56 ` Ard Biesheuvel @ 2023-11-01 12:25 ` Michael Brown 2023-11-01 12:51 ` Ard Biesheuvel 0 siblings, 1 reply; 10+ messages in thread From: Michael Brown @ 2023-11-01 12:25 UTC (permalink / raw) To: devel, ardb, pedro.falcato; +Cc: jlotwo, Leif Lindholm, Sami Mujawar, Ray Ni On 01/11/2023 09:56, Ard Biesheuvel wrote: > On Wed, 1 Nov 2023 at 03:09, Pedro Falcato <pedro.falcato@gmail.com> wrote: >> On Wed, Nov 1, 2023 at 12:40 AM Joe L <jlotwo@gmail.com> wrote: >>> Our CMN TRM showcases an example where ECAM and MMIO are two different regions in the HN-I SAM. The implication is that we would expect a DSB between the ECAM write and MMIO read. I'm asking our Open Source Software group to confirm that standard PCIe software is generally expected to be aware of the need for a DSB--but my impression from talking to some of our hardware engineers is that that is indeed the expectation. > > <snip> > > 1) as per the architecture (as interpreted by the ARM architects), a > DSB is required to ensure that the side effects of enabling a MMIO BAR > in the PCI config space are sufficiently observable to memory accesses > to that BAR that appear after the PCI config space access in the > program. It's possibly worth mentioning what the PCIe specification requires in terms of ECAM ordering: "As an example, software may wish to configure a device Function’s Base Address register by writing to the device using the ECAM, and then read a location in the memory-mapped range described by this Base Address register. If the software were to issue the memory-mapped read before the ECAM write was completed, it would be possible for the memory-mapped read to be re-ordered and arrive at the device before the Configuration Write Request, thus causing unpredictable results. To avoid this problem, processor and host bridge implementations must ensure that a method exists for the software to determine when the write using the ECAM is completed by the completer." By my reading, the PCIe specification seems to therefore require something stronger than an ordering guarantee: it requires the ability for software to make a standalone determination that the write has *completed*, independent of the existence of any subsequent I/O operations. As a practical example of when this might be relevant: software could be writing to device configuration space to disable bus mastering as part of a reset or shutdown sequence, in order to guarantee that the device will initiate no further DMA operations and that any DMA buffers allocated to the device can be freed and reused. In this situation, there may be no subsequent MMIO read or write to the device, and so there is no way to rely upon an ordering guarantee to satisfy the requirement. Any solution involving ordering guarantees can therefore mask the problem in some situations, but cannot solve it. The PCIe specification does not mandate that any particular mechanism be used, but it does require that the processor and/or host bridge provides *some* mechanism for software to determine that the ECAM write has completed. What mechanism does ARM (or the host bridge) provide to determine completion of an ECAM write? Thanks, Michael -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110477): https://edk2.groups.io/g/devel/message/110477 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 12:25 ` Michael Brown @ 2023-11-01 12:51 ` Ard Biesheuvel 2023-11-01 13:23 ` Michael Brown 0 siblings, 1 reply; 10+ messages in thread From: Ard Biesheuvel @ 2023-11-01 12:51 UTC (permalink / raw) To: Michael Brown Cc: devel, pedro.falcato, jlotwo, Leif Lindholm, Sami Mujawar, Ray Ni On Wed, 1 Nov 2023 at 13:25, Michael Brown <mcb30@ipxe.org> wrote: > > On 01/11/2023 09:56, Ard Biesheuvel wrote: > > On Wed, 1 Nov 2023 at 03:09, Pedro Falcato <pedro.falcato@gmail.com> wrote: > >> On Wed, Nov 1, 2023 at 12:40 AM Joe L <jlotwo@gmail.com> wrote: > >>> Our CMN TRM showcases an example where ECAM and MMIO are two different regions in the HN-I SAM. The implication is that we would expect a DSB between the ECAM write and MMIO read. I'm asking our Open Source Software group to confirm that standard PCIe software is generally expected to be aware of the need for a DSB--but my impression from talking to some of our hardware engineers is that that is indeed the expectation. > > > > <snip> > > > > 1) as per the architecture (as interpreted by the ARM architects), a > > DSB is required to ensure that the side effects of enabling a MMIO BAR > > in the PCI config space are sufficiently observable to memory accesses > > to that BAR that appear after the PCI config space access in the > > program. > > It's possibly worth mentioning what the PCIe specification requires in > terms of ECAM ordering: > > "As an example, software may wish to configure a device Function’s > Base Address register by writing to the device using the ECAM, > and then read a location in the memory-mapped range described by > this Base Address register. If the software were to issue the > memory-mapped read before the ECAM write was completed, it would > be possible for the memory-mapped read to be re-ordered and arrive > at the device before the Configuration Write Request, thus causing > unpredictable results. > > To avoid this problem, processor and host bridge implementations must > ensure that a method exists for the software to determine when the > write using the ECAM is completed by the completer." > > By my reading, the PCIe specification seems to therefore require > something stronger than an ordering guarantee: it requires the ability > for software to make a standalone determination that the write has > *completed*, independent of the existence of any subsequent I/O operations. > indeed, thanks for bringing this up. > As a practical example of when this might be relevant: software could be > writing to device configuration space to disable bus mastering as part > of a reset or shutdown sequence, in order to guarantee that the device > will initiate no further DMA operations and that any DMA buffers > allocated to the device can be freed and reused. In this situation, > there may be no subsequent MMIO read or write to the device, and so > there is no way to rely upon an ordering guarantee to satisfy the > requirement. > > Any solution involving ordering guarantees can therefore mask the > problem in some situations, but cannot solve it. > > The PCIe specification does not mandate that any particular mechanism be > used, but it does require that the processor and/or host bridge provides > *some* mechanism for software to determine that the ECAM write has > completed. > > What mechanism does ARM (or the host bridge) provide to determine > completion of an ECAM write? > A MMIO read of the same location should ensure that the MMIO write has completed by the time the read returns. Not sure whether or not there are any other requirements (e.g., wrt.the size of the read vs the size of the write). -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110478): https://edk2.groups.io/g/devel/message/110478 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 12:51 ` Ard Biesheuvel @ 2023-11-01 13:23 ` Michael Brown 2023-11-01 16:41 ` Ard Biesheuvel 0 siblings, 1 reply; 10+ messages in thread From: Michael Brown @ 2023-11-01 13:23 UTC (permalink / raw) To: devel, ardb; +Cc: pedro.falcato, jlotwo, Leif Lindholm, Sami Mujawar, Ray Ni On 01/11/2023 12:51, Ard Biesheuvel wrote: > On Wed, 1 Nov 2023 at 13:25, Michael Brown <mcb30@ipxe.org> wrote: >> By my reading, the PCIe specification seems to therefore require >> something stronger than an ordering guarantee: it requires the ability >> for software to make a standalone determination that the write has >> *completed*, independent of the existence of any subsequent I/O operations. > > indeed, thanks for bringing this up. > >> The PCIe specification does not mandate that any particular mechanism be >> used, but it does require that the processor and/or host bridge provides >> *some* mechanism for software to determine that the ECAM write has >> completed. >> >> What mechanism does ARM (or the host bridge) provide to determine >> completion of an ECAM write? > > A MMIO read of the same location should ensure that the MMIO write has > completed by the time the read returns. Not sure whether or not there > are any other requirements (e.g., wrt.the size of the read vs the size > of the write). That seems to suggest that a logical PCIe configuration space write operation using ECAM should probably always comprise: 1. ECAM write 2. ECAM read from the same location (using the same size) If reads are not allowed to have side effects (e.g. read-clear registers) then this seems safe. The PCIe specification "Configuration Register Types" list comprises (in version 3.0, at least): HwInit - read-only, no read side effects RO - read-only, no read side effects RW - read-write, no read side effects RW1C - write 1 to clear bits, no read side effects ROS - read-only, no read side effects RWS - read-write, no read side effects RW1CS - write 1 to clear bits, no read side effects RsvdP - read-write, no read side effects RsvdZ - read-write, no read side effects So, unless newer versions of the PCIe specification have allowed for the existence of configuration register types with read side effects, then the approach of always reading back from ECAM seems to be safe for any conforming PCIe device. I would therefore suggest that all ECAM driver implementation functions in EDK2 (e.g. PciExpressWrite32(), PciExpressOr32(), PciSegmentWrite32(), etc) be updated to add the relevant ECAM read following the write operation. PCI configuration space writes are never fast-path operations (in any sane hardware), and so the delay introduced by the read should not be significant. Does this seem like a sensible solution? Thanks, Michael -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110480): https://edk2.groups.io/g/devel/message/110480 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 13:23 ` Michael Brown @ 2023-11-01 16:41 ` Ard Biesheuvel 2023-11-01 20:17 ` Joe L 0 siblings, 1 reply; 10+ messages in thread From: Ard Biesheuvel @ 2023-11-01 16:41 UTC (permalink / raw) To: Michael Brown Cc: devel, pedro.falcato, jlotwo, Leif Lindholm, Sami Mujawar, Ray Ni On Wed, 1 Nov 2023 at 14:24, Michael Brown <mcb30@ipxe.org> wrote: > > On 01/11/2023 12:51, Ard Biesheuvel wrote: > > On Wed, 1 Nov 2023 at 13:25, Michael Brown <mcb30@ipxe.org> wrote: > >> By my reading, the PCIe specification seems to therefore require > >> something stronger than an ordering guarantee: it requires the ability > >> for software to make a standalone determination that the write has > >> *completed*, independent of the existence of any subsequent I/O operations. > > > > indeed, thanks for bringing this up. > > > >> The PCIe specification does not mandate that any particular mechanism be > >> used, but it does require that the processor and/or host bridge provides > >> *some* mechanism for software to determine that the ECAM write has > >> completed. > >> > >> What mechanism does ARM (or the host bridge) provide to determine > >> completion of an ECAM write? > > > > A MMIO read of the same location should ensure that the MMIO write has > > completed by the time the read returns. Not sure whether or not there > > are any other requirements (e.g., wrt.the size of the read vs the size > > of the write). > > That seems to suggest that a logical PCIe configuration space write > operation using ECAM should probably always comprise: > > 1. ECAM write > 2. ECAM read from the same location (using the same size) > > If reads are not allowed to have side effects (e.g. read-clear > registers) then this seems safe. The PCIe specification "Configuration > Register Types" list comprises (in version 3.0, at least): > > HwInit - read-only, no read side effects > > RO - read-only, no read side effects > > RW - read-write, no read side effects > > RW1C - write 1 to clear bits, no read side effects > > ROS - read-only, no read side effects > > RWS - read-write, no read side effects > > RW1CS - write 1 to clear bits, no read side effects > > RsvdP - read-write, no read side effects > > RsvdZ - read-write, no read side effects > > So, unless newer versions of the PCIe specification have allowed for the > existence of configuration register types with read side effects, then > the approach of always reading back from ECAM seems to be safe for any > conforming PCIe device. > > I would therefore suggest that all ECAM driver implementation functions > in EDK2 (e.g. PciExpressWrite32(), PciExpressOr32(), > PciSegmentWrite32(), etc) be updated to add the relevant ECAM read > following the write operation. > > PCI configuration space writes are never fast-path operations (in any > sane hardware), and so the delay introduced by the read should not be > significant. > > Does this seem like a sensible solution? > I think that would be reasonable, but it needs to be implemented at the correct level of abstraction. We have some plumbing to iterate over ranges to do what basically comes down to memcpy and memset on MMIO ranges, and I don't think we want the readback on every store in a sequence of multiple. RootBridgeIoPciAccess() looks like a reasonable location to insert a readback of the last access if it was a write. -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110486): https://edk2.groups.io/g/devel/message/110486 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 16:41 ` Ard Biesheuvel @ 2023-11-01 20:17 ` Joe L 2023-11-01 21:51 ` Michael Brown 0 siblings, 1 reply; 10+ messages in thread From: Joe L @ 2023-11-01 20:17 UTC (permalink / raw) To: Ard Biesheuvel, devel [-- Attachment #1: Type: text/plain, Size: 1222 bytes --] Thanks for the discussion, Are we saying that DataSynchronizationBarrier () before the return from RootBridgeIoPciAccess() is not strong enough to determine that the final ECAM write would have completed? According to Learn the architecture - ARMv8-A memory systems ( https://developer.arm.com/documentation/100941/0101/Barriers ) the DSB should block "execution of any further instructions, not just loads or stores, until synchronization is complete". To me this means that for Arm the DSB will stall any subsequent instructions until the completion for the ECAM write is received by the processor. Though if an architecture-agnostic solution is desired the readback before returning from RootBridgeIoPciAccess() does make sense. If the access spanned multiple DWORDs then should a read from the final aligned DWORD in the "buffer" be sufficient? -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110489): https://edk2.groups.io/g/devel/message/110489 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- [-- Attachment #2: Type: text/html, Size: 1851 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 20:17 ` Joe L @ 2023-11-01 21:51 ` Michael Brown 2023-11-01 23:07 ` Pedro Falcato 0 siblings, 1 reply; 10+ messages in thread From: Michael Brown @ 2023-11-01 21:51 UTC (permalink / raw) To: devel, jlotwo, Ard Biesheuvel On 01/11/2023 20:17, Joe L wrote: > Thanks for the discussion, > > Are we saying that DataSynchronizationBarrier () before the return > from RootBridgeIoPciAccess() is not strong enough to determine that > the final ECAM write would have completed? According to Learn the > architecture - ARMv8-A memory systems > <https://developer.arm.com/documentation/100941/0101/Barriers> the > DSB should block "execution of any further instructions, not just > loads or stores, until synchronization is complete". To me this means > that for Arm the DSB will stall any subsequent instructions until the > completion for the ECAM write is received by the processor. I honestly can't tell from the wording there whether or not DSB would guarantee that the configuration space write has completed all the way to the target PCIe device (as opposed to e.g. completing as far as the host bridge, or to an intermediate PCIe bridge). I don't know the answer, and it feels like the kind of messy area where adding a barrier will definitely reduce the probability of the issue occurring but might not guarantee a fix, which is a bad situation to be left in. > Though if an architecture-agnostic solution is desired the readback > before returning from RootBridgeIoPciAccess() does make sense. Personally I like having an architecture-agnostic solution, and I'll be updating the ECAM driver in iPXE to use the readback approach. > If the access spanned multiple DWORDs then should a read from the > final aligned DWORD in the "buffer" be sufficient? Quite possibly. Given that PCIe configuration space accesses are never performance-critical, I'm not sure it's worth the optimisation, but I'll defer to the people who actually have to implement it in EDK2. Thanks, Michael -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110493): https://edk2.groups.io/g/devel/message/110493 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations 2023-11-01 21:51 ` Michael Brown @ 2023-11-01 23:07 ` Pedro Falcato 0 siblings, 0 replies; 10+ messages in thread From: Pedro Falcato @ 2023-11-01 23:07 UTC (permalink / raw) To: devel, mcb30; +Cc: jlotwo, Ard Biesheuvel On Wed, Nov 1, 2023 at 9:51 PM Michael Brown <mcb30@ipxe.org> wrote: > > On 01/11/2023 20:17, Joe L wrote: > > Thanks for the discussion, > > > > Are we saying that DataSynchronizationBarrier () before the return > > from RootBridgeIoPciAccess() is not strong enough to determine that > > the final ECAM write would have completed? According to Learn the > > architecture - ARMv8-A memory systems > > <https://developer.arm.com/documentation/100941/0101/Barriers> the > > DSB should block "execution of any further instructions, not just > > loads or stores, until synchronization is complete". To me this means > > that for Arm the DSB will stall any subsequent instructions until the > > completion for the ECAM write is received by the processor. > > I honestly can't tell from the wording there whether or not DSB would > guarantee that the configuration space write has completed all the way > to the target PCIe device (as opposed to e.g. completing as far as the > host bridge, or to an intermediate PCIe bridge). > > I don't know the answer, and it feels like the kind of messy area where > adding a barrier will definitely reduce the probability of the issue > occurring but might not guarantee a fix, which is a bad situation to be > left in. Given we are working with Device nGnRnE memory, and the documentation says stuff like " This determines whether an intermediate write buffer between the processor and the slave device being accessed is allowed to send an acknowledgement of a write completion. If the address is marked as non Early Write Acknowledgement (nE), then the write response must come from the peripheral. If the address is marked as Early Write Acknowledgement (E), then it is permissible for a buffer in the interconnect logic to signal write acceptance, in advance of the write actually being received by the end device. This is essentially a message to the external memory system." I would expect the write ACK to come from the device itself (I can't wait for the obscure ARM doc that proves me wrong!) -- Pedro -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110494): https://edk2.groups.io/g/devel/message/110494 Mute This Topic: https://groups.io/mt/102310377/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-11-01 23:08 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-10-31 23:24 [edk2-devel] [RFC] Ordering of Arm PCI ECAM and MMIO operations Joe L 2023-11-01 2:09 ` Pedro Falcato 2023-11-01 9:56 ` Ard Biesheuvel 2023-11-01 12:25 ` Michael Brown 2023-11-01 12:51 ` Ard Biesheuvel 2023-11-01 13:23 ` Michael Brown 2023-11-01 16:41 ` Ard Biesheuvel 2023-11-01 20:17 ` Joe L 2023-11-01 21:51 ` Michael Brown 2023-11-01 23:07 ` Pedro Falcato
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox