linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option
       [not found]     ` <1443608419-37801-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
@ 2015-09-30  1:36       ` kbuild test robot
       [not found]         ` <201509300948.PGoujrqX%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: kbuild test robot @ 2015-09-30  1:36 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	mingo-H+wXaHxf7aLQT0dZR+AlfA, hpa-YMNOUZJC4hwAvxtiuMwx3w,
	tony.luck-ral2JQCrhuEAvxtiuMwx3w, qinxishi-hv44wF8Li93QT0dZR+AlfA,
	kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A, Taku Izumi

[-- Attachment #1: Type: text/plain, Size: 6595 bytes --]

Hi Taku,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please ignore]

config: i386-allmodconfig (attached as .config)
reproduce:
  git checkout afcc94d3f91a00ce97d735a563a8e5d595f45a03
  # save the attached .config to linux build tree
  make ARCH=i386 

All error/warnings (new ones prefixed by >>):

>> drivers/firmware/efi/fake_mem.c:36:25: error: 'CONFIG_EFI_MAX_FAKEMEM' undeclared here (not in a function)
    #define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKEMEM
                            ^
>> drivers/firmware/efi/fake_mem.c:42:34: note: in expansion of macro 'EFI_MAX_FAKEMEM'
    static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
                                     ^
   drivers/firmware/efi/fake_mem.c: In function 'efi_fake_memmap':
>> drivers/firmware/efi/fake_mem.c:186:20: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     memmap.phys_map = (void *)new_memmap_phy;
                       ^
   drivers/firmware/efi/fake_mem.c: At top level:
>> drivers/firmware/efi/fake_mem.c:42:24: warning: 'fake_mems' defined but not used [-Wunused-variable]
    static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
                           ^

vim +/CONFIG_EFI_MAX_FAKEMEM +36 drivers/firmware/efi/fake_mem.c

    30	#include <linux/init.h>
    31	#include <linux/memblock.h>
    32	#include <linux/types.h>
    33	#include <linux/sort.h>
    34	#include <asm/efi.h>
    35	
  > 36	#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKEMEM
    37	
    38	struct fake_mem {
    39		struct range range;
    40		u64 attribute;
    41	};
  > 42	static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
    43	static int nr_fake_mem;
    44	
    45	static int __init cmp_fake_mem(const void *x1, const void *x2)
    46	{
    47		const struct fake_mem *m1 = x1;
    48		const struct fake_mem *m2 = x2;
    49	
    50		if (m1->range.start < m2->range.start)
    51			return -1;
    52		if (m1->range.start > m2->range.start)
    53			return 1;
    54		return 0;
    55	}
    56	
    57	void __init efi_fake_memmap(void)
    58	{
    59		u64 start, end, m_start, m_end, m_attr;
    60		int new_nr_map = memmap.nr_map;
    61		efi_memory_desc_t *md;
    62		u64 new_memmap_phy;
    63		void *new_memmap;
    64		void *old, *new;
    65		int i;
    66	
    67		if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP))
    68			return;
    69	
    70		/* count up the number of EFI memory descriptor */
    71		for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
    72			md = old;
    73			start = md->phys_addr;
    74			end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
    75	
    76			for (i = 0; i < nr_fake_mem; i++) {
    77				/* modifying range */
    78				m_start = fake_mems[i].range.start;
    79				m_end = fake_mems[i].range.end;
    80	
    81				if (m_start <= start) {
    82					/* split into 2 parts */
    83					if (start < m_end && m_end < end)
    84						new_nr_map++;
    85				}
    86				if (start < m_start && m_start < end) {
    87					/* split into 3 parts */
    88					if (m_end < end)
    89						new_nr_map += 2;
    90					/* split into 2 parts */
    91					if (end <= m_end)
    92						new_nr_map++;
    93				}
    94			}
    95		}
    96	
    97		/* allocate memory for new EFI memmap */
    98		new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
    99						PAGE_SIZE);
   100		if (!new_memmap_phy)
   101			return;
   102	
   103		/* create new EFI memmap */
   104		new_memmap = early_memremap(new_memmap_phy,
   105					    memmap.desc_size * new_nr_map);
   106		if (!new_memmap) {
   107			memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
   108			return;
   109		}
   110	
   111		for (old = memmap.map, new = new_memmap;
   112		     old < memmap.map_end;
   113		     old += memmap.desc_size, new += memmap.desc_size) {
   114	
   115			/* copy original EFI memory descriptor */
   116			memcpy(new, old, memmap.desc_size);
   117			md = new;
   118			start = md->phys_addr;
   119			end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
   120	
   121			for (i = 0; i < nr_fake_mem; i++) {
   122				/* modifying range */
   123				m_start = fake_mems[i].range.start;
   124				m_end = fake_mems[i].range.end;
   125				m_attr = fake_mems[i].attribute;
   126	
   127				if (m_start <= start && end <= m_end)
   128					md->attribute |= m_attr;
   129	
   130				if (m_start <= start &&
   131				    (start < m_end && m_end < end)) {
   132					/* first part */
   133					md->attribute |= m_attr;
   134					md->num_pages = (m_end - md->phys_addr + 1) >>
   135						EFI_PAGE_SHIFT;
   136					/* latter part */
   137					new += memmap.desc_size;
   138					memcpy(new, old, memmap.desc_size);
   139					md = new;
   140					md->phys_addr = m_end + 1;
   141					md->num_pages = (end - md->phys_addr + 1) >>
   142						EFI_PAGE_SHIFT;
   143				}
   144	
   145				if ((start < m_start && m_start < end) && m_end < end) {
   146					/* first part */
   147					md->num_pages = (m_start - md->phys_addr) >>
   148						EFI_PAGE_SHIFT;
   149					/* middle part */
   150					new += memmap.desc_size;
   151					memcpy(new, old, memmap.desc_size);
   152					md = new;
   153					md->attribute |= m_attr;
   154					md->phys_addr = m_start;
   155					md->num_pages = (m_end - m_start + 1) >>
   156						EFI_PAGE_SHIFT;
   157					/* last part */
   158					new += memmap.desc_size;
   159					memcpy(new, old, memmap.desc_size);
   160					md = new;
   161					md->phys_addr = m_end + 1;
   162					md->num_pages = (end - m_end) >>
   163						EFI_PAGE_SHIFT;
   164				}
   165	
   166				if ((start < m_start && m_start < end) &&
   167				    (end <= m_end)) {
   168					/* first part */
   169					md->num_pages = (m_start - md->phys_addr) >>
   170						EFI_PAGE_SHIFT;
   171					/* latter part */
   172					new += memmap.desc_size;
   173					memcpy(new, old, memmap.desc_size);
   174					md = new;
   175					md->phys_addr = m_start;
   176					md->num_pages = (end - md->phys_addr + 1) >>
   177						EFI_PAGE_SHIFT;
   178					md->attribute |= m_attr;
   179				}
   180			}
   181		}
   182	
   183		/* swap into new EFI memmap */
   184		efi_unmap_memmap();
   185		memmap.map = new_memmap;
 > 186		memmap.phys_map = (void *)new_memmap_phy;
   187		memmap.nr_map = new_nr_map;
   188		memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
   189		set_bit(EFI_MEMMAP, &efi.flags);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 51602 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option
       [not found]         ` <201509300948.PGoujrqX%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2015-09-30  4:51           ` Izumi, Taku
  2015-09-30 14:01           ` Taku Izumi
  1 sibling, 0 replies; 8+ messages in thread
