diff --git a/efi/OVMF_VARS.fd b/efi/OVMF_VARS.fd
index c264692..5a5f193 100644
Binary files a/efi/OVMF_VARS.fd and b/efi/OVMF_VARS.fd differ
diff --git a/kernel/src/entry/kernel_entry.cpp b/kernel/src/entry/kernel_entry.cpp
index 4bf27f3..35c7d38 100644
--- a/kernel/src/entry/kernel_entry.cpp
+++ b/kernel/src/entry/kernel_entry.cpp
@@ -40,6 +40,19 @@ char __usermodeKernelEntryStack[USERMODE_KERNEL_ENTRY_STACK_SIZE];
 
 void _kuser_entry();
 
+struct ThreadParams {
+    int x, y, z;
+    char* test;
+};
+
+void testFunction(void* param) {
+    ThreadParams* data = (ThreadParams*)param;
+    kuPrint("Request is being serviced by core %i\n", getCurrentCpuId());
+    kuPrint("x: %i, y: %i, z: %i\n", data->x, data->y, data->z);
+    kuPrint("test: %s\n", data->test);
+    exitKernelThread();
+}
+
 __PRIVILEGED_CODE void _kentry(KernelEntryParams* params) {
     // Setup kernel stack
     uint64_t kernelStackTop = reinterpret_cast<uint64_t>(params->kernelStack) + PAGE_SIZE;
@@ -189,6 +202,15 @@ void _kuser_entry() {
     });
 #endif
 
+    ThreadParams* params = new ThreadParams();
+    params->x = 4554;
+    params->y = 72;
+    params->z = 42;
+    params->test = (char*)"Stellux is working!";
+    
+    Task* testTask = createKernelTask(testFunction, params);
+    sched.addTask(testTask);
+
     // Infinite loop
     while (1) { __asm__ volatile("nop"); }
 }
diff --git a/kernel/src/entry/tests/multithreading.test.cpp b/kernel/src/entry/tests/multithreading.test.cpp
index cf51a77..de5d1bc 100644
--- a/kernel/src/entry/tests/multithreading.test.cpp
+++ b/kernel/src/entry/tests/multithreading.test.cpp
@@ -9,7 +9,7 @@
 DECLARE_SPINLOCK(mtUnitTestLock);
 uint64_t g_mtUnitTestCounter = 0;
 
-void incrementMtUnitTestCounter() {
+void incrementMtUnitTestCounter(void*) {
     acquireSpinlock(&mtUnitTestLock);
     ++g_mtUnitTestCounter;
     releaseSpinlock(&mtUnitTestLock);
@@ -24,7 +24,7 @@ DECLARE_UNIT_TEST("Multithreading Test - Kernel Task Creation", mtTaskCreationUn
     Task** taskArray = (Task**)kmalloc(sizeof(Task*) * iterations);
 
     for (size_t i = 0; i < iterations; i++) {
-        Task* task = createKernelTask(incrementMtUnitTestCounter);
+        Task* task = createKernelTask(incrementMtUnitTestCounter, nullptr);
         ASSERT_TRUE(task, "Failed to allocate a kernel task");
 
         taskArray[i] = task;
@@ -62,7 +62,7 @@ DECLARE_UNIT_TEST("Multithreading Test - Single Core", mtSingleCoreUnitTest) {
 
     // Create the tasks
     for (size_t i = 0; i < taskCount; i++) {
-        Task* task = createKernelTask(incrementMtUnitTestCounter);
+        Task* task = createKernelTask(incrementMtUnitTestCounter, nullptr);
         ASSERT_TRUE(task, "Failed to allocate a kernel task");
 
         taskArray[i] = task;
@@ -111,7 +111,7 @@ DECLARE_UNIT_TEST("Multithreading Test - Multi Core (Automatic Load Balancing)",
 
     // Create the tasks
     for (size_t i = 0; i < taskCount; i++) {
-        Task* task = createKernelTask(incrementMtUnitTestCounter);
+        Task* task = createKernelTask(incrementMtUnitTestCounter, nullptr);
         ASSERT_TRUE(task, "Failed to allocate a kernel task");
 
         taskArray[i] = task;
diff --git a/kernel/src/sched/sched.cpp b/kernel/src/sched/sched.cpp
index 4c30b1d..13d7247 100644
--- a/kernel/src/sched/sched.cpp
+++ b/kernel/src/sched/sched.cpp
@@ -189,7 +189,8 @@ size_t Scheduler::_loadBalance() {
     return cpu;
 }
 
-Task* createKernelTask(void (*taskEntry)(), int priority) {
+Task* createKernelTask(TaskEntryFn_t entry, void* taskData, int priority) {
+    (void)taskData;
     Task* task = (Task*)kmalloc(sizeof(Task));
     if (!task) {
         return nullptr;
@@ -219,7 +220,8 @@ Task* createKernelTask(void (*taskEntry)(), int priority) {
     // Initialize the CPU context
     task->context.rsp = (uint64_t)userStack + SCHED_USER_STACK_SIZE; // Point to the top of the stack
     task->context.rbp = task->context.rsp;       // Point to the top of the stack
-    task->context.rip = (uint64_t)taskEntry;     // Set instruction pointer to the task function
+    task->context.rip = (uint64_t)entry;         // Set instruction pointer to the task function
+    task->context.rdi = (uint64_t)taskData;      // Task parameter buffer pointer
     task->context.rflags = 0x200;                // Enable interrupts
 
     // Set up segment registers for user space. These values correspond to the selectors in the GDT.
diff --git a/kernel/src/sched/sched.h b/kernel/src/sched/sched.h
index ed4933d..c003045 100644
--- a/kernel/src/sched/sched.h
+++ b/kernel/src/sched/sched.h
@@ -6,6 +6,7 @@
 #include <sync.h>
 
 using Task = PCB;
+typedef void (*TaskEntryFn_t)(void*);
 
 EXTERN_C Task g_kernelSwapperTasks[MAX_CPUS];
 
@@ -70,7 +71,7 @@ class Scheduler {
 // Allocates a task object for a new kernel thread that will
 // start its execution at a given function in userspace (DPL=3).
 //
-Task* createKernelTask(void (*taskEntry)(), int priority = 0);
+Task* createKernelTask(TaskEntryFn_t entry, void* taskData, int priority = 0);
 
 //
 // Destroys a task object, releasing any resources allocated for the task.