qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Laurent Vivier <lvivier@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [PATCH] scripts: add a script to list virtio devices in a system
Date: Tue, 11 May 2021 04:32:39 -0400	[thread overview]
Message-ID: <20210511043103-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20210506193341.140141-1-lvivier@redhat.com>

On Thu, May 06, 2021 at 09:33:41PM +0200, Laurent Vivier wrote:
> Add "lsvirtio" that lists all virtio devices in a system
> the same way lspci does for the PCI cards.
> 
> For instance:
> 
>  $ ./lsvirtio
>  0000:01:00.0 virtio0 Red Hat, Inc. (PCI) Virtio Network Card
> 	 Subsystem: virtio
> 	 Modalias: virtio:d00000001v00001AF4
> 	 Status: ACKNOWLEDGE DRIVER_OK DRIVER FEATURES_OK
> 	 Feature: CSUM
> 	 Feature: GUEST_CSUM
> 	 Feature: CTRL_GUEST_OFFLOADS
> 	 Feature: MAC
> 	 Feature: GUEST_TSO4
> 	 Feature: GUEST_TSO6
> 	 Feature: GUEST_ECN
> 	 Feature: GUEST_UFO
> 	 Feature: HOST_TSO4
> 	 Feature: HOST_TSO6
> 	 Feature: HOST_ECN
> 	 Feature: HOST_UFO
> 	 Feature: MRG_RXBUF
> 	 Feature: STATUS
> 	 Feature: CTRL_VQ
> 	 Feature: CTRL_RX
> 	 Feature: CTRL_VLAN
> 	 Feature: GUEST_ANNOUNCE
> 	 Feature: CTRL_MAC_ADDR
> 	 Feature: RING_INDIRECT_DESC
> 	 Feature: RING_EVENT_IDX
> 	 Feature: VERSION_1
> 	 Kernel driver in use: virtio_net
>          Interfaces: enp1s0
> 
>  0000:03:00.0 virtio1 Red Hat, Inc. (PCI) Virtio Console
> 	 Subsystem: virtio
> 	 Modalias: virtio:d00000003v00001AF4
> 	 Status: ACKNOWLEDGE DRIVER_OK DRIVER FEATURES_OK
> 	 Feature: MULTIPORT
> 	 Feature: RING_INDIRECT_DESC
> 	 Feature: RING_EVENT_IDX
> 	 Feature: VERSION_1
> 	 Kernel driver in use: virtio_console
>          Interfaces: vport1p1
>  ...
> 
> This is useful to have the list of virtio devices when they are not
> mapped by a PCI card:
> 
>  $ ./lsvirtio
>  virtio-mmio.121 virtio0 Virt (MMIO) Virtio 9P transport
> 	 Subsystem: virtio
> 	 Modalias: virtio:d00000009v554D4551
> 	 Status: FEATURES_OK ACKNOWLEDGE DRIVER DRIVER_OK
> 	 Feature: MOUNT_TAG
> 	 Feature: RING_INDIRECT_DESC
> 	 Feature: RING_EVENT_IDX
> 	 Feature: VERSION_1
> 	 Kernel driver in use: 9pnet_virtio
>          Interfaces: home0
> 
>  virtio-mmio.122 virtio1 Virt (MMIO) Virtio GPU Device
> 	 Subsystem: virtio
> 	 Modalias: virtio:d00000010v554D4551
> 	 Status: FEATURES_OK ACKNOWLEDGE DRIVER DRIVER_OK
> 	 Feature: EDID
> 	 Feature: RING_INDIRECT_DESC
> 	 Feature: RING_EVENT_IDX
> 	 Feature: VERSION_1
> 	 Kernel driver in use: virtio_gpu
>          Interfaces: fb0
>  ...
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
>  scripts/lsvirtio | 317 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 317 insertions(+)
>  create mode 100755 scripts/lsvirtio
> 
> diff --git a/scripts/lsvirtio b/scripts/lsvirtio
> new file mode 100755
> index 000000000000..f457d5b7344d
> --- /dev/null
> +++ b/scripts/lsvirtio
> @@ -0,0 +1,317 @@
> +#!/usr/bin/env python3
> +#
> +# Copyright (C) 2021 Red Hat, Inc.
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +import os
> +
> +# Virtual I/O Device (VIRTIO) Version 1.1
> +
> +# 2.1 Device Status Field
> +status_name = {
> +    ( 1, 'ACKNOWLEDGE' ),
> +    ( 2, 'DRIVER') ,
> +    ( 4, 'DRIVER_OK' ),
> +    ( 8, 'FEATURES_OK' ),
> +    ( 64, 'DEVICE_NEEDS_RESET' ),
> +    ( 128, 'FAILED' )
> +}
> +
> +# 5 Device Types
> +device_name = {
> +    1:'Network Card',
> +    2:'Block Device',
> +    3:'Console',
> +    4:'Entropy Source',
> +    5:'Memory Ballooning (traditional)',
> +    6:'ioMemory',
> +    7:'rpmsg',
> +    8:'SCSI host',
> +    9:'9P transport',
> +    10:'MAC80211 WLAN',
> +    11:'rproc serial',
> +    12:'CAIF',
> +    13:'Memory Balloon',
> +    16:'GPU Device',
> +    17:'Timer/Clock Device',
> +    18:'Input Device',
> +    19:'Socket Device',
> +    20:'Crypto Device',
> +    21:'Signal Distribution Module',
> +    22:'pstore Device',
> +    23:'IOMMU Device',
> +    24:'Memory Device',
> +# From linux headers
> +    26:'Filesystem',
> +    27:'pmem',
> +    29:'mac80211-hwsim',
> +}
> +
> +# 5.1 Network Device
> +# 5.1.3 Feature bits
> +net_feature_name = {
> +    0:'CSUM',
> +    1:'GUEST_CSUM',
> +    2:'CTRL_GUEST_OFFLOADS',
> +    3:'MTU',
> +    5:'MAC',
> +    6:'GSO',
> +    7:'GUEST_TSO4',
> +    8:'GUEST_TSO6',
> +    9:'GUEST_ECN',
> +    10:'GUEST_UFO',
> +    11:'HOST_TSO4',
> +    12:'HOST_TSO6',
> +    13:'HOST_ECN',
> +    14:'HOST_UFO',
> +    15:'MRG_RXBUF',
> +    16:'STATUS',
> +    17:'CTRL_VQ',
> +    18:'CTRL_RX',
> +    19:'CTRL_VLAN',
> +    21:'GUEST_ANNOUNCE',
> +    22:'MQ',
> +    23:'CTRL_MAC_ADDR',
> +    41:'GUEST_RSC4',
> +    42:'GUEST_RSC6',
> +    61:'RSC_EXT',
> +    62:'STANDBY',
> +}
> +
> +def get_feature_net(feature):
> +    return net_feature_name[feature]
> +
> +# 5.2 Block Device
> +# 5.2.3 Feature bits
> +block_feature_name = {
> +    0:'BARRIER',
> +    1:'SIZE_MAX',
> +    2:'SEG_MAX',
> +    4:'GEOMETRY',
> +    5:'RO',
> +    6:'BLK_SIZE',
> +    7:'SCSI',
> +    9:'FLUSH',
> +    10:'TOPOLOGY',
> +    11:'CONFIG_WCE',
> +    13:'DISCARD',
> +    14:'WRITE_ZEROES',
> +}
> +
> +def get_feature_block(feature):
> +    return block_feature_name[feature]
> +
> +# 5.3 Console Device
> +# 5.3.3 Feature bits
> +console_feature_name = {
> +    0:'SIZE',
> +    1:'MULTIPORT',
> +    2:'EMERG_WRITE',
> +}
> +
> +def get_feature_console(feature):
> +    return console_feature_name[feature]
> +
> +# 5.4 Entropy Device
> +# 5.4.3 Feature bits
> +# No feature bits
> +
> +# 5.5 Traditional Memory Balloon Device
> +# 5.5.3 Feature bits
> +balloon_traditional_feature_name = {
> +    0:'MUST_TELL_HOST',
> +    1:'STATS_VQ',
> +    2:'DEFLATE_ON_OOM',
> +# from linux headers
> +    3:'FREE_PAGE_HINT',
> +    4:'PAGE_POISON',
> +    5:'REPORTING',
> +}
> +
> +def get_feature_balloon_traditional(feature):
> +    return balloon_traditional_feature_name[feature]
> +
> +# 5.6 SCSI Host Device
> +# 5.6.3 Feature bits
> +scsi_feature_name = {
> +    0:'INOUT',
> +    1:'HOTPLUG',
> +    2:'CHANGE',
> +    3:'T10_PI',
> +}
> +
> +def get_feature_scsi_host(feature):
> +    return scsi_feature_name[feature]
> +
> +# 5.7 GPU Device
> +# 5.7.3 Feature bits
> +gpu_feature_name = {
> +    0:'VIRGL',
> +    1:'EDID',
> +}
> +
> +def get_feature_gpu(feature):
> +    return gpu_feature_name[feature]
> +
> +# 5.8 Input Device
> +# 5.8.3 Feature bits
> +# No feature bits
> +
> +# 5.9 Crypto Device
> +# 5.9.3 Feature bits
> +crypto_feature_name = {
> +    0:'REVISION_1',
> +    1:'CIPHER_STATELESS_MODE',
> +    2:'HASH_STATELESS_MODE',
> +    3:'MAC_STATELESS_MODE',
> +    4:'AEAD_STATELESS_MODE',
> +}
> +
> +def get_feature_crypto(feature):
> +    return crypto_feature_name[feature]
> +
> +# 5.10 Socket Device
> +# 5.10.3 Feature bits
> +# No feature bits
> +
> +# following feature bits from linux headers
> +# 9P
> +ninep_feature_name = {
> +    0:'MOUNT_TAG',
> +}
> +
> +def get_feature_9p(feature):
> +    return ninep_feature_name[feature]
> +
> +# IOMMU
> +iommu_feature_name = {
> +    0:'INPUT_RANGE',
> +    1:'DOMAIN_RANGE',
> +    2:'MAP_UNMAP',
> +    3:'BYPASS',
> +    4:'PROBE',
> +    5:'MMIO',
> +}
> +
> +def get_feature_iommu(feature):
> +    return iommu_feature_name[feature]
> +
> +# MEM
> +
> +mem_feature_name = {
> +    0:'ACPI_PXM',
> +}
> +
> +def get_feature_memory(feature):
> +    return mem_feature_name[feature]
> +
> +get_feature = {
> +    1:get_feature_net,
> +    2:get_feature_block,
> +    3:get_feature_console,
> +    5:get_feature_balloon_traditional,
> +    8:get_feature_scsi_host,
> +    9:get_feature_9p,
> +    16:get_feature_gpu,
> +    20:get_feature_crypto,
> +    23:get_feature_iommu,
> +    24:get_feature_memory,
> +}
> +
> +# 6 Reserved Feature Bits
> +reserved_feature_name = {
> +    24:'NOTIFY_ON_EMPTY',
> +    27:'ANY_LAYOUT',
> +    28:'RING_INDIRECT_DESC',
> +    29:'RING_EVENT_IDX',
> +    30:'BAD_FEATURE',
> +    32:'VERSION_1',
> +    33:'ACCESS_PLATFORM',
> +    34:'RING_PACKED',
> +    35:'IN_ORDER',
> +    36:'ORDER_PLATFORM',
> +    37:'SR_IOV',
> +    38:'NOTIFICATION_DATA'
> +}


