device probe - virtio

device の probe

virtio-console は PCI のデバイスとして export されているので普通に見つかる。

PciInf pciInf;
Pci pci;
pci.CheckPciExist(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_CONSOLE, &pciInf);

if (pciInf.isExist) {
    _printf("device found\n");
    _printf("base=%x\n", pciInf.baseAdress & ~1);
    _printf("irqLine=%x\n", pciInf.irqLine);
} else {
    _printf("device not found\n");
}
}

このベースアドレスを基準に各 virtio device に対して read/write できる。

_printf("%x", inp32((pciInf.baseAdress & ~1) + VIRTIO_PCI_HOST_FEATURES));

利用可能なのは

VIRTIO_PCI_HOST_FEATURES
VIRTIO_PCI_GUEST_FEATURES
VIRTIO_PCI_QUEUE_PFN
VIRTIO_PCI_QUEUE_NUM
VIRTIO_PCI_QUEUE_SEL
VIRTIO_PCI_STATUS
VIRTIO_PCI_ISR

config

virtio-net では PCI config で mac address / status が取り出せる。

struct virtio_net_config
{
    /* The config defining mac address (6 bytes) */
    uint8_t mac[6];
    /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
    uint16_t status;
} __attribute__((packed));

int main(int argc, char* argv[])
{
    PciInf pciInf;
    Pci pci;
    pci.CheckPciExist(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_NET, &pciInf);

    if (pciInf.isExist)
    {
        _printf("device found\n");
        _printf("base=%x\n", pciInf.baseAdress);
        _printf("base=%x\n", pciInf.baseAdress & ~1);
        _printf("irqLine=%x\n", pciInf.irqLine);

        struct virtio_net_config config;
        for (int i = 0; i < sizeof(config); i += 4) {
            (((uint32_t*)&config)[i / 4]) = inp32((pciInf.baseAdress & ~1) + VIRTIO_PCI_CONFIG + i);
        }

        printf("config.mac= %x:%x:%x:%x:%x:%x\n", config.mac[0], config.mac[1], config.mac[2], config.mac[3], config.mac[4], config.mac[5]);
    } else {
        _printf("device not found\n");
    }
    return 0;
}

qemu 起動オプション

% qemu -virtioconsole stdio -net nic,model=virtio -cdrom /home/taro/mona/tool/mkimg/mona.iso -fda /home/taro/mona/tool/mkimg/mona.img -boot d

思い出せない

取り出した baseAdress & ~1 するのはなぜだっけか?思い出せない。
id:Yamami さんならご存じかな。

これか。

BARs are used to hold memory addresses used by the device, for example the DMA address. It can also hold I/O ports. To distinguish between them, you can check if the lowest bit is 1. If it is, the lower word represents the I/O port. Also don't forget to zero the lowest bit.

todo

  • virtio queue の利用方法が分からない
    • pfn って何?これが鍵か?