version 1.1.1.1, 2008/06/03 10:38:45 |
version 1.1.1.1.2.1, 2008/08/13 17:12:29 |
|
|
*/ |
*/ |
|
|
#include <conf/config.h> |
#include <conf/config.h> |
|
#include <machine/asm.h> |
#include <platform.h> |
#include <platform.h> |
#include <cpu.h> |
#include <cpu.h> |
|
|
#define ENTRY(x) .global x; .align 4,0x90; x##: |
|
|
|
/* |
/* |
* Macro to save/restore registers |
* Macro to save/restore registers |
* |
* |
|
|
movl %edx, %ds; \ |
movl %edx, %ds; \ |
movl %edx, %es; |
movl %edx, %es; |
|
|
/* |
|
* Pointer to boot infomation |
|
*/ |
|
.section ".rodata" |
|
ENTRY(boot_info) |
|
.long PAGE_OFFSET + BOOT_INFO |
|
|
|
/* |
|
* Interrupt nest counter. |
|
* |
|
* This counter is incremented in the entry of interrupt handler |
|
* to switch the interrupt stack. Since all interrupt handlers |
|
* share same one interrupt stack, each handler must pay attention |
|
* to the stack overflow. |
|
*/ |
|
.section ".bss" |
|
irq_nesting: |
|
.long 0 |
|
|
|
.section ".text" |
.section ".text" |
|
|
/* |
/* |
|
|
/* |
/* |
* Call kernel main routine |
* Call kernel main routine |
*/ |
*/ |
call kernel_main |
call main |
/* NOTREACHED */ |
/* NOTREACHED */ |
cli |
cli |
hlt |
hlt |
|
|
ENTRY(interrupt_common) |
ENTRY(interrupt_common) |
SAVE_ALL |
SAVE_ALL |
SETUP_SEG |
SETUP_SEG |
incl irq_nesting |
incl irq_nesting /* Increment nesting level */ |
cmpl $1, irq_nesting /* Outermost interrupt ? */ |
cmpl $1, irq_nesting /* Outermost interrupt ? */ |
jne nested_irq |
jne nested_irq |
mov %esp, %ebp /* Save current stack */ |
mov %esp, %ebp /* Save current stack */ |
|
|
decl irq_nesting |
decl irq_nesting |
call sched_unlock /* Try to preempt */ |
call sched_unlock /* Try to preempt */ |
testl $3, 0x30(%esp) /* Return to kernel mode ? */ |
testl $3, 0x30(%esp) /* Return to kernel mode ? */ |
jz interrupt_ret |
jz interrupt_ret /* Skip exception if kernel mode */ |
call exception_deliver /* Check exception */ |
call exception_deliver /* Check exception */ |
interrupt_ret: |
interrupt_ret: |
RESTORE_ALL |
RESTORE_ALL |
|
|
* |
* |
* syntax - void cpu_switch(kern_regs *prev, kern_regs *next) |
* syntax - void cpu_switch(kern_regs *prev, kern_regs *next) |
* |
* |
* Note: GCC assumes ebp,edi,esi registers are not changed in each routine. |
* Note: GCC assumes ebx,ebp,edi,esi registers are not changed in each routine. |
*/ |
*/ |
ENTRY(cpu_switch) |
ENTRY(cpu_switch) |
movl 4(%esp), %ebx /* Point ebx to previous registers */ |
movl 4(%esp), %ecx /* Point ecx to previous registers */ |
movl (%esp), %eax /* Get return address */ |
movl (%esp), %eax /* Get return address */ |
movl %eax, 0(%ebx) /* Save it as eip */ |
movl %eax, 0(%ecx) /* Save it as eip */ |
movl %edi, 4(%ebx) /* Save edi */ |
movl %ebx, 4(%ecx) /* Save ebx */ |
movl %esi, 8(%ebx) /* Save esi */ |
movl %edi, 8(%ecx) /* Save edi */ |
movl %ebp, 12(%ebx) /* Save ebp */ |
movl %esi, 12(%ecx) /* Save esi */ |
movl %esp, 16(%ebx) /* Save esp */ |
movl %ebp, 16(%ecx) /* Save ebp */ |
movl 8(%esp), %ebx /* Point ebx to next registers */ |
movl %esp, 20(%ecx) /* Save esp */ |
movl 4(%ebx), %edi /* Restore edi */ |
movl 8(%esp), %ecx /* Point ecx to next registers */ |
movl 8(%ebx), %esi /* Restore esi */ |
movl 4(%ecx), %ebx /* Restore ebx */ |
movl 12(%ebx), %ebp /* Restore ebp */ |
movl 8(%ecx), %edi /* Restore edi */ |
movl 16(%ebx), %esp /* Restore esp */ |
movl 12(%ecx), %esi /* Restore esp */ |
movl 0(%ebx), %eax /* Get eip */ |
movl 16(%ecx), %ebp /* Restore ebp */ |
|
movl 20(%ecx), %esp /* Restore esp */ |
|
movl 0(%ecx), %eax /* Get eip */ |
movl %eax, (%esp) /* Restore it as return address */ |
movl %eax, (%esp) /* Restore it as return address */ |
ret |
ret |
|
|
|
|
* Copy data from user to kernel space. |
* Copy data from user to kernel space. |
* Returns 0 on success, or EFAULT on page fault. |
* Returns 0 on success, or EFAULT on page fault. |
* |
* |
* syntax - int umem_copyin(void *uaddr, void *kaddr, size_t len) |
* syntax - int umem_copyin(const void *uaddr, void *kaddr, size_t len) |
*/ |
*/ |
.global known_fault1 |
.global known_fault1 |
ENTRY(umem_copyin) |
ENTRY(umem_copyin) |
|
|
* Copy data to user from kernel space. |
* Copy data to user from kernel space. |
* Returns 0 on success, or EFAULT on page fault. |
* Returns 0 on success, or EFAULT on page fault. |
* |
* |
* syntax - int umem_copyout(void *kaddr, void *uaddr, size_t len) |
* syntax - int umem_copyout(const void *kaddr, void *uaddr, size_t len) |
*/ |
*/ |
.global known_fault2 |
.global known_fault2 |
ENTRY(umem_copyout) |
ENTRY(umem_copyout) |
|
|
int $3 |
int $3 |
hlt |
hlt |
|
|
|
ENTRY(flush_tlb) |
|
movl %cr3, %eax |
|
movl %eax, %cr3 |
|
ret |
|
|
|
ENTRY(ltr) |
|
movl 4(%esp), %eax |
|
ltr %ax |
|
ret |
|
|
|
ENTRY(lgdt) |
|
movl 4(%esp), %eax |
|
lgdt (%eax) |
|
jmp 1f /* Flush the prefetch queue */ |
|
nop |
|
1: |
|
movl $(KERNEL_DS), %eax |
|
movl %eax, %ds |
|
movl %eax, %es |
|
movl %eax, %fs |
|
movl %eax, %gs |
|
movl %eax, %ss |
|
movl $(KERNEL_CS), %eax |
|
pushl %eax |
|
pushl $2f |
|
lret |
|
2: |
|
ret |
|
|
|
ENTRY(lidt) |
|
movl 4(%esp), %eax |
|
lidt (%eax) |
|
ret |
|
|
|
ENTRY(get_eflags) |
|
pushfl |
|
popl %eax |
|
ret |
|
|
|
ENTRY(set_eflags) |
|
movl 4(%esp), %eax |
|
pushl %eax |
|
popfl |
|
ret |
|
|
|
ENTRY(set_cr0) |
|
movl 4(%esp), %eax |
|
movl %eax, %cr0 |
|
ret |
|
|
|
ENTRY(get_cr0) |
|
movl %cr0, %eax |
|
ret |
|
|
|
ENTRY(get_cr2) |
|
movl %cr2, %eax |
|
ret |
|
|
|
ENTRY(set_cr3) |
|
movl 4(%esp), %eax |
|
movl %eax, %cr3 |
|
ret |
|
|
|
ENTRY(get_cr3) |
|
movl %cr3, %eax |
|
ret |
|
|
|
ENTRY(outb) |
|
movl 4(%esp), %eax |
|
movl 8(%esp), %edx |
|
outb %al, %dx |
|
ret |
|
|
|
ENTRY(inb) |
|
movl 4(%esp), %edx |
|
xorl %eax, %eax |
|
inb %dx, %al |
|
ret |
|
|
|
ENTRY(outb_p) |
|
movl 4(%esp), %eax |
|
movl 8(%esp), %edx |
|
outb %al, %dx |
|
outb %al, $0x80 |
|
ret |
|
|
|
ENTRY(inb_p) |
|
movl 4(%esp), %edx |
|
xorl %eax, %eax |
|
inb %dx, %al |
|
outb %al, $0x80 |
|
ret |
|
|
|
ENTRY(interrupt_disable) |
|
cli |
|
ret |
|
|
|
ENTRY(interrupt_enable) |
|
sti |
|
ret |
|
|
|
ENTRY(breakpoint) |
|
int $3 |
|
ret |
|
|
|
ENTRY(cpu_idle) |
|
sti |
|
hlt |
|
ret |
|
|
.align 4 |
.align 4 |
null_idt: |
null_idt: |
.word 0 |
.word 0 |
.long 0 |
.long 0 |
|
|
|
|
|
/* |
|
* Pointer to boot infomation |
|
*/ |
|
.section ".rodata" |
|
.global boot_info |
|
boot_info: |
|
.long PAGE_OFFSET + BOOT_INFO |
|
|
|
/* |
|
* Interrupt nest counter. |
|
* |
|
* This counter is incremented in the entry of interrupt handler |
|
* to switch the interrupt stack. Since all interrupt handlers |
|
* share same one interrupt stack, each handler must pay attention |
|
* to the stack overflow. |
|
*/ |
|
.section ".bss" |
|
irq_nesting: |
|
.long 0 |