cbc9586c13
- FPU context is stored only if conflict between 2 FPU users or while exporting context of a process to userspace while it is the active user of FPU - FPU has its owner (fpu_owner) which points to the process whose state is currently loaded in FPU - the FPU exception is only turned on when scheduling a process which is not the owner of FPU - FPU state is restored for the process that generated the FPU exception. This process runs immediately without letting scheduler to pick a new process to resolve the FPU conflict asap, to minimize the FPU thrashing and FPU exception hadler execution - faster all non-FPU-exception kernel entries as FPU state is not checked nor saved - removed MF_USED_FPU flag, only MF_FPU_INITIALIZED remains to signal that a process has used FPU in the past
151 lines
4 KiB
C
151 lines
4 KiB
C
#ifndef __SCONST_H__
|
|
#define __SCONST_H__
|
|
|
|
#include "kernel/const.h"
|
|
|
|
/* Miscellaneous constants used in assembler code. */
|
|
W = _WORD_SIZE /* Machine word size. */
|
|
|
|
/* Offsets in struct proc. They MUST match proc.h. */
|
|
P_STACKBASE = 0
|
|
GSREG = P_STACKBASE
|
|
FSREG = GSREG+2 /* 386 introduces FS and GS segments*/
|
|
ESREG = FSREG+2
|
|
DSREG = ESREG+2
|
|
DIREG = DSREG+2
|
|
SIREG = DIREG+W
|
|
BPREG = SIREG+W
|
|
STREG = BPREG+W /* hole for another SP*/
|
|
BXREG = STREG+W
|
|
DXREG = BXREG+W
|
|
CXREG = DXREG+W
|
|
AXREG = CXREG+W
|
|
RETADR = AXREG+W /* return address for save() call*/
|
|
PCREG = RETADR+W
|
|
CSREG = PCREG+W
|
|
PSWREG = CSREG+W
|
|
SPREG = PSWREG+W
|
|
SSREG = SPREG+W
|
|
P_STACKTOP = SSREG+W
|
|
FP_SAVE_AREA_P = P_STACKTOP
|
|
P_LDT_SEL = FP_SAVE_AREA_P + 532
|
|
P_CR3 = P_LDT_SEL+W
|
|
P_CR3_V = P_CR3+4
|
|
P_LDT = P_CR3_V+W
|
|
P_MISC_FLAGS = P_LDT + 50
|
|
Msize = 9 /* size of a message in 32-bit words*/
|
|
|
|
|
|
/*
|
|
* offset to current process pointer right after trap, we assume we always have
|
|
* error code on the stack
|
|
*/
|
|
#define CURR_PROC_PTR 20
|
|
|
|
/*
|
|
* tests whether the interrupt was triggered in kernel. If so, jump to the
|
|
* label. Displacement tell the macro ha far is the CS value saved by the trap
|
|
* from the current %esp. The kernel code segment selector has the lower 3 bits
|
|
* zeroed
|
|
*/
|
|
#define TEST_INT_IN_KERNEL(displ, label) \
|
|
cmpl $CS_SELECTOR, displ(%esp) ;\
|
|
je label ;
|
|
|
|
/*
|
|
* saves the basic interrupt context (no error code) to the process structure
|
|
*
|
|
* displ is the displacement of %esp from the original stack after trap
|
|
* pptr is the process structure pointer
|
|
* tmp is an available temporary register
|
|
*/
|
|
#define SAVE_TRAP_CTX(displ, pptr, tmp) \
|
|
movl (0 + displ)(%esp), tmp ;\
|
|
movl tmp, PCREG(pptr) ;\
|
|
movl (4 + displ)(%esp), tmp ;\
|
|
movl tmp, CSREG(pptr) ;\
|
|
movl (8 + displ)(%esp), tmp ;\
|
|
movl tmp, PSWREG(pptr) ;\
|
|
movl (12 + displ)(%esp), tmp ;\
|
|
movl tmp, SPREG(pptr) ;\
|
|
movl tmp, STREG(pptr) ;\
|
|
movl (16 + displ)(%esp), tmp ;\
|
|
movl tmp, SSREG(pptr) ;
|
|
|
|
#define SAVE_SEGS(pptr) \
|
|
mov %ds, %ss:DSREG(pptr) ;\
|
|
mov %es, %ss:ESREG(pptr) ;\
|
|
mov %fs, %ss:FSREG(pptr) ;\
|
|
mov %gs, %ss:GSREG(pptr) ;
|
|
|
|
#define RESTORE_SEGS(pptr) \
|
|
movw %ss:DSREG(pptr), %ds ;\
|
|
movw %ss:ESREG(pptr), %es ;\
|
|
movw %ss:FSREG(pptr), %fs ;\
|
|
movw %ss:GSREG(pptr), %gs ;
|
|
|
|
/*
|
|
* restore kernel segments, %ss is kernnel data segment, %cs is aready set and
|
|
* %fs, %gs are not used
|
|
*/
|
|
#define RESTORE_KERNEL_SEGS \
|
|
mov %ss, %si ;\
|
|
mov %si, %ds ;\
|
|
mov %si, %es ;\
|
|
movw $0, %si ;\
|
|
mov %si, %gs ;\
|
|
mov %si, %fs ;
|
|
|
|
#define SAVE_GP_REGS(pptr) \
|
|
mov %eax, %ss:AXREG(pptr) ;\
|
|
mov %ecx, %ss:CXREG(pptr) ;\
|
|
mov %edx, %ss:DXREG(pptr) ;\
|
|
mov %ebx, %ss:BXREG(pptr) ;\
|
|
mov %esi, %ss:SIREG(pptr) ;\
|
|
mov %edi, %ss:DIREG(pptr) ;
|
|
|
|
#define RESTORE_GP_REGS(pptr) \
|
|
movl %ss:AXREG(pptr), %eax ;\
|
|
movl %ss:CXREG(pptr), %ecx ;\
|
|
movl %ss:DXREG(pptr), %edx ;\
|
|
movl %ss:BXREG(pptr), %ebx ;\
|
|
movl %ss:SIREG(pptr), %esi ;\
|
|
movl %ss:DIREG(pptr), %edi ;
|
|
|
|
/*
|
|
* save the context of the interrupted process to the structure in the process
|
|
* table. It pushses the %ebp to stack to get a scratch register. After %esi is
|
|
* saved, we can use it to get the saved %ebp from stack and save it to the
|
|
* final location
|
|
*
|
|
* displ is the stack displacement. In case of an exception, there are two extra
|
|
* value on the stack - error code and the exception number
|
|
*/
|
|
#define SAVE_PROCESS_CTX(displ) \
|
|
\
|
|
cld /* set the direction flag to a known state */ ;\
|
|
\
|
|
push %ebp ;\
|
|
;\
|
|
movl (CURR_PROC_PTR + 4 + displ)(%esp), %ebp ;\
|
|
;\
|
|
/* save the segment registers */ \
|
|
SAVE_SEGS(%ebp) ;\
|
|
\
|
|
SAVE_GP_REGS(%ebp) ;\
|
|
pop %esi /* get the orig %ebp and save it */ ;\
|
|
mov %esi, %ss:BPREG(%ebp) ;\
|
|
\
|
|
RESTORE_KERNEL_SEGS ;\
|
|
SAVE_TRAP_CTX(displ, %ebp, %esi) ;
|
|
|
|
/*
|
|
* clear the IF flag in eflags which are stored somewhere in memory, e.g. on
|
|
* stack. iret or popf will load the new value later
|
|
*/
|
|
#define CLEAR_IF(where) \
|
|
mov where, %eax ;\
|
|
andl $0xfffffdff, %eax ;\
|
|
mov %eax, where ;
|
|
|
|
#endif /* __SCONST_H__ */
|