X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=warm.git;a=blobdiff_plain;f=warm.c;h=d17b12273373406dc2a698199aa21444c219ab8d;hp=fd3fb4cb1c0099582d71f45eded34e43b354c089;hb=55b74e0bebeb4b3bdffa77f5ebedc87c85770308;hpb=cc9517321fda63efa03335ff0c47540394fd93ce diff --git a/warm.c b/warm.c index fd3fb4c..d17b122 100644 --- a/warm.c +++ b/warm.c @@ -42,10 +42,15 @@ #define WARM_CODE #include "warm.h" -extern long init_module(void *, unsigned long, const char *); /* provided by glibc */ +#define PFX "wARM: " + +/* provided by glibc */ +extern long init_module(void *, unsigned long, const char *); +extern long delete_module(const char *, unsigned int); static int warm_fd = -1; static int kernel_version; +static int module_inserted; static void sys_cacheflush(void *start, void *end) { @@ -68,6 +73,8 @@ static void sys_cacheflush(void *start, void *end) #endif } +/* Those are here because system() occasionaly fails on Wiz + * with errno 12 for some unknown reason */ static int manual_insmod_26(const char *fname, const char *opts) { unsigned long len, read_len; @@ -89,7 +96,7 @@ static int manual_insmod_26(const char *fname, const char *opts) read_len = fread(buff, 1, len, f); if (read_len != len) { - fprintf(stderr, "failed to read module\n"); + fprintf(stderr, PFX "failed to read module\n"); goto fail1; } @@ -102,51 +109,59 @@ fail0: return ret; } +static int manual_rmmod(const char *name) +{ + return delete_module(name, O_NONBLOCK|O_EXCL); +} + int warm_init(void) { struct utsname unm; char buff1[32], buff2[128]; int ret; - warm_fd = open("/proc/warm", O_RDWR); - if (warm_fd >= 0) - return 0; - memset(&unm, 0, sizeof(unm)); uname(&unm); if (strlen(unm.release) < 3 || unm.release[1] != '.') { - fprintf(stderr, "unexpected version string: %s\n", unm.release); + fprintf(stderr, PFX "unexpected version string: %s\n", unm.release); goto fail; } kernel_version = ((unm.release[0] - '0') << 4) | (unm.release[2] - '0'); + warm_fd = open("/proc/warm", O_RDWR); + if (warm_fd >= 0) + return 0; + snprintf(buff1, sizeof(buff1), "warm_%s.%s", unm.release, kernel_version >= 0x26 ? "ko" : "o"); snprintf(buff2, sizeof(buff2), "/sbin/insmod %s verbose=1", buff1); /* try to insmod */ ret = system(buff2); if (ret != 0) { - fprintf(stderr, "system/insmod failed: %d %d\n", ret, errno); + fprintf(stderr, PFX "system/insmod failed: %d %d\n", ret, errno); if (kernel_version >= 0x26) { ret = manual_insmod_26(buff1, "verbose=1"); if (ret != 0) - fprintf(stderr, "manual insmod also failed: %d\n", ret); + fprintf(stderr, PFX "manual insmod also failed: %d\n", ret); } } + if (ret == 0) + module_inserted = 1; warm_fd = open("/proc/warm", O_RDWR); if (warm_fd >= 0) return 0; fail: - fprintf(stderr, "wARM: can't init, acting as sys_cacheflush wrapper\n"); + fprintf(stderr, PFX "can't init, acting as sys_cacheflush wrapper\n"); return -1; } void warm_finish(void) { - char cmd[64]; + char name[32], cmd[64]; + int ret; if (warm_fd < 0) return; @@ -154,16 +169,23 @@ void warm_finish(void) close(warm_fd); warm_fd = -1; - if (kernel_version < 0x26) { - struct utsname unm; - memset(&unm, 0, sizeof(unm)); - uname(&unm); - snprintf(cmd, sizeof(cmd), "/sbin/rmmod warm_%s", unm.release); + if (module_inserted) { + if (kernel_version < 0x26) { + struct utsname unm; + memset(&unm, 0, sizeof(unm)); + uname(&unm); + snprintf(name, sizeof(name), "warm_%s", unm.release); + } + else + strcpy(name, "warm"); + + snprintf(cmd, sizeof(cmd), "/sbin/rmmod %s", name); + ret = system(cmd); + if (ret != 0) { + fprintf(stderr, PFX "system/rmmod failed: %d %d\n", ret, errno); + manual_rmmod(name); + } } - else - strcpy(cmd, "/sbin/rmmod warm"); - - system(cmd); } int warm_cache_op_range(int op, void *addr, unsigned long size) @@ -183,7 +205,7 @@ int warm_cache_op_range(int op, void *addr, unsigned long size) ret = ioctl(warm_fd, WARMC_CACHE_OP, &wop); if (ret != 0) { - perror("WARMC_CACHE_OP failed"); + perror(PFX "WARMC_CACHE_OP failed"); return -1; } @@ -210,7 +232,7 @@ int warm_change_cb_range(int cb, int is_set, void *addr, unsigned long size) ret = ioctl(warm_fd, WARMC_CHANGE_CB, &ccb); if (ret != 0) { - perror("WARMC_CHANGE_CB failed"); + perror(PFX "WARMC_CHANGE_CB failed"); return -1; } @@ -230,10 +252,55 @@ unsigned long warm_virt2phys(const void *ptr) ptrio = (unsigned long)ptr; ret = ioctl(warm_fd, WARMC_VIRT2PHYS, &ptrio); if (ret != 0) { - perror("WARMC_VIRT2PHYS failed"); + perror(PFX "WARMC_VIRT2PHYS failed"); return (unsigned long)-1; } return ptrio; } +int warm_do_section(void *virt_addr, unsigned long phys_addr, + unsigned long size, int cb, int is_unmap) +{ + struct warm_map_op mop; + unsigned long vaddr; + int ret; + + if (warm_fd < 0) + return -1; + + vaddr = (unsigned long)virt_addr; + if (vaddr & 0xfffff) { + fprintf(stderr, PFX "virt_addr is unaligned\n"); + return -1; + } + if (phys_addr & 0xfffff) { + fprintf(stderr, PFX "phys_addr is unaligned\n"); + return -1; + } + + mop.virt_addr = vaddr; + mop.phys_addr = phys_addr; + mop.size = size; + mop.cb = cb; + mop.is_unmap = is_unmap; + + ret = ioctl(warm_fd, WARMC_MMAP, &mop); + if (ret != 0) { + perror(PFX "WARMC_MMAP failed"); + return -1; + } + + return 0; +} + +int warm_mmap_section(void *virt_addr, unsigned long phys_addr, + unsigned long size, int cb) +{ + return warm_do_section(virt_addr, phys_addr, size, cb, 0); +} + +int warm_munmap_section(void *virt_addr, unsigned long size) +{ + return warm_do_section(virt_addr, 0, size, 0, 1); +}