From ac913e49f9666548ae877b1ead007f9000dc89b7 Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Fri, 24 Feb 2023 23:05:11 +0100
Subject: [PATCH] Pin kmain contexts to corresponding CPUs.

---
 src/context/list.rs | 19 +++++++++++++++----
 src/context/mod.rs  |  4 +++-
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/src/context/list.rs b/src/context/list.rs
index 7d2973a9..efca76da 100644
--- a/src/context/list.rs
+++ b/src/context/list.rs
@@ -50,10 +50,23 @@ impl ContextList {
         self.map.range(range)
     }
 
+    pub(crate) fn insert_context_raw(&mut self, id: ContextId) -> Result<&Arc<RwLock<Context>>> {
+        assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)?))).is_none());
+
+        Ok(self.map.get(&id).expect("Failed to insert new context. ID is out of bounds."))
+    }
+
     /// Create a new context.
     pub fn new_context(&mut self) -> Result<&Arc<RwLock<Context>>> {
+        // Zero is not a valid context ID, therefore add 1.
+        //
+        // FIXME: Ensure the number of CPUs can't switch between new_context calls.
+        let min = crate::cpu_count() + 1;
+
+        self.next_id = core::cmp::max(self.next_id, min);
+
         if self.next_id >= super::CONTEXT_MAX_CONTEXTS {
-            self.next_id = 1;
+            self.next_id = min;
         }
 
         while self.map.contains_key(&ContextId::from(self.next_id)) {
@@ -67,9 +80,7 @@ impl ContextList {
         let id = ContextId::from(self.next_id);
         self.next_id += 1;
 
-        assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)?))).is_none());
-
-        Ok(self.map.get(&id).expect("Failed to insert new context. ID is out of bounds."))
+        self.insert_context_raw(id)
     }
 
     /// Spawn a context from a function.
diff --git a/src/context/mod.rs b/src/context/mod.rs
index c3296d4f..7f5fc849 100644
--- a/src/context/mod.rs
+++ b/src/context/mod.rs
@@ -65,8 +65,10 @@ pub use self::arch::empty_cr3;
 
 pub fn init() {
     let mut contexts = contexts_mut();
-    let context_lock = contexts.new_context().expect("could not initialize first context");
+    let id = ContextId::from(crate::cpu_id() + 1);
+    let context_lock = contexts.insert_context_raw(id).expect("could not initialize first context");
     let mut context = context_lock.write();
+    context.sched_affinity = Some(crate::cpu_id());
 
     self::arch::EMPTY_CR3.call_once(|| unsafe { RmmA::table(TableKind::User) });
 
-- 
GitLab