qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information)
@ 2021-04-01  8:25 Vincent Bernat
  2021-04-01  8:25 ` [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41 Vincent Bernat
  2021-04-01  8:41 ` [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Daniel P. Berrangé
  0 siblings, 2 replies; 11+ messages in thread
From: Vincent Bernat @ 2021-04-01  8:25 UTC (permalink / raw)
  To: Michael S. Tsirkin, Igor Mammedov, qemu-devel, Daniel P . Berrangé
  Cc: Vincent Bernat

Type 41 defines the attributes of devices that are onboard. The
original intent was to imply the BIOS had some level of control over
the enablement of the associated devices.

If network devices are present in this table, by default, udev will
name the corresponding interfaces enoX, X being the instance number.
Without such information, udev will fallback to using the PCI ID and
this usually gives ens3 or ens4. This can be a bit annoying as the
name of the network card may depend on the order of options and may
change if a new PCI device is added earlier on the commande line.
Being able to provide SMBIOS type 41 entry ensure the name of the
interface won't change and helps the user guess the right name without
booting a first time.

This can be invoked with:

    $QEMU -netdev user,id=internet
          -device virtio-net-pci,mac=50:54:00:00:00:42,netdev=internet \
          -smbios type=41,designation='Onboard LAN',instance=1,kind=ethernet,pci=0000:00:09.0

Which results in the guest seeing dmidecode data and the interface
exposed as "eno1":

    $ dmidecode -t 41
    # dmidecode 3.3
    Getting SMBIOS data from sysfs.
    SMBIOS 2.8 present.Handle 0x2900, DMI type 41, 11 bytes
    Onboard Device
            Reference Designation: Onboard LAN
            Type: Ethernet
            Status: Enabled
            Type Instance: 1
            Bus Address: 0000:00:09.0
    $ udevadm info -p /sys/class/net/eno1 | grep ONBOARD
    E: ID_NET_NAME_ONBOARD=eno1
    E: ID_NET_LABEL_ONBOARD=Onboard LAN

Signed-off-by: Vincent Bernat <vincent@bernat.ch>
---
 hw/smbios/smbios.c           | 119 +++++++++++++++++++++++++++++++++++
 include/hw/firmware/smbios.h |  11 ++++
 qemu-options.hx              |   7 ++-
 3 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index f22c4f5b734e..46a08652dff4 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -118,6 +118,32 @@ static struct {
     uint16_t speed;
 } type17;
 
+static QEnumLookup type41_kind_lookup = {
+    .array = (const char *const[]) {
+        "other",
+        "unknown",
+        "video",
+        "scsi",
+        "ethernet",
+        "tokenring",
+        "sound",
+        "pata",
+        "sata",
+        "sas",
+    },
+    .size = 10
+};
+struct type41_instance {
+    const char *designation;
+    uint8_t instance, kind;
+    struct {
+        uint16_t segment;
+        uint8_t bus, device;
+    } pci;
+    QTAILQ_ENTRY(type41_instance) next;
+};
+static QTAILQ_HEAD(, type41_instance) type41 = QTAILQ_HEAD_INITIALIZER(type41);
+
 static QemuOptsList qemu_smbios_opts = {
     .name = "smbios",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
@@ -358,6 +384,33 @@ static const QemuOptDesc qemu_smbios_type17_opts[] = {
     { /* end of list */ }
 };
 
+static const QemuOptDesc qemu_smbios_type41_opts[] = {
+    {
+        .name = "type",
+        .type = QEMU_OPT_NUMBER,
+        .help = "SMBIOS element type",
+    },{
+        .name = "designation",
+        .type = QEMU_OPT_STRING,
+        .help = "reference designation string",
+    },{
+        .name = "kind",
+        .type = QEMU_OPT_STRING,
+        .help = "device type",
+        .def_value_str = "other",
+    },{
+        .name = "instance",
+        .type = QEMU_OPT_NUMBER,
+        .help = "device type instance",
+    },{
+        .name = "pci",
+        .type = QEMU_OPT_STRING,
+        .help = "PCI device",
+        .def_value_str = "0:0.0",
+    },
+    { /* end of list */ }
+};
+
 static void smbios_register_config(void)
 {
     qemu_add_opts(&qemu_smbios_opts);
@@ -773,6 +826,26 @@ static void smbios_build_type_32_table(void)
     SMBIOS_BUILD_TABLE_POST;
 }
 
+static void smbios_build_type_41_table(void)
+{
+    unsigned instance = 0;
+    struct type41_instance *t41;
+
+    QTAILQ_FOREACH(t41, &type41, next) {
+        SMBIOS_BUILD_TABLE_PRE(41, 0x2900 + instance, true);
+
+        SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation);
+        t->device_type = t41->kind;
+        t->device_type_instance = t41->instance;
+        t->segment_group_number = cpu_to_le16(t41->pci.segment);
+        t->bus_number = t41->pci.bus;
+        t->device_number = t41->pci.device;
+
+        SMBIOS_BUILD_TABLE_POST;
+        instance++;
+    }
+}
+
 static void smbios_build_type_127_table(void)
 {
     SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */
@@ -928,6 +1001,7 @@ void smbios_get_tables(MachineState *ms,
 
         smbios_build_type_32_table();
         smbios_build_type_38_table();
+        smbios_build_type_41_table();
         smbios_build_type_127_table();
 
         smbios_validate_table(ms);
@@ -1224,6 +1298,51 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
             save_opt(&type17.part, opts, "part");
             type17.speed = qemu_opt_get_number(opts, "speed", 0);
             return;
+        case 41: {
+            struct type41_instance *t;
+            Error *local_err = NULL;
+            int pseg, pbus, pdevice, pfunction;
+
+            if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) {
+                return;
+            }
+            t = calloc(1, sizeof(struct type41_instance));
+            if (!t) {
+                error_setg(errp,
+                           "Unable to allocate memory for a new type 41 instance");
+                return;
+            }
+
+            save_opt(&t->designation, opts, "designation");
+            t->kind = qapi_enum_parse(&type41_kind_lookup,
+                                      qemu_opt_get(opts, "kind"),
+                                      0, &local_err) + 1;
+            t->kind |= 0x80;     /* enabled */
+            if (local_err != NULL) {
+                error_propagate(errp, local_err);
+                free(t);
+                return;
+            }
+            t->instance = qemu_opt_get_number(opts, "instance", 1);
+            if (sscanf(qemu_opt_get(opts, "pci"), "%x:%x:%x.%x",
+                       &pseg,
+                       &pbus,
+                       &pdevice,
+                       &pfunction) != 4) {
+                error_setg(errp, "unable to parse %s: %s",
+                           qemu_opt_get(opts, "pci"),
+                           g_strerror(errno));
+                free(t);
+                return;
+            }
+            t->pci.segment = pseg;
+            t->pci.bus = pbus;
+            t->pci.device = ((uint8_t)pdevice << 3) +
+                ((uint8_t)pfunction & 0x7);
+
+            QTAILQ_INSERT_TAIL(&type41, t, next);
+            return;
+        }
         default:
             error_setg(errp,
                        "Don't know how to build fields for SMBIOS type %ld",
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index 02a0ced0a09f..4504dd03c303 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -258,6 +258,17 @@ struct smbios_type_32 {
     uint8_t boot_status;
 } QEMU_PACKED;
 
+/* SMBIOS type 41 - Onboard Devices Extended Information */
+struct smbios_type_41 {
+    struct smbios_structure_header header;
+    uint8_t reference_designation_str;
+    uint8_t device_type;
+    uint8_t device_type_instance;
+    uint16_t segment_group_number;
+    uint8_t bus_number;
+    uint8_t device_number;
+} QEMU_PACKED;
+
 /* SMBIOS type 127 -- End-of-table */
 struct smbios_type_127 {
     struct smbios_structure_header header;
diff --git a/qemu-options.hx b/qemu-options.hx
index fd21002bd61d..eb2de7c372c7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2370,7 +2370,9 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
     "                specify SMBIOS type 11 fields\n"
     "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n"
     "               [,asset=str][,part=str][,speed=%d]\n"
-    "                specify SMBIOS type 17 fields\n",
+    "                specify SMBIOS type 17 fields\n"
+    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pci=%x:%x:%x.%x]\n"
+    "                specify SMBIOS type 41 fields\n",
     QEMU_ARCH_I386 | QEMU_ARCH_ARM)
 SRST
 ``-smbios file=binary``
@@ -2432,6 +2434,9 @@ SRST
 
 ``-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str][,asset=str][,part=str][,speed=%d]``
     Specify SMBIOS type 17 fields
+
+``-smbios type=41[,designation=str][,kind=str][,instance=%d][,dev=str]``
+    Specify SMBIOS type 41 fields
 ERST
 
 DEFHEADING()
-- 
2.31.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01  8:25 [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Vincent Bernat
@ 2021-04-01  8:25 ` Vincent Bernat
  2021-04-01  9:38   ` Daniel P. Berrangé
  2021-04-01 13:59   ` Michael S. Tsirkin
  2021-04-01  8:41 ` [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Daniel P. Berrangé
  1 sibling, 2 replies; 11+ messages in thread
From: Vincent Bernat @ 2021-04-01  8:25 UTC (permalink / raw)
  To: Michael S. Tsirkin, Igor Mammedov, qemu-devel, Daniel P . Berrangé
  Cc: Vincent Bernat

Instead of specifying the PCI address manually, the device can be
specified by ID:

    $QEMU -netdev user,id=internet
          -device virtio-net-pci,mac=50:54:00:00:00:42,netdev=internet,id=internet-dev \
          -smbios type=41,designation='Onboard LAN',instance=1,kind=ethernet,pcidev=internet-dev

The PCI segment is assumed to be 0. This should hold true for most
cases.

    $ dmidecode -t 41
    # dmidecode 3.3
    Getting SMBIOS data from sysfs.
    SMBIOS 2.8 present.

    Handle 0x2900, DMI type 41, 11 bytes
    Onboard Device
            Reference Designation: Onboard LAN
            Type: Ethernet
            Status: Enabled
            Type Instance: 1
            Bus Address: 0000:00:09.0

    $ ip -brief a
    lo               UNKNOWN        127.0.0.1/8 ::1/128
    eno1             UP             10.0.2.14/24 fec0::5254:ff:fe00:42/64 fe80::5254:ff:fe00:42/64

Signed-off-by: Vincent Bernat <vincent@bernat.ch>
---
 hw/smbios/smbios.c | 47 +++++++++++++++++++++-------------------------
 qemu-options.hx    |  2 +-
 2 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 46a08652dff4..0f390e03453c 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -27,6 +27,7 @@
 #include "hw/firmware/smbios.h"
 #include "hw/loader.h"
 #include "hw/boards.h"
+#include "hw/pci/pci.h"
 #include "smbios_build.h"
 
 /* legacy structures and constants for <= 2.0 machines */
@@ -134,12 +135,8 @@ static QEnumLookup type41_kind_lookup = {
     .size = 10
 };
 struct type41_instance {
-    const char *designation;
+    const char *designation, *pcidev;
     uint8_t instance, kind;
-    struct {
-        uint16_t segment;
-        uint8_t bus, device;
-    } pci;
     QTAILQ_ENTRY(type41_instance) next;
 };
 static QTAILQ_HEAD(, type41_instance) type41 = QTAILQ_HEAD_INITIALIZER(type41);
@@ -403,10 +400,9 @@ static const QemuOptDesc qemu_smbios_type41_opts[] = {
         .type = QEMU_OPT_NUMBER,
         .help = "device type instance",
     },{
-        .name = "pci",
+        .name = "pcidev",
         .type = QEMU_OPT_STRING,
         .help = "PCI device",
-        .def_value_str = "0:0.0",
     },
     { /* end of list */ }
 };
@@ -837,9 +833,23 @@ static void smbios_build_type_41_table(void)
         SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation);
         t->device_type = t41->kind;
         t->device_type_instance = t41->instance;
-        t->segment_group_number = cpu_to_le16(t41->pci.segment);
-        t->bus_number = t41->pci.bus;
-        t->device_number = t41->pci.device;
+
+        if (t41->pcidev) {
+            PCIDevice *pdev = NULL;
+            int rc = pci_qdev_find_device(t41->pcidev, &pdev);
+            if (rc == 0) {
+                /*
+                 * TODO: Extract the appropriate value. Most of the
+                 * time, this will be 0.
+                 */
+                t->segment_group_number = cpu_to_le16(0);
+                t->bus_number = pci_dev_bus_num(pdev);
+                t->device_number = pdev->devfn;
+            } else {
+                fprintf(stderr, "%s: cannot find PCI device %s\n",
+                        __func__, t41->pcidev);
+            }
+        }
 
         SMBIOS_BUILD_TABLE_POST;
         instance++;
@@ -1301,7 +1311,6 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
         case 41: {
             struct type41_instance *t;
             Error *local_err = NULL;
-            int pseg, pbus, pdevice, pfunction;
 
             if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) {
                 return;
@@ -1324,21 +1333,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
                 return;
             }
             t->instance = qemu_opt_get_number(opts, "instance", 1);
-            if (sscanf(qemu_opt_get(opts, "pci"), "%x:%x:%x.%x",
-                       &pseg,
-                       &pbus,
-                       &pdevice,
-                       &pfunction) != 4) {
-                error_setg(errp, "unable to parse %s: %s",
-                           qemu_opt_get(opts, "pci"),
-                           g_strerror(errno));
-                free(t);
-                return;
-            }
-            t->pci.segment = pseg;
-            t->pci.bus = pbus;
-            t->pci.device = ((uint8_t)pdevice << 3) +
-                ((uint8_t)pfunction & 0x7);
+            save_opt(&t->pcidev, opts, "pcidev");
 
             QTAILQ_INSERT_TAIL(&type41, t, next);
             return;
diff --git a/qemu-options.hx b/qemu-options.hx
index eb2de7c372c7..e6e54f9bd1f3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2371,7 +2371,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
     "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n"
     "               [,asset=str][,part=str][,speed=%d]\n"
     "                specify SMBIOS type 17 fields\n"
-    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pci=%x:%x:%x.%x]\n"
+    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n"
     "                specify SMBIOS type 41 fields\n",
     QEMU_ARCH_I386 | QEMU_ARCH_ARM)
 SRST
