Permalink
Browse files

Add support for FreeBSD guests.

  • Loading branch information...
xez committed Jun 27, 2015
1 parent 84868be commit 0e9d07db34b2d44618cf1e0f273ef199dbe82030
Showing with 3,154 additions and 55 deletions.
  1. +3 −2 Makefile
  2. +1 −7 README.md
  3. +5 −0 include/xhyve/acpi.h
  4. +102 −0 include/xhyve/firmware/fbsd.h
  5. +24 −21 include/xhyve/support/segments.h
  6. +1,076 −0 src/acpitbl.c
  7. +841 −0 src/dsdt.asl
  8. +1,006 −0 src/firmware/fbsd.c
  9. +39 −0 src/pci_emul.c
  10. +39 −25 src/xhyve.c
  11. BIN test/userboot.so
  12. +8 −0 test/userboot.txt
  13. +10 −0 xhyverun.sh
View
@@ -30,7 +30,7 @@ VMM_SRC := \
src/vmm/io/vrtc.c
XHYVE_SRC := \
- src/acpi.c \
+ src/acpitbl.c \
src/atkbdc.c \
src/block_if.c \
src/consport.c \
@@ -61,7 +61,8 @@ XHYVE_SRC := \
src/xmsr.c
FIRMWARE_SRC := \
- src/firmware/kexec.c
+ src/firmware/kexec.c \
+ src/firmware/fbsd.c
SRC := \
$(VMM_SRC) \
View
@@ -6,7 +6,7 @@
About
-----
-The *xhyve hypervisor* is a port of [bhyve](http://www.bhyve.org) to OS X. It is built on top of Hypervisor.framework in OS X 10.10 Yosemite and higher, runs entirely in userspace, and has no other dependencies. It can run vanilla Linux distributions and may gain support for other guest operating systems in the future.
+The *xhyve hypervisor* is a port of [bhyve](http://www.bhyve.org) to OS X. It is built on top of Hypervisor.framework in OS X 10.10 Yosemite and higher, runs entirely in userspace, and has no other dependencies. It can run FreeBSD and vanilla Linux distributions and may gain support for other guest operating systems in the future.
License: BSD
@@ -184,12 +184,6 @@ TODO
- make it not require root
- unify TAP and vmnet backends
- performance: send/receive more than a single packet at a time
-- ACPI tables don't work
- - bhyve creates ASL on the fly and then calls out to an ASL compiler (iasl) on
- every VM boot to create the DSDT:
- - remove dependency on iasl by creating AML bytecode directly
- - shouldn't be to hard since we we are only interested in a very small
- subset of ASL
- virtio_rnd:
- is untested
- remove explicit state transitions:
View
@@ -30,6 +30,9 @@
#include <stdint.h>
+/* if set, create AML instead of ASL and calling out to iasl */
+#define ACPITBL_AML 1
+
#define SCI_INT 9
#define SMI_CMD 0xb2
@@ -49,4 +52,6 @@ void dsdt_fixed_irq(uint8_t irq);
void dsdt_fixed_mem32(uint32_t base, uint32_t length);
void dsdt_indent(int levels);
void dsdt_unindent(int levels);
+void dsdt_fixup(int bus, uint16_t iobase, uint16_t iolimit, uint32_t membase32,
+ uint32_t memlimit32, uint64_t membase64, uint64_t memlimit64);
void sci_init(void);
@@ -0,0 +1,102 @@
+#pragma once
+
+#include <stdint.h>
+
+/*
+ * USERBOOT interface versions
+ */
+#define USERBOOT_VERSION_1 1
+#define USERBOOT_VERSION_2 2
+#define USERBOOT_VERSION_3 3
+
+/*
+ * Exit codes from the loader
+ */
+#define USERBOOT_EXIT_QUIT 1
+#define USERBOOT_EXIT_REBOOT 2
+
+struct loader_callbacks {
+ /* Console i/o */
+
+ /* Wait until a key is pressed on the console and then return it */
+ int (*getc)(void *arg);
+ /* Write the character ch to the console */
+ void (*putc)(void *arg, int ch);
+ /* Return non-zero if a key can be read from the console */
+ int (*poll)(void *arg);
+
+ /* Host filesystem i/o */
+
+ /* Open a file in the host filesystem */
+ int (*open)(void *arg, const char *filename, void **h_return);
+ /* Close a file */
+ int (*close)(void *arg, void *h);
+ /* Return non-zero if the file is a directory */
+ int (*isdir)(void *arg, void *h);
+ /* Read size bytes from a file. The number of bytes remaining in dst after
+ * reading is returned in *resid_return
+ */
+ int (*read)(void *arg, void *h, void *dst, size_t size,
+ size_t *resid_return);
+ /* Read an entry from a directory. The entry's inode number is returned in
+ * fileno_return, its type in *type_return and the name length in
+ * *namelen_return. The name itself is copied to the buffer name which must
+ * be at least PATH_MAX in size.
+ */
+ int (*readdir)(void *arg, void *h, uint32_t *fileno_return,
+ uint8_t *type_return, size_t *namelen_return, char *name);
+ /* Seek to a location within an open file */
+ int (*seek)(void *arg, void *h, uint64_t offset, int whence);
+ /* Return some stat(2) related information about the file */
+ int (*stat)(void *arg, void *h, int *mode_return, int *uid_return,
+ int *gid_return, uint64_t *size_return);
+
+ /* Disk image i/o */
+
+ /* Read from a disk image at the given offset */
+ int (*diskread)(void *arg, int unit, uint64_t offset, void *dst,
+ size_t size, size_t *resid_return);
+
+ /* Guest virtual machine i/o */
+
+ /* Copy to the guest address space */
+ int (*copyin)(void *arg, const void *from, uint64_t to, size_t size);
+ /* Copy from the guest address space */
+ int (*copyout)(void *arg, uint64_t from, void *to, size_t size);
+ /* Set a guest register value */
+ void (*setreg)(void *arg, int, uint64_t);
+ /* Set a guest MSR value */
+ void (*setmsr)(void *arg, int, uint64_t);
+ /* Set a guest CR value */
+ void (*setcr)(void *arg, int, uint64_t);
+ /* Set the guest GDT address */
+ void (*setgdt)(void *arg, uint64_t, size_t);
+ /* Transfer control to the guest at the given address */
+ void (*exec)(void *arg, uint64_t pc);
+
+ /* Misc */
+
+ /* Sleep for usec microseconds */
+ void (*delay)(void *arg, int usec);
+ /* Exit with the given exit code */
+ void (*exit)(void);
+ /* Return guest physical memory map details */
+ void (*getmem)(void *arg, uint64_t *lowmem, uint64_t *highmem);
+ /* ioctl interface to the disk device */
+ int (*diskioctl)(void *arg, int unit, u_long cmd, void *data);
+ /*
+ * Returns an environment variable in the form "name=value".
+ *
+ * If there are no more variables that need to be set in the
+ * loader environment then return NULL.
+ *
+ * 'num' is used as a handle for the callback to identify which
+ * environment variable to return next. It will begin at 0 and
+ * each invocation will add 1 to the previous value of 'num'.
+ */
+ const char * (*getenv)(void *arg, int num);
+};
+
+void fbsd_init(char *userboot_path, char *bootvolume_path, char *kernelenv,
+ char *cons);
+uint64_t fbsd_load(void);
@@ -54,23 +54,26 @@
#define LSEL(s,r) (((s)<<3) | SEL_LDT | r) /* a local selector */
#define GSEL(s,r) (((s)<<3) | r) /* a global selector */
-// /*
-// * User segment descriptors (%cs, %ds etc for i386 apps. 64 bit wide)
-// * For long-mode apps, %cs only has the conforming bit in sd_type, the sd_dpl,
-// * sd_p, sd_l and sd_def32 which must be zero). %ds only has sd_p.
-// */
-// struct segment_descriptor {
-// unsigned sd_lolimit:16; /* segment extent (lsb) */
-// unsigned sd_lobase:24; /* segment base address (lsb) */
-// unsigned sd_type:5; /* segment type */
-// unsigned sd_dpl:2; /* segment descriptor priority level */
-// unsigned sd_p:1; /* segment descriptor present */
-// unsigned sd_hilimit:4; /* segment extent (msb) */
-// unsigned sd_xx:2; /* unused */
-// unsigned sd_def32:1; /* default 32 vs 16 bit size */
-// unsigned sd_gran:1; /* limit granularity (byte/page units)*/
-// unsigned sd_hibase:8; /* segment base address (msb) */
-// } __packed;
+/*
+ * User segment descriptors (%cs, %ds etc for i386 apps. 64 bit wide)
+ * For long-mode apps, %cs only has the conforming bit in sd_type, the sd_dpl,
+ * sd_p, sd_l and sd_def32 which must be zero). %ds only has sd_p.
+ */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpacked"
+struct segment_descriptor {
+ unsigned sd_lolimit:16; /* segment extent (lsb) */
+ unsigned sd_lobase:24; /* segment base address (lsb) */
+ unsigned sd_type:5; /* segment type */
+ unsigned sd_dpl:2; /* segment descriptor priority level */
+ unsigned sd_p:1; /* segment descriptor present */
+ unsigned sd_hilimit:4; /* segment extent (msb) */
+ unsigned sd_xx:2; /* unused */
+ unsigned sd_def32:1; /* default 32 vs 16 bit size */
+ unsigned sd_gran:1; /* limit granularity (byte/page units)*/
+ unsigned sd_hibase:8; /* segment base address (msb) */
+} __packed;
+#pragma clang diagnostic pop
struct user_segment_descriptor {
uint64_t sd_lolimit:16; /* segment extent (lsb) */
@@ -167,16 +170,16 @@ struct user_segment_descriptor {
// /* memory segment types */
// #define SDT_MEMRO 16 memory read only
// #define SDT_MEMROA 17 /* memory read only accessed */
-// #define SDT_MEMRW 18 /* memory read write */
-// #define SDT_MEMRWA 19 /* memory read write accessed */
+#define SDT_MEMRW 18 /* memory read write */
+#define SDT_MEMRWA 19 /* memory read write accessed */
// #define SDT_MEMROD 20 /* memory read only expand dwn limit */
// #define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */
// #define SDT_MEMRWD 22 /* memory read write expand dwn limit */
// #define SDT_MEMRWDA 23 /* memory read write expand dwn limit accessed*/
// #define SDT_MEME 24 /* memory execute only */
// #define SDT_MEMEA 25 /* memory execute only accessed */
-// #define SDT_MEMER 26 /* memory execute read */
-// #define SDT_MEMERA 27 /* memory execute read accessed */
+#define SDT_MEMER 26 /* memory execute read */
+#define SDT_MEMERA 27 /* memory execute read accessed */
// #define SDT_MEMEC 28 /* memory execute only conforming */
// #define SDT_MEMEAC 29 /* memory execute only accessed conforming */
// #define SDT_MEMERC 30 /* memory execute read conforming */
Oops, something went wrong.

1 comment on commit 0e9d07d

@exdrunmeswt

This comment has been minimized.

Show comment
Hide comment

#0e9d07d

Please sign in to comment.