On Fri, Apr 17, 2015 at 01:54:28PM +0100, Andrew Cooper wrote:
> On 17/04/15 13:39, Jan Beulich wrote:
> >>>> On 17.04.15 at 13:59, <andrew.coop...@citrix.com> wrote:
> >> On 17/04/15 12:17, Olaf Hering wrote:
> >>> Since booting xen fails on my ProBook unless I specify "maxcpus=1" I
> >>> tried the EFI firmware today. To my surprise it boots and finds all
> >>> cpus. But once some efi driver in dom0 is loaded xen crashes. The same
> >>> happens with xen-4.4 as included in SLE12.
> >>>
> >>> ...
> >>> (XEN) Xen call trace:
> >>> (XEN)    [<00000000aec1e8e1>] 00000000aec1e8e1
> >>> (XEN)    [<ffff82d080222600>] efi_runtime_call+0x7f0/0x890
> >>> (XEN)    [<ffff82d0801641a9>] do_platform_op+0x679/0x1670
> >>> (XEN)    [<ffff82d08021dfb9>] syscall_enter+0xa9/0xae
> >>> ....
> >>>
> >>> Can I do anything about it, or is this a firmware bug? I will move the
> >>> offending efi driver away and try again.
> >>>
> >>> Olaf
> >> This is a firmware bug.
> > +1 (and I'm surprised how common this is)
> 
> The bug is present in the reference implementation code, which means it
> is present in a lot of real firmware.  We have kit from 3 different
> vendors which are affected, including latest available firmware.
> 
> >
> >>> (XEN)  0000100000000-000023fffffff type=7 attr=000000000000000
> >>> (XEN)  00000fec10000-00000fec10fff type=11 attr=8000000000000001
> >>> (XEN)  00000fff40000-00000fff46fff type=11 attr=8000000000000000
> >>> (XEN) Unknown cachability for MFNs 0xfff40-0xfff46
> >> This unknown cacheability causes Xen not to make pagetables for the region.
> >>
> >> There is a patch or two floating around the list, but currently no
> >> resolution on the argument it created.
> >>
> >> https://github.com/xenserver/xen-4.5.pg/blob/master/master/unknown-cacheabilit
> >>  
> >> y.patch
> >> is the XenServer fix.
> > Now that's surely wrong
> 
> Right or wrong, this is (apparently; I have not checked) what Linux does.
> 
> >  - if anything, unknown should be treated as
> > UC (and quite likely specifically in a case like the one Olaf reports here,
> > as the offending memory range pretty likely is other than normal RAM).
> > What I'd accept as a patch would be the addition of a command line
> > option enforcing the mapping of such unknown cacheability areas with
> > a certain caching type (default then being UC).
> 
> If I can find some copious free time, I will see about making this happen.

I actually did cobble a patch like this, but it is based on Daniel's Multibootv2
so it won't apply cleany. See attached patchset with various 'work-arounds'.

Jan if you are OK with them (well the 'idea' behind them) I can refresh
it against staging and post them?
>From 33badf8e314251e9d9c3b768c0b7a34b225aa45c Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
Date: Tue, 3 Feb 2015 11:56:33 -0500
Subject: [PATCH 1/3] EFI/early: Implement /noexit to not ExitBootServices

The /noexitboot will inhibit Xen from calling ExitBootServices.
This allows on Lenovo ThinkPad x230 to use GetNextVariableName
in 1-1 mapping mode.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
---
 xen/arch/x86/efi/efi-boot.h |  2 +-
 xen/common/efi/boot.c       | 15 +++++++++++----
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index f50c10a..0fbc4de 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -676,7 +676,7 @@ void __init efi_multiboot2(EFI_HANDLE ImageHandle, 
EFI_SYSTEM_TABLE *SystemTable
     setup_efi_pci();
     efi_variables();
     efi_set_gop_mode(gop, gop_mode);
-    efi_exit_boot(ImageHandle, SystemTable);
+    efi_exit_boot(ImageHandle, SystemTable, 0);
 }
 
 /*
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index d1d06d7..2389a1a 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -86,7 +86,7 @@ static void efi_tables(void);
 static void setup_efi_pci(void);
 static void efi_variables(void);
 static void efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN 
gop_mode);
-static void efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable);
+static void efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable, int exit_boot_services);
 
 static const EFI_BOOT_SERVICES *__initdata efi_bs;
 static EFI_HANDLE __initdata efi_ih;
@@ -882,7 +882,7 @@ static void __init 
efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop
         efi_arch_video_init(gop, info_size, mode_info);
 }
 
-static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
+static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable, int exit_boot_services)
 {
     EFI_STATUS status;
     UINTN map_key;
@@ -906,7 +906,10 @@ static void __init efi_exit_boot(EFI_HANDLE ImageHandle, 
EFI_SYSTEM_TABLE *Syste
 
         efi_arch_pre_exit_boot();
 
-        status = efi_bs->ExitBootServices(ImageHandle, map_key);
+        if ( exit_boot_services )
+            status = efi_bs->ExitBootServices(ImageHandle, map_key);
+        else
+            status = 0;
         if ( status != EFI_INVALID_PARAMETER || retry )
             break;
     }
@@ -1023,6 +1026,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
     char *option_str;
     bool_t use_cfg_file;
     bool_t query_only = 0;
+    bool_t exit_boot_services = 1;
 
 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
     efi_platform = 1;
@@ -1065,6 +1069,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
                     base_video = 1;
                 else if ( wstrcmp(ptr + 1, L"query") == 0 )
                     query_only = 1;
+                else if ( wstrcmp(ptr + 1, L"noexit") == 0 )
+                    exit_boot_services = 0;
                 else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
                     cfg_file_name = ptr + 5;
                 else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
@@ -1076,6 +1082,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
                     PrintStr(L"-basevideo   retain current video mode\r\n");
                     PrintStr(L"-cfg=<file>  specify configuration file\r\n");
                     PrintStr(L"-query       GetNextVariableName up to 
five\r\n");
+                    PrintStr(L"-noexit      Don't call ExitBootServices\r\n");
                     PrintStr(L"-help, -?    display this help\r\n");
                     blexit(NULL);
                 }
@@ -1242,7 +1249,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
 
     efi_set_gop_mode(gop, gop_mode);
 
-    efi_exit_boot(ImageHandle, SystemTable);
+    efi_exit_boot(ImageHandle, SystemTable, exit_boot_services);
 
     efi_arch_post_exit_boot();
     for( ; ; ); /* not reached */
-- 
2.1.0

>From e3048d6500ace943c8ce6ee52e00ee832615b6ab Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
Date: Tue, 3 Feb 2015 15:55:13 -0500
Subject: [PATCH 2/3] EFI/early: Implement /map to map EfiBootServicesData and
 Code

Signed-off-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
---
 xen/arch/x86/efi/efi-boot.h | 12 +++++++++---
 xen/common/efi/boot.c       | 43 ++++++++++++++++++++++++++++++++++---------
 xen/common/efi/efi.h        |  2 +-
 xen/common/efi/runtime.c    |  1 +
 4 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 0fbc4de..346f273 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -159,7 +159,8 @@ static void __init 
efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
                                                void *map,
                                                UINTN map_size,
                                                UINTN desc_size,
-                                               UINT32 desc_ver)
+                                               UINT32 desc_ver,
+                                               UINT32 map_bootservices)
 {
     struct e820entry *e;
     unsigned int i;
@@ -177,9 +178,14 @@ static void __init 
efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
         default:
             type = E820_RESERVED;
             break;
-        case EfiConventionalMemory:
         case EfiBootServicesCode:
         case EfiBootServicesData:
+            if ( map_bootservices )
+            {
+                type = E820_RESERVED;
+                break;
+            }
+        case EfiConventionalMemory:
             if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
                  len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
                 cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
@@ -676,7 +682,7 @@ void __init efi_multiboot2(EFI_HANDLE ImageHandle, 
EFI_SYSTEM_TABLE *SystemTable
     setup_efi_pci();
     efi_variables();
     efi_set_gop_mode(gop, gop_mode);
-    efi_exit_boot(ImageHandle, SystemTable, 0);
+    efi_exit_boot(ImageHandle, SystemTable, 0, 0);
 }
 
 /*
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 2389a1a..ec98914 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -86,7 +86,7 @@ static void efi_tables(void);
 static void setup_efi_pci(void);
 static void efi_variables(void);
 static void efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN 
gop_mode);
-static void efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable, int exit_boot_services);
+static void efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable, int exit_boot_services, int map_bs);
 
 static const EFI_BOOT_SERVICES *__initdata efi_bs;
 static EFI_HANDLE __initdata efi_ih;
@@ -882,7 +882,7 @@ static void __init 
efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop
         efi_arch_video_init(gop, info_size, mode_info);
 }
 
-static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable, int exit_boot_services)
+static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable, int exit_boot_services, int map_bs)
 {
     EFI_STATUS status;
     UINTN map_key;
@@ -902,7 +902,7 @@ static void __init efi_exit_boot(EFI_HANDLE ImageHandle, 
EFI_SYSTEM_TABLE *Syste
             PrintErrMesg(L"Cannot obtain memory map", status);
 
         efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size,
-                                    efi_mdesc_size, mdesc_ver);
+                                    efi_mdesc_size, mdesc_ver, map_bs);
 
         efi_arch_pre_exit_boot();
 
@@ -924,6 +924,7 @@ static void __init efi_exit_boot(EFI_HANDLE ImageHandle, 
EFI_SYSTEM_TABLE *Syste
 #endif
     efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
     efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
+    efi_map = map_bs;
 }
 
 static int __init efi_getnextvariable(bool_t query_only)
@@ -1027,7 +1028,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
     bool_t use_cfg_file;
     bool_t query_only = 0;
     bool_t exit_boot_services = 1;
-
+    bool_t map_bs = 0;
 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
     efi_platform = 1;
     efi_loader = 1;
@@ -1071,6 +1072,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
                     query_only = 1;
                 else if ( wstrcmp(ptr + 1, L"noexit") == 0 )
                     exit_boot_services = 0;
+                else if ( wstrcmp(ptr + 1, L"map") == 0 )
+                    map_bs = 1;
                 else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
                     cfg_file_name = ptr + 5;
                 else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
@@ -1082,6 +1085,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
                     PrintStr(L"-basevideo   retain current video mode\r\n");
                     PrintStr(L"-cfg=<file>  specify configuration file\r\n");
                     PrintStr(L"-query       GetNextVariableName up to 
five\r\n");
+                    PrintStr(L"-map         map EfiBootServices Code and 
Data\r\n");
                     PrintStr(L"-noexit      Don't call ExitBootServices\r\n");
                     PrintStr(L"-help, -?    display this help\r\n");
                     blexit(NULL);
@@ -1249,7 +1253,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
 
     efi_set_gop_mode(gop, gop_mode);
 
-    efi_exit_boot(ImageHandle, SystemTable, exit_boot_services);
+    efi_exit_boot(ImageHandle, SystemTable, exit_boot_services, map_bs);
 
     efi_arch_post_exit_boot();
     for( ; ; ); /* not reached */
@@ -1325,20 +1329,30 @@ void __init efi_init_memory(void)
         return;
 #endif
 
-    printk(XENLOG_INFO "EFI memory map:\n");
+    printk(XENLOG_INFO "EFI memory map: %s\n", efi_map ? "(mapping 
BootServices)" : "");
     for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
     {
         EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
         u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
         unsigned long smfn, emfn;
         unsigned int prot = PAGE_HYPERVISOR;
+        unsigned int skip = 1;
 
         printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
                            " type=%u attr=%016" PRIx64 "\n",
                desc->PhysicalStart, desc->PhysicalStart + len - 1,
                desc->Type, desc->Attribute);
 
-        if ( !efi_rs_enable || !(desc->Attribute & EFI_MEMORY_RUNTIME) )
+        if ( desc->Attribute & EFI_MEMORY_RUNTIME )
+            skip = 0;
+
+        if ( desc->Type == 4 && desc->Attribute != 0 && efi_map )
+            skip = 0;
+
+        if ( desc->Type == 3 && desc->Attribute != 0 && efi_map )
+            skip = 0;
+
+        if ( !efi_rs_enable || skip )
         {
             printk(XENLOG_INFO " .. skipped!\n");
             continue;
@@ -1422,18 +1436,29 @@ void __init efi_init_memory(void)
 
     copy_mapping(0, max_page, ram_range_valid);
 
+    printk(XENLOG_INFO "Copying..\n");
     /* Insert non-RAM runtime mappings inside the direct map. */
     for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
     {
         const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
 
-        if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
+        if ( ((desc->Attribute & EFI_MEMORY_RUNTIME) ||
+             ((desc->Type == 3 && desc->Attribute != 0 && efi_map ) ||
+             (desc->Type == 4 && desc->Attribute != 0 && efi_map ))) &&
              desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
-             desc->VirtualStart != desc->PhysicalStart )
+             desc->VirtualStart != desc->PhysicalStart ) {
+
+            printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
+                           " type=%u attr=%016" PRIx64 "\n",
+               PFN_DOWN(desc->PhysicalStart),
+               PFN_UP(desc->PhysicalStart + (desc->NumberOfPages << 
EFI_PAGE_SHIFT)),
+               desc->Type, desc->Attribute);
+
             copy_mapping(PFN_DOWN(desc->PhysicalStart),
                          PFN_UP(desc->PhysicalStart +
                                 (desc->NumberOfPages << EFI_PAGE_SHIFT)),
                          rt_range_valid);
+            }
     }
 
     /* Insert non-RAM runtime mappings outside of the direct map. */
