diff mbox

[v2,1/2] efi: esrt: use memremap not ioremap to access ESRT table in memory

Message ID 1455535953-5056-2-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Feb. 15, 2016, 11:32 a.m. UTC
On ARM and arm64, ioremap() and memremap() are not interchangeable like
on x86, and the use of ioremap() on ordinary RAM is typically flagged
as an error if the memory region being mapped is also covered by the
linear mapping, since that would lead to aliases with conflicting
cacheability attributes.

Since what we are dealing with is not an I/O region with side effects,
using ioremap() here is arguably incorrect anyway, so let's replace
it with memremap instead. Also add a missing unmap on the success path,
and drop a memblock_remove() call which does not belong here, this far
into the boot sequence.

Cc: Peter Jones <pjones@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
 drivers/firmware/efi/esrt.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

-- 
2.5.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Comments

Ard Biesheuvel Feb. 18, 2016, 12:16 p.m. UTC | #1
On 18 February 2016 at 11:44, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Mon, 15 Feb, at 12:32:32PM, Ard Biesheuvel wrote:

>> On ARM and arm64, ioremap() and memremap() are not interchangeable like

>> on x86, and the use of ioremap() on ordinary RAM is typically flagged

>> as an error if the memory region being mapped is also covered by the

>> linear mapping, since that would lead to aliases with conflicting

>> cacheability attributes.

>>

>> Since what we are dealing with is not an I/O region with side effects,

>> using ioremap() here is arguably incorrect anyway, so let's replace

>> it with memremap instead. Also add a missing unmap on the success path,

>> and drop a memblock_remove() call which does not belong here, this far

>> into the boot sequence.

>>

>> Cc: Peter Jones <pjones@redhat.com>

>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

>> ---

>>  drivers/firmware/efi/esrt.c | 16 ++++++++--------

>>  1 file changed, 8 insertions(+), 8 deletions(-)

>>

>

> [...]

>

>> @@ -432,8 +434,6 @@ static int __init esrt_sysfs_init(void)

>>       if (error)

>>               goto err_cleanup_list;

>>

>> -     memblock_remove(esrt_data, esrt_data_size);

>> -

>>       pr_debug("esrt-sysfs: loaded.\n");

>>

>>       return 0;

>

> Shouldn't we be replacing memblock_remove() with free_bootmem_late()?

> The original ESRT region is still reserved at this point, so we should

> do our best to release it to the page allocator.


I'd rather we keep it reserved. That way, the config table entry still
points to something valid, which could be useful for kexec(), I think?
At least, that is how I intended to handle config tables on ARM ...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Ard Biesheuvel Feb. 18, 2016, 1:29 p.m. UTC | #2
On 18 February 2016 at 14:28, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Thu, 18 Feb, at 01:16:05PM, Ard Biesheuvel wrote:

>> On 18 February 2016 at 11:44, Matt Fleming <matt@codeblueprint.co.uk> wrote:

>> > On Mon, 15 Feb, at 12:32:32PM, Ard Biesheuvel wrote:

>> >> On ARM and arm64, ioremap() and memremap() are not interchangeable like

>> >> on x86, and the use of ioremap() on ordinary RAM is typically flagged

>> >> as an error if the memory region being mapped is also covered by the

>> >> linear mapping, since that would lead to aliases with conflicting

>> >> cacheability attributes.

>> >>

>> >> Since what we are dealing with is not an I/O region with side effects,

>> >> using ioremap() here is arguably incorrect anyway, so let's replace

>> >> it with memremap instead. Also add a missing unmap on the success path,

>> >> and drop a memblock_remove() call which does not belong here, this far

>> >> into the boot sequence.

>> >>

>> >> Cc: Peter Jones <pjones@redhat.com>

>> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

>> >> ---

>> >>  drivers/firmware/efi/esrt.c | 16 ++++++++--------

>> >>  1 file changed, 8 insertions(+), 8 deletions(-)

>> >>

>> >

>> > [...]

>> >

>> >> @@ -432,8 +434,6 @@ static int __init esrt_sysfs_init(void)

>> >>       if (error)

