All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/16] x86: multiboot2 protocol support
@ 2016-08-19 22:43 Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms Daniel Kiper
                   ` (16 more replies)
  0 siblings, 17 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Hi,

I am sending fifth version of multiboot2 protocol support for
legacy BIOS and EFI platforms. This patch series release contains
fixes for all known issues (many of them were found by Jan Beulich;
thanks a lot!).

The final goal is xen.efi binary file which could be loaded by EFI
loader, multiboot (v1) protocol (only on legacy BIOS platforms) and
multiboot2 protocol. This way we will have:
  - smaller Xen code base,
  - one code base for xen.gz and xen.efi,
  - one build method for xen.gz and xen.efi;
    xen.efi will be extracted from xen(-syms)
    file using objcopy or special custom tool,
  - xen.efi build will not so strongly depend
    on a given GCC and binutils version.

Here is short list of changes since v4:
  - changed patches: 01, 03, 04, 05, 09, 10, 11.

Patches 12-16 were reviewed by nobody last time.

This patch series was build with following tools:
  - gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
    and binutils 2.17-3+etch1,
  - gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
    and binutils 2.23.2-2.el6,
  - gcc version 4.7.2 (Debian 4.7.2-5)
    and binutils 2.22-8,
  - gcc version 5.1.1 20150618 (Red Hat 5.1.1-4) (GCC)
    and binutils 2.25-9.fc22.

I hope that features provided by this patch series will be included
in Xen 4.8 release in one way or another.

If you are not interested in this patch series at all please
drop me a line and I will remove you from distribution list.

Daniel

PS FYI, I will be on vacation next week. It will be nice if
   you review my patches during that time.

 .gitignore                        |    5 +-
 xen/arch/x86/Makefile             |    8 +-
 xen/arch/x86/Rules.mk             |    4 +
 xen/arch/x86/boot/Makefile        |   10 +-
 xen/arch/x86/boot/build32.lds     |   52 ++++++++
 xen/arch/x86/boot/build32.mk      |   18 ++-
 xen/arch/x86/boot/cmdline.S       |  367 -----------------------------------------------------
 xen/arch/x86/boot/cmdline.c       |  376 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/boot/edd.S           |    3 -
 xen/arch/x86/boot/head.S          |  568 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 xen/arch/x86/boot/reloc.c         |  249 ++++++++++++++++++++++++++++--------
 xen/arch/x86/boot/trampoline.S    |   22 +++-
 xen/arch/x86/boot/video.S         |    7 -
 xen/arch/x86/boot/wakeup.S        |    4 +-
 xen/arch/x86/boot/x86_64.S        |   51 +++-----
 xen/arch/x86/dmi_scan.c           |    4 +-
 xen/arch/x86/domain_page.c        |    2 +-
 xen/arch/x86/efi/Makefile         |   11 +-
 xen/arch/x86/efi/efi-boot.h       |  108 ++++++++++++++--
 xen/arch/x86/efi/stub.c           |   33 ++++-
 xen/arch/x86/mpparse.c            |    4 +-
 xen/arch/x86/setup.c              |   48 +++----
 xen/arch/x86/shutdown.c           |    5 +-
 xen/arch/x86/time.c               |    2 +-
 xen/arch/x86/x86_64/asm-offsets.c |   12 ++
 xen/arch/x86/xen.lds.S            |   16 ++-
 xen/common/efi/boot.c             |   31 ++++-
 xen/common/efi/runtime.c          |   21 ++-
 xen/drivers/acpi/osl.c            |    2 +-
 xen/include/asm-x86/config.h      |    1 +
 xen/include/asm-x86/page.h        |    2 +-
 xen/include/xen/efi.h             |   10 +-
 xen/include/xen/multiboot2.h      |  182 ++++++++++++++++++++++++++
 33 files changed, 1624 insertions(+), 614 deletions(-)

Daniel Kiper (16):
      x86: allow EFI reboot method neither on EFI platforms...
      x86/boot: remove multiboot1_header_end from symbol table
      x86/boot: create *.lnk files with linker script
      x86/boot/reloc: reduce assembly usage as much as possible
      x86/boot: call reloc() using stdcall calling convention
      x86/boot/reloc: create generic alloc and copy functions
      x86/boot: use %ecx instead of %eax
      x86/boot/reloc: rename some variables and rearrange code a bit
      x86: add multiboot2 protocol support
      efi: create efi_enabled()
      efi: build xen.gz with EFI code
      x86/efi: create new early memory allocator
      x86: add multiboot2 protocol support for EFI platforms
      x86/boot: implement early command line parser in C
      x86: make Xen early boot code relocatable
      x86: add multiboot2 protocol support for relocatable images


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

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

* [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms...
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 11:19   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table Daniel Kiper
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

..nor EFI platforms with runtime services enabled.

Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v5 - suggestions/fixes:
   - fix build error
     (suggested by Jan Beulich),
   - improve commit message.
---
 xen/arch/x86/shutdown.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c
index 0e1499d..972e20b 100644
--- a/xen/arch/x86/shutdown.c
+++ b/xen/arch/x86/shutdown.c
@@ -80,6 +80,9 @@ static void __init set_reboot_type(char *str)
             break;
         str++;
     }
+
+    if ( reboot_type == BOOT_EFI && !efi_enabled )
+        reboot_type = BOOT_INVALID;
 }
 custom_param("reboot", set_reboot_type);
 
-- 
1.7.10.4


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

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

* [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 11:21   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 03/16] x86/boot: create *.lnk files with linker script Daniel Kiper
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Its visibility is not needed and just pollute symbol table.

Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 xen/arch/x86/boot/head.S |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 85770e8..e34351c 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -32,7 +32,7 @@ multiboot1_header_start:       /*** MULTIBOOT1 HEADER ****/
         .long   MULTIBOOT_HEADER_FLAGS
         /* Checksum: must be the negated sum of the first two fields. */
         .long   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
-multiboot1_header_end:
+.Lmultiboot1_header_end:
 
         .section .init.rodata, "a", @progbits
         .align 4
-- 
1.7.10.4


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

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

* [PATCH v5 03/16] x86/boot: create *.lnk files with linker script
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 11:28   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 04/16] x86/boot/reloc: reduce assembly usage as much as possible Daniel Kiper
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Newer GCC (e.g. gcc version 5.1.1 20150618 (Red Hat 5.1.1-4) (GCC)) does
some code optimizations by creating data sections (e.g. jump addresses
for C switch/case are calculated using data in .rodata section). This
thing is not accepted by *.lnk build recipe which requires that only .text
section lives in output. Potentially we can inhibit this GCC behavior by
using special options, e.g. -fno-tree-switch-conversion. However, this
does not guarantee that in the future new similar optimizations or anything
else which creates not accepted sections will not break our build recipes
again. I do not mention that probably this is not good idea to just disable
random optimizations. So, take over full control on *.lnk linking process
by using linker script and merge all text and data sections into one
.text section.

Additionally, remove .got.plt section which is not used in our final code.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v5 - suggestions/fixes:
   - merge __ALL__ text and data sections into one .text section
     (suggested by Jan Beulich),
   - check that .got.plt size is correct
     (suggested by Jan Beulich),
   - reformat comments
     (suggested by Jan Beulich),
   - improve commit message.

v4 - suggestions/fixes:
   - remove my name from copyright (Oracle requirement)
     (suggested by Konrad Rzeszutek Wilk),
   - improve comments,
     (suggested by Jan Beulich),
   - improve commit message
     (suggested by Jan Beulich).
---
 xen/arch/x86/boot/build32.lds |   52 +++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/boot/build32.mk  |   16 +++++++------
 2 files changed, 61 insertions(+), 7 deletions(-)
 create mode 100644 xen/arch/x86/boot/build32.lds

diff --git a/xen/arch/x86/boot/build32.lds b/xen/arch/x86/boot/build32.lds
new file mode 100644
index 0000000..da35aee
--- /dev/null
+++ b/xen/arch/x86/boot/build32.lds
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/>.
+ */
+
+ENTRY(_start)
+
+SECTIONS
+{
+  /* Merge code and data into one section. */
+  .text : {
+        *(.text)
+        *(.text.*)
+        *(.data)
+        *(.data.*)
+        *(.rodata)
+        *(.rodata.*)
+        *(.bss)
+        *(.bss.*)
+  }
+
+  /DISCARD/ : {
+        /*
+         * PIC/PIE executable contains .got.plt section even if it is not linked
+         * with dynamic libraries. In such case it is just placeholder for
+         * _GLOBAL_OFFSET_TABLE_ symbol and .PLT0. .PLT0 is filled by dynamic
+         * linker and our code is not supposed to be loaded by dynamic linker.
+         * So, from our point of view .PLT0 is unused. This means that there is
+         * pretty good chance that we can safely drop .got.plt as a whole here.
+         * Sadly this is not true. _GLOBAL_OFFSET_TABLE_ is used as a reference
+         * for relative addressing (and only for that thing) and ld complains if
+         * we remove .got.plt section here because it cannot find required symbol.
+         * However, _GLOBAL_OFFSET_TABLE_ is no longer needed in final output.
+         * So, drop .got.plt section during conversion to plain binary format.
+         *
+         * Please check build32.mk for more details.
+         */
+        /* *(.got.plt) */
+  }
+}
diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk
index 4a7d388..39e6453 100644
--- a/xen/arch/x86/boot/build32.mk
+++ b/xen/arch/x86/boot/build32.mk
@@ -12,20 +12,22 @@ CFLAGS := $(filter-out -flto,$(CFLAGS))
 	(od -v -t x $< | tr -s ' ' | awk 'NR > 1 {print s} {s=$$0}' | \
 	sed 's/ /,0x/g' | sed 's/,0x$$//' | sed 's/^[0-9]*,/ .long /') >$@
 
+# Drop .got.plt during conversion to plain binary format.
+# Please check build32.lds for more details.
 %.bin: %.lnk
-	$(OBJCOPY) -O binary $< $@
-
-%.lnk: %.o
-	$(OBJDUMP) -h $< | sed -n '/[0-9]/{s,00*,0,g;p;}' |\
+	$(OBJDUMP) -h $< | sed -n '/[0-9]/{s,00*,0,g;p;}' | \
 		while read idx name sz rest; do \
 			case "$$name" in \
-			.data|.data.*|.rodata|.rodata.*|.bss|.bss.*) \
-				test $$sz != 0 || continue; \
+			.got.plt) \
+				test $$sz != 0c || continue; \
 				echo "Error: non-empty $$name: 0x$$sz" >&2; \
 				exit $$(expr $$idx + 1);; \
 			esac; \
 		done
-	$(LD) $(LDFLAGS_DIRECT) -N -Ttext 0 -o $@ $<
+	$(OBJCOPY) -O binary -R .got.plt $< $@
+
+%.lnk: %.o
+	$(LD) $(LDFLAGS_DIRECT) -N -T build32.lds -o $@ $<
 
 %.o: %.c
 	$(CC) $(CFLAGS) -c -fpic $< -o $@
-- 
1.7.10.4


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

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

* [PATCH v5 04/16] x86/boot/reloc: reduce assembly usage as much as possible
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (2 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 03/16] x86/boot: create *.lnk files with linker script Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 11:29   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 05/16] x86/boot: call reloc() using stdcall calling convention Daniel Kiper
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

..to increase code readability and ease its maintenance.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v5 - suggestions/fixes:
   - improve commit message
     (suggested by Jan Beulich).
---
 xen/arch/x86/boot/reloc.c |   52 ++++++++++++++++++++++-----------------------
 1 file changed, 25 insertions(+), 27 deletions(-)

diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 63045c0..9ae42e2 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -15,39 +15,33 @@ asm (
     "    .text                         \n"
     "    .globl _start                 \n"
     "_start:                           \n"
-    "    call 1f                       \n"
-    "1:  pop  %ebx                     \n"
-    "    mov  %eax,alloc-1b(%ebx)      \n"
-    "    jmp  reloc                    \n"
-    );
-
-/*
- * This is our data. Because the code must be relocatable, no BSS is
- * allowed. All data is accessed PC-relative with inline assembly.
- */
-asm (
-    "alloc:                            \n"
-    "    .long 0                       \n"
+    "    push %eax                     \n"
+    "    push 0x8(%esp)                \n"
+    "    call reloc                    \n"
+    "    ret  $0x4                     \n"
     );
 
 typedef unsigned int u32;
 #include "../../../include/xen/multiboot.h"
 
+#define __stdcall	__attribute__((__stdcall__))
+
+#define ALIGN_UP(arg, align) \
+                (((arg) + (align) - 1) & ~((typeof(arg))(align) - 1))
+
+static u32 alloc;
+
 static void *reloc_mbi_struct(void *old, unsigned int bytes)
 {
     void *new;
-    asm(
-    "    call 1f                      \n"
-    "1:  pop  %%edx                   \n"
-    "    mov  alloc-1b(%%edx),%0      \n"
-    "    sub  %1,%0                   \n"
-    "    and  $~15,%0                 \n"
-    "    mov  %0,alloc-1b(%%edx)      \n"
-    "    mov  %0,%%edi                \n"
-    "    rep  movsb                   \n"
-       : "=&r" (new), "+c" (bytes), "+S" (old)
-	: : "edx", "edi", "memory");
-    return new;
+
+    alloc -= ALIGN_UP(bytes, 16);
+    new = (void *)alloc;
+
+    while ( bytes-- )
+        *(char *)new++ = *(char *)old++;
+
+    return (void *)alloc;
 }
 
 static char *reloc_mbi_string(char *old)
@@ -58,11 +52,15 @@ static char *reloc_mbi_string(char *old)
     return reloc_mbi_struct(old, p - old + 1);
 }
 
-multiboot_info_t *reloc(multiboot_info_t *mbi_old)
+multiboot_info_t __stdcall *reloc(multiboot_info_t *mbi_old, u32 trampoline)
 {
-    multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi));
+    multiboot_info_t *mbi;
     int i;
 
+    alloc = trampoline;
+
+    mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi));
+
     if ( mbi->flags & MBI_CMDLINE )
         mbi->cmdline = (u32)reloc_mbi_string((char *)mbi->cmdline);
 
-- 
1.7.10.4


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

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

* [PATCH v5 05/16] x86/boot: call reloc() using stdcall calling convention
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (3 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 04/16] x86/boot/reloc: reduce assembly usage as much as possible Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions Daniel Kiper
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Current reloc() call method makes confusion and does not scale well
for more arguments. And subsequent patch adding multiboot2 protocol
support have to pass 3 arguments instead of 2. Hence, move reloc()
call to stdcall calling convention. One may argue that we should use
standard cdecl calling convention. However, stdcall is better here
than cdecl because we do not need to remove "manually" arguments from
stack in xen/arch/x86/boot/head.S assembly file.

Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
v5 - suggestions/fixes:
   - improve commit message
     (suggested by Jan Beulich).

v4 - suggestions/fixes:
   - move to stdcall calling convention
     (suggested by Jan Beulich).

v3 - suggestions/fixes:
   - simplify assembly in xen/arch/x86/boot/reloc.c file
     (suggested by Jan Beulich),
   - reorder arguments for reloc() call from xen/arch/x86/boot/head.S
     (suggested by Jan Beulich),
   - improve commit message
     (suggested by Jan Beulich).
---
 xen/arch/x86/boot/head.S  |    3 ++-
 xen/arch/x86/boot/reloc.c |   11 ++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index e34351c..7e5ae12 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -119,7 +119,8 @@ __start:
 
         /* Save the Multiboot info struct (after relocation) for later use. */
         mov     $sym_phys(cpu0_stack)+1024,%esp
-        push    %ebx
+        push    %eax                /* Boot trampoline address. */
+        push    %ebx                /* Multiboot information address. */
         call    reloc
         mov     %eax,sym_phys(multiboot_ptr)
 
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 9ae42e2..28c6cea 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -10,15 +10,16 @@
  *    Keir Fraser <keir@xen.org>
  */
 
-/* entered with %eax = BOOT_TRAMPOLINE */
+/*
+ * This entry point is entered from xen/arch/x86/boot/head.S with:
+ *   - 0x4(%esp) = MULTIBOOT_INFORMATION_ADDRESS,
+ *   - 0x8(%esp) = BOOT_TRAMPOLINE_ADDRESS.
+ */
 asm (
     "    .text                         \n"
     "    .globl _start                 \n"
     "_start:                           \n"
-    "    push %eax                     \n"
-    "    push 0x8(%esp)                \n"
-    "    call reloc                    \n"
-    "    ret  $0x4                     \n"
+    "    jmp  reloc                    \n"
     );
 
 typedef unsigned int u32;
-- 
1.7.10.4


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

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

* [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (4 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 05/16] x86/boot: call reloc() using stdcall calling convention Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 11:34   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 07/16] x86/boot: use %ecx instead of %eax Daniel Kiper
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Create generic alloc and copy functions. We need
separate tools for memory allocation and copy to
provide multiboot2 protocol support.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v4 - suggestions/fixes:
   - avoid assembly usage.

v3 - suggestions/fixes:
   - use "g" constraint instead of "r" for alloc_mem() bytes argument
     (suggested by Jan Beulich).

v2 - suggestions/fixes:
   - generalize new functions names
     (suggested by Jan Beulich),
   - reduce number of casts
     (suggested by Jan Beulich).
---
 xen/arch/x86/boot/reloc.c |   51 ++++++++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 28c6cea..21b1f32 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -32,60 +32,69 @@ typedef unsigned int u32;
 
 static u32 alloc;
 
-static void *reloc_mbi_struct(void *old, unsigned int bytes)
+static u32 alloc_mem(u32 bytes)
 {
-    void *new;
+    return alloc -= ALIGN_UP(bytes, 16);
+}
 
-    alloc -= ALIGN_UP(bytes, 16);
-    new = (void *)alloc;
+static u32 copy_mem(u32 src, u32 bytes)
+{
+    u32 dst, dst_ret;
+
+    dst = alloc_mem(bytes);
+    dst_ret = dst;
 
     while ( bytes-- )
-        *(char *)new++ = *(char *)old++;
+        *(char *)dst++ = *(char *)src++;
 
-    return (void *)alloc;
+    return dst_ret;
 }
 
-static char *reloc_mbi_string(char *old)
+static u32 copy_string(u32 src)
 {
-    char *p;
-    for ( p = old; *p != '\0'; p++ )
+    u32 p;
+
+    if ( src == 0 )
+        return 0;
+
+    for ( p = src; *(char *)p != '\0'; p++ )
         continue;
-    return reloc_mbi_struct(old, p - old + 1);
+
+    return copy_mem(src, p - src + 1);
 }
 
-multiboot_info_t __stdcall *reloc(multiboot_info_t *mbi_old, u32 trampoline)
+multiboot_info_t __stdcall *reloc(u32 mbi_old, u32 trampoline)
 {
     multiboot_info_t *mbi;
     int i;
 
     alloc = trampoline;
 
-    mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi));
+    mbi = (multiboot_info_t *)copy_mem(mbi_old, sizeof(*mbi));
 
     if ( mbi->flags & MBI_CMDLINE )
-        mbi->cmdline = (u32)reloc_mbi_string((char *)mbi->cmdline);
+        mbi->cmdline = copy_string(mbi->cmdline);
 
     if ( mbi->flags & MBI_MODULES )
     {
-        module_t *mods = reloc_mbi_struct(
-            (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+        module_t *mods;
 
-        mbi->mods_addr = (u32)mods;
+        mbi->mods_addr = copy_mem(mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+
+        mods = (module_t *)mbi->mods_addr;
 
         for ( i = 0; i < mbi->mods_count; i++ )
         {
             if ( mods[i].string )
-                mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
+                mods[i].string = copy_string(mods[i].string);
         }
     }
 
     if ( mbi->flags & MBI_MEMMAP )
-        mbi->mmap_addr = (u32)reloc_mbi_struct(
-            (memory_map_t *)mbi->mmap_addr, mbi->mmap_length);
+        mbi->mmap_addr = copy_mem(mbi->mmap_addr, mbi->mmap_length);
 
     if ( mbi->flags & MBI_LOADERNAME )
-        mbi->boot_loader_name = (u32)reloc_mbi_string(
-            (char *)mbi->boot_loader_name);
+        mbi->boot_loader_name = copy_string(mbi->boot_loader_name);
 
     /* Mask features we don't understand or don't relocate. */
     mbi->flags &= (MBI_MEMLIMITS |
-- 
1.7.10.4


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

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

* [PATCH v5 07/16] x86/boot: use %ecx instead of %eax
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (5 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 08/16] x86/boot/reloc: rename some variables and rearrange code a bit Daniel Kiper
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Use %ecx instead of %eax to store low memory upper limit from EBDA.
This way we do not wipe multiboot protocol identifier. It is needed
in reloc() to differentiate between multiboot (v1) and
multiboot2 protocol.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 xen/arch/x86/boot/head.S |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 7e5ae12..ffafcb5 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -87,14 +87,14 @@ __start:
         jne     not_multiboot
 
         /* Set up trampoline segment 64k below EBDA */
-        movzwl  0x40e,%eax          /* EBDA segment */
-        cmp     $0xa000,%eax        /* sanity check (high) */
+        movzwl  0x40e,%ecx          /* EBDA segment */
+        cmp     $0xa000,%ecx        /* sanity check (high) */
         jae     0f
-        cmp     $0x4000,%eax        /* sanity check (low) */
+        cmp     $0x4000,%ecx        /* sanity check (low) */
         jae     1f
 0:
-        movzwl  0x413,%eax          /* use base memory size on failure */
-        shl     $10-4,%eax
+        movzwl  0x413,%ecx          /* use base memory size on failure */
+        shl     $10-4,%ecx
 1:
         /*
          * Compare the value in the BDA with the information from the
@@ -106,20 +106,20 @@ __start:
         cmp     $0x100,%edx         /* is the multiboot value too small? */
         jb      2f                  /* if so, do not use it */
         shl     $10-4,%edx
-        cmp     %eax,%edx           /* compare with BDA value */
-        cmovb   %edx,%eax           /* and use the smaller */
+        cmp     %ecx,%edx           /* compare with BDA value */
+        cmovb   %edx,%ecx           /* and use the smaller */
 
 2:      /* Reserve 64kb for the trampoline */
-        sub     $0x1000,%eax
+        sub     $0x1000,%ecx
 
         /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
-        xor     %al, %al
-        shl     $4, %eax
-        mov     %eax,sym_phys(trampoline_phys)
+        xor     %cl, %cl
+        shl     $4, %ecx
+        mov     %ecx,sym_phys(trampoline_phys)
 
         /* Save the Multiboot info struct (after relocation) for later use. */
         mov     $sym_phys(cpu0_stack)+1024,%esp
-        push    %eax                /* Boot trampoline address. */
+        push    %ecx                /* Boot trampoline address. */
         push    %ebx                /* Multiboot information address. */
         call    reloc
         mov     %eax,sym_phys(multiboot_ptr)
-- 
1.7.10.4


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

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

* [PATCH v5 08/16] x86/boot/reloc: rename some variables and rearrange code a bit
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (6 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 07/16] x86/boot: use %ecx instead of %eax Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-19 22:43 ` [PATCH v5 09/16] x86: add multiboot2 protocol support Daniel Kiper
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Replace mbi with mbi_out and mbi_old with mbi_in and rearrange code
a bit to make it more readable. Additionally, this way multiboot (v1)
protocol implementation and future multiboot2 protocol implementation
will use the same variable naming convention.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
v4 - suggestions/fixes:
   - move to stdcall calling convention.

v3 - suggestions/fixes:
   - improve commit message
     (suggested by Konrad Rzeszutek Wilk).

v2 - suggestions/fixes:
   - extract this change from main mutliboot2
     protocol implementation
     (suggested by Jan Beulich).
---
 xen/arch/x86/boot/reloc.c |   39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 21b1f32..dc6a435 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -63,45 +63,46 @@ static u32 copy_string(u32 src)
     return copy_mem(src, p - src + 1);
 }
 
-multiboot_info_t __stdcall *reloc(u32 mbi_old, u32 trampoline)
+multiboot_info_t __stdcall *reloc(u32 mbi_in, u32 trampoline)
 {
-    multiboot_info_t *mbi;
     int i;
+    multiboot_info_t *mbi_out;
 
     alloc = trampoline;
 
-    mbi = (multiboot_info_t *)copy_mem(mbi_old, sizeof(*mbi));
+    mbi_out = (multiboot_info_t *)copy_mem(mbi_in, sizeof(*mbi_out));
 
-    if ( mbi->flags & MBI_CMDLINE )
-        mbi->cmdline = copy_string(mbi->cmdline);
+    if ( mbi_out->flags & MBI_CMDLINE )
+        mbi_out->cmdline = copy_string(mbi_out->cmdline);
 
-    if ( mbi->flags & MBI_MODULES )
+    if ( mbi_out->flags & MBI_MODULES )
     {
         module_t *mods;
 
-        mbi->mods_addr = copy_mem(mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+        mbi_out->mods_addr = copy_mem(mbi_out->mods_addr,
+                                      mbi_out->mods_count * sizeof(module_t));
 
-        mods = (module_t *)mbi->mods_addr;
+        mods = (module_t *)mbi_out->mods_addr;
 
-        for ( i = 0; i < mbi->mods_count; i++ )
+        for ( i = 0; i < mbi_out->mods_count; i++ )
         {
             if ( mods[i].string )
                 mods[i].string = copy_string(mods[i].string);
         }
     }
 
-    if ( mbi->flags & MBI_MEMMAP )
-        mbi->mmap_addr = copy_mem(mbi->mmap_addr, mbi->mmap_length);
+    if ( mbi_out->flags & MBI_MEMMAP )
+        mbi_out->mmap_addr = copy_mem(mbi_out->mmap_addr, mbi_out->mmap_length);
 
-    if ( mbi->flags & MBI_LOADERNAME )
-        mbi->boot_loader_name = copy_string(mbi->boot_loader_name);
+    if ( mbi_out->flags & MBI_LOADERNAME )
+        mbi_out->boot_loader_name = copy_string(mbi_out->boot_loader_name);
 
     /* Mask features we don't understand or don't relocate. */
-    mbi->flags &= (MBI_MEMLIMITS |
-                   MBI_CMDLINE |
-                   MBI_MODULES |
-                   MBI_MEMMAP |
-                   MBI_LOADERNAME);
+    mbi_out->flags &= (MBI_MEMLIMITS |
+                       MBI_CMDLINE |
+                       MBI_MODULES |
+                       MBI_MEMMAP |
+                       MBI_LOADERNAME);
 
-    return mbi;
+    return mbi_out;
 }
-- 
1.7.10.4


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

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

* [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (7 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 08/16] x86/boot/reloc: rename some variables and rearrange code a bit Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 11:50   ` Jan Beulich
  2016-08-31 20:18   ` Andrew Cooper
  2016-08-19 22:43 ` [PATCH v5 10/16] efi: create efi_enabled() Daniel Kiper
                   ` (7 subsequent siblings)
  16 siblings, 2 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Add multiboot2 protocol support. Alter min memory limit handling as we
now may not find it from either multiboot (v1) or multiboot2.

This way we are laying the foundation for EFI + GRUB2 + Xen development.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v5 - suggestions/fixes:
   - check multiboot2_tag_mmap_t.entry_size before
     multiboot2_tag_mmap_t.entries[] use
     (suggested by Jan Beulich),
   - properly index multiboot2_tag_mmap_t.entries[]
     (suggested by Jan Beulich),
   - use "type name[]" instad of "type name[0]"
     in xen/include/xen/multiboot2.h
     (suggested by Jan Beulich),
   - remove unneeded comment
     (suggested by Jan Beulich).

v4 - suggestions/fixes:
   - avoid assembly usage in xen/arch/x86/boot/reloc.c,
   - fix boundary check issue and optimize
     for() loops in mbi2_mbi(),
   - move to stdcall calling convention,
   - remove unneeded typeof() from ALIGN_UP() macro
     (suggested by Jan Beulich),
   - add and use NULL definition in xen/arch/x86/boot/reloc.c
     (suggested by Jan Beulich),
   - do not read data beyond the end of multiboot2
     information in xen/arch/x86/boot/head.S
     (suggested by Jan Beulich),
   - add :req to some .macro arguments
     (suggested by Jan Beulich),
   - use cmovcc if possible,
   - add .L to multiboot2_header_end label
     (suggested by Jan Beulich),
   - add .L to multiboot2_proto label
     (suggested by Jan Beulich),
   - improve label names
     (suggested by Jan Beulich).

v3 - suggestions/fixes:
   - reorder reloc() arguments
     (suggested by Jan Beulich),
   - remove .L from multiboot2 header labels
     (suggested by Andrew Cooper, Jan Beulich and Konrad Rzeszutek Wilk),
   - take into account alignment when skipping multiboot2 fixed part
     (suggested by Konrad Rzeszutek Wilk),
   - create modules data if modules count != 0
     (suggested by Jan Beulich),
   - improve macros
     (suggested by Jan Beulich),
   - reduce number of casts
     (suggested by Jan Beulich),
   - use const if possible
     (suggested by Jan Beulich),
   - drop static and __used__ attribute from reloc()
     (suggested by Jan Beulich),
   - remove isolated/stray __packed attribute from
     multiboot2_memory_map_t type definition
     (suggested by Jan Beulich),
   - reformat xen/include/xen/multiboot2.h
     (suggested by Konrad Rzeszutek Wilk),
   - improve comments
     (suggested by Konrad Rzeszutek Wilk),
   - remove hard tabs
     (suggested by Jan Beulich and Konrad Rzeszutek Wilk).

v2 - suggestions/fixes:
   - generate multiboot2 header using macros
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Jan Beulich),
   - simplify assembly in xen/arch/x86/boot/head.S
     (suggested by Jan Beulich),
   - do not include include/xen/compiler.h
     in xen/arch/x86/boot/reloc.c
     (suggested by Jan Beulich),
   - do not read data beyond the end of multiboot2 information
     (suggested by Jan Beulich).

v2 - not fixed yet:
   - dynamic dependency generation for xen/arch/x86/boot/reloc.S;
     this requires more work; I am not sure that it pays because
     potential patch requires more changes than addition of just
     multiboot2.h to Makefile
     (suggested by Jan Beulich),
   - isolated/stray __packed attribute usage for multiboot2_memory_map_t
     (suggested by Jan Beulich).
---
 xen/arch/x86/boot/Makefile        |    3 +-
 xen/arch/x86/boot/head.S          |  107 ++++++++++++++++++++++-
 xen/arch/x86/boot/reloc.c         |  144 +++++++++++++++++++++++++++++--
 xen/arch/x86/x86_64/asm-offsets.c |    9 ++
 xen/include/xen/multiboot2.h      |  169 +++++++++++++++++++++++++++++++++++++
 5 files changed, 422 insertions(+), 10 deletions(-)
 create mode 100644 xen/include/xen/multiboot2.h

diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index 5fdb5ae..06893d8 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1,6 +1,7 @@
 obj-bin-y += head.o
 
-RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h
+RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h \
+	     $(BASEDIR)/include/xen/multiboot2.h
 
 head.o: reloc.S
 
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index ffafcb5..5e61854 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -1,5 +1,6 @@
 #include <xen/config.h>
 #include <xen/multiboot.h>
+#include <xen/multiboot2.h>
 #include <public/xen.h>
 #include <asm/asm_defns.h>
 #include <asm/desc.h>
@@ -19,6 +20,28 @@
 #define BOOT_PSEUDORM_CS 0x0020
 #define BOOT_PSEUDORM_DS 0x0028
 
+#define MB2_HT(name)      (MULTIBOOT2_HEADER_TAG_##name)
+#define MB2_TT(name)      (MULTIBOOT2_TAG_TYPE_##name)
+
+        .macro mb2ht_args arg:req, args:vararg
+        .long \arg
+        .ifnb \args
+        mb2ht_args \args
+        .endif
+        .endm
+
+        .macro mb2ht_init type:req, req:req, args:vararg
+        .align MULTIBOOT2_TAG_ALIGN
+.Lmb2ht_init_start\@:
+        .short \type
+        .short \req
+        .long .Lmb2ht_init_end\@ - .Lmb2ht_init_start\@
+        .ifnb \args
+        mb2ht_args \args
+        .endif
+.Lmb2ht_init_end\@:
+        .endm
+
 ENTRY(start)
         jmp     __start
 
@@ -34,6 +57,42 @@ multiboot1_header_start:       /*** MULTIBOOT1 HEADER ****/
         .long   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
 .Lmultiboot1_header_end:
 
+/*** MULTIBOOT2 HEADER ****/
+/* Some ideas are taken from grub-2.00/grub-core/tests/boot/kernel-i386.S file. */
+        .align  MULTIBOOT2_HEADER_ALIGN
+
+multiboot2_header_start:
+        /* Magic number indicating a Multiboot2 header. */
+        .long   MULTIBOOT2_HEADER_MAGIC
+        /* Architecture: i386. */
+        .long   MULTIBOOT2_ARCHITECTURE_I386
+        /* Multiboot2 header length. */
+        .long   .Lmultiboot2_header_end - multiboot2_header_start
+        /* Multiboot2 header checksum. */
+        .long   -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 + \
+                        (.Lmultiboot2_header_end - multiboot2_header_start))
+
+        /* Multiboot2 information request tag. */
+        mb2ht_init MB2_HT(INFORMATION_REQUEST), MB2_HT(REQUIRED), \
+                   MB2_TT(BASIC_MEMINFO), MB2_TT(MMAP)
+
+        /* Align modules at page boundry. */
+        mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
+
+        /* Console flags tag. */
+        mb2ht_init MB2_HT(CONSOLE_FLAGS), MB2_HT(OPTIONAL), \
+                   MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
+
+        /* Framebuffer tag. */
+        mb2ht_init MB2_HT(FRAMEBUFFER), MB2_HT(OPTIONAL), \
+                   0, /* Number of the columns - no preference. */ \
+                   0, /* Number of the lines - no preference. */ \
+                   0  /* Number of bits per pixel - no preference. */
+
+        /* Multiboot2 header end tag. */
+        mb2ht_init MB2_HT(END), MB2_HT(REQUIRED)
+.Lmultiboot2_header_end:
+
         .section .init.rodata, "a", @progbits
         .align 4
 
@@ -82,10 +141,52 @@ __start:
         mov     %ecx,%es
         mov     %ecx,%ss
 
-        /* Check for Multiboot bootloader */
+        /* Bootloaders may set multiboot{1,2}.mem_lower to a nonzero value. */
+        xor     %edx,%edx
+
+        /* Check for Multiboot2 bootloader. */
+        cmp     $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
+        je      .Lmultiboot2_proto
+
+        /* Check for Multiboot bootloader. */
         cmp     $MULTIBOOT_BOOTLOADER_MAGIC,%eax
         jne     not_multiboot
 
+        /* Get mem_lower from Multiboot information. */
+        testb   $MBI_MEMLIMITS,MB_flags(%ebx)
+
+        /* Not available? BDA value will be fine. */
+        cmovnz  MB_mem_lower(%ebx),%edx
+        jmp     trampoline_setup
+
+.Lmultiboot2_proto:
+        /* Skip Multiboot2 information fixed part. */
+        lea     (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%ebx),%ecx
+        and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
+
+0:
+        /* Check Multiboot2 information total size. */
+        mov     %ecx,%edi
+        sub     %ebx,%edi
+        cmp     %edi,MB2_fixed_total_size(%ebx)
+        jbe     trampoline_setup
+
+        /* Get mem_lower from Multiboot2 information. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,MB2_tag_type(%ecx)
+        cmove   MB2_mem_lower(%ecx),%edx
+        je      trampoline_setup
+
+        /* Is it the end of Multiboot2 information? */
+        cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%ecx)
+        je      trampoline_setup
+
+        /* Go to next Multiboot2 information tag. */
+        add     MB2_tag_size(%ecx),%ecx
+        add     $(MULTIBOOT2_TAG_ALIGN-1),%ecx
+        and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
+        jmp     0b
+
+trampoline_setup:
         /* Set up trampoline segment 64k below EBDA */
         movzwl  0x40e,%ecx          /* EBDA segment */
         cmp     $0xa000,%ecx        /* sanity check (high) */
@@ -100,9 +201,6 @@ __start:
          * Compare the value in the BDA with the information from the
          * multiboot structure (if available) and use the smallest.
          */
-        testb   $MBI_MEMLIMITS,(%ebx)
-        jz      2f                  /* not available? BDA value will be fine */
-        mov     MB_mem_lower(%ebx),%edx
         cmp     $0x100,%edx         /* is the multiboot value too small? */
         jb      2f                  /* if so, do not use it */
         shl     $10-4,%edx
@@ -121,6 +219,7 @@ __start:
         mov     $sym_phys(cpu0_stack)+1024,%esp
         push    %ecx                /* Boot trampoline address. */
         push    %ebx                /* Multiboot information address. */
+        push    %eax                /* Multiboot magic. */
         call    reloc
         mov     %eax,sym_phys(multiboot_ptr)
 
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index dc6a435..7553097 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -5,15 +5,18 @@
  * and modules. This is most easily done early with paging disabled.
  *
  * Copyright (c) 2009, Citrix Systems, Inc.
+ * Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
  *
  * Authors:
  *    Keir Fraser <keir@xen.org>
+ *    Daniel Kiper <daniel.kiper@oracle.com>
  */
 
 /*
  * This entry point is entered from xen/arch/x86/boot/head.S with:
- *   - 0x4(%esp) = MULTIBOOT_INFORMATION_ADDRESS,
- *   - 0x8(%esp) = BOOT_TRAMPOLINE_ADDRESS.
+ *   - 0x4(%esp) = MULTIBOOT_MAGIC,
+ *   - 0x8(%esp) = MULTIBOOT_INFORMATION_ADDRESS,
+ *   - 0xc(%esp) = BOOT_TRAMPOLINE_ADDRESS.
  */
 asm (
     "    .text                         \n"
@@ -23,13 +26,21 @@ asm (
     );
 
 typedef unsigned int u32;
+typedef unsigned long long u64;
+
 #include "../../../include/xen/multiboot.h"
+#include "../../../include/xen/multiboot2.h"
+
+#define NULL		((void *)0)
 
 #define __stdcall	__attribute__((__stdcall__))
 
 #define ALIGN_UP(arg, align) \
                 (((arg) + (align) - 1) & ~((typeof(arg))(align) - 1))
 
+#define get_mb2_data(tag, type, member)   (((multiboot2_tag_##type##_t *)(tag))->member)
+#define get_mb2_string(tag, type, member) ((u32)get_mb2_data(tag, type, member))
+
 static u32 alloc;
 
 static u32 alloc_mem(u32 bytes)
@@ -37,6 +48,12 @@ static u32 alloc_mem(u32 bytes)
     return alloc -= ALIGN_UP(bytes, 16);
 }
 
+static void zero_mem(u32 s, u32 bytes)
+{
+    while ( bytes-- )
+        *(char *)s++ = 0;
+}
+
 static u32 copy_mem(u32 src, u32 bytes)
 {
     u32 dst, dst_ret;
@@ -63,13 +80,11 @@ static u32 copy_string(u32 src)
     return copy_mem(src, p - src + 1);
 }
 
-multiboot_info_t __stdcall *reloc(u32 mbi_in, u32 trampoline)
+static multiboot_info_t *mbi_mbi(u32 mbi_in)
 {
     int i;
     multiboot_info_t *mbi_out;
 
-    alloc = trampoline;
-
     mbi_out = (multiboot_info_t *)copy_mem(mbi_in, sizeof(*mbi_out));
 
     if ( mbi_out->flags & MBI_CMDLINE )
@@ -106,3 +121,122 @@ multiboot_info_t __stdcall *reloc(u32 mbi_in, u32 trampoline)
 
     return mbi_out;
 }
+
+static multiboot_info_t *mbi2_mbi(u32 mbi_in)
+{
+    const multiboot2_memory_map_t *mmap_src;
+    const multiboot2_tag_t *tag;
+    module_t *mbi_out_mods = NULL;
+    memory_map_t *mmap_dst;
+    multiboot_info_t *mbi_out;
+    u32 ptr;
+    unsigned int i, mod_idx = 0;
+
+    ptr = alloc_mem(sizeof(*mbi_out));
+    mbi_out = (multiboot_info_t *)ptr;
+    zero_mem(ptr, sizeof(*mbi_out));
+
+    /* Skip Multiboot2 information fixed part. */
+    ptr = ALIGN_UP(mbi_in + sizeof(multiboot2_fixed_t), MULTIBOOT2_TAG_ALIGN);
+
+    /* Get the number of modules. */
+    for ( tag = (multiboot2_tag_t *)ptr;
+          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
+          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )
+        if ( tag->type == MULTIBOOT2_TAG_TYPE_MODULE )
+            ++mbi_out->mods_count;
+        else if ( tag->type == MULTIBOOT2_TAG_TYPE_END )
+            break;
+
+    if ( mbi_out->mods_count )
+    {
+        mbi_out->flags = MBI_MODULES;
+        mbi_out->mods_addr = alloc_mem(mbi_out->mods_count * sizeof(module_t));
+        mbi_out_mods = (module_t *)mbi_out->mods_addr;
+    }
+
+    /* Skip Multiboot2 information fixed part. */
+    ptr = ALIGN_UP(mbi_in + sizeof(multiboot2_fixed_t), MULTIBOOT2_TAG_ALIGN);
+
+    /* Put all needed data into mbi_out. */
+    for ( tag = (multiboot2_tag_t *)ptr;
+          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
+          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )
+        switch ( tag->type )
+        {
+        case MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME:
+            mbi_out->flags |= MBI_LOADERNAME;
+            ptr = get_mb2_string(tag, string, string);
+            mbi_out->boot_loader_name = copy_string(ptr);
+            break;
+
+        case MULTIBOOT2_TAG_TYPE_CMDLINE:
+            mbi_out->flags |= MBI_CMDLINE;
+            ptr = get_mb2_string(tag, string, string);
+            mbi_out->cmdline = copy_string(ptr);
+            break;
+
+        case MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO:
+            mbi_out->flags |= MBI_MEMLIMITS;
+            mbi_out->mem_lower = get_mb2_data(tag, basic_meminfo, mem_lower);
+            mbi_out->mem_upper = get_mb2_data(tag, basic_meminfo, mem_upper);
+            break;
+
+        case MULTIBOOT2_TAG_TYPE_MMAP:
+            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
+                break;
+
+            mbi_out->flags |= MBI_MEMMAP;
+            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
+            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
+            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
+            mbi_out->mmap_length *= sizeof(memory_map_t);
+
+            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);
+
+            mmap_src = get_mb2_data(tag, mmap, entries);
+            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;
+
+            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
+            {
+                /* Init size member properly. */
+                mmap_dst[i].size = sizeof(memory_map_t);
+                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
+                /* Now copy a given region data. */
+                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);
+                mmap_dst[i].base_addr_low = (u32)mmap_src->addr;
+                mmap_dst[i].base_addr_high = (u32)(mmap_src->addr >> 32);
+                mmap_dst[i].length_low = (u32)mmap_src->len;
+                mmap_dst[i].length_high = (u32)(mmap_src->len >> 32);
+                mmap_dst[i].type = mmap_src->type;
+            }
+            break;
+
+        case MULTIBOOT2_TAG_TYPE_MODULE:
+            mbi_out_mods[mod_idx].mod_start = get_mb2_data(tag, module, mod_start);
+            mbi_out_mods[mod_idx].mod_end = get_mb2_data(tag, module, mod_end);
+            ptr = get_mb2_string(tag, module, cmdline);
+            mbi_out_mods[mod_idx].string = copy_string(ptr);
+            mbi_out_mods[mod_idx].reserved = 0;
+            ++mod_idx;
+            break;
+
+        case MULTIBOOT2_TAG_TYPE_END:
+            return mbi_out;
+
+        default:
+            break;
+        }
+
+    return mbi_out;
+}
+
+multiboot_info_t __stdcall *reloc(u32 mb_magic, u32 mbi_in, u32 trampoline)
+{
+    alloc = trampoline;
+
+    if ( mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC )
+        return mbi2_mbi(mbi_in);
+    else
+        return mbi_mbi(mbi_in);
+}
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 05d2b85..0fc1c63 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -13,6 +13,7 @@
 #include <asm/fixmap.h>
 #include <asm/hardirq.h>
 #include <xen/multiboot.h>
+#include <xen/multiboot2.h>
 
 #define DEFINE(_sym, _val)                                                 \
     asm volatile ("\n.ascii\"==>#define " #_sym " %0 /* " #_val " */<==\"" \
@@ -168,6 +169,14 @@ void __dummy__(void)
     OFFSET(MB_flags, multiboot_info_t, flags);
     OFFSET(MB_cmdline, multiboot_info_t, cmdline);
     OFFSET(MB_mem_lower, multiboot_info_t, mem_lower);
+    BLANK();
+
+    DEFINE(MB2_fixed_sizeof, sizeof(multiboot2_fixed_t));
+    OFFSET(MB2_fixed_total_size, multiboot2_fixed_t, total_size);
+    OFFSET(MB2_tag_type, multiboot2_tag_t, type);
+    OFFSET(MB2_tag_size, multiboot2_tag_t, size);
+    OFFSET(MB2_mem_lower, multiboot2_tag_basic_meminfo_t, mem_lower);
+    BLANK();
 
     OFFSET(DOMAIN_vm_assist, struct domain, vm_assist);
 }
diff --git a/xen/include/xen/multiboot2.h b/xen/include/xen/multiboot2.h
new file mode 100644
index 0000000..8dd5800
--- /dev/null
+++ b/xen/include/xen/multiboot2.h
@@ -0,0 +1,169 @@
+/*
+ *  Copyright (C) 1999,2003,2007,2008,2009,2010  Free Software Foundation, Inc.
+ *
+ *  multiboot2.h - Multiboot 2 header file.
+ *
+ *  Based on grub-2.00/include/multiboot2.h file.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to
+ *  deal in the Software without restriction, including without limitation the
+ *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ *  sell copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MULTIBOOT2_H__
+#define __MULTIBOOT2_H__
+
+/* The magic field should contain this.  */
+#define MULTIBOOT2_HEADER_MAGIC				0xe85250d6
+
+/* This should be in %eax on x86 architecture.  */
+#define MULTIBOOT2_BOOTLOADER_MAGIC			0x36d76289
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MULTIBOOT2_SEARCH				32768
+
+/* Multiboot 2 header alignment. */
+#define MULTIBOOT2_HEADER_ALIGN				8
+
+/* Alignment of multiboot 2 modules.  */
+#define MULTIBOOT2_MOD_ALIGN				0x00001000
+
+/* Alignment of the multiboot 2 info structure.  */
+#define MULTIBOOT2_INFO_ALIGN				0x00000008
+
+/* Multiboot 2 architectures. */
+#define MULTIBOOT2_ARCHITECTURE_I386			0
+#define MULTIBOOT2_ARCHITECTURE_MIPS32			4
+
+/* Header tag types. */
+#define MULTIBOOT2_HEADER_TAG_END			0
+#define MULTIBOOT2_HEADER_TAG_INFORMATION_REQUEST	1
+#define MULTIBOOT2_HEADER_TAG_ADDRESS			2
+#define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS		3
+#define MULTIBOOT2_HEADER_TAG_CONSOLE_FLAGS		4
+#define MULTIBOOT2_HEADER_TAG_FRAMEBUFFER		5
+#define MULTIBOOT2_HEADER_TAG_MODULE_ALIGN		6
+#define MULTIBOOT2_HEADER_TAG_EFI_BS			7
+#define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI32	8
+#define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI64	9
+
+/* Header tag flags. */
+#define MULTIBOOT2_HEADER_TAG_REQUIRED			0
+#define MULTIBOOT2_HEADER_TAG_OPTIONAL			1
+
+/* Header console tag console_flags. */
+#define MULTIBOOT2_CONSOLE_FLAGS_CONSOLE_REQUIRED	1
+#define MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED	2
+
+/* Flags set in the 'flags' member of the multiboot header.  */
+#define MULTIBOOT2_TAG_TYPE_END				0
+#define MULTIBOOT2_TAG_TYPE_CMDLINE			1
+#define MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME		2
+#define MULTIBOOT2_TAG_TYPE_MODULE			3
+#define MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO		4
+#define MULTIBOOT2_TAG_TYPE_BOOTDEV			5
+#define MULTIBOOT2_TAG_TYPE_MMAP			6
+#define MULTIBOOT2_TAG_TYPE_VBE				7
+#define MULTIBOOT2_TAG_TYPE_FRAMEBUFFER			8
+#define MULTIBOOT2_TAG_TYPE_ELF_SECTIONS		9
+#define MULTIBOOT2_TAG_TYPE_APM				10
+#define MULTIBOOT2_TAG_TYPE_EFI32			11
+#define MULTIBOOT2_TAG_TYPE_EFI64			12
+#define MULTIBOOT2_TAG_TYPE_SMBIOS			13
+#define MULTIBOOT2_TAG_TYPE_ACPI_OLD			14
+#define MULTIBOOT2_TAG_TYPE_ACPI_NEW			15
+#define MULTIBOOT2_TAG_TYPE_NETWORK			16
+#define MULTIBOOT2_TAG_TYPE_EFI_MMAP			17
+#define MULTIBOOT2_TAG_TYPE_EFI_BS			18
+#define MULTIBOOT2_TAG_TYPE_EFI32_IH			19
+#define MULTIBOOT2_TAG_TYPE_EFI64_IH			20
+
+/* Multiboot 2 tag alignment. */
+#define MULTIBOOT2_TAG_ALIGN				8
+
+/* Memory types. */
+#define MULTIBOOT2_MEMORY_AVAILABLE			1
+#define MULTIBOOT2_MEMORY_RESERVED			2
+#define MULTIBOOT2_MEMORY_ACPI_RECLAIMABLE		3
+#define MULTIBOOT2_MEMORY_NVS				4
+#define MULTIBOOT2_MEMORY_BADRAM			5
+
+/* Framebuffer types. */
+#define MULTIBOOT2_FRAMEBUFFER_TYPE_INDEXED		0
+#define MULTIBOOT2_FRAMEBUFFER_TYPE_RGB			1
+#define MULTIBOOT2_FRAMEBUFFER_TYPE_EGA_TEXT		2
+
+#ifndef __ASSEMBLY__
+typedef struct {
+    u32 total_size;
+    u32 reserved;
+} multiboot2_fixed_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+} multiboot2_tag_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+    char string[];
+} multiboot2_tag_string_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+    u32 mem_lower;
+    u32 mem_upper;
+} multiboot2_tag_basic_meminfo_t;
+
+typedef struct {
+    u64 addr;
+    u64 len;
+    u32 type;
+    u32 zero;
+} multiboot2_memory_map_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+    u32 entry_size;
+    u32 entry_version;
+    multiboot2_memory_map_t entries[];
+} multiboot2_tag_mmap_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+    u64 pointer;
+} multiboot2_tag_efi64_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+    u64 pointer;
+} multiboot2_tag_efi64_ih_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
+    u32 mod_start;
+    u32 mod_end;
+    char cmdline[];
+} multiboot2_tag_module_t;
+#endif /* __ASSEMBLY__ */
+
+#endif /* __MULTIBOOT2_H__ */
-- 
1.7.10.4


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

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

* [PATCH v5 10/16] efi: create efi_enabled()
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (8 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 09/16] x86: add multiboot2 protocol support Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 12:16   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 11/16] efi: build xen.gz with EFI code Daniel Kiper
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

First of all we need to differentiate between legacy BIOS
and EFI platforms during runtime, not during build, because
one image will have legacy and EFI code and can be executed
on both platforms. Additionally, we need more fine grained
knowledge about EFI environment and check for EFI platform
and EFI loader separately to properly support multiboot2
protocol. In general Xen loaded by this protocol uses memory
mappings and loaded modules in similar way to Xen loaded by
multiboot (v1) protocol. Hence, create efi_enabled() which
checks available features in efi_flags. This patch defines
EFI_BOOT, EFI_LOADER and EFI_RS features. EFI_BOOT is equal
to old efi_enabled == 1. EFI_RS ease control on runtime
services usage. EFI_LOADER tells that Xen was loaded
directly from EFI as PE executable.

Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v5 - suggestions/fixes:
   - squash three patches into one
     (suggested by Jan Beulich),
   - introduce all features at once
     (suggested by Jan Beulich),
   - efi_enabled() returns bool_t
     instead of unsigned int
     (suggested by Jan Beulich),
   - update commit message.

v4 - suggestions/fixes:
   - rename EFI_PLATFORM to EFI_BOOT
     (suggested by Jan Beulich),
   - move EFI_BOOT definition to efi struct definition
     (suggested by Jan Beulich),
   - remove unneeded efi.flags initialization
     (suggested by Jan Beulich),
   - use __set_bit() instead of set_bit() if possible
     (suggested by Jan Beulich),
   - do efi_enabled() cleanup
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Jan Beulich),
   - improve commit message.

v3 - suggestions/fixes:
   - define efi struct in xen/arch/x86/efi/stub.c
     in earlier patch
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Jan Beulich),
   - improve commit message
     (suggested by Jan Beulich).
---
 xen/arch/x86/dmi_scan.c    |    4 ++--
 xen/arch/x86/domain_page.c |    2 +-
 xen/arch/x86/efi/stub.c    |    7 ++++---
 xen/arch/x86/mpparse.c     |    4 ++--
 xen/arch/x86/setup.c       |   14 ++++++++------
 xen/arch/x86/shutdown.c    |    4 ++--
 xen/arch/x86/time.c        |    2 +-
 xen/common/efi/boot.c      |   17 +++++++++++++----
 xen/common/efi/runtime.c   |   15 +++++++++------
 xen/drivers/acpi/osl.c     |    2 +-
 xen/include/xen/efi.h      |    9 +++++++--
 11 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c
index b049e31..8dcb640 100644
--- a/xen/arch/x86/dmi_scan.c
+++ b/xen/arch/x86/dmi_scan.c
@@ -238,7 +238,7 @@ const char *__init dmi_get_table(paddr_t *base, u32 *len)
 {
 	static unsigned int __initdata instance;
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_BOOT)) {
 		if (efi_smbios3_size && !(instance & 1)) {
 			*base = efi_smbios3_address;
 			*len = efi_smbios3_size;
@@ -696,7 +696,7 @@ static void __init dmi_decode(struct dmi_header *dm)
 
 void __init dmi_scan_machine(void)
 {
-	if ((!efi_enabled ? dmi_iterate(dmi_decode) :
+	if ((!efi_enabled(EFI_BOOT) ? dmi_iterate(dmi_decode) :
 	                    dmi_efi_iterate(dmi_decode)) == 0)
  		dmi_check_system(dmi_blacklist);
 	else
diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
index d86f8fe..7541b91 100644
--- a/xen/arch/x86/domain_page.c
+++ b/xen/arch/x86/domain_page.c
@@ -36,7 +36,7 @@ static inline struct vcpu *mapcache_current_vcpu(void)
      * domain's page tables but current may point at another domain's VCPU.
      * Return NULL as though current is not properly set up yet.
      */
-    if ( efi_enabled && efi_rs_using_pgtables() )
+    if ( efi_enabled(EFI_RS) && efi_rs_using_pgtables() )
         return NULL;
 
     /*
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index 07c2bd0..f087023 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -4,9 +4,10 @@
 #include <xen/lib.h>
 #include <asm/page.h>
 
-#ifndef efi_enabled
-const bool_t efi_enabled = 0;
-#endif
+bool_t efi_enabled(int feature)
+{
+    return false;
+}
 
 void __init efi_init_memory(void) { }
 
diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c
index ef6557c..c3d5bdc 100644
--- a/xen/arch/x86/mpparse.c
+++ b/xen/arch/x86/mpparse.c
@@ -564,7 +564,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
 
 static __init void efi_unmap_mpf(void)
 {
-	if (efi_enabled)
+	if (efi_enabled(EFI_BOOT))
 		clear_fixmap(FIX_EFI_MPF);
 }
 
@@ -722,7 +722,7 @@ void __init find_smp_config (void)
 {
 	unsigned int address;
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_BOOT)) {
 		efi_check_config();
 		return;
 	}
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 8ae897a..360ca59 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -439,8 +439,8 @@ static void __init parse_video_info(void)
 {
     struct boot_video_info *bvi = &bootsym(boot_vid_info);
 
-    /* The EFI loader fills vga_console_info directly. */
-    if ( efi_enabled )
+    /* vga_console_info is filled directly on EFI platform. */
+    if ( efi_enabled(EFI_BOOT) )
         return;
 
     if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
@@ -726,7 +726,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
         panic("dom0 kernel not specified. Check bootloader configuration.");
 
-    if ( efi_enabled )
+    if ( efi_enabled(EFI_LOADER) )
     {
         set_pdx_range(xen_phys_start >> PAGE_SHIFT,
                       (xen_phys_start + BOOTSTRAP_MAP_BASE) >> PAGE_SHIFT);
@@ -739,8 +739,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] =
             l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR);
 
-        memmap_type = loader;
+        memmap_type = "EFI";
     }
+    else if ( efi_enabled(EFI_BOOT) )
+        memmap_type = "EFI";
     else if ( e820_raw_nr != 0 )
     {
         memmap_type = "Xen-e820";
@@ -837,7 +839,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
      * we can relocate the dom0 kernel and other multiboot modules. Also, on
      * x86/64, we relocate Xen to higher memory.
      */
-    for ( i = 0; !efi_enabled && i < mbi->mods_count; i++ )
+    for ( i = 0; !efi_enabled(EFI_LOADER) && i < mbi->mods_count; i++ )
     {
         if ( mod[i].mod_start & (PAGE_SIZE - 1) )
             panic("Bootloader didn't honor module alignment request.");
@@ -1078,7 +1080,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     if ( !xen_phys_start )
         panic("Not enough memory to relocate Xen.");
-    reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start),
+    reserve_e820_ram(&boot_e820, efi_enabled(EFI_BOOT) ? mbi->mem_upper : __pa(&_start),
                      __pa(&_end));
 
     /* Late kexec reservation (dynamic start address). */
diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c
index 972e20b..b429fd0 100644
--- a/xen/arch/x86/shutdown.c
+++ b/xen/arch/x86/shutdown.c
@@ -81,7 +81,7 @@ static void __init set_reboot_type(char *str)
         str++;
     }
 
-    if ( reboot_type == BOOT_EFI && !efi_enabled )
+    if ( reboot_type == BOOT_EFI && !efi_enabled(EFI_RS) )
         reboot_type = BOOT_INVALID;
 }
 custom_param("reboot", set_reboot_type);
@@ -119,7 +119,7 @@ void machine_halt(void)
 static void default_reboot_type(void)
 {
     if ( reboot_type == BOOT_INVALID )
-        reboot_type = efi_enabled ? BOOT_EFI
+        reboot_type = efi_enabled(EFI_RS) ? BOOT_EFI
                                   : acpi_disabled ? BOOT_KBD
                                                   : BOOT_ACPI;
 }
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index b316f23..34f82cb 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -727,7 +727,7 @@ static unsigned long get_cmos_time(void)
     static bool_t __read_mostly cmos_rtc_probe;
     boolean_param("cmos-rtc-probe", cmos_rtc_probe);
 
-    if ( efi_enabled )
+    if ( efi_enabled(EFI_RS) )
     {
         res = efi_get_time();
         if ( res )
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 125c9ce..d7c484e 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -934,6 +934,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     char *option_str;
     bool_t use_cfg_file;
 
+    __set_bit(EFI_BOOT, &efi_flags);
+    __set_bit(EFI_LOADER, &efi_flags);
+
+#ifndef CONFIG_ARM /* Disabled until runtime services implemented. */
+    __set_bit(EFI_RS, &efi_flags);
+#endif
+
     efi_init(ImageHandle, SystemTable);
 
     use_cfg_file = efi_arch_use_config_file(SystemTable);
@@ -1153,7 +1160,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 
 #ifndef CONFIG_ARM /* TODO - runtime service support */
 
-static bool_t __initdata efi_rs_enable = 1;
 static bool_t __initdata efi_map_uc;
 
 static void __init parse_efi_param(char *s)
@@ -1171,7 +1177,10 @@ static void __init parse_efi_param(char *s)
             *ss = '\0';
 
         if ( !strcmp(s, "rs") )
-            efi_rs_enable = val;
+        {
+            if ( !val )
+                __clear_bit(EFI_RS, &efi_flags);
+        }
         else if ( !strcmp(s, "attr=uc") )
             efi_map_uc = val;
 
@@ -1254,7 +1263,7 @@ void __init efi_init_memory(void)
                desc->PhysicalStart, desc->PhysicalStart + len - 1,
                desc->Type, desc->Attribute);
 
-        if ( !efi_rs_enable ||
+        if ( !efi_enabled(EFI_RS) ||
              (!(desc->Attribute & EFI_MEMORY_RUNTIME) &&
               (!map_bs ||
                (desc->Type != EfiBootServicesCode &&
@@ -1328,7 +1337,7 @@ void __init efi_init_memory(void)
         }
     }
 
-    if ( !efi_rs_enable )
+    if ( !efi_enabled(EFI_RS) )
     {
         efi_fw_vendor = NULL;
         return;
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index c256814..6bffda0 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -10,12 +10,6 @@ DEFINE_XEN_GUEST_HANDLE(CHAR16);
 
 #ifndef COMPAT
 
-/*
- * Currently runtime services are not implemented on ARM. To boot Xen with ACPI,
- * set efi_enabled to 1, so that Xen can get the ACPI root pointer from EFI.
- */
-const bool_t efi_enabled = 1;
-
 #ifndef CONFIG_ARM
 # include <asm/i387.h>
 # include <asm/xstate.h>
@@ -43,6 +37,9 @@ UINT64 __read_mostly efi_boot_max_var_store_size;
 UINT64 __read_mostly efi_boot_remain_var_store_size;
 UINT64 __read_mostly efi_boot_max_var_size;
 
+/* Bit fields representing available EFI features/properties. */
+unsigned long efi_flags;
+
 struct efi __read_mostly efi = {
 	.acpi   = EFI_INVALID_TABLE_ADDR,
 	.acpi20 = EFI_INVALID_TABLE_ADDR,
@@ -53,6 +50,12 @@ struct efi __read_mostly efi = {
 
 const struct efi_pci_rom *__read_mostly efi_pci_roms;
 
+/* Test whether EFI_* bits are enabled. */
+bool_t efi_enabled(int feature)
+{
+    return test_bit(feature, &efi_flags);
+}
+
 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
 unsigned long efi_rs_enter(void)
 {
diff --git a/xen/drivers/acpi/osl.c b/xen/drivers/acpi/osl.c
index 9a49029..3616dfd 100644
--- a/xen/drivers/acpi/osl.c
+++ b/xen/drivers/acpi/osl.c
@@ -66,7 +66,7 @@ void __init acpi_os_vprintf(const char *fmt, va_list args)
 
 acpi_physical_address __init acpi_os_get_root_pointer(void)
 {
-	if (efi_enabled) {
+	if (efi_enabled(EFI_BOOT)) {
 		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
 			return efi.acpi20;
 		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h
index e74dad1..8372ae2 100644
--- a/xen/include/xen/efi.h
+++ b/xen/include/xen/efi.h
@@ -2,13 +2,17 @@
 #define __XEN_EFI_H__
 
 #ifndef __ASSEMBLY__
+#include <xen/bitops.h>
 #include <xen/types.h>
 #endif
 
-extern const bool_t efi_enabled;
-
 #define EFI_INVALID_TABLE_ADDR (~0UL)
 
+extern unsigned long efi_flags;
+#define EFI_BOOT	0	/* Were we booted from EFI? */
+#define EFI_LOADER	1	/* Were we booted directly from EFI loader? */
+#define EFI_RS		2	/* Can we use runtime services? */
+
 /* Add fields here only if they need to be referenced from non-EFI code. */
 struct efi {
     unsigned long mps;          /* MPS table */
@@ -28,6 +32,7 @@ union compat_pf_efi_info;
 struct xenpf_efi_runtime_call;
 struct compat_pf_efi_runtime_call;
 
+bool_t efi_enabled(int feature);
 void efi_init_memory(void);
 bool_t efi_rs_using_pgtables(void);
 unsigned long efi_get_time(void);
-- 
1.7.10.4


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

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

* [PATCH v5 11/16] efi: build xen.gz with EFI code
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (9 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 10/16] efi: create efi_enabled() Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 12:23   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 12/16] x86/efi: create new early memory allocator Daniel Kiper
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Build xen.gz with EFI code. We need this to support multiboot2
protocol on EFI platforms.

If we wish to load non-ELF file using multiboot (v1) or multiboot2 then
it must contain "linear" (or "flat") representation of code and data.
This is requirement of both boot protocols. Currently, PE file contains
many sections which are not "linear" (one after another without any holes)
or even do not have representation in a file (e.g. BSS). From EFI point
of view everything is OK and works. However, this file layout cannot be
properly interpreted by multiboot protocols family. In theory there is
a chance that we could build proper PE file (from multiboot protocols POV)
using current build system. However, it means that xen.efi further diverge
from Xen ELF file (in terms of contents and build method). On the other
hand ELF has all needed properties. So, it means that this is good starting
point for further development. Additionally, I think that this is also good
starting point for further xen.efi code and build optimizations. It looks
that there is a chance that finally we can generate xen.efi directly from
Xen ELF using just simple objcopy or other tool. This way we will have one
Xen binary which can be loaded by three boot protocols: EFI native loader,
multiboot (v1) and multiboot2.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
v5 - suggestions/fixes:
   - properly calculate efi symbol address in
     xen/arch/x86/xen.lds.S (I hope that this
     change does not invalidate Jan's ACK).

v4 - suggestions/fixes:
   - functions should return -ENOSYS instead
     of -EOPNOTSUPP if EFI runtime services
     are not available
     (suggested by Jan Beulich),
   - remove stale bits from xen/arch/x86/Makefile
     (suggested by Jan Beulich).

v3 - suggestions/fixes:
   - check for EFI platform in EFI code
     (suggested by Jan Beulich),
   - fix Makefiles
     (suggested by Jan Beulich),
   - improve commit message
     (suggested by Jan Beulich).

v2 - suggestions/fixes:
   - build EFI code only if it is supported in a given build environment
     (suggested by Jan Beulich).
---
 xen/arch/x86/Makefile     |    2 +-
 xen/arch/x86/efi/Makefile |   11 +++--------
 xen/arch/x86/xen.lds.S    |    4 ++--
 xen/common/efi/boot.c     |    3 +++
 xen/common/efi/runtime.c  |    6 ++++++
 5 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index b18f033..71ec34e 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -211,7 +211,7 @@ efi/mkreloc: efi/mkreloc.c
 clean::
 	rm -f asm-offsets.s *.lds boot/*.o boot/*~ boot/core boot/mkelf32
 	rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
-	rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi efi/disabled efi/mkreloc
+	rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.efi efi/disabled efi/mkreloc
 	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
 	rm -f note.o
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C test clean
diff --git a/xen/arch/x86/efi/Makefile b/xen/arch/x86/efi/Makefile
index 5099430..2a7d3e5 100644
--- a/xen/arch/x86/efi/Makefile
+++ b/xen/arch/x86/efi/Makefile
@@ -1,14 +1,9 @@
 CFLAGS += -fshort-wchar
 
-obj-y += stub.o
-
-create = test -e $(1) || touch -t 199901010000 $(1)
-
 efi := y$(shell rm -f disabled)
 efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) .%.d,$(CFLAGS)) -c check.c 2>disabled && echo y))
 efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2>disabled && echo y))
-efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.init.o); $(call create,runtime.o)))
+efi := $(if $(efi),$(shell rm disabled)y)
 
-extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o
-
-stub.o: $(extra-y)
+obj-y := stub.o
+obj-$(efi) := boot.init.o compat.o relocs-dummy.o runtime.o
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 2d1d43d..40eb4c5 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -262,10 +262,10 @@ SECTIONS
   .pad : {
     . = ALIGN(MB(16));
   } :text
-#else
-  efi = .;
 #endif
 
+  efi = DEFINED(efi) ? efi : .;
+
   /* Sections to be discarded */
   /DISCARD/ : {
        *(.exit.text)
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index d7c484e..48ef8ad 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -1249,6 +1249,9 @@ void __init efi_init_memory(void)
     } *extra, *extra_head = NULL;
 #endif
 
+    if ( !efi_enabled(EFI_BOOT) )
+        return;
+
     printk(XENLOG_INFO "EFI memory map:%s\n",
            map_bs ? " (mapping BootServices)" : "");
     for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index 6bffda0..64c632c 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -175,6 +175,9 @@ int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
 {
     unsigned int i, n;
 
+    if ( !efi_enabled(EFI_BOOT) )
+        return -ENOSYS;
+
     switch ( idx )
     {
     case XEN_FW_EFI_VERSION:
@@ -309,6 +312,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
     EFI_STATUS status = EFI_NOT_STARTED;
     int rc = 0;
 
+    if ( !efi_enabled(EFI_RS) )
+        return -ENOSYS;
+
     switch ( op->function )
     {
     case XEN_EFI_get_time:
-- 
1.7.10.4


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

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

* [PATCH v5 12/16] x86/efi: create new early memory allocator
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (10 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 11/16] efi: build xen.gz with EFI code Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-09-05 12:33   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms Daniel Kiper
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

There is a problem with place_string() which is used as early memory
allocator. It gets memory chunks starting from start symbol and goes
down. Sadly this does not work when Xen is loaded using multiboot2
protocol because then the start lives on 1 MiB address and we should
not allocate a memory from below of it. So, I tried to use mem_lower
address calculated by GRUB2. However, this solution works only on some
machines. There are machines in the wild (e.g. Dell PowerEdge R820)
which uses first ~640 KiB for boot services code or data... :-(((
Hence, we need new memory allocator for Xen EFI boot code which is
quite simple and generic and could be used by place_string() and
efi_arch_allocate_mmap_buffer(). I think about following solutions:

1) We could use native EFI allocation functions (e.g. AllocatePool()
   or AllocatePages()) to get memory chunk. However, later (somewhere
   in __start_xen()) we must copy its contents to safe place or reserve
   it in e820 memory map and map it in Xen virtual address space. This
   means that the code referring to Xen command line, loaded modules and
   EFI memory map, mostly in __start_xen(), will be further complicated
   and diverge from legacy BIOS cases. Additionally, both former things
   have to be placed below 4 GiB because their addresses are stored in
   multiboot_info_t structure which has 32-bit relevant members.

2) We may allocate memory area statically somewhere in Xen code which
   could be used as memory pool for early dynamic allocations. Looks
   quite simple. Additionally, it would not depend on EFI at all and
   could be used on legacy BIOS platforms if we need it. However, we
   must carefully choose size of this pool. We do not want increase Xen
   binary size too much and waste too much memory but also we must fit
   at least memory map on x86 EFI platforms. As I saw on small machine,
   e.g. IBM System x3550 M2 with 8 GiB RAM, memory map may contain more
   than 200 entries. Every entry on x86-64 platform is 40 bytes in size.
   So, it means that we need more than 8 KiB for EFI memory map only.
   Additionally, if we use this memory pool for Xen and modules command
   line storage (it would be used when xen.efi is executed as EFI application)
   then we should add, I think, about 1 KiB. In this case, to be on safe
   side, we should assume at least 64 KiB pool for early memory allocations.
   Which is about 4 times of our earlier calculations. However, during
   discussion on Xen-devel Jan Beulich suggested that just in case we should
   use 1 MiB memory pool like it is in original place_string() implementation.
   So, let's use 1 MiB as it was proposed. If we think that we should not
   waste unallocated memory in the pool on running system then we can mark
   this region as __initdata and move all required data to dynamically
   allocated places somewhere in __start_xen().

2a) We could put memory pool into .bss.page_aligned section. Then allocate
    memory chunks starting from the lowest address. After init phase we can
    free unused portion of the memory pool as in case of .init.text or .init.data
    sections. This way we do not need to allocate any space in image file and
    freeing of unused area in the memory pool is very simple.

Now #2a solution is implemented because it is quite simple and requires
limited number of changes, especially in __start_xen().

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v4 - suggestions/fixes:
   - move from #2 solution to #2a solution,
   - improve commit message.
---
 xen/arch/x86/efi/efi-boot.h |   58 +++++++++++++++++++++++++++++++++++++------
 xen/arch/x86/efi/stub.c     |    2 ++
 xen/arch/x86/setup.c        |    5 ++--
 xen/include/xen/efi.h       |    1 +
 4 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 1fa9e47..3f87b7c 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -103,9 +103,56 @@ static void __init relocate_trampoline(unsigned long phys)
         *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
 }
 
+#define EBMALLOC_SIZE	MB(1)
+
+static char __section(".bss.page_aligned") ebmalloc_mem[EBMALLOC_SIZE];
+static char __initdata *ebmalloc_free = NULL;
+
+/* EFI boot allocator. */
+static void __init *ebmalloc(size_t size)
+{
+    void *ptr;
+
+    /*
+     * Init ebmalloc_free on runtime. Static initialization
+     * will not work because it puts virtual address there.
+     */
+    if ( ebmalloc_free == NULL )
+        ebmalloc_free = ebmalloc_mem;
+
+    ptr = ebmalloc_free;
+
+    ebmalloc_free += size;
+
+    if ( ebmalloc_free - ebmalloc_mem > sizeof(ebmalloc_mem) )
+        blexit(L"Out of static memory\r\n");
+
+    return ptr;
+}
+
+void __init free_ebmalloc_unused_mem(void)
+{
+    unsigned long start, end;
+
+    if ( ebmalloc_free )
+    {
+        start = (unsigned long)ebmalloc_free - xen_phys_start;
+        start = PAGE_ALIGN(start + XEN_VIRT_START);
+    }
+    else
+        start = (unsigned long)ebmalloc_mem;
+
+    end = (unsigned long)ebmalloc_mem + sizeof(ebmalloc_mem);
+
+    destroy_xen_mappings(start, end);
+    init_xenheap_pages(__pa(start), __pa(end));
+
+    printk("Freed %lukB unused BSS memory\n", (end - start) >> 10);
+}
+
 static void __init place_string(u32 *addr, const char *s)
 {
-    static char *__initdata alloc = start;
+    char *alloc = NULL;
 
     if ( s && *s )
     {
@@ -113,7 +160,7 @@ static void __init place_string(u32 *addr, const char *s)
         const char *old = (char *)(long)*addr;
         size_t len2 = *addr ? strlen(old) + 1 : 0;
 
-        alloc -= len1 + len2;
+        alloc = ebmalloc(len1 + len2);
         /*
          * Insert new string before already existing one. This is needed
          * for options passed on the command line to override options from
@@ -196,12 +243,7 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
 
 static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
 {
-    place_string(&mbi.mem_upper, NULL);
-    mbi.mem_upper -= map_size;
-    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
-    if ( mbi.mem_upper < xen_phys_start )
-        return NULL;
-    return (void *)(long)mbi.mem_upper;
+    return ebmalloc(map_size);
 }
 
 static void __init efi_arch_pre_exit_boot(void)
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index f087023..f7bc042 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -9,6 +9,8 @@ bool_t efi_enabled(int feature)
     return false;
 }
 
+void __init free_ebmalloc_unused_mem(void) { }
+
 void __init efi_init_memory(void) { }
 
 void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t l4e) { }
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 360ca59..bc48351 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -520,6 +520,8 @@ static void noinline init_done(void)
 
     system_state = SYS_STATE_active;
 
+    free_ebmalloc_unused_mem();
+
     /* MUST be done prior to removing .init data. */
     unregister_init_virtual_region();
 
@@ -1080,8 +1082,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     if ( !xen_phys_start )
         panic("Not enough memory to relocate Xen.");
-    reserve_e820_ram(&boot_e820, efi_enabled(EFI_BOOT) ? mbi->mem_upper : __pa(&_start),
-                     __pa(&_end));
+    reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end));
 
     /* Late kexec reservation (dynamic start address). */
     kexec_reserve_area(&boot_e820);
diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h
index 8372ae2..147a0e8 100644
--- a/xen/include/xen/efi.h
+++ b/xen/include/xen/efi.h
@@ -33,6 +33,7 @@ struct xenpf_efi_runtime_call;
 struct compat_pf_efi_runtime_call;
 
 bool_t efi_enabled(int feature);
+void free_ebmalloc_unused_mem(void);
 void efi_init_memory(void);
 bool_t efi_rs_using_pgtables(void);
 unsigned long efi_get_time(void);
-- 
1.7.10.4


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

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

* [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (11 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 12/16] x86/efi: create new early memory allocator Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 12:59   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 14/16] x86/boot: implement early command line parser in C Daniel Kiper
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

This way Xen can be loaded on EFI platforms using GRUB2 and
other boot loaders which support multiboot2 protocol.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v4 - suggestions/fixes:
   - remove redundant BSS alignment,
   - update BSS alignment check,
   - use __set_bit() instead of set_bit() if possible
     (suggested by Jan Beulich),
   - call efi_arch_cpu() from efi_multiboot2()
     even if the same work is done later in
     other place right now
     (suggested by Jan Beulich),
   - xen/arch/x86/efi/stub.c:efi_multiboot2()
     fail properly on EFI platforms,
   - do not read data beyond the end of multiboot2
     information in xen/arch/x86/boot/head.S
     (suggested by Jan Beulich),
   - use 32-bit registers in x86_64 code if possible
     (suggested by Jan Beulich),
   - multiboot2 information address is 64-bit
     in x86_64 code, so, treat it is as is
     (suggested by Jan Beulich),
   - use cmovcc if possible,
   - leave only one space between rep and stosq
     (suggested by Jan Beulich),
   - improve error handling,
   - improve early error messages,
     (suggested by Jan Beulich),
   - improve early error messages printing code,
   - improve label names
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Jan Beulich),
   - various minor cleanups.

v3 - suggestions/fixes:
   - take into account alignment when skipping multiboot2 fixed part
     (suggested by Konrad Rzeszutek Wilk),
   - improve segment registers initialization
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Jan Beulich and Konrad Rzeszutek Wilk),
   - improve commit message
     (suggested by Jan Beulich).

v2 - suggestions/fixes:
   - generate multiboot2 header using macros
     (suggested by Jan Beulich),
   - switch CPU to x86_32 mode before
     jumping to 32-bit code
     (suggested by Andrew Cooper),
   - reduce code changes to increase patch readability
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Jan Beulich),
   - ignore MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO tag on EFI platform
     and find on my own multiboot2.mem_lower value,
   - stop execution if EFI platform is detected
     in legacy BIOS path.
---
 xen/arch/x86/boot/head.S          |  243 ++++++++++++++++++++++++++++++++++---
 xen/arch/x86/efi/efi-boot.h       |   49 +++++++-
 xen/arch/x86/efi/stub.c           |   24 ++++
 xen/arch/x86/x86_64/asm-offsets.c |    2 +
 xen/arch/x86/xen.lds.S            |    4 +-
 xen/common/efi/boot.c             |   11 ++
 6 files changed, 312 insertions(+), 21 deletions(-)

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 5e61854..aca5370 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -89,6 +89,13 @@ multiboot2_header_start:
                    0, /* Number of the lines - no preference. */ \
                    0  /* Number of bits per pixel - no preference. */
 
+        /* Inhibit bootloader from calling ExitBootServices(). */
+        mb2ht_init MB2_HT(EFI_BS), MB2_HT(OPTIONAL)
+
+        /* EFI64 entry point. */
+        mb2ht_init MB2_HT(ENTRY_ADDRESS_EFI64), MB2_HT(OPTIONAL), \
+                   sym_phys(__efi64_start)
+
         /* Multiboot2 header end tag. */
         mb2ht_init MB2_HT(END), MB2_HT(REQUIRED)
 .Lmultiboot2_header_end:
@@ -100,19 +107,45 @@ multiboot2_header_start:
 gdt_boot_descr:
         .word   6*8-1
         .long   sym_phys(trampoline_gdt)
+        .long   0 /* Needed for 64-bit lgdt */
+
+cs32_switch_addr:
+        .long   sym_phys(cs32_switch)
+        .word   BOOT_CS32
+
+vga_text_buffer:
+        .long   0xb8000
 
 .Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!"
 .Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!"
+.Lbad_ldr_nbs: .asciz "ERR: Bootloader shutdown EFI x64 boot services!"
+.Lbad_ldr_nst: .asciz "ERR: EFI SystemTable is not provided by bootloader!"
+.Lbad_ldr_nih: .asciz "ERR: EFI ImageHandle is not provided by bootloader!"
+.Lbad_efi_msg: .asciz "ERR: EFI IA-32 platforms are not supported!"
 
         .section .init.text, "ax", @progbits
 
 bad_cpu:
         mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
-        jmp     print_err
+        jmp     0f
 not_multiboot:
         mov     $(sym_phys(.Lbad_ldr_msg)),%esi # Error message
-print_err:
-        mov     $0xB8000,%edi  # VGA framebuffer
+        jmp     0f
+mb2_no_st:
+        mov     $(sym_phys(.Lbad_ldr_nst)),%esi # Error message
+        jmp     0f
+mb2_no_ih:
+        mov     $(sym_phys(.Lbad_ldr_nih)),%esi # Error message
+        jmp     0f
+mb2_no_bs:
+        mov     $(sym_phys(.Lbad_ldr_nbs)),%esi # Error message
+        xor     %edi,%edi                       # No VGA text buffer
+        jmp     1f
+mb2_efi_ia_32:
+        mov     $(sym_phys(.Lbad_efi_msg)),%esi # Error message
+        xor     %edi,%edi                       # No VGA text buffer
+        jmp     1f
+0:      mov     sym_phys(vga_text_buffer),%edi
 1:      mov     (%esi),%bl
         test    %bl,%bl        # Terminate on '\0' sentinel
         je      .Lhalt
@@ -123,13 +156,173 @@ print_err:
         mov     $0x3f8+0,%dx   # UART Transmit Holding Register
         mov     %bl,%al
         out     %al,%dx        # Send a character over the serial line
-        movsb                  # Write a character to the VGA framebuffer
+        test    %edi,%edi      # Is the VGA text buffer available?
+        jz      1b
+        movsb                  # Write a character to the VGA text buffer
         mov     $7,%al
-        stosb                  # Write an attribute to the VGA framebuffer
+        stosb                  # Write an attribute to the VGA text buffer
         jmp     1b
 .Lhalt: hlt
         jmp     .Lhalt
 
+        .code64
+
+__efi64_start:
+        cld
+
+        /* VGA is not available on EFI platforms. */
+        movl   $0,vga_text_buffer(%rip)
+
+        /* Check for Multiboot2 bootloader. */
+        cmp     $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
+        je      .Lefi_multiboot2_proto
+
+        /* Jump to not_multiboot after switching CPU to x86_32 mode. */
+        lea     not_multiboot(%rip),%edi
+        jmp     x86_32_switch
+
+.Lefi_multiboot2_proto:
+        /* Zero EFI SystemTable and EFI ImageHandle addresses. */
+        xor     %esi,%esi
+        xor     %edi,%edi
+
+        /* Skip Multiboot2 information fixed part. */
+        lea     (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%ebx),%ecx
+        and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
+
+0:
+        /* Check Multiboot2 information total size. */
+        mov     %ecx,%r8d
+        sub     %ebx,%r8d
+        cmp     %r8d,MB2_fixed_total_size(%rbx)
+        jbe     run_bs
+
+        /* Are EFI boot services available? */
+        cmpl    $MULTIBOOT2_TAG_TYPE_EFI_BS,MB2_tag_type(%rcx)
+        jne     1f
+
+        /* Yes, skip real mode and do not do other unneeded things. */
+        incb    skip_realmode(%rip)
+        jmp     9f
+
+1:
+        /* Get EFI SystemTable address from Multiboot2 information. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
+        cmove   MB2_efi64_st(%rcx),%rsi
+        je      9f
+
+        /* Get EFI ImageHandle address from Multiboot2 information. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
+        cmove   MB2_efi64_ih(%rcx),%rdi
+        je      9f
+
+        /* Is it the end of Multiboot2 information? */
+        cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
+        je      run_bs
+
+9:
+        /* Go to next Multiboot2 information tag. */
+        add     MB2_tag_size(%rcx),%ecx
+        add     $(MULTIBOOT2_TAG_ALIGN-1),%ecx
+        and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
+        jmp     0b
+
+run_bs:
+        /* Are EFI boot services available? */
+        cmpb    $0,skip_realmode(%rip)
+        jnz     0f
+
+        /* Jump to mb2_no_bs after switching CPU to x86_32 mode. */
+        lea     mb2_no_bs(%rip),%edi
+        jmp     x86_32_switch
+
+0:
+        /* Is EFI SystemTable address provided by boot loader? */
+        test    %rsi,%rsi
+        jnz     1f
+
+        /* Jump to mb2_no_st after switching CPU to x86_32 mode. */
+        lea     mb2_no_st(%rip),%edi
+        jmp     x86_32_switch
+
+1:
+        /* Is EFI ImageHandle address provided by boot loader? */
+        test    %rdi,%rdi
+        jnz     2f
+
+        /* Jump to mb2_no_ih after switching CPU to x86_32 mode. */
+        lea     mb2_no_ih(%rip),%edi
+        jmp     x86_32_switch
+
+2:
+        push    %rax
+        push    %rdi
+
+        /*
+         * Initialize BSS (no nasty surprises!).
+         * It must be done earlier than in BIOS case
+         * because efi_multiboot2() touches it.
+         */
+        lea     __bss_start(%rip),%edi
+        lea     __bss_end(%rip),%ecx
+        sub     %edi,%ecx
+        shr     $3,%ecx
+        xor     %eax,%eax
+        rep stosq
+
+        pop     %rdi
+
+        /*
+         * IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable.
+         * OUT: %rax - Highest available memory address below 1 MiB.
+         *
+         * MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO tag is not provided
+         * on EFI platforms. Hence, it could not be used like
+         * on legacy BIOS platforms.
+         */
+        call    efi_multiboot2
+
+        /* Convert memory address to bytes/16 and store it in safe place. */
+        shr     $4,%eax
+        mov     %eax,%ecx
+
+        pop     %rax
+
+        /* Jump to trampoline_setup after switching CPU to x86_32 mode. */
+        lea     trampoline_setup(%rip),%edi
+
+x86_32_switch:
+        cli
+
+        /* Initialise GDT. */
+        lgdt    gdt_boot_descr(%rip)
+
+        /* Reload code selector. */
+        ljmpl   *cs32_switch_addr(%rip)
+
+        .code32
+
+cs32_switch:
+        /* Initialise basic data segments. */
+        mov     $BOOT_DS,%edx
+        mov     %edx,%ds
+        mov     %edx,%es
+        mov     %edx,%ss
+        /* %esp is initialised later. */
+
+        /* Load null descriptor to unused segment registers. */
+        xor     %edx,%edx
+        mov     %edx,%fs
+        mov     %edx,%gs
+
+        /* Disable paging. */
+        mov     %cr0,%edx
+        and     $(~X86_CR0_PG),%edx
+        mov     %edx,%cr0
+
+        /* Jump to earlier loaded address. */
+        jmp     *%edi
+
 __start:
         cld
         cli
@@ -157,7 +350,7 @@ __start:
 
         /* Not available? BDA value will be fine. */
         cmovnz  MB_mem_lower(%ebx),%edx
-        jmp     trampoline_setup
+        jmp     trampoline_bios_setup
 
 .Lmultiboot2_proto:
         /* Skip Multiboot2 information fixed part. */
@@ -169,16 +362,24 @@ __start:
         mov     %ecx,%edi
         sub     %ebx,%edi
         cmp     %edi,MB2_fixed_total_size(%ebx)
-        jbe     trampoline_setup
+        jbe     trampoline_bios_setup
 
         /* Get mem_lower from Multiboot2 information. */
         cmpl    $MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,MB2_tag_type(%ecx)
         cmove   MB2_mem_lower(%ecx),%edx
-        je      trampoline_setup
+        je      trampoline_bios_setup
+
+        /* EFI IA-32 platforms are not supported. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_EFI32,MB2_tag_type(%ecx)
+        je      mb2_efi_ia_32
+
+        /* Bootloader shutdown EFI x64 boot services. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%ecx)
+        je      mb2_no_bs
 
         /* Is it the end of Multiboot2 information? */
         cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%ecx)
-        je      trampoline_setup
+        je      trampoline_bios_setup
 
         /* Go to next Multiboot2 information tag. */
         add     MB2_tag_size(%ecx),%ecx
@@ -186,7 +387,7 @@ __start:
         and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
         jmp     0b
 
-trampoline_setup:
+trampoline_bios_setup:
         /* Set up trampoline segment 64k below EBDA */
         movzwl  0x40e,%ecx          /* EBDA segment */
         cmp     $0xa000,%ecx        /* sanity check (high) */
@@ -202,12 +403,13 @@ trampoline_setup:
          * multiboot structure (if available) and use the smallest.
          */
         cmp     $0x100,%edx         /* is the multiboot value too small? */
-        jb      2f                  /* if so, do not use it */
+        jb      trampoline_setup    /* if so, do not use it */
         shl     $10-4,%edx
         cmp     %ecx,%edx           /* compare with BDA value */
         cmovb   %edx,%ecx           /* and use the smaller */
 
-2:      /* Reserve 64kb for the trampoline */
+trampoline_setup:
+        /* Reserve 64kb for the trampoline. */
         sub     $0x1000,%ecx
 
         /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
@@ -223,14 +425,22 @@ trampoline_setup:
         call    reloc
         mov     %eax,sym_phys(multiboot_ptr)
 
-        /* Initialize BSS (no nasty surprises!) */
+        /*
+         * Do not zero BSS on EFI platform here.
+         * It was initialized earlier.
+         */
+        cmpb    $0,sym_phys(skip_realmode)
+        jnz     1f
+
+        /* Initialize BSS (no nasty surprises!). */
         mov     $sym_phys(__bss_start),%edi
         mov     $sym_phys(__bss_end),%ecx
         sub     %edi,%ecx
-        xor     %eax,%eax
         shr     $2,%ecx
+        xor     %eax,%eax
         rep stosl
 
+1:
         /* Interrogate CPU extended features via CPUID. */
         mov     $0x80000000,%eax
         cpuid
@@ -282,8 +492,13 @@ trampoline_setup:
         cmp     $sym_phys(__trampoline_seg_stop),%edi
         jb      1b
 
+        /* Do not parse command line on EFI platform here. */
+        cmpb    $0,sym_phys(skip_realmode)
+        jnz     1f
+
         call    cmdline_parse_early
 
+1:
         /* Switch to low-memory stack.  */
         mov     sym_phys(trampoline_phys),%edi
         lea     0x10000(%edi),%esp
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 3f87b7c..2622cf7 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -248,12 +248,14 @@ static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
 
 static void __init efi_arch_pre_exit_boot(void)
 {
-    if ( !trampoline_phys )
-    {
-        if ( !cfg.addr )
-            blexit(L"No memory for trampoline");
+    if ( trampoline_phys )
+        return;
+
+    if ( !cfg.addr )
+        blexit(L"No memory for trampoline");
+
+    if ( efi_enabled(EFI_LOADER) )
         relocate_trampoline(cfg.addr);
-    }
 }
 
 static void __init noreturn efi_arch_post_exit_boot(void)
@@ -687,6 +689,43 @@ static bool_t __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
 
 static void efi_arch_flush_dcache_area(const void *vaddr, UINTN size) { }
 
+paddr_t __init efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
+    UINTN cols, gop_mode = ~0, rows;
+
+    __set_bit(EFI_BOOT, &efi_flags);
+    __set_bit(EFI_RS, &efi_flags);
+
+    efi_init(ImageHandle, SystemTable);
+
+    efi_console_set_mode();
+
+    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
+                           &cols, &rows) == EFI_SUCCESS )
+        efi_arch_console_init(cols, rows);
+
+    gop = efi_get_gop();
+
+    if ( gop )
+        gop_mode = efi_find_gop_mode(gop, 0, 0, 0);
+
+    efi_arch_edd();
+    efi_arch_cpu();
+
+    efi_tables();
+    setup_efi_pci();
+    efi_variables();
+
+    if ( gop )
+        efi_set_gop_mode(gop, gop_mode);
+
+    efi_exit_boot(ImageHandle, SystemTable);
+
+    /* Return highest available memory address below 1 MiB. */
+    return cfg.addr;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index f7bc042..d886de6 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -3,6 +3,30 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <asm/page.h>
+#include <asm/efibind.h>
+#include <efi/efidef.h>
+#include <efi/eficapsule.h>
+#include <efi/eficon.h>
+#include <efi/efidevp.h>
+#include <efi/efiapi.h>
+
+paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
+    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
+
+    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
+
+    /* Print error message and halt the system. */
+    asm volatile(
+    "    call %2                      \n"
+    "0:  hlt                          \n"
+    "    jmp  0b                      \n"
+       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
+       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");
+
+    unreachable();
+}
 
 bool_t efi_enabled(int feature)
 {
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 0fc1c63..9695ea6 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -176,6 +176,8 @@ void __dummy__(void)
     OFFSET(MB2_tag_type, multiboot2_tag_t, type);
     OFFSET(MB2_tag_size, multiboot2_tag_t, size);
     OFFSET(MB2_mem_lower, multiboot2_tag_basic_meminfo_t, mem_lower);
+    OFFSET(MB2_efi64_st, multiboot2_tag_efi64_t, pointer);
+    OFFSET(MB2_efi64_ih, multiboot2_tag_efi64_ih_t, pointer);
     BLANK();
 
     OFFSET(DOMAIN_vm_assist, struct domain, vm_assist);
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 40eb4c5..a6246c0 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -323,5 +323,5 @@ ASSERT(IS_ALIGNED(__init_end,   PAGE_SIZE), "__init_end misaligned")
 
 ASSERT(IS_ALIGNED(trampoline_start, 4), "trampoline_start misaligned")
 ASSERT(IS_ALIGNED(trampoline_end,   4), "trampoline_end misaligned")
-ASSERT(IS_ALIGNED(__bss_start,      4), "__bss_start misaligned")
-ASSERT(IS_ALIGNED(__bss_end,        4), "__bss_end misaligned")
+ASSERT(IS_ALIGNED(__bss_start,      8), "__bss_start misaligned")
+ASSERT(IS_ALIGNED(__bss_end,        8), "__bss_end misaligned")
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 48ef8ad..8d81069 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -79,6 +79,17 @@ static size_t wstrlen(const CHAR16 * s);
 static int set_color(u32 mask, int bpp, u8 *pos, u8 *sz);
 static bool_t match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2);
 
+static void efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable);
+static void efi_console_set_mode(void);
+static EFI_GRAPHICS_OUTPUT_PROTOCOL *efi_get_gop(void);
+static UINTN efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
+                               UINTN cols, UINTN rows, UINTN depth);
+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 const EFI_BOOT_SERVICES *__initdata efi_bs;
 static UINT32 __initdata efi_bs_revision;
 static EFI_HANDLE __initdata efi_ih;
-- 
1.7.10.4


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

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

* [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (12 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 13:27   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 15/16] x86: make Xen early boot code relocatable Daniel Kiper
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Current early command line parser implementation in assembler
is very difficult to change to relocatable stuff using segment
registers. This requires a lot of changes in very weird and
fragile code. So, reimplement this functionality in C. This
way code will be relocatable out of the box (without playing
with segment registers) and much easier to maintain.

Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v4 - suggestions/fixes:
   - move to stdcall calling convention
     (suggested by Jan Beulich),
   - define bool_t and use it properly
     (suggested by Jan Beulich),
   - put list of delimiter chars into
     static const char[]
     (suggested by Jan Beulich),
   - use strlen() instead of strlen_opt()
     (suggested by Jan Beulich),
   - change strtoi() to strtoui() and
     optimize it a bit
     (suggested by Jan Beulich),
   - define strchr() and use it in strtoui()
     (suggested by Jan Beulich),
   - optimize vga_parse()
     (suggested by Jan Beulich),
   - move !cmdline check from assembly to C
     (suggested by Jan Beulich),
   - remove my name from copyright (Oracle requirement)
     (suggested by Konrad Rzeszutek Wilk).

v3 - suggestions/fixes:
   - optimize some code
     (suggested by Jan Beulich),
   - put VESA data into early_boot_opts_t members
     (suggested by Jan Beulich),
   - rename some functions and variables
     (suggested by Jan Beulich),
   - move around video.h include in xen/arch/x86/boot/trampoline.S
     (suggested by Jan Beulich),
   - fix coding style
     (suggested by Jan Beulich),
   - fix build with older GCC
     (suggested by Konrad Rzeszutek Wilk),
   - remove redundant comments
     (suggested by Jan Beulich),
   - add some comments
   - improve commit message
     (suggested by Jan Beulich).
---
 .gitignore                     |    5 +-
 xen/arch/x86/Makefile          |    2 +-
 xen/arch/x86/boot/Makefile     |    7 +-
 xen/arch/x86/boot/build32.mk   |    2 +
 xen/arch/x86/boot/cmdline.S    |  367 ---------------------------------------
 xen/arch/x86/boot/cmdline.c    |  376 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/boot/edd.S        |    3 -
 xen/arch/x86/boot/head.S       |    8 +
 xen/arch/x86/boot/trampoline.S |   12 ++
 xen/arch/x86/boot/video.S      |    7 -
 10 files changed, 408 insertions(+), 381 deletions(-)
 delete mode 100644 xen/arch/x86/boot/cmdline.S
 create mode 100644 xen/arch/x86/boot/cmdline.c

diff --git a/.gitignore b/.gitignore
index d193820..23637d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -248,9 +248,10 @@ xen/arch/arm/xen.lds
 xen/arch/x86/asm-offsets.s
 xen/arch/x86/boot/mkelf32
 xen/arch/x86/xen.lds
+xen/arch/x86/boot/cmdline.S
 xen/arch/x86/boot/reloc.S
-xen/arch/x86/boot/reloc.bin
-xen/arch/x86/boot/reloc.lnk
+xen/arch/x86/boot/*.bin
+xen/arch/x86/boot/*.lnk
 xen/arch/x86/efi.lds
 xen/arch/x86/efi/check.efi
 xen/arch/x86/efi/disabled
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 71ec34e..9464b7b 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -212,6 +212,6 @@ clean::
 	rm -f asm-offsets.s *.lds boot/*.o boot/*~ boot/core boot/mkelf32
 	rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
 	rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.efi efi/disabled efi/mkreloc
-	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
+	rm -f boot/cmdline.S boot/reloc.S boot/*.lnk boot/*.bin
 	rm -f note.o
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C test clean
diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index 06893d8..d73cc76 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1,9 +1,14 @@
 obj-bin-y += head.o
 
+CMDLINE_DEPS = video.h
+
 RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h \
 	     $(BASEDIR)/include/xen/multiboot2.h
 
-head.o: reloc.S
+head.o: cmdline.S reloc.S
+
+cmdline.S: cmdline.c $(CMDLINE_DEPS)
+	$(MAKE) -f build32.mk $@ CMDLINE_DEPS="$(CMDLINE_DEPS)"
 
 reloc.S: reloc.c $(RELOC_DEPS)
 	$(MAKE) -f build32.mk $@ RELOC_DEPS="$(RELOC_DEPS)"
diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk
index 39e6453..3d01698 100644
--- a/xen/arch/x86/boot/build32.mk
+++ b/xen/arch/x86/boot/build32.mk
@@ -32,6 +32,8 @@ CFLAGS := $(filter-out -flto,$(CFLAGS))
 %.o: %.c
 	$(CC) $(CFLAGS) -c -fpic $< -o $@
 
+cmdline.o: cmdline.c $(CMDLINE_DEPS)
+
 reloc.o: reloc.c $(RELOC_DEPS)
 
 .PRECIOUS: %.bin %.lnk
diff --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S
deleted file mode 100644
index 00687eb..0000000
--- a/xen/arch/x86/boot/cmdline.S
+++ /dev/null
@@ -1,367 +0,0 @@
-/******************************************************************************
- * cmdline.S
- *
- * Early command-line parsing.
- */
-
-        .code32
-
-#include "video.h"
-
-# NB. String pointer on stack is modified to point past parsed digits.
-.Latoi:
-        push    %ebx
-        push    %ecx
-        push    %edx
-        push    %esi
-        xor     %ebx,%ebx       /* %ebx = accumulator */
-        mov     $10,%ecx        /* %ecx = base (default base 10) */
-        mov     16+4(%esp),%esi /* %esi = pointer into ascii string. */
-        lodsb
-        cmpb    $'0',%al
-        jne     2f
-        mov     $8,%ecx         /* Prefix '0' => octal (base 8) */
-        lodsb
-        cmpb    $'x',%al
-        jne     2f
-        mov     $16,%ecx        /* Prefix '0x' => hex (base 16) */
-1:      lodsb
-2:      sub     $'0',%al
-        jb      4f
-        cmp     $9,%al
-        jbe     3f
-        sub     $'A'-'0'-10,%al
-        jb      4f
-        cmp     $15,%al
-        jbe     3f
-        sub     $'a'-'A',%al
-        jb      4f
-3:      cmp     %cl,%al
-        jae     4f
-        movzbl  %al,%eax
-        xchg    %eax,%ebx
-        mul     %ecx
-        xchg    %eax,%ebx
-        add     %eax,%ebx
-        jmp     1b
-4:      mov     %ebx,%eax
-        dec     %esi
-        mov     %esi,16+4(%esp)
-        pop     %esi
-        pop     %edx
-        pop     %ecx
-        pop     %ebx
-        ret
-
-.Lstrstr:
-        push    %ecx
-        push    %edx
-        push    %esi
-        push    %edi
-        xor     %eax,%eax
-        xor     %ecx,%ecx
-        not     %ecx
-        mov     16+4(%esp),%esi
-        mov     16+8(%esp),%edi
-        repne   scasb
-        not     %ecx
-        dec     %ecx
-        mov     %ecx,%edx
-1:      mov     16+8(%esp),%edi
-        mov     %esi,%eax
-        mov     %edx,%ecx
-        repe    cmpsb
-        je      2f
-        xchg    %eax,%esi
-        inc     %esi
-        cmpb    $0,-1(%eax)
-        jne     1b
-        xor     %eax,%eax
-2:      pop     %edi
-        pop     %esi
-        pop     %edx
-        pop     %ecx
-        ret
-
-.Lstr_prefix:
-        push    %esi
-        push    %edi
-        mov     8+4(%esp),%esi /* 1st arg is prefix string */
-        mov     8+8(%esp),%edi /* 2nd arg is main string */
-1:      lodsb
-        test    %al,%al
-        jz      2f
-        scasb
-        je      1b
-        sbb     %eax,%eax
-        or      $1,%al
-        jmp     3f
-2:      xor     %eax,%eax
-3:      pop     %edi
-        pop     %esi
-        ret
-
-.Lstrlen:
-        push    %ecx
-        push    %esi
-        push    %edi
-        xor     %eax,%eax
-        xor     %ecx,%ecx
-        not     %ecx
-        mov     12+4(%esp),%edi
-        repne   scasb
-        not     %ecx
-        dec     %ecx
-        mov     %ecx,%eax
-        pop     %edi
-        pop     %esi
-        pop     %ecx
-        ret
-
-.Lfind_option:
-        mov     4(%esp),%eax
-        dec     %eax
-        push    %ebx
-1:      pushl   4+8(%esp)
-        inc     %eax
-        push    %eax
-        call    .Lstrstr
-        add     $8,%esp
-        test    %eax,%eax
-        jz      3f
-        cmp     %eax,4+4(%esp)
-        je      2f
-        cmpb    $' ',-1(%eax)
-        jne     1b
-2:      mov     %eax,%ebx
-        pushl   4+8(%esp)
-        call    .Lstrlen
-        add     $4,%esp
-        xadd    %eax,%ebx
-        /* NUL check (as $'\0' == 0x30 in GAS) */
-        cmpb    $0,(%ebx)
-        je      3f
-        cmpb    $' ',(%ebx)
-        je      3f
-        cmpb    $'=',(%ebx)
-        jne     1b
-3:      pop     %ebx
-        ret
-
-cmdline_parse_early:
-        pusha
-
-        /* Bail if there is no command line to parse. */
-        mov     sym_phys(multiboot_ptr),%ebx
-        mov     MB_flags(%ebx),%eax
-        test    $4,%al
-        jz      .Lcmdline_exit
-        mov     MB_cmdline(%ebx),%eax
-        test    %eax,%eax
-        jz      .Lcmdline_exit
-
-        /* Check for 'no-real-mode' command-line option. */
-        pushl   $sym_phys(.Lno_rm_opt)
-        pushl   MB_cmdline(%ebx)
-        call    .Lfind_option
-        test    %eax,%eax
-        setnz   %al
-        or      %al,sym_phys(skip_realmode)
-
-        /* Check for 'tboot=' command-line option. */
-        movl    $sym_phys(.Ltboot_opt),4(%esp)
-        call    .Lfind_option
-        test    %eax,%eax
-        setnz   %al
-        or      %al,sym_phys(skip_realmode) /* tboot= implies no-real-mode */
-
-.Lparse_edd:
-        /* Check for 'edd=' command-line option. */
-        movl    $sym_phys(.Ledd_opt),4(%esp)
-        call    .Lfind_option
-        test    %eax,%eax
-        jz      .Lparse_edid
-        cmpb    $'=',3(%eax)
-        jne     .Lparse_edid
-        add     $4,%eax
-        movb    $2,sym_phys(opt_edd)  /* opt_edd=2: edd=off */
-        cmpw    $0x666f,(%eax)            /* 0x666f == "of" */
-        je      .Lparse_edid
-        decb    sym_phys(opt_edd)     /* opt_edd=1: edd=skipmbr */
-        cmpw    $0x6b73,(%eax)            /* 0x6b73 == "sk" */
-        je      .Lparse_edid
-        decb    sym_phys(opt_edd)     /* opt_edd=0: edd=on (default) */
-
-.Lparse_edid:
-        /* Check for 'edid=' command-line option. */
-        movl    $sym_phys(.Ledid_opt),4(%esp)
-        call    .Lfind_option
-        test    %eax,%eax
-        jz      .Lparse_vga
-        cmpb    $'=',4(%eax)
-        jne     .Lparse_vga
-        add     $5,%eax
-        mov     %eax,%ebx
-        push    %ebx
-        pushl   $sym_phys(.Ledid_force)
-        call    .Lstr_prefix
-        add     $8,%esp
-        movb    $2,sym_phys(opt_edid) /* opt_edid=2: edid=force */
-        test    %eax,%eax
-        jz      .Lparse_vga
-        push    %ebx
-        pushl   $sym_phys(.Ledid_no)
-        call    .Lstr_prefix
-        add     $8,%esp
-        decb    sym_phys(opt_edid)    /* opt_edid=1: edid=no */
-        test    %eax,%eax
-        jz      .Lparse_vga
-        decb    sym_phys(opt_edid)    /* opt_edid=0: default */
-
-.Lparse_vga:
-        /* Check for 'vga=' command-line option. */
-        movl    $sym_phys(.Lvga_opt),4(%esp)
-        call    .Lfind_option
-        add     $8,%esp
-        test    %eax,%eax
-        jz      .Lcmdline_exit
-        cmpb    $'=',3(%eax)
-        jne     .Lcmdline_exit
-        add     $4,%eax
-
-        /* Found the 'vga=' option. Default option is to display vga menu. */
-        movw    $ASK_VGA,sym_phys(boot_vid_mode)
-
-        /* Check for 'vga=text-80x<rows>. */
-        mov     %eax,%ebx
-        push    %ebx
-        pushl   $sym_phys(.Lvga_text80)
-        call    .Lstr_prefix
-        add     $8,%esp
-        test    %eax,%eax
-        jnz     .Lparse_vga_gfx
-
-        /* We have 'vga=text-80x<rows>'. */
-        add     $8,%ebx
-        push    %ebx
-        call    .Latoi
-        add     $4,%esp
-        mov     %ax,%bx
-        lea     sym_phys(.Lvga_text_modes),%esi
-1:      lodsw
-        test    %ax,%ax
-        jz      .Lcmdline_exit
-        cmp     %ax,%bx
-        lodsw
-        jne     1b
-        mov     %ax,sym_phys(boot_vid_mode)
-        jmp     .Lcmdline_exit
-
-.Lparse_vga_gfx:
-        /* Check for 'vga=gfx-<width>x<height>x<depth>'. */
-        push    %ebx
-        pushl   $sym_phys(.Lvga_gfx)
-        call    .Lstr_prefix
-        add     $8,%esp
-        test    %eax,%eax
-        jnz     .Lparse_vga_mode
-
-        /* We have 'vga=gfx-<width>x<height>x<depth>'. */
-        /* skip 'gfx-' */
-        add     $4,%ebx
-        /* parse <width> */
-        push    %ebx
-        call    .Latoi
-        pop     %esi
-        mov     %ax,sym_phys(vesa_size)+0
-        /* skip 'x' */
-        lodsb
-        cmpb    $'x',%al
-        jne     .Lcmdline_exit
-        /* parse <height> */
-        push    %esi
-        call    .Latoi
-        pop     %esi
-        mov     %ax,sym_phys(vesa_size)+2
-        /* skip 'x' */
-        lodsb
-        cmpb    $'x',%al
-        jne     .Lcmdline_exit
-        /* parse <depth> */
-        push    %esi
-        call    .Latoi
-        pop     %esi
-        mov     %ax,sym_phys(vesa_size)+4
-        /* commit to vesa mode */
-        movw    $VIDEO_VESA_BY_SIZE,sym_phys(boot_vid_mode)
-        jmp     .Lcmdline_exit
-
-.Lparse_vga_mode:
-        /* Check for 'vga=mode-<mode>'. */
-        push    %ebx
-        pushl   $sym_phys(.Lvga_mode)
-        call    .Lstr_prefix
-        add     $8,%esp
-        test    %eax,%eax
-        jnz     .Lparse_vga_current
-
-        /* We have 'vga=mode-<mode>'. */
-        add     $5,%ebx
-        push    %ebx
-        call    .Latoi
-        add     $4,%esp
-        mov     %ax,sym_phys(boot_vid_mode)
-        jmp     .Lcmdline_exit
-
-.Lparse_vga_current:
-        /* Check for 'vga=current'. */
-        push    %ebx
-        pushl   $sym_phys(.Lvga_current)
-        call    .Lstr_prefix
-        add     $8,%esp
-        test    %eax,%eax
-        jnz     .Lcmdline_exit
-
-        /* We have 'vga=current'. */
-        movw    $VIDEO_CURRENT_MODE,sym_phys(boot_vid_mode)
-
-.Lcmdline_exit:
-        popa
-        ret
-
-        .pushsection .init.rodata, "a", @progbits
-
-.Lvga_text_modes: /* rows, mode_number */
-        .word   25,VIDEO_80x25
-        .word   50,VIDEO_80x50
-        .word   43,VIDEO_80x43
-        .word   28,VIDEO_80x28
-        .word   30,VIDEO_80x30
-        .word   34,VIDEO_80x34
-        .word   60,VIDEO_80x60
-        .word   0
-
-.Lvga_opt:
-        .asciz  "vga"
-.Lvga_text80:
-        .asciz  "text-80x"
-.Lvga_gfx:
-        .asciz  "gfx-"
-.Lvga_mode:
-        .asciz  "mode-"
-.Lvga_current:
-        .asciz  "current"
-.Lno_rm_opt:
-        .asciz  "no-real-mode"
-.Ltboot_opt:
-        .asciz  "tboot"
-.Ledid_opt:
-        .asciz  "edid"
-.Ledid_force:
-        .asciz  "force"
-.Ledid_no:
-        .asciz  "no"
-.Ledd_opt:
-        .asciz  "edd"
-
-        .popsection
diff --git a/xen/arch/x86/boot/cmdline.c b/xen/arch/x86/boot/cmdline.c
new file mode 100644
index 0000000..2da804c
--- /dev/null
+++ b/xen/arch/x86/boot/cmdline.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/>.
+ *
+ * strlen(), strncmp(), strchr(), strspn() and strcspn() were copied from
+ * Linux kernel source (linux/lib/string.c).
+ *
+ * max() was copied from xen/xen/include/xen/kernel.h.
+ */
+
+/*
+ * This entry point is entered from xen/arch/x86/boot/head.S with:
+ *   - 0x4(%esp) = &cmdline,
+ *   - 0x8(%esp) = &early_boot_opts.
+ */
+asm (
+    "    .text                         \n"
+    "    .globl _start                 \n"
+    "_start:                           \n"
+    "    jmp  cmdline_parse_early      \n"
+    );
+
+#include "video.h"
+
+#define NULL	((void *)0)
+
+#define __packed	__attribute__((__packed__))
+#define __stdcall	__attribute__((__stdcall__))
+
+#define max(x,y) ({ \
+        const typeof(x) _x = (x);       \
+        const typeof(y) _y = (y);       \
+        (void) (&_x == &_y);            \
+        _x > _y ? _x : _y; })
+
+#define tolower(c) ((c) | 0x20)
+
+typedef unsigned char bool_t;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int size_t;
+
+#define FALSE		0
+#define TRUE		1
+
+#define U16_MAX		((u16)(~0U))
+#define UINT_MAX	(~0U)
+
+/* Keep in sync with trampoline.S:early_boot_opts label! */
+typedef struct __packed {
+    bool_t skip_realmode;
+    u8 opt_edd;
+    u8 opt_edid;
+    u16 boot_vid_mode;
+    u16 vesa_width;
+    u16 vesa_height;
+    u16 vesa_depth;
+} early_boot_opts_t;
+
+/*
+ * Space and TAB are obvious delimiters. However, I am
+ * adding "\n" and "\r" here too. Just in case when
+ * crazy bootloader/user puts them somewhere.
+ */
+static const char delim_chars_comma[] = ", \n\r\t";
+static const char delim_chars[] = " \n\r\t";
+
+/*
+ * static const char *delim_chars = &delim_chars_comma[1];
+ *
+ * Older compilers, e.g. gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21),
+ * put &delim_chars_comma[1] directly into *delim_chars. This means that the address
+ * in *delim_chars is not properly updated during runtime. Newer compilers are much
+ * smarter and build fully relocatable code even if above shown construct is used.
+ * However, define delim_chars[] separately to properly build Xen code on
+ * older systems.
+ */
+
+static size_t strlen(const char *s)
+{
+    const char *sc;
+
+    for ( sc = s; *sc != '\0'; ++sc )
+        /* nothing */;
+    return sc - s;
+}
+
+static int strncmp(const char *cs, const char *ct, size_t count)
+{
+    unsigned char c1, c2;
+
+    while ( count )
+    {
+        c1 = *cs++;
+        c2 = *ct++;
+        if ( c1 != c2 )
+            return c1 < c2 ? -1 : 1;
+        if ( !c1 )
+            break;
+        count--;
+    }
+    return 0;
+}
+
+static char *strchr(const char *s, int c)
+{
+    for ( ; *s != (char)c; ++s )
+        if ( *s == '\0' )
+            return NULL;
+    return (char *)s;
+}
+
+static size_t strspn(const char *s, const char *accept)
+{
+    const char *p;
+    const char *a;
+    size_t count = 0;
+
+    for ( p = s; *p != '\0'; ++p )
+    {
+        for ( a = accept; *a != '\0'; ++a )
+        {
+            if ( *p == *a )
+                break;
+        }
+        if ( *a == '\0' )
+            return count;
+        ++count;
+    }
+    return count;
+}
+
+static size_t strcspn(const char *s, const char *reject)
+{
+    const char *p;
+    const char *r;
+    size_t count = 0;
+
+    for ( p = s; *p != '\0'; ++p )
+    {
+        for ( r = reject; *r != '\0'; ++r )
+        {
+            if ( *p == *r )
+                return count;
+        }
+        ++count;
+    }
+    return count;
+}
+
+static unsigned int strtoui(const char *s, const char *stop, const char **next)
+{
+    char l;
+    unsigned int base = 10, ores = 0, res = 0;
+
+    if ( *s == '0' )
+      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
+
+    for ( ; *s != '\0'; ++s )
+    {
+        if ( stop && strchr(stop, *s) )
+            goto out;
+
+        if ( *s < '0' || (*s > '7' && base == 8) )
+        {
+            res = UINT_MAX;
+            goto out;
+        }
+
+        l = tolower(*s);
+
+        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
+        {
+            res = UINT_MAX;
+            goto out;
+        }
+
+        res *= base;
+        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
+
+        if ( ores > res )
+        {
+            res = UINT_MAX;
+            goto out;
+        }
+
+        ores = res;
+    }
+
+ out:
+    if ( next )
+      *next = s;
+
+    return res;
+}
+
+static int strmaxcmp(const char *cs, const char *ct, const char *delim_chars)
+{
+    return strncmp(cs, ct, max(strcspn(cs, delim_chars), strlen(ct)));
+}
+
+static int strsubcmp(const char *cs, const char *ct)
+{
+    return strncmp(cs, ct, strlen(ct));
+}
+
+static const char *find_opt(const char *cmdline, const char *opt, bool_t arg)
+{
+    size_t lc, lo;
+
+    lo = strlen(opt);
+
+    for ( ; ; )
+    {
+        cmdline += strspn(cmdline, delim_chars);
+
+        if ( *cmdline == '\0' )
+            return NULL;
+
+        if ( !strmaxcmp(cmdline, "--", delim_chars) )
+            return NULL;
+
+        lc = strcspn(cmdline, delim_chars);
+
+        if ( !strncmp(cmdline, opt, arg ? lo : max(lc, lo)) )
+            return cmdline + lo;
+
+        cmdline += lc;
+    }
+}
+
+static bool_t skip_realmode(const char *cmdline)
+{
+    return find_opt(cmdline, "no-real-mode", FALSE) || find_opt(cmdline, "tboot=", TRUE);
+}
+
+static u8 edd_parse(const char *cmdline)
+{
+    const char *c;
+
+    c = find_opt(cmdline, "edd=", TRUE);
+
+    if ( !c )
+        return 0;
+
+    if ( !strmaxcmp(c, "off", delim_chars) )
+        return 2;
+
+    return !strmaxcmp(c, "skipmbr", delim_chars);
+}
+
+static u8 edid_parse(const char *cmdline)
+{
+    const char *c;
+
+    c = find_opt(cmdline, "edid=", TRUE);
+
+    if ( !c )
+        return 0;
+
+    if ( !strmaxcmp(c, "force", delim_chars) )
+        return 2;
+
+    return !strmaxcmp(c, "no", delim_chars);
+}
+
+static u16 rows2vmode(unsigned int rows)
+{
+    switch ( rows )
+    {
+    case 25:
+        return VIDEO_80x25;
+
+    case 28:
+        return VIDEO_80x28;
+
+    case 30:
+        return VIDEO_80x30;
+
+    case 34:
+        return VIDEO_80x34;
+
+    case 43:
+        return VIDEO_80x43;
+
+    case 50:
+        return VIDEO_80x50;
+
+    case 60:
+        return VIDEO_80x60;
+
+    default:
+        return ASK_VGA;
+    }
+}
+
+static void vga_parse(const char *cmdline, early_boot_opts_t *ebo)
+{
+    const char *c;
+    unsigned int tmp, vesa_depth, vesa_height, vesa_width;
+
+    c = find_opt(cmdline, "vga=", TRUE);
+
+    if ( !c )
+        return;
+
+    ebo->boot_vid_mode = ASK_VGA;
+
+    if ( !strmaxcmp(c, "current", delim_chars_comma) )
+        ebo->boot_vid_mode = VIDEO_CURRENT_MODE;
+    else if ( !strsubcmp(c, "text-80x") )
+    {
+        c += strlen("text-80x");
+        ebo->boot_vid_mode = rows2vmode(strtoui(c, delim_chars_comma, NULL));
+    }
+    else if ( !strsubcmp(c, "gfx-") )
+    {
+        vesa_width = strtoui(c + strlen("gfx-"), "x", &c);
+
+        if ( vesa_width > U16_MAX )
+            return;
+
+        /*
+         * Increment c outside of strtoui() because otherwise some
+         * compiler may complain with following message:
+         * warning: operation on 'c' may be undefined.
+         */
+        ++c;
+        vesa_height = strtoui(c, "x", &c);
+
+        if ( vesa_height > U16_MAX )
+            return;
+
+        vesa_depth = strtoui(++c, delim_chars_comma, NULL);
+
+        if ( vesa_depth > U16_MAX )
+            return;
+
+        ebo->vesa_width = vesa_width;
+        ebo->vesa_height = vesa_height;
+        ebo->vesa_depth = vesa_depth;
+        ebo->boot_vid_mode = VIDEO_VESA_BY_SIZE;
+    }
+    else if ( !strsubcmp(c, "mode-") )
+    {
+        tmp = strtoui(c + strlen("mode-"), delim_chars_comma, NULL);
+
+        if ( tmp > U16_MAX )
+            return;
+
+        ebo->boot_vid_mode = tmp;
+    }
+}
+
+void __stdcall cmdline_parse_early(const char *cmdline, early_boot_opts_t *ebo)
+{
+    if ( !cmdline )
+        return;
+
+    ebo->skip_realmode = skip_realmode(cmdline);
+    ebo->opt_edd = edd_parse(cmdline);
+    ebo->opt_edid = edid_parse(cmdline);
+    vga_parse(cmdline, ebo);
+}
diff --git a/xen/arch/x86/boot/edd.S b/xen/arch/x86/boot/edd.S
index 5c80da6..73371f9 100644
--- a/xen/arch/x86/boot/edd.S
+++ b/xen/arch/x86/boot/edd.S
@@ -142,9 +142,6 @@ edd_next:
 edd_done:
         ret
 
-opt_edd:
-        .byte   0                               # edd=on/off/skipmbr
-
 GLOBAL(boot_edd_info_nr)
         .byte   0
 GLOBAL(boot_mbr_signature_nr)
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index aca5370..b832b21 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -496,6 +496,13 @@ trampoline_setup:
         cmpb    $0,sym_phys(skip_realmode)
         jnz     1f
 
+        /* Bail if there is no command line to parse. */
+        mov     sym_phys(multiboot_ptr),%ebx
+        testl   $MBI_CMDLINE,MB_flags(%ebx)
+        jz      1f
+
+        pushl   $sym_phys(early_boot_opts)
+        pushl   MB_cmdline(%ebx)
         call    cmdline_parse_early
 
 1:
@@ -514,6 +521,7 @@ trampoline_setup:
         /* Jump into the relocated trampoline. */
         lret
 
+cmdline_parse_early:
 #include "cmdline.S"
 
 reloc:
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index b013614..8a32728 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -220,8 +220,20 @@ trampoline_boot_cpu_entry:
         /* Jump to the common bootstrap entry point. */
         jmp     trampoline_protmode_entry
 
+#include "video.h"
+
+/* Keep in sync with cmdline.c:early_boot_opts_t type! */
+early_boot_opts:
 skip_realmode:
         .byte   0
+opt_edd:
+        .byte   0                               /* edd=on/off/skipmbr */
+opt_edid:
+        .byte   0                               /* EDID parsing option (force/no/default). */
+GLOBAL(boot_vid_mode)
+        .word   VIDEO_80x25                     /* If we don't run at all, assume basic video mode 3 at 80x25. */
+vesa_size:
+        .word   0,0,0                           /* width x depth x height */
 
 GLOBAL(kbd_shift_flags)
         .byte   0
diff --git a/xen/arch/x86/boot/video.S b/xen/arch/x86/boot/video.S
index 2aafbeb..335a51c 100644
--- a/xen/arch/x86/boot/video.S
+++ b/xen/arch/x86/boot/video.S
@@ -945,7 +945,6 @@ store_edid:
 #endif
         ret
 
-opt_edid:       .byte   0       # EDID parsing option (force/no/default)
 mt_end:         .word   0       # End of video mode table if built
 edit_buf:       .space  6       # Line editor buffer
 card_name:      .word   0       # Pointer to adapter name
@@ -991,12 +990,6 @@ name_bann:      .asciz  "Video adapter: "
 
 force_size:     .word   0       # Use this size instead of the one in BIOS vars
 
-vesa_size:      .word   0,0,0   # width x depth x height
-
-/* If we don't run at all, assume basic video mode 3 at 80x25. */
-        .align  2
-GLOBAL(boot_vid_mode)
-        .word   VIDEO_80x25
 GLOBAL(boot_vid_info)
         .byte   0, 0    /* orig_x, orig_y */
         .byte   3       /* text mode 3    */
-- 
1.7.10.4


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

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

* [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (13 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 14/16] x86/boot: implement early command line parser in C Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-25 14:41   ` Jan Beulich
  2016-08-19 22:43 ` [PATCH v5 16/16] x86: add multiboot2 protocol support for relocatable images Daniel Kiper
  2016-08-22 10:10 ` [PATCH v5 00/16] x86: multiboot2 protocol support Jan Beulich
  16 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Every multiboot protocol (regardless of version) compatible image must
specify its load address (in ELF or multiboot header). Multiboot protocol
compatible loader have to load image at specified address. However, there
is no guarantee that the requested memory region (in case of Xen it starts
at 1 MiB and ends at 17 MiB) where image should be loaded initially is a RAM
and it is free (legacy BIOS platforms are merciful for Xen but I found at
least one EFI platform on which Xen load address conflicts with EFI boot
services; it is Dell PowerEdge R820 with latest firmware). To cope with that
problem we must make Xen early boot code relocatable and help boot loader to
relocate image in proper way by suggesting, not requesting specific load
addresses as it is right now, allowed address ranges. This patch does former.
It does not add multiboot2 protocol interface which is done in "x86: add
multiboot2 protocol support for relocatable images" patch.

This patch changes following things:
  - default load address is changed from 1 MiB to 2 MiB; I did that because
    initial page tables are using 2 MiB huge pages and this way required
    updates for them are quite easy; it means that e.g. we avoid spacial
    cases for start and end of required memory region if it live at address
    not aligned to 2 MiB,
  - %esi and %r15d registers are used as a storage for Xen image load base
    address (%r15d shortly because %rsi is used for EFI SystemTable address
    in 64-bit code); both registers are (%esi is mostly) unused in early
    boot code and preserved during C functions calls,
  - %fs is used as base for Xen data relative addressing in 32-bit code
    if it is possible; %esi is used for that thing during error printing
    because it is not always possible to properly and efficiently
    initialize %fs.

PS I am still not convinced that move to %fs relative addressing is good
   idea. As you can see code grows larger due to GDT initialization stuff,
   etc. However, I cannot see potential gains for now and future (probably
   it would be if whole Xen code, not early boot one, played segment registers
   games). Well, maybe in one or two places where base register is not used
   in full SIB addressing mode. So, question is: does it pay? Does gains
   overweight all efforts related to %fs games? Maybe we should stay with
   %esi relative addressing? Of course I am aware that it is not perfect.
   However, IMO, it is much simpler and clearer.
   This is my suggestion. If you agree with me I can change code once again
   and back to %esi. This is not big problem. If not I am not going to argue
   longer. I will do what you request. Well, it will be nice if you convince
   me that your idea is good and I am wrong then...  ;-)))

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v4 - suggestions/fixes:
   - do not relocate Xen image if boot loader did work for us
     (suggested by Andrew Cooper and Jan Beulich),
   - initialize xen_img_load_base_addr in EFI boot code too,
   - properly initialize trampoline_xen_phys_start,
   - calculate Xen image load base address in
     x86_64 code ourselves,
     (suggested by Jan Beulich),
   - change how and when Xen image base address is printed,
   - use %fs instead of %esi for relative addressing
     (suggested by Andrew Cooper and Jan Beulich),
   - create esi_offset and fs_offset() macros in assembly,
   - calculate <final-exec-addr> mkelf32 argument automatically,
   - optimize and cleanup code,
   - improve comments,
   - improve commit message.

v3 - suggestions/fixes:
   - improve segment registers initialization
     (suggested by Jan Beulich),
   - simplify Xen image load base address calculation
     (suggested by Jan Beulich),
   - use %esi and %r15d instead of %ebp to store
     Xen image load base address,
   - use %esi instead of %fs for relative addressing;
     this way we get shorter and simpler code,
   - rename some variables and constants
     (suggested by Jan Beulich),
   - improve comments
     (suggested by Konrad Rzeszutek Wilk),
   - improve commit message
     (suggested by Jan Beulich).
---
 xen/arch/x86/Makefile          |    4 +-
 xen/arch/x86/Rules.mk          |    4 +
 xen/arch/x86/boot/head.S       |  204 +++++++++++++++++++++++++++++++---------
 xen/arch/x86/boot/trampoline.S |   10 +-
 xen/arch/x86/boot/wakeup.S     |    4 +-
 xen/arch/x86/boot/x86_64.S     |   51 ++++------
 xen/arch/x86/efi/efi-boot.h    |    3 +-
 xen/arch/x86/setup.c           |   31 +++---
 xen/arch/x86/xen.lds.S         |    8 +-
 xen/include/asm-x86/config.h   |    1 +
 xen/include/asm-x86/page.h     |    2 +-
 11 files changed, 217 insertions(+), 105 deletions(-)

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 9464b7b..df899c1 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -89,8 +89,8 @@ all_symbols =
 endif
 
 $(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32
-	./boot/mkelf32 $(notes_phdrs) $(TARGET)-syms $(TARGET) 0x100000 \
-	`$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
+	./boot/mkelf32 $(notes_phdrs) $(TARGET)-syms $(TARGET) $(XEN_IMG_OFFSET) \
+		`$(NM) -nr $(TARGET)-syms | awk '$$3 == "__end_of_image__" {print "0x"$$1}'`
 
 .PHONY: tests
 tests:
diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk
index 42be4bc..dd10afe 100644
--- a/xen/arch/x86/Rules.mk
+++ b/xen/arch/x86/Rules.mk
@@ -1,6 +1,10 @@
 ########################################
 # x86-specific definitions
 
+XEN_IMG_OFFSET = 0x200000
+
+CFLAGS += -DXEN_IMG_OFFSET=$(XEN_IMG_OFFSET)
+
 CFLAGS += -I$(BASEDIR)/include
 CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic
 CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index b832b21..a1b0c05 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -12,13 +12,16 @@
         .text
         .code32
 
-#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
+#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)
+#define esi_offset(sym)   sym_offset(sym)(%esi)
+#define fs_offset(sym)    %fs:sym_offset(sym)
 
 #define BOOT_CS32        0x0008
 #define BOOT_CS64        0x0010
 #define BOOT_DS          0x0018
 #define BOOT_PSEUDORM_CS 0x0020
 #define BOOT_PSEUDORM_DS 0x0028
+#define BOOT_FS          0x0030
 
 #define MB2_HT(name)      (MULTIBOOT2_HEADER_TAG_##name)
 #define MB2_TT(name)      (MULTIBOOT2_TAG_TYPE_##name)
@@ -94,7 +97,7 @@ multiboot2_header_start:
 
         /* EFI64 entry point. */
         mb2ht_init MB2_HT(ENTRY_ADDRESS_EFI64), MB2_HT(OPTIONAL), \
-                   sym_phys(__efi64_start)
+                   sym_offset(__efi64_start)
 
         /* Multiboot2 header end tag. */
         mb2ht_init MB2_HT(END), MB2_HT(REQUIRED)
@@ -105,12 +108,13 @@ multiboot2_header_start:
 
         .word   0
 gdt_boot_descr:
-        .word   6*8-1
-        .long   sym_phys(trampoline_gdt)
+        .word   7*8-1
+gdt_boot_base:
+        .long   sym_offset(trampoline_gdt)
         .long   0 /* Needed for 64-bit lgdt */
 
 cs32_switch_addr:
-        .long   sym_phys(cs32_switch)
+        .long   sym_offset(cs32_switch)
         .word   BOOT_CS32
 
 vga_text_buffer:
@@ -126,26 +130,26 @@ vga_text_buffer:
         .section .init.text, "ax", @progbits
 
 bad_cpu:
-        mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
+        lea     esi_offset(.Lbad_cpu_msg),%esi  # Error message
         jmp     0f
 not_multiboot:
-        mov     $(sym_phys(.Lbad_ldr_msg)),%esi # Error message
+        lea     esi_offset(.Lbad_ldr_msg),%esi  # Error message
         jmp     0f
 mb2_no_st:
-        mov     $(sym_phys(.Lbad_ldr_nst)),%esi # Error message
+        lea     esi_offset(.Lbad_ldr_nst),%esi  # Error message
         jmp     0f
 mb2_no_ih:
-        mov     $(sym_phys(.Lbad_ldr_nih)),%esi # Error message
+        lea     esi_offset(.Lbad_ldr_nih),%esi  # Error message
         jmp     0f
 mb2_no_bs:
-        mov     $(sym_phys(.Lbad_ldr_nbs)),%esi # Error message
+        lea     esi_offset(.Lbad_ldr_nbs),%esi  # Error message
         xor     %edi,%edi                       # No VGA text buffer
         jmp     1f
 mb2_efi_ia_32:
-        mov     $(sym_phys(.Lbad_efi_msg)),%esi # Error message
+        lea     esi_offset(.Lbad_efi_msg),%esi  # Error message
         xor     %edi,%edi                       # No VGA text buffer
         jmp     1f
-0:      mov     sym_phys(vga_text_buffer),%edi
+0:      mov     esi_offset(vga_text_buffer),%edi
 1:      mov     (%esi),%bl
         test    %bl,%bl        # Terminate on '\0' sentinel
         je      .Lhalt
@@ -173,6 +177,9 @@ __efi64_start:
         /* VGA is not available on EFI platforms. */
         movl   $0,vga_text_buffer(%rip)
 
+        /* Load Xen image load base address. */
+        lea     __image_base__(%rip),%r15d
+
         /* Check for Multiboot2 bootloader. */
         cmp     $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
         je      .Lefi_multiboot2_proto
@@ -288,6 +295,9 @@ run_bs:
 
         pop     %rax
 
+        /* Store Xen image load base address in place accessible for 32-bit code. */
+        mov     %r15d,%esi
+
         /* Jump to trampoline_setup after switching CPU to x86_32 mode. */
         lea     trampoline_setup(%rip),%edi
 
@@ -295,9 +305,11 @@ x86_32_switch:
         cli
 
         /* Initialise GDT. */
+        add     %esi,gdt_boot_base(%rip)
         lgdt    gdt_boot_descr(%rip)
 
         /* Reload code selector. */
+        add     %esi,cs32_switch_addr(%rip)
         ljmpl   *cs32_switch_addr(%rip)
 
         .code32
@@ -327,12 +339,8 @@ __start:
         cld
         cli
 
-        /* Initialise GDT and basic data segments. */
-        lgdt    %cs:sym_phys(gdt_boot_descr)
-        mov     $BOOT_DS,%ecx
-        mov     %ecx,%ds
-        mov     %ecx,%es
-        mov     %ecx,%ss
+        /* Load default Xen image load base address. */
+        mov     $sym_offset(__image_base__),%esi
 
         /* Bootloaders may set multiboot{1,2}.mem_lower to a nonzero value. */
         xor     %edx,%edx
@@ -388,6 +396,25 @@ __start:
         jmp     0b
 
 trampoline_bios_setup:
+        /*
+         * Called on legacy BIOS platforms only.
+         *
+         * Initialise GDT and basic data segments.
+         */
+        add     %esi,esi_offset(gdt_boot_base)
+        lgdt    esi_offset(gdt_boot_descr)
+
+        mov     $BOOT_DS,%ecx
+        mov     %ecx,%ds
+        mov     %ecx,%es
+        mov     %ecx,%ss
+        /* %esp is initialised later. */
+
+        /* Load null descriptor to unused segment registers. */
+        xor     %ecx,%ecx
+        mov     %ecx,%fs
+        mov     %ecx,%gs
+
         /* Set up trampoline segment 64k below EBDA */
         movzwl  0x40e,%ecx          /* EBDA segment */
         cmp     $0xa000,%ecx        /* sanity check (high) */
@@ -409,36 +436,93 @@ trampoline_bios_setup:
         cmovb   %edx,%ecx           /* and use the smaller */
 
 trampoline_setup:
+        /*
+         * Called on legacy BIOS and EFI platforms.
+         *
+         * Compute 0-15 bits of BOOT_FS segment descriptor base address.
+         */
+        mov     %esi,%edx
+        shl     $16,%edx
+        or      %edx,BOOT_FS+esi_offset(trampoline_gdt)
+
+        /* Compute 16-23 bits of BOOT_FS segment descriptor base address. */
+        mov     %esi,%edx
+        shr     $16,%edx
+        and     $0x000000ff,%edx
+        or      %edx,BOOT_FS+4+esi_offset(trampoline_gdt)
+
+        /* Compute 24-31 bits of BOOT_FS segment descriptor base address. */
+        mov     %esi,%edx
+        and     $0xff000000,%edx
+        or      %edx,BOOT_FS+4+esi_offset(trampoline_gdt)
+
+        /*
+         * Initialise %fs and later use it to access Xen data if possible.
+         * According to Intel 64 and IA-32 Architectures Software Developer’s
+         * Manual it is safe to do that without reloading GDTR before.
+         *
+         * Please check Intel 64 and IA-32 Architectures Software Developer’s
+         * Manual, Volume 2 (2A, 2B & 2C): Instruction Set Reference,
+         * LGDT and MOV instructions description and
+         * Intel 64 and IA-32 Architectures Software Developer’s
+         * Manual Volume 3 (3A, 3B & 3C): System Programming Guide,
+         * section 3.4.3, Segment Registers for more details.
+         *
+         * AIUI, only GDT address and limit are loaded into GDTR when
+         * lgdt is executed. Segment descriptor is loaded directly from
+         * memory into segment register (hiden part) only when relevant
+         * load instruction is used (e.g. mov %edx,%fs). Though GDT content
+         * probably could be stored in CPU cache but nothing suggest that
+         * CPU caching interfere in one way or another with segment descriptor
+         * load. So, it looks that every change in active GDT is immediately
+         * available for relevant segment descriptor load instruction.
+         *
+         * I was not able to find anything which invalidates above.
+         * So, everything suggest that we do not need an extra lgdt here.
+         */
+        mov     $BOOT_FS,%edx
+        mov     %edx,%fs
+
         /* Reserve 64kb for the trampoline. */
         sub     $0x1000,%ecx
 
         /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
         xor     %cl, %cl
         shl     $4, %ecx
-        mov     %ecx,sym_phys(trampoline_phys)
+        mov     %ecx,fs_offset(trampoline_phys)
+
+        /* Save Xen image load base address for later use. */
+        mov     %esi,fs_offset(xen_img_load_base_addr)
+        mov     %esi,fs_offset(trampoline_xen_phys_start)
+
+        /* Setup stack. %ss was initialized earlier. */
+        lea     1024+esi_offset(cpu0_stack),%esp
 
         /* Save the Multiboot info struct (after relocation) for later use. */
-        mov     $sym_phys(cpu0_stack)+1024,%esp
         push    %ecx                /* Boot trampoline address. */
         push    %ebx                /* Multiboot information address. */
         push    %eax                /* Multiboot magic. */
         call    reloc
-        mov     %eax,sym_phys(multiboot_ptr)
+        mov     %eax,fs_offset(multiboot_ptr)
 
         /*
          * Do not zero BSS on EFI platform here.
          * It was initialized earlier.
          */
-        cmpb    $0,sym_phys(skip_realmode)
+        cmpb    $0,fs_offset(skip_realmode)
         jnz     1f
 
         /* Initialize BSS (no nasty surprises!). */
-        mov     $sym_phys(__bss_start),%edi
-        mov     $sym_phys(__bss_end),%ecx
+        mov     $sym_offset(__bss_start),%edi
+        mov     $sym_offset(__bss_end),%ecx
+        push    %fs
+        pop     %es
         sub     %edi,%ecx
         shr     $2,%ecx
         xor     %eax,%eax
         rep stosl
+        push    %ds
+        pop     %es
 
 1:
         /* Interrogate CPU extended features via CPUID. */
@@ -452,8 +536,8 @@ trampoline_setup:
         jbe     1f
         mov     $0x80000001,%eax
         cpuid
-1:      mov     %edx,sym_phys(cpuid_ext_features)
-        mov     %edx,sym_phys(boot_cpu_data)+CPUINFO_FEATURE_OFFSET(X86_FEATURE_LM)
+1:      mov     %edx,fs_offset(cpuid_ext_features)
+        mov     %edx,fs_offset(boot_cpu_data)+CPUINFO_FEATURE_OFFSET(X86_FEATURE_LM)
 
         /* Check for availability of long mode. */
         bt      $cpufeat_bit(X86_FEATURE_LM),%edx
@@ -461,62 +545,88 @@ trampoline_setup:
 
         /* Stash TSC to calculate a good approximation of time-since-boot */
         rdtsc
-        mov     %eax,sym_phys(boot_tsc_stamp)
-        mov     %edx,sym_phys(boot_tsc_stamp+4)
+        mov     %eax,fs_offset(boot_tsc_stamp)
+        mov     %edx,fs_offset(boot_tsc_stamp)+4
+
+        /* Update frame addresses in page tables. */
+        mov     $((__page_tables_end-__page_tables_start)/8),%ecx
+1:      testl   $_PAGE_PRESENT,fs_offset(__page_tables_start)-8(,%ecx,8)
+        jz      2f
+        add     %esi,fs_offset(__page_tables_start)-8(,%ecx,8)
+2:      loop    1b
+
+        /* Initialise L2 boot-map/direct map page table entries (14MB). */
+        lea     esi_offset(start),%ebx
+        lea     (1<<L2_PAGETABLE_SHIFT)*7+(PAGE_HYPERVISOR|_PAGE_PSE)(%ebx),%eax
+        shr     $(L2_PAGETABLE_SHIFT-3),%ebx
+        mov     $8,%ecx
+1:      mov     %eax,fs_offset(l2_bootmap)-8(%ebx,%ecx,8)
+        mov     %eax,fs_offset(l2_identmap)-8(%ebx,%ecx,8)
+        sub     $(1<<L2_PAGETABLE_SHIFT),%eax
+        loop    1b
+
+        /* Initialise L3 boot-map page directory entry. */
+        lea     __PAGE_HYPERVISOR+(L2_PAGETABLE_ENTRIES*8)*3+esi_offset(l2_bootmap),%eax
+        mov     $4,%ecx
+1:      mov     %eax,fs_offset(l3_bootmap)-8(,%ecx,8)
+        sub     $(L2_PAGETABLE_ENTRIES*8),%eax
+        loop    1b
 
         /*
          * During boot, hook 4kB mappings of first 2MB of memory into L2.
-         * This avoids mixing cachability for the legacy VGA region, and is
-         * corrected when Xen relocates itself.
+         * This avoids mixing cachability for the legacy VGA region.
          */
-        mov     $sym_phys(l1_identmap)+__PAGE_HYPERVISOR,%edi
-        mov     %edi,sym_phys(l2_xenmap)
+        lea     __PAGE_HYPERVISOR+esi_offset(l1_identmap),%edi
+        mov     %edi,fs_offset(l2_bootmap)
 
         /* Apply relocations to bootstrap trampoline. */
-        mov     sym_phys(trampoline_phys),%edx
-        mov     $sym_phys(__trampoline_rel_start),%edi
+        mov     fs_offset(trampoline_phys),%edx
+        mov     $sym_offset(__trampoline_rel_start),%edi
+        mov     $sym_offset(__trampoline_rel_stop),%ebx
 1:
-        mov     (%edi),%eax
-        add     %edx,(%edi,%eax)
+        mov     %fs:(%edi),%eax
+        add     %edx,%fs:(%edi,%eax)
         add     $4,%edi
-        cmp     $sym_phys(__trampoline_rel_stop),%edi
+        cmp     %ebx,%edi
         jb      1b
 
         /* Patch in the trampoline segment. */
         shr     $4,%edx
-        mov     $sym_phys(__trampoline_seg_start),%edi
+        mov     $sym_offset(__trampoline_seg_start),%edi
+        mov     $sym_offset(__trampoline_seg_stop),%ebx
 1:
-        mov     (%edi),%eax
-        mov     %dx,(%edi,%eax)
+        mov     %fs:(%edi),%eax
+        mov     %dx,%fs:(%edi,%eax)
         add     $4,%edi
-        cmp     $sym_phys(__trampoline_seg_stop),%edi
+        cmp     %ebx,%edi
         jb      1b
 
         /* Do not parse command line on EFI platform here. */
-        cmpb    $0,sym_phys(skip_realmode)
+        cmpb    $0,fs_offset(skip_realmode)
         jnz     1f
 
         /* Bail if there is no command line to parse. */
-        mov     sym_phys(multiboot_ptr),%ebx
+        mov     fs_offset(multiboot_ptr),%ebx
         testl   $MBI_CMDLINE,MB_flags(%ebx)
         jz      1f
 
-        pushl   $sym_phys(early_boot_opts)
+        lea     esi_offset(early_boot_opts),%eax
+        push    %eax
         pushl   MB_cmdline(%ebx)
         call    cmdline_parse_early
 
 1:
         /* Switch to low-memory stack.  */
-        mov     sym_phys(trampoline_phys),%edi
+        mov     fs_offset(trampoline_phys),%edi
         lea     0x10000(%edi),%esp
         lea     trampoline_boot_cpu_entry-trampoline_start(%edi),%eax
         pushl   $BOOT_CS32
         push    %eax
 
         /* Copy bootstrap trampoline to low memory, below 1MB. */
-        mov     $sym_phys(trampoline_start),%esi
+        mov     $sym_offset(trampoline_start),%esi
         mov     $((trampoline_end - trampoline_start) / 4),%ecx
-        rep movsl
+        rep movsl %fs:(%esi),%es:(%edi)
 
         /* Jump into the relocated trampoline. */
         lret
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index 8a32728..cfb47a4 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -54,12 +54,20 @@ trampoline_gdt:
         /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
         .long   0x0000ffff
         .long   0x00009200
+        /*
+         * 0x0030: ring 0 Xen data, 16 MiB size, base
+         * address is computed during runtime.
+         */
+        .quad   0x00c0920000001000
 
         .pushsection .trampoline_rel, "a"
         .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
         .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
         .popsection
 
+GLOBAL(xen_img_load_base_addr)
+        .long   0
+
 GLOBAL(trampoline_misc_enable_off)
         .quad   0
 
@@ -87,7 +95,7 @@ trampoline_protmode_entry:
         mov     %ecx,%cr4
 
         /* Load pagetable base register. */
-        mov     $sym_phys(idle_pg_table),%eax
+        mov     $sym_offset(idle_pg_table),%eax
         add     bootsym_rel(trampoline_xen_phys_start,4,%eax)
         mov     %eax,%cr3
 
diff --git a/xen/arch/x86/boot/wakeup.S b/xen/arch/x86/boot/wakeup.S
index 08ea9b2..3c56d12 100644
--- a/xen/arch/x86/boot/wakeup.S
+++ b/xen/arch/x86/boot/wakeup.S
@@ -120,7 +120,7 @@ wakeup_32:
         mov     $bootsym_rel(wakeup_stack, 4, %esp)
 
         # check saved magic again
-        mov     $sym_phys(saved_magic), %eax
+        mov     $sym_offset(saved_magic),%eax
         add     bootsym_rel(trampoline_xen_phys_start, 4, %eax)
         mov     (%eax), %eax
         cmp     $0x9abcdef0, %eax
@@ -133,7 +133,7 @@ wakeup_32:
         mov     %ecx, %cr4
 
         /* Load pagetable base register */
-        mov     $sym_phys(idle_pg_table),%eax
+        mov     $sym_offset(idle_pg_table),%eax
         add     bootsym_rel(trampoline_xen_phys_start,4,%eax)
         mov     %eax,%cr3
 
diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S
index 9ab9231..9929dd0 100644
--- a/xen/arch/x86/boot/x86_64.S
+++ b/xen/arch/x86/boot/x86_64.S
@@ -81,7 +81,6 @@ GLOBAL(boot_cpu_compat_gdt_table)
         .quad 0x0000910000000000     /* per-CPU entry (limit == cpu)      */
         .align PAGE_SIZE, 0
 
-GLOBAL(__page_tables_start)
 /*
  * Mapping of first 2 megabytes of memory. This is mapped with 4kB mappings
  * to avoid type conflicts with fixed-range MTRRs covering the lowest megabyte
@@ -101,18 +100,12 @@ GLOBAL(l1_identmap)
         .endr
         .size l1_identmap, . - l1_identmap
 
-/*
- * Space for mapping the first 4GB of memory, with the first 16 megabytes
- * actualy mapped (mostly using superpages).  Uses 4x 4k pages.
- */
+GLOBAL(__page_tables_start)
+
+/* Space for mapping the first 4GB of memory. Uses 4x 4k pages. */
 GLOBAL(l2_identmap)
-        .quad sym_phys(l1_identmap) + __PAGE_HYPERVISOR
-        idx = 1
-        .rept 7
-        .quad (idx << L2_PAGETABLE_SHIFT) | PAGE_HYPERVISOR | _PAGE_PSE
-        idx = idx + 1
-        .endr
-        .fill 4 * L2_PAGETABLE_ENTRIES - 8, 8, 0
+        .quad sym_offset(l1_identmap) + __PAGE_HYPERVISOR
+        .fill 4 * L2_PAGETABLE_ENTRIES - 1, 8, 0
         .size l2_identmap, . - l2_identmap
 
 /*
@@ -121,9 +114,10 @@ GLOBAL(l2_identmap)
  * page.
  */
 GLOBAL(l2_xenmap)
-        idx = 0
-        .rept 8
-        .quad sym_phys(__image_base__) + (idx << L2_PAGETABLE_SHIFT) + (PAGE_HYPERVISOR | _PAGE_PSE)
+        .quad 0
+        idx = 1
+        .rept 7
+        .quad sym_offset(__image_base__) + (idx << L2_PAGETABLE_SHIFT) + (PAGE_HYPERVISOR | _PAGE_PSE)
         idx = idx + 1
         .endr
         .fill L2_PAGETABLE_ENTRIES - 8, 8, 0
@@ -134,7 +128,7 @@ l2_fixmap:
         idx = 0
         .rept L2_PAGETABLE_ENTRIES
         .if idx == l2_table_offset(FIXADDR_TOP - 1)
-        .quad sym_phys(l1_fixmap) + __PAGE_HYPERVISOR
+        .quad sym_offset(l1_fixmap) + __PAGE_HYPERVISOR
         .else
         .quad 0
         .endif
@@ -146,7 +140,7 @@ l2_fixmap:
 GLOBAL(l3_identmap)
         idx = 0
         .rept 4
-        .quad sym_phys(l2_identmap) + (idx << PAGE_SHIFT) + __PAGE_HYPERVISOR
+        .quad sym_offset(l2_identmap) + (idx << PAGE_SHIFT) + __PAGE_HYPERVISOR
         idx = idx + 1
         .endr
         .fill L3_PAGETABLE_ENTRIES - 4, 8, 0
@@ -157,9 +151,9 @@ l3_xenmap:
         idx = 0
         .rept L3_PAGETABLE_ENTRIES
         .if idx == l3_table_offset(XEN_VIRT_START)
-        .quad sym_phys(l2_xenmap) + __PAGE_HYPERVISOR
+        .quad sym_offset(l2_xenmap) + __PAGE_HYPERVISOR
         .elseif idx == l3_table_offset(FIXADDR_TOP - 1)
-        .quad sym_phys(l2_fixmap) + __PAGE_HYPERVISOR
+        .quad sym_offset(l2_fixmap) + __PAGE_HYPERVISOR
         .else
         .quad 0
         .endif
@@ -169,13 +163,13 @@ l3_xenmap:
 
 /* Top-level master (and idle-domain) page directory. */
 GLOBAL(idle_pg_table)
-        .quad sym_phys(l3_bootmap) + __PAGE_HYPERVISOR
+        .quad sym_offset(l3_bootmap) + __PAGE_HYPERVISOR
         idx = 1
         .rept L4_PAGETABLE_ENTRIES - 1
         .if idx == l4_table_offset(DIRECTMAP_VIRT_START)
-        .quad sym_phys(l3_identmap) + __PAGE_HYPERVISOR
+        .quad sym_offset(l3_identmap) + __PAGE_HYPERVISOR
         .elseif idx == l4_table_offset(XEN_VIRT_START)
-        .quad sym_phys(l3_xenmap) + __PAGE_HYPERVISOR
+        .quad sym_offset(l3_xenmap) + __PAGE_HYPERVISOR
         .else
         .quad 0
         .endif
@@ -185,21 +179,14 @@ GLOBAL(idle_pg_table)
 
 GLOBAL(__page_tables_end)
 
-/* Init pagetables.  Enough page directories to map into the bottom 1GB. */
+/* Init pagetables. Enough page directories to map into 4GB. */
         .section .init.data, "a", @progbits
         .align PAGE_SIZE, 0
 
 GLOBAL(l2_bootmap)
-        .quad sym_phys(l1_identmap) + __PAGE_HYPERVISOR
-        idx = 1
-        .rept 7
-        .quad (idx << L2_PAGETABLE_SHIFT) | __PAGE_HYPERVISOR | _PAGE_PSE
-        idx = idx + 1
-        .endr
-        .fill L2_PAGETABLE_ENTRIES - 8, 8, 0
+        .fill 4 * L2_PAGETABLE_ENTRIES, 8, 0
         .size l2_bootmap, . - l2_bootmap
 
 GLOBAL(l3_bootmap)
-        .quad sym_phys(l2_bootmap) + __PAGE_HYPERVISOR
-        .fill L3_PAGETABLE_ENTRIES - 1, 8, 0
+        .fill L3_PAGETABLE_ENTRIES, 8, 0
         .size l3_bootmap, . - l3_bootmap
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 2622cf7..82f4216 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -136,7 +136,7 @@ void __init free_ebmalloc_unused_mem(void)
 
     if ( ebmalloc_free )
     {
-        start = (unsigned long)ebmalloc_free - xen_phys_start;
+        start = (unsigned long)ebmalloc_free - xen_img_load_base_addr;
         start = PAGE_ALIGN(start + XEN_VIRT_START);
     }
     else
@@ -679,6 +679,7 @@ static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
         blexit(L"Xen must be loaded below 4Gb.");
     if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
         blexit(L"Xen must be loaded at a 2Mb boundary.");
+    xen_img_load_base_addr = xen_phys_start;
     trampoline_xen_phys_start = xen_phys_start;
 }
 
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index bc48351..9706b43 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -286,9 +286,6 @@ static void *__init bootstrap_map(const module_t *mod)
     if ( start >= end )
         return NULL;
 
-    if ( end <= BOOTSTRAP_MAP_BASE )
-        return (void *)(unsigned long)start;
-
     ret = (void *)(map_cur + (unsigned long)(start & mask));
     start &= ~mask;
     end = (end + mask) & ~mask;
@@ -674,6 +671,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     printk("Command line: %s\n", cmdline);
 
+    printk("Xen image load base address: 0x%08x\n", xen_img_load_base_addr);
+
     printk("Video information:\n");
 
     /* Print VGA display mode information. */
@@ -861,15 +860,17 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         highmem_start &= ~((1UL << L3_PAGETABLE_SHIFT) - 1);
 #endif
 
+    /* Do not relocate Xen image if boot loader did work for us. */
+    if ( xen_img_load_base_addr )
+        xen_phys_start = xen_img_load_base_addr;
+
     for ( i = boot_e820.nr_map-1; i >= 0; i-- )
     {
         uint64_t s, e, mask = (1UL << L2_PAGETABLE_SHIFT) - 1;
         uint64_t end, limit = ARRAY_SIZE(l2_identmap) << L2_PAGETABLE_SHIFT;
 
-        /* Superpage-aligned chunks from BOOTSTRAP_MAP_BASE. */
         s = (boot_e820.map[i].addr + mask) & ~mask;
         e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
-        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
         if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
             continue;
 
@@ -901,7 +902,6 @@ void __init noreturn __start_xen(unsigned long mbi_p)
             l4_pgentry_t *pl4e;
             l3_pgentry_t *pl3e;
             l2_pgentry_t *pl2e;
-            uint64_t load_start;
             int i, j, k;
 
             /* Select relocation address. */
@@ -915,9 +915,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
              * with a barrier(). After this we must *not* modify static/global
              * data until after we have switched to the relocated pagetables!
              */
-            load_start = (unsigned long)_start - XEN_VIRT_START;
             barrier();
-            move_memory(e + load_start, load_start, _end - _start, 1);
+            move_memory(e + XEN_IMG_OFFSET, XEN_IMG_OFFSET, _end - _start, 1);
 
             /* Walk initial pagetables, relocating page directory entries. */
             pl4e = __va(__pa(idle_pg_table));
@@ -933,7 +932,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                     /* Not present, 1GB mapping, or already relocated? */
                     if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) ||
                          (l3e_get_flags(*pl3e) & _PAGE_PSE) ||
-                         (l3e_get_pfn(*pl3e) > 0x1000) )
+                         (l3e_get_pfn(*pl3e) > PFN_DOWN(xen_phys_start)) )
                         continue;
                     *pl3e = l3e_from_intpte(l3e_get_intpte(*pl3e) +
                                             xen_phys_start);
@@ -943,7 +942,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                         /* Not present, PSE, or already relocated? */
                         if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ||
                              (l2e_get_flags(*pl2e) & _PAGE_PSE) ||
-                             (l2e_get_pfn(*pl2e) > 0x1000) )
+                             (l2e_get_pfn(*pl2e) > PFN_DOWN(xen_phys_start)) )
                             continue;
                         *pl2e = l2e_from_intpte(l2e_get_intpte(*pl2e) +
                                                 xen_phys_start);
@@ -957,15 +956,14 @@ void __init noreturn __start_xen(unsigned long mbi_p)
              * Undo the temporary-hooking of the l1_identmap.  __2M_text_start
              * is contained in this PTE.
              */
-            BUG_ON(l2_table_offset((unsigned long)_erodata) ==
-                   l2_table_offset((unsigned long)_stext));
             *pl2e++ = l2e_from_pfn(xen_phys_start >> PAGE_SHIFT,
                                    PAGE_HYPERVISOR_RX | _PAGE_PSE);
             for ( i = 1; i < L2_PAGETABLE_ENTRIES; i++, pl2e++ )
             {
                 unsigned int flags;
 
-                if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+                if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ||
+                     (l2e_get_pfn(*pl2e) > PFN_DOWN(xen_phys_start)) )
                     continue;
 
                 if ( !using_2M_mapping() )
@@ -1019,6 +1017,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                 : "memory" );
 
             bootstrap_map(NULL);
+
+            printk("New Xen image base address: 0x%08lx\n", xen_phys_start);
         }
 
         /* Is the region suitable for relocating the multiboot modules? */
@@ -1082,6 +1082,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     if ( !xen_phys_start )
         panic("Not enough memory to relocate Xen.");
+
     reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end));
 
     /* Late kexec reservation (dynamic start address). */
@@ -1154,14 +1155,12 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
         set_pdx_range(s >> PAGE_SHIFT, e >> PAGE_SHIFT);
 
-        /* Need to create mappings above BOOTSTRAP_MAP_BASE. */
-        map_s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
+        map_s = s;
         map_e = min_t(uint64_t, e,
                       ARRAY_SIZE(l2_identmap) << L2_PAGETABLE_SHIFT);
 
         /* Pass mapped memory to allocator /before/ creating new mappings. */
         init_boot_pages(s, min(map_s, e));
-        s = map_s;
         if ( s < map_e )
         {
             uint64_t mask = (1UL << L2_PAGETABLE_SHIFT) - 1;
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index a6246c0..a0d1ea3 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -55,7 +55,7 @@ SECTIONS
   __2M_text_start = .;         /* Start of 2M superpages, mapped RX. */
 #endif
 
-  . = __XEN_VIRT_START + MB(1);
+  . = __XEN_VIRT_START + XEN_IMG_OFFSET;
   _start = .;
   .text : {
         _stext = .;            /* Text and read-only data */
@@ -257,12 +257,14 @@ SECTIONS
   .reloc : {
     *(.reloc)
   } :text
-  /* Trick the linker into setting the image size to exactly 16Mb. */
   . = ALIGN(__section_alignment__);
+#endif
+
+  /* Trick the linker into setting the image size to exactly 16Mb. */
   .pad : {
     . = ALIGN(MB(16));
+    __end_of_image__ = .;
   } :text
-#endif
 
   efi = DEFINED(efi) ? efi : .;
 
diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h
index 6fd84e7..f5a2d2f 100644
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -96,6 +96,7 @@ extern unsigned long trampoline_phys;
                  trampoline_phys-__pa(trampoline_start)))
 extern char trampoline_start[], trampoline_end[];
 extern char trampoline_realmode_entry[];
+extern unsigned int xen_img_load_base_addr;
 extern unsigned int trampoline_xen_phys_start;
 extern unsigned char trampoline_cpu_started;
 extern char wakeup_start[];
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index 4ae387f..7324afe 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -288,7 +288,7 @@ extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES];
 extern l2_pgentry_t  *compat_idle_pg_table_l2;
 extern unsigned int   m2p_compat_vstart;
 extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES],
-    l2_bootmap[L2_PAGETABLE_ENTRIES];
+    l2_bootmap[4*L2_PAGETABLE_ENTRIES];
 extern l3_pgentry_t l3_bootmap[L3_PAGETABLE_ENTRIES];
 extern l2_pgentry_t l2_identmap[4*L2_PAGETABLE_ENTRIES];
 extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES],
-- 
1.7.10.4


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

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

* [PATCH v5 16/16] x86: add multiboot2 protocol support for relocatable images
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (14 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 15/16] x86: make Xen early boot code relocatable Daniel Kiper
@ 2016-08-19 22:43 ` Daniel Kiper
  2016-08-22 10:10 ` [PATCH v5 00/16] x86: multiboot2 protocol support Jan Beulich
  16 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-19 22:43 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, sstabellini, andrew.cooper3, cardoe, pgnet.dev, ning.sun,
	david.vrabel, jbeulich, qiaowei.ren, gang.wei, fu.wei

Add multiboot2 protocol support for relocatable images. Only GRUB2 with
"multiboot2: Add support for relocatable images" patch understands
that feature. Older multiboot protocol (regardless of version)
compatible loaders ignore it and everything works as usual.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v4 - suggestions/fixes:
   - do not get Xen image load base address from
     multiboot2 information in x86_64 code
     (suggested by Jan Beulich),
   - improve label names
     (suggested by Jan Beulich),
   - improve comments,
     (suggested by Jan Beulich).

v3 - suggestions/fixes:
   - use %esi and %r15d instead of %ebp to store
     Xen image load base address,
   - rename some types and constants,
   - reformat xen/include/xen/multiboot2.h
     (suggested by Konrad Rzeszutek Wilk),
   - improve comments,
   - improve commit message
     (suggested by Konrad Rzeszutek Wilk).
---
 xen/arch/x86/boot/head.S          |   19 ++++++++++++++++++-
 xen/arch/x86/x86_64/asm-offsets.c |    1 +
 xen/include/xen/multiboot2.h      |   13 +++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index a1b0c05..25a92e0 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -82,6 +82,13 @@ multiboot2_header_start:
         /* Align modules at page boundry. */
         mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
 
+        /* Load address preference. */
+        mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \
+                   sym_offset(start), /* Min load address. */ \
+                   0xffffffff, /* The end of image max load address (4 GiB - 1). */ \
+                   0x200000, /* Load address alignment (2 MiB). */ \
+                   MULTIBOOT2_LOAD_PREFERENCE_HIGH
+
         /* Console flags tag. */
         mb2ht_init MB2_HT(CONSOLE_FLAGS), MB2_HT(OPTIONAL), \
                    MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
@@ -372,10 +379,19 @@ __start:
         cmp     %edi,MB2_fixed_total_size(%ebx)
         jbe     trampoline_bios_setup
 
+        /* Get Xen image load base address from Multiboot2 information. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%ecx)
+        jne     1f
+
+        mov     MB2_load_base_addr(%ecx),%esi
+        sub     $XEN_IMG_OFFSET,%esi
+        jmp     9f
+
+1:
         /* Get mem_lower from Multiboot2 information. */
         cmpl    $MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,MB2_tag_type(%ecx)
         cmove   MB2_mem_lower(%ecx),%edx
-        je      trampoline_bios_setup
+        je      9f
 
         /* EFI IA-32 platforms are not supported. */
         cmpl    $MULTIBOOT2_TAG_TYPE_EFI32,MB2_tag_type(%ecx)
@@ -389,6 +405,7 @@ __start:
         cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%ecx)
         je      trampoline_bios_setup
 
+9:
         /* Go to next Multiboot2 information tag. */
         add     MB2_tag_size(%ecx),%ecx
         add     $(MULTIBOOT2_TAG_ALIGN-1),%ecx
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 9695ea6..022c280 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -175,6 +175,7 @@ void __dummy__(void)
     OFFSET(MB2_fixed_total_size, multiboot2_fixed_t, total_size);
     OFFSET(MB2_tag_type, multiboot2_tag_t, type);
     OFFSET(MB2_tag_size, multiboot2_tag_t, size);
+    OFFSET(MB2_load_base_addr, multiboot2_tag_load_base_addr_t, load_base_addr);
     OFFSET(MB2_mem_lower, multiboot2_tag_basic_meminfo_t, mem_lower);
     OFFSET(MB2_efi64_st, multiboot2_tag_efi64_t, pointer);
     OFFSET(MB2_efi64_ih, multiboot2_tag_efi64_ih_t, pointer);
diff --git a/xen/include/xen/multiboot2.h b/xen/include/xen/multiboot2.h
index 8dd5800..feb4297 100644
--- a/xen/include/xen/multiboot2.h
+++ b/xen/include/xen/multiboot2.h
@@ -59,11 +59,17 @@
 #define MULTIBOOT2_HEADER_TAG_EFI_BS			7
 #define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI32	8
 #define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI64	9
+#define MULTIBOOT2_HEADER_TAG_RELOCATABLE		10
 
 /* Header tag flags. */
 #define MULTIBOOT2_HEADER_TAG_REQUIRED			0
 #define MULTIBOOT2_HEADER_TAG_OPTIONAL			1
 
+/* Where image should be loaded (suggestion not requirement). */
+#define MULTIBOOT2_LOAD_PREFERENCE_NONE			0
+#define MULTIBOOT2_LOAD_PREFERENCE_LOW			1
+#define MULTIBOOT2_LOAD_PREFERENCE_HIGH			2
+
 /* Header console tag console_flags. */
 #define MULTIBOOT2_CONSOLE_FLAGS_CONSOLE_REQUIRED	1
 #define MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED	2
@@ -90,6 +96,7 @@
 #define MULTIBOOT2_TAG_TYPE_EFI_BS			18
 #define MULTIBOOT2_TAG_TYPE_EFI32_IH			19
 #define MULTIBOOT2_TAG_TYPE_EFI64_IH			20
+#define MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR		21
 
 /* Multiboot 2 tag alignment. */
 #define MULTIBOOT2_TAG_ALIGN				8
@@ -120,6 +127,12 @@ typedef struct {
 typedef struct {
     u32 type;
     u32 size;
+    u32 load_base_addr;
+} multiboot2_tag_load_base_addr_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
     char string[];
 } multiboot2_tag_string_t;
 
-- 
1.7.10.4


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

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

* Re: [PATCH v5 00/16] x86: multiboot2 protocol support
  2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
                   ` (15 preceding siblings ...)
  2016-08-19 22:43 ` [PATCH v5 16/16] x86: add multiboot2 protocol support for relocatable images Daniel Kiper
@ 2016-08-22 10:10 ` Jan Beulich
  2016-08-30 14:15   ` Daniel Kiper
  16 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-22 10:10 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> The final goal is xen.efi binary file which could be loaded by EFI
> loader, multiboot (v1) protocol (only on legacy BIOS platforms) and
> multiboot2 protocol. This way we will have:
>   - smaller Xen code base,
>   - one code base for xen.gz and xen.efi,
>   - one build method for xen.gz and xen.efi;
>     xen.efi will be extracted from xen(-syms)
>     file using objcopy or special custom tool,
>   - xen.efi build will not so strongly depend
>     on a given GCC and binutils version.

Just in case you aren't aware: The partial revert done by
0b8a172444 ("x86: partially revert use of 2M mappings for
hypervisor image") now puts us a step further away from that
goal, compared to when you had started your work.

Jan


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

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

* Re: [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms...
  2016-08-19 22:43 ` [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms Daniel Kiper
@ 2016-08-25 11:19   ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 11:19 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> ..nor EFI platforms with runtime services enabled.
> 
> Suggested-by: Jan Beulich <jbeulich@suse.com>
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
> ---
> v5 - suggestions/fixes:
>    - fix build error
>      (suggested by Jan Beulich),
>    - improve commit message.

Not really - it is now stale, as there's no checking of whether runtime
service use is allowed. I also don't see what change in behavior this
patch brings when viewed on its own. I think instead of fixing the
prior build error you'd better have moved this later in the series.

Jan


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

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

* Re: [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table
  2016-08-19 22:43 ` [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table Daniel Kiper
@ 2016-08-25 11:21   ` Jan Beulich
  2016-08-30 14:27     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 11:21 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> Its visibility is not needed and just pollute symbol table.
> 
> Suggested-by: Jan Beulich <jbeulich@suse.com>
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>

With Andrew effectively having NAK-ed v4 of this patch, I don't see
why - without further argumentation - this has been included again.

Jan


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

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

* Re: [PATCH v5 03/16] x86/boot: create *.lnk files with linker script
  2016-08-19 22:43 ` [PATCH v5 03/16] x86/boot: create *.lnk files with linker script Daniel Kiper
@ 2016-08-25 11:28   ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 11:28 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> Newer GCC (e.g. gcc version 5.1.1 20150618 (Red Hat 5.1.1-4) (GCC)) does
> some code optimizations by creating data sections (e.g. jump addresses
> for C switch/case are calculated using data in .rodata section). This
> thing is not accepted by *.lnk build recipe which requires that only .text
> section lives in output. Potentially we can inhibit this GCC behavior by
> using special options, e.g. -fno-tree-switch-conversion. However, this
> does not guarantee that in the future new similar optimizations or anything
> else which creates not accepted sections will not break our build recipes
> again. I do not mention that probably this is not good idea to just disable
> random optimizations. So, take over full control on *.lnk linking process
> by using linker script and merge all text and data sections into one
> .text section.
> 
> Additionally, remove .got.plt section which is not used in our final code.
> 
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>

I'm still not overly happy with the description, as it make things look
like we need this immediately when - aiui - it's only a prereq for your
later additions, but nevertheless

Reviewed-by: Jan Beulich <jbeulich@suse.com>


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

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

* Re: [PATCH v5 04/16] x86/boot/reloc: reduce assembly usage as much as possible
  2016-08-19 22:43 ` [PATCH v5 04/16] x86/boot/reloc: reduce assembly usage as much as possible Daniel Kiper
@ 2016-08-25 11:29   ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 11:29 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> ..to increase code readability and ease its maintenance.
> 
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>


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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-19 22:43 ` [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions Daniel Kiper
@ 2016-08-25 11:34   ` Jan Beulich
  2016-08-30 14:32     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 11:34 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> Create generic alloc and copy functions. We need
> separate tools for memory allocation and copy to
> provide multiboot2 protocol support.
> 
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>

The amount of casting in this patch alone looks very reasonable now.
Before ack-ing this and respective subsequent patches I'd like to see
the final result though. To facilitate that I have to re-raise a previously
asked question: Do you have a tree somewhere which one could use
to look at the final result?

Jan


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

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

* Re: [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-19 22:43 ` [PATCH v5 09/16] x86: add multiboot2 protocol support Daniel Kiper
@ 2016-08-25 11:50   ` Jan Beulich
  2016-08-30 14:41     ` Daniel Kiper
  2016-08-31 20:18   ` Andrew Cooper
  1 sibling, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 11:50 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> +        case MULTIBOOT2_TAG_TYPE_MMAP:
> +            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
> +                break;
> +
> +            mbi_out->flags |= MBI_MEMMAP;
> +            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
> +            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
> +            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
> +            mbi_out->mmap_length *= sizeof(memory_map_t);
> +
> +            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);
> +
> +            mmap_src = get_mb2_data(tag, mmap, entries);
> +            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;
> +
> +            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
> +            {
> +                /* Init size member properly. */
> +                mmap_dst[i].size = sizeof(memory_map_t);
> +                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
> +                /* Now copy a given region data. */
> +                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);

Why do you multiply by i here? The way you've written it you want to
increment mmap_src by entry_size _at the end_ of each iteration. Or
else you need a second variable.

Jan


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

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

* Re: [PATCH v5 10/16] efi: create efi_enabled()
  2016-08-19 22:43 ` [PATCH v5 10/16] efi: create efi_enabled() Daniel Kiper
@ 2016-08-25 12:16   ` Jan Beulich
  2016-08-30 17:19     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 12:16 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> --- a/xen/arch/x86/efi/stub.c
> +++ b/xen/arch/x86/efi/stub.c
> @@ -4,9 +4,10 @@
>  #include <xen/lib.h>
>  #include <asm/page.h>
>  
> -#ifndef efi_enabled
> -const bool_t efi_enabled = 0;
> -#endif
> +bool_t efi_enabled(int feature)
> +{
> +    return false;
> +}

Plain bool please, the more that you use false. And I'm relatively
certain I did ask for the parameter type to be unsigned int, as you
don't mean to pass negative values.

> @@ -739,8 +739,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>          l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] =
>              l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR);
>  
> -        memmap_type = loader;
> +        memmap_type = "EFI";
>      }
> +    else if ( efi_enabled(EFI_BOOT) )
> +        memmap_type = "EFI";

Is the change ahead of the "else" really necessary?

> @@ -1078,7 +1080,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>  
>      if ( !xen_phys_start )
>          panic("Not enough memory to relocate Xen.");
> -    reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start),
> +    reserve_e820_ram(&boot_e820, efi_enabled(EFI_BOOT) ? mbi->mem_upper : __pa(&_start),

Is this really EFI_BOOT and not EFI_LOADER?

> @@ -1153,7 +1160,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>  
>  #ifndef CONFIG_ARM /* TODO - runtime service support */
>  
> -static bool_t __initdata efi_rs_enable = 1;
>  static bool_t __initdata efi_map_uc;
>  
>  static void __init parse_efi_param(char *s)
> @@ -1171,7 +1177,10 @@ static void __init parse_efi_param(char *s)
>              *ss = '\0';
>  
>          if ( !strcmp(s, "rs") )
> -            efi_rs_enable = val;
> +        {
> +            if ( !val )
> +                __clear_bit(EFI_RS, &efi_flags);

"else __set_bit(...)" to continue to allow to override an earlier
"efi=no-rs".

> @@ -43,6 +37,9 @@ UINT64 __read_mostly efi_boot_max_var_store_size;
>  UINT64 __read_mostly efi_boot_remain_var_store_size;
>  UINT64 __read_mostly efi_boot_max_var_size;
>  
> +/* Bit fields representing available EFI features/properties. */

Bit field ...

> +unsigned long efi_flags;

An unsigned int would suffice for now, afaict.

> @@ -53,6 +50,12 @@ struct efi __read_mostly efi = {
>  
>  const struct efi_pci_rom *__read_mostly efi_pci_roms;
>  
> +/* Test whether EFI_* bits are enabled. */
> +bool_t efi_enabled(int feature)
> +{
> +    return test_bit(feature, &efi_flags);
> +}

Please either make the comment useful, or drop it.

> --- a/xen/include/xen/efi.h
> +++ b/xen/include/xen/efi.h
> @@ -2,13 +2,17 @@
>  #define __XEN_EFI_H__
>  
>  #ifndef __ASSEMBLY__
> +#include <xen/bitops.h>

If efi_enabled() doesn't get inlined here I don't see what you need
this include for.

Jan


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

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

* Re: [PATCH v5 11/16] efi: build xen.gz with EFI code
  2016-08-19 22:43 ` [PATCH v5 11/16] efi: build xen.gz with EFI code Daniel Kiper
@ 2016-08-25 12:23   ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 12:23 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> Build xen.gz with EFI code. We need this to support multiboot2
> protocol on EFI platforms.
> 
> If we wish to load non-ELF file using multiboot (v1) or multiboot2 then
> it must contain "linear" (or "flat") representation of code and data.
> This is requirement of both boot protocols. Currently, PE file contains
> many sections which are not "linear" (one after another without any holes)
> or even do not have representation in a file (e.g. BSS). From EFI point
> of view everything is OK and works. However, this file layout cannot be
> properly interpreted by multiboot protocols family. In theory there is
> a chance that we could build proper PE file (from multiboot protocols POV)
> using current build system. However, it means that xen.efi further diverge
> from Xen ELF file (in terms of contents and build method). On the other
> hand ELF has all needed properties. So, it means that this is good starting
> point for further development. Additionally, I think that this is also good
> starting point for further xen.efi code and build optimizations. It looks
> that there is a chance that finally we can generate xen.efi directly from
> Xen ELF using just simple objcopy or other tool. This way we will have one
> Xen binary which can be loaded by three boot protocols: EFI native loader,
> multiboot (v1) and multiboot2.
> 
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
> Acked-by: Jan Beulich <jbeulich@suse.com>
> ---
> v5 - suggestions/fixes:
>    - properly calculate efi symbol address in
>      xen/arch/x86/xen.lds.S (I hope that this
>      change does not invalidate Jan's ACK).

Looks okay. But there's one more thing:

> @@ -309,6 +312,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
>      EFI_STATUS status = EFI_NOT_STARTED;
>      int rc = 0;
>  
> +    if ( !efi_enabled(EFI_RS) )
> +        return -ENOSYS;

I think this should be two checks:

    if ( !efi_enabled(EFI_BOOT) )
        return -ENOSYS;
    if ( !efi_enabled(EFI_RS) )
        return -EOPNOTSUPP;

Jan



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

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

* Re: [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-08-19 22:43 ` [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms Daniel Kiper
@ 2016-08-25 12:59   ` Jan Beulich
  2016-08-30 19:32     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 12:59 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> @@ -100,19 +107,45 @@ multiboot2_header_start:
>  gdt_boot_descr:
>          .word   6*8-1
>          .long   sym_phys(trampoline_gdt)
> +        .long   0 /* Needed for 64-bit lgdt */
> +
> +cs32_switch_addr:
> +        .long   sym_phys(cs32_switch)
> +        .word   BOOT_CS32
> +
> +vga_text_buffer:
> +        .long   0xb8000

This now ends up being misaligned. Not a big deal, but anyway.

>          .section .init.text, "ax", @progbits
>  
>  bad_cpu:
>          mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
> -        jmp     print_err
> +        jmp     0f
>  not_multiboot:
>          mov     $(sym_phys(.Lbad_ldr_msg)),%esi # Error message
> -print_err:
> -        mov     $0xB8000,%edi  # VGA framebuffer
> +        jmp     0f
> +mb2_no_st:
> +        mov     $(sym_phys(.Lbad_ldr_nst)),%esi # Error message
> +        jmp     0f
> +mb2_no_ih:
> +        mov     $(sym_phys(.Lbad_ldr_nih)),%esi # Error message
> +        jmp     0f
> +mb2_no_bs:
> +        mov     $(sym_phys(.Lbad_ldr_nbs)),%esi # Error message
> +        xor     %edi,%edi                       # No VGA text buffer
> +        jmp     1f
> +mb2_efi_ia_32:
> +        mov     $(sym_phys(.Lbad_efi_msg)),%esi # Error message
> +        xor     %edi,%edi                       # No VGA text buffer
> +        jmp     1f
> +0:      mov     sym_phys(vga_text_buffer),%edi
>  1:      mov     (%esi),%bl

All the labels you add should imo be .L ones. And the two numeric
labels, considering their use across other label boundaries, would
perhaps better become .L ones too.

> +__efi64_start:
> +        cld
> +
> +        /* VGA is not available on EFI platforms. */
> +        movl   $0,vga_text_buffer(%rip)
> +
> +        /* Check for Multiboot2 bootloader. */
> +        cmp     $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
> +        je      .Lefi_multiboot2_proto
> +
> +        /* Jump to not_multiboot after switching CPU to x86_32 mode. */
> +        lea     not_multiboot(%rip),%edi
> +        jmp     x86_32_switch

Does the boot loader, btw, make any guarantees towards placing
the image below 4G?

> +.Lefi_multiboot2_proto:
> +        /* Zero EFI SystemTable and EFI ImageHandle addresses. */
> +        xor     %esi,%esi
> +        xor     %edi,%edi
> +
> +        /* Skip Multiboot2 information fixed part. */
> +        lea     (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%ebx),%ecx

As indicated before - please use %rbx here; there's no need for
having a pointless address size prefix.

> +        and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
> +
> +0:
> +        /* Check Multiboot2 information total size. */
> +        mov     %ecx,%r8d
> +        sub     %ebx,%r8d
> +        cmp     %r8d,MB2_fixed_total_size(%rbx)
> +        jbe     run_bs
> +
> +        /* Are EFI boot services available? */
> +        cmpl    $MULTIBOOT2_TAG_TYPE_EFI_BS,MB2_tag_type(%rcx)
> +        jne     1f
> +
> +        /* Yes, skip real mode and do not do other unneeded things. */
> +        incb    skip_realmode(%rip)
> +        jmp     9f

I think this comment need extending: Why again is not skipping
real mode fine if there's no such tag, no matter that we got called
in 64-bit mode here? Actually, looking further down, wasn't it that
you simply abuse that label (you jump to an error label below when
it is still zero)? That needs to be said here if so, for someone
reading the code in order to understand that there's no actual use
of real mode anywhere on this path.

> +        /*
> +         * Initialize BSS (no nasty surprises!).
> +         * It must be done earlier than in BIOS case
> +         * because efi_multiboot2() touches it.
> +         */
> +        lea     __bss_start(%rip),%edi
> +        lea     __bss_end(%rip),%ecx

In assembly code please use .startof.(.bss) and .sizeof.(.bss), as
being propose for other uses by
https://lists.xenproject.org/archives/html/xen-devel/2016-08/msg02718.html

> +        /*
> +         * IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable.
> +         * OUT: %rax - Highest available memory address below 1 MiB.

Please be more precise, as "available" leaves open how much space
is actually available there, and hence what this can be used for. Also
according to ...

> +         * MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO tag is not provided
> +         * on EFI platforms. Hence, it could not be used like
> +         * on legacy BIOS platforms.
> +         */
> +        call    efi_multiboot2
> +
> +        /* Convert memory address to bytes/16 and store it in safe place. */
> +        shr     $4,%eax
> +        mov     %eax,%ecx

... the output really is in %eax.

> @@ -223,14 +425,22 @@ trampoline_setup:
>          call    reloc
>          mov     %eax,sym_phys(multiboot_ptr)
>  
> -        /* Initialize BSS (no nasty surprises!) */
> +        /*
> +         * Do not zero BSS on EFI platform here.
> +         * It was initialized earlier.
> +         */
> +        cmpb    $0,sym_phys(skip_realmode)
> +        jnz     1f
> +
> +        /* Initialize BSS (no nasty surprises!). */
>          mov     $sym_phys(__bss_start),%edi
>          mov     $sym_phys(__bss_end),%ecx
>          sub     %edi,%ecx
> -        xor     %eax,%eax
>          shr     $2,%ecx
> +        xor     %eax,%eax
>          rep stosl

Please avoid pointless code movement like this.

> +paddr_t __init efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> +{
> +    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
> +    UINTN cols, gop_mode = ~0, rows;
> +
> +    __set_bit(EFI_BOOT, &efi_flags);
> +    __set_bit(EFI_RS, &efi_flags);
> +
> +    efi_init(ImageHandle, SystemTable);
> +
> +    efi_console_set_mode();
> +
> +    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
> +                           &cols, &rows) == EFI_SUCCESS )
> +        efi_arch_console_init(cols, rows);
> +
> +    gop = efi_get_gop();
> +
> +    if ( gop )
> +        gop_mode = efi_find_gop_mode(gop, 0, 0, 0);
> +
> +    efi_arch_edd();
> +    efi_arch_cpu();
> +
> +    efi_tables();
> +    setup_efi_pci();
> +    efi_variables();
> +
> +    if ( gop )
> +        efi_set_gop_mode(gop, gop_mode);
> +
> +    efi_exit_boot(ImageHandle, SystemTable);
> +
> +    /* Return highest available memory address below 1 MiB. */
> +    return cfg.addr;

Where is it being made certain that there are 64k of space available
right below this address, as is being assumed at trampoline_setup?

> --- a/xen/arch/x86/efi/stub.c
> +++ b/xen/arch/x86/efi/stub.c
> @@ -3,6 +3,30 @@
>  #include <xen/init.h>
>  #include <xen/lib.h>
>  #include <asm/page.h>
> +#include <asm/efibind.h>
> +#include <efi/efidef.h>
> +#include <efi/eficapsule.h>
> +#include <efi/eficon.h>
> +#include <efi/efidevp.h>
> +#include <efi/efiapi.h>
> +
> +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> +{
> +    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
> +    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
> +
> +    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
> +
> +    /* Print error message and halt the system. */
> +    asm volatile(
> +    "    call %2                      \n"
> +    "0:  hlt                          \n"
> +    "    jmp  0b                      \n"
> +       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
> +       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");

There are explanations missing here: First, a warning should be added
alongside the EFI header inclusions, making clear that no services
whatsoever can be called. And then the asm() here needs to explain
that it open codes an MS-ABI function call. Which then makes me
wonder (even if it doesn't matter much) - are the clobbers actually
correct? I think you also need to clobber rsi and rdi. Otoh there's no
need for an explicit "cc" clobber on x86.

Jan

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

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

* Re: [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-08-19 22:43 ` [PATCH v5 14/16] x86/boot: implement early command line parser in C Daniel Kiper
@ 2016-08-25 13:27   ` Jan Beulich
  2016-08-30 19:58     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 13:27 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> +#define NULL	((void *)0)
> +
> +#define __packed	__attribute__((__packed__))
> +#define __stdcall	__attribute__((__stdcall__))
> +
> +#define max(x,y) ({ \
> +        const typeof(x) _x = (x);       \
> +        const typeof(y) _y = (y);       \
> +        (void) (&_x == &_y);            \
> +        _x > _y ? _x : _y; })

Now that you add a second instance of (some of) these, please
move them to a new (local to this directory) header, e.g. defs.h.

> +#define tolower(c) ((c) | 0x20)
> +
> +typedef unsigned char bool_t;

_Bool and bool please and ...

> +typedef unsigned char u8;
> +typedef unsigned short u16;
> +typedef unsigned int size_t;
> +
> +#define FALSE		0
> +#define TRUE		1

... these replaced by true and false. In fact I see no reason why
you couldn't include xen/stdbool.h here now that it can be more
generally used.

> +/*
> + * Space and TAB are obvious delimiters. However, I am
> + * adding "\n" and "\r" here too. Just in case when
> + * crazy bootloader/user puts them somewhere.
> + */
> +static const char delim_chars_comma[] = ", \n\r\t";
> +static const char delim_chars[] = " \n\r\t";

I realize it's minor, but why two arrays instead of

#define delim_chars (delim_chars_comma + 1)

?

> +/*
> + * static const char *delim_chars = &delim_chars_comma[1];
> + *
> + * Older compilers, e.g. gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21),
> + * put &delim_chars_comma[1] directly into *delim_chars. This means that the address
> + * in *delim_chars is not properly updated during runtime. Newer compilers are much
> + * smarter and build fully relocatable code even if above shown construct is used.
> + * However, define delim_chars[] separately to properly build Xen code on
> + * older systems.
> + */

I have to admit that I don't really understand what you want to
say with this comment.

> +static unsigned int strtoui(const char *s, const char *stop, const char **next)
> +{
> +    char l;
> +    unsigned int base = 10, ores = 0, res = 0;
> +
> +    if ( *s == '0' )
> +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
> +
> +    for ( ; *s != '\0'; ++s )
> +    {
> +        if ( stop && strchr(stop, *s) )
> +            goto out;
> +
> +        if ( *s < '0' || (*s > '7' && base == 8) )
> +        {
> +            res = UINT_MAX;
> +            goto out;
> +        }
> +
> +        l = tolower(*s);
> +
> +        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
> +        {
> +            res = UINT_MAX;
> +            goto out;
> +        }
> +
> +        res *= base;
> +        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
> +
> +        if ( ores > res )
> +        {
> +            res = UINT_MAX;
> +            goto out;
> +        }

Without having spent time to try and find an example, it feels like this
check won't catch all possible overflow conditions. If you care about
overflow, please make sure you catch all cases.

> --- a/xen/arch/x86/boot/trampoline.S
> +++ b/xen/arch/x86/boot/trampoline.S
> @@ -220,8 +220,20 @@ trampoline_boot_cpu_entry:
>          /* Jump to the common bootstrap entry point. */
>          jmp     trampoline_protmode_entry
>  
> +#include "video.h"
> +
> +/* Keep in sync with cmdline.c:early_boot_opts_t type! */
> +early_boot_opts:
>  skip_realmode:
>          .byte   0
> +opt_edd:
> +        .byte   0                               /* edd=on/off/skipmbr */
> +opt_edid:
> +        .byte   0                               /* EDID parsing option (force/no/default). */
> +GLOBAL(boot_vid_mode)
> +        .word   VIDEO_80x25                     /* If we don't run at all, assume basic video mode 3 at 80x25. */
> +vesa_size:
> +        .word   0,0,0                           /* width x depth x height */

While I don't mind you using the packed attribute on the C variant,
please insert a padding byte here and there to make the four words
aligned, and add an alignment directive to make the whole structure
at least word aligned.

Jan

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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-08-19 22:43 ` [PATCH v5 15/16] x86: make Xen early boot code relocatable Daniel Kiper
@ 2016-08-25 14:41   ` Jan Beulich
  2016-08-31 14:59     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-25 14:41 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> Every multiboot protocol (regardless of version) compatible image must
> specify its load address (in ELF or multiboot header). Multiboot protocol
> compatible loader have to load image at specified address. However, there
> is no guarantee that the requested memory region (in case of Xen it starts
> at 1 MiB and ends at 17 MiB) where image should be loaded initially is a RAM
> and it is free (legacy BIOS platforms are merciful for Xen but I found at
> least one EFI platform on which Xen load address conflicts with EFI boot
> services; it is Dell PowerEdge R820 with latest firmware). To cope with that
> problem we must make Xen early boot code relocatable and help boot loader to
> relocate image in proper way by suggesting, not requesting specific load
> addresses as it is right now, allowed address ranges. This patch does former.
> It does not add multiboot2 protocol interface which is done in "x86: add
> multiboot2 protocol support for relocatable images" patch.
> 
> This patch changes following things:
>   - default load address is changed from 1 MiB to 2 MiB; I did that because
>     initial page tables are using 2 MiB huge pages and this way required
>     updates for them are quite easy; it means that e.g. we avoid spacial
>     cases for start and end of required memory region if it live at address
>     not aligned to 2 MiB,

Should this be a separate change then, to separate possible
regressions due to that from such due to any other of the changes
here? And then I don't see why, when making the image relocatable
anyway, the link time load address actually still matters.

>   - %esi and %r15d registers are used as a storage for Xen image load base
>     address (%r15d shortly because %rsi is used for EFI SystemTable address
>     in 64-bit code); both registers are (%esi is mostly) unused in early
>     boot code and preserved during C functions calls,

In a context where you (also) talk about 64-bit code, %esi can't
be called preserved unilaterally. You should make clear that this is
for 32-bit function calls.

> --- a/xen/arch/x86/boot/head.S
> +++ b/xen/arch/x86/boot/head.S
> @@ -12,13 +12,16 @@
>          .text
>          .code32
>  
> -#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
> +#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)

In a patch already large and hence hard to review, did you really
need to do this rename?

> @@ -126,26 +130,26 @@ vga_text_buffer:
>          .section .init.text, "ax", @progbits
>  
>  bad_cpu:
> -        mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
> +        lea     esi_offset(.Lbad_cpu_msg),%esi  # Error message

Why not just

        add     $sym_offset(.Lbad_cpu_msg),%esi  # Error message

? Together with not doing said rename, this would be more obviously
correct.

> @@ -409,36 +436,93 @@ trampoline_bios_setup:
>          cmovb   %edx,%ecx           /* and use the smaller */
>  
>  trampoline_setup:
> +        /*
> +         * Called on legacy BIOS and EFI platforms.
> +         *
> +         * Compute 0-15 bits of BOOT_FS segment descriptor base address.
> +         */
> +        mov     %esi,%edx
> +        shl     $16,%edx
> +        or      %edx,BOOT_FS+esi_offset(trampoline_gdt)

	mov   %si,BOOT_FS+esi_offset(trampoline_gdt)

> +        /* Compute 16-23 bits of BOOT_FS segment descriptor base address. */
> +        mov     %esi,%edx
> +        shr     $16,%edx
> +        and     $0x000000ff,%edx
> +        or      %edx,BOOT_FS+4+esi_offset(trampoline_gdt)

	mov   %dl,BOOT_FS+4+esi_offset(trampoline_gdt)

> +        /* Compute 24-31 bits of BOOT_FS segment descriptor base address. */
> +        mov     %esi,%edx
> +        and     $0xff000000,%edx
> +        or      %edx,BOOT_FS+4+esi_offset(trampoline_gdt)

	mov   %dh,BOOT_FS+7+esi_offset(trampoline_gdt)

(with various of the intermediate instructions dropped)

That'll reduce you code size concern for the GDT setup quite a bit.

> +        /*
> +         * Initialise %fs and later use it to access Xen data if possible.
> +         * According to Intel 64 and IA-32 Architectures Software Developer’s
> +         * Manual it is safe to do that without reloading GDTR before.
> +         *
> +         * Please check Intel 64 and IA-32 Architectures Software Developer’s
> +         * Manual, Volume 2 (2A, 2B & 2C): Instruction Set Reference,
> +         * LGDT and MOV instructions description and
> +         * Intel 64 and IA-32 Architectures Software Developer’s
> +         * Manual Volume 3 (3A, 3B & 3C): System Programming Guide,
> +         * section 3.4.3, Segment Registers for more details.
> +         *
> +         * AIUI, only GDT address and limit are loaded into GDTR when
> +         * lgdt is executed. Segment descriptor is loaded directly from
> +         * memory into segment register (hiden part) only when relevant
> +         * load instruction is used (e.g. mov %edx,%fs). Though GDT content
> +         * probably could be stored in CPU cache but nothing suggest that
> +         * CPU caching interfere in one way or another with segment descriptor
> +         * load. So, it looks that every change in active GDT is immediately
> +         * available for relevant segment descriptor load instruction.
> +         *
> +         * I was not able to find anything which invalidates above.
> +         * So, everything suggest that we do not need an extra lgdt here.
> +         */

All of this comment except for the first sentence is just stating basic
architecture facts. Please drop all that.

> +        mov     $BOOT_FS,%edx
> +        mov     %edx,%fs
> +
>          /* Reserve 64kb for the trampoline. */
>          sub     $0x1000,%ecx
>  
>          /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
>          xor     %cl, %cl
>          shl     $4, %ecx
> -        mov     %ecx,sym_phys(trampoline_phys)
> +        mov     %ecx,fs_offset(trampoline_phys)

Seeing the first instance, together with the earlier comment about
not renaming sym_phys() I think this would end up more consistently
with using sym_fs() (and then obviously sym_esi()) as names.

> @@ -461,62 +545,88 @@ trampoline_setup:
>  
>          /* Stash TSC to calculate a good approximation of time-since-boot */
>          rdtsc
> -        mov     %eax,sym_phys(boot_tsc_stamp)
> -        mov     %edx,sym_phys(boot_tsc_stamp+4)
> +        mov     %eax,fs_offset(boot_tsc_stamp)
> +        mov     %edx,fs_offset(boot_tsc_stamp)+4
> +
> +        /* Update frame addresses in page tables. */
> +        mov     $((__page_tables_end-__page_tables_start)/8),%ecx
> +1:      testl   $_PAGE_PRESENT,fs_offset(__page_tables_start)-8(,%ecx,8)
> +        jz      2f
> +        add     %esi,fs_offset(__page_tables_start)-8(,%ecx,8)
> +2:      loop    1b

This loop includes the mapping of the low Mb, which I don't think it
should modify. Or wait - you move __page_tables_start, which by
itself is fragile (but looks to be acceptable if accompanied by a
comment explaining why it doesn't cover l1_identmap).

Also, just to double check - all these page table setup adjustments
don't require reflecting in xen.efi's page table setup code?

>          /* Apply relocations to bootstrap trampoline. */
> -        mov     sym_phys(trampoline_phys),%edx
> -        mov     $sym_phys(__trampoline_rel_start),%edi
> +        mov     fs_offset(trampoline_phys),%edx
> +        mov     $sym_offset(__trampoline_rel_start),%edi
> +        mov     $sym_offset(__trampoline_rel_stop),%ebx
>  1:
> -        mov     (%edi),%eax
> -        add     %edx,(%edi,%eax)
> +        mov     %fs:(%edi),%eax
> +        add     %edx,%fs:(%edi,%eax)
>          add     $4,%edi
> -        cmp     $sym_phys(__trampoline_rel_stop),%edi
> +        cmp     %ebx,%edi
>          jb      1b

And again it looks like the switch to using %ebx here is not needed.

>          /* Patch in the trampoline segment. */
>          shr     $4,%edx
> -        mov     $sym_phys(__trampoline_seg_start),%edi
> +        mov     $sym_offset(__trampoline_seg_start),%edi
> +        mov     $sym_offset(__trampoline_seg_stop),%ebx
>  1:
> -        mov     (%edi),%eax
> -        mov     %dx,(%edi,%eax)
> +        mov     %fs:(%edi),%eax
> +        mov     %dx,%fs:(%edi,%eax)
>          add     $4,%edi
> -        cmp     $sym_phys(__trampoline_seg_stop),%edi
> +        cmp     %ebx,%edi
>          jb      1b

Same here then, obviously.

> --- a/xen/arch/x86/boot/trampoline.S
> +++ b/xen/arch/x86/boot/trampoline.S
> @@ -54,12 +54,20 @@ trampoline_gdt:
>          /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
>          .long   0x0000ffff
>          .long   0x00009200
> +        /*
> +         * 0x0030: ring 0 Xen data, 16 MiB size, base
> +         * address is computed during runtime.
> +         */
> +        .quad   0x00c0920000001000

This does not look like it covers 1Mb, it's more like 1Mb+4k-1.

>          .pushsection .trampoline_rel, "a"
>          .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
>          .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
>          .popsection
>  
> +GLOBAL(xen_img_load_base_addr)
> +        .long   0

I've yet to understand the purpose of this symbol, but in any case:
If the trampoline code doesn't reference it, why does it get placed
here?

> @@ -861,15 +860,17 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>          highmem_start &= ~((1UL << L3_PAGETABLE_SHIFT) - 1);
>  #endif
>  
> +    /* Do not relocate Xen image if boot loader did work for us. */
> +    if ( xen_img_load_base_addr )
> +        xen_phys_start = xen_img_load_base_addr;

Okay, with this change the question really is: Why do you need the
new symbol? I.e. why can't you just use xen_phys_start, just like I
managed to re-use it when I introduced boot from EFI?

>      for ( i = boot_e820.nr_map-1; i >= 0; i-- )
>      {
>          uint64_t s, e, mask = (1UL << L2_PAGETABLE_SHIFT) - 1;
>          uint64_t end, limit = ARRAY_SIZE(l2_identmap) << L2_PAGETABLE_SHIFT;
>  
> -        /* Superpage-aligned chunks from BOOTSTRAP_MAP_BASE. */

I can see that you want to get rid of BOOTSTRAP_MAP_BASE, but
please don't delete the comment as a whole.

>          s = (boot_e820.map[i].addr + mask) & ~mask;
>          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
> -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
>          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
>              continue;

This means you now map memory between 2Mb and 16Mb here. Is
this necessary?

> @@ -901,7 +902,6 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>              l4_pgentry_t *pl4e;
>              l3_pgentry_t *pl3e;
>              l2_pgentry_t *pl2e;
> -            uint64_t load_start;
>              int i, j, k;
>  
>              /* Select relocation address. */
> @@ -915,9 +915,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>               * with a barrier(). After this we must *not* modify static/global
>               * data until after we have switched to the relocated pagetables!
>               */
> -            load_start = (unsigned long)_start - XEN_VIRT_START;
>              barrier();
> -            move_memory(e + load_start, load_start, _end - _start, 1);
> +            move_memory(e + XEN_IMG_OFFSET, XEN_IMG_OFFSET, _end - _start, 1);

Assuming _start - XEN_VIRT_START == XEN_IMG_OFFSET, is this
change necessary? Or is it rather just simplification, which again
should be split from an already complex patch.

> @@ -957,15 +956,14 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>               * Undo the temporary-hooking of the l1_identmap.  __2M_text_start
>               * is contained in this PTE.
>               */
> -            BUG_ON(l2_table_offset((unsigned long)_erodata) ==
> -                   l2_table_offset((unsigned long)_stext));

At least when using_2M_mapping() this surely ought to hold?

> @@ -1019,6 +1017,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>                  : "memory" );
>  
>              bootstrap_map(NULL);
> +
> +            printk("New Xen image base address: 0x%08lx\n", xen_phys_start);

I don't see the motivation for adding such a message in this patch,
but if, then please use %#lx.

> @@ -1082,6 +1082,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>  
>      if ( !xen_phys_start )
>          panic("Not enough memory to relocate Xen.");
> +
>      reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end));

Another stray change.

> --- a/xen/arch/x86/xen.lds.S
> +++ b/xen/arch/x86/xen.lds.S
> @@ -55,7 +55,7 @@ SECTIONS
>    __2M_text_start = .;         /* Start of 2M superpages, mapped RX. */
>  #endif
>  
> -  . = __XEN_VIRT_START + MB(1);
> +  . = __XEN_VIRT_START + XEN_IMG_OFFSET;
>    _start = .;
>    .text : {
>          _stext = .;            /* Text and read-only data */
> @@ -257,12 +257,14 @@ SECTIONS
>    .reloc : {
>      *(.reloc)
>    } :text
> -  /* Trick the linker into setting the image size to exactly 16Mb. */
>    . = ALIGN(__section_alignment__);
> +#endif
> +
> +  /* Trick the linker into setting the image size to exactly 16Mb. */
>    .pad : {
>      . = ALIGN(MB(16));
> +    __end_of_image__ = .;

I see that you use this symbol in xen/arch/x86/Makefile, but I again
don't follow why this logic needs to change.

> --- a/xen/include/asm-x86/page.h
> +++ b/xen/include/asm-x86/page.h
> @@ -288,7 +288,7 @@ extern root_pgentry_t 
> idle_pg_table[ROOT_PAGETABLE_ENTRIES];
>  extern l2_pgentry_t  *compat_idle_pg_table_l2;
>  extern unsigned int   m2p_compat_vstart;
>  extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES],
> -    l2_bootmap[L2_PAGETABLE_ENTRIES];
> +    l2_bootmap[4*L2_PAGETABLE_ENTRIES];

Why do you need 4 of them? I can see why one might not suffice,
but two surely should?

Jan

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

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

* Re: [PATCH v5 00/16] x86: multiboot2 protocol support
  2016-08-22 10:10 ` [PATCH v5 00/16] x86: multiboot2 protocol support Jan Beulich
@ 2016-08-30 14:15   ` Daniel Kiper
  2016-08-30 15:09     ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 14:15 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Mon, Aug 22, 2016 at 04:10:04AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > The final goal is xen.efi binary file which could be loaded by EFI
> > loader, multiboot (v1) protocol (only on legacy BIOS platforms) and
> > multiboot2 protocol. This way we will have:
> >   - smaller Xen code base,
> >   - one code base for xen.gz and xen.efi,
> >   - one build method for xen.gz and xen.efi;
> >     xen.efi will be extracted from xen(-syms)
> >     file using objcopy or special custom tool,
> >   - xen.efi build will not so strongly depend
> >     on a given GCC and binutils version.
>
> Just in case you aren't aware: The partial revert done by
> 0b8a172444 ("x86: partially revert use of 2M mappings for
> hypervisor image") now puts us a step further away from that
> goal, compared to when you had started your work.

I am not sure about that. Andrew patches changed xen.gz size significantly.
My patches does not do that in significant way. They (precisely it) just
move load address from 1 MiB to 2 MiB. So, I do not expect major issues
here. However, anyway it should be tested (and it was tested, IIRC, by
Konrad some time ago).

Daniel

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

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

* Re: [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table
  2016-08-25 11:21   ` Jan Beulich
@ 2016-08-30 14:27     ` Daniel Kiper
  2016-08-30 15:11       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 14:27 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 05:21:24AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > Its visibility is not needed and just pollute symbol table.
> >
> > Suggested-by: Jan Beulich <jbeulich@suse.com>
> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
>
> With Andrew effectively having NAK-ed v4 of this patch, I don't see
> why - without further argumentation - this has been included again.

I have saw that discussion stopped somewhere in the middle, so, I was
not sure what is your final decision. However, if you approve/agree
Andrew's NAK then I think that we should use "multiboot2_header_end"
label instead of .Lmultiboot2_header_end in patch #9 (x86: add multiboot2
protocol support). Just to be in line with multiboot (v1) protocol header.

Daniel

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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-25 11:34   ` Jan Beulich
@ 2016-08-30 14:32     ` Daniel Kiper
  2016-08-30 15:12       ` Jan Beulich
  2016-09-06 15:33       ` Doug Goldstein
  0 siblings, 2 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 14:32 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 05:34:31AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > Create generic alloc and copy functions. We need
> > separate tools for memory allocation and copy to
> > provide multiboot2 protocol support.
> >
> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
>
> The amount of casting in this patch alone looks very reasonable now.
> Before ack-ing this and respective subsequent patches I'd like to see
> the final result though. To facilitate that I have to re-raise a previously
> asked question: Do you have a tree somewhere which one could use
> to look at the final result?

Sadly no.

Daniel

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

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

* Re: [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-25 11:50   ` Jan Beulich
@ 2016-08-30 14:41     ` Daniel Kiper
  2016-08-30 15:14       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 14:41 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 05:50:04AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > +        case MULTIBOOT2_TAG_TYPE_MMAP:
> > +            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
> > +                break;
> > +
> > +            mbi_out->flags |= MBI_MEMMAP;
> > +            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
> > +            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
> > +            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
> > +            mbi_out->mmap_length *= sizeof(memory_map_t);
> > +
> > +            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);
> > +
> > +            mmap_src = get_mb2_data(tag, mmap, entries);
> > +            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;
> > +
> > +            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
> > +            {
> > +                /* Init size member properly. */
> > +                mmap_dst[i].size = sizeof(memory_map_t);
> > +                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
> > +                /* Now copy a given region data. */
> > +                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);
>
> Why do you multiply by i here? The way you've written it you want to
> increment mmap_src by entry_size _at the end_ of each iteration. Or

This is another option. If you wish I can do that.

> else you need a second variable.

I think that former is better.

Daniel

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

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

* Re: [PATCH v5 00/16] x86: multiboot2 protocol support
  2016-08-30 14:15   ` Daniel Kiper
@ 2016-08-30 15:09     ` Jan Beulich
  2016-08-31 15:05       ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-30 15:09 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 16:15, <daniel.kiper@oracle.com> wrote:
> On Mon, Aug 22, 2016 at 04:10:04AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > The final goal is xen.efi binary file which could be loaded by EFI
>> > loader, multiboot (v1) protocol (only on legacy BIOS platforms) and
>> > multiboot2 protocol. This way we will have:
>> >   - smaller Xen code base,
>> >   - one code base for xen.gz and xen.efi,
>> >   - one build method for xen.gz and xen.efi;
>> >     xen.efi will be extracted from xen(-syms)
>> >     file using objcopy or special custom tool,
>> >   - xen.efi build will not so strongly depend
>> >     on a given GCC and binutils version.
>>
>> Just in case you aren't aware: The partial revert done by
>> 0b8a172444 ("x86: partially revert use of 2M mappings for
>> hypervisor image") now puts us a step further away from that
>> goal, compared to when you had started your work.
> 
> I am not sure about that. Andrew patches changed xen.gz size significantly.
> My patches does not do that in significant way. They (precisely it) just
> move load address from 1 MiB to 2 MiB. So, I do not expect major issues
> here. However, anyway it should be tested (and it was tested, IIRC, by
> Konrad some time ago).

Looks like you didn't understand: This is not about image size. The
issue is that the EFI binary, other than xen.gz, now properly uses
RX, RO, and RW permissions (and large pages) for the individual
pieces of the image. Moving to a single binary would hence result
in a (slight) regression unless that gets taken care of beforehand.

Jan


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

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

* Re: [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table
  2016-08-30 14:27     ` Daniel Kiper
@ 2016-08-30 15:11       ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-08-30 15:11 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 16:27, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 05:21:24AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > Its visibility is not needed and just pollute symbol table.
>> >
>> > Suggested-by: Jan Beulich <jbeulich@suse.com>
>> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
>>
>> With Andrew effectively having NAK-ed v4 of this patch, I don't see
>> why - without further argumentation - this has been included again.
> 
> I have saw that discussion stopped somewhere in the middle, so, I was
> not sure what is your final decision. However, if you approve/agree
> Andrew's NAK then I think that we should use "multiboot2_header_end"
> label instead of .Lmultiboot2_header_end in patch #9 (x86: add multiboot2
> protocol support). Just to be in line with multiboot (v1) protocol header.

I don't agree with Andrew, but I also won't approve and commit a
patch he did nak. Since I'm of the opinion that I should not have
given my ack to his original change, I'm going to nak introduction
of another such bogus label.

Jan


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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-30 14:32     ` Daniel Kiper
@ 2016-08-30 15:12       ` Jan Beulich
  2016-08-31 15:13         ` Daniel Kiper
  2016-09-06 15:33       ` Doug Goldstein
  1 sibling, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-30 15:12 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 16:32, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 05:34:31AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > Create generic alloc and copy functions. We need
>> > separate tools for memory allocation and copy to
>> > provide multiboot2 protocol support.
>> >
>> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
>>
>> The amount of casting in this patch alone looks very reasonable now.
>> Before ack-ing this and respective subsequent patches I'd like to see
>> the final result though. To facilitate that I have to re-raise a previously
>> asked question: Do you have a tree somewhere which one could use
>> to look at the final result?
> 
> Sadly no.

Alternatively, could you simply send the final resulting source file?

Jan


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

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

* Re: [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-30 14:41     ` Daniel Kiper
@ 2016-08-30 15:14       ` Jan Beulich
  2016-08-31 15:21         ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-30 15:14 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 16:41, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 05:50:04AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > +        case MULTIBOOT2_TAG_TYPE_MMAP:
>> > +            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
>> > +                break;
>> > +
>> > +            mbi_out->flags |= MBI_MEMMAP;
>> > +            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
>> > +            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
>> > +            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
>> > +            mbi_out->mmap_length *= sizeof(memory_map_t);
>> > +
>> > +            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);
>> > +
>> > +            mmap_src = get_mb2_data(tag, mmap, entries);
>> > +            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;
>> > +
>> > +            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
>> > +            {
>> > +                /* Init size member properly. */
>> > +                mmap_dst[i].size = sizeof(memory_map_t);
>> > +                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
>> > +                /* Now copy a given region data. */
>> > +                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);
>>
>> Why do you multiply by i here? The way you've written it you want to
>> increment mmap_src by entry_size _at the end_ of each iteration. Or
> 
> This is another option. If you wish I can do that.

This is not just another option - afaict the code as is won't work for
more than one map entry.

Jan


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

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

* Re: [PATCH v5 10/16] efi: create efi_enabled()
  2016-08-25 12:16   ` Jan Beulich
@ 2016-08-30 17:19     ` Daniel Kiper
  2016-08-31 12:31       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 17:19 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 06:16:35AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > --- a/xen/arch/x86/efi/stub.c
> > +++ b/xen/arch/x86/efi/stub.c
> > @@ -4,9 +4,10 @@
> >  #include <xen/lib.h>
> >  #include <asm/page.h>
> >
> > -#ifndef efi_enabled
> > -const bool_t efi_enabled = 0;
> > -#endif
> > +bool_t efi_enabled(int feature)
> > +{
> > +    return false;
> > +}
>
> Plain bool please, the more that you use false. And I'm relatively

What is wrong with bool_t? bool is equal to bool_t.

> certain I did ask for the parameter type to be unsigned int, as you
> don't mean to pass negative values.

Sure. However, full blown efi_enabled() calls test_bit(). Latter calls
constant_test_bit() or variable_test_bit() which take bit position as
int. So, I do not think that efi_enabled() should take unsigned int. Or
we should change constant_test_bit() and variable_test_bit() respectively.
Hmmm... No, we should not. It looks that negative offsets are valid.

> > @@ -739,8 +739,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >          l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] =
> >              l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR);
> >
> > -        memmap_type = loader;
> > +        memmap_type = "EFI";
> >      }
> > +    else if ( efi_enabled(EFI_BOOT) )
> > +        memmap_type = "EFI";
>
> Is the change ahead of the "else" really necessary?

No. However, in this case memmap_type is always "EFI" and we do not need
to get this value from loader variable. Which, of course, is always also
"EFI" (to be precise pointer to) here but IMO "memmap_type = loader" suggests
that memmap_type could be anything else.

> > @@ -1078,7 +1080,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >
> >      if ( !xen_phys_start )
> >          panic("Not enough memory to relocate Xen.");
> > -    reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start),
> > +    reserve_e820_ram(&boot_e820, efi_enabled(EFI_BOOT) ? mbi->mem_upper : __pa(&_start),
>
> Is this really EFI_BOOT and not EFI_LOADER?

Yep, it should be EFI_LOADER. I am not sure why it has changed to EFI_BOOT.
Or it did not... Anyway, it is my fault. I will fix it.

Daniel

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

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

* Re: [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-08-25 12:59   ` Jan Beulich
@ 2016-08-30 19:32     ` Daniel Kiper
  2016-08-31 12:49       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 19:32 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 06:59:54AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > @@ -100,19 +107,45 @@ multiboot2_header_start:
> >  gdt_boot_descr:
> >          .word   6*8-1
> >          .long   sym_phys(trampoline_gdt)
> > +        .long   0 /* Needed for 64-bit lgdt */
> > +
> > +cs32_switch_addr:
> > +        .long   sym_phys(cs32_switch)
> > +        .word   BOOT_CS32
> > +
> > +vga_text_buffer:
> > +        .long   0xb8000
>
> This now ends up being misaligned. Not a big deal, but anyway.
>
> >          .section .init.text, "ax", @progbits

I hope that ".align 4" is sufficient here.

> >  bad_cpu:
> >          mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
> > -        jmp     print_err
> > +        jmp     0f
> >  not_multiboot:
> >          mov     $(sym_phys(.Lbad_ldr_msg)),%esi # Error message
> > -print_err:
> > -        mov     $0xB8000,%edi  # VGA framebuffer
> > +        jmp     0f
> > +mb2_no_st:
> > +        mov     $(sym_phys(.Lbad_ldr_nst)),%esi # Error message
> > +        jmp     0f
> > +mb2_no_ih:
> > +        mov     $(sym_phys(.Lbad_ldr_nih)),%esi # Error message
> > +        jmp     0f
> > +mb2_no_bs:
> > +        mov     $(sym_phys(.Lbad_ldr_nbs)),%esi # Error message
> > +        xor     %edi,%edi                       # No VGA text buffer
> > +        jmp     1f
> > +mb2_efi_ia_32:
> > +        mov     $(sym_phys(.Lbad_efi_msg)),%esi # Error message
> > +        xor     %edi,%edi                       # No VGA text buffer
> > +        jmp     1f
> > +0:      mov     sym_phys(vga_text_buffer),%edi
> >  1:      mov     (%esi),%bl
>
> All the labels you add should imo be .L ones. And the two numeric
> labels, considering their use across other label boundaries, would
> perhaps better become .L ones too.

OK.

> > +__efi64_start:
> > +        cld
> > +
> > +        /* VGA is not available on EFI platforms. */
> > +        movl   $0,vga_text_buffer(%rip)
> > +
> > +        /* Check for Multiboot2 bootloader. */
> > +        cmp     $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
> > +        je      .Lefi_multiboot2_proto
> > +
> > +        /* Jump to not_multiboot after switching CPU to x86_32 mode. */
> > +        lea     not_multiboot(%rip),%edi
> > +        jmp     x86_32_switch
>
> Does the boot loader, btw, make any guarantees towards placing
> the image below 4G?

Yep.

[...]

> > +        /*
> > +         * IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable.
> > +         * OUT: %rax - Highest available memory address below 1 MiB.
>
> Please be more precise, as "available" leaves open how much space
> is actually available there, and hence what this can be used for. Also
> according to ...
>
> > +         * MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO tag is not provided
> > +         * on EFI platforms. Hence, it could not be used like
> > +         * on legacy BIOS platforms.
> > +         */
> > +        call    efi_multiboot2
> > +
> > +        /* Convert memory address to bytes/16 and store it in safe place. */
> > +        shr     $4,%eax
> > +        mov     %eax,%ecx
>
> ... the output really is in %eax.

efi_multiboot2() is called according to System V AMD64 ABI. So, according to it
return value is stored in %rax. Hence, from spec point of view comment is correct.
Use of %eax is a bit different thing (our need/choice) and if you wish it can be
documented accordingly.

> > @@ -223,14 +425,22 @@ trampoline_setup:
> >          call    reloc
> >          mov     %eax,sym_phys(multiboot_ptr)
> >
> > -        /* Initialize BSS (no nasty surprises!) */
> > +        /*
> > +         * Do not zero BSS on EFI platform here.
> > +         * It was initialized earlier.
> > +         */
> > +        cmpb    $0,sym_phys(skip_realmode)
> > +        jnz     1f
> > +
> > +        /* Initialize BSS (no nasty surprises!). */
> >          mov     $sym_phys(__bss_start),%edi
> >          mov     $sym_phys(__bss_end),%ecx
> >          sub     %edi,%ecx
> > -        xor     %eax,%eax
> >          shr     $2,%ecx
> > +        xor     %eax,%eax
> >          rep stosl
>
> Please avoid pointless code movement like this.

I think that shr should be close to sub because both operations are related
to some extent. However, you are right that maybe this cleanup should be in
separate patch. Does it make sense for you?

> > +paddr_t __init efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> > +{
> > +    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
> > +    UINTN cols, gop_mode = ~0, rows;
> > +
> > +    __set_bit(EFI_BOOT, &efi_flags);
> > +    __set_bit(EFI_RS, &efi_flags);
> > +
> > +    efi_init(ImageHandle, SystemTable);
> > +
> > +    efi_console_set_mode();
> > +
> > +    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
> > +                           &cols, &rows) == EFI_SUCCESS )
> > +        efi_arch_console_init(cols, rows);
> > +
> > +    gop = efi_get_gop();
> > +
> > +    if ( gop )
> > +        gop_mode = efi_find_gop_mode(gop, 0, 0, 0);
> > +
> > +    efi_arch_edd();
> > +    efi_arch_cpu();
> > +
> > +    efi_tables();
> > +    setup_efi_pci();
> > +    efi_variables();
> > +
> > +    if ( gop )
> > +        efi_set_gop_mode(gop, gop_mode);
> > +
> > +    efi_exit_boot(ImageHandle, SystemTable);
> > +
> > +    /* Return highest available memory address below 1 MiB. */
> > +    return cfg.addr;
>
> Where is it being made certain that there are 64k of space available
> right below this address, as is being assumed at trampoline_setup?

You are right. This is a bug. However, the problem is more generic
and should be fixed for all boot cases (BIOS, EFI loader and EFI with
GRUB2). Additionally, in case of BIOS and EFI with GRUB2 we should
check that it is possible to put all data from grub loader in low
memory. So, it looks that there is a place for at least two (three?)
additional patches. Do you want them at the beginning of or the end
of this patch series.

> > --- a/xen/arch/x86/efi/stub.c
> > +++ b/xen/arch/x86/efi/stub.c
> > @@ -3,6 +3,30 @@
> >  #include <xen/init.h>
> >  #include <xen/lib.h>
> >  #include <asm/page.h>
> > +#include <asm/efibind.h>
> > +#include <efi/efidef.h>
> > +#include <efi/eficapsule.h>
> > +#include <efi/eficon.h>
> > +#include <efi/efidevp.h>
> > +#include <efi/efiapi.h>
> > +
> > +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> > +{
> > +    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
> > +    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
> > +
> > +    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
> > +
> > +    /* Print error message and halt the system. */
> > +    asm volatile(
> > +    "    call %2                      \n"
> > +    "0:  hlt                          \n"
> > +    "    jmp  0b                      \n"
> > +       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
> > +       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");
>
> There are explanations missing here: First, a warning should be added
> alongside the EFI header inclusions, making clear that no services
> whatsoever can be called. And then the asm() here needs to explain

I am not convinced but if you wish...

> that it open codes an MS-ABI function call. Which then makes me

OK.

> wonder (even if it doesn't matter much) - are the clobbers actually
> correct? I think you also need to clobber rsi and rdi. Otoh there's no

Nope, MS-ABI says that %rsi and %rdi must be saved and restored by
function which uses them. So, we do not need list both registers
in clobbers here.

> need for an explicit "cc" clobber on x86.

Why?

Daniel

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

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

* Re: [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-08-25 13:27   ` Jan Beulich
@ 2016-08-30 19:58     ` Daniel Kiper
  2016-08-31 13:01       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-30 19:58 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 07:27:21AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > +#define NULL	((void *)0)
> > +
> > +#define __packed	__attribute__((__packed__))
> > +#define __stdcall	__attribute__((__stdcall__))
> > +
> > +#define max(x,y) ({ \
> > +        const typeof(x) _x = (x);       \
> > +        const typeof(y) _y = (y);       \
> > +        (void) (&_x == &_y);            \
> > +        _x > _y ? _x : _y; })
>
> Now that you add a second instance of (some of) these, please
> move them to a new (local to this directory) header, e.g. defs.h.
>
> > +#define tolower(c) ((c) | 0x20)
> > +
> > +typedef unsigned char bool_t;
>
> _Bool and bool please and ...
>
> > +typedef unsigned char u8;
> > +typedef unsigned short u16;
> > +typedef unsigned int size_t;
> > +
> > +#define FALSE		0
> > +#define TRUE		1
>
> ... these replaced by true and false. In fact I see no reason why
> you couldn't include xen/stdbool.h here now that it can be more
> generally used.

Maybe we should include xen/stdbool.h in defs.h and move to it (defs.h)
all macros, types definitions, etc. from reloc.c and cmdline.c. This way
we can share more stuff without duplicating it in both files. Does it
make sense?

> > +/*
> > + * Space and TAB are obvious delimiters. However, I am
> > + * adding "\n" and "\r" here too. Just in case when
> > + * crazy bootloader/user puts them somewhere.
> > + */
> > +static const char delim_chars_comma[] = ", \n\r\t";
> > +static const char delim_chars[] = " \n\r\t";
>
> I realize it's minor, but why two arrays instead of
>
> #define delim_chars (delim_chars_comma + 1)
>
> ?

I can try it.

> > +/*
> > + * static const char *delim_chars = &delim_chars_comma[1];
> > + *
> > + * Older compilers, e.g. gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21),
> > + * put &delim_chars_comma[1] directly into *delim_chars. This means that the address
> > + * in *delim_chars is not properly updated during runtime. Newer compilers are much
> > + * smarter and build fully relocatable code even if above shown construct is used.
> > + * However, define delim_chars[] separately to properly build Xen code on
> > + * older systems.
> > + */
>
> I have to admit that I don't really understand what you want to
> say with this comment.

I tried to use following thing suggested by you earlier:
  static const char *delim_chars = &delim_chars_comma[1];

Sadly, it does not work because after building/linking by older
GCC/linker delim_chars contains static address and cannot be
properly relocated during runtime. Newer GCC/linkers are much
smarter and all references to delim_chars and finally to
&delim_chars_comma[1] are properly relocated during runtime.
However, there is a chance that your approach with #define
will work with all supported build environments.

> > +static unsigned int strtoui(const char *s, const char *stop, const char **next)
> > +{
> > +    char l;
> > +    unsigned int base = 10, ores = 0, res = 0;
> > +
> > +    if ( *s == '0' )
> > +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
> > +
> > +    for ( ; *s != '\0'; ++s )
> > +    {
> > +        if ( stop && strchr(stop, *s) )
> > +            goto out;
> > +
> > +        if ( *s < '0' || (*s > '7' && base == 8) )
> > +        {
> > +            res = UINT_MAX;
> > +            goto out;
> > +        }
> > +
> > +        l = tolower(*s);
> > +
> > +        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
> > +        {
> > +            res = UINT_MAX;
> > +            goto out;
> > +        }
> > +
> > +        res *= base;
> > +        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
> > +
> > +        if ( ores > res )
> > +        {
> > +            res = UINT_MAX;
> > +            goto out;
> > +        }
>
> Without having spent time to try and find an example, it feels like this
> check won't catch all possible overflow conditions. If you care about
> overflow, please make sure you catch all cases.

Hmmm.... How come? Could you give an example?

Daniel

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

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

* Re: [PATCH v5 10/16] efi: create efi_enabled()
  2016-08-30 17:19     ` Daniel Kiper
@ 2016-08-31 12:31       ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-08-31 12:31 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 19:19, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 06:16:35AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > --- a/xen/arch/x86/efi/stub.c
>> > +++ b/xen/arch/x86/efi/stub.c
>> > @@ -4,9 +4,10 @@
>> >  #include <xen/lib.h>
>> >  #include <asm/page.h>
>> >
>> > -#ifndef efi_enabled
>> > -const bool_t efi_enabled = 0;
>> > -#endif
>> > +bool_t efi_enabled(int feature)
>> > +{
>> > +    return false;
>> > +}
>>
>> Plain bool please, the more that you use false. And I'm relatively
> 
> What is wrong with bool_t? bool is equal to bool_t.

With the (recent) introduction of bool we want to switch away from
bool_t.

>> certain I did ask for the parameter type to be unsigned int, as you
>> don't mean to pass negative values.
> 
> Sure. However, full blown efi_enabled() calls test_bit(). Latter calls
> constant_test_bit() or variable_test_bit() which take bit position as
> int. So, I do not think that efi_enabled() should take unsigned int. Or
> we should change constant_test_bit() and variable_test_bit() respectively.
> Hmmm... No, we should not. It looks that negative offsets are valid.

But in the context here you mean an unsigned value, so you should
use an unsigned type. Feel free to ASSERT(... <= INT_MAX) if you
really care.

>> > @@ -739,8 +739,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>> >          l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] =
>> >              l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR);
>> >
>> > -        memmap_type = loader;
>> > +        memmap_type = "EFI";
>> >      }
>> > +    else if ( efi_enabled(EFI_BOOT) )
>> > +        memmap_type = "EFI";
>>
>> Is the change ahead of the "else" really necessary?
> 
> No. However, in this case memmap_type is always "EFI" and we do not need
> to get this value from loader variable. Which, of course, is always also
> "EFI" (to be precise pointer to) here but IMO "memmap_type = loader" suggests
> that memmap_type could be anything else.

Well - it's been okay so far, so I see no reason to change it, unless
you want to do this in a separate patch with an acceptable explanation.

Jan


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

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

* Re: [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-08-30 19:32     ` Daniel Kiper
@ 2016-08-31 12:49       ` Jan Beulich
  2016-08-31 17:07         ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-31 12:49 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 21:32, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 06:59:54AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > @@ -223,14 +425,22 @@ trampoline_setup:
>> >          call    reloc
>> >          mov     %eax,sym_phys(multiboot_ptr)
>> >
>> > -        /* Initialize BSS (no nasty surprises!) */
>> > +        /*
>> > +         * Do not zero BSS on EFI platform here.
>> > +         * It was initialized earlier.
>> > +         */
>> > +        cmpb    $0,sym_phys(skip_realmode)
>> > +        jnz     1f
>> > +
>> > +        /* Initialize BSS (no nasty surprises!). */
>> >          mov     $sym_phys(__bss_start),%edi
>> >          mov     $sym_phys(__bss_end),%ecx
>> >          sub     %edi,%ecx
>> > -        xor     %eax,%eax
>> >          shr     $2,%ecx
>> > +        xor     %eax,%eax
>> >          rep stosl
>>
>> Please avoid pointless code movement like this.
> 
> I think that shr should be close to sub because both operations are related
> to some extent. However, you are right that maybe this cleanup should be in
> separate patch. Does it make sense for you?

Separating dependent instructions by other unrelated ones can
actually improve performance. I agree that performance isn't of
much relevance here, but I think I still wouldn't agree to a change
like this even if submitted separately.

>> > +paddr_t __init efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>> > +{
>> > +    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
>> > +    UINTN cols, gop_mode = ~0, rows;
>> > +
>> > +    __set_bit(EFI_BOOT, &efi_flags);
>> > +    __set_bit(EFI_RS, &efi_flags);
>> > +
>> > +    efi_init(ImageHandle, SystemTable);
>> > +
>> > +    efi_console_set_mode();
>> > +
>> > +    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
>> > +                           &cols, &rows) == EFI_SUCCESS )
>> > +        efi_arch_console_init(cols, rows);
>> > +
>> > +    gop = efi_get_gop();
>> > +
>> > +    if ( gop )
>> > +        gop_mode = efi_find_gop_mode(gop, 0, 0, 0);
>> > +
>> > +    efi_arch_edd();
>> > +    efi_arch_cpu();
>> > +
>> > +    efi_tables();
>> > +    setup_efi_pci();
>> > +    efi_variables();
>> > +
>> > +    if ( gop )
>> > +        efi_set_gop_mode(gop, gop_mode);
>> > +
>> > +    efi_exit_boot(ImageHandle, SystemTable);
>> > +
>> > +    /* Return highest available memory address below 1 MiB. */
>> > +    return cfg.addr;
>>
>> Where is it being made certain that there are 64k of space available
>> right below this address, as is being assumed at trampoline_setup?
> 
> You are right. This is a bug. However, the problem is more generic
> and should be fixed for all boot cases (BIOS, EFI loader and EFI with
> GRUB2). Additionally, in case of BIOS and EFI with GRUB2 we should
> check that it is possible to put all data from grub loader in low
> memory. So, it looks that there is a place for at least two (three?)
> additional patches. Do you want them at the beginning of or the end
> of this patch series.

If you think there are bugs in pre-existing code, then for having the
option of backporting putting such patches at the beginning would
be desirable. That said, I'm not convinced there are problems really
in need of fixing here (yet the grub environment is different and
hence will need taking care of even if we leave the other code paths
as they are now).

>> > --- a/xen/arch/x86/efi/stub.c
>> > +++ b/xen/arch/x86/efi/stub.c
>> > @@ -3,6 +3,30 @@
>> >  #include <xen/init.h>
>> >  #include <xen/lib.h>
>> >  #include <asm/page.h>
>> > +#include <asm/efibind.h>
>> > +#include <efi/efidef.h>
>> > +#include <efi/eficapsule.h>
>> > +#include <efi/eficon.h>
>> > +#include <efi/efidevp.h>
>> > +#include <efi/efiapi.h>
>> > +
>> > +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>> > +{
>> > +    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
>> > +    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
>> > +
>> > +    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
>> > +
>> > +    /* Print error message and halt the system. */
>> > +    asm volatile(
>> > +    "    call %2                      \n"
>> > +    "0:  hlt                          \n"
>> > +    "    jmp  0b                      \n"
>> > +       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
>> > +       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");
>>
>> There are explanations missing here: First, a warning should be added
>> alongside the EFI header inclusions, making clear that no services
>> whatsoever can be called. And then the asm() here needs to explain
> 
> I am not convinced but if you wish...

Not convinced of what?

>> that it open codes an MS-ABI function call. Which then makes me
> 
> OK.
> 
>> wonder (even if it doesn't matter much) - are the clobbers actually
>> correct? I think you also need to clobber rsi and rdi. Otoh there's no
> 
> Nope, MS-ABI says that %rsi and %rdi must be saved and restored by
> function which uses them. So, we do not need list both registers
> in clobbers here.

Oh, right, I manage to mix up calling conventions.

>> need for an explicit "cc" clobber on x86.
> 
> Why?

Because such a clobber gets added to every asm() by the compiler,
unless it uses the (new in gcc 6) flag output. I've actually suggested
to upstream a patch making it possible to avoid that automatic
addition, but there hadn't been a whole lot of useful feedback.

Jan

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

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

* Re: [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-08-30 19:58     ` Daniel Kiper
@ 2016-08-31 13:01       ` Jan Beulich
  2016-08-31 19:31         ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-31 13:01 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 30.08.16 at 21:58, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 07:27:21AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > +#define NULL	((void *)0)
>> > +
>> > +#define __packed	__attribute__((__packed__))
>> > +#define __stdcall	__attribute__((__stdcall__))
>> > +
>> > +#define max(x,y) ({ \
>> > +        const typeof(x) _x = (x);       \
>> > +        const typeof(y) _y = (y);       \
>> > +        (void) (&_x == &_y);            \
>> > +        _x > _y ? _x : _y; })
>>
>> Now that you add a second instance of (some of) these, please
>> move them to a new (local to this directory) header, e.g. defs.h.
>>
>> > +#define tolower(c) ((c) | 0x20)
>> > +
>> > +typedef unsigned char bool_t;
>>
>> _Bool and bool please and ...
>>
>> > +typedef unsigned char u8;
>> > +typedef unsigned short u16;
>> > +typedef unsigned int size_t;
>> > +
>> > +#define FALSE		0
>> > +#define TRUE		1
>>
>> ... these replaced by true and false. In fact I see no reason why
>> you couldn't include xen/stdbool.h here now that it can be more
>> generally used.
> 
> Maybe we should include xen/stdbool.h in defs.h and move to it (defs.h)
> all macros, types definitions, etc. from reloc.c and cmdline.c. This way
> we can share more stuff without duplicating it in both files. Does it
> make sense?

Well, that's what I did suggest in the very first comment still visible
in context above.

>> > +/*
>> > + * static const char *delim_chars = &delim_chars_comma[1];
>> > + *
>> > + * Older compilers, e.g. gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21),
>> > + * put &delim_chars_comma[1] directly into *delim_chars. This means that the address
>> > + * in *delim_chars is not properly updated during runtime. Newer compilers are much
>> > + * smarter and build fully relocatable code even if above shown construct is used.
>> > + * However, define delim_chars[] separately to properly build Xen code on
>> > + * older systems.
>> > + */
>>
>> I have to admit that I don't really understand what you want to
>> say with this comment.
> 
> I tried to use following thing suggested by you earlier:
>   static const char *delim_chars = &delim_chars_comma[1];

I've never suggested anything like that. All I suggested is the
#define approach you've now said you'd give a try.

>> > +static unsigned int strtoui(const char *s, const char *stop, const char **next)
>> > +{
>> > +    char l;
>> > +    unsigned int base = 10, ores = 0, res = 0;
>> > +
>> > +    if ( *s == '0' )
>> > +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
>> > +
>> > +    for ( ; *s != '\0'; ++s )
>> > +    {
>> > +        if ( stop && strchr(stop, *s) )
>> > +            goto out;
>> > +
>> > +        if ( *s < '0' || (*s > '7' && base == 8) )
>> > +        {
>> > +            res = UINT_MAX;
>> > +            goto out;
>> > +        }
>> > +
>> > +        l = tolower(*s);
>> > +
>> > +        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
>> > +        {
>> > +            res = UINT_MAX;
>> > +            goto out;
>> > +        }
>> > +
>> > +        res *= base;
>> > +        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
>> > +
>> > +        if ( ores > res )
>> > +        {
>> > +            res = UINT_MAX;
>> > +            goto out;
>> > +        }
>>
>> Without having spent time to try and find an example, it feels like this
>> check won't catch all possible overflow conditions. If you care about
>> overflow, please make sure you catch all cases.
> 
> Hmmm.... How come? Could you give an example?

Excuse me, but shouldn't you instead demonstrate the logic is
correct? Or - consider what I had said - try to find an example
yourself? It's not that difficult: With 16-bit word size
0x3333 * 10 = 0x1fffe, which truncates to 0xfffe and is hence
larger than both inputs but still produced an overflow. This
easily extends to 32- and 64-bit word size.

Jan


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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-08-25 14:41   ` Jan Beulich
@ 2016-08-31 14:59     ` Daniel Kiper
  2016-08-31 15:46       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 14:59 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> > Every multiboot protocol (regardless of version) compatible image must
> > specify its load address (in ELF or multiboot header). Multiboot protocol
> > compatible loader have to load image at specified address. However, there
> > is no guarantee that the requested memory region (in case of Xen it starts
> > at 1 MiB and ends at 17 MiB) where image should be loaded initially is a RAM
> > and it is free (legacy BIOS platforms are merciful for Xen but I found at
> > least one EFI platform on which Xen load address conflicts with EFI boot
> > services; it is Dell PowerEdge R820 with latest firmware). To cope with that
> > problem we must make Xen early boot code relocatable and help boot loader to
> > relocate image in proper way by suggesting, not requesting specific load
> > addresses as it is right now, allowed address ranges. This patch does former.
> > It does not add multiboot2 protocol interface which is done in "x86: add
> > multiboot2 protocol support for relocatable images" patch.
> >
> > This patch changes following things:
> >   - default load address is changed from 1 MiB to 2 MiB; I did that because
> >     initial page tables are using 2 MiB huge pages and this way required
> >     updates for them are quite easy; it means that e.g. we avoid spacial
> >     cases for start and end of required memory region if it live at address
> >     not aligned to 2 MiB,
>
> Should this be a separate change then, to separate possible
> regressions due to that from such due to any other of the changes

Potentially yes. However, it should be done properly. Otherwise in
case of revert we can break Xen relocatable infrastructure and other
things. So, I am not sure does it pays. Anyway, I will check is it
possible or not.

> here? And then I don't see why, when making the image relocatable
> anyway, the link time load address actually still matters.

It matters for multiboot (v1) and multiboot2 compatible boot
loaders not supporting relocatable images.

> >   - %esi and %r15d registers are used as a storage for Xen image load base
> >     address (%r15d shortly because %rsi is used for EFI SystemTable address
> >     in 64-bit code); both registers are (%esi is mostly) unused in early
> >     boot code and preserved during C functions calls,
>
> In a context where you (also) talk about 64-bit code, %esi can't
> be called preserved unilaterally. You should make clear that this is
> for 32-bit function calls.

OK.

> > --- a/xen/arch/x86/boot/head.S
> > +++ b/xen/arch/x86/boot/head.S
> > @@ -12,13 +12,16 @@
> >          .text
> >          .code32
> >
> > -#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
> > +#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)
>
> In a patch already large and hence hard to review, did you really
> need to do this rename?

I think that sym_offset() is better term here. However, if you wish
I can leave sym_phys() as is. Though, IMO, sym_phys() name suggests
that we are playing with physical addresses and it is not correct in
all contexts, e.g. loot at fs_offset() (or sym_fs() as you wish).

> > @@ -126,26 +130,26 @@ vga_text_buffer:
> >          .section .init.text, "ax", @progbits
> >
> >  bad_cpu:
> > -        mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
> > +        lea     esi_offset(.Lbad_cpu_msg),%esi  # Error message
>
> Why not just
>
>         add     $sym_offset(.Lbad_cpu_msg),%esi  # Error message

OK.

[...]

> > @@ -461,62 +545,88 @@ trampoline_setup:
> >
> >          /* Stash TSC to calculate a good approximation of time-since-boot */
> >          rdtsc
> > -        mov     %eax,sym_phys(boot_tsc_stamp)
> > -        mov     %edx,sym_phys(boot_tsc_stamp+4)
> > +        mov     %eax,fs_offset(boot_tsc_stamp)
> > +        mov     %edx,fs_offset(boot_tsc_stamp)+4
> > +
> > +        /* Update frame addresses in page tables. */
> > +        mov     $((__page_tables_end-__page_tables_start)/8),%ecx
> > +1:      testl   $_PAGE_PRESENT,fs_offset(__page_tables_start)-8(,%ecx,8)
> > +        jz      2f
> > +        add     %esi,fs_offset(__page_tables_start)-8(,%ecx,8)
> > +2:      loop    1b
>
> This loop includes the mapping of the low Mb, which I don't think it
> should modify. Or wait - you move __page_tables_start, which by
> itself is fragile (but looks to be acceptable if accompanied by a
> comment explaining why it doesn't cover l1_identmap).

OK, I will add relevant comment somewhere.

> Also, just to double check - all these page table setup adjustments
> don't require reflecting in xen.efi's page table setup code?

I will check it once again but I do not think so.

[...]

> > --- a/xen/arch/x86/boot/trampoline.S
> > +++ b/xen/arch/x86/boot/trampoline.S
> > @@ -54,12 +54,20 @@ trampoline_gdt:
> >          /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
> >          .long   0x0000ffff
> >          .long   0x00009200
> > +        /*
> > +         * 0x0030: ring 0 Xen data, 16 MiB size, base
> > +         * address is computed during runtime.
> > +         */
> > +        .quad   0x00c0920000001000
>
> This does not look like it covers 1Mb, it's more like 1Mb+4k-1.

I have checked it once again. It covers 16 MiB as required:
  4 KiB * 0x1000 = 0x1000000 (no taking into account relocation).

By the way, it looks that we can define this segment as 0x200000 - 0x1000000.
However, then sym_fs() should be defined as:

#define sym_fs(sym)    %fs:(sym_offset(sym) - XEN_IMG_OFFSET)

Does it make sense?

> >          .pushsection .trampoline_rel, "a"
> >          .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
> >          .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
> >          .popsection
> >
> > +GLOBAL(xen_img_load_base_addr)
> > +        .long   0
>
> I've yet to understand the purpose of this symbol, but in any case:
> If the trampoline code doesn't reference it, why does it get placed
> here?

This symbol was used by code which unconditionally relocated Xen image
even if boot loader did work for us. I removed most of this code because
we agreed that if boot loader relocated Xen image then we do not have to
relocate it higher once again. If you are still OK with this idea I can go
further, as I planned, and remove all such remnants from next release.
However, it looks that then I have to store load address in xen_phys_start
from 32-bit assembly code. So, it will be nice if I can define it as
"unsigned int" instead of "unsigned long". Is it safe? I am asking because
this variable is used in quite important places and I do not want to break
something by mistake. At first sight it looks that it is safe but it will
be nice if you double check it.

> > @@ -861,15 +860,17 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >          highmem_start &= ~((1UL << L3_PAGETABLE_SHIFT) - 1);
> >  #endif
> >
> > +    /* Do not relocate Xen image if boot loader did work for us. */
> > +    if ( xen_img_load_base_addr )
> > +        xen_phys_start = xen_img_load_base_addr;
>
> Okay, with this change the question really is: Why do you need the
> new symbol? I.e. why can't you just use xen_phys_start, just like I
> managed to re-use it when I introduced boot from EFI?

This is what I was going to do in next release... If... Please look above...

> >      for ( i = boot_e820.nr_map-1; i >= 0; i-- )
> >      {
> >          uint64_t s, e, mask = (1UL << L2_PAGETABLE_SHIFT) - 1;
> >          uint64_t end, limit = ARRAY_SIZE(l2_identmap) << L2_PAGETABLE_SHIFT;
> >
> > -        /* Superpage-aligned chunks from BOOTSTRAP_MAP_BASE. */
>
> I can see that you want to get rid of BOOTSTRAP_MAP_BASE, but
> please don't delete the comment as a whole.

OK.

> >          s = (boot_e820.map[i].addr + mask) & ~mask;
> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
> >              continue;
>
> This means you now map memory between 2Mb and 16Mb here. Is
> this necessary?

Without this change Xen relocated by boot loader crashes with:

(XEN) Panic on CPU 0:
(XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902

So, it must be mapped. However, maybe we should not map this
region when Xen is not relocated by boot loader.

> > @@ -901,7 +902,6 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >              l4_pgentry_t *pl4e;
> >              l3_pgentry_t *pl3e;
> >              l2_pgentry_t *pl2e;
> > -            uint64_t load_start;
> >              int i, j, k;
> >
> >              /* Select relocation address. */
> > @@ -915,9 +915,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >               * with a barrier(). After this we must *not* modify static/global
> >               * data until after we have switched to the relocated pagetables!
> >               */
> > -            load_start = (unsigned long)_start - XEN_VIRT_START;
> >              barrier();
> > -            move_memory(e + load_start, load_start, _end - _start, 1);
> > +            move_memory(e + XEN_IMG_OFFSET, XEN_IMG_OFFSET, _end - _start, 1);
>
> Assuming _start - XEN_VIRT_START == XEN_IMG_OFFSET, is this
> change necessary? Or is it rather just simplification, which again
> should be split from an already complex patch.

Just simplification. I will split it from this patch.

> > @@ -957,15 +956,14 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >               * Undo the temporary-hooking of the l1_identmap.  __2M_text_start
> >               * is contained in this PTE.
> >               */
> > -            BUG_ON(l2_table_offset((unsigned long)_erodata) ==
> > -                   l2_table_offset((unsigned long)_stext));
>
> At least when using_2M_mapping() this surely ought to hold?

OK.

> > @@ -1019,6 +1017,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >                  : "memory" );
> >
> >              bootstrap_map(NULL);
> > +
> > +            printk("New Xen image base address: 0x%08lx\n", xen_phys_start);
>
> I don't see the motivation for adding such a message in this patch,
> but if, then please use %#lx.

OK, I will use %#lx.

> > @@ -1082,6 +1082,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
> >
> >      if ( !xen_phys_start )
> >          panic("Not enough memory to relocate Xen.");
> > +
> >      reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end));
>
> Another stray change.

I will fix it.

> > --- a/xen/arch/x86/xen.lds.S
> > +++ b/xen/arch/x86/xen.lds.S
> > @@ -55,7 +55,7 @@ SECTIONS
> >    __2M_text_start = .;         /* Start of 2M superpages, mapped RX. */
> >  #endif
> >
> > -  . = __XEN_VIRT_START + MB(1);
> > +  . = __XEN_VIRT_START + XEN_IMG_OFFSET;
> >    _start = .;
> >    .text : {
> >          _stext = .;            /* Text and read-only data */
> > @@ -257,12 +257,14 @@ SECTIONS
> >    .reloc : {
> >      *(.reloc)
> >    } :text
> > -  /* Trick the linker into setting the image size to exactly 16Mb. */
> >    . = ALIGN(__section_alignment__);
> > +#endif
> > +
> > +  /* Trick the linker into setting the image size to exactly 16Mb. */
> >    .pad : {
> >      . = ALIGN(MB(16));
> > +    __end_of_image__ = .;
>
> I see that you use this symbol in xen/arch/x86/Makefile, but I again
> don't follow why this logic needs to change.

Current logic does not work because it gets wrong address from xen/xen-syms.
This way boot loader allocates incorrect, usually huge, buffer for Xen image
(wait, there is a chance that this is a fix for issues related to 2 MiB mappings
found by Andrew). I do not see simple reliable fix for current solution. So,
I introduced __end_of_image__ and look for its address. This is much better
method to establish end of image address then previous one. However, I can
agree that this could be introduced in separate patch.

> > --- a/xen/include/asm-x86/page.h
> > +++ b/xen/include/asm-x86/page.h
> > @@ -288,7 +288,7 @@ extern root_pgentry_t
> > idle_pg_table[ROOT_PAGETABLE_ENTRIES];
> >  extern l2_pgentry_t  *compat_idle_pg_table_l2;
> >  extern unsigned int   m2p_compat_vstart;
> >  extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES],
> > -    l2_bootmap[L2_PAGETABLE_ENTRIES];
> > +    l2_bootmap[4*L2_PAGETABLE_ENTRIES];
>
> Why do you need 4 of them? I can see why one might not suffice,
> but two surely should?

In worst case we need three. One for l1_identmap hook and two
for Xen image mapping. So, I am not sure that it pays to complicate
assembly mapping code just to save just 1 page. Additionally, you
should remember that l2_bootmap is freed after init.

Daniel

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

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

* Re: [PATCH v5 00/16] x86: multiboot2 protocol support
  2016-08-30 15:09     ` Jan Beulich
@ 2016-08-31 15:05       ` Daniel Kiper
  0 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 15:05 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Tue, Aug 30, 2016 at 09:09:50AM -0600, Jan Beulich wrote:
> >>> On 30.08.16 at 16:15, <daniel.kiper@oracle.com> wrote:
> > On Mon, Aug 22, 2016 at 04:10:04AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> > The final goal is xen.efi binary file which could be loaded by EFI
> >> > loader, multiboot (v1) protocol (only on legacy BIOS platforms) and
> >> > multiboot2 protocol. This way we will have:
> >> >   - smaller Xen code base,
> >> >   - one code base for xen.gz and xen.efi,
> >> >   - one build method for xen.gz and xen.efi;
> >> >     xen.efi will be extracted from xen(-syms)
> >> >     file using objcopy or special custom tool,
> >> >   - xen.efi build will not so strongly depend
> >> >     on a given GCC and binutils version.
> >>
> >> Just in case you aren't aware: The partial revert done by
> >> 0b8a172444 ("x86: partially revert use of 2M mappings for
> >> hypervisor image") now puts us a step further away from that
> >> goal, compared to when you had started your work.
> >
> > I am not sure about that. Andrew patches changed xen.gz size significantly.
> > My patches does not do that in significant way. They (precisely it) just
> > move load address from 1 MiB to 2 MiB. So, I do not expect major issues
> > here. However, anyway it should be tested (and it was tested, IIRC, by
> > Konrad some time ago).
>
> Looks like you didn't understand: This is not about image size. The
> issue is that the EFI binary, other than xen.gz, now properly uses
> RX, RO, and RW permissions (and large pages) for the individual
> pieces of the image. Moving to a single binary would hence result
> in a (slight) regression unless that gets taken care of beforehand.

OK. However, there is chance that it is quite easy to fix. Please look
at my comments for patch #15. Especially regarding _end_of_image__ symbol.

Daniel

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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-30 15:12       ` Jan Beulich
@ 2016-08-31 15:13         ` Daniel Kiper
  2016-08-31 15:25           ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 15:13 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Tue, Aug 30, 2016 at 09:12:45AM -0600, Jan Beulich wrote:
> >>> On 30.08.16 at 16:32, <daniel.kiper@oracle.com> wrote:
> > On Thu, Aug 25, 2016 at 05:34:31AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> > Create generic alloc and copy functions. We need
> >> > separate tools for memory allocation and copy to
> >> > provide multiboot2 protocol support.
> >> >
> >> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
> >>
> >> The amount of casting in this patch alone looks very reasonable now.
> >> Before ack-ing this and respective subsequent patches I'd like to see
> >> the final result though. To facilitate that I have to re-raise a previously
> >> asked question: Do you have a tree somewhere which one could use
> >> to look at the final result?
> >
> > Sadly no.
>
> Alternatively, could you simply send the final resulting source file?

Please look below...

Daniel

/*
 * reloc.c
 *
 * 32-bit flat memory-map routines for relocating Multiboot structures
 * and modules. This is most easily done early with paging disabled.
 *
 * Copyright (c) 2009, Citrix Systems, Inc.
 *
 * Authors:
 *    Keir Fraser <keir@xen.org>
 */

/*
 * This entry point is entered from xen/arch/x86/boot/head.S with:
 *   - 0x4(%esp) = MULTIBOOT_INFORMATION_ADDRESS,
 *   - 0x8(%esp) = BOOT_TRAMPOLINE_ADDRESS.
 */
asm (
    "    .text                         \n"
    "    .globl _start                 \n"
    "_start:                           \n"
    "    jmp  reloc                    \n"
    );

typedef unsigned int u32;
#include "../../../include/xen/multiboot.h"

#define __stdcall	__attribute__((__stdcall__))

#define ALIGN_UP(arg, align) \
                (((arg) + (align) - 1) & ~((typeof(arg))(align) - 1))

static u32 alloc;

static u32 alloc_mem(u32 bytes)
{
    return alloc -= ALIGN_UP(bytes, 16);
}

static u32 copy_mem(u32 src, u32 bytes)
{
    u32 dst, dst_ret;

    dst = alloc_mem(bytes);
    dst_ret = dst;

    while ( bytes-- )
        *(char *)dst++ = *(char *)src++;

    return dst_ret;
}

static u32 copy_string(u32 src)
{
    u32 p;

    if ( src == 0 )
        return 0;

    for ( p = src; *(char *)p != '\0'; p++ )
        continue;

    return copy_mem(src, p - src + 1);
}

multiboot_info_t __stdcall *reloc(u32 mbi_old, u32 trampoline)
{
    multiboot_info_t *mbi;
    int i;

    alloc = trampoline;

    mbi = (multiboot_info_t *)copy_mem(mbi_old, sizeof(*mbi));

    if ( mbi->flags & MBI_CMDLINE )
        mbi->cmdline = copy_string(mbi->cmdline);

    if ( mbi->flags & MBI_MODULES )
    {
        module_t *mods;

        mbi->mods_addr = copy_mem(mbi->mods_addr, mbi->mods_count * sizeof(module_t));

        mods = (module_t *)mbi->mods_addr;

        for ( i = 0; i < mbi->mods_count; i++ )
        {
            if ( mods[i].string )
                mods[i].string = copy_string(mods[i].string);
        }
    }

    if ( mbi->flags & MBI_MEMMAP )
        mbi->mmap_addr = copy_mem(mbi->mmap_addr, mbi->mmap_length);

    if ( mbi->flags & MBI_LOADERNAME )
        mbi->boot_loader_name = copy_string(mbi->boot_loader_name);

    /* Mask features we don't understand or don't relocate. */
    mbi->flags &= (MBI_MEMLIMITS |
                   MBI_CMDLINE |
                   MBI_MODULES |
                   MBI_MEMMAP |
                   MBI_LOADERNAME);

    return mbi;
}

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

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

* Re: [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-30 15:14       ` Jan Beulich
@ 2016-08-31 15:21         ` Daniel Kiper
  0 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 15:21 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Tue, Aug 30, 2016 at 09:14:28AM -0600, Jan Beulich wrote:
> >>> On 30.08.16 at 16:41, <daniel.kiper@oracle.com> wrote:
> > On Thu, Aug 25, 2016 at 05:50:04AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> > +        case MULTIBOOT2_TAG_TYPE_MMAP:
> >> > +            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
> >> > +                break;
> >> > +
> >> > +            mbi_out->flags |= MBI_MEMMAP;
> >> > +            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
> >> > +            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
> >> > +            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
> >> > +            mbi_out->mmap_length *= sizeof(memory_map_t);
> >> > +
> >> > +            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);
> >> > +
> >> > +            mmap_src = get_mb2_data(tag, mmap, entries);
> >> > +            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;
> >> > +
> >> > +            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
> >> > +            {
> >> > +                /* Init size member properly. */
> >> > +                mmap_dst[i].size = sizeof(memory_map_t);
> >> > +                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
> >> > +                /* Now copy a given region data. */
> >> > +                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);
> >>
> >> Why do you multiply by i here? The way you've written it you want to
> >> increment mmap_src by entry_size _at the end_ of each iteration. Or
> >
> > This is another option. If you wish I can do that.
>
> This is not just another option - afaict the code as is won't work for
> more than one map entry.

Ugh... Sorry, you are right. Stupid mistake. I will change this.

Daniel

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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-31 15:13         ` Daniel Kiper
@ 2016-08-31 15:25           ` Jan Beulich
  2016-08-31 19:39             ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-31 15:25 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 31.08.16 at 17:13, <daniel.kiper@oracle.com> wrote:
> On Tue, Aug 30, 2016 at 09:12:45AM -0600, Jan Beulich wrote:
>> >>> On 30.08.16 at 16:32, <daniel.kiper@oracle.com> wrote:
>> > On Thu, Aug 25, 2016 at 05:34:31AM -0600, Jan Beulich wrote:
>> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> >> > Create generic alloc and copy functions. We need
>> >> > separate tools for memory allocation and copy to
>> >> > provide multiboot2 protocol support.
>> >> >
>> >> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
>> >>
>> >> The amount of casting in this patch alone looks very reasonable now.
>> >> Before ack-ing this and respective subsequent patches I'd like to see
>> >> the final result though. To facilitate that I have to re-raise a previously
>> >> asked question: Do you have a tree somewhere which one could use
>> >> to look at the final result?
>> >
>> > Sadly no.
>>
>> Alternatively, could you simply send the final resulting source file?
> 
> Please look below...

I don't think that was the file at the end of the series, as asked
for above? There's no mb2 code in there afaics...

Jan


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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-08-31 14:59     ` Daniel Kiper
@ 2016-08-31 15:46       ` Jan Beulich
  2016-08-31 20:50         ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-08-31 15:46 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 31.08.16 at 16:59, <daniel.kiper@oracle.com> wrote:
> On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > Every multiboot protocol (regardless of version) compatible image must
>> > specify its load address (in ELF or multiboot header). Multiboot protocol
>> > compatible loader have to load image at specified address. However, there
>> > is no guarantee that the requested memory region (in case of Xen it starts
>> > at 1 MiB and ends at 17 MiB) where image should be loaded initially is a RAM
>> > and it is free (legacy BIOS platforms are merciful for Xen but I found at
>> > least one EFI platform on which Xen load address conflicts with EFI boot
>> > services; it is Dell PowerEdge R820 with latest firmware). To cope with that
>> > problem we must make Xen early boot code relocatable and help boot loader to
>> > relocate image in proper way by suggesting, not requesting specific load
>> > addresses as it is right now, allowed address ranges. This patch does former.
>> > It does not add multiboot2 protocol interface which is done in "x86: add
>> > multiboot2 protocol support for relocatable images" patch.
>> >
>> > This patch changes following things:
>> >   - default load address is changed from 1 MiB to 2 MiB; I did that because
>> >     initial page tables are using 2 MiB huge pages and this way required
>> >     updates for them are quite easy; it means that e.g. we avoid spacial
>> >     cases for start and end of required memory region if it live at address
>> >     not aligned to 2 MiB,
>>
>> Should this be a separate change then, to separate possible
>> regressions due to that from such due to any other of the changes
> 
> Potentially yes. However, it should be done properly. Otherwise in
> case of revert we can break Xen relocatable infrastructure and other
> things. So, I am not sure does it pays. Anyway, I will check is it
> possible or not.

It's not so much about possibly reverting (we'd rather revert
everything if such a need arises) than bisecting.

>> here? And then I don't see why, when making the image relocatable
>> anyway, the link time load address actually still matters.
> 
> It matters for multiboot (v1) and multiboot2 compatible boot
> loaders not supporting relocatable images.

Oh, right.

>> > --- a/xen/arch/x86/boot/head.S
>> > +++ b/xen/arch/x86/boot/head.S
>> > @@ -12,13 +12,16 @@
>> >          .text
>> >          .code32
>> >
>> > -#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
>> > +#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)
>>
>> In a patch already large and hence hard to review, did you really
>> need to do this rename?
> 
> I think that sym_offset() is better term here. However, if you wish
> I can leave sym_phys() as is. Though, IMO, sym_phys() name suggests
> that we are playing with physical addresses and it is not correct in
> all contexts, e.g. loot at fs_offset() (or sym_fs() as you wish).

After some more thinking about this I agree sym_phys() isn't
ideal anymore after this patch. Still, to avoid unrelated changes in
this quite hard to review patch, I'd like to ask that you keep the
name here and do just the rename in a subsequent patch.

>> Also, just to double check - all these page table setup adjustments
>> don't require reflecting in xen.efi's page table setup code?
> 
> I will check it once again but I do not think so.

Thanks for doing so. You perhaps realize that Andrew said the same
for what became 2ce5963727, and then recently we had to fix things.

>> > --- a/xen/arch/x86/boot/trampoline.S
>> > +++ b/xen/arch/x86/boot/trampoline.S
>> > @@ -54,12 +54,20 @@ trampoline_gdt:
>> >          /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
>> >          .long   0x0000ffff
>> >          .long   0x00009200
>> > +        /*
>> > +         * 0x0030: ring 0 Xen data, 16 MiB size, base
>> > +         * address is computed during runtime.
>> > +         */
>> > +        .quad   0x00c0920000001000
>>
>> This does not look like it covers 1Mb, it's more like 1Mb+4k-1.
> 
> I have checked it once again. It covers 16 MiB as required:
>   4 KiB * 0x1000 = 0x1000000 (no taking into account relocation).

I'm sorry, but no. The raw limit value taken from that descriptor
is 0x1000, and the G bit is set. That makes the actual limit 0x1000fff.

> By the way, it looks that we can define this segment as 0x200000 - 0x1000000.
> However, then sym_fs() should be defined as:
> 
> #define sym_fs(sym)    %fs:(sym_offset(sym) - XEN_IMG_OFFSET)
> 
> Does it make sense?

If you feel like it's worth it ...

>> >          .pushsection .trampoline_rel, "a"
>> >          .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
>> >          .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
>> >          .popsection
>> >
>> > +GLOBAL(xen_img_load_base_addr)
>> > +        .long   0
>>
>> I've yet to understand the purpose of this symbol, but in any case:
>> If the trampoline code doesn't reference it, why does it get placed
>> here?
> 
> This symbol was used by code which unconditionally relocated Xen image
> even if boot loader did work for us. I removed most of this code because
> we agreed that if boot loader relocated Xen image then we do not have to
> relocate it higher once again. If you are still OK with this idea I can go
> further, as I planned, and remove all such remnants from next release.
> However, it looks that then I have to store load address in xen_phys_start
> from 32-bit assembly code. So, it will be nice if I can define it as
> "unsigned int" instead of "unsigned long". Is it safe?

I don't see why you shouldn't be able to store into the low 32 bits of
the variable without altering the high ones (which are all zero).

>> >          s = (boot_e820.map[i].addr + mask) & ~mask;
>> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
>> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
>> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
>> >              continue;
>>
>> This means you now map memory between 2Mb and 16Mb here. Is
>> this necessary?
> 
> Without this change Xen relocated by boot loader crashes with:
> 
> (XEN) Panic on CPU 0:
> (XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
> 
> So, it must be mapped.

That's too little context to be useful for understanding the full
background.

>> > --- a/xen/arch/x86/xen.lds.S
>> > +++ b/xen/arch/x86/xen.lds.S
>> > @@ -55,7 +55,7 @@ SECTIONS
>> >    __2M_text_start = .;         /* Start of 2M superpages, mapped RX. */
>> >  #endif
>> >
>> > -  . = __XEN_VIRT_START + MB(1);
>> > +  . = __XEN_VIRT_START + XEN_IMG_OFFSET;
>> >    _start = .;
>> >    .text : {
>> >          _stext = .;            /* Text and read-only data */
>> > @@ -257,12 +257,14 @@ SECTIONS
>> >    .reloc : {
>> >      *(.reloc)
>> >    } :text
>> > -  /* Trick the linker into setting the image size to exactly 16Mb. */
>> >    . = ALIGN(__section_alignment__);
>> > +#endif
>> > +
>> > +  /* Trick the linker into setting the image size to exactly 16Mb. */
>> >    .pad : {
>> >      . = ALIGN(MB(16));
>> > +    __end_of_image__ = .;
>>
>> I see that you use this symbol in xen/arch/x86/Makefile, but I again
>> don't follow why this logic needs to change.
> 
> Current logic does not work because it gets wrong address from xen/xen-syms.
> This way boot loader allocates incorrect, usually huge, buffer for Xen image
> (wait, there is a chance that this is a fix for issues related to 2 MiB mappings
> found by Andrew). I do not see simple reliable fix for current solution. So,
> I introduced __end_of_image__ and look for its address. This is much better
> method to establish end of image address then previous one. However, I can
> agree that this could be introduced in separate patch.

Yes please, as that also will (hopefully) result in the need for the
change getting properly explained.

>> > --- a/xen/include/asm-x86/page.h
>> > +++ b/xen/include/asm-x86/page.h
>> > @@ -288,7 +288,7 @@ extern root_pgentry_t
>> > idle_pg_table[ROOT_PAGETABLE_ENTRIES];
>> >  extern l2_pgentry_t  *compat_idle_pg_table_l2;
>> >  extern unsigned int   m2p_compat_vstart;
>> >  extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES],
>> > -    l2_bootmap[L2_PAGETABLE_ENTRIES];
>> > +    l2_bootmap[4*L2_PAGETABLE_ENTRIES];
>>
>> Why do you need 4 of them? I can see why one might not suffice,
>> but two surely should?
> 
> In worst case we need three. One for l1_identmap hook and two
> for Xen image mapping. So, I am not sure that it pays to complicate
> assembly mapping code just to save just 1 page. Additionally, you
> should remember that l2_bootmap is freed after init.

Well, I was asking, not saying this needs to change. And you
pointing out the l1_identmap aspect makes clear this is fine as is.

Jan

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

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

* Re: [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-08-31 12:49       ` Jan Beulich
@ 2016-08-31 17:07         ` Daniel Kiper
  2016-09-01  7:40           ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 17:07 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Wed, Aug 31, 2016 at 06:49:51AM -0600, Jan Beulich wrote:
> >>> On 30.08.16 at 21:32, <daniel.kiper@oracle.com> wrote:
> > On Thu, Aug 25, 2016 at 06:59:54AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:

[...]

> >> > +paddr_t __init efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> >> > +{
> >> > +    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
> >> > +    UINTN cols, gop_mode = ~0, rows;
> >> > +
> >> > +    __set_bit(EFI_BOOT, &efi_flags);
> >> > +    __set_bit(EFI_RS, &efi_flags);
> >> > +
> >> > +    efi_init(ImageHandle, SystemTable);
> >> > +
> >> > +    efi_console_set_mode();
> >> > +
> >> > +    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
> >> > +                           &cols, &rows) == EFI_SUCCESS )
> >> > +        efi_arch_console_init(cols, rows);
> >> > +
> >> > +    gop = efi_get_gop();
> >> > +
> >> > +    if ( gop )
> >> > +        gop_mode = efi_find_gop_mode(gop, 0, 0, 0);
> >> > +
> >> > +    efi_arch_edd();
> >> > +    efi_arch_cpu();
> >> > +
> >> > +    efi_tables();
> >> > +    setup_efi_pci();
> >> > +    efi_variables();
> >> > +
> >> > +    if ( gop )
> >> > +        efi_set_gop_mode(gop, gop_mode);
> >> > +
> >> > +    efi_exit_boot(ImageHandle, SystemTable);
> >> > +
> >> > +    /* Return highest available memory address below 1 MiB. */
> >> > +    return cfg.addr;
> >>
> >> Where is it being made certain that there are 64k of space available
> >> right below this address, as is being assumed at trampoline_setup?
> >
> > You are right. This is a bug. However, the problem is more generic
> > and should be fixed for all boot cases (BIOS, EFI loader and EFI with
> > GRUB2). Additionally, in case of BIOS and EFI with GRUB2 we should
> > check that it is possible to put all data from grub loader in low
> > memory. So, it looks that there is a place for at least two (three?)
> > additional patches. Do you want them at the beginning of or the end
> > of this patch series.
>
> If you think there are bugs in pre-existing code, then for having the
> option of backporting putting such patches at the beginning would
> be desirable. That said, I'm not convinced there are problems really
> in need of fixing here (yet the grub environment is different and
> hence will need taking care of even if we leave the other code paths
> as they are now).

I think that we should no blindly assume that a given amount of memory
is available. However, we do that in a few places including this one which
you pointed out. So, it should be fixed. Though, the question is: Is it
possible? Right now I am not sure that it is true in all cases mentioned
above. There is a chance that in case pointed out by you it is. Anyway,
I will check it.

> >> > --- a/xen/arch/x86/efi/stub.c
> >> > +++ b/xen/arch/x86/efi/stub.c
> >> > @@ -3,6 +3,30 @@
> >> >  #include <xen/init.h>
> >> >  #include <xen/lib.h>
> >> >  #include <asm/page.h>
> >> > +#include <asm/efibind.h>
> >> > +#include <efi/efidef.h>
> >> > +#include <efi/eficapsule.h>
> >> > +#include <efi/eficon.h>
> >> > +#include <efi/efidevp.h>
> >> > +#include <efi/efiapi.h>
> >> > +
> >> > +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> >> > +{
> >> > +    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
> >> > +    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
> >> > +
> >> > +    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
> >> > +
> >> > +    /* Print error message and halt the system. */
> >> > +    asm volatile(
> >> > +    "    call %2                      \n"
> >> > +    "0:  hlt                          \n"
> >> > +    "    jmp  0b                      \n"
> >> > +       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
> >> > +       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");
> >>
> >> There are explanations missing here: First, a warning should be added
> >> alongside the EFI header inclusions, making clear that no services
> >> whatsoever can be called. And then the asm() here needs to explain
> >
> > I am not convinced but if you wish...
>
> Not convinced of what?

About "... a warning should be added alongside the EFI header inclusions,
making clear that no services whatsoever can be called". AIUI, "warning" ==
"comment" here. However, I think that everybody who reads this file is
aware that "no services whatsoever can be called". So, I am not sure
where is the point.

[...]

> >> need for an explicit "cc" clobber on x86.
> >
> > Why?
>
> Because such a clobber gets added to every asm() by the compiler,
> unless it uses the (new in gcc 6) flag output. I've actually suggested
> to upstream a patch making it possible to avoid that automatic
> addition, but there hadn't been a whole lot of useful feedback.

So, when somebody uses this new flag then "cc" will not be add here.
This is not big deal but I think that extra "cc" clobbers does not
hurt too.

Daniel

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

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

* Re: [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-08-31 13:01       ` Jan Beulich
@ 2016-08-31 19:31         ` Daniel Kiper
  2016-09-01  7:41           ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 19:31 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Wed, Aug 31, 2016 at 07:01:10AM -0600, Jan Beulich wrote:
> >>> On 30.08.16 at 21:58, <daniel.kiper@oracle.com> wrote:
> > On Thu, Aug 25, 2016 at 07:27:21AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:

[...]

> >> > +static unsigned int strtoui(const char *s, const char *stop, const char **next)
> >> > +{
> >> > +    char l;
> >> > +    unsigned int base = 10, ores = 0, res = 0;
> >> > +
> >> > +    if ( *s == '0' )
> >> > +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
> >> > +
> >> > +    for ( ; *s != '\0'; ++s )
> >> > +    {
> >> > +        if ( stop && strchr(stop, *s) )
> >> > +            goto out;
> >> > +
> >> > +        if ( *s < '0' || (*s > '7' && base == 8) )
> >> > +        {
> >> > +            res = UINT_MAX;
> >> > +            goto out;
> >> > +        }
> >> > +
> >> > +        l = tolower(*s);
> >> > +
> >> > +        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
> >> > +        {
> >> > +            res = UINT_MAX;
> >> > +            goto out;
> >> > +        }
> >> > +
> >> > +        res *= base;
> >> > +        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
> >> > +
> >> > +        if ( ores > res )
> >> > +        {
> >> > +            res = UINT_MAX;
> >> > +            goto out;
> >> > +        }
> >>
> >> Without having spent time to try and find an example, it feels like this
> >> check won't catch all possible overflow conditions. If you care about
> >> overflow, please make sure you catch all cases.
> >
> > Hmmm.... How come? Could you give an example?
>
> Excuse me, but shouldn't you instead demonstrate the logic is
> correct? Or - consider what I had said - try to find an example
> yourself? It's not that difficult: With 16-bit word size
> 0x3333 * 10 = 0x1fffe, which truncates to 0xfffe and is hence
> larger than both inputs but still produced an overflow. This
> easily extends to 32- and 64-bit word size.

Oh, boy. I forgot about multiplication. I think that we can define
res as unsigned long and then check that it is < UINT_MAX.
If not then return UINT_MAX.

Daniel

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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-31 15:25           ` Jan Beulich
@ 2016-08-31 19:39             ` Daniel Kiper
  2016-09-01  7:35               ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 19:39 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Wed, Aug 31, 2016 at 09:25:57AM -0600, Jan Beulich wrote:
> >>> On 31.08.16 at 17:13, <daniel.kiper@oracle.com> wrote:
> > On Tue, Aug 30, 2016 at 09:12:45AM -0600, Jan Beulich wrote:
> >> >>> On 30.08.16 at 16:32, <daniel.kiper@oracle.com> wrote:
> >> > On Thu, Aug 25, 2016 at 05:34:31AM -0600, Jan Beulich wrote:
> >> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> >> > Create generic alloc and copy functions. We need
> >> >> > separate tools for memory allocation and copy to
> >> >> > provide multiboot2 protocol support.
> >> >> >
> >> >> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
> >> >>
> >> >> The amount of casting in this patch alone looks very reasonable now.
> >> >> Before ack-ing this and respective subsequent patches I'd like to see
> >> >> the final result though. To facilitate that I have to re-raise a previously
> >> >> asked question: Do you have a tree somewhere which one could use
> >> >> to look at the final result?
> >> >
> >> > Sadly no.
> >>
> >> Alternatively, could you simply send the final resulting source file?
> >
> > Please look below...
>
> I don't think that was the file at the end of the series, as asked
> for above? There's no mb2 code in there afaics...

I understood that you need reloc.c after this patch but it looks
that I was wrong. So, here it is after applying whole series.

Daniel

/*
 * reloc.c
 *
 * 32-bit flat memory-map routines for relocating Multiboot structures
 * and modules. This is most easily done early with paging disabled.
 *
 * Copyright (c) 2009, Citrix Systems, Inc.
 * Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
 *
 * Authors:
 *    Keir Fraser <keir@xen.org>
 *    Daniel Kiper <daniel.kiper@oracle.com>
 */

/*
 * This entry point is entered from xen/arch/x86/boot/head.S with:
 *   - 0x4(%esp) = MULTIBOOT_MAGIC,
 *   - 0x8(%esp) = MULTIBOOT_INFORMATION_ADDRESS,
 *   - 0xc(%esp) = BOOT_TRAMPOLINE_ADDRESS.
 */
asm (
    "    .text                         \n"
    "    .globl _start                 \n"
    "_start:                           \n"
    "    jmp  reloc                    \n"
    );

typedef unsigned int u32;
typedef unsigned long long u64;

#include "../../../include/xen/multiboot.h"
#include "../../../include/xen/multiboot2.h"

#define NULL		((void *)0)

#define __stdcall	__attribute__((__stdcall__))

#define ALIGN_UP(arg, align) \
                (((arg) + (align) - 1) & ~((typeof(arg))(align) - 1))

#define get_mb2_data(tag, type, member)   (((multiboot2_tag_##type##_t *)(tag))->member)
#define get_mb2_string(tag, type, member) ((u32)get_mb2_data(tag, type, member))

static u32 alloc;

static u32 alloc_mem(u32 bytes)
{
    return alloc -= ALIGN_UP(bytes, 16);
}

static void zero_mem(u32 s, u32 bytes)
{
    while ( bytes-- )
        *(char *)s++ = 0;
}

static u32 copy_mem(u32 src, u32 bytes)
{
    u32 dst, dst_ret;

    dst = alloc_mem(bytes);
    dst_ret = dst;

    while ( bytes-- )
        *(char *)dst++ = *(char *)src++;

    return dst_ret;
}

static u32 copy_string(u32 src)
{
    u32 p;

    if ( src == 0 )
        return 0;

    for ( p = src; *(char *)p != '\0'; p++ )
        continue;

    return copy_mem(src, p - src + 1);
}

static multiboot_info_t *mbi_mbi(u32 mbi_in)
{
    int i;
    multiboot_info_t *mbi_out;

    mbi_out = (multiboot_info_t *)copy_mem(mbi_in, sizeof(*mbi_out));

    if ( mbi_out->flags & MBI_CMDLINE )
        mbi_out->cmdline = copy_string(mbi_out->cmdline);

    if ( mbi_out->flags & MBI_MODULES )
    {
        module_t *mods;

        mbi_out->mods_addr = copy_mem(mbi_out->mods_addr,
                                      mbi_out->mods_count * sizeof(module_t));

        mods = (module_t *)mbi_out->mods_addr;

        for ( i = 0; i < mbi_out->mods_count; i++ )
        {
            if ( mods[i].string )
                mods[i].string = copy_string(mods[i].string);
        }
    }

    if ( mbi_out->flags & MBI_MEMMAP )
        mbi_out->mmap_addr = copy_mem(mbi_out->mmap_addr, mbi_out->mmap_length);

    if ( mbi_out->flags & MBI_LOADERNAME )
        mbi_out->boot_loader_name = copy_string(mbi_out->boot_loader_name);

    /* Mask features we don't understand or don't relocate. */
    mbi_out->flags &= (MBI_MEMLIMITS |
                       MBI_CMDLINE |
                       MBI_MODULES |
                       MBI_MEMMAP |
                       MBI_LOADERNAME);

    return mbi_out;
}

static multiboot_info_t *mbi2_mbi(u32 mbi_in)
{
    const multiboot2_memory_map_t *mmap_src;
    const multiboot2_tag_t *tag;
    module_t *mbi_out_mods = NULL;
    memory_map_t *mmap_dst;
    multiboot_info_t *mbi_out;
    u32 ptr;
    unsigned int i, mod_idx = 0;

    ptr = alloc_mem(sizeof(*mbi_out));
    mbi_out = (multiboot_info_t *)ptr;
    zero_mem(ptr, sizeof(*mbi_out));

    /* Skip Multiboot2 information fixed part. */
    ptr = ALIGN_UP(mbi_in + sizeof(multiboot2_fixed_t), MULTIBOOT2_TAG_ALIGN);

    /* Get the number of modules. */
    for ( tag = (multiboot2_tag_t *)ptr;
          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )
        if ( tag->type == MULTIBOOT2_TAG_TYPE_MODULE )
            ++mbi_out->mods_count;
        else if ( tag->type == MULTIBOOT2_TAG_TYPE_END )
            break;

    if ( mbi_out->mods_count )
    {
        mbi_out->flags = MBI_MODULES;
        mbi_out->mods_addr = alloc_mem(mbi_out->mods_count * sizeof(module_t));
        mbi_out_mods = (module_t *)mbi_out->mods_addr;
    }

    /* Skip Multiboot2 information fixed part. */
    ptr = ALIGN_UP(mbi_in + sizeof(multiboot2_fixed_t), MULTIBOOT2_TAG_ALIGN);

    /* Put all needed data into mbi_out. */
    for ( tag = (multiboot2_tag_t *)ptr;
          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )
        switch ( tag->type )
        {
        case MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME:
            mbi_out->flags |= MBI_LOADERNAME;
            ptr = get_mb2_string(tag, string, string);
            mbi_out->boot_loader_name = copy_string(ptr);
            break;

        case MULTIBOOT2_TAG_TYPE_CMDLINE:
            mbi_out->flags |= MBI_CMDLINE;
            ptr = get_mb2_string(tag, string, string);
            mbi_out->cmdline = copy_string(ptr);
            break;

        case MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO:
            mbi_out->flags |= MBI_MEMLIMITS;
            mbi_out->mem_lower = get_mb2_data(tag, basic_meminfo, mem_lower);
            mbi_out->mem_upper = get_mb2_data(tag, basic_meminfo, mem_upper);
            break;

        case MULTIBOOT2_TAG_TYPE_MMAP:
            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
                break;

            mbi_out->flags |= MBI_MEMMAP;
            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
            mbi_out->mmap_length *= sizeof(memory_map_t);

            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);

            mmap_src = get_mb2_data(tag, mmap, entries);
            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;

            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
            {
                /* Init size member properly. */
                mmap_dst[i].size = sizeof(memory_map_t);
                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
                /* Now copy a given region data. */
                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);
                mmap_dst[i].base_addr_low = (u32)mmap_src->addr;
                mmap_dst[i].base_addr_high = (u32)(mmap_src->addr >> 32);
                mmap_dst[i].length_low = (u32)mmap_src->len;
                mmap_dst[i].length_high = (u32)(mmap_src->len >> 32);
                mmap_dst[i].type = mmap_src->type;
            }
            break;

        case MULTIBOOT2_TAG_TYPE_MODULE:
            mbi_out_mods[mod_idx].mod_start = get_mb2_data(tag, module, mod_start);
            mbi_out_mods[mod_idx].mod_end = get_mb2_data(tag, module, mod_end);
            ptr = get_mb2_string(tag, module, cmdline);
            mbi_out_mods[mod_idx].string = copy_string(ptr);
            mbi_out_mods[mod_idx].reserved = 0;
            ++mod_idx;
            break;

        case MULTIBOOT2_TAG_TYPE_END:
            return mbi_out;

        default:
            break;
        }

    return mbi_out;
}

multiboot_info_t __stdcall *reloc(u32 mb_magic, u32 mbi_in, u32 trampoline)
{
    alloc = trampoline;

    if ( mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC )
        return mbi2_mbi(mbi_in);
    else
        return mbi_mbi(mbi_in);
}

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

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

* Re: [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-19 22:43 ` [PATCH v5 09/16] x86: add multiboot2 protocol support Daniel Kiper
  2016-08-25 11:50   ` Jan Beulich
@ 2016-08-31 20:18   ` Andrew Cooper
  2016-08-31 21:01     ` Daniel Kiper
  1 sibling, 1 reply; 70+ messages in thread
From: Andrew Cooper @ 2016-08-31 20:18 UTC (permalink / raw)
  To: Daniel Kiper, xen-devel
  Cc: jgross, sstabellini, cardoe, pgnet.dev, ning.sun, david.vrabel,
	jbeulich, qiaowei.ren, gang.wei, fu.wei

On 19/08/2016 23:43, Daniel Kiper wrote:
> @@ -106,3 +121,122 @@ multiboot_info_t __stdcall *reloc(u32 mbi_in, u32 trampoline)
>  
>      return mbi_out;
>  }
> +
> +static multiboot_info_t *mbi2_mbi(u32 mbi_in)
> +{
> +    const multiboot2_memory_map_t *mmap_src;
> +    const multiboot2_tag_t *tag;
> +    module_t *mbi_out_mods = NULL;
> +    memory_map_t *mmap_dst;
> +    multiboot_info_t *mbi_out;
> +    u32 ptr;
> +    unsigned int i, mod_idx = 0;
> +
> +    ptr = alloc_mem(sizeof(*mbi_out));
> +    mbi_out = (multiboot_info_t *)ptr;

It occurs to me that a lot of this code would be more simple if you also
pulled the

#define _p(val) ((void *)(unsigned long)val)

in from the usual header files.  It would shorten a lot of the
(multiboot_info_t *) casting, and reduce most multi-line statements to
single lines.

Can I also suggest using:

static multiboot_info_t *mbi2_mbi(u32 mbi_in_addr)
{
    const multiboot_info_t *mbi_in = _p(mbi_in_addr);
...

This would avoid repeatedly needing to cast the old mbi_in integer to
access fields like ->total_size.

> +    zero_mem(ptr, sizeof(*mbi_out));
> +
> +    /* Skip Multiboot2 information fixed part. */
> +    ptr = ALIGN_UP(mbi_in + sizeof(multiboot2_fixed_t), MULTIBOOT2_TAG_ALIGN);
> +
> +    /* Get the number of modules. */
> +    for ( tag = (multiboot2_tag_t *)ptr;
> +          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
> +          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )

Braces here please
{

> +        if ( tag->type == MULTIBOOT2_TAG_TYPE_MODULE )
> +            ++mbi_out->mods_count;
> +        else if ( tag->type == MULTIBOOT2_TAG_TYPE_END )
> +            break;

}

Given the complexity of the for statement, the exact code contained
inside the loop could do with this added clarity.

> +
> +    if ( mbi_out->mods_count )
> +    {

In the case that this condition evaluates false, and...

> +        mbi_out->flags = MBI_MODULES;
> +        mbi_out->mods_addr = alloc_mem(mbi_out->mods_count * sizeof(module_t));
> +        mbi_out_mods = (module_t *)mbi_out->mods_addr;
> +    }
> +
> +    /* Skip Multiboot2 information fixed part. */
> +    ptr = ALIGN_UP(mbi_in + sizeof(multiboot2_fixed_t), MULTIBOOT2_TAG_ALIGN);
> +
> +    /* Put all needed data into mbi_out. */
> +    for ( tag = (multiboot2_tag_t *)ptr;
> +          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
> +          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )
> +        switch ( tag->type )
> +        {
> +        case MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME:
> +            mbi_out->flags |= MBI_LOADERNAME;
> +            ptr = get_mb2_string(tag, string, string);
> +            mbi_out->boot_loader_name = copy_string(ptr);
> +            break;
> +
> +        case MULTIBOOT2_TAG_TYPE_CMDLINE:
> +            mbi_out->flags |= MBI_CMDLINE;
> +            ptr = get_mb2_string(tag, string, string);
> +            mbi_out->cmdline = copy_string(ptr);
> +            break;
> +
> +        case MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO:
> +            mbi_out->flags |= MBI_MEMLIMITS;
> +            mbi_out->mem_lower = get_mb2_data(tag, basic_meminfo, mem_lower);
> +            mbi_out->mem_upper = get_mb2_data(tag, basic_meminfo, mem_upper);
> +            break;
> +
> +        case MULTIBOOT2_TAG_TYPE_MMAP:
> +            if ( get_mb2_data(tag, mmap, entry_size) < sizeof(*mmap_src) )
> +                break;
> +
> +            mbi_out->flags |= MBI_MEMMAP;
> +            mbi_out->mmap_length = get_mb2_data(tag, mmap, size);
> +            mbi_out->mmap_length -= sizeof(multiboot2_tag_mmap_t);
> +            mbi_out->mmap_length /= get_mb2_data(tag, mmap, entry_size);
> +            mbi_out->mmap_length *= sizeof(memory_map_t);
> +
> +            mbi_out->mmap_addr = alloc_mem(mbi_out->mmap_length);
> +
> +            mmap_src = get_mb2_data(tag, mmap, entries);
> +            mmap_dst = (memory_map_t *)mbi_out->mmap_addr;
> +
> +            for ( i = 0; i < mbi_out->mmap_length / sizeof(memory_map_t); i++ )
> +            {
> +                /* Init size member properly. */
> +                mmap_dst[i].size = sizeof(memory_map_t);
> +                mmap_dst[i].size -= sizeof(((memory_map_t){0}).size);
> +                /* Now copy a given region data. */
> +                mmap_src = (void *)mmap_src + i * get_mb2_data(tag, mmap, entry_size);
> +                mmap_dst[i].base_addr_low = (u32)mmap_src->addr;
> +                mmap_dst[i].base_addr_high = (u32)(mmap_src->addr >> 32);
> +                mmap_dst[i].length_low = (u32)mmap_src->len;
> +                mmap_dst[i].length_high = (u32)(mmap_src->len >> 32);
> +                mmap_dst[i].type = mmap_src->type;
> +            }
> +            break;
> +
> +        case MULTIBOOT2_TAG_TYPE_MODULE:

... this tag gets found, then a NULL mbi_out_mods gets followed.

I realise that this calculation is a result of a double loop over the
tag list, but it would be better to code slightly more resiliently
(given both the very liberal use of casting, and the possiblity that
something else is modifying the memory while we are looking at it). 
Something like:

if ( mod_idx < mbi_out->mods_count )
{

> +            mbi_out_mods[mod_idx].mod_start = get_mb2_data(tag, module, mod_start);
> +            mbi_out_mods[mod_idx].mod_end = get_mb2_data(tag, module, mod_end);
> +            ptr = get_mb2_string(tag, module, cmdline);
> +            mbi_out_mods[mod_idx].string = copy_string(ptr);
> +            mbi_out_mods[mod_idx].reserved = 0;
> +            ++mod_idx;

}

should do.

~Andrew

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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-08-31 15:46       ` Jan Beulich
@ 2016-08-31 20:50         ` Daniel Kiper
  2016-09-01  7:46           ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 20:50 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Wed, Aug 31, 2016 at 09:46:31AM -0600, Jan Beulich wrote:
> >>> On 31.08.16 at 16:59, <daniel.kiper@oracle.com> wrote:
> > On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:

[...]

> >> > --- a/xen/arch/x86/boot/head.S
> >> > +++ b/xen/arch/x86/boot/head.S
> >> > @@ -12,13 +12,16 @@
> >> >          .text
> >> >          .code32
> >> >
> >> > -#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
> >> > +#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)
> >>
> >> In a patch already large and hence hard to review, did you really
> >> need to do this rename?
> >
> > I think that sym_offset() is better term here. However, if you wish
> > I can leave sym_phys() as is. Though, IMO, sym_phys() name suggests
> > that we are playing with physical addresses and it is not correct in
> > all contexts, e.g. loot at fs_offset() (or sym_fs() as you wish).
>
> After some more thinking about this I agree sym_phys() isn't
> ideal anymore after this patch. Still, to avoid unrelated changes in
> this quite hard to review patch, I'd like to ask that you keep the
> name here and do just the rename in a subsequent patch.

Granted!

[...]

> >> > --- a/xen/arch/x86/boot/trampoline.S
> >> > +++ b/xen/arch/x86/boot/trampoline.S
> >> > @@ -54,12 +54,20 @@ trampoline_gdt:
> >> >          /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
> >> >          .long   0x0000ffff
> >> >          .long   0x00009200
> >> > +        /*
> >> > +         * 0x0030: ring 0 Xen data, 16 MiB size, base
> >> > +         * address is computed during runtime.
> >> > +         */
> >> > +        .quad   0x00c0920000001000
> >>
> >> This does not look like it covers 1Mb, it's more like 1Mb+4k-1.
> >
> > I have checked it once again. It covers 16 MiB as required:
> >   4 KiB * 0x1000 = 0x1000000 (no taking into account relocation).
>
> I'm sorry, but no. The raw limit value taken from that descriptor
> is 0x1000, and the G bit is set. That makes the actual limit 0x1000fff.

I was not sure why but this explains it: "When the granularity flag is
set, the twelve least significant bits of an offset are not tested when
checking the offset against the segment limit. For example, when the
granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095."
(Intel(R) 64 and IA-32 Architectures Software Developer’s Manual Volume 3
(3A, 3B & 3C): System Programming Guide). So, it means that this should be:

  .quad 0x00c0920000000fff

[...]

> >> >          .pushsection .trampoline_rel, "a"
> >> >          .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
> >> >          .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
> >> >          .popsection
> >> >
> >> > +GLOBAL(xen_img_load_base_addr)
> >> > +        .long   0
> >>
> >> I've yet to understand the purpose of this symbol, but in any case:
> >> If the trampoline code doesn't reference it, why does it get placed
> >> here?
> >
> > This symbol was used by code which unconditionally relocated Xen image
> > even if boot loader did work for us. I removed most of this code because
> > we agreed that if boot loader relocated Xen image then we do not have to
> > relocate it higher once again. If you are still OK with this idea I can go
> > further, as I planned, and remove all such remnants from next release.
> > However, it looks that then I have to store load address in xen_phys_start
> > from 32-bit assembly code. So, it will be nice if I can define it as
> > "unsigned int" instead of "unsigned long". Is it safe?
>
> I don't see why you shouldn't be able to store into the low 32 bits of
> the variable without altering the high ones (which are all zero).

I was thinking about that too but IMO it is not nice. However, if you
are OK with that I can do it.

> >> >          s = (boot_e820.map[i].addr + mask) & ~mask;
> >> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
> >> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
> >> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
> >> >              continue;
> >>
> >> This means you now map memory between 2Mb and 16Mb here. Is
> >> this necessary?
> >
> > Without this change Xen relocated by boot loader crashes with:
> >
> > (XEN) Panic on CPU 0:
> > (XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
> >
> > So, it must be mapped.
>
> That's too little context to be useful for understanding the full
> background.

Here it is:

(XEN) Detected 2194.733 MHz processor.
(XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
(XEN) ----[ Xen-4.8-unstable  x86_64  debug=y  Tainted:  C   ]----
(XEN) CPU:    0
(XEN) RIP:    e008:[<ffff82d0803c55d4>] subarch_init_memory+0x53e/0x5ea
(XEN) RFLAGS: 0000000000010046   CONTEXT: hypervisor
(XEN) rax: ffff830000200000   rbx: ffffffffffffffff   rcx: 0000000000000000
(XEN) rdx: 0000000000000000   rsi: 000000007ea04000   rdi: 8000000000000000
(XEN) rbp: ffff82d080417d78   rsp: ffff82d080417d38   r8:  ffff830000000000
(XEN) r9:  00000007c7ffffff   r10: ffffffffffffffff   r11: 0000000000000000
(XEN) r12: ffff83007ea04008   r13: 0000000000000000   r14: 0000000000000000
(XEN) r15: 0000000000000000   cr0: 000000008005003b   cr4: 00000000000006e0
(XEN) cr3: 000000007ea0c000   cr2: 0000000000000000
(XEN) ds: 0000   es: 0000   fs: 0000   gs: 0000   ss: 0000   cs: e008
(XEN) Xen code around <ffff82d0803c55d4> (subarch_init_memory+0x53e/0x5ea):
(XEN)  09 fe 41 f6 c6 01 75 02 <0f> 0b 41 f6 c6 80 74 0f 48 09 fa 49 89 14 24 48
(XEN) Xen stack trace from rsp=ffff82d080417d38:
(XEN)    ffff82d0802324c3 000000000007ea04 ffff82d080417d78 0000000000180000
(XEN)    0000000000000009 0000000000180000 ffff82e000000000 0000000000180000
(XEN)    ffff82d080417db8 ffff82d0803c42af ffff82d080417da8 ffff82d080417fff
(XEN)    ffff83017f1e0670 ffff82d08054cad0 ffff82d08054cad0 0000000000000003
(XEN)    ffff82d080417f08 ffff82d0803ca8d5 0000000000000000 0000000000000001
(XEN)    0000024d00000000 000000000034cc00 000000000000014d 00000000000001f5
(XEN)    00000000000001f5 000000000000019f 000000000000019f 000000000000014e
(XEN)    000000000000014e 0000000000000002 0000000000000001 0000000000000001
(XEN)    0000000000000001 0000000000000001 0000000000000001 0000000000000001
(XEN)    0000000000b42000 ffff83000008eee0 0000000000000000 000000000000000e
(XEN)    0000000000180000 ffff83000008efa0 000000017f1f2000 fffffffffffff001
(XEN)    ffff83000008efb0 ffff82d0803ef99c 0000000000000000 0000000000000000
(XEN)    0000000800000000 000000010000006e 0000000000000003 00000000000002f8
(XEN)    0000000000000000 0000000000000000 0000000000000000 0000000000000000
(XEN)    0000000000000000 0000000000000000 0000000000000000 ffff82d0802000f3
(XEN)    0000000000000000 0000000000000000 0000000000000000 0000000000000000
(XEN)    0000000000000000 0000000000000000 0000000000000000 0000000000000000
(XEN)    0000000000000000 0000000000000000 0000000000000000 0000000000000000
(XEN)    0000000000000000 0000000000000000 0000000000000000 0000000000000000
(XEN)    0000000000000000 0000000000000000 0000000000000000 0000000000000000
(XEN) Xen call trace:
(XEN)    [<ffff82d0803c55d4>] subarch_init_memory+0x53e/0x5ea
(XEN)    [<ffff82d0803c42af>] arch_init_memory+0x2f3/0x5d3
(XEN)    [<ffff82d0803ca8d5>] __start_xen+0x242f/0x2965
(XEN)    [<ffff82d0802000f3>] __high_start+0x53/0x60
(XEN)
(XEN)
(XEN) ****************************************
(XEN) Panic on CPU 0:
(XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
(XEN) ****************************************

Is it sufficient? If not please drop me a line what else do you need.

Daniel

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

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

* Re: [PATCH v5 09/16] x86: add multiboot2 protocol support
  2016-08-31 20:18   ` Andrew Cooper
@ 2016-08-31 21:01     ` Daniel Kiper
  0 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-08-31 21:01 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: jgross, sstabellini, cardoe, pgnet.dev, ning.sun, david.vrabel,
	jbeulich, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Wed, Aug 31, 2016 at 09:18:39PM +0100, Andrew Cooper wrote:
> On 19/08/2016 23:43, Daniel Kiper wrote:
> > @@ -106,3 +121,122 @@ multiboot_info_t __stdcall *reloc(u32 mbi_in, u32 trampoline)
> >
> >      return mbi_out;
> >  }
> > +
> > +static multiboot_info_t *mbi2_mbi(u32 mbi_in)
> > +{
> > +    const multiboot2_memory_map_t *mmap_src;
> > +    const multiboot2_tag_t *tag;
> > +    module_t *mbi_out_mods = NULL;
> > +    memory_map_t *mmap_dst;
> > +    multiboot_info_t *mbi_out;
> > +    u32 ptr;
> > +    unsigned int i, mod_idx = 0;
> > +
> > +    ptr = alloc_mem(sizeof(*mbi_out));
> > +    mbi_out = (multiboot_info_t *)ptr;
>
> It occurs to me that a lot of this code would be more simple if you also
> pulled the
>
> #define _p(val) ((void *)(unsigned long)val)
>
> in from the usual header files.  It would shorten a lot of the
> (multiboot_info_t *) casting, and reduce most multi-line statements to
> single lines.
>
> Can I also suggest using:

[...]

Make sense for me. I will try to get all your comments into account.

Thanks a lot,

Daniel

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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-31 19:39             ` Daniel Kiper
@ 2016-09-01  7:35               ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-09-01  7:35 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 31.08.16 at 21:39, <daniel.kiper@oracle.com> wrote:
> I understood that you need reloc.c after this patch but it looks
> that I was wrong. So, here it is after applying whole series.

Thanks. Here are my notes:

All callers of alloc_mem() cast the result to a pointer. While most of
them also need the result as an integer, there's one exception:

    ptr = alloc_mem(sizeof(*mbi_out));
    mbi_out = (multiboot_info_t *)ptr;
    zero_mem(ptr, sizeof(*mbi_out));

Since this is also the only caller of zero_mem() it tells me that less
casting would be needed if alloc_mem() returned void *, and if
zero_mem() took void * for its first parameter.

Otoh it looks like copy_{mem,string}() are best left the way they are
now.

The amount of casting in e.g.

    for ( tag = (multiboot2_tag_t *)ptr;
          (u32)tag - mbi_in < ((multiboot2_fixed_t *)mbi_in)->total_size;
          tag = (multiboot2_tag_t *)ALIGN_UP((u32)tag + tag->size, MULTIBOOT2_TAG_ALIGN) )

is still ugly, the more that the entire construct exists more than once.
One thing to consider (which would make things at least a little less
fragile) would be to make tag (and maybe then also mbi_in) a union of
u32 and multiboot2_fixed_t *. For parameter passing purposes from
reloc() it may then be desirable for this to actually be a transparent
union.

Jan


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

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

* Re: [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-08-31 17:07         ` Daniel Kiper
@ 2016-09-01  7:40           ` Jan Beulich
  2016-09-01 20:37             ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-09-01  7:40 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 31.08.16 at 19:07, <daniel.kiper@oracle.com> wrote:
> On Wed, Aug 31, 2016 at 06:49:51AM -0600, Jan Beulich wrote:
>> >>> On 30.08.16 at 21:32, <daniel.kiper@oracle.com> wrote:
>> > On Thu, Aug 25, 2016 at 06:59:54AM -0600, Jan Beulich wrote:
>> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> >> > --- a/xen/arch/x86/efi/stub.c
>> >> > +++ b/xen/arch/x86/efi/stub.c
>> >> > @@ -3,6 +3,30 @@
>> >> >  #include <xen/init.h>
>> >> >  #include <xen/lib.h>
>> >> >  #include <asm/page.h>
>> >> > +#include <asm/efibind.h>
>> >> > +#include <efi/efidef.h>
>> >> > +#include <efi/eficapsule.h>
>> >> > +#include <efi/eficon.h>
>> >> > +#include <efi/efidevp.h>
>> >> > +#include <efi/efiapi.h>
>> >> > +
>> >> > +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>> >> > +{
>> >> > +    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
>> >> > +    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
>> >> > +
>> >> > +    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
>> >> > +
>> >> > +    /* Print error message and halt the system. */
>> >> > +    asm volatile(
>> >> > +    "    call %2                      \n"
>> >> > +    "0:  hlt                          \n"
>> >> > +    "    jmp  0b                      \n"
>> >> > +       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
>> >> > +       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");
>> >>
>> >> There are explanations missing here: First, a warning should be added
>> >> alongside the EFI header inclusions, making clear that no services
>> >> whatsoever can be called. And then the asm() here needs to explain
>> >
>> > I am not convinced but if you wish...
>>
>> Not convinced of what?
> 
> About "... a warning should be added alongside the EFI header inclusions,
> making clear that no services whatsoever can be called". AIUI, "warning" ==
> "comment" here. However, I think that everybody who reads this file is
> aware that "no services whatsoever can be called". So, I am not sure
> where is the point.

Odd - you do an EFI call here (in the asm()) and talk about reader's
awareness?

>> >> need for an explicit "cc" clobber on x86.
>> >
>> > Why?
>>
>> Because such a clobber gets added to every asm() by the compiler,
>> unless it uses the (new in gcc 6) flag output. I've actually suggested
>> to upstream a patch making it possible to avoid that automatic
>> addition, but there hadn't been a whole lot of useful feedback.
> 
> So, when somebody uses this new flag then "cc" will not be add here.
> This is not big deal but I think that extra "cc" clobbers does not
> hurt too.

It surely doesn't hurt, but it makes code bigger and hence results in
it taking longer to be read and parsed (for all of these - even if just
slightly). I'm sorry, but I'm opposed to adding unnecessary stuff.

Jan


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

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

* Re: [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-08-31 19:31         ` Daniel Kiper
@ 2016-09-01  7:41           ` Jan Beulich
  2016-09-01 20:43             ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-09-01  7:41 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 31.08.16 at 21:31, <daniel.kiper@oracle.com> wrote:
> On Wed, Aug 31, 2016 at 07:01:10AM -0600, Jan Beulich wrote:
>> >>> On 30.08.16 at 21:58, <daniel.kiper@oracle.com> wrote:
>> > On Thu, Aug 25, 2016 at 07:27:21AM -0600, Jan Beulich wrote:
>> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> 
> [...]
> 
>> >> > +static unsigned int strtoui(const char *s, const char *stop, const char 
> **next)
>> >> > +{
>> >> > +    char l;
>> >> > +    unsigned int base = 10, ores = 0, res = 0;
>> >> > +
>> >> > +    if ( *s == '0' )
>> >> > +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
>> >> > +
>> >> > +    for ( ; *s != '\0'; ++s )
>> >> > +    {
>> >> > +        if ( stop && strchr(stop, *s) )
>> >> > +            goto out;
>> >> > +
>> >> > +        if ( *s < '0' || (*s > '7' && base == 8) )
>> >> > +        {
>> >> > +            res = UINT_MAX;
>> >> > +            goto out;
>> >> > +        }
>> >> > +
>> >> > +        l = tolower(*s);
>> >> > +
>> >> > +        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
>> >> > +        {
>> >> > +            res = UINT_MAX;
>> >> > +            goto out;
>> >> > +        }
>> >> > +
>> >> > +        res *= base;
>> >> > +        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
>> >> > +
>> >> > +        if ( ores > res )
>> >> > +        {
>> >> > +            res = UINT_MAX;
>> >> > +            goto out;
>> >> > +        }
>> >>
>> >> Without having spent time to try and find an example, it feels like this
>> >> check won't catch all possible overflow conditions. If you care about
>> >> overflow, please make sure you catch all cases.
>> >
>> > Hmmm.... How come? Could you give an example?
>>
>> Excuse me, but shouldn't you instead demonstrate the logic is
>> correct? Or - consider what I had said - try to find an example
>> yourself? It's not that difficult: With 16-bit word size
>> 0x3333 * 10 = 0x1fffe, which truncates to 0xfffe and is hence
>> larger than both inputs but still produced an overflow. This
>> easily extends to 32- and 64-bit word size.
> 
> Oh, boy. I forgot about multiplication. I think that we can define
> res as unsigned long and then check that it is < UINT_MAX.
> If not then return UINT_MAX.

Aren't we in 32-bit code here, i.e. sizeof(int) == sizeof(long)?

Jan


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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-08-31 20:50         ` Daniel Kiper
@ 2016-09-01  7:46           ` Jan Beulich
  2016-09-01 21:19             ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-09-01  7:46 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 31.08.16 at 22:50, <daniel.kiper@oracle.com> wrote:
> On Wed, Aug 31, 2016 at 09:46:31AM -0600, Jan Beulich wrote:
>> >>> On 31.08.16 at 16:59, <daniel.kiper@oracle.com> wrote:
>> > On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
>> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> >> > --- a/xen/arch/x86/boot/head.S
>> >> > +++ b/xen/arch/x86/boot/head.S
>> >> > @@ -12,13 +12,16 @@
>> >> >          .text
>> >> >          .code32
>> >> >
>> >> > -#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
>> >> > +#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)
>> >>
>> >> In a patch already large and hence hard to review, did you really
>> >> need to do this rename?
>> >
>> > I think that sym_offset() is better term here. However, if you wish
>> > I can leave sym_phys() as is. Though, IMO, sym_phys() name suggests
>> > that we are playing with physical addresses and it is not correct in
>> > all contexts, e.g. loot at fs_offset() (or sym_fs() as you wish).
>>
>> After some more thinking about this I agree sym_phys() isn't
>> ideal anymore after this patch. Still, to avoid unrelated changes in
>> this quite hard to review patch, I'd like to ask that you keep the
>> name here and do just the rename in a subsequent patch.
> 
> Granted!

Btw., to save on typing and since you will need to touch this anyway
- can I talk you into using sym_offs() instead of sym_offset()?

>> >> >          .pushsection .trampoline_rel, "a"
>> >> >          .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
>> >> >          .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
>> >> >          .popsection
>> >> >
>> >> > +GLOBAL(xen_img_load_base_addr)
>> >> > +        .long   0
>> >>
>> >> I've yet to understand the purpose of this symbol, but in any case:
>> >> If the trampoline code doesn't reference it, why does it get placed
>> >> here?
>> >
>> > This symbol was used by code which unconditionally relocated Xen image
>> > even if boot loader did work for us. I removed most of this code because
>> > we agreed that if boot loader relocated Xen image then we do not have to
>> > relocate it higher once again. If you are still OK with this idea I can go
>> > further, as I planned, and remove all such remnants from next release.
>> > However, it looks that then I have to store load address in xen_phys_start
>> > from 32-bit assembly code. So, it will be nice if I can define it as
>> > "unsigned int" instead of "unsigned long". Is it safe?
>>
>> I don't see why you shouldn't be able to store into the low 32 bits of
>> the variable without altering the high ones (which are all zero).
> 
> I was thinking about that too but IMO it is not nice. However, if you
> are OK with that I can do it.

Well, imo that's something which is perfectly fine in assembly code.

>> >> >          s = (boot_e820.map[i].addr + mask) & ~mask;
>> >> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
>> >> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
>> >> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
>> >> >              continue;
>> >>
>> >> This means you now map memory between 2Mb and 16Mb here. Is
>> >> this necessary?
>> >
>> > Without this change Xen relocated by boot loader crashes with:
>> >
>> > (XEN) Panic on CPU 0:
>> > (XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
>> >
>> > So, it must be mapped.
>>
>> That's too little context to be useful for understanding the full
>> background.
> 
> Here it is:
>[...]
> Is it sufficient? If not please drop me a line what else do you need.

I'm sorry, but no. I didn't mean the whole register and stack dump. I
meant an explanation of _why_ this assertion triggers (after all it
doesn't trigger without your patches, and hence I can't just go and
check the relevant source files).

Jan


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

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

* Re: [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms
  2016-09-01  7:40           ` Jan Beulich
@ 2016-09-01 20:37             ` Daniel Kiper
  0 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-09-01 20:37 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Sep 01, 2016 at 01:40:11AM -0600, Jan Beulich wrote:
> >>> On 31.08.16 at 19:07, <daniel.kiper@oracle.com> wrote:
> > On Wed, Aug 31, 2016 at 06:49:51AM -0600, Jan Beulich wrote:
> >> >>> On 30.08.16 at 21:32, <daniel.kiper@oracle.com> wrote:
> >> > On Thu, Aug 25, 2016 at 06:59:54AM -0600, Jan Beulich wrote:
> >> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> >> > --- a/xen/arch/x86/efi/stub.c
> >> >> > +++ b/xen/arch/x86/efi/stub.c
> >> >> > @@ -3,6 +3,30 @@
> >> >> >  #include <xen/init.h>
> >> >> >  #include <xen/lib.h>
> >> >> >  #include <asm/page.h>
> >> >> > +#include <asm/efibind.h>
> >> >> > +#include <efi/efidef.h>
> >> >> > +#include <efi/eficapsule.h>
> >> >> > +#include <efi/eficon.h>
> >> >> > +#include <efi/efidevp.h>
> >> >> > +#include <efi/efiapi.h>
> >> >> > +
> >> >> > +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> >> >> > +{
> >> >> > +    CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n";
> >> >> > +    SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
> >> >> > +
> >> >> > +    StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut;
> >> >> > +
> >> >> > +    /* Print error message and halt the system. */
> >> >> > +    asm volatile(
> >> >> > +    "    call %2                      \n"
> >> >> > +    "0:  hlt                          \n"
> >> >> > +    "    jmp  0b                      \n"
> >> >> > +       : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString)
> >> >> > +       : "rax", "r8", "r9", "r10", "r11", "cc", "memory");
> >> >>
> >> >> There are explanations missing here: First, a warning should be added
> >> >> alongside the EFI header inclusions, making clear that no services
> >> >> whatsoever can be called. And then the asm() here needs to explain
> >> >
> >> > I am not convinced but if you wish...
> >>
> >> Not convinced of what?
> >
> > About "... a warning should be added alongside the EFI header inclusions,
> > making clear that no services whatsoever can be called". AIUI, "warning" ==
> > "comment" here. However, I think that everybody who reads this file is
> > aware that "no services whatsoever can be called". So, I am not sure
> > where is the point.
>
> Odd - you do an EFI call here (in the asm()) and talk about reader's
> awareness?

I do this in quite strange way just to display clear error from file called
stub.c which contains just mostly function stubs. So, I have a feeling that
sane reader will be conscious here and will not expect code which does sensible
stuff. However, if you still think that these are insufficient then I can add
warninng/comment which assures potential reader that this is a stub file and
most functions does nothing except efi_multiboot2().

> >> >> need for an explicit "cc" clobber on x86.
> >> >
> >> > Why?
> >>
> >> Because such a clobber gets added to every asm() by the compiler,
> >> unless it uses the (new in gcc 6) flag output. I've actually suggested
> >> to upstream a patch making it possible to avoid that automatic
> >> addition, but there hadn't been a whole lot of useful feedback.
> >
> > So, when somebody uses this new flag then "cc" will not be add here.
> > This is not big deal but I think that extra "cc" clobbers does not
> > hurt too.
>
> It surely doesn't hurt, but it makes code bigger and hence results in
> it taking longer to be read and parsed (for all of these - even if just
> slightly). I'm sorry, but I'm opposed to adding unnecessary stuff.

As you wish...

Daniel

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

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

* Re: [PATCH v5 14/16] x86/boot: implement early command line parser in C
  2016-09-01  7:41           ` Jan Beulich
@ 2016-09-01 20:43             ` Daniel Kiper
  0 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-09-01 20:43 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Sep 01, 2016 at 01:41:26AM -0600, Jan Beulich wrote:
> >>> On 31.08.16 at 21:31, <daniel.kiper@oracle.com> wrote:
> > On Wed, Aug 31, 2016 at 07:01:10AM -0600, Jan Beulich wrote:
> >> >>> On 30.08.16 at 21:58, <daniel.kiper@oracle.com> wrote:
> >> > On Thu, Aug 25, 2016 at 07:27:21AM -0600, Jan Beulich wrote:
> >> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >
> > [...]
> >
> >> >> > +static unsigned int strtoui(const char *s, const char *stop, const char
> > **next)
> >> >> > +{
> >> >> > +    char l;
> >> >> > +    unsigned int base = 10, ores = 0, res = 0;
> >> >> > +
> >> >> > +    if ( *s == '0' )
> >> >> > +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
> >> >> > +
> >> >> > +    for ( ; *s != '\0'; ++s )
> >> >> > +    {
> >> >> > +        if ( stop && strchr(stop, *s) )
> >> >> > +            goto out;
> >> >> > +
> >> >> > +        if ( *s < '0' || (*s > '7' && base == 8) )
> >> >> > +        {
> >> >> > +            res = UINT_MAX;
> >> >> > +            goto out;
> >> >> > +        }
> >> >> > +
> >> >> > +        l = tolower(*s);
> >> >> > +
> >> >> > +        if ( *s > '9' && (base != 16 || l < 'a' || l > 'f') )
> >> >> > +        {
> >> >> > +            res = UINT_MAX;
> >> >> > +            goto out;
> >> >> > +        }
> >> >> > +
> >> >> > +        res *= base;
> >> >> > +        res += (l >= 'a') ? (l - 'a' + 10) : (*s - '0');
> >> >> > +
> >> >> > +        if ( ores > res )
> >> >> > +        {
> >> >> > +            res = UINT_MAX;
> >> >> > +            goto out;
> >> >> > +        }
> >> >>
> >> >> Without having spent time to try and find an example, it feels like this
> >> >> check won't catch all possible overflow conditions. If you care about
> >> >> overflow, please make sure you catch all cases.
> >> >
> >> > Hmmm.... How come? Could you give an example?
> >>
> >> Excuse me, but shouldn't you instead demonstrate the logic is
> >> correct? Or - consider what I had said - try to find an example
> >> yourself? It's not that difficult: With 16-bit word size
> >> 0x3333 * 10 = 0x1fffe, which truncates to 0xfffe and is hence
> >> larger than both inputs but still produced an overflow. This
> >> easily extends to 32- and 64-bit word size.
> >
> > Oh, boy. I forgot about multiplication. I think that we can define
> > res as unsigned long and then check that it is < UINT_MAX.
> > If not then return UINT_MAX.
>
> Aren't we in 32-bit code here, i.e. sizeof(int) == sizeof(long)?

Yep, this should be unsigned long long here.

Daniel

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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-09-01  7:46           ` Jan Beulich
@ 2016-09-01 21:19             ` Daniel Kiper
  2016-09-02  6:58               ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-09-01 21:19 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Thu, Sep 01, 2016 at 01:46:24AM -0600, Jan Beulich wrote:
> >>> On 31.08.16 at 22:50, <daniel.kiper@oracle.com> wrote:
> > On Wed, Aug 31, 2016 at 09:46:31AM -0600, Jan Beulich wrote:
> >> >>> On 31.08.16 at 16:59, <daniel.kiper@oracle.com> wrote:
> >> > On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
> >> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> >> > --- a/xen/arch/x86/boot/head.S
> >> >> > +++ b/xen/arch/x86/boot/head.S
> >> >> > @@ -12,13 +12,16 @@
> >> >> >          .text
> >> >> >          .code32
> >> >> >
> >> >> > -#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
> >> >> > +#define sym_offset(sym)   ((sym) - __XEN_VIRT_START)
> >> >>
> >> >> In a patch already large and hence hard to review, did you really
> >> >> need to do this rename?
> >> >
> >> > I think that sym_offset() is better term here. However, if you wish
> >> > I can leave sym_phys() as is. Though, IMO, sym_phys() name suggests
> >> > that we are playing with physical addresses and it is not correct in
> >> > all contexts, e.g. loot at fs_offset() (or sym_fs() as you wish).
> >>
> >> After some more thinking about this I agree sym_phys() isn't
> >> ideal anymore after this patch. Still, to avoid unrelated changes in
> >> this quite hard to review patch, I'd like to ask that you keep the
> >> name here and do just the rename in a subsequent patch.
> >
> > Granted!
>
> Btw., to save on typing and since you will need to touch this anyway
> - can I talk you into using sym_offs() instead of sym_offset()?

Sure thing!

> >> >> >          .pushsection .trampoline_rel, "a"
> >> >> >          .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
> >> >> >          .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
> >> >> >          .popsection
> >> >> >
> >> >> > +GLOBAL(xen_img_load_base_addr)
> >> >> > +        .long   0
> >> >>
> >> >> I've yet to understand the purpose of this symbol, but in any case:
> >> >> If the trampoline code doesn't reference it, why does it get placed
> >> >> here?
> >> >
> >> > This symbol was used by code which unconditionally relocated Xen image
> >> > even if boot loader did work for us. I removed most of this code because
> >> > we agreed that if boot loader relocated Xen image then we do not have to
> >> > relocate it higher once again. If you are still OK with this idea I can go
> >> > further, as I planned, and remove all such remnants from next release.
> >> > However, it looks that then I have to store load address in xen_phys_start
> >> > from 32-bit assembly code. So, it will be nice if I can define it as
> >> > "unsigned int" instead of "unsigned long". Is it safe?
> >>
> >> I don't see why you shouldn't be able to store into the low 32 bits of
> >> the variable without altering the high ones (which are all zero).
> >
> > I was thinking about that too but IMO it is not nice. However, if you
> > are OK with that I can do it.
>
> Well, imo that's something which is perfectly fine in assembly code.

OK, I will do that.

> >> >> >          s = (boot_e820.map[i].addr + mask) & ~mask;
> >> >> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
> >> >> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
> >> >> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
> >> >> >              continue;
> >> >>
> >> >> This means you now map memory between 2Mb and 16Mb here. Is
> >> >> this necessary?
> >> >
> >> > Without this change Xen relocated by boot loader crashes with:
> >> >
> >> > (XEN) Panic on CPU 0:
> >> > (XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
> >> >
> >> > So, it must be mapped.
> >>
> >> That's too little context to be useful for understanding the full
> >> background.
> >
> > Here it is:
> >[...]
> > Is it sufficient? If not please drop me a line what else do you need.
>
> I'm sorry, but no. I didn't mean the whole register and stack dump. I
> meant an explanation of _why_ this assertion triggers (after all it
> doesn't trigger without your patches, and hence I can't just go and
> check the relevant source files).

AIUI, if Xen image is not relocated by boot loader (e.g. GRUB2) then region
2 MiB - 16 MiB is mapped. Later Xen after relocating itself marks 1 MiB - 16 MiB
region as NX (if it is supported by hardware) in subarch_init_memory(). However,
if boot loader relocate Xen then region 2 MiB - 16 MiB is not mapped if change
under consideration is not applied. Then ASSERT(l2e_get_flags(l2e) & _PAGE_PRESENT)
in subarch_init_memory() is triggered and Xen crashes.

I hope that helps.

Daniel

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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-09-01 21:19             ` Daniel Kiper
@ 2016-09-02  6:58               ` Jan Beulich
  2016-09-02  7:28                 ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-09-02  6:58 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 01.09.16 at 23:19, <daniel.kiper@oracle.com> wrote:
> On Thu, Sep 01, 2016 at 01:46:24AM -0600, Jan Beulich wrote:
>> >>> On 31.08.16 at 22:50, <daniel.kiper@oracle.com> wrote:
>> > On Wed, Aug 31, 2016 at 09:46:31AM -0600, Jan Beulich wrote:
>> >> >>> On 31.08.16 at 16:59, <daniel.kiper@oracle.com> wrote:
>> >> > On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
>> >> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> >> >> >          s = (boot_e820.map[i].addr + mask) & ~mask;
>> >> >> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
>> >> >> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
>> >> >> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
>> >> >> >              continue;
>> >> >>
>> >> >> This means you now map memory between 2Mb and 16Mb here. Is
>> >> >> this necessary?
>> >> >
>> >> > Without this change Xen relocated by boot loader crashes with:
>> >> >
>> >> > (XEN) Panic on CPU 0:
>> >> > (XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
>> >> >
>> >> > So, it must be mapped.
>> >>
>> >> That's too little context to be useful for understanding the full
>> >> background.
>> >
>> > Here it is:
>> >[...]
>> > Is it sufficient? If not please drop me a line what else do you need.
>>
>> I'm sorry, but no. I didn't mean the whole register and stack dump. I
>> meant an explanation of _why_ this assertion triggers (after all it
>> doesn't trigger without your patches, and hence I can't just go and
>> check the relevant source files).
> 
> AIUI, if Xen image is not relocated by boot loader (e.g. GRUB2) then region
> 2 MiB - 16 MiB is mapped. Later Xen after relocating itself marks 1 MiB - 16 MiB
> region as NX (if it is supported by hardware) in subarch_init_memory(). However,
> if boot loader relocate Xen then region 2 MiB - 16 MiB is not mapped if change
> under consideration is not applied. Then ASSERT(l2e_get_flags(l2e) & _PAGE_PRESENT)
> in subarch_init_memory() is triggered and Xen crashes.

Ah, I see now. But instead of altering the setup.c logic even for the
not relocated case, perhaps you'd better establish the here expected
mapping in the relocated case? I'm rather hesitant to see that setup.c
logic change for pre-existing cases; it may alternatively be acceptable
to make the line you delete conditional.

Jan


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

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

* Re: [PATCH v5 15/16] x86: make Xen early boot code relocatable
  2016-09-02  6:58               ` Jan Beulich
@ 2016-09-02  7:28                 ` Daniel Kiper
  0 siblings, 0 replies; 70+ messages in thread
From: Daniel Kiper @ 2016-09-02  7:28 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Fri, Sep 02, 2016 at 12:58:14AM -0600, Jan Beulich wrote:
> >>> On 01.09.16 at 23:19, <daniel.kiper@oracle.com> wrote:
> > On Thu, Sep 01, 2016 at 01:46:24AM -0600, Jan Beulich wrote:
> >> >>> On 31.08.16 at 22:50, <daniel.kiper@oracle.com> wrote:
> >> > On Wed, Aug 31, 2016 at 09:46:31AM -0600, Jan Beulich wrote:
> >> >> >>> On 31.08.16 at 16:59, <daniel.kiper@oracle.com> wrote:
> >> >> > On Thu, Aug 25, 2016 at 08:41:39AM -0600, Jan Beulich wrote:
> >> >> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> >> >> >          s = (boot_e820.map[i].addr + mask) & ~mask;
> >> >> >> >          e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
> >> >> >> > -        s = max_t(uint64_t, s, BOOTSTRAP_MAP_BASE);
> >> >> >> >          if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
> >> >> >> >              continue;
> >> >> >>
> >> >> >> This means you now map memory between 2Mb and 16Mb here. Is
> >> >> >> this necessary?
> >> >> >
> >> >> > Without this change Xen relocated by boot loader crashes with:
> >> >> >
> >> >> > (XEN) Panic on CPU 0:
> >> >> > (XEN) Assertion 'l2e_get_flags(l2e) & _PAGE_PRESENT' failed at x86_64/mm.c:902
> >> >> >
> >> >> > So, it must be mapped.
> >> >>
> >> >> That's too little context to be useful for understanding the full
> >> >> background.
> >> >
> >> > Here it is:
> >> >[...]
> >> > Is it sufficient? If not please drop me a line what else do you need.
> >>
> >> I'm sorry, but no. I didn't mean the whole register and stack dump. I
> >> meant an explanation of _why_ this assertion triggers (after all it
> >> doesn't trigger without your patches, and hence I can't just go and
> >> check the relevant source files).
> >
> > AIUI, if Xen image is not relocated by boot loader (e.g. GRUB2) then region
> > 2 MiB - 16 MiB is mapped. Later Xen after relocating itself marks 1 MiB - 16 MiB
> > region as NX (if it is supported by hardware) in subarch_init_memory(). However,
> > if boot loader relocate Xen then region 2 MiB - 16 MiB is not mapped if change
> > under consideration is not applied. Then ASSERT(l2e_get_flags(l2e) & _PAGE_PRESENT)
> > in subarch_init_memory() is triggered and Xen crashes.
>
> Ah, I see now. But instead of altering the setup.c logic even for the
> not relocated case, perhaps you'd better establish the here expected
> mapping in the relocated case? I'm rather hesitant to see that setup.c
> logic change for pre-existing cases; it may alternatively be acceptable
> to make the line you delete conditional.

...or map 2 MiB - 16 MiB region in xen/arch/x86/boot/head.S. It could
be done in similar way to Xen image mapping. However, this should be
tested...

Daniel

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

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

* Re: [PATCH v5 12/16] x86/efi: create new early memory allocator
  2016-08-19 22:43 ` [PATCH v5 12/16] x86/efi: create new early memory allocator Daniel Kiper
@ 2016-09-05 12:33   ` Jan Beulich
  2016-09-07 12:05     ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-09-05 12:33 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> --- a/xen/arch/x86/efi/efi-boot.h
> +++ b/xen/arch/x86/efi/efi-boot.h
> @@ -103,9 +103,56 @@ static void __init relocate_trampoline(unsigned long phys)
>          *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
>  }
>  
> +#define EBMALLOC_SIZE	MB(1)
> +
> +static char __section(".bss.page_aligned") ebmalloc_mem[EBMALLOC_SIZE];

You need to specify the alignment of the object (using the relatively
new __aligned() construct).

> +static char __initdata *ebmalloc_free = NULL;
> +
> +/* EFI boot allocator. */
> +static void __init *ebmalloc(size_t size)
> +{
> +    void *ptr;
> +
> +    /*
> +     * Init ebmalloc_free on runtime. Static initialization
> +     * will not work because it puts virtual address there.
> +     */

I don't understand this static allocation comment: We have this issue
elsewhere (and use bootsym() as needed), and we do not have this
issue at all in xen.efi (which this code also gets built for). So I think at
the very least the comment needs improvement. And then, if static
initialization indeed can't be used, then a static symbol's initializer of
NULL is pointless and hence should be omitted.

> +    if ( ebmalloc_free == NULL )
> +        ebmalloc_free = ebmalloc_mem;
> +
> +    ptr = ebmalloc_free;
> +
> +    ebmalloc_free += size;

No minimal (at least pointer size) alignment getting enforced
somewhere here?

> +void __init free_ebmalloc_unused_mem(void)
> +{
> +    unsigned long start, end;
> +
> +    if ( ebmalloc_free )
> +    {
> +        start = (unsigned long)ebmalloc_free - xen_phys_start;
> +        start = PAGE_ALIGN(start + XEN_VIRT_START);
> +    }
> +    else
> +        start = (unsigned long)ebmalloc_mem;
> +
> +    end = (unsigned long)ebmalloc_mem + sizeof(ebmalloc_mem);
> +
> +    destroy_xen_mappings(start, end);
> +    init_xenheap_pages(__pa(start), __pa(end));
> +
> +    printk("Freed %lukB unused BSS memory\n", (end - start) >> 10);

XENLOG_INFO

And then - wouldn't this better go into xen/common/efi/boot.c,
even if ARM64 does not have a use for it right away? The code
certainly isn't really x86-specific.

Jan


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

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

* Re: [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions
  2016-08-30 14:32     ` Daniel Kiper
  2016-08-30 15:12       ` Jan Beulich
@ 2016-09-06 15:33       ` Doug Goldstein
  1 sibling, 0 replies; 70+ messages in thread
From: Doug Goldstein @ 2016-09-06 15:33 UTC (permalink / raw)
  To: Daniel Kiper, Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, pgnet.dev, ning.sun,
	david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei


[-- Attachment #1.1.1: Type: text/plain, Size: 1082 bytes --]

On 8/30/16 9:32 AM, Daniel Kiper wrote:
> On Thu, Aug 25, 2016 at 05:34:31AM -0600, Jan Beulich wrote:
>>>>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>>> Create generic alloc and copy functions. We need
>>> separate tools for memory allocation and copy to
>>> provide multiboot2 protocol support.
>>>
>>> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
>>
>> The amount of casting in this patch alone looks very reasonable now.
>> Before ack-ing this and respective subsequent patches I'd like to see
>> the final result though. To facilitate that I have to re-raise a previously
>> asked question: Do you have a tree somewhere which one could use
>> to look at the final result?
> 
> Sadly no.
> 
> Daniel
> 

Daniel,

I'd encourage you to go to https://github.com/xen-project/xen and "fork"
the project and use that space to push your branches. It's free (as in
beer) hosting for any long series and you can enable
https://travis-ci.org to do some basic build tests on patch series
before you mail them out.

-- 
Doug Goldstein


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 959 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

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

* Re: [PATCH v5 12/16] x86/efi: create new early memory allocator
  2016-09-05 12:33   ` Jan Beulich
@ 2016-09-07 12:05     ` Daniel Kiper
  2016-09-07 14:01       ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-09-07 12:05 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Mon, Sep 05, 2016 at 06:33:57AM -0600, Jan Beulich wrote:
> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:

[...]

> > +static char __initdata *ebmalloc_free = NULL;
> > +
> > +/* EFI boot allocator. */
> > +static void __init *ebmalloc(size_t size)
> > +{
> > +    void *ptr;
> > +
> > +    /*
> > +     * Init ebmalloc_free on runtime. Static initialization
> > +     * will not work because it puts virtual address there.
> > +     */
>
> I don't understand this static allocation comment: We have this issue
> elsewhere (and use bootsym() as needed), and we do not have this
> issue at all in xen.efi (which this code also gets built for). So I think at
> the very least the comment needs improvement. And then, if static
> initialization indeed can't be used, then a static symbol's initializer of
> NULL is pointless and hence should be omitted.

You have to remember that xen/arch/x86/efi/efi-boot.h stuff is build
into xen.efi and xen.gz. Of course xen.efi with

static char __initdata *ebmalloc_free = ebmalloc_mem;

works, however, xen.gz does not. Sadly, I have not found simpler
solution for that issue, so, I do initialization during runtime.

> > +    if ( ebmalloc_free == NULL )
> > +        ebmalloc_free = ebmalloc_mem;
> > +
> > +    ptr = ebmalloc_free;
> > +
> > +    ebmalloc_free += size;
>
> No minimal (at least pointer size) alignment getting enforced
> somewhere here?

For what?

> > +void __init free_ebmalloc_unused_mem(void)
> > +{
> > +    unsigned long start, end;
> > +
> > +    if ( ebmalloc_free )
> > +    {
> > +        start = (unsigned long)ebmalloc_free - xen_phys_start;
> > +        start = PAGE_ALIGN(start + XEN_VIRT_START);
> > +    }
> > +    else
> > +        start = (unsigned long)ebmalloc_mem;
> > +
> > +    end = (unsigned long)ebmalloc_mem + sizeof(ebmalloc_mem);
> > +
> > +    destroy_xen_mappings(start, end);
> > +    init_xenheap_pages(__pa(start), __pa(end));
> > +
> > +    printk("Freed %lukB unused BSS memory\n", (end - start) >> 10);
>
> XENLOG_INFO

OK.

> And then - wouldn't this better go into xen/common/efi/boot.c,
> even if ARM64 does not have a use for it right away? The code
> certainly isn't really x86-specific.

Sure thing. However, if it is not used by ARM64 then I think ebmalloc
stuff should not be moved to xen/common/efi/boot.c.

Daniel

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

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

* Re: [PATCH v5 12/16] x86/efi: create new early memory allocator
  2016-09-07 12:05     ` Daniel Kiper
@ 2016-09-07 14:01       ` Jan Beulich
  2016-09-08  8:29         ` Daniel Kiper
  0 siblings, 1 reply; 70+ messages in thread
From: Jan Beulich @ 2016-09-07 14:01 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 07.09.16 at 14:05, <daniel.kiper@oracle.com> wrote:
> On Mon, Sep 05, 2016 at 06:33:57AM -0600, Jan Beulich wrote:
>> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> > +static char __initdata *ebmalloc_free = NULL;
>> > +
>> > +/* EFI boot allocator. */
>> > +static void __init *ebmalloc(size_t size)
>> > +{
>> > +    void *ptr;
>> > +
>> > +    /*
>> > +     * Init ebmalloc_free on runtime. Static initialization
>> > +     * will not work because it puts virtual address there.
>> > +     */
>>
>> I don't understand this static allocation comment: We have this issue
>> elsewhere (and use bootsym() as needed), and we do not have this
>> issue at all in xen.efi (which this code also gets built for). So I think at
>> the very least the comment needs improvement. And then, if static
>> initialization indeed can't be used, then a static symbol's initializer of
>> NULL is pointless and hence should be omitted.
> 
> You have to remember that xen/arch/x86/efi/efi-boot.h stuff is build
> into xen.efi and xen.gz. Of course xen.efi with
> 
> static char __initdata *ebmalloc_free = ebmalloc_mem;
> 
> works, however, xen.gz does not. Sadly, I have not found simpler
> solution for that issue, so, I do initialization during runtime.

Which all is in line with my request of improving the comment.

>> > +    if ( ebmalloc_free == NULL )
>> > +        ebmalloc_free = ebmalloc_mem;
>> > +
>> > +    ptr = ebmalloc_free;
>> > +
>> > +    ebmalloc_free += size;
>>
>> No minimal (at least pointer size) alignment getting enforced
>> somewhere here?
> 
> For what?

To avoid the penalty unaligned accesses incur? And that's alongside
the fact that it's simply bad practice to knowingly but without actual
need cause unaligned accesses even if they work fine.

>> And then - wouldn't this better go into xen/common/efi/boot.c,
>> even if ARM64 does not have a use for it right away? The code
>> certainly isn't really x86-specific.
> 
> Sure thing. However, if it is not used by ARM64 then I think ebmalloc
> stuff should not be moved to xen/common/efi/boot.c.

Being architecture independent it has all reasons to be moved
there. Agreed there may be compiler warnings for these then
being unused static functions, but I'd rather see this code get
#ifdef-ed out for ARM for the time being than it needing to be
moved over later on. And of course a question to be asked first
is whether in fact there is something in common or ARM specific
code that could benefit from using this new allocator, if you
already introduce it.

Jan


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

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

* Re: [PATCH v5 12/16] x86/efi: create new early memory allocator
  2016-09-07 14:01       ` Jan Beulich
@ 2016-09-08  8:29         ` Daniel Kiper
  2016-09-08  9:59           ` Jan Beulich
  0 siblings, 1 reply; 70+ messages in thread
From: Daniel Kiper @ 2016-09-08  8:29 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

On Wed, Sep 07, 2016 at 08:01:31AM -0600, Jan Beulich wrote:
> >>> On 07.09.16 at 14:05, <daniel.kiper@oracle.com> wrote:
> > On Mon, Sep 05, 2016 at 06:33:57AM -0600, Jan Beulich wrote:
> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
> >> > +static char __initdata *ebmalloc_free = NULL;
> >> > +
> >> > +/* EFI boot allocator. */
> >> > +static void __init *ebmalloc(size_t size)
> >> > +{
> >> > +    void *ptr;
> >> > +
> >> > +    /*
> >> > +     * Init ebmalloc_free on runtime. Static initialization
> >> > +     * will not work because it puts virtual address there.
> >> > +     */
> >>
> >> I don't understand this static allocation comment: We have this issue
> >> elsewhere (and use bootsym() as needed), and we do not have this
> >> issue at all in xen.efi (which this code also gets built for). So I think at
> >> the very least the comment needs improvement. And then, if static
> >> initialization indeed can't be used, then a static symbol's initializer of
> >> NULL is pointless and hence should be omitted.
> >
> > You have to remember that xen/arch/x86/efi/efi-boot.h stuff is build
> > into xen.efi and xen.gz. Of course xen.efi with
> >
> > static char __initdata *ebmalloc_free = ebmalloc_mem;
> >
> > works, however, xen.gz does not. Sadly, I have not found simpler
> > solution for that issue, so, I do initialization during runtime.
>
> Which all is in line with my request of improving the comment.

OK.

> >> > +    if ( ebmalloc_free == NULL )
> >> > +        ebmalloc_free = ebmalloc_mem;
> >> > +
> >> > +    ptr = ebmalloc_free;
> >> > +
> >> > +    ebmalloc_free += size;
> >>
> >> No minimal (at least pointer size) alignment getting enforced
> >> somewhere here?
> >
> > For what?
>
> To avoid the penalty unaligned accesses incur? And that's alongside
> the fact that it's simply bad practice to knowingly but without actual
> need cause unaligned accesses even if they work fine.

I expected that but I do not think it is very important here. Anyway,
I am still not sure why you say "at least pointer size". Because
sizeof(void *) assures proper alignment on any architecture?
Additionally, will this alignment sufficiently replace alignment
provided by current efi_arch_allocate_mmap_buffer() implementation?

> >> And then - wouldn't this better go into xen/common/efi/boot.c,
> >> even if ARM64 does not have a use for it right away? The code
> >> certainly isn't really x86-specific.
> >
> > Sure thing. However, if it is not used by ARM64 then I think ebmalloc
> > stuff should not be moved to xen/common/efi/boot.c.
>
> Being architecture independent it has all reasons to be moved
> there. Agreed there may be compiler warnings for these then
> being unused static functions, but I'd rather see this code get
> #ifdef-ed out for ARM for the time being than it needing to be

OK.

> moved over later on. And of course a question to be asked first
> is whether in fact there is something in common or ARM specific
> code that could benefit from using this new allocator, if you
> already introduce it.

I think that it is x86 specific stuff and should stay here as is.
However, potentially it can be common allocator for both architectures.
Though I do not see gains on ARM itself.

Daniel

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

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

* Re: [PATCH v5 12/16] x86/efi: create new early memory allocator
  2016-09-08  8:29         ` Daniel Kiper
@ 2016-09-08  9:59           ` Jan Beulich
  0 siblings, 0 replies; 70+ messages in thread
From: Jan Beulich @ 2016-09-08  9:59 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Juergen Gross, sstabellini, andrew.cooper3, cardoe, pgnet.dev,
	ning.sun, david.vrabel, xen-devel, qiaowei.ren, gang.wei, fu.wei

>>> On 08.09.16 at 10:29, <daniel.kiper@oracle.com> wrote:
> On Wed, Sep 07, 2016 at 08:01:31AM -0600, Jan Beulich wrote:
>> >>> On 07.09.16 at 14:05, <daniel.kiper@oracle.com> wrote:
>> > On Mon, Sep 05, 2016 at 06:33:57AM -0600, Jan Beulich wrote:
>> >> >>> On 20.08.16 at 00:43, <daniel.kiper@oracle.com> wrote:
>> >> > +    if ( ebmalloc_free == NULL )
>> >> > +        ebmalloc_free = ebmalloc_mem;
>> >> > +
>> >> > +    ptr = ebmalloc_free;
>> >> > +
>> >> > +    ebmalloc_free += size;
>> >>
>> >> No minimal (at least pointer size) alignment getting enforced
>> >> somewhere here?
>> >
>> > For what?
>>
>> To avoid the penalty unaligned accesses incur? And that's alongside
>> the fact that it's simply bad practice to knowingly but without actual
>> need cause unaligned accesses even if they work fine.
> 
> I expected that but I do not think it is very important here. Anyway,
> I am still not sure why you say "at least pointer size". Because
> sizeof(void *) assures proper alignment on any architecture?

Yes, this gives (on "normal" architectures at least) machine word
size alignment, which commonly is good enough for everything
except SIMD data (or things similar to it).

> Additionally, will this alignment sufficiently replace alignment
> provided by current efi_arch_allocate_mmap_buffer() implementation?

Just compare __alignof__(EFI_MEMORY_DESCRIPTOR) and
__alignof__(void *).

Jan


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

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

end of thread, other threads:[~2016-09-08  9:59 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-19 22:43 [PATCH v5 00/16] x86: multiboot2 protocol support Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 01/16] x86: allow EFI reboot method neither on EFI platforms Daniel Kiper
2016-08-25 11:19   ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 02/16] x86/boot: remove multiboot1_header_end from symbol table Daniel Kiper
2016-08-25 11:21   ` Jan Beulich
2016-08-30 14:27     ` Daniel Kiper
2016-08-30 15:11       ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 03/16] x86/boot: create *.lnk files with linker script Daniel Kiper
2016-08-25 11:28   ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 04/16] x86/boot/reloc: reduce assembly usage as much as possible Daniel Kiper
2016-08-25 11:29   ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 05/16] x86/boot: call reloc() using stdcall calling convention Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 06/16] x86/boot/reloc: create generic alloc and copy functions Daniel Kiper
2016-08-25 11:34   ` Jan Beulich
2016-08-30 14:32     ` Daniel Kiper
2016-08-30 15:12       ` Jan Beulich
2016-08-31 15:13         ` Daniel Kiper
2016-08-31 15:25           ` Jan Beulich
2016-08-31 19:39             ` Daniel Kiper
2016-09-01  7:35               ` Jan Beulich
2016-09-06 15:33       ` Doug Goldstein
2016-08-19 22:43 ` [PATCH v5 07/16] x86/boot: use %ecx instead of %eax Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 08/16] x86/boot/reloc: rename some variables and rearrange code a bit Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 09/16] x86: add multiboot2 protocol support Daniel Kiper
2016-08-25 11:50   ` Jan Beulich
2016-08-30 14:41     ` Daniel Kiper
2016-08-30 15:14       ` Jan Beulich
2016-08-31 15:21         ` Daniel Kiper
2016-08-31 20:18   ` Andrew Cooper
2016-08-31 21:01     ` Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 10/16] efi: create efi_enabled() Daniel Kiper
2016-08-25 12:16   ` Jan Beulich
2016-08-30 17:19     ` Daniel Kiper
2016-08-31 12:31       ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 11/16] efi: build xen.gz with EFI code Daniel Kiper
2016-08-25 12:23   ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 12/16] x86/efi: create new early memory allocator Daniel Kiper
2016-09-05 12:33   ` Jan Beulich
2016-09-07 12:05     ` Daniel Kiper
2016-09-07 14:01       ` Jan Beulich
2016-09-08  8:29         ` Daniel Kiper
2016-09-08  9:59           ` Jan Beulich
2016-08-19 22:43 ` [PATCH v5 13/16] x86: add multiboot2 protocol support for EFI platforms Daniel Kiper
2016-08-25 12:59   ` Jan Beulich
2016-08-30 19:32     ` Daniel Kiper
2016-08-31 12:49       ` Jan Beulich
2016-08-31 17:07         ` Daniel Kiper
2016-09-01  7:40           ` Jan Beulich
2016-09-01 20:37             ` Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 14/16] x86/boot: implement early command line parser in C Daniel Kiper
2016-08-25 13:27   ` Jan Beulich
2016-08-30 19:58     ` Daniel Kiper
2016-08-31 13:01       ` Jan Beulich
2016-08-31 19:31         ` Daniel Kiper
2016-09-01  7:41           ` Jan Beulich
2016-09-01 20:43             ` Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 15/16] x86: make Xen early boot code relocatable Daniel Kiper
2016-08-25 14:41   ` Jan Beulich
2016-08-31 14:59     ` Daniel Kiper
2016-08-31 15:46       ` Jan Beulich
2016-08-31 20:50         ` Daniel Kiper
2016-09-01  7:46           ` Jan Beulich
2016-09-01 21:19             ` Daniel Kiper
2016-09-02  6:58               ` Jan Beulich
2016-09-02  7:28                 ` Daniel Kiper
2016-08-19 22:43 ` [PATCH v5 16/16] x86: add multiboot2 protocol support for relocatable images Daniel Kiper
2016-08-22 10:10 ` [PATCH v5 00/16] x86: multiboot2 protocol support Jan Beulich
2016-08-30 14:15   ` Daniel Kiper
2016-08-30 15:09     ` Jan Beulich
2016-08-31 15:05       ` Daniel Kiper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.