From: Izumi, Taku @ 2015-09-30  4:51 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all-JC7UmRfGjtg@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org,
	mingo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
	hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org,
	tony.luck-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	qinxishi-hv44wF8Li93QT0dZR+AlfA@public.gmane.org,
	Kamezawa, Hiroyuki,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org

 I've missed git-format-patch after rebasing.
 I'll resend right one..

> -----Original Message-----
> From: kbuild test robot [mailto:lkp-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org]
> Sent: Wednesday, September 30, 2015 10:37 AM
> To: Izumi, Taku/泉 拓
> Cc: kbuild-all-JC7UmRfGjtg@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org;
> tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org; mingo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org; hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org; tony.luck-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org; qinxishi-hv44wF8Li93QT0dZR+AlfA@public.gmane.org; Kamezawa, Hiroyuki/亀
> 澤 寛之; ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org; Izumi, Taku/泉 拓
> Subject: Re: [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option
> 
> Hi Taku,
> 
> [auto build test results on v4.3-rc3 -- if it's inappropriate base, please ignore]
> 
> config: i386-allmodconfig (attached as .config)
> reproduce:
>   git checkout afcc94d3f91a00ce97d735a563a8e5d595f45a03
>   # save the attached .config to linux build tree
>   make ARCH=i386
> 
> All error/warnings (new ones prefixed by >>):
> 
> >> drivers/firmware/efi/fake_mem.c:36:25: error: 'CONFIG_EFI_MAX_FAKEMEM' undeclared here (not in a function)
>     #define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKEMEM
>                             ^
> >> drivers/firmware/efi/fake_mem.c:42:34: note: in expansion of macro 'EFI_MAX_FAKEMEM'
>     static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
>                                      ^
>    drivers/firmware/efi/fake_mem.c: In function 'efi_fake_memmap':
> >> drivers/firmware/efi/fake_mem.c:186:20: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
>      memmap.phys_map = (void *)new_memmap_phy;
>                        ^
>    drivers/firmware/efi/fake_mem.c: At top level:
> >> drivers/firmware/efi/fake_mem.c:42:24: warning: 'fake_mems' defined but not used [-Wunused-variable]
>     static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
>                            ^
> 
> vim +/CONFIG_EFI_MAX_FAKEMEM +36 drivers/firmware/efi/fake_mem.c
> 
>     30	#include <linux/init.h>
>     31	#include <linux/memblock.h>
>     32	#include <linux/types.h>
>     33	#include <linux/sort.h>
>     34	#include <asm/efi.h>
>     35
>   > 36	#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKEMEM
>     37
>     38	struct fake_mem {
>     39		struct range range;
>     40		u64 attribute;
>     41	};
>   > 42	static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
>     43	static int nr_fake_mem;
>     44
>     45	static int __init cmp_fake_mem(const void *x1, const void *x2)
>     46	{
>     47		const struct fake_mem *m1 = x1;
>     48		const struct fake_mem *m2 = x2;
>     49
>     50		if (m1->range.start < m2->range.start)
>     51			return -1;
>     52		if (m1->range.start > m2->range.start)
>     53			return 1;
>     54		return 0;
>     55	}
>     56
>     57	void __init efi_fake_memmap(void)
>     58	{
>     59		u64 start, end, m_start, m_end, m_attr;
>     60		int new_nr_map = memmap.nr_map;
>     61		efi_memory_desc_t *md;
>     62		u64 new_memmap_phy;
>     63		void *new_memmap;
>     64		void *old, *new;
>     65		int i;
>     66
>     67		if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP))
>     68			return;
>     69
>     70		/* count up the number of EFI memory descriptor */
>     71		for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
>     72			md = old;
>     73			start = md->phys_addr;
>     74			end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
>     75
>     76			for (i = 0; i < nr_fake_mem; i++) {
>     77				/* modifying range */
>     78				m_start = fake_mems[i].range.start;
>     79				m_end = fake_mems[i].range.end;
>     80
>     81				if (m_start <= start) {
>     82					/* split into 2 parts */
>     83					if (start < m_end && m_end < end)
>     84						new_nr_map++;
>     85				}
>     86				if (start < m_start && m_start < end) {
>     87					/* split into 3 parts */
>     88					if (m_end < end)
>     89						new_nr_map += 2;
>     90					/* split into 2 parts */
>     91					if (end <= m_end)
>     92						new_nr_map++;
>     93				}
>     94			}
>     95		}
>     96
>     97		/* allocate memory for new EFI memmap */
>     98		new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
>     99						PAGE_SIZE);
>    100		if (!new_memmap_phy)
>    101			return;
>    102
>    103		/* create new EFI memmap */
>    104		new_memmap = early_memremap(new_memmap_phy,
>    105					    memmap.desc_size * new_nr_map);
>    106		if (!new_memmap) {
>    107			memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
>    108			return;
>    109		}
>    110
>    111		for (old = memmap.map, new = new_memmap;
>    112		     old < memmap.map_end;
>    113		     old += memmap.desc_size, new += memmap.desc_size) {
>    114
>    115			/* copy original EFI memory descriptor */
>    116			memcpy(new, old, memmap.desc_size);
>    117			md = new;
>    118			start = md->phys_addr;
>    119			end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
>    120
>    121			for (i = 0; i < nr_fake_mem; i++) {
>    122				/* modifying range */
>    123				m_start = fake_mems[i].range.start;
>    124				m_end = fake_mems[i].range.end;
>    125				m_attr = fake_mems[i].attribute;
>    126
>    127				if (m_start <= start && end <= m_end)
>    128					md->attribute |= m_attr;
>    129
>    130				if (m_start <= start &&
>    131				    (start < m_end && m_end < end)) {
>    132					/* first part */
>    133					md->attribute |= m_attr;
>    134					md->num_pages = (m_end - md->phys_addr + 1) >>
>    135						EFI_PAGE_SHIFT;
>    136					/* latter part */
>    137					new += memmap.desc_size;
>    138					memcpy(new, old, memmap.desc_size);
>    139					md = new;
>    140					md->phys_addr = m_end + 1;
>    141					md->num_pages = (end - md->phys_addr + 1) >>
>    142						EFI_PAGE_SHIFT;
>    143				}
>    144
>    145				if ((start < m_start && m_start < end) && m_end < end) {
>    146					/* first part */
>    147					md->num_pages = (m_start - md->phys_addr) >>
>    148						EFI_PAGE_SHIFT;
>    149					/* middle part */
>    150					new += memmap.desc_size;
>    151					memcpy(new, old, memmap.desc_size);
>    152					md = new;
>    153					md->attribute |= m_attr;
>    154					md->phys_addr = m_start;
>    155					md->num_pages = (m_end - m_start + 1) >>
>    156						EFI_PAGE_SHIFT;
>    157					/* last part */
>    158					new += memmap.desc_size;
>    159					memcpy(new, old, memmap.desc_size);
>    160					md = new;
>    161					md->phys_addr = m_end + 1;
>    162					md->num_pages = (end - m_end) >>
>    163						EFI_PAGE_SHIFT;
>    164				}
>    165
>    166				if ((start < m_start && m_start < end) &&
>    167				    (end <= m_end)) {
>    168					/* first part */
>    169					md->num_pages = (m_start - md->phys_addr) >>
>    170						EFI_PAGE_SHIFT;
>    171					/* latter part */
>    172					new += memmap.desc_size;
>    173					memcpy(new, old, memmap.desc_size);
>    174					md = new;
>    175					md->phys_addr = m_start;
>    176					md->num_pages = (end - md->phys_addr + 1) >>
>    177						EFI_PAGE_SHIFT;
>    178					md->attribute |= m_attr;
>    179				}
>    180			}
>    181		}
>    182
>    183		/* swap into new EFI memmap */
>    184		efi_unmap_memmap();
>    185		memmap.map = new_memmap;
>  > 186		memmap.phys_map = (void *)new_memmap_phy;
>    187		memmap.nr_map = new_nr_map;
>    188		memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
>    189		set_bit(EFI_MEMMAP, &efi.flags);
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 0/2] Introduce "efi_fake_mem" boot option
@ 2015-09-30 10:18 Taku Izumi
       [not found] ` <1443608292-37686-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Taku Izumi @ 2015-09-30 10:18 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	mingo-H+wXaHxf7aLQT0dZR+AlfA, hpa-YMNOUZJC4hwAvxtiuMwx3w
  Cc: tony.luck-ral2JQCrhuEAvxtiuMwx3w, qinxishi-hv44wF8Li93QT0dZR+AlfA,
	kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A, Taku Izumi

UEFI spec 2.5 introduces new Memory Attribute Definition named
EFI_MEMORY_MORE_RELIABLE which indicates which memory ranges are
mirrored. Now linux kernel can recognize which memory ranges are mirrored
by handling EFI_MEMORY_MORE_RELIABLE attributes.
However testing this feature necesitates boxes with UEFI spec 2.5 complied
firmware.

This patchset introduces new boot option named "efi_fake_mem".
By specifying this parameter, you can add arbitrary attribute to
specific memory range. This is useful for debugging of Memory 
Address Range Mirroring feature.

This is updated version one of the former patch posted at
 http://www.mail-archive.com/linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg05936.html

changelog:
 - change boot option name and spec
   efi_fake_mem_mirror=nn@ss -> efi_fake_mem=nn@ss:aa
 - rename print_efi_memmap() to efi_print_memmap()
 - introduce new config named CONFIG_EFI_MAX_FAKE_MEM
 - and some fix pointed by Matt Flemming

Taku Izumi (2):
  x86, efi: rename print_efi_memmap() to efi_print_memmap()
  x86, efi: Add "efi_fake_mem" boot option

 Documentation/kernel-parameters.txt |  15 +++
 arch/x86/include/asm/efi.h          |   1 +
 arch/x86/kernel/setup.c             |   4 +-
 arch/x86/platform/efi/efi.c         |   4 +-
 drivers/firmware/efi/Kconfig        |  22 ++++
 drivers/firmware/efi/Makefile       |   1 +
 drivers/firmware/efi/fake_mem.c     | 238 ++++++++++++++++++++++++++++++++++++
 include/linux/efi.h                 |   6 +
 8 files changed, 288 insertions(+), 3 deletions(-)
 create mode 100644 drivers/firmware/efi/fake_mem.c

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] x86, efi: rename print_efi_memmap() to efi_print_memmap()
       [not found] ` <1443608292-37686-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
