From 50e2064049171fb3c6122276ecd0959d1c41eaaf Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 7 May 2012 16:03:35 +0200 Subject: [PATCH] No more intel/minix segments. This commit removes all traces of Minix segments (the text/data/stack memory map abstraction in the kernel) and significance of Intel segments (hardware segments like CS, DS that add offsets to all addressing before page table translation). This ultimately simplifies the memory layout and addressing and makes the same layout possible on non-Intel architectures. There are only two types of addresses in the world now: virtual and physical; even the kernel and processes have the same virtual address space. Kernel and user processes can be distinguished at a glance as processes won't use 0xF0000000 and above. No static pre-allocated memory sizes exist any more. Changes to booting: . The pre_init.c leaves the kernel and modules exactly as they were left by the bootloader in physical memory . The kernel starts running using physical addressing, loaded at a fixed location given in its linker script by the bootloader. All code and data in this phase are linked to this fixed low location. . It makes a bootstrap pagetable to map itself to a fixed high location (also in linker script) and jumps to the high address. All code and data then use this high addressing. . All code/data symbols linked at the low addresses is prefixed by an objcopy step with __k_unpaged_*, so that that code cannot reference highly-linked symbols (which aren't valid yet) or vice versa (symbols that aren't valid any more). . The two addressing modes are separated in the linker script by collecting the unpaged_*.o objects and linking them with low addresses, and linking the rest high. Some objects are linked twice, once low and once high. . The bootstrap phase passes a lot of information (e.g. free memory list, physical location of the modules, etc.) using the kinfo struct. . After this bootstrap the low-linked part is freed. . The kernel maps in VM into the bootstrap page table so that VM can begin executing. Its first job is to make page tables for all other boot processes. So VM runs before RS, and RS gets a fully dynamic, VM-managed address space. VM gets its privilege info from RS as usual but that happens after RS starts running. . Both the kernel loading VM and VM organizing boot processes happen using the libexec logic. This removes the last reason for VM to still know much about exec() and vm/exec.c is gone. Further Implementation: . All segments are based at 0 and have a 4 GB limit. . The kernel is mapped in at the top of the virtual address space so as not to constrain the user processes. . Processes do not use segments from the LDT at all; there are no segments in the LDT any more, so no LLDT is needed. . The Minix segments T/D/S are gone and so none of the user-space or in-kernel copy functions use them. The copy functions use a process endpoint of NONE to realize it's a physical address, virtual otherwise. . The umap call only makes sense to translate a virtual address to a physical address now. . Segments-related calls like newmap and alloc_segments are gone. . All segments-related translation in VM is gone (vir2map etc). . Initialization in VM is simpler as no moving around is necessary. . VM and all other boot processes can be linked wherever they wish and will be mapped in at the right location by the kernel and VM respectively. Other changes: . The multiboot code is less special: it does not use mb_print for its diagnostics any more but uses printf() as normal, saving the output into the diagnostics buffer, only printing to the screen using the direct print functions if a panic() occurs. . The multiboot code uses the flexible 'free memory map list' style to receive the list of free memory if available. . The kernel determines the memory layout of the processes to a degree: it tells VM where the kernel starts and ends and where the kernel wants the top of the process to be. VM then uses this entire range, i.e. the stack is right at the top, and mmap()ped bits of memory are placed below that downwards, and the break grows upwards. Other Consequences: . Every process gets its own page table as address spaces can't be separated any more by segments. . As all segments are 0-based, there is no distinction between virtual and linear addresses, nor between userspace and kernel addresses. . Less work is done when context switching, leading to a net performance increase. (8% faster on my machine for 'make servers'.) . The layout and configuration of the GDT makes sysenter and syscall possible. --- commands/Makefile | 2 +- drivers/pci/pci.c | 38 +- drivers/tty/console.c | 2 +- include/arch/i386/include/archtypes.h | 15 +- include/arch/i386/include/interrupt.h | 19 +- include/arch/i386/include/multiboot.h | 27 +- include/arch/i386/include/vmparam.h | 5 - include/minix/com.h | 15 +- include/minix/const.h | 16 +- include/minix/profile.h | 2 +- include/minix/syslib.h | 5 +- include/minix/type.h | 99 ++-- include/minix/vm.h | 1 - kernel/Makefile | 12 +- kernel/arch/i386/Makefile.inc | 33 +- kernel/arch/i386/apic.c | 30 +- kernel/arch/i386/arch_do_vmctl.c | 53 +-- kernel/arch/i386/arch_reset.c | 154 ++++++ kernel/arch/i386/arch_smp.c | 20 +- kernel/arch/i386/arch_system.c | 261 ++-------- kernel/arch/i386/direct_tty_utils.c | 140 ++++++ kernel/arch/i386/do_readbios.c | 2 - kernel/arch/i386/do_sdevio.c | 20 +- kernel/arch/i386/exception.c | 27 +- kernel/arch/i386/head.S | 98 ++++ kernel/arch/i386/i8259.c | 27 +- kernel/arch/i386/include/arch_proto.h | 47 +- kernel/arch/i386/include/arch_watchdog.h | 2 +- kernel/arch/i386/include/archconst.h | 58 +-- kernel/arch/i386/include/direct_utils.h | 11 + kernel/arch/i386/kernel.lds | 58 +-- kernel/arch/i386/klib.S | 226 ++------- kernel/arch/i386/mb_utils.h | 12 - kernel/arch/i386/memory.c | 431 +++++------------ kernel/arch/i386/mpx.S | 130 +---- kernel/arch/i386/multiboot.S | 73 --- kernel/arch/i386/pg_utils.c | 260 ++++++++++ kernel/arch/i386/pre_init.c | 574 +++++++--------------- kernel/arch/i386/procoffsets.cf | 9 - kernel/arch/i386/protect.c | 581 ++++++++++------------- kernel/arch/i386/sconst.h | 53 +-- kernel/arch/i386/trampoline.S | 2 +- kernel/clock.c | 2 +- kernel/config.h | 6 - kernel/const.h | 4 - kernel/debug.c | 1 - kernel/glo.h | 14 +- kernel/main.c | 235 ++++++--- kernel/perf.h | 7 - kernel/proc.c | 13 +- kernel/proc.h | 5 +- kernel/profile.c | 2 +- kernel/proto.h | 39 +- kernel/start.c | 151 ------ kernel/system.c | 11 +- kernel/system.h | 5 - kernel/system/Makefile.inc | 1 - kernel/system/do_abort.c | 4 - kernel/system/do_copy.c | 13 +- kernel/system/do_exec.c | 12 +- kernel/system/do_fork.c | 13 +- kernel/system/do_getinfo.c | 4 +- kernel/system/do_newmap.c | 50 -- kernel/system/do_safecopy.c | 10 +- kernel/system/do_safemap.c | 15 +- kernel/system/do_trace.c | 20 +- kernel/system/do_umap_remote.c | 14 +- kernel/system/do_update.c | 5 - kernel/system/do_vmctl.c | 11 +- kernel/system/do_vumap.c | 12 +- kernel/table.c | 50 +- kernel/type.h | 21 +- kernel/utility.c | 42 +- lib/libasyn/asyn.h | 2 + lib/libaudiodriver/audio_fw.c | 2 +- lib/libexec/exec_elf.c | 108 +---- lib/libexec/exec_general.c | 14 + lib/libexec/libexec.h | 8 +- lib/libminlib/i386/_cpufeature.c | 16 +- lib/libsys/Makefile | 3 +- lib/libsys/alloc_util.c | 17 +- lib/libsys/env_get_prm.c | 2 +- lib/libsys/env_parse.c | 43 +- lib/libsys/kputc.c | 3 +- lib/libsys/sef.c | 4 +- lib/libsys/sys_fork.c | 4 +- lib/libsys/sys_newmap.c | 15 - lib/libsys/sys_physcopy.c | 4 +- lib/libsys/sys_safecopy.c | 4 +- lib/libsys/sys_safemap.c | 4 +- lib/libsys/sys_vircopy.c | 4 +- lib/libsys/sys_vmctl.c | 9 - lib/libvassert/vassert.c | 13 +- servers/init/Makefile | 2 - servers/is/dmp.c | 1 - servers/is/dmp_kernel.c | 65 +-- servers/is/dmp_vm.c | 11 +- servers/is/proto.h | 1 - servers/pm/exec.c | 6 +- servers/pm/glo.h | 3 +- servers/pm/main.c | 7 +- servers/pm/misc.c | 11 - servers/procfs/pid.c | 51 +- servers/rs/const.h | 2 +- servers/rs/exec.c | 2 + servers/rs/glo.h | 2 + servers/rs/main.c | 19 +- servers/rs/manager.c | 3 +- servers/vfs/exec.c | 17 +- servers/vfs/glo.h | 2 + servers/vfs/main.c | 3 + servers/vfs/table.c | 2 +- servers/vm/Makefile | 4 +- servers/vm/alloc.c | 17 +- servers/vm/arch/i386/Makefile.inc | 2 +- servers/vm/arch/i386/arch_vmproc.h | 21 - servers/vm/arch/i386/memory.h | 17 +- servers/vm/arch/i386/pagetable.c | 482 +++++++------------ servers/vm/arch/i386/vm.c | 143 ------ servers/vm/break.c | 104 ---- servers/vm/exec.c | 216 --------- servers/vm/exit.c | 19 +- servers/vm/fork.c | 123 +---- servers/vm/glo.h | 8 +- servers/vm/main.c | 336 +++++++------ servers/vm/mmap.c | 41 +- servers/vm/pagefaults.c | 11 +- servers/vm/proto.h | 23 +- servers/vm/region.c | 143 +++--- servers/vm/rs.c | 4 - servers/vm/sanitycheck.h | 5 +- servers/vm/slaballoc.c | 2 +- servers/vm/utility.c | 32 +- servers/vm/vmproc.h | 23 +- share/mk/bsd.prog.mk | 3 +- share/mk/minix.bootprog.mk | 2 - usr.bin/Makefile | 2 +- usr.bin/mkimage/Makefile | 8 - usr.bin/mkimage/mkimage.c | 120 ----- 139 files changed, 2465 insertions(+), 4377 deletions(-) create mode 100644 kernel/arch/i386/arch_reset.c create mode 100644 kernel/arch/i386/direct_tty_utils.c create mode 100644 kernel/arch/i386/head.S create mode 100644 kernel/arch/i386/include/direct_utils.h delete mode 100644 kernel/arch/i386/mb_utils.h delete mode 100644 kernel/arch/i386/multiboot.S create mode 100644 kernel/arch/i386/pg_utils.c delete mode 100644 kernel/start.c delete mode 100644 kernel/system/do_newmap.c delete mode 100644 lib/libsys/sys_newmap.c delete mode 100644 servers/vm/arch/i386/arch_vmproc.h delete mode 100644 servers/vm/arch/i386/vm.c delete mode 100644 servers/vm/exec.c delete mode 100644 usr.bin/mkimage/Makefile delete mode 100644 usr.bin/mkimage/mkimage.c 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; - 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; - } + if(OK != sys_getkinfo(&kinfo)) + panic("can't get kinfo"); + /* Set memgap_low to just above physical memory */ + 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 -} -#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 + /* Reserve some BIOS ranges */ + cut_memmap(&kinfo, BIOS_MEM_BEGIN, BIOS_MEM_END); + cut_memmap(&kinfo, BASE_MEM_TOP, UPPER_MEM_END); } - /*===========================================================================* * 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 */ - -/* 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) +/* 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 */ + +#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; - - 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); + } else { + if(!isokendpt(proc_e, &proc_nr)) { + printf("virtual_copy: no reasonable endpoint\n"); + return ESRCH; } - - assert(caller); - assert(target); - - vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL); - return VMSUSPEND; + p = proc_addr(proc_nr); } - return OK; + procs[i] = p; } - assert(!vm_running); + 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; + } + } - /* 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=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; + } + + 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); } +void memory_init(void) +{ + 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); +} + /*===========================================================================* - * arch_pre_exec * + * arch_proc_init * *===========================================================================*/ -void arch_pre_exec(struct proc *pr, const u32_t ip, const u32_t sp) +void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, char *name) { -/* set program counter and stack pointer. */ + arch_proc_reset(pr); + strcpy(pr->p_name, name); + + /* set custom state we know */ pr->p_reg.pc = ip; pr->p_reg.sp = sp; } -/* VM reports page directory slot we're allowed to use freely. */ -void i386_freepde(const int pde) -{ - if(nfreepdes >= MAX_FREEPDES) - return; - freepdes[nfreepdes++] = pde; -} - 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; - - /* 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. - */ - - vm_stop(); - write_cr3(0); + assert(caller->p_seg.p_cr3); - /* switch from segmentation only to paging */ - segmentation2paging(caller); + /* load caller's page table */ + switch_address_space(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_GP_REGS(%ebp) + /* 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 - RESTORE_SEGS(%ebp) + /* Same for general-purpose registers. */ + RESTORE_GP_REGS(%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) -{ - 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) +static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi) { - /* 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; - 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]; - - /* Determine the value of rootdev */ - dev += 0x80 - + (disk * NR_PARTITIONS + prim) * NR_PARTITIONS + sub; - - mb_itoa(dev, temp); - mb_set_param("rootdev", temp); - mb_set_param("ramimagedev", temp); + 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; } - 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); + 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; + 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]; + + /* get our own copy of the multiboot info struct and module list */ + memcpy((void *) mbi, (void *) ebx, sizeof(*mbi)); + + /* 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; - /* 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; + /* 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; + + 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; - - /* 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; + /* 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"); + + 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 * + * sdesc * *===========================================================================*/ -phys_bytes seg2phys(const u16_t seg) + void sdesc(struct segdesc_s *segdp, phys_bytes base, vir_bytes size) { -/* 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; +/* 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]; + int index = TSS_INDEX(cpu); + struct segdesc_s *tssgdt; + + tssgdt = &gdt[index]; - t->ss0 = DS_SELECTOR; - init_dataseg(&gdt[TSS_INDEX(cpu)], vir2phys(t), + init_param_dataseg(tssgdt, (phys_bytes) t, sizeof(struct tss_s), INTR_PRIVILEGE); - gdt[TSS_INDEX(cpu)].access = PRESENT | - (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; + tssgdt->access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; - /* Complete building of main TSS. */ + /* 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; - - /* 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)); - - /* 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); - - dtp= (struct desctableptr_s *) &gdt[IDT_INDEX]; - * (u16_t *) dtp->limit = (sizeof idt) - 1; - * (u32_t *) dtp->base = vir2phys(idt); - - /* 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; - } + struct desctableptr_s *dtp = (struct desctableptr_s *) &gdt[gdt_index]; + dtp->limit = size - 1; + dtp->base = (phys_bytes) base; + + return (phys_bytes) dtp; +} + +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; + + 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 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; -} - -/*===========================================================================* - * alloc_segments * - *===========================================================================*/ -void alloc_segments(register struct proc *rp) +void idt_reload(void) { -/* 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; - - 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; - - 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; + x86_lidt(&idt_desc); } -#if 0 -/*===========================================================================* - * check_segments * - *===========================================================================*/ -static void check_segments(char *File, int line) +multiboot_module_t *bootmod(int pnr) { - 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; + int i; - privilege = USER_PRIVILEGE; + assert(pnr >= 0); - 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); + /* 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]; + } } - CHECK(rp->p_reg.ds, ds); - } - if(fail) { - printf("%d/%d checks failed\n", fail, checked); - panic("wrong: %d", fail); - } + + panic("boot module %d not found", pnr); } -#endif /*===========================================================================* - * printseg * + * prot_init * *===========================================================================*/ -void printseg(char *banner, const int iscs, struct proc *pr, - const u32_t selector) +void prot_init() { -#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; - } - 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 "); - } + int sel_tss; + extern char k_boot_stktop; + + memset(gdt, 0, sizeof(gdt)); + memset(idt, 0, sizeof(idt)); + + /* 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); + + /* 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); + + x86_lgdt(&gdt_desc); /* Load gdt */ + idt_init(); + idt_reload(); + x86_lldt(LDT_SELECTOR); /* Load bogus ldt */ + x86_ltr(sel_tss); /* Load global TSS */ + + /* 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. + */ - dpl = ((u32_t) desc->access & DPL) >> DPL_SHIFT; + 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 */ +} - printf("DPL %d\n", dpl); +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); +} - return; -#endif /* USE_SYSDEBUG */ +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; } -/*===========================================================================* - * prot_set_kern_seg_limit * - *===========================================================================*/ -int prot_set_kern_seg_limit(const vir_bytes limit) +void arch_boot_proc(struct boot_image *ip, struct proc *rp) { - struct proc *rp; - int orig_click; - int incr_clicks; + multiboot_module_t *mod; - if(limit <= kinfo.data_base) { - printf("prot_set_kern_seg_limit: limit bogus\n"); - return EINVAL; - } + if(rp->p_nr < 0) return; - /* 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; + mod = bootmod(rp->p_nr); - prot_init(); + /* Important special case: we put VM in the bootstrap pagetable + * so it can run. + */ - /* 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; + 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); } - - return OK; } 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; - /* 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; - } - - /* 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 */ + sys_getkinfo(&kinfo); - /* 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 */ + /* Initialize everything to zero. */ + memset(mem_chunks, 0, maxchunks*sizeof(*mem_chunks)); - /* 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; - - /* Shorthand. */ - newpt = &vmprocess->vm_pt; + static u32_t currentpagedir[I386_VM_DIR_ENTRIES]; + int m = kernel_boot_info.kern_mod; + u32_t mycr3; + + /* 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; - - /* 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++; - } + I386_VM_PRESENT | I386_VM_WRITE; + + /* 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; - /* first pde in use by process. */ - proc_pde = free_pde; + /* 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; - /* 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; + if(pt_ptalloc(newpt, p, 0) != OK) + panic("pt_ptalloc failed"); + assert(newpt->pt_dir[p] & I386_VM_PRESENT); - /* Now actually enable paging. */ - if(sys_vmctl_enable_paging(&ep_data) != OK) - panic("pt_init: enable paging failed"); + ptaddr_kern = entry & I386_VM_ADDR_MASK; + ptaddr_us = newpt->pt_dir[p] & I386_VM_ADDR_MASK; - /* Back to reality - this is where the stack actually is. */ - vmprocess->vm_arch.vm_seg[S].mem_len -= extra_clicks; + /* 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"); + } - /* 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); - - 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"); + assert(bigpage_ok); + assert(pagedir_pde >= 0); + assert(kern_pde >= 0); + + /* 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; - - 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 + SANITYCHECK(SCL_DETAIL); - 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,179 +159,214 @@ 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]; + + /* 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); + } - /* No live update support for now. */ + 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); + } + } + } - /* Register signal callbacks. */ - sef_setcb_signal_handler(sef_cb_signal_handler); + /* RS expects this response that it then again wants to reply to: */ + m->RS_INIT_RESULT = OK; + sendrec(RS_PROC_NR, m); - /* Let SEF perform startup. */ - sef_startup(); + 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]; - struct boot_image *ip; - struct rprocpub rprocpub[NR_BOOT_PROCS]; - phys_bytes limit = 0; - int is_elf = 0; + static struct boot_image *ip; -#if SANITYCHECKS - incheck = nocheck = 0; -#endif + for (ip = &kernel_boot_info.boot_procs[0]; + ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) { + struct vmproc *vmp; -#if SANITYCHECKS - env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX); -#endif + if(ip->proc_nr != ep_nr) continue; - /* Get chunks of available memory. */ - get_mem_chunks(mem_chunks); + if(ip->proc_nr >= _NR_PROCS || ip->proc_nr < 0) + panic("proc: %d", ip->proc_nr); - /* 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); + 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; - /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ - memset(vmproc, 0, sizeof(vmproc)); + return vmp; + } - for(i = 0; i < ELEMENTS(vmproc); i++) { - vmproc[i].vm_slot = i; + panic("no init_proc"); +} + +struct vm_exec_info { + struct exec_info execi; + struct boot_image *ip; + 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"); } +} - /* 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; +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; +} - if(ip->proc_nr >= _NR_PROCS) { panic("proc: %d", ip->proc_nr); } - if(ip->proc_nr < 0 && ip->proc_nr != SYSTEM) continue; +static int libexec_alloc_vm_ondemand(struct exec_info *execi, + off_t vaddr, size_t len) +{ + boot_alloc(execi, vaddr, len, 0); + return OK; +} -#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); \ - } +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); +} - /* Initialize normal process table slot or special SYSTEM - * table slot. Kernel memory is already reserved. - */ - GETVMP(vmp, ip->proc_nr); +void init_vm(void) +{ + int s, i; + static struct memory mem_chunks[NR_MEMS]; + static struct boot_image *ip; - /* reset fields as if exited */ - clear_proc(vmp); +#if SANITYCHECKS + incheck = nocheck = 0; +#endif - /* 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); + /* Retrieve various crucial boot parameters */ + if(OK != (s=sys_getkinfo(&kernel_boot_info))) { + panic("couldn't get bootinfo: %d", s); + } - /* Remove this memory from the free list. */ - reserve_proc_mem(mem_chunks, vmp->vm_arch.vm_seg); + /* Sanity check */ + assert(kernel_boot_info.mmap_size > 0); + assert(kernel_boot_info.mods_with_kernel > 0); - /* Set memory limit. */ - proclimit = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys + - vmp->vm_arch.vm_seg[S].mem_len) - 1; +#if SANITYCHECKS + env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX); - if(proclimit > limit) - limit = proclimit; + vm_sanitychecklevel = 1; +#endif - 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); + /* Get chunks of available memory. */ + get_mem_chunks(mem_chunks); + + /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */ + memset(vmproc, 0, sizeof(vmproc)); - if (vmp->vm_arch.vm_seg[T].mem_len != 0) - vmp->vm_flags |= VMF_SEPARATE; + for(i = 0; i < ELEMENTS(vmproc); i++) { + vmproc[i].vm_slot = i; } /* 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; - - 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"); - } + /* 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; - 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; + vmp = init_proc(ip->proc_nr); - free_mem(vmp->vm_arch.vm_seg[D].mem_phys + - vmp->vm_arch.vm_seg[D].mem_len, - old_stacklen); + exec_bootproc(vmp, ip); -#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()); -} -- 2.44.0