patch-1.3.31 linux/arch/i386/kernel/entry.S
Next file: linux/arch/i386/kernel/head.S
Previous file: linux/arch/i386/kernel/Makefile
Back to the patch index
Back to the overall index
- Lines: 251
- Date:
Tue Oct 3 12:10:12 1995
- Orig file:
v1.3.30/linux/arch/i386/kernel/entry.S
- Orig date:
Mon Aug 28 14:52:18 1995
diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
@@ -41,8 +41,11 @@
*/
#include <linux/sys.h>
+#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/segment.h>
+#define ASSEMBLY
+#include <asm/smp.h>
EBX = 0x00
ECX = 0x04
@@ -102,13 +105,112 @@
movl $(USER_DS),%edx; \
mov %dx,%fs;
+#ifdef CONFIG_SMP
+
+#define GET_PROCESSOR_ID \
+ movl SYMBOL_NAME(apic_reg), %edx; \
+ movl 32(%edx), %eax;\
+ movl %eax,SYMBOL_NAME(apic_retval); \
+ shrl $24,%eax; \
+ andb $0x0F,%al;
+
+/*
+ * Get the processor ID multiplied by 4
+ */
+
+#define GET_PROCESSOR_OFFSET(x) \
+ movl SYMBOL_NAME(apic_reg), x ; \
+ movl 32( x ), x ; \
+ shrl $22, x ; \
+ andl $0x3C, x ;
+
+/* macro LEAVE_KERNEL decrements kernel_counter and resets kernel_flag and
+ saves processor variables if zero */
+#define LEAVE_KERNEL \
+ pushfl; \
+ cli; \
+ decl SYMBOL_NAME(syscall_count); \
+ decl SYMBOL_NAME(kernel_counter); \
+ jnz 1f; \
+ movb $(NO_PROC_ID), SYMBOL_NAME(active_kernel_processor); \
+ lock; \
+ btrl $0, SYMBOL_NAME(kernel_flag); \
+1: popfl;
+
+/* macro ENTER_KERNEL waits for entering the kernel, increments
+ kernel_counter, and reloads the processor variables if necessary
+ uses : %eax, %edx (pushed and popped)
+
+ Note: We go to great pains to minimise the number of locked operations.
+ We want to spin without locking, and lock when we attempt an update.
+ The pentium has a MESI cache so the spin without lock will exit when
+ another CPU write invalidates our cache, and the lock is avoided when
+ possible so we don't play ping-pong games with the cache line.
+
+*/
+
+#define ENTER_KERNEL \
+ pushl %eax; \
+ pushl %edx; \
+ pushfl; \
+ cli; \
+ GET_PROCESSOR_ID \
+1: lock; \
+ btsl $0, SYMBOL_NAME(kernel_flag); \
+ jnc 3f; \
+ cmpb SYMBOL_NAME(active_kernel_processor), %al; \
+ je 4f; \
+2: incl SYMBOL_NAME(smp_spins); \
+ btl %al, SYMBOL_NAME(smp_invalidate_needed); \
+ jnc 5f; \
+ lock; \
+ btrl %al, SYMBOL_NAME(smp_invalidate_needed); \
+ jnc 5f; \
+ movl %cr3,%edx; \
+ movl %edx,%cr3; \
+5: btl $0, SYMBOL_NAME(kernel_flag); \
+ jc 2b; \
+ jmp 1b; \
+3: movb %al, SYMBOL_NAME(active_kernel_processor); \
+4: incl SYMBOL_NAME(kernel_counter); \
+ incl SYMBOL_NAME(syscall_count); \
+ popfl; \
+ popl %edx; \
+ popl %eax;
+
+
+#define RESTORE_ALL \
+ cmpw $(KERNEL_CS),CS(%esp); \
+ je 1f; \
+ GET_PROCESSOR_OFFSET(%edx) \
+ movl SYMBOL_NAME(current_set)(,%edx), %eax ; ; \
+ movl dbgreg7(%eax),%ebx; \
+ movl %ebx,%db7; \
+1: LEAVE_KERNEL \
+ popl %ebx; \
+ popl %ecx; \
+ popl %edx; \
+ popl %esi; \
+ popl %edi; \
+ popl %ebp; \
+ popl %eax; \
+ pop %ds; \
+ pop %es; \
+ pop %fs; \
+ pop %gs; \
+ addl $4,%esp; \
+ iret
+
+#else
+
#define RESTORE_ALL \
cmpw $(KERNEL_CS),CS(%esp); \
je 1f; \
- movl SYMBOL_NAME(current),%eax; \
+ movl SYMBOL_NAME(current_set),%eax; \
movl dbgreg7(%eax),%ebx; \
movl %ebx,%db7; \
-1: popl %ebx; \
+1: \
+ popl %ebx; \
popl %ecx; \
popl %edx; \
popl %esi; \
@@ -121,11 +223,16 @@
pop %gs; \
addl $4,%esp; \
iret
+#endif
+
ENTRY(lcall7)
pushfl # We get a different stack layout with call gates,
pushl %eax # which has to be cleaned up later..
SAVE_ALL
+#ifdef CONFIG_SMP
+ ENTER_KERNEL
+#endif
movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
movl CS(%esp),%edx # this is eip..
movl EFLAGS(%esp),%ecx # and this is cs..
@@ -133,7 +240,12 @@
movl %edx,EIP(%esp) # Now we move them to their "normal" places
movl %ecx,CS(%esp) #
movl %esp,%eax
- movl SYMBOL_NAME(current),%edx
+#ifdef CONFIG_SMP
+ GET_PROCESSOR_OFFSET(%edx) # Processor offset into edx
+ movl SYMBOL_NAME(current_set)(,%edx),%edx
+#else
+ movl SYMBOL_NAME(current_set),%edx
+#endif
pushl %eax
movl exec_domain(%edx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
@@ -153,18 +265,26 @@
ALIGN
reschedule:
pushl $ret_from_sys_call
- jmp SYMBOL_NAME(schedule)
+ jmp SYMBOL_NAME(schedule) # test
ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
+#ifdef CONFIG_SMP
+ ENTER_KERNEL
+#endif
movl $-ENOSYS,EAX(%esp)
cmpl $(NR_syscalls),%eax
jae ret_from_sys_call
movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax
testl %eax,%eax
je ret_from_sys_call
- movl SYMBOL_NAME(current),%ebx
+#ifdef CONFIG_SMP
+ GET_PROCESSOR_OFFSET(%edx)
+ movl SYMBOL_NAME(current_set)(,%edx),%ebx
+#else
+ movl SYMBOL_NAME(current_set),%ebx
+#endif
andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
movl $0,errno(%ebx)
movl %db6,%edx
@@ -184,7 +304,12 @@
movl ORIG_EAX(%esp),%eax
call SYMBOL_NAME(sys_call_table)(,%eax,4)
movl %eax,EAX(%esp) # save the return value
- movl SYMBOL_NAME(current),%eax
+#ifdef CONFIG_SMP
+ GET_PROCESSOR_OFFSET(%eax)
+ movl SYMBOL_NAME(current_set)(,%eax),%eax
+#else
+ movl SYMBOL_NAME(current_set),%eax
+#endif
movl errno(%eax),%edx
negl %edx
je 1f
@@ -211,7 +336,12 @@
movl %eax,EFLAGS(%esp) # stupid
cmpl $0,SYMBOL_NAME(need_resched)
jne reschedule
- movl SYMBOL_NAME(current),%eax
+#ifdef CONFIG_SMP
+ GET_PROCESSOR_OFFSET(%eax)
+ movl SYMBOL_NAME(current_set)(,%eax), %eax
+#else
+ movl SYMBOL_NAME(current_set),%eax
+#endif
cmpl SYMBOL_NAME(task),%eax # task[0] cannot have signals
je 2f
cmpl $0,state(%eax) # state
@@ -277,8 +407,16 @@
mov %dx,%es
movl $(USER_DS),%edx
mov %dx,%fs
+#ifdef CONFIG_SMP
+ ENTER_KERNEL
+#endif
pushl %eax
- movl SYMBOL_NAME(current),%eax
+#ifdef CONFIG_SMP
+ GET_PROCESSOR_OFFSET(%eax)
+ movl SYMBOL_NAME(current_set)(,%eax), %eax
+#else
+ movl SYMBOL_NAME(current_set),%eax
+#endif
movl %db6,%edx
movl %edx,dbgreg6(%eax) # save current hardware debugging status
popl %eax
@@ -294,6 +432,9 @@
ENTRY(device_not_available)
pushl $-1 # mark this as an int
SAVE_ALL
+#ifdef CONFIG_SMP
+ ENTER_KERNEL
+#endif
pushl $ret_from_sys_call
movl %cr0,%eax
testl $0x4,%eax # EM (math emulation bit)
@@ -518,4 +659,6 @@
.long SYMBOL_NAME(sys_select)
.long SYMBOL_NAME(sys_flock)
.long SYMBOL_NAME(sys_msync)
- .space (NR_syscalls-144)*4
+ .long SYMBOL_NAME(sys_readv) /* 145 */
+ .long SYMBOL_NAME(sys_writev)
+ .space (NR_syscalls-146)*4
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this