diff options
author | Mike Gerdts <mike.gerdts@joyent.com> | 2018-11-09 22:44:37 +0000 |
---|---|---|
committer | Mike Gerdts <mike.gerdts@joyent.com> | 2018-11-29 18:02:52 +0000 |
commit | cc78e0e8a9ef1c3c42ba267e1850ca73fa4e0395 (patch) | |
tree | 359ca34bd55c703c42804d149acce5ebdb1e1bf6 | |
parent | c75576d2f6b4d8218702164bc9cc3e642ff88ccc (diff) | |
download | illumos-joyent-cc78e0e8a9ef1c3c42ba267e1850ca73fa4e0395.tar.gz |
OS-7353 bhyve support for persistent pci slots for disks
Reviewed by: Jorge Schrauwen <sjorge@blackdot.be>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: John Levon <john.levon@joyent.com>
Approved by: John Levon <john.levon@joyent.com>
-rw-r--r-- | usr/src/lib/brand/bhyve/zone/boot.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/usr/src/lib/brand/bhyve/zone/boot.c b/usr/src/lib/brand/bhyve/zone/boot.c index 58160a88cc..6e6f3dc640 100644 --- a/usr/src/lib/brand/bhyve/zone/boot.c +++ b/usr/src/lib/brand/bhyve/zone/boot.c @@ -181,35 +181,82 @@ add_ram(int *argc, char **argv) } static int +parse_pcislot(const char *pcislot, uint_t *busp, uint_t *devp, uint_t *funcp) +{ + char junk; + + switch (sscanf(pcislot, "%u:%u:%u%c", busp, devp, funcp, &junk)) { + case 3: + break; + case 2: + case 1: + *funcp = *devp; + *devp = *busp; + *busp = 0; + break; + default: + (void) printf("Error: device %d has illegal PCI slot: %s\n", + *devp, pcislot); + return (-1); + } + + if (*busp > 255 || *devp > 31 || *funcp > 7) { + (void) printf("Error: device %d has illegal PCI slot: %s\n", + *devp, pcislot); + return (-1); + } + + return (0); +} + +/* + * In the initial implementation, slot assignment was dynamic on every boot. + * Now, each device resource can have a pci_slot property that will override + * dynamic assignment. The original behavior is preserved, but no effort is + * made to detect or avoid conflicts between legacy behavior and new behavior. + * When used with vmadm, this is not an issue, as it will update the zone + * config at boot time to contain static assignments. + */ +static int add_disk(char *disk, char *path, char *slotconf, size_t slotconf_len) { static char *boot = NULL; static int next_cd = 0; static int next_other = 0; const char *model = "virtio-blk"; - int pcislot; - int pcifn; + uint_t pcibus = 0, pcidev = 0, pcifn = 0; + const char *slotstr; + boolean_t isboot; - /* Allow at most one "primary" disk */ - if (is_env_true("device", disk, "boot")) { + isboot = is_env_true("device", disk, "boot"); + if (isboot) { + /* Allow at most one "primary" disk */ if (boot != NULL) { (void) printf("Error: multiple boot disks: %s %s\n", boot, path); return (-1); } boot = path; - pcislot = PCI_SLOT_BOOT_DISK; - pcifn = 0; - } else if (is_env_string("device", disk, "media", "cdrom")) { - pcislot = PCI_SLOT_CD; - pcifn = next_cd; - next_cd++; - } else { - pcislot = PCI_SLOT_OTHER_DISKS; - pcifn = next_other; - next_other++; } + if ((slotstr = get_zcfg_var("device", disk, "pci_slot")) != NULL) { + if (parse_pcislot(slotstr, &pcibus, &pcidev, &pcifn) != 0) { + return (-1); + } + } else { + if (isboot) { + pcidev = PCI_SLOT_BOOT_DISK; + pcifn = 0; + } else if (is_env_string("device", disk, "media", "cdrom")) { + pcidev = PCI_SLOT_CD; + pcifn = next_cd; + next_cd++; + } else { + pcidev = PCI_SLOT_OTHER_DISKS; + pcifn = next_other; + next_other++; + } + } if (is_env_string("device", disk, "model", "virtio")) { model = "virtio-blk"; @@ -224,8 +271,8 @@ add_disk(char *disk, char *path, char *slotconf, size_t slotconf_len) return (-1); } - if (snprintf(slotconf, slotconf_len, "%d:%d,%s,%s", - pcislot, pcifn, model, path) >= slotconf_len) { + if (snprintf(slotconf, slotconf_len, "%u:%u:%u,%s,%s", + pcibus, pcidev, pcifn, model, path) >= slotconf_len) { (void) printf("Error: disk path '%s' too long\n", path); return (-1); } @@ -239,7 +286,7 @@ add_ppt(int *argc, char **argv, char *ppt, char *path, char *slotconf, { static boolean_t wired = B_FALSE; static boolean_t acpi = B_FALSE; - unsigned int bus = 0, dev = 0, func = 0; + uint_t bus = 0, dev = 0, func = 0; char *pcislot; pcislot = get_zcfg_var("device", ppt, "pci_slot"); @@ -249,24 +296,7 @@ add_ppt(int *argc, char **argv, char *ppt, char *path, char *slotconf, return (-1); } - switch (sscanf(pcislot, "%u:%u:%u", &bus, &dev, &func)) { - case 3: - break; - case 2: - case 1: - func = dev; - dev = bus; - bus = 0; - break; - default: - (void) printf("Error: device %d has illegal PCI slot: %s\n", - dev, pcislot); - return (-1); - } - - if (bus > 255 || dev > 31 || func > 7) { - (void) printf("Error: device %d has illegal PCI slot: %s\n", - dev, pcislot); + if (parse_pcislot(pcislot, &bus, &dev, &func) != 0) { return (-1); } |