diff -Naur -X exclude-files ac_cur/arch/um/include/mem_user.h ac/arch/um/include/mem_user.h --- ac_cur/arch/um/include/mem_user.h Wed Dec 31 19:00:00 1969 +++ ac/arch/um/include/mem_user.h Sun Jul 15 21:44:24 2001 @@ -0,0 +1,55 @@ +/* + * arch/um/include/mem_user.h + * + * BRIEF MODULE DESCRIPTION + * user side memory interface for support IO memory inside user mode linux + * + * Copyright (C) 2001 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MEM_USER_H +#define _MEM_USER_H + +extern int create_mem_file(unsigned long len); +extern void setup_range(int fd, char *driver, unsigned long start, + unsigned long usable, unsigned long total); +extern void map(unsigned long virt, void *p, unsigned long len, int r, + int w, int x); +extern void parse_iomem(char *str); +extern void setup_memory(void); +extern unsigned long find_iomem(char *driver, unsigned long *len_out); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/include/user_util.h ac/arch/um/include/user_util.h --- ac_cur/arch/um/include/user_util.h Sun Jul 15 21:54:27 2001 +++ ac/arch/um/include/user_util.h Sun Jul 15 21:44:24 2001 @@ -30,7 +30,6 @@ extern struct cpu_task cpu_tasks[]; -extern int physmem_fd; extern int brk_fd; extern unsigned long low_physmem; @@ -42,8 +41,6 @@ extern void *last_brk; extern void *brk_start; -extern int physmem_inode; - extern int tracing_pid; extern char host_info[]; @@ -65,9 +62,6 @@ extern void stack_protections(unsigned long address, int len); extern void abandon_proc_space(int (*proc)(void *), unsigned long sp); extern int signals(int (*init_proc)(void *), void *sp); -extern unsigned long setup_memory(unsigned long total_size, - unsigned long physmem_size, int *fd_out, - int *inode_out); extern void map(unsigned long virt, void *p, unsigned long len, int r, int w, int x); extern int unmap(unsigned long address, unsigned long len); @@ -122,7 +116,6 @@ extern int raw(int fd, int complain); extern void cooked(int fd); extern int switcheroo(int fd, int prot, void *from, void *to, int size); -extern int create_vm_file(unsigned long len); extern void *update_brk(void); extern void check_brk(void *process_brk); extern void idle_sleep(int secs); diff -Naur -X exclude-files ac_cur/arch/um/kernel/Makefile ac/arch/um/kernel/Makefile --- ac_cur/arch/um/kernel/Makefile Sun Jul 15 21:54:27 2001 +++ ac/arch/um/kernel/Makefile Sun Jul 15 21:44:24 2001 @@ -1,9 +1,9 @@ OBJ = um.o OBJS = process.o current.o exec_kern.o exec_user.o init_task.o irq.o \ - irq_user.o mem.o ptrace.o reboot.o resource.o \ - setup.o signal_user.o smp.o syscall_kern.o \ - syscall_user.o sys_call_table.o time.o time_kern.o tlb.o trap_kern.o \ + irq_user.o mem.o mem_user.o ptrace.o reboot.o resource.o \ + setup.o signal_user.o smp.o syscall_kern.o syscall_user.o \ + sys_call_table.o time.o time_kern.o tlb.o trap_kern.o \ trap_user.o um_arch.o user_util.o uaccess_user.o OX_OBJS = ksyms.o process_kern.o signal_kern.o user_syms.o @@ -32,25 +32,28 @@ exec_user.o: exec_user.c $(CC) $(USER_CFLAGS) -c -o $@ $< -process.o: process.c +irq_user.o: irq_user.c $(CC) $(USER_CFLAGS) -c -o $@ $< -syscall_user.o: syscall_user.c +mem_user.o: mem_user.c $(CC) $(USER_CFLAGS) -c -o $@ $< -trap_user.o: trap_user.c +process.o: process.c $(CC) $(USER_CFLAGS) -c -o $@ $< signal_user.o: signal_user.c $(CC) $(USER_CFLAGS) -c -o $@ $< +syscall_user.o: syscall_user.c + $(CC) $(USER_CFLAGS) -c -o $@ $< + time.o: time.c $(CC) $(USER_CFLAGS) -c -o $@ $< -user_util.o: user_util.c +trap_user.o: trap_user.c $(CC) $(USER_CFLAGS) -c -o $@ $< -irq_user.o: irq_user.c +user_util.o: user_util.c $(CC) $(USER_CFLAGS) -c -o $@ $< uaccess.o: uaccess_user.c diff -Naur -X exclude-files ac_cur/arch/um/kernel/mem_user.c ac/arch/um/kernel/mem_user.c --- ac_cur/arch/um/kernel/mem_user.c Wed Dec 31 19:00:00 1969 +++ ac/arch/um/kernel/mem_user.c Sun Jul 15 21:44:24 2001 @@ -0,0 +1,212 @@ +/* + * arch/um/kernel/mem_user.c + * + * BRIEF MODULE DESCRIPTION + * user side memory routines for supporting IO memory inside user mode linux + * + * Copyright (C) 2001 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kern_util.h" +#include "user.h" + +struct mem_region { + struct mem_region *next; + char *driver; + unsigned long start; + unsigned long usable; + unsigned long total; + int fd; +}; + +struct mem_region physmem_region; + +struct mem_region *mem_list = &physmem_region; + +int create_mem_file(unsigned long len) +{ + char tempname[sizeof("/tmp/vm_file-XXXXXX\0")]; + int fd; + char zero; + + strcpy(tempname, "/tmp/vm_file-XXXXXX"); + if((fd = mkstemp(tempname)) < 0){ + perror("open - cannot create /tmp/vm_file-XXXXXX"); + exit(1); + } + if(unlink(tempname) < 0){ + perror("unlink"); + exit(1); + } + if (fchmod(fd, 0777) < 0){ + perror("fchmod"); + exit(1); + } + if(lseek(fd, len, SEEK_SET) < 0){ + perror("lseek"); + exit(1); + } + zero = 0; + if(write(fd, &zero, 1) != 1){ + perror("write"); + exit(1); + } + return(fd); +} + +void setup_range(int fd, char *driver, unsigned long start, + unsigned long usable, unsigned long total) +{ + struct mem_region *region, *next; + + if(fd == -1){ + fd = create_mem_file(usable); + region = &physmem_region; + next = physmem_region.next; + } + else { + region = malloc(sizeof(*region)); + if(region == NULL){ + perror("Allocating iomem struct"); + exit(1); + } + next = physmem_region.next; + } + *region = ((struct mem_region) { next, driver, start, usable, + total, fd } ); + if(region != &physmem_region) physmem_region.next = region; +} + +void setup_memory(void) +{ + struct mem_region *region; + void *loc; + unsigned long start; + int page; + + start = -1; + region = mem_list; + page = page_size(); + while(region){ + if(region->start != -1) start = region->start; + else region->start = start; + loc = mmap((void *) region->start, region->usable, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, + region->fd, 0); + if(loc != (void *) region->start){ + perror("Mapping memory"); + exit(1); + } + start += region->total; + start = (start + page - 1) & ~(page - 1); + region = region->next; + } +} + +void parse_iomem(char *str) +{ + struct stat buf; + char *file, *driver; + int fd; + + driver = str; + file = strchr(str,','); + if(file == NULL){ + printk(__FUNCTION__ " failed to parse iomem\n"); + return; + } + *file = '\0'; + file++; + fd = open(file, O_RDWR); + if(fd < 0){ + perror("Couldn't open io file"); + return; + } + if(fstat(fd, &buf) < 0) { + perror(__FUNCTION__ "fstat - cannot fstat file"); + exit(1); + } + setup_range(fd, driver, -1, buf.st_size, buf.st_size); +} + +void map(unsigned long virt, void *p, unsigned long len, int r, + int w, int x) +{ + struct mem_region *region; + unsigned long phys = (unsigned long) p; + void *loc; + int prot; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + for(region = mem_list; region ; region = region->next) { + if((phys < region->start) || + (phys >= region->start + region->usable)) + continue; + phys -= region->start; + loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, + region->fd, phys); + if(loc != (void *) virt){ + panic("Error mapping a page - errno = %d", errno); + } + return; + } + panic("No physical or IO memory region for address 0x%x\n", phys); +} + +unsigned long find_iomem(char *driver, unsigned long *len_out) +{ + struct mem_region *region; + + for(region = mem_list; region ; region = region->next) { + if(!strcmp(region->driver, driver)) { + *len_out = region->usable; + return(region->start); + } + } + *len_out = 0; + return 0; +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c --- ac_cur/arch/um/kernel/um_arch.c Sun Jul 15 21:56:00 2001 +++ ac/arch/um/kernel/um_arch.c Sun Jul 15 21:53:25 2001 @@ -27,6 +27,7 @@ #include "kern_util.h" #include "kern.h" #include "mprot.h" +#include "mem_user.h" unsigned long _stext; @@ -81,14 +82,12 @@ #define XSTRING(s) #s #define STRING(s) XSTRING(s) -int physmem_fd = -1; - extern unsigned long high_physmem; -unsigned long physmem; +unsigned long physmem = 0x50000000 + NESTING * 0x10000000; + unsigned long start_vm; unsigned long end_vm; -int physmem_inode; int ncpus = 1; @@ -202,7 +201,7 @@ brk_start = sbrk(0); remap_data(ROUND_DOWN(&__bss_start), ROUND_UP(brk_start)); last_brk = (void *) brk_start; - brk_fd = create_vm_file(0); + brk_fd = create_mem_file(0); #ifdef CONFIG_GPROF remap_profiling_buffers(); #endif @@ -266,8 +265,9 @@ add_process_vmas(); unblock_shlib_mem(); - physmem = setup_memory(physmem_size + VMALLOC_OFFSET + virtmem_size, - physmem_size, &physmem_fd, &physmem_inode); + setup_range(-1, NULL, physmem, physmem_size, + physmem_size + VMALLOC_OFFSET + virtmem_size); + setup_memory(); high_physmem = physmem + physmem_size; start_vm = physmem + physmem_size + VMALLOC_OFFSET; end_vm = start_vm + virtmem_size; diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_syms.c ac/arch/um/kernel/user_syms.c --- ac_cur/arch/um/kernel/user_syms.c Sun Jul 15 21:56:00 2001 +++ ac/arch/um/kernel/user_syms.c Sun Jul 15 21:44:24 2001 @@ -8,6 +8,7 @@ #include #include #include "user_util.h" +#include "mem_user.h" /* XXX All the __CONFIG_* stuff is broken because this file can't include * config.h @@ -97,3 +98,5 @@ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(getuid); + +EXPORT_SYMBOL(find_iomem); diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_util.c ac/arch/um/kernel/user_util.c --- ac_cur/arch/um/kernel/user_util.c Sun Jul 15 21:56:00 2001 +++ ac/arch/um/kernel/user_util.c Sun Jul 15 21:44:24 2001 @@ -24,6 +24,7 @@ #include "user_util.h" #include "kern_util.h" #include "user.h" +#include "mem_user.h" #define COMMAND_LINE_SIZE _POSIX_ARG_MAX @@ -83,39 +84,6 @@ fclose(maps); } -int create_vm_file(unsigned long len) -{ - char tempname[32]; - int fd; - char zero; - - strcpy(tempname, "/tmp/vm_file-XXXXXX"); - if ((fd = mkstemp(tempname)) < 0) { - perror("open - cannot create /tmp/vm_file-XXXXXX"); - exit(1); - } - if(unlink(tempname) < 0){ - perror("unlink"); - exit(1); - } - if (fchmod(fd, 0777) < 0){ - perror("fchmod"); - exit(1); - } - if(len > 0){ - if(lseek(fd, len, SEEK_SET) < 0){ - perror("lseek"); - exit(1); - } - zero = 0; - if(write(fd, &zero, 1) != 1){ - perror("write"); - exit(1); - } - } - return(fd); -} - void remap_data(void *segment_start, void *segment_end) { void *addr; @@ -131,7 +99,7 @@ prot = PROT_READ | PROT_WRITE | PROT_EXEC; size = (unsigned long) segment_end - (unsigned long) segment_start; - data = create_vm_file(size); + data = create_mem_file(size); if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0)) < 0){ perror("mapping new data segment"); @@ -207,53 +175,6 @@ void stack_protections(unsigned long address, int len) { mprotect((void *) address, len, PROT_READ | PROT_WRITE | PROT_EXEC); -} - -static unsigned long physmem_start = 0x50000000 + NESTING * 0x10000000; - -unsigned long setup_memory(unsigned long total_size, - unsigned long physmem_size, int *fd_out, - int *inode_out) -{ - void *mem; - struct stat buf; - - mem = mmap((void *) physmem_start, total_size, PROT_NONE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - if(mem < 0){ - perror("Mapping all of memory"); - exit(1); - } - munmap(mem, total_size); - *fd_out = create_vm_file(physmem_size); - if(mmap(mem, physmem_size, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_FIXED, *fd_out, 0) != mem){ - perror("Mapping physical memory"); - exit(1); - } - if(fstat(*fd_out, &buf) < 0){ - perror("Stat-ing phymem_fd"); - exit(1); - } - *inode_out = buf.st_ino; - return((unsigned long) mem); -} - -void map(unsigned long virt, void *p, unsigned long len, int r, - int w, int x) -{ - unsigned long phys = (unsigned long) p; - int prot; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - if((phys < physmem) || (phys > high_physmem)) - panic("map : physmem out of range"); - phys -= physmem; - if(mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, physmem_fd, - phys) != (void *) virt){ - panic("Error mapping a page - errno = %d", errno); - } } void protect(unsigned long addr, unsigned long len, int r, int w, int x) diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c --- ac_cur/arch/um/kernel/um_arch.c Sun Jul 15 21:53:25 2001 +++ ac/arch/um/kernel/um_arch.c Sun Jul 15 22:03:32 2001 @@ -243,6 +243,9 @@ else if(!strncmp(argv[i], "umid=", strlen("umid="))){ create_pid_file(&argv[i][strlen("umid=")]); } + else if(!strncmp(argv[i], "iomem=",strlen("iomem="))){ + parse_iomem(&argv[i][strlen("iomem=")]); + } else if(!strcmp(argv[i], "--version")){ printf("%s\n", system_utsname.release); exit(0);