예제 #1
0
int
main(int argc, char *argv[])
{
	int c, error, gdb_port, err, bvmcons;
	int dump_guest_memory, max_vcpus, mptgen;
	int rtc_localtime;
	struct vmctx *ctx;
	uint64_t rip;
	size_t memsize;

	bvmcons = 0;
	dump_guest_memory = 0;
	progname = basename(argv[0]);
	gdb_port = 0;
	guest_ncpus = 1;
	memsize = 256 * MB;
	mptgen = 1;
	rtc_localtime = 1;

	while ((c = getopt(argc, argv, "abehuwxACHIPWYp:g:c:s:m:l:U:")) != -1) {
		switch (c) {
		case 'a':
			x2apic_mode = 0;
			break;
		case 'A':
			acpi = 1;
			break;
		case 'b':
			bvmcons = 1;
			break;
		case 'p':
                        if (pincpu_parse(optarg) != 0) {
                            errx(EX_USAGE, "invalid vcpu pinning "
                                 "configuration '%s'", optarg);
                        }
			break;
                case 'c':
			guest_ncpus = atoi(optarg);
			break;
		case 'C':
			dump_guest_memory = 1;
			break;
		case 'g':
			gdb_port = atoi(optarg);
			break;
		case 'l':
			if (lpc_device_parse(optarg) != 0) {
				errx(EX_USAGE, "invalid lpc device "
				    "configuration '%s'", optarg);
			}
			break;
		case 's':
			if (pci_parse_slot(optarg) != 0)
				exit(1);
			else
				break;
                case 'm':
			error = vm_parse_memsize(optarg, &memsize);
			if (error)
				errx(EX_USAGE, "invalid memsize '%s'", optarg);
			break;
		case 'H':
			guest_vmexit_on_hlt = 1;
			break;
		case 'I':
			/*
			 * The "-I" option was used to add an ioapic to the
			 * virtual machine.
			 *
			 * An ioapic is now provided unconditionally for each
			 * virtual machine and this option is now deprecated.
			 */
			break;
		case 'P':
			guest_vmexit_on_pause = 1;
			break;
		case 'e':
			strictio = 1;
			break;
		case 'u':
			rtc_localtime = 0;
			break;
		case 'U':
			guest_uuid_str = optarg;
			break;
		case 'w':
			strictmsr = 0;
			break;
		case 'W':
			virtio_msix = 0;
			break;
		case 'x':
			x2apic_mode = 1;
			break;
		case 'Y':
			mptgen = 0;
			break;
		case 'h':
			usage(0);			
		default:
			usage(1);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		usage(1);

	vmname = argv[0];

	ctx = vm_open(vmname);
	if (ctx == NULL) {
		perror("vm_open");
		exit(1);
	}

	if (guest_ncpus < 1) {
		fprintf(stderr, "Invalid guest vCPUs (%d)\n", guest_ncpus);
		exit(1);
	}

	max_vcpus = num_vcpus_allowed(ctx);
	if (guest_ncpus > max_vcpus) {
		fprintf(stderr, "%d vCPUs requested but only %d available\n",
			guest_ncpus, max_vcpus);
		exit(1);
	}

	fbsdrun_set_capabilities(ctx, BSP);

	if (dump_guest_memory)
		vm_set_memflags(ctx, VM_MEM_F_INCORE);
	err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
	if (err) {
		fprintf(stderr, "Unable to setup memory (%d)\n", err);
		exit(1);
	}

	error = init_msr();
	if (error) {
		fprintf(stderr, "init_msr error %d", error);
		exit(1);
	}

	init_mem();
	init_inout();
	pci_irq_init(ctx);
	ioapic_init(ctx);

	rtc_init(ctx, rtc_localtime);
	sci_init(ctx);

	/*
	 * Exit if a device emulation finds an error in it's initilization
	 */
	if (init_pci(ctx) != 0)
		exit(1);

	if (gdb_port != 0)
		init_dbgport(gdb_port);

	if (bvmcons)
		init_bvmcons();

	error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
	assert(error == 0);

	/*
	 * build the guest tables, MP etc.
	 */
	if (mptgen) {
		error = mptable_build(ctx, guest_ncpus);
		if (error)
			exit(1);
	}

	error = smbios_build(ctx);
	assert(error == 0);

	if (acpi) {
		error = acpi_build(ctx, guest_ncpus);
		assert(error == 0);
	}

	/*
	 * Change the proc title to include the VM name.
	 */
	setproctitle("%s", vmname); 
	
	/*
	 * Add CPU 0
	 */
	fbsdrun_addcpu(ctx, BSP, BSP, rip);

	/*
	 * Head off to the main event dispatch loop
	 */
	mevent_dispatch();

	exit(1);
}
예제 #2
0
int
grub_emu_bhyve_init(const char *name, grub_uint64_t memsz)
{
  int err;
  int val;
  grub_uint64_t lomemsz;
#ifdef VMMAPI_VERSION
  int need_reinit = 0;
#endif

  err = vm_create (name);
  if (err != 0)
    {
      if (errno != EEXIST)
        {
          fprintf (stderr, "Could not create VM %s\n", name);
          return GRUB_ERR_ACCESS_DENIED;
        }
#ifdef VMMAPI_VERSION
        need_reinit = 1;
#endif
    }

  bhyve_ctx = vm_open (name);
  if (bhyve_ctx == NULL)
    {
      fprintf (stderr, "Could not open VM %s\n", name);
      return GRUB_ERR_BUG;
    }

#ifdef VMMAPI_VERSION
  if (need_reinit)
    {
      err = vm_reinit (bhyve_ctx);
      if (err != 0)
        {
          fprintf (stderr, "Could not reinit VM %s\n", name);
          return GRUB_ERR_BUG;
        }
    }
#endif

  val = 0;
  err = vm_get_capability (bhyve_ctx, 0, VM_CAP_UNRESTRICTED_GUEST, &val);
  if (err != 0)
    {
      fprintf (stderr, "VM unrestricted guest capability required\n");
      return GRUB_ERR_BAD_DEVICE;
    }

  err = vm_set_capability (bhyve_ctx, 0, VM_CAP_UNRESTRICTED_GUEST, 1);
  if (err != 0)
    {
      fprintf (stderr, "Could not enable unrestricted guest for VM\n");
      return GRUB_ERR_BUG;
    }

#ifdef VM_MEM_F_WIRED
  if (bhyve_memwire)
    {
      vm_set_memflags(bhyve_ctx, VM_MEM_F_WIRED);
    }
#endif

  err = vm_setup_memory (bhyve_ctx, memsz, VM_MMAP_ALL);
  if (err) {
    fprintf (stderr, "Could not setup memory for VM\n");
    return GRUB_ERR_OUT_OF_MEMORY;
  }

  lomemsz = vm_get_lowmem_limit(bhyve_ctx);

  /*
   * Extract the virtual address of the mapped guest memory.
   */
  if (memsz >= lomemsz) {
    bhyve_g2h.lomem = lomemsz;
    bhyve_g2h.himem = memsz - lomemsz;
    bhyve_g2h.himem_ptr = vm_map_gpa(bhyve_ctx, 4*GB, bhyve_g2h.himem);
  } else {
    bhyve_g2h.lomem = memsz;
    bhyve_g2h.himem = 0;    
  }
  bhyve_g2h.lomem_ptr = vm_map_gpa(bhyve_ctx, 0, bhyve_g2h.lomem);

  /*
   * bhyve is going to return the following memory segments
   *
   * 0 - 640K    - usable
   * 640K- 1MB   - vga hole, BIOS, not usable.
   * 1MB - lomem - usable
   * lomem - 4G  - not usable
   * 4G - himem  - usable [optional if himem != 0]
   */
  bhyve_info.nsegs = 2;
  bhyve_info.segs = bhyve_mm;

  bhyve_mm[0].start = 0x0;
  bhyve_mm[0].end = 640*1024 - 1;		/* 640K */
  bhyve_mm[0].type = GRUB_MEMORY_AVAILABLE;

  bhyve_mm[1].start = 1024*1024;
  bhyve_mm[1].end = (memsz > lomemsz) ? lomemsz : memsz;
  bhyve_mm[1].type = GRUB_MEMORY_AVAILABLE;

  if (memsz > lomemsz) {
    bhyve_info.nsegs++;
    bhyve_mm[2].start = 4*GB;
    bhyve_mm[2].end = (memsz - lomemsz) + bhyve_mm[2].start;
    bhyve_mm[2].type = GRUB_MEMORY_AVAILABLE;
  }

  /* The boot-code size is just the GDT that needs to be copied */
  bhyve_info.bootsz = sizeof(bhyve_gdt);

  return 0;
}
예제 #3
0
int
main(int argc, char *argv[])
{
	int c, error, dbg_port, gdb_port, err, bvmcons;
	int max_vcpus, mptgen, memflags;
	int rtc_localtime;
	bool gdb_stop;
	struct vmctx *ctx;
	uint64_t rip;
	size_t memsize;
	char *optstr;

	bvmcons = 0;
	progname = basename(argv[0]);
	dbg_port = 0;
	gdb_port = 0;
	gdb_stop = false;
	guest_ncpus = 1;
	sockets = cores = threads = 1;
	maxcpus = 0;
	memsize = 256 * MB;
	mptgen = 1;
	rtc_localtime = 1;
	memflags = 0;

	optstr = "abehuwxACHIPSWYp:g:G:c:s:m:l:U:";
	while ((c = getopt(argc, argv, optstr)) != -1) {
		switch (c) {
		case 'a':
			x2apic_mode = 0;
			break;
		case 'A':
			acpi = 1;
			break;
		case 'b':
			bvmcons = 1;
			break;
		case 'p':
                        if (pincpu_parse(optarg) != 0) {
                            errx(EX_USAGE, "invalid vcpu pinning "
                                 "configuration '%s'", optarg);
                        }
			break;
                case 'c':
			if (topology_parse(optarg) != 0) {
			    errx(EX_USAGE, "invalid cpu topology "
				"'%s'", optarg);
			}
			break;
		case 'C':
			memflags |= VM_MEM_F_INCORE;
			break;
		case 'g':
			dbg_port = atoi(optarg);
			break;
		case 'G':
			if (optarg[0] == 'w') {
				gdb_stop = true;
				optarg++;
			}
			gdb_port = atoi(optarg);
			break;
		case 'l':
			if (lpc_device_parse(optarg) != 0) {
				errx(EX_USAGE, "invalid lpc device "
				    "configuration '%s'", optarg);
			}
			break;
		case 's':
			if (pci_parse_slot(optarg) != 0)
				exit(1);
			else
				break;
		case 'S':
			memflags |= VM_MEM_F_WIRED;
			break;
                case 'm':
			error = vm_parse_memsize(optarg, &memsize);
			if (error)
				errx(EX_USAGE, "invalid memsize '%s'", optarg);
			break;
		case 'H':
			guest_vmexit_on_hlt = 1;
			break;
		case 'I':
			/*
			 * The "-I" option was used to add an ioapic to the
			 * virtual machine.
			 *
			 * An ioapic is now provided unconditionally for each
			 * virtual machine and this option is now deprecated.
			 */
			break;
		case 'P':
			guest_vmexit_on_pause = 1;
			break;
		case 'e':
			strictio = 1;
			break;
		case 'u':
			rtc_localtime = 0;
			break;
		case 'U':
			guest_uuid_str = optarg;
			break;
		case 'w':
			strictmsr = 0;
			break;
		case 'W':
			virtio_msix = 0;
			break;
		case 'x':
			x2apic_mode = 1;
			break;
		case 'Y':
			mptgen = 0;
			break;
		case 'h':
			usage(0);			
		default:
			usage(1);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		usage(1);

	vmname = argv[0];
	ctx = do_open(vmname);

	max_vcpus = num_vcpus_allowed(ctx);
	if (guest_ncpus > max_vcpus) {
		fprintf(stderr, "%d vCPUs requested but only %d available\n",
			guest_ncpus, max_vcpus);
		exit(1);
	}

	fbsdrun_set_capabilities(ctx, BSP);

	vm_set_memflags(ctx, memflags);
	err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
	if (err) {
		fprintf(stderr, "Unable to setup memory (%d)\n", errno);
		exit(1);
	}

	error = init_msr();
	if (error) {
		fprintf(stderr, "init_msr error %d", error);
		exit(1);
	}

	init_mem();
	init_inout();
	atkbdc_init(ctx);
	pci_irq_init(ctx);
	ioapic_init(ctx);

	rtc_init(ctx, rtc_localtime);
	sci_init(ctx);

	/*
	 * Exit if a device emulation finds an error in its initilization
	 */
	if (init_pci(ctx) != 0)
		exit(1);

	if (dbg_port != 0)
		init_dbgport(dbg_port);

	if (gdb_port != 0)
		init_gdb(ctx, gdb_port, gdb_stop);

	if (bvmcons)
		init_bvmcons();

	if (lpc_bootrom()) {
		if (vm_set_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, 1)) {
			fprintf(stderr, "ROM boot failed: unrestricted guest "
			    "capability not available\n");
			exit(1);
		}
		error = vcpu_reset(ctx, BSP);
		assert(error == 0);
	}

	error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
	assert(error == 0);

	/*
	 * build the guest tables, MP etc.
	 */
	if (mptgen) {
		error = mptable_build(ctx, guest_ncpus);
		if (error)
			exit(1);
	}

	error = smbios_build(ctx);
	assert(error == 0);

	if (acpi) {
		error = acpi_build(ctx, guest_ncpus);
		assert(error == 0);
	}

	if (lpc_bootrom())
		fwctl_init();

#ifndef WITHOUT_CAPSICUM
	caph_cache_catpages();

	if (caph_limit_stdout() == -1 || caph_limit_stderr() == -1)
		errx(EX_OSERR, "Unable to apply rights for sandbox");

	if (cap_enter() == -1 && errno != ENOSYS)
		errx(EX_OSERR, "cap_enter() failed");
#endif

	/*
	 * Change the proc title to include the VM name.
	 */
	setproctitle("%s", vmname); 
	
	/*
	 * Add CPU 0
	 */
	fbsdrun_addcpu(ctx, BSP, BSP, rip);

	/*
	 * Head off to the main event dispatch loop
	 */
	mevent_dispatch();

	exit(1);
}