From owner-svn-src-user@FreeBSD.ORG Sun Aug 4 19:17:07 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id AF95822C; Sun, 4 Aug 2013 19:17:07 +0000 (UTC) (envelope-from syuu@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 9AF582518; Sun, 4 Aug 2013 19:17:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r74JH7AJ063784; Sun, 4 Aug 2013 19:17:07 GMT (envelope-from syuu@svn.freebsd.org) Received: (from syuu@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r74JH6BZ063779; Sun, 4 Aug 2013 19:17:06 GMT (envelope-from syuu@svn.freebsd.org) Message-Id: <201308041917.r74JH6BZ063779@svn.freebsd.org> From: Takuya ASADA Date: Sun, 4 Aug 2013 19:17:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r253935 - user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 04 Aug 2013 19:17:07 -0000 Author: syuu Date: Sun Aug 4 19:17:06 2013 New Revision: 253935 URL: http://svnweb.freebsd.org/changeset/base/253935 Log: support '-S' option for standalone guest program Added: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/standalone.c Modified: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/Makefile user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.8 user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c Modified: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/Makefile ============================================================================== --- user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/Makefile Sun Aug 4 18:20:53 2013 (r253934) +++ user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/Makefile Sun Aug 4 19:17:06 2013 (r253935) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= bhyveload -SRCS= bhyveload.c +SRCS= bhyveload.c standalone.c MAN= bhyveload.8 DPADD+= ${LIBVMMAPI} Modified: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.8 ============================================================================== --- user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.8 Sun Aug 4 18:20:53 2013 (r253934) +++ user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.8 Sun Aug 4 19:17:06 2013 (r253935) @@ -38,6 +38,7 @@ guest inside a bhyve virtual machine .Op Fl m Ar mem-size .Op Fl d Ar disk-path .Op Fl h Ar host-path +.Op Fl S Ar stand-binary:stand-addr .Ar vmname .Sh DESCRIPTION .Nm @@ -75,6 +76,13 @@ is the pathname of the guest's boot disk The .Ar host-path is the directory at the top of the guest's boot filesystem. +.It Fl S Ar stand-binary:stand-addr +The +.Ar stand-binary +is the pathname of the standalone guest program. +The +.Ar stand-addr +is the entrypoint address of the standalone guest program. .El .Sh EXAMPLES To create a virtual machine named Modified: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c ============================================================================== --- user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c Sun Aug 4 18:20:53 2013 (r253934) +++ user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c Sun Aug 4 19:17:06 2013 (r253935) @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -76,8 +75,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include @@ -98,6 +95,9 @@ static uint64_t gdtbase, cr3, rsp; static void cb_exit(void *arg, int v); +extern int stand_load(struct loader_callbacks *cb, char *image, + uint64_t addr); + /* * Console i/o callbacks */ @@ -555,152 +555,16 @@ usage(void) fprintf(stderr, "usage: %s [-m mem-size][-d ] [-h ] " + "[-S stand-binary:stand-addr] " "\n", progname); exit(1); } -#define MSR_EFER 0xc0000080 -#define CR4_PAE 0x00000020 -#define CR4_PSE 0x00000010 -#define CR0_PG 0x80000000 -#define CR0_PE 0x00000001 /* Protected mode Enable */ -#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ - -#define PG_V 0x001 -#define PG_RW 0x002 -#define PG_U 0x004 -#define PG_PS 0x080 - -typedef u_int64_t p4_entry_t; -typedef u_int64_t p3_entry_t; -typedef u_int64_t p2_entry_t; - -#define GUEST_NULL_SEL 0 -#define GUEST_CODE_SEL 1 -#define GUEST_DATA_SEL 2 -#define GUEST_GDTR_LIMIT (3 * 8 - 1) - -static void -setup_stand_gdt(uint64_t *gdtr) -{ - gdtr[GUEST_NULL_SEL] = 0; - gdtr[GUEST_CODE_SEL] = 0x0020980000000000; - gdtr[GUEST_DATA_SEL] = 0x0000900000000000; -} - -static int -stand_load(char *image, uint64_t addr) -{ - int i; - int fd; - struct stat sb; - char *buf; - uint32_t stack[1024]; - p4_entry_t PT4[512]; - p3_entry_t PT3[512]; - p2_entry_t PT2[512]; - uint64_t gdtr[3]; - - if ((fd = open(image, O_RDONLY)) < 0) { - perror("open"); - return (1); - } - if (fstat(fd, &sb)) { - perror("fstat"); - return (1); - } - buf = alloca(sb.st_size); - if (read(fd, buf, sb.st_size) != sb.st_size) { - perror("read"); - return (1); - } - if (close(fd) < 0) { - perror("close"); - return (1); - } - if (cb_copyin(NULL, buf, addr, sb.st_size)) { - perror("copyin"); - return (1); - } - - bzero(PT4, PAGE_SIZE); - bzero(PT3, PAGE_SIZE); - bzero(PT2, PAGE_SIZE); - - /* - * Build a scratch stack at physical 0x1000, page tables: - * PT4 at 0x2000, - * PT3 at 0x3000, - * PT2 at 0x4000, - * gdtr at 0x5000, - */ - - /* - * This is kinda brutal, but every single 1GB VM memory segment - * points to the same first 1GB of physical memory. But it is - * more than adequate. - */ - for (i = 0; i < 512; i++) { - /* Each slot of the level 4 pages points to the same level 3 page */ - PT4[i] = (p4_entry_t) 0x3000; - PT4[i] |= PG_V | PG_RW | PG_U; - - /* Each slot of the level 3 pages points to the same level 2 page */ - PT3[i] = (p3_entry_t) 0x4000; - PT3[i] |= PG_V | PG_RW | PG_U; - - /* The level 2 page slots are mapped with 2MB pages for 1GB. */ - PT2[i] = i * (2 * 1024 * 1024); - PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; - } - -#ifdef DEBUG - printf("Start @ %#llx ...\n", addr); -#endif - - cb_copyin(NULL, stack, 0x1000, sizeof(stack)); - cb_copyin(NULL, PT4, 0x2000, sizeof(PT4)); - cb_copyin(NULL, PT3, 0x3000, sizeof(PT3)); - cb_copyin(NULL, PT2, 0x4000, sizeof(PT2)); - cb_setreg(NULL, 4, 0x1000); - - cb_setmsr(NULL, MSR_EFER, EFER_LMA | EFER_LME); - cb_setcr(NULL, 4, CR4_PAE | CR4_VMXE); - cb_setcr(NULL, 3, 0x2000); - cb_setcr(NULL, 0, CR0_PG | CR0_PE | CR0_NE); - - setup_stand_gdt(gdtr); - cb_copyin(NULL, gdtr, 0x5000, sizeof(gdtr)); - cb_setgdt(NULL, 0x5000, sizeof(gdtr)); - - cb_exec(NULL, addr); - return (0); -} - -static int -freebsd_load(void) -{ - void *h; - void (*func)(struct loader_callbacks *, void *, int, int); - - h = dlopen("/boot/userboot.so", RTLD_LOCAL); - if (!h) { - printf("%s\n", dlerror()); - return (1); - } - func = dlsym(h, "loader_main"); - if (!func) { - printf("%s\n", dlerror()); - return (1); - } - - func(&cb, NULL, USERBOOT_VERSION_3, disk_fd >= 0); - return (0); -} - int main(int argc, char** argv) { + void *h; + void (*func)(struct loader_callbacks *, void *, int, int); uint64_t mem_size; int opt, error; uint64_t stand_addr; @@ -712,7 +576,7 @@ main(int argc, char** argv) mem_size = 256 * MB; disk_image = NULL; - while ((opt = getopt(argc, argv, "d:h:m:S:I:")) != -1) { + while ((opt = getopt(argc, argv, "d:h:m:S:")) != -1) { switch (opt) { case 'd': disk_image = optarg; @@ -744,7 +608,7 @@ main(int argc, char** argv) break; } - + case '?': usage(); } @@ -782,16 +646,24 @@ main(int argc, char** argv) term.c_lflag &= ~(ICANON|ECHO); term.c_iflag &= ~ICRNL; tcsetattr(0, TCSAFLUSH, &term); + if (stand_image) { + if (stand_load(&cb, stand_image, stand_addr)) + exit(1); + exit(0); + } + h = dlopen("/boot/userboot.so", RTLD_LOCAL); + if (!h) { + printf("%s\n", dlerror()); + return (1); + } + func = dlsym(h, "loader_main"); + if (!func) { + printf("%s\n", dlerror()); + return (1); + } if (disk_image) { disk_fd = open(disk_image, O_RDONLY); } - - if (stand_image) { - if (stand_load(stand_image, stand_addr)) - exit(1); - }else{ - if (freebsd_load()) - exit(1); - } + func(&cb, NULL, USERBOOT_VERSION_3, disk_fd >= 0); } Added: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/standalone.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/standalone.c Sun Aug 4 19:17:06 2013 (r253935) @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c 253922 2013-08-04 01:22:26Z syuu $ + */ + +/*- + * Copyright (c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c 253922 2013-08-04 01:22:26Z syuu $ + */ + +#include +__FBSDID("$FreeBSD: user/syuu/bhyve_standalone_guest/usr.sbin/bhyveload/bhyveload.c 253922 2013-08-04 01:22:26Z syuu $"); + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "userboot.h" + +#define MSR_EFER 0xc0000080 +#define CR4_PAE 0x00000020 +#define CR4_PSE 0x00000010 +#define CR0_PG 0x80000000 +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ + +#define PG_V 0x001 +#define PG_RW 0x002 +#define PG_U 0x004 +#define PG_PS 0x080 + +typedef u_int64_t p4_entry_t; +typedef u_int64_t p3_entry_t; +typedef u_int64_t p2_entry_t; + +#define GUEST_NULL_SEL 0 +#define GUEST_CODE_SEL 1 +#define GUEST_DATA_SEL 2 +#define GUEST_GDTR_LIMIT (3 * 8 - 1) + +int stand_load(struct loader_callbacks *cb, char *image, uint64_t addr); + +static void +setup_stand_gdt(uint64_t *gdtr) +{ + gdtr[GUEST_NULL_SEL] = 0; + gdtr[GUEST_CODE_SEL] = 0x0020980000000000; + gdtr[GUEST_DATA_SEL] = 0x0000900000000000; +} + +int +stand_load(struct loader_callbacks *cb, char *image, uint64_t addr) +{ + int i; + int fd; + struct stat sb; + char *buf; + uint32_t stack[1024]; + p4_entry_t PT4[512]; + p3_entry_t PT3[512]; + p2_entry_t PT2[512]; + uint64_t gdtr[3]; + + if ((fd = open(image, O_RDONLY)) < 0) { + perror("open"); + return (1); + } + if (fstat(fd, &sb)) { + perror("fstat"); + return (1); + } + buf = alloca(sb.st_size); + if (read(fd, buf, sb.st_size) != sb.st_size) { + perror("read"); + return (1); + } + if (close(fd) < 0) { + perror("close"); + return (1); + } + if (cb->copyin(NULL, buf, addr, sb.st_size)) { + perror("copyin"); + return (1); + } + + bzero(PT4, PAGE_SIZE); + bzero(PT3, PAGE_SIZE); + bzero(PT2, PAGE_SIZE); + + /* + * Build a scratch stack at physical 0x1000, page tables: + * PT4 at 0x2000, + * PT3 at 0x3000, + * PT2 at 0x4000, + * gdtr at 0x5000, + */ + + /* + * This is kinda brutal, but every single 1GB VM memory segment + * points to the same first 1GB of physical memory. But it is + * more than adequate. + */ + for (i = 0; i < 512; i++) { + /* Each slot of the level 4 pages points to the same level 3 page */ + PT4[i] = (p4_entry_t) 0x3000; + PT4[i] |= PG_V | PG_RW | PG_U; + + /* Each slot of the level 3 pages points to the same level 2 page */ + PT3[i] = (p3_entry_t) 0x4000; + PT3[i] |= PG_V | PG_RW | PG_U; + + /* The level 2 page slots are mapped with 2MB pages for 1GB. */ + PT2[i] = i * (2 * 1024 * 1024); + PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; + } + +#ifdef DEBUG + printf("Start @ %#llx ...\n", addr); +#endif + + cb->copyin(NULL, stack, 0x1000, sizeof(stack)); + cb->copyin(NULL, PT4, 0x2000, sizeof(PT4)); + cb->copyin(NULL, PT3, 0x3000, sizeof(PT3)); + cb->copyin(NULL, PT2, 0x4000, sizeof(PT2)); + cb->setreg(NULL, 4, 0x1000); + + cb->setmsr(NULL, MSR_EFER, EFER_LMA | EFER_LME); + cb->setcr(NULL, 4, CR4_PAE | CR4_VMXE); + cb->setcr(NULL, 3, 0x2000); + cb->setcr(NULL, 0, CR0_PG | CR0_PE | CR0_NE); + + setup_stand_gdt(gdtr); + cb->copyin(NULL, gdtr, 0x5000, sizeof(gdtr)); + cb->setgdt(NULL, 0x5000, sizeof(gdtr)); + + cb->exec(NULL, addr); + return (0); +} +