diff --git a/commands/Makefile b/commands/Makefile index b4bd668ef..6092e6a7f 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -17,7 +17,7 @@ SUBDIR= add_route arp ash at \ intr ipcrm ipcs irdpd isoread join kill last \ less loadkeys loadramdisk logger look lp \ lpd ls lspci mail MAKEDEV \ - mdb mesg mined mkfifo mknod \ + mesg mined mkfifo mknod \ mkproto mount mt netconf nice acknm nohup \ nonamed od paste patch pax \ ping postinstall poweroff pr prep printf printroot \ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d753faf36..09e64b91c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1448,38 +1448,16 @@ static void complete_bridges() *===========================================================================*/ static void complete_bars(void) { - int i, j, r, bar_nr, reg; + int i, j, bar_nr, reg; u32_t memgap_low, memgap_high, iogap_low, iogap_high, io_high, base, size, v32, diff1, diff2; - char *cp, *next; - char memstr[256]; + kinfo_t kinfo; + + if(OK != sys_getkinfo(&kinfo)) + panic("can't get kinfo"); - r= env_get_param("memory", memstr, sizeof(memstr)); - if (r != OK) - panic("env_get_param failed: %d", r); - /* Set memgap_low to just above physical memory */ - memgap_low= 0; - cp= memstr; - while (*cp != '\0') - { - base= strtoul(cp, &next, 16); - if (!(*next) || next == cp || *next != ':') - goto bad_mem_string; - cp= next+1; - size= strtoul(cp, &next, 16); - if (next == cp || (*next != ',' && *next != '\0')) - if (!*next) - goto bad_mem_string; - if (base+size > memgap_low) - memgap_low= base+size; - - if (*next) - cp= next+1; - else - break; - } - + memgap_low= kinfo.mem_high_phys; memgap_high= 0xfe000000; /* Leave space for the CPU (APIC) */ if (debug) @@ -1661,10 +1639,6 @@ static void complete_bars(void) } } return; - -bad_mem_string: - printf("PCI: bad memory environment string '%s'\n", memstr); - panic(NULL); } /*===========================================================================* diff --git a/drivers/tty/console.c b/drivers/tty/console.c index 05971f634..023c9449f 100644 --- a/drivers/tty/console.c +++ b/drivers/tty/console.c @@ -971,7 +971,6 @@ tty_t *tp; if(font_memory == MAP_FAILED) panic("Console couldn't map font memory"); - vid_size >>= 1; /* word count */ vid_mask = vid_size - 1; @@ -983,6 +982,7 @@ tty_t *tp; if (nr_cons > NR_CONS) nr_cons = NR_CONS; if (nr_cons > 1) wrap = 0; + if (nr_cons < 1) panic("no consoles"); page_size = vid_size / nr_cons; } diff --git a/include/arch/i386/include/archtypes.h b/include/arch/i386/include/archtypes.h index 75e0f1eea..62bc5aaae 100644 --- a/include/arch/i386/include/archtypes.h +++ b/include/arch/i386/include/archtypes.h @@ -14,24 +14,19 @@ struct segdesc_s { /* segment descriptor for protected mode */ u8_t access; /* |P|DL|1|X|E|R|A| */ u8_t granularity; /* |G|X|0|A|LIMT| */ u8_t base_high; -}; +} __attribute__((packed)); -#define LDT_SIZE 2 /* CS and DS */ - -/* Fixed local descriptors. */ -#define CS_LDT_INDEX 0 /* process CS */ -#define DS_LDT_INDEX 1 /* process DS=ES=FS=GS=SS */ +struct desctableptr_s { + u16_t limit; + u32_t base; +} __attribute__((packed)); typedef struct segframe { - reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */ reg_t p_cr3; /* page table root */ u32_t *p_cr3_v; char *fpu_state; - struct segdesc_s p_ldt[LDT_SIZE]; /* CS, DS and remote */ } segframe_t; -#define INMEMORY(p) (!p->p_seg.p_cr3 || get_cpulocal_var(ptproc) == p) - typedef u32_t atomic_t; /* access to an aligned 32bit value is atomic on i386 */ #endif /* #ifndef _I386_TYPES_H */ diff --git a/include/arch/i386/include/interrupt.h b/include/arch/i386/include/interrupt.h index c13a1e422..649cc084a 100644 --- a/include/arch/i386/include/interrupt.h +++ b/include/arch/i386/include/interrupt.h @@ -14,6 +14,9 @@ /* Magic numbers for interrupt controller. */ #define END_OF_INT 0x20 /* code used to re-enable after an interrupt */ +#define IRQ0_VECTOR 0x50 /* nice vectors to relocate IRQ0-7 to */ +#define IRQ8_VECTOR 0x70 /* no need to move IRQ8-15 */ + /* Interrupt vectors defined/reserved by processor. */ #define DIVIDE_VECTOR 0 /* divide error */ #define DEBUG_VECTOR 1 /* single step (trace) */ @@ -25,15 +28,6 @@ #define KERN_CALL_VECTOR 32 /* system calls are made with int SYSVEC */ #define IPC_VECTOR 33 /* interrupt vector for ipc */ -/* Suitable irq bases for hardware interrupts. Reprogram the 8259(s) from - * the PC BIOS defaults since the BIOS doesn't respect all the processor's - * reserved vectors (0 to 31). - */ -#define BIOS_IRQ0_VEC 0x08 /* base of IRQ0-7 vectors used by BIOS */ -#define BIOS_IRQ8_VEC 0x70 /* base of IRQ8-15 vectors used by BIOS */ -#define IRQ0_VECTOR 0x50 /* nice vectors to relocate IRQ0-7 to */ -#define IRQ8_VECTOR 0x70 /* no need to move IRQ8-15 */ - /* Hardware interrupt numbers. */ #ifndef USE_APIC #define NR_IRQ_VECTORS 16 @@ -55,11 +49,8 @@ #define AT_WINI_0_IRQ 14 /* at winchester controller 0 */ #define AT_WINI_1_IRQ 15 /* at winchester controller 1 */ -/* Interrupt number to hardware vector. */ -#define BIOS_VECTOR(irq) \ - (((irq) < 8 ? BIOS_IRQ0_VEC : BIOS_IRQ8_VEC) + ((irq) & 0x07)) -#define VECTOR(irq) \ - (((irq) < 8 ? IRQ0_VECTOR : IRQ8_VECTOR) + ((irq) & 0x07)) +#define VECTOR(irq) \ + (((irq) < 8 ? IRQ0_VECTOR : IRQ8_VECTOR) + ((irq) & 0x07)) #endif /* (CHIP == INTEL) */ diff --git a/include/arch/i386/include/multiboot.h b/include/arch/i386/include/multiboot.h index df2bafa37..751c5cdba 100644 --- a/include/arch/i386/include/multiboot.h +++ b/include/arch/i386/include/multiboot.h @@ -14,8 +14,6 @@ #define MULTIBOOT_AOUT_KLUDGE 0x00010000 -#define MULTIBOOT_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN) - /* consts used for Multiboot pre-init */ #define MULTIBOOT_VIDEO_MODE_EGA 1 @@ -28,13 +26,18 @@ #define MULTIBOOT_CONSOLE_LINES 25 #define MULTIBOOT_CONSOLE_COLS 80 +#define MULTIBOOT_VIDEO_BUFFER_BYTES \ + (MULTIBOOT_CONSOLE_LINES*MULTIBOOT_CONSOLE_COLS*2) #define MULTIBOOT_STACK_SIZE 4096 #define MULTIBOOT_PARAM_BUF_SIZE 1024 +#define MULTIBOOT_MAX_MODS 20 + /* Flags to be set in the ’flags’ member of the multiboot info structure. */ #define MULTIBOOT_INFO_MEMORY 0x00000001 +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 /* Is there a boot device set? */ #define MULTIBOOT_INFO_BOOTDEV 0x00000002 @@ -45,6 +48,8 @@ /* Are there modules to do something with? */ #define MULTIBOOT_INFO_MODS 0x00000008 +#define MULTIBOOT_HIGH_MEM_BASE 0x100000 + #ifndef __ASSEMBLY__ #include @@ -73,8 +78,8 @@ struct multiboot_info /* Multiboot info version number */ u32_t flags; /* Available memory from BIOS */ - u32_t mem_lower; - u32_t mem_upper; + u32_t mem_lower_unused; /* minix uses memmap instead */ + u32_t mem_upper_unused; /* "root" partition */ u32_t boot_device; /* Kernel command line */ @@ -121,8 +126,18 @@ struct multiboot_mod_list }; typedef struct multiboot_mod_list multiboot_module_t; -/* Buffer for multiboot parameters */ -extern char multiboot_param_buf[]; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +struct multiboot_mmap_entry +{ + u32_t size; + u64_t addr; + u64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 + u32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; #endif /* __ASSEMBLY__ */ #endif /* __MULTIBOOT_H__ */ diff --git a/include/arch/i386/include/vmparam.h b/include/arch/i386/include/vmparam.h index a8e217d49..63aef5c2c 100644 --- a/include/arch/i386/include/vmparam.h +++ b/include/arch/i386/include/vmparam.h @@ -49,9 +49,4 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_MASK (PAGE_SIZE - 1) -/* As visible from the user space process, where is the top of the - * stack (first non-stack byte), when in paged mode? - */ -#define VM_STACKTOP 0x80000000 - #endif /* _I386_VMPARAM_H_ */ diff --git a/include/minix/com.h b/include/minix/com.h index 46242b16e..d0f091fa6 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -89,9 +89,6 @@ #define ROOT_SYS_PROC_NR RS_PROC_NR #define ROOT_USR_PROC_NR INIT_PROC_NR -/* Number of processes contained in the system image. */ -#define NR_BOOT_PROCS (NR_TASKS + LAST_SPECIAL_PROC_NR + 1) - /*===========================================================================* * Kernel notification types * *===========================================================================*/ @@ -307,7 +304,6 @@ # define SYS_SIGSEND (KERNEL_CALL + 9) /* sys_sigsend() */ # define SYS_SIGRETURN (KERNEL_CALL + 10) /* sys_sigreturn() */ -# define SYS_NEWMAP (KERNEL_CALL + 11) /* sys_newmap() */ # define SYS_MEMSET (KERNEL_CALL + 13) /* sys_memset() */ # define SYS_UMAP (KERNEL_CALL + 14) /* sys_umap() */ @@ -533,16 +529,13 @@ #define SIG_MAP m2_l1 /* used by kernel to pass signal bit map */ #define SIG_CTXT_PTR m2_p1 /* pointer to info to restore signal context */ -/* Field names for SYS_FORK, _EXEC, _EXIT, _NEWMAP, GETMCONTEXT, SETMCONTEXT.*/ +/* Field names for SYS_FORK, _EXEC, _EXIT, GETMCONTEXT, SETMCONTEXT.*/ #define PR_ENDPT m1_i1 /* indicates a process */ #define PR_PRIORITY m1_i2 /* process priority */ #define PR_SLOT m1_i2 /* indicates a process slot */ #define PR_STACK_PTR m1_p1 /* used for stack ptr in sys_exec, sys_getsp */ #define PR_NAME_PTR m1_p2 /* tells where program name is for dmp */ #define PR_IP_PTR m1_p3 /* initial value for ip after exec */ -#define PR_MEM_PTR m1_p1 /* tells where memory map is for sys_newmap - * and sys_fork - */ #define PR_FORK_FLAGS m1_i3 /* optional flags for fork operation */ #define PR_FORK_MSGADDR m1_p1 /* reply message address of forked child */ #define PR_CTX_PTR m1_p1 /* pointer to mcontext_t structure */ @@ -624,11 +617,8 @@ #define VMCTL_I386_GETCR3 13 #define VMCTL_MEMREQ_GET 14 #define VMCTL_MEMREQ_REPLY 15 -#define VMCTL_INCSP 16 #define VMCTL_NOPAGEZERO 18 #define VMCTL_I386_KERNELLIMIT 19 -#define VMCTL_I386_FREEPDE 23 -#define VMCTL_ENABLE_PAGING 24 #define VMCTL_I386_INVLPG 25 #define VMCTL_FLUSHTLB 26 #define VMCTL_KERN_PHYSMAP 27 @@ -636,6 +626,7 @@ #define VMCTL_SETADDRSPACE 29 #define VMCTL_VMINHIBIT_SET 30 #define VMCTL_VMINHIBIT_CLEAR 31 +#define VMCTL_CLEARMAPCACHE 32 /* Codes and field names for SYS_SYSCTL. */ #define SYSCTL_CODE m1_i1 /* SYSCTL_CODE_* below */ @@ -830,7 +821,7 @@ /* Parameters for the EXEC_NEWMEM call */ #define EXC_NM_PROC m1_i1 /* process that needs new map */ -#define EXC_NM_PTR m1_p1 /* parameters in struct exec_newmem */ +#define EXC_NM_PTR m1_p1 /* parameters in struct exec_info */ /* Results: * the status will be in m_type. * the top of the stack will be in m1_i1. diff --git a/include/minix/const.h b/include/minix/const.h index 2342645e5..b52f94e94 100644 --- a/include/minix/const.h +++ b/include/minix/const.h @@ -57,18 +57,14 @@ #define SEGMENT_TYPE 0xFF00 /* bit mask to get segment type */ #define SEGMENT_INDEX 0x00FF /* bit mask to get segment index */ -#define LOCAL_SEG 0x0000 /* flags indicating local memory segment */ -#define NR_LOCAL_SEGS 3 /* # local segments per process (fixed) */ -#define T 0 /* proc[i].mem_map[T] is for text */ -#define D 1 /* proc[i].mem_map[D] is for data */ -#define S 2 /* proc[i].mem_map[S] is for stack */ +#define D_OBSOLETE 1 /* proc[i].mem_map[D] is for data */ #define PHYS_SEG 0x0400 /* flag indicating entire physical memory */ #define LOCAL_VM_SEG 0x1000 /* same as LOCAL_SEG, but with vm lookup */ -#define VM_D (LOCAL_VM_SEG | D) -#define VM_T (LOCAL_VM_SEG | T) #define MEM_GRANT 3 +#define VIR_ADDR 1 +#define VM_D (LOCAL_VM_SEG | VIR_ADDR) #define VM_GRANT (LOCAL_VM_SEG | MEM_GRANT) /* Labels used to disable code sections for different reasons. */ @@ -76,6 +72,9 @@ #define FUTURE_CODE 0 /* new code to be activated + tested later */ #define TEMP_CODE 1 /* active code to be removed later */ +/* Number of processes contained in the system image. */ +#define NR_BOOT_PROCS (NR_TASKS + LAST_SPECIAL_PROC_NR + 1) + /* Process name length in the PM process table, including '\0'. */ #define PROC_NAME_LEN 16 @@ -157,9 +156,6 @@ #define SERVARNAME "cttyline" #define SERBAUDVARNAME "cttybaud" -/* Bits for the system property flags in boot image processes. */ -#define PROC_FULLVM 0x100 /* VM sets and manages full pagetable */ - /* Bits for s_flags in the privilege structure. */ #define PREEMPTIBLE 0x002 /* kernel tasks are not preemptible */ #define BILLABLE 0x004 /* some processes are not billable */ diff --git a/include/minix/profile.h b/include/minix/profile.h index aa94dd567..c3f5eed46 100644 --- a/include/minix/profile.h +++ b/include/minix/profile.h @@ -31,7 +31,7 @@ struct sprof_sample { struct sprof_proc { endpoint_t proc; - char name[8]; + char name[PROC_NAME_LEN]; }; #include diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 90b172934..141201ac8 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -37,9 +37,8 @@ int sys_abort(int how, ...); int sys_enable_iop(endpoint_t proc_ep); int sys_exec(endpoint_t proc_ep, char *ptr, char *aout, vir_bytes initpc); -int sys_fork(endpoint_t parent, endpoint_t child, endpoint_t *, struct - mem_map *ptr, u32_t vm, vir_bytes *); -int sys_newmap(endpoint_t proc_ep, struct mem_map *ptr); +int sys_fork(endpoint_t parent, endpoint_t child, endpoint_t *, + u32_t vm, vir_bytes *); int sys_clear(endpoint_t proc_ep); int sys_exit(void); int sys_trace(int req, endpoint_t proc_ep, long addr, long *data_p); diff --git a/include/minix/type.h b/include/minix/type.h index 3ed23852e..094cd50c6 100644 --- a/include/minix/type.h +++ b/include/minix/type.h @@ -1,5 +1,6 @@ #ifndef _TYPE_H #define _TYPE_H +#include #ifndef _MINIX_SYS_CONFIG_H #include @@ -9,6 +10,9 @@ #include #endif +#include +#include + #include /* Type definitions. */ @@ -16,39 +20,12 @@ 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. */ - -#if (_MINIX_CHIP == _CHIP_INTEL) typedef long unsigned int vir_bytes; /* virtual addresses/lengths in bytes */ -#endif - -#if (_MINIX_CHIP == _CHIP_M68000) -typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */ -#endif - -#if (_MINIX_CHIP == _CHIP_SPARC) -typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */ -#endif - -/* Memory map for local text, stack, data segments. */ -struct mem_map { - vir_clicks mem_vir; /* virtual address */ - phys_clicks mem_phys; /* physical address */ - vir_clicks mem_len; /* length */ -}; - -/* Memory map for remote memory areas, e.g., for the RAM disk. */ -struct far_mem { - int in_use; /* entry in use, unless zero */ - phys_clicks mem_phys; /* physical address */ - vir_clicks mem_len; /* length */ -}; /* Structure for virtual copying by means of a vector with requests. */ struct vir_addr { - endpoint_t proc_nr_e; - int segment; + endpoint_t proc_nr_e; /* NONE for phys, otherwise process endpoint */ vir_bytes offset; }; @@ -99,27 +76,6 @@ struct sigmsg { vir_bytes sm_stkptr; /* user stack pointer */ }; -/* This is used to obtain system information through SYS_GETINFO. */ -struct kinfo { - phys_bytes code_base; /* base of kernel code */ - phys_bytes code_size; - phys_bytes data_base; /* base of kernel data */ - phys_bytes data_size; - vir_bytes proc_addr; /* virtual address of process table */ - phys_bytes _kmem_base; /* kernel memory layout (/dev/kmem) */ - phys_bytes _kmem_size; - phys_bytes bootdev_base; /* boot device from boot image (/dev/boot) */ - phys_bytes bootdev_size; - phys_bytes ramdev_base; /* boot device from boot image (/dev/boot) */ - phys_bytes ramdev_size; - phys_bytes _params_base; /* parameters passed by boot monitor */ - phys_bytes _params_size; - 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 */ -}; - /* Load data accounted every this no. of seconds. */ #define _LOAD_UNIT_SECS 6 /* Changing this breaks ABI. */ @@ -166,12 +122,55 @@ struct mem_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))) { \ @@ -184,6 +183,8 @@ 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 diff --git a/include/minix/vm.h b/include/minix/vm.h index 4f0978c1b..b12e6f2ec 100644 --- a/include/minix/vm.h +++ b/include/minix/vm.h @@ -55,7 +55,6 @@ struct vm_usage_info { }; struct vm_region_info { - int vri_seg; /* segment of virtual region (T or D) */ vir_bytes vri_addr; /* base address of region */ vir_bytes vri_length; /* length of region */ int vri_prot; /* protection flags (PROT_) */ diff --git a/kernel/Makefile b/kernel/Makefile index fb3c22ee0..b46a65efd 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -5,16 +5,18 @@ PROG= kernel .include "arch/${MACHINE_ARCH}/Makefile.inc" -SRCS+= clock.c cpulocals.c interrupt.c main.c proc.c start.c system.c \ +SRCS+= clock.c cpulocals.c interrupt.c main.c proc.c system.c \ table.c utility.c -DPADD+= ${LIBTIMERS} ${LIBSYS} ${LIBEXEC} +LINKERSCRIPT=${.CURDIR}/arch/${ARCH}/kernel.lds + +DPADD+= ${LIBTIMERS} ${LIBSYS} ${LIBEXEC} $(LINKERSCRIPT) LDADD+= -ltimers -lsys -lexec -CFLAGS += -D__kernel__ +CFLAGS += -D__kernel__ CPPFLAGS+= -fno-stack-protector -D_NETBSD_SOURCE -LDFLAGS+= -T ${.CURDIR}/arch/${MACHINE_ARCH}/kernel.lds +LDFLAGS+= -T $(LINKERSCRIPT) LDFLAGS+= -nostdlib -L${DESTDIR}/${LIBDIR} LDADD+= -lminlib DPADD+= ${LIBMINLIB} @@ -87,3 +89,5 @@ extracted-mtype.h: extract-mtype.sh ../include/minix/com.h clean: rm -f extracted-errno.h extracted-mfield.h extracted-mtype.h + + diff --git a/kernel/arch/i386/Makefile.inc b/kernel/arch/i386/Makefile.inc index 172803a19..18fbc399a 100644 --- a/kernel/arch/i386/Makefile.inc +++ b/kernel/arch/i386/Makefile.inc @@ -4,10 +4,37 @@ HERE=${.CURDIR}/arch/${MACHINE_ARCH} .PATH: ${HERE} + +# objects we want unpaged from -lminlib, -lminc +MINLIB_OBJS_UNPAGED=_cpufeature.o _cpuid.o get_bp.o +MINC_OBJS_UNPAGED=strcat.o strlen.o memcpy.o strcpy.o strncmp.o memset.o \ + memmove.o strcmp.o atoi.o ctype_.o _stdfile.o strtol.o _errno.o errno.o +SYS_OBJS_UNPAGED=kprintf.o vprintf.o assert.o stacktrace.o + +# some object files we give a symbol prefix (or namespace) of __k_unpaged_ +# that must live in their own unique namespace. +# +.for UNPAGED_OBJ in head.o pre_init.o direct_tty_utils.o io_outb.o \ + io_inb.o pg_utils.o klib.o utility.o arch_reset.o \ + $(MINLIB_OBJS_UNPAGED) $(MINC_OBJS_UNPAGED) $(SYS_OBJS_UNPAGED) +unpaged_${UNPAGED_OBJ}: ${UNPAGED_OBJ} + objcopy --prefix-symbols=__k_unpaged_ ${UNPAGED_OBJ} unpaged_${UNPAGED_OBJ} +UNPAGED_OBJS += unpaged_${UNPAGED_OBJ} +.endfor + +# we have to extract some object files from libminc.a and libminlib.a +$(MINLIB_OBJS_UNPAGED) $(MINC_OBJS_UNPAGED) $(SYS_OBJS_UNPAGED): $(LIBMINLIB) $(LIBMINC) $(LIBSYS) + ar x $(LIBMINLIB) $(MINLIB_OBJS_UNPAGED) + ar x $(LIBMINC) $(MINC_OBJS_UNPAGED) + ar x $(LIBSYS) $(SYS_OBJS_UNPAGED) + SRCS+= mpx.S arch_clock.c arch_do_vmctl.c arch_system.c \ do_iopenable.c do_readbios.c do_sdevio.c exception.c i8259.c io_inb.S \ - io_inl.S io_intr.S io_inw.S io_outb.S io_outl.S io_outw.S klib.S klib16.S memory.c multiboot.S \ - oxpcie.c pre_init.c protect.c + io_inl.S io_intr.S io_inw.S io_outb.S io_outl.S io_outw.S klib.S klib16.S memory.c \ + oxpcie.c protect.c direct_tty_utils.c arch_reset.c \ + pg_utils.c + +OBJS.kernel+= ${UNPAGED_OBJS} .if ${USE_ACPI} != "no" SRCS+= acpi.c @@ -28,7 +55,7 @@ SRCS+= arch_watchdog.c CPPFLAGS+= -DUSE_WATCHDOG .endif -apic_asm.d klib.d mpx.d: procoffsets.h +apic_asm.d klib.d mpx.d head.d: procoffsets.h # It's OK to hardcode the arch as i386 here as this and procoffsets.cf # are i386-specific. diff --git a/kernel/arch/i386/apic.c b/kernel/arch/i386/apic.c index 69f7c4d94..bb342c4b3 100644 --- a/kernel/arch/i386/apic.c +++ b/kernel/arch/i386/apic.c @@ -361,8 +361,6 @@ void ioapic_disable_all(void) apic_idt_init(TRUE); /* reset */ idt_reload(); - - intr_init(INTS_ORIG, 0); /* no auto eoi */ } static void ioapic_disable_irq(unsigned irq) @@ -649,12 +647,12 @@ static int lapic_enable_in_msr(void) * update it */ addr = (msr_lo >> 12) | ((msr_hi & 0xf) << 20); - if (phys2vir(addr) != (lapic_addr >> 12)) { + if (addr != (lapic_addr >> 12)) { if (msr_hi & 0xf) { printf("ERROR : APIC address needs more then 32 bits\n"); return 0; } - lapic_addr = phys2vir(msr_lo & ~((1 << 12) - 1)); + lapic_addr = msr_lo & ~((1 << 12) - 1); } #endif @@ -848,7 +846,7 @@ static void lapic_set_dummy_handlers(void) handler += vect * LAPIC_INTR_DUMMY_HANDLER_SIZE; for(; handler < &lapic_intr_dummy_handles_end; handler += LAPIC_INTR_DUMMY_HANDLER_SIZE) { - int_gate(vect++, (vir_bytes) handler, + int_gate_idt(vect++, (vir_bytes) handler, PRESENT | INT_GATE_TYPE | (INTR_PRIVILEGE << DPL_SHIFT)); } @@ -862,14 +860,16 @@ void apic_idt_init(const int reset) /* Set up idt tables for smp mode. */ - int is_bsp = is_boot_apic(apicid()); + int is_bsp; if (reset) { - idt_copy_vectors(gate_table_pic); + idt_copy_vectors_pic(); idt_copy_vectors(gate_table_common); return; } + is_bsp = is_boot_apic(apicid()); + #ifdef APIC_DEBUG if (is_bsp) printf("APIC debugging is enabled\n"); @@ -880,7 +880,7 @@ void apic_idt_init(const int reset) if (ioapic_enabled) idt_copy_vectors(gate_table_ioapic); else - idt_copy_vectors(gate_table_pic); + idt_copy_vectors_pic(); idt_copy_vectors(gate_table_common); @@ -899,7 +899,7 @@ void apic_idt_init(const int reset) if (is_bsp) { BOOT_VERBOSE(printf("Initiating APIC timer handler\n")); /* register the timer interrupt handler for this CPU */ - int_gate(APIC_TIMER_INT_VECTOR, (vir_bytes) lapic_timer_int_handler, + int_gate_idt(APIC_TIMER_INT_VECTOR, (vir_bytes) lapic_timer_int_handler, PRESENT | INT_GATE_TYPE | (INTR_PRIVILEGE << DPL_SHIFT)); } @@ -916,7 +916,7 @@ static int acpi_get_ioapics(struct io_apic * ioa, unsigned * nioa, unsigned max) break; ioa[n].id = acpi_ioa->id; - ioa[n].addr = phys2vir(acpi_ioa->address); + ioa[n].addr = acpi_ioa->address; ioa[n].paddr = (phys_bytes) acpi_ioa->address; ioa[n].gsi_base = acpi_ioa->global_int_base; ioa[n].pins = ((ioapic_read(ioa[n].addr, @@ -936,13 +936,15 @@ int detect_ioapics(void) { int status; - if (machine.acpi_rsdp) + if (machine.acpi_rsdp) { status = acpi_get_ioapics(io_apic, &nioapics, MAX_NR_IOAPICS); - else + } else { status = 0; + } if (!status) { /* try something different like MPS */ } + return status; } @@ -1113,7 +1115,7 @@ int apic_single_cpu_init(void) if (!cpu_feature_apic_on_chip()) return 0; - lapic_addr = phys2vir(LOCAL_APIC_DEF_ADDR); + lapic_addr = LOCAL_APIC_DEF_ADDR; ioapic_enabled = 0; if (!lapic_enable(0)) { @@ -1234,8 +1236,6 @@ void ioapic_reset_pic(void) * master and slave. */ outb(0x22, 0x70); outb(0x23, 0x00); - - intr_init(INTS_ORIG, 0); /* no auto eoi */ } static void irq_lapic_status(int irq) diff --git a/kernel/arch/i386/arch_do_vmctl.c b/kernel/arch/i386/arch_do_vmctl.c index 7a90bf6a7..bb134c680 100644 --- a/kernel/arch/i386/arch_do_vmctl.c +++ b/kernel/arch/i386/arch_do_vmctl.c @@ -8,10 +8,31 @@ */ #include "kernel/system.h" +#include #include #include "arch_proto.h" +extern phys_bytes video_mem_vaddr; + +extern char *video_mem; + +static void setcr3(struct proc *p, u32_t cr3, u32_t *v) +{ + /* Set process CR3. */ + p->p_seg.p_cr3 = cr3; + assert(p->p_seg.p_cr3); + p->p_seg.p_cr3_v = v; + if(p == get_cpulocal_var(ptproc)) { + write_cr3(p->p_seg.p_cr3); + } + if(p->p_nr == VM_PROC_NR) { + if (arch_enable_paging(p) != OK) + panic("arch_enable_paging failed"); + } + RTS_UNSET(p, RTS_VMINHIBIT); +} + /*===========================================================================* * arch_do_vmctl * *===========================================================================*/ @@ -25,37 +46,8 @@ struct proc *p; m_ptr->SVMCTL_VALUE = p->p_seg.p_cr3; return OK; case VMCTL_SETADDRSPACE: - /* Set process CR3. */ - if(m_ptr->SVMCTL_PTROOT) { - p->p_seg.p_cr3 = m_ptr->SVMCTL_PTROOT; - p->p_seg.p_cr3_v = (u32_t *) m_ptr->SVMCTL_PTROOT_V; - p->p_misc_flags |= MF_FULLVM; - if(p == get_cpulocal_var(ptproc)) { - write_cr3(p->p_seg.p_cr3); - } - } else { - p->p_seg.p_cr3 = 0; - p->p_seg.p_cr3_v = NULL; - p->p_misc_flags &= ~MF_FULLVM; - } - RTS_UNSET(p, RTS_VMINHIBIT); + setcr3(p, m_ptr->SVMCTL_PTROOT, (u32_t *) m_ptr->SVMCTL_PTROOT_V); return OK; - case VMCTL_INCSP: - /* Increase process SP. */ - p->p_reg.sp += m_ptr->SVMCTL_VALUE; - return OK; - case VMCTL_I386_KERNELLIMIT: - { - int r; - /* VM wants kernel to increase its segment. */ - r = prot_set_kern_seg_limit(m_ptr->SVMCTL_VALUE); - return r; - } - case VMCTL_I386_FREEPDE: - { - i386_freepde(m_ptr->SVMCTL_VALUE); - return OK; - } case VMCTL_FLUSHTLB: { reload_cr3(); @@ -66,7 +58,6 @@ struct proc *p; i386_invlpg(m_ptr->SVMCTL_VALUE); return OK; } - } diff --git a/kernel/arch/i386/arch_reset.c b/kernel/arch/i386/arch_reset.c new file mode 100644 index 000000000..7891abe42 --- /dev/null +++ b/kernel/arch/i386/arch_reset.c @@ -0,0 +1,154 @@ + +#include "kernel/kernel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "archconst.h" +#include "arch_proto.h" +#include "serial.h" +#include "oxpcie.h" +#include "kernel/proc.h" +#include "kernel/debug.h" +#include "direct_utils.h" +#include + +#define KBCMDP 4 /* kbd controller port (O) */ +#define KBC_PULSE0 0xfe /* pulse output bit 0 */ +#define IO_KBD 0x060 /* 8042 Keyboard */ + +int cpu_has_tsc; + +void +reset(void) +{ + uint8_t b; + /* + * The keyboard controller has 4 random output pins, one of which is + * connected to the RESET pin on the CPU in many PCs. We tell the + * keyboard controller to pulse this line a couple of times. + */ + outb(IO_KBD + KBCMDP, KBC_PULSE0); + busy_delay_ms(100); + outb(IO_KBD + KBCMDP, KBC_PULSE0); + busy_delay_ms(100); + + /* + * Attempt to force a reset via the Reset Control register at + * I/O port 0xcf9. Bit 2 forces a system reset when it + * transitions from 0 to 1. Bit 1 selects the type of reset + * to attempt: 0 selects a "soft" reset, and 1 selects a + * "hard" reset. We try a "hard" reset. The first write sets + * bit 1 to select a "hard" reset and clears bit 2. The + * second write forces a 0 -> 1 transition in bit 2 to trigger + * a reset. + */ + outb(0xcf9, 0x2); + outb(0xcf9, 0x6); + busy_delay_ms(500); /* wait 0.5 sec to see if that did it */ + + /* + * Attempt to force a reset via the Fast A20 and Init register + * at I/O port 0x92. Bit 1 serves as an alternate A20 gate. + * Bit 0 asserts INIT# when set to 1. We are careful to only + * preserve bit 1 while setting bit 0. We also must clear bit + * 0 before setting it if it isn't already clear. + */ + b = inb(0x92); + if (b != 0xff) { + if ((b & 0x1) != 0) + outb(0x92, b & 0xfe); + outb(0x92, b | 0x1); + busy_delay_ms(500); /* wait 0.5 sec to see if that did it */ + } + + /* Triple fault */ + x86_triplefault(); + + /* Give up on resetting */ + while(1) { + ; + } +} + +__dead void arch_shutdown(int how) +{ + unsigned char unused_ch; + /* Mask all interrupts, including the clock. */ + outb( INT_CTLMASK, ~0); + + /* Empty buffer */ + while(direct_read_char(&unused_ch)) + ; + + if(kinfo.minix_panicing) { + /* Printing is done synchronously over serial. */ + if (kinfo.do_serial_debug) + reset(); + + /* Print accumulated diagnostics buffer and reset. */ + direct_cls(); + direct_print("Minix panic. System diagnostics buffer:\n\n"); + direct_print(kmess.kmess_buf); + direct_print("\nSystem has panicked, press any key to reboot"); + while (!direct_read_char(&unused_ch)) + ; + reset(); + } + + if (how == RBT_DEFAULT) { + how = RBT_RESET; + } + + switch (how) { + case RBT_HALT: + /* Stop */ + for (; ; ) halt_cpu(); + NOT_REACHABLE; + + default: + case RBT_REBOOT: + case RBT_RESET: + /* Reset the system by forcing a processor shutdown. + * First stop the BIOS memory test by setting a soft + * reset flag. + */ + reset(); + NOT_REACHABLE; + } + + NOT_REACHABLE; +} + +#ifdef DEBUG_SERIAL +void ser_putc(char c) +{ + int i; + int lsr, thr; + +#if CONFIG_OXPCIE + oxpcie_putc(c); +#else + lsr= COM1_LSR; + thr= COM1_THR; + for (i= 0; i<100000; i++) + { + if (inb( lsr) & LSR_THRE) + break; + } + outb( thr, c); +#endif +} + +#endif diff --git a/kernel/arch/i386/arch_smp.c b/kernel/arch/i386/arch_smp.c index 3cb9aed71..83a3b0b7e 100644 --- a/kernel/arch/i386/arch_smp.c +++ b/kernel/arch/i386/arch_smp.c @@ -32,7 +32,7 @@ void trampoline(void); * 16-bit mode */ extern volatile u32_t __ap_id; -extern volatile struct segdesc_s __ap_gdt, __ap_idt; +extern volatile struct desctableptr_s __ap_gdt, __ap_idt; extern void * __trampoline_end; extern u32_t busclock[CONFIG_MAX_CPUS]; @@ -93,6 +93,8 @@ static phys_bytes copy_trampoline(void) return tramp_base; } +extern struct desctableptr_s gdt_desc, idt_desc; + static void smp_start_aps(void) { /* @@ -111,8 +113,8 @@ static void smp_start_aps(void) outb(RTC_IO, 0xA); /* prepare gdt and idt for the new cpus */ - __ap_gdt = gdt[GDT_INDEX]; - __ap_idt = gdt[IDT_INDEX]; + __ap_gdt = gdt_desc; + __ap_idt = idt_desc; if (!(trampoline_base = copy_trampoline())) { printf("Copying trampoline code failed, cannot boot SMP\n"); @@ -136,7 +138,8 @@ static void smp_start_aps(void) } __ap_id = cpu; - phys_copy(vir2phys(__ap_id), __ap_id_phys, sizeof(__ap_id)); + phys_copy(vir2phys((void *) &__ap_id), + __ap_id_phys, sizeof(__ap_id)); mfence(); if (apic_send_init_ipi(cpu, trampoline_base) || apic_send_startup_ipi(cpu, trampoline_base)) { @@ -216,7 +219,7 @@ static void ap_finish_booting(void) /* inform the world of our presence. */ ap_cpu_ready = cpu; - while(!i386_paging_enabled) + while(!bootstrap_pagetable_done) arch_pause(); /* @@ -232,7 +235,8 @@ static void ap_finish_booting(void) * we must load some page tables befre we turn paging on. As VM is * always present we use those */ - segmentation2paging(proc_addr(VM_PROC_NR)); + pg_load(); /* load bootstrap pagetable built by BSP */ + vm_enable_paging(); printf("CPU %d paging is on\n", cpu); @@ -301,7 +305,7 @@ void smp_init (void) goto uniproc_fallback; } - lapic_addr = phys2vir(LOCAL_APIC_DEF_ADDR); + lapic_addr = LOCAL_APIC_DEF_ADDR; ioapic_enabled = 0; tss_init_all(); @@ -347,7 +351,7 @@ uniproc_fallback: apic_idt_init(1); /* Reset to PIC idt ! */ idt_reload(); smp_reinit_vars (); /* revert to a single proc system. */ - intr_init (INTS_MINIX, 0); /* no auto eoi */ + intr_init(0); /* no auto eoi */ printf("WARNING : SMP initialization failed\n"); } diff --git a/kernel/arch/i386/arch_system.c b/kernel/arch/i386/arch_system.c index 0f3e1cf14..fd706dd21 100644 --- a/kernel/arch/i386/arch_system.c +++ b/kernel/arch/i386/arch_system.c @@ -21,7 +21,7 @@ #include "oxpcie.h" #include "kernel/proc.h" #include "kernel/debug.h" -#include "mb_utils.h" +#include "direct_utils.h" #include #include "glo.h" @@ -36,10 +36,6 @@ static int osfxsr_feature; /* FXSAVE/FXRSTOR instructions support (SSEx) */ -extern __dead void poweroff_jmp(); -extern void poweroff16(); -extern void poweroff16_end(); - /* set MP and NE flags to handle FPU exceptions in native mode. */ #define CR0_MP_NE 0x0022 /* set CR4.OSFXSR[bit 9] if FXSR is supported. */ @@ -57,142 +53,6 @@ static void ser_dump_proc_cpu(void); static void ser_init(void); #endif -#define KBCMDP 4 /* kbd controller port (O) */ -#define KBC_PULSE0 0xfe /* pulse output bit 0 */ -#define IO_KBD 0x060 /* 8042 Keyboard */ - -void -reset(void) -{ - uint8_t b; - /* - * The keyboard controller has 4 random output pins, one of which is - * connected to the RESET pin on the CPU in many PCs. We tell the - * keyboard controller to pulse this line a couple of times. - */ - outb(IO_KBD + KBCMDP, KBC_PULSE0); - busy_delay_ms(100); - outb(IO_KBD + KBCMDP, KBC_PULSE0); - busy_delay_ms(100); - - /* - * Attempt to force a reset via the Reset Control register at - * I/O port 0xcf9. Bit 2 forces a system reset when it - * transitions from 0 to 1. Bit 1 selects the type of reset - * to attempt: 0 selects a "soft" reset, and 1 selects a - * "hard" reset. We try a "hard" reset. The first write sets - * bit 1 to select a "hard" reset and clears bit 2. The - * second write forces a 0 -> 1 transition in bit 2 to trigger - * a reset. - */ - outb(0xcf9, 0x2); - outb(0xcf9, 0x6); - busy_delay_ms(500); /* wait 0.5 sec to see if that did it */ - - /* - * Attempt to force a reset via the Fast A20 and Init register - * at I/O port 0x92. Bit 1 serves as an alternate A20 gate. - * Bit 0 asserts INIT# when set to 1. We are careful to only - * preserve bit 1 while setting bit 0. We also must clear bit - * 0 before setting it if it isn't already clear. - */ - b = inb(0x92); - if (b != 0xff) { - if ((b & 0x1) != 0) - outb(0x92, b & 0xfe); - outb(0x92, b | 0x1); - busy_delay_ms(500); /* wait 0.5 sec to see if that did it */ - } - - /* Triple fault */ - x86_triplefault(); - - /* Give up on resetting */ - while(1) { - ; - } -} - -static __dead void arch_bios_poweroff(void) -{ - u32_t cr0; - - /* Disable paging */ - cr0 = read_cr0(); - cr0 &= ~I386_CR0_PG; - write_cr0(cr0); - /* Copy 16-bit poweroff code to below 1M */ - phys_copy( - (u32_t)&poweroff16, - BIOS_POWEROFF_ENTRY, - (u32_t)&poweroff16_end-(u32_t)&poweroff16); - poweroff_jmp(); -} - -int cpu_has_tsc; - -__dead void arch_shutdown(int how) -{ - vm_stop(); - - /* Mask all interrupts, including the clock. */ - outb( INT_CTLMASK, ~0); - - if(minix_panicing) { - unsigned char unused_ch; - /* We're panicing? Then retrieve and decode currently - * loaded segment selectors. - */ - printseg("cs: ", 1, get_cpulocal_var(proc_ptr), read_cs()); - printseg("ds: ", 0, get_cpulocal_var(proc_ptr), read_ds()); - if(read_ds() != read_ss()) { - printseg("ss: ", 0, NULL, read_ss()); - } - - /* Printing is done synchronously over serial. */ - if (do_serial_debug) - reset(); - - /* Print accumulated diagnostics buffer and reset. */ - mb_cls(); - mb_print("Minix panic. System diagnostics buffer:\n\n"); - mb_print(kmess_buf); - mb_print("\nSystem has panicked, press any key to reboot"); - while (!mb_read_char(&unused_ch)) - ; - reset(); - } - - if (how == RBT_DEFAULT) { - how = RBT_RESET; - } - - switch (how) { - - case RBT_HALT: - /* Poweroff without boot monitor */ - arch_bios_poweroff(); - NOT_REACHABLE; - - case RBT_PANIC: - /* Allow user to read panic message */ - for (; ; ) halt_cpu(); - NOT_REACHABLE; - - default: - case RBT_REBOOT: - case RBT_RESET: - /* Reset the system by forcing a processor shutdown. - * First stop the BIOS memory test by setting a soft - * reset flag. - */ - reset(); - NOT_REACHABLE; - } - - NOT_REACHABLE; -} - void fpu_init(void) { unsigned short cw, sw; @@ -288,19 +148,38 @@ void save_fpu(struct proc *pr) */ static char fpu_state[NR_PROCS][FPU_XFP_SIZE] __aligned(FPUALIGN); -void arch_proc_init(int nr, struct proc *pr) +void arch_proc_reset(struct proc *pr) { - if(nr < 0) return; - char *v; + char *v = NULL; - assert(nr < NR_PROCS); + assert(pr->p_nr < NR_PROCS); - v = fpu_state[nr]; + if(pr->p_nr >= 0) { + v = fpu_state[pr->p_nr]; + /* verify alignment */ + assert(!((vir_bytes)v % FPUALIGN)); + /* initialize state */ + memset(v, 0, FPU_XFP_SIZE); + } + + /* Clear process state. */ + memset(&pr->p_reg, 0, sizeof(pr->p_reg)); + if(iskerneln(pr->p_nr)) + pr->p_reg.psw = INIT_TASK_PSW; + else + pr->p_reg.psw = INIT_PSW; - /* verify alignment */ - assert(!((vir_bytes)v % FPUALIGN)); - pr->p_seg.fpu_state = v; + + /* Initialize the fundamentals that are (initially) the same for all + * processes - the segment selectors it gets to use. + */ + pr->p_reg.cs = USER_CS_SELECTOR; + pr->p_reg.gs = + pr->p_reg.fs = + pr->p_reg.ss = + pr->p_reg.es = + pr->p_reg.ds = USER_DS_SELECTOR; } int restore_fpu(struct proc *pr) @@ -362,18 +241,6 @@ void cpu_identify(void) void arch_init(void) { -#ifdef USE_APIC - /* - * this is setting kernel segments to cover most of the phys memory. The - * value is high enough to reach local APIC nad IOAPICs before paging is - * turned on. - */ - prot_set_kern_seg_limit(0xfff00000); - reload_ds(); -#endif - - idt_init(); - /* FIXME stupid a.out * align the stacks in the stack are to the K_STACK_SIZE which is a * power of 2 @@ -405,29 +272,12 @@ void arch_init(void) BOOT_VERBOSE(printf("APIC not present, using legacy PIC\n")); } #endif + + /* Reserve some BIOS ranges */ + cut_memmap(&kinfo, BIOS_MEM_BEGIN, BIOS_MEM_END); + cut_memmap(&kinfo, BASE_MEM_TOP, UPPER_MEM_END); } -#ifdef DEBUG_SERIAL -void ser_putc(char c) -{ - int i; - int lsr, thr; - -#if CONFIG_OXPCIE - oxpcie_putc(c); -#else - lsr= COM1_LSR; - thr= COM1_THR; - for (i= 0; i<100000; i++) - { - if (inb( lsr) & LSR_THRE) - break; - } - outb( thr, c); -#endif -} - - /*===========================================================================* * do_ser_debug * *===========================================================================*/ @@ -484,22 +334,6 @@ static void ser_dump_queues(void) #endif } -static void ser_dump_segs(void) -{ - struct proc *pp; - for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++) - { - if (isemptyp(pp)) - continue; - printf("%d: %s ep %d\n", proc_nr(pp), pp->p_name, pp->p_endpoint); - printseg("cs: ", 1, pp, pp->p_reg.cs); - printseg("ds: ", 0, pp, pp->p_reg.ds); - if(pp->p_reg.ss != pp->p_reg.ds) { - printseg("ss: ", 0, pp, pp->p_reg.ss); - } - } -} - #ifdef CONFIG_SMP static void dump_bkl_usage(void) { @@ -548,9 +382,6 @@ static void ser_debug(const int c) case '2': ser_dump_queues(); break; - case '3': - ser_dump_segs(); - break; #ifdef CONFIG_SMP case '4': ser_dump_proc_cpu(); @@ -580,6 +411,7 @@ static void ser_debug(const int c) serial_debug_active = 0; } +#if DEBUG_SERIAL void ser_dump_proc() { struct proc *pp; @@ -650,25 +482,6 @@ void arch_ack_profile_clock(void) #endif -/* Saved by mpx386.s into these variables. */ -u32_t params_size, params_offset, mon_ds; - -int arch_get_params(char *params, int maxsize) -{ - phys_copy(seg2phys(mon_ds) + params_offset, vir2phys(params), - MIN(maxsize, params_size)); - params[maxsize-1] = '\0'; - return OK; -} - -int arch_set_params(char *params, int size) -{ - if(size > params_size) - return E2BIG; - phys_copy(vir2phys(params), seg2phys(mon_ds) + params_offset, size); - return OK; -} - void arch_do_syscall(struct proc *proc) { /* do_ipc assumes that it's running because of the current process */ @@ -691,6 +504,12 @@ struct proc * arch_finish_switch_to_user(void) /* set pointer to the process to run on the stack */ p = get_cpulocal_var(proc_ptr); *((reg_t *)stk) = (reg_t) p; + + /* make sure IF is on in FLAGS so that interrupts won't be disabled + * once p's context is restored. this should not be possible. + */ + assert(p->p_reg.psw & (1L << 9)); + return p; } @@ -734,14 +553,14 @@ static void ser_init(void) unsigned divisor; /* keep BIOS settings if cttybaud is not set */ - if (serial_debug_baud <= 0) return; + if (kinfo.serial_debug_baud <= 0) return; /* set DLAB to make baud accessible */ lcr = LCR_8BIT | LCR_1STOP | LCR_NPAR; outb(COM1_LCR, lcr | LCR_DLAB); /* set baud rate */ - divisor = UART_BASE_FREQ / serial_debug_baud; + divisor = UART_BASE_FREQ / kinfo.serial_debug_baud; if (divisor < 1) divisor = 1; if (divisor > 65535) divisor = 65535; diff --git a/kernel/arch/i386/direct_tty_utils.c b/kernel/arch/i386/direct_tty_utils.c new file mode 100644 index 000000000..873cfa7a4 --- /dev/null +++ b/kernel/arch/i386/direct_tty_utils.c @@ -0,0 +1,140 @@ + +#include "kernel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "string.h" +#include "arch_proto.h" +#include "libexec.h" +#include "direct_utils.h" +#include "serial.h" +#include "glo.h" +#include + +/* Give non-zero values to avoid them in BSS */ +static int print_line = 1, print_col = 1; + +#include + +extern char *video_mem; +#define VIDOFFSET(line, col) ((line) * MULTIBOOT_CONSOLE_COLS * 2 + (col) * 2) +#define VIDSIZE VIDOFFSET(MULTIBOOT_CONSOLE_LINES-1,MULTIBOOT_CONSOLE_COLS-1) + +void direct_put_char(char c, int line, int col) +{ + int offset = VIDOFFSET(line, col); + video_mem[offset] = c; + video_mem[offset+1] = 0x07; /* grey-on-black */ +} + +static char direct_get_char(int line, int col) +{ + return video_mem[VIDOFFSET(line, col)]; +} + +void direct_cls(void) +{ + /* Clear screen */ + int i,j; + + for(i = 0; i < MULTIBOOT_CONSOLE_COLS; i++) + for(j = 0; j < MULTIBOOT_CONSOLE_LINES; j++) + direct_put_char(' ', j, i); + + print_line = print_col = 0; + + /* Tell video hardware origin is 0. */ + outb(C_6845+INDEX, VID_ORG); + outb(C_6845+DATA, 0); + outb(C_6845+INDEX, VID_ORG+1); + outb(C_6845+DATA, 0); +} + +static void direct_scroll_up(int lines) +{ + int i, j; + for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ ) { + for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) { + char c = 0; + if(i < MULTIBOOT_CONSOLE_LINES-lines) + c = direct_get_char(i + lines, j); + direct_put_char(c, i, j); + } + } + print_line-= lines; +} + +void direct_print_char(char c) +{ + while (print_line >= MULTIBOOT_CONSOLE_LINES) + direct_scroll_up(1); + +#define TABWIDTH 8 + if(c == '\t') { + if(print_col >= MULTIBOOT_CONSOLE_COLS - TABWIDTH) { + c = '\n'; + } else { + do { + direct_put_char(' ', print_line, print_col++); + } while(print_col % TABWIDTH); + return; + } + } + + if (c == '\n') { + while (print_col < MULTIBOOT_CONSOLE_COLS) + direct_put_char(' ', print_line, print_col++); + print_line++; + print_col = 0; + return; + } + + direct_put_char(c, print_line, print_col++); + + if (print_col >= MULTIBOOT_CONSOLE_COLS) { + print_line++; + print_col = 0; + } + + while (print_line >= MULTIBOOT_CONSOLE_LINES) + direct_scroll_up(1); +} + +void direct_print(const char *str) +{ + while (*str) { + direct_print_char(*str); + str++; + } +} + +/* Standard and AT keyboard. (PS/2 MCA implies AT throughout.) */ +#define KEYBD 0x60 /* I/O port for keyboard data */ +#define KB_STATUS 0x64 /* I/O port for status on AT */ +#define KB_OUT_FULL 0x01 /* status bit set when keypress char pending */ +#define KB_AUX_BYTE 0x20 /* Auxiliary Device Output Buffer Full */ + +int direct_read_char(unsigned char *ch) +{ + unsigned long b, sb; + + sb = inb(KB_STATUS); + + if (!(sb & KB_OUT_FULL)) { + return 0; + } + + b = inb(KEYBD); + + if (!(sb & KB_AUX_BYTE)) + return 1; + + return 0; +} + diff --git a/kernel/arch/i386/do_readbios.c b/kernel/arch/i386/do_readbios.c index e8cb08725..3f162570f 100644 --- a/kernel/arch/i386/do_readbios.c +++ b/kernel/arch/i386/do_readbios.c @@ -18,8 +18,6 @@ int do_readbios(struct proc * caller, message * m_ptr) struct vir_addr src, dst; vir_bytes len = m_ptr->RDB_SIZE, limit; - src.segment = PHYS_SEG; - dst.segment = D; src.offset = m_ptr->RDB_ADDR; dst.offset = (vir_bytes) m_ptr->RDB_BUF; src.proc_nr_e = NONE; diff --git a/kernel/arch/i386/do_sdevio.c b/kernel/arch/i386/do_sdevio.c index 2f3e0822d..d71056bea 100644 --- a/kernel/arch/i386/do_sdevio.c +++ b/kernel/arch/i386/do_sdevio.c @@ -29,7 +29,7 @@ int do_sdevio(struct proc * caller, message *m_ptr) endpoint_t proc_nr_e = m_ptr->DIO_VEC_ENDPT; vir_bytes count = m_ptr->DIO_VEC_SIZE; long port = m_ptr->DIO_PORT; - phys_bytes phys_buf; + phys_bytes vir_buf; int i, req_type, req_dir, size, nr_io_range; struct priv *privp; struct io_range *iorp; @@ -79,11 +79,7 @@ int do_sdevio(struct proc * caller, message *m_ptr) if(!isokendpt(newep, &proc_nr)) return(EINVAL); destproc = proc_addr(proc_nr); - if ((phys_buf = umap_local(destproc, D, - (vir_bytes) newoffset, count)) == 0) { - printf("do_sdevio: umap_local failed\n"); - return(EFAULT); - } + vir_buf = newoffset; } else { if(proc_nr != _ENDPOINT_P(caller->p_endpoint)) { @@ -92,9 +88,7 @@ int do_sdevio(struct proc * caller, message *m_ptr) return EPERM; } /* Get and check physical address. */ - if ((phys_buf = umap_local(proc_addr(proc_nr), D, - (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0) - return(EFAULT); + vir_buf = (phys_bytes) m_ptr->DIO_VEC_ADDR; destproc = proc_addr(proc_nr); } /* current process must be target for phys_* to be OK */ @@ -139,16 +133,16 @@ int do_sdevio(struct proc * caller, message *m_ptr) /* Perform device I/O for bytes and words. Longs are not supported. */ if (req_dir == _DIO_INPUT) { switch (req_type) { - case _DIO_BYTE: phys_insb(port, phys_buf, count); break; - case _DIO_WORD: phys_insw(port, phys_buf, count); break; + case _DIO_BYTE: phys_insb(port, vir_buf, count); break; + case _DIO_WORD: phys_insw(port, vir_buf, count); break; default: retval = EINVAL; goto return_error; } } else if (req_dir == _DIO_OUTPUT) { switch (req_type) { - case _DIO_BYTE: phys_outsb(port, phys_buf, count); break; - case _DIO_WORD: phys_outsw(port, phys_buf, count); break; + case _DIO_BYTE: phys_outsb(port, vir_buf, count); break; + case _DIO_WORD: phys_outsw(port, vir_buf, count); break; default: retval = EINVAL; goto return_error; diff --git a/kernel/arch/i386/exception.c b/kernel/arch/i386/exception.c index e0a8fae26..8611c81ce 100644 --- a/kernel/arch/i386/exception.c +++ b/kernel/arch/i386/exception.c @@ -98,27 +98,18 @@ static void pagefault( struct proc *pr, inkernel_disaster(pr, frame, NULL, is_nested); } - /* System processes that don't have their own page table can't - * have page faults. VM does have its own page table but also - * can't have page faults (because VM has to handle them). - */ - if((pr->p_endpoint <= INIT_PROC_NR && - !(pr->p_misc_flags & MF_FULLVM)) || pr->p_endpoint == VM_PROC_NR) { + /* VM can't handle page faults. */ + if(pr->p_endpoint == VM_PROC_NR) { /* Page fault we can't / don't want to * handle. */ - printf("pagefault for process %d ('%s') on CPU %d, " + printf("pagefault for VM on CPU %d, " "pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n", - pr->p_endpoint, pr->p_name, cpuid, pr->p_reg.pc, - pagefaultcr2, frame->errcode, is_nested); - if(!is_nested) { - printf("process vir addr of pagefault is 0x%lx\n", - pagefaultcr2 - - (pr->p_memmap[D].mem_phys << CLICK_SHIFT)); - } + cpuid, pr->p_reg.pc, pagefaultcr2, frame->errcode, + is_nested); proc_stacktrace(pr); printf("pc of pagefault: 0x%lx\n", frame->eip); - cause_sig(proc_nr(pr), SIGSEGV); + panic("pagefault in VM"); return; } @@ -172,13 +163,9 @@ static void inkernel_disaster(struct proc *saved_proc, proc_stacktrace_execute(proc_addr(SYSTEM), k_ebp, frame->eip); } - printseg("ker cs: ", 1, NULL, frame->cs); - printseg("ker ds: ", 0, NULL, DS_SELECTOR); - if (saved_proc) { printf("scheduled was: process %d (%s), ", saved_proc->p_endpoint, saved_proc->p_name); - printf("pc = %u:0x%x\n", (unsigned) saved_proc->p_reg.cs, - (unsigned) saved_proc->p_reg.pc); + printf("pc = 0x%x\n", (unsigned) saved_proc->p_reg.pc); proc_stacktrace(saved_proc); panic("Unhandled kernel exception"); diff --git a/kernel/arch/i386/head.S b/kernel/arch/i386/head.S new file mode 100644 index 000000000..c019ab11d --- /dev/null +++ b/kernel/arch/i386/head.S @@ -0,0 +1,98 @@ +#include "kernel/kernel.h" /* configures the kernel */ + +/* sections */ + +#include +#include "../../kernel.h" +#include +#include +#include +#include +#include +#include "archconst.h" +#include "kernel/const.h" +#include "kernel/proc.h" +#include "sconst.h" +#include + +#include "arch_proto.h" /* K_STACK_SIZE */ + +#ifdef CONFIG_SMP +#include "kernel/smp.h" +#endif + +/* Selected 386 tss offsets. */ +#define TSS3_S_SP0 4 + +IMPORT(copr_not_available_handler) +IMPORT(params_size) +IMPORT(params_offset) +IMPORT(mon_ds) +IMPORT(switch_to_user) +IMPORT(multiboot_init) + +.text +/*===========================================================================*/ +/* MINIX */ +/*===========================================================================*/ +.global MINIX +MINIX: +/* this is the entry point for the MINIX kernel */ + jmp multiboot_init + +/* Multiboot header here*/ + +.balign 8 + +#define MULTIBOOT_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN) + +multiboot_magic: + .long MULTIBOOT_HEADER_MAGIC +multiboot_flags: + .long MULTIBOOT_FLAGS +multiboot_checksum: + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_FLAGS) + .long 0 + .long 0 + .long 0 + .long 0 + .long 0 +/* Video mode */ +multiboot_mode_type: + .long MULTIBOOT_VIDEO_MODE_EGA +multiboot_width: + .long MULTIBOOT_CONSOLE_COLS +multiboot_height: + .long MULTIBOOT_CONSOLE_LINES +multiboot_depth: + .long 0 + +multiboot_init: + mov $load_stack_start, %esp /* make usable stack */ + mov $0, %ebp + push $0 /* set flags to known good state */ + popf /* esp, clear nested task and int enable */ + push $0 + + push %ebx /* multiboot information struct */ + push %eax /* multiboot magic number */ + call _C_LABEL(pre_init) + + /* Kernel is mapped high now and ready to go, with + * the boot info pointer returnd in %eax. Set the + * highly mapped stack, initialize it, push the boot + * info pointer and jump to the highly mapped kernel. + */ + mov $k_initial_stktop, %esp + push $0 /* Terminate stack */ + push %eax + call _C_LABEL(kmain) + + /* not reached */ +hang: + jmp hang + +.data +load_stack: + .space 4096 +load_stack_start: diff --git a/kernel/arch/i386/i8259.c b/kernel/arch/i386/i8259.c index ca3eac642..65e0021bd 100644 --- a/kernel/arch/i386/i8259.c +++ b/kernel/arch/i386/i8259.c @@ -27,20 +27,11 @@ /*===========================================================================* * intr_init * *===========================================================================*/ -int intr_init(const int mine, const int auto_eoi) +int intr_init(const int auto_eoi) { -/* Initialize the 8259s, finishing with all interrupts disabled. This is - * only done in protected mode, in real mode we don't touch the 8259s, but - * use the BIOS locations instead. The flag "mine" is set if the 8259s are - * to be programmed for MINIX, or to be reset to what the BIOS expects. - */ - - /* The AT and newer PS/2 have two interrupt controllers, one master, - * one slaved at IRQ 2. (We don't have to deal with the PC that - * has just one controller, because it must run in real mode.) - */ +/* Initialize the 8259s, finishing with all interrupts disabled. */ outb( INT_CTL, ICW1_AT); - outb( INT_CTLMASK, mine == INTS_MINIX ? IRQ0_VECTOR : BIOS_IRQ0_VEC); + outb( INT_CTLMASK, IRQ0_VECTOR); /* ICW2 for master */ outb( INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */ @@ -50,7 +41,7 @@ int intr_init(const int mine, const int auto_eoi) outb( INT_CTLMASK, ICW4_AT_MASTER); outb( INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */ outb( INT2_CTL, ICW1_AT); - outb( INT2_CTLMASK, mine == INTS_MINIX ? IRQ8_VECTOR : BIOS_IRQ8_VEC); + outb( INT2_CTLMASK, IRQ8_VECTOR); /* ICW2 for slave */ outb( INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */ if (auto_eoi) @@ -59,16 +50,6 @@ int intr_init(const int mine, const int auto_eoi) outb( INT2_CTLMASK, ICW4_AT_SLAVE); outb( INT2_CTLMASK, ~0); /* IRQ 8-15 mask */ - /* Copy the BIOS vectors from the BIOS to the Minix location, so we - * can still make BIOS calls without reprogramming the i8259s. - */ -#if IRQ0_VECTOR != BIOS_IRQ0_VEC - phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L); -#endif -#if IRQ8_VECTOR != BIOS_IRQ8_VEC - phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L); -#endif - return OK; } diff --git a/kernel/arch/i386/include/arch_proto.h b/kernel/arch/i386/include/arch_proto.h index 2f03715fe..d6519151a 100644 --- a/kernel/arch/i386/include/arch_proto.h +++ b/kernel/arch/i386/include/arch_proto.h @@ -53,12 +53,6 @@ void ipc_entry(void); void kernel_call_entry(void); void level0_call(void); -/* memory.c */ -void segmentation2paging(struct proc * current); -void i386_freepde(int pde); -void getcr3val(void); - - /* exception.c */ struct exception_frame { reg_t vector; /* which interrupt vector was triggered */ @@ -83,6 +77,7 @@ unsigned long read_cr4(void); void write_cr4(unsigned long value); void write_cr3(unsigned long value); unsigned long read_cpu_flags(void); +phys_bytes vir2phys(void *); void phys_insb(u16_t port, phys_bytes buf, size_t count); void phys_insw(u16_t port, phys_bytes buf, size_t count); void phys_outsb(u16_t port, phys_bytes buf, size_t count); @@ -105,6 +100,17 @@ int __frstor_end(void *); int __frstor_failure(void *); unsigned short fnstsw(void); void fnstcw(unsigned short* cw); +void x86_lgdt(void *); +void x86_lldt(u32_t); +void x86_ltr(u32_t); +void x86_lidt(void *); +void x86_load_kerncs(void); +void x86_load_ds(u32_t); +void x86_load_ss(u32_t); +void x86_load_es(u32_t); +void x86_load_fs(u32_t); +void x86_load_gs(u32_t); + void switch_k_stack(void * esp, void (* continuation)(void)); @@ -147,19 +153,25 @@ struct tss_s { u16_t trap; u16_t iobase; /* u8_t iomap[0]; */ -}; +} __attribute__((packed)); -void prot_init(void); -void idt_init(void); -void init_dataseg(struct segdesc_s *segdp, phys_bytes base, vir_bytes - size, int privilege); void enable_iop(struct proc *pp); -int prot_set_kern_seg_limit(vir_bytes limit); -void printseg(char *banner, int iscs, struct proc *pr, u32_t selector); u32_t read_cs(void); u32_t read_ds(void); u32_t read_ss(void); +void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len); +void vm_enable_paging(void); +void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end); +phys_bytes pg_roundup(phys_bytes b); +void pg_info(reg_t *, u32_t **); +void pg_clear(void); +void pg_identity(void); +phys_bytes pg_load(void); +void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end, kinfo_t *cbi); +int pg_mapkernel(void); +void pg_mapproc(struct proc *p, struct boot_image *ip, kinfo_t *cbi); + /* prototype of an interrupt vector table entry */ struct gate_table_s { void(*gate) (void); @@ -167,13 +179,11 @@ struct gate_table_s { unsigned char privilege; }; -extern struct gate_table_s gate_table_pic[]; - /* copies an array of vectors to the IDT. The last vector must be zero filled */ void idt_copy_vectors(struct gate_table_s * first); +void idt_copy_vectors_pic(void); void idt_reload(void); -EXTERN void * k_boot_stktop; EXTERN void * k_stacks_start; extern void * k_stacks; @@ -196,9 +206,9 @@ reg_t read_ebp(void); /* * sets up TSS for a cpu and assigns kernel stack and cpu id */ -void tss_init(unsigned cpu, void * kernel_stack); +int tss_init(unsigned cpu, void * kernel_stack); -void int_gate(unsigned vec_nr, vir_bytes offset, unsigned dpl_type); +void int_gate_idt(unsigned vec_nr, vir_bytes offset, unsigned dpl_type); void __copy_msg_from_user_end(void); void __copy_msg_to_user_end(void); @@ -210,6 +220,7 @@ int platform_tbl_ptr(phys_bytes start, phys_bytes end, unsigned cmp_f)(void *))); /* breakpoints.c */ +int breakpoint_set(phys_bytes linaddr, int bp, const int flags); #define BREAKPOINT_COUNT 4 #define BREAKPOINT_FLAG_RW_MASK (3 << 0) #define BREAKPOINT_FLAG_RW_EXEC (0 << 0) diff --git a/kernel/arch/i386/include/arch_watchdog.h b/kernel/arch/i386/include/arch_watchdog.h index 00b47c174..80dd1fb0b 100644 --- a/kernel/arch/i386/include/arch_watchdog.h +++ b/kernel/arch/i386/include/arch_watchdog.h @@ -23,6 +23,6 @@ struct nmi_frame { int i386_watchdog_start(void); -#define nmi_in_kernel(f) ((f)->cs == CS_SELECTOR) +#define nmi_in_kernel(f) ((f)->cs == KERN_CS_SELECTOR) #endif /* __I386_WATCHDOG_H__ */ diff --git a/kernel/arch/i386/include/archconst.h b/kernel/arch/i386/include/archconst.h index 2e124ac82..123bc4768 100644 --- a/kernel/arch/i386/include/archconst.h +++ b/kernel/arch/i386/include/archconst.h @@ -8,44 +8,25 @@ /* Constants for protected mode. */ /* Table sizes. */ -#define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) - /* spec. and LDT's */ #define IDT_SIZE 256 /* the table is set to it's maximal size */ -/* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */ -#define GDT_INDEX 1 /* GDT descriptor */ -#define IDT_INDEX 2 /* IDT descriptor */ -#define DS_INDEX 3 /* kernel DS */ -#define ES_INDEX 4 /* kernel ES (386: flag 4 Gb at startup) */ -#define SS_INDEX 5 /* kernel SS (386: monitor SS at startup) */ -#define CS_INDEX 6 /* kernel CS */ -#define MON_CS_INDEX 7 /* temp for BIOS (386: monitor CS at startup) */ -#define TSS_INDEX_FIRST 8 /* first kernel TSS */ -#define TSS_INDEX_BOOT TSS_INDEX_FIRST -#define TSS_INDEX(cpu) (TSS_INDEX_FIRST + (cpu)) /* per cpu kernel tss */ -#define FIRST_LDT_INDEX TSS_INDEX(CONFIG_MAX_CPUS) /* rest of descriptors are LDT's */ +/* GDT layout (SYSENTER/SYSEXIT compliant) */ +#define KERN_CS_INDEX 1 +#define KERN_DS_INDEX 2 +#define USER_CS_INDEX 3 +#define USER_DS_INDEX 4 +#define LDT_INDEX 5 +#define TSS_INDEX_FIRST 6 +#define TSS_INDEX(cpu) (TSS_INDEX_FIRST + (cpu)) /* per cpu kernel tss */ +#define GDT_SIZE (TSS_INDEX(CONFIG_MAX_CPUS)) /* LDT descriptor */ -/* Descriptor structure offsets. */ -#define DESC_BASE 2 /* to base_low */ -#define DESC_BASE_MIDDLE 4 /* to base_middle */ -#define DESC_ACCESS 5 /* to access byte */ -#define DESC_SIZE 8 /* sizeof (struct segdesc_s) */ - -/* - * WARNING no () around the macros, be careful. This is because of ACK assembler - * and will be fixed after switching to GAS - */ -#define GDT_SELECTOR GDT_INDEX * DESC_SIZE -#define IDT_SELECTOR IDT_INDEX * DESC_SIZE -#define DS_SELECTOR DS_INDEX * DESC_SIZE -#define ES_SELECTOR ES_INDEX * DESC_SIZE -/* flat DS is less privileged ES */ -#define FLAT_DS_SELECTOR ES_SELECTOR -#define SS_SELECTOR SS_INDEX * DESC_SIZE -#define CS_SELECTOR CS_INDEX * DESC_SIZE -#define MON_CS_SELECTOR MON_CS_INDEX * DESC_SIZE -#define TSS_SELECTOR(cpu) (TSS_INDEX(cpu) * DESC_SIZE) -#define TSS_SELECTOR_BOOT (TSS_INDEX_BOOT * DESC_SIZE) +#define SEG_SELECTOR(i) ((i)*8) +#define KERN_CS_SELECTOR SEG_SELECTOR(KERN_CS_INDEX) +#define KERN_DS_SELECTOR SEG_SELECTOR(KERN_DS_INDEX) +#define USER_CS_SELECTOR (SEG_SELECTOR(USER_CS_INDEX) | USER_PRIVILEGE) +#define USER_DS_SELECTOR (SEG_SELECTOR(USER_DS_INDEX) | USER_PRIVILEGE) +#define LDT_SELECTOR SEG_SELECTOR(LDT_INDEX) +#define TSS_SELECTOR(cpu) SEG_SELECTOR(TSS_INDEX(cpu)) /* Privileges. */ #define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */ @@ -140,9 +121,6 @@ #define IF_MASK 0x00000200 #define IOPL_MASK 0x003000 -#define vir2phys(vir) ((phys_bytes)((kinfo.data_base + (vir_bytes) (vir)))) -#define phys2vir(ph) ((vir_bytes)((vir_bytes) (ph) - kinfo.data_base)) - #define INTEL_CPUID_GEN_EBX 0x756e6547 /* ASCII value of "Genu" */ #define INTEL_CPUID_GEN_EDX 0x49656e69 /* ASCII value of "ineI" */ #define INTEL_CPUID_GEN_ECX 0x6c65746e /* ASCII value of "ntel" */ @@ -168,4 +146,6 @@ */ #define X86_STACK_TOP_RESERVED (2 * sizeof(reg_t)) +#define PG_ALLOCATEME ((phys_bytes)-1) + #endif /* _I386_ACONST_H */ diff --git a/kernel/arch/i386/include/direct_utils.h b/kernel/arch/i386/include/direct_utils.h new file mode 100644 index 000000000..5b7943d74 --- /dev/null +++ b/kernel/arch/i386/include/direct_utils.h @@ -0,0 +1,11 @@ +#ifndef MB_UTILS_H +#define MB_UTILS_H + +#include "kernel/kernel.h" + +void direct_cls(void); +void direct_print(const char*); +void direct_print_char(char); +int direct_read_char(unsigned char*); + +#endif diff --git a/kernel/arch/i386/kernel.lds b/kernel/arch/i386/kernel.lds index cdc5380fb..98a543d1f 100644 --- a/kernel/arch/i386/kernel.lds +++ b/kernel/arch/i386/kernel.lds @@ -1,44 +1,30 @@ OUTPUT_ARCH("i386") -ENTRY(MINIX) +ENTRY(__k_unpaged_MINIX) + +_kern_phys_base = 0x00400000; /* phys 4MB aligned for convenient remapping */ +_kern_vir_base = 0xF0400000; /* map kernel high for max. user vir space */ +_kern_offset = (_kern_vir_base - _kern_phys_base); + +__k_unpaged__kern_offset = _kern_offset; +__k_unpaged__kern_vir_base = _kern_vir_base; +__k_unpaged__kern_phys_base = _kern_phys_base; + SECTIONS { - . = 0x200000 + SIZEOF_HEADERS; - .text . : AT (ADDR(.text) - 0x0000) { - *(.text) - *(.text.*) - } - _etext = .; - etext = .; - . = ALIGN(4096); + . = _kern_phys_base; + __k_unpaged__kern_unpaged_start = .; - .data . : AT (ADDR(.data) - 0x0000) { - _rodata = .; - /* kernel data starts with this magic number */ - SHORT(0x526f); - *(.rodata) - *(.rodata.*) - _erodata = .; - *(.data) - *(.data.*) - . = ALIGN(4096); - } - _edata = .; + .unpaged_text : { unpaged_*.o(.text) } + .unpaged_data ALIGN(4096) : { unpaged_*.o(.data .rodata*) } + .unpaged_bss ALIGN(4096) : { unpaged_*.o(.bss COMMON) } + __k_unpaged__kern_unpaged_end = .; - .bss . : AT (ADDR(.bss) - 0x0000) { - *(.bss) - *(.bss.*) - *(COMMON) - } - _end = .; - end = .; + . += _kern_offset; - /DISCARD/ : - { - *(.eh_frame) - *(.comment) - *(.comment.*) - *(.note) - *(.note.*) - *(.ident) + .text : AT(ADDR(.text) - _kern_offset) { *(.text*) } + .data ALIGN(4096) : AT(ADDR(.data) - _kern_offset) { *(.data .rodata* ) } + .bss ALIGN(4096) : AT(ADDR(.bss) - _kern_offset) { *(.bss* COMMON) + __k_unpaged__kern_size = . - _kern_vir_base; + _kern_size = __k_unpaged__kern_size; } } diff --git a/kernel/arch/i386/klib.S b/kernel/arch/i386/klib.S index 4b2eebf40..b10595ec1 100644 --- a/kernel/arch/i386/klib.S +++ b/kernel/arch/i386/klib.S @@ -80,16 +80,12 @@ ENTRY(phys_insw) mov %esp, %ebp cld push %edi - push %es - mov $FLAT_DS_SELECTOR, %ecx - mov %cx, %es mov 8(%ebp), %edx /* port to read from */ mov 12(%ebp), %edi /* destination addr */ mov 16(%ebp), %ecx /* byte count */ shr $1, %ecx /* word count */ rep insw /* input many words */ - pop %es pop %edi pop %ebp ret @@ -108,15 +104,11 @@ ENTRY(phys_insb) mov %esp, %ebp cld push %edi - push %es - mov $FLAT_DS_SELECTOR, %ecx - mov %cx, %es mov 8(%ebp), %edx /* port to read from */ mov 12(%ebp), %edi /* destination addr */ mov 16(%ebp), %ecx /* byte count */ rep insb /* input many bytes */ - pop %es pop %edi pop %ebp ret @@ -135,16 +127,12 @@ ENTRY(phys_outsw) mov %esp, %ebp cld push %esi - push %ds - mov $FLAT_DS_SELECTOR, %ecx - mov %cx, %ds mov 8(%ebp), %edx /* port to write to */ mov 12(%ebp), %esi /* source addr */ mov 16(%ebp), %ecx /* byte count */ shr $1, %ecx /* word count */ rep outsw /* output many words */ - pop %ds pop %esi pop %ebp ret @@ -163,15 +151,11 @@ ENTRY(phys_outsb) mov %esp, %ebp cld push %esi - push %ds - mov $FLAT_DS_SELECTOR, %ecx - mov %cx, %ds mov 8(%ebp), %edx /* port to write to */ mov 12(%ebp), %esi /* source addr */ mov 16(%ebp), %ecx /* byte count */ rep outsb /* output many bytes */ - pop %ds pop %esi pop %ebp ret @@ -185,20 +169,18 @@ ENTRY(phys_outsb) * phys_bytes bytecount); * Copy a block of data from anywhere to anywhere in physical memory. */ - PC_ARGS = 4+4+4+4 /* 4 + 4 + 4 */ /* es edi esi eip src dst len */ ENTRY(phys_copy) + push %ebp + mov %esp, %ebp + cld push %esi push %edi - push %es - mov $FLAT_DS_SELECTOR, %eax - mov %ax, %es - - mov PC_ARGS(%esp), %esi - mov PC_ARGS+4(%esp), %edi - mov PC_ARGS+4+4(%esp), %eax + mov 8(%ebp), %esi + mov 12(%ebp), %edi + mov 16(%ebp), %eax cmp $10, %eax /* avoid align overhead for small counts */ jb pc_small @@ -207,43 +189,40 @@ ENTRY(phys_copy) and $3, %ecx /* count for alignment */ sub %ecx, %eax - rep movsb %es:(%esi), %es:(%edi) + rep movsb (%esi), (%edi) mov %eax, %ecx shr $2, %ecx /* count of dwords */ - rep movsl %es:(%esi), %es:(%edi) + rep movsl (%esi), (%edi) and $3, %eax pc_small: xchg %eax, %ecx /* remainder */ - rep movsb %es:(%esi), %es:(%edi) + rep movsb (%esi), (%edi) mov $0, %eax /* 0 means: no fault */ LABEL(phys_copy_fault) /* kernel can send us here */ - pop %es pop %edi pop %esi + pop %ebp ret LABEL(phys_copy_fault_in_kernel) /* kernel can send us here */ - pop %es pop %edi pop %esi + pop %ebp mov %cr2, %eax ret + /*===========================================================================*/ /* copy_msg_from_user */ /*===========================================================================*/ /* - * int copy_msg_from_user(struct proc * p, message * user_mbuf, message * dst); + * int copy_msg_from_user(message * user_mbuf, message * dst); * * Copies a message of 36 bytes from user process space to a kernel buffer. This - * function assumes that the process address space is installed (cr3 loaded) and - * the local descriptor table of this process is loaded too. - * - * The %gs segment register is used to access the userspace memory. We load the - * process' data segment in this register. + * function assumes that the process address space is installed (cr3 loaded). * * This function from the callers point of view either succeeds or returns an * error which gives the caller a chance to respond accordingly. In fact it @@ -255,39 +234,31 @@ LABEL(phys_copy_fault_in_kernel) /* kernel can send us here */ * userspace as if wrong values or request were passed to the kernel */ ENTRY(copy_msg_from_user) - push %gs - - mov 8(%esp), %eax - movw DSREG(%eax), %gs - /* load the source pointer */ - mov 12(%esp), %ecx + mov 4(%esp), %ecx /* load the destination pointer */ - mov 16(%esp), %edx + mov 8(%esp), %edx - mov %gs:0*4(%ecx), %eax - mov %eax, 0*4(%edx) - mov %gs:1*4(%ecx), %eax +/* mov 0*4(%ecx), %eax + mov %eax, 0*4(%edx) */ + mov 1*4(%ecx), %eax mov %eax, 1*4(%edx) - mov %gs:2*4(%ecx), %eax + mov 2*4(%ecx), %eax mov %eax, 2*4(%edx) - mov %gs:3*4(%ecx), %eax + mov 3*4(%ecx), %eax mov %eax, 3*4(%edx) - mov %gs:4*4(%ecx), %eax + mov 4*4(%ecx), %eax mov %eax, 4*4(%edx) - mov %gs:5*4(%ecx), %eax + mov 5*4(%ecx), %eax mov %eax, 5*4(%edx) - mov %gs:6*4(%ecx), %eax + mov 6*4(%ecx), %eax mov %eax, 6*4(%edx) - mov %gs:7*4(%ecx), %eax + mov 7*4(%ecx), %eax mov %eax, 7*4(%edx) - mov %gs:8*4(%ecx), %eax + mov 8*4(%ecx), %eax mov %eax, 8*4(%edx) LABEL(__copy_msg_from_user_end) - - pop %gs - movl $0, %eax ret @@ -295,48 +266,38 @@ LABEL(__copy_msg_from_user_end) /* copy_msg_to_user */ /*===========================================================================*/ /* - * void copy_msg_to_user(struct proc * p, message * src, message * user_mbuf); + * void copy_msg_to_user(message * src, message * user_mbuf); * - * Copies a message of 36 bytes to user process space from a kernel buffer. This - * function assumes that the process address space is installed (cr3 loaded) and - * the local descriptor table of this process is loaded too. + * Copies a message of 36 bytes to user process space from a kernel buffer. * * All the other copy_msg_from_user() comments apply here as well! */ ENTRY(copy_msg_to_user) - push %gs - - mov 8(%esp), %eax - movw DSREG(%eax), %gs - /* load the source pointer */ - mov 12(%esp), %ecx + mov 4(%esp), %ecx /* load the destination pointer */ - mov 16(%esp), %edx + mov 8(%esp), %edx mov 0*4(%ecx), %eax - mov %eax, %gs:0*4(%edx) + mov %eax, 0*4(%edx) mov 1*4(%ecx), %eax - mov %eax, %gs:1*4(%edx) + mov %eax, 1*4(%edx) mov 2*4(%ecx), %eax - mov %eax, %gs:2*4(%edx) + mov %eax, 2*4(%edx) mov 3*4(%ecx), %eax - mov %eax, %gs:3*4(%edx) + mov %eax, 3*4(%edx) mov 4*4(%ecx), %eax - mov %eax, %gs:4*4(%edx) + mov %eax, 4*4(%edx) mov 5*4(%ecx), %eax - mov %eax, %gs:5*4(%edx) + mov %eax, 5*4(%edx) mov 6*4(%ecx), %eax - mov %eax, %gs:6*4(%edx) + mov %eax, 6*4(%edx) mov 7*4(%ecx), %eax - mov %eax, %gs:7*4(%edx) + mov %eax, 7*4(%edx) mov 8*4(%ecx), %eax - mov %eax, %gs:8*4(%edx) + mov %eax, 8*4(%edx) LABEL(__copy_msg_to_user_end) - - pop %gs - movl $0, %eax ret @@ -348,8 +309,6 @@ LABEL(__copy_msg_to_user_end) * here to continue, clean up and report the error */ ENTRY(__user_copy_msg_pointer_failure) - pop %gs - movl $-1, %eax ret @@ -366,12 +325,9 @@ ENTRY(phys_memset) mov %esp, %ebp push %esi push %ebx - push %ds mov 8(%ebp), %esi mov 16(%ebp), %eax - mov $FLAT_DS_SELECTOR, %ebx - mov %bx, %ds mov 12(%ebp), %ebx shr $2, %eax fill_start: @@ -395,37 +351,18 @@ remain_fill: fill_done: LABEL(memset_fault) /* kernel can send us here */ mov $0, %eax /* 0 means: no fault */ - pop %ds pop %ebx pop %esi pop %ebp ret LABEL(memset_fault_in_kernel) /* kernel can send us here */ - pop %ds pop %ebx pop %esi pop %ebp mov %cr2, %eax ret - -/*===========================================================================*/ -/* mem_rdw */ -/*===========================================================================*/ -/* - * PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset); - * Load and return word at far pointer segment:offset. - */ -ENTRY(mem_rdw) - mov %ds, %cx - mov 4(%esp), %ds - mov 4+4(%esp), %eax /* offset */ - movzwl (%eax), %eax /* word to return */ - mov %cx, %ds - ret - - /*===========================================================================*/ /* x86_triplefault */ /*===========================================================================*/ @@ -565,12 +502,13 @@ ARG_EAX_ACTION(fnstcw, fnstcw (%eax)); /* invlpg */ ARG_EAX_ACTION(i386_invlpg, invlpg (%eax)); -/*===========================================================================*/ -/* getcr3val */ -/*===========================================================================*/ -/* PUBLIC unsigned long getcr3val(void); */ -ENTRY(getcr3val) - mov %cr3, %eax +ENTRY(x86_load_kerncs) + push %ebp + mov %esp, %ebp + mov 8(%ebp), %eax + jmp $KERN_CS_SELECTOR, $newcs +newcs: + pop %ebp ret /* @@ -609,27 +547,6 @@ ENTRY(ia32_msr_write) pop %ebp ret -/*===========================================================================*/ -/* idt_reload */ -/*===========================================================================*/ -/* PUBLIC void idt_reload (void); */ -/* reload idt when returning to monitor. */ -ENTRY(idt_reload) - lidt _C_LABEL(gdt)+IDT_SELECTOR /* reload interrupt descriptor table */ - ret - -/* - * void reload_segment_regs(void) - */ - -#define RELOAD_SEG_REG(reg) \ - mov reg, %ax ;\ - mov %ax, reg ; - -ENTRY(reload_ds) - RELOAD_SEG_REG(%ds) - ret - /*===========================================================================*/ /* __switch_address_space */ /*===========================================================================*/ @@ -642,8 +559,6 @@ ENTRY(reload_ds) ENTRY(__switch_address_space) /* read the process pointer */ mov 4(%esp), %edx - /* enable process' segment descriptors */ - lldt P_LDT_SEL(%edx) /* get the new cr3 value */ movl P_CR3(%edx), %eax /* test if the new cr3 != NULL */ @@ -664,52 +579,6 @@ ENTRY(__switch_address_space) 0: ret -/*===========================================================================*/ -/* poweroff */ -/*===========================================================================*/ -/* PUBLIC void poweroff(); */ -/* Jump to 16-bit poweroff code */ -ENTRY(poweroff_jmp) - cli - /* Make real mode descriptor */ - mov $(_C_LABEL(gdt) + SS_SELECTOR), %edi - mov $0x100, %eax - movw %ax, 2(%edi) - shr $16, %eax - movb %al, 4(%edi) - and $0xff00, %ax - andw $0xff, 6(%edi) - or %ax, 6(%edi) - mov $0xffff, %eax - movw %ax, (%edi) - shr $16, %eax - and $0xf, %ax - andb $0xf0, 6(%edi) - or %ax, 6(%edi) - - /* Flush TLB */ - xor %eax, %eax - mov %eax, %cr3 - - xor %esp, %esp /* clear esp for real mode*/ - - /* Reset IDTR */ - lidt idt_ptr - - mov $SS_SELECTOR, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - - /* Save real mode cr0 in eax */ - mov %cr0, %eax - andl $~I386_CR0_PE, %eax - - /* Jump to 16-bit code that is copied to below 1MB */ - ljmp $MON_CS_SELECTOR, $0 - /* acknowledge just the master PIC */ ENTRY(eoi_8259_master) movb $END_OF_INT, %al @@ -909,3 +778,6 @@ ENTRY(switch_k_stack) idt_ptr: .short 0x3ff .long 0x0 + +ldtsel: + .long LDT_SELECTOR diff --git a/kernel/arch/i386/mb_utils.h b/kernel/arch/i386/mb_utils.h deleted file mode 100644 index f45a27cee..000000000 --- a/kernel/arch/i386/mb_utils.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MB_UTILS_H -#define MB_UTILS_H - -#include "kernel/kernel.h" - -void mb_cls(void); -void mb_print(char*); -void mb_print_char(char); -int mb_read_char(unsigned char*); - - -#endif diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c index b3dbe8c22..c78077601 100644 --- a/kernel/arch/i386/memory.c +++ b/kernel/arch/i386/memory.c @@ -27,24 +27,27 @@ #endif #endif -int i386_paging_enabled = 0; - -static int psok = 0; - -#define MAX_FREEPDES 2 -static int nfreepdes = 0, freepdes[MAX_FREEPDES]; +phys_bytes video_mem_vaddr = 0; #define HASPT(procptr) ((procptr)->p_seg.p_cr3 != 0) +static int nfreepdes = 0; +#define MAXFREEPDES 2 +static int freepdes[MAXFREEPDES]; static u32_t phys_get32(phys_bytes v); -static void vm_enable_paging(void); - -void segmentation2paging(struct proc * current) +void mem_clear_mapcache(void) { - /* switch to the current process page tables before turning paging on */ - switch_address_space(current); - vm_enable_paging(); + int i; + for(i = 0; i < nfreepdes; i++) { + struct proc *ptproc = get_cpulocal_var(ptproc); + int pde = freepdes[i]; + u32_t *ptv; + assert(ptproc); + ptv = ptproc->p_seg.p_cr3_v; + assert(ptv); + ptv[pde] = 0; + } } /* This function sets up a mapping from within the kernel's address @@ -65,7 +68,7 @@ void segmentation2paging(struct proc * current) * * The logical number supplied by the caller is translated into an actual * pde number to be used, and a pointer to it (linear address) is returned - * for actual use by phys_copy or phys_memset. + * for actual use by phys_copy or memset. */ static phys_bytes createpde( const struct proc *pr, /* Requested process, NULL for physical. */ @@ -83,10 +86,10 @@ static phys_bytes createpde( pde = freepdes[free_pde_idx]; assert(pde >= 0 && pde < 1024); - if(pr && ((pr == get_cpulocal_var(ptproc)) || !HASPT(pr))) { + if(pr && ((pr == get_cpulocal_var(ptproc)) || iskernelp(pr))) { /* Process memory is requested, and * it's a process that is already in current page table, or - * a process that is in every page table. + * the kernel, which is always there. * Therefore linaddr is valid directly, with the requested * size. */ @@ -138,9 +141,6 @@ static int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u32_t addr; proc_nr_t procslot; - assert(vm_running); - assert(nfreepdes >= MAX_FREEPDES); - assert(get_cpulocal_var(ptproc)); assert(get_cpulocal_var(proc_ptr)); assert(read_cr3() == get_cpulocal_var(ptproc)->p_seg.p_cr3); @@ -219,13 +219,8 @@ static u32_t phys_get32(phys_bytes addr) const u32_t v; int r; - if(!vm_running) { - phys_copy(addr, vir2phys(&v), sizeof(v)); - return v; - } - if((r=lin_lin_copy(NULL, addr, - proc_addr(SYSTEM), vir2phys(&v), sizeof(v))) != OK) { + proc_addr(SYSTEM), (phys_bytes) &v, sizeof(v))) != OK) { panic("lin_lin_copy for phys_get32 failed: %d", r); } @@ -266,87 +261,6 @@ static char *cr4_str(u32_t e) } #endif -void vm_stop(void) -{ - write_cr0(read_cr0() & ~I386_CR0_PG); -} - -static void vm_enable_paging(void) -{ - u32_t cr0, cr4; - int pgeok; - - psok = _cpufeature(_CPUF_I386_PSE); - pgeok = _cpufeature(_CPUF_I386_PGE); - - cr0= read_cr0(); - cr4= read_cr4(); - - /* First clear PG and PGE flag, as PGE must be enabled after PG. */ - write_cr0(cr0 & ~I386_CR0_PG); - write_cr4(cr4 & ~(I386_CR4_PGE | I386_CR4_PSE)); - - cr0= read_cr0(); - cr4= read_cr4(); - - /* Our first page table contains 4MB entries. */ - if(psok) - cr4 |= I386_CR4_PSE; - - write_cr4(cr4); - - /* First enable paging, then enable global page flag. */ - cr0 |= I386_CR0_PG; - write_cr0(cr0 ); - cr0 |= I386_CR0_WP; - write_cr0(cr0); - - /* May we enable these features? */ - if(pgeok) - cr4 |= I386_CR4_PGE; - - write_cr4(cr4); -} - -/*===========================================================================* - * umap_local * - *===========================================================================*/ -phys_bytes umap_local(rp, seg, vir_addr, bytes) -register struct proc *rp; /* pointer to proc table entry for process */ -int seg; /* T, D, or S segment */ -vir_bytes vir_addr; /* virtual address in bytes within the seg */ -vir_bytes bytes; /* # of bytes to be copied */ -{ -/* Calculate the physical memory address for a given virtual address. */ - vir_clicks vc; /* the virtual address in clicks */ - phys_bytes pa; /* intermediate variables as phys_bytes */ - phys_bytes seg_base; - - if(seg != T && seg != D && seg != S) - panic("umap_local: wrong seg: %d", seg); - - if (bytes <= 0) return( (phys_bytes) 0); - if (vir_addr + bytes <= vir_addr) return 0; /* overflow */ - vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */ - - if (seg != T) - seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S); - else if (rp->p_memmap[T].mem_len == 0) /* common I&D? */ - seg = D; /* ptrace needs this */ - - if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir + - rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 ); - - if (vc >= rp->p_memmap[seg].mem_vir + - rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 ); - - seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys; - seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */ - pa = (phys_bytes) vir_addr; - pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT; - return(seg_base + pa); -} - /*===========================================================================* * umap_virtual * *===========================================================================*/ @@ -356,22 +270,15 @@ int seg; /* T, D, or S segment */ vir_bytes vir_addr; /* virtual address in bytes within the seg */ vir_bytes bytes; /* # of bytes to be copied */ { - vir_bytes linear; phys_bytes phys = 0; - if(!(linear = umap_local(rp, seg, vir_addr, bytes))) { - printf("SYSTEM:umap_virtual: umap_local failed\n"); - phys = 0; - } else { - if(vm_lookup(rp, linear, &phys, NULL) != OK) { - printf("SYSTEM:umap_virtual: vm_lookup of %s: seg 0x%x: 0x%lx failed\n", rp->p_name, seg, vir_addr); - phys = 0; - } else { - if(phys == 0) - panic("vm_lookup returned phys: %d", phys); - } - } - + if(vm_lookup(rp, vir_addr, &phys, NULL) != OK) { + printf("SYSTEM:umap_virtual: vm_lookup of %s: seg 0x%x: 0x%lx failed\n", rp->p_name, seg, vir_addr); + phys = 0; + } else { + if(phys == 0) + panic("vm_lookup returned phys: %d", phys); + } if(phys == 0) { printf("SYSTEM:umap_virtual: lookup failed\n"); @@ -381,9 +288,9 @@ vir_bytes bytes; /* # of bytes to be copied */ /* Now make sure addresses are contiguous in physical memory * so that the umap makes sense. */ - if(bytes > 0 && vm_lookup_range(rp, linear, NULL, bytes) != bytes) { + if(bytes > 0 && vm_lookup_range(rp, vir_addr, NULL, bytes) != bytes) { printf("umap_virtual: %s: %lu at 0x%lx (vir 0x%lx) not contiguous\n", - rp->p_name, bytes, linear, vir_addr); + rp->p_name, bytes, vir_addr, vir_addr); return 0; } @@ -409,11 +316,7 @@ int vm_lookup(const struct proc *proc, const vir_bytes virtual, assert(proc); assert(physical); assert(!isemptyp(proc)); - - if(!HASPT(proc)) { - *physical = virtual; - return OK; - } + assert(HASPT(proc)); /* Retrieve page directory entry. */ root = (u32_t *) proc->p_seg.p_cr3; @@ -472,9 +375,7 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr, assert(proc); assert(bytes > 0); - - if (!HASPT(proc)) - return bytes; + assert(HASPT(proc)); /* Look up the first page. */ if (vm_lookup(proc, vir_addr, &phys, NULL) != OK) @@ -548,9 +449,6 @@ int vm_check_range(struct proc *caller, struct proc *target, */ int r; - if (!vm_running) - return EFAULT; - if ((caller->p_misc_flags & MF_KCALL_RESUME) && (r = caller->p_vmrequest.vmresult) != OK) return r; @@ -570,7 +468,7 @@ void delivermsg(struct proc *rp) assert(rp->p_misc_flags & MF_DELIVERMSG); assert(rp->p_delivermsg.m_source != NONE); - if (copy_msg_to_user(rp, &rp->p_delivermsg, + if (copy_msg_to_user(&rp->p_delivermsg, (message *) rp->p_delivermsg_vir)) { printf("WARNING wrong user pointer 0x%08lx from " "process %s / %d\n", @@ -671,24 +569,12 @@ int vm_memset(endpoint_t who, phys_bytes ph, const u8_t c, phys_bytes bytes) /* NONE for physical, otherwise virtual */ if(who != NONE) { int n; - vir_bytes lin; - assert(vm_running); if(!isokendpt(who, &n)) return ESRCH; whoptr = proc_addr(n); - if(!(lin = umap_local(whoptr, D, ph, bytes))) return EFAULT; - ph = lin; } p = c | (c << 8) | (c << 16) | (c << 24); - if(!vm_running) { - if(who != NONE) panic("can't vm_memset without vm running"); - phys_memset(ph, p, bytes); - return OK; - } - - assert(nfreepdes >= MAX_FREEPDES); - assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v); assert(!catch_pagefaults); @@ -736,9 +622,7 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ { /* Copy bytes from virtual address src_addr to virtual address dst_addr. */ struct vir_addr *vir_addr[2]; /* virtual source and destination address */ - phys_bytes phys_addr[2]; /* absolute source and destination */ - int seg_index; - int i; + int i, r; struct proc *procs[2]; assert((vmcheck && caller) || (!vmcheck && !caller)); @@ -751,111 +635,57 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ vir_addr[_DST_] = dst_addr; for (i=_SRC_; i<=_DST_; i++) { - int proc_nr, type; + endpoint_t proc_e = vir_addr[i]->proc_nr_e; + int proc_nr; struct proc *p; - type = vir_addr[i]->segment & SEGMENT_TYPE; - if((type != PHYS_SEG) && isokendpt(vir_addr[i]->proc_nr_e, &proc_nr)) - p = proc_addr(proc_nr); - else + if(proc_e == NONE) { p = NULL; + } else { + if(!isokendpt(proc_e, &proc_nr)) { + printf("virtual_copy: no reasonable endpoint\n"); + return ESRCH; + } + p = proc_addr(proc_nr); + } procs[i] = p; - - /* Get physical address. */ - switch(type) { - case LOCAL_SEG: - case LOCAL_VM_SEG: - if(!p) { - return EDEADSRCDST; - } - seg_index = vir_addr[i]->segment & SEGMENT_INDEX; - if(type == LOCAL_SEG) - phys_addr[i] = umap_local(p, seg_index, vir_addr[i]->offset, - bytes); - else - phys_addr[i] = umap_virtual(p, seg_index, - vir_addr[i]->offset, bytes); - if(phys_addr[i] == 0) { - printf("virtual_copy: map 0x%x failed for %s seg %d, " - "offset %lx, len %lu, i %d\n", - type, p->p_name, seg_index, vir_addr[i]->offset, - bytes, i); - } - break; - case PHYS_SEG: - phys_addr[i] = vir_addr[i]->offset; - break; - default: - printf("virtual_copy: strange type 0x%x\n", type); - return EINVAL; - } - - /* Check if mapping succeeded. */ - if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) { - printf("virtual_copy EFAULT\n"); - return EFAULT; - } } - if(vm_running) { - int r; - - if(caller && (caller->p_misc_flags & MF_KCALL_RESUME)) { - assert(caller->p_vmrequest.vmresult != VMSUSPEND); - if(caller->p_vmrequest.vmresult != OK) { - return caller->p_vmrequest.vmresult; - } - } - - if((r=lin_lin_copy(procs[_SRC_], phys_addr[_SRC_], - procs[_DST_], phys_addr[_DST_], bytes)) != OK) { - struct proc *target = NULL; - phys_bytes lin; - if(r != EFAULT_SRC && r != EFAULT_DST) - panic("lin_lin_copy failed: %d", r); - if(!vmcheck || !caller) { - return r; - } - - if(r == EFAULT_SRC) { - lin = phys_addr[_SRC_]; - target = procs[_SRC_]; - } else if(r == EFAULT_DST) { - lin = phys_addr[_DST_]; - target = procs[_DST_]; - } else { - panic("r strange: %d", r); - } - - assert(caller); - assert(target); - - vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL); - return VMSUSPEND; - } - - return OK; + if(caller && (caller->p_misc_flags & MF_KCALL_RESUME)) { + assert(caller->p_vmrequest.vmresult != VMSUSPEND); + if(caller->p_vmrequest.vmresult != OK) { + return caller->p_vmrequest.vmresult; + } } - assert(!vm_running); + if((r=lin_lin_copy(procs[_SRC_], vir_addr[_SRC_]->offset, + procs[_DST_], vir_addr[_DST_]->offset, bytes)) != OK) { + struct proc *target = NULL; + phys_bytes lin; + if(r != EFAULT_SRC && r != EFAULT_DST) + panic("lin_lin_copy failed: %d", r); + if(!vmcheck || !caller) { + return r; + } - /* can't copy to/from process with PT without VM */ -#define NOPT(p) (!(p) || !HASPT(p)) - if(!NOPT(procs[_SRC_])) { - printf("ignoring page table src: %s / %d at 0x%x\n", - procs[_SRC_]->p_name, procs[_SRC_]->p_endpoint, procs[_SRC_]->p_seg.p_cr3); -} - if(!NOPT(procs[_DST_])) { - printf("ignoring page table dst: %s / %d at 0x%x\n", - procs[_DST_]->p_name, procs[_DST_]->p_endpoint, - procs[_DST_]->p_seg.p_cr3); + if(r == EFAULT_SRC) { + lin = vir_addr[_SRC_]->offset; + target = procs[_SRC_]; + } else if(r == EFAULT_DST) { + lin = vir_addr[_DST_]->offset; + target = procs[_DST_]; + } else { + panic("r strange: %d", r); + } + + assert(caller); + assert(target); + + vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL); + return VMSUSPEND; } - /* Now copy bytes between physical addresseses. */ - if(phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes)) - return EFAULT; - return OK; } @@ -868,11 +698,12 @@ int data_copy(const endpoint_t from_proc, const vir_bytes from_addr, { struct vir_addr src, dst; - src.segment = dst.segment = D; src.offset = from_addr; dst.offset = to_addr; src.proc_nr_e = from_proc; dst.proc_nr_e = to_proc; + assert(src.proc_nr_e != NONE); + assert(dst.proc_nr_e != NONE); return virtual_copy(&src, &dst, bytes); } @@ -887,37 +718,48 @@ int data_copy_vmcheck(struct proc * caller, { struct vir_addr src, dst; - src.segment = dst.segment = D; src.offset = from_addr; dst.offset = to_addr; src.proc_nr_e = from_proc; dst.proc_nr_e = to_proc; + assert(src.proc_nr_e != NONE); + assert(dst.proc_nr_e != NONE); return virtual_copy_vmcheck(caller, &src, &dst, bytes); } -/*===========================================================================* - * arch_pre_exec * - *===========================================================================*/ -void arch_pre_exec(struct proc *pr, const u32_t ip, const u32_t sp) +void memory_init(void) { -/* set program counter and stack pointer. */ - pr->p_reg.pc = ip; - pr->p_reg.sp = sp; + assert(nfreepdes == 0); + + freepdes[nfreepdes++] = kinfo.freepde_start++; + freepdes[nfreepdes++] = kinfo.freepde_start++; + + assert(kinfo.freepde_start < I386_VM_DIR_ENTRIES); + assert(nfreepdes == 2); + assert(nfreepdes <= MAXFREEPDES); } -/* VM reports page directory slot we're allowed to use freely. */ -void i386_freepde(const int pde) +/*===========================================================================* + * arch_proc_init * + *===========================================================================*/ +void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, char *name) { - if(nfreepdes >= MAX_FREEPDES) - return; - freepdes[nfreepdes++] = pde; + arch_proc_reset(pr); + strcpy(pr->p_name, name); + + /* set custom state we know */ + pr->p_reg.pc = ip; + pr->p_reg.sp = sp; } static int oxpcie_mapping_index = -1, lapic_mapping_index = -1, ioapic_first_index = -1, - ioapic_last_index = -1; + ioapic_last_index = -1, + video_mem_mapping_index = -1; + +extern char *video_mem; int arch_phys_map(const int index, phys_bytes *addr, @@ -929,6 +771,8 @@ int arch_phys_map(const int index, static char *ser_var = NULL; if(first) { + video_mem_mapping_index = freeidx++; + #ifdef USE_APIC if(lapic_addr) lapic_mapping_index = freeidx++; @@ -950,20 +794,28 @@ int arch_phys_map(const int index, } } #endif + first = 0; } #ifdef USE_APIC - /* map the local APIC if enabled */ - if (index == lapic_mapping_index) { + if (index == video_mem_mapping_index) { + /* map video memory in so we can print panic messages */ + *addr = MULTIBOOT_VIDEO_BUFFER; + *len = I386_PAGE_SIZE; + *flags = 0; + return OK; + } + else if (index == lapic_mapping_index) { + /* map the local APIC if enabled */ if (!lapic_addr) return EINVAL; - *addr = vir2phys(lapic_addr); + *addr = lapic_addr; *len = 4 << 10 /* 4kB */; *flags = VMMF_UNCACHED; return OK; } - else if (ioapic_enabled && index <= nioapics) { + else if (ioapic_enabled && index <= ioapic_last_index) { *addr = io_apic[index - 1].paddr; *len = 4 << 10 /* 4kB */; *flags = VMMF_UNCACHED; @@ -993,7 +845,8 @@ int arch_phys_map_reply(const int index, const vir_bytes addr) } else if (ioapic_enabled && index >= ioapic_first_index && index <= ioapic_last_index) { - io_apic[index - ioapic_first_index].vaddr = addr; + int i = index - ioapic_first_index; + io_apic[i].vaddr = addr; return OK; } #endif @@ -1004,56 +857,22 @@ int arch_phys_map_reply(const int index, const vir_bytes addr) return OK; } #endif + if (index == video_mem_mapping_index) { + video_mem_vaddr = addr; + return OK; + } return EINVAL; } -int arch_enable_paging(struct proc * caller, const message * m_ptr) +int arch_enable_paging(struct proc * caller) { - struct vm_ep_data ep_data; - int r; + assert(caller->p_seg.p_cr3); - /* switch_address_space() checks what is in cr3, and do nothing if it's - * the same as the cr3 of its argument, newptproc. If MINIX was - * previously booted, this could very well be the case. - * - * The first time switch_address_space() is called, we want to - * force it to do something (load cr3 and set newptproc), so we - * zero cr3, and force paging off to make that a safe thing to do. - * - * After that, segmentation2paging() enables paging with the page table - * of caller loaded. - */ + /* load caller's page table */ + switch_address_space(caller); - vm_stop(); - write_cr3(0); - - /* switch from segmentation only to paging */ - segmentation2paging(caller); - - vm_running = 1; - - /* - * copy the extra data associated with the call from userspace - */ - if((r=data_copy(caller->p_endpoint, (vir_bytes)m_ptr->SVMCTL_VALUE, - KERNEL, (vir_bytes) &ep_data, sizeof(ep_data))) != OK) { - printf("vmctl_enable_paging: data_copy failed! (%d)\n", r); - return r; - } - - /* - * when turning paging on i386 we also change the segment limits to make - * the special mappings requested by the kernel reachable - */ - if ((r = prot_set_kern_seg_limit(ep_data.data_seg_limit)) != OK) - return r; - - /* - * install the new map provided by the call - */ - if (newmap(caller, caller, ep_data.mem_map) != OK) - panic("arch_enable_paging: newmap failed"); + video_mem = (char *) video_mem_vaddr; #ifdef USE_APIC /* start using the virtual addresses */ @@ -1074,8 +893,6 @@ int arch_enable_paging(struct proc * caller, const message * m_ptr) #if CONFIG_SMP barrier(); - i386_paging_enabled = 1; - wait_for_APs_to_finish_booting(); #endif #endif @@ -1120,7 +937,7 @@ int platform_tbl_ptr(phys_bytes start, phys_bytes addr; for (addr = start; addr < end; addr += increment) { - phys_copy (addr, vir2phys(buff), size); + phys_copy (addr, (phys_bytes) buff, size); if (cmp_f(buff)) { if (phys_addr) *phys_addr = addr; diff --git a/kernel/arch/i386/mpx.S b/kernel/arch/i386/mpx.S index 89c0d8659..830a99415 100644 --- a/kernel/arch/i386/mpx.S +++ b/kernel/arch/i386/mpx.S @@ -50,116 +50,10 @@ IMPORT(copr_not_available_handler) IMPORT(params_size) IMPORT(params_offset) -IMPORT(mon_ds) IMPORT(switch_to_user) IMPORT(multiboot_init) .text -/*===========================================================================*/ -/* MINIX */ -/*===========================================================================*/ -.global MINIX -MINIX: -/* this is the entry point for the MINIX kernel */ - - jmp _C_LABEL(multiboot_init) - -/* Multiboot header here*/ - -.balign 8 - -multiboot_magic: - .long MULTIBOOT_HEADER_MAGIC -multiboot_flags: - .long MULTIBOOT_FLAGS -multiboot_checksum: - .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_FLAGS) - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 -/* Video mode */ -multiboot_mode_type: - .long MULTIBOOT_VIDEO_MODE_EGA -multiboot_width: - .long MULTIBOOT_CONSOLE_COLS -multiboot_height: - .long MULTIBOOT_CONSOLE_LINES -multiboot_depth: - .long 0 - -.globl kernel_init -kernel_init: /* after pre-init*/ - push %ebp - mov %esp, %ebp - push %esi - push %edi -/* Copy the monitor global descriptor table to the address space of kernel and */ -/* switch over to it. Prot_init() can then update it with immediate effect. */ - - sgdt _C_LABEL(gdt)+GDT_SELECTOR /* get the monitor gdtr */ - movl _C_LABEL(gdt)+GDT_SELECTOR+2, %esi /* absolute address of GDT */ - mov $_C_LABEL(gdt), %ebx /* address of kernel GDT */ - mov $8*8, %ecx /* copying eight descriptors */ -copygdt: - movb %es:(%esi), %al - movb %al, (%ebx) - inc %esi - inc %ebx - loop copygdt - movl _C_LABEL(gdt)+DS_SELECTOR+2, %eax /* base of kernel data */ - and $0x00FFFFFF, %eax /* only 24 bits */ - add $_C_LABEL(gdt), %eax /* eax = vir2phys(gdt) */ - movl %eax, _C_LABEL(gdt)+GDT_SELECTOR+2 /* set base of GDT */ - lgdt _C_LABEL(gdt)+GDT_SELECTOR /* switch over to kernel GDT */ - -/* Locate boot parameters, set up kernel segment registers and stack. */ - mov 8(%ebp), %ebx /* boot parameters offset */ - mov 12(%ebp), %edx /* boot parameters length */ - mov 16(%ebp), %eax /* address of a.out headers */ - mov %ds, %ax /* kernel data */ - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - mov $_C_LABEL(k_boot_stktop) - 4, %esp /* set sp to point to the top of kernel stack */ - -/* Save boot parameters into these global variables for i386 code */ - movl %edx, _C_LABEL(params_size) - movl %ebx, _C_LABEL(params_offset) - movl $SS_SELECTOR, _C_LABEL(mon_ds) - -/* Call C startup code to set up a proper environment to run main(). */ - push %edx - push %ebx - push $SS_SELECTOR - push $DS_SELECTOR - push $CS_SELECTOR - call _C_LABEL(cstart) /* cstart(cs, ds, mds, parmoff, parmlen) */ - add $5*4, %esp - -/* Reload gdtr, idtr and the segment registers to global descriptor table set */ -/* up by prot_init(). */ - - lgdt _C_LABEL(gdt)+GDT_SELECTOR - lidt _C_LABEL(gdt)+IDT_SELECTOR - - ljmp $CS_SELECTOR, $csinit -csinit: - movw $DS_SELECTOR, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - movw $TSS_SELECTOR_BOOT, %ax /* no other TSS is used */ - ltr %ax - push $0 /* set flags to known good state */ - popf /* esp, clear nested task and int enable */ - jmp _C_LABEL(main) /* main() */ - - /*===========================================================================*/ /* interrupt handlers */ /* interrupt handlers for 386 32-bit protected mode */ @@ -419,22 +313,26 @@ ENTRY(restore_user_context) mov 4(%esp), %ebp /* will assume P_STACKBASE == 0 */ /* reconstruct the stack for iret */ - movl SSREG(%ebp), %eax - push %eax + push $USER_DS_SELECTOR /* ss */ movl SPREG(%ebp), %eax push %eax movl PSWREG(%ebp), %eax push %eax - movl CSREG(%ebp), %eax - push %eax + push $USER_CS_SELECTOR /* cs */ movl PCREG(%ebp), %eax push %eax + /* Restore segments as the user should see them. */ + movw $USER_DS_SELECTOR, %si + movw %si, %ds + movw %si, %es + movw %si, %fs + movw %si, %gs + + /* Same for general-purpose registers. */ RESTORE_GP_REGS(%ebp) - RESTORE_SEGS(%ebp) - - movl %ss:BPREG(%ebp), %ebp + movl BPREG(%ebp), %ebp iret /* continue process */ @@ -582,7 +480,7 @@ ENTRY(startup_ap_32) * we are in protected mode now, %cs is correct and we need to set the * data descriptors before we can touch anything */ - movw $DS_SELECTOR, %ax + movw $KERN_DS_SELECTOR, %ax mov %ax, %ds mov %ax, %ss mov %ax, %es @@ -613,6 +511,10 @@ ENTRY(startup_ap_32) .data .short 0x526F /* this must be the first data entry (magic #) */ .bss +k_initial_stack: +.space K_STACK_SIZE +LABEL(__k_unpaged_k_initial_stktop) + /* * the kernel stack */ diff --git a/kernel/arch/i386/multiboot.S b/kernel/arch/i386/multiboot.S deleted file mode 100644 index 4fdd0973a..000000000 --- a/kernel/arch/i386/multiboot.S +++ /dev/null @@ -1,73 +0,0 @@ -#include "kernel/kernel.h" /* configures the kernel */ -#include -#include -#include -#include -#include -#include "archconst.h" -#include "kernel/const.h" -#include "kernel/proc.h" -#include "sconst.h" -#include - -#define GDT_SET_ENTRY(selector, base, limit) \ - mov %ebp, %edi; \ - add $(_C_LABEL(gdt) + selector), %edi; \ - mov base, %eax; \ - movw %ax, 2(%edi); \ - shr $16, %eax; \ - movb %al, 4(%edi); \ - and $0xff00, %ax; \ - andw $0xff, 6(%edi); \ - or %ax, 6(%edi); \ - mov limit, %eax; \ - movw %ax, (%edi); \ - shr $16, %eax; \ - and $0xf, %ax; \ - andb $0xf0, 6(%edi); \ - or %ax, 6(%edi); \ - -IMPORT(pre_init) -.extern kernel_init - -ENTRY(multiboot_init) - mov $(GDT_SIZE*DESC_SIZE), %eax - mov $(_C_LABEL(gdt) + GDT_SELECTOR), %edi - mov %ax, (%edi) - mov $_C_LABEL(gdt), %eax - mov %eax, 2(%edi) - lgdt (%edi) - ljmp $(CS_SELECTOR), $reload_cs - -reload_cs: - mov $DS_SELECTOR, %eax - mov %eax, %ds - mov %eax, %ss - mov %eax, %es - mov %eax, %fs - mov %eax, %gs - - mov $(multiboot_stack + MULTIBOOT_STACK_SIZE), %esp - - push %ebx - call _C_LABEL(pre_init) - - add $4, %esp - - /* return to old boot code of kernel */ - push %eax - push $MULTIBOOT_PARAM_BUF_SIZE - push $_C_LABEL(multiboot_param_buf) - push $0 - - mov $ES_SELECTOR, %eax - mov %eax, %es - - jmp kernel_init - -.data -LABEL(multiboot_param_buf) - .space MULTIBOOT_PARAM_BUF_SIZE - -multiboot_stack: -.space MULTIBOOT_STACK_SIZE + 4 diff --git a/kernel/arch/i386/pg_utils.c b/kernel/arch/i386/pg_utils.c new file mode 100644 index 000000000..270250001 --- /dev/null +++ b/kernel/arch/i386/pg_utils.c @@ -0,0 +1,260 @@ + +#include + +#include +#include +#include +#include "kernel.h" +#include "arch_proto.h" + +#include +#include +#include + +/* These are set/computed in kernel.lds. */ +extern char _kern_vir_base, _kern_phys_base, _kern_size; + +/* Retrieve the absolute values to something we can use. */ +static phys_bytes kern_vir_start = (phys_bytes) &_kern_vir_base; +static phys_bytes kern_phys_start = (phys_bytes) &_kern_phys_base; +static phys_bytes kern_kernlen = (phys_bytes) &_kern_size; + +/* page directory we can use to map things */ +static u32_t pagedir[1024] __aligned(4096); + +void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end) +{ + int m; + phys_bytes o; + + if((o=start % I386_PAGE_SIZE)) + start -= o; + if((o=end % I386_PAGE_SIZE)) + end += I386_PAGE_SIZE - o; + + for(m = 0; m < cbi->mmap_size; m++) { + phys_bytes substart = start, subend = end; + phys_bytes memaddr = cbi->memmap[m].addr, + memend = cbi->memmap[m].addr + cbi->memmap[m].len; + + /* adjust cut range to be a subset of the free memory */ + if(substart < memaddr) substart = memaddr; + if(subend > memend) subend = memend; + if(substart >= subend) continue; + + /* if there is any overlap, forget this one and add + * 1-2 subranges back + */ + cbi->memmap[m].addr = cbi->memmap[m].len = 0; + if(substart > memaddr) + add_memmap(cbi, memaddr, substart-memaddr); + if(subend < memend) + add_memmap(cbi, subend, memend-subend); + } +} + +void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len) +{ + int m; + phys_bytes highmark; +#define LIMIT 0xFFFFF000 + /* Truncate available memory at 4GB as the rest of minix + * currently can't deal with any bigger. + */ + if(addr > LIMIT) return; + if(addr + len > LIMIT) { + len -= (addr + len - LIMIT); + } + assert(cbi->mmap_size < MAXMEMMAP); + if(len == 0) return; + addr = roundup(addr, I386_PAGE_SIZE); + len = rounddown(len, I386_PAGE_SIZE); + for(m = 0; m < MAXMEMMAP; m++) { + if(cbi->memmap[m].len) continue; + cbi->memmap[m].addr = addr; + cbi->memmap[m].len = len; + cbi->memmap[m].type = MULTIBOOT_MEMORY_AVAILABLE; + if(m >= cbi->mmap_size) + cbi->mmap_size = m+1; + return; + } + + highmark = addr + len; + if(highmark > cbi->mem_high_phys) + cbi->mem_high_phys = highmark; + + panic("no available memmap slot"); +} + +u32_t *alloc_pagetable(phys_bytes *ph) +{ + u32_t *ret; +#define PG_PAGETABLES 3 + static u32_t pagetables[PG_PAGETABLES][1024] __aligned(4096); + static int pt_inuse = 0; + if(pt_inuse >= PG_PAGETABLES) panic("no more pagetables"); + assert(sizeof(pagetables[pt_inuse]) == I386_PAGE_SIZE); + ret = pagetables[pt_inuse++]; + *ph = vir2phys(ret); + return ret; +} + +#define PAGE_KB (I386_PAGE_SIZE / 1024) + +phys_bytes pg_alloc_page(kinfo_t *cbi) +{ + int m; + multiboot_memory_map_t *mmap; + for(m = cbi->mmap_size-1; m >= 0; m--) { + mmap = &cbi->memmap[m]; + if(!mmap->len) continue; + assert(mmap->len > 0); + assert(!(mmap->len % I386_PAGE_SIZE)); + assert(!(mmap->addr % I386_PAGE_SIZE)); + + mmap->len -= I386_PAGE_SIZE; + + return mmap->addr + mmap->len; + } + + panic("can't find free memory"); +} + +void pg_identity(void) +{ + int i; + phys_bytes phys; + + /* Set up an identity mapping page directory */ + for(i = 0; i < I386_VM_DIR_ENTRIES; i++) { + phys = i * I386_BIG_PAGE_SIZE; + pagedir[i] = phys | I386_VM_PRESENT | I386_VM_BIGPAGE | + I386_VM_USER | I386_VM_WRITE; + } +} + +int pg_mapkernel(void) +{ + int pde; + u32_t mapped = 0, kern_phys = kern_phys_start; + + assert(!(kern_vir_start % I386_BIG_PAGE_SIZE)); + assert(!(kern_phys % I386_BIG_PAGE_SIZE)); + pde = kern_vir_start / I386_BIG_PAGE_SIZE; /* start pde */ + while(mapped < kern_kernlen) { + pagedir[pde] = kern_phys | I386_VM_PRESENT | + I386_VM_BIGPAGE | I386_VM_WRITE; + mapped += I386_BIG_PAGE_SIZE; + kern_phys += I386_BIG_PAGE_SIZE; + pde++; + } + return pde; /* free pde */ +} + +void vm_enable_paging(void) +{ + u32_t cr0, cr4; + int pgeok; + + pgeok = _cpufeature(_CPUF_I386_PGE); + + cr0= read_cr0(); + cr4= read_cr4(); + + /* The boot loader should have put us in protected mode. */ + assert(cr0 & I386_CR0_PE); + + /* First clear PG and PGE flag, as PGE must be enabled after PG. */ + write_cr0(cr0 & ~I386_CR0_PG); + write_cr4(cr4 & ~(I386_CR4_PGE | I386_CR4_PSE)); + + cr0= read_cr0(); + cr4= read_cr4(); + + /* Our page table contains 4MB entries. */ + cr4 |= I386_CR4_PSE; + + write_cr4(cr4); + + /* First enable paging, then enable global page flag. */ + cr0 |= I386_CR0_PG; + write_cr0(cr0); + cr0 |= I386_CR0_WP; + write_cr0(cr0); + + /* May we enable these features? */ + if(pgeok) + cr4 |= I386_CR4_PGE; + + write_cr4(cr4); +} + +phys_bytes pg_load() +{ + phys_bytes phpagedir = vir2phys(pagedir); + write_cr3(phpagedir); + return phpagedir; +} + +void pg_clear(void) +{ + memset(pagedir, 0, sizeof(pagedir)); +} + +phys_bytes pg_rounddown(phys_bytes b) +{ + phys_bytes o; + if(!(o = b % I386_PAGE_SIZE)) + return b; + return b - o; +} + +void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end, + kinfo_t *cbi) +{ + static int mapped_pde = -1; + static u32_t *pt = NULL; + int pde, pte; + + if(phys == PG_ALLOCATEME) { + assert(!(vaddr % I386_PAGE_SIZE)); + } else { + assert((vaddr % I386_PAGE_SIZE) == (phys % I386_PAGE_SIZE)); + vaddr = pg_rounddown(vaddr); + phys = pg_rounddown(phys); + } + assert(vaddr < kern_vir_start); + + while(vaddr < vaddr_end) { + phys_bytes source = phys; + assert(!(vaddr % I386_PAGE_SIZE)); + if(phys == PG_ALLOCATEME) { + source = pg_alloc_page(cbi); + } else { + assert(!(phys % I386_PAGE_SIZE)); + } + assert(!(source % I386_PAGE_SIZE)); + pde = I386_VM_PDE(vaddr); + pte = I386_VM_PTE(vaddr); + if(mapped_pde < pde) { + phys_bytes ph; + pt = alloc_pagetable(&ph); + pagedir[pde] = (ph & I386_VM_ADDR_MASK) + | I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE; + mapped_pde = pde; + } + assert(pt); + pt[pte] = (source & I386_VM_ADDR_MASK) | + I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE; + vaddr += I386_PAGE_SIZE; + if(phys != PG_ALLOCATEME) + phys += I386_PAGE_SIZE; + } +} + +void pg_info(reg_t *pagedir_ph, u32_t **pagedir_v) +{ + *pagedir_ph = vir2phys(pagedir); + *pagedir_v = pagedir; +} + diff --git a/kernel/arch/i386/pre_init.c b/kernel/arch/i386/pre_init.c index 0e5532436..53aac5b66 100644 --- a/kernel/arch/i386/pre_init.c +++ b/kernel/arch/i386/pre_init.c @@ -1,258 +1,60 @@ -#include "kernel/kernel.h" + +#define UNPAGED 1 /* for proper kmain() prototype */ + +#include "kernel.h" +#include +#include #include #include -/* - * == IMPORTANT == - * Routines in this file can not use any variable in kernel BSS, - * since before image is extracted, no BSS is allocated. - * So pay attention to any external call (including library call). - * - * */ #include #include #include #include +#include #include #include "string.h" #include "arch_proto.h" #include "libexec.h" -#include "mb_utils.h" +#include "direct_utils.h" #include "serial.h" +#include "glo.h" #include #if USE_SYSDEBUG #define MULTIBOOT_VERBOSE 1 #endif -/* FIXME: Share this define with kernel linker script */ -#define MULTIBOOT_KERNEL_ADDR 0x00200000UL +/* to-be-built kinfo struct, diagnostics buffer */ +kinfo_t kinfo; +struct kmessages kmess; -/* Granularity used in image file and copying */ -#define GRAN 512 -#define SECT_CEIL(x) ((((x) - 1) / GRAN + 1) * GRAN) +/* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */ +phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; } + +/* mb_utils.c uses this; we can reach it directly */ +char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER; /* String length used for mb_itoa */ #define ITOA_BUFFER_SIZE 20 -#define mb_load_phymem(buf, phy, len) \ - phys_copy((phy), (u32_t)(buf), (len)) - -#define mb_save_phymem(buf, phy, len) \ - phys_copy((u32_t)(buf), (phy), (len)) - -#define mb_clear_memrange(start, end) \ - phys_memset((start), 0, (end)-(start)) - -static void mb_itoa(u32_t val, char * out) +static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi) { - char ret[ITOA_BUFFER_SIZE]; - int i = ITOA_BUFFER_SIZE - 2; - /* Although there's a library version of itoa(int n), - * we can't use it since that implementation relies on BSS segment - */ - ret[ITOA_BUFFER_SIZE - 2] = '0'; - if (val) { - for (; i >= 0; i--) { - char c; - if (val == 0) break; - c = val % 10; - val = val / 10; - c += '0'; - ret[i] = c; - } - } - else - i--; - ret[ITOA_BUFFER_SIZE - 1] = 0; - strcpy(out, ret + i + 1); -} - -static void mb_itox(u32_t val, char *out) -{ - char ret[9]; - int i = 7; - /* Convert a number to hex string */ - ret[7] = '0'; - if (val) { - for (; i >= 0; i--) { - char c; - if (val == 0) break; - c = val & 0xF; - val = val >> 4; - if (c > 9) - c += 'A' - 10; - else - c += '0'; - ret[i] = c; - } - } - else - i--; - ret[8] = 0; - strcpy(out, ret + i + 1); -} - -static void mb_put_char(char c, int line, int col) -{ - /* Write a char to vga display buffer. */ - if (line - -void mb_cls(void) -{ - int i, j; - /* Clear screen */ - for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ ) - for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) - mb_put_char(0, i, j); - print_line = print_col = 0; - - /* Tell video hardware origin is 0. */ - outb(C_6845+INDEX, VID_ORG); - outb(C_6845+DATA, 0); - outb(C_6845+INDEX, VID_ORG+1); - outb(C_6845+DATA, 0); -} - -static void mb_scroll_up(int lines) -{ - int i, j; - for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ ) { - for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) { - char c = 0; - if(i < MULTIBOOT_CONSOLE_LINES-lines) - c = mb_get_char(i + lines, j); - mb_put_char(c, i, j); - } - } - print_line-= lines; -} - -void mb_print_char(char c) -{ - while (print_line >= MULTIBOOT_CONSOLE_LINES) - mb_scroll_up(1); - - if (c == '\n') { - while (print_col < MULTIBOOT_CONSOLE_COLS) - mb_put_char(' ', print_line, print_col++); - print_line++; - print_col = 0; - return; - } - - mb_put_char(c, print_line, print_col++); - - if (print_col >= MULTIBOOT_CONSOLE_COLS) { - print_line++; - print_col = 0; - } - - while (print_line >= MULTIBOOT_CONSOLE_LINES) - mb_scroll_up(1); -} - -void mb_print(char *str) -{ - while (*str) { - mb_print_char(*str); - str++; - } -} - -/* Standard and AT keyboard. (PS/2 MCA implies AT throughout.) */ -#define KEYBD 0x60 /* I/O port for keyboard data */ -#define KB_STATUS 0x64 /* I/O port for status on AT */ -#define KB_OUT_FULL 0x01 /* status bit set when keypress char pending */ -#define KB_AUX_BYTE 0x20 /* Auxiliary Device Output Buffer Full */ - -int mb_read_char(unsigned char *ch) -{ - unsigned long b, sb; -#ifdef DEBUG_SERIAL - u8_t c, lsr; - - if (do_serial_debug) { - lsr= inb(COM1_LSR); - if (!(lsr & LSR_DR)) - return 0; - c = inb(COM1_RBR); - return 1; - } -#endif /* DEBUG_SERIAL */ - - sb = inb(KB_STATUS); - - if (!(sb & KB_OUT_FULL)) { - return 0; - } - - b = inb(KEYBD); - - if (!(sb & KB_AUX_BYTE)) - return 1; - - return 0; -} - -static void mb_print_hex(u32_t value) -{ - int i; - char c; - char out[9] = "00000000"; - /* Print a hex value */ - for (i = 7; i >= 0; i--) { - c = value % 0x10; - value /= 0x10; - if (c < 10) - c += '0'; - else - c += 'A'-10; - out[i] = c; - } - mb_print(out); -} - -static int mb_set_param(char *name, char *value) -{ - char *p = multiboot_param_buf; + char *p = bigbuf; + char *bufend = bigbuf + MULTIBOOT_PARAM_BUF_SIZE; char *q; int namelen = strlen(name); int valuelen = strlen(value); - + + /* Some variables we recognize */ + if(!strcmp(name, SERVARNAME)) { cbi->do_serial_debug = 1; return 0; } + if(!strcmp(name, SERBAUDVARNAME)) { cbi->serial_debug_baud = atoi(value); return 0; } + /* Delete the item if already exists */ while (*p) { if (strncmp(p, name, namelen) == 0 && p[namelen] == '=') { q = p; while (*q) q++; - for (q++; - q < multiboot_param_buf + MULTIBOOT_PARAM_BUF_SIZE; - q++, p++) + for (q++; q < bufend; q++, p++) *p = *q; break; } @@ -261,16 +63,12 @@ static int mb_set_param(char *name, char *value) p++; } - for (p = multiboot_param_buf; - p < multiboot_param_buf + MULTIBOOT_PARAM_BUF_SIZE - && (*p || *(p + 1)); - p++) + for (p = bigbuf; p < bufend && (*p || *(p + 1)); p++) ; - if (p > multiboot_param_buf) p++; + if (p > bigbuf) p++; /* Make sure there's enough space for the new parameter */ - if (p + namelen + valuelen + 3 - > multiboot_param_buf + MULTIBOOT_PARAM_BUF_SIZE) + if (p + namelen + valuelen + 3 > bufend) return -1; strcpy(p, name); @@ -281,202 +79,172 @@ static int mb_set_param(char *name, char *value) return 0; } -static void get_parameters(multiboot_info_t *mbi) +int overlaps(multiboot_module_t *mod, int n, int cmp_mod) { - char mem_value[40], temp[ITOA_BUFFER_SIZE]; - int i; - int dev; - int ctrlr; - int disk, prim, sub; - int var_i,value_i; + multiboot_module_t *cmp = &mod[cmp_mod]; + int m; + +#define INRANGE(mod, v) ((v) >= mod->mod_start && (v) <= thismod->mod_end) +#define OVERLAP(mod1, mod2) (INRANGE(mod1, mod2->mod_start) || \ + INRANGE(mod1, mod2->mod_end)) + for(m = 0; m < n; m++) { + multiboot_module_t *thismod = &mod[m]; + if(m == cmp_mod) continue; + if(OVERLAP(thismod, cmp)) + return 1; + } + return 0; +} + +void print_memmap(kinfo_t *cbi) +{ + int m; + assert(cbi->mmap_size < MAXMEMMAP); + for(m = 0; m < cbi->mmap_size; m++) { + printf("%08lx-%08lx ",cbi->memmap[m].addr, cbi->memmap[m].addr + cbi->memmap[m].len); + } + printf("\nsize %08lx\n", cbi->mmap_size); +} + +void get_parameters(u32_t ebx, kinfo_t *cbi) +{ + multiboot_memory_map_t *mmap; + multiboot_info_t *mbi = &cbi->mbi; + int var_i,value_i, m, k; char *p; - const static int dev_cNd0[] = { 0x0300, 0x0800, 0x0A00, 0x0C00, 0x1000 }; - static char mb_cmd_buff[GRAN] = "add some value to avoid me in BSS"; - static char var[GRAN] = "add some value to avoid me in BSS"; - static char value[GRAN] = "add some value to avoid me in BSS"; - for (i = 0; i < MULTIBOOT_PARAM_BUF_SIZE; i++) - multiboot_param_buf[i] = 0; - - if (mbi->flags & MULTIBOOT_INFO_BOOTDEV) { - disk = ((mbi->boot_device&0xff000000) >> 24)-0x80; - prim = (mbi->boot_device & 0xff0000) >> 16; - if (prim == 0xff) - prim = 0; - sub = (mbi->boot_device & 0xff00) >> 8; - if (sub == 0xff) - sub = 0; - ctrlr = 0; - dev = dev_cNd0[ctrlr]; + extern char _kern_phys_base, _kern_vir_base, _kern_size, + _kern_unpaged_start, _kern_unpaged_end; + phys_bytes kernbase = (phys_bytes) &_kern_phys_base, + kernsize = (phys_bytes) &_kern_size; +#define BUF 1024 + static char cmdline[BUF]; - /* Determine the value of rootdev */ - dev += 0x80 - + (disk * NR_PARTITIONS + prim) * NR_PARTITIONS + sub; + /* get our own copy of the multiboot info struct and module list */ + memcpy((void *) mbi, (void *) ebx, sizeof(*mbi)); - mb_itoa(dev, temp); - mb_set_param("rootdev", temp); - mb_set_param("ramimagedev", temp); - } - mb_set_param("hz", "60"); - - if (mbi->flags & MULTIBOOT_INFO_MEMORY) - { - strcpy(mem_value, "800:"); - mb_itox( - mbi->mem_lower * 1024 > MULTIBOOT_LOWER_MEM_MAX ? - MULTIBOOT_LOWER_MEM_MAX : mbi->mem_lower * 1024, - temp); - strcat(mem_value, temp); - strcat(mem_value, ",100000:"); - mb_itox(mbi->mem_upper * 1024, temp); - strcat(mem_value, temp); - mb_set_param("memory", mem_value); - } - + /* Set various bits of info for the higher-level kernel. */ + cbi->mem_high_phys = 0; + cbi->user_sp = (vir_bytes) &_kern_vir_base; + cbi->vir_kern_start = (vir_bytes) &_kern_vir_base; + cbi->bootstrap_start = (vir_bytes) &_kern_unpaged_start; + cbi->bootstrap_len = (vir_bytes) &_kern_unpaged_end - + cbi->bootstrap_start; + cbi->kmess = &kmess; + + /* set some configurable defaults */ + cbi->do_serial_debug = 0; + cbi->serial_debug_baud = 115200; + + /* parse boot command line */ if (mbi->flags&MULTIBOOT_INFO_CMDLINE) { + static char var[BUF]; + static char value[BUF]; + /* Override values with cmdline argument */ - p = mb_cmd_buff; - mb_load_phymem(mb_cmd_buff, mbi->cmdline, GRAN); + memcpy(cmdline, (void *) mbi->cmdline, BUF); + p = cmdline; while (*p) { var_i = 0; value_i = 0; while (*p == ' ') p++; if (!*p) break; - while (*p && *p != '=' && *p != ' ' && var_i < GRAN - 1) + while (*p && *p != '=' && *p != ' ' && var_i < BUF - 1) var[var_i++] = *p++ ; var[var_i] = 0; if (*p++ != '=') continue; /* skip if not name=value */ - while (*p && *p != ' ' && value_i < GRAN - 1) + while (*p && *p != ' ' && value_i < BUF - 1) value[value_i++] = *p++ ; value[value_i] = 0; - mb_set_param(var, value); + mb_set_param(cbi->param_buf, var, value, cbi); } } -} -static void mb_extract_image(multiboot_info_t mbi) -{ - phys_bytes start_paddr = 0x5000000; - multiboot_module_t *mb_module_info; - multiboot_module_t *module; - u32_t mods_count = mbi.mods_count; - int r, i; - vir_bytes text_vaddr, text_filebytes, text_membytes; - vir_bytes data_vaddr, data_filebytes, data_membytes; - phys_bytes text_paddr, data_paddr; - vir_bytes stack_bytes; - vir_bytes pc; - off_t text_offset, data_offset; + /* round user stack down to leave a gap to catch kernel + * stack overflow; and to distinguish kernel and user addresses + * at a glance (0xf.. vs 0xe..) + */ + cbi->user_sp &= 0xF0000000; + cbi->user_end = cbi->user_sp; - /* Save memory map for kernel tasks */ - r = read_header_elf((char *) MULTIBOOT_KERNEL_ADDR, - 4096, /* everything is there */ - &text_vaddr, &text_paddr, - &text_filebytes, &text_membytes, - &data_vaddr, &data_paddr, - &data_filebytes, &data_membytes, - &pc, &text_offset, &data_offset); - - for (i = 0; i < NR_TASKS; ++i) { - image[i].memmap.text_vaddr = trunc_page(text_vaddr); - image[i].memmap.text_paddr = trunc_page(text_paddr); - image[i].memmap.text_bytes = text_membytes; - image[i].memmap.data_vaddr = trunc_page(data_vaddr); - image[i].memmap.data_paddr = trunc_page(data_paddr); - image[i].memmap.data_bytes = data_membytes; - image[i].memmap.stack_bytes = 0; - image[i].memmap.entry = pc; + assert(!(cbi->bootstrap_start % I386_PAGE_SIZE)); + cbi->bootstrap_len = rounddown(cbi->bootstrap_len, I386_PAGE_SIZE); + assert(mbi->flags & MULTIBOOT_INFO_MODS); + assert(mbi->mods_count < MULTIBOOT_MAX_MODS); + assert(mbi->mods_count > 0); + memcpy(&cbi->module_list, (void *) mbi->mods_addr, + mbi->mods_count * sizeof(multiboot_module_t)); + + memset(cbi->memmap, 0, sizeof(cbi->memmap)); + /* mem_map has a variable layout */ + if(mbi->flags & MULTIBOOT_INFO_MEM_MAP) { + cbi->mmap_size = 0; + for (mmap = (multiboot_memory_map_t *) mbi->mmap_addr; + (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length; + mmap = (multiboot_memory_map_t *) + ((unsigned long) mmap + mmap->size + sizeof(mmap->size))) { + if(mmap->type != MULTIBOOT_MEMORY_AVAILABLE) continue; + add_memmap(cbi, mmap->addr, mmap->len); + } + } else { + assert(mbi->flags & MULTIBOOT_INFO_MEMORY); + add_memmap(cbi, 0, mbi->mem_lower_unused*1024); + add_memmap(cbi, 0x100000, mbi->mem_upper_unused*1024); } -#ifdef MULTIBOOT_VERBOSE - mb_print("\nKernel: "); - mb_print_hex(trunc_page(text_paddr)); - mb_print("-"); - mb_print_hex(trunc_page(data_paddr) + data_membytes); - mb_print(" Entry: "); - mb_print_hex(pc); -#endif - - mb_module_info = ((multiboot_module_t *)mbi.mods_addr); - module = &mb_module_info[0]; - - /* Load boot image services into memory and save memory map */ - for (i = 0; module < &mb_module_info[mods_count]; ++module, ++i) { - r = read_header_elf((char *) module->mod_start, - module->mod_end - module->mod_start + 1, - &text_vaddr, &text_paddr, - &text_filebytes, &text_membytes, - &data_vaddr, &data_paddr, - &data_filebytes, &data_membytes, - &pc, &text_offset, &data_offset); - if (r) { - mb_print("fatal: ELF parse failure\n"); - /* Spin here */ - while (1) - ; - } - - stack_bytes = image[NR_TASKS+i].stack_kbytes * 1024; - - text_paddr = start_paddr + (text_vaddr & PAGE_MASK); - - /* Load text segment */ - phys_copy(module->mod_start+text_offset, text_paddr, - text_filebytes); - mb_clear_memrange(text_paddr+text_filebytes, - round_page(text_paddr) + text_membytes); - - data_paddr = round_page((text_paddr + text_membytes)); - data_paddr += data_vaddr & PAGE_MASK; - /* start of next module */ - start_paddr = round_page(data_paddr + data_membytes + stack_bytes); - - /* Load data and stack segments */ - phys_copy(module->mod_start+data_offset, data_paddr, data_filebytes); - mb_clear_memrange(data_paddr+data_filebytes, start_paddr); - - /* Save memmap for non-kernel tasks, so subscript past kernel - tasks. */ - image[NR_TASKS+i].memmap.text_vaddr = trunc_page(text_vaddr); - image[NR_TASKS+i].memmap.text_paddr = trunc_page(text_paddr); - image[NR_TASKS+i].memmap.text_bytes = text_membytes; - image[NR_TASKS+i].memmap.data_vaddr = trunc_page(data_vaddr); - image[NR_TASKS+i].memmap.data_paddr = trunc_page(data_paddr); - image[NR_TASKS+i].memmap.data_bytes = data_membytes; - image[NR_TASKS+i].memmap.stack_bytes = stack_bytes; - image[NR_TASKS+i].memmap.entry = pc; - -#ifdef MULTIBOOT_VERBOSE - mb_print("\n"); - mb_print_hex(i); - mb_print(": "); - mb_print_hex(trunc_page(text_paddr)); - mb_print("-"); - mb_print_hex(trunc_page(data_paddr) + data_membytes + stack_bytes); - mb_print(" Entry: "); - mb_print_hex(pc); - mb_print(" Stack: "); - mb_print_hex(stack_bytes); - mb_print(" "); - mb_print((char *)module->cmdline); + /* Sanity check: the kernel nor any of the modules may overlap + * with each other. Pretend the kernel is an extra module for a + * second. + */ + k = mbi->mods_count; + assert(k < MULTIBOOT_MAX_MODS); + cbi->module_list[k].mod_start = kernbase; + cbi->module_list[k].mod_end = kernbase + kernsize; + cbi->mods_with_kernel = mbi->mods_count+1; + cbi->kern_mod = k; + + for(m = 0; m < cbi->mods_with_kernel; m++) { +#if 0 + printf("checking overlap of module %08lx-%08lx\n", + cbi->module_list[m].mod_start, cbi->module_list[m].mod_end); #endif + if(overlaps(cbi->module_list, cbi->mods_with_kernel, m)) + panic("overlapping boot modules/kernel"); + /* We cut out the bits of memory that we know are + * occupied by the kernel and boot modules. + */ + cut_memmap(cbi, + cbi->module_list[m].mod_start, + cbi->module_list[m].mod_end); } - - return; } -phys_bytes pre_init(u32_t ebx) +kinfo_t *pre_init(u32_t magic, u32_t ebx) { - multiboot_info_t mbi; + /* Get our own copy boot params pointed to by ebx. + * Here we find out whether we should do serial output. + */ + get_parameters(ebx, &kinfo); + + /* Say hello. */ + printf("MINIX loading\n"); - /* Do pre-initialization for multiboot, returning physical address of - * of multiboot module info - */ - mb_cls(); - mb_print("\nMINIX booting... "); - mb_load_phymem(&mbi, ebx, sizeof(mbi)); - get_parameters(&mbi); - mb_print("\nLoading image... "); - mb_extract_image(mbi); - return mbi.mods_addr; + assert(magic == MULTIBOOT_BOOTLOADER_MAGIC); + + /* Make and load a pagetable that will map the kernel + * to where it should be; but first a 1:1 mapping so + * this code stays where it should be. + */ + pg_clear(); + pg_identity(); + kinfo.freepde_start = pg_mapkernel(); + pg_load(); + vm_enable_paging(); + + /* Done, return boot info so it can be passed to kmain(). */ + return &kinfo; } + +int send_sig(endpoint_t proc_nr, int sig_nr) { return 0; } +void minix_shutdown(timer_t *t) { arch_shutdown(RBT_PANIC); } +void busy_delay_ms(int x) { } diff --git a/kernel/arch/i386/procoffsets.cf b/kernel/arch/i386/procoffsets.cf index 835a6f649..a0264d03a 100644 --- a/kernel/arch/i386/procoffsets.cf +++ b/kernel/arch/i386/procoffsets.cf @@ -3,10 +3,6 @@ include "kernel.h" include "proc.h" struct proc -member GSREG p_reg.gs -member FSREG p_reg.fs -member ESREG p_reg.es -member DSREG p_reg.ds member DIREG p_reg.di member SIREG p_reg.si member BPREG p_reg.fp @@ -20,9 +16,4 @@ member PCREG p_reg.pc member CSREG p_reg.cs member PSWREG p_reg.psw member SPREG p_reg.sp -member SSREG p_reg.ss -member P_LDT_SEL p_seg.p_ldt_sel member P_CR3 p_seg.p_cr3 -member P_CR3_V p_seg.p_cr3_v -member P_LDT p_seg.p_ldt - diff --git a/kernel/arch/i386/protect.c b/kernel/arch/i386/protect.c index 4c5949d0a..8efa837f0 100644 --- a/kernel/arch/i386/protect.c +++ b/kernel/arch/i386/protect.c @@ -3,19 +3,23 @@ * for local descriptors in the process table. */ +#include +#include +#include + #include "kernel/kernel.h" #include "kernel/proc.h" #include "archconst.h" #include "arch_proto.h" +#include + #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT) #define TSS_TYPE (AVL_286_TSS | DESC_386_BIT) -struct desctableptr_s { - char limit[sizeof(u16_t)]; - char base[sizeof(u32_t)]; /* really u24_t + pad for 286 */ -}; +/* This is OK initially, when the 1:1 mapping is still there. */ +char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER; struct gatedesc_s { u16_t offset_low; @@ -23,27 +27,20 @@ struct gatedesc_s { u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */ u8_t p_dpl_type; /* |P|DL|0|TYPE| */ u16_t offset_high; -}; +} __attribute__((packed)); +/* Storage for gdt, idt and tss. */ +static struct segdesc_s gdt[GDT_SIZE] __aligned(DESC_SIZE); +struct gatedesc_s idt[IDT_SIZE] __aligned(DESC_SIZE); +struct tss_s tss[CONFIG_MAX_CPUS]; -/* used in klib.s and mpx.s */ -struct segdesc_s gdt[GDT_SIZE] __aligned(DESC_SIZE) = -{ {0}, - {0,0,0,0}, /* GDT descriptor */ - {0,0,0,0}, /* IDT descriptor */ - {0xffff,0,0,0x93,0xcf,0}, /* kernel DS */ - {0xffff,0,0,0x93,0xcf,0}, /* kernel ES (386: flag 4 Gb at startup) */ - {0xffff,0,0,0x93,0xcf,0}, /* kernel SS (386: monitor SS at startup) */ - {0xffff,0,0,0x9b,0xcf,0}, /* kernel CS */ - {0xffff,0,0,0x9b,0xcf,0}, /* temp for BIOS (386: monitor CS at startup) */ -}; - -/* zero-init so none present */ -static struct gatedesc_s idt[IDT_SIZE] __aligned(DESC_SIZE); -struct tss_s tss[CONFIG_MAX_CPUS]; /* zero init */ - -static void sdesc(struct segdesc_s *segdp, phys_bytes base, vir_bytes - size); +phys_bytes vir2phys(void *vir) +{ + extern char _kern_vir_base, _kern_phys_base; /* in kernel.lds */ + u32_t offset = (vir_bytes) &_kern_vir_base - + (vir_bytes) &_kern_phys_base; + return (phys_bytes)vir - offset; +} /*===========================================================================* * enable_iop * @@ -58,51 +55,60 @@ void enable_iop(struct proc *pp) pp->p_reg.psw |= 0x3000; } -/*===========================================================================* - * seg2phys * - *===========================================================================*/ -phys_bytes seg2phys(const u16_t seg) -{ -/* Return the base address of a segment, with seg being a - * register, or a 286/386 segment selector. - */ - phys_bytes base; - struct segdesc_s *segdp; - segdp = &gdt[seg >> 3]; - base = ((u32_t) segdp->base_low << 0) - | ((u32_t) segdp->base_middle << 16) - | ((u32_t) segdp->base_high << 24); - return base; +/*===========================================================================* + * sdesc * + *===========================================================================*/ + void sdesc(struct segdesc_s *segdp, phys_bytes base, vir_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; + 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 */ } /*===========================================================================* * init_dataseg * *===========================================================================*/ -void init_dataseg(register struct segdesc_s *segdp, +void init_param_dataseg(register struct segdesc_s *segdp, phys_bytes base, vir_bytes size, const int privilege) { /* Build descriptor for a data segment. */ sdesc(segdp, base, size); segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | - WRITEABLE); + WRITEABLE | ACCESSED); /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */ } +void init_dataseg(int index, const int privilege) +{ + init_param_dataseg(&gdt[index], 0, 0xFFFFFFFF, privilege); +} + /*===========================================================================* * init_codeseg * *===========================================================================*/ -static void init_codeseg(register struct segdesc_s *segdp, phys_bytes base, - vir_bytes size, int privilege) +static void init_codeseg(int index, int privilege) { /* Build descriptor for a code segment. */ - sdesc(segdp, base, size); - segdp->access = (privilege << DPL_SHIFT) + sdesc(&gdt[index], 0, 0xFFFFFFFF); + gdt[index].access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | EXECUTABLE | READABLE); /* CONFORMING = 0, ACCESSED = 0 */ } -struct gate_table_s gate_table_pic[] = { +static struct gate_table_s gate_table_pic[] = { { hwint00, VECTOR( 0), INTR_PRIVILEGE }, { hwint01, VECTOR( 1), INTR_PRIVILEGE }, { hwint02, VECTOR( 2), INTR_PRIVILEGE }, @@ -122,17 +128,47 @@ struct gate_table_s gate_table_pic[] = { { NULL, 0, 0} }; -void tss_init(unsigned cpu, void * kernel_stack) +static struct gate_table_s gate_table_exceptions[] = { + { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE }, + { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE }, + { nmi, NMI_VECTOR, INTR_PRIVILEGE }, + { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE }, + { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE }, + { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE }, + { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE }, + { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE }, + { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE }, + { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE }, + { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE }, + { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE }, + { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE }, + { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE }, + { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE }, + { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE }, + { alignment_check, ALIGNMENT_CHECK_VECTOR, INTR_PRIVILEGE }, + { machine_check, MACHINE_CHECK_VECTOR, INTR_PRIVILEGE }, + { simd_exception, SIMD_EXCEPTION_VECTOR, INTR_PRIVILEGE }, + { ipc_entry, IPC_VECTOR, USER_PRIVILEGE }, + { kernel_call_entry, KERN_CALL_VECTOR, USER_PRIVILEGE }, + { NULL, 0, 0} +}; + +int tss_init(unsigned cpu, void * kernel_stack) { struct tss_s * t = &tss[cpu]; - - t->ss0 = DS_SELECTOR; - init_dataseg(&gdt[TSS_INDEX(cpu)], vir2phys(t), - sizeof(struct tss_s), INTR_PRIVILEGE); - gdt[TSS_INDEX(cpu)].access = PRESENT | - (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; + int index = TSS_INDEX(cpu); + struct segdesc_s *tssgdt; - /* Complete building of main TSS. */ + tssgdt = &gdt[index]; + + init_param_dataseg(tssgdt, (phys_bytes) t, + sizeof(struct tss_s), INTR_PRIVILEGE); + tssgdt->access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; + + /* Build TSS. */ + memset(t, 0, sizeof(*t)); + t->ds = t->es = t->fs = t->gs = t->ss0 = KERN_DS_SELECTOR; + t->cs = KERN_CS_SELECTOR; t->iobase = sizeof(struct tss_s); /* empty i/o permissions map */ /* @@ -145,344 +181,203 @@ void tss_init(unsigned cpu, void * kernel_stack) * this stak in use when we trap to kernel */ *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu; + + return SEG_SELECTOR(index); } -/*===========================================================================* - * prot_init * - *===========================================================================*/ -void prot_init(void) +phys_bytes init_segdesc(int gdt_index, void *base, int size) { -/* Set up tables for protected mode. - * All GDT slots are allocated at compile time. - */ - struct desctableptr_s *dtp; - unsigned ldt_index; - register struct proc *rp; + struct desctableptr_s *dtp = (struct desctableptr_s *) &gdt[gdt_index]; + dtp->limit = size - 1; + dtp->base = (phys_bytes) base; - /* Click-round kernel. */ - if(kinfo.data_base % CLICK_SIZE) - panic("kinfo.data_base not aligned"); - kinfo.data_size = (phys_bytes) (CLICK_CEIL(kinfo.data_size)); + return (phys_bytes) dtp; +} - /* Build gdt and idt pointers in GDT where the BIOS expects them. */ - dtp= (struct desctableptr_s *) &gdt[GDT_INDEX]; - * (u16_t *) dtp->limit = (sizeof gdt) - 1; - * (u32_t *) dtp->base = vir2phys(gdt); +void int_gate(struct gatedesc_s *tab, + unsigned vec_nr, vir_bytes offset, unsigned dpl_type) +{ +/* Build descriptor for an interrupt gate. */ + register struct gatedesc_s *idp; - dtp= (struct desctableptr_s *) &gdt[IDT_INDEX]; - * (u16_t *) dtp->limit = (sizeof idt) - 1; - * (u32_t *) dtp->base = vir2phys(idt); + idp = &tab[vec_nr]; + idp->offset_low = offset; + idp->selector = KERN_CS_SELECTOR; + idp->p_dpl_type = dpl_type; + idp->offset_high = offset >> OFFSET_HIGH_SHIFT; +} - /* Build segment descriptors for tasks and interrupt handlers. */ - init_codeseg(&gdt[CS_INDEX], - kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE); - init_dataseg(&gdt[DS_INDEX], - kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE); - init_dataseg(&gdt[ES_INDEX], 0L, 0, INTR_PRIVILEGE); - - /* 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. - */ - for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX; - rp < END_PROC_ADDR; ++rp, ldt_index++) { - init_dataseg(&gdt[ldt_index], vir2phys(rp->p_seg.p_ldt), - sizeof(rp->p_seg.p_ldt), INTR_PRIVILEGE); - gdt[ldt_index].access = PRESENT | LDT; - rp->p_seg.p_ldt_sel = ldt_index * DESC_SIZE; - } - - /* Build boot TSS */ - tss_init(0, &k_boot_stktop); +void int_gate_idt(unsigned vec_nr, vir_bytes offset, unsigned dpl_type) +{ + int_gate(idt, vec_nr, offset, dpl_type); } void idt_copy_vectors(struct gate_table_s * first) { struct gate_table_s *gtp; for (gtp = first; gtp->gate; gtp++) { - int_gate(gtp->vec_nr, (vir_bytes) gtp->gate, + int_gate(idt, gtp->vec_nr, (vir_bytes) gtp->gate, PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT)); } } -/* Build descriptors for interrupt gates in IDT. */ -void idt_init(void) +void idt_copy_vectors_pic(void) { - struct gate_table_s gate_table[] = { - { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE }, - { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE }, - { nmi, NMI_VECTOR, INTR_PRIVILEGE }, - { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE }, - { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE }, - { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE }, - { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE }, - { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE }, - { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE }, - { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE }, - { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE }, - { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE }, - { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE }, - { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE }, - { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE }, - { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE }, - { alignment_check, ALIGNMENT_CHECK_VECTOR, INTR_PRIVILEGE }, - { machine_check, MACHINE_CHECK_VECTOR, INTR_PRIVILEGE }, - { simd_exception, SIMD_EXCEPTION_VECTOR, INTR_PRIVILEGE }, - { ipc_entry, IPC_VECTOR, USER_PRIVILEGE }, - { kernel_call_entry, KERN_CALL_VECTOR, USER_PRIVILEGE }, - { NULL, 0, 0} - }; - - idt_copy_vectors(gate_table); idt_copy_vectors(gate_table_pic); } - -/*===========================================================================* - * sdesc * - *===========================================================================*/ -static void sdesc(segdp, base, size) -register struct segdesc_s *segdp; -phys_bytes base; -vir_bytes size; +void idt_init(void) { -/* Fill in the size fields (base, limit and granularity) of a descriptor. */ - segdp->base_low = base; - segdp->base_middle = base >> BASE_MIDDLE_SHIFT; - 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 */ + idt_copy_vectors_pic(); + idt_copy_vectors(gate_table_exceptions); } -/*===========================================================================* - * int_gate * - *===========================================================================*/ -void int_gate(unsigned vec_nr, vir_bytes offset, unsigned dpl_type) -{ -/* Build descriptor for an interrupt gate. */ - register struct gatedesc_s *idp; +struct desctableptr_s gdt_desc, idt_desc; - idp = &idt[vec_nr]; - idp->offset_low = offset; - idp->selector = CS_SELECTOR; - idp->p_dpl_type = dpl_type; - idp->offset_high = offset >> OFFSET_HIGH_SHIFT; +void idt_reload(void) +{ + x86_lidt(&idt_desc); } -/*===========================================================================* - * alloc_segments * - *===========================================================================*/ -void alloc_segments(register struct proc *rp) +multiboot_module_t *bootmod(int pnr) { -/* This is called at system initialization from main() and by do_newmap(). - * The code has a separate function because of all hardware-dependencies. - */ - phys_bytes code_bytes; - phys_bytes data_bytes; - phys_bytes text_vaddr, data_vaddr; - phys_bytes text_segbase, data_segbase; - int privilege; + int i; - 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 = USER_PRIVILEGE; + assert(pnr >= 0); - text_vaddr = rp->p_memmap[T].mem_vir << CLICK_SHIFT; - data_vaddr = rp->p_memmap[D].mem_vir << CLICK_SHIFT; - text_segbase = (rp->p_memmap[T].mem_phys - - rp->p_memmap[T].mem_vir) << CLICK_SHIFT; - data_segbase = (rp->p_memmap[D].mem_phys - - rp->p_memmap[D].mem_vir) << CLICK_SHIFT; - - init_codeseg(&rp->p_seg.p_ldt[CS_LDT_INDEX], - text_segbase, - text_vaddr + code_bytes, privilege); - init_dataseg(&rp->p_seg.p_ldt[DS_LDT_INDEX], - data_segbase, - data_vaddr + data_bytes, privilege); - rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege; - rp->p_reg.gs = - rp->p_reg.fs = - rp->p_reg.ss = - rp->p_reg.es = - rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege; -} - -#if 0 -/*===========================================================================* - * check_segments * - *===========================================================================*/ -static void check_segments(char *File, int line) -{ - int checked = 0; -int fail = 0; -struct proc *rp; -for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; ++rp) { - - int privilege; - int cs, ds; - - if (isemptyp(rp)) - continue; - - privilege = USER_PRIVILEGE; - - cs = (CS_LDT_INDEX*DESC_SIZE) | TI | privilege; - ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege; - -#define CHECK(s1, s2) if(s1 != s2) { \ - printf("%s:%d: " #s1 " != " #s2 " for ep %d\n", \ - File, line, rp->p_endpoint); fail++; } checked++; - - CHECK(rp->p_reg.cs, cs); - CHECK(rp->p_reg.gs, ds); - CHECK(rp->p_reg.fs, ds); - CHECK(rp->p_reg.ss, ds); - if(rp->p_endpoint != SYSTEM) { - CHECK(rp->p_reg.es, ds); - } - CHECK(rp->p_reg.ds, ds); - } - if(fail) { - printf("%d/%d checks failed\n", fail, checked); - panic("wrong: %d", fail); - } -} -#endif - -/*===========================================================================* - * printseg * - *===========================================================================*/ -void printseg(char *banner, const int iscs, struct proc *pr, - const u32_t selector) -{ -#if USE_SYSDEBUG - u32_t base, limit, index, dpl; - struct segdesc_s *desc; - - if(banner) { printf("%s", banner); } - - index = selector >> 3; - - printf("RPL %d, ind %d of ", - (selector & RPL_MASK), index); - - if(selector & TI) { - printf("LDT"); - if(index >= LDT_SIZE) { - printf("invalid index in ldt\n"); - return; + /* Search for desired process in boot process + * list. The first NR_TASKS ones do not correspond + * to a module, however, so we don't search those. + */ + for(i = NR_TASKS; i < NR_BOOT_PROCS; i++) { + int p; + p = i - NR_TASKS; + if(image[i].proc_nr == pnr) { + assert(p < MULTIBOOT_MAX_MODS); + assert(p < kinfo.mbi.mods_count); + return &kinfo.module_list[p]; } - if(!pr) { - printf("local selector but unknown process\n"); - return; - } - desc = &pr->p_seg.p_ldt[index]; - } else { - printf("GDT"); - if(index >= GDT_SIZE) { - printf("invalid index in gdt\n"); - return; - } - desc = &gdt[index]; } - limit = desc->limit_low | - (((u32_t) desc->granularity & LIMIT_HIGH) << GRANULARITY_SHIFT); - - if(desc->granularity & GRANULAR) { - limit = (limit << PAGE_GRAN_SHIFT) + 0xfff; - } - - base = desc->base_low | - ((u32_t) desc->base_middle << BASE_MIDDLE_SHIFT) | - ((u32_t) desc->base_high << BASE_HIGH_SHIFT); - - printf(" -> base 0x%08lx size 0x%08lx ", base, limit+1); - - if(iscs) { - if(!(desc->granularity & BIG)) - printf("16bit "); - } else { - if(!(desc->granularity & BIG)) - printf("not big "); - } - - if(desc->granularity & 0x20) { /* reserved */ - panic("granularity reserved field set"); - } - - if(!(desc->access & PRESENT)) - printf("notpresent "); - - if(!(desc->access & SEGMENT)) - printf("system "); - - if(desc->access & EXECUTABLE) { - printf(" exec "); - if(desc->access & CONFORMING) printf("conforming "); - if(!(desc->access & READABLE)) printf("non-readable "); - } else { - printf("nonexec "); - if(desc->access & EXPAND_DOWN) printf("non-expand-down "); - if(!(desc->access & WRITEABLE)) printf("non-writable "); - } - - if(!(desc->access & ACCESSED)) { - printf("nonacc "); - } - - dpl = ((u32_t) desc->access & DPL) >> DPL_SHIFT; - - printf("DPL %d\n", dpl); - - return; -#endif /* USE_SYSDEBUG */ + panic("boot module %d not found", pnr); } /*===========================================================================* - * prot_set_kern_seg_limit * + * prot_init * *===========================================================================*/ -int prot_set_kern_seg_limit(const vir_bytes limit) +void prot_init() { - struct proc *rp; - int orig_click; - int incr_clicks; + int sel_tss; + extern char k_boot_stktop; - if(limit <= kinfo.data_base) { - printf("prot_set_kern_seg_limit: limit bogus\n"); - return EINVAL; - } + memset(gdt, 0, sizeof(gdt)); + memset(idt, 0, sizeof(idt)); - /* Do actual increase. */ - orig_click = kinfo.data_size / CLICK_SIZE; - kinfo.data_size = limit - kinfo.data_base; - incr_clicks = kinfo.data_size / CLICK_SIZE - orig_click; + /* Build GDT, IDT, IDT descriptors. */ + gdt_desc.base = (u32_t) gdt; + gdt_desc.limit = sizeof(gdt)-1; + idt_desc.base = (u32_t) idt; + idt_desc.limit = sizeof(idt)-1; + sel_tss = tss_init(0, &k_boot_stktop); - prot_init(); + /* Build GDT */ + init_param_dataseg(&gdt[LDT_INDEX], + (phys_bytes) 0, 0, INTR_PRIVILEGE); /* unusable LDT */ + gdt[LDT_INDEX].access = PRESENT | LDT; + init_codeseg(KERN_CS_INDEX, INTR_PRIVILEGE); + init_dataseg(KERN_DS_INDEX, INTR_PRIVILEGE); + init_codeseg(USER_CS_INDEX, USER_PRIVILEGE); + init_dataseg(USER_DS_INDEX, USER_PRIVILEGE); - /* Increase kernel processes too. */ - for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; ++rp) { - if (isemptyp(rp) || !iskernelp(rp)) - continue; - rp->p_memmap[S].mem_len += incr_clicks; - alloc_segments(rp); - rp->p_memmap[S].mem_len -= incr_clicks; - } + x86_lgdt(&gdt_desc); /* Load gdt */ + idt_init(); + idt_reload(); + x86_lldt(LDT_SELECTOR); /* Load bogus ldt */ + x86_ltr(sel_tss); /* Load global TSS */ - return OK; + /* Currently the multiboot segments are loaded; which is fine, but + * let's replace them with the ones from our own GDT so we test + * right away whether they work as expected. + */ + x86_load_kerncs(); + x86_load_ds(KERN_DS_SELECTOR); + x86_load_es(KERN_DS_SELECTOR); + x86_load_fs(KERN_DS_SELECTOR); + x86_load_gs(KERN_DS_SELECTOR); + x86_load_ss(KERN_DS_SELECTOR); + + /* Set up a new post-relocate bootstrap pagetable so that + * we can map in VM, and we no longer rely on pre-relocated + * data. + */ + + pg_clear(); + pg_identity(); /* Still need 1:1 for lapic and video mem and such. */ + pg_mapkernel(); + pg_load(); + bootstrap_pagetable_done = 1; /* secondary CPU's can use it too */ +} + +void arch_post_init(void) +{ + /* Let memory mapping code know what's going on at bootstrap time */ + struct proc *vm; + vm = proc_addr(VM_PROC_NR); + get_cpulocal_var(ptproc) = vm; + pg_info(&vm->p_seg.p_cr3, &vm->p_seg.p_cr3_v); +} + +int libexec_pg_alloc(struct exec_info *execi, off_t vaddr, size_t len) +{ + pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo); + pg_load(); + memset((char *) vaddr, 0, len); + return OK; +} + +void arch_boot_proc(struct boot_image *ip, struct proc *rp) +{ + multiboot_module_t *mod; + + if(rp->p_nr < 0) return; + + mod = bootmod(rp->p_nr); + + /* Important special case: we put VM in the bootstrap pagetable + * so it can run. + */ + + if(rp->p_nr == VM_PROC_NR) { + struct exec_info execi; + + memset(&execi, 0, sizeof(execi)); + + /* exec parameters */ + execi.stack_high = kinfo.user_sp; + execi.stack_size = 16 * 1024; /* not too crazy as it must be preallocated */ + execi.proc_e = ip->endpoint; + execi.hdr = (char *) mod->mod_start; /* phys mem direct */ + execi.hdr_len = mod->mod_end - mod->mod_start; + strcpy(execi.progname, ip->proc_name); + execi.frame_len = 0; + + /* callbacks for use in the kernel */ + execi.copymem = libexec_copy_memcpy; + execi.clearmem = libexec_clear_memset; + execi.allocmem_prealloc = libexec_pg_alloc; + execi.allocmem_ondemand = libexec_pg_alloc; + execi.clearproc = NULL; + + /* parse VM ELF binary and alloc/map it into bootstrap pagetable */ + libexec_load_elf(&execi); + + /* Initialize the server stack pointer. Take it down three words + * to give startup code something to use as "argc", "argv" and "envp". + */ + arch_proc_init(rp, execi.pc, kinfo.user_sp - 3*4, ip->proc_name); + + /* Free VM blob that was just copied into existence. */ + cut_memmap(&kinfo, mod->mod_start, mod->mod_end); + } } diff --git a/kernel/arch/i386/sconst.h b/kernel/arch/i386/sconst.h index c0108185e..1262f6cd6 100644 --- a/kernel/arch/i386/sconst.h +++ b/kernel/arch/i386/sconst.h @@ -17,7 +17,7 @@ * zeroed */ #define TEST_INT_IN_KERNEL(displ, label) \ - cmpl $CS_SELECTOR, displ(%esp) ;\ + cmpl $KERN_CS_SELECTOR, displ(%esp) ;\ je label ; /* @@ -36,28 +36,12 @@ movl tmp, PSWREG(pptr) ;\ movl (12 + displ)(%esp), tmp ;\ movl tmp, SPREG(pptr) ;\ - movl tmp, STREG(pptr) ;\ - movl (16 + displ)(%esp), tmp ;\ - movl tmp, SSREG(pptr) ; - -#define SAVE_SEGS(pptr) \ - mov %ds, %ss:DSREG(pptr) ;\ - mov %es, %ss:ESREG(pptr) ;\ - mov %fs, %ss:FSREG(pptr) ;\ - mov %gs, %ss:GSREG(pptr) ; - -#define RESTORE_SEGS(pptr) \ - movw %ss:DSREG(pptr), %ds ;\ - movw %ss:ESREG(pptr), %es ;\ - movw %ss:FSREG(pptr), %fs ;\ - movw %ss:GSREG(pptr), %gs ; + movl tmp, STREG(pptr) /* - * restore kernel segments, %ss is kernnel data segment, %cs is aready set and - * %fs, %gs are not used - */ + * restore kernel segments. %cs is aready set and %fs, %gs are not used */ #define RESTORE_KERNEL_SEGS \ - mov %ss, %si ;\ + mov $KERN_DS_SELECTOR, %si ;\ mov %si, %ds ;\ mov %si, %es ;\ movw $0, %si ;\ @@ -65,20 +49,20 @@ mov %si, %fs ; #define SAVE_GP_REGS(pptr) \ - mov %eax, %ss:AXREG(pptr) ;\ - mov %ecx, %ss:CXREG(pptr) ;\ - mov %edx, %ss:DXREG(pptr) ;\ - mov %ebx, %ss:BXREG(pptr) ;\ - mov %esi, %ss:SIREG(pptr) ;\ - mov %edi, %ss:DIREG(pptr) ; + mov %eax, AXREG(pptr) ;\ + mov %ecx, CXREG(pptr) ;\ + mov %edx, DXREG(pptr) ;\ + mov %ebx, BXREG(pptr) ;\ + mov %esi, SIREG(pptr) ;\ + mov %edi, DIREG(pptr) ; #define RESTORE_GP_REGS(pptr) \ - movl %ss:AXREG(pptr), %eax ;\ - movl %ss:CXREG(pptr), %ecx ;\ - movl %ss:DXREG(pptr), %edx ;\ - movl %ss:BXREG(pptr), %ebx ;\ - movl %ss:SIREG(pptr), %esi ;\ - movl %ss:DIREG(pptr), %edi ; + movl AXREG(pptr), %eax ;\ + movl CXREG(pptr), %ecx ;\ + movl DXREG(pptr), %edx ;\ + movl BXREG(pptr), %ebx ;\ + movl SIREG(pptr), %esi ;\ + movl DIREG(pptr), %edi ; /* * save the context of the interrupted process to the structure in the process @@ -97,12 +81,9 @@ ;\ movl (CURR_PROC_PTR + 4 + displ)(%esp), %ebp ;\ \ - /* save the segment registers */ \ - SAVE_SEGS(%ebp) ;\ - \ SAVE_GP_REGS(%ebp) ;\ pop %esi /* get the orig %ebp and save it */ ;\ - mov %esi, %ss:BPREG(%ebp) ;\ + mov %esi, BPREG(%ebp) ;\ \ RESTORE_KERNEL_SEGS ;\ SAVE_TRAP_CTX(displ, %ebp, %esi) ; diff --git a/kernel/arch/i386/trampoline.S b/kernel/arch/i386/trampoline.S index 43d0c709c..a03aedbf8 100644 --- a/kernel/arch/i386/trampoline.S +++ b/kernel/arch/i386/trampoline.S @@ -20,7 +20,7 @@ ENTRY(trampoline) orb $1, %al mov %eax, %cr0 - ljmpl $CS_SELECTOR, $_C_LABEL(startup_ap_32) + ljmpl $KERN_CS_SELECTOR, $_C_LABEL(startup_ap_32) .balign 4 LABEL(__ap_id) diff --git a/kernel/clock.c b/kernel/clock.c index 5571da27e..1049d6b55 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -141,7 +141,7 @@ int timer_int_handler(void) } #ifdef DEBUG_SERIAL - if (do_serial_debug) + if (kinfo.do_serial_debug) do_ser_debug(); #endif diff --git a/kernel/config.h b/kernel/config.h index a3dd15219..55c24a09f 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -43,12 +43,6 @@ #define USE_MEMSET 1 /* write char to a given memory area */ #define USE_RUNCTL 1 /* control stop flags of a process */ -/* Length of program names stored in the process table. This is only used - * for the debugging dumps that can be generated with the IS server. The PM - * server keeps its own copy of the program name. - */ -#define P_NAME_LEN 8 - /* This section contains defines for valuable system resources that are used * by device drivers. The number of elements of the vectors is determined by * the maximum needed by any given driver. The number of interrupt hooks may diff --git a/kernel/const.h b/kernel/const.h index 16857462b..7e7e3da9b 100644 --- a/kernel/const.h +++ b/kernel/const.h @@ -27,10 +27,6 @@ #define unset_sys_bit(map,bit) \ ( MAP_CHUNK((map).chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) )) -/* args to intr_init() */ -#define INTS_ORIG 0 /* restore interrupts */ -#define INTS_MINIX 1 /* initialize interrupts for minix */ - /* for kputc() */ #define END_OF_KMESS 0 diff --git a/kernel/debug.c b/kernel/debug.c index 8c37e32a8..f0ac507b0 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -175,7 +175,6 @@ miscflagstr(const u32_t flags) str[0] = '\0'; FLAG(MF_REPLY_PEND); - FLAG(MF_FULLVM); FLAG(MF_DELIVERMSG); FLAG(MF_KCALL_RESUME); diff --git a/kernel/glo.h b/kernel/glo.h index bb0ef7235..4bb96da52 100644 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -22,7 +22,6 @@ EXTERN struct kinfo kinfo; /* kernel information for users */ EXTERN struct machine machine; /* machine information for users */ EXTERN struct kmessages kmess; /* diagnostic messages in kernel */ -EXTERN char kmess_buf[80*25]; /* printable copy of message buffer */ EXTERN struct k_randomness krandom; /* gather kernel random information */ EXTERN struct loadinfo kloadinfo; /* status of load average */ @@ -40,14 +39,8 @@ EXTERN int irq_use; /* map of all in-use irq's */ EXTERN u32_t system_hz; /* HZ value */ /* Miscellaneous. */ -EXTERN int do_serial_debug; -EXTERN int serial_debug_baud; EXTERN time_t boottime; -EXTERN char params_buffer[512]; /* boot monitor parameters */ -EXTERN int minix_panicing; EXTERN int verboseboot; /* verbose boot, init'ed in cstart */ -#define MAGICTEST 0xC0FFEE23 -EXTERN u32_t magictest; /* global magic number */ #if DEBUG_TRACE EXTERN int verboseflags; @@ -66,14 +59,14 @@ EXTERN u64_t cpu_hz[CONFIG_MAX_CPUS]; #ifdef CONFIG_SMP EXTERN int config_no_smp; /* optionaly turn off SMP */ #endif +EXTERN int bootstrap_pagetable_done; /* VM */ EXTERN int vm_running; EXTERN int catch_pagefaults; /* Variables that are initialized elsewhere are just extern here. */ -extern struct boot_image image[]; /* system image processes */ -extern struct segdesc_s gdt[]; /* global descriptor table */ +extern struct boot_image image[NR_BOOT_PROCS]; /* system image processes */ EXTERN volatile int serial_debug_active; @@ -85,4 +78,7 @@ EXTERN u64_t bkl_ticks[CONFIG_MAX_CPUS]; EXTERN unsigned bkl_tries[CONFIG_MAX_CPUS]; EXTERN unsigned bkl_succ[CONFIG_MAX_CPUS]; +/* Feature flags */ +EXTERN int minix_feature_flags; + #endif /* GLO_H */ diff --git a/kernel/main.c b/kernel/main.c index 004948aa3..5cf56e1db 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -10,12 +10,16 @@ */ #include "kernel.h" #include +#include #include #include +#include #include #include #include +#include #include +#include #include "proc.h" #include "debug.h" #include "clock.h" @@ -102,35 +106,40 @@ void bsp_finish_booting(void) machine.processors_count = 1; machine.bsp_id = 0; #endif - + switch_to_user(); NOT_REACHABLE; } /*===========================================================================* - * main * + * kmain * *===========================================================================*/ -int main(void) +void kmain(kinfo_t *local_cbi) { /* Start the ball rolling. */ struct boot_image *ip; /* boot image pointer */ register struct proc *rp; /* process pointer */ register int i, j; - size_t argsz; /* size of arguments passed to crtso on stack */ + + /* save a global copy of the boot parameters */ + memcpy(&kinfo, local_cbi, sizeof(kinfo)); + memcpy(&kmess, kinfo.kmess, sizeof(kmess)); + + /* We can talk now */ + printf("MINIX booting\n"); + + assert(sizeof(kinfo.boot_procs) == sizeof(image)); + memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs)); + + cstart(); BKL_LOCK(); - /* Global value to test segment sanity. */ - magictest = MAGICTEST; DEBUGEXTRA(("main()\n")); proc_init(); - /* Set up proc table entries for processes in boot image. The stacks - * of the servers have been added to the data segment by the monitor, so - * the stack pointer is set to the end of the data segment. - */ - + /* Set up proc table entries for processes in boot image. */ for (i=0; i < NR_BOOT_PROCS; ++i) { int schedulable_proc; proc_nr_t proc_nr; @@ -142,7 +151,13 @@ int main(void) rp = proc_addr(ip->proc_nr); /* get process pointer */ ip->endpoint = rp->p_endpoint; /* ipc endpoint */ make_zero64(rp->p_cpu_time_left); - strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */ + + if(i >= NR_TASKS) { + /* Remember this so it can be passed to VM */ + multiboot_module_t *mb_mod = &kinfo.module_list[i - NR_TASKS]; + ip->start_addr = mb_mod->mod_start; + ip->len = mb_mod->mod_end - mb_mod->mod_start; + } reset_proc_accounting(rp); @@ -154,13 +169,23 @@ int main(void) * process has set their privileges. */ proc_nr = proc_nr(rp); - schedulable_proc = (iskerneln(proc_nr) || isrootsysn(proc_nr)); + schedulable_proc = (iskerneln(proc_nr) || isrootsysn(proc_nr) || + proc_nr == VM_PROC_NR); if(schedulable_proc) { /* Assign privilege structure. Force a static privilege id. */ (void) get_priv(rp, static_priv_id(proc_nr)); /* Priviliges for kernel tasks. */ - if(iskerneln(proc_nr)) { + if(proc_nr == VM_PROC_NR) { + priv(rp)->s_flags = VM_F; + priv(rp)->s_trap_mask = SRV_T; + ipc_to_m = SRV_M; + kcalls = SRV_KC; + priv(rp)->s_sig_mgr = SELF; + rp->p_priority = SRV_Q; + rp->p_quantum_size_ms = SRV_QT; + } + else if(iskerneln(proc_nr)) { /* Privilege flags. */ priv(rp)->s_flags = (proc_nr == IDLE ? IDL_F : TSK_F); /* Allowed traps. */ @@ -203,64 +228,34 @@ int main(void) /* Don't let the process run for now. */ RTS_SET(rp, RTS_NO_PRIV | RTS_NO_QUANTUM); } - rp->p_memmap[T].mem_vir = ABS2CLICK(ip->memmap.text_vaddr); - rp->p_memmap[T].mem_phys = ABS2CLICK(ip->memmap.text_paddr); - rp->p_memmap[T].mem_len = ABS2CLICK(ip->memmap.text_bytes); - rp->p_memmap[D].mem_vir = ABS2CLICK(ip->memmap.data_vaddr); - rp->p_memmap[D].mem_phys = ABS2CLICK(ip->memmap.data_paddr); - rp->p_memmap[D].mem_len = ABS2CLICK(ip->memmap.data_bytes); - rp->p_memmap[S].mem_phys = ABS2CLICK(ip->memmap.data_paddr + - ip->memmap.data_bytes + - ip->memmap.stack_bytes); - rp->p_memmap[S].mem_vir = ABS2CLICK(ip->memmap.data_vaddr + - ip->memmap.data_bytes + - ip->memmap.stack_bytes); - rp->p_memmap[S].mem_len = 0; - /* Set initial register values. The processor status word for tasks - * is different from that of other processes because tasks can - * access I/O; this is not allowed to less-privileged processes - */ - rp->p_reg.pc = ip->memmap.entry; - rp->p_reg.psw = (iskerneln(proc_nr)) ? INIT_TASK_PSW : INIT_PSW; - - /* Initialize the server stack pointer. Take it down three words - * to give crtso.s something to use as "argc", "argv" and "envp". - */ - if (isusern(proc_nr)) { /* user-space process? */ - rp->p_reg.sp = (rp->p_memmap[S].mem_vir + - rp->p_memmap[S].mem_len) << CLICK_SHIFT; - argsz = 3 * sizeof(reg_t); - rp->p_reg.sp -= argsz; - phys_memset(rp->p_reg.sp - - (rp->p_memmap[S].mem_vir << CLICK_SHIFT) + - (rp->p_memmap[S].mem_phys << CLICK_SHIFT), - 0, argsz); - } + /* Arch-specific state initialization. */ + arch_boot_proc(ip, rp); /* scheduling functions depend on proc_ptr pointing somewhere. */ if(!get_cpulocal_var(proc_ptr)) get_cpulocal_var(proc_ptr) = rp; - /* If this process has its own page table, VM will set the - * PT up and manage it. VM will signal the kernel when it has - * done this; until then, don't let it run. - */ - if(ip->flags & PROC_FULLVM) + /* Process isn't scheduled until VM has set up a pagetable for it. */ + if(rp->p_nr != VM_PROC_NR && rp->p_nr >= 0) rp->p_rts_flags |= RTS_VMINHIBIT; rp->p_rts_flags |= RTS_PROC_STOP; rp->p_rts_flags &= ~RTS_SLOT_FREE; - alloc_segments(rp); DEBUGEXTRA(("done\n")); } + /* update boot procs info for VM */ + memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs)); + #define IPCNAME(n) { \ assert((n) >= 0 && (n) <= IPCNO_HIGHEST); \ assert(!ipc_call_names[n]); \ ipc_call_names[n] = #n; \ } + arch_post_init(); + IPCNAME(SEND); IPCNAME(RECEIVE); IPCNAME(SENDREC); @@ -268,16 +263,17 @@ int main(void) IPCNAME(SENDNB); IPCNAME(SENDA); - /* Architecture-dependent initialization. */ - DEBUGEXTRA(("arch_init()... ")); - arch_init(); - DEBUGEXTRA(("done\n")); - /* System and processes initialization */ + memory_init(); DEBUGEXTRA(("system_init()... ")); system_init(); DEBUGEXTRA(("done\n")); + /* The bootstrap phase is over, so we can add the physical + * memory used for it to the free list. + */ + add_memmap(&kinfo, kinfo.bootstrap_start, kinfo.bootstrap_len); + #ifdef CONFIG_SMP if (config_no_apic) { BOOT_VERBOSE(printf("APIC disabled, disables SMP, using legacy PIC\n")); @@ -303,7 +299,6 @@ int main(void) #endif NOT_REACHABLE; - return 1; } /*===========================================================================* @@ -360,7 +355,127 @@ void minix_shutdown(timer_t *tp) #endif hw_intr_disable_all(); stop_local_timer(); - intr_init(INTS_ORIG, 0); arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC); } +/*===========================================================================* + * cstart * + *===========================================================================*/ +void cstart() +{ +/* Perform system initializations prior to calling main(). Most settings are + * determined with help of the environment strings passed by MINIX' loader. + */ + register char *value; /* value in key=value pair */ + int h; + + /* low-level initialization */ + prot_init(); + + /* determine verbosity */ + if ((value = env_get(VERBOSEBOOTVARNAME))) + verboseboot = atoi(value); + + /* Get clock tick frequency. */ + value = env_get("hz"); + if(value) + system_hz = atoi(value); + if(!value || system_hz < 2 || system_hz > 50000) /* sanity check */ + system_hz = DEFAULT_HZ; + + DEBUGEXTRA(("cstart\n")); + + /* Record miscellaneous information for user-space servers. */ + kinfo.nr_procs = NR_PROCS; + kinfo.nr_tasks = NR_TASKS; + strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release)); + kinfo.release[sizeof(kinfo.release)-1] = '\0'; + strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version)); + kinfo.version[sizeof(kinfo.version)-1] = '\0'; + + /* Load average data initialization. */ + kloadinfo.proc_last_slot = 0; + for(h = 0; h < _LOAD_HISTORY; h++) + kloadinfo.proc_load_history[h] = 0; + +#ifdef USE_APIC + value = env_get("no_apic"); + if(value) + config_no_apic = atoi(value); + else + config_no_apic = 1; + value = env_get("apic_timer_x"); + if(value) + config_apic_timer_x = atoi(value); + else + config_apic_timer_x = 1; +#endif + +#ifdef USE_WATCHDOG + value = env_get("watchdog"); + if (value) + watchdog_enabled = atoi(value); +#endif + +#ifdef CONFIG_SMP + if (config_no_apic) + config_no_smp = 1; + value = env_get("no_smp"); + if(value) + config_no_smp = atoi(value); + else + config_no_smp = 0; +#endif + DEBUGEXTRA(("intr_init(0)\n")); + + intr_init(0); + + arch_init(); +} + +/*===========================================================================* + * get_value * + *===========================================================================*/ + +char *get_value( + const char *params, /* boot monitor parameters */ + const char *name /* key to look up */ +) +{ +/* Get environment value - kernel version of getenv to avoid setting up the + * usual environment array. + */ + register const char *namep; + register char *envp; + + for (envp = (char *) params; *envp != 0;) { + for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++) + ; + if (*namep == '\0' && *envp == '=') return(envp + 1); + while (*envp++ != 0) + ; + } + return(NULL); +} + +/*===========================================================================* + * env_get * + *===========================================================================*/ +char *env_get(const char *name) +{ + return get_value(kinfo.param_buf, name); +} + +void cpu_print_freq(unsigned cpu) +{ + u64_t freq; + + freq = cpu_get_freq(cpu); + printf("CPU %d freq %lu MHz\n", cpu, div64u(freq, 1000000)); +} + +int is_fpu(void) +{ + return get_cpulocal_var(fpu_presence); +} + diff --git a/kernel/perf.h b/kernel/perf.h index 8dcf53b23..e47298555 100644 --- a/kernel/perf.h +++ b/kernel/perf.h @@ -6,11 +6,4 @@ /* Enable copy-on-write optimization for safecopy. */ #define PERF_USE_COW_SAFECOPY 0 -/* Use a private page table for critical system processes. */ -#ifdef CONFIG_SMP -#define PERF_SYS_CORE_FULLVM 1 -#else -#define PERF_SYS_CORE_FULLVM 0 -#endif - #endif /* PERF_H */ diff --git a/kernel/proc.c b/kernel/proc.c index 6c1f5098e..0d5330693 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -72,10 +72,7 @@ static void set_idle_name(char * name, int n) { int i, c; int p_z = 0; - /* - * P_NAME_LEN limits us to 3 characters for the idle task numer. 999 - * should be enough though. - */ + if (n > 999) n = 999; @@ -138,7 +135,7 @@ void proc_init(void) rp->p_quantum_size_ms = 0; /* no quantum size */ /* arch-specific initialization */ - arch_proc_init(i, rp); + arch_proc_reset(rp); } for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { sp->s_proc_nr = NONE; /* initialize as free */ @@ -387,7 +384,7 @@ check_misc_flags: */ p->p_misc_flags &= ~MF_CONTEXT_SET; - assert(!(p->p_misc_flags & MF_FULLVM) || p->p_seg.p_cr3 != 0); + assert(p->p_seg.p_cr3 != 0); #ifdef CONFIG_SMP if (p->p_misc_flags & MF_FLUSH_TLB) { if (tlb_must_refresh) @@ -816,7 +813,7 @@ int mini_send( assert(!(dst_ptr->p_misc_flags & MF_DELIVERMSG)); if (!(flags & FROM_KERNEL)) { - if(copy_msg_from_user(caller_ptr, m_ptr, &dst_ptr->p_delivermsg)) + if(copy_msg_from_user(m_ptr, &dst_ptr->p_delivermsg)) return EFAULT; } else { dst_ptr->p_delivermsg = *m_ptr; @@ -851,7 +848,7 @@ int mini_send( /* Destination is not waiting. Block and dequeue caller. */ if (!(flags & FROM_KERNEL)) { - if(copy_msg_from_user(caller_ptr, m_ptr, &caller_ptr->p_sendmsg)) + if(copy_msg_from_user(m_ptr, &caller_ptr->p_sendmsg)) return EFAULT; } else { caller_ptr->p_sendmsg = *m_ptr; diff --git a/kernel/proc.h b/kernel/proc.h index ea546ef33..9b792b931 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -54,8 +54,6 @@ struct proc { unsigned long preempted; } p_accounting; - struct mem_map p_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */ - clock_t p_user_time; /* user time in ticks */ clock_t p_sys_time; /* sys time in ticks */ @@ -74,7 +72,7 @@ struct proc { sigset_t p_pending; /* bit map for pending kernel signals */ - char p_name[P_NAME_LEN]; /* name of the process, including \0 */ + char p_name[PROC_NAME_LEN]; /* name of the process, including \0 */ endpoint_t p_endpoint; /* endpoint number, generation-aware */ @@ -237,7 +235,6 @@ struct proc { We need to resume the kernel call execution now */ -#define MF_FULLVM 0x020 #define MF_DELIVERMSG 0x040 /* Copy message for him before running */ #define MF_SIG_DELAY 0x080 /* Send signal when no longer sending */ #define MF_SC_ACTIVE 0x100 /* Syscall tracing: in a system call now */ diff --git a/kernel/profile.c b/kernel/profile.c index a417aa8ac..29e4ea3d4 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -82,7 +82,7 @@ static void sprof_save_proc(struct proc * p) s = (struct sprof_proc *) (sprof_sample_buffer + sprof_info.mem_used); s->proc = p->p_endpoint; - memcpy(&s->name, p->p_name, P_NAME_LEN); + strcpy(s->name, p->p_name); sprof_info.mem_used += sizeof(struct sprof_proc); } diff --git a/kernel/proto.h b/kernel/proto.h index 7ceb06e25..0159fbf71 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -38,7 +38,10 @@ void fpu_sigcontext(struct proc *, struct sigframe *fr, struct sigcontext *sc); /* main.c */ -int main(void); +#ifndef UNPAGED +#define kmain __k_unpaged_kmain +#endif +void kmain(kinfo_t *cbi); void prepare_shutdown(int how); __dead void minix_shutdown(struct timer *tp); void bsp_finish_booting(void); @@ -55,7 +58,7 @@ int mini_notify(const struct proc *src, endpoint_t dst); void enqueue(struct proc *rp); void dequeue(struct proc *rp); void switch_to_user(void); -void arch_proc_init(int nr, struct proc *rp); +void arch_proc_reset(struct proc *rp); struct proc * arch_finish_switch_to_user(void); struct proc *endpoint_lookup(endpoint_t ep); #if DEBUG_ENABLE_IPC_WARNINGS @@ -73,8 +76,7 @@ int try_deliver_senda(struct proc *caller_ptr, asynmsg_t *table, size_t size); /* start.c */ -void cstart(u16_t cs, u16_t ds, u16_t mds, u16_t parmoff, u16_t - parmsize); +void cstart(); char *env_get(const char *key); /* system.c */ @@ -87,17 +89,11 @@ void cause_sig(proc_nr_t proc_nr, int sig_nr); void sig_delay_done(struct proc *rp); void kernel_call(message *m_user, struct proc * caller); void system_init(void); -#define numap_local(proc_nr, vir_addr, bytes) \ - umap_local(proc_addr(proc_nr), D, (vir_addr), (bytes)) void clear_endpoint(struct proc *rc); void clear_ipc_refs(struct proc *rc, int caller_ret); void kernel_call_resume(struct proc *p); int sched_proc(struct proc *rp, int priority, int quantum, int cpu); -/* system/do_newmap.c */ -int newmap(struct proc * caller, struct proc *rp, struct mem_map - *map_ptr); - /* system/do_vtimer.c */ void vtimer_check(struct proc *rp); @@ -152,7 +148,8 @@ void stop_profile_clock(void); #endif /* functions defined in architecture-dependent files. */ -void prot_init(void); +void prot_init(); +void arch_post_init(); phys_bytes phys_copy(phys_bytes source, phys_bytes dest, phys_bytes count); void phys_copy_fault(void); @@ -169,18 +166,15 @@ int data_copy(endpoint_t from, vir_bytes from_addr, endpoint_t to, vir_bytes to_addr, size_t bytes); int data_copy_vmcheck(struct proc *, endpoint_t from, vir_bytes from_addr, endpoint_t to, vir_bytes to_addr, size_t bytes); -void alloc_segments(struct proc *rp); -void vm_stop(void); -phys_bytes umap_local(register struct proc *rp, int seg, vir_bytes - vir_addr, vir_bytes bytes); phys_bytes umap_virtual(struct proc* rp, int seg, vir_bytes vir_addr, vir_bytes bytes); phys_bytes seg2phys(u16_t); int vm_memset(endpoint_t who, phys_bytes source, u8_t pattern, phys_bytes count); -int intr_init(int, int); +int intr_init(int); void halt_cpu(void); void arch_init(void); +void arch_boot_proc(struct boot_image *b, struct proc *p); void cpu_identify(void); /* arch dependent FPU initialization per CPU */ void fpu_init(void); @@ -195,8 +189,9 @@ void arch_stop_profile_clock(void); void arch_ack_profile_clock(void); void do_ser_debug(void); int arch_get_params(char *parm, int max); -int arch_set_params(char *parm, int max); -void arch_pre_exec(struct proc *pr, u32_t, u32_t); +void memory_init(void); +void mem_clear_mapcache(void); +void arch_proc_init(struct proc *pr, u32_t, u32_t, char *); int arch_do_vmctl(message *m_ptr, struct proc *p); int vm_contiguous(const struct proc *targetproc, vir_bytes vir_buf, size_t count); @@ -210,14 +205,12 @@ void arch_do_syscall(struct proc *proc); int arch_phys_map(int index, phys_bytes *addr, phys_bytes *len, int *flags); int arch_phys_map_reply(int index, vir_bytes addr); -int arch_enable_paging(struct proc * caller, const message * m_ptr); +int arch_enable_paging(struct proc * caller); int vm_check_range(struct proc *caller, struct proc *target, vir_bytes vir_addr, size_t bytes); -int copy_msg_from_user(struct proc * p, message * user_mbuf, message * - dst); -int copy_msg_to_user(struct proc * p, message * src, message * - user_mbuf); +int copy_msg_from_user(message * user_mbuf, message * dst); +int copy_msg_to_user(message * src, message * user_mbuf); void switch_address_space(struct proc * p); void release_address_space(struct proc *pr); diff --git a/kernel/start.c b/kernel/start.c deleted file mode 100644 index 32127b66a..000000000 --- a/kernel/start.c +++ /dev/null @@ -1,151 +0,0 @@ - -/* First C file used by the kernel. */ - -#include "kernel.h" -#include "proc.h" -#include -#include -#include "proto.h" - -#ifdef USE_WATCHDOG -#include "watchdog.h" -#endif - -/*===========================================================================* - * cstart * - *===========================================================================*/ -void cstart( - u16_t cs, /* kernel code segment */ - u16_t ds, /* kernel data segment */ - u16_t mds, /* monitor data segment */ - u16_t parmoff, /* boot parameters offset */ - u16_t parmsize /* boot parameters length */ -) -{ -/* Perform system initializations prior to calling main(). Most settings are - * determined with help of the environment strings passed by MINIX' loader. - */ - register char *value; /* value in key=value pair */ - extern int etext, end; - int h; - - /* Record where the kernel and the monitor are. */ - kinfo.code_base = seg2phys(cs); - kinfo.code_size = (phys_bytes) &etext; /* size of code segment */ - kinfo.data_base = seg2phys(ds); - kinfo.data_size = (phys_bytes) &end; /* size of data segment */ - - /* protection initialization */ - prot_init(); - - /* Copy the boot parameters to the local buffer. */ - arch_get_params(params_buffer, sizeof(params_buffer)); - - /* determine verbosity */ - if ((value = env_get(VERBOSEBOOTVARNAME))) - verboseboot = atoi(value); - - /* Get clock tick frequency. */ - value = env_get("hz"); - if(value) - system_hz = atoi(value); - if(!value || system_hz < 2 || system_hz > 50000) /* sanity check */ - system_hz = DEFAULT_HZ; - -#ifdef DEBUG_SERIAL - /* Intitialize serial debugging */ - value = env_get(SERVARNAME); - if(value && atoi(value) == 0) { - do_serial_debug=1; - - value = env_get(SERBAUDVARNAME); - if (value) serial_debug_baud = atoi(value); - } -#endif - - DEBUGEXTRA(("cstart\n")); - - /* Record miscellaneous information for user-space servers. */ - kinfo.nr_procs = NR_PROCS; - kinfo.nr_tasks = NR_TASKS; - strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release)); - kinfo.release[sizeof(kinfo.release)-1] = '\0'; - strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version)); - kinfo.version[sizeof(kinfo.version)-1] = '\0'; - kinfo.proc_addr = (vir_bytes) proc; - - /* Load average data initialization. */ - kloadinfo.proc_last_slot = 0; - for(h = 0; h < _LOAD_HISTORY; h++) - kloadinfo.proc_load_history[h] = 0; - -#ifdef USE_APIC - value = env_get("no_apic"); - if(value) - config_no_apic = atoi(value); - else - config_no_apic = 1; - value = env_get("apic_timer_x"); - if(value) - config_apic_timer_x = atoi(value); - else - config_apic_timer_x = 1; -#endif - -#ifdef USE_WATCHDOG - value = env_get("watchdog"); - if (value) - watchdog_enabled = atoi(value); -#endif - -#ifdef CONFIG_SMP - if (config_no_apic) - config_no_smp = 1; - value = env_get("no_smp"); - if(value) - config_no_smp = atoi(value); - else - config_no_smp = 0; -#endif - - /* Return to assembler code to switch to protected mode (if 286), - * reload selectors and call main(). - */ - - DEBUGEXTRA(("intr_init(%d, 0)\n", INTS_MINIX)); - intr_init(INTS_MINIX, 0); -} - -/*===========================================================================* - * get_value * - *===========================================================================*/ - -char *get_value( - const char *params, /* boot monitor parameters */ - const char *name /* key to look up */ -) -{ -/* Get environment value - kernel version of getenv to avoid setting up the - * usual environment array. - */ - register const char *namep; - register char *envp; - - for (envp = (char *) params; *envp != 0;) { - for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++) - ; - if (*namep == '\0' && *envp == '=') return(envp + 1); - while (*envp++ != 0) - ; - } - return(NULL); -} - -/*===========================================================================* - * env_get * - *===========================================================================*/ -char *env_get(const char *name) -{ - return get_value(params_buffer, name); -} - diff --git a/kernel/system.c b/kernel/system.c index 2b08d4cfe..b1dd9337e 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -81,8 +81,7 @@ static void kernel_call_finish(struct proc * caller, message *msg, int result) #if DEBUG_IPC_HOOK hook_ipc_msgkresult(msg, caller); #endif - if (copy_msg_to_user(caller, msg, - (message *)caller->p_delivermsg_vir)) { + if (copy_msg_to_user(msg, (message *)caller->p_delivermsg_vir)) { printf("WARNING wrong user pointer 0x%08x from " "process %s / %d\n", caller->p_delivermsg_vir, @@ -146,7 +145,7 @@ void kernel_call(message *m_user, struct proc * caller) * into the kernel or was already set in switch_to_user() before we resume * execution of an interrupted kernel call */ - if (copy_msg_from_user(caller, m_user, &msg) == 0) { + if (copy_msg_from_user(m_user, &msg) == 0) { msg.m_source = caller->p_endpoint; result = kernel_call_dispatch(caller, &msg); } @@ -216,7 +215,6 @@ void system_init(void) map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */ /* Memory management. */ - map(SYS_NEWMAP, do_newmap); /* set up a process memory map */ map(SYS_MEMSET, do_memset); /* write char to memory area */ map(SYS_VMCTL, do_vmctl); /* various VM process settings */ @@ -366,13 +364,16 @@ int send_sig(endpoint_t ep, int sig_nr) * send a notification with source SYSTEM. */ register struct proc *rp; + struct priv *priv; int proc_nr; if(!isokendpt(ep, &proc_nr) || isemptyn(proc_nr)) return EINVAL; rp = proc_addr(proc_nr); - sigaddset(&priv(rp)->s_sig_pending, sig_nr); + priv = priv(rp); + if(!priv) return ENOENT; + sigaddset(&priv->s_sig_pending, sig_nr); mini_notify(proc_addr(SYSTEM), rp->p_endpoint); return OK; diff --git a/kernel/system.h b/kernel/system.h index 59c9ef31f..755ebae4e 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -46,11 +46,6 @@ int do_fork(struct proc * caller, message *m_ptr); #define do_fork NULL #endif -int do_newmap(struct proc * caller, message *m_ptr); -#if ! USE_NEWMAP -#define do_newmap NULL -#endif - int do_clear(struct proc * caller, message *m_ptr); #if ! USE_CLEAR #define do_clear NULL diff --git a/kernel/system/Makefile.inc b/kernel/system/Makefile.inc index 4209c9901..c4ccc04ed 100644 --- a/kernel/system/Makefile.inc +++ b/kernel/system/Makefile.inc @@ -5,7 +5,6 @@ SRCS+= \ do_fork.c \ do_exec.c \ - do_newmap.c \ do_clear.c \ do_exit.c \ do_trace.c \ diff --git a/kernel/system/do_abort.c b/kernel/system/do_abort.c index c0c507881..8208af524 100644 --- a/kernel/system/do_abort.c +++ b/kernel/system/do_abort.c @@ -35,10 +35,6 @@ int do_abort(struct proc * caller, message * m_ptr) return p; } paramsbuffer[len] = '\0'; - - /* Parameters seem ok, copy them and prepare shutting down. */ - if((p = arch_set_params(paramsbuffer, len+1)) != OK) - return p; } /* Now prepare to shutdown MINIX. */ diff --git a/kernel/system/do_copy.c b/kernel/system/do_copy.c index 2e80c8351..52b535b74 100644 --- a/kernel/system/do_copy.c +++ b/kernel/system/do_copy.c @@ -26,7 +26,6 @@ int do_copy(struct proc * caller, message * m_ptr) struct vir_addr vir_addr[2]; /* virtual source and destination address */ phys_bytes bytes; /* number of bytes to copy */ int i; - endpoint_t pe; #if 0 if (caller->p_endpoint != PM_PROC_NR && caller->p_endpoint != VFS_PROC_NR && @@ -47,11 +46,10 @@ int do_copy(struct proc * caller, message * m_ptr) #endif /* Dismember the command message. */ - pe = vir_addr[_SRC_].proc_nr_e = m_ptr->CP_SRC_ENDPT; - vir_addr[_SRC_].segment = (pe == NONE ? PHYS_SEG : D); + vir_addr[_SRC_].proc_nr_e = m_ptr->CP_SRC_ENDPT; + vir_addr[_DST_].proc_nr_e = m_ptr->CP_DST_ENDPT; + vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR; - pe = vir_addr[_DST_].proc_nr_e = m_ptr->CP_DST_ENDPT; - vir_addr[_DST_].segment = (pe == NONE ? PHYS_SEG : D); vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR; bytes = (phys_bytes) m_ptr->CP_NR_BYTES; @@ -63,10 +61,9 @@ int do_copy(struct proc * caller, message * m_ptr) /* Check if process number was given implictly with SELF and is valid. */ if (vir_addr[i].proc_nr_e == SELF) vir_addr[i].proc_nr_e = caller->p_endpoint; - if (vir_addr[i].segment != PHYS_SEG) { + if (vir_addr[i].proc_nr_e != NONE) { if(! isokendpt(vir_addr[i].proc_nr_e, &p)) { - printf("do_copy: %d: seg 0x%x, %d not ok endpoint\n", - i, vir_addr[i].segment, vir_addr[i].proc_nr_e); + printf("do_copy: %d: %d not ok endpoint\n", i, vir_addr[i].proc_nr_e); return(EINVAL); } } diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index 0919d8dc9..74370544b 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -21,6 +21,7 @@ int do_exec(struct proc * caller, message * m_ptr) /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ register struct proc *rp; int proc_nr; + char name[PROC_NAME_LEN]; if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return EINVAL; @@ -33,11 +34,14 @@ int do_exec(struct proc * caller, message * m_ptr) /* Save command name for debugging, ps(1) output, etc. */ if(data_copy(caller->p_endpoint, (vir_bytes) m_ptr->PR_NAME_PTR, - KERNEL, (vir_bytes) rp->p_name, (phys_bytes) P_NAME_LEN - 1) != OK) - strncpy(rp->p_name, "", P_NAME_LEN); + KERNEL, (vir_bytes) name, + (phys_bytes) sizeof(name) - 1) != OK) + strncpy(name, "", PROC_NAME_LEN); - /* Do architecture-specific exec() stuff. */ - arch_pre_exec(rp, (u32_t) m_ptr->PR_IP_PTR, (u32_t) m_ptr->PR_STACK_PTR); + name[sizeof(name)-1] = '\0'; + + /* Set process state. */ + arch_proc_init(rp, (u32_t) m_ptr->PR_IP_PTR, (u32_t) m_ptr->PR_STACK_PTR, name); /* No reply to EXEC call */ RTS_UNSET(rp, RTS_RECEIVING); diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index 6d588b107..e7ef19a23 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -26,13 +26,11 @@ int do_fork(struct proc * caller, message * m_ptr) { /* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */ #if (_MINIX_CHIP == _CHIP_INTEL) - reg_t old_ldt_sel; char *old_fpu_save_area_p; #endif register struct proc *rpc; /* child process pointer */ struct proc *rpp; /* parent process pointer */ - struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ - int gen, r; + int gen; int p_proc; int namelen; @@ -51,19 +49,15 @@ int do_fork(struct proc * caller, message * m_ptr) return EINVAL; } - map_ptr= (struct mem_map *) m_ptr->PR_MEM_PTR; - /* make sure that the FPU context is saved in parent before copy */ save_fpu(rpp); /* Copy parent 'proc' struct to child. And reinitialize some fields. */ gen = _ENDPOINT_G(rpc->p_endpoint); #if (_MINIX_CHIP == _CHIP_INTEL) - old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */ old_fpu_save_area_p = rpc->p_seg.fpu_state; #endif *rpc = *rpp; /* copy 'proc' struct */ #if (_MINIX_CHIP == _CHIP_INTEL) - rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */ rpc->p_seg.fpu_state = old_fpu_save_area_p; if(proc_used_fpu(rpp)) memcpy(rpc->p_seg.fpu_state, rpp->p_seg.fpu_state, FPU_XFP_SIZE); @@ -111,9 +105,6 @@ int do_fork(struct proc * caller, message * m_ptr) m_ptr->PR_ENDPT = rpc->p_endpoint; m_ptr->PR_FORK_MSGADDR = (char *) rpp->p_delivermsg_vir; - /* Install new map */ - r = newmap(caller, rpc, map_ptr); - /* Don't schedule process in VM mode until it has a new pagetable. */ if(m_ptr->PR_FORK_FLAGS & PFF_VMINHIBIT) { RTS_SET(rpc, RTS_VMINHIBIT); @@ -128,7 +119,7 @@ int do_fork(struct proc * caller, message * m_ptr) rpc->p_seg.p_cr3 = 0; rpc->p_seg.p_cr3_v = NULL; - return r; + return OK; } #endif /* USE_FORK */ diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index b13e6e2ef..5ccc6abcb 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -133,8 +133,8 @@ int do_getinfo(struct proc * caller, message * m_ptr) return OK; } case GET_MONPARAMS: { - src_vir = (vir_bytes) params_buffer; - length = sizeof(params_buffer); + src_vir = (vir_bytes) kinfo.param_buf; + length = sizeof(kinfo.param_buf); break; } case GET_RANDOMNESS: { diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c deleted file mode 100644 index 307f4b086..000000000 --- a/kernel/system/do_newmap.c +++ /dev/null @@ -1,50 +0,0 @@ -/* The kernel call implemented in this file: - * m_type: SYS_NEWMAP - * - * The parameters for this kernel call are: - * m1_i1: PR_ENDPT (install new map for this process) - * m1_p1: PR_MEM_PTR (pointer to the new memory map) - */ -#include "kernel/system.h" -#include - -#if USE_NEWMAP - -/*===========================================================================* - * do_newmap * - *===========================================================================*/ -int do_newmap(struct proc * caller, message * m_ptr) -{ -/* Handle sys_newmap(). Fetch the memory map. */ - struct proc *rp; /* process whose map is to be loaded */ - struct mem_map *map_ptr; /* virtual address of map inside caller */ - int proc_nr; - - map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; - if (! isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return(EINVAL); - if (iskerneln(proc_nr)) return(EPERM); - rp = proc_addr(proc_nr); - - return newmap(caller, rp, map_ptr); -} - - -/*===========================================================================* - * newmap * - *===========================================================================*/ -int newmap(struct proc *caller, struct proc *rp, struct mem_map *map_ptr) -{ - int r; -/* Fetch the memory map. */ - if((r=data_copy(caller->p_endpoint, (vir_bytes) map_ptr, - KERNEL, (vir_bytes) rp->p_memmap, sizeof(rp->p_memmap))) != OK) { - printf("newmap: data_copy failed! (%d)\n", r); - return r; - } - - alloc_segments(rp); - - return(OK); -} -#endif /* USE_NEWMAP */ - diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 3812afc41..86a433355 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -13,6 +13,7 @@ * VSCP_VEC_SIZE number of significant elements in vector */ +#include #include #include @@ -245,6 +246,11 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE vir_bytes size; #endif + if(granter == NONE || grantee == NONE) { + printf("safecopy: nonsense processes\n"); + return EFAULT; + } + /* See if there is a reasonable grant table. */ if(!(granter_p = endpoint_lookup(granter))) return EINVAL; if(!HASGRANTTABLE(granter_p)) { @@ -277,8 +283,6 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE granter = new_granter; /* Now it's a regular copy. */ - v_src.segment = D; - v_dst.segment = D; v_src.proc_nr_e = *src; v_dst.proc_nr_e = *dst; @@ -373,8 +377,8 @@ int do_vsafecopy(struct proc * caller, message * m_ptr) /* Set vector copy parameters. */ src.proc_nr_e = caller->p_endpoint; + assert(src.proc_nr_e != NONE); src.offset = (vir_bytes) m_ptr->VSCP_VEC_ADDR; - src.segment = dst.segment = D; dst.proc_nr_e = KERNEL; dst.offset = (vir_bytes) vec; diff --git a/kernel/system/do_safemap.c b/kernel/system/do_safemap.c index f9a28ec90..1b59b6e5f 100644 --- a/kernel/system/do_safemap.c +++ b/kernel/system/do_safemap.c @@ -120,21 +120,12 @@ int map_invoke_vm(struct proc * caller, size_t size, int flag) { struct proc *src, *dst; - phys_bytes lin_src, lin_dst; src = endpoint_lookup(end_s); dst = endpoint_lookup(end_d); - lin_src = umap_local(src, D, off_s, size); - lin_dst = umap_local(dst, D, off_d, size); - if(lin_src == 0 || lin_dst == 0) { - printf("map_invoke_vm: error in umap_local.\n"); - return EINVAL; - } - /* Make sure the linear addresses are both page aligned. */ - if(lin_src % CLICK_SIZE != 0 - || lin_dst % CLICK_SIZE != 0) { + if(off_s % CLICK_SIZE != 0 || off_d % CLICK_SIZE != 0) { printf("map_invoke_vm: linear addresses not page aligned.\n"); return EINVAL; } @@ -149,9 +140,9 @@ int map_invoke_vm(struct proc * caller, /* Map to the destination. */ caller->p_vmrequest.req_type = req_type; caller->p_vmrequest.target = end_d; /* destination proc */ - caller->p_vmrequest.params.map.vir_d = lin_dst; /* destination addr */ + caller->p_vmrequest.params.map.vir_d = off_d; /* destination addr */ caller->p_vmrequest.params.map.ep_s = end_s; /* source process */ - caller->p_vmrequest.params.map.vir_s = lin_src; /* source address */ + caller->p_vmrequest.params.map.vir_s = off_s; /* source address */ caller->p_vmrequest.params.map.length = (vir_bytes) size; caller->p_vmrequest.params.map.writeflag = flag; diff --git a/kernel/system/do_trace.c b/kernel/system/do_trace.c index 896615454..48dbae360 100644 --- a/kernel/system/do_trace.c +++ b/kernel/system/do_trace.c @@ -51,15 +51,13 @@ int do_trace(struct proc * caller, message * m_ptr) unsigned char ub; int i; -#define COPYTOPROC(seg, addr, myaddr, length) { \ +#define COPYTOPROC(addr, myaddr, length) { \ struct vir_addr fromaddr, toaddr; \ int r; \ fromaddr.proc_nr_e = KERNEL; \ toaddr.proc_nr_e = tr_proc_nr_e; \ fromaddr.offset = (myaddr); \ toaddr.offset = (addr); \ - fromaddr.segment = D; \ - toaddr.segment = (seg); \ if((r=virtual_copy_vmcheck(caller, &fromaddr, \ &toaddr, length)) != OK) { \ printf("Can't copy in sys_trace: %d\n", r);\ @@ -67,15 +65,13 @@ int do_trace(struct proc * caller, message * m_ptr) } \ } -#define COPYFROMPROC(seg, addr, myaddr, length) { \ +#define COPYFROMPROC(addr, myaddr, length) { \ struct vir_addr fromaddr, toaddr; \ int r; \ fromaddr.proc_nr_e = tr_proc_nr_e; \ toaddr.proc_nr_e = KERNEL; \ fromaddr.offset = (addr); \ toaddr.offset = (myaddr); \ - fromaddr.segment = (seg); \ - toaddr.segment = D; \ if((r=virtual_copy_vmcheck(caller, &fromaddr, \ &toaddr, length)) != OK) { \ printf("Can't copy in sys_trace: %d\n", r);\ @@ -96,12 +92,12 @@ int do_trace(struct proc * caller, message * m_ptr) return(OK); case T_GETINS: /* return value from instruction space */ - COPYFROMPROC(T, tr_addr, (vir_bytes) &tr_data, sizeof(long)); + COPYFROMPROC(tr_addr, (vir_bytes) &tr_data, sizeof(long)); m_ptr->CTL_DATA = tr_data; break; case T_GETDATA: /* return value from data space */ - COPYFROMPROC(D, tr_addr, (vir_bytes) &tr_data, sizeof(long)); + COPYFROMPROC(tr_addr, (vir_bytes) &tr_data, sizeof(long)); m_ptr->CTL_DATA= tr_data; break; @@ -125,12 +121,12 @@ int do_trace(struct proc * caller, message * m_ptr) break; case T_SETINS: /* set value in instruction space */ - COPYTOPROC(T, tr_addr, (vir_bytes) &tr_data, sizeof(long)); + COPYTOPROC(tr_addr, (vir_bytes) &tr_data, sizeof(long)); m_ptr->CTL_DATA = 0; break; case T_SETDATA: /* set value in data space */ - COPYTOPROC(D, tr_addr, (vir_bytes) &tr_data, sizeof(long)); + COPYTOPROC(tr_addr, (vir_bytes) &tr_data, sizeof(long)); m_ptr->CTL_DATA = 0; break; @@ -184,13 +180,13 @@ int do_trace(struct proc * caller, message * m_ptr) break; case T_READB_INS: /* get value from instruction space */ - COPYFROMPROC(T, tr_addr, (vir_bytes) &ub, 1); + COPYFROMPROC(tr_addr, (vir_bytes) &ub, 1); m_ptr->CTL_DATA = ub; break; case T_WRITEB_INS: /* set value in instruction space */ ub = (unsigned char) (tr_data & 0xff); - COPYTOPROC(T, tr_addr, (vir_bytes) &ub, 1); + COPYTOPROC(tr_addr, (vir_bytes) &ub, 1); m_ptr->CTL_DATA = 0; break; diff --git a/kernel/system/do_umap_remote.c b/kernel/system/do_umap_remote.c index a4ecc64f9..57dad9af6 100644 --- a/kernel/system/do_umap_remote.c +++ b/kernel/system/do_umap_remote.c @@ -33,7 +33,6 @@ int do_umap_remote(struct proc * caller, message * m_ptr) int endpt = (int) m_ptr->CP_SRC_ENDPT; endpoint_t grantee = (endpoint_t) m_ptr->CP_DST_ENDPT; int proc_nr, proc_nr_grantee; - int naughty = 0; phys_bytes phys_addr = 0, lin_addr = 0; struct proc *targetpr; @@ -57,11 +56,6 @@ int do_umap_remote(struct proc * caller, message * m_ptr) /* See which mapping should be made. */ switch(seg_type) { - case LOCAL_SEG: - phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count); - if(!lin_addr) return EFAULT; - naughty = 1; - break; case LOCAL_VM_SEG: if(seg_index == MEM_GRANT) { vir_bytes newoffset; @@ -84,11 +78,11 @@ int do_umap_remote(struct proc * caller, message * m_ptr) /* New lookup. */ offset = newoffset; targetpr = proc_addr(new_proc_nr); - seg_index = D; + seg_index = VIR_ADDR; } - if(seg_index == T || seg_index == D || seg_index == S) { - phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count); + if(seg_index == VIR_ADDR) { + phys_addr = lin_addr = offset; } else { printf("SYSTEM: bogus seg type 0x%lx\n", seg_index); return EFAULT; @@ -115,7 +109,7 @@ int do_umap_remote(struct proc * caller, message * m_ptr) } m_ptr->CP_DST_ADDR = phys_addr; - if(naughty || phys_addr == 0) { + if(phys_addr == 0) { printf("kernel: umap 0x%x done by %d / %s, pc 0x%lx, 0x%lx -> 0x%lx\n", seg_type, caller->p_endpoint, caller->p_name, caller->p_reg.pc, offset, phys_addr); diff --git a/kernel/system/do_update.c b/kernel/system/do_update.c index 127157509..38341b32a 100644 --- a/kernel/system/do_update.c +++ b/kernel/system/do_update.c @@ -111,11 +111,6 @@ int do_update(struct proc * caller, message * m_ptr) /* Swap global process slot addresses. */ swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp); - /* Fix segments. */ - alloc_segments(src_rp); - alloc_segments(dst_rp); - prot_init(); - #if DEBUG printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n", src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr, diff --git a/kernel/system/do_vmctl.c b/kernel/system/do_vmctl.c index 20ef5672e..f3a9b980e 100644 --- a/kernel/system/do_vmctl.c +++ b/kernel/system/do_vmctl.c @@ -120,13 +120,6 @@ int do_vmctl(struct proc * caller, message * m_ptr) RTS_UNSET(p, RTS_VMREQUEST); return OK; - case VMCTL_ENABLE_PAGING: - if(vm_running) - panic("do_vmctl: paging already enabled"); - if (arch_enable_paging(caller, m_ptr) != OK) - panic("do_vmctl: paging enabling failed"); - return OK; - case VMCTL_KERN_PHYSMAP: { int i = m_ptr->SVMCTL_VALUE; @@ -177,6 +170,10 @@ int do_vmctl(struct proc * caller, message * m_ptr) bits_fill(p->p_stale_tlb, CONFIG_MAX_CPUS); #endif return OK; + case VMCTL_CLEARMAPCACHE: + /* VM says: forget about old mappings we have cached. */ + mem_clear_mapcache(); + return OK; } /* Try architecture-specific vmctls. */ diff --git a/kernel/system/do_vumap.c b/kernel/system/do_vumap.c index 6ad430361..56bd635f4 100644 --- a/kernel/system/do_vumap.c +++ b/kernel/system/do_vumap.c @@ -29,7 +29,7 @@ int do_vumap(struct proc *caller, message *m_ptr) struct proc *procp; struct vumap_vir vvec[MAPVEC_NR]; struct vumap_phys pvec[MAPVEC_NR]; - vir_bytes vaddr, paddr, vir_addr, lin_addr; + vir_bytes vaddr, paddr, vir_addr; phys_bytes phys_addr; int i, r, proc_nr, vcount, pcount, pmax, access; size_t size, chunk, offset; @@ -89,13 +89,9 @@ int do_vumap(struct proc *caller, message *m_ptr) okendpt(granter, &proc_nr); procp = proc_addr(proc_nr); - lin_addr = umap_local(procp, D, vir_addr, size); - if (!lin_addr) - return EFAULT; - /* Each virtual range is made up of one or more physical ranges. */ while (size > 0 && pcount < pmax) { - chunk = vm_lookup_range(procp, lin_addr, &phys_addr, size); + chunk = vm_lookup_range(procp, vir_addr, &phys_addr, size); if (!chunk) { /* Try to get the memory allocated, unless the memory @@ -107,14 +103,14 @@ int do_vumap(struct proc *caller, message *m_ptr) /* This call may suspend the current call, or return an * error for a previous invocation. */ - return vm_check_range(caller, procp, lin_addr, size); + return vm_check_range(caller, procp, vir_addr, size); } pvec[pcount].vp_addr = phys_addr; pvec[pcount].vp_size = chunk; pcount++; - lin_addr += chunk; + vir_addr += chunk; size -= chunk; } diff --git a/kernel/table.c b/kernel/table.c index 4975a7dd6..6a4a3f3d1 100644 --- a/kernel/table.c +++ b/kernel/table.c @@ -34,13 +34,6 @@ #include "ipc.h" #include -/* Define boot process flags. */ -#define BVM_F (PROC_FULLVM) /* boot processes with VM */ -#define OVM_F (PERF_SYS_CORE_FULLVM ? PROC_FULLVM : 0) /* critical boot - * processes with - * optional VM. - */ - /* The system image table lists all programs that are part of the boot image. * The order of the entries here MUST agree with the order of the programs * in the boot image and all kernel tasks must come first. @@ -51,33 +44,26 @@ * to prioritize ping messages periodically delivered to system processes. */ -struct boot_image image[] = { +struct boot_image image[NR_BOOT_PROCS] = { /* process nr, flags, stack size, name */ -{ASYNCM, 0, 0, "asyncm"}, -{IDLE, 0, 0, "idle" }, -{CLOCK, 0, 0, "clock" }, -{SYSTEM, 0, 0, "system"}, -{HARDWARE, 0, 0, "kernel"}, +{ASYNCM, "asyncm"}, +{IDLE, "idle" }, +{CLOCK, "clock" }, +{SYSTEM, "system"}, +{HARDWARE, "kernel"}, -{DS_PROC_NR, BVM_F, 16, "ds" }, -{RS_PROC_NR, 0, 8125, "rs" }, +{DS_PROC_NR, "ds" }, +{RS_PROC_NR, "rs" }, -{PM_PROC_NR, OVM_F, 32, "pm" }, -{SCHED_PROC_NR,OVM_F, 32, "sched" }, -{VFS_PROC_NR, BVM_F, 16, "vfs" }, -{MEM_PROC_NR, BVM_F, 8, "memory"}, -{LOG_PROC_NR, BVM_F, 32, "log" }, -{TTY_PROC_NR, BVM_F, 16, "tty" }, -{MFS_PROC_NR, BVM_F, 128, "mfs" }, -{VM_PROC_NR, 0, 128, "vm" }, -{PFS_PROC_NR, BVM_F, 128, "pfs" }, -{INIT_PROC_NR, BVM_F, 64, "init" }, +{PM_PROC_NR, "pm" }, +{SCHED_PROC_NR, "sched" }, +{VFS_PROC_NR, "vfs" }, +{MEM_PROC_NR, "memory"}, +{LOG_PROC_NR, "log" }, +{TTY_PROC_NR, "tty" }, +{MFS_PROC_NR, "mfs" }, +{VM_PROC_NR, "vm" }, +{PFS_PROC_NR, "pfs" }, +{INIT_PROC_NR, "init" }, }; -/* Verify the size of the system image table at compile time. - * If a problem is detected, the size of the 'dummy' array will be negative, - * causing a compile time error. Note that no space is actually allocated - * because 'dummy' is declared extern. - */ -extern int dummy[(NR_BOOT_PROCS==sizeof(image)/ - sizeof(struct boot_image))?1:-1]; diff --git a/kernel/type.h b/kernel/type.h index 27aa46e28..4c45bcf65 100644 --- a/kernel/type.h +++ b/kernel/type.h @@ -3,6 +3,7 @@ #include #include +#include /* Process table and system property related types. */ typedef int proc_nr_t; /* process table entry number */ @@ -11,26 +12,6 @@ typedef struct { /* bitmap for system indexes */ bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)]; } sys_map_t; -struct boot_image_memmap { - phys_bytes text_vaddr; /* Virtual start address of text */ - phys_bytes text_paddr; /* Physical start address of text */ - phys_bytes text_bytes; /* Text segment's size (bytes) */ - phys_bytes data_vaddr; /* Virtual start address of data */ - phys_bytes data_paddr; /* Physical start address of data */ - phys_bytes data_bytes; /* Data segment's size (bytes) */ - phys_bytes stack_bytes; /* Size of stack set aside (bytes) */ - phys_bytes entry; /* Entry point of executable */ -}; - -struct boot_image { - proc_nr_t proc_nr; /* process number to use */ - int flags; /* process flags */ - int stack_kbytes; /* stack size (in KB) */ - char proc_name[P_NAME_LEN]; /* name in process table */ - endpoint_t endpoint; /* endpoint number when started */ - struct boot_image_memmap memmap; /* memory map info for boot image */ -}; - typedef unsigned long irq_policy_t; typedef unsigned long irq_id_t; diff --git a/kernel/utility.c b/kernel/utility.c index a513b57e2..1751573f5 100644 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -24,10 +24,10 @@ void panic(const char *fmt, ...) { va_list arg; /* The system has run aground of a fatal kernel error. Terminate execution. */ - if (minix_panicing == ARE_PANICING) { + if (kinfo.minix_panicing == ARE_PANICING) { reset(); } - minix_panicing = ARE_PANICING; + kinfo.minix_panicing = ARE_PANICING; if (fmt != NULL) { printf("kernel panic: "); va_start(arg, fmt); @@ -38,8 +38,12 @@ void panic(const char *fmt, ...) printf("kernel on CPU %d: ", cpuid); util_stacktrace(); - printf("current process : "); - proc_stacktrace(get_cpulocal_var(proc_ptr)); +#if 0 + if(get_cpulocal_var(proc_ptr)) { + printf("current process : "); + proc_stacktrace(get_cpulocal_var(proc_ptr)); + } +#endif /* Abort MINIX. */ minix_shutdown(NULL); @@ -55,29 +59,29 @@ int c; /* character to append */ * to the output driver if an END_OF_KMESS is encountered. */ if (c != END_OF_KMESS) { - static int blpos = 0; - int maxblpos = sizeof(kmess_buf) - 2; + int maxblpos = sizeof(kmess.kmess_buf) - 2; #ifdef DEBUG_SERIAL - if (do_serial_debug) { + if (kinfo.do_serial_debug) { if(c == '\n') ser_putc('\r'); ser_putc(c); } #endif kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */ - kmess_buf[blpos] = c; + kmess.kmess_buf[kmess.blpos] = c; if (kmess.km_size < sizeof(kmess.km_buf)) kmess.km_size += 1; kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE; - if(blpos == maxblpos) { - memmove(kmess_buf, kmess_buf+1, sizeof(kmess_buf)-1); - } else blpos++; + if(kmess.blpos == maxblpos) { + memmove(kmess.kmess_buf, + kmess.kmess_buf+1, sizeof(kmess.kmess_buf)-1); + } else kmess.blpos++; } else { int p; endpoint_t outprocs[] = OUTPUT_PROCS_ARRAY; - if(!(minix_panicing || do_serial_debug)) { + if(!(kinfo.minix_panicing || kinfo.do_serial_debug)) { for(p = 0; outprocs[p] != NONE; p++) { - if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) { + if(isokprocn(outprocs[p])) { send_sig(outprocs[p], SIGKMESS); } } @@ -86,15 +90,3 @@ int c; /* character to append */ return; } -void cpu_print_freq(unsigned cpu) -{ - u64_t freq; - - freq = cpu_get_freq(cpu); - printf("CPU %d freq %lu MHz\n", cpu, div64u(freq, 1000000)); -} - -int is_fpu(void) -{ - return get_cpulocal_var(fpu_presence); -} diff --git a/lib/libasyn/asyn.h b/lib/libasyn/asyn.h index 4acfdbbd6..301f34050 100644 --- a/lib/libasyn/asyn.h +++ b/lib/libasyn/asyn.h @@ -14,4 +14,6 @@ typedef struct _asynfd asynfd_t; +#undef IDLE + typedef enum state { IDLE, WAITING, PENDING } state_t; diff --git a/lib/libaudiodriver/audio_fw.c b/lib/libaudiodriver/audio_fw.c index 88d248094..6ff932c5d 100644 --- a/lib/libaudiodriver/audio_fw.c +++ b/lib/libaudiodriver/audio_fw.c @@ -933,7 +933,7 @@ static int init_buffers(sub_dev_t *sub_dev_ptr) } sub_dev_ptr->DmaPtr = sub_dev_ptr->DmaBuf; - i = sys_umap(SELF, D, + i = sys_umap(SELF, VM_D, (vir_bytes) sub_dev_ptr->DmaBuf, (phys_bytes) sizeof(sub_dev_ptr->DmaBuf), &(sub_dev_ptr->DmaPhys)); diff --git a/lib/libexec/exec_elf.c b/lib/libexec/exec_elf.c index 4f2c15759..3fc9f71c6 100644 --- a/lib/libexec/exec_elf.c +++ b/lib/libexec/exec_elf.c @@ -14,6 +14,7 @@ #include #include #include +#include /* For verbose logging */ #define ELF_DEBUG 0 @@ -59,16 +60,12 @@ static int elf_unpack(char *exec_hdr, { *hdr = (Elf_Ehdr *) exec_hdr; if(!elf_sane(*hdr)) { -#if ELF_DEBUG - printf("elf_sane failed\n"); -#endif + printf("elf_unpack: elf_sane failed\n"); return ENOEXEC; } *phdr = (Elf_Phdr *)(exec_hdr + (*hdr)->e_phoff); if(!elf_ph_sane(*phdr)) { -#if ELF_DEBUG - printf("elf_ph_sane failed\n"); -#endif + printf("elf_unpack: elf_ph_sane failed\n"); return ENOEXEC; } #if 0 @@ -77,98 +74,6 @@ static int elf_unpack(char *exec_hdr, return OK; } -int read_header_elf( - char *exec_hdr, /* executable header */ - int hdr_len, /* significant bytes in exec_hdr */ - vir_bytes *text_vaddr, /* text virtual address */ - phys_bytes *text_paddr, /* text physical address */ - vir_bytes *text_filebytes, /* text segment size (in the file) */ - vir_bytes *text_membytes, /* text segment size (in memory) */ - vir_bytes *data_vaddr, /* data virtual address */ - phys_bytes *data_paddr, /* data physical address */ - vir_bytes *data_filebytes, /* data segment size (in the file) */ - vir_bytes *data_membytes, /* data segment size (in memory) */ - vir_bytes *pc, /* program entry point (initial PC) */ - off_t *text_offset, /* file offset to text segment */ - off_t *data_offset /* file offset to data segment */ -) -{ - Elf_Ehdr *hdr = NULL; - Elf_Phdr *phdr = NULL; - unsigned long seg_filebytes, seg_membytes; - int e, i = 0; - - *text_vaddr = *text_paddr = 0; - *text_filebytes = *text_membytes = 0; - *data_vaddr = *data_paddr = 0; - *data_filebytes = *data_membytes = 0; - *pc = *text_offset = *data_offset = 0; - - if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) { -#if ELF_DEBUG - printf("elf_unpack failed\n"); -#endif - return e; - } - -#if ELF_DEBUG - printf("Program header file offset (phoff): %ld\n", hdr->e_phoff); - printf("Section header file offset (shoff): %ld\n", hdr->e_shoff); - printf("Program header entry size (phentsize): %d\n", hdr->e_phentsize); - printf("Program header entry num (phnum): %d\n", hdr->e_phnum); - printf("Section header entry size (shentsize): %d\n", hdr->e_shentsize); - printf("Section header entry num (shnum): %d\n", hdr->e_shnum); - printf("Section name strings index (shstrndx): %d\n", hdr->e_shstrndx); - printf("Entry Point: 0x%lx\n", hdr->e_entry); -#endif - - for (i = 0; i < hdr->e_phnum; i++) { - switch (phdr[i].p_type) { - case PT_LOAD: - if (phdr[i].p_memsz == 0) - break; - seg_filebytes = phdr[i].p_filesz; - seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - - trunc_page(phdr[i].p_vaddr)); - - if (hdr->e_entry >= phdr[i].p_vaddr && - hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) { - *text_vaddr = phdr[i].p_vaddr; - *text_paddr = phdr[i].p_paddr; - *text_filebytes = seg_filebytes; - *text_membytes = seg_membytes; - *pc = (vir_bytes)hdr->e_entry; - *text_offset = phdr[i].p_offset; - } else { - *data_vaddr = phdr[i].p_vaddr; - *data_paddr = phdr[i].p_paddr; - *data_filebytes = seg_filebytes; - *data_membytes = seg_membytes; - *data_offset = phdr[i].p_offset; - } - break; - default: - break; - } - } - -#if ELF_DEBUG - printf("Text vaddr: 0x%lx\n", *text_vaddr); - printf("Text paddr: 0x%lx\n", *text_paddr); - printf("Text filebytes: 0x%lx\n", *text_filebytes); - printf("Text membytes: 0x%lx\n", *text_membytes); - printf("Data vaddr: 0x%lx\n", *data_vaddr); - printf("Data paddr: 0x%lx\n", *data_paddr); - printf("Data filebyte: 0x%lx\n", *data_filebytes); - printf("Data membytes: 0x%lx\n", *data_membytes); - printf("PC: 0x%lx\n", *pc); - printf("Text offset: 0x%lx\n", *text_offset); - printf("Data offset: 0x%lx\n", *data_offset); -#endif - - return OK; -} - #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ @@ -243,8 +148,7 @@ int libexec_load_elf(struct exec_info *execi) } execi->stack_size = roundup(execi->stack_size, PAGE_SIZE); - execi->stack_high = VM_STACKTOP; - assert(!(VM_STACKTOP % PAGE_SIZE)); + execi->stack_high = rounddown(execi->stack_high, PAGE_SIZE); stacklow = execi->stack_high - execi->stack_size; assert(execi->copymem); @@ -311,6 +215,10 @@ int libexec_load_elf(struct exec_info *execi) return ENOMEM; } +#if ELF_DEBUG + printf("stack mmapped 0x%lx-0x%lx\n", stacklow, stacklow+execi->stack_size); +#endif + /* record entry point and lowest load vaddr for caller */ execi->pc = hdr->e_entry; execi->load_base = startv; diff --git a/lib/libexec/exec_general.c b/lib/libexec/exec_general.c index 1887c7f23..20d3ca9ee 100644 --- a/lib/libexec/exec_general.c +++ b/lib/libexec/exec_general.c @@ -49,6 +49,20 @@ int libexec_clear_sys_memset(struct exec_info *execi, off_t vaddr, size_t len) return sys_memset(execi->proc_e, 0, vaddr, len); } +int libexec_copy_memcpy(struct exec_info *execi, + off_t off, off_t vaddr, size_t len) +{ + assert(off + len <= execi->hdr_len); + memcpy((char *) vaddr, (char *) execi->hdr + off, len); + return OK; +} + +int libexec_clear_memset(struct exec_info *execi, off_t vaddr, size_t len) +{ + memset((char *) vaddr, 0, len); + return OK; +} + void libexec_patch_ptr(char stack[ARG_MAX], vir_bytes base) { /* When doing an exec(name, argv, envp) call, the user builds up a stack diff --git a/lib/libexec/libexec.h b/lib/libexec/libexec.h index 613839c60..5169c4b21 100644 --- a/lib/libexec/libexec.h +++ b/lib/libexec/libexec.h @@ -44,12 +44,6 @@ struct exec_info { int elf_has_interpreter(char *exec_hdr, int hdr_len, char *interp, int maxsz); int elf_phdr(char *exec_hdr, int hdr_len, vir_bytes *phdr); -int read_header_elf(char *exec_hdr, int hdr_len, - vir_bytes *text_vaddr, phys_bytes *text_paddr, - vir_bytes *text_filebytes, vir_bytes *text_membytes, - vir_bytes *data_vaddr, phys_bytes *data_paddr, - vir_bytes *data_filebytes, vir_bytes *data_membytes, - vir_bytes *pc, off_t *text_offset, off_t *data_offset); void libexec_patch_ptr(char stack[ARG_MAX], vir_bytes base); int libexec_pm_newexec(endpoint_t proc_e, struct exec_info *execi); @@ -57,6 +51,8 @@ int libexec_pm_newexec(endpoint_t proc_e, struct exec_info *execi); typedef int (*libexec_exec_loadfunc_t)(struct exec_info *execi); int libexec_load_elf(struct exec_info *execi); +int libexec_copy_memcpy(struct exec_info *execi, off_t offset, off_t vaddr, size_t len); +int libexec_clear_memset(struct exec_info *execi, off_t vaddr, size_t len); int libexec_alloc_mmap_prealloc(struct exec_info *execi, off_t vaddr, size_t len); int libexec_alloc_mmap_ondemand(struct exec_info *execi, off_t vaddr, size_t len); int libexec_clearproc_vm_procctl(struct exec_info *execi); diff --git a/lib/libminlib/i386/_cpufeature.c b/lib/libminlib/i386/_cpufeature.c index 7a9630efd..52d8db2dc 100644 --- a/lib/libminlib/i386/_cpufeature.c +++ b/lib/libminlib/i386/_cpufeature.c @@ -7,21 +7,15 @@ int _cpufeature(int cpufeature) { u32_t eax, ebx, ecx, edx; - int proc; eax = ebx = ecx = edx = 0; - proc = getprocessor(); - /* If processor supports CPUID and its CPUID supports enough - * parameters, retrieve EDX feature flags to test against. - */ - if(proc >= 586) { - eax = 0; + /* We assume >= pentium for cpuid */ + eax = 0; + _cpuid(&eax, &ebx, &ecx, &edx); + if(eax > 0) { + eax = 1; _cpuid(&eax, &ebx, &ecx, &edx); - if(eax > 0) { - eax = 1; - _cpuid(&eax, &ebx, &ecx, &edx); - } } switch(cpufeature) { diff --git a/lib/libsys/Makefile b/lib/libsys/Makefile index 1076178f4..9f91256a7 100644 --- a/lib/libsys/Makefile +++ b/lib/libsys/Makefile @@ -74,7 +74,6 @@ SRCS= \ sys_kill.c \ sys_mcontext.c \ sys_memset.c \ - sys_newmap.c \ sys_out.c \ sys_physcopy.c \ sys_privctl.c \ @@ -127,7 +126,7 @@ SRCS= \ vm_umap.c \ vm_yield_get_block.c \ vm_procctl.c \ - vprintf.c \ + vprintf.c .if ${MKCOVERAGE} != "no" SRCS+= gcov.c \ diff --git a/lib/libsys/alloc_util.c b/lib/libsys/alloc_util.c index 03db92f13..280598e76 100644 --- a/lib/libsys/alloc_util.c +++ b/lib/libsys/alloc_util.c @@ -6,21 +6,6 @@ #include #include -int sys_umap_data_fb(endpoint_t ep, vir_bytes buf, vir_bytes len, phys_bytes *phys) -{ - int r; - - if((r=sys_umap(ep, VM_D, buf, len, phys)) != OK) { - if(r != EINVAL) - return r; - r = sys_umap(ep, D, buf, len, phys); - } - - - return r; -} - - void *alloc_contig(size_t len, int flags, phys_bytes *phys) { vir_bytes buf; @@ -66,7 +51,7 @@ void *alloc_contig(size_t len, int flags, phys_bytes *phys) } /* Get physical address, if requested. */ - if(phys != NULL && sys_umap_data_fb(SELF, buf, len, phys) != OK) + if(phys != NULL && sys_umap(SELF, VM_D, buf, len, phys) != OK) panic("sys_umap_data_fb failed"); return (void *) buf; diff --git a/lib/libsys/env_get_prm.c b/lib/libsys/env_get_prm.c index da2031bee..24e577a7c 100644 --- a/lib/libsys/env_get_prm.c +++ b/lib/libsys/env_get_prm.c @@ -26,7 +26,7 @@ char *value; /* where to store value */ int max_len; /* maximum length of value */ { message m; - static char mon_params[128*sizeof(char *)]; /* copy parameters here */ + static char mon_params[MULTIBOOT_PARAM_BUF_SIZE]; /* copy parameters here */ char *key_value; int i, s; size_t keylen; diff --git a/lib/libsys/env_parse.c b/lib/libsys/env_parse.c index b48d763b5..8e93252cd 100644 --- a/lib/libsys/env_parse.c +++ b/lib/libsys/env_parse.c @@ -97,44 +97,17 @@ int env_memory_parse(mem_chunks, maxchunks) struct memory *mem_chunks; /* where to store the memory bits */ int maxchunks; /* how many were found */ { - int i, done = 0; - char *s; - struct memory *memp; - char memstr[100], *end; + static kinfo_t kinfo; + int mm; + + sys_getkinfo(&kinfo); /* Initialize everything to zero. */ - for (i = 0; i < maxchunks; i++) { - memp = &mem_chunks[i]; /* next mem chunk is stored here */ - memp->base = memp->size = 0; - } + memset(mem_chunks, 0, maxchunks*sizeof(*mem_chunks)); - /* 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. - */ - if(env_get_param("memory", memstr, sizeof(memstr)-1) != OK) - return -1; - s = memstr; - for (i = 0; i < maxchunks && !done; i++) { - phys_bytes base = 0, size = 0; - memp = &mem_chunks[i]; /* next mem chunk is stored here */ - if (*s != 0) { /* get fresh data, unless at end */ - - /* Read fresh base and expect colon as next char. */ - base = strtoul(s, &end, 0x10); /* get number */ - if (end != s && *end == ':') s = ++end; /* skip ':' */ - else *s=0; /* terminate, should not happen */ - - /* Read fresh size and expect comma or assume end. */ - size = strtoul(s, &end, 0x10); /* get number */ - if (end != s && *end == ',') s = ++end; /* skip ',' */ - else done = 1; - } - if (base + size <= base) continue; - memp->base = base; - memp->size = size; + for(mm = 0; mm < MAXMEMMAP; mm++) { + mem_chunks[mm].base = kinfo.memmap[mm].addr; + mem_chunks[mm].size = kinfo.memmap[mm].len; } return OK; diff --git a/lib/libsys/kputc.c b/lib/libsys/kputc.c index 2f6d7135a..9e7301272 100644 --- a/lib/libsys/kputc.c +++ b/lib/libsys/kputc.c @@ -26,6 +26,7 @@ void kputc(int c) if (c != 0) { /* Append a single character to the output buffer. */ - print_buf[buf_count++] = c; + print_buf[buf_count] = c; + buf_count++; } } diff --git a/lib/libsys/sef.c b/lib/libsys/sef.c index f1bc4eee8..c625ce1b7 100644 --- a/lib/libsys/sef.c +++ b/lib/libsys/sef.c @@ -84,7 +84,9 @@ void sef_startup() panic("RS unable to complete init: %d", r); } } - else { + else if(sef_self_endpoint == VM_PROC_NR) { + /* VM handles initialization by RS later */ + } else { message m; /* Wait for an initialization message from RS. We need this to learn the diff --git a/lib/libsys/sys_fork.c b/lib/libsys/sys_fork.c index f978f40eb..811e2301d 100644 --- a/lib/libsys/sys_fork.c +++ b/lib/libsys/sys_fork.c @@ -1,10 +1,9 @@ #include "syslib.h" -int sys_fork(parent, child, child_endpoint, map_ptr, flags, msgaddr) +int sys_fork(parent, child, child_endpoint, flags, msgaddr) endpoint_t parent; /* process doing the fork */ endpoint_t child; /* which proc has been created by the fork */ endpoint_t *child_endpoint; -struct mem_map *map_ptr; u32_t flags; vir_bytes *msgaddr; { @@ -15,7 +14,6 @@ vir_bytes *msgaddr; m.PR_ENDPT = parent; m.PR_SLOT = child; - m.PR_MEM_PTR = (char *) map_ptr; m.PR_FORK_FLAGS = flags; r = _kernel_call(SYS_FORK, &m); *child_endpoint = m.PR_ENDPT; diff --git a/lib/libsys/sys_newmap.c b/lib/libsys/sys_newmap.c deleted file mode 100644 index 764a703e1..000000000 --- a/lib/libsys/sys_newmap.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "syslib.h" - -int sys_newmap( -endpoint_t proc_ep, /* process whose map is to be changed */ -struct mem_map *ptr /* pointer to new map */ -) -{ -/* A process has been assigned a new memory map. Tell the kernel. */ - - message m; - - m.PR_ENDPT = proc_ep; - m.PR_MEM_PTR = (char *) ptr; - return(_kernel_call(SYS_NEWMAP, &m)); -} diff --git a/lib/libsys/sys_physcopy.c b/lib/libsys/sys_physcopy.c index 9c1dab179..3698332df 100644 --- a/lib/libsys/sys_physcopy.c +++ b/lib/libsys/sys_physcopy.c @@ -25,8 +25,8 @@ phys_bytes bytes; /* how many bytes */ /* provide backwards compatability arguments to old * kernels based on process id's; NONE <=> physical */ - copy_mess.CP_DST_SPACE_OBSOLETE = (dst_proc == NONE ? PHYS_SEG : D); - copy_mess.CP_SRC_SPACE_OBSOLETE = (src_proc == NONE ? PHYS_SEG : D); + copy_mess.CP_DST_SPACE_OBSOLETE = (dst_proc == NONE ? PHYS_SEG : D_OBSOLETE); + copy_mess.CP_SRC_SPACE_OBSOLETE = (src_proc == NONE ? PHYS_SEG : D_OBSOLETE); return(_kernel_call(SYS_PHYSCOPY, ©_mess)); } diff --git a/lib/libsys/sys_safecopy.c b/lib/libsys/sys_safecopy.c index bc2b6f781..4140b12a4 100644 --- a/lib/libsys/sys_safecopy.c +++ b/lib/libsys/sys_safecopy.c @@ -22,7 +22,7 @@ int sys_safecopyfrom(endpoint_t src_e, /* for older kernels that still need the 'seg' field * provide the right value. */ - copy_mess.SCP_SEG_OBSOLETE = D; + copy_mess.SCP_SEG_OBSOLETE = D_OBSOLETE; return(_kernel_call(SYS_SAFECOPYFROM, ©_mess)); @@ -47,7 +47,7 @@ int sys_safecopyto(endpoint_t dst_e, /* for older kernels that still need the 'seg' field * provide the right value. */ - copy_mess.SCP_SEG_OBSOLETE = D; + copy_mess.SCP_SEG_OBSOLETE = D_OBSOLETE; return(_kernel_call(SYS_SAFECOPYTO, ©_mess)); diff --git a/lib/libsys/sys_safemap.c b/lib/libsys/sys_safemap.c index 426b7d58a..e3d3d111f 100644 --- a/lib/libsys/sys_safemap.c +++ b/lib/libsys/sys_safemap.c @@ -23,7 +23,7 @@ int sys_safemap(endpoint_t grantor, cp_grant_id_t grant, copy_mess.SMAP_BYTES = bytes; copy_mess.SMAP_FLAG = writable; - copy_mess.SMAP_SEG_OBSOLETE = (void *) D; + copy_mess.SMAP_SEG_OBSOLETE = (void *) D_OBSOLETE; return(_kernel_call(SYS_SAFEMAP, ©_mess)); @@ -67,7 +67,7 @@ int sys_safeunmap(vir_bytes my_address) copy_mess.SMAP_ADDRESS = my_address; - copy_mess.SMAP_SEG_OBSOLETE = (void *) D; + copy_mess.SMAP_SEG_OBSOLETE = (void *) D_OBSOLETE; return(_kernel_call(SYS_SAFEUNMAP, ©_mess)); } diff --git a/lib/libsys/sys_vircopy.c b/lib/libsys/sys_vircopy.c index a9e57abb8..29e8d2c66 100644 --- a/lib/libsys/sys_vircopy.c +++ b/lib/libsys/sys_vircopy.c @@ -23,8 +23,8 @@ phys_bytes bytes; /* how many bytes */ copy_mess.CP_NR_BYTES = (long) bytes; /* backwards compatability D segs */ - copy_mess.CP_DST_SPACE_OBSOLETE = D; - copy_mess.CP_SRC_SPACE_OBSOLETE = D; + copy_mess.CP_DST_SPACE_OBSOLETE = D_OBSOLETE; + copy_mess.CP_SRC_SPACE_OBSOLETE = D_OBSOLETE; return(_kernel_call(SYS_VIRCOPY, ©_mess)); } diff --git a/lib/libsys/sys_vmctl.c b/lib/libsys/sys_vmctl.c index c0aef7fec..08951f65c 100644 --- a/lib/libsys/sys_vmctl.c +++ b/lib/libsys/sys_vmctl.c @@ -63,15 +63,6 @@ int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem, return r; } -int sys_vmctl_enable_paging(void * data) -{ - message m; - m.SVMCTL_WHO = SELF; - m.SVMCTL_PARAM = VMCTL_ENABLE_PAGING; - m.SVMCTL_VALUE = (u32_t) data; - return _kernel_call(SYS_VMCTL, &m); -} - int sys_vmctl_get_mapping(int index, phys_bytes *addr, phys_bytes *len, int *flags) { diff --git a/lib/libvassert/vassert.c b/lib/libvassert/vassert.c index b3a2893fd..695c5b10c 100644 --- a/lib/libvassert/vassert.c +++ b/lib/libvassert/vassert.c @@ -131,7 +131,7 @@ char VAssert_Init(void) { uint32 eax, ebx, ecx, edx; - VA page_address = (VA) &vassert_state.inReplay, ph; + VA page_address = (VA) &vassert_state.inReplay; if (!VAssert_IsInVM()) { return -1; } @@ -143,16 +143,7 @@ VAssert_Init(void) } #endif - /* vmware expects a linear address (or is simply forgetting - * to adjust the given address for segments) - */ - - if(sys_umap(SELF, D, page_address, 1, (phys_bytes *) &ph)) { - printf("VAssert_Init: sys_umap failed\n"); - return -1; - } - - libvassert_process_backdoor(CMD_SET_ADDRESS, ph, + libvassert_process_backdoor(CMD_SET_ADDRESS, page_address, MAGIC_PORT|(1<<16), &eax, &ebx, &ecx, &edx); return (eax != -1) ? 0 : -1; diff --git a/servers/init/Makefile b/servers/init/Makefile index 71b807834..95d47b394 100644 --- a/servers/init/Makefile +++ b/servers/init/Makefile @@ -8,6 +8,4 @@ MAN= BINDIR?= /usr/sbin -LDFLAGS+= -Wl,--section-start=.init=0x0 - .include diff --git a/servers/is/dmp.c b/servers/is/dmp.c index 1e8b65e89..a33b7d077 100644 --- a/servers/is/dmp.c +++ b/servers/is/dmp.c @@ -17,7 +17,6 @@ struct hook_entry { char *name; } hooks[] = { { F1, proctab_dmp, "Kernel process table" }, - { F2, memmap_dmp, "Process memory maps" }, { F3, image_dmp, "System image" }, { F4, privileges_dmp, "Process privileges" }, { F5, monparams_dmp, "Boot monitor parameters" }, diff --git a/servers/is/dmp_kernel.c b/servers/is/dmp_kernel.c index 77b98a05f..36f1116f5 100644 --- a/servers/is/dmp_kernel.c +++ b/servers/is/dmp_kernel.c @@ -45,7 +45,6 @@ static char *proc_name(int proc_nr); static char *s_traps_str(int flags); static char *s_flags_str(int flags); static char *p_rts_flags_str(int flags); -static char *boot_flags_str(int flags); /* Some global data that is shared among several dumping procedures. * Note that the process table copy has the same name as in the kernel @@ -92,7 +91,7 @@ void kmessages_dmp() *===========================================================================*/ void monparams_dmp() { - char val[1024]; + char val[MULTIBOOT_PARAM_BUF_SIZE]; char *e; int r; @@ -160,18 +159,6 @@ void irqtab_dmp() printf("\n"); } -/*===========================================================================* - * boot_flags_str * - *===========================================================================*/ -static char *boot_flags_str(int flags) -{ - static char str[10]; - str[0] = (flags & PROC_FULLVM) ? 'V' : '-'; - str[1] = '\0'; - - return str; -} - /*===========================================================================* * image_dmp * *===========================================================================*/ @@ -188,9 +175,7 @@ void image_dmp() printf("---name- -nr- flags -stack-\n"); for (m=0; mproc_name, ip->proc_nr, - boot_flags_str(ip->flags)); + printf("%8s %4d\n", ip->proc_name, ip->proc_nr); } printf("\n"); } @@ -215,15 +200,6 @@ void kenv_dmp() printf("Dump of kinfo structure.\n\n"); printf("Kernel info structure:\n"); - printf("- code_base: %5lu\n", kinfo.code_base); - printf("- code_size: %5lu\n", kinfo.code_size); - printf("- data_base: %5lu\n", kinfo.data_base); - printf("- data_size: %5lu\n", kinfo.data_size); - printf("- proc_addr: %5lu\n", kinfo.proc_addr); - printf("- bootdev_base: %5lu\n", kinfo.bootdev_base); - printf("- bootdev_size: %5lu\n", kinfo.bootdev_size); - printf("- ramdev_base: %5lu\n", kinfo.ramdev_base); - printf("- ramdev_size: %5lu\n", kinfo.ramdev_size); printf("- nr_procs: %3u\n", kinfo.nr_procs); printf("- nr_tasks: %3u\n", kinfo.nr_tasks); printf("- release: %.6s\n", kinfo.release); @@ -341,7 +317,6 @@ void proctab_dmp() register struct proc *rp; static struct proc *oldrp = BEG_PROC_ADDR; int r; - phys_clicks text, data, size; /* First obtain a fresh copy of the current process table. */ if ((r = sys_getproctab(proc)) != OK) { @@ -352,10 +327,6 @@ void proctab_dmp() printf("\n-nr-----gen---endpoint-name--- -prior-quant- -user----sys-rtsflags-from/to-\n"); PROCLOOP(rp, oldrp) - text = rp->p_memmap[T].mem_phys; - data = rp->p_memmap[D].mem_phys; - size = rp->p_memmap[T].mem_len - + ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len) - data); printf(" %5d %10d ", _ENDPOINT_G(rp->p_endpoint), rp->p_endpoint); printf("%-8.8s %5u %5u %6lu %6lu ", rp->p_name, @@ -393,38 +364,6 @@ void procstack_dmp() } } -/*===========================================================================* - * memmap_dmp * - *===========================================================================*/ -void memmap_dmp() -{ - register struct proc *rp; - static struct proc *oldrp = proc; - int r; - phys_clicks size; - - /* First obtain a fresh copy of the current process table. */ - if ((r = sys_getproctab(proc)) != OK) { - printf("IS: warning: couldn't get copy of process table: %d\n", r); - return; - } - - printf("\n-nr/name--- --pc-- --sp-- -text---- -data---- -stack--- -cr3-\n"); - PROCLOOP(rp, oldrp) - size = rp->p_memmap[T].mem_len - + ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len) - - rp->p_memmap[D].mem_phys); - printf("%-7.7s%7lx %8lx %4x %4x %4x %4x %5x %5x %8u\n", - rp->p_name, - (unsigned long) rp->p_reg.pc, - (unsigned long) rp->p_reg.sp, - rp->p_memmap[T].mem_phys, rp->p_memmap[T].mem_len, - rp->p_memmap[D].mem_phys, rp->p_memmap[D].mem_len, - rp->p_memmap[S].mem_phys, rp->p_memmap[S].mem_len, - rp->p_seg.p_cr3); - } -} - /*===========================================================================* * proc_name * *===========================================================================*/ diff --git a/servers/is/dmp_vm.c b/servers/is/dmp_vm.c index 6d61ac556..ad43b9a24 100644 --- a/servers/is/dmp_vm.c +++ b/servers/is/dmp_vm.c @@ -12,14 +12,12 @@ static void print_region(struct vm_region_info *vri, int *n) { static int vri_count, vri_prev_set; static struct vm_region_info vri_prev; - char c; int is_repeat; /* part of a contiguous identical run? */ is_repeat = vri && vri_prev_set && - vri->vri_seg == vri_prev.vri_seg && vri->vri_prot == vri_prev.vri_prot && vri->vri_flags == vri_prev.vri_flags && vri->vri_length == vri_prev.vri_length && @@ -44,14 +42,7 @@ static void print_region(struct vm_region_info *vri, int *n) /* NULL indicates the end of a list of mappings, nothing else to do */ if (!vri) return; - /* first in a run, print all info */ - switch (vri->vri_seg) { - case T: c = 'T'; break; - case D: c = 'D'; break; - default: c = '?'; - } - - printf(" %c %08lx-%08lx %c%c%c %c (%lu kB)\n", c, vri->vri_addr, + printf(" %08lx-%08lx %c%c%c %c (%lu kB)\n", vri->vri_addr, vri->vri_addr + vri->vri_length, (vri->vri_prot & PROT_READ) ? 'r' : '-', (vri->vri_prot & PROT_WRITE) ? 'w' : '-', diff --git a/servers/is/proto.h b/servers/is/proto.h index 1dd800585..bc8a8c590 100644 --- a/servers/is/proto.h +++ b/servers/is/proto.h @@ -12,7 +12,6 @@ void vm_dmp(void); /* dmp_kernel.c */ void proctab_dmp(void); void procstack_dmp(void); -void memmap_dmp(void); void privileges_dmp(void); void image_dmp(void); void irqtab_dmp(void); diff --git a/servers/pm/exec.c b/servers/pm/exec.c index c29b5ec26..d000fc708 100644 --- a/servers/pm/exec.c +++ b/servers/pm/exec.c @@ -12,7 +12,7 @@ * * The entry points into this file are: * do_exec: perform the EXEC system call - * do_exec_newmem: allocate new memory map for a process that tries to exec + * do_newexec: handle PM part of exec call after VFS * do_execrestart: finish the special exec call for RS * exec_restart: finish a regular exec call */ @@ -73,14 +73,14 @@ int do_newexec() proc_e= m_in.EXC_NM_PROC; if (pm_isokendpt(proc_e, &proc_n) != OK) { - panic("do_exec_newmem: got bad endpoint: %d", proc_e); + panic("do_newexec: got bad endpoint: %d", proc_e); } rmp= &mproc[proc_n]; ptr= m_in.EXC_NM_PTR; r= sys_datacopy(who_e, (vir_bytes)ptr, SELF, (vir_bytes)&args, sizeof(args)); if (r != OK) - panic("do_exec_newmem: sys_datacopy failed: %d", r); + panic("do_newexec: sys_datacopy failed: %d", r); allow_setuid = 0; /* Do not allow setuid execution */ rmp->mp_flags &= ~TAINTED; /* By default not tainted */ diff --git a/servers/pm/glo.h b/servers/pm/glo.h index d512e0f18..ef483e450 100644 --- a/servers/pm/glo.h +++ b/servers/pm/glo.h @@ -7,7 +7,7 @@ /* Global variables. */ EXTERN struct mproc *mp; /* ptr to 'mproc' slot of current process */ EXTERN int procs_in_use; /* how many processes are marked as IN_USE */ -EXTERN char monitor_params[128*sizeof(char *)]; /* boot monitor parameters */ +EXTERN char monitor_params[MULTIBOOT_PARAM_BUF_SIZE]; EXTERN struct kinfo kinfo; /* kernel information */ /* Misc.c */ @@ -25,7 +25,6 @@ EXTERN sigset_t noign_sset; /* which signals cannot be ignored */ EXTERN u32_t system_hz; /* System clock frequency. */ EXTERN int abort_flag; -EXTERN char monitor_code[256]; EXTERN struct machine machine; /* machine info */ #ifdef CONFIG_SMP diff --git a/servers/pm/main.c b/servers/pm/main.c index ac140b92a..72750f4b8 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -399,16 +399,11 @@ static void handle_vfs_reply() * Handle its reply first. */ if (call_nr == PM_REBOOT_REPLY) { - vir_bytes code_addr; - size_t code_size; - /* Ask the kernel to abort. All system services, including * the PM, will get a HARD_STOP notification. Await the * notification in the main loop. */ - code_addr = (vir_bytes) monitor_code; - code_size = strlen(monitor_code) + 1; - sys_abort(abort_flag, PM_PROC_NR, code_addr, code_size); + sys_abort(RBT_DEFAULT); return; } diff --git a/servers/pm/misc.c b/servers/pm/misc.c index 705c1088d..c052a7d83 100644 --- a/servers/pm/misc.c +++ b/servers/pm/misc.c @@ -294,17 +294,6 @@ int do_reboot() /* See how the system should be aborted. */ abort_flag = (unsigned) m_in.reboot_flag; if (abort_flag >= RBT_INVALID) return(EINVAL); - if (RBT_MONITOR == abort_flag) { - int r; - if(m_in.reboot_strlen >= sizeof(monitor_code)) - return EINVAL; - if((r = sys_datacopy(who_e, (vir_bytes) m_in.reboot_code, - SELF, (vir_bytes) monitor_code, m_in.reboot_strlen)) != OK) - return r; - monitor_code[m_in.reboot_strlen] = '\0'; - } - else - monitor_code[0] = '\0'; /* Order matters here. When VFS is told to reboot, it exits all its * processes, and then would be confused if they're exited again by diff --git a/servers/procfs/pid.c b/servers/procfs/pid.c index a07032994..faa984aaa 100644 --- a/servers/procfs/pid.c +++ b/servers/procfs/pid.c @@ -112,18 +112,8 @@ static void pid_psinfo(int i) memset(&vui, 0, sizeof(vui)); if (!is_zombie(i)) { - /* We don't care if this fails. It may still return - * zero memory usage for processes that don't have a - * pagetable, though. Look at vui_total instead. - */ + /* We don't care if this fails. */ (void) vm_info_usage(proc[i].p_endpoint, &vui); - - if (vui.vui_total == 0L) { - vui.vui_total = - (proc[i].p_memmap[T].mem_len + - proc[i].p_memmap[D].mem_len) << - CLICK_SHIFT; - } } if (mproc[pi].mp_flags & PAUSED) @@ -340,7 +330,7 @@ static int dump_regions(int slot) */ struct vm_region_info vri[MAX_VRI_COUNT]; vir_bytes next; - int i, r, seg, count; + int i, r, count; count = 0; next = 0; @@ -356,15 +346,8 @@ static int dump_regions(int slot) break; for (i = 0; i < r; i++) { - switch (vri[i].vri_seg) { - case T: seg = 'T'; break; - case D: seg = 'D'; break; - default: seg = '?'; break; - } - - buf_printf("%c %08lx-%08lx %c%c%c %c\n", - seg, vri[i].vri_addr, - vri[i].vri_addr + vri[i].vri_length, + buf_printf("%08lx-%08lx %c%c%c %c\n", + vri[i].vri_addr, vri[i].vri_addr + vri[i].vri_length, (vri[i].vri_prot & PROT_READ) ? 'r' : '-', (vri[i].vri_prot & PROT_WRITE) ? 'w' : '-', (vri[i].vri_prot & PROT_EXEC) ? 'x' : '-', @@ -377,26 +360,6 @@ static int dump_regions(int slot) return count; } -/*===========================================================================* - * dump_segments * - *===========================================================================*/ -static void dump_segments(int slot) -{ - /* Print the memory segments of a process. - */ - int i; - - for (i = 0; i < NR_LOCAL_SEGS; i++) { - buf_printf("%c %08lx-%08lx %s -\n", - i == T ? 'T' : 'D', - proc[slot].p_memmap[i].mem_vir << CLICK_SHIFT, - (proc[slot].p_memmap[i].mem_vir + - proc[slot].p_memmap[i].mem_len) << CLICK_SHIFT, - (i == T) ? "r-x" : - (proc[slot].p_memmap[T].mem_len == 0) ? "rwx" : "rw-"); - } -} - /*===========================================================================* * pid_map * *===========================================================================*/ @@ -415,10 +378,4 @@ static void pid_map(int slot) if (dump_regions(slot) != 0) return; } - - /* For kernel tasks, or for processes that have no regions according to - * VM, we assume they are not using virtual memory, and we print their - * segments instead. - */ - dump_segments(slot); } diff --git a/servers/rs/const.h b/servers/rs/const.h index 87733ef6e..4df7f5b96 100644 --- a/servers/rs/const.h +++ b/servers/rs/const.h @@ -68,7 +68,7 @@ #define SRV_SF (SF_CORE_SRV) /* system services */ #define SRVR_SF (SRV_SF | SF_NEED_REPL) /* services needing a replica */ #define DSRV_SF (0) /* dynamic system services */ -#define VM_SF (SRVR_SF | SF_SYNCH_BOOT) /* vm */ +#define VM_SF (SRVR_SF) /* vm */ /* Define device flags for the various process types. */ #define SRV_DF (DRV_FORCED) /* system services */ diff --git a/servers/rs/exec.c b/servers/rs/exec.c index 1c3117c92..bb9d2b822 100644 --- a/servers/rs/exec.c +++ b/servers/rs/exec.c @@ -9,6 +9,7 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, static int exec_restart(int proc_e, int result, vir_bytes pc); static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes); +static int exec_restart(int proc_e, int result, vir_bytes pc); /* Array of loaders for different object formats */ static struct exec_loaders { @@ -119,6 +120,7 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, memset(&execi, 0, sizeof(execi)); + execi.stack_high = kinfo.user_sp; execi.stack_size = DEFAULT_STACK_LIMIT; execi.proc_e = proc_e; execi.hdr = exec; diff --git a/servers/rs/glo.h b/servers/rs/glo.h index 4c883ad21..d34a4b7eb 100644 --- a/servers/rs/glo.h +++ b/servers/rs/glo.h @@ -52,5 +52,7 @@ EXTERN unsigned system_hz; EXTERN struct machine machine; /* machine info */ +EXTERN struct kinfo kinfo; /* kernel information */ + #endif /* RS_GLO_H */ diff --git a/servers/rs/main.c b/servers/rs/main.c index f7e0e910c..a4c070b43 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -49,6 +49,9 @@ int main(void) if (OK != (s=sys_getmachine(&machine))) panic("couldn't get machine info: %d", s); + if (OK != (s=sys_getkinfo(&kinfo))) + panic("couldn't get kernel kinfo: %d", s); + /* Main loop - get work and do it, forever. */ while (TRUE) { @@ -272,8 +275,11 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) fill_call_mask(calls, NR_SYS_CALLS, rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE); - /* Set the privilege structure. */ - if(boot_image_priv->endpoint != RS_PROC_NR) { + /* Set the privilege structure. RS and VM are exceptions and are already + * running. + */ + if(boot_image_priv->endpoint != RS_PROC_NR && + boot_image_priv->endpoint != VM_PROC_NR) { if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv))) != OK) { panic("unable to set privilege structure: %d", s); @@ -352,10 +358,11 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; - /* RS is already running as we speak. */ - if(boot_image_priv->endpoint == RS_PROC_NR) { + /* RS/VM are already running as we speak. */ + if(boot_image_priv->endpoint == RS_PROC_NR || + boot_image_priv->endpoint == VM_PROC_NR) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { - panic("unable to initialize RS: %d", s); + panic("unable to initialize %d: %d", boot_image_priv->endpoint, s); } continue; } @@ -422,7 +429,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) panic("couldn't set alarm: %d", s); #if USE_LIVEUPDATE - /* Now create a new RS instance with a private page table and let the current + /* Now create a new RS instance and let the current * instance live update into the replica. Clone RS' own slot first. */ rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; diff --git a/servers/rs/manager.c b/servers/rs/manager.c index ebf1c28fc..13ebb4b41 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -1018,7 +1018,8 @@ void terminate_service(struct rproc *rp) if (rp->r_flags & RS_EXITING) { /* If a core system service is exiting, we are in trouble. */ if (rp->r_pub->sys_flags & SF_CORE_SRV && !shutting_down) { - panic("core system service died: %s", srv_to_string(rp)); + printf("core system service died: %s\n", srv_to_string(rp)); + _exit(1); } /* See if a late reply has to be sent. */ diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 3e490777f..d4f933ace 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -216,6 +216,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, /* passed from exec() libc code */ execi.userflags = user_exec_flags; + execi.args.stack_high = kinfo.user_sp; execi.args.stack_size = DEFAULT_STACK_LIMIT; okendpt(proc_e, &slot); @@ -617,15 +618,15 @@ static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t s if (off + seg_bytes > LONG_MAX) return(EIO); if ((unsigned long) vp->v_size < off+seg_bytes) return(EIO); - if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, - execi->proc_e, (char*)seg_addr, seg_bytes, - &new_pos, &cum_io)) != OK) { - printf("VFS: read_seg: req_readwrite failed (data)\n"); - return(r); - } + if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, + execi->proc_e, (char*)seg_addr, seg_bytes, + &new_pos, &cum_io)) != OK) { + printf("VFS: read_seg: req_readwrite failed (data)\n"); + return(r); + } - if (r == OK && cum_io != seg_bytes) - printf("VFS: read_seg segment has not been read properly\n"); + if (r == OK && cum_io != seg_bytes) + printf("VFS: read_seg segment has not been read properly\n"); return(r); } diff --git a/servers/vfs/glo.h b/servers/vfs/glo.h index ac35c6d94..dd1b6add1 100644 --- a/servers/vfs/glo.h +++ b/servers/vfs/glo.h @@ -52,4 +52,6 @@ extern int(*call_vec[]) (void); extern int(*pfs_call_vec[]) (void); extern char mode_map[]; /* mapping from O_ACCMODE mask to R_BIT/W_BIT flags */ +EXTERN struct kinfo kinfo; /* kernel information */ + #endif diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 04858e8a3..63d434a18 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -79,6 +79,9 @@ int main(void) printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS); + if (OK != (sys_getkinfo(&kinfo))) + panic("couldn't get kernel kinfo"); + /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { yield_all(); /* let other threads run */ diff --git a/servers/vfs/table.c b/servers/vfs/table.c index cd4c3e7ba..8371e3498 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -115,7 +115,7 @@ int (*call_vec[])(void) = { no_sys, /* 97 = unused */ no_sys, /* 98 = (sprofile) */ no_sys, /* 99 = (cprofile) */ - no_sys, /* 100 = (exec_newmem) */ + no_sys, /* 100 = (newexec) */ no_sys, /* 101 = (srv_fork) */ no_sys, /* 102 = (exec_restart) */ no_sys, /* 103 = unused */ diff --git a/servers/vm/Makefile b/servers/vm/Makefile index 993af5bc9..cfe24c038 100644 --- a/servers/vm/Makefile +++ b/servers/vm/Makefile @@ -2,12 +2,12 @@ .include PROG= vm -SRCS= main.c alloc.c utility.c exec.c exit.c fork.c break.c \ +SRCS= main.c alloc.c utility.c exit.c fork.c break.c \ signal.c mmap.c slaballoc.c region.c pagefaults.c addravl.c \ physravl.c rs.c queryexit.c yieldedavl.c regionavl.c DPADD+= ${LIBSYS} -LDADD+= -lsys +LDADD+= -lsys -lexec MAN= diff --git a/servers/vm/alloc.c b/servers/vm/alloc.c index 68a5c11e6..8a7108308 100644 --- a/servers/vm/alloc.c +++ b/servers/vm/alloc.c @@ -358,7 +358,7 @@ struct memory *chunks; /* list of free memory chunks */ } #if SANITYCHECKS -static void sanitycheck(void) +void mem_sanitycheck(char *file, int line) { pagerange_t *p, *prevp = NULL; addr_iter iter; @@ -368,8 +368,10 @@ static void sanitycheck(void) assert(p->size > 0); if(prevp) { assert(prevp->addr < p->addr); - assert(prevp->addr + p->addr < p->addr); + assert(prevp->addr + prevp->size < p->addr); } + usedpages_add(p->addr * VM_PAGE_SIZE, p->size * VM_PAGE_SIZE); + prevp = p; addr_incr_iter(&iter); } } @@ -383,9 +385,7 @@ void memstats(int *nodes, int *pages, int *largest) *nodes = 0; *pages = 0; *largest = 0; -#if SANITYCHECKS - sanitycheck(); -#endif + while((p=addr_get_iter(&iter))) { SLABSANE(p); (*nodes)++; @@ -424,7 +424,6 @@ static phys_bytes alloc_pages(int pages, int memflags, phys_bytes *len) #endif memstats(&firstnodes, &firstpages, &largest); - sanitycheck(); wantnodes = firstnodes; wantpages = firstpages - pages; #endif @@ -513,7 +512,6 @@ static phys_bytes alloc_pages(int pages, int memflags, phys_bytes *len) #if SANITYCHECKS memstats(&finalnodes, &finalpages, &largest); - sanitycheck(); assert(finalnodes == wantnodes); assert(finalpages == wantpages); @@ -534,7 +532,6 @@ static void free_pages(phys_bytes pageno, int npages) int finalnodes, finalpages, largest; memstats(&firstnodes, &firstpages, &largest); - sanitycheck(); wantnodes = firstnodes; wantpages = firstpages + npages; @@ -561,7 +558,6 @@ static void free_pages(phys_bytes pageno, int npages) wantnodes = firstnodes; wantpages = firstpages + npages; - sanitycheck(); #endif assert(npages > 0); USE(pr, pr->addr = pageno; @@ -593,7 +589,6 @@ static void free_pages(phys_bytes pageno, int npages) #if SANITYCHECKS memstats(&finalnodes, &finalpages, &largest); - sanitycheck(); assert(finalnodes == wantnodes); assert(finalpages == wantpages); @@ -817,7 +812,6 @@ void usedpages_reset(void) *===========================================================================*/ int usedpages_add_f(phys_bytes addr, phys_bytes len, char *file, int line) { - pagerange_t *pr; u32_t pagestart, pages; if(!incheck) @@ -836,7 +830,6 @@ int usedpages_add_f(phys_bytes addr, phys_bytes len, char *file, int line) assert(pagestart < MAXPAGES); thisaddr = pagestart * VM_PAGE_SIZE; if(GET_BIT(pagemap, pagestart)) { - int i; printf("%s:%d: usedpages_add: addr 0x%lx reused.\n", file, line, thisaddr); return EFAULT; diff --git a/servers/vm/arch/i386/Makefile.inc b/servers/vm/arch/i386/Makefile.inc index 530df1a1f..f3d71c80b 100644 --- a/servers/vm/arch/i386/Makefile.inc +++ b/servers/vm/arch/i386/Makefile.inc @@ -2,4 +2,4 @@ #Arch-specific sources .PATH: ${.CURDIR}/arch/${MACHINE_ARCH} -SRCS+= vm.c pagetable.c #util.S +SRCS+= pagetable.c #util.S diff --git a/servers/vm/arch/i386/arch_vmproc.h b/servers/vm/arch/i386/arch_vmproc.h deleted file mode 100644 index 455e167e9..000000000 --- a/servers/vm/arch/i386/arch_vmproc.h +++ /dev/null @@ -1,21 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include - -struct vm_arch { - struct mem_map vm_seg[NR_LOCAL_SEGS]; /* text, data, stack */ - - /* vm_data_top points to top of data address space, as visible - * from user-space, in bytes. - * for segments processes this is the same - * as the top of vm_seg[S] segment. for paged processes this - * can be much higher (so more memory is available above the - * stack). - */ - u32_t vm_data_top; /* virtual process space in bytes */ -}; diff --git a/servers/vm/arch/i386/memory.h b/servers/vm/arch/i386/memory.h index 6d84440cf..d72de15bc 100644 --- a/servers/vm/arch/i386/memory.h +++ b/servers/vm/arch/i386/memory.h @@ -1,23 +1,12 @@ #include /* And what is the highest addressable piece of memory, when in paged - * mode? Some data for kernel and stack are subtracted from this, the - * final results stored in bytes in arch.vm_data_top. + * mode? */ -#define VM_DATATOP 0xFFFFF000 +#define VM_DATATOP kernel_boot_info.user_end +#define VM_STACKTOP kernel_boot_info.user_sp #define SLAB_PAGESIZE I386_PAGE_SIZE #define VM_PAGE_SIZE I386_PAGE_SIZE -/* Where do processes start in linear (i.e. page table) memory? */ -#define VM_PROCSTART (I386_BIG_PAGE_SIZE*100) - #define CLICKSPERPAGE (I386_PAGE_SIZE/CLICK_SIZE) - -/* Where is the kernel? */ -#define KERNEL_TEXT CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[T].mem_phys) -#define KERNEL_TEXT_LEN CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[T].mem_len) -#define KERNEL_DATA CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[D].mem_phys) -#define KERNEL_DATA_LEN CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[D].mem_len \ - + vmproc[VMP_SYSTEM].vm_arch.vm_seg[S].mem_len) - diff --git a/servers/vm/arch/i386/pagetable.c b/servers/vm/arch/i386/pagetable.c index 73f930ae6..1fc4e2fc8 100644 --- a/servers/vm/arch/i386/pagetable.c +++ b/servers/vm/arch/i386/pagetable.c @@ -36,15 +36,13 @@ #include "memory.h" -/* Free PDE slots we tell kernel about */ -#define FREE_PDES 2 -static int first_free_pde = -1; - /* PDE used to map in kernel, kernel physical address. */ -static int id_map_high_pde = -1, pagedir_pde = -1; +static int pagedir_pde = -1; static u32_t global_bit = 0, pagedir_pde_val; -static int proc_pde = 0; +static multiboot_module_t *kern_mb_mod = NULL; +static size_t kern_size = 0; +static int kern_start_pde = -1; /* 4MB page size available in hardware? */ static int bigpage_ok = 0; @@ -56,7 +54,7 @@ struct vmproc *vmprocess = &vmproc[VM_PROC_NR]; * circular dependency on allocating memory and writing it into VM's * page table. */ -#define SPAREPAGES 25 +#define SPAREPAGES 15 int missing_spares = SPAREPAGES; static struct { void *page; @@ -67,7 +65,7 @@ static struct { static struct { phys_bytes phys_addr; /* Physical addr. */ phys_bytes len; /* Length in bytes. */ - vir_bytes lin_addr; /* Offset in page table. */ + vir_bytes vir_addr; /* Offset in page table. */ int flags; } kern_mappings[MAX_KERNMAPPINGS]; int kernmappings = 0; @@ -83,19 +81,13 @@ int kernmappings = 0; #error CLICK_SIZE must be page size. #endif -/* Bytes of virtual address space one pde controls. */ -#define BYTESPERPDE (I386_VM_PT_ENTRIES * I386_PAGE_SIZE) - -/* Nevertheless, introduce these macros to make the code readable. */ -#define CLICK2PAGE(c) ((c) / CLICKSPERPAGE) - /* Page table that contains pointers to all page directories. */ phys_bytes page_directories_phys; u32_t *page_directories = NULL; #define STATIC_SPAREPAGES 10 -static char static_sparepages[I386_PAGE_SIZE*STATIC_SPAREPAGES + I386_PAGE_SIZE]; +static char static_sparepages[I386_PAGE_SIZE*STATIC_SPAREPAGES + I386_PAGE_SIZE] __aligned(I386_PAGE_SIZE); #if SANITYCHECKS /*===========================================================================* @@ -104,7 +96,6 @@ static char static_sparepages[I386_PAGE_SIZE*STATIC_SPAREPAGES + I386_PAGE_SIZE] void pt_sanitycheck(pt_t *pt, char *file, int line) { /* Basic pt sanity check. */ - int i; int slot; MYASSERT(pt); @@ -121,37 +112,24 @@ void pt_sanitycheck(pt_t *pt, char *file, int line) } MYASSERT(usedpages_add(pt->pt_dir_phys, I386_PAGE_SIZE) == OK); - - for(i = proc_pde; i < I386_VM_DIR_ENTRIES; i++) { - if(pt->pt_pt[i]) { - int pte; - MYASSERT(vm_addrok(pt->pt_pt[i], 1)); - if(!(pt->pt_dir[i] & I386_VM_PRESENT)) { - printf("slot %d: pt->pt_pt[%d] = %p, but pt_dir entry 0x%lx\n", - slot, i, pt->pt_pt[i], pt->pt_dir[i]); - } - MYASSERT(pt->pt_dir[i] & I386_VM_PRESENT); - MYASSERT(usedpages_add(I386_VM_PFA(pt->pt_dir[i]), - I386_PAGE_SIZE) == OK); - } else { - MYASSERT(!(pt->pt_dir[i] & I386_VM_PRESENT)); - } - } } #endif /*===========================================================================* * findhole * *===========================================================================*/ -static u32_t findhole(pt_t *pt, u32_t vmin, u32_t vmax) +static u32_t findhole(void) { -/* Find a space in the virtual address space of pageteble 'pt', - * between page-aligned BYTE offsets vmin and vmax, to fit - * a page in. Return byte offset. - */ +/* Find a space in the virtual address space of VM. */ u32_t curv; int pde = 0, try_restart; static u32_t lastv = 0; + pt_t *pt = &vmprocess->vm_pt; + extern char _end; + vir_bytes vmin, vmax; + + vmin = (vir_bytes) (&_end) & I386_VM_ADDR_MASK; /* marks end of VM BSS */ + vmax = VM_STACKTOP; /* Input sanity check. */ assert(vmin + I386_PAGE_SIZE >= vmin); @@ -205,18 +183,20 @@ static u32_t findhole(pt_t *pt, u32_t vmin, u32_t vmax) static void vm_freepages(vir_bytes vir, vir_bytes phys, int pages, int reason) { assert(reason >= 0 && reason < VMP_CATEGORIES); - if(vir >= vmprocess->vm_stacktop) { - assert(!(vir % I386_PAGE_SIZE)); - assert(!(phys % I386_PAGE_SIZE)); - free_mem(ABS2CLICK(phys), pages); - if(pt_writemap(vmprocess, &vmprocess->vm_pt, arch_vir2map(vmprocess, vir), - MAP_NONE, pages*I386_PAGE_SIZE, 0, WMF_OVERWRITE) != OK) - panic("vm_freepages: pt_writemap failed"); - } else { - printf("VM: vm_freepages not freeing VM heap pages (%d)\n", - pages); + assert(!(vir % I386_PAGE_SIZE)); + assert(!(phys % I386_PAGE_SIZE)); + extern char _end; + + if(vir < (vir_bytes) &_end) { + printf("VM: not freeing static page\n"); + return; } + free_mem(ABS2CLICK(phys), pages); + if(pt_writemap(vmprocess, &vmprocess->vm_pt, vir, + MAP_NONE, pages*I386_PAGE_SIZE, 0, WMF_OVERWRITE) != OK) + panic("vm_freepages: pt_writemap failed"); + #if SANITYCHECKS /* If SANITYCHECKS are on, flush tlb so accessing freed pages is * always trapped, also if not in tlb. @@ -295,7 +275,7 @@ void *vm_allocpage(phys_bytes *phys, int reason) assert(level >= 1); assert(level <= 2); - if(level > 1 || !(vmprocess->vm_flags & VMF_HASPT) || !meminit_done) { + if(level > 1 || !meminit_done) { void *s; s=vm_getsparepage(phys); level--; @@ -309,8 +289,7 @@ void *vm_allocpage(phys_bytes *phys, int reason) /* VM does have a pagetable, so get a page and map it in there. * Where in our virtual address space can we put it? */ - loc = findhole(pt, arch_vir2map(vmprocess, vmprocess->vm_stacktop), - vmprocess->vm_arch.vm_data_top); + loc = findhole(); if(loc == NO_MEM) { level--; printf("VM: vm_allocpage: findhole failed\n"); @@ -344,7 +323,7 @@ void *vm_allocpage(phys_bytes *phys, int reason) level--; /* Return user-space-ready pointer to it. */ - ret = (void *) arch_map2vir(vmprocess, loc); + ret = (void *) loc; return ret; } @@ -355,13 +334,12 @@ void *vm_allocpage(phys_bytes *phys, int reason) void vm_pagelock(void *vir, int lockflag) { /* Mark a page allocated by vm_allocpage() unwritable, i.e. only for VM. */ - vir_bytes m; + vir_bytes m = (vir_bytes) vir; int r; u32_t flags = I386_VM_PRESENT | I386_VM_USER; pt_t *pt; pt = &vmprocess->vm_pt; - m = arch_vir2map(vmprocess, (vir_bytes) vir); assert(!(m % I386_PAGE_SIZE)); @@ -386,15 +364,9 @@ void vm_pagelock(void *vir, int lockflag) *===========================================================================*/ int vm_addrok(void *vir, int writeflag) { -/* Mark a page allocated by vm_allocpage() unwritable, i.e. only for VM. */ pt_t *pt = &vmprocess->vm_pt; int pde, pte; - vir_bytes v = arch_vir2map(vmprocess, (vir_bytes) vir); - - /* No PT yet? Don't bother looking. */ - if(!(vmprocess->vm_flags & VMF_HASPT)) { - return 1; - } + vir_bytes v = (vir_bytes) vir; pde = I386_VM_PDE(v); pte = I386_VM_PTE(v); @@ -471,8 +443,8 @@ int pt_ptalloc_in_range(pt_t *pt, vir_bytes start, vir_bytes end, /* Allocate all the page tables in the range specified. */ int pde, first_pde, last_pde; - first_pde = start ? I386_VM_PDE(start) : proc_pde; - last_pde = end ? I386_VM_PDE(end) : I386_VM_DIR_ENTRIES - 1; + first_pde = I386_VM_PDE(start); + last_pde = I386_VM_PDE(end-1); assert(first_pde >= 0); assert(last_pde < I386_VM_DIR_ENTRIES); @@ -498,6 +470,7 @@ int pt_ptalloc_in_range(pt_t *pt, vir_bytes start, vir_bytes end, return r; } } + assert(pt->pt_dir[pde]); assert(pt->pt_dir[pde] & I386_VM_PRESENT); } @@ -549,7 +522,7 @@ int pt_map_in_range(struct vmproc *src_vmp, struct vmproc *dst_vmp, end = end ? end : VM_DATATOP; assert(start % I386_PAGE_SIZE == 0); assert(end % I386_PAGE_SIZE == 0); - assert(I386_VM_PDE(start) >= proc_pde && start <= end); + assert(I386_VM_PDE(start) >= 0 && start <= end); assert(I386_VM_PDE(end) < I386_VM_DIR_ENTRIES); #if LU_DEBUG @@ -596,7 +569,6 @@ int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp) vir_bytes viraddr; pt_t *pt; - assert(src_vmp->vm_stacktop == dst_vmp->vm_stacktop); pt = &src_vmp->vm_pt; #if LU_DEBUG @@ -605,8 +577,7 @@ int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp) #endif /* Transfer mapping to the page directory. */ - assert((vir_bytes) pt->pt_dir >= src_vmp->vm_stacktop); - viraddr = arch_vir2map(src_vmp, (vir_bytes) pt->pt_dir); + viraddr = (vir_bytes) pt->pt_dir; physaddr = pt->pt_dir_phys & I386_VM_ADDR_MASK; if((r=pt_writemap(dst_vmp, &dst_vmp->vm_pt, viraddr, physaddr, I386_PAGE_SIZE, I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, @@ -619,14 +590,13 @@ int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp) #endif /* Scan all non-reserved page-directory entries. */ - for(pde=proc_pde; pde < I386_VM_DIR_ENTRIES; pde++) { + for(pde=0; pde < I386_VM_DIR_ENTRIES; pde++) { if(!(pt->pt_dir[pde] & I386_VM_PRESENT)) { continue; } /* Transfer mapping to the page table. */ - assert((vir_bytes) pt->pt_pt[pde] >= src_vmp->vm_stacktop); - viraddr = arch_vir2map(src_vmp, (vir_bytes) pt->pt_pt[pde]); + viraddr = (vir_bytes) pt->pt_pt[pde]; physaddr = pt->pt_dir[pde] & I386_VM_ADDR_MASK; if((r=pt_writemap(dst_vmp, &dst_vmp->vm_pt, viraddr, physaddr, I386_PAGE_SIZE, I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, @@ -634,24 +604,18 @@ int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp) return r; } } -#if LU_DEBUG - printf("VM: pt_ptmap: transferred mappings to page tables, pde range %d - %d\n", - proc_pde, I386_VM_DIR_ENTRIES - 1); -#endif return OK; } void pt_clearmapcache(void) { - int f; /* Make sure kernel will invalidate tlb when using current * pagetable (i.e. vm's) to make new mappings before new cr3 * is loaded. */ - for(f = first_free_pde; f < first_free_pde+FREE_PDES; f++) { - vmprocess->vm_pt.pt_dir[f] = 0; - } + if(sys_vmctl(SELF, VMCTL_CLEARMAPCACHE, 0) != OK) + panic("VMCTL_CLEARMAPCACHE failed"); } /*===========================================================================* @@ -706,6 +670,7 @@ int pt_writemap(struct vmproc * vmp, */ ret = pt_ptalloc_in_range(pt, v, v + I386_PAGE_SIZE*pages, flags, verify); if(ret != OK) { + printf("VM: writemap: pt_ptalloc_in_range failed\n"); goto resume_exit; } @@ -715,6 +680,9 @@ int pt_writemap(struct vmproc * vmp, int pde = I386_VM_PDE(v); int pte = I386_VM_PTE(v); + if(!v) { printf("VM: warning: making zero page for %d\n", + vmp->vm_endpoint); } + assert(!(v % I386_PAGE_SIZE)); assert(pte >= 0 && pte < I386_VM_PT_ENTRIES); assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES); @@ -722,10 +690,12 @@ int pt_writemap(struct vmproc * vmp, /* Page table has to be there. */ assert(pt->pt_dir[pde] & I386_VM_PRESENT); + /* We do not expect it to be a bigpage. */ + assert(!(pt->pt_dir[pde] & I386_VM_BIGPAGE)); + /* Make sure page directory entry for this page table * is marked present and page table entry is available. */ - assert((pt->pt_dir[pde] & I386_VM_PRESENT)); assert(pt->pt_pt[pde]); #if SANITYCHECKS @@ -770,9 +740,6 @@ int pt_writemap(struct vmproc * vmp, } } else { /* Write pagetable entry. */ -#if SANITYCHECKS - assert(vm_addrok(pt->pt_pt[pde], 1)); -#endif pt->pt_pt[pde][pte] = entry; } @@ -874,53 +841,62 @@ int pt_new(pt_t *pt) return OK; } +static int freepde(void) +{ + int p = kernel_boot_info.freepde_start++; + assert(kernel_boot_info.freepde_start < I386_VM_DIR_ENTRIES); + return p; +} + /*===========================================================================* * pt_init * *===========================================================================*/ -void pt_init(phys_bytes usedlimit) +void pt_init(void) { -/* By default, the kernel gives us a data segment with pre-allocated - * memory that then can't grow. We want to be able to allocate memory - * dynamically, however. So here we copy the part of the page table - * that's ours, so we get a private page table. Then we increase the - * hardware segment size so we can allocate memory above our stack. - */ pt_t *newpt; - int s, r; - vir_bytes v; - phys_bytes lo, hi; - vir_bytes extra_clicks; - u32_t moveup = 0; + int s, r, p; int global_bit_ok = 0; - int free_pde; - struct vm_ep_data ep_data; vir_bytes sparepages_mem; - phys_bytes sparepages_ph; - vir_bytes ptr; - int f = 0; + static u32_t currentpagedir[I386_VM_DIR_ENTRIES]; + int m = kernel_boot_info.kern_mod; + u32_t mycr3; - /* Shorthand. */ - newpt = &vmprocess->vm_pt; + /* Find what the physical location of the kernel is. */ + assert(m >= 0); + assert(m < kernel_boot_info.mods_with_kernel); + assert(kernel_boot_info.mods_with_kernel < MULTIBOOT_MAX_MODS); + kern_mb_mod = &kernel_boot_info.module_list[m]; + kern_size = kern_mb_mod->mod_end - kern_mb_mod->mod_start; + assert(!(kern_mb_mod->mod_start % I386_BIG_PAGE_SIZE)); + assert(!(kernel_boot_info.vir_kern_start % I386_BIG_PAGE_SIZE)); + kern_start_pde = kernel_boot_info.vir_kern_start / I386_BIG_PAGE_SIZE; /* Get ourselves spare pages. */ - ptr = (vir_bytes) static_sparepages; - ptr += I386_PAGE_SIZE - (ptr % I386_PAGE_SIZE); - if(!(sparepages_mem = ptr)) - panic("pt_init: aalloc for spare failed"); - if((r=sys_umap(SELF, VM_D, (vir_bytes) sparepages_mem, - I386_PAGE_SIZE*SPAREPAGES, &sparepages_ph)) != OK) - panic("pt_init: sys_umap failed: %d", r); + sparepages_mem = (vir_bytes) static_sparepages; + assert(!(sparepages_mem % I386_PAGE_SIZE)); + + /* Spare pages are used to allocate memory before VM has its own page + * table that things (i.e. arbitrary physical memory) can be mapped into. + * We get it by pre-allocating it in our bss (allocated and mapped in by + * the kernel) in static_sparepages. We also need the physical addresses + * though; we look them up now so they are ready for use. + */ missing_spares = 0; assert(STATIC_SPAREPAGES < SPAREPAGES); for(s = 0; s < SPAREPAGES; s++) { + vir_bytes v = (sparepages_mem + s*I386_PAGE_SIZE);; + phys_bytes ph; + if((r=sys_umap(SELF, VM_D, (vir_bytes) v, + I386_PAGE_SIZE*SPAREPAGES, &ph)) != OK) + panic("pt_init: sys_umap failed: %d", r); if(s >= STATIC_SPAREPAGES) { sparepages[s].page = NULL; missing_spares++; continue; } - sparepages[s].page = (void *) (sparepages_mem + s*I386_PAGE_SIZE); - sparepages[s].phys = sparepages_ph + s*I386_PAGE_SIZE; + sparepages[s].page = (void *) v; + sparepages[s].phys = ph; } /* global bit and 4MB pages available? */ @@ -931,51 +907,6 @@ void pt_init(phys_bytes usedlimit) if(global_bit_ok) global_bit = I386_VM_GLOBAL; - /* The kernel and boot time processes need an identity mapping. - * We use full PDE's for this without separate page tables. - * Figure out which pde we can start using for other purposes. - */ - id_map_high_pde = usedlimit / I386_BIG_PAGE_SIZE; - - /* We have to make mappings up till here. */ - free_pde = id_map_high_pde+1; - - /* Initial (current) range of our virtual address space. */ - lo = CLICK2ABS(vmprocess->vm_arch.vm_seg[T].mem_phys); - hi = CLICK2ABS(vmprocess->vm_arch.vm_seg[S].mem_phys + - vmprocess->vm_arch.vm_seg[S].mem_len); - - assert(!(lo % I386_PAGE_SIZE)); - assert(!(hi % I386_PAGE_SIZE)); - - if(lo < VM_PROCSTART) { - moveup = VM_PROCSTART - lo; - assert(!(VM_PROCSTART % I386_PAGE_SIZE)); - assert(!(lo % I386_PAGE_SIZE)); - assert(!(moveup % I386_PAGE_SIZE)); - } - - /* Make new page table for ourselves, partly copied - * from the current one. - */ - if(pt_new(newpt) != OK) - panic("pt_init: pt_new failed"); - - /* Set up mappings for VM process. */ - for(v = lo; v < hi; v += I386_PAGE_SIZE) { - /* We have to write the new position in the PT, - * so we can move our segments. - */ - if(pt_writemap(vmprocess, newpt, v+moveup, v, I386_PAGE_SIZE, - I386_VM_PRESENT|I386_VM_WRITE|I386_VM_USER, 0) != OK) - panic("pt_init: pt_writemap failed"); - } - - /* Move segments up too. */ - vmprocess->vm_arch.vm_seg[T].mem_phys += ABS2CLICK(moveup); - vmprocess->vm_arch.vm_seg[D].mem_phys += ABS2CLICK(moveup); - vmprocess->vm_arch.vm_seg[S].mem_phys += ABS2CLICK(moveup); - /* Allocate us a page table in which to remember page directory * pointers. */ @@ -984,28 +915,6 @@ void pt_init(phys_bytes usedlimit) panic("no virt addr for vm mappings"); memset(page_directories, 0, I386_PAGE_SIZE); - - /* Increase our hardware data segment to create virtual address - * space above our stack. We want to increase it to VM_DATATOP, - * like regular processes have. - */ - extra_clicks = ABS2CLICK(VM_DATATOP - hi); - vmprocess->vm_arch.vm_seg[S].mem_len += extra_clicks; - - /* We pretend to the kernel we have a huge stack segment to - * increase our data segment. - */ - vmprocess->vm_arch.vm_data_top = - (vmprocess->vm_arch.vm_seg[S].mem_vir + - vmprocess->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT; - - /* Where our free virtual address space starts. - * This is only a hint to the VM system. - */ - newpt->pt_virtop = 0; - - /* Let other functions know VM now has a private page table. */ - vmprocess->vm_flags |= VMF_HASPT; /* Now reserve another pde for kernel's own mappings. */ { @@ -1014,7 +923,7 @@ void pt_init(phys_bytes usedlimit) int flags, index = 0; u32_t offset = 0; - kernmap_pde = free_pde++; + kernmap_pde = freepde(); offset = kernmap_pde * I386_BIG_PAGE_SIZE; while(sys_vmctl_get_mapping(index, &addr, &len, @@ -1025,17 +934,16 @@ void pt_init(phys_bytes usedlimit) kern_mappings[index].phys_addr = addr; kern_mappings[index].len = len; kern_mappings[index].flags = flags; - kern_mappings[index].lin_addr = offset; + kern_mappings[index].vir_addr = offset; kern_mappings[index].flags = - I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE | - global_bit; + I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE; if(flags & VMMF_UNCACHED) kern_mappings[index].flags |= PTF_NOCACHE; if(addr % I386_PAGE_SIZE) panic("VM: addr unaligned: %d", addr); if(len % I386_PAGE_SIZE) panic("VM: len unaligned: %d", len); - vir = arch_map2vir(&vmproc[VMP_SYSTEM], offset); + vir = offset; if(sys_vmctl_reply_mapping(index, vir) != OK) panic("VM: reply failed"); offset += len; @@ -1045,131 +953,68 @@ void pt_init(phys_bytes usedlimit) } /* Find a PDE below processes available for mapping in the - * page directories (readonly). + * page directories. */ - pagedir_pde = free_pde++; + pagedir_pde = freepde(); pagedir_pde_val = (page_directories_phys & I386_VM_ADDR_MASK) | - I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE; + I386_VM_PRESENT | I386_VM_WRITE; - /* Tell kernel about free pde's. */ - first_free_pde = free_pde; - while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART && f < FREE_PDES) { - if((r=sys_vmctl(SELF, VMCTL_I386_FREEPDE, free_pde++)) != OK) { - panic("VMCTL_I386_FREEPDE failed: %d", r); - } - f++; + /* Allright. Now. We have to make our own page directory and page tables, + * that the kernel has already set up, accessible to us. It's easier to + * understand if we just copy all the required pages (i.e. page directory + * and page tables), and set up the pointers as if VM had done it itself. + * + * This allocation will happen without using any page table, and just + * uses spare pages. + */ + newpt = &vmprocess->vm_pt; + if(pt_new(newpt) != OK) + panic("vm pt_new failed"); + + /* Get our current pagedir so we can see it. */ + if(sys_vmctl_get_cr3_i386(SELF, &mycr3) != OK) + panic("VM: sys_vmctl_get_cr3_i386 failed"); + if(sys_vircopy(NONE, mycr3, SELF, + (vir_bytes) currentpagedir, I386_PAGE_SIZE) != OK) + panic("VM: sys_vircopy failed"); + + /* We have mapped in kernel ourselves; now copy mappings for VM + * that kernel made, including allocations for BSS. Skip identity + * mapping bits; just map in VM. + */ + for(p = 0; p < I386_VM_DIR_ENTRIES; p++) { + u32_t entry = currentpagedir[p]; + phys_bytes ptaddr_kern, ptaddr_us; + + /* BIGPAGEs are kernel mapping (do ourselves) or boot + * identity mapping (don't want). + */ + if(!(entry & I386_VM_PRESENT)) continue; + if((entry & I386_VM_BIGPAGE)) continue; + + if(pt_ptalloc(newpt, p, 0) != OK) + panic("pt_ptalloc failed"); + assert(newpt->pt_dir[p] & I386_VM_PRESENT); + + ptaddr_kern = entry & I386_VM_ADDR_MASK; + ptaddr_us = newpt->pt_dir[p] & I386_VM_ADDR_MASK; + + /* Copy kernel-initialized pagetable contents into our + * normally accessible pagetable. + */ + if(sys_abscopy(ptaddr_kern, ptaddr_us, I386_PAGE_SIZE) != OK) + panic("pt_init: abscopy failed"); } - /* first pde in use by process. */ - proc_pde = free_pde; - - /* Give our process the new, copied, private page table. */ - pt_mapkernel(newpt); /* didn't know about vm_dir pages earlier */ - pt_bind(newpt, vmprocess); - - /* new segment limit for the kernel after paging is enabled */ - ep_data.data_seg_limit = free_pde*I386_BIG_PAGE_SIZE; - /* the memory map which must be installed after paging is enabled */ - ep_data.mem_map = vmprocess->vm_arch.vm_seg; - - /* Now actually enable paging. */ - if(sys_vmctl_enable_paging(&ep_data) != OK) - panic("pt_init: enable paging failed"); - - /* Back to reality - this is where the stack actually is. */ - vmprocess->vm_arch.vm_seg[S].mem_len -= extra_clicks; - - /* Pretend VM stack top is the same as any regular process, not to - * have discrepancies with new VM instances later on. - */ - vmprocess->vm_stacktop = VM_STACKTOP; + /* Inform kernel vm has a newly built page table. */ + assert(vmproc[VM_PROC_NR].vm_endpoint == VM_PROC_NR); + pt_mapkernel(newpt); + pt_bind(newpt, &vmproc[VM_PROC_NR]); /* All OK. */ return; } -/*===========================================================================* - * pt_init_mem * - *===========================================================================*/ -void pt_init_mem() -{ -/* Architecture-specific memory initialization. Make sure all the pages - * shared with the kernel and VM's page tables are mapped above the stack, - * so that we can easily transfer existing mappings for new VM instances. - */ - phys_bytes new_page_directories_phys; - u32_t *new_page_directories; - phys_bytes new_pt_dir_phys; - u32_t *new_pt_dir; - phys_bytes new_pt_phys; - u32_t *new_pt; - pt_t *vmpt; - int i; - - vmpt = &vmprocess->vm_pt; - - /* We should be running this when VM has been assigned a page - * table and memory initialization has already been performed. - */ - assert(vmprocess->vm_flags & VMF_HASPT); - assert(meminit_done); - - /* Throw away static spare pages. */ - vm_checkspares(); - for(i = 0; i < SPAREPAGES; i++) { - if(sparepages[i].page && (vir_bytes) sparepages[i].page - < vmprocess->vm_stacktop) { - sparepages[i].page = NULL; - missing_spares++; - } - } - vm_checkspares(); - - /* Rellocate page for page directories pointers. */ - if(!(new_page_directories = vm_allocpage(&new_page_directories_phys, - VMP_PAGETABLE))) - panic("unable to reallocated page for page dir ptrs"); - assert((vir_bytes) new_page_directories >= vmprocess->vm_stacktop); - memcpy(new_page_directories, page_directories, I386_PAGE_SIZE); - page_directories = new_page_directories; - pagedir_pde_val = (new_page_directories_phys & I386_VM_ADDR_MASK) | - (pagedir_pde_val & ~I386_VM_ADDR_MASK); - - /* Remap in kernel. */ - pt_mapkernel(vmpt); - - /* Reallocate VM's page directory. */ - if((vir_bytes) vmpt->pt_dir < vmprocess->vm_stacktop) { - if(!(new_pt_dir= vm_allocpage(&new_pt_dir_phys, VMP_PAGEDIR))) { - panic("unable to reallocate VM's page directory"); - } - assert((vir_bytes) new_pt_dir >= vmprocess->vm_stacktop); - memcpy(new_pt_dir, vmpt->pt_dir, I386_PAGE_SIZE); - vmpt->pt_dir = new_pt_dir; - vmpt->pt_dir_phys = new_pt_dir_phys; - pt_bind(vmpt, vmprocess); - } - - /* Reallocate VM's page tables. */ - for(i = proc_pde; i < I386_VM_DIR_ENTRIES; i++) { - if(!(vmpt->pt_dir[i] & I386_VM_PRESENT)) { - continue; - } - assert(vmpt->pt_pt[i]); - if((vir_bytes) vmpt->pt_pt[i] >= vmprocess->vm_stacktop) { - continue; - } - vm_checkspares(); - if(!(new_pt = vm_allocpage(&new_pt_phys, VMP_PAGETABLE))) - panic("unable to reallocate VM's page table"); - assert((vir_bytes) new_pt >= vmprocess->vm_stacktop); - memcpy(new_pt, vmpt->pt_pt[i], I386_PAGE_SIZE); - vmpt->pt_pt[i] = new_pt; - vmpt->pt_dir[i] = (new_pt_phys & I386_VM_ADDR_MASK) | - (vmpt->pt_dir[i] & ~I386_VM_ADDR_MASK); - } -} - /*===========================================================================* * pt_bind * *===========================================================================*/ @@ -1200,8 +1045,7 @@ int pt_bind(pt_t *pt, struct vmproc *who) /* This is where the PDE's will be visible to the kernel * in its address space. */ - pdes = (void *) arch_map2vir(&vmproc[VMP_SYSTEM], - pagedir_pde*I386_BIG_PAGE_SIZE + + pdes = (void *) (pagedir_pde*I386_BIG_PAGE_SIZE + slot * I386_PAGE_SIZE); #if 0 @@ -1209,9 +1053,7 @@ int pt_bind(pt_t *pt, struct vmproc *who) slot, who->vm_endpoint, page_directories[slot], pdes); #endif /* Tell kernel about new page table root. */ - return sys_vmctl_set_addrspace(who->vm_endpoint, - pt ? pt->pt_dir_phys : 0, - pt ? pdes : 0); + return sys_vmctl_set_addrspace(who->vm_endpoint, pt->pt_dir_phys, pdes); } /*===========================================================================* @@ -1236,32 +1078,34 @@ void pt_free(pt_t *pt) int pt_mapkernel(pt_t *pt) { int i; + int kern_pde = kern_start_pde; + phys_bytes addr, mapped = 0; /* Any i386 page table needs to map in the kernel address space. */ - assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE); + assert(bigpage_ok); + assert(pagedir_pde >= 0); + assert(kern_pde >= 0); - if(bigpage_ok) { - int pde; - for(pde = 0; pde <= id_map_high_pde; pde++) { - phys_bytes addr; - addr = pde * I386_BIG_PAGE_SIZE; - assert((addr & I386_VM_ADDR_MASK) == addr); - pt->pt_dir[pde] = addr | I386_VM_PRESENT | - I386_VM_BIGPAGE | I386_VM_USER | - I386_VM_WRITE | global_bit; - } - } else { - panic("VM: pt_mapkernel: no bigpage"); + /* pt_init() has made sure this is ok. */ + addr = kern_mb_mod->mod_start; + + /* Actually mapping in kernel */ + while(mapped < kern_size) { + pt->pt_dir[kern_pde] = addr | I386_VM_PRESENT | + I386_VM_BIGPAGE | I386_VM_WRITE | global_bit; + kern_pde++; + mapped += I386_BIG_PAGE_SIZE; + addr += I386_BIG_PAGE_SIZE; } - if(pagedir_pde >= 0) { - /* Kernel also wants to know about all page directories. */ - pt->pt_dir[pagedir_pde] = pagedir_pde_val; - } + /* Kernel also wants to know about all page directories. */ + assert(pagedir_pde > kern_pde); + pt->pt_dir[pagedir_pde] = pagedir_pde_val; + /* Kernel also wants various mappings of its own. */ for(i = 0; i < kernmappings; i++) { if(pt_writemap(NULL, pt, - kern_mappings[i].lin_addr, + kern_mappings[i].vir_addr, kern_mappings[i].phys_addr, kern_mappings[i].len, kern_mappings[i].flags, 0) != OK) { diff --git a/servers/vm/arch/i386/vm.c b/servers/vm/arch/i386/vm.c deleted file mode 100644 index 1d206f660..000000000 --- a/servers/vm/arch/i386/vm.c +++ /dev/null @@ -1,143 +0,0 @@ - -#define _SYSTEM 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "proto.h" -#include "vm.h" -#include "util.h" - -#include "memory.h" - -/*===========================================================================* - * arch_map2vir * - *===========================================================================*/ -vir_bytes arch_map2vir(struct vmproc *vmp, vir_bytes addr) -{ - vir_bytes textstart = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys); - vir_bytes datastart = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys); - vir_bytes datasegbase = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys - - vmp->vm_arch.vm_seg[D].mem_vir); - - /* Could be a text address. */ - assert(datastart <= addr || textstart <= addr); - - return addr - datasegbase; -} - -/*===========================================================================* - * arch_map2str * - *===========================================================================*/ -char *arch_map2str(struct vmproc *vmp, vir_bytes addr) -{ - static char bufstr[100]; - vir_bytes textstart = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys); - vir_bytes datastart = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys); - vir_bytes textsegbase = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys - - vmp->vm_arch.vm_seg[T].mem_vir); - vir_bytes datasegbase = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys - - vmp->vm_arch.vm_seg[D].mem_vir); - - if(addr < textstart) { - sprintf(bufstr, "", addr); - } else if(addr < datastart) { - sprintf(bufstr, "0x%lx (codeseg)", addr - textsegbase); - } else { - sprintf(bufstr, "0x%lx (dataseg)", addr - datasegbase); - } - - return bufstr; -} - -/*===========================================================================* - * arch_map2info * - *===========================================================================*/ -vir_bytes arch_map2info(struct vmproc *vmp, vir_bytes addr, int *seg, - int *prot) -{ - vir_bytes textstart = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys); - vir_bytes textend = textstart + - CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_len); - vir_bytes datastart = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys); - vir_bytes textsegbase = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys - - vmp->vm_arch.vm_seg[T].mem_vir); - vir_bytes datasegbase = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys - - vmp->vm_arch.vm_seg[D].mem_vir); - - /* The protection to be returned here is that of the segment. */ - if(addr < textstart) { - *seg = D; - *prot = PROT_READ | PROT_WRITE | PROT_EXEC; - return addr; - } else if(addr < datastart) { - *seg = T; - *prot = PROT_READ | PROT_EXEC; - return addr - textsegbase; - } else { - *seg = D; - if (textstart == textend) /* common I&D? */ - *prot = PROT_READ | PROT_WRITE | PROT_EXEC; - else - *prot = PROT_READ | PROT_WRITE; - return addr - datasegbase; - } -} - -/*===========================================================================* - * arch_addrok * - *===========================================================================*/ -vir_bytes arch_addrok(struct vmproc *vmp, vir_bytes addr) -{ - vir_bytes textstart = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys); - vir_bytes textend = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys + - vmp->vm_arch.vm_seg[T].mem_phys); - vir_bytes datastart = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys); - - if(addr >= textstart && addr < textstart+textend) - return 1; - - if(addr >= datastart && addr < VM_DATATOP) - return 1; - - return 0; -} - -/*===========================================================================* - * arch_vir2map * - *===========================================================================*/ -vir_bytes arch_vir2map(struct vmproc *vmp, vir_bytes addr) -{ - vir_bytes datasegbase = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys - - vmp->vm_arch.vm_seg[D].mem_vir); - - return addr + datasegbase; -} - -/*===========================================================================* - * arch_vir2map_text * - *===========================================================================*/ -vir_bytes arch_vir2map_text(struct vmproc *vmp, vir_bytes addr) -{ - vir_bytes textsegbase = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys - - vmp->vm_arch.vm_seg[T].mem_vir); - - return addr + textsegbase; -} diff --git a/servers/vm/break.c b/servers/vm/break.c index bc4a0687a..b8ea5f0be 100644 --- a/servers/vm/break.c +++ b/servers/vm/break.c @@ -59,107 +59,6 @@ int do_brk(message *msg) return real_brk(&vmproc[proc], (vir_bytes) msg->VMB_ADDR); } -/*===========================================================================* - * adjust * - *===========================================================================*/ -int adjust(rmp, data_clicks, sp) -struct vmproc *rmp; /* whose memory is being adjusted? */ -vir_clicks data_clicks; /* how big is data segment to become? */ -vir_bytes sp; /* new value of sp */ -{ -/* See if data and stack segments can coexist, adjusting them if need be. - * Memory is never allocated or freed. Instead it is added or removed from the - * gap between data segment and stack segment. If the gap size becomes - * negative, the adjustment of data or stack fails and ENOMEM is returned. - */ - - register struct mem_map *mem_sp, *mem_dp; - vir_clicks sp_click, gap_base, sp_lower, old_clicks; - int changed, r, sp_in_dp; - long base_of_stack, sp_delta; /* longs avoid certain problems */ - - mem_dp = &rmp->vm_arch.vm_seg[D]; /* pointer to data segment map */ - mem_sp = &rmp->vm_arch.vm_seg[S]; /* pointer to stack segment map */ - changed = 0; /* set when either segment changed */ - - /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */ - base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len; - sp_click = sp >> CLICK_SHIFT; /* click containing sp */ - if (sp_click >= base_of_stack) - { - return(ENOMEM); /* sp too high */ - } - - /* In order to support user-space libraries, processes might change sp to - point to somewhere inside the data segment. If that's the case, be careful - not to erroneously think that the data and stack have collided. */ - sp_in_dp = (mem_dp->mem_vir <= sp_click) && - (mem_dp->mem_vir + mem_dp->mem_len >= sp_click); - - /* Compute size of gap between stack and data segments. */ - sp_delta = (long) mem_sp->mem_vir - (long) sp_click; - sp_lower = ((sp_delta > 0 && !sp_in_dp) ? sp_click : mem_sp->mem_vir); - - /* Add a safety margin for future stack growth. Impossible to do right. */ -#define SAFETY_BYTES (384 * sizeof(char *)) -#define SAFETY_CLICKS ((vir_clicks) (CLICK_CEIL(SAFETY_BYTES) >> CLICK_SHIFT)) - gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS; - if (sp_lower < gap_base) - { - return(ENOMEM); /* data and stack collided */ - } - - /* Update data length (but not data orgin) on behalf of brk() system call. */ - old_clicks = mem_dp->mem_len; - if (data_clicks != mem_dp->mem_len) { - mem_dp->mem_len = data_clicks; - changed |= DATA_CHANGED; - } - - /* Update stack length and origin due to change in stack pointer. */ - if (sp_delta > 0 && !sp_in_dp) { - mem_sp->mem_vir -= sp_delta; - mem_sp->mem_phys -= sp_delta; - mem_sp->mem_len += sp_delta; - changed |= STACK_CHANGED; - } - - /* Do the new data and stack segment sizes fit in the address space? */ - r = (rmp->vm_arch.vm_seg[D].mem_vir + rmp->vm_arch.vm_seg[D].mem_len > - rmp->vm_arch.vm_seg[S].mem_vir) ? ENOMEM : OK; - - if(r == OK && (rmp->vm_flags & VMF_HASPT) && - rmp->vm_endpoint != VM_PROC_NR && rmp->vm_heap) { - if(old_clicks < data_clicks) { - vir_bytes more; - more = (data_clicks - old_clicks) << CLICK_SHIFT; - if(map_region_extend(rmp, rmp->vm_heap, more) != OK) { - printf("VM: brk: map_region_extend failed\n"); - return ENOMEM; - } - } else if(old_clicks > data_clicks) { - vir_bytes less; - less = (old_clicks - data_clicks) << CLICK_SHIFT; - if(map_region_shrink(rmp->vm_heap, less) != OK) { - printf("VM: brk: map_region_shrink failed\n"); - return ENOMEM; - } - } - } - - if (r == OK) - return(OK); - - /* New sizes don't fit or require too many page/segment registers. Restore.*/ - if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks; - if (changed & STACK_CHANGED) { - mem_sp->mem_vir += sp_delta; - mem_sp->mem_phys += sp_delta; - mem_sp->mem_len -= sp_delta; - } - return(ENOMEM); -} - /*===========================================================================* * real_brk * *===========================================================================*/ @@ -167,9 +66,6 @@ int real_brk(vmp, v) struct vmproc *vmp; vir_bytes v; { - if(!(vmp->vm_flags & VMF_HASPT)) - return OK; - if(map_region_extend_upto_v(vmp, v) == OK) return OK; diff --git a/servers/vm/exec.c b/servers/vm/exec.c deleted file mode 100644 index 9a0500880..000000000 --- a/servers/vm/exec.c +++ /dev/null @@ -1,216 +0,0 @@ - -#define _SYSTEM 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "glo.h" -#include "proto.h" -#include "util.h" -#include "vm.h" -#include "region.h" -#include "sanitycheck.h" - -#include "memory.h" - -/*===========================================================================* - * find_kernel_top * - *===========================================================================*/ -phys_bytes find_kernel_top(void) -{ -/* Find out where the kernel is, so we know where to start mapping - * user processes. - */ - u32_t kernel_top = 0; -#define MEMTOP(v, i) \ - (vmproc[v].vm_arch.vm_seg[i].mem_phys + vmproc[v].vm_arch.vm_seg[i].mem_len) - assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE); - kernel_top = MEMTOP(VMP_SYSTEM, T); - kernel_top = MAX(kernel_top, MEMTOP(VMP_SYSTEM, D)); - kernel_top = MAX(kernel_top, MEMTOP(VMP_SYSTEM, S)); - assert(kernel_top); - - return CLICK2ABS(kernel_top); -} - -void regular_segs(struct vmproc *vmp) -{ - int s; - memset(vmp->vm_arch.vm_seg, 0, sizeof(vmp->vm_arch.vm_seg)); - vmp->vm_arch.vm_seg[T].mem_phys = - vmp->vm_arch.vm_seg[D].mem_phys = ABS2CLICK(VM_PROCSTART); - vmp->vm_arch.vm_seg[T].mem_len = - vmp->vm_arch.vm_seg[D].mem_len = - vmp->vm_arch.vm_seg[S].mem_len = ABS2CLICK(VM_DATATOP-VM_PROCSTART); - if((s=sys_newmap(vmp->vm_endpoint, vmp->vm_arch.vm_seg)) != OK) - panic("regular_segs: sys_newmap failed: %d", s); - if((s=pt_bind(&vmp->vm_pt, vmp)) != OK) - panic("regular_segs: pt_bind failed: %d", s); -} - -/*===========================================================================* - * proc_new * - *===========================================================================*/ -int proc_new(struct vmproc *vmp, - phys_bytes vstart, /* where to start the process in page table */ - phys_bytes text_addr, /* address at which to load code */ - phys_bytes text_bytes, /* how much code, in bytes but page aligned */ - phys_bytes data_addr, /* address at which to load data */ - phys_bytes data_bytes, /* how much data + bss, in bytes but page aligned */ - phys_bytes stack_bytes, /* stack space to reserve, in bytes, page aligned */ - phys_bytes gap_bytes, /* gap bytes, page aligned */ - phys_bytes text_start, /* text starts here, if preallocated, otherwise 0 */ - phys_bytes data_start, /* data starts here, if preallocated, otherwise 0 */ - phys_bytes stacktop, - int prealloc_stack, - int is_elf, - int full_memview -) -{ - int s; - vir_bytes hole_bytes; - struct vir_region *reg; - phys_bytes map_text_addr, map_data_addr, map_stack_addr; - - assert(!(vstart % VM_PAGE_SIZE)); - assert(!(text_addr % VM_PAGE_SIZE)); - assert(!(text_bytes % VM_PAGE_SIZE)); - assert(!(data_addr % VM_PAGE_SIZE)); - assert(!(data_bytes % VM_PAGE_SIZE)); - assert(!(stack_bytes % VM_PAGE_SIZE)); - assert(!(gap_bytes % VM_PAGE_SIZE)); - assert(!(text_start % VM_PAGE_SIZE)); - assert(!(data_start % VM_PAGE_SIZE)); - assert((!text_start && !data_start) || (text_start && data_start)); - - /* Place text at start of process. */ - map_text_addr = vstart + text_addr; - vmp->vm_arch.vm_seg[T].mem_phys = ABS2CLICK(map_text_addr); - vmp->vm_arch.vm_seg[T].mem_vir = ABS2CLICK(text_addr); - if(full_memview) { - vmp->vm_arch.vm_seg[T].mem_len = ABS2CLICK(VM_DATATOP) - - vmp->vm_arch.vm_seg[T].mem_phys; - } else { - vmp->vm_arch.vm_seg[T].mem_len = ABS2CLICK(text_bytes); - } - - vmp->vm_offset = vstart; - - /* page mapping flags for code */ -#define TEXTFLAGS (PTF_PRESENT | PTF_USER) - SANITYCHECK(SCL_DETAIL); - if(text_bytes > 0) { - if(!(reg=map_page_region(vmp, map_text_addr, 0, text_bytes, - text_start ? text_start : MAP_NONE, - VR_ANON | VR_WRITABLE, text_start ? 0 : MF_PREALLOC))) { - SANITYCHECK(SCL_DETAIL); - printf("VM: proc_new: map_page_region failed (text)\n"); - map_free_proc(vmp); - SANITYCHECK(SCL_DETAIL); - return(ENOMEM); - } - - map_region_set_tag(reg, VRT_TEXT); - SANITYCHECK(SCL_DETAIL); - } - SANITYCHECK(SCL_DETAIL); - - /* Allocate memory for data (including bss, but not including gap - * or stack), make sure it's cleared, and map it in after text - * (if any). - */ - if (is_elf) { - map_data_addr = vstart + data_addr; - } else { - map_data_addr = vstart + text_bytes; - } - - if(!(vmp->vm_heap = map_page_region(vmp, map_data_addr, 0, - data_bytes, data_start ? data_start : MAP_NONE, VR_ANON | VR_WRITABLE, - data_start ? 0 : MF_PREALLOC))) { - printf("VM: exec: map_page_region for data failed\n"); - map_free_proc(vmp); - SANITYCHECK(SCL_DETAIL); - return ENOMEM; - } - - /* Tag the heap so brk() call knows which region to extend. */ - map_region_set_tag(vmp->vm_heap, VRT_HEAP); - - /* How many address space clicks between end of data - * and start of stack? - * stacktop is the first address after the stack, as addressed - * from within the user process. - */ - hole_bytes = stacktop - data_bytes - stack_bytes - - gap_bytes - data_addr; - - map_stack_addr = map_data_addr + data_bytes + hole_bytes; - - if(!(reg=map_page_region(vmp, - map_stack_addr, - 0, stack_bytes + gap_bytes, MAP_NONE, - VR_ANON | VR_WRITABLE, prealloc_stack ? MF_PREALLOC : 0)) != OK) { - panic("map_page_region failed for stack"); - } - - map_region_set_tag(reg, VRT_STACK); - - vmp->vm_arch.vm_seg[D].mem_phys = ABS2CLICK(map_data_addr); - vmp->vm_arch.vm_seg[D].mem_vir = ABS2CLICK(data_addr); - vmp->vm_arch.vm_seg[D].mem_len = ABS2CLICK(data_bytes); - - vmp->vm_arch.vm_seg[S].mem_phys = ABS2CLICK(map_data_addr + - data_bytes + gap_bytes + hole_bytes); - vmp->vm_arch.vm_seg[S].mem_vir = ABS2CLICK(data_addr + - data_bytes + gap_bytes + hole_bytes); - - /* Where are we allowed to start using the rest of the virtual - * address space? - */ - vmp->vm_stacktop = stacktop; - - vmp->vm_flags |= VMF_HASPT; - - if(vmp->vm_endpoint != NONE) { - - /* Pretend the stack is the full size of the data segment, so - * we get a full-sized data segment, up to VM_DATATOP. - * After sys_newmap(), change the stack to what we know the - * stack to be (up to stacktop). - */ - vmp->vm_arch.vm_seg[S].mem_len = (VM_DATATOP >> CLICK_SHIFT) - - vmp->vm_arch.vm_seg[S].mem_vir - ABS2CLICK(map_data_addr); - - /* What is the final size of the data segment in bytes? */ - vmp->vm_arch.vm_data_top = - (vmp->vm_arch.vm_seg[S].mem_vir + - vmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT; - - if((s=sys_newmap(vmp->vm_endpoint, vmp->vm_arch.vm_seg)) != OK) - panic("sys_newmap (vm) failed: %d", s); - if((s=pt_bind(&vmp->vm_pt, vmp)) != OK) - panic("exec_newmem: pt_bind failed: %d", s); - } - - return OK; -} diff --git a/servers/vm/exit.c b/servers/vm/exit.c index 247172bb9..afb6993dc 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -27,11 +27,7 @@ void free_proc(struct vmproc *vmp) { map_free_proc(vmp); - vmp->vm_heap = NULL; - if(vmp->vm_flags & VMF_HASPT) { - vmp->vm_flags &= ~VMF_HASPT; - pt_free(&vmp->vm_pt); - } + pt_free(&vmp->vm_pt); region_init(&vmp->vm_regions_avl); vmp->vm_region_top = 0; #if VMSTATS @@ -45,7 +41,6 @@ void clear_proc(struct vmproc *vmp) vmp->vm_region_top = 0; vmp->vm_callback = NULL; /* No pending vfs callback. */ vmp->vm_flags = 0; /* Clear INUSE, so slot is free. */ - vmp->vm_heap = NULL; vmp->vm_yielded = 0; #if VMSTATS vmp->vm_bytecopies = 0; @@ -74,18 +69,12 @@ SANITYCHECK(SCL_FUNCTIONS); if(vmp->vm_flags & VMF_HAS_DMA) { release_dma(vmp); - } else if(vmp->vm_flags & VMF_HASPT) { + } else { /* Free pagetable and pages allocated by pt code. */ SANITYCHECK(SCL_DETAIL); free_proc(vmp); SANITYCHECK(SCL_DETAIL); - } else { - /* Free the data and stack segments. */ - free_mem(vmp->vm_arch.vm_seg[D].mem_phys, - vmp->vm_arch.vm_seg[S].mem_vir + - vmp->vm_arch.vm_seg[S].mem_len - - vmp->vm_arch.vm_seg[D].mem_vir); - } + } SANITYCHECK(SCL_DETAIL); /* Reset process slot fields. */ @@ -134,9 +123,7 @@ int do_procctl(message *msg) return EPERM; free_proc(vmp); pt_new(&vmp->vm_pt); - vmp->vm_flags |= VMF_HASPT; pt_bind(&vmp->vm_pt, vmp); - regular_segs(vmp); return OK; default: return EINVAL; diff --git a/servers/vm/fork.c b/servers/vm/fork.c index 807fba710..d42a27c8a 100644 --- a/servers/vm/fork.c +++ b/servers/vm/fork.c @@ -34,7 +34,7 @@ *===========================================================================*/ int do_fork(message *msg) { - int r, proc, childproc, fullvm; + int r, proc, childproc; struct vmproc *vmp, *vmc; pt_t origpt; vir_bytes msgaddr; @@ -63,8 +63,6 @@ int do_fork(message *msg) return EINVAL; } - fullvm = vmp->vm_flags & VMF_HASPT; - /* The child is basically a copy of the parent. */ origpt = vmc->vm_pt; *vmc = *vmp; @@ -72,7 +70,6 @@ int do_fork(message *msg) region_init(&vmc->vm_regions_avl); vmc->vm_endpoint = NONE; /* In case someone tries to use it. */ vmc->vm_pt = origpt; - vmc->vm_flags &= ~VMF_HASPT; #if VMSTATS vmc->vm_bytecopies = 0; @@ -83,136 +80,38 @@ int do_fork(message *msg) return ENOMEM; } - vmc->vm_flags |= VMF_HASPT; + SANITYCHECK(SCL_DETAIL); - if(fullvm) { - SANITYCHECK(SCL_DETAIL); - - if(map_proc_copy(vmc, vmp) != OK) { - printf("VM: fork: map_proc_copy failed\n"); - pt_free(&vmc->vm_pt); - return(ENOMEM); - } - - if(vmp->vm_heap) { - vmc->vm_heap = map_region_lookup_tag(vmc, VRT_HEAP); - assert(vmc->vm_heap); - } - - SANITYCHECK(SCL_DETAIL); - } else { - vir_bytes sp; - struct vir_region *heap, *stack; - vir_bytes text_bytes, data_bytes, stack_bytes, parent_gap_bytes, - child_gap_bytes; - vir_bytes text_addr, data_addr; - int is_elf = 0; - - /* Get SP of new process (using parent). */ - if(get_stack_ptr(vmp->vm_endpoint, &sp) != OK) { - printf("VM: fork: get_stack_ptr failed for %d\n", - vmp->vm_endpoint); - return ENOMEM; - } - - /* Update size of stack segment using current SP. */ - if(adjust(vmp, vmp->vm_arch.vm_seg[D].mem_len, sp) != OK) { - printf("VM: fork: adjust failed for %d\n", - vmp->vm_endpoint); - return ENOMEM; - } - - /* Copy newly adjust()ed stack segment size to child. */ - vmc->vm_arch.vm_seg[S] = vmp->vm_arch.vm_seg[S]; - - text_addr = CLICK2ABS(vmc->vm_arch.vm_seg[T].mem_vir); - text_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[T].mem_len); - data_addr = CLICK2ABS(vmc->vm_arch.vm_seg[D].mem_vir); - data_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[D].mem_len); - stack_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[S].mem_len); - - /* how much space after break and before lower end (which is the - * logical top) of stack for the parent - */ - parent_gap_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[S].mem_vir - - vmc->vm_arch.vm_seg[D].mem_len - - vmc->vm_arch.vm_seg[D].mem_vir); - - /* how much space can the child stack grow downwards, below - * the current SP? The rest of the gap is available for the - * heap to grow upwards. - */ - child_gap_bytes = VM_PAGE_SIZE; - -#if defined(__ELF__) - is_elf = 1; -#endif - - if((r=proc_new(vmc, VM_PROCSTART, - text_addr, text_bytes, - data_addr, data_bytes, - stack_bytes, child_gap_bytes, 0, 0, - CLICK2ABS(vmc->vm_arch.vm_seg[S].mem_vir + - vmc->vm_arch.vm_seg[S].mem_len), - 1, is_elf, 0)) != OK) { - printf("VM: fork: proc_new failed\n"); - return r; - } - - if(!(heap = map_region_lookup_tag(vmc, VRT_HEAP))) - panic("couldn't lookup heap"); - assert(heap->phys); - if(!(stack = map_region_lookup_tag(vmc, VRT_STACK))) - panic("couldn't lookup stack"); - assert(stack->phys); - - /* Now copy the memory regions. */ - - if(vmc->vm_arch.vm_seg[T].mem_len > 0) { - struct vir_region *text; - if(!(text = map_region_lookup_tag(vmc, VRT_TEXT))) - panic("couldn't lookup text"); - assert(text->phys); - if(copy_abs2region(CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys), - text, 0, text_bytes) != OK) - panic("couldn't copy text"); - } - - if(copy_abs2region(CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys), - heap, 0, data_bytes) != OK) - panic("couldn't copy heap"); - - if(copy_abs2region(CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys + - vmc->vm_arch.vm_seg[D].mem_len) + parent_gap_bytes, - stack, child_gap_bytes, stack_bytes) != OK) - panic("couldn't copy stack"); + if(map_proc_copy(vmc, vmp) != OK) { + printf("VM: fork: map_proc_copy failed\n"); + pt_free(&vmc->vm_pt); + return(ENOMEM); } /* Only inherit these flags. */ - vmc->vm_flags &= (VMF_INUSE|VMF_SEPARATE|VMF_HASPT); + vmc->vm_flags &= VMF_INUSE; /* inherit the priv call bitmaps */ memcpy(&vmc->vm_call_mask, &vmp->vm_call_mask, sizeof(vmc->vm_call_mask)); /* Tell kernel about the (now successful) FORK. */ if((r=sys_fork(vmp->vm_endpoint, childproc, - &vmc->vm_endpoint, vmc->vm_arch.vm_seg, - PFF_VMINHIBIT, &msgaddr)) != OK) { + &vmc->vm_endpoint, PFF_VMINHIBIT, &msgaddr)) != OK) { panic("do_fork can't sys_fork: %d", r); } if((r=pt_bind(&vmc->vm_pt, vmc)) != OK) panic("fork can't pt_bind: %d", r); - if(fullvm) { + { vir_bytes vir; /* making these messages writable is an optimisation * and its return value needn't be checked. */ - vir = arch_vir2map(vmc, msgaddr); + vir = msgaddr; if (handle_memory(vmc, vir, sizeof(message), 1) != OK) panic("do_fork: handle_memory for child failed\n"); - vir = arch_vir2map(vmp, msgaddr); + vir = msgaddr; if (handle_memory(vmp, vir, sizeof(message), 1) != OK) panic("do_fork: handle_memory for parent failed\n"); } diff --git a/servers/vm/glo.h b/servers/vm/glo.h index 8616f79a6..e0ba5366f 100644 --- a/servers/vm/glo.h +++ b/servers/vm/glo.h @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -12,12 +13,13 @@ #define EXTERN #endif -#define VMP_SYSTEM _NR_PROCS -#define VMP_EXECTMP _NR_PROCS+1 -#define VMP_NR _NR_PROCS+2 +#define VMP_EXECTMP _NR_PROCS +#define VMP_NR _NR_PROCS+1 EXTERN struct vmproc vmproc[VMP_NR]; +EXTERN kinfo_t kernel_boot_info; + #if SANITYCHECKS EXTERN int nocheck; EXTERN int incheck; diff --git a/servers/vm/main.c b/servers/vm/main.c index 9acc02b0c..4023ea4d6 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include #include @@ -38,6 +40,7 @@ extern int missing_spares; #include +#include #include "kernel/const.h" #include "kernel/config.h" #include "kernel/proc.h" @@ -60,12 +63,13 @@ struct { static int map_service(struct rprocpub *rpub); static int vm_acl_ok(endpoint_t caller, int call); +static int do_rs_init(message *m); /* SEF functions and variables. */ -static void sef_local_startup(void); -static int sef_cb_init_fresh(int type, sef_init_info_t *info); static void sef_cb_signal_handler(int signo); +void init_vm(void); + /*===========================================================================* * main * *===========================================================================*/ @@ -76,8 +80,15 @@ int main(void) int caller_slot; struct vmproc *vmp_caller; - /* SEF local startup. */ - sef_local_startup(); + /* Initialize system so that all processes are runnable */ + init_vm(); + + /* Register init callbacks. */ + sef_setcb_init_restart(sef_cb_init_fail); + sef_setcb_signal_handler(sef_cb_signal_handler); + + /* Let SEF perform startup. */ + sef_startup(); SANITYCHECK(SCL_TOP); @@ -100,11 +111,14 @@ int main(void) } who_e = msg.m_source; if(vm_isokendpt(who_e, &caller_slot) != OK) - panic("invalid caller", who_e); + panic("invalid caller %d", who_e); vmp_caller = &vmproc[caller_slot]; c = CALLNUMBER(msg.m_type); result = ENOSYS; /* Out of range or restricted calls return this. */ - if (msg.m_type == VM_PAGEFAULT) { + + if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) { + result = do_rs_init(&msg); + } else if (msg.m_type == VM_PAGEFAULT) { if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) { printf("VM: process %d faked VM_PAGEFAULT " "message!\n", msg.m_source); @@ -145,56 +159,173 @@ int main(void) return(OK); } -/*===========================================================================* - * sef_local_startup * - *===========================================================================*/ -static void sef_local_startup() +static int do_rs_init(message *m) { - /* Register init callbacks. */ - sef_setcb_init_fresh(sef_cb_init_fresh); - sef_setcb_init_restart(sef_cb_init_fail); + int s, i; + static struct rprocpub rprocpub[NR_BOOT_PROCS]; - /* No live update support for now. */ + /* Map all the services in the boot image. */ + if((s = sys_safecopyfrom(RS_PROC_NR, m->RS_INIT_RPROCTAB_GID, 0, + (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { + panic("vm: sys_safecopyfrom (rs) failed: %d", s); + } - /* Register signal callbacks. */ - sef_setcb_signal_handler(sef_cb_signal_handler); + for(i=0;i < NR_BOOT_PROCS;i++) { + if(rprocpub[i].in_use) { + if((s = map_service(&rprocpub[i])) != OK) { + panic("unable to map service: %d", s); + } + } + } - /* Let SEF perform startup. */ - sef_startup(); + /* RS expects this response that it then again wants to reply to: */ + m->RS_INIT_RESULT = OK; + sendrec(RS_PROC_NR, m); + + return(SUSPEND); } -/*===========================================================================* - * sef_cb_init_fresh * - *===========================================================================*/ -static int sef_cb_init_fresh(int type, sef_init_info_t *info) +struct vmproc *init_proc(endpoint_t ep_nr) { -/* Initialize the vm server. */ - int s, i; - struct memory mem_chunks[NR_MEMS]; - struct boot_image image[NR_BOOT_PROCS]; + static struct boot_image *ip; + + for (ip = &kernel_boot_info.boot_procs[0]; + ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { + struct vmproc *vmp; + + if(ip->proc_nr != ep_nr) continue; + + if(ip->proc_nr >= _NR_PROCS || ip->proc_nr < 0) + panic("proc: %d", ip->proc_nr); + + vmp = &vmproc[ip->proc_nr]; + assert(!(vmp->vm_flags & VMF_INUSE)); /* no double procs */ + clear_proc(vmp); + vmp->vm_flags = VMF_INUSE; + vmp->vm_endpoint = ip->endpoint; + vmp->vm_boot = ip; + + return vmp; + } + + panic("no init_proc"); +} + +struct vm_exec_info { + struct exec_info execi; struct boot_image *ip; - struct rprocpub rprocpub[NR_BOOT_PROCS]; - phys_bytes limit = 0; - int is_elf = 0; + struct vmproc *vmp; +}; + +static int libexec_copy_physcopy(struct exec_info *execi, + off_t off, off_t vaddr, size_t len) +{ + vir_bytes end; + struct vm_exec_info *ei = execi->opaque; + end = ei->ip->start_addr + ei->ip->len; + assert(ei->ip->start_addr + off + len <= end); + return sys_physcopy(NONE, ei->ip->start_addr + off, + execi->proc_e, vaddr, len); +} + +static void boot_alloc(struct exec_info *execi, off_t vaddr, + size_t len, int flags) +{ + struct vmproc *vmp = ((struct vm_exec_info *) execi->opaque)->vmp; + + if(!(map_page_region(vmp, vaddr, 0, + len, MAP_NONE, VR_ANON | VR_WRITABLE | VR_UNINITIALIZED, flags))) { + panic("VM: exec: map_page_region for boot process failed"); + } +} + +static int libexec_alloc_vm_prealloc(struct exec_info *execi, + off_t vaddr, size_t len) +{ + boot_alloc(execi, vaddr, len, MF_PREALLOC); + return OK; +} + +static int libexec_alloc_vm_ondemand(struct exec_info *execi, + off_t vaddr, size_t len) +{ + boot_alloc(execi, vaddr, len, 0); + return OK; +} + +void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) +{ + struct vm_exec_info vmexeci; + struct exec_info *execi = &vmexeci.execi; + char hdr[VM_PAGE_SIZE]; + + memset(&vmexeci, 0, sizeof(vmexeci)); + + if(pt_new(&vmp->vm_pt) != OK) + panic("VM: no new pagetable"); + + if(pt_bind(&vmp->vm_pt, vmp) != OK) + panic("VM: pt_bind failed"); + + if(sys_physcopy(NONE, ip->start_addr, SELF, + (vir_bytes) hdr, sizeof(hdr)) != OK) + panic("can't look at boot proc header"); + + execi->stack_high = kernel_boot_info.user_sp; + execi->stack_size = DEFAULT_STACK_LIMIT; + execi->proc_e = vmp->vm_endpoint; + execi->hdr = hdr; + execi->hdr_len = sizeof(hdr); + strcpy(execi->progname, ip->proc_name); + execi->frame_len = 0; + execi->opaque = &vmexeci; + + vmexeci.ip = ip; + vmexeci.vmp = vmp; + + /* callback functions and data */ + execi->copymem = libexec_copy_physcopy; + execi->clearproc = NULL; + execi->clearmem = libexec_clear_sys_memset; + execi->allocmem_prealloc = libexec_alloc_vm_prealloc; + execi->allocmem_ondemand = libexec_alloc_vm_ondemand; + + if(libexec_load_elf(execi) != OK) + panic("vm: boot process load of %d failed\n", vmp->vm_endpoint); + + if(sys_exec(vmp->vm_endpoint, (char *) execi->stack_high - 12, + (char *) ip->proc_name, execi->pc) != OK) + panic("vm: boot process exec of %d failed\n", vmp->vm_endpoint); +} + +void init_vm(void) +{ + int s, i; + static struct memory mem_chunks[NR_MEMS]; + static struct boot_image *ip; #if SANITYCHECKS incheck = nocheck = 0; #endif + /* Retrieve various crucial boot parameters */ + if(OK != (s=sys_getkinfo(&kernel_boot_info))) { + panic("couldn't get bootinfo: %d", s); + } + + /* Sanity check */ + assert(kernel_boot_info.mmap_size > 0); + assert(kernel_boot_info.mods_with_kernel > 0); + #if SANITYCHECKS env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX); + + vm_sanitychecklevel = 1; #endif /* Get chunks of available memory. */ get_mem_chunks(mem_chunks); - /* Initialize VM's process table. Request a copy of the system - * image table that is defined at the kernel level to see which - * slots to fill in. - */ - if (OK != (s=sys_getimage(image))) - panic("couldn't get image table: %d", s); - /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ memset(vmproc, 0, sizeof(vmproc)); @@ -202,122 +333,40 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info) vmproc[i].vm_slot = i; } - /* Walk through boot-time system processes that are alive - * now and make valid slot entries for them. - */ - for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) { - phys_bytes proclimit; - struct vmproc *vmp; - - if(ip->proc_nr >= _NR_PROCS) { panic("proc: %d", ip->proc_nr); } - if(ip->proc_nr < 0 && ip->proc_nr != SYSTEM) continue; - -#define GETVMP(v, nr) \ - if(nr >= 0) { \ - vmp = &vmproc[ip->proc_nr]; \ - } else if(nr == SYSTEM) { \ - vmp = &vmproc[VMP_SYSTEM]; \ - } else { \ - panic("init: crazy proc_nr: %d", nr); \ - } - - /* Initialize normal process table slot or special SYSTEM - * table slot. Kernel memory is already reserved. - */ - GETVMP(vmp, ip->proc_nr); - - /* reset fields as if exited */ - clear_proc(vmp); - - /* Get memory map for this process from the kernel. */ - if ((s=get_mem_map(ip->proc_nr, vmp->vm_arch.vm_seg)) != OK) - panic("couldn't get process mem_map: %d", s); - - /* Remove this memory from the free list. */ - reserve_proc_mem(mem_chunks, vmp->vm_arch.vm_seg); - - /* Set memory limit. */ - proclimit = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys + - vmp->vm_arch.vm_seg[S].mem_len) - 1; - - if(proclimit > limit) - limit = proclimit; - - vmp->vm_flags = VMF_INUSE; - vmp->vm_endpoint = ip->endpoint; - vmp->vm_stacktop = - CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir + - vmp->vm_arch.vm_seg[S].mem_len); - - if (vmp->vm_arch.vm_seg[T].mem_len != 0) - vmp->vm_flags |= VMF_SEPARATE; - } - /* region management initialization. */ map_region_init(); /* Architecture-dependent initialization. */ - pt_init(limit); + init_proc(VM_PROC_NR); + pt_init(); /* Initialize tables to all physical memory. */ mem_init(mem_chunks); meminit_done = 1; - /* Architecture-dependent memory initialization. */ - pt_init_mem(); - /* Give these processes their own page table. */ - for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) { + for (ip = &kernel_boot_info.boot_procs[0]; + ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { struct vmproc *vmp; - vir_bytes old_stacktop, old_stacklen; if(ip->proc_nr < 0) continue; - GETVMP(vmp, ip->proc_nr); + assert(ip->start_addr); - if(!(ip->flags & PROC_FULLVM)) - continue; + /* VM has already been set up by the kernel and pt_init(). + * Any other boot process is already in memory and is set up + * here. + */ + if(ip->proc_nr == VM_PROC_NR) continue; - if(pt_new(&vmp->vm_pt) != OK) - panic("VM: no new pagetable"); -#define BASICSTACK VM_PAGE_SIZE - old_stacktop = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir + - vmp->vm_arch.vm_seg[S].mem_len); - if(sys_vmctl(vmp->vm_endpoint, VMCTL_INCSP, - VM_STACKTOP - old_stacktop) != OK) { - panic("VM: vmctl for new stack failed"); - } + vmp = init_proc(ip->proc_nr); - old_stacklen = - vmp->vm_arch.vm_seg[S].mem_vir + - vmp->vm_arch.vm_seg[S].mem_len - - vmp->vm_arch.vm_seg[D].mem_len - - vmp->vm_arch.vm_seg[D].mem_vir; + exec_bootproc(vmp, ip); - free_mem(vmp->vm_arch.vm_seg[D].mem_phys + - vmp->vm_arch.vm_seg[D].mem_len, - old_stacklen); - -#if defined(__ELF__) - is_elf = 1; -#endif - - if(proc_new(vmp, - VM_PROCSTART, - CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_vir), - CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_len), - CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_vir), - CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_len), - BASICSTACK, - CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir + - vmp->vm_arch.vm_seg[S].mem_len - - vmp->vm_arch.vm_seg[D].mem_len - - vmp->vm_arch.vm_seg[D].mem_vir) - BASICSTACK, - CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys), - CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys), - VM_STACKTOP, 0, is_elf, 0) != OK) { - panic("failed proc_new for boot process"); - } + /* Free the file blob */ + assert(!(ip->start_addr % VM_PAGE_SIZE)); + ip->len = roundup(ip->len, VM_PAGE_SIZE); + free_mem(ABS2CLICK(ip->start_addr), ABS2CLICK(ip->len)); } /* Set up table of calls. */ @@ -372,27 +421,8 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info) CALLMAP(VM_FORGETBLOCK, do_forgetblock); CALLMAP(VM_YIELDBLOCKGETBLOCK, do_yieldblockgetblock); - /* Sanity checks */ - if(find_kernel_top() >= VM_PROCSTART) - panic("kernel loaded too high"); - /* Initialize the structures for queryexit */ init_query_exit(); - - /* Map all the services in the boot image. */ - if((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, - (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { - panic("sys_safecopyfrom failed: %d", s); - } - for(i=0;i < NR_BOOT_PROCS;i++) { - if(rprocpub[i].in_use) { - if((s = map_service(&rprocpub[i])) != OK) { - panic("unable to map service: %d", s); - } - } - } - - return(OK); } /*===========================================================================* diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index 2110cccda..a54f9b2b4 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -62,9 +62,6 @@ int do_mmap(message *m) vmp = &vmproc[n]; - if(!(vmp->vm_flags & VMF_HASPT)) - return ENXIO; - if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANON)) { u32_t vrflags = VR_ANON | VR_WRITABLE; size_t len = (vir_bytes) m->VMM_LEN; @@ -102,7 +99,7 @@ int do_mmap(message *m) vr = NULL; if (m->VMM_ADDR || (m->VMM_FLAGS & MAP_FIXED)) { /* An address is given, first try at that address. */ - addr = arch_vir2map(vmp, m->VMM_ADDR); + addr = m->VMM_ADDR; vr = map_page_region(vmp, addr, 0, len, MAP_NONE, vrflags, mfflags); if(!vr && (m->VMM_FLAGS & MAP_FIXED)) @@ -110,8 +107,7 @@ int do_mmap(message *m) } if (!vr) { /* No address given or address already in use. */ - addr = arch_vir2map(vmp, vmp->vm_stacktop); - vr = map_page_region(vmp, addr, VM_DATATOP, len, + vr = map_page_region(vmp, 0, VM_DATATOP, len, MAP_NONE, vrflags, mfflags); } if (!vr) { @@ -123,7 +119,7 @@ int do_mmap(message *m) /* Return mapping, as seen from process. */ assert(vr); - m->VMM_RETADDR = arch_map2vir(vmp, vr->vaddr); + m->VMM_RETADDR = vr->vaddr; return OK; @@ -194,9 +190,6 @@ int do_map_phys(message *m) vmp = &vmproc[n]; - if(!(vmp->vm_flags & VMF_HASPT)) - return ENXIO; - offset = startaddr % VM_PAGE_SIZE; len += offset; startaddr -= offset; @@ -204,13 +197,12 @@ int do_map_phys(message *m) if(len % VM_PAGE_SIZE) len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE); - if(!(vr = map_page_region(vmp, arch_vir2map(vmp, vmp->vm_stacktop), - VM_DATATOP, len, startaddr, + if(!(vr = map_page_region(vmp, 0, VM_DATATOP, len, startaddr, VR_DIRECT | VR_NOPF | VR_WRITABLE, 0))) { return ENOMEM; } - m->VMMP_VADDR_REPLY = (void *) (arch_map2vir(vmp, vr->vaddr) + offset); + m->VMMP_VADDR_REPLY = (void *) (vr->vaddr + offset); return OK; } @@ -234,8 +226,7 @@ int do_unmap_phys(message *m) vmp = &vmproc[n]; - if(!(region = map_lookup(vmp, - arch_vir2map(vmp, (vir_bytes) m->VMUM_ADDR)))) { + if(!(region = map_lookup(vmp, (vir_bytes) m->VMUM_ADDR))) { return EINVAL; } @@ -289,8 +280,6 @@ int do_remap(message *m) * about whether the user needs to bind to * THAT address or be chosen by the system. */ - sa = arch_vir2map(svmp, sa); - if (!(region = map_lookup(svmp, sa))) return EINVAL; @@ -315,7 +304,7 @@ int do_remap(message *m) if ((r = map_remap(dvmp, da, size, region, &startv, readonly)) != OK) return r; - m->VMRE_RETA = (char *) arch_map2vir(dvmp, startv); + m->VMRE_RETA = (char *) startv; return OK; } @@ -339,7 +328,7 @@ int do_shared_unmap(message *m) vmp = &vmproc[n]; - addr = arch_vir2map(vmp, m->VMUN_ADDR); + addr = m->VMUN_ADDR; if(!(vr = map_lookup(vmp, addr))) { printf("VM: addr 0x%lx not found.\n", m->VMUN_ADDR); @@ -380,7 +369,6 @@ int do_get_phys(message *m) return EINVAL; vmp = &vmproc[n]; - addr = arch_vir2map(vmp, addr); r = map_get_phys(vmp, addr, &ret); @@ -406,7 +394,6 @@ int do_get_refcount(message *m) return EINVAL; vmp = &vmproc[n]; - addr = arch_vir2map(vmp, addr); r = map_get_ref(vmp, addr, &cnt); @@ -430,13 +417,10 @@ int do_munmap(message *m) vmp = &vmproc[n]; - if(!(vmp->vm_flags & VMF_HASPT)) - return ENXIO; - if(m->m_type == VM_MUNMAP) { - addr = (vir_bytes) arch_vir2map(vmp, (vir_bytes) m->VMUM_ADDR); + addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR; } else if(m->m_type == VM_MUNMAP_TEXT) { - addr = (vir_bytes) arch_vir2map_text(vmp, (vir_bytes) m->VMUM_ADDR); + addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR; } else { panic("do_munmap: strange type"); } @@ -495,7 +479,7 @@ int minix_munmap(void *addr, size_t len) vir_bytes laddr; if(!unmap_ok) return ENOSYS; - laddr = (vir_bytes) arch_vir2map(&vmproc[VM_PROC_NR], (vir_bytes) addr); + laddr = (vir_bytes) (vir_bytes) addr; return munmap_lin(laddr, len); } @@ -507,8 +491,7 @@ int minix_munmap_text(void *addr, size_t len) vir_bytes laddr; if(!unmap_ok) return ENOSYS; - laddr = (vir_bytes) arch_vir2map_text(&vmproc[VM_PROC_NR], - (vir_bytes) addr); + laddr = (vir_bytes) addr; return munmap_lin(laddr, len); } diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c index ed0aeae62..6b2f0ebab 100644 --- a/servers/vm/pagefaults.c +++ b/servers/vm/pagefaults.c @@ -72,8 +72,8 @@ void do_pagefaults(message *m) /* See if address is valid at all. */ if(!(region = map_lookup(vmp, addr))) { assert(PFERR_NOPAGE(err)); - printf("VM: pagefault: SIGSEGV %d bad addr %s; %s\n", - ep, arch_map2str(vmp, addr), pf_errstr(err)); + printf("VM: pagefault: SIGSEGV %d bad addr 0x%x; %s\n", + ep, addr, pf_errstr(err)); if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK) panic("sys_kill failed: %d", s); if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK) @@ -88,8 +88,8 @@ void do_pagefaults(message *m) /* If process was writing, see if it's writable. */ if(!(region->flags & VR_WRITABLE) && wr) { - printf("VM: pagefault: SIGSEGV %d ro map 0x%lx %s\n", - ep, arch_map2vir(vmp, addr), pf_errstr(err)); + printf("VM: pagefault: SIGSEGV %d ro map 0x%x %s\n", + ep, addr, pf_errstr(err)); if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK) panic("sys_kill failed: %d", s); if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK) @@ -203,8 +203,7 @@ int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag) if(r != OK) { #if VERBOSE printf("VM: memory range 0x%lx-0x%lx not available in %d\n", - arch_map2vir(vmp, mem), arch_map2vir(vmp, mem+len), - vmp->vm_endpoint); + mem, mem+len, vmp->vm_endpoint); #endif return r; } diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 8cc9a2e37..01d9a7c1e 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -2,7 +2,6 @@ struct vmproc; struct stat; -struct mem_map; struct memory; struct vir_region; struct phys_region; @@ -19,6 +18,7 @@ struct phys_region; #include "yielded.h" /* alloc.c */ +void mem_sanitycheck(char *file, int line); phys_clicks alloc_mem(phys_clicks clicks, u32_t flags); struct memlist *alloc_mem_in_list(phys_bytes bytes, u32_t flags); int do_adddma(message *msg); @@ -38,7 +38,6 @@ void print_mem_list(struct memlist *ml); void mem_init(struct memory *chunks); /* utility.c */ -int get_mem_map(int proc_nr, struct mem_map *mem_map); void get_mem_chunks(struct memory *mem_chunks); void reserve_proc_mem(struct memory *mem_chunks, struct mem_map *map_ptr); @@ -58,15 +57,6 @@ void free_proc(struct vmproc *vmp); /* fork.c */ int do_fork(message *msg); -/* exec.c */ -int do_exec_newmem(message *msg); -int proc_new(struct vmproc *vmp, phys_bytes start, phys_bytes text_addr, - phys_bytes text_bytes, phys_bytes data_addr, phys_bytes data_bytes, - phys_bytes stack, phys_bytes gap, phys_bytes text_here, phys_bytes - data_here, vir_bytes stacktop, int prealloc_stack, int is_elf, int full); -phys_bytes find_kernel_top(void); -void regular_segs(struct vmproc *); - /* break.c */ int do_brk(message *msg); int adjust(struct vmproc *rmp, vir_clicks data_clicks, vir_bytes sp); @@ -99,7 +89,7 @@ int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag); /* $(ARCH)/pagetable.c */ -void pt_init(phys_bytes limit); +void pt_init(); void pt_init_mem(void); void pt_check(struct vmproc *vmp); int pt_new(pt_t *pt); @@ -192,15 +182,6 @@ int do_forgetblock(message *m); int do_yieldblockgetblock(message *m); vir_bytes free_yielded(vir_bytes bytes); -/* $(ARCH)/vm.c */ -vir_bytes arch_map2vir(struct vmproc *vmp, vir_bytes addr); -char *arch_map2str(struct vmproc *vmp, vir_bytes addr); -vir_bytes arch_map2info(struct vmproc *vmp, vir_bytes addr, int *space, - int *prot); -vir_bytes arch_vir2map(struct vmproc *vmp, vir_bytes addr); -vir_bytes arch_vir2map_text(struct vmproc *vmp, vir_bytes addr); -vir_bytes arch_addrok(struct vmproc *vmp, vir_bytes addr); - /* rs.c */ int do_rs_set_priv(message *m); int do_rs_update(message *m); diff --git a/servers/vm/region.c b/servers/vm/region.c index e31510729..a7edf1464 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -133,14 +133,13 @@ void map_printregion(struct vmproc *vmp, struct vir_region *vr) physr_iter iter; struct phys_region *ph; printf("map_printmap: map_name: %s\n", map_name(vr)); - printf("\t%s (len 0x%lx, %lukB), %s\n", - arch_map2str(vmp, vr->vaddr), vr->length, - vr->length/1024, map_name(vr)); + printf("\t%lx (len 0x%lx, %lukB), %p\n", + vr->vaddr, vr->length, vr->length/1024, map_name(vr)); printf("\t\tphysblocks:\n"); physr_start_iter_least(vr->phys, &iter); while((ph = physr_get_iter(&iter))) { - printf("\t\t@ %s (refs %d): phys 0x%lx len 0x%lx\n", - arch_map2str(vmp, vr->vaddr + ph->offset), + printf("\t\t@ %lx (refs %d): phys 0x%lx len 0x%lx\n", + (vr->vaddr + ph->offset), ph->ph->refcount, ph->ph->phys, ph->ph->length); physr_incr_iter(&iter); } @@ -194,9 +193,6 @@ static int map_sanitycheck_pt(struct vmproc *vmp, int rw; int r; - if(!(vmp->vm_flags & VMF_HASPT)) - return OK; - if(WRITABLE(vr, pb)) rw = PTF_WRITE; else @@ -406,7 +402,7 @@ static int map_ph_writept(struct vmproc *vmp, struct vir_region *vr, static vir_bytes region_find_slot_range(struct vmproc *vmp, vir_bytes minv, vir_bytes maxv, vir_bytes length) { - struct vir_region *firstregion; + struct vir_region *lastregion; vir_bytes startv = 0; int foundflag = 0; region_iter iter; @@ -439,40 +435,50 @@ static vir_bytes region_find_slot_range(struct vmproc *vmp, assert(minv < maxv); assert(minv + length <= maxv); -#define FREEVRANGE(rangestart, rangeend) { \ +#define FREEVRANGE_TRY(rangestart, rangeend) { \ vir_bytes frstart = (rangestart), frend = (rangeend); \ frstart = MAX(frstart, minv); \ frend = MIN(frend, maxv); \ if(frend > frstart && (frend - frstart) >= length) { \ - startv = frstart; \ + startv = frend-length; \ foundflag = 1; \ } } - /* find region before minv. */ - region_start_iter(&vmp->vm_regions_avl, &iter, minv, AVL_LESS_EQUAL); - firstregion = region_get_iter(&iter); +#define FREEVRANGE(start, end) { \ + assert(!foundflag); \ + FREEVRANGE_TRY(((start)+VM_PAGE_SIZE), ((end)-VM_PAGE_SIZE)); \ + if(!foundflag) { \ + FREEVRANGE_TRY((start), (end)); \ + } \ +} - if(!firstregion) { - /* This is the free virtual address space before the first region. */ - region_start_iter(&vmp->vm_regions_avl, &iter, minv, AVL_GREATER_EQUAL); - firstregion = region_get_iter(&iter); - FREEVRANGE(0, firstregion ? firstregion->vaddr : VM_DATATOP); + /* find region after maxv. */ + region_start_iter(&vmp->vm_regions_avl, &iter, maxv, AVL_GREATER_EQUAL); + lastregion = region_get_iter(&iter); + + if(!lastregion) { + /* This is the free virtual address space after the last region. */ + region_start_iter(&vmp->vm_regions_avl, &iter, maxv, AVL_LESS); + lastregion = region_get_iter(&iter); + FREEVRANGE(lastregion ? + lastregion->vaddr+lastregion->length : 0, VM_DATATOP); } if(!foundflag) { struct vir_region *vr; while((vr = region_get_iter(&iter)) && !foundflag) { struct vir_region *nextvr; - region_incr_iter(&iter); + region_decr_iter(&iter); nextvr = region_get_iter(&iter); - FREEVRANGE(vr->vaddr + vr->length, - nextvr ? nextvr->vaddr : VM_DATATOP); + FREEVRANGE(nextvr ? nextvr->vaddr+nextvr->length : 0, + vr->vaddr); } } if(!foundflag) { printf("VM: region_find_slot: no 0x%lx bytes found for %d between 0x%lx and 0x%lx\n", length, vmp->vm_endpoint, minv, maxv); + util_stacktrace(); return SLOT_FAIL; } @@ -500,7 +506,7 @@ static vir_bytes region_find_slot(struct vmproc *vmp, */ if(maxv && hint < maxv && hint >= minv) { - v = region_find_slot_range(vmp, hint, maxv, length); + v = region_find_slot_range(vmp, minv, hint, length); if(v != SLOT_FAIL) return v; @@ -530,6 +536,11 @@ int mapflags; SANITYCHECK(SCL_FUNCTIONS); + if((flags & VR_CONTIG) && !(mapflags & MF_PREALLOC)) { + printf("map_page_region: can't make contiguous allocation without preallocating\n"); + return NULL; + } + startv = region_find_slot(vmp, minv, maxv, length); if (startv == SLOT_FAIL) return NULL; @@ -977,7 +988,10 @@ int written; if((region->flags & VR_CONTIG) && (start_offset > 0 || length < region->length)) { - printf("VM: map_new_physblock: non-full allocation requested\n"); + printf("VM: region length 0x%lx, offset 0x%lx length 0x%lx\n", + region->length, start_offset, length); + map_printmap(vmp); + printf("VM: map_new_physblock: non-full contig allocation requested\n"); return EFAULT; } @@ -1379,8 +1393,8 @@ int write; #if SANITYCHECKS if(OK != pt_checkrange(&vmp->vm_pt, region->vaddr+offset, length, write)) { - printf("handle mem %s-", arch_map2str(vmp, region->vaddr+offset)); - printf("%s failed\n", arch_map2str(vmp, region->vaddr+offset+length)); + printf("handle mem 0x%lx-0x%lx failed\n", + region->vaddr+offset,region->vaddr+offset+length); map_printregion(vmp, region); panic("checkrange failed"); } @@ -1647,46 +1661,13 @@ struct vir_region *start_src_vr; return OK; } -/*========================================================================* - * map_proc_kernel * - *========================================================================*/ -struct vir_region *map_proc_kernel(struct vmproc *vmp) -{ - struct vir_region *vr; - - /* We assume these are the first regions to be mapped to - * make the function a bit simpler (free all regions on error). - */ - assert(!region_search_root(&vmp->vm_regions_avl)); - assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE); - assert(!(KERNEL_TEXT % VM_PAGE_SIZE)); - assert(!(KERNEL_TEXT_LEN % VM_PAGE_SIZE)); - assert(!(KERNEL_DATA % VM_PAGE_SIZE)); - assert(!(KERNEL_DATA_LEN % VM_PAGE_SIZE)); - - if(!(vr = map_page_region(vmp, KERNEL_TEXT, 0, KERNEL_TEXT_LEN, - KERNEL_TEXT, VR_DIRECT | VR_WRITABLE | VR_NOPF, 0)) || - !(vr = map_page_region(vmp, KERNEL_DATA, 0, KERNEL_DATA_LEN, - KERNEL_DATA, VR_DIRECT | VR_WRITABLE | VR_NOPF, 0))) { - map_free_proc(vmp); - return NULL; - } - - return vr; /* Return pointer not useful, just non-NULL. */ -} - int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes v) { - vir_bytes offset, o, end; + vir_bytes offset = v, end; struct vir_region *vr, *nextvr; + int r = OK; - offset = arch_vir2map(vmp, v); - - if((o=(offset % VM_PAGE_SIZE))) { - offset+= VM_PAGE_SIZE - o; - } - - if(!(vr = region_search(&vmp->vm_regions_avl, offset, AVL_LESS_EQUAL))) { + if(!(vr = region_search(&vmp->vm_regions_avl, offset, AVL_LESS))) { printf("VM: nothing to extend\n"); return ENOMEM; } @@ -1698,17 +1679,17 @@ int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes v) assert(vr->vaddr <= offset); if((nextvr = getnextvr(vr))) { - assert(offset < nextvr->vaddr); + assert(offset <= nextvr->vaddr); } end = vr->vaddr + vr->length; - if(offset < end) - return map_region_shrink(vr, end - offset); + offset = roundup(offset, VM_PAGE_SIZE); - return map_region_extend(vmp, vr, offset - end); + if(end < offset) + r = map_region_extend(vmp, vr, offset - end); - return ENOMEM; + return r; } /*========================================================================* @@ -1723,6 +1704,10 @@ int map_region_extend(struct vmproc *vmp, struct vir_region *vr, assert(vr); assert(vr->flags & VR_ANON); assert(!(delta % VM_PAGE_SIZE)); + if(vr->flags & VR_CONTIG) { + printf("VM: can't grow contig region\n"); + return EFAULT; + } if(!delta) return OK; end = vr->vaddr + vr->length; @@ -1868,10 +1853,9 @@ int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size, /* da is handled differently */ if (!da) - dst_addr = dvmp->vm_stacktop; + dst_addr = 0; else dst_addr = da; - dst_addr = arch_vir2map(dvmp, dst_addr); /* round up to page size */ assert(!(size % VM_PAGE_SIZE)); @@ -2054,8 +2038,8 @@ int get_region_info(struct vmproc *vmp, struct vm_region_info *vri, if(!ph1 || !ph2) { assert(!ph1 && !ph2); continue; } /* Report start+length of region starting from lowest use. */ - vri->vri_addr = arch_map2info(vmp, vr->vaddr + ph1->offset, - &vri->vri_seg, &vri->vri_prot); + vri->vri_addr = vr->vaddr + ph1->offset; + vri->vri_prot = 0; vri->vri_length = ph2->offset + ph2->ph->length - ph1->offset; /* "AND" the provided protection with per-page protection. */ @@ -2434,7 +2418,7 @@ get_clean_phys_region(struct vmproc *vmp, vir_bytes vaddr, vir_bytes length, vir_bytes regionoffset, mapaddr; struct phys_region *ph; - mapaddr = arch_vir2map(vmp, vaddr); + mapaddr = vaddr; if(!(region = map_lookup(vmp, mapaddr))) { printf("VM: get_clean_phys_region: 0x%lx not found\n", vaddr); @@ -2638,11 +2622,6 @@ int do_forgetblocks(message *m) vmp = &vmproc[n]; - if(!(vmp->vm_flags & VMF_HASPT)) { - printf("do_forgetblocks: no pt\n"); - return EFAULT; - } - free_yielded_proc(vmp); return OK; @@ -2667,11 +2646,6 @@ int do_forgetblock(message *m) vmp = &vmproc[n]; - if(!(vmp->vm_flags & VMF_HASPT)) { - printf("do_forgetblock: no pt\n"); - return EFAULT; - } - id = make64(m->VMFB_IDLO, m->VMFB_IDHI); blockid.id = id; @@ -2703,11 +2677,6 @@ int do_yieldblockgetblock(message *m) vmp = &vmproc[n]; - if(!(vmp->vm_flags & VMF_HASPT)) { - printf("do_yieldblockgetblock: no pt\n"); - return EFAULT; - } - len = m->VMYBGB_LEN; if((len % VM_PAGE_SIZE)) { diff --git a/servers/vm/rs.c b/servers/vm/rs.c index 6a126483a..e41e80d17 100644 --- a/servers/vm/rs.c +++ b/servers/vm/rs.c @@ -124,10 +124,6 @@ static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp) this_vm_vmp = &vmproc[VM_PROC_NR]; - /* Copy settings from current VM. */ - new_vm_vmp->vm_stacktop = this_vm_vmp->vm_stacktop; - new_vm_vmp->vm_arch.vm_data_top = this_vm_vmp->vm_arch.vm_data_top; - /* Pin memory for the new VM instance. */ r = map_pin_memory(new_vm_vmp); if(r != OK) { diff --git a/servers/vm/sanitycheck.h b/servers/vm/sanitycheck.h index 60c8a1eb6..a3f7d7fd2 100644 --- a/servers/vm/sanitycheck.h +++ b/servers/vm/sanitycheck.h @@ -24,14 +24,15 @@ usedpages_reset(); \ slab_sanitycheck(__FILE__, __LINE__); \ for(vmpr = vmproc; vmpr < &vmproc[VMP_NR]; vmpr++) { \ - if((vmpr->vm_flags & (VMF_INUSE | VMF_HASPT)) == \ - (VMF_INUSE | VMF_HASPT)) { \ + if((vmpr->vm_flags & (VMF_INUSE))) { \ PT_SANE(&vmpr->vm_pt); \ } \ } \ map_sanitycheck(__FILE__, __LINE__); \ + mem_sanitycheck(__FILE__, __LINE__); \ assert(incheck == 1); \ incheck = 0; \ + /* printf("(%s:%d OK) ", __FILE__, __LINE__); */ \ } #define SLABSANE(ptr) { \ diff --git a/servers/vm/slaballoc.c b/servers/vm/slaballoc.c index fecb86ee2..1711a318c 100644 --- a/servers/vm/slaballoc.c +++ b/servers/vm/slaballoc.c @@ -552,7 +552,7 @@ void slabunlock(void *mem, int bytes) *===========================================================================*/ void slabstats(void) { - int s, total = 0, totalbytes = 0; + int s, totalbytes = 0; static int n; n++; if(n%1000) return; diff --git a/servers/vm/utility.c b/servers/vm/utility.c index 691d1807d..a02a38ee5 100644 --- a/servers/vm/utility.c +++ b/servers/vm/utility.c @@ -38,23 +38,6 @@ #include "kernel/type.h" #include "kernel/proc.h" -/*===========================================================================* - * get_mem_map * - *===========================================================================*/ -int get_mem_map(proc_nr, mem_map) -int proc_nr; /* process to get map of */ -struct mem_map *mem_map; /* put memory map here */ -{ - struct proc p; - int s; - - if ((s=sys_getproc(&p, proc_nr)) != OK) - return(s); - - memcpy(mem_map, p.p_memmap, sizeof(p.p_memmap)); - return(OK); -} - /*===========================================================================* * get_mem_chunks * *===========================================================================*/ @@ -89,6 +72,7 @@ struct memory *mem_chunks; /* store mem chunks here */ } } +#if 0 /*===========================================================================* * reserve_proc_mem * *===========================================================================*/ @@ -135,6 +119,7 @@ struct mem_map *map_ptr; /* memory to remove */ map_ptr[T].mem_phys); } } +#endif /*===========================================================================* * vm_isokendpt * @@ -243,7 +228,7 @@ int do_info(message *m) * deadlock. Note that no memory mapping can be undone without the * involvement of VM, so we are safe until we're done. */ - r = handle_memory(vmp, arch_vir2map(vmp, ptr), size, 1 /*wrflag*/); + r = handle_memory(vmp, ptr, size, 1 /*wrflag*/); if (r != OK) return r; /* Now that we know the copy out will succeed, perform the actual copy @@ -305,9 +290,7 @@ int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp) printf("VM: swap_proc_dyn_data: tranferring regions above the stack from old VM (%d) to new VM (%d)\n", src_vmp->vm_endpoint, dst_vmp->vm_endpoint); #endif - assert(src_vmp->vm_stacktop == dst_vmp->vm_stacktop); - r = pt_map_in_range(src_vmp, dst_vmp, - arch_vir2map(src_vmp, src_vmp->vm_stacktop), 0); + r = pt_map_in_range(src_vmp, dst_vmp, VM_STACKTOP, 0); if(r != OK) { printf("swap_proc_dyn_data: pt_map_in_range failed\n"); return r; @@ -329,15 +312,14 @@ int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp) * new instance and prevent state corruption on rollback, we share all * the regions between the two instances as COW. */ - if(!is_vm && (dst_vmp->vm_flags & VMF_HASPT)) { + if(!is_vm) { struct vir_region *vr; - vr = map_lookup(dst_vmp, arch_vir2map(dst_vmp, dst_vmp->vm_stacktop)); - if(vr && !map_lookup(src_vmp, arch_vir2map(src_vmp, src_vmp->vm_stacktop))) { + vr = map_lookup(dst_vmp, VM_STACKTOP); + if(vr && !map_lookup(src_vmp, VM_STACKTOP)) { #if LU_DEBUG printf("VM: swap_proc_dyn_data: tranferring regions above the stack from %d to %d\n", src_vmp->vm_endpoint, dst_vmp->vm_endpoint); #endif - assert(src_vmp->vm_stacktop == dst_vmp->vm_stacktop); r = map_proc_copy_from(src_vmp, dst_vmp, vr); if(r != OK) { return r; diff --git a/servers/vm/vmproc.h b/servers/vm/vmproc.h index 8dd0ed62e..b2ee8fd6f 100644 --- a/servers/vm/vmproc.h +++ b/servers/vm/vmproc.h @@ -3,7 +3,6 @@ #define _VMPROC_H 1 #include -#include #include #include @@ -17,25 +16,15 @@ struct vmproc; typedef void (*callback_t)(struct vmproc *who, message *m); struct vmproc { - struct vm_arch vm_arch; /* architecture-specific data */ int vm_flags; endpoint_t vm_endpoint; - pt_t vm_pt; /* page table data, if VMF_HASPT is set */ - vir_bytes vm_stacktop; /* top of stack as seen from process */ - vir_bytes vm_offset; /* offset of addr 0 for process */ - - /* File identification for cs sharing. */ - ino_t vm_ino; /* inode number of file */ - dev_t vm_dev; /* device number of file system */ - time_t vm_ctime; /* inode changed time */ + pt_t vm_pt; /* page table data */ + struct boot_image *vm_boot; /* if boot time process */ /* Regions in virtual address space. */ region_avl vm_regions_avl; vir_bytes vm_region_top; /* highest vaddr last inserted */ - /* Heap for brk() to extend. */ - struct vir_region *vm_heap; - bitchunk_t vm_call_mask[VM_CALL_MASK_SIZE]; /* State for requests pending to be done to vfs on behalf of @@ -59,12 +48,10 @@ struct vmproc { /* Bits for vm_flags */ #define VMF_INUSE 0x001 /* slot contains a process */ -#define VMF_SEPARATE 0x002 /* separate i&d */ -#define VMF_HASPT 0x004 /* has private page table */ -#define VMF_EXITING 0x008 /* PM is cleaning up this process */ -#define VMF_HAS_DMA 0x010 /* Process directly or indirectly granted +#define VMF_EXITING 0x002 /* PM is cleaning up this process */ +#define VMF_HAS_DMA 0x004 /* Process directly or indirectly granted * DMA buffers. */ -#define VMF_WATCHEXIT 0x020 /* Store in queryexit table */ +#define VMF_WATCHEXIT 0x008 /* Store in queryexit table */ #endif diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index 0fe175f7c..4926f04b3 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -59,7 +59,8 @@ MKDEP_SUFFIXES?= .o .ln # rumpfs_tmpfs rumpfs_udf rumpfs_ufs .for _lib in \ c curses blockdriver chardriver netdriver edit end m sys timers util \ - bz2 l audiodriver exec ddekit devman usb elf bdev sffs hgfs vboxfs + bz2 l audiodriver exec ddekit devman usb elf bdev sffs hgfs vboxfs \ + minc minlib .ifndef LIB${_lib:tu} LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a .MADE: ${LIB${_lib:tu}} # Note: ${DESTDIR} will be expanded diff --git a/share/mk/minix.bootprog.mk b/share/mk/minix.bootprog.mk index 654b0e8ce..36f7397b2 100644 --- a/share/mk/minix.bootprog.mk +++ b/share/mk/minix.bootprog.mk @@ -1,6 +1,4 @@ # MINIX-specific boot program options .include -LDFLAGS+= -Wl,--section-start=.init=0x0 - .include diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 29b4e9042..73183dc34 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -11,6 +11,6 @@ SUBDIR= login indent m4 make mktemp stat tic sed mkdep uniq seq du man \ SUBDIR+= ministat # Minix commands -SUBDIR+= top mkimage +SUBDIR+= top .include diff --git a/usr.bin/mkimage/Makefile b/usr.bin/mkimage/Makefile deleted file mode 100644 index 622d5c909..000000000 --- a/usr.bin/mkimage/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -PROG= mkimage -SRCS= mkimage.c -MAN= - -DPADD+= ${LIBELF} -LDADD+= -lelf - -.include diff --git a/usr.bin/mkimage/mkimage.c b/usr.bin/mkimage/mkimage.c deleted file mode 100644 index 0228ed2aa..000000000 --- a/usr.bin/mkimage/mkimage.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Update physical addresses of boot services - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#define BOOTPROG_LOAD_START 0x01000000ULL - -int nflag = 0; - -int stack_kbytes[] = { - /* ds rs pm sched vfs memory log tty mfs vm pfs init */ - 16, 8125, 32, 32, 16, 8, 32, 16, 128, 128, 128, 64 -}; - -static void usage(void); - -GElf_Addr -update_paddr(int nr, char *fname, GElf_Addr startaddr) -{ - int i, fd; - Elf *e; - size_t n; - - GElf_Phdr phdr; - GElf_Addr endaddr = 0; - - if ((fd = open(fname, O_RDWR, 0)) < 0) - err(EX_NOINPUT, "open \"%s\" failed", fname); - - if ((e = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) - errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1)); - - if (elf_kind(e) != ELF_K_ELF) - errx(EX_DATAERR, "\"%s\" is not an ELF object.", fname); - - if (elf_getphdrnum(e, &n) != 0) - errx(EX_DATAERR, "elf_getphdrnum() failed: %s.", elf_errmsg(-1)); - - for (i = 0; i < n; i++) { - if (gelf_getphdr(e, i, &phdr) != &phdr) - errx(EX_SOFTWARE, "getphdr() failed: %s.", - elf_errmsg(-1)); - - if (phdr.p_type == PT_LOAD) { - phdr.p_paddr = startaddr + phdr.p_vaddr; - - endaddr = round_page(phdr.p_paddr + phdr.p_memsz) - + round_page(stack_kbytes[nr] * 1024); - - if (gelf_update_phdr(e, i, &phdr) < 0) - errx(EX_SOFTWARE, - "gelf_update_phdr failed: %s.", - elf_errmsg(-1)); - } - - } - - if (elf_update(e, ELF_C_WRITE) < 0) - errx(EX_SOFTWARE, "elf_update failed: %s.", elf_errmsg(-1)); - - (void) elf_end(e); - (void) close(fd); - - return endaddr; - -} - -int -main(int argc, char **argv) -{ - int i, ch; - GElf_Addr startaddr; - - startaddr = BOOTPROG_LOAD_START; - - while ((ch = getopt(argc, argv, "n")) != -1) { - switch (ch) { - case 'n': - nflag = 1; - break; - case '?': - default: - usage(); - exit(EX_USAGE); - } - } - argc -= optind; - argv += optind; - - if (argc < 1) - usage(); - - if (elf_version(EV_CURRENT) == EV_NONE) - errx(EX_SOFTWARE, "ELF library intialization failed: %s", - elf_errmsg(-1)); - - startaddr = BOOTPROG_LOAD_START; - for (i = 0; i < argc; i++) { - startaddr = update_paddr(i, argv[i], startaddr); - } - - exit(EX_OK); -} - -static void -usage(void) -{ - (void) fprintf(stderr, "usage: %s [-n] elf1 elf2...\n", getprogname()); -}