Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/swtch.s
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | ENTRY(cpu_throw) | ||||
movl PCPU(CURPMAP), %ebx | movl PCPU(CURPMAP), %ebx | ||||
#ifdef SMP | #ifdef SMP | ||||
lock | lock | ||||
#endif | #endif | ||||
btrl %esi, PM_ACTIVE(%ebx) /* clear old */ | btrl %esi, PM_ACTIVE(%ebx) /* clear old */ | ||||
1: | 1: | ||||
movl 8(%esp),%ecx /* New thread */ | movl 8(%esp),%ecx /* New thread */ | ||||
movl TD_PCB(%ecx),%edx | movl TD_PCB(%ecx),%edx | ||||
movl PCB_CR3(%edx),%eax | |||||
movl %eax,%cr3 | |||||
/* set bit in new pm_active */ | /* set bit in new pm_active */ | ||||
movl TD_PROC(%ecx),%eax | movl TD_PROC(%ecx),%eax | ||||
movl P_VMSPACE(%eax), %ebx | movl P_VMSPACE(%eax), %ebx | ||||
addl $VM_PMAP, %ebx | addl $VM_PMAP, %ebx | ||||
movl %ebx, PCPU(CURPMAP) | movl %ebx, PCPU(CURPMAP) | ||||
#ifdef SMP | #ifdef SMP | ||||
lock | lock | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | 1: | ||||
/* have we used fp, and need a save? */ | /* have we used fp, and need a save? */ | ||||
cmpl %ecx,PCPU(FPCURTHREAD) | cmpl %ecx,PCPU(FPCURTHREAD) | ||||
jne 1f | jne 1f | ||||
pushl PCB_SAVEFPU(%edx) /* h/w bugs make saving complicated */ | pushl PCB_SAVEFPU(%edx) /* h/w bugs make saving complicated */ | ||||
call npxsave /* do it in a big C function */ | call npxsave /* do it in a big C function */ | ||||
popl %eax | popl %eax | ||||
1: | 1: | ||||
/* Save is done. Now fire up new thread. Leave old vmspace. */ | /* Save is done. Now fire up new thread. */ | ||||
movl 4(%esp),%edi | movl 4(%esp),%edi | ||||
movl 8(%esp),%ecx /* New thread */ | movl 8(%esp),%ecx /* New thread */ | ||||
movl 12(%esp),%esi /* New lock */ | movl 12(%esp),%esi /* New lock */ | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
testl %ecx,%ecx /* no thread? */ | testl %ecx,%ecx /* no thread? */ | ||||
jz badsw3 /* no, panic */ | jz badsw3 /* no, panic */ | ||||
#endif | #endif | ||||
movl TD_PCB(%ecx),%edx | movl TD_PCB(%ecx),%edx | ||||
/* switch address space */ | /* Switchout td_lock */ | ||||
movl PCB_CR3(%edx),%eax | |||||
movl %cr3,%ebx /* The same address space? */ | |||||
cmpl %ebx,%eax | |||||
je sw0 | |||||
movl %eax,%cr3 /* new address space */ | |||||
movl %esi,%eax | movl %esi,%eax | ||||
movl PCPU(CPUID),%esi | movl PCPU(CPUID),%esi | ||||
SETOP %eax,TD_LOCK(%edi) /* Switchout td_lock */ | SETOP %eax,TD_LOCK(%edi) | ||||
/* Release bit from old pmap->pm_active */ | /* Release bit from old pmap->pm_active */ | ||||
movl PCPU(CURPMAP), %ebx | movl PCPU(CURPMAP), %ebx | ||||
#ifdef SMP | #ifdef SMP | ||||
lock | lock | ||||
#endif | #endif | ||||
btrl %esi, PM_ACTIVE(%ebx) /* clear old */ | btrl %esi, PM_ACTIVE(%ebx) /* clear old */ | ||||
/* Set bit in new pmap->pm_active */ | /* Set bit in new pmap->pm_active */ | ||||
movl TD_PROC(%ecx),%eax /* newproc */ | movl TD_PROC(%ecx),%eax /* newproc */ | ||||
movl P_VMSPACE(%eax), %ebx | movl P_VMSPACE(%eax), %ebx | ||||
addl $VM_PMAP, %ebx | addl $VM_PMAP, %ebx | ||||
movl %ebx, PCPU(CURPMAP) | movl %ebx, PCPU(CURPMAP) | ||||
#ifdef SMP | #ifdef SMP | ||||
lock | lock | ||||
#endif | #endif | ||||
btsl %esi, PM_ACTIVE(%ebx) /* set new */ | btsl %esi, PM_ACTIVE(%ebx) /* set new */ | ||||
jmp sw1 | jmp sw1 | ||||
sw0: | sw0: | ||||
SETOP %esi,TD_LOCK(%edi) /* Switchout td_lock */ | SETOP %esi,TD_LOCK(%edi) /* Switchout td_lock */ | ||||
sw1: | sw1: | ||||
BLOCK_SPIN(%ecx) | BLOCK_SPIN(%ecx) | ||||
/* | /* | ||||
* At this point, we've switched address spaces and are ready | * At this point, we have managed thread locks and are ready | ||||
* to load up the rest of the next context. | * to load up the rest of the next context. | ||||
*/ | */ | ||||
/* Load a pointer to the thread kernel stack into PCPU. */ | |||||
leal -VM86_STACK_SPACE(%edx), %eax /* leave space for vm86 */ | |||||
movl %eax, PCPU(KESP0) | |||||
cmpl $0, PCB_EXT(%edx) /* has pcb extension? */ | cmpl $0, PCB_EXT(%edx) /* has pcb extension? */ | ||||
je 1f /* If not, use the default */ | je 1f /* If not, use the default */ | ||||
movl $1, PCPU(PRIVATE_TSS) /* mark use of private tss */ | movl $1, PCPU(PRIVATE_TSS) /* mark use of private tss */ | ||||
movl PCB_EXT(%edx), %edi /* new tss descriptor */ | movl PCB_EXT(%edx), %edi /* new tss descriptor */ | ||||
movl PCPU(TRAMPSTK), %ebx | |||||
movl %ebx, PCB_EXT_TSS+TSS_ESP0(%edi) | |||||
jmp 2f /* Load it up */ | jmp 2f /* Load it up */ | ||||
1: /* | 1: /* | ||||
* Use the common default TSS instead of our own. | * Use the common default TSS instead of our own. | ||||
* Set our stack pointer into the TSS, it's set to just | * Stack pointer in the common TSS points to the trampoline stack | ||||
* below the PCB. In C, common_tss.tss_esp0 = &pcb - 16; | * already and should be not changed. | ||||
*/ | * | ||||
leal -16(%edx), %ebx /* leave space for vm86 */ | * Test this CPU's flag to see if this CPU was using a private TSS. | ||||
movl %ebx, PCPU(COMMON_TSS) + TSS_ESP0 | |||||
/* | |||||
* Test this CPU's bit in the bitmap to see if this | |||||
* CPU was using a private TSS. | |||||
*/ | */ | ||||
cmpl $0, PCPU(PRIVATE_TSS) /* Already using the common? */ | cmpl $0, PCPU(PRIVATE_TSS) /* Already using the common? */ | ||||
je 3f /* if so, skip reloading */ | je 3f /* if so, skip reloading */ | ||||
movl $0, PCPU(PRIVATE_TSS) | movl $0, PCPU(PRIVATE_TSS) | ||||
PCPU_ADDR(COMMON_TSSD, %edi) | PCPU_ADDR(COMMON_TSSD, %edi) | ||||
2: | 2: | ||||
/* Move correct tss descriptor into GDT slot, then reload tr. */ | /* Move correct tss descriptor into GDT slot, then reload tr. */ | ||||
movl PCPU(TSS_GDT), %ebx /* entry in GDT */ | movl PCPU(TSS_GDT), %ebx /* entry in GDT */ | ||||
▲ Show 20 Lines • Show All 241 Lines • Show Last 20 Lines |