From 0cfc9af8bd85f715171dff5b032b3867d1230489 Mon Sep 17 00:00:00 2001
From: Stefan Lankes <slankes@eonerc.rwth-aachen.de>
Date: Sun, 24 Jul 2022 09:35:11 +0200
Subject: [PATCH] add option to assign a task to the nic

the new syscall allows us to handle the network interrupt on the core,
where the network thread (see hermit-sys) is running
---
 src/arch/x86_64/kernel/apic.rs |  5 +++++
 src/drivers/net/mod.rs         |  2 ++
 src/drivers/net/rtl8139.rs     |  7 ++++++-
 src/drivers/net/virtio_net.rs  |  7 ++++++-
 src/syscalls/interfaces/mod.rs |  7 +++++++
 src/syscalls/mod.rs            | 11 +++++++++++
 6 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/arch/x86_64/kernel/apic.rs b/src/arch/x86_64/kernel/apic.rs
index 89f8594cd..8853d5dcf 100644
--- a/src/arch/x86_64/kernel/apic.rs
+++ b/src/arch/x86_64/kernel/apic.rs
@@ -634,6 +634,11 @@ pub fn init_local_apic() {
 	);
 }
 
+pub(crate) fn assign_irq_to_core(irq: u8, core_id: CoreId) {
+	info!("Assign interrupt {} to core {}", irq, core_id);
+	ioapic_inton(irq, core_id.try_into().unwrap()).unwrap();
+}
+
 fn calibrate_timer() {
 	// The APIC Timer is used to provide a one-shot interrupt for the tickless timer
 	// implemented through processor::get_timer_ticks.
diff --git a/src/drivers/net/mod.rs b/src/drivers/net/mod.rs
index 673e0b500..cb455bcfa 100644
--- a/src/drivers/net/mod.rs
+++ b/src/drivers/net/mod.rs
@@ -40,6 +40,8 @@ pub trait NetworkInterface {
 	fn set_polling_mode(&mut self, value: bool);
 	/// Handle interrupt and check if a packet is available
 	fn handle_interrupt(&mut self) -> bool;
+	/// handle interrupt on the same core, where the current task is running
+	fn assign_task_to_nic(&self);
 }
 
 #[cfg(all(not(feature = "newlib"), target_arch = "x86_64"))]
diff --git a/src/drivers/net/rtl8139.rs b/src/drivers/net/rtl8139.rs
index 0f52fc58f..87de243ba 100644
--- a/src/drivers/net/rtl8139.rs
+++ b/src/drivers/net/rtl8139.rs
@@ -8,10 +8,11 @@ use core::mem;
 
 use crate::arch::kernel::irq::*;
 use crate::arch::kernel::pci;
-use crate::arch::kernel::percore::increment_irq_counter;
+use crate::arch::kernel::percore::{core_id, increment_irq_counter};
 use crate::arch::mm::paging::virt_to_phys;
 use crate::arch::mm::VirtAddr;
 use crate::drivers::error::DriverError;
+use crate::drivers::net::apic::assign_irq_to_core;
 use crate::drivers::net::{network_irqhandler, NetworkInterface};
 use crate::x86::io::*;
 
@@ -217,6 +218,10 @@ impl NetworkInterface for RTL8139Driver {
 		self.mac
 	}
 
+	fn assign_task_to_nic(&self) {
+		assign_irq_to_core(self.irq, core_id());
+	}
+
 	/// Returns the current MTU of the device.
 	fn get_mtu(&self) -> u16 {
 		self.mtu
diff --git a/src/drivers/net/virtio_net.rs b/src/drivers/net/virtio_net.rs
index f9b4afc6c..b4c649254 100644
--- a/src/drivers/net/virtio_net.rs
+++ b/src/drivers/net/virtio_net.rs
@@ -4,7 +4,7 @@
 
 #[cfg(not(feature = "newlib"))]
 use super::netwakeup;
-use crate::arch::kernel::percore::increment_irq_counter;
+use crate::arch::kernel::percore::{core_id, increment_irq_counter};
 use crate::config::VIRTIO_MAX_QUEUE_SIZE;
 use crate::drivers::net::NetworkInterface;
 
@@ -16,6 +16,7 @@ use core::mem;
 use core::result::Result;
 use core::{cell::RefCell, cmp::Ordering};
 
+use crate::drivers::net::apic::assign_irq_to_core;
 #[cfg(not(feature = "pci"))]
 use crate::drivers::net::virtio_mmio::NetDevCfgRaw;
 #[cfg(feature = "pci")]
@@ -515,6 +516,10 @@ impl NetworkInterface for VirtioNetDriver {
 		}
 	}
 
+	fn assign_task_to_nic(&self) {
+		assign_irq_to_core(self.irq, core_id());
+	}
+
 	/// Returns the current MTU of the device.
 	/// Currently, if VIRTIO_NET_F_MAC is not set
 	//  MTU is set static to 1500 bytes.
diff --git a/src/syscalls/interfaces/mod.rs b/src/syscalls/interfaces/mod.rs
index 5f9b66f42..676a51ff8 100644
--- a/src/syscalls/interfaces/mod.rs
+++ b/src/syscalls/interfaces/mod.rs
@@ -127,6 +127,13 @@ pub trait SyscallInterface: Send + Sync {
 		Err(())
 	}
 
+	fn assign_task_to_nic(&self) {
+		#[cfg(not(target_arch = "aarch64"))]
+		if let Some(driver) = get_network_driver() {
+			driver.lock().assign_task_to_nic();
+		}
+	}
+
 	fn get_mtu(&self) -> Result<u16, ()> {
 		#[cfg(not(target_arch = "aarch64"))]
 		match get_network_driver() {
diff --git a/src/syscalls/mod.rs b/src/syscalls/mod.rs
index 037543640..cc0ac4d52 100644
--- a/src/syscalls/mod.rs
+++ b/src/syscalls/mod.rs
@@ -103,6 +103,17 @@ pub fn sys_get_mac_address() -> Result<[u8; 6], ()> {
 	kernel_function!(__sys_get_mac_address())
 }
 
+extern "C" fn __sys_assign_task_to_nic() {
+	unsafe {
+		SYS.assign_task_to_nic();
+	}
+}
+
+#[no_mangle]
+fn sys_assign_task_to_nic() {
+	kernel_function!(__sys_assign_task_to_nic());
+}
+
 #[allow(improper_ctypes_definitions)]
 extern "C" fn __sys_get_mtu() -> Result<u16, ()> {
 	unsafe { SYS.get_mtu() }
-- 
GitLab