#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include <string.h>
-#include <sys/stat.h>
+#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "kern_util.h"
#include "init.h"
#include "os.h"
#include "tempfile.h"
+#include "kern_constants.h"
extern struct mem_region physmem_region;
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
-int create_mem_file(unsigned long len)
+static int create_tmp_file(unsigned long len)
{
- int fd;
+ int fd, err;
char zero;
fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
- if (fchmod(fd, 0777) < 0){
- perror("fchmod");
+ if(fd < 0) {
+ os_print_error(fd, "make_tempfile");
exit(1);
}
- if(os_seek_file(fd, len) < 0){
- perror("lseek");
+
+ err = os_mode_fd(fd, 0777);
+ if(err < 0){
+ os_print_error(err, "os_mode_fd");
+ exit(1);
+ }
+ err = os_seek_file(fd, len);
+ if(err < 0){
+ os_print_error(err, "os_seek_file");
exit(1);
}
zero = 0;
- if(write(fd, &zero, 1) != 1){
- perror("write");
+ err = os_write_file(fd, &zero, 1);
+ if(err != 1){
+ os_print_error(err, "os_write_file");
exit(1);
}
- if(fcntl(fd, F_SETFD, 1) != 0)
- perror("Setting FD_CLOEXEC failed");
+
return(fd);
}
-int setup_region(struct mem_region *region, void *entry)
+static int have_devanon = 0;
+
+void check_devanon(void)
{
- void *loc, *start;
- char *driver;
- int err, offset;
-
- if(region->start != -1){
- err = reserve_vm(region->start,
- region->start + region->len, entry);
- if(err){
- printk("setup_region : failed to reserve "
- "0x%x - 0x%x for driver '%s'\n",
- region->start,
- region->start + region->len,
- region->driver);
- return(-1);
- }
- }
- else region->start = get_vm(region->len);
- if(region->start == 0){
- if(region->driver == NULL) driver = "physmem";
- else driver = region->driver;
- printk("setup_region : failed to find vm for "
- "driver '%s' (length %d)\n", driver, region->len);
- return(-1);
- }
- if(region->start == uml_physmem){
- start = (void *) uml_reserved;
- offset = uml_reserved - uml_physmem;
+ int fd;
+
+ printk("Checking for /dev/anon on the host...");
+ fd = open("/dev/anon", O_RDWR);
+ if(fd < 0){
+ printk("Not available (open failed with errno %d)\n", errno);
+ return;
}
- else {
- start = (void *) region->start;
- offset = 0;
+
+ printk("OK\n");
+ have_devanon = 1;
+}
+
+static int create_anon_file(unsigned long len)
+{
+ void *addr;
+ int fd;
+
+ fd = open("/dev/anon", O_RDWR);
+ if(fd < 0) {
+ os_print_error(fd, "opening /dev/anon");
+ exit(1);
}
- loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_FIXED, region->fd, offset);
- if(loc != start){
- perror("Mapping memory");
+ addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
+ if(addr == MAP_FAILED){
+ os_print_error((int) addr, "mapping physmem file");
exit(1);
}
- return(0);
+ munmap(addr, len);
+
+ return(fd);
}
+int create_mem_file(unsigned long len)
+{
+ int err, fd;
+
+ if(have_devanon)
+ fd = create_anon_file(len);
+ else fd = create_tmp_file(len);
+
+ err = os_set_exec_close(fd, 1);
+ if(err < 0)
+ os_print_error(err, "exec_close");
+ return(fd);
+}
+
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
static int __init parse_iomem(char *str, int *add)
{
- struct stat buf;
+ struct iomem_region *new;
+ struct uml_stat buf;
char *file, *driver;
- int fd;
+ int fd, err, size;
driver = str;
file = strchr(str,',');
if(file == NULL){
- printk("parse_iomem : failed to parse iomem\n");
- return(1);
+ printf("parse_iomem : failed to parse iomem\n");
+ goto out;
}
*file = '\0';
file++;
fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
if(fd < 0){
- printk("parse_iomem - Couldn't open io file, errno = %d\n",
- errno);
- return(1);
+ os_print_error(fd, "parse_iomem - Couldn't open io file");
+ goto out;
+ }
+
+ err = os_stat_fd(fd, &buf);
+ if(err < 0){
+ os_print_error(err, "parse_iomem - cannot stat_fd file");
+ goto out_close;
}
- if(fstat(fd, &buf) < 0) {
- printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
- return(1);
+
+ new = malloc(sizeof(*new));
+ if(new == NULL){
+ perror("Couldn't allocate iomem_region struct");
+ goto out_close;
}
- add_iomem(driver, fd, buf.st_size);
+
+ size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+
+ *new = ((struct iomem_region) { .next = iomem_regions,
+ .driver = driver,
+ .fd = fd,
+ .size = size,
+ .phys = 0,
+ .virt = 0 });
+ iomem_regions = new;
+ iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
return(0);
+ out_close:
+ os_close_file(fd);
+ out:
+ return(1);
}
__uml_setup("iomem=", parse_iomem,
" Configure <file> as an IO memory region named <name>.\n\n"
);
-#ifdef notdef
-int logging = 0;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[256];
-
-void log(char *fmt, ...)
-{
- va_list ap;
- struct timeval tv;
- struct openflags flags;
-
- if(logging == 0) return;
- if(logging_fd < 0){
- flags = of_create(of_trunc(of_rdrw(OPENFLAGS())));
- logging_fd = os_open_file("log", flags, 0644);
- }
- gettimeofday(&tv, NULL);
- sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec,
- tv.tv_usec);
- va_start(ap, fmt);
- vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
- va_end(ap);
- write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-int map_memory(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x)
-{
- struct mem_region *region = phys_region(phys);
-
- return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
- r, w, x));
-}
-
int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
int must_succeed)
{
- if(os_protect_memory((void *) addr, len, r, w, x) < 0){
+ int err;
+
+ err = os_protect_memory((void *) addr, len, r, w, x);
+ if(err < 0){
if(must_succeed)
- panic("protect failed, errno = %d", errno);
- else return(-errno);
+ panic("protect failed, err = %d", -err);
+ else return(err);
}
return(0);
}
-unsigned long find_iomem(char *driver, unsigned long *len_out)
+#if 0
+/* Debugging facility for dumping stuff out to the host, avoiding the timing
+ * problems that come with printf and breakpoints.
+ * Enable in case of emergency.
+ */
+
+int logging = 1;
+int logging_fd = -1;
+
+int logging_line = 0;
+char logging_buf[512];
+
+void log(char *fmt, ...)
{
- struct mem_region *region;
- int i, n;
-
- n = nregions();
- for(i = 0; i < n; i++){
- region = regions[i];
- if(region == NULL) continue;
- if((region->driver != NULL) &&
- !strcmp(region->driver, driver)){
- *len_out = region->len;
- return(region->start);
- }
- }
- *len_out = 0;
- return 0;
+ va_list ap;
+ struct timeval tv;
+ struct openflags flags;
+
+ if(logging == 0) return;
+ if(logging_fd < 0){
+ flags = of_create(of_trunc(of_rdwr(OPENFLAGS())));
+ logging_fd = os_open_file("log", flags, 0644);
+ }
+ gettimeofday(&tv, NULL);
+ sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec,
+ tv.tv_usec);
+ va_start(ap, fmt);
+ vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
+ va_end(ap);
+ write(logging_fd, logging_buf, strlen(logging_buf));
}
+#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.