I worry about maintaining all these feature bits though.

Can we somehow script this in scripts/update-linux-headers.sh ?


> +
> +vendor_name = {
> +    0x554D4551:'Virt (MMIO)',
> +    0x1AF4:'Red Hat, Inc. (PCI)',
> +}
> +
> +def get_status_name(status):
> +    result = ''
> +    for name in status_name:
> +        if name[0] & status:
> +            result = result + name[1] + ' '
> +    return result
> +
> +def list_interfaces(path):
> +    interfaces = ''
> +    for interface in sorted(os.listdir(path)):
> +        interfaces = interfaces + interface + ' '
> +    return interfaces
> +
> +def get_net_interfaces(path):
> +    return list_interfaces(path + '/net')
> +
> +def get_block_interfaces(path):
> +    return list_interfaces(path + '/block')
> +
> +def get_console_interfaces(path):
> +    return list_interfaces(path + '/block')
> +
> +def get_9p_interfaces(path):
> +    return open(path + '/mount_tag').read().rstrip()
> +
> +def get_gpu_interfaces(path):
> +    return list_interfaces(path + '/graphics')
> +
> +def get_input_interaces(path):
> +    return list_interfaces(path + '/input')
> +
> +get_interfaces = {
> +    1:get_net_interfaces,
> +    2:get_block_interfaces,
> +    3:get_console_interfaces,
> +    9:get_9p_interfaces,
> +    16:get_gpu_interfaces,
> +    18:get_input_interaces,
> +}
> +
> +busses = '/sys/bus/virtio'
> +devices = busses + '/devices'
> +
> +for device in sorted(os.listdir(devices)):
> +    bus = os.path.basename(os.path.dirname(os.readlink(devices + '/' + device)))
> +    path = devices + '/' + device
> +    subsystem = os.path.basename(os.readlink(path + '/subsystem'))
> +    device_id = int(open(path + '/device').read(), base = 0)
> +    vendor = int(open(path + '/vendor').read(), base = 0)
> +    driver = os.path.basename(os.readlink(path + '/driver'))
> +    modalias = open(path + '/modalias').read().rstrip()
> +    features = open(path + '/features').read().rstrip()
> +    status = open(path + '/status').read().rstrip()
> +
> +    print(bus + ' ' + device + ' ' + vendor_name[vendor] + ' Virtio ' + device_name[device_id])
> +    print('\tSubsystem: ' + subsystem)
> +    print('\tModalias: ' + modalias)
> +    print('\tStatus: ' + get_status_name(int(status, base=0)))
> +    bit=0
> +    for feature in features:
> +        if feature == '1':
> +            try:
> +                if bit >= 24:
> +                    print('\tFeature: ' + reserved_feature_name[bit])
> +                else:
> +                    print('\tFeature: ' + get_feature[device_id](bit))
> +            except:
> +                print('\tFeature: ' + str(bit))
> +        bit += 1
> +    print('\tKernel driver in use: ' + driver)
> +    try:
> +        print('\tInterfaces: ' + get_interfaces[device_id](path))
> +    except:
> +        print('\tNo interface')
> +    print('')
> -- 
> 2.31.1
> 
> 



  parent reply	other threads:[~2021-05-11  9:10 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-06 19:33 [PATCH] scripts: add a script to list virtio devices in a system Laurent Vivier
2021-05-06 19:50 ` Philippe Mathieu-Daudé
2021-05-07  6:17   ` Laurent Vivier
2021-05-11  8:33     ` Michael S. Tsirkin
2021-05-11  8:32 ` Michael S. Tsirkin [this message]
2021-05-11  9:17 ` Peter Maydell
2021-05-12  7:44   ` Laurent Vivier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210511043103-mutt-send-email-mst@kernel.org \
    --to=mst@redhat.com \
    --cc=lvivier@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).