From: Matthias Kruk Date: Thu, 14 Nov 2019 07:46:53 +0000 (+0900) Subject: Add task_move_stack() function, which moves the current stack and updates ESP and EBP X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=8045d8888f5f5e47e5f2c2cb1c3523b6e539a12f;p=corax Add task_move_stack() function, which moves the current stack and updates ESP and EBP --- diff --git a/kernel/arch/task.S b/kernel/arch/task.S index c7e5e32..1897a6d 100644 --- a/kernel/arch/task.S +++ b/kernel/arch/task.S @@ -29,6 +29,7 @@ .global task_switch .global task_get_current .global task_set_current +.global task_move_stack task_prepare: /* @@ -397,3 +398,89 @@ task_set_current: 1: movl 4(%esp), %ecx movl %ecx, OFFSET_CPU_CTASK(%eax) ret + +task_move_stack: + /* + * void task_move_stack(void *dst, void *src, u32_t size) + * + * dst = 4(%esp) + * src = 8(%esp) + * size = 12(%esp) + */ + + /* + * For the sake of performance, don't copy the entire stack + * but just the portion that was actually used, i.e. the + * following: + * + * +-----+ <- src + size + * | | + * | | + * +-----+ <- ESP + * | | + * | | + * +-----+ <- src + */ + + /* compute the offset into the new stack */ + movl %esp, %edi + subl 8(%esp), %edi /* ESP - src = offset */ + addl 4(%esp), %edi /* offset + dst = nESP */ + + /* put ESP into ESI so we can copy from ESI to EDI */ + movl %esp, %esi + + /* calculate the upper limit for EDI and put it into EDX */ + movl 4(%esp), %edx + addl 12(%esp), %edx + + /* + * Update the stack pointers now, since we won't need the + * stack anymore afterwards. To update EBP, we need to subtract + * the old base and add the new one, so do that before updating + * ESP. + */ + subl 8(%esp), %ebp + addl 4(%esp), %ebp + movl %edi, %esp + + /* + * To copy the stack, keep copying from %(esi) to (%edi), + * increasing the two pointers, until %edi reaches %edx + */ + +0: cmpl %edx, %edi + jge 1f + + movl (%esi), %eax + movl %eax, (%edi) + addl $4, %esi + addl $4, %edi + jmp 0b + + /* iterate over the new stack, adjusting pointers */ +1: movl %esp, %edi + movl %edx, %esi + movl 8(%esp), %ecx /* lower bound */ + movl %ecx, %edx + addl 12(%esp), %edx /* upper bound */ + +2: cmpl %esi, %edi + jge 4f + + movl (%edi), %eax + cmpl %ecx, %eax + jl 3f + cmpl %edx, %eax + jge 3f + + /* adjust the pointer */ + subl %ecx, %eax + addl 4(%esp), %eax + /* store it on the stack */ + movl %eax, (%edi) +3: addl $4, %edi + jmp 2b + + /* Stacks have been copied and stack pointers updated. We're done. */ +4: ret diff --git a/kernel/include/arch.h b/kernel/include/arch.h index 10536e5..ed9b2b9 100644 --- a/kernel/include/arch.h +++ b/kernel/include/arch.h @@ -82,6 +82,7 @@ int task_switch(struct task*); task_t* task_get_current(void); void task_set_current(task_t*); +void task_move_stack(void*, void*, u32_t); /* * Definitions, types, and prototypes related to paging