>> >>               goto err_cleanup_list;

>> >>

>> >> -     memblock_remove(esrt_data, esrt_data_size);

>> >> -

>> >>       pr_debug("esrt-sysfs: loaded.\n");

>> >>

>> >>       return 0;

>> >

>> > Shouldn't we be replacing memblock_remove() with free_bootmem_late()?

>> > The original ESRT region is still reserved at this point, so we should

>> > do our best to release it to the page allocator.

>>

>> I'd rather we keep it reserved. That way, the config table entry still

>> points to something valid, which could be useful for kexec(), I think?

>> At least, that is how I intended to handle config tables on ARM ...

>

> If we're going to reserve it why do we need to copy the data out at

> all in esrt_sysfs_init()?


Excellent question. I don't think there is any point to doing that.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Ard Biesheuvel Feb. 18, 2016, 1:44 p.m. UTC | #3
On 18 February 2016 at 14:43, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Thu, 18 Feb, at 02:29:32PM, Ard Biesheuvel wrote:

>> On 18 February 2016 at 14:28, Matt Fleming <matt@codeblueprint.co.uk> wrote:

>> > On Thu, 18 Feb, at 01:16:05PM, Ard Biesheuvel wrote:

>> >> On 18 February 2016 at 11:44, Matt Fleming <matt@codeblueprint.co.uk> wrote:

>> >> > On Mon, 15 Feb, at 12:32:32PM, Ard Biesheuvel wrote:

>> >> >> On ARM and arm64, ioremap() and memremap() are not interchangeable like

>> >> >> on x86, and the use of ioremap() on ordinary RAM is typically flagged

>> >> >> as an error if the memory region being mapped is also covered by the

>> >> >> linear mapping, since that would lead to aliases with conflicting

>> >> >> cacheability attributes.

>> >> >>

>> >> >> Since what we are dealing with is not an I/O region with side effects,

>> >> >> using ioremap() here is arguably incorrect anyway, so let's replace

>> >> >> it with memremap instead. Also add a missing unmap on the success path,

>> >> >> and drop a memblock_remove() call which does not belong here, this far

>> >> >> into the boot sequence.

>> >> >>

>> >> >> Cc: Peter Jones <pjones@redhat.com>

>> >> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

>> >> >> ---

>> >> >>  drivers/firmware/efi/esrt.c | 16 ++++++++--------

>> >> >>  1 file changed, 8 insertions(+), 8 deletions(-)

>> >> >>

>> >> >

>> >> > [...]

>> >> >

>> >> >> @@ -432,8 +434,6 @@ static int __init esrt_sysfs_init(void)

>> >> >>       if (error)

>> >> >>               goto err_cleanup_list;

>> >> >>

>> >> >> -     memblock_remove(esrt_data, esrt_data_size);

>> >> >> -

>> >> >>       pr_debug("esrt-sysfs: loaded.\n");

>> >> >>

>> >> >>       return 0;

>> >> >

>> >> > Shouldn't we be replacing memblock_remove() with free_bootmem_late()?

>> >> > The original ESRT region is still reserved at this point, so we should

>> >> > do our best to release it to the page allocator.

>> >>

>> >> I'd rather we keep it reserved. That way, the config table entry still

>> >> points to something valid, which could be useful for kexec(), I think?

>> >> At least, that is how I intended to handle config tables on ARM ...

>> >

>> > If we're going to reserve it why do we need to copy the data out at

>> > all in esrt_sysfs_init()?

>>

>> Excellent question. I don't think there is any point to doing that.

>

> ... Unless the data is contained in an EFI Boot Services region ;-)

>

> Peter?


Yes, it usually is. Is that a problem?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Ard Biesheuvel Feb. 18, 2016, 2:21 p.m. UTC | #4
On 18 February 2016 at 15:15, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Thu, 18 Feb, at 02:44:02PM, Ard Biesheuvel wrote:

>> On 18 February 2016 at 14:43, Matt Fleming <matt@codeblueprint.co.uk> wrote:

>> > On Thu, 18 Feb, at 02:29:32PM, Ard Biesheuvel wrote:

>> >> On 18 February 2016 at 14:28, Matt Fleming <matt@codeblueprint.co.uk> wrote:

>> >> > On Thu, 18 Feb, at 01:16:05PM, Ard Biesheuvel wrote:

>> >> >> On 18 February 2016 at 11:44, Matt Fleming <matt@codeblueprint.co.uk> wrote:

>> >> >> > On Mon, 15 Feb, at 12:32:32PM, Ard Biesheuvel wrote:

>> >> >> >> On ARM and arm64, ioremap() and memremap() are not interchangeable like

>> >> >> >> on x86, and the use of ioremap() on ordinary RAM is typically flagged

>> >> >> >> as an error if the memory region being mapped is also covered by the

>> >> >> >> linear mapping, since that would lead to aliases with conflicting

>> >> >> >> cacheability attributes.

>> >> >> >>

>> >> >> >> Since what we are dealing with is not an I/O region with side effects,

>> >> >> >> using ioremap() here is arguably incorrect anyway, so let's replace

>> >> >> >> it with memremap instead. Also add a missing unmap on the success path,

>> >> >> >> and drop a memblock_remove() call which does not belong here, this far

>> >> >> >> into the boot sequence.

>> >> >> >>

>> >> >> >> Cc: Peter Jones <pjones@redhat.com>

>> >> >> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

>> >> >> >> ---

>> >> >> >>  drivers/firmware/efi/esrt.c | 16 ++++++++--------

>> >> >> >>  1 file changed, 8 insertions(+), 8 deletions(-)

>> >> >> >>

>> >> >> >

>> >> >> > [...]

>> >> >> >

>> >> >> >> @@ -432,8 +434,6 @@ static int __init esrt_sysfs_init(void)

>> >> >> >>       if (error)

>> >> >> >>               goto err_cleanup_list;

>> >> >> >>

>> >> >> >> -     memblock_remove(esrt_data, esrt_data_size);

>> >> >> >> -

>> >> >> >>       pr_debug("esrt-sysfs: loaded.\n");

>> >> >> >>

>> >> >> >>       return 0;

>> >> >> >

>> >> >> > Shouldn't we be replacing memblock_remove() with free_bootmem_late()?

>> >> >> > The original ESRT region is still reserved at this point, so we should

>> >> >> > do our best to release it to the page allocator.

>> >> >>

>> >> >> I'd rather we keep it reserved. That way, the config table entry still

>> >> >> points to something valid, which could be useful for kexec(), I think?

>> >> >> At least, that is how I intended to handle config tables on ARM ...

>> >> >

>> >> > If we're going to reserve it why do we need to copy the data out at

>> >> > all in esrt_sysfs_init()?

>> >>

>> >> Excellent question. I don't think there is any point to doing that.

>> >

>> > ... Unless the data is contained in an EFI Boot Services region ;-)

>> >

>> > Peter?

>>

>> Yes, it usually is. Is that a problem?

>

> Yes, we free the Boot Services regions before hitting userspace on

> x86, see efi_free_boot_services(). We do this map/copy/unmap trick in

> the ACPI BGRT driver for that reason.

>

> The Boot Services regions can be many gigabytes in size, which makes

> leaving them alone impractical.

>

> For kexec on x86 we simply discard the BGRT table, which isn't the end

> of the world because who really needs access to the BGRT image on

> kexec reboot? However, I can see the value of preserving the ESRT.

>

> I guess we've got two options, 1) copy out the chunks of Boot Services

> regions we're interested in and rewrite the EFI tables to point at

> these new allocations and free/discard all of the original Boot

> Services regions or 2) only selectively free the Boot Services

> regions.

>

> I've always stayed clear of 2) in case there exists cross-region

> references in the data that isn't obvious. I'd like to think that

> would never happen, but, you know, dragons lurk here, etc.

>

> Though actually, now I think about it, cross-region references can't

> possibly exist because they'd cause issues with the current code.

>

> So maybe the best solution is actually 2), where we preserve the Boot

> Services regions if any of the drivers (ESRT, BGRT) request them but

> free all the others?

>

> What are the lifetime rules for Boot Services regions on arm*?