-- 
2.31.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information)
  2021-04-01  8:25 [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Vincent Bernat
  2021-04-01  8:25 ` [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41 Vincent Bernat
@ 2021-04-01  8:41 ` Daniel P. Berrangé
  2021-04-01  8:46   ` Vincent Bernat
  1 sibling, 1 reply; 11+ messages in thread
From: Daniel P. Berrangé @ 2021-04-01  8:41 UTC (permalink / raw)
  To: Vincent Bernat; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin

On Thu, Apr 01, 2021 at 10:25:43AM +0200, Vincent Bernat wrote:
> Type 41 defines the attributes of devices that are onboard. The
> original intent was to imply the BIOS had some level of control over
> the enablement of the associated devices.
> 
> If network devices are present in this table, by default, udev will
> name the corresponding interfaces enoX, X being the instance number.
> Without such information, udev will fallback to using the PCI ID and
> this usually gives ens3 or ens4. This can be a bit annoying as the
> name of the network card may depend on the order of options and may
> change if a new PCI device is added earlier on the commande line.
> Being able to provide SMBIOS type 41 entry ensure the name of the
> interface won't change and helps the user guess the right name without
> booting a first time.
> 
> This can be invoked with:
> 
>     $QEMU -netdev user,id=internet
>           -device virtio-net-pci,mac=50:54:00:00:00:42,netdev=internet \
>           -smbios type=41,designation='Onboard LAN',instance=1,kind=ethernet,pci=0000:00:09.0
> 
> Which results in the guest seeing dmidecode data and the interface
> exposed as "eno1":
> 
>     $ dmidecode -t 41
>     # dmidecode 3.3
>     Getting SMBIOS data from sysfs.
>     SMBIOS 2.8 present.Handle 0x2900, DMI type 41, 11 bytes
>     Onboard Device
>             Reference Designation: Onboard LAN
>             Type: Ethernet
>             Status: Enabled
>             Type Instance: 1
>             Bus Address: 0000:00:09.0
>     $ udevadm info -p /sys/class/net/eno1 | grep ONBOARD
>     E: ID_NET_NAME_ONBOARD=eno1
>     E: ID_NET_LABEL_ONBOARD=Onboard LAN
> 
> Signed-off-by: Vincent Bernat <vincent@bernat.ch>
> ---
>  hw/smbios/smbios.c           | 119 +++++++++++++++++++++++++++++++++++
>  include/hw/firmware/smbios.h |  11 ++++
>  qemu-options.hx              |   7 ++-
>  3 files changed, 136 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index f22c4f5b734e..46a08652dff4 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c


>  static void smbios_register_config(void)
>  {
>      qemu_add_opts(&qemu_smbios_opts);
> @@ -773,6 +826,26 @@ static void smbios_build_type_32_table(void)
>      SMBIOS_BUILD_TABLE_POST;
>  }
>  
> +static void smbios_build_type_41_table(void)
> +{
> +    unsigned instance = 0;
> +    struct type41_instance *t41;
> +
> +    QTAILQ_FOREACH(t41, &type41, next) {
> +        SMBIOS_BUILD_TABLE_PRE(41, 0x2900 + instance, true);
> +
> +        SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation);
> +        t->device_type = t41->kind;
> +        t->device_type_instance = t41->instance;
> +        t->segment_group_number = cpu_to_le16(t41->pci.segment);
> +        t->bus_number = t41->pci.bus;
> +        t->device_number = t41->pci.device;
> +
> +        SMBIOS_BUILD_TABLE_POST;
> +        instance++;
> +    }
> +}
> +
>  static void smbios_build_type_127_table(void)
>  {
>      SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */
> @@ -928,6 +1001,7 @@ void smbios_get_tables(MachineState *ms,
>  
>          smbios_build_type_32_table();
>          smbios_build_type_38_table();
> +        smbios_build_type_41_table();
>          smbios_build_type_127_table();
>  
>          smbios_validate_table(ms);
> @@ -1224,6 +1298,51 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>              save_opt(&type17.part, opts, "part");
>              type17.speed = qemu_opt_get_number(opts, "speed", 0);
>              return;
> +        case 41: {
> +            struct type41_instance *t;
> +            Error *local_err = NULL;
> +            int pseg, pbus, pdevice, pfunction;
> +
> +            if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) {
> +                return;
> +            }
> +            t = calloc(1, sizeof(struct type41_instance));
> +            if (!t) {
> +                error_setg(errp,
> +                           "Unable to allocate memory for a new type 41 instance");
> +                return;
> +            }

QEMU uses GLib allocation functions throughout, which abort
on OOM. So replace this with g_new0.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information)
  2021-04-01  8:41 ` [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Daniel P. Berrangé
@ 2021-04-01  8:46   ` Vincent Bernat
  0 siblings, 0 replies; 11+ messages in thread
From: Vincent Bernat @ 2021-04-01  8:46 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin

 ❦  1 avril 2021 09:41 +01, Daniel P. Berrangé:

>> +            t = calloc(1, sizeof(struct type41_instance));
>> +            if (!t) {
>> +                error_setg(errp,
>> +                           "Unable to allocate memory for a new type 41 instance");
>> +                return;
>> +            }
>
> QEMU uses GLib allocation functions throughout, which abort
> on OOM. So replace this with g_new0.

Ack. Will be fixed on the next version. Thanks!
-- 
Make input easy to proofread.
            - The Elements of Programming Style (Kernighan & Plauger)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01  8:25 ` [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41 Vincent Bernat
@ 2021-04-01  9:38   ` Daniel P. Berrangé
  2021-04-01 10:07     ` Vincent Bernat
  2021-04-01 12:27     ` Vincent Bernat
  2021-04-01 13:59   ` Michael S. Tsirkin
  1 sibling, 2 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2021-04-01  9:38 UTC (permalink / raw)
  To: Vincent Bernat; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin

On Thu, Apr 01, 2021 at 10:25:44AM +0200, Vincent Bernat wrote:
> Instead of specifying the PCI address manually, the device can be
> specified by ID:
> 
>     $QEMU -netdev user,id=internet
>           -device virtio-net-pci,mac=50:54:00:00:00:42,netdev=internet,id=internet-dev \
>           -smbios type=41,designation='Onboard LAN',instance=1,kind=ethernet,pcidev=internet-dev
> 
> The PCI segment is assumed to be 0. This should hold true for most
> cases.
> 
>     $ dmidecode -t 41
>     # dmidecode 3.3
>     Getting SMBIOS data from sysfs.
>     SMBIOS 2.8 present.
> 
>     Handle 0x2900, DMI type 41, 11 bytes
>     Onboard Device
>             Reference Designation: Onboard LAN
>             Type: Ethernet
>             Status: Enabled
>             Type Instance: 1
>             Bus Address: 0000:00:09.0
> 
>     $ ip -brief a
>     lo               UNKNOWN        127.0.0.1/8 ::1/128
>     eno1             UP             10.0.2.14/24 fec0::5254:ff:fe00:42/64 fe80::5254:ff:fe00:42/64
> 
> Signed-off-by: Vincent Bernat <vincent@bernat.ch>
> ---
>  hw/smbios/smbios.c | 47 +++++++++++++++++++++-------------------------
>  qemu-options.hx    |  2 +-
>  2 files changed, 22 insertions(+), 27 deletions(-)

It doesn't really make sense to have this as a separate patch
when it is deleting half the code you added in the previous
patch. Just merge them together as one.

> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 46a08652dff4..0f390e03453c 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -27,6 +27,7 @@
>  #include "hw/firmware/smbios.h"
>  #include "hw/loader.h"
>  #include "hw/boards.h"
> +#include "hw/pci/pci.h"
>  #include "smbios_build.h"
>  
>  /* legacy structures and constants for <= 2.0 machines */
> @@ -134,12 +135,8 @@ static QEnumLookup type41_kind_lookup = {
>      .size = 10
>  };
>  struct type41_instance {
> -    const char *designation;
> +    const char *designation, *pcidev;
>      uint8_t instance, kind;
> -    struct {
> -        uint16_t segment;
> -        uint8_t bus, device;
> -    } pci;
>      QTAILQ_ENTRY(type41_instance) next;
>  };
>  static QTAILQ_HEAD(, type41_instance) type41 = QTAILQ_HEAD_INITIALIZER(type41);
> @@ -403,10 +400,9 @@ static const QemuOptDesc qemu_smbios_type41_opts[] = {
>          .type = QEMU_OPT_NUMBER,
>          .help = "device type instance",
>      },{
> -        .name = "pci",
> +        .name = "pcidev",
>          .type = QEMU_OPT_STRING,
>          .help = "PCI device",
> -        .def_value_str = "0:0.0",
>      },
>      { /* end of list */ }
>  };
> @@ -837,9 +833,23 @@ static void smbios_build_type_41_table(void)
>          SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation);
>          t->device_type = t41->kind;
>          t->device_type_instance = t41->instance;
> -        t->segment_group_number = cpu_to_le16(t41->pci.segment);
> -        t->bus_number = t41->pci.bus;
> -        t->device_number = t41->pci.device;
> +
> +        if (t41->pcidev) {
> +            PCIDevice *pdev = NULL;
> +            int rc = pci_qdev_find_device(t41->pcidev, &pdev);
> +            if (rc == 0) {
> +                /*
> +                 * TODO: Extract the appropriate value. Most of the
> +                 * time, this will be 0.
> +                 */
> +                t->segment_group_number = cpu_to_le16(0);

Hmm, tricky, as it requires interpreting the PCI topology. Wonder if
there's any helper that can do the hard work for you

> +                t->bus_number = pci_dev_bus_num(pdev);
> +                t->device_number = pdev->devfn;
> +            } else {
> +                fprintf(stderr, "%s: cannot find PCI device %s\n",
> +                        __func__, t41->pcidev);

This isn't terminating execution which looks like a bug.

Modify this method to have an 'Error **errp' parameter and
use 'error_setg' to report it.  You'll need to modify the
smbios_get_tables caller to have an 'Error **errp' too.

For the callers of smbios_get_tables(), you can then just pass
in '&error_fatal', to make it print the error + exit.

> +            }
> +        }
>  
>          SMBIOS_BUILD_TABLE_POST;
>          instance++;
> @@ -1301,7 +1311,6 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>          case 41: {
>              struct type41_instance *t;
>              Error *local_err = NULL;
> -            int pseg, pbus, pdevice, pfunction;
>  
>              if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) {
>                  return;
> @@ -1324,21 +1333,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>                  return;
>              }
>              t->instance = qemu_opt_get_number(opts, "instance", 1);
> -            if (sscanf(qemu_opt_get(opts, "pci"), "%x:%x:%x.%x",
> -                       &pseg,
> -                       &pbus,
> -                       &pdevice,
> -                       &pfunction) != 4) {
> -                error_setg(errp, "unable to parse %s: %s",
> -                           qemu_opt_get(opts, "pci"),
> -                           g_strerror(errno));
> -                free(t);
> -                return;
> -            }
> -            t->pci.segment = pseg;
> -            t->pci.bus = pbus;
> -            t->pci.device = ((uint8_t)pdevice << 3) +
> -                ((uint8_t)pfunction & 0x7);
> +            save_opt(&t->pcidev, opts, "pcidev");
>  
>              QTAILQ_INSERT_TAIL(&type41, t, next);
>              return;
> diff --git a/qemu-options.hx b/qemu-options.hx
> index eb2de7c372c7..e6e54f9bd1f3 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2371,7 +2371,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
>      "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n"
>      "               [,asset=str][,part=str][,speed=%d]\n"
>      "                specify SMBIOS type 17 fields\n"
> -    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pci=%x:%x:%x.%x]\n"
> +    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n"
>      "                specify SMBIOS type 41 fields\n",
>      QEMU_ARCH_I386 | QEMU_ARCH_ARM)
>  SRST
> -- 
> 2.31.0
> 

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01  9:38   ` Daniel P. Berrangé
@ 2021-04-01 10:07     ` Vincent Bernat
  2021-04-01 10:19       ` Daniel P. Berrangé
  2021-04-01 12:27     ` Vincent Bernat
  1 sibling, 1 reply; 11+ messages in thread
