Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xen PVH booting via multiboot protocol (from pvgrub2-pvh) #482

Merged
merged 3 commits into from
Nov 9, 2020

Conversation

marmarek
Copy link
Contributor

@marmarek marmarek commented Nov 4, 2020

See QubesOS/qubes-issues#6162 for context.

TODO items:

  • reorganize headers: avoid cross-platform includes;
  • deduplicate multiboot parsing (move to bindings/multiboot.c?); alternative: don't parse multiboot info at all - will loose cmdline, but memmap can be retrieved via XENMEM_memory_map hypercall
  • consider mapping low memory too (multiboot boot information is placed there) - will avoid the need to parse hvm_start_info and multiboot in different places

Copy link
Member

@mato mato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks! Various comments in-line.

@@ -55,6 +74,13 @@ ENTRY(_start32)
pushl $0
pushl %ebx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, %ebx is now either a (struct hvm_start_info *) with direct boot, OR a (struct multiboot_info *), right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, can you please update both the header comment for this entry point and the comment immediately above to make sense in the new arrangement?

@@ -20,10 +20,29 @@

#include "../cpu_x86_64.h"
#include "xen/elfnote.h"
#include "../virtio/multiboot.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can leave this as-is, virtio needs some reverse consolidation with Xen anyway, so can do that then.


.align 4
_multiboot_header:
.long MULTIBOOT_HEADER_MAGIC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Indent the rest of this block by 4 spaces.

@@ -227,19 +228,64 @@ static void hypercall_init(void)
assert(HYPERCALL_PAGE[0] != 0xc3);
}

void platform_init(const void *arg __attribute__((unused)))
/* Parse multiboot boot information */
static void parse_multiboot(const void *arg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for the comment.


static void parse_hvm_start_info(const void *arg) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Opening { goes on the following line.


void platform_init(const void *arg)
{
bool multiboot = *((uint32_t*)arg) != XEN_HVM_START_MAGIC_VALUE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does too much in one line, including assignment of a truth value based on the negation of another truth value. Please make it more explicit, e.g.:

bool is_xl_boot;
if (*(uint32_t *)arg == XEN_HVM_START_MAGIC_VALUE)
    is_xl_boot = true;
else
    is_xl_boot = false;

and modify below to suit.

bool multiboot = *((uint32_t*)arg) != XEN_HVM_START_MAGIC_VALUE;

/*
* Parse multiboot before setting page tables, as its location may not be
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"If booted via multiboot, parse multiboot structure before setting up page tables ..."

console_init();

/*
* Parse Xen HVM/PVH start_info structure after setting hypercall page - it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"If booted directly, parse the Xen hvm_start_info structure after setting up hypercalls"

.interp : {
*(.interp)
} :interp :text

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this need moving, exactly? It doesn't really matter for Xen, but I'd still like to understand what's going on.

Copy link
Contributor Author

@marmarek marmarek Nov 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The multiboot header needs to be in the first 8k of the file. Without this change, first 4k were program headers, then the second 4k were just this section, pushing multiboot header beyond the first 8k.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to accomplish the same thing without re-ordering by placing *(.data.multiboot) into the .text output section as is done in solo5_virtio.lds?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already here and it wasn't enough. .text was linked at 8k offset in the file - just beyond what we need. I'm not sure what's the difference with virtio, perhaps more notes here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, don't worry about it, leave it as-is (and in a separate commit). Thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(... looking at the linker scripts and readelf output, I actually think .interp doesn't belong in :text at all but I'm not going to muck with that now...)

@mato
Copy link
Member

mato commented Nov 5, 2020

reorganize headers: avoid cross-platform includes;
deduplicate multiboot parsing (move to bindings/multiboot.c?)

As I mentioned, there is more to sync/de-duplicate between virtio and xen than this, I'm happy to do it at some stage, no need to do it here.

consider mapping low memory too (multiboot boot information is placed there) - will avoid the need to parse hvm_start_info and multiboot in different places

I'd prefer to leave the low memory unmapped as it stops the unikernel from trivially mucking with its pagetables, intentionally or not.

@marmarek
Copy link
Contributor Author

marmarek commented Nov 5, 2020

I'd prefer to leave the low memory unmapped as it stops the unikernel from trivially mucking with its pagetables, intentionally or not.

I was considering mapping read-only.

@mato
Copy link
Member

mato commented Nov 5, 2020

I was considering mapping read-only.

I like the fact that you can't even introspect your pagetables (or anything else Xen might have "helpfully" put in low memory) without reloading %cr3.

@marmarek
Copy link
Contributor Author

marmarek commented Nov 5, 2020

Sure, no problem - as you can see it isn't a blocker.

Add multiboot header pointing at the same entry point. Then, in
platform_init distinguish which boot structure is in use based on its
magic.
Borrow the multiboot structure parsing from virtio bindings.
Currently two boot modes are supported:
 - native PVH
 - multiboot (not multiboot2)

While hvm_start_info structure (PVH native) has a magic at the start,
multiboot protocol set it in separate register (eax), which doesn't
survive until platform_init.
Add an early sanity check while both magic values are available,
otherwise boot structures parsing will blow up.
Multiboot header needs to be in the first 8k of the file.
@xaki23
Copy link

xaki23 commented Nov 8, 2020

tested with a qubes-builder build of mirage-firewall.
build works.
kernel binary starts in both "direct xen" and "via grub" modes.
basic firewall functionality works in both modes.

minor confusion about memory-limits (maxmem setting actualy "works" now), but thats just "different" (compared to minios-pv), not "wrong".

Copy link
Member

@mato mato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants