Message ID | 1372183863-11333-2-git-send-email-leif.lindholm@linaro.org |
---|---|
State | New |
Headers | show |
On 06/25/2013 02:11 PM, Leif Lindholm wrote: > This patch provides documentation of the [U]EFI runtime services and > configuration features. > > Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> > --- > Documentation/arm/00-INDEX | 3 +++ > Documentation/arm/uefi.txt | 39 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 42 insertions(+) > create mode 100644 Documentation/arm/uefi.txt > > diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX > index 4978456..87e01d1 100644 > --- a/Documentation/arm/00-INDEX > +++ b/Documentation/arm/00-INDEX > @@ -36,3 +36,6 @@ nwfpe/ > - NWFPE floating point emulator documentation > swp_emulation > - SWP/SWPB emulation handler/logging description > + > +uefi.txt > + - [U]EFI configuration and runtime services documentation > diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt > new file mode 100644 > index 0000000..5c48271 > --- /dev/null > +++ b/Documentation/arm/uefi.txt > @@ -0,0 +1,39 @@ > +The nomenclature EFI and UEFI are used interchangeably in this document. > + > +The implementation depends on receiving pointers to the UEFI memory map > +and System Table in a Flattened Device Tree - so is only available with > +CONFIG_OF. > + > +It (early) parses the FDT for the following parameters: > +- 'efi-system-table': > + Physical address of the system table. (required) > +- 'efi-runtime-mmap': > + Physical address of an EFI memory map, containing at least > + the regions to be preserved. (required) > +- 'efi-runtime-mmap-size': > + Size in bytes of the provided memory map. (required) > +- 'efi-mmap-desc-size': > + Size of each descriptor in the memory map. (override default) > +- 'efi-mmap-desc-ver': > + Memory descriptor format version. (override default) > + > +Since UEFI firmware on ARM systems are required to use a 1:1 memory map > +even on LPAE-capable systems, the above fields are 32-bit regardless. > + > +It also depends on early_ioremap to parse the memory map and preserve > +the regions required for runtime services. > + > +For actually enabling [U]EFI support, enable: > +- CONFIG_EFI=y > +- CONFIG_EFI_VARS=y or m > + > +After the kernel has mapped the required regions into its address space, > +a SetVirtualAddressMap() call is made into UEFI in order to update > +relocations. This call must be performed with all the code in a 1:1 > +mapping. This implementation achieves this by temporarily disabling the > +MMU for the duration of this call. This can only be done safely: > +- before secondary CPUs are brought online. > +- after early_initcalls have completed, sinze it uses setup_mm_for_reboot(). since > + > +For verbose debug messages, specify 'uefi_debug' on the kernel command > +line. > Christopher
On 06/25/2013 12:11 PM, Leif Lindholm wrote: > This patch provides documentation of the [U]EFI runtime services and > configuration features. > diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt > +The implementation depends on receiving pointers to the UEFI memory map > +and System Table in a Flattened Device Tree - so is only available with > +CONFIG_OF. > + > +It (early) parses the FDT for the following parameters: Part of this document (the raw requirements for DT content, rather than the discussion of OS implementation/behaviour in parsing/interpreting the properties) should be part of a file in Documentation/devicetree/bindings/ (arm/uefi.txt?). What node are these properties expected to be contained within? Shouldn't that node be required to contain a compatible value, which would define the schema for the other properties? > +- 'efi-system-table': > + Physical address of the system table. (required) > +- 'efi-runtime-mmap': > + Physical address of an EFI memory map, containing at least > + the regions to be preserved. (required) > +- 'efi-runtime-mmap-size': > + Size in bytes of the provided memory map. (required) > +- 'efi-mmap-desc-size': > + Size of each descriptor in the memory map. (override default) > +- 'efi-mmap-desc-ver': > + Memory descriptor format version. (override default) > + > +Since UEFI firmware on ARM systems are required to use a 1:1 memory map > +even on LPAE-capable systems, the above fields are 32-bit regardless. What about ARMv8? Is the intention to have a separate definition for the UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a future version of UEFI allows LPAE usage? It may be better to explicitly state that the size of those properties is either #address-cells from the parent node (presumably the top-level of the DT), and/or introduce some property to explicitly state the size of the properties. Those mechanisms would allow forward-compatibility to LPAE usage or ARMv8 without requiring the text of the binding definition to change. Also, it seems legal to state the physical addresses using 64-bits even if the actual values themselves are restricted to 32-bit range by the UEFI spec. Illegal values would presumably cause SW that interprets them to fail error-checks, and be rejected. > +After the kernel has mapped the required regions into its address space, > +a SetVirtualAddressMap() call is made into UEFI in order to update > +relocations. This call must be performed with all the code in a 1:1 Presumably "all the code" also includes "all .data and .bss", or whatever the UEFI-equivalent may be? I'm not familiar with UEFI at all; does the "EFI memory map" mentioned above describe all the memory regions that must be mapped to use UEFI? > +mapping. This implementation achieves this by temporarily disabling the > +MMU for the duration of this call. This can only be done safely: > +- before secondary CPUs are brought online. > +- after early_initcalls have completed, sinze it uses setup_mm_for_reboot().
On Tue, Jun 25, 2013 at 7:11 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote: > This patch provides documentation of the [U]EFI runtime services and > configuration features. > > Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> > --- > Documentation/arm/00-INDEX | 3 +++ > Documentation/arm/uefi.txt | 39 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 42 insertions(+) > create mode 100644 Documentation/arm/uefi.txt > > diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX > index 4978456..87e01d1 100644 > --- a/Documentation/arm/00-INDEX > +++ b/Documentation/arm/00-INDEX > @@ -36,3 +36,6 @@ nwfpe/ > - NWFPE floating point emulator documentation > swp_emulation > - SWP/SWPB emulation handler/logging description > + > +uefi.txt > + - [U]EFI configuration and runtime services documentation > diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt > new file mode 100644 > index 0000000..5c48271 > --- /dev/null > +++ b/Documentation/arm/uefi.txt > @@ -0,0 +1,39 @@ > +The nomenclature EFI and UEFI are used interchangeably in this document. > + > +The implementation depends on receiving pointers to the UEFI memory map > +and System Table in a Flattened Device Tree - so is only available with > +CONFIG_OF. > + > +It (early) parses the FDT for the following parameters: Need to state which node these properties can be found in. I recommend /chosen I would also prefix all of the following properties with "linux," since they are very much about what the Linux kernel needs for booting. EFI stub will be creating these properties specifically for Linux, and the LinuxLoader should do the same (until we eventually kill it). > +- 'efi-system-table': > + Physical address of the system table. (required) Need to mention the size of this address. Is it 64 bit or 32 bit? I would follow the lead of 'linux,initrd-start' here and make the size of property the size of the address. ie. If it is 8 bytes long, then it is a 64 bit address. > +- 'efi-runtime-mmap': > + Physical address of an EFI memory map, containing at least > + the regions to be preserved. (required) > +- 'efi-runtime-mmap-size': > + Size in bytes of the provided memory map. (required) I would collapse the above two properties into a single property that actually contains the memory map instead of pointing to it. You will also need to specify the exact format of the data in this property. > +- 'efi-mmap-desc-size': > + Size of each descriptor in the memory map. (override default) > +- 'efi-mmap-desc-ver': > + Memory descriptor format version. (override default) I don't understand how these properties will actually work. What changes in the parsing if these properties are set? > + > +Since UEFI firmware on ARM systems are required to use a 1:1 memory map > +even on LPAE-capable systems, the above fields are 32-bit regardless. > + > +It also depends on early_ioremap to parse the memory map and preserve > +the regions required for runtime services. > + > +For actually enabling [U]EFI support, enable: > +- CONFIG_EFI=y > +- CONFIG_EFI_VARS=y or m > + > +After the kernel has mapped the required regions into its address space, > +a SetVirtualAddressMap() call is made into UEFI in order to update > +relocations. This call must be performed with all the code in a 1:1 > +mapping. This implementation achieves this by temporarily disabling the > +MMU for the duration of this call. This can only be done safely: > +- before secondary CPUs are brought online. > +- after early_initcalls have completed, sinze it uses setup_mm_for_reboot(). > + > +For verbose debug messages, specify 'uefi_debug' on the kernel command > +line. Looks good otherwise, Thanks! g.
On Wed, Jun 26, 2013 at 12:42 AM, Stephen Warren <swarren@wwwdotorg.org> wrote: > On 06/25/2013 12:11 PM, Leif Lindholm wrote: >> This patch provides documentation of the [U]EFI runtime services and >> configuration features. > > >> diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt > >> +The implementation depends on receiving pointers to the UEFI memory map >> +and System Table in a Flattened Device Tree - so is only available with >> +CONFIG_OF. >> + >> +It (early) parses the FDT for the following parameters: > > Part of this document (the raw requirements for DT content, rather than > the discussion of OS implementation/behaviour in parsing/interpreting > the properties) should be part of a file in > Documentation/devicetree/bindings/ (arm/uefi.txt?). > > What node are these properties expected to be contained within? > > Shouldn't that node be required to contain a compatible value, which > would define the schema for the other properties? Typically, a compatible property isn't only used for nodes that represent a device or a so-called 'virtual' device (ie. such as to describe how all the sound complex is wired together) since that should be the clue to an OS that a device driver will bind against the node. I think these properties can be dropped into /chosen without defining a new compatible value. >> +- 'efi-system-table': >> + Physical address of the system table. (required) >> +- 'efi-runtime-mmap': >> + Physical address of an EFI memory map, containing at least >> + the regions to be preserved. (required) >> +- 'efi-runtime-mmap-size': >> + Size in bytes of the provided memory map. (required) >> +- 'efi-mmap-desc-size': >> + Size of each descriptor in the memory map. (override default) >> +- 'efi-mmap-desc-ver': >> + Memory descriptor format version. (override default) >> + >> +Since UEFI firmware on ARM systems are required to use a 1:1 memory map >> +even on LPAE-capable systems, the above fields are 32-bit regardless. > > What about ARMv8? Is the intention to have a separate definition for the > UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a > future version of UEFI allows LPAE usage? It is unlikely that will happen on v7 since newer versions of UEFI are expected to remain backwards compatible with the current spec. > It may be better to explicitly state that the size of those properties > is either #address-cells from the parent node (presumably the top-level > of the DT), and/or introduce some property to explicitly state the size > of the properties. Those mechanisms would allow forward-compatibility to > LPAE usage or ARMv8 without requiring the text of the binding definition > to change. > > Also, it seems legal to state the physical addresses using 64-bits even > if the actual values themselves are restricted to 32-bit range by the > UEFI spec. Illegal values would presumably cause SW that interprets them > to fail error-checks, and be rejected. > >> +After the kernel has mapped the required regions into its address space, >> +a SetVirtualAddressMap() call is made into UEFI in order to update >> +relocations. This call must be performed with all the code in a 1:1 > > Presumably "all the code" also includes "all .data and .bss", or > whatever the UEFI-equivalent may be? I'm not familiar with UEFI at all; > does the "EFI memory map" mentioned above describe all the memory > regions that must be mapped to use UEFI? yes. Actually, there is an API for retrieving the memory map from UEFI at runtime, but it is difficult to call from within the kernel. Actually, my preference would be to not require GRUB or the Linux Loader to add the above properties at all and instead have the kernel proper retrieve the memory map directly. That would reduce the dependency on GRUB/LinuxLoader doing things correctly, but Leif knows better how feasible that would be. > >> +mapping. This implementation achieves this by temporarily disabling the >> +MMU for the duration of this call. This can only be done safely: >> +- before secondary CPUs are brought online. >> +- after early_initcalls have completed, sinze it uses setup_mm_for_reboot(). > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/
On Wed, Jun 26, 2013 at 02:20:23PM +0100, Grant Likely wrote: > On Wed, Jun 26, 2013 at 12:42 AM, Stephen Warren <swarren@wwwdotorg.org> wrote: > > the properties) should be part of a file in > > Documentation/devicetree/bindings/ (arm/uefi.txt?). > > > > What node are these properties expected to be contained within? > > > > Shouldn't that node be required to contain a compatible value, which > > would define the schema for the other properties? > > Typically, a compatible property isn't only used for nodes that > represent a device or a so-called 'virtual' device (ie. such as to > describe how all the sound complex is wired together) since that > should be the clue to an OS that a device driver will bind against the > node. I think these properties can be dropped into /chosen without > defining a new compatible value. That would be my preference. But yes, that should be documented, and will be in the next version. > >> +Since UEFI firmware on ARM systems are required to use a 1:1 memory map > >> +even on LPAE-capable systems, the above fields are 32-bit regardless. > > > > What about ARMv8? Is the intention to have a separate definition for the > > UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a > > future version of UEFI allows LPAE usage? > > It is unlikely that will happen on v7 since newer versions of UEFI are > expected to remain backwards compatible with the current spec. I'm going to go out on a limb here and claim that it wouldn't be possible to do that compatibly. The current spec doesn't ban LPAE (or "use of long descriptors"). But it does specify that all RAM known to UEFI must use a 1:1 mapping. > >> +After the kernel has mapped the required regions into its address space, > >> +a SetVirtualAddressMap() call is made into UEFI in order to update > >> +relocations. This call must be performed with all the code in a 1:1 > > > > Presumably "all the code" also includes "all .data and .bss", or > > whatever the UEFI-equivalent may be? I'm not familiar with UEFI at all; > > does the "EFI memory map" mentioned above describe all the memory > > regions that must be mapped to use UEFI? > > yes.Actually, there is an API for retrieving the memory map from UEFI > at runtime, but it is difficult to call from within the kernel. > Actually, my preference would be to not require GRUB or the Linux > Loader to add the above properties at all and instead have the kernel > proper retrieve the memory map directly. That would reduce the > dependency on GRUB/LinuxLoader doing things correctly, but Leif knows > better how feasible that would be. It's completely feasible, but we'd need to use a different method to do the boot services call with a 1:1 mapping (idmap support is not available until much later in the boot process). The System Table pointer still needs to be passed across though. / Leif
On Wed, 26 Jun, at 03:53:11PM, Leif Lindholm wrote: > It's completely feasible, but we'd need to use a different method to do > the boot services call with a 1:1 mapping (idmap support is not available > until much later in the boot process). At least if you no longer relied upon the idmap we could potentially have a single efi_enter_virtual_mode() call-site in init/main.c, which would be nice.
On Wed, Jun 26, 2013 at 02:13:39PM +0100, Grant Likely wrote: > > diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt > > +It (early) parses the FDT for the following parameters: > > Need to state which node these properties can be found in. I recommend /chosen Will do. > I would also prefix all of the following properties with "linux," > since they are very much about what the Linux kernel needs for > booting. EFI stub will be creating these properties specifically for > Linux, and the LinuxLoader should do the same (until we eventually > kill it). And that. > > +- 'efi-system-table': > > + Physical address of the system table. (required) > > Need to mention the size of this address. Is it 64 bit or 32 bit? I > would follow the lead of 'linux,initrd-start' here and make the size > of property the size of the address. ie. If it is 8 bytes long, then > it is a 64 bit address. Currently, it's a 4-byte address. Although technically possible to be >32-bit in an LPAE system, the 1:1 mappign requirement of the UEFI spec forces it to reside in the lower 4GB on a 32-bit system. > > +- 'efi-runtime-mmap': > > + Physical address of an EFI memory map, containing at least > > + the regions to be preserved. (required) > > +- 'efi-runtime-mmap-size': > > + Size in bytes of the provided memory map. (required) > > I would collapse the above two properties into a single property that > actually contains the memory map instead of pointing to it. You will > also need to specify the exact format of the data in this property. Ok, that makes sense. Hmm. The data is an array of struct EFI_MEMORY_DESCRIPTOR entries, known in Linux as efi_memory_desc_t. Is that a good enough description? > > +- 'efi-mmap-desc-size': > > + Size of each descriptor in the memory map. (override default) > > +- 'efi-mmap-desc-ver': > > + Memory descriptor format version. (override default) > > I don't understand how these properties will actually work. What > changes in the parsing if these properties are set? I guess the intended use is that these options would permit you to append new fields to the struct and have old code correctly parse the array anyway. / Leif
On Wed, Jun 26, 2013 at 3:04 PM, Leif Lindholm <leif.lindholm@linaro.org> wrote: > On Wed, Jun 26, 2013 at 02:13:39PM +0100, Grant Likely wrote: >> > +- 'efi-runtime-mmap': >> > + Physical address of an EFI memory map, containing at least >> > + the regions to be preserved. (required) >> > +- 'efi-runtime-mmap-size': >> > + Size in bytes of the provided memory map. (required) >> >> I would collapse the above two properties into a single property that >> actually contains the memory map instead of pointing to it. You will >> also need to specify the exact format of the data in this property. > > Ok, that makes sense. > > Hmm. The data is an array of struct EFI_MEMORY_DESCRIPTOR entries, > known in Linux as efi_memory_desc_t. Is that a good enough description? Yes, it is perfectly valid to point at another spec and state "it is in that format". You'll also want to be specific that the data is using the UEFI byte ordering, and not the ordering normally used by FDT. One could argue that it should be 'translated' into a native DT data format, but I think it is better to view it as a BLOB that DT doesn't have anything to say about. >> > +- 'efi-mmap-desc-size': >> > + Size of each descriptor in the memory map. (override default) >> > +- 'efi-mmap-desc-ver': >> > + Memory descriptor format version. (override default) >> >> I don't understand how these properties will actually work. What >> changes in the parsing if these properties are set? > > I guess the intended use is that these options would permit you to > append new fields to the struct and have old code correctly parse the > array anyway. Let's leave them out as part of the binding until it is actually needed. g.
On Wed, 2013-06-26 at 14:59 +0100, Matt Fleming wrote: > On Wed, 26 Jun, at 03:53:11PM, Leif Lindholm wrote: > > It's completely feasible, but we'd need to use a different method to do > > the boot services call with a 1:1 mapping (idmap support is not available > > until much later in the boot process). > > At least if you no longer relied upon the idmap we could potentially > have a single efi_enter_virtual_mode() call-site in init/main.c, which > would be nice. The fixed virtual address scheme currently being looked at for x86_64 to make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit because the address space isn't big enough. For ARM, given that we've much more opportunity to work with the vendors, can we just avoid transitioning to a virtual address map and always just install a physical mapping before doing efi calls? James
On 06/26/2013 07:20 AM, Grant Likely wrote: > On Wed, Jun 26, 2013 at 12:42 AM, Stephen Warren <swarren@wwwdotorg.org> wrote: >> On 06/25/2013 12:11 PM, Leif Lindholm wrote: >>> This patch provides documentation of the [U]EFI runtime services and >>> configuration features. >> >> >>> diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt >> >>> +The implementation depends on receiving pointers to the UEFI memory map >>> +and System Table in a Flattened Device Tree - so is only available with >>> +CONFIG_OF. >>> + >>> +It (early) parses the FDT for the following parameters: >> >> Part of this document (the raw requirements for DT content, rather than >> the discussion of OS implementation/behaviour in parsing/interpreting >> the properties) should be part of a file in >> Documentation/devicetree/bindings/ (arm/uefi.txt?). >> >> What node are these properties expected to be contained within? >> >> Shouldn't that node be required to contain a compatible value, which >> would define the schema for the other properties? > > Typically, a compatible property isn't only used for nodes that > represent a device or a so-called 'virtual' device (ie. such as to > describe how all the sound complex is wired together) since that > should be the clue to an OS that a device driver will bind against the > node. I think these properties can be dropped into /chosen without > defining a new compatible value. > >>> +- 'efi-system-table': >>> + Physical address of the system table. (required) >>> +- 'efi-runtime-mmap': >>> + Physical address of an EFI memory map, containing at least >>> + the regions to be preserved. (required) >>> +- 'efi-runtime-mmap-size': >>> + Size in bytes of the provided memory map. (required) >>> +- 'efi-mmap-desc-size': >>> + Size of each descriptor in the memory map. (override default) >>> +- 'efi-mmap-desc-ver': >>> + Memory descriptor format version. (override default) >>> + >>> +Since UEFI firmware on ARM systems are required to use a 1:1 memory map >>> +even on LPAE-capable systems, the above fields are 32-bit regardless. >> >> What about ARMv8? Is the intention to have a separate definition for the >> UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a >> future version of UEFI allows LPAE usage? > > It is unlikely that will happen on v7 since newer versions of UEFI are > expected to remain backwards compatible with the current spec. The expectation of backwards-compatibility sounds nice, but it seems a little dangerous to outright rely on it. Even if not a regular compatible property, can we define a property that indicates the UEFI revision or revision of this DT binding, so that if we ever have to change it, there is some way of explicitly indicating which exact schema the DT corresponds to, rather than having to reverse-engineer it from the set of properties that "just happen" to be present in DT? This is rather like the firmware node discussion that happened recently, where we were expecting to represent a firmware (secure mode) interface by a DT node, which would have a compatible value, which in turn would convey information about which "OS" the secure firmware was running, and well as any potential SoC-/OEM-/board-specific interface provided by it. And who knows, what if UEFI gets replaced someday; presumably we'd want some way of explicitly stating "running under UEFI" vs. "running under something else"?
On Wed, Jun 26, 2013 at 12:32:30PM -0600, Stephen Warren wrote: > >> What about ARMv8? Is the intention to have a separate definition for the > >> UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a > >> future version of UEFI allows LPAE usage? > > > > It is unlikely that will happen on v7 since newer versions of UEFI are > > expected to remain backwards compatible with the current spec. > > The expectation of backwards-compatibility sounds nice, but it seems a > little dangerous to outright rely on it. > > Even if not a regular compatible property, can we define a property that > indicates the UEFI revision or revision of this DT binding, so that if > we ever have to change it, there is some way of explicitly indicating > which exact schema the DT corresponds to, rather than having to > reverse-engineer it from the set of properties that "just happen" to be > present in DT? > > This is rather like the firmware node discussion that happened recently, > where we were expecting to represent a firmware (secure mode) interface > by a DT node, which would have a compatible value, which in turn would > convey information about which "OS" the secure firmware was running, and > well as any potential SoC-/OEM-/board-specific interface provided by it. > > And who knows, what if UEFI gets replaced someday; presumably we'd want > some way of explicitly stating "running under UEFI" vs. "running under > something else"? To me, these concerns are all covered by the existence of the efi-system-table node, and the version number that you can extract from the table (mandatory in any UEFI implementation) located at that address. There is no reverse-engineering involved. / Leif
On Wed, Jun 26, 2013 at 07:38:19AM -0700, James Bottomley wrote: > The fixed virtual address scheme currently being looked at for x86_64 to > make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit > because the address space isn't big enough. For ARM, given that we've > much more opportunity to work with the vendors, can we just avoid > transitioning to a virtual address map and always just install a > physical mapping before doing efi calls? We can probably get away with that now, but it does risk us ending up with some firmware that expects to run in physical mode (boards designed for Linux) and some firmware that expects to run in virtual mode (boards designed for Windows). The degree of lockdown in the Windows ecosystem at present means it's not a real problem at the moment, but if that ever changes we're going to risk incompatibility.
On Thu, Jun 27, 2013 at 2:32 AM, Matthew Garrett <mjg59@srcf.ucam.org> wrote: > On Wed, Jun 26, 2013 at 07:38:19AM -0700, James Bottomley wrote: >> The fixed virtual address scheme currently being looked at for x86_64 to >> make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit >> because the address space isn't big enough. For ARM, given that we've >> much more opportunity to work with the vendors, can we just avoid >> transitioning to a virtual address map and always just install a >> physical mapping before doing efi calls? > > We can probably get away with that now, but it does risk us ending up > with some firmware that expects to run in physical mode (boards designed > for Linux) and some firmware that expects to run in virtual mode (boards > designed for Windows). The degree of lockdown in the Windows ecosystem > at present means it's not a real problem at the moment, but if that ever > changes we're going to risk incompatibility. What is the problem trying to be avoided by not using the virtual map? Is it passing the virtual mapping data from one kernel to the next when kexecing? Or something else? g.
On Thu, 2013-06-27 at 07:23 +0100, Grant Likely wrote: > On Thu, Jun 27, 2013 at 2:32 AM, Matthew Garrett <mjg59@srcf.ucam.org> wrote: > > On Wed, Jun 26, 2013 at 07:38:19AM -0700, James Bottomley wrote: > >> The fixed virtual address scheme currently being looked at for x86_64 to > >> make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit > >> because the address space isn't big enough. For ARM, given that we've > >> much more opportunity to work with the vendors, can we just avoid > >> transitioning to a virtual address map and always just install a > >> physical mapping before doing efi calls? > > > > We can probably get away with that now, but it does risk us ending up > > with some firmware that expects to run in physical mode (boards designed > > for Linux) and some firmware that expects to run in virtual mode (boards > > designed for Windows). The degree of lockdown in the Windows ecosystem > > at present means it's not a real problem at the moment, but if that ever > > changes we're going to risk incompatibility. > > What is the problem trying to be avoided by not using the virtual map? > Is it passing the virtual mapping data from one kernel to the next > when kexecing? Or something else? Where to begin ... SetVirtualAddressMap() is one massive hack job ... just look at the tiano core implementation. Basically it has a fixed idea of where all the pointers are and it tries to convert them all to the new address space. The problem we see in x86 is that this conversion process isn't exhaustive due to implementation cockups, so the post virtual address map image occasionally tries to access unconverted pointers via the old physical address and oopses the kernel. The problem for kexec is that SetVirtualAddressMap isn't idempotent. In fact by API fiat it can only ever be called once for the entire lifetime of the UEFI bios, which could be many kernels in a kexec situation. So, somehow the subsequent kernels have to know not to call it, plus, obviously, the virtual address map of the previous kernel has to work in the next because it can't set up a new one. James
On Thu, Jun 27, 2013 at 02:32:19AM +0100, Matthew Garrett wrote: > On Wed, Jun 26, 2013 at 07:38:19AM -0700, James Bottomley wrote: > > The fixed virtual address scheme currently being looked at for x86_64 to > > make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit > > because the address space isn't big enough. For ARM, given that we've > > much more opportunity to work with the vendors, can we just avoid > > transitioning to a virtual address map and always just install a > > physical mapping before doing efi calls? > > We can probably get away with that now, but it does risk us ending up > with some firmware that expects to run in physical mode (boards designed > for Linux) and some firmware that expects to run in virtual mode (boards > designed for Windows). The degree of lockdown in the Windows ecosystem > at present means it's not a real problem at the moment, but if that ever > changes we're going to risk incompatibility. Is there anything preventing calling SetVirtualAddressMap() with a 1:1 map? Or do you simply mean that some platforms might cruise along with undetected bugs in their relocation hooks? / Leif
On Wednesday 26 June 2013, Grant Likely wrote: > > index 0000000..5c48271 > > --- /dev/null > > +++ b/Documentation/arm/uefi.txt > > @@ -0,0 +1,39 @@ > > +The nomenclature EFI and UEFI are used interchangeably in this document. > > + > > +The implementation depends on receiving pointers to the UEFI memory map > > +and System Table in a Flattened Device Tree - so is only available with > > +CONFIG_OF. > > + > > +It (early) parses the FDT for the following parameters: > > Need to state which node these properties can be found in. I recommend /chosen > > I would also prefix all of the following properties with "linux," > since they are very much about what the Linux kernel needs for > booting. EFI stub will be creating these properties specifically for > Linux, and the LinuxLoader should do the same (until we eventually > kill it). Why not make it a separate /efi node instead, mirroring what we have for hypervisor specific information and things like rtas? Arnd
On Wed, Jun 26, 2013 at 11:33:41PM -0700, James Bottomley wrote: > On Thu, 2013-06-27 at 07:23 +0100, Grant Likely wrote: > > What is the problem trying to be avoided by not using the virtual map? > > Is it passing the virtual mapping data from one kernel to the next > > when kexecing? Or something else? > > Where to begin ... SetVirtualAddressMap() is one massive hack job ... > just look at the tiano core implementation. Basically it has a fixed > idea of where all the pointers are and it tries to convert them all to > the new address space. The problem we see in x86 is that this > conversion process isn't exhaustive due to implementation cockups, so > the post virtual address map image occasionally tries to access > unconverted pointers via the old physical address and oopses the kernel. And yet it's the only mode in which the firmrware is actually tested against an OS, so we don't have any real choice in the matter.
On Thu, Jun 27, 2013 at 11:00:50AM +0200, Leif Lindholm wrote: > On Thu, Jun 27, 2013 at 02:32:19AM +0100, Matthew Garrett wrote: > > We can probably get away with that now, but it does risk us ending up > > with some firmware that expects to run in physical mode (boards designed > > for Linux) and some firmware that expects to run in virtual mode (boards > > designed for Windows). The degree of lockdown in the Windows ecosystem > > at present means it's not a real problem at the moment, but if that ever > > changes we're going to risk incompatibility. > > Is there anything preventing calling SetVirtualAddressMap() with a > 1:1 map? No, but we've seen bugs as a result on some x86 systems. As far as the spec, though, you're fine.
On Thu, Jun 27, 2013 at 7:33 AM, James Bottomley <James.Bottomley@hansenpartnership.com> wrote: > On Thu, 2013-06-27 at 07:23 +0100, Grant Likely wrote: >> On Thu, Jun 27, 2013 at 2:32 AM, Matthew Garrett <mjg59@srcf.ucam.org> wrote: >> > On Wed, Jun 26, 2013 at 07:38:19AM -0700, James Bottomley wrote: >> >> The fixed virtual address scheme currently being looked at for x86_64 to >> >> make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit >> >> because the address space isn't big enough. For ARM, given that we've >> >> much more opportunity to work with the vendors, can we just avoid >> >> transitioning to a virtual address map and always just install a >> >> physical mapping before doing efi calls? >> > >> > We can probably get away with that now, but it does risk us ending up >> > with some firmware that expects to run in physical mode (boards designed >> > for Linux) and some firmware that expects to run in virtual mode (boards >> > designed for Windows). The degree of lockdown in the Windows ecosystem >> > at present means it's not a real problem at the moment, but if that ever >> > changes we're going to risk incompatibility. >> >> What is the problem trying to be avoided by not using the virtual map? >> Is it passing the virtual mapping data from one kernel to the next >> when kexecing? Or something else? > > Where to begin ... SetVirtualAddressMap() is one massive hack job ... > just look at the tiano core implementation. Basically it has a fixed > idea of where all the pointers are and it tries to convert them all to > the new address space. The problem we see in x86 is that this > conversion process isn't exhaustive due to implementation cockups, so > the post virtual address map image occasionally tries to access > unconverted pointers via the old physical address and oopses the kernel. Would it be possible to run the UEFI hooks in some form of pseudo userspace thread that protects against dereferencing addresses that are no longer UEFI addresses? > The problem for kexec is that SetVirtualAddressMap isn't idempotent. In > fact by API fiat it can only ever be called once for the entire lifetime > of the UEFI bios, which could be many kernels in a kexec situation. So, > somehow the subsequent kernels have to know not to call it, plus, > obviously, the virtual address map of the previous kernel has to work in > the next because it can't set up a new one. For this problem at least I think we've got a solution on ARM because the virtual map can be passed across the kexec boundary via the device tree. It will still (probably) need to be located in the ioremap region and the size of the map will push down the maximum address for ioremapping. The value of VMALLOC_END on arm 32bit is 0xff000000 and that is a pretty stable number. As long as both the new and old kernels have the same VMALLOC_END (very likely) then it should be okay to pass the map over. Let me know if I'm missing something important. g.
On Thu, 2013-06-27 at 15:54 +0100, Grant Likely wrote: > On Thu, Jun 27, 2013 at 7:33 AM, James Bottomley > <James.Bottomley@hansenpartnership.com> wrote: > > On Thu, 2013-06-27 at 07:23 +0100, Grant Likely wrote: > >> On Thu, Jun 27, 2013 at 2:32 AM, Matthew Garrett <mjg59@srcf.ucam.org> wrote: > >> > On Wed, Jun 26, 2013 at 07:38:19AM -0700, James Bottomley wrote: > >> >> The fixed virtual address scheme currently being looked at for x86_64 to > >> >> make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit > >> >> because the address space isn't big enough. For ARM, given that we've > >> >> much more opportunity to work with the vendors, can we just avoid > >> >> transitioning to a virtual address map and always just install a > >> >> physical mapping before doing efi calls? > >> > > >> > We can probably get away with that now, but it does risk us ending up > >> > with some firmware that expects to run in physical mode (boards designed > >> > for Linux) and some firmware that expects to run in virtual mode (boards > >> > designed for Windows). The degree of lockdown in the Windows ecosystem > >> > at present means it's not a real problem at the moment, but if that ever > >> > changes we're going to risk incompatibility. > >> > >> What is the problem trying to be avoided by not using the virtual map? > >> Is it passing the virtual mapping data from one kernel to the next > >> when kexecing? Or something else? > > > > Where to begin ... SetVirtualAddressMap() is one massive hack job ... > > just look at the tiano core implementation. Basically it has a fixed > > idea of where all the pointers are and it tries to convert them all to > > the new address space. The problem we see in x86 is that this > > conversion process isn't exhaustive due to implementation cockups, so > > the post virtual address map image occasionally tries to access > > unconverted pointers via the old physical address and oopses the kernel. > > Would it be possible to run the UEFI hooks in some form of pseudo > userspace thread that protects against dereferencing addresses that > are no longer UEFI addresses? That's what the x86_64 proposal from Borislav Petkov does. We alter the page tables before calling into the UEFI hooks to make sure both the physical and virtual addresses work. Your problem on ARM with this approach is that you're a VI platform, not a PI platform like intel, so now you have to worry about inequivalent aliasing. I think you can actually fix this by making sure you call SetVirtualAddressMap with a 1:1 offset mapping that's equivalent to the old physical addresses. > > The problem for kexec is that SetVirtualAddressMap isn't idempotent. In > > fact by API fiat it can only ever be called once for the entire lifetime > > of the UEFI bios, which could be many kernels in a kexec situation. So, > > somehow the subsequent kernels have to know not to call it, plus, > > obviously, the virtual address map of the previous kernel has to work in > > the next because it can't set up a new one. > > For this problem at least I think we've got a solution on ARM because > the virtual map can be passed across the kexec boundary via the device > tree. It will still (probably) need to be located in the ioremap > region and the size of the map will push down the maximum address for > ioremapping. The value of VMALLOC_END on arm 32bit is 0xff000000 and > that is a pretty stable number. As long as both the new and old > kernels have the same VMALLOC_END (very likely) then it should be okay > to pass the map over. > > Let me know if I'm missing something important. No, that works. We have to use a fixed address as an ABI on x86_64 because we don't have a data capsule that survives kexec. James
On Thu, 2013-06-27 at 15:37 +0100, Matthew Garrett wrote: > On Wed, Jun 26, 2013 at 11:33:41PM -0700, James Bottomley wrote: > > On Thu, 2013-06-27 at 07:23 +0100, Grant Likely wrote: > > > What is the problem trying to be avoided by not using the virtual map? > > > Is it passing the virtual mapping data from one kernel to the next > > > when kexecing? Or something else? > > > > Where to begin ... SetVirtualAddressMap() is one massive hack job ... > > just look at the tiano core implementation. Basically it has a fixed > > idea of where all the pointers are and it tries to convert them all to > > the new address space. The problem we see in x86 is that this > > conversion process isn't exhaustive due to implementation cockups, so > > the post virtual address map image occasionally tries to access > > unconverted pointers via the old physical address and oopses the kernel. > > And yet it's the only mode in which the firmrware is actually tested > against an OS, so we don't have any real choice in the matter. Agree for x86 ... we just have to cope with the implementations we see in the field. However, ARM has much more scope to have the UEFI implementation developed collaboratively with Linux as the reference platform. If we can convince the ARM implementors that SetVirtualAddressMap is an accident waiting to happen, they might be more flexible. James
On Thu, Jun 27, 2013 at 4:09 PM, James Bottomley <James.Bottomley@hansenpartnership.com> wrote: > On Thu, 2013-06-27 at 15:37 +0100, Matthew Garrett wrote: >> On Wed, Jun 26, 2013 at 11:33:41PM -0700, James Bottomley wrote: >> > On Thu, 2013-06-27 at 07:23 +0100, Grant Likely wrote: >> > > What is the problem trying to be avoided by not using the virtual map? >> > > Is it passing the virtual mapping data from one kernel to the next >> > > when kexecing? Or something else? >> > >> > Where to begin ... SetVirtualAddressMap() is one massive hack job ... >> > just look at the tiano core implementation. Basically it has a fixed >> > idea of where all the pointers are and it tries to convert them all to >> > the new address space. The problem we see in x86 is that this >> > conversion process isn't exhaustive due to implementation cockups, so >> > the post virtual address map image occasionally tries to access >> > unconverted pointers via the old physical address and oopses the kernel. >> >> And yet it's the only mode in which the firmrware is actually tested >> against an OS, so we don't have any real choice in the matter. > > Agree for x86 ... we just have to cope with the implementations we see > in the field. However, ARM has much more scope to have the UEFI > implementation developed collaboratively with Linux as the reference > platform. If we can convince the ARM implementors that > SetVirtualAddressMap is an accident waiting to happen, they might be > more flexible. We may not have any success convincing them of that; but given the larger scope for Linux on ARM UEFI implementations, it will actually get tested. If Linux chooses to use a 1:1 mapping, then the hardware vendors will make sure a 1:1 mapping will actually work. I must say that I'm a whole lot more comfortable with this approach. I've never been comfortable with calling out to UEFI functions while leaving the entirety of kernel space accessable. Sure UEFI can still do nasty things if it really wants to and important devices get mapped, but at least it will protect against accidental accesses. g.
On Thu, Jun 27, 2013 at 08:09:50AM -0700, James Bottomley wrote: > On Thu, 2013-06-27 at 15:37 +0100, Matthew Garrett wrote: > > And yet it's the only mode in which the firmrware is actually tested > > against an OS, so we don't have any real choice in the matter. > > Agree for x86 ... we just have to cope with the implementations we see > in the field. However, ARM has much more scope to have the UEFI > implementation developed collaboratively with Linux as the reference > platform. If we can convince the ARM implementors that > SetVirtualAddressMap is an accident waiting to happen, they might be > more flexible. The majority of existing ARM UEFI implementations have only ever been used to boot Windows, so like I said, this really isn't a safe assumption.
On 06/26/2013 01:31 PM, Leif Lindholm wrote: > On Wed, Jun 26, 2013 at 12:32:30PM -0600, Stephen Warren wrote: >>>> What about ARMv8? Is the intention to have a separate definition for the >>>> UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a >>>> future version of UEFI allows LPAE usage? >>> >>> It is unlikely that will happen on v7 since newer versions of UEFI are >>> expected to remain backwards compatible with the current spec. >> >> The expectation of backwards-compatibility sounds nice, but it seems a >> little dangerous to outright rely on it. >> >> Even if not a regular compatible property, can we define a property that >> indicates the UEFI revision or revision of this DT binding, so that if >> we ever have to change it, there is some way of explicitly indicating >> which exact schema the DT corresponds to, rather than having to >> reverse-engineer it from the set of properties that "just happen" to be >> present in DT? >> >> This is rather like the firmware node discussion that happened recently, >> where we were expecting to represent a firmware (secure mode) interface >> by a DT node, which would have a compatible value, which in turn would >> convey information about which "OS" the secure firmware was running, and >> well as any potential SoC-/OEM-/board-specific interface provided by it. >> >> And who knows, what if UEFI gets replaced someday; presumably we'd want >> some way of explicitly stating "running under UEFI" vs. "running under >> something else"? > > To me, these concerns are all covered by the existence of the > efi-system-table node, and the version number that you can extract > from the table (mandatory in any UEFI implementation) located at that > address. There is no reverse-engineering involved. So, what you're saying is that the existence (or lack thereof) of the efi-system-table property is the indicator whether EFI is present? I guess if we assume that EFI will always evolve at least compatibly enough that the system table will always exist and be formatted identically at least to the extent of allowing the EFI version number to be parsed then that's workable. If that guarantee is broken, then we can always define a different property that points at the new format of the table. This still seems a little implicit to me; having an explicit node with an explicit compatible value is much more in line with what's been discussed for other firmware interfaces. However, I suppose it will work fine.
On 06/26/2013 07:38 AM, James Bottomley wrote: > On Wed, 2013-06-26 at 14:59 +0100, Matt Fleming wrote: >> On Wed, 26 Jun, at 03:53:11PM, Leif Lindholm wrote: >>> It's completely feasible, but we'd need to use a different method to do >>> the boot services call with a 1:1 mapping (idmap support is not available >>> until much later in the boot process). >> >> At least if you no longer relied upon the idmap we could potentially >> have a single efi_enter_virtual_mode() call-site in init/main.c, which >> would be nice. > > The fixed virtual address scheme currently being looked at for x86_64 to > make SetVirtualAddressMap() kexec invariant doesn't work on 32 bit > because the address space isn't big enough. For ARM, given that we've > much more opportunity to work with the vendors, can we just avoid > transitioning to a virtual address map and always just install a > physical mapping before doing efi calls? > What we could do on x86-32 is to map from 0xc0000000 downwards. It wouldn't be invariant across kernel builds with different user/kernel split... but I'm not sure we can win that one. The other option is to say sod it and just use straight 1:1 mapping on 32 bits... -hpa
On Thu, Jun 27, 2013 at 7:04 PM, Stephen Warren <swarren@wwwdotorg.org> wrote: > On 06/26/2013 01:31 PM, Leif Lindholm wrote: >> On Wed, Jun 26, 2013 at 12:32:30PM -0600, Stephen Warren wrote: >>>>> What about ARMv8? Is the intention to have a separate definition for the >>>>> UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a >>>>> future version of UEFI allows LPAE usage? >>>> >>>> It is unlikely that will happen on v7 since newer versions of UEFI are >>>> expected to remain backwards compatible with the current spec. >>> >>> The expectation of backwards-compatibility sounds nice, but it seems a >>> little dangerous to outright rely on it. >>> >>> Even if not a regular compatible property, can we define a property that >>> indicates the UEFI revision or revision of this DT binding, so that if >>> we ever have to change it, there is some way of explicitly indicating >>> which exact schema the DT corresponds to, rather than having to >>> reverse-engineer it from the set of properties that "just happen" to be >>> present in DT? >>> >>> This is rather like the firmware node discussion that happened recently, >>> where we were expecting to represent a firmware (secure mode) interface >>> by a DT node, which would have a compatible value, which in turn would >>> convey information about which "OS" the secure firmware was running, and >>> well as any potential SoC-/OEM-/board-specific interface provided by it. >>> >>> And who knows, what if UEFI gets replaced someday; presumably we'd want >>> some way of explicitly stating "running under UEFI" vs. "running under >>> something else"? >> >> To me, these concerns are all covered by the existence of the >> efi-system-table node, and the version number that you can extract >> from the table (mandatory in any UEFI implementation) located at that >> address. There is no reverse-engineering involved. > > So, what you're saying is that the existence (or lack thereof) of the > efi-system-table property is the indicator whether EFI is present? I > guess if we assume that EFI will always evolve at least compatibly > enough that the system table will always exist and be formatted > identically at least to the extent of allowing the EFI version number to > be parsed then that's workable. If that guarantee is broken, then we can > always define a different property that points at the new format of the > table. Yes, that is what it means, and there is *immense* pressure from the OEM market to not break that contract in a non-backwards-compatible way. g.
diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 4978456..87e01d1 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -36,3 +36,6 @@ nwfpe/ - NWFPE floating point emulator documentation swp_emulation - SWP/SWPB emulation handler/logging description + +uefi.txt + - [U]EFI configuration and runtime services documentation diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 0000000..5c48271 --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,39 @@ +The nomenclature EFI and UEFI are used interchangeably in this document. + +The implementation depends on receiving pointers to the UEFI memory map +and System Table in a Flattened Device Tree - so is only available with +CONFIG_OF. + +It (early) parses the FDT for the following parameters: +- 'efi-system-table': + Physical address of the system table. (required) +- 'efi-runtime-mmap': + Physical address of an EFI memory map, containing at least + the regions to be preserved. (required) +- 'efi-runtime-mmap-size': + Size in bytes of the provided memory map. (required) +- 'efi-mmap-desc-size': + Size of each descriptor in the memory map. (override default) +- 'efi-mmap-desc-ver': + Memory descriptor format version. (override default) + +Since UEFI firmware on ARM systems are required to use a 1:1 memory map +even on LPAE-capable systems, the above fields are 32-bit regardless. + +It also depends on early_ioremap to parse the memory map and preserve +the regions required for runtime services. + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +After the kernel has mapped the required regions into its address space, +a SetVirtualAddressMap() call is made into UEFI in order to update +relocations. This call must be performed with all the code in a 1:1 +mapping. This implementation achieves this by temporarily disabling the +MMU for the duration of this call. This can only be done safely: +- before secondary CPUs are brought online. +- after early_initcalls have completed, sinze it uses setup_mm_for_reboot(). + +For verbose debug messages, specify 'uefi_debug' on the kernel command +line.
This patch provides documentation of the [U]EFI runtime services and configuration features. Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> --- Documentation/arm/00-INDEX | 3 +++ Documentation/arm/uefi.txt | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 Documentation/arm/uefi.txt