From: Vincent Bernat @ 2021-04-01 10:07 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin

 ❦  1 avril 2021 10:38 +01, Daniel P. Berrangé:

>>  hw/smbios/smbios.c | 47 +++++++++++++++++++++-------------------------
>>  qemu-options.hx    |  2 +-
>>  2 files changed, 22 insertions(+), 27 deletions(-)
>
> It doesn't really make sense to have this as a separate patch
> when it is deleting half the code you added in the previous
> patch. Just merge them together as one.

I'll do that.

>> +                /*
>> +                 * TODO: Extract the appropriate value. Most of the
>> +                 * time, this will be 0.
>> +                 */
>> +                t->segment_group_number = cpu_to_le16(0);
>
> Hmm, tricky, as it requires interpreting the PCI topology. Wonder if
> there's any helper that can do the hard work for you

There is pci_root_bus_path(), but it returns a string which could just
contain a segment or several segments. It seems the SMBIOS standard
didn't account for complex topologies. I could parse the string. and
keep only the right-most segment.

>> +                t->bus_number = pci_dev_bus_num(pdev);
>> +                t->device_number = pdev->devfn;
>> +            } else {
>> +                fprintf(stderr, "%s: cannot find PCI device %s\n",
>> +                        __func__, t41->pcidev);
>
> This isn't terminating execution which looks like a bug.

It was my intention. The PCI address will then be 00:00:00.0. If you
think it's better to terminate, I can do what you suggest.
-- 
Replace repetitive expressions by calls to a common function.
            - The Elements of Programming Style (Kernighan & Plauger)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01 10:07     ` Vincent Bernat
@ 2021-04-01 10:19       ` Daniel P. Berrangé
  0 siblings, 0 replies; 11+ messages in thread
From: Daniel P. Berrangé @ 2021-04-01 10:19 UTC (permalink / raw)
  To: Vincent Bernat; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin

On Thu, Apr 01, 2021 at 12:07:30PM +0200, Vincent Bernat wrote:
>  ❦  1 avril 2021 10:38 +01, Daniel P. Berrangé:
> 
> >>  hw/smbios/smbios.c | 47 +++++++++++++++++++++-------------------------
> >>  qemu-options.hx    |  2 +-
> >>  2 files changed, 22 insertions(+), 27 deletions(-)
> >
> > It doesn't really make sense to have this as a separate patch
> > when it is deleting half the code you added in the previous
> > patch. Just merge them together as one.
> 
> I'll do that.
> 
> >> +                /*
> >> +                 * TODO: Extract the appropriate value. Most of the
> >> +                 * time, this will be 0.
> >> +                 */
> >> +                t->segment_group_number = cpu_to_le16(0);
> >
> > Hmm, tricky, as it requires interpreting the PCI topology. Wonder if
> > there's any helper that can do the hard work for you
> 
> There is pci_root_bus_path(), but it returns a string which could just
> contain a segment or several segments. It seems the SMBIOS standard
> didn't account for complex topologies. I could parse the string. and
> keep only the right-most segment.
> 
> >> +                t->bus_number = pci_dev_bus_num(pdev);
> >> +                t->device_number = pdev->devfn;
> >> +            } else {
> >> +                fprintf(stderr, "%s: cannot find PCI device %s\n",
> >> +                        __func__, t41->pcidev);
> >
> > This isn't terminating execution which looks like a bug.
> 
> It was my intention. The PCI address will then be 00:00:00.0. If you
> think it's better to terminate, I can do what you suggest.

If we can't find the PCI device, that's user configuration error, and
we prefer to report those & exit, rather than continuing with likely
bogus data.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01  9:38   ` Daniel P. Berrangé
  2021-04-01 10:07     ` Vincent Bernat
@ 2021-04-01 12:27     ` Vincent Bernat
  1 sibling, 0 replies; 11+ messages in thread
From: Vincent Bernat @ 2021-04-01 12:27 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: Igor Mammedov, qemu-devel, Michael S. Tsirkin

 ❦  1 avril 2021 10:38 +01, Daniel P. Berrangé:

>> +                t->bus_number = pci_dev_bus_num(pdev);
>> +                t->device_number = pdev->devfn;
>> +            } else {
>> +                fprintf(stderr, "%s: cannot find PCI device %s\n",
>> +                        __func__, t41->pcidev);
>
> This isn't terminating execution which looks like a bug.
>
> Modify this method to have an 'Error **errp' parameter and
> use 'error_setg' to report it.  You'll need to modify the
> smbios_get_tables caller to have an 'Error **errp' too.
>
> For the callers of smbios_get_tables(), you can then just pass
> in '&error_fatal', to make it print the error + exit.

I did that. I wanted to also return -1, but it would require to tweak a
bit more code, notably the SMBIOS_BUILD_TABLE_PRE() macro. As the
callers are using error_fatal, I suppose this is not strictly mandatory
to signal the error through a return code.
-- 
Have a place for everything and keep the thing somewhere else; this is not
advice, it is merely custom.
		-- Mark Twain


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01  8:25 ` [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41 Vincent Bernat
  2021-04-01  9:38   ` Daniel P. Berrangé
@ 2021-04-01 13:59   ` Michael S. Tsirkin
  2021-04-01 14:26     ` Vincent Bernat
  1 sibling, 1 reply; 11+ messages in thread
From: Michael S. Tsirkin @ 2021-04-01 13:59 UTC (permalink / raw)
  To: Vincent Bernat; +Cc: Igor Mammedov, Daniel P . Berrangé, qemu-devel

On Thu, Apr 01, 2021 at 10:25:44AM +0200, Vincent Bernat wrote:
> Instead of specifying the PCI address manually, the device can be
> specified by ID:
> 
>     $QEMU -netdev user,id=internet
>           -device virtio-net-pci,mac=50:54:00:00:00:42,netdev=internet,id=internet-dev \
>           -smbios type=41,designation='Onboard LAN',instance=1,kind=ethernet,pcidev=internet-dev
> 
> The PCI segment is assumed to be 0. This should hold true for most
> cases.
> 
>     $ dmidecode -t 41
>     # dmidecode 3.3
>     Getting SMBIOS data from sysfs.
>     SMBIOS 2.8 present.
> 
>     Handle 0x2900, DMI type 41, 11 bytes
>     Onboard Device
>             Reference Designation: Onboard LAN
>             Type: Ethernet
>             Status: Enabled
>             Type Instance: 1
>             Bus Address: 0000:00:09.0
> 
>     $ ip -brief a
>     lo               UNKNOWN        127.0.0.1/8 ::1/128
>     eno1             UP             10.0.2.14/24 fec0::5254:ff:fe00:42/64 fe80::5254:ff:fe00:42/64
> 
> Signed-off-by: Vincent Bernat <vincent@bernat.ch>
> ---
>  hw/smbios/smbios.c | 47 +++++++++++++++++++++-------------------------
>  qemu-options.hx    |  2 +-
>  2 files changed, 22 insertions(+), 27 deletions(-)
> 
> diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
> index 46a08652dff4..0f390e03453c 100644
> --- a/hw/smbios/smbios.c
> +++ b/hw/smbios/smbios.c
> @@ -27,6 +27,7 @@
>  #include "hw/firmware/smbios.h"
>  #include "hw/loader.h"
>  #include "hw/boards.h"
> +#include "hw/pci/pci.h"
>  #include "smbios_build.h"
>  
>  /* legacy structures and constants for <= 2.0 machines */
> @@ -134,12 +135,8 @@ static QEnumLookup type41_kind_lookup = {
>      .size = 10
>  };
>  struct type41_instance {
> -    const char *designation;
> +    const char *designation, *pcidev;
>      uint8_t instance, kind;
> -    struct {
> -        uint16_t segment;
> -        uint8_t bus, device;
> -    } pci;
>      QTAILQ_ENTRY(type41_instance) next;
>  };
>  static QTAILQ_HEAD(, type41_instance) type41 = QTAILQ_HEAD_INITIALIZER(type41);
> @@ -403,10 +400,9 @@ static const QemuOptDesc qemu_smbios_type41_opts[] = {
>          .type = QEMU_OPT_NUMBER,
>          .help = "device type instance",
>      },{
> -        .name = "pci",
> +        .name = "pcidev",
>          .type = QEMU_OPT_STRING,
>          .help = "PCI device",
> -        .def_value_str = "0:0.0",
>      },
>      { /* end of list */ }
>  };
> @@ -837,9 +833,23 @@ static void smbios_build_type_41_table(void)
>          SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation);
>          t->device_type = t41->kind;
>          t->device_type_instance = t41->instance;
> -        t->segment_group_number = cpu_to_le16(t41->pci.segment);
> -        t->bus_number = t41->pci.bus;
> -        t->device_number = t41->pci.device;
> +
> +        if (t41->pcidev) {
> +            PCIDevice *pdev = NULL;
> +            int rc = pci_qdev_find_device(t41->pcidev, &pdev);
> +            if (rc == 0) {
> +                /*
> +                 * TODO: Extract the appropriate value. Most of the
> +                 * time, this will be 0.
> +                 */
> +                t->segment_group_number = cpu_to_le16(0);
> +                t->bus_number = pci_dev_bus_num(pdev);
> +                t->device_number = pdev->devfn;

Problem is, for devices behind bridges for example, bus is only
configured by guest, after pci has been enumerated.

So I suspect this either
- needs to be limited to only work for the root bus
- needs to be re-evaluted on guest access, like we do
  with ACPI

Thoughts?



> +            } else {
> +                fprintf(stderr, "%s: cannot find PCI device %s\n",
> +                        __func__, t41->pcidev);
> +            }
> +        }
>  
>          SMBIOS_BUILD_TABLE_POST;
>          instance++;
> @@ -1301,7 +1311,6 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>          case 41: {
>              struct type41_instance *t;
>              Error *local_err = NULL;
> -            int pseg, pbus, pdevice, pfunction;
>  
>              if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) {
>                  return;
> @@ -1324,21 +1333,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
>                  return;
>              }
>              t->instance = qemu_opt_get_number(opts, "instance", 1);
> -            if (sscanf(qemu_opt_get(opts, "pci"), "%x:%x:%x.%x",
> -                       &pseg,
> -                       &pbus,
> -                       &pdevice,
> -                       &pfunction) != 4) {
> -                error_setg(errp, "unable to parse %s: %s",
> -                           qemu_opt_get(opts, "pci"),
> -                           g_strerror(errno));
> -                free(t);
> -                return;
> -            }
> -            t->pci.segment = pseg;
> -            t->pci.bus = pbus;
> -            t->pci.device = ((uint8_t)pdevice << 3) +
> -                ((uint8_t)pfunction & 0x7);
> +            save_opt(&t->pcidev, opts, "pcidev");
>  
>              QTAILQ_INSERT_TAIL(&type41, t, next);
>              return;
> diff --git a/qemu-options.hx b/qemu-options.hx
> index eb2de7c372c7..e6e54f9bd1f3 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2371,7 +2371,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
>      "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n"
>      "               [,asset=str][,part=str][,speed=%d]\n"
>      "                specify SMBIOS type 17 fields\n"
> -    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pci=%x:%x:%x.%x]\n"
> +    "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n"
>      "                specify SMBIOS type 41 fields\n",
>      QEMU_ARCH_I386 | QEMU_ARCH_ARM)
>  SRST
> -- 
> 2.31.0



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01 13:59   ` Michael S. Tsirkin
@ 2021-04-01 14:26     ` Vincent Bernat
  2021-04-01 16:32       ` Michael S. Tsirkin
  0 siblings, 1 reply; 11+ messages in thread
From: Vincent Bernat @ 2021-04-01 14:26 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Igor Mammedov, Daniel P . Berrangé, qemu-devel

 ❦  1 avril 2021 09:59 -04, Michael S. Tsirkin:

>> +                /*
>> +                 * TODO: Extract the appropriate value. Most of the
>> +                 * time, this will be 0.
>> +                 */
>> +                t->segment_group_number = cpu_to_le16(0);
>> +                t->bus_number = pci_dev_bus_num(pdev);
>> +                t->device_number = pdev->devfn;
>
> Problem is, for devices behind bridges for example, bus is only
> configured by guest, after pci has been enumerated.
>
> So I suspect this either
> - needs to be limited to only work for the root bus
> - needs to be re-evaluted on guest access, like we do
>   with ACPI

Or the address can be provided by the user. I didn't want to keep that
at this is error prone and there may be surprises after adding a device
or after a QEMU upgrade.

Otherwise, limiting to the root bus seems a fine limitation by me. How
do I check that?
-- 
Don't just echo the code with comments - make every comment count.
            - The Elements of Programming Style (Kernighan & Plauger)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41
  2021-04-01 14:26     ` Vincent Bernat
@ 2021-04-01 16:32       ` Michael S. Tsirkin
  0 siblings, 0 replies; 11+ messages in thread
From: Michael S. Tsirkin @ 2021-04-01 16:32 UTC (permalink / raw)
  To: Vincent Bernat; +Cc: Igor Mammedov, Daniel P . Berrangé, qemu-devel

On Thu, Apr 01, 2021 at 04:26:50PM +0200, Vincent Bernat wrote:
>  ❦  1 avril 2021 09:59 -04, Michael S. Tsirkin:
> 
> >> +                /*
> >> +                 * TODO: Extract the appropriate value. Most of the
> >> +                 * time, this will be 0.
> >> +                 */
> >> +                t->segment_group_number = cpu_to_le16(0);
> >> +                t->bus_number = pci_dev_bus_num(pdev);
> >> +                t->device_number = pdev->devfn;
> >
> > Problem is, for devices behind bridges for example, bus is only
> > configured by guest, after pci has been enumerated.
> >
> > So I suspect this either
> > - needs to be limited to only work for the root bus
> > - needs to be re-evaluted on guest access, like we do
> >   with ACPI
> 
> Or the address can be provided by the user. I didn't want to keep that
> at this is error prone and there may be surprises after adding a device
> or after a QEMU upgrade.

Or on guest changes.

> 
> Otherwise, limiting to the root bus seems a fine limitation by me. How
> do I check that?

pci_bus_is_root will do this. Pls document the reason for the
limitation.


> -- 
> Don't just echo the code with comments - make every comment count.
>             - The Elements of Programming Style (Kernighan & Plauger)



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-04-01 16:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-01  8:25 [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Vincent Bernat
2021-04-01  8:25 ` [PATCH v2 2/2] hw/smbios: retrieve PCI address from specified device for Type 41 Vincent Bernat
2021-04-01  9:38   ` Daniel P. Berrangé
2021-04-01 10:07     ` Vincent Bernat
2021-04-01 10:19       ` Daniel P. Berrangé
2021-04-01 12:27     ` Vincent Bernat
2021-04-01 13:59   ` Michael S. Tsirkin
2021-04-01 14:26     ` Vincent Bernat
2021-04-01 16:32       ` Michael S. Tsirkin
2021-04-01  8:41 ` [PATCH v2 1/2] hw/smbios: support for type 41 (onboard devices extended information) Daniel P. Berrangé
2021-04-01  8:46   ` Vincent Bernat

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).