Ben Gras 50e2064049 No more intel/minix segments.
This commit removes all traces of Minix segments (the text/data/stack
memory map abstraction in the kernel) and significance of Intel segments
(hardware segments like CS, DS that add offsets to all addressing before
page table translation). This ultimately simplifies the memory layout
and addressing and makes the same layout possible on non-Intel
architectures.

There are only two types of addresses in the world now: virtual
and physical; even the kernel and processes have the same virtual
address space. Kernel and user processes can be distinguished at a
glance as processes won't use 0xF0000000 and above.

No static pre-allocated memory sizes exist any more.

Changes to booting:
        . The pre_init.c leaves the kernel and modules exactly as
          they were left by the bootloader in physical memory
        . The kernel starts running using physical addressing,
          loaded at a fixed location given in its linker script by the
          bootloader.  All code and data in this phase are linked to
          this fixed low location.
        . It makes a bootstrap pagetable to map itself to a
          fixed high location (also in linker script) and jumps to
          the high address. All code and data then use this high addressing.
        . All code/data symbols linked at the low addresses is prefixed by
          an objcopy step with __k_unpaged_*, so that that code cannot
          reference highly-linked symbols (which aren't valid yet) or vice
          versa (symbols that aren't valid any more).
        . The two addressing modes are separated in the linker script by
          collecting the unpaged_*.o objects and linking them with low
          addresses, and linking the rest high. Some objects are linked
          twice, once low and once high.
        . The bootstrap phase passes a lot of information (e.g. free memory
          list, physical location of the modules, etc.) using the kinfo
          struct.
        . After this bootstrap the low-linked part is freed.
        . The kernel maps in VM into the bootstrap page table so that VM can
          begin executing. Its first job is to make page tables for all other
          boot processes. So VM runs before RS, and RS gets a fully dynamic,
          VM-managed address space. VM gets its privilege info from RS as usual
          but that happens after RS starts running.
        . Both the kernel loading VM and VM organizing boot processes happen
	  using the libexec logic. This removes the last reason for VM to
	  still know much about exec() and vm/exec.c is gone.

Further Implementation:
        . All segments are based at 0 and have a 4 GB limit.
        . The kernel is mapped in at the top of the virtual address
          space so as not to constrain the user processes.
        . Processes do not use segments from the LDT at all; there are
          no segments in the LDT any more, so no LLDT is needed.
        . The Minix segments T/D/S are gone and so none of the
          user-space or in-kernel copy functions use them. The copy
          functions use a process endpoint of NONE to realize it's
          a physical address, virtual otherwise.
        . The umap call only makes sense to translate a virtual address
          to a physical address now.
        . Segments-related calls like newmap and alloc_segments are gone.
        . All segments-related translation in VM is gone (vir2map etc).
        . Initialization in VM is simpler as no moving around is necessary.
        . VM and all other boot processes can be linked wherever they wish
          and will be mapped in at the right location by the kernel and VM
          respectively.

Other changes:
        . The multiboot code is less special: it does not use mb_print
          for its diagnostics any more but uses printf() as normal, saving
          the output into the diagnostics buffer, only printing to the
          screen using the direct print functions if a panic() occurs.
        . The multiboot code uses the flexible 'free memory map list'
          style to receive the list of free memory if available.
        . The kernel determines the memory layout of the processes to
          a degree: it tells VM where the kernel starts and ends and
          where the kernel wants the top of the process to be. VM then
          uses this entire range, i.e. the stack is right at the top,
          and mmap()ped bits of memory are placed below that downwards,
          and the break grows upwards.

Other Consequences:
        . Every process gets its own page table as address spaces
          can't be separated any more by segments.
        . As all segments are 0-based, there is no distinction between
          virtual and linear addresses, nor between userspace and
          kernel addresses.
        . Less work is done when context switching, leading to a net
          performance increase. (8% faster on my machine for 'make servers'.)
	. The layout and configuration of the GDT makes sysenter and syscall
	  possible.
2012-07-15 22:30:15 +02:00

210 lines
6.4 KiB
C

#ifndef _TYPE_H
#define _TYPE_H
#include <machine/multiboot.h>
#ifndef _MINIX_SYS_CONFIG_H
#include <minix/sys_config.h>
#endif
#ifndef _TYPES_H
#include <minix/types.h>
#endif
#include <minix/const.h>
#include <minix/com.h>
#include <stdint.h>
/* Type definitions. */
typedef unsigned int vir_clicks; /* virtual addr/length in clicks */
typedef unsigned long phys_bytes; /* physical addr/length in bytes */
typedef unsigned int phys_clicks; /* physical addr/length in clicks */
typedef int endpoint_t; /* process identifier */
typedef int32_t cp_grant_id_t; /* A grant ID. */
typedef long unsigned int vir_bytes; /* virtual addresses/lengths in bytes */
/* Structure for virtual copying by means of a vector with requests. */
struct vir_addr {
endpoint_t proc_nr_e; /* NONE for phys, otherwise process endpoint */
vir_bytes offset;
};
#define phys_cp_req vir_cp_req
struct vir_cp_req {
struct vir_addr src;
struct vir_addr dst;
phys_bytes count;
};
/* Structures for SYS_VUMAP. */
struct vumap_vir {
union {
cp_grant_id_t u_grant; /* grant identifier, for non-SELF endpoint */
vir_bytes u_addr; /* local virtual address, for SELF endpoint */
} vv_u;
size_t vv_size; /* size in bytes */
};
#define vv_grant vv_u.u_grant
#define vv_addr vv_u.u_addr
struct vumap_phys {
phys_bytes vp_addr; /* physical address */
size_t vp_size; /* size in bytes */
};
/* I/O vector structures used in protocols between services. */
typedef struct {
vir_bytes iov_addr; /* address of an I/O buffer */
vir_bytes iov_size; /* sizeof an I/O buffer */
} iovec_t;
typedef struct {
cp_grant_id_t iov_grant; /* grant ID of an I/O buffer */
vir_bytes iov_size; /* sizeof an I/O buffer */
} iovec_s_t;
/* PM passes the address of a structure of this type to KERNEL when
* sys_sigsend() is invoked as part of the signal catching mechanism.
* The structure contain all the information that KERNEL needs to build
* the signal stack.
*/
struct sigmsg {
int sm_signo; /* signal number being caught */
unsigned long sm_mask; /* mask to restore when handler returns */
vir_bytes sm_sighandler; /* address of handler */
vir_bytes sm_sigreturn; /* address of _sigreturn in C library */
vir_bytes sm_stkptr; /* user stack pointer */
};
/* Load data accounted every this no. of seconds. */
#define _LOAD_UNIT_SECS 6 /* Changing this breaks ABI. */
/* Load data history is kept for this long. */
#define _LOAD_HISTORY_MINUTES 15 /* Changing this breaks ABI. */
#define _LOAD_HISTORY_SECONDS (60*_LOAD_HISTORY_MINUTES)
/* We need this many slots to store the load history. */
#define _LOAD_HISTORY (_LOAD_HISTORY_SECONDS/_LOAD_UNIT_SECS)
/* Runnable processes and other load-average information. */
struct loadinfo {
u16_t proc_load_history[_LOAD_HISTORY]; /* history of proc_s_cur */
u16_t proc_last_slot;
clock_t last_clock;
};
struct cpu_info {
u8_t vendor;
u8_t family;
u8_t model;
u8_t stepping;
u32_t freq; /* in MHz */
u32_t flags[2];
};
struct machine {
unsigned processors_count; /* how many cpus are available */
unsigned bsp_id; /* id of the bootstrap cpu */
int padding; /* used to be protected */
int apic_enabled; /* does the kernel use APIC or not? */
phys_bytes acpi_rsdp; /* where is the acpi RSDP */
};
struct io_range
{
unsigned ior_base; /* Lowest I/O port in range */
unsigned ior_limit; /* Highest I/O port in range */
};
struct mem_range
{
phys_bytes mr_base; /* Lowest memory address in range */
phys_bytes mr_limit; /* Highest memory address in range */
};
/* List of boot-time processes set in kernel/table.c. */
struct boot_image {
int proc_nr; /* process number to use */
char proc_name[PROC_NAME_LEN]; /* name in process table */
endpoint_t endpoint; /* endpoint number when started */
phys_bytes start_addr; /* Where it's in memory */
phys_bytes len;
};
/* Memory chunks. */
struct memory {
phys_bytes base;
phys_bytes size;
};
/* This is used to obtain system information through SYS_GETINFO. */
#define MAXMEMMAP 40
typedef struct kinfo {
/* Straight multiboot-provided info */
multiboot_info_t mbi;
multiboot_module_t module_list[MULTIBOOT_MAX_MODS];
multiboot_memory_map_t memmap[MAXMEMMAP]; /* free mem list */
phys_bytes mem_high_phys;
int mmap_size;
/* Multiboot-derived */
int mods_with_kernel; /* no. of mods incl kernel */
int kern_mod; /* which one is kernel */
/* Minix stuff, started at bootstrap phase */
int freepde_start; /* lowest pde unused kernel pde */
char param_buf[MULTIBOOT_PARAM_BUF_SIZE];
/* Minix stuff */
struct kmessages *kmess;
int do_serial_debug; /* system serial output */
int serial_debug_baud; /* serial baud rate */
int minix_panicing; /* are we panicing? */
vir_bytes user_sp; /* where does kernel want stack set */
vir_bytes user_end; /* upper proc limit */
vir_bytes vir_kern_start; /* kernel addrspace starts */
vir_bytes bootstrap_start, bootstrap_len;
struct boot_image boot_procs[NR_BOOT_PROCS];
int nr_procs; /* number of user processes */
int nr_tasks; /* number of kernel tasks */
char release[6]; /* kernel release number */
char version[6]; /* kernel version number */
} kinfo_t;
#define STATICINIT(v, n) \
if(!(v)) { \
if(!((v) = alloc_contig(sizeof(*(v)) * (n), 0, NULL))) { \
panic("allocating " #v " failed: %d", n); \
} \
}
/* The kernel outputs diagnostic messages in a circular buffer. */
struct kmessages {
int km_next; /* next index to write */
int km_size; /* current size in buffer */
char km_buf[_KMESS_BUF_SIZE]; /* buffer for messages */
char kmess_buf[80*25]; /* printable copy of message buffer */
int blpos; /* kmess_buf position */
};
#include <minix/config.h>
#include <machine/interrupt.h>
/* randomness struct: random sources after interrupts: */
#define RANDOM_SOURCES 16
#define RANDOM_ELEMENTS 64
typedef unsigned short rand_t;
struct k_randomness {
int random_elements, random_sources;
struct k_randomness_bin {
int r_next; /* next index to write */
int r_size; /* number of random elements */
rand_t r_buf[RANDOM_ELEMENTS]; /* buffer for random info */
} bin[RANDOM_SOURCES];
};
#endif /* _TYPE_H */