Minix1.5/kernel/protect1.c
/* This file contains routines to initialize code and data segment
* descriptors, and to initialize global descriptors for local descriptors
* in the process table.
* It is separate from protect.c for the 386 32-bit kernel.
* There it must be compiled into 32-bit code (for use by the kernel) and
* (apart from the LDT initialization) into static 16-bit code (for use by
* the routines in protect.c), while protect.c must be compiled into 16-bit
* code to initialize 32-bit mode.
*/
#ifdef _SYSTEM /* this is being included by protect.c */
#define MAYBE_PUBLIC PRIVATE
#define NEED_LDT_INIT 0
#define init_codeseg linit_codeseg
#define init_dataseg linit_dataseg
#define sdesc lsdesc
#else /* native version */
#include "kernel.h"
#include "proc.h"
#include "protect.h"
#define MAYBE_PUBLIC PUBLIC
#define NEED_LDT_INIT 1
#endif
FORWARD void sdesc();
/*=========================================================================*
* init_codeseg *
*=========================================================================*/
MAYBE_PUBLIC void init_codeseg(segdp, base, size, privilege)
register struct segdesc_s *segdp;
phys_bytes base;
phys_bytes size;
int privilege;
{
/* Build descriptor for a code segment. */
sdesc(segdp, base, size);
segdp->access = (privilege << DPL_SHIFT)
| (PRESENT | SEGMENT | EXECUTABLE | READABLE);
/* CONFORMING = 0, ACCESSED = 0 */
}
/*=========================================================================*
* init_dataseg *
*=========================================================================*/
MAYBE_PUBLIC void init_dataseg(segdp, base, size, privilege)
register struct segdesc_s *segdp;
phys_bytes base;
phys_bytes size;
int privilege;
{
/* Build descriptor for a data segment. */
sdesc(segdp, base, size);
segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
/* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
}
#if NEED_LDT_INIT
/*=========================================================================*
* ldt_init *
*=========================================================================*/
PUBLIC void ldt_init()
{
/* Build local descriptors in GDT for LDT's in process table.
* The LDT's are allocated at compile time in the process table, and
* initialized whenever a process' map is initialized or changed.
*/
unsigned ldt_selector;
register struct proc *rp;
for (rp = BEG_PROC_ADDR, ldt_selector = FIRST_LDT_INDEX * DESC_SIZE;
rp < END_PROC_ADDR; ++rp, ldt_selector += DESC_SIZE) {
init_dataseg(&gdt[ldt_selector / DESC_SIZE],
data_base + (phys_bytes) (vir_bytes) rp->p_ldt,
(phys_bytes) sizeof rp->p_ldt, INTR_PRIVILEGE);
gdt[ldt_selector / DESC_SIZE].access = PRESENT | LDT;
rp->p_ldt_sel = ldt_selector;
}
}
#endif /* NEED_LDT_INIT */
/*=========================================================================*
* sdesc *
*=========================================================================*/
PRIVATE void sdesc(segdp, base, size)
register struct segdesc_s *segdp;
phys_bytes base;
phys_bytes size;
{
/* Fill in the size fields (base, limit and granularity) of a descriptor. */
segdp->base_low = base;
segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
#if INTEL_32BITS
segdp->base_high = base >> BASE_HIGH_SHIFT;
--size; /* convert to a limit, 0 size means 4G */
if (size > BYTE_GRAN_MAX) {
segdp->limit_low = size >> PAGE_GRAN_SHIFT;
segdp->granularity = GRANULAR | (size >>
(PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
} else {
segdp->limit_low = size;
segdp->granularity = size >> GRANULARITY_SHIFT;
}
segdp->granularity |= DEFAULT; /* means BIG for data seg */
#else
segdp->limit_low = size - 1;
#endif
}