minix/kernel/memory.c
2005-04-21 14:53:53 +00:00

120 lines
4.4 KiB
C
Executable file

/* Entry points into this file:
* mem_init: create a list a free memory
* alloc_segments: allocate segments for 8088 or higher processor
*/
#include "kernel.h"
#include "protect.h"
#include "proc.h"
#if (CHIP == INTEL)
/* In real mode only 1M can be addressed, and in 16-bit protected we can go
* no further than we can count in clicks. (The 286 is further limited by
* its 24 bit address bus, but we can assume in that case that no more than
* 16M memory is reported by the BIOS.)
*/
#define MAX_REAL 0x00100000L
#define MAX_16BIT (0xFFF0L << CLICK_SHIFT)
/*=========================================================================*
* mem_init *
*=========================================================================*/
PUBLIC void mem_init()
{
/* Initialize the free memory list from the 'memory' boot variable. Translate
* the byte offsets and sizes in this list to clicks, properly truncated. Also
* make sure that we don't exceed the maximum address space of the 286 or the
* 8086, i.e. when running in 16-bit protected mode or real mode.
*/
long base, size, limit;
char *s, *end; /* use to parse boot variable */
int i;
struct memory *memp;
#if _WORD_SIZE == 2
unsigned long max_address;
#endif
/* The available memory is determined by MINIX' boot loader as a list of
* (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
* in boot.s. The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
* b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1
* and b2:s2 are combined if the memory is adjacent.
*/
s = getkenv("memory"); /* get memory boot variable */
tot_mem_size = 0;
for (i = 0; i < NR_MEMS; i++) {
memp = &mem[i]; /* result is stored here */
base = size = 0;
if (*s != 0) { /* end of boot variable */
/* Expect base to be read (end != s) and ':' as next char. */
base = kstrtoul(s, &end, 0x10); /* get number */
if (end != s && *end == ':') s = ++end; /* skip ':' */
else *s=0; /* fake end for next; should not happen */
/* Expect size to be read and skip ',', unless at end. */
size = kstrtoul(s, &end, 0x10); /* get number */
if (end != s && *end == ',') s = ++end; /* skip ',' */
else if (end != s && *end == 0) s = end; /* end found */
else *s=0; /* fake end for next; should not happen */
}
limit = base + size;
#if _WORD_SIZE == 2
max_address = protected_mode ? MAX_16BIT : MAX_REAL;
if (limit > max_address) limit = max_address;
#endif
base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
limit &= ~(long)(CLICK_SIZE-1);
if (limit <= base) continue;
memp->base = base >> CLICK_SHIFT;
memp->size = (limit - base) >> CLICK_SHIFT;
tot_mem_size += memp->size;
}
}
/*==========================================================================*
* alloc_segments *
*==========================================================================*/
PUBLIC void alloc_segments(rp)
register struct proc *rp;
{
/* This is called at system initialization from main() and by do_newmap().
* The code has a separate function because of all hardware-dependencies.
* Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
*/
phys_bytes code_bytes;
phys_bytes data_bytes;
int privilege;
if (protected_mode) {
data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
if (rp->p_memmap[T].mem_len == 0)
code_bytes = data_bytes; /* common I&D, poor protect */
else
code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
privilege = (isidlep(rp) || istaskp(rp)) ?
TASK_PRIVILEGE : USER_PRIVILEGE;
init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
(phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
data_bytes, privilege);
rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
#if _WORD_SIZE == 4
rp->p_reg.gs =
rp->p_reg.fs =
#endif
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
} else {
rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
}
}
#endif /* (CHIP == INTEL) */