Skip to content

Commit ab61d11

Browse files
committed
Add user mode task spawning interface
Kernel requires distinct privilege modes for kernel services and user applications. Return from trap instruction needs previous interrupt enable bit set to preserve interrupt state across privilege transitions. Parameterize context initialization to configure privilege mode during task creation. Set previous interrupt enable bit for correct interrupt behavior after mode transitions. Provide separate interface for spawning user mode tasks alongside existing kernel task interface.
1 parent a81d65e commit ab61d11

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

arch/riscv/hal.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,21 @@ void hal_timer_irq_disable(
105105
void hal_interrupt_tick(void); /* Enable interrupts on first task run */
106106
void *hal_build_initial_frame(
107107
void *stack_top,
108-
void (*task_entry)(void)); /* Build ISR frame for preemptive mode */
108+
void (*task_entry)(void),
109+
int user_mode); /* Build ISR frame for preemptive mode */
109110

110111
/* Initializes the context structure for a new task.
111-
* @ctx : Pointer to jmp_buf to initialize (must be non-NULL).
112-
* @sp : Base address of the task's stack (must be valid).
113-
* @ss : Total size of the stack in bytes (must be >= MIN_STACK_SIZE).
114-
* @ra : The task's entry point function (must be non-NULL).
112+
* @ctx : Pointer to jmp_buf to initialize (must be non-NULL).
113+
* @sp : Base address of the task's stack (must be valid).
114+
* @ss : Total size of the stack in bytes (must be >= MIN_STACK_SIZE).
115+
* @ra : The task's entry point function (must be non-NULL).
116+
* @user_mode : Non-zero to initialize for user mode, zero for machine mode.
115117
*/
116-
void hal_context_init(jmp_buf *ctx, size_t sp, size_t ss, size_t ra);
118+
void hal_context_init(jmp_buf *ctx,
119+
size_t sp,
120+
size_t ss,
121+
size_t ra,
122+
int user_mode);
117123

118124
/* Halts the CPU in an unrecoverable error state, shutting down if possible */
119125
void hal_panic(void);

include/sys/task.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,25 @@ void _yield(void);
187187

188188
/* Task Lifecycle Management */
189189

190-
/* Creates and starts a new task.
190+
/* Creates and starts a new task in machine mode.
191191
* @task_entry : Pointer to the task's entry function (void func(void))
192192
* @stack_size : The desired stack size in bytes (minimum is enforced)
193193
*
194194
* Returns the new task's ID on success. Panics on memory allocation failure.
195195
*/
196196
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size);
197197

198+
/* Creates and starts a new task in user mode.
199+
* User mode tasks run with reduced privileges and must use syscalls to access
200+
* kernel services. This provides memory protection and privilege separation.
201+
*
202+
* @task_entry : Pointer to the task's entry function (void func(void))
203+
* @stack_size : The desired stack size in bytes (minimum is enforced)
204+
*
205+
* Returns the new task's ID on success. Panics on memory allocation failure.
206+
*/
207+
int32_t mo_task_spawn_user(void *task_entry, uint16_t stack_size);
208+
198209
/* Cancels and removes a task from the system. A task cannot cancel itself.
199210
* @id : The ID of the task to cancel
200211
*

kernel/task.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,10 @@ static bool init_task_stack(tcb_t *tcb, size_t stack_size)
712712

713713
/* Task Management API */
714714

715-
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
715+
/* Internal task spawning implementation with privilege mode control */
716+
static int32_t task_spawn_impl(void *task_entry,
717+
uint16_t stack_size_req,
718+
int user_mode)
716719
{
717720
if (!task_entry)
718721
panic(ERR_TCB_ALLOC);
@@ -777,13 +780,13 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
777780

778781
/* Initialize execution context outside critical section. */
779782
hal_context_init(&tcb->context, (size_t) tcb->stack, new_stack_size,
780-
(size_t) task_entry);
783+
(size_t) task_entry, user_mode);
781784

782785
/* Initialize SP for preemptive mode.
783786
* Build initial ISR frame on stack with mepc pointing to task entry.
784787
*/
785788
void *stack_top = (void *) ((uint8_t *) tcb->stack + new_stack_size);
786-
tcb->sp = hal_build_initial_frame(stack_top, task_entry);
789+
tcb->sp = hal_build_initial_frame(stack_top, task_entry, user_mode);
787790

788791
printf("task %u: entry=%p stack=%p size=%u prio_level=%u time_slice=%u\n",
789792
tcb->id, task_entry, tcb->stack, (unsigned int) new_stack_size,
@@ -796,6 +799,16 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
796799
return tcb->id;
797800
}
798801

802+
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
803+
{
804+
return task_spawn_impl(task_entry, stack_size_req, false);
805+
}
806+
807+
int32_t mo_task_spawn_user(void *task_entry, uint16_t stack_size_req)
808+
{
809+
return task_spawn_impl(task_entry, stack_size_req, true);
810+
}
811+
799812
int32_t mo_task_cancel(uint16_t id)
800813
{
801814
if (id == 0 || id == mo_task_id())

0 commit comments

Comments
 (0)