|
Figure 6 - Process Control Block
/* Intel 386 process control block */
struct pcb {
struct i386tss pcbtss;
#define pcb_ksp pcbtss.tss_esp0
#define pcb_ptd pcbtss.tss_cr3
#define pcb_pc pcbtss.tss_eip
#define pcb_psl pcbtss.tss_eflags
#define pcb_usp pcbtss.tss_esp
#define pcb_fp pcbtss.tss_ebp
/* Software pcb (extension) */
int pcb_fpsav;
#define FP_NEEDSAVE 0x1 /* need save on next context switch */
#define FP_NEEDRESTORE 0x2 /* need restore on next DNA fault */
struct save87 pcb_savefpu;
struct pte *pcb_p0br;
struct pte *pcb_p1br;
int pcb_p0lr;
int pcb_p1lr;
int pcb_szpt; /* number of pages of user page table */
int pcb_cmap2;
int *pcb_sswap;
long pcb_sigc[8]; /* sigcode actually 19 bytes */
int pcb_iml; /* interrupt mask level */
};
/* Intel 386 Task Switch State */
struct i386tss {
long tss_link; /* actually 16 bits: top 16 bits must be zero */
long tss_esp0; /* kernel stack pointer priviledge level 0 */
#define tss_ksp tss_esp0
long tss_ss0; /* actually 16 bits: top 16 bits must be zero */
long tss_esp1; /* kernel stack pointer priviledge level 1 */
long tss_ss1; /* actually 16 bits: top 16 bits must be zero */
long tss_esp2; /* kernel stack pointer priviledge level 2 */
long tss_ss2; /* actually 16 bits: top 16 bits must be zero */
long tss_cr3; /* page table directory physical address */
#define tss_ptd tss_cr3
long tss_eip; /* program counter */
#define tss_pc tss_eip
long tss_eflags; /* program status longword */
#define tss_psl tss_eflags
long tss_eax;
long tss_ecx;
long tss_edx;
long tss_ebx;
long tss_esp; /* user stack pointer */
#define tss_usp tss_esp
long tss_ebp; /* user frame pointer */
#define tss_fp tss_ebp
long tss_esi;
long tss_edi;
long tss_es; /* actually 16 bits: top 16 bits must be zero */
long tss_cs; /* actually 16 bits: top 16 bits must be zero */
long tss_ss; /* actually 16 bits: top 16 bits must be zero */
long tss_ds; /* actually 16 bits: top 16 bits must be zero */
long tss_fs; /* actually 16 bits: top 16 bits must be zero */
long tss_gs; /* actually 16 bits: top 16 bits must be zero */
long tss_ldt; /* actually 16 bits: top 16 bits must be zero */
long tss_ioopt; /* options & io offset bitmap: currently zero */
/* XXX unimplemented .. i/o permission bitmap */
};
The 386's hardware context switch facility can be used to switch from process to process. By placing the hardware-dependent information at the beginning of the process control block, in the form of the 386's Task Switch State (TSS) data structure, it is possible to switch from one process to another with a single intersegment ljmp instruction to the appropriate task gate selector. While this feature has been implemented in 386BSD, it is not used at this time for switching between processes due to performance considerations. However, it can be used in other cases, such as exception handling, and we may elect to use it for process switching in the future. We view this as one of those rare "have your cake and eat it too" decisions. In 386BSD, not all hardware context is switched in this manner, because some processes never access the large amount of state information (108 bytes) used by the numeric coprocessor. We allow for this with the pcb_fpusav structure. Other fields correspond to some implementation demands specific to Berkeley UNIX, including simulating VAX hardware constructs invoked by the virtual memory system not existing on the 386. Fortunately, this was a small amount of code. It is a tribute to the concept of UNIX that the machine-dependent portion of the system is as small as it is.
|
|