#define WARM_CODE
#include "warm.h"
+#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)
{
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;
}
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');
/* 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;
}
close(warm_fd);
warm_fd = -1;
- 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, "system/rmmod failed: %d %d\n", ret, errno);
- manual_rmmod(name);
+ 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);
+ }
}
}
ret = ioctl(warm_fd, WARMC_CACHE_OP, &wop);
if (ret != 0) {
- perror("WARMC_CACHE_OP failed");
+ perror(PFX "WARMC_CACHE_OP failed");
return -1;
}
ret = ioctl(warm_fd, WARMC_CHANGE_CB, &ccb);
if (ret != 0) {
- perror("WARMC_CHANGE_CB failed");
+ perror(PFX "WARMC_CHANGE_CB failed");
return -1;
}
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);
+}