Don't allow MPtable generation if there are multiple PCI hierarchies. This is

because there isn't a standard way to relay this information to the guest OS.

Add a command line option "-Y" to bhyve(8) to inhibit MPtable generation.

If the virtual machine is using PCI devices on buses other than 0 then it can
still use ACPI tables to convey this information to the guest.

Discussed with:	grehan@
This commit is contained in:
Neel Natu 2014-05-02 04:51:31 +00:00
parent e625c10b2f
commit b100acf254
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=265211
5 changed files with 39 additions and 5 deletions

View File

@ -236,6 +236,8 @@ This is intended for debug purposes.
Ignore accesses to unimplemented Model Specific Registers (MSRs). This is intended for debug purposes.
.It Fl x
The guest's local APIC is configured in x2APIC mode.
.It Fl Y
Disable MPtable generation.
.It Fl h
Print help message and exit.
.It Ar vmname

View File

@ -145,6 +145,7 @@ usage(int code)
" -m: memory size in MB\n"
" -w: ignore unimplemented MSRs\n"
" -x: local apic is in x2APIC mode\n"
" -Y: disable MPtable generation\n"
" -U: uuid\n",
progname, (int)strlen(progname), "");
@ -616,7 +617,7 @@ int
main(int argc, char *argv[])
{
int c, error, gdb_port, err, bvmcons;
int max_vcpus;
int max_vcpus, mptgen;
struct vmctx *ctx;
uint64_t rip;
size_t memsize;
@ -626,8 +627,9 @@ main(int argc, char *argv[])
gdb_port = 0;
guest_ncpus = 1;
memsize = 256 * MB;
mptgen = 1;
while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) {
while ((c = getopt(argc, argv, "abehwxAHIPWYp:g:c:s:m:l:U:")) != -1) {
switch (c) {
case 'a':
x2apic_mode = 0;
@ -693,6 +695,9 @@ main(int argc, char *argv[])
case 'x':
x2apic_mode = 1;
break;
case 'Y':
mptgen = 0;
break;
case 'h':
usage(0);
default:
@ -752,7 +757,11 @@ main(int argc, char *argv[])
/*
* build the guest tables, MP etc.
*/
mptable_build(ctx, guest_ncpus);
if (mptgen) {
error = mptable_build(ctx, guest_ncpus);
if (error)
exit(1);
}
error = smbios_build(ctx);
assert(error == 0);

View File

@ -303,16 +303,31 @@ mptable_build(struct vmctx *ctx, int ncpu)
proc_entry_ptr mpep;
mpfps_t mpfp;
int_entry_ptr mpie;
int ioints;
int ioints, bus;
char *curraddr;
char *startaddr;
startaddr = paddr_guest2host(ctx, MPTABLE_BASE, MPTABLE_MAX_LENGTH);
if (startaddr == NULL) {
printf("mptable requires mapped mem\n");
fprintf(stderr, "mptable requires mapped mem\n");
return (ENOMEM);
}
/*
* There is no way to advertise multiple PCI hierarchies via MPtable
* so require that there is no PCI hierarchy with a non-zero bus
* number.
*/
for (bus = 1; bus <= PCI_BUSMAX; bus++) {
if (pci_bus_configured(bus)) {
fprintf(stderr, "MPtable is incompatible with "
"multiple PCI hierarchies.\r\n");
fprintf(stderr, "MPtable generation can be disabled "
"by passing the -Y option to bhyve(8).\r\n");
return (EINVAL);
}
}
curraddr = startaddr;
mpfp = (mpfps_t)curraddr;
mpt_build_mpfp(mpfp, MPTABLE_BASE);

View File

@ -1260,6 +1260,13 @@ pci_write_dsdt(void)
pci_bus_write_dsdt(bus);
}
int
pci_bus_configured(int bus)
{
assert(bus >= 0 && bus < MAXBUSES);
return (pci_businfo[bus] != NULL);
}
int
pci_msi_enabled(struct pci_devinst *pi)
{

View File

@ -233,6 +233,7 @@ uint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size);
int pci_count_lintr(int bus);
void pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg);
void pci_write_dsdt(void);
int pci_bus_configured(int bus);
static __inline void
pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val)