diff --git a/src/drivers/e1000.cpp b/src/drivers/e1000.cpp index 61b6aa18f9..2f2a8a7fdc 100644 --- a/src/drivers/e1000.cpp +++ b/src/drivers/e1000.cpp @@ -25,6 +25,9 @@ #include // loosely based on OSdev article http://wiki.osdev.org/Intel_Ethernet_i217 +static int deferred_event = 0; +static std::vector deferred_devices; + e1000::e1000(hw::PCI_Device& d) : Link(Link_protocol{{this, &e1000::transmit}, mac()}, bufstore_), m_pcidev(d), bufstore_{1024, 2048} @@ -40,6 +43,11 @@ e1000::e1000(hw::PCI_Device& d) : __arch_enable_legacy_irq(this->m_irq); INFO2("Subscribed on IRQ %u", this->m_irq); + if (deferred_event == 0) + { + deferred_event = Events::get().subscribe(&e1000::do_deferred_xmit); + } + // shared-memory & I/O address this->shm_base = d.get_bar(0); this->io_base = d.iobase(); @@ -208,6 +216,8 @@ void e1000::event_handler() void e1000::recv_handler() { + uint16_t old_idx = 0xffff; + while (rx.desc[rx.current].status & 1) { auto& tk = rx.desc[rx.current]; @@ -221,11 +231,11 @@ void e1000::recv_handler() tk.addr = (uint64_t) this->new_rx_packet(); tk.status = 0; // go to next index - uint16_t old_idx = rx.current; + old_idx = rx.current; rx.current = (rx.current + 1) % NUM_RX_DESC; - write_cmd(REG_RXDESCTAIL, old_idx); } - + if (old_idx != 0xffff) + write_cmd(REG_RXDESCTAIL, old_idx); } void e1000::transmit(net::Packet_ptr pckt) @@ -265,12 +275,28 @@ void e1000::transmit_data(uint8_t* data, uint16_t length) tk.status = 0; tx.current = (tx.current + 1) % NUM_TX_DESC; + if (tx.deferred == false) + { + tx.deferred = true; + deferred_devices.push_back(this); + Events::get().trigger_event(deferred_event); + } +} +void e1000::xmit_kick() +{ write_cmd(REG_TXDESCTAIL, tx.current); + tx.deferred = false; +} +void e1000::do_deferred_xmit() +{ + for (auto& dev : deferred_devices) + dev->xmit_kick(); + deferred_devices.clear(); } void e1000::flush() { - + this->transmit(std::move(sendq)); } void e1000::poll() { @@ -283,7 +309,7 @@ void e1000::deactivate() } void e1000::move_to_this_cpu() { - + // TODO: implement me } #include @@ -294,5 +320,6 @@ static void register_func() PCI_manager::register_nic(PCI::VENDOR_INTEL, 0x100E, &e1000::new_instance); PCI_manager::register_nic(PCI::VENDOR_INTEL, 0x100F, &e1000::new_instance); PCI_manager::register_nic(PCI::VENDOR_INTEL, 0x153A, &e1000::new_instance); + PCI_manager::register_nic(PCI::VENDOR_INTEL, 0x1539, &e1000::new_instance); PCI_manager::register_nic(PCI::VENDOR_INTEL, 0x10EA, &e1000::new_instance); } diff --git a/src/drivers/e1000.hpp b/src/drivers/e1000.hpp index ef58cb9e6a..ecf1443d5e 100644 --- a/src/drivers/e1000.hpp +++ b/src/drivers/e1000.hpp @@ -90,6 +90,8 @@ class e1000 : public net::Link_layer void recv_handler(); bool can_transmit(); void transmit_data(uint8_t*, uint16_t); + void xmit_kick(); + static void do_deferred_xmit(); hw::PCI_Device& m_pcidev; std::vector irqs; @@ -127,6 +129,7 @@ class e1000 : public net::Link_layer struct tx_t { tx_desc desc[NUM_TX_DESC]; uint16_t current = 0; + bool deferred = false; } tx; // sendq as packet chain diff --git a/vmrunner/vm.schema.json b/vmrunner/vm.schema.json index c2dff759ed..705317567d 100644 --- a/vmrunner/vm.schema.json +++ b/vmrunner/vm.schema.json @@ -99,6 +99,11 @@ "vga" : { "description" : "Enable VGA screen", "enum" : ["std", "cirrus", "vmware", "qxl", "xenfb", "tcx", "cg3", "virtio", "none"] + }, + + "vfio" : { + "description" : "VFIO PCI-passthrough on device", + "type" : "string" } } diff --git a/vmrunner/vmrunner.py b/vmrunner/vmrunner.py index 987004fad4..6f4bcd9066 100644 --- a/vmrunner/vmrunner.py +++ b/vmrunner/vmrunner.py @@ -379,13 +379,17 @@ def boot(self, multiboot, kernel_args = "", image_name = None): if "vga" in self._config: vga_arg = ["-vga", str(self._config["vga"])] + pci_arg = [] + if "vfio" in self._config: + pci_arg = ["-device", "vfio-pci,host=" + self._config["vfio"]] + # TODO: sudo is only required for tap networking and kvm. Check for those. command = ["sudo", "--preserve-env", "qemu-system-x86_64"] if self._kvm_present: command.extend(["--enable-kvm"]) command += kernel_args - command += disk_args + net_args + mem_arg + vga_arg + mod_args + command += disk_args + net_args + mem_arg + vga_arg + pci_arg + mod_args #command_str = " ".join(command) #command_str.encode('ascii','ignore')