/joh'liks/ n.,adj. 386BSD

Porting Unix to the 386: A Practical Approach



William & Lynne Jolitz


Hardware context switch state description and the part where 386BSD context switching intrudes into the machine independent code semantics.




Process Context Description
As seen in Figure 6, the process control block (struct pcb), contains the 386-specific per-process information. This is broken down into hardware-dependent fields and software-related fields. The process control block is place at the front of the user structure so that the information can be reloaded from the address of the user structure and force active a previously inactive process. The user structure address is recorded in the process table. Each entry describes global information about a process.

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.



<<BACK NEXT >>



Copyright 1989, 1990, 2006 TeleMuse Partners, William Jolitz and Lynne Jolitz