qrap: Introduce machine-specific PCI address base
For pc machines, devices are placed directly on pci.0 with
addresses like
bus=pci.0,addr=0xa
and in this case the existing code works correctly.
For q35 machines, however, a separate PCI bus is created for
each devices using a pcie-root-port, and the resulting
addresses look like
bus=pci.9,addr=0x0
In this case, we need to treat PCI addresses as decimal, not
hexadecimal, both when parsing and generating them.
This issue has gone unnoticed for a long time because it only
shows up when enough PCI devices are present: for small
numbers, decimal and hexadecimal overlap, masking the issue.
Reported-by: Alona Paz <alkaplan@redhat.com>
Fixes: 5307faa059
("qrap: Strip network devices from command line, set them up according to machine")
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
8828a637ba
commit
4f2341f31d
1 changed files with 24 additions and 10 deletions
22
qrap.c
22
qrap.c
|
@ -77,6 +77,7 @@ static const struct drop_arg {
|
||||||
* @template_post: Suffix for device specification (last part of address)
|
* @template_post: Suffix for device specification (last part of address)
|
||||||
* @template_json: Device prefix for when JSON is used
|
* @template_json: Device prefix for when JSON is used
|
||||||
* @template_json_post: Device suffix for when JSON is used
|
* @template_json_post: Device suffix for when JSON is used
|
||||||
|
* @base: Base used for PCI addresses
|
||||||
* @first: First usable PCI address
|
* @first: First usable PCI address
|
||||||
* @last: Last usable PCI address
|
* @last: Last usable PCI address
|
||||||
*/
|
*/
|
||||||
|
@ -87,6 +88,7 @@ static const struct pci_dev {
|
||||||
char *template_post;
|
char *template_post;
|
||||||
char *template_json;
|
char *template_json;
|
||||||
char *template_json_post;
|
char *template_json_post;
|
||||||
|
int base;
|
||||||
int first;
|
int first;
|
||||||
int last;
|
int last;
|
||||||
} pci_devs[] = {
|
} pci_devs[] = {
|
||||||
|
@ -94,19 +96,19 @@ static const struct pci_dev {
|
||||||
"pc-q35", "virtio-net-pci",
|
"pc-q35", "virtio-net-pci",
|
||||||
"bus=pci.", ",addr=0x0",
|
"bus=pci.", ",addr=0x0",
|
||||||
"\"bus\":\"pci.", ",\"addr\":\"0x0\"",
|
"\"bus\":\"pci.", ",\"addr\":\"0x0\"",
|
||||||
3, /* 2: hotplug bus */ 31
|
10, 3, /* 2: hotplug bus */ 31
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pc-", "virtio-net-pci",
|
"pc-", "virtio-net-pci",
|
||||||
"bus=pci.0,addr=0x", "",
|
"bus=pci.0,addr=0x", "",
|
||||||
"\"bus\":\"pci.0\",\"addr\":\"0x", "",
|
"\"bus\":\"pci.0\",\"addr\":\"0x", "",
|
||||||
2, /* 1: ISA bridge */ 31
|
16, 2, /* 1: ISA bridge */ 31
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"s390-ccw", "virtio-net-ccw",
|
"s390-ccw", "virtio-net-ccw",
|
||||||
"devno=fe.0.", "",
|
"devno=fe.0.", "",
|
||||||
"\"devno\":\"fe.0.", "",
|
"\"devno\":\"fe.0.", "",
|
||||||
1, 16
|
16, 1, 16
|
||||||
},
|
},
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
@ -264,7 +266,7 @@ int main(int argc, char **argv)
|
||||||
if (template) {
|
if (template) {
|
||||||
long n;
|
long n;
|
||||||
|
|
||||||
n = strtol(p + strlen(template), NULL, 16);
|
n = strtol(p + strlen(template), NULL, dev->base);
|
||||||
if (!errno)
|
if (!errno)
|
||||||
addr_map |= (1 << n);
|
addr_map |= (1 << n);
|
||||||
}
|
}
|
||||||
|
@ -285,13 +287,25 @@ int main(int argc, char **argv)
|
||||||
if (has_dev) {
|
if (has_dev) {
|
||||||
qemu_argv[qemu_argc++] = "-device";
|
qemu_argv[qemu_argc++] = "-device";
|
||||||
if (!has_json) {
|
if (!has_json) {
|
||||||
|
if (dev->base == 16) {
|
||||||
snprintf(dev_str, ARG_MAX,
|
snprintf(dev_str, ARG_MAX,
|
||||||
"%s,%s%x%s,netdev=hostnet0,x-txburst=4096",
|
"%s,%s%x%s,netdev=hostnet0,x-txburst=4096",
|
||||||
dev->name, dev->template, i, dev->template_post);
|
dev->name, dev->template, i, dev->template_post);
|
||||||
|
} else if (dev->base == 10) {
|
||||||
|
snprintf(dev_str, ARG_MAX,
|
||||||
|
"%s,%s%d%s,netdev=hostnet0,x-txburst=4096",
|
||||||
|
dev->name, dev->template, i, dev->template_post);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (dev->base == 16) {
|
||||||
snprintf(dev_str, ARG_MAX,
|
snprintf(dev_str, ARG_MAX,
|
||||||
"{\"driver\":\"%s\",%s%x\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
|
"{\"driver\":\"%s\",%s%x\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
|
||||||
dev->name, dev->template_json, i, dev->template_json_post);
|
dev->name, dev->template_json, i, dev->template_json_post);
|
||||||
|
} else if (dev->base == 10) {
|
||||||
|
snprintf(dev_str, ARG_MAX,
|
||||||
|
"{\"driver\":\"%s\",%s%d\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
|
||||||
|
dev->name, dev->template_json, i, dev->template_json_post);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
qemu_argv[qemu_argc++] = dev_str;
|
qemu_argv[qemu_argc++] = dev_str;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue