From 8d04105aa13941487ebc8f647b3c1e368c2c55fc Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 20 Jun 2009 00:18:15 +0300 Subject: [PATCH] few bugfixes, some features, starting 2.4 port --- module/Makefile_2.4 | 22 +++++++++++ module/warm_main.c | 92 +++++++++++++++++++++++++++++++++++---------- module/warm_ops.S | 8 ++-- warm.c | 2 +- 4 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 module/Makefile_2.4 diff --git a/module/Makefile_2.4 b/module/Makefile_2.4 new file mode 100644 index 0000000..14e286a --- /dev/null +++ b/module/Makefile_2.4 @@ -0,0 +1,22 @@ +ifndef KERNEL_DIR +$(error specify KERNEL_DIR) +endif + +CROSS_COMPILE = arm-linux- +INCLUDE = $(KERNEL_DIR)/include +CPPFLAGS = -O2 -DMODULE -D__KERNEL__ -I${INCLUDE} +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld + +TARGET = warm.o +OBJS = warm_main.o warm_ops.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(LD) -r -o $@ $(OBJS) + + +clean: + rm -rf $(TARGET) $(OBJS) + diff --git a/module/warm_main.c b/module/warm_main.c index 5b8e910..21c54d4 100644 --- a/module/warm_main.c +++ b/module/warm_main.c @@ -14,9 +14,19 @@ #include #include #include -#include #include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) +#include +#else +#include +#include +#include +#define __user +#define unlocked_ioctl ioctl +#endif + #define WARM_CODE #include "../warm.h" #include "warm_ops.h" @@ -25,21 +35,36 @@ #error need proc_fs #endif -#define WARM_VER "r1" +#define WARM_VER "r2" #define PFX "wARM: " +#define WARM_INFO(fmt, ...) \ + if (verbose) \ + pr_info(PFX fmt, ##__VA_ARGS__) + #define MAX_CACHEOP_RANGE 16384 /* assume RAM starts at phys addr 0 (this is really machine specific) */ #define RAM_PHYS_START 0 #define RAM_MAX_SIZE 0x10000000 /* 256M, try to be future proof */ +/* expected CPU id */ +#if defined(CONFIG_CPU_ARM926T) +#define EXPECTED_ID 0x069260 +#elif defined(CONFIG_CPU_ARM920T) +#define EXPECTED_ID 0x029200 +#else +#error "unsupported CPU" +#endif + extern unsigned long max_mapnr; /* "upper" physical memory, not seen by Linux and to be mmap'ed */ static u32 uppermem_start; static u32 uppermem_end; +static int verbose; + static u32 *get_pgtable(void) { u32 ttb; @@ -68,8 +93,8 @@ static int do_set_cb_uppermem(int in_cb, int is_set) for (i = 0; i < 4096; i++) { - if (!(pgtable[i] & 1)) - /* must be course of fine page table */ + if ((pgtable[i] & 3) != 1) + /* must be coarse page table */ continue; cpt = __va(pgtable[i] & 0xfffffc00); @@ -110,7 +135,7 @@ static int do_set_cb_uppermem(int in_cb, int is_set) warm_cop_clean_d(); warm_drain_wb_inval_tlb(); - pr_info(PFX "%c%c bit(s) %s for phys %08x-%08x (%d pages)\n", + WARM_INFO("%c%c bit(s) %s for phys %08x-%08x (%d pages)\n", bits & 8 ? 'c' : ' ', bits & 4 ? 'b' : ' ', is_set ? "set" : "cleared", uppermem_start, uppermem_end - 1, count); @@ -130,7 +155,7 @@ static int do_set_cb_virt(int in_cb, int is_set, u32 addr, u32 size) if (in_cb & WCB_B_BIT) bits |= 4; - size += addr & ~(PAGE_SIZE - 1); + size += addr & (PAGE_SIZE - 1); size = ALIGN(size, PAGE_SIZE); addr &= ~(PAGE_SIZE - 1); @@ -143,8 +168,10 @@ static int do_set_cb_virt(int in_cb, int is_set, u32 addr, u32 size) { desc1 = pgtable[addr >> 20]; - if (!(desc1 & 3)) + if ((desc1 & 3) != 1) { + printk(KERN_WARNING PFX "not coarse table? %08x %08x\n", desc1, addr); return -EINVAL; + } cpt = __va(desc1 & 0xfffffc00); desc2 = cpt[(addr >> 12) & 0xff]; @@ -167,7 +194,7 @@ static int do_set_cb_virt(int in_cb, int is_set, u32 addr, u32 size) warm_cop_clean_d(); warm_drain_wb_inval_tlb(); - pr_info(PFX "%c%c bit(s) %s virt %08x-%08x (%d pages)\n", + WARM_INFO("%c%c bit(s) %s virt %08x-%08x (%d pages)\n", bits & 8 ? 'c' : ' ', bits & 4 ? 'b' : ' ', is_set ? "set" : "cleared", start, end - 1, count); @@ -183,24 +210,36 @@ static int do_virt2phys(unsigned long *_addr) pgtable = get_pgtable(); desc1 = pgtable[addr >> 20]; - if (!(desc1 & 3)) - return -EINVAL; - - if ((desc1 & 3) == 2) { - /* 1MB section */ + switch (desc1 & 3) { + case 1: /* coarse table */ + cpt = __va(desc1 & 0xfffffc00); + desc2 = cpt[(addr >> 12) & 0xff]; + break; + case 2: /* 1MB section */ *_addr = (desc1 & 0xfff00000) | (addr & 0xfffff); return 0; + case 3: /* fine table */ + cpt = __va(desc1 & 0xfffff000); + desc2 = cpt[(addr >> 10) & 0x3ff]; + default: + return -EINVAL; } - cpt = __va(desc1 & 0xfffffc00); - desc2 = cpt[(addr >> 12) & 0xff]; - if ((desc2 & 3) != 2) { - printk(KERN_WARNING PFX "not small page? %08x %08x\n", desc2, addr); + switch (desc2 & 3) { + case 1: /* large page */ + *_addr = (desc2 & 0xffff0000) | (addr & 0xffff); + break; + case 2: /* small page */ + *_addr = (desc2 & 0xfffff000) | (addr & 0x0fff); + break; + case 3: /* tiny page */ + *_addr = (desc2 & 0xfffffc00) | (addr & 0x03ff); + break; + default: return -EINVAL; } - *_addr = (desc2 & 0xfffffc00) | (addr & 0x3ff); return 0; } @@ -262,7 +301,12 @@ static int do_cache_ops(int ops, u32 addr, u32 size) return 0; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) static long warm_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) +#else +static int warm_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long __arg) +#endif { void __user *arg = (void __user *) __arg; union { @@ -278,7 +322,8 @@ static long warm_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) return -EFAULT; if (u.wcop.ops & ~(WOP_D_CLEAN|WOP_D_INVALIDATE|WOP_I_INVALIDATE)) return -EINVAL; - if (u.wcop.size > MAX_CACHEOP_RANGE) + if (u.wcop.size == (unsigned long)-1 || + (u.wcop.size > MAX_CACHEOP_RANGE && !(u.wcop.ops & WOP_D_INVALIDATE))) ret = do_cache_ops_whole(u.wcop.ops); else ret = do_cache_ops(u.wcop.ops, u.wcop.addr, u.wcop.size); @@ -444,6 +489,13 @@ static const struct file_operations warm_fops = { static int __init warm_module_init(void) { struct proc_dir_entry *pret; + u32 cpuid; + + asm ("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid)); + if ((cpuid & 0x0ffff0) != EXPECTED_ID) { + printk(KERN_ERR PFX "module was compiled for different CPU, aborting\n"); + return -1; + } pret = create_proc_entry("warm", S_IWUGO | S_IRUGO, NULL); if (!pret) { @@ -480,6 +532,8 @@ static void __exit warm_module_exit(void) module_init(warm_module_init); module_exit(warm_module_exit); +module_param(verbose, int, 0644); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ARM processor services"); MODULE_AUTHOR("Grazvydas Ignotas"); diff --git a/module/warm_ops.S b/module/warm_ops.S index 8752e05..541d69d 100644 --- a/module/warm_ops.S +++ b/module/warm_ops.S @@ -3,6 +3,8 @@ #include +#define CACHELINE_SZC #32 + #ifndef CONFIG_CPU_ARM926T #error CPU not supported #endif @@ -60,11 +62,11 @@ warm_cop_drain_wb: #define WARM_COP_MK_RANGE_FUNC(name,f1,f2) \ .global name ;\ name: ;\ - bic r0, r0, #32-1 ;\ + bic r0, r0, CACHELINE_SZC-1 ;\ 0: f1 ;\ f2 ;\ - add r0, r0, #32 ;\ - subs r1, r1, #32 ;\ + add r0, r0, CACHELINE_SZC ;\ + subs r1, r1, CACHELINE_SZC ;\ bgt 0b ;\ bx lr diff --git a/warm.c b/warm.c index 197df0f..f56a372 100644 --- a/warm.c +++ b/warm.c @@ -55,7 +55,7 @@ int warm_init(void) memset(&unm, 0, sizeof(unm)); uname(&unm); - snprintf(buff, sizeof(buff), "/sbin/insmod warm_%s.ko", unm.release); + snprintf(buff, sizeof(buff), "/sbin/insmod warm_%s.ko verbose=1", unm.release); /* try to insmod */ system(buff); -- 2.39.2