We treat all Boot Services regions like Loader Code/Data or free
regions: it is all recorded in memblock as usable memory, and only the
regions that are explicitly reserved are protected from further
general use.

I am currently looking into the memory attribute table, and the use
case is very similar. It would be very useful from our pov to simply
memblock_reserve() the region right after having called
efi_config_parse_tables(), and actually consume its data when we get
around to it later. The ESRT handling is already split down the middle
in the same way.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Ard Biesheuvel May 18, 2016, 8:36 a.m. UTC | #5
On 4 March 2016 at 07:25, Dave Young <dyoung@redhat.com> wrote:
>> I have a very rough draft of patches that implement this strategy on

>> the 'experiemntal/efi-memmap' branch in the EFI tree if anyone is

>> curious and wants to take a look. The series will be sent out soon.

>>

>> I wouldn't necessarily try running them or anything as there's a few

>> things that I know are broken; ia64 build, EFI mixed mode boot,

>> probably arm64 regressions.

>

> Matt, I tried :). I see a build warning about print phys_addr_t without

> %pa anotation and booting with ioremap error messages about slot not found

> , and ioremap region leak messages.

>

> Looking forward to your formal posts.

>


So what is the status here? I know Sai is working on x86 support for
the memory attributes table, so it would make sense settle this matter
as well.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Ard Biesheuvel June 16, 2016, 1:47 p.m. UTC | #6
On 18 May 2016 at 10:53, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> On Wed, 18 May, at 10:36:33AM, Ard Biesheuvel wrote:

>>

>> So what is the status here? I know Sai is working on x86 support for

>> the memory attributes table, so it would make sense settle this matter

>> as well.

>

> This got stuck behind some other work, sorry about that.

>

> Some of this was just merged by Linus (getting rid of the global

> memmap and switching everyone over to efi.memmap), a large chunk

> remains however.

>

> I should be able to get those patches mailed out once the merge window

> closes.


Hi Matt,

Any progress here?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
diff mbox

Patch

diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 22c5285f7705..f096a0a26dbd 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -16,6 +16,7 @@ 
 #include <linux/device.h>
 #include <linux/efi.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kobject.h>
 #include <linux/list.h>
@@ -385,15 +386,15 @@  static void cleanup_entry_list(void)
 static int __init esrt_sysfs_init(void)
 {
 	int error;
-	struct efi_system_resource_table __iomem *ioesrt;
+	struct efi_system_resource_table *memesrt;
 
 	pr_debug("esrt-sysfs: loading.\n");
 	if (!esrt_data || !esrt_data_size)
 		return -ENOSYS;
 
-	ioesrt = ioremap(esrt_data, esrt_data_size);
-	if (!ioesrt) {
-		pr_err("ioremap(%pa, %zu) failed.\n", &esrt_data,
+	memesrt = memremap(esrt_data, esrt_data_size, MEMREMAP_WB);
+	if (!memesrt) {
+		pr_err("memremap(%pa, %zu, MEMREMAP_WB) failed.\n", &esrt_data,
 		       esrt_data_size);
 		return -ENOMEM;
 	}
@@ -401,11 +402,12 @@  static int __init esrt_sysfs_init(void)
 	esrt = kmalloc(esrt_data_size, GFP_KERNEL);
 	if (!esrt) {
 		pr_err("kmalloc failed. (wanted %zu bytes)\n", esrt_data_size);
-		iounmap(ioesrt);
+		memunmap(memesrt);
 		return -ENOMEM;
 	}
 
-	memcpy_fromio(esrt, ioesrt, esrt_data_size);
+	memcpy(esrt, memesrt, esrt_data_size);
+	memunmap(memesrt);
 
 	esrt_kobj = kobject_create_and_add("esrt", efi_kobj);
 	if (!esrt_kobj) {
@@ -432,8 +434,6 @@  static int __init esrt_sysfs_init(void)
 	if (error)
 		goto err_cleanup_list;
 
-	memblock_remove(esrt_data, esrt_data_size);
-
 	pr_debug("esrt-sysfs: loaded.\n");
 
 	return 0;