Skip to content

Commit

Permalink
Xen bindings
Browse files Browse the repository at this point in the history
These are minimal bindings to Xen, for x86_64 only. The purpose of these
bindings is primarily to serve as a replacement for Mini-OS in the
MirageOS Xen platform stack. As such, no network or block device support
is implemeted and the related Solo5 APIs are stubbed out.

Only the Xen PVH v2 ABI is supported. This is available from Xen 4.10
onwards.

Being based off the existing virtio bindings, page table setup is
entirely static, but is extended to a 4GB identity map in order to be
able to access Xen PV device rings which the hypervisor places at the
top of memory below the 4GB mark.

Like virtio, all pages are marked RWX for now. This will be addressed in
later changes.

In order for MirageOS to be able to interface directly with Xen while
still using Solo5 for early boot, a number of private ABIs are
introduced:

1. The location of the hypercall page is exported using
   the solo5__xen_HYPERCALL_PAGE symbol.
2. The location of the shared_info page is exported using
   the solo5__xen_HYPERVISOR_SHARED_INFO symbol.
3. The event channel upcall from Xen may be overriden by
   providing a strong symbol for solo5__xen_evtchn_vector_handler.

These private ABIs are exclusively for the use of MirageOS, and may
change or go away entirely at any time.
  • Loading branch information
mato committed Jun 4, 2020
1 parent 978e504 commit f4b47d1
Show file tree
Hide file tree
Showing 31 changed files with 4,693 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ tests/*/*.spt
tests/*/*.virtio
tests/*/*.muen
tests/*/*.genode
tests/*/*.xen
tests/*/*.xl
tests/*/manifest.c
tenders/hvt/solo5-hvt
tenders/hvt/solo5-hvt-debug
Expand Down
5 changes: 3 additions & 2 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2015-2019 Contributors as noted in the AUTHORS file
# Copyright (c) 2015-2020 Contributors as noted in the AUTHORS file
#
# This file is part of Solo5, a sandboxed execution environment.
#
Expand Down Expand Up @@ -73,14 +73,15 @@ $(SUBDIRS):
# Ensure that a top-level "make clean" always cleans *all* possible build
# products and not some subset dependent on the setting of $(BUILD_*).
before-clean:
$(eval export SUBOVERRIDE := CONFIG_HVT=1 CONFIG_SPT=1 CONFIG_VIRTIO=1 CONFIG_MUEN=1 CONFIG_GENODE=1)
$(eval export SUBOVERRIDE := CONFIG_HVT=1 CONFIG_SPT=1 CONFIG_VIRTIO=1 CONFIG_MUEN=1 CONFIG_GENODE=1 CONFIG_XEN=1)
clean: before-clean $(SUBDIRS)
@echo "CLEAN solo5"
$(RM) opam/solo5-bindings-hvt.pc
$(RM) opam/solo5-bindings-spt.pc
$(RM) opam/solo5-bindings-virtio.pc
$(RM) opam/solo5-bindings-muen.pc
$(RM) opam/solo5-bindings-genode.pc
$(RM) opam/solo5-bindings-xen.pc
$(RM) $(VERSION_H)

.PHONY: distclean
Expand Down
20 changes: 19 additions & 1 deletion bindings/GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2015-2019 Contributors as noted in the AUTHORS file
# Copyright (c) 2015-2020 Contributors as noted in the AUTHORS file
#
# This file is part of Solo5, a sandboxed execution environment.
#
Expand Down Expand Up @@ -59,6 +59,10 @@ muen_SRCS := muen/start.c $(common_SRCS) $(common_hvt_SRCS) \

genode_SRCS := genode/stubs.c

xen_SRCS := xen/boot.S xen/start.c $(common_SRCS) \
xen/hypercall_page.S xen/console.c xen/platform.c xen/platform_intr.c \
xen/evtchn.c xen/time.c xen/pvclock.c xen/stubs.c

CPPFLAGS+=-D__SOLO5_BINDINGS__

ifeq ($(CONFIG_ARCH), x86_64)
Expand Down Expand Up @@ -154,6 +158,20 @@ genode/solo5.lib.so: $(genode_OBJS)
all_SRCS += $(genode_SRCS)
endif

ifdef CONFIG_XEN
xen_OBJS := $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(xen_SRCS)))

xen/solo5_xen.o: $(xen_OBJS)
$(LINK.bindings)

all_TARGETS += xen/solo5_xen.o
all_OBJS += $(xen_OBJS)
all_SRCS += $(xen_SRCS)

CPPFLAGS+=-D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ \
-I$(TOPDIR)/include/xen
endif

all: $(all_TARGETS)

all_DEPS := $(patsubst %.o,%.d,$(all_OBJS))
Expand Down
73 changes: 73 additions & 0 deletions bindings/xen/bindings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2015-2020 Contributors as noted in the AUTHORS file
*
* This file is part of Solo5, a sandboxed execution environment.
*
* Permission to use, copy, modify, and/or distribute this software
* for any purpose with or without fee is hereby granted, provided
* that the above copyright notice and this permission notice appear
* in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/*
* bindings.h: Solo5 bindings, Xen implementation additions.
*
* This header file includes (supersedes) the common bindings.h for the Xen
* implementation.
*/

#ifndef __XEN_BINDINGS_H__
#define __XEN_BINDINGS_H__

#include "../bindings.h"
#include "elf_abi.h"

#include "xen/xen.h"
#include "xen/event_channel.h"

/* console.c: Xen console */
void console_init(void);
void console_write(const char *, size_t);

/* pvclock.c: Xen paravirtualized clock */
int pvclock_init(void);
uint64_t pvclock_monotonic(void);
uint64_t pvclock_epochoffset(void);

