Hello community, here is the log from the commit of package grub2 for openSUSE:Factory checked in at 2016-10-26 13:27:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grub2 (Old) and /work/SRC/openSUSE:Factory/.grub2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "grub2" Changes: -------- --- /work/SRC/openSUSE:Factory/grub2/grub2.changes 2016-10-18 10:37:31.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.grub2.new/grub2.changes 2016-10-26 13:27:23.000000000 +0200 @@ -1,0 +2,17 @@ +Fri Oct 21 09:34:58 UTC 2016 - [email protected] + +- From Juergen Gross <[email protected]>: grub-xen: support booting huge + pv-domains (bsc#1004398) (bsc#899465) + * 0001-xen-make-xen-loader-callable-multiple-times.patch + * 0002-xen-avoid-memleaks-on-error.patch + * 0003-xen-reduce-number-of-global-variables-in-xen-loader.patch + * 0004-xen-add-elfnote.h-to-avoid-using-numbers-instead-of-.patch + * 0005-xen-synchronize-xen-header.patch + * 0006-xen-factor-out-p2m-list-allocation-into-separate-fun.patch + * 0007-xen-factor-out-allocation-of-special-pages-into-sepa.patch + * 0008-xen-factor-out-allocation-of-page-tables-into-separa.patch + * 0009-xen-add-capability-to-load-initrd-outside-of-initial.patch + * 0010-xen-modify-page-table-construction.patch + * 0011-xen-add-capability-to-load-p2m-list-outside-of-kerne.patch + +------------------------------------------------------------------- New: ---- 0001-xen-make-xen-loader-callable-multiple-times.patch 0002-xen-avoid-memleaks-on-error.patch 0003-xen-reduce-number-of-global-variables-in-xen-loader.patch 0004-xen-add-elfnote.h-to-avoid-using-numbers-instead-of-.patch 0005-xen-synchronize-xen-header.patch 0006-xen-factor-out-p2m-list-allocation-into-separate-fun.patch 0007-xen-factor-out-allocation-of-special-pages-into-sepa.patch 0008-xen-factor-out-allocation-of-page-tables-into-separa.patch 0009-xen-add-capability-to-load-initrd-outside-of-initial.patch 0010-xen-modify-page-table-construction.patch 0011-xen-add-capability-to-load-p2m-list-outside-of-kerne.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ grub2.spec ++++++ --- /var/tmp/diff_new_pack.Y5Fpht/_old 2016-10-26 13:27:25.000000000 +0200 +++ /var/tmp/diff_new_pack.Y5Fpht/_new 2016-10-26 13:27:25.000000000 +0200 @@ -230,6 +230,18 @@ Patch285: 0006-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch Patch286: 0007-efinet-Setting-network-from-UEFI-device-path.patch Patch287: 0008-efinet-Setting-DNS-server-from-UEFI-protocol.patch +# Support booting huge xen pv-domains (bsc#1004398) (bsc#899465) +Patch300: 0001-xen-make-xen-loader-callable-multiple-times.patch +Patch301: 0002-xen-avoid-memleaks-on-error.patch +Patch302: 0003-xen-reduce-number-of-global-variables-in-xen-loader.patch +Patch303: 0004-xen-add-elfnote.h-to-avoid-using-numbers-instead-of-.patch +Patch304: 0005-xen-synchronize-xen-header.patch +Patch305: 0006-xen-factor-out-p2m-list-allocation-into-separate-fun.patch +Patch306: 0007-xen-factor-out-allocation-of-special-pages-into-sepa.patch +Patch307: 0008-xen-factor-out-allocation-of-page-tables-into-separa.patch +Patch308: 0009-xen-add-capability-to-load-initrd-outside-of-initial.patch +Patch309: 0010-xen-modify-page-table-construction.patch +Patch310: 0011-xen-add-capability-to-load-p2m-list-outside-of-kerne.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -463,6 +475,17 @@ %patch285 -p1 %patch286 -p1 %patch287 -p1 +%patch300 -p1 +%patch301 -p1 +%patch302 -p1 +%patch303 -p1 +%patch304 -p1 +%patch305 -p1 +%patch306 -p1 +%patch307 -p1 +%patch308 -p1 +%patch309 -p1 +%patch310 -p1 # This simplifies patch handling without need to use git to create patch # that renames file ++++++ 0001-xen-make-xen-loader-callable-multiple-times.patch ++++++ >From 3fcf47254678ddd9387b8ee80f21ad5f163cb7a9 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:06 +0100 Subject: [PATCH 01/11] xen: make xen loader callable multiple times The loader for xen paravirtualized environment isn't callable multiple times as it won't free any memory in case of failure. Call grub_relocator_unload() as other modules do it before allocating a new relocator or when unloading the module. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index c4d9689..179e89c 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -316,11 +316,23 @@ grub_xen_boot (void) xen_inf.virt_base); } +static void +grub_xen_reset (void) +{ + grub_memset (&next_start, 0, sizeof (next_start)); + xen_module_info_page = NULL; + n_modules = 0; + + grub_relocator_unload (relocator); + relocator = NULL; + loaded = 0; +} + static grub_err_t grub_xen_unload (void) { + grub_xen_reset (); grub_dl_unref (my_mod); - loaded = 0; return GRUB_ERR_NONE; } @@ -403,10 +415,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), grub_loader_unset (); - grub_memset (&next_start, 0, sizeof (next_start)); - - xen_module_info_page = NULL; - n_modules = 0; + grub_xen_reset (); grub_create_loader_cmdline (argc - 1, argv + 1, (char *) next_start.cmd_line, @@ -503,16 +512,18 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), goto fail; fail: + /* grub_errno might be clobbered by further calls, save the error reason. */ + err = grub_errno; if (elf) grub_elf_close (elf); else if (file) grub_file_close (file); - if (grub_errno != GRUB_ERR_NONE) - loaded = 0; + if (err != GRUB_ERR_NONE) + grub_xen_reset (); - return grub_errno; + return err; } static grub_err_t -- 2.6.6 ++++++ 0002-xen-avoid-memleaks-on-error.patch ++++++ >From da05ded53eea9316b03f0e00dff3a8c9c4661c95 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:07 +0100 Subject: [PATCH 02/11] xen: avoid memleaks on error When loading a Xen pv-kernel avoid memory leaks in case of errors. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 2 +- grub-core/loader/i386/xen_fileXX.c | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index 179e89c..f45f70f 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -563,7 +563,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), { err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, size); if (err) - return err; + goto fail; if (grub_initrd_load (&initrd_ctx, argv, get_virtual_current_address (ch))) diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c index 1ba5649..36b40e4 100644 --- a/grub-core/loader/i386/xen_fileXX.c +++ b/grub-core/loader/i386/xen_fileXX.c @@ -26,6 +26,8 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, char *buf; char *ptr; int has_paddr = 0; + + grub_errno = GRUB_ERR_NONE; if (grub_file_seek (elf->file, off) == (grub_off_t) -1) return grub_errno; buf = grub_malloc (sz); @@ -35,7 +37,8 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz) { if (grub_errno) - return grub_errno; + goto out; + grub_free (buf); return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), elf->file->name); } @@ -123,14 +126,14 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, { xi->virt_base = grub_strtoull (ptr + sizeof ("VIRT_BASE=") - 1, &ptr, 16); if (grub_errno) - return grub_errno; + goto out; continue; } if (grub_strncmp (ptr, "VIRT_ENTRY=", sizeof ("VIRT_ENTRY=") - 1) == 0) { xi->entry_point = grub_strtoull (ptr + sizeof ("VIRT_ENTRY=") - 1, &ptr, 16); if (grub_errno) - return grub_errno; + goto out; continue; } if (grub_strncmp (ptr, "HYPERCALL_PAGE=", sizeof ("HYPERCALL_PAGE=") - 1) == 0) @@ -138,7 +141,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, xi->hypercall_page = grub_strtoull (ptr + sizeof ("HYPERCALL_PAGE=") - 1, &ptr, 16); xi->has_hypercall_page = 1; if (grub_errno) - return grub_errno; + goto out; continue; } if (grub_strncmp (ptr, "ELF_PADDR_OFFSET=", sizeof ("ELF_PADDR_OFFSET=") - 1) == 0) @@ -146,7 +149,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, xi->paddr_offset = grub_strtoull (ptr + sizeof ("ELF_PADDR_OFFSET=") - 1, &ptr, 16); has_paddr = 1; if (grub_errno) - return grub_errno; + goto out; continue; } } @@ -154,7 +157,11 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, xi->hypercall_page = (xi->hypercall_page << 12) + xi->virt_base; if (!has_paddr) xi->paddr_offset = xi->virt_base; - return GRUB_ERR_NONE; + +out: + grub_free (buf); + + return grub_errno; } #pragma GCC diagnostic ignored "-Wcast-align" -- 2.6.6 ++++++ 0003-xen-reduce-number-of-global-variables-in-xen-loader.patch ++++++ >From d0c3974a455c50de4bc6b6fa8ef9b280a6f99faa Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:08 +0100 Subject: [PATCH 03/11] xen: reduce number of global variables in xen loader The loader for xen paravirtualized environment is using lots of global variables. Reduce the number by making them either local or by putting them into a single state structure. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 267 +++++++++++++++++++++++--------------------- 1 file changed, 142 insertions(+), 125 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index f45f70f..691c22e 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -42,16 +42,20 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static struct grub_relocator *relocator = NULL; -static grub_uint64_t max_addr; +struct xen_loader_state { + struct grub_relocator *relocator; + struct start_info next_start; + struct grub_xen_file_info xen_inf; + grub_uint64_t max_addr; + struct xen_multiboot_mod_list *module_info_page; + grub_uint64_t modules_target_start; + grub_size_t n_modules; + int loaded; +}; + +static struct xen_loader_state xen_state; + static grub_dl_t my_mod; -static int loaded = 0; -static struct start_info next_start; -static void *kern_chunk_src; -static struct grub_xen_file_info xen_inf; -static struct xen_multiboot_mod_list *xen_module_info_page; -static grub_uint64_t modules_target_start; -static grub_size_t n_modules; #define PAGE_SIZE 4096 #define MAX_MODULES (PAGE_SIZE / sizeof (struct xen_multiboot_mod_list)) @@ -225,50 +229,55 @@ grub_xen_boot (void) if (grub_xen_n_allocated_shared_pages) return grub_error (GRUB_ERR_BUG, "active grants"); - state.mfn_list = max_addr; - next_start.mfn_list = max_addr + xen_inf.virt_base; - next_start.first_p2m_pfn = max_addr >> PAGE_SHIFT; /* Is this right? */ + state.mfn_list = xen_state.max_addr; + xen_state.next_start.mfn_list = + xen_state.max_addr + xen_state.xen_inf.virt_base; + xen_state.next_start.first_p2m_pfn = xen_state.max_addr >> PAGE_SHIFT; pgtsize = sizeof (grub_xen_mfn_t) * grub_xen_start_page_addr->nr_pages; - err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, pgtsize); - next_start.nr_p2m_frames = (pgtsize + PAGE_SIZE - 1) >> PAGE_SHIFT; + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, pgtsize); + xen_state.next_start.nr_p2m_frames = (pgtsize + PAGE_SIZE - 1) >> PAGE_SHIFT; if (err) return err; new_mfn_list = get_virtual_current_address (ch); grub_memcpy (new_mfn_list, (void *) grub_xen_start_page_addr->mfn_list, pgtsize); - max_addr = ALIGN_UP (max_addr + pgtsize, PAGE_SIZE); + xen_state.max_addr = ALIGN_UP (xen_state.max_addr + pgtsize, PAGE_SIZE); - err = grub_relocator_alloc_chunk_addr (relocator, &ch, - max_addr, sizeof (next_start)); + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, + sizeof (xen_state.next_start)); if (err) return err; - state.start_info = max_addr + xen_inf.virt_base; + state.start_info = xen_state.max_addr + xen_state.xen_inf.virt_base; nst = get_virtual_current_address (ch); - max_addr = ALIGN_UP (max_addr + sizeof (next_start), PAGE_SIZE); - - next_start.nr_pages = grub_xen_start_page_addr->nr_pages; - grub_memcpy (next_start.magic, grub_xen_start_page_addr->magic, - sizeof (next_start.magic)); - next_start.store_mfn = grub_xen_start_page_addr->store_mfn; - next_start.store_evtchn = grub_xen_start_page_addr->store_evtchn; - next_start.console.domU = grub_xen_start_page_addr->console.domU; - next_start.shared_info = grub_xen_start_page_addr->shared_info; - - err = set_mfns (new_mfn_list, max_addr >> PAGE_SHIFT); + xen_state.max_addr = + ALIGN_UP (xen_state.max_addr + sizeof (xen_state.next_start), PAGE_SIZE); + + xen_state.next_start.nr_pages = grub_xen_start_page_addr->nr_pages; + grub_memcpy (xen_state.next_start.magic, grub_xen_start_page_addr->magic, + sizeof (xen_state.next_start.magic)); + xen_state.next_start.store_mfn = grub_xen_start_page_addr->store_mfn; + xen_state.next_start.store_evtchn = grub_xen_start_page_addr->store_evtchn; + xen_state.next_start.console.domU = grub_xen_start_page_addr->console.domU; + xen_state.next_start.shared_info = grub_xen_start_page_addr->shared_info; + + err = set_mfns (new_mfn_list, xen_state.max_addr >> PAGE_SHIFT); if (err) return err; - max_addr += 2 * PAGE_SIZE; + xen_state.max_addr += 2 * PAGE_SIZE; - next_start.pt_base = max_addr + xen_inf.virt_base; - state.paging_start = max_addr >> PAGE_SHIFT; + xen_state.next_start.pt_base = + xen_state.max_addr + xen_state.xen_inf.virt_base; + state.paging_start = xen_state.max_addr >> PAGE_SHIFT; - nr_info_pages = max_addr >> PAGE_SHIFT; + nr_info_pages = xen_state.max_addr >> PAGE_SHIFT; nr_pages = nr_info_pages; while (1) { nr_pages = ALIGN_UP (nr_pages, (ALIGN_SIZE >> PAGE_SHIFT)); - nr_pt_pages = get_pgtable_size (nr_pages, xen_inf.virt_base); + nr_pt_pages = get_pgtable_size (nr_pages, xen_state.xen_inf.virt_base); nr_need_pages = nr_info_pages + nr_pt_pages + ((ADDITIONAL_SIZE + STACK_SIZE) >> PAGE_SHIFT); @@ -278,27 +287,28 @@ grub_xen_boot (void) } grub_dprintf ("xen", "bootstrap domain %llx+%llx\n", - (unsigned long long) xen_inf.virt_base, + (unsigned long long) xen_state.xen_inf.virt_base, (unsigned long long) page2offset (nr_pages)); - err = grub_relocator_alloc_chunk_addr (relocator, &ch, - max_addr, page2offset (nr_pt_pages)); + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, + page2offset (nr_pt_pages)); if (err) return err; generate_page_table (get_virtual_current_address (ch), - max_addr >> PAGE_SHIFT, nr_pages, - xen_inf.virt_base, new_mfn_list); + xen_state.max_addr >> PAGE_SHIFT, nr_pages, + xen_state.xen_inf.virt_base, new_mfn_list); - max_addr += page2offset (nr_pt_pages); - state.stack = max_addr + STACK_SIZE + xen_inf.virt_base; - state.entry_point = xen_inf.entry_point; + xen_state.max_addr += page2offset (nr_pt_pages); + state.stack = xen_state.max_addr + STACK_SIZE + xen_state.xen_inf.virt_base; + state.entry_point = xen_state.xen_inf.entry_point; - next_start.nr_p2m_frames += nr_pt_pages; - next_start.nr_pt_frames = nr_pt_pages; + xen_state.next_start.nr_p2m_frames += nr_pt_pages; + xen_state.next_start.nr_pt_frames = nr_pt_pages; state.paging_size = nr_pt_pages; - *nst = next_start; + *nst = xen_state.next_start; grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver)); @@ -308,24 +318,20 @@ grub_xen_boot (void) for (i = 0; i < ARRAY_SIZE (grub_xen_shared_info->evtchn_pending); i++) grub_xen_shared_info->evtchn_pending[i] = 0; - return grub_relocator_xen_boot (relocator, state, nr_pages, - xen_inf.virt_base < + return grub_relocator_xen_boot (xen_state.relocator, state, nr_pages, + xen_state.xen_inf.virt_base < PAGE_SIZE ? page2offset (nr_pages) : 0, nr_pages - 1, page2offset (nr_pages - 1) + - xen_inf.virt_base); + xen_state.xen_inf.virt_base); } static void grub_xen_reset (void) { - grub_memset (&next_start, 0, sizeof (next_start)); - xen_module_info_page = NULL; - n_modules = 0; + grub_relocator_unload (xen_state.relocator); - grub_relocator_unload (relocator); - relocator = NULL; - loaded = 0; + grub_memset (&xen_state, 0, sizeof (xen_state)); } static grub_err_t @@ -409,17 +415,22 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), grub_file_t file; grub_elf_t elf; grub_err_t err; + void *kern_chunk_src; + grub_relocator_chunk_t ch; + grub_addr_t kern_start; + grub_addr_t kern_end; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + /* Call grub_loader_unset early to avoid it being called by grub_loader_set */ grub_loader_unset (); grub_xen_reset (); grub_create_loader_cmdline (argc - 1, argv + 1, - (char *) next_start.cmd_line, - sizeof (next_start.cmd_line) - 1); + (char *) xen_state.next_start.cmd_line, + sizeof (xen_state.next_start.cmd_line) - 1); file = grub_file_open (argv[0]); if (!file) @@ -429,85 +440,82 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), if (!elf) goto fail; - err = grub_xen_get_info (elf, &xen_inf); + err = grub_xen_get_info (elf, &xen_state.xen_inf); if (err) goto fail; #ifdef __x86_64__ - if (xen_inf.arch != GRUB_XEN_FILE_X86_64) + if (xen_state.xen_inf.arch != GRUB_XEN_FILE_X86_64) #else - if (xen_inf.arch != GRUB_XEN_FILE_I386_PAE - && xen_inf.arch != GRUB_XEN_FILE_I386_PAE_BIMODE) + if (xen_state.xen_inf.arch != GRUB_XEN_FILE_I386_PAE + && xen_state.xen_inf.arch != GRUB_XEN_FILE_I386_PAE_BIMODE) #endif { grub_error (GRUB_ERR_BAD_OS, "incompatible architecture: %d", - xen_inf.arch); + xen_state.xen_inf.arch); goto fail; } - if (xen_inf.virt_base & (PAGE_SIZE - 1)) + if (xen_state.xen_inf.virt_base & (PAGE_SIZE - 1)) { grub_error (GRUB_ERR_BAD_OS, "unaligned virt_base"); goto fail; } grub_dprintf ("xen", "virt_base = %llx, entry = %llx\n", - (unsigned long long) xen_inf.virt_base, - (unsigned long long) xen_inf.entry_point); + (unsigned long long) xen_state.xen_inf.virt_base, + (unsigned long long) xen_state.xen_inf.entry_point); - relocator = grub_relocator_new (); - if (!relocator) + xen_state.relocator = grub_relocator_new (); + if (!xen_state.relocator) goto fail; - grub_relocator_chunk_t ch; - grub_addr_t kern_start = xen_inf.kern_start - xen_inf.paddr_offset; - grub_addr_t kern_end = xen_inf.kern_end - xen_inf.paddr_offset; + kern_start = xen_state.xen_inf.kern_start - xen_state.xen_inf.paddr_offset; + kern_end = xen_state.xen_inf.kern_end - xen_state.xen_inf.paddr_offset; - if (xen_inf.has_hypercall_page) + if (xen_state.xen_inf.has_hypercall_page) { grub_dprintf ("xen", "hypercall page at 0x%llx\n", - (unsigned long long) xen_inf.hypercall_page); - if (xen_inf.hypercall_page - xen_inf.virt_base < kern_start) - kern_start = xen_inf.hypercall_page - xen_inf.virt_base; - - if (xen_inf.hypercall_page - xen_inf.virt_base + PAGE_SIZE > kern_end) - kern_end = xen_inf.hypercall_page - xen_inf.virt_base + PAGE_SIZE; + (unsigned long long) xen_state.xen_inf.hypercall_page); + kern_start = grub_min (kern_start, xen_state.xen_inf.hypercall_page - + xen_state.xen_inf.virt_base); + kern_end = grub_max (kern_end, xen_state.xen_inf.hypercall_page - + xen_state.xen_inf.virt_base + PAGE_SIZE); } - max_addr = ALIGN_UP (kern_end, PAGE_SIZE); + xen_state.max_addr = ALIGN_UP (kern_end, PAGE_SIZE); - err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start, + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start, kern_end - kern_start); if (err) goto fail; kern_chunk_src = get_virtual_current_address (ch); grub_dprintf ("xen", "paddr_offset = 0x%llx\n", - (unsigned long long) xen_inf.paddr_offset); + (unsigned long long) xen_state.xen_inf.paddr_offset); grub_dprintf ("xen", "kern_start = 0x%llx, kern_end = 0x%llx\n", - (unsigned long long) xen_inf.kern_start, - (unsigned long long) xen_inf.kern_end); + (unsigned long long) xen_state.xen_inf.kern_start, + (unsigned long long) xen_state.xen_inf.kern_end); err = grub_elfXX_load (elf, argv[0], (grub_uint8_t *) kern_chunk_src - kern_start - - xen_inf.paddr_offset, 0, 0, 0); + - xen_state.xen_inf.paddr_offset, 0, 0, 0); - if (xen_inf.has_hypercall_page) + if (xen_state.xen_inf.has_hypercall_page) { unsigned i; for (i = 0; i < PAGE_SIZE / HYPERCALL_INTERFACE_SIZE; i++) set_hypercall_interface ((grub_uint8_t *) kern_chunk_src + i * HYPERCALL_INTERFACE_SIZE + - xen_inf.hypercall_page - xen_inf.virt_base - - kern_start, i); + xen_state.xen_inf.hypercall_page - + xen_state.xen_inf.virt_base - kern_start, i); } if (err) goto fail; grub_dl_ref (my_mod); - loaded = 1; + xen_state.loaded = 1; grub_loader_set (grub_xen_boot, grub_xen_unload, 0); - loaded = 1; goto fail; @@ -541,14 +549,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - if (!loaded) + if (!xen_state.loaded) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } - if (next_start.mod_start || next_start.mod_len) + if (xen_state.next_start.mod_start || xen_state.next_start.mod_len) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("initrd already loaded")); goto fail; @@ -561,7 +569,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), if (size) { - err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, size); + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, size); if (err) goto fail; @@ -570,13 +579,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - next_start.mod_start = max_addr + xen_inf.virt_base; - next_start.mod_len = size; + xen_state.next_start.mod_start = + xen_state.max_addr + xen_state.xen_inf.virt_base; + xen_state.next_start.mod_len = size; - max_addr = ALIGN_UP (max_addr + size, PAGE_SIZE); + xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE); grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n", - (unsigned) next_start.mod_start, (unsigned) size); + (unsigned) xen_state.next_start.mod_start, (unsigned) size); fail: grub_initrd_close (&initrd_ctx); @@ -608,45 +618,48 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - if (!loaded) + if (!xen_state.loaded) { return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); } - if ((next_start.mod_start || next_start.mod_len) && !xen_module_info_page) + if ((xen_state.next_start.mod_start || xen_state.next_start.mod_len) && + !xen_state.module_info_page) { return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("initrd already loaded")); } /* Leave one space for terminator. */ - if (n_modules >= MAX_MODULES - 1) + if (xen_state.n_modules >= MAX_MODULES - 1) { return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many modules"); } - if (!xen_module_info_page) + if (!xen_state.module_info_page) { - n_modules = 0; - max_addr = ALIGN_UP (max_addr, PAGE_SIZE); - modules_target_start = max_addr; - next_start.mod_start = max_addr + xen_inf.virt_base; - next_start.flags |= SIF_MULTIBOOT_MOD; - - err = grub_relocator_alloc_chunk_addr (relocator, &ch, - max_addr, MAX_MODULES + xen_state.n_modules = 0; + xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE); + xen_state.modules_target_start = xen_state.max_addr; + xen_state.next_start.mod_start = + xen_state.max_addr + xen_state.xen_inf.virt_base; + xen_state.next_start.flags |= SIF_MULTIBOOT_MOD; + + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, MAX_MODULES * - sizeof (xen_module_info_page + sizeof (xen_state.module_info_page [0])); if (err) return err; - xen_module_info_page = get_virtual_current_address (ch); - grub_memset (xen_module_info_page, 0, MAX_MODULES - * sizeof (xen_module_info_page[0])); - max_addr += MAX_MODULES * sizeof (xen_module_info_page[0]); + xen_state.module_info_page = get_virtual_current_address (ch); + grub_memset (xen_state.module_info_page, 0, MAX_MODULES + * sizeof (xen_state.module_info_page[0])); + xen_state.max_addr += + MAX_MODULES * sizeof (xen_state.module_info_page[0]); } - max_addr = ALIGN_UP (max_addr, PAGE_SIZE); + xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE); if (nounzip) grub_file_filter_disable_compression (); @@ -657,20 +670,22 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), cmdline_len = grub_loader_cmdline_size (argc - 1, argv + 1); - err = grub_relocator_alloc_chunk_addr (relocator, &ch, - max_addr, cmdline_len); + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, cmdline_len); if (err) goto fail; grub_create_loader_cmdline (argc - 1, argv + 1, get_virtual_current_address (ch), cmdline_len); - xen_module_info_page[n_modules].cmdline = max_addr - modules_target_start; - max_addr = ALIGN_UP (max_addr + cmdline_len, PAGE_SIZE); + xen_state.module_info_page[xen_state.n_modules].cmdline = + xen_state.max_addr - xen_state.modules_target_start; + xen_state.max_addr = ALIGN_UP (xen_state.max_addr + cmdline_len, PAGE_SIZE); if (size) { - err = grub_relocator_alloc_chunk_addr (relocator, &ch, max_addr, size); + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, size); if (err) goto fail; if (grub_file_read (file, get_virtual_current_address (ch), size) @@ -682,15 +697,17 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), goto fail; } } - next_start.mod_len = max_addr + size - modules_target_start; - xen_module_info_page[n_modules].mod_start = max_addr - modules_target_start; - xen_module_info_page[n_modules].mod_end = - max_addr + size - modules_target_start; - - n_modules++; + xen_state.next_start.mod_len = + xen_state.max_addr + size - xen_state.modules_target_start; + xen_state.module_info_page[xen_state.n_modules].mod_start = + xen_state.max_addr - xen_state.modules_target_start; + xen_state.module_info_page[xen_state.n_modules].mod_end = + xen_state.max_addr + size - xen_state.modules_target_start; + + xen_state.n_modules++; grub_dprintf ("xen", "module, addr=0x%x, size=0x%x\n", - (unsigned) max_addr, (unsigned) size); - max_addr = ALIGN_UP (max_addr + size, PAGE_SIZE); + (unsigned) xen_state.max_addr, (unsigned) size); + xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE); fail: -- 2.6.6 ++++++ 0004-xen-add-elfnote.h-to-avoid-using-numbers-instead-of-.patch ++++++ >From 0c3821e10ca0a47c436e3aacb230c47412cf517f Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:09 +0100 Subject: [PATCH 04/11] xen: add elfnote.h to avoid using numbers instead of constants Various features and parameters of a pv-kernel are specified via elf notes in the kernel image. Those notes are part of the interface between the Xen hypervisor and the kernel. Instead of using num,bers in the code when interpreting the elf notes make use of the header supplied by Xen for that purpose. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen_fileXX.c | 19 +-- include/xen/elfnote.h | 281 +++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+), 9 deletions(-) create mode 100644 include/xen/elfnote.h diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c index 36b40e4..03215ca 100644 --- a/grub-core/loader/i386/xen_fileXX.c +++ b/grub-core/loader/i386/xen_fileXX.c @@ -18,6 +18,7 @@ #include <grub/xen_file.h> #include <grub/misc.h> +#include <xen/elfnote.h> static grub_err_t parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, @@ -203,35 +204,35 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi, xi->has_note = 1; switch (nh->n_type) { - case 1: + case XEN_ELFNOTE_ENTRY: xi->entry_point = grub_le_to_cpu_addr (*(Elf_Addr *) desc); break; - case 2: + case XEN_ELFNOTE_HYPERCALL_PAGE: xi->hypercall_page = grub_le_to_cpu_addr (*(Elf_Addr *) desc); xi->has_hypercall_page = 1; break; - case 3: + case XEN_ELFNOTE_VIRT_BASE: xi->virt_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc); break; - case 4: + case XEN_ELFNOTE_PADDR_OFFSET: xi->paddr_offset = grub_le_to_cpu_addr (*(Elf_Addr *) desc); break; - case 5: + case XEN_ELFNOTE_XEN_VERSION: grub_dprintf ("xen", "xenversion = `%s'\n", (char *) desc); break; - case 6: + case XEN_ELFNOTE_GUEST_OS: grub_dprintf ("xen", "name = `%s'\n", (char *) desc); break; - case 7: + case XEN_ELFNOTE_GUEST_VERSION: grub_dprintf ("xen", "version = `%s'\n", (char *) desc); break; - case 8: + case XEN_ELFNOTE_LOADER: if (descsz < 7 || grub_memcmp (desc, "generic", descsz == 7 ? 7 : 8) != 0) return grub_error (GRUB_ERR_BAD_OS, "invalid loader"); break; /* PAE */ - case 9: + case XEN_ELFNOTE_PAE_MODE: grub_dprintf ("xen", "pae = `%s', %d, %d\n", (char *) desc, xi->arch, descsz); if (xi->arch != GRUB_XEN_FILE_I386 diff --git a/include/xen/elfnote.h b/include/xen/elfnote.h new file mode 100644 index 0000000..353985f --- /dev/null +++ b/include/xen/elfnote.h @@ -0,0 +1,281 @@ +/****************************************************************************** + * elfnote.h + * + * Definitions used for the Xen ELF notes. + * + * 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 THE + * AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Copyright (c) 2006, Ian Campbell, XenSource Ltd. + */ + +#ifndef __XEN_PUBLIC_ELFNOTE_H__ +#define __XEN_PUBLIC_ELFNOTE_H__ + +/* + * `incontents 200 elfnotes ELF notes + * + * The notes should live in a PT_NOTE segment and have "Xen" in the + * name field. + * + * Numeric types are either 4 or 8 bytes depending on the content of + * the desc field. + * + * LEGACY indicated the fields in the legacy __xen_guest string which + * this a note type replaces. + * + * String values (for non-legacy) are NULL terminated ASCII, also known + * as ASCIZ type. + */ + +/* + * NAME=VALUE pair (string). + */ +#define XEN_ELFNOTE_INFO 0 + +/* + * The virtual address of the entry point (numeric). + * + * LEGACY: VIRT_ENTRY + */ +#define XEN_ELFNOTE_ENTRY 1 + +/* The virtual address of the hypercall transfer page (numeric). + * + * LEGACY: HYPERCALL_PAGE. (n.b. legacy value is a physical page + * number not a virtual address) + */ +#define XEN_ELFNOTE_HYPERCALL_PAGE 2 + +/* The virtual address where the kernel image should be mapped (numeric). + * + * Defaults to 0. + * + * LEGACY: VIRT_BASE + */ +#define XEN_ELFNOTE_VIRT_BASE 3 + +/* + * The offset of the ELF paddr field from the actual required + * pseudo-physical address (numeric). + * + * This is used to maintain backwards compatibility with older kernels + * which wrote __PAGE_OFFSET into that field. This field defaults to 0 + * if not present. + * + * LEGACY: ELF_PADDR_OFFSET. (n.b. legacy default is VIRT_BASE) + */ +#define XEN_ELFNOTE_PADDR_OFFSET 4 + +/* + * The version of Xen that we work with (string). + * + * LEGACY: XEN_VER + */ +#define XEN_ELFNOTE_XEN_VERSION 5 + +/* + * The name of the guest operating system (string). + * + * LEGACY: GUEST_OS + */ +#define XEN_ELFNOTE_GUEST_OS 6 + +/* + * The version of the guest operating system (string). + * + * LEGACY: GUEST_VER + */ +#define XEN_ELFNOTE_GUEST_VERSION 7 + +/* + * The loader type (string). + * + * LEGACY: LOADER + */ +#define XEN_ELFNOTE_LOADER 8 + +/* + * The kernel supports PAE (x86/32 only, string = "yes", "no" or + * "bimodal"). + * + * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting + * may be given as "yes,bimodal" which will cause older Xen to treat + * this kernel as PAE. + * + * LEGACY: PAE (n.b. The legacy interface included a provision to + * indicate 'extended-cr3' support allowing L3 page tables to be + * placed above 4G. It is assumed that any kernel new enough to use + * these ELF notes will include this and therefore "yes" here is + * equivalent to "yes[entended-cr3]" in the __xen_guest interface. + */ +#define XEN_ELFNOTE_PAE_MODE 9 + +/* + * The features supported/required by this kernel (string). + * + * The string must consist of a list of feature names (as given in + * features.h, without the "XENFEAT_" prefix) separated by '|' + * characters. If a feature is required for the kernel to function + * then the feature name must be preceded by a '!' character. + * + * LEGACY: FEATURES + */ +#define XEN_ELFNOTE_FEATURES 10 + +/* + * The kernel requires the symbol table to be loaded (string = "yes" or "no") + * LEGACY: BSD_SYMTAB (n.b. The legacy treated the presence or absence + * of this string as a boolean flag rather than requiring "yes" or + * "no". + */ +#define XEN_ELFNOTE_BSD_SYMTAB 11 + +/* + * The lowest address the hypervisor hole can begin at (numeric). + * + * This must not be set higher than HYPERVISOR_VIRT_START. Its presence + * also indicates to the hypervisor that the kernel can deal with the + * hole starting at a higher address. + */ +#define XEN_ELFNOTE_HV_START_LOW 12 + +/* + * List of maddr_t-sized mask/value pairs describing how to recognize + * (non-present) L1 page table entries carrying valid MFNs (numeric). + */ +#define XEN_ELFNOTE_L1_MFN_VALID 13 + +/* + * Whether or not the guest supports cooperative suspend cancellation. + * This is a numeric value. + * + * Default is 0 + */ +#define XEN_ELFNOTE_SUSPEND_CANCEL 14 + +/* + * The (non-default) location the initial phys-to-machine map should be + * placed at by the hypervisor (Dom0) or the tools (DomU). + * The kernel must be prepared for this mapping to be established using + * large pages, despite such otherwise not being available to guests. + * The kernel must also be able to handle the page table pages used for + * this mapping not being accessible through the initial mapping. + * (Only x86-64 supports this at present.) + */ +#define XEN_ELFNOTE_INIT_P2M 15 + +/* + * Whether or not the guest can deal with being passed an initrd not + * mapped through its initial page tables. + */ +#define XEN_ELFNOTE_MOD_START_PFN 16 + +/* + * The features supported by this kernel (numeric). + * + * Other than XEN_ELFNOTE_FEATURES on pre-4.2 Xen, this note allows a + * kernel to specify support for features that older hypervisors don't + * know about. The set of features 4.2 and newer hypervisors will + * consider supported by the kernel is the combination of the sets + * specified through this and the string note. + * + * LEGACY: FEATURES + */ +#define XEN_ELFNOTE_SUPPORTED_FEATURES 17 + +/* + * Physical entry point into the kernel. + * + * 32bit entry point into the kernel. When requested to launch the + * guest kernel in a HVM container, Xen will use this entry point to + * launch the guest in 32bit protected mode with paging disabled. + * Ignored otherwise. + */ +#define XEN_ELFNOTE_PHYS32_ENTRY 18 + +/* + * The number of the highest elfnote defined. + */ +#define XEN_ELFNOTE_MAX XEN_ELFNOTE_PHYS32_ENTRY + +/* + * System information exported through crash notes. + * + * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO + * note in case of a system crash. This note will contain various + * information about the system, see xen/include/xen/elfcore.h. + */ +#define XEN_ELFNOTE_CRASH_INFO 0x1000001 + +/* + * System registers exported through crash notes. + * + * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS + * note per cpu in case of a system crash. This note is architecture + * specific and will contain registers not saved in the "CORE" note. + * See xen/include/xen/elfcore.h for more information. + */ +#define XEN_ELFNOTE_CRASH_REGS 0x1000002 + + +/* + * xen dump-core none note. + * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_NONE + * in its dump file to indicate that the file is xen dump-core + * file. This note doesn't have any other information. + * See tools/libxc/xc_core.h for more information. + */ +#define XEN_ELFNOTE_DUMPCORE_NONE 0x2000000 + +/* + * xen dump-core header note. + * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_HEADER + * in its dump file. + * See tools/libxc/xc_core.h for more information. + */ +#define XEN_ELFNOTE_DUMPCORE_HEADER 0x2000001 + +/* + * xen dump-core xen version note. + * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_XEN_VERSION + * in its dump file. It contains the xen version obtained via the + * XENVER hypercall. + * See tools/libxc/xc_core.h for more information. + */ +#define XEN_ELFNOTE_DUMPCORE_XEN_VERSION 0x2000002 + +/* + * xen dump-core format version note. + * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION + * in its dump file. It contains a format version identifier. + * See tools/libxc/xc_core.h for more information. + */ +#define XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION 0x2000003 + +#endif /* __XEN_PUBLIC_ELFNOTE_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- 2.6.6 ++++++ 0005-xen-synchronize-xen-header.patch ++++++ >From 21078a54248f25f9831c3b1007bec0cbfbd720a7 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:10 +0100 Subject: [PATCH 05/11] xen: synchronize xen header Get actual version of include/xen/xen.h from the Xen repository in order to be able to use constants defined there. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- include/xen/arch-x86/xen-x86_32.h | 22 +++---- include/xen/arch-x86/xen-x86_64.h | 8 +-- include/xen/xen.h | 125 +++++++++++++++++++++++++++----------- 3 files changed, 105 insertions(+), 50 deletions(-) diff --git a/include/xen/arch-x86/xen-x86_32.h b/include/xen/arch-x86/xen-x86_32.h index 1504191..7eca6cd 100644 --- a/include/xen/arch-x86/xen-x86_32.h +++ b/include/xen/arch-x86/xen-x86_32.h @@ -58,34 +58,31 @@ #define __HYPERVISOR_VIRT_START_PAE 0xF5800000 #define __MACH2PHYS_VIRT_START_PAE 0xF5800000 #define __MACH2PHYS_VIRT_END_PAE 0xF6800000 -#define HYPERVISOR_VIRT_START_PAE \ - mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE) -#define MACH2PHYS_VIRT_START_PAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE) -#define MACH2PHYS_VIRT_END_PAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE) +#define HYPERVISOR_VIRT_START_PAE xen_mk_ulong(__HYPERVISOR_VIRT_START_PAE) +#define MACH2PHYS_VIRT_START_PAE xen_mk_ulong(__MACH2PHYS_VIRT_START_PAE) +#define MACH2PHYS_VIRT_END_PAE xen_mk_ulong(__MACH2PHYS_VIRT_END_PAE) /* Non-PAE bounds are obsolete. */ #define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000 #define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000 #define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000 #define HYPERVISOR_VIRT_START_NONPAE \ - mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE) + xen_mk_ulong(__HYPERVISOR_VIRT_START_NONPAE) #define MACH2PHYS_VIRT_START_NONPAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE) + xen_mk_ulong(__MACH2PHYS_VIRT_START_NONPAE) #define MACH2PHYS_VIRT_END_NONPAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE) + xen_mk_ulong(__MACH2PHYS_VIRT_END_NONPAE) #define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE #define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE #define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE #ifndef HYPERVISOR_VIRT_START -#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START) +#define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START) #endif -#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START) -#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END) +#define MACH2PHYS_VIRT_START xen_mk_ulong(__MACH2PHYS_VIRT_START) +#define MACH2PHYS_VIRT_END xen_mk_ulong(__MACH2PHYS_VIRT_END) #define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2) #ifndef machine_to_phys_mapping #define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START) @@ -104,6 +101,7 @@ do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \ (hnd).p = val; \ } while ( 0 ) +#define int64_aligned_t int64_t __attribute__((aligned(8))) #define uint64_aligned_t uint64_t __attribute__((aligned(8))) #define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name #define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name) diff --git a/include/xen/arch-x86/xen-x86_64.h b/include/xen/arch-x86/xen-x86_64.h index 1c4e159..5e18613 100644 --- a/include/xen/arch-x86/xen-x86_64.h +++ b/include/xen/arch-x86/xen-x86_64.h @@ -76,12 +76,12 @@ #define __MACH2PHYS_VIRT_END 0xFFFF804000000000 #ifndef HYPERVISOR_VIRT_START -#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START) -#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END) +#define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START) +#define HYPERVISOR_VIRT_END xen_mk_ulong(__HYPERVISOR_VIRT_END) #endif -#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START) -#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END) +#define MACH2PHYS_VIRT_START xen_mk_ulong(__MACH2PHYS_VIRT_START) +#define MACH2PHYS_VIRT_END xen_mk_ulong(__MACH2PHYS_VIRT_END) #define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3) #ifndef machine_to_phys_mapping #define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) diff --git a/include/xen/xen.h b/include/xen/xen.h index a6a2092..6c9e42b 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h @@ -52,6 +52,19 @@ DEFINE_XEN_GUEST_HANDLE(void); DEFINE_XEN_GUEST_HANDLE(uint64_t); DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); + +/* Turn a plain number into a C unsigned (long) constant. */ +#define __xen_mk_uint(x) x ## U +#define __xen_mk_ulong(x) x ## UL +#define xen_mk_uint(x) __xen_mk_uint(x) +#define xen_mk_ulong(x) __xen_mk_ulong(x) + +#else + +/* In assembly code we cannot use C numeric constant suffixes. */ +#define xen_mk_uint(x) x +#define xen_mk_ulong(x) x + #endif /* @@ -101,6 +114,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); #define __HYPERVISOR_kexec_op 37 #define __HYPERVISOR_tmem_op 38 #define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */ +#define __HYPERVISOR_xenpmu_op 40 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 @@ -160,6 +174,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); #define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occured */ #define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient */ #define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */ +#define VIRQ_XENPMU 13 /* V. PMC interrupt */ /* Architecture-specific VIRQ definitions. */ #define VIRQ_ARCH_0 16 @@ -449,13 +464,13 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t); /* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */ /* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */ /* ` enum uvm_flags { */ -#define UVMF_NONE (0UL<<0) /* No flushing at all. */ -#define UVMF_TLB_FLUSH (1UL<<0) /* Flush entire TLB(s). */ -#define UVMF_INVLPG (2UL<<0) /* Flush only one entry. */ -#define UVMF_FLUSHTYPE_MASK (3UL<<0) -#define UVMF_MULTI (0UL<<2) /* Flush subset of TLBs. */ -#define UVMF_LOCAL (0UL<<2) /* Flush local TLB. */ -#define UVMF_ALL (1UL<<2) /* Flush all TLBs. */ +#define UVMF_NONE (xen_mk_ulong(0)<<0) /* No flushing at all. */ +#define UVMF_TLB_FLUSH (xen_mk_ulong(1)<<0) /* Flush entire TLB(s). */ +#define UVMF_INVLPG (xen_mk_ulong(2)<<0) /* Flush only one entry. */ +#define UVMF_FLUSHTYPE_MASK (xen_mk_ulong(3)<<0) +#define UVMF_MULTI (xen_mk_ulong(0)<<2) /* Flush subset of TLBs. */ +#define UVMF_LOCAL (xen_mk_ulong(0)<<2) /* Flush local TLB. */ +#define UVMF_ALL (xen_mk_ulong(1)<<2) /* Flush all TLBs. */ /* ` } */ /* @@ -486,17 +501,27 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t); /* x86/PAE guests: support PDPTs above 4GB. */ #define VMASST_TYPE_pae_extended_cr3 3 -#define MAX_VMASST_TYPE 3 - -#ifndef __ASSEMBLY__ +/* + * x86/64 guests: strictly hide M2P from user mode. + * This allows the guest to control respective hypervisor behavior: + * - when not set, L4 tables get created with the respective slot blank, + * and whenever the L4 table gets used as a kernel one the missing + * mapping gets inserted, + * - when set, L4 tables get created with the respective slot initialized + * as before, and whenever the L4 table gets used as a user one the + * mapping gets zapped. + */ +#define VMASST_TYPE_m2p_strict 32 -typedef uint16_t domid_t; +#if __XEN_INTERFACE_VERSION__ < 0x00040600 +#define MAX_VMASST_TYPE 3 +#endif /* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */ -#define DOMID_FIRST_RESERVED (0x7FF0U) +#define DOMID_FIRST_RESERVED xen_mk_uint(0x7FF0) /* DOMID_SELF is used in certain contexts to refer to oneself. */ -#define DOMID_SELF (0x7FF0U) +#define DOMID_SELF xen_mk_uint(0x7FF0) /* * DOMID_IO is used to restrict page-table updates to mapping I/O memory. @@ -507,7 +532,7 @@ typedef uint16_t domid_t; * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can * be specified by any calling domain. */ -#define DOMID_IO (0x7FF1U) +#define DOMID_IO xen_mk_uint(0x7FF1) /* * DOMID_XEN is used to allow privileged domains to map restricted parts of @@ -515,17 +540,21 @@ typedef uint16_t domid_t; * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if * the caller is privileged. */ -#define DOMID_XEN (0x7FF2U) +#define DOMID_XEN xen_mk_uint(0x7FF2) /* * DOMID_COW is used as the owner of sharable pages */ -#define DOMID_COW (0x7FF3U) +#define DOMID_COW xen_mk_uint(0x7FF3) /* DOMID_INVALID is used to identify pages with unknown owner. */ -#define DOMID_INVALID (0x7FF4U) +#define DOMID_INVALID xen_mk_uint(0x7FF4) /* Idle domain. */ -#define DOMID_IDLE (0x7FFFU) +#define DOMID_IDLE xen_mk_uint(0x7FFF) + +#ifndef __ASSEMBLY__ + +typedef uint16_t domid_t; /* * Send an array of these to HYPERVISOR_mmu_update(). @@ -682,6 +711,12 @@ struct shared_info { uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */ uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */ uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */ +#if !defined(__i386__) + uint32_t wc_sec_hi; +# define xen_wc_sec_hi wc_sec_hi +#elif !defined(__XEN__) && !defined(__XEN_TOOLS__) +# define xen_wc_sec_hi arch.wc_sec_hi +#endif struct arch_shared_info arch; @@ -698,24 +733,27 @@ typedef struct shared_info shared_info_t; * 3. This the order of bootstrap elements in the initial virtual region: * a. relocated kernel image * b. initial ram disk [mod_start, mod_len] + * (may be omitted) * c. list of allocated page frames [mfn_list, nr_pages] * (unless relocated due to XEN_ELFNOTE_INIT_P2M) * d. start_info_t structure [register ESI (x86)] - * e. bootstrap page tables [pt_base and CR3 (x86)] - * f. bootstrap stack [register ESP (x86)] + * in case of dom0 this page contains the console info, too + * e. unless dom0: xenstore ring page + * f. unless dom0: console ring page + * g. bootstrap page tables [pt_base and CR3 (x86)] + * h. bootstrap stack [register ESP (x86)] * 4. Bootstrap elements are packed together, but each is 4kB-aligned. - * 5. The initial ram disk may be omitted. - * 6. The list of page frames forms a contiguous 'pseudo-physical' memory + * 5. The list of page frames forms a contiguous 'pseudo-physical' memory * layout for the domain. In particular, the bootstrap virtual-memory * region is a 1:1 mapping to the first section of the pseudo-physical map. - * 7. All bootstrap elements are mapped read-writable for the guest OS. The + * 6. All bootstrap elements are mapped read-writable for the guest OS. The * only exception is the bootstrap page table, which is mapped read-only. - * 8. There is guaranteed to be at least 512kB padding after the final + * 7. There is guaranteed to be at least 512kB padding after the final * bootstrap element. If necessary, the bootstrap virtual region is * extended by an extra 4MB to ensure this. * * Note: Prior to 25833:bb85bbccb1c9. ("x86/32-on-64 adjust Dom0 initial page - * table layout") a bug caused the pt_base (3.e above) and cr3 to not point + * table layout") a bug caused the pt_base (3.g above) and cr3 to not point * to the start of the guest page tables (it was offset by two pages). * This only manifested itself on 32-on-64 dom0 kernels and not 32-on-64 domU * or 64-bit kernels of any colour. The page tables for a 32-on-64 dom0 got @@ -759,6 +797,29 @@ struct start_info { }; typedef struct start_info start_info_t; +/* + * Start of day structure passed to PVH guests in %ebx. + * + * NOTE: nothing will be loaded at physical address 0, so + * a 0 value in any of the address fields should be treated + * as not present. + */ +struct hvm_start_info { +#define HVM_START_MAGIC_VALUE 0x336ec578 + uint32_t magic; /* Contains the magic value 0x336ec578 */ + /* ("xEn3" with the 0x80 bit of the "E" set).*/ + uint32_t flags; /* SIF_xxx flags. */ + uint32_t cmdline_paddr; /* Physical address of the command line. */ + uint32_t nr_modules; /* Number of modules passed to the kernel. */ + uint32_t modlist_paddr; /* Physical address of an array of */ + /* hvm_modlist_entry. */ +}; + +struct hvm_modlist_entry { + uint32_t paddr; /* Physical address of the module. */ + uint32_t size; /* Size of the module in bytes. */ +}; + /* New console union for dom0 introduced in 0x00030203. */ #if __XEN_INTERFACE_VERSION__ < 0x00030203 #define console_mfn console.domU.mfn @@ -771,6 +832,8 @@ typedef struct start_info start_info_t; #define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */ #define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */ #define SIF_MOD_START_PFN (1<<3) /* Is mod_start a PFN? */ +#define SIF_VIRT_P2M_4TOOLS (1<<4) /* Do Xen tools understand a virt. mapped */ + /* P->M making the 3 level tree obsolete? */ #define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */ /* @@ -851,25 +914,19 @@ typedef struct dom0_vga_console_info { typedef uint8_t xen_domain_handle_t[16]; -/* Turn a plain number into a C unsigned long constant. */ -#define __mk_unsigned_long(x) x ## UL -#define mk_unsigned_long(x) __mk_unsigned_long(x) - __DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t); __DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t); __DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t); __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t); -#else /* __ASSEMBLY__ */ - -/* In assembly code we cannot use C numeric constant suffixes. */ -#define mk_unsigned_long(x) x - #endif /* !__ASSEMBLY__ */ /* Default definitions for macros used by domctl/sysctl. */ #if defined(__XEN__) || defined(__XEN_TOOLS__) +#ifndef int64_aligned_t +#define int64_aligned_t int64_t +#endif #ifndef uint64_aligned_t #define uint64_aligned_t uint64_t #endif -- 2.6.6 ++++++ 0006-xen-factor-out-p2m-list-allocation-into-separate-fun.patch ++++++ >From e7afb8d41e024a88bfc78f4ee579e7c5dbd39616 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:11 +0100 Subject: [PATCH 06/11] xen: factor out p2m list allocation into separate function Do the p2m list allocation of the to be loaded kernel in a separate function. This will allow doing the p2m list allocation at different times of the boot preparations depending on the features the kernel is supporting. While at this remove superfluous setting of first_p2m_pfn and nr_p2m_frames as those are needed only in case of the p2m list not being mapped by the initial kernel mapping. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 89 ++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index 691c22e..a2fd1f6 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -44,8 +44,10 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct xen_loader_state { struct grub_relocator *relocator; + struct grub_relocator_xen_state state; struct start_info next_start; struct grub_xen_file_info xen_inf; + grub_xen_mfn_t *virt_mfn_list; grub_uint64_t max_addr; struct xen_multiboot_mod_list *module_info_page; grub_uint64_t modules_target_start; @@ -170,7 +172,7 @@ generate_page_table (grub_uint64_t *where, grub_uint64_t paging_start, } static grub_err_t -set_mfns (grub_xen_mfn_t * new_mfn_list, grub_xen_mfn_t pfn) +set_mfns (grub_xen_mfn_t pfn) { grub_xen_mfn_t i, t; grub_xen_mfn_t cn_pfn = -1, st_pfn = -1; @@ -179,32 +181,34 @@ set_mfns (grub_xen_mfn_t * new_mfn_list, grub_xen_mfn_t pfn) for (i = 0; i < grub_xen_start_page_addr->nr_pages; i++) { - if (new_mfn_list[i] == grub_xen_start_page_addr->console.domU.mfn) + if (xen_state.virt_mfn_list[i] == + grub_xen_start_page_addr->console.domU.mfn) cn_pfn = i; - if (new_mfn_list[i] == grub_xen_start_page_addr->store_mfn) + if (xen_state.virt_mfn_list[i] == grub_xen_start_page_addr->store_mfn) st_pfn = i; } if (cn_pfn == (grub_xen_mfn_t)-1) return grub_error (GRUB_ERR_BUG, "no console"); if (st_pfn == (grub_xen_mfn_t)-1) return grub_error (GRUB_ERR_BUG, "no store"); - t = new_mfn_list[pfn]; - new_mfn_list[pfn] = new_mfn_list[cn_pfn]; - new_mfn_list[cn_pfn] = t; - t = new_mfn_list[pfn + 1]; - new_mfn_list[pfn + 1] = new_mfn_list[st_pfn]; - new_mfn_list[st_pfn] = t; - - m2p_updates[0].ptr = page2offset (new_mfn_list[pfn]) | MMU_MACHPHYS_UPDATE; + t = xen_state.virt_mfn_list[pfn]; + xen_state.virt_mfn_list[pfn] = xen_state.virt_mfn_list[cn_pfn]; + xen_state.virt_mfn_list[cn_pfn] = t; + t = xen_state.virt_mfn_list[pfn + 1]; + xen_state.virt_mfn_list[pfn + 1] = xen_state.virt_mfn_list[st_pfn]; + xen_state.virt_mfn_list[st_pfn] = t; + + m2p_updates[0].ptr = + page2offset (xen_state.virt_mfn_list[pfn]) | MMU_MACHPHYS_UPDATE; m2p_updates[0].val = pfn; m2p_updates[1].ptr = - page2offset (new_mfn_list[pfn + 1]) | MMU_MACHPHYS_UPDATE; + page2offset (xen_state.virt_mfn_list[pfn + 1]) | MMU_MACHPHYS_UPDATE; m2p_updates[1].val = pfn + 1; m2p_updates[2].ptr = - page2offset (new_mfn_list[cn_pfn]) | MMU_MACHPHYS_UPDATE; + page2offset (xen_state.virt_mfn_list[cn_pfn]) | MMU_MACHPHYS_UPDATE; m2p_updates[2].val = cn_pfn; m2p_updates[3].ptr = - page2offset (new_mfn_list[st_pfn]) | MMU_MACHPHYS_UPDATE; + page2offset (xen_state.virt_mfn_list[st_pfn]) | MMU_MACHPHYS_UPDATE; m2p_updates[3].val = st_pfn; grub_xen_mmu_update (m2p_updates, 4, NULL, DOMID_SELF); @@ -213,43 +217,52 @@ set_mfns (grub_xen_mfn_t * new_mfn_list, grub_xen_mfn_t pfn) } static grub_err_t +grub_xen_p2m_alloc (void) +{ + grub_relocator_chunk_t ch; + grub_size_t p2msize; + grub_err_t err; + + xen_state.state.mfn_list = xen_state.max_addr; + xen_state.next_start.mfn_list = + xen_state.max_addr + xen_state.xen_inf.virt_base; + p2msize = sizeof (grub_xen_mfn_t) * grub_xen_start_page_addr->nr_pages; + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, + xen_state.max_addr, p2msize); + if (err) + return err; + xen_state.virt_mfn_list = get_virtual_current_address (ch); + grub_memcpy (xen_state.virt_mfn_list, + (void *) grub_xen_start_page_addr->mfn_list, p2msize); + xen_state.max_addr = ALIGN_UP (xen_state.max_addr + p2msize, PAGE_SIZE); + + return GRUB_ERR_NONE; +} + +static grub_err_t grub_xen_boot (void) { - struct grub_relocator_xen_state state; grub_relocator_chunk_t ch; grub_err_t err; - grub_size_t pgtsize; struct start_info *nst; grub_uint64_t nr_info_pages; grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages; struct gnttab_set_version gnttab_setver; - grub_xen_mfn_t *new_mfn_list; grub_size_t i; if (grub_xen_n_allocated_shared_pages) return grub_error (GRUB_ERR_BUG, "active grants"); - state.mfn_list = xen_state.max_addr; - xen_state.next_start.mfn_list = - xen_state.max_addr + xen_state.xen_inf.virt_base; - xen_state.next_start.first_p2m_pfn = xen_state.max_addr >> PAGE_SHIFT; - pgtsize = sizeof (grub_xen_mfn_t) * grub_xen_start_page_addr->nr_pages; - err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, - xen_state.max_addr, pgtsize); - xen_state.next_start.nr_p2m_frames = (pgtsize + PAGE_SIZE - 1) >> PAGE_SHIFT; + err = grub_xen_p2m_alloc (); if (err) return err; - new_mfn_list = get_virtual_current_address (ch); - grub_memcpy (new_mfn_list, - (void *) grub_xen_start_page_addr->mfn_list, pgtsize); - xen_state.max_addr = ALIGN_UP (xen_state.max_addr + pgtsize, PAGE_SIZE); err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, xen_state.max_addr, sizeof (xen_state.next_start)); if (err) return err; - state.start_info = xen_state.max_addr + xen_state.xen_inf.virt_base; + xen_state.state.start_info = xen_state.max_addr + xen_state.xen_inf.virt_base; nst = get_virtual_current_address (ch); xen_state.max_addr = ALIGN_UP (xen_state.max_addr + sizeof (xen_state.next_start), PAGE_SIZE); @@ -262,14 +275,14 @@ grub_xen_boot (void) xen_state.next_start.console.domU = grub_xen_start_page_addr->console.domU; xen_state.next_start.shared_info = grub_xen_start_page_addr->shared_info; - err = set_mfns (new_mfn_list, xen_state.max_addr >> PAGE_SHIFT); + err = set_mfns (xen_state.max_addr >> PAGE_SHIFT); if (err) return err; xen_state.max_addr += 2 * PAGE_SIZE; xen_state.next_start.pt_base = xen_state.max_addr + xen_state.xen_inf.virt_base; - state.paging_start = xen_state.max_addr >> PAGE_SHIFT; + xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT; nr_info_pages = xen_state.max_addr >> PAGE_SHIFT; nr_pages = nr_info_pages; @@ -298,15 +311,15 @@ grub_xen_boot (void) generate_page_table (get_virtual_current_address (ch), xen_state.max_addr >> PAGE_SHIFT, nr_pages, - xen_state.xen_inf.virt_base, new_mfn_list); + xen_state.xen_inf.virt_base, xen_state.virt_mfn_list); xen_state.max_addr += page2offset (nr_pt_pages); - state.stack = xen_state.max_addr + STACK_SIZE + xen_state.xen_inf.virt_base; - state.entry_point = xen_state.xen_inf.entry_point; + xen_state.state.stack = + xen_state.max_addr + STACK_SIZE + xen_state.xen_inf.virt_base; + xen_state.state.entry_point = xen_state.xen_inf.entry_point; - xen_state.next_start.nr_p2m_frames += nr_pt_pages; xen_state.next_start.nr_pt_frames = nr_pt_pages; - state.paging_size = nr_pt_pages; + xen_state.state.paging_size = nr_pt_pages; *nst = xen_state.next_start; @@ -318,7 +331,7 @@ grub_xen_boot (void) for (i = 0; i < ARRAY_SIZE (grub_xen_shared_info->evtchn_pending); i++) grub_xen_shared_info->evtchn_pending[i] = 0; - return grub_relocator_xen_boot (xen_state.relocator, state, nr_pages, + return grub_relocator_xen_boot (xen_state.relocator, xen_state.state, nr_pages, xen_state.xen_inf.virt_base < PAGE_SIZE ? page2offset (nr_pages) : 0, nr_pages - 1, -- 2.6.6 ++++++ 0007-xen-factor-out-allocation-of-special-pages-into-sepa.patch ++++++ >From 7f6888bb015764b99d90892bc506ded98f6ed9fe Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:12 +0100 Subject: [PATCH 07/11] xen: factor out allocation of special pages into separate function Do the allocation of special pages (start info, console and xenbus ring buffers) in a separate function. This will allow to do the allocation at different times of the boot preparations depending on the features the kernel is supporting. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 48 +++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index a2fd1f6..a80c0f8 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -48,6 +48,8 @@ struct xen_loader_state { struct start_info next_start; struct grub_xen_file_info xen_inf; grub_xen_mfn_t *virt_mfn_list; + struct start_info *virt_start_info; + grub_xen_mfn_t console_pfn; grub_uint64_t max_addr; struct xen_multiboot_mod_list *module_info_page; grub_uint64_t modules_target_start; @@ -240,22 +242,10 @@ grub_xen_p2m_alloc (void) } static grub_err_t -grub_xen_boot (void) +grub_xen_special_alloc (void) { grub_relocator_chunk_t ch; grub_err_t err; - struct start_info *nst; - grub_uint64_t nr_info_pages; - grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages; - struct gnttab_set_version gnttab_setver; - grub_size_t i; - - if (grub_xen_n_allocated_shared_pages) - return grub_error (GRUB_ERR_BUG, "active grants"); - - err = grub_xen_p2m_alloc (); - if (err) - return err; err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, xen_state.max_addr, @@ -263,9 +253,11 @@ grub_xen_boot (void) if (err) return err; xen_state.state.start_info = xen_state.max_addr + xen_state.xen_inf.virt_base; - nst = get_virtual_current_address (ch); + xen_state.virt_start_info = get_virtual_current_address (ch); xen_state.max_addr = ALIGN_UP (xen_state.max_addr + sizeof (xen_state.next_start), PAGE_SIZE); + xen_state.console_pfn = xen_state.max_addr >> PAGE_SHIFT; + xen_state.max_addr += 2 * PAGE_SIZE; xen_state.next_start.nr_pages = grub_xen_start_page_addr->nr_pages; grub_memcpy (xen_state.next_start.magic, grub_xen_start_page_addr->magic, @@ -275,10 +267,28 @@ grub_xen_boot (void) xen_state.next_start.console.domU = grub_xen_start_page_addr->console.domU; xen_state.next_start.shared_info = grub_xen_start_page_addr->shared_info; - err = set_mfns (xen_state.max_addr >> PAGE_SHIFT); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_xen_boot (void) +{ + grub_relocator_chunk_t ch; + grub_err_t err; + grub_uint64_t nr_info_pages; + grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages; + struct gnttab_set_version gnttab_setver; + grub_size_t i; + + if (grub_xen_n_allocated_shared_pages) + return grub_error (GRUB_ERR_BUG, "active grants"); + + err = grub_xen_p2m_alloc (); + if (err) + return err; + err = grub_xen_special_alloc (); if (err) return err; - xen_state.max_addr += 2 * PAGE_SIZE; xen_state.next_start.pt_base = xen_state.max_addr + xen_state.xen_inf.virt_base; @@ -309,6 +319,10 @@ grub_xen_boot (void) if (err) return err; + err = set_mfns (xen_state.console_pfn); + if (err) + return err; + generate_page_table (get_virtual_current_address (ch), xen_state.max_addr >> PAGE_SHIFT, nr_pages, xen_state.xen_inf.virt_base, xen_state.virt_mfn_list); @@ -321,7 +335,7 @@ grub_xen_boot (void) xen_state.next_start.nr_pt_frames = nr_pt_pages; xen_state.state.paging_size = nr_pt_pages; - *nst = xen_state.next_start; + *xen_state.virt_start_info = xen_state.next_start; grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver)); -- 2.6.6 ++++++ 0008-xen-factor-out-allocation-of-page-tables-into-separa.patch ++++++ >From e5cce22a4448d84c50ef30acdd1990ecee16f2c2 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:13 +0100 Subject: [PATCH 08/11] xen: factor out allocation of page tables into separate function Do the allocation of page tables in a separate function. This will allow to do the allocation at different times of the boot preparations depending on the features the kernel is supporting. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 85 ++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index a80c0f8..2e12763 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -51,6 +51,9 @@ struct xen_loader_state { struct start_info *virt_start_info; grub_xen_mfn_t console_pfn; grub_uint64_t max_addr; + grub_uint64_t *virt_pgtable; + grub_uint64_t pgtbl_start; + grub_uint64_t pgtbl_end; struct xen_multiboot_mod_list *module_info_page; grub_uint64_t modules_target_start; grub_size_t n_modules; @@ -110,17 +113,17 @@ get_pgtable_size (grub_uint64_t total_pages, grub_uint64_t virt_base) static void generate_page_table (grub_uint64_t *where, grub_uint64_t paging_start, - grub_uint64_t total_pages, grub_uint64_t virt_base, - grub_xen_mfn_t *mfn_list) + grub_uint64_t paging_end, grub_uint64_t total_pages, + grub_uint64_t virt_base, grub_xen_mfn_t *mfn_list) { if (!virt_base) - total_pages++; + paging_end++; grub_uint64_t lx[NUMBER_OF_LEVELS], lxs[NUMBER_OF_LEVELS]; grub_uint64_t nlx, nls, sz = 0; int l; - nlx = total_pages; + nlx = paging_end; nls = virt_base >> PAGE_SHIFT; for (l = 0; l < NUMBER_OF_LEVELS; l++) { @@ -164,7 +167,7 @@ generate_page_table (grub_uint64_t *where, grub_uint64_t paging_start, if (pr) pg += POINTERS_PER_PAGE; - for (j = 0; j < total_pages; j++) + for (j = 0; j < paging_end; j++) { if (j >= paging_start && j < lp) pg[j + lxs[0]] = page2offset (mfn_list[j]) | 5; @@ -271,24 +274,12 @@ grub_xen_special_alloc (void) } static grub_err_t -grub_xen_boot (void) +grub_xen_pt_alloc (void) { grub_relocator_chunk_t ch; grub_err_t err; grub_uint64_t nr_info_pages; grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages; - struct gnttab_set_version gnttab_setver; - grub_size_t i; - - if (grub_xen_n_allocated_shared_pages) - return grub_error (GRUB_ERR_BUG, "active grants"); - - err = grub_xen_p2m_alloc (); - if (err) - return err; - err = grub_xen_special_alloc (); - if (err) - return err; xen_state.next_start.pt_base = xen_state.max_addr + xen_state.xen_inf.virt_base; @@ -309,32 +300,62 @@ grub_xen_boot (void) nr_pages = nr_need_pages; } - grub_dprintf ("xen", "bootstrap domain %llx+%llx\n", - (unsigned long long) xen_state.xen_inf.virt_base, - (unsigned long long) page2offset (nr_pages)); - err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, xen_state.max_addr, page2offset (nr_pt_pages)); if (err) return err; + xen_state.virt_pgtable = get_virtual_current_address (ch); + xen_state.pgtbl_start = xen_state.max_addr >> PAGE_SHIFT; + xen_state.max_addr += page2offset (nr_pt_pages); + xen_state.state.stack = + xen_state.max_addr + STACK_SIZE + xen_state.xen_inf.virt_base; + xen_state.state.paging_size = nr_pt_pages; + xen_state.next_start.nr_pt_frames = nr_pt_pages; + xen_state.max_addr = page2offset (nr_pages); + xen_state.pgtbl_end = nr_pages; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_xen_boot (void) +{ + grub_err_t err; + grub_uint64_t nr_pages; + struct gnttab_set_version gnttab_setver; + grub_size_t i; + + if (grub_xen_n_allocated_shared_pages) + return grub_error (GRUB_ERR_BUG, "active grants"); + + err = grub_xen_p2m_alloc (); + if (err) + return err; + err = grub_xen_special_alloc (); + if (err) + return err; + err = grub_xen_pt_alloc (); + if (err) + return err; + err = set_mfns (xen_state.console_pfn); if (err) return err; - generate_page_table (get_virtual_current_address (ch), - xen_state.max_addr >> PAGE_SHIFT, nr_pages, + nr_pages = xen_state.max_addr >> PAGE_SHIFT; + + grub_dprintf ("xen", "bootstrap domain %llx+%llx\n", + (unsigned long long) xen_state.xen_inf.virt_base, + (unsigned long long) page2offset (nr_pages)); + + generate_page_table (xen_state.virt_pgtable, xen_state.pgtbl_start, + xen_state.pgtbl_end, nr_pages, xen_state.xen_inf.virt_base, xen_state.virt_mfn_list); - xen_state.max_addr += page2offset (nr_pt_pages); - xen_state.state.stack = - xen_state.max_addr + STACK_SIZE + xen_state.xen_inf.virt_base; xen_state.state.entry_point = xen_state.xen_inf.entry_point; - xen_state.next_start.nr_pt_frames = nr_pt_pages; - xen_state.state.paging_size = nr_pt_pages; - *xen_state.virt_start_info = xen_state.next_start; grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver)); @@ -348,8 +369,8 @@ grub_xen_boot (void) return grub_relocator_xen_boot (xen_state.relocator, xen_state.state, nr_pages, xen_state.xen_inf.virt_base < PAGE_SIZE ? page2offset (nr_pages) : 0, - nr_pages - 1, - page2offset (nr_pages - 1) + + xen_state.pgtbl_end - 1, + page2offset (xen_state.pgtbl_end - 1) + xen_state.xen_inf.virt_base); } -- 2.6.6 ++++++ 0009-xen-add-capability-to-load-initrd-outside-of-initial.patch ++++++ >From 9c7798d3bed807f29a7056bac5bd8c4b0f33ca34 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:14 +0100 Subject: [PATCH 09/11] xen: add capability to load initrd outside of initial mapping Modern pvops linux kernels support an initrd not covered by the initial mapping. This capability is flagged by an elf-note. In case the elf-note is set by the kernel don't place the initrd into the initial mapping. This will allow to load larger initrds and/or support domains with larger memory, as the initial mapping is limited to 2GB and it is containing the p2m list. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 60 +++++++++++++++++++++++++++++++------- grub-core/loader/i386/xen_fileXX.c | 3 ++ include/grub/xen_file.h | 1 + 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index 2e12763..9639ca1 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -228,6 +228,9 @@ grub_xen_p2m_alloc (void) grub_size_t p2msize; grub_err_t err; + if (xen_state.virt_mfn_list) + return GRUB_ERR_NONE; + xen_state.state.mfn_list = xen_state.max_addr; xen_state.next_start.mfn_list = xen_state.max_addr + xen_state.xen_inf.virt_base; @@ -250,6 +253,9 @@ grub_xen_special_alloc (void) grub_relocator_chunk_t ch; grub_err_t err; + if (xen_state.virt_start_info) + return GRUB_ERR_NONE; + err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, xen_state.max_addr, sizeof (xen_state.next_start)); @@ -281,6 +287,9 @@ grub_xen_pt_alloc (void) grub_uint64_t nr_info_pages; grub_uint64_t nr_pages, nr_pt_pages, nr_need_pages; + if (xen_state.virt_pgtable) + return GRUB_ERR_NONE; + xen_state.next_start.pt_base = xen_state.max_addr + xen_state.xen_inf.virt_base; xen_state.state.paging_start = xen_state.max_addr >> PAGE_SHIFT; @@ -319,16 +328,11 @@ grub_xen_pt_alloc (void) return GRUB_ERR_NONE; } +/* Allocate all not yet allocated areas mapped by initial page tables. */ static grub_err_t -grub_xen_boot (void) +grub_xen_alloc_boot_data (void) { grub_err_t err; - grub_uint64_t nr_pages; - struct gnttab_set_version gnttab_setver; - grub_size_t i; - - if (grub_xen_n_allocated_shared_pages) - return grub_error (GRUB_ERR_BUG, "active grants"); err = grub_xen_p2m_alloc (); if (err) @@ -340,6 +344,24 @@ grub_xen_boot (void) if (err) return err; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_xen_boot (void) +{ + grub_err_t err; + grub_uint64_t nr_pages; + struct gnttab_set_version gnttab_setver; + grub_size_t i; + + if (grub_xen_n_allocated_shared_pages) + return grub_error (GRUB_ERR_BUG, "active grants"); + + err = grub_xen_alloc_boot_data (); + if (err) + return err; + err = set_mfns (xen_state.console_pfn); if (err) return err; @@ -610,6 +632,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } + if (xen_state.xen_inf.unmapped_initrd) + { + err = grub_xen_alloc_boot_data (); + if (err) + goto fail; + } + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; @@ -627,14 +656,22 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - xen_state.next_start.mod_start = - xen_state.max_addr + xen_state.xen_inf.virt_base; xen_state.next_start.mod_len = size; - xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE); + if (xen_state.xen_inf.unmapped_initrd) + { + xen_state.next_start.flags |= SIF_MOD_START_PFN; + xen_state.next_start.mod_start = xen_state.max_addr >> PAGE_SHIFT; + } + else + xen_state.next_start.mod_start = + xen_state.max_addr + xen_state.xen_inf.virt_base; grub_dprintf ("xen", "Initrd, addr=0x%x, size=0x%x\n", - (unsigned) xen_state.next_start.mod_start, (unsigned) size); + (unsigned) (xen_state.max_addr + xen_state.xen_inf.virt_base), + (unsigned) size); + + xen_state.max_addr = ALIGN_UP (xen_state.max_addr + size, PAGE_SIZE); fail: grub_initrd_close (&initrd_ctx); @@ -686,6 +723,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), if (!xen_state.module_info_page) { + xen_state.xen_inf.unmapped_initrd = 0; xen_state.n_modules = 0; xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE); xen_state.modules_target_start = xen_state.max_addr; diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c index 03215ca..8751174 100644 --- a/grub-core/loader/i386/xen_fileXX.c +++ b/grub-core/loader/i386/xen_fileXX.c @@ -261,6 +261,9 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi, descsz == 2 ? 2 : 3) == 0) xi->arch = GRUB_XEN_FILE_I386; break; + case XEN_ELFNOTE_MOD_START_PFN: + xi->unmapped_initrd = !!grub_le_to_cpu32(*(grub_uint32_t *) desc); + break; default: grub_dprintf ("xen", "unknown note type %d\n", nh->n_type); break; diff --git a/include/grub/xen_file.h b/include/grub/xen_file.h index 4b2ccba..ed749fa 100644 --- a/include/grub/xen_file.h +++ b/include/grub/xen_file.h @@ -36,6 +36,7 @@ struct grub_xen_file_info int has_note; int has_xen_guest; int extended_cr3; + int unmapped_initrd; enum { GRUB_XEN_FILE_I386 = 1, -- 2.6.6 ++++++ 0010-xen-modify-page-table-construction.patch ++++++ ++++ 951 lines (skipped) ++++++ 0011-xen-add-capability-to-load-p2m-list-outside-of-kerne.patch ++++++ >From e776ceae4d7fe4ba66484bec7f85110f737168f9 Mon Sep 17 00:00:00 2001 From: Juergen Gross <[email protected]> Date: Thu, 3 Mar 2016 10:38:16 +0100 Subject: [PATCH 11/11] xen: add capability to load p2m list outside of kernel mapping Modern pvops linux kernels support a p2m list not covered by the kernel mapping. This capability is flagged by an elf-note specifying the virtual address the kernel is expecting the p2m list to be mapped to. In case the elf-note is set by the kernel don't place the p2m list into the kernel mapping, but map it to the given address. This will allow to support domains with larger memory, as the kernel mapping is limited to 2GB and a domain with huge memory in the TB range will have a p2m list larger than this. Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- grub-core/loader/i386/xen.c | 53 +++++++++++++++++++++++++++++++------- grub-core/loader/i386/xen_fileXX.c | 4 +++ include/grub/xen_file.h | 2 ++ 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index a98badf..51d1ddd 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -313,24 +313,50 @@ static grub_err_t grub_xen_p2m_alloc (void) { grub_relocator_chunk_t ch; - grub_size_t p2msize; + grub_size_t p2msize, p2malloc; grub_err_t err; + struct grub_xen_mapping *map; if (xen_state.virt_mfn_list) return GRUB_ERR_NONE; + map = xen_state.mappings + xen_state.n_mappings; + p2msize = ALIGN_UP (sizeof (grub_xen_mfn_t) * + grub_xen_start_page_addr->nr_pages, PAGE_SIZE); + if (xen_state.xen_inf.has_p2m_base) + { + err = get_pgtable_size (xen_state.xen_inf.p2m_base, + xen_state.xen_inf.p2m_base + p2msize, + (xen_state.max_addr + p2msize) >> PAGE_SHIFT); + if (err) + return err; + + map->area.pfn_start = xen_state.max_addr >> PAGE_SHIFT; + p2malloc = p2msize + page2offset (map->area.n_pt_pages); + xen_state.n_mappings++; + xen_state.next_start.mfn_list = xen_state.xen_inf.p2m_base; + xen_state.next_start.first_p2m_pfn = map->area.pfn_start; + xen_state.next_start.nr_p2m_frames = p2malloc >> PAGE_SHIFT; + } + else + { + xen_state.next_start.mfn_list = + xen_state.max_addr + xen_state.xen_inf.virt_base; + p2malloc = p2msize; + } + xen_state.state.mfn_list = xen_state.max_addr; - xen_state.next_start.mfn_list = - xen_state.max_addr + xen_state.xen_inf.virt_base; - p2msize = sizeof (grub_xen_mfn_t) * grub_xen_start_page_addr->nr_pages; err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, - xen_state.max_addr, p2msize); + xen_state.max_addr, p2malloc); if (err) return err; xen_state.virt_mfn_list = get_virtual_current_address (ch); + if (xen_state.xen_inf.has_p2m_base) + map->where = (grub_uint64_t *) xen_state.virt_mfn_list + + p2msize / sizeof (grub_uint64_t); grub_memcpy (xen_state.virt_mfn_list, (void *) grub_xen_start_page_addr->mfn_list, p2msize); - xen_state.max_addr = ALIGN_UP (xen_state.max_addr + p2msize, PAGE_SIZE); + xen_state.max_addr += p2malloc; return GRUB_ERR_NONE; } @@ -448,9 +474,12 @@ grub_xen_alloc_boot_data (void) { grub_err_t err; - err = grub_xen_p2m_alloc (); - if (err) - return err; + if (!xen_state.xen_inf.has_p2m_base) + { + err = grub_xen_p2m_alloc (); + if (err) + return err; + } err = grub_xen_special_alloc (); if (err) return err; @@ -475,6 +504,12 @@ grub_xen_boot (void) err = grub_xen_alloc_boot_data (); if (err) return err; + if (xen_state.xen_inf.has_p2m_base) + { + err = grub_xen_p2m_alloc (); + if (err) + return err; + } err = set_mfns (xen_state.console_pfn); if (err) diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c index 8751174..fb66e66 100644 --- a/grub-core/loader/i386/xen_fileXX.c +++ b/grub-core/loader/i386/xen_fileXX.c @@ -261,6 +261,10 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi, descsz == 2 ? 2 : 3) == 0) xi->arch = GRUB_XEN_FILE_I386; break; + case XEN_ELFNOTE_INIT_P2M: + xi->p2m_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc); + xi->has_p2m_base = 1; + break; case XEN_ELFNOTE_MOD_START_PFN: xi->unmapped_initrd = !!grub_le_to_cpu32(*(grub_uint32_t *) desc); break; diff --git a/include/grub/xen_file.h b/include/grub/xen_file.h index ed749fa..6587999 100644 --- a/include/grub/xen_file.h +++ b/include/grub/xen_file.h @@ -32,9 +32,11 @@ struct grub_xen_file_info grub_uint64_t entry_point; grub_uint64_t hypercall_page; grub_uint64_t paddr_offset; + grub_uint64_t p2m_base; int has_hypercall_page; int has_note; int has_xen_guest; + int has_p2m_base; int extended_cr3; int unmapped_initrd; enum -- 2.6.6
