QEMU源码全解析 —— PCI设备模拟(12)

发布时间:2024年01月15日

接前一篇文章:

3. PCI设备中断模拟

上一节介绍了操作系统驱动设备的MMIO/PIO基址以及QEMU是如何模拟该机制的。操作系统与设备通信的另一方面则是设备产生了事件,通过中断机制通知操作系统。设备寄存器和I/O端口提供操作系统向设备的通信,而中断机制则提供了设备向操作系统的通信。

前文书介绍了每个PCI设备都有4个引脚,都可以触发中断,单功能设备都用INTA#触发中断,只有多功能设备会用到INTB#、INTC#、INTD#等中断引脚。使用哪个引脚通常体现在QEMU在设备具现化的时候写入PCI设备配置空间内0x3d处的一个字节。比如下边的代码显示了e1000设备使用了INTA#引脚。

hw/net/e1000.c中:

static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
{
    DeviceState *dev = DEVICE(pci_dev);
    E1000State *d = E1000(pci_dev);
    uint8_t *pci_conf;
    uint8_t *macaddr;

    pci_dev->config_write = e1000_write_config;

    pci_conf = pci_dev->config;

    /* TODO: RST# value should be 0, PCI spec 6.2.4 */
    pci_conf[PCI_CACHE_LINE_SIZE] = 0x10;

    pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */

    e1000_mmio_setup(d);

    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);

    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);

    qemu_macaddr_default_if_unset(&d->conf.macaddr);
    macaddr = d->conf.macaddr.a;

    e1000x_core_prepare_eeprom(d->eeprom_data,
                               e1000_eeprom_template,
                               sizeof(e1000_eeprom_template),
                               PCI_DEVICE_GET_CLASS(pci_dev)->device_id,
                               macaddr);

    d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
                          object_get_typename(OBJECT(d)), dev->id,
                          &dev->mem_reentrancy_guard, d);

    qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);

    d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
    d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
    d->flush_queue_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
                                        e1000_flush_queue_timer, d);
}

QEMU中很多地方都定义了PI_INTERRUPT_PIN,但无论是哪一处,都是如下:

#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */

PCI总线上能够挂载多个设备,而通常中断控制器的中断线是有限的,加上一些中断线已经分配给了主板上的设备,所以通常留给PCI设备的中断个数只有4个或者8个,QEMU在i440fx主板上只有4个中断。将PCI设备使用的中断引脚与中断控制器的中断线关联起来,通常叫作PCI设备的中断路由。

PCI设备中断路由器涉及3个概念:一是已经介绍过的PCI设备的中断引脚;二是中断控制器的中断线;三是所谓的PCI链接设备(PCI Linking device,LNK)。PCI链接设备可以理解成用来将PCI总线与中断线连接在一起的设备。i440fx主板模拟给PCI设备的中断线有4条,所以通常有LNKA、LNKB、LNKC、LNKD这4个PCI链接设备。

PCI设备中断路由包括两个部分一个是设备INTA连接到LNKA的交错链接,这样可以均衡每个LNKA的负载。因为大多数设备都是用INTA触发中断,所以如此连接使每个设备的INTA都链接到了不同的PCI链接设备上;PCI中断路由的第二个部分包括PCI链接设备路由到具体的IRQ线上,这通常是由BIOS设定的。这里需要注意的是,LNK[A-D]路由到的IRQ不一定是一一对应的,可能有两个LNK*链接到同一个IRQ的情况

PCI链接设备到中断控制器上的路由信息是通过SeaBIOS配置完成的。具体细节请看下回。

文章来源:https://blog.csdn.net/phmatthaus/article/details/135595941
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。