315 lines
6.6 KiB
ArmAsm
315 lines
6.6 KiB
ArmAsm
.globl entry, __switch_context, __exit_context, halt, init_exceptions
|
|
|
|
.text
|
|
.align 4
|
|
|
|
/*
|
|
* Entry point
|
|
* We start execution from here.
|
|
* It is assumed that CPU is in 32-bit protected mode and
|
|
* all segments are 4GB and base zero (flat model).
|
|
*/
|
|
entry:
|
|
/* Save boot context and switch to our main context.
|
|
* Main context is statically defined in C.
|
|
*/
|
|
pushl %cs
|
|
call __switch_context
|
|
|
|
/* We get here when the main context switches back to
|
|
* the boot context.
|
|
* Return to previous bootloader.
|
|
*/
|
|
ret
|
|
|
|
/*
|
|
* Switch execution context
|
|
* This saves registers, segments, and GDT in the stack, then
|
|
* switches the stack, and restores everything from the new stack.
|
|
* This function takes no argument. New stack pointer is
|
|
* taken from global variable __context, and old stack pointer
|
|
* is also saved to __context. This way we can just jump to
|
|
* this routine to get back to the original context.
|
|
*
|
|
* Call this routine with lcall or pushl %cs; call.
|
|
*/
|
|
__switch_context:
|
|
/* Save everything in current stack */
|
|
pushfl /* 56 */
|
|
pushl %ds /* 52 */
|
|
pushl %es /* 48 */
|
|
pushl %fs /* 44 */
|
|
pushl %gs /* 40 */
|
|
pushal /* 8 */
|
|
subl $8, %esp
|
|
movw %ss, (%esp) /* 0 */
|
|
sgdt 2(%esp) /* 2 */
|
|
|
|
#if 0
|
|
/* Swap %cs and %eip on the stack, so lret will work */
|
|
movl 60(%esp), %eax
|
|
xchgl %eax, 64(%esp)
|
|
movl %eax, 60(%esp)
|
|
#endif
|
|
|
|
/* At this point we don't know if we are on flat segment
|
|
* or relocated. So compute the address offset from %eip.
|
|
* Assuming CS.base==DS.base==SS.base.
|
|
*/
|
|
call 1f
|
|
1: popl %ebx
|
|
subl $1b, %ebx
|
|
|
|
/* Interrupts are not allowed... */
|
|
cli
|
|
|
|
/* Current context pointer is our stack pointer */
|
|
movl %esp, %esi
|
|
|
|
/* Normalize the ctx pointer */
|
|
subl %ebx, %esi
|
|
|
|
/* Swap it with new value */
|
|
xchgl %esi, __context(%ebx)
|
|
|
|
/* Adjust new ctx pointer for current address offset */
|
|
addl %ebx, %esi
|
|
|
|
/* Load new %ss and %esp to temporary */
|
|
movzwl (%esi), %edx
|
|
movl 20(%esi), %eax
|
|
|
|
/* Load new GDT */
|
|
lgdt 2(%esi)
|
|
|
|
/* Load new stack segment with new GDT */
|
|
movl %edx, %ss
|
|
|
|
/* Set new stack pointer, but we have to adjust it because
|
|
* pushal saves %esp value before pushal, and we want the value
|
|
* after pushal.
|
|
*/
|
|
leal -32(%eax), %esp
|
|
|
|
/* Load the rest from new stack */
|
|
popal
|
|
popl %gs
|
|
popl %fs
|
|
popl %es
|
|
popl %ds
|
|
popfl
|
|
|
|
/* Finally, load new %cs and %eip */
|
|
lret
|
|
|
|
__exit_context:
|
|
/* Get back to the original context */
|
|
pushl %cs
|
|
call __switch_context
|
|
|
|
/* We get here if the other context attempt to switch to this
|
|
* dead context. This should not happen. */
|
|
|
|
halt:
|
|
cli
|
|
hlt
|
|
jmp halt
|
|
|
|
/*
|
|
* initialize exception handler. All exceptions end up in the same
|
|
* C function.
|
|
*/
|
|
|
|
init_exceptions:
|
|
pushl %ebx
|
|
pushl %edi
|
|
|
|
/* Initialize the Interrupt Descriptor table */
|
|
leal _idt, %edi
|
|
leal vec0, %ebx
|
|
movl $(0x08 << 16), %eax /* cs selector */
|
|
|
|
1: movw %bx, %ax
|
|
movl %ebx, %edx
|
|
movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */
|
|
movl %eax, 0(%edi)
|
|
movl %edx, 4(%edi)
|
|
addl $6, %ebx
|
|
addl $8, %edi
|
|
cmpl $_idt_end, %edi
|
|
jne 1b
|
|
|
|
/* Load the Interrupt descriptor table */
|
|
lidt idtarg
|
|
|
|
movl $0, %eax
|
|
popl %edi
|
|
popl %ebx
|
|
ret
|
|
|
|
vec0:
|
|
pushl $0 /* error code */
|
|
pushl $0 /* vector */
|
|
jmp int_hand
|
|
vec1:
|
|
pushl $0 /* error code */
|
|
pushl $1 /* vector */
|
|
jmp int_hand
|
|
|
|
vec2:
|
|
pushl $0 /* error code */
|
|
pushl $2 /* vector */
|
|
jmp int_hand
|
|
|
|
vec3:
|
|
pushl $0 /* error code */
|
|
pushl $3 /* vector */
|
|
jmp int_hand
|
|
|
|
vec4:
|
|
pushl $0 /* error code */
|
|
pushl $4 /* vector */
|
|
jmp int_hand
|
|
|
|
vec5:
|
|
pushl $0 /* error code */
|
|
pushl $5 /* vector */
|
|
jmp int_hand
|
|
|
|
vec6:
|
|
pushl $0 /* error code */
|
|
pushl $6 /* vector */
|
|
jmp int_hand
|
|
vec7:
|
|
pushl $0 /* error code */
|
|
pushl $7 /* vector */
|
|
jmp int_hand
|
|
|
|
vec8:
|
|
/* error code */
|
|
pushl $8 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec9:
|
|
pushl $0 /* error code */
|
|
pushl $9 /* vector */
|
|
jmp int_hand
|
|
|
|
vec10:
|
|
/* error code */
|
|
pushl $10 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec11:
|
|
/* error code */
|
|
pushl $11 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec12:
|
|
/* error code */
|
|
pushl $12 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec13:
|
|
/* error code */
|
|
pushl $13 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec14:
|
|
/* error code */
|
|
pushl $14 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec15:
|
|
pushl $0 /* error code */
|
|
pushl $15 /* vector */
|
|
jmp int_hand
|
|
|
|
vec16:
|
|
pushl $0 /* error code */
|
|
pushl $16 /* vector */
|
|
jmp int_hand
|
|
|
|
vec17:
|
|
/* error code */
|
|
pushl $17 /* vector */
|
|
jmp int_hand
|
|
.word 0x9090
|
|
|
|
vec18:
|
|
pushl $0 /* error code */
|
|
pushl $18 /* vector */
|
|
jmp int_hand
|
|
|
|
vec19:
|
|
pushl $0 /* error code */
|
|
pushl $19 /* vector */
|
|
jmp int_hand
|
|
|
|
__divide_error:
|
|
pushl $0 /* error code */
|
|
pushl $20 /* vector */
|
|
jmp int_hand
|
|
.global __divide_error
|
|
|
|
int_hand:
|
|
/* At this point on the stack there is:
|
|
* 0(%esp) vector
|
|
* 4(%esp) error code
|
|
* 8(%esp) eip
|
|
* 12(%esp) cs
|
|
* 16(%esp) eflags
|
|
*/
|
|
pushl %edi
|
|
pushl %esi
|
|
pushl %ebp
|
|
/* Original stack pointer */
|
|
leal 32(%esp), %ebp
|
|
pushl %ebp
|
|
pushl %ebx
|
|
pushl %edx
|
|
pushl %ecx
|
|
pushl %eax
|
|
|
|
pushl %esp /* Pointer to structure on the stack */
|
|
|
|
call x86_exception
|
|
pop %eax /* Drop the pointer */
|
|
|
|
popl %eax
|
|
popl %ecx
|
|
popl %edx
|
|
popl %ebx
|
|
popl %ebp /* Ignore saved %esp value */
|
|
popl %ebp
|
|
popl %esi
|
|
popl %edi
|
|
|
|
addl $8, %esp /* pop of the vector and error code */
|
|
|
|
iret
|
|
|
|
idtarg:
|
|
.word _idt_end - _idt - 1 /* limit */
|
|
.long _idt
|
|
.word 0
|
|
_idt:
|
|
.fill 20, 8, 0 # idt is unitiailzed
|
|
_idt_end:
|
|
|
|
.globl arch_nvram_size, arch_nvram_get, arch_nvram_put
|
|
arch_nvram_size:
|
|
xor %eax, %eax
|
|
ret
|
|
|
|
arch_nvram_get:
|
|
ret
|
|
|
|
arch_nvram_put:
|
|
ret
|