@ 2015-09-30 10:20   ` Taku Izumi
       [not found]     ` <1443608400-37744-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
  2015-09-30 10:20   ` [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option Taku Izumi
  1 sibling, 1 reply; 8+ messages in thread
From: Taku Izumi @ 2015-09-30 10:20 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	mingo-H+wXaHxf7aLQT0dZR+AlfA, hpa-YMNOUZJC4hwAvxtiuMwx3w
  Cc: tony.luck-ral2JQCrhuEAvxtiuMwx3w, qinxishi-hv44wF8Li93QT0dZR+AlfA,
	kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A, Taku Izumi

This patch renames print_efi_memmap() to efi_print_memmap() and
make it global function so that we can invoke it outside of
arch/x86/platform/efi/efi.c

Signed-off-by: Taku Izumi <izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 arch/x86/include/asm/efi.h  | 1 +
 arch/x86/platform/efi/efi.c | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index ab5f1d4..f8b93d6 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -103,6 +103,7 @@ extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int __init efi_memblock_x86_reserve_range(void);
 extern pgd_t * __init efi_call_phys_prolog(void);
 extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
+extern void __init efi_print_memmap(void);
 extern void __init efi_unmap_memmap(void);
 extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1db84c0..1f95caf 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -222,7 +222,7 @@ int __init efi_memblock_x86_reserve_range(void)
 	return 0;
 }
 
-static void __init print_efi_memmap(void)
+void __init efi_print_memmap(void)
 {
 #ifdef EFI_DEBUG
 	efi_memory_desc_t *md;
@@ -524,7 +524,7 @@ void __init efi_init(void)
 		return;
 
 	if (efi_enabled(EFI_DBG))
-		print_efi_memmap();
+		efi_print_memmap();
 
 	efi_esrt_init();
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option
       [not found] ` <1443608292-37686-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
  2015-09-30 10:20   ` [PATCH 1/2] x86, efi: rename print_efi_memmap() to efi_print_memmap() Taku Izumi
@ 2015-09-30 10:20   ` Taku Izumi
       [not found]     ` <1443608419-37801-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
  1 sibling, 1 reply; 8+ messages in thread
From: Taku Izumi @ 2015-09-30 10:20 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	mingo-H+wXaHxf7aLQT0dZR+AlfA, hpa-YMNOUZJC4hwAvxtiuMwx3w
  Cc: tony.luck-ral2JQCrhuEAvxtiuMwx3w, qinxishi-hv44wF8Li93QT0dZR+AlfA,
	kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A, Taku Izumi

This patch introduces new boot option named "efi_fake_mem".
By specifying this parameter, you can add arbitrary attribute
to specific memory range.
This is useful for debugging of Address Range Mirroring feature.

For example, if "efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000"
is specified, the original (firmware provided) EFI memmap will be
updated so that the specified memory regions have
EFI_MEMORY_MORE_RELIABLE attribute (0x10000):

 <original>
   efi: mem36: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000000100000000-0x00000020a0000000) (129536MB)

 <updated>
   efi: mem36: [Conventional Memory|  |MR|  |  |  |   |WB|WT|WC|UC] range=[0x0000000100000000-0x0000000180000000) (2048MB)
   efi: mem37: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000000180000000-0x00000010a0000000) (61952MB)
   efi: mem38: [Conventional Memory|  |MR|  |  |  |   |WB|WT|WC|UC] range=[0x00000010a0000000-0x0000001120000000) (2048MB)
   efi: mem39: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000001120000000-0x00000020a0000000) (63488MB)

And you will find that the following message is output:

   efi: Memory: 4096M/131455M mirrored memory

Signed-off-by: Taku Izumi <izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 Documentation/kernel-parameters.txt |  15 +++
 arch/x86/kernel/setup.c             |   4 +-
 drivers/firmware/efi/Kconfig        |  22 ++++
 drivers/firmware/efi/Makefile       |   1 +
 drivers/firmware/efi/fake_mem.c     | 238 ++++++++++++++++++++++++++++++++++++
 include/linux/efi.h                 |   6 +
 6 files changed, 285 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/efi/fake_mem.c

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 22a4b68..50fc09b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1094,6 +1094,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			you are really sure that your UEFI does sane gc and
 			fulfills the spec otherwise your board may brick.
 
+	efi_fake_mem=	nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86]
+			Add arbitrary attribute to specific memory range by
+			updating original EFI memory map.
+			Region of memory which aa attribute is added to is
+			from ss to ss+nn.
+			If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
+			is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
+			attribute is added to range 0x100000000-0x180000000 and
+			0x10a0000000-0x1120000000.
+
+			Using this parameter you can do debugging of EFI memmap
+			related feature. For example, you can do debugging of
+			Address Range Mirroring feature even if your box
+			doesn't support it.
+
 	eisa_irq_edge=	[PARISC,HW]
 			See header of drivers/parisc/eisa.c.
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fdb7f2a..30b4c44 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1079,8 +1079,10 @@ void __init setup_arch(char **cmdline_p)
 	memblock_set_current_limit(ISA_END_ADDRESS);
 	memblock_x86_fill();
 
-	if (efi_enabled(EFI_BOOT))
+	if (efi_enabled(EFI_BOOT)) {
+		efi_fake_memmap();
 		efi_find_mirror();
+	}
 
 	/*
 	 * The EFI specification says that boot service code won't be called
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 84533e0..ac47cc4d 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -52,6 +52,28 @@ config EFI_RUNTIME_MAP
 
 	  See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
+config EFI_FAKE_MEMMAP
+	bool "Enable EFI fake memory map"
+	depends on EFI && X86
+	default n
+	help
+	  Saying Y here will enable "efi_fake_mem" boot option.
+	  By specifying this parameter, you can add arbitrary attribute
+	  to specific memory range by updating original (firmware provided)
+	  EFI memmap.
+	  This is useful for debugging of EFI memmap related feature.
+	  e.g. Address Range Mirroring feature.
+
+config EFI_MAX_FAKE_MEM
+	int "maximum allowable number of ranges in efi_fake_mem boot option"
+	depends on EFI && X86 && EFI_FAKE_MEMMAP
+	range 1 128
+	default 8
+	help
+	  Maximum allowable number of ranges in efi_fake_mem boot option.
+	  Ranges can be set up to this value using comma-separated list.
+	  The default value is 8.
+
 config EFI_PARAMS_FROM_FDT
 	bool
 	help
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 6fd3da9..c24f005 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_UEFI_CPER)			+= cper.o
 obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtime-map.o
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
 obj-$(CONFIG_EFI_STUB)			+= libstub/
+obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
new file mode 100644
index 0000000..a666bec
--- /dev/null
+++ b/drivers/firmware/efi/fake_mem.c
@@ -0,0 +1,238 @@
+/*
+ * fake_mem.c
+ *
+ * Copyright (C) 2015 FUJITSU LIMITED
+ * Author: Taku Izumi <izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
+ *
+ * This code introduces new boot option named "efi_fake_mem"
+ * By specifying this parameter, you can add arbitrary attribute to
+ * specific memory range by updating original (firmware provided) EFI
+ * memmap.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms and conditions of the GNU General Public License,
+ *  version 2, as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
+ */
+
+#include <linux/kernel.h>
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/types.h>
+#include <linux/sort.h>
+#include <asm/efi.h>
+
+#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKEMEM
+
+struct fake_mem {
+	struct range range;
+	u64 attribute;
+};
+static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
+static int nr_fake_mem;
+
+static int __init cmp_fake_mem(const void *x1, const void *x2)
+{
+	const struct fake_mem *m1 = x1;
+	const struct fake_mem *m2 = x2;
+
+	if (m1->range.start < m2->range.start)
+		return -1;
+	if (m1->range.start > m2->range.start)
+		return 1;
+	return 0;
+}
+
+void __init efi_fake_memmap(void)
+{
+	u64 start, end, m_start, m_end, m_attr;
+	int new_nr_map = memmap.nr_map;
+	efi_memory_desc_t *md;
+	u64 new_memmap_phy;
+	void *new_memmap;
+	void *old, *new;
+	int i;
+
+	if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP))
+		return;
+
+	/* count up the number of EFI memory descriptor */
+	for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
+		md = old;
+		start = md->phys_addr;
+		end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+		for (i = 0; i < nr_fake_mem; i++) {
+			/* modifying range */
+			m_start = fake_mems[i].range.start;
+			m_end = fake_mems[i].range.end;
+
+			if (m_start <= start) {
+				/* split into 2 parts */
+				if (start < m_end && m_end < end)
+					new_nr_map++;
+			}
+			if (start < m_start && m_start < end) {
+				/* split into 3 parts */
+				if (m_end < end)
+					new_nr_map += 2;
+				/* split into 2 parts */
+				if (end <= m_end)
+					new_nr_map++;
+			}
+		}
+	}
+
+	/* allocate memory for new EFI memmap */
+	new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
+					PAGE_SIZE);
+	if (!new_memmap_phy)
+		return;
+
+	/* create new EFI memmap */
+	new_memmap = early_memremap(new_memmap_phy,
+				    memmap.desc_size * new_nr_map);
+	if (!new_memmap) {
+		memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
+		return;
+	}
+
+	for (old = memmap.map, new = new_memmap;
+	     old < memmap.map_end;
+	     old += memmap.desc_size, new += memmap.desc_size) {
+
+		/* copy original EFI memory descriptor */
+		memcpy(new, old, memmap.desc_size);
+		md = new;
+		start = md->phys_addr;
+		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+		for (i = 0; i < nr_fake_mem; i++) {
+			/* modifying range */
+			m_start = fake_mems[i].range.start;
+			m_end = fake_mems[i].range.end;
+			m_attr = fake_mems[i].attribute;
+
+			if (m_start <= start && end <= m_end)
+				md->attribute |= m_attr;
+
+			if (m_start <= start &&
+			    (start < m_end && m_end < end)) {
+				/* first part */
+				md->attribute |= m_attr;
+				md->num_pages = (m_end - md->phys_addr + 1) >>
+					EFI_PAGE_SHIFT;
+				/* latter part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->phys_addr = m_end + 1;
+				md->num_pages = (end - md->phys_addr + 1) >>
+					EFI_PAGE_SHIFT;
+			}
+
+			if ((start < m_start && m_start < end) && m_end < end) {
+				/* first part */
+				md->num_pages = (m_start - md->phys_addr) >>
+					EFI_PAGE_SHIFT;
+				/* middle part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->attribute |= m_attr;
+				md->phys_addr = m_start;
+				md->num_pages = (m_end - m_start + 1) >>
+					EFI_PAGE_SHIFT;
+				/* last part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->phys_addr = m_end + 1;
+				md->num_pages = (end - m_end) >>
+					EFI_PAGE_SHIFT;
+			}
+
+			if ((start < m_start && m_start < end) &&
+			    (end <= m_end)) {
+				/* first part */
+				md->num_pages = (m_start - md->phys_addr) >>
+					EFI_PAGE_SHIFT;
+				/* latter part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->phys_addr = m_start;
+				md->num_pages = (end - md->phys_addr + 1) >>
+					EFI_PAGE_SHIFT;
+				md->attribute |= m_attr;
+			}
+		}
+	}
+
+	/* swap into new EFI memmap */
+	efi_unmap_memmap();
+	memmap.map = new_memmap;
+	memmap.phys_map = (void *)new_memmap_phy;
+	memmap.nr_map = new_nr_map;
+	memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
+	set_bit(EFI_MEMMAP, &efi.flags);
+
+	/* print new EFI memmap */
+	efi_print_memmap();
+}
+
+static int __init setup_fake_mem(char *p)
+{
+	u64 start = 0, mem_size = 0, attribute = 0;
+	int i;
+
+	if (!p)
+		return -EINVAL;
+
+	while (*p != '\0') {
+		mem_size = memparse(p, &p);
+		if (*p == '@')
+			start = memparse(p+1, &p);
+		else
+			break;
+
+		if (*p == ':')
+			attribute = simple_strtoull(p+1, &p, 0);
+		else
+			break;
+
+		if (nr_fake_mem >= EFI_MAX_FAKEMEM)
+			break;
+
+		fake_mems[nr_fake_mem].range.start = start;
+		fake_mems[nr_fake_mem].range.end = start + mem_size - 1;
+		fake_mems[nr_fake_mem].attribute = attribute;
+		nr_fake_mem++;
+
+		if (*p == ',')
+			p++;
+	}
+
+	sort(fake_mems, nr_fake_mem, sizeof(struct fake_mem),
+	     cmp_fake_mem, NULL);
+
+	for (i = 0; i < nr_fake_mem; i++)
+		pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]",
+			fake_mems[i].attribute, fake_mems[i].range.start,
+			fake_mems[i].range.end);
+
+	return *p == '\0' ? 0 : -EINVAL;
+}
+
+early_param("efi_fake_mem", setup_fake_mem);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85ef051..620baec 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -908,6 +908,12 @@ extern struct kobject *efi_kobj;
 extern int efi_reboot_quirk_mode;
 extern bool efi_poweroff_required(void);
 
+#ifdef CONFIG_EFI_FAKE_MEMMAP
+extern void __init efi_fake_memmap(void);
+#else
+static inline void efi_fake_memmap(void) { }
+#endif
+
 /* Iterate through an efi_memory_map */
 #define for_each_efi_memory_desc(m, md)					   \
 	for ((md) = (m)->map;						   \
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option
       [not found]         ` <201509300948.PGoujrqX%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  2015-09-30  4:51           ` Izumi, Taku
@ 2015-09-30 14:01           ` Taku Izumi
  2015-10-10 20:36             ` Matt Fleming
  1 sibling, 1 reply; 8+ messages in thread
From: Taku Izumi @ 2015-09-30 14:01 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	mingo-H+wXaHxf7aLQT0dZR+AlfA, hpa-YMNOUZJC4hwAvxtiuMwx3w
  Cc: tony.luck-ral2JQCrhuEAvxtiuMwx3w, qinxishi-hv44wF8Li93QT0dZR+AlfA,
	kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A, Taku Izumi

This patch introduces new boot option named "efi_fake_mem".
By specifying this parameter, you can add arbitrary attribute
to specific memory range.
This is useful for debugging of Address Range Mirroring feature.

For example, if "efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000"
is specified, the original (firmware provided) EFI memmap will be
updated so that the specified memory regions have
EFI_MEMORY_MORE_RELIABLE attribute (0x10000):

 <original>
   efi: mem36: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000000100000000-0x00000020a0000000) (129536MB)

 <updated>
   efi: mem36: [Conventional Memory|  |MR|  |  |  |   |WB|WT|WC|UC] range=[0x0000000100000000-0x0000000180000000) (2048MB)
   efi: mem37: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000000180000000-0x00000010a0000000) (61952MB)
   efi: mem38: [Conventional Memory|  |MR|  |  |  |   |WB|WT|WC|UC] range=[0x00000010a0000000-0x0000001120000000) (2048MB)
   efi: mem39: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000001120000000-0x00000020a0000000) (63488MB)

And you will find that the following message is output:

   efi: Memory: 4096M/131455M mirrored memory

Signed-off-by: Taku Izumi <izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 Documentation/kernel-parameters.txt |  15 +++
 arch/x86/kernel/setup.c             |   4 +-
 drivers/firmware/efi/Kconfig        |  22 ++++
 drivers/firmware/efi/Makefile       |   1 +
 drivers/firmware/efi/fake_mem.c     | 238 ++++++++++++++++++++++++++++++++++++
 include/linux/efi.h                 |   6 +
 6 files changed, 285 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/efi/fake_mem.c

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 22a4b68..50fc09b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1094,6 +1094,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			you are really sure that your UEFI does sane gc and
 			fulfills the spec otherwise your board may brick.
 
+	efi_fake_mem=	nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86]
+			Add arbitrary attribute to specific memory range by
+			updating original EFI memory map.
+			Region of memory which aa attribute is added to is
+			from ss to ss+nn.
+			If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
+			is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
+			attribute is added to range 0x100000000-0x180000000 and
+			0x10a0000000-0x1120000000.
+
+			Using this parameter you can do debugging of EFI memmap
+			related feature. For example, you can do debugging of
+			Address Range Mirroring feature even if your box
+			doesn't support it.
+
 	eisa_irq_edge=	[PARISC,HW]
 			See header of drivers/parisc/eisa.c.
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fdb7f2a..30b4c44 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1079,8 +1079,10 @@ void __init setup_arch(char **cmdline_p)
 	memblock_set_current_limit(ISA_END_ADDRESS);
 	memblock_x86_fill();
 
-	if (efi_enabled(EFI_BOOT))
+	if (efi_enabled(EFI_BOOT)) {
+		efi_fake_memmap();
 		efi_find_mirror();
+	}
 
 	/*
 	 * The EFI specification says that boot service code won't be called
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 84533e0..ac47cc4d 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -52,6 +52,28 @@ config EFI_RUNTIME_MAP
 
 	  See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
+config EFI_FAKE_MEMMAP
+	bool "Enable EFI fake memory map"
+	depends on EFI && X86
+	default n
+	help
+	  Saying Y here will enable "efi_fake_mem" boot option.
+	  By specifying this parameter, you can add arbitrary attribute
+	  to specific memory range by updating original (firmware provided)
+	  EFI memmap.
+	  This is useful for debugging of EFI memmap related feature.
+	  e.g. Address Range Mirroring feature.
+
+config EFI_MAX_FAKE_MEM
+	int "maximum allowable number of ranges in efi_fake_mem boot option"
+	depends on EFI && X86 && EFI_FAKE_MEMMAP
+	range 1 128
+	default 8
+	help
+	  Maximum allowable number of ranges in efi_fake_mem boot option.
+	  Ranges can be set up to this value using comma-separated list.
+	  The default value is 8.
+
 config EFI_PARAMS_FROM_FDT
 	bool
 	help
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 6fd3da9..c24f005 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_UEFI_CPER)			+= cper.o
 obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtime-map.o
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
 obj-$(CONFIG_EFI_STUB)			+= libstub/
+obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
new file mode 100644
index 0000000..32bcb14
--- /dev/null
+++ b/drivers/firmware/efi/fake_mem.c
@@ -0,0 +1,238 @@
+/*
+ * fake_mem.c
+ *
+ * Copyright (C) 2015 FUJITSU LIMITED
+ * Author: Taku Izumi <izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
+ *
+ * This code introduces new boot option named "efi_fake_mem"
+ * By specifying this parameter, you can add arbitrary attribute to
+ * specific memory range by updating original (firmware provided) EFI
+ * memmap.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms and conditions of the GNU General Public License,
+ *  version 2, as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
+ */
+
+#include <linux/kernel.h>
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/types.h>
+#include <linux/sort.h>
+#include <asm/efi.h>
+
+#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM
+
+struct fake_mem {
+	struct range range;
+	u64 attribute;
+};
+static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
+static int nr_fake_mem;
+
+static int __init cmp_fake_mem(const void *x1, const void *x2)
+{
+	const struct fake_mem *m1 = x1;
+	const struct fake_mem *m2 = x2;
+
+	if (m1->range.start < m2->range.start)
+		return -1;
+	if (m1->range.start > m2->range.start)
+		return 1;
+	return 0;
+}
+
+void __init efi_fake_memmap(void)
+{
+	u64 start, end, m_start, m_end, m_attr;
+	int new_nr_map = memmap.nr_map;
+	efi_memory_desc_t *md;
+	u64 new_memmap_phy;
+	void *new_memmap;
+	void *old, *new;
+	int i;
+
+	if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP))
+		return;
+
+	/* count up the number of EFI memory descriptor */
+	for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
+		md = old;
+		start = md->phys_addr;
+		end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+		for (i = 0; i < nr_fake_mem; i++) {
+			/* modifying range */
+			m_start = fake_mems[i].range.start;
+			m_end = fake_mems[i].range.end;
+
+			if (m_start <= start) {
+				/* split into 2 parts */
+				if (start < m_end && m_end < end)
+					new_nr_map++;
+			}
+			if (start < m_start && m_start < end) {
+				/* split into 3 parts */
+				if (m_end < end)
+					new_nr_map += 2;
+				/* split into 2 parts */
+				if (end <= m_end)
+					new_nr_map++;
+			}
+		}
+	}
+
+	/* allocate memory for new EFI memmap */
+	new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
+					PAGE_SIZE);
+	if (!new_memmap_phy)
+		return;
+
+	/* create new EFI memmap */
+	new_memmap = early_memremap(new_memmap_phy,
+				    memmap.desc_size * new_nr_map);
+	if (!new_memmap) {
+		memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
+		return;
+	}
+
+	for (old = memmap.map, new = new_memmap;
+	     old < memmap.map_end;
+	     old += memmap.desc_size, new += memmap.desc_size) {
+
+		/* copy original EFI memory descriptor */
+		memcpy(new, old, memmap.desc_size);
+		md = new;
+		start = md->phys_addr;
+		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+		for (i = 0; i < nr_fake_mem; i++) {
+			/* modifying range */
+			m_start = fake_mems[i].range.start;
+			m_end = fake_mems[i].range.end;
+			m_attr = fake_mems[i].attribute;
+
+			if (m_start <= start && end <= m_end)
+				md->attribute |= m_attr;
+
+			if (m_start <= start &&
+			    (start < m_end && m_end < end)) {
+				/* first part */
+				md->attribute |= m_attr;
+				md->num_pages = (m_end - md->phys_addr + 1) >>
+					EFI_PAGE_SHIFT;
+				/* latter part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->phys_addr = m_end + 1;
+				md->num_pages = (end - md->phys_addr + 1) >>
+					EFI_PAGE_SHIFT;
+			}
+
+			if ((start < m_start && m_start < end) && m_end < end) {
+				/* first part */
+				md->num_pages = (m_start - md->phys_addr) >>
+					EFI_PAGE_SHIFT;
+				/* middle part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->attribute |= m_attr;
+				md->phys_addr = m_start;
+				md->num_pages = (m_end - m_start + 1) >>
+					EFI_PAGE_SHIFT;
+				/* last part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->phys_addr = m_end + 1;
+				md->num_pages = (end - m_end) >>
+					EFI_PAGE_SHIFT;
+			}
+
+			if ((start < m_start && m_start < end) &&
+			    (end <= m_end)) {
+				/* first part */
+				md->num_pages = (m_start - md->phys_addr) >>
+					EFI_PAGE_SHIFT;
+				/* latter part */
+				new += memmap.desc_size;
+				memcpy(new, old, memmap.desc_size);
+				md = new;
+				md->phys_addr = m_start;
+				md->num_pages = (end - md->phys_addr + 1) >>
+					EFI_PAGE_SHIFT;
+				md->attribute |= m_attr;
+			}
+		}
+	}
+
+	/* swap into new EFI memmap */
+	efi_unmap_memmap();
+	memmap.map = new_memmap;
+	memmap.phys_map = (void *)new_memmap_phy;
+	memmap.nr_map = new_nr_map;
+	memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
+	set_bit(EFI_MEMMAP, &efi.flags);
+
+	/* print new EFI memmap */
+	efi_print_memmap();
+}
+
+static int __init setup_fake_mem(char *p)
+{
+	u64 start = 0, mem_size = 0, attribute = 0;
+	int i;
+
+	if (!p)
+		return -EINVAL;
+
+	while (*p != '\0') {
+		mem_size = memparse(p, &p);
+		if (*p == '@')
+			start = memparse(p+1, &p);
+		else
+			break;
+
+		if (*p == ':')
+			attribute = simple_strtoull(p+1, &p, 0);
+		else
+			break;
+
+		if (nr_fake_mem >= EFI_MAX_FAKEMEM)
+			break;
+
+		fake_mems[nr_fake_mem].range.start = start;
+		fake_mems[nr_fake_mem].range.end = start + mem_size - 1;
+		fake_mems[nr_fake_mem].attribute = attribute;
+		nr_fake_mem++;
+
+		if (*p == ',')
+			p++;
+	}
+
+	sort(fake_mems, nr_fake_mem, sizeof(struct fake_mem),
+	     cmp_fake_mem, NULL);
+
+	for (i = 0; i < nr_fake_mem; i++)
+		pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]",
+			fake_mems[i].attribute, fake_mems[i].range.start,
+			fake_mems[i].range.end);
+
+	return *p == '\0' ? 0 : -EINVAL;
+}
+
+early_param("efi_fake_mem", setup_fake_mem);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85ef051..620baec 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -908,6 +908,12 @@ extern struct kobject *efi_kobj;
 extern int efi_reboot_quirk_mode;
 extern bool efi_poweroff_required(void);
 
+#ifdef CONFIG_EFI_FAKE_MEMMAP
+extern void __init efi_fake_memmap(void);
+#else
+static inline void efi_fake_memmap(void) { }
+#endif
+
 /* Iterate through an efi_memory_map */
 #define for_each_efi_memory_desc(m, md)					   \
 	for ((md) = (m)->map;						   \
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] x86, efi: rename print_efi_memmap() to efi_print_memmap()
       [not found]     ` <1443608400-37744-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
@ 2015-10-10 19:31       ` Matt Fleming
  0 siblings, 0 replies; 8+ messages in thread
From: Matt Fleming @ 2015-10-10 19:31 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	matt.fleming-ral2JQCrhuEAvxtiuMwx3w, tglx-hfZtesqFncYOwBW4kG4KsQ,
	mingo-H+wXaHxf7aLQT0dZR+AlfA, hpa-YMNOUZJC4hwAvxtiuMwx3w,
	tony.luck-ral2JQCrhuEAvxtiuMwx3w, qinxishi-hv44wF8Li93QT0dZR+AlfA,
	kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A,
	ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A

On Wed, 30 Sep, at 07:20:00PM, Taku Izumi wrote:
> This patch renames print_efi_memmap() to efi_print_memmap() and
> make it global function so that we can invoke it outside of
> arch/x86/platform/efi/efi.c
> 
> Signed-off-by: Taku Izumi <izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
> ---
>  arch/x86/include/asm/efi.h  | 1 +
>  arch/x86/platform/efi/efi.c | 4 ++--
>  2 files changed, 3 insertions(+), 2 deletions(-)

Thanks, applied.

-- 
Matt Fleming, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option
  2015-09-30 14:01           ` Taku Izumi
@ 2015-10-10 20:36             ` Matt Fleming
  0 siblings, 0 replies; 8+ messages in thread
From: Matt Fleming @ 2015-10-10 20:36 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-kernel, linux-efi, x86, matt.fleming, tglx, mingo, hpa,
	tony.luck, qiuxishi, kamezawa.hiroyu, ard.biesheuvel

On Wed, 30 Sep, at 11:01:56PM, Taku Izumi wrote:
> This patch introduces new boot option named "efi_fake_mem".
> By specifying this parameter, you can add arbitrary attribute
> to specific memory range.
> This is useful for debugging of Address Range Mirroring feature.
> 
> For example, if "efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000"
> is specified, the original (firmware provided) EFI memmap will be
> updated so that the specified memory regions have
> EFI_MEMORY_MORE_RELIABLE attribute (0x10000):
> 
>  <original>
>    efi: mem36: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000000100000000-0x00000020a0000000) (129536MB)
> 
>  <updated>
>    efi: mem36: [Conventional Memory|  |MR|  |  |  |   |WB|WT|WC|UC] range=[0x0000000100000000-0x0000000180000000) (2048MB)
>    efi: mem37: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000000180000000-0x00000010a0000000) (61952MB)
>    efi: mem38: [Conventional Memory|  |MR|  |  |  |   |WB|WT|WC|UC] range=[0x00000010a0000000-0x0000001120000000) (2048MB)
>    efi: mem39: [Conventional Memory|  |  |  |  |  |   |WB|WT|WC|UC] range=[0x0000001120000000-0x00000020a0000000) (63488MB)
> 
> And you will find that the following message is output:
> 
>    efi: Memory: 4096M/131455M mirrored memory
> 
> Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
> ---
>  Documentation/kernel-parameters.txt |  15 +++
>  arch/x86/kernel/setup.c             |   4 +-
>  drivers/firmware/efi/Kconfig        |  22 ++++
>  drivers/firmware/efi/Makefile       |   1 +
>  drivers/firmware/efi/fake_mem.c     | 238 ++++++++++++++++++++++++++++++++++++
>  include/linux/efi.h                 |   6 +
>  6 files changed, 285 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/firmware/efi/fake_mem.c
 
Looks good to me! I've queued this up with one minor change...

> +config EFI_MAX_FAKE_MEM
> +	int "maximum allowable number of ranges in efi_fake_mem boot option"
> +	depends on EFI && X86 && EFI_FAKE_MEMMAP

We can simplify this depends line since EFI_FAKE_MEMMAP itself is
dependent on EFI and X86, and we should use that level of indirection
to our advantage to save updating this line if/when arm64 support is
added.

-- 
Matt Fleming, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-10-10 20:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-30 10:18 [PATCH 0/2] Introduce "efi_fake_mem" boot option Taku Izumi
     [not found] ` <1443608292-37686-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
2015-09-30 10:20   ` [PATCH 1/2] x86, efi: rename print_efi_memmap() to efi_print_memmap() Taku Izumi
     [not found]     ` <1443608400-37744-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
2015-10-10 19:31       ` Matt Fleming
2015-09-30 10:20   ` [PATCH 2/2] x86, efi: Add "efi_fake_mem" boot option Taku Izumi
     [not found]     ` <1443608419-37801-1-git-send-email-izumi.taku-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
2015-09-30  1:36       ` kbuild test robot
     [not found]         ` <201509300948.PGoujrqX%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2015-09-30  4:51           ` Izumi, Taku
2015-09-30 14:01           ` Taku Izumi
2015-10-10 20:36             ` Matt Fleming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).