/* time.c: Timekeeping */
void time_init(void);

/* evtchn.c: Xen event channel interface */
typedef void(*evtchn_handler_fn_t)(evtchn_port_t, void *);

void evtchn_init(void);
void evtchn_register_handler(evtchn_port_t, evtchn_handler_fn_t, void *);
evtchn_port_t evtchn_bind_virq(uint32_t);
void evtchn_mask(evtchn_port_t);
void evtchn_unmask(evtchn_port_t);

/* Accessors for Xen shared_info and VCPU 0 info structures shared with
* hypervisor.
*/
extern uint8_t HYPERVISOR_SHARED_INFO[];

inline struct shared_info *SHARED_INFO(void)
{
return (struct shared_info *)&HYPERVISOR_SHARED_INFO;
}

inline struct vcpu_info *VCPU0_INFO(void)
{
return &(SHARED_INFO()->vcpu_info[0]);
}

#endif /* __XEN_BINDINGS_H__ */
198 changes: 198 additions & 0 deletions bindings/xen/boot.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* Copyright (c) 2015-2020 Contributors as noted in the AUTHORS file
*
* This file is part of Solo5, a sandboxed execution environment.
*
* Permission to use, copy, modify, and/or distribute this software
* for any purpose with or without fee is hereby granted, provided
* that the above copyright notice and this permission notice appear
* in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "../cpu_x86_64.h"
#include "xen/elfnote.h"

#define ENTRY(x) .text; .globl x; .type x,%function; x:
#define END(x) .size x, . - x

/*
* Tell Xen that we are a PVH-capable kernel.
* See https://xenbits.xen.org/docs/unstable/misc/pvh.html.
*/
.section .note.solo5.xen, "a", @note

.align 4
.long 4
.long 4
.long XEN_ELFNOTE_PHYS32_ENTRY
.ascii "Xen\0"
.long _start32

.code32

/*
* Xen PVH entry point.
*
* Xen puts us only in 32bit flat protected mode, and passes a pointer to
* struct hvm_start_info in %ebx. It's our responsibility to install a page
* table and switch to long mode. Notably, we can't call C code until we've
* switched to long mode.
*/
ENTRY(_start32)
cld
movl $bootstack, %esp

/* Save Xen hvm_start_info pointer at top of stack, we pop it in 64bit */
pushl $0
pushl %ebx

/*
* Load bootstrap GDT and reload segment registers, with the exception of
* CS, which will be reloaded on jumping to _start64
*/
lgdt (gdt64_ptr)

movl $0x10, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %ss

xorl %eax, %eax
movl %eax, %fs
movl %eax, %gs

/*
* x86_64 switch to long mode
*/

/* 1: Enable PAE */
movl %cr4, %eax
orl $X86_CR4_PAE, %eax
movl %eax, %cr4

/* 2: Load PML4 pointer */
movl $cpu_pml4, %eax
movl %eax, %cr3

/* 3: Request long mode enable */
movl $0xc0000080, %ecx
rdmsr
orl $X86_EFER_LME, %eax
wrmsr

/* 4a: Enable paging */
movl %cr0, %eax
orl $X86_CR0_PG, %eax

/* 4b: CPU sets long mode enabled after this instruction */
movl %eax, %cr0

/* 5: Reload CS with a 64-bit selector */
pushw $0x08
pushl $_start64
lret

/* NOTREACHED */
jmp haltme

haltme:
cli
hlt
jmp haltme
END(_start32)

.code64

ENTRY(_start64)
movq $bootstack, %rsp
xorq %rbp, %rbp

/* Enable FPU and SSE units */
movq %cr0, %rax
andq $(~X86_CR0_EM), %rax
orq $(X86_CR0_MP | X86_CR0_NE), %rax
movq %rax, %cr0
movq %cr4, %rax
orq $(X86_CR4_OSXMMEXCPT | X86_CR4_OSFXSR), %rax
movq %rax, %cr4
ldmxcsr (mxcsr_ptr)

/* Read Xen hvm_start_info pointer */
movq -8(%rsp), %rdi

/* Call into C with correct start-of-day stack alignment */
pushq $0x0
pushq $0x0
call _start

/* NOTREACHED */
jmp haltme
END(_start64)

/*
* void _newstack(uint64_t stack_start, void (*tramp)(void *), void *arg);
*
* Switch to a new stack at (stack_start), and transfer control to
* (*tramp)(arg).
*/
ENTRY(_newstack)
movq %rdi, %rsp
movq %rdx, %rdi

/* As above, ensure correct start-of-day stack alignment */
pushq $0x0
pushq $0x0
call *%rsi

/* NOTREACHED */
jmp haltme
END(_newstack)

.data

/*
* amd64 programmer's manual:
*
* "In long mode, segmentation is not used ... except for a few exceptions."
*
* Uuuyea, exceptions.
*
* The GDT here is used only during bootstrapping, and is reloaded by
* cpu_init().
*/

.align 64
gdt64:
.quad 0x0 /* 0: NULL selector */
.quad GDT_DESC_CODE_VAL /* 0x8: 64-bit code */
.quad GDT_DESC_DATA_VAL /* 0x10: 64-bit data */
gdt64_end:
.align 64

.type gdt64_ptr, @object
gdt64_ptr:
.word gdt64_end-gdt64-1
.quad gdt64

.type mxcsr_ptr, @object
mxcsr_ptr:
.word 0x1f80 /* Intel SDM power-on default */

#include "pagetable.S"

.section .bss

/*
* Stack used during bootstrapping, reloaded before calling _start2().
*/
.space 4096
bootstack:
Loading

0 comments on commit f4b47d1

Please sign in to comment.