diff --git a/xen/common/efi/efi.h b/xen/common/efi/efi.h
index c557104..6267020 100644
--- a/xen/common/efi/efi.h
+++ b/xen/common/efi/efi.h
@@ -20,7 +20,7 @@ struct efi_pci_rom {
 extern unsigned int efi_num_ct;
 extern const EFI_CONFIGURATION_TABLE *efi_ct;
 
-extern unsigned int efi_version, efi_fw_revision;
+extern unsigned int efi_version, efi_fw_revision, efi_map;
 extern const CHAR16 *efi_fw_vendor;
 
 extern const EFI_RUNTIME_SERVICES *efi_rs;
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index 4ca25c2..e1709fd 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -27,6 +27,7 @@ const EFI_CONFIGURATION_TABLE *__read_mostly efi_ct;
 
 unsigned int __read_mostly efi_version;
 unsigned int __read_mostly efi_fw_revision;
+unsigned int __read_mostly efi_map;
 const CHAR16 *__read_mostly efi_fw_vendor;
 
 const EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
-- 
2.1.0

>From 9e7d26786c006f7fa5eb8165b4fad182f75f988e Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
Date: Tue, 3 Feb 2015 15:57:54 -0500
Subject: [PATCH 3/3] efi: Implement 'efi-attr-uc=1' Xen command line to map
 Runtime services with no attribute.

For example on Dell machines we see:

(XEN)  00000fed18000-00000fed19fff type=11 attr=8000000000000000
(XEN) Unknown cachability for MFNs 0xfed18-0xfed19

Lets allow them to be mapped as UC with said attribute.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com>
---
 xen/common/efi/boot.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index ec98914..724f75c 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -1264,6 +1264,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
*SystemTable)
 static bool_t __initdata efi_rs_enable = 1;
 boolean_param("efi-rs", efi_rs_enable);
 
+static bool_t __initdata efi_attr_uc = 1;
+boolean_param("efi-attr-uc", efi_attr_uc);
+
 #ifndef USE_SET_VIRTUAL_ADDRESS_MAP
 static __init void copy_mapping(unsigned long mfn, unsigned long end,
                                 bool_t (*is_valid)(unsigned long smfn,
@@ -1373,9 +1376,12 @@ void __init efi_init_memory(void)
             prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
         else
         {
-            printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
-                   smfn, emfn - 1);
-            continue;
+            printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx %s\n",
+                   smfn, emfn - 1, efi_attr_uc ? "assuming UC" : "");
+            if ( efi_attr_uc )
+                prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
+            else
+                continue;
         }
 
         if ( desc->Attribute & EFI_MEMORY_WP )
-- 
2.1.0

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to