QEMU 模拟的 E1000 是否在每次收到数据包后发送中断?

问题描述 投票:0回答:1

我正在做网络驱动程序实验室(MIT 6.1810的一部分)

当接收到多个数据包时(在多个进程同时 ping 的情况下),E1000 仅发出 1 个中断(因此,在服务中断时,代码必须扫描所有接收到的数据包),但是 文档(第 3.2.7.1.1 节) 说(强调我的):

将数据包定时器设置为 0b 将禁用数据包定时器和绝对定时器(已描述) 如下),并且每当新数据包被接收时就会生成 接收定时器中断 存储在内存中.

这是初始化设备的代码的一部分(其中

E1000_RDTR
是数据包计时器):

// ask e1000 for receive interrupts.
  regs[E1000_RDTR] = 0; // interrupt after every received packet (no timer)
  regs[E1000_RADV] = 0; // interrupt after every packet (no timer)

我的理解是,代码正是文档中描述的用于在每个数据包后接收中断的代码,但实际情况并非如此。

我的问题是,为什么 qemu 模拟的 E1000 在每个接收到的数据包后不发出中断,或者我错过了什么?

如果我尝试同时进行 10 个以上(11-15 之间)的 ping,有时,E1000 将无法传送所有收到的数据包(也就是说,当它发出中断时,我最多可以找到 10 个数据包,并且没有将引发更多中断)。

这是我在 e1000 引发中断时接收数据包的代码:

e1000_recv(void)
{
  int index = 0, i = 0;
  struct mbuf *m[RX_RING_SIZE];

  acquire(&e1000_lock);

  for (i = (regs[E1000_RDT]+1) % RX_RING_SIZE; rx_ring[i].status & E1000_RXD_STAT_DD; i++) {
    rx_mbufs[i]->len = rx_ring[i].length;
    rx_mbufs[i]->head = (char*)rx_ring[i].addr;

    m[index] = rx_mbufs[i];

    rx_mbufs[i] = mbufalloc(0);
    rx_ring[i].addr = (uint64) rx_mbufs[i]->head;
    rx_ring[i].status = 0;
    index++;
  }

  regs[E1000_RDT] = i-1;

  release(&e1000_lock);

  for (int i = 0; i < index; i++)
    net_rx(m[i]);
}
c kernel qemu riscv xv6
1个回答
0
投票

我最近用 xv6 做这个实验,遇到了同样的问题。经过相同的初始化过程。我设置变量来检测

e1000_intr
中的中断数量。发现10个进程调用ping函数后中断数不等于10。

我以为中断可能会因为

acquire
屏蔽中断而丢失,但是发现PLIC会把中断挂起,所以我认为这个行为应该是e1000 因此我认为这个行为应该是e1000的默认行为,说明书上的描述不一致。我也期待更专业的人给出更合理的答案。

© www.soinside.com 2019 - 2024. All rights reserved.