From a2e2725541fad72416326798c2d7fa4dafb7d337 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 12 Oct 2009 23:40:10 -0700 Subject: net: Introduce recvmmsg socket syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Meaning receive multiple messages, reducing the number of syscalls and net stack entry/exit operations. Next patches will introduce mechanisms where protocols that want to optimize this operation will provide an unlocked_recvmsg operation. This takes into account comments made by: . Paul Moore: sock_recvmsg is called only for the first datagram, sock_recvmsg_nosec is used for the rest. . Caitlin Bestler: recvmmsg now has a struct timespec timeout, that works in the same fashion as the ppoll one. If the underlying protocol returns a datagram with MSG_OOB set, this will make recvmmsg return right away with as many datagrams (+ the OOB one) it has received so far. . Rémi Denis-Courmont & Steven Whitehouse: If we receive N < vlen datagrams and then recvmsg returns an error, recvmmsg will return the successfully received datagrams, store the error and return it in the next call. This paves the way for a subsequent optimization, sk_prot->unlocked_recvmsg, where we will be able to acquire the lock only at batch start and end, not at every underlying recvmsg call. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- arch/microblaze/kernel/syscall_table.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index ecec19155135..c1ab1dc10898 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -371,3 +371,4 @@ ENTRY(sys_call_table) .long sys_ni_syscall .long sys_rt_tgsigqueueinfo /* 365 */ .long sys_perf_event_open + .long sys_recvmmsg -- cgit v1.2.2 From d8678b58708d7e6bf947ebd03eaf44baf2adfad8 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 15 Oct 2009 10:57:53 -0600 Subject: of: add common header for flattened device tree representation Add a common header file for working with the flattened device tree data structure and merge the shared data tags used by Microblaze and PowerPC Signed-off-by: Grant Likely Acked-by: David S. Miller Acked-by: Wolfram Sang Acked-by: Michal Simek Acked-by: Stephen Neuendorffer Acked-by: Stephen Rothwell --- arch/microblaze/kernel/head.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index 697ce3007f30..30916193fcc7 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -31,7 +31,7 @@ #include #include #include -#include /* for OF_DT_HEADER */ +#include /* for OF_DT_HEADER */ #ifdef CONFIG_MMU #include /* COMMAND_LINE_SIZE */ -- cgit v1.2.2 From e91edcf5a2940bb7f1f316c871dfe9e2aaf9d6d9 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 15 Oct 2009 10:58:09 -0600 Subject: of: merge of_find_all_nodes() implementations Merge common code between Microblaze and PowerPC, and make it available to Sparc Signed-off-by: Grant Likely Acked-by: David S. Miller Acked-by: Wolfram Sang Acked-by: Michal Simek Acked-by: Stephen Neuendorffer Acked-by: Stephen Rothwell --- arch/microblaze/kernel/prom.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index c005cc6f1aaf..b817df172aa9 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -859,29 +859,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -/** - * of_find_all_nodes - Get next node in global list - * @prev: Previous node or NULL to start iteration - * of_node_put() will be called on it - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_all_nodes(struct device_node *prev) -{ - struct device_node *np; - - read_lock(&devtree_lock); - np = prev ? prev->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (of_node_get(np)) - break; - of_node_put(prev); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_all_nodes); - /** * of_node_get - Increment refcount of a node * @node: Node to inc refcount, NULL is supported to -- cgit v1.2.2 From e169cfbef46d62e042614ffafa8880eed1d894bb Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 14:53:09 -0700 Subject: of/flattree: merge find_flat_dt_string and initial_boot_params Merge common code between Microblaze and PowerPC. Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index b817df172aa9..06d620ab4168 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -47,17 +47,9 @@ static int __initdata dt_root_size_cells; typedef u32 cell_t; -static struct boot_param_header *initial_boot_params; - /* export that to outside world */ struct device_node *of_chosen; -static inline char *find_flat_dt_string(u32 offset) -{ - return ((char *)initial_boot_params) + - initial_boot_params->off_dt_strings + offset; -} - /** * This function is used to scan the flattened device-tree, it is * used to extract the memory informations at boot before we can -- cgit v1.2.2 From c8cb7a59842c0b512b44f6f818cdb0b5a3ddc89e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 18:54:23 -0700 Subject: of/flattree: merge of_scan_flat_dt Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 61 ------------------------------------------- 1 file changed, 61 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 06d620ab4168..0db8ee64ffe6 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,67 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -/** - * This function is used to scan the flattened device-tree, it is - * used to extract the memory informations at boot before we can - * unflatten the tree - */ -int __init of_scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - int rc = 0; - int depth = -1; - - do { - u32 tag = *((u32 *)p); - char *pathp; - - p += 4; - if (tag == OF_DT_END_NODE) { - depth--; - continue; - } - if (tag == OF_DT_NOP) - continue; - if (tag == OF_DT_END) - break; - if (tag == OF_DT_PROP) { - u32 sz = *((u32 *)p); - p += 8; - if (initial_boot_params->version < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - p += sz; - p = _ALIGN(p, 4); - continue; - } - if (tag != OF_DT_BEGIN_NODE) { - printk(KERN_WARNING "Invalid tag %x scanning flattened" - " device tree !\n", tag); - return -EINVAL; - } - depth++; - pathp = (char *)p; - p = _ALIGN(p + strlen(pathp) + 1, 4); - if ((*pathp) == '/') { - char *lp, *np; - for (lp = NULL, np = pathp; *np; np++) - if ((*np) == '/') - lp = np+1; - if (lp != NULL) - pathp = lp; - } - rc = it(p, pathp, depth, data); - if (rc != 0) - break; - } while (1); - - return rc; -} - unsigned long __init of_get_flat_dt_root(void) { unsigned long p = ((unsigned long)initial_boot_params) + -- cgit v1.2.2 From 819d2819303654c6829d572e698e2d0021c08599 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 19:44:23 -0700 Subject: of/flattree: merge of_get_flat_dt_root Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 0db8ee64ffe6..7eb6f8bdb81a 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,18 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -unsigned long __init of_get_flat_dt_root(void) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - - while (*((u32 *)p) == OF_DT_NOP) - p += 4; - BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE); - p += 4; - return _ALIGN(p + strlen((char *)p) + 1, 4); -} - /** * This function can be used within scan_flattened_dt callback to get * access to properties -- cgit v1.2.2 From ca900cfa2944448bdb76e1246f282e59bc65f472 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:06:59 -0700 Subject: of/flattree: merge of_get_flat_dt_prop Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 7eb6f8bdb81a..d75c6253c0de 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,48 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -/** - * This function can be used within scan_flattened_dt callback to get - * access to properties - */ -void *__init of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) -{ - unsigned long p = node; - - do { - u32 tag = *((u32 *)p); - u32 sz, noff; - const char *nstr; - - p += 4; - if (tag == OF_DT_NOP) - continue; - if (tag != OF_DT_PROP) - return NULL; - - sz = *((u32 *)p); - noff = *((u32 *)(p + 4)); - p += 8; - if (initial_boot_params->version < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - - nstr = find_flat_dt_string(noff); - if (nstr == NULL) { - printk(KERN_WARNING "Can't find property index" - " name !\n"); - return NULL; - } - if (strcmp(name, nstr) == 0) { - if (size) - *size = sz; - return (void *)p; - } - p += sz; - p = _ALIGN(p, 4); - } while (1); -} - int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) { const char *cp; -- cgit v1.2.2 From 00e38efd90f27518ec96b37b1c7773e3ac529966 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:07:00 -0700 Subject: of/flattree: Merge of_flat_dt_is_compatible Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index d75c6253c0de..eb27bd3a39b4 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,25 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) -{ - const char *cp; - unsigned long cplen, l; - - cp = of_get_flat_dt_prop(node, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncasecmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} - static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, unsigned long align) { -- cgit v1.2.2 From bbd33931a08362f78266a4016211a35947b91041 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:07:00 -0700 Subject: of/flattree: Merge unflatten_dt_node Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 195 ------------------------------------------ 1 file changed, 195 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index eb27bd3a39b4..021770abfbd7 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,201 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, - unsigned long align) -{ - void *res; - - *mem = _ALIGN(*mem, align); - res = (void *)*mem; - *mem += size; - - return res; -} - -static unsigned long __init unflatten_dt_node(unsigned long mem, - unsigned long *p, - struct device_node *dad, - struct device_node ***allnextpp, - unsigned long fpsize) -{ - struct device_node *np; - struct property *pp, **prev_pp = NULL; - char *pathp; - u32 tag; - unsigned int l, allocl; - int has_name = 0; - int new_format = 0; - - tag = *((u32 *)(*p)); - if (tag != OF_DT_BEGIN_NODE) { - printk("Weird tag at start of node: %x\n", tag); - return mem; - } - *p += 4; - pathp = (char *)*p; - l = allocl = strlen(pathp) + 1; - *p = _ALIGN(*p + l, 4); - - /* version 0x10 has a more compact unit name here instead of the full - * path. we accumulate the full path size using "fpsize", we'll rebuild - * it later. We detect this because the first character of the name is - * not '/'. - */ - if ((*pathp) != '/') { - new_format = 1; - if (fpsize == 0) { - /* root node: special case. fpsize accounts for path - * plus terminating zero. root node only has '/', so - * fpsize should be 2, but we want to avoid the first - * level nodes to have two '/' so we use fpsize 1 here - */ - fpsize = 1; - allocl = 2; - } else { - /* account for '/' and path size minus terminal 0 - * already in 'l' - */ - fpsize += l; - allocl = fpsize; - } - } - - np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, - __alignof__(struct device_node)); - if (allnextpp) { - memset(np, 0, sizeof(*np)); - np->full_name = ((char *)np) + sizeof(struct device_node); - if (new_format) { - char *p2 = np->full_name; - /* rebuild full path for new format */ - if (dad && dad->parent) { - strcpy(p2, dad->full_name); -#ifdef DEBUG - if ((strlen(p2) + l + 1) != allocl) { - pr_debug("%s: p: %d, l: %d, a: %d\n", - pathp, (int)strlen(p2), - l, allocl); - } -#endif - p2 += strlen(p2); - } - *(p2++) = '/'; - memcpy(p2, pathp, l); - } else - memcpy(np->full_name, pathp, l); - prev_pp = &np->properties; - **allnextpp = np; - *allnextpp = &np->allnext; - if (dad != NULL) { - np->parent = dad; - /* we temporarily use the next field as `last_child'*/ - if (dad->next == NULL) - dad->child = np; - else - dad->next->sibling = np; - dad->next = np; - } - kref_init(&np->kref); - } - while (1) { - u32 sz, noff; - char *pname; - - tag = *((u32 *)(*p)); - if (tag == OF_DT_NOP) { - *p += 4; - continue; - } - if (tag != OF_DT_PROP) - break; - *p += 4; - sz = *((u32 *)(*p)); - noff = *((u32 *)((*p) + 4)); - *p += 8; - if (initial_boot_params->version < 0x10) - *p = _ALIGN(*p, sz >= 8 ? 8 : 4); - - pname = find_flat_dt_string(noff); - if (pname == NULL) { - printk(KERN_INFO - "Can't find property name in list !\n"); - break; - } - if (strcmp(pname, "name") == 0) - has_name = 1; - l = strlen(pname) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property), - __alignof__(struct property)); - if (allnextpp) { - if (strcmp(pname, "linux,phandle") == 0) { - np->node = *((u32 *)*p); - if (np->linux_phandle == 0) - np->linux_phandle = np->node; - } - if (strcmp(pname, "ibm,phandle") == 0) - np->linux_phandle = *((u32 *)*p); - pp->name = pname; - pp->length = sz; - pp->value = (void *)*p; - *prev_pp = pp; - prev_pp = &pp->next; - } - *p = _ALIGN((*p) + sz, 4); - } - /* with version 0x10 we may not have the name property, recreate - * it here from the unit name if absent - */ - if (!has_name) { - char *p1 = pathp, *ps = pathp, *pa = NULL; - int sz; - - while (*p1) { - if ((*p1) == '@') - pa = p1; - if ((*p1) == '/') - ps = p1 + 1; - p1++; - } - if (pa < ps) - pa = p1; - sz = (pa - ps) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, - __alignof__(struct property)); - if (allnextpp) { - pp->name = "name"; - pp->length = sz; - pp->value = pp + 1; - *prev_pp = pp; - prev_pp = &pp->next; - memcpy(pp->value, ps, sz - 1); - ((char *)pp->value)[sz - 1] = 0; - pr_debug("fixed up name for %s -> %s\n", pathp, - (char *)pp->value); - } - } - if (allnextpp) { - *prev_pp = NULL; - np->name = of_get_property(np, "name", NULL); - np->type = of_get_property(np, "device_type", NULL); - - if (!np->name) - np->name = ""; - if (!np->type) - np->type = ""; - } - while (tag == OF_DT_BEGIN_NODE) { - mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); - tag = *((u32 *)(*p)); - } - if (tag != OF_DT_END_NODE) { - printk(KERN_INFO "Weird tag at end of node: %x\n", tag); - return mem; - } - *p += 4; - return mem; -} - /** * unflattens the device-tree passed by the firmware, creating the * tree of struct device_node. It also fills the "name" and "type" -- cgit v1.2.2 From 41f880091c15b039ffcc8b3d831656b81517a6d3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:07:01 -0700 Subject: of/flattree: Merge unflatten_device_tree Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 49 ------------------------------------------- 1 file changed, 49 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 021770abfbd7..901d538c15ef 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -50,55 +50,6 @@ typedef u32 cell_t; /* export that to outside world */ struct device_node *of_chosen; -/** - * unflattens the device-tree passed by the firmware, creating the - * tree of struct device_node. It also fills the "name" and "type" - * pointers of the nodes so the normal device-tree walking functions - * can be used (this used to be done by finish_device_tree) - */ -void __init unflatten_device_tree(void) -{ - unsigned long start, mem, size; - struct device_node **allnextp = &allnodes; - - pr_debug(" -> unflatten_device_tree()\n"); - - /* First pass, scan for size */ - start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - size = unflatten_dt_node(0, &start, NULL, NULL, 0); - size = (size | 3) + 1; - - pr_debug(" size is %lx, allocating...\n", size); - - /* Allocate memory for the expanded device tree */ - mem = lmb_alloc(size + 4, __alignof__(struct device_node)); - mem = (unsigned long) __va(mem); - - ((u32 *)mem)[size / 4] = 0xdeadbeef; - - pr_debug(" unflattening %lx...\n", mem); - - /* Second pass, do actual unflattening */ - start = ((unsigned long)initial_boot_params) + - initial_boot_params->off_dt_struct; - unflatten_dt_node(mem, &start, NULL, &allnextp, 0); - if (*((u32 *)start) != OF_DT_END) - printk(KERN_WARNING "Weird tag at end of tree: %08x\n", - *((u32 *)start)); - if (((u32 *)mem)[size / 4] != 0xdeadbeef) - printk(KERN_WARNING "End of tree marker overwritten: %08x\n", - ((u32 *)mem)[size / 4]); - *allnextp = NULL; - - /* Get pointer to OF "/chosen" node for use everywhere */ - of_chosen = of_find_node_by_path("/chosen"); - if (of_chosen == NULL) - of_chosen = of_find_node_by_path("/chosen@0"); - - pr_debug(" <- unflatten_device_tree()\n"); -} - #define early_init_dt_scan_drconf_memory(node) 0 static int __init early_init_dt_scan_cpus(unsigned long node, -- cgit v1.2.2 From 02af11b03fce3ddb264d7873d7a2e295e697938c Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 23 Nov 2009 20:16:45 -0700 Subject: of: merge prom_{add,remove,modify}_property Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Reviewed-by: Wolfram Sang Tested-by: Michal Simek --- arch/microblaze/kernel/prom.c | 113 ------------------------------------------ 1 file changed, 113 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 901d538c15ef..a38e3733a09c 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -606,119 +606,6 @@ out_unlock: write_unlock_irqrestore(&devtree_lock, flags); } -/* - * Add a property to a node - */ -int prom_add_property(struct device_node *np, struct property *prop) -{ - struct property **next; - unsigned long flags; - - prop->next = NULL; - write_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (strcmp(prop->name, (*next)->name) == 0) { - /* duplicate ! don't insert it */ - write_unlock_irqrestore(&devtree_lock, flags); - return -1; - } - next = &(*next)->next; - } - *next = prop; - write_unlock_irqrestore(&devtree_lock, flags); - -#ifdef CONFIG_PROC_DEVICETREE - /* try to add to proc as well if it was initialized */ - if (np->pde) - proc_device_tree_add_prop(np->pde, prop); -#endif /* CONFIG_PROC_DEVICETREE */ - - return 0; -} - -/* - * Remove a property from a node. Note that we don't actually - * remove it, since we have given out who-knows-how-many pointers - * to the data using get-property. Instead we just move the property - * to the "dead properties" list, so it won't be found any more. - */ -int prom_remove_property(struct device_node *np, struct property *prop) -{ - struct property **next; - unsigned long flags; - int found = 0; - - write_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (*next == prop) { - /* found the node */ - *next = prop->next; - prop->next = np->deadprops; - np->deadprops = prop; - found = 1; - break; - } - next = &(*next)->next; - } - write_unlock_irqrestore(&devtree_lock, flags); - - if (!found) - return -ENODEV; - -#ifdef CONFIG_PROC_DEVICETREE - /* try to remove the proc node as well */ - if (np->pde) - proc_device_tree_remove_prop(np->pde, prop); -#endif /* CONFIG_PROC_DEVICETREE */ - - return 0; -} - -/* - * Update a property in a node. Note that we don't actually - * remove it, since we have given out who-knows-how-many pointers - * to the data using get-property. Instead we just move the property - * to the "dead properties" list, and add the new property to the - * property list - */ -int prom_update_property(struct device_node *np, - struct property *newprop, - struct property *oldprop) -{ - struct property **next; - unsigned long flags; - int found = 0; - - write_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (*next == oldprop) { - /* found the node */ - newprop->next = oldprop->next; - *next = newprop; - oldprop->next = np->deadprops; - np->deadprops = oldprop; - found = 1; - break; - } - next = &(*next)->next; - } - write_unlock_irqrestore(&devtree_lock, flags); - - if (!found) - return -ENODEV; - -#ifdef CONFIG_PROC_DEVICETREE - /* try to add to proc as well if it was initialized */ - if (np->pde) - proc_device_tree_update_prop(np->pde, newprop, oldprop); -#endif /* CONFIG_PROC_DEVICETREE */ - - return 0; -} - #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) static struct debugfs_blob_wrapper flat_dt_blob; -- cgit v1.2.2 From f7b3a8355ba6cad251297844a0bdd08898ea36e0 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 24 Nov 2009 03:26:58 -0700 Subject: of/flattree: Merge early_init_dt_check_for_initrd() Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index a38e3733a09c..7959495b1d00 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -113,38 +113,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -#ifdef CONFIG_BLK_DEV_INITRD -static void __init early_init_dt_check_for_initrd(unsigned long node) -{ - unsigned long l; - u32 *prop; - - pr_debug("Looking for initrd properties... "); - - prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); - if (prop) { - initrd_start = (unsigned long) - __va((u32)of_read_ulong(prop, l/4)); - - prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); - if (prop) { - initrd_end = (unsigned long) - __va((u32)of_read_ulong(prop, 1/4)); - initrd_below_start_ok = 1; - } else { - initrd_start = 0; - } - } - - pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", - initrd_start, initrd_end); -} -#else -static inline void early_init_dt_check_for_initrd(unsigned long node) -{ -} -#endif /* CONFIG_BLK_DEV_INITRD */ - static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { -- cgit v1.2.2 From f00abd94918c9780f9d2d961fc0e419c11457922 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 24 Nov 2009 03:27:10 -0700 Subject: of/flattree: Merge earlyinit_dt_scan_root() Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Tested-by: Wolfram Sang --- arch/microblaze/kernel/prom.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 7959495b1d00..189179a9b554 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -42,9 +42,6 @@ #include #include -static int __initdata dt_root_addr_cells; -static int __initdata dt_root_size_cells; - typedef u32 cell_t; /* export that to outside world */ @@ -158,26 +155,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 1; } -static int __init early_init_dt_scan_root(unsigned long node, - const char *uname, int depth, void *data) -{ - u32 *prop; - - if (depth != 0) - return 0; - - prop = of_get_flat_dt_prop(node, "#size-cells", NULL); - dt_root_size_cells = (prop == NULL) ? 1 : *prop; - pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); - - prop = of_get_flat_dt_prop(node, "#address-cells", NULL); - dt_root_addr_cells = (prop == NULL) ? 2 : *prop; - pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); - - /* break now */ - return 1; -} - static u64 __init dt_mem_next_cell(int s, cell_t **cellp) { cell_t *p = *cellp; -- cgit v1.2.2 From 83f7a06eb479e2aeb83536e77a2cb14cc2285e32 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 24 Nov 2009 03:37:56 -0700 Subject: of/flattree: merge dt_mem_next_cell Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Tested-by: Wolfram Sang --- arch/microblaze/kernel/prom.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 189179a9b554..e0f4c34ed0f2 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -155,14 +155,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 1; } -static u64 __init dt_mem_next_cell(int s, cell_t **cellp) -{ - cell_t *p = *cellp; - - *cellp = p + s; - return of_read_number(p, s); -} - static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { -- cgit v1.2.2 From 0f0b56c3f2df4a083fc9e934266e5bab1710e286 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 10 Dec 2009 23:42:17 -0700 Subject: of/flattree: eliminate cell_t typedef A cell is firmly established as a u32. No need to do an ugly typedef to redefine it to cell_t. Eliminate the unnecessary typedef so that it doesn't have to be added to the of_fdt header file Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index e0f4c34ed0f2..50d8b09d5e3f 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -42,8 +42,6 @@ #include #include -typedef u32 cell_t; - /* export that to outside world */ struct device_node *of_chosen; @@ -159,7 +157,7 @@ static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { char *type = of_get_flat_dt_prop(node, "device_type", NULL); - cell_t *reg, *endp; + __be32 *reg, *endp; unsigned long l; /* Look for the ibm,dynamic-reconfiguration-memory node */ @@ -178,13 +176,13 @@ static int __init early_init_dt_scan_memory(unsigned long node, } else if (strcmp(type, "memory") != 0) return 0; - reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); + reg = (__be32 *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); if (reg == NULL) - reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); + reg = (__be32 *)of_get_flat_dt_prop(node, "reg", &l); if (reg == NULL) return 0; - endp = reg + (l / sizeof(cell_t)); + endp = reg + (l / sizeof(__be32)); pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", uname, l, reg[0], reg[1], reg[2], reg[3]); -- cgit v1.2.2 From 86e032213424958b45564d0cc96b3316641a49d3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 10 Dec 2009 23:42:21 -0700 Subject: of/flattree: merge early_init_dt_scan_chosen() Merge common code between PowerPC and Microblaze. This patch splits the arch-specific stuff out into a new function, early_init_dt_scan_chosen_arch(). Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 44 ++----------------------------------------- 1 file changed, 2 insertions(+), 42 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 50d8b09d5e3f..5505bcffd7dd 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -108,49 +108,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -static int __init early_init_dt_scan_chosen(unsigned long node, - const char *uname, int depth, void *data) +void __init early_init_dt_scan_chosen_arch(unsigned long node) { - unsigned long l; - char *p; - - pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); - - if (depth != 1 || - (strcmp(uname, "chosen") != 0 && - strcmp(uname, "chosen@0") != 0)) - return 0; - -#ifdef CONFIG_KEXEC - lprop = (u64 *)of_get_flat_dt_prop(node, - "linux,crashkernel-base", NULL); - if (lprop) - crashk_res.start = *lprop; - - lprop = (u64 *)of_get_flat_dt_prop(node, - "linux,crashkernel-size", NULL); - if (lprop) - crashk_res.end = crashk_res.start + *lprop - 1; -#endif - - early_init_dt_check_for_initrd(node); - - /* Retreive command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); - if (p != NULL && l > 0) - strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); - -#ifdef CONFIG_CMDLINE -#ifndef CONFIG_CMDLINE_FORCE - if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) -#endif - strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", cmd_line); - - /* break now */ - return 1; + /* No Microblaze specific code here */ } static int __init early_init_dt_scan_memory(unsigned long node, -- cgit v1.2.2 From f8b7256096a20436f6d0926747e3ac3d64c81d24 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 30 Nov 2009 17:37:04 -0500 Subject: Unify sys_mmap* New helper - sys_mmap_pgoff(); switch syscalls to using it. Acked-by: David S. Miller Signed-off-by: Al Viro --- arch/microblaze/kernel/sys_microblaze.c | 38 +++------------------------------ arch/microblaze/kernel/syscall_table.S | 2 +- 2 files changed, 4 insertions(+), 36 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 07cabed4b947..9f3c205fb75b 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -62,46 +62,14 @@ out: return error; } -asmlinkage long -sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file *file = NULL; - int ret = -EBADF; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) { - printk(KERN_INFO "no fd in mmap\r\n"); - goto out; - } - } - - down_write(¤t->mm->mmap_sem); - ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return ret; -} - asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t pgoff) { - int err = -EINVAL; - - if (pgoff & ~PAGE_MASK) { - printk(KERN_INFO "no pagemask in mmap\r\n"); - goto out; - } + if (pgoff & ~PAGE_MASK) + return -EINVAL; - err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); -out: - return err; + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); } /* diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index c1ab1dc10898..b96f365ea6b1 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -196,7 +196,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 /* mmap2 */ + .long sys_mmap_pgoff /* mmap2 */ .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ -- cgit v1.2.2 From 42a2478b789cb1b4335909e0fecc721c07be7d90 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 2 Oct 2009 12:48:47 +0200 Subject: microblaze: GPIO reset support Signed-off-by: Michal Simek --- arch/microblaze/kernel/Makefile | 2 +- arch/microblaze/kernel/reset.c | 138 ++++++++++++++++++++++++++++++++++++++++ arch/microblaze/kernel/setup.c | 29 --------- 3 files changed, 139 insertions(+), 30 deletions(-) create mode 100644 arch/microblaze/kernel/reset.c (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index d487729683de..fddd0c403d40 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds obj-y += exceptions.o \ hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ of_platform.o process.o prom.o prom_parse.o ptrace.o \ - setup.o signal.o sys_microblaze.o timer.o traps.o + setup.o signal.o sys_microblaze.o timer.o traps.o reset.o obj-y += cpu/ diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c new file mode 100644 index 000000000000..ce74a6f436e3 --- /dev/null +++ b/arch/microblaze/kernel/reset.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +/* Trigger specific functions */ +#ifdef CONFIG_GPIOLIB + +#include + +static int handle; /* reset pin handle */ + +static int of_reset_gpio_handle(void) +{ + int ret; /* variable which stored handle reset gpio pin */ + struct device_node *root; /* root node */ + struct device_node *gpio; /* gpio node */ + struct of_gpio_chip *of_gc = NULL; + enum of_gpio_flags flags ; + const void *gpio_spec; + + /* find out root node */ + root = of_find_node_by_path("/"); + + /* give me handle for gpio node to be possible allocate pin */ + ret = of_parse_phandles_with_args(root, "hard-reset-gpios", + "#gpio-cells", 0, &gpio, &gpio_spec); + if (ret) { + pr_debug("%s: can't parse gpios property\n", __func__); + goto err0; + } + + of_gc = gpio->data; + if (!of_gc) { + pr_debug("%s: gpio controller %s isn't registered\n", + root->full_name, gpio->full_name); + ret = -ENODEV; + goto err1; + } + + ret = of_gc->xlate(of_gc, root, gpio_spec, &flags); + if (ret < 0) + goto err1; + + ret += of_gc->gc.base; +err1: + of_node_put(gpio); +err0: + pr_debug("%s exited with status %d\n", __func__, ret); + return ret; +} + +void of_platform_reset_gpio_probe(void) +{ + int ret; + handle = of_reset_gpio_handle(); + + if (!gpio_is_valid(handle)) { + printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n", + handle, "reset"); + } + + ret = gpio_request(handle, "reset"); + if (ret < 0) { + printk(KERN_INFO "GPIO pin is already allocated\n"); + return; + } + + /* get current setup value */ + ret = gpio_get_value(handle); + /* FIXME maybe worth to perform any action */ + pr_debug("Reset: Gpio output state: 0x%x\n", ret); + + /* Setup GPIO as output */ + ret = gpio_direction_output(handle, 0); + if (ret < 0) + goto err; + + /* Setup output direction */ + gpio_set_value(handle, 0); + + printk(KERN_INFO "Registered reset device: %d\n", handle); + return; +err: + gpio_free(handle); + return; +} + + +static void gpio_system_reset(void) +{ + gpio_set_value(handle, 1); +} +#else +#define gpio_system_reset() do {} while (0) +void of_platform_reset_gpio_probe(void) +{ + return; +} +#endif + +void machine_restart(char *cmd) +{ + printk(KERN_NOTICE "Machine restart...\n"); + gpio_system_reset(); + dump_stack(); + while (1) + ; +} + +void machine_shutdown(void) +{ + printk(KERN_NOTICE "Machine shutdown...\n"); + while (1) + ; +} + +void machine_halt(void) +{ + printk(KERN_NOTICE "Machine halt...\n"); + while (1) + ; +} + +void machine_power_off(void) +{ + printk(KERN_NOTICE "Machine power off...\n"); + while (1) + ; +} diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 8c1e0f4dcf18..367ad330148e 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -186,32 +186,3 @@ static int microblaze_debugfs_init(void) } arch_initcall(microblaze_debugfs_init); #endif - -void machine_restart(char *cmd) -{ - printk(KERN_NOTICE "Machine restart...\n"); - dump_stack(); - while (1) - ; -} - -void machine_shutdown(void) -{ - printk(KERN_NOTICE "Machine shutdown...\n"); - while (1) - ; -} - -void machine_halt(void) -{ - printk(KERN_NOTICE "Machine halt...\n"); - while (1) - ; -} - -void machine_power_off(void) -{ - printk(KERN_NOTICE "Machine power off...\n"); - while (1) - ; -} -- cgit v1.2.2 From 13cdee23296c437cdd0262a09c3455de8e1e85b2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Oct 2009 14:41:52 +0100 Subject: microblaze: __init_begin symbol must be aligned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem was that free_initmem pass to free_initrd_mem got bad aligned __init_begin symbol and free_initrd_mem don't care about __init_end but take PAGE_SIZE instead. Here is behavior in kernel bootlog. ramdisk_execute_command from (init/main.c) was rewrite Freeing unused kernel memory: 6224k freed Failed to execute ��������������{��� Failed to execute ��������������{����. Attempting defaults... Mounting proc: Mounting var: Signed-off-by: Michal Simek --- arch/microblaze/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index e704188d7855..ecee15342e66 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -86,6 +86,7 @@ SECTIONS { _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ; } + . = ALIGN(PAGE_SIZE); __init_begin = .; INIT_TEXT_SECTION(PAGE_SIZE) -- cgit v1.2.2 From 7cf79d59ea650ae82868a99cc2954871d2a239bf Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 6 Nov 2009 12:27:25 +0100 Subject: microblaze: Add IRQENTRY_TEXT to lds It is important for ftrace irqsoff support Signed-off-by: Michal Simek --- arch/microblaze/kernel/vmlinux.lds.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index ecee15342e66..5ef619aad634 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -26,11 +26,12 @@ SECTIONS { _stext = . ; *(.text .text.*) *(.fixup) - EXIT_TEXT - EXIT_CALL + EXIT_TEXT + EXIT_CALL SCHED_TEXT LOCK_TEXT KPROBES_TEXT + IRQENTRY_TEXT . = ALIGN (4) ; _etext = . ; } -- cgit v1.2.2 From 24b45a12c21132e78e14f3aedf74bb1297228072 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 10 Nov 2009 15:57:01 +0100 Subject: microblaze: Stack trace support This is working implemetation but the problem is that Microblaze misses frame pointer that's why is there big loop which trace and show all addresses which are in text. It shows addresses which are in registers, etc. This is problem and this is the reason why all Microblaze traces are wrong. There is an option to do hacks and trace the kernel code but this is too complicated. Signed-off-by: Michal Simek --- arch/microblaze/kernel/Makefile | 1 + arch/microblaze/kernel/stacktrace.c | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 arch/microblaze/kernel/stacktrace.c (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index fddd0c403d40..c465a5c4669c 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_SELFMOD) += selfmod.o obj-$(CONFIG_HEART_BEAT) += heartbeat.o obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o obj-$(CONFIG_MMU) += misc.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += entry$(MMU).o diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c new file mode 100644 index 000000000000..123692f22647 --- /dev/null +++ b/arch/microblaze/kernel/stacktrace.c @@ -0,0 +1,65 @@ +/* + * Stack trace support for Microblaze. + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include + +/* FIXME initial support */ +void save_stack_trace(struct stack_trace *trace) +{ + unsigned long *sp; + unsigned long addr; + asm("addik %0, r1, 0" : "=r" (sp)); + + while (!kstack_end(sp)) { + addr = *sp++; + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + unsigned int *sp; + unsigned long addr; + + struct thread_info *ti = task_thread_info(tsk); + + if (tsk == current) + asm("addik %0, r1, 0" : "=r" (sp)); + else + sp = (unsigned int *)ti->cpu_context.r1; + + while (!kstack_end(sp)) { + addr = *sp++; + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -- cgit v1.2.2 From 519e9f417388ba055b7604db5f4f492f7c84f427 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 6 Nov 2009 12:31:00 +0100 Subject: microblaze: Register timecounter/cyclecounter It is the same counter as we use as free running one. I would like to use it for ftrace. Signed-off-by: Michal Simek --- arch/microblaze/kernel/timer.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 5499deae7fa6..ed61b2f17719 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -183,6 +183,31 @@ static cycle_t microblaze_read(struct clocksource *cs) return (cycle_t) (in_be32(TIMER_BASE + TCR1)); } +static struct timecounter microblaze_tc = { + .cc = NULL, +}; + +static cycle_t microblaze_cc_read(const struct cyclecounter *cc) +{ + return microblaze_read(NULL); +} + +static struct cyclecounter microblaze_cc = { + .read = microblaze_cc_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 24, +}; + +int __init init_microblaze_timecounter(void) +{ + microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + microblaze_cc.shift); + + timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); + + return 0; +} + static struct clocksource clocksource_microblaze = { .name = "microblaze_clocksource", .rating = 300, @@ -204,6 +229,9 @@ static int __init microblaze_clocksource_init(void) out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); /* start timer1 - up counting without interrupt */ out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); + + /* register timecounter - for ftrace support */ + init_microblaze_timecounter(); return 0; } -- cgit v1.2.2 From bf2d809668907c69b554459764b36584e4d57e4a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 10 Dec 2009 12:07:02 +0100 Subject: microblaze: Lockdep support Microblaze needs to do lock_init very soon because MMU init calls lock functions. Here is the explanation from Peter Zijlstra why we have to enable __ARCH_WANTS_INTERRUPTS_ON_CTSW. "So we schedule while holding rq->lock (for obvious reasons), but since lockdep tracks held locks per tasks, we need to transfer the held state from the prev to the next task. We do this by explicity calling spin_release(&rq->lock) in context_switch() right before switch_to(), and calling spin_acquire(&rq->lock) in finish_task_switch()->finish_lock_switch(). Now, for some reason lockdep thinks that interrupts got enabled over the context switch (git grep __ARCH_WANTS_INTERRUPTS_ON_CTSW arch/microblaze doesn't seem to turn up anything). Clearly trying to acquire the rq->lock with interrupts enabled is a bad idea and lockdep warns you about this." Signed-off-by: Michal Simek --- arch/microblaze/kernel/setup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 367ad330148e..acd70fe30a71 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -131,6 +131,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE); #endif + lockdep_init(); + /* initialize device tree for usage in early_printk */ early_init_devtree((void *)_fdt_start); -- cgit v1.2.2 From a3cd613b2e775eb59816c2c7c49c038d54917208 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Oct 2009 12:26:53 +0100 Subject: microblaze: Add TRACE_IRQFLAGS_SUPPORT There are just two major changes Renamed local_irq functions to raw_local_irq in irq.c. Added TRACE_IRQFLAGS_SUPPORT to Kconfig.debug. Look at Documentation/irqflags-tracing.txt Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/pvr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c index c9a4340ddd53..9bee9382bf74 100644 --- a/arch/microblaze/kernel/cpu/pvr.c +++ b/arch/microblaze/kernel/cpu/pvr.c @@ -45,7 +45,7 @@ int cpu_has_pvr(void) { - unsigned flags; + unsigned long flags; unsigned pvr0; local_save_flags(flags); -- cgit v1.2.2 From 2fd7c761a24c28e83d7194b4b4a099451126a503 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 16 Nov 2009 09:40:14 +0100 Subject: microblaze: ftrace: add static function tracer If -pg of gcc is enabled with CONFIG_FUNCTION_TRACER=y. a calling to _mcount will be inserted into each kernel function. so, there is a possibility to trace the kernel functions in _mcount. This patch add the specific _mcount support for static function tracing. by default, ftrace_trace_function is initialized as ftrace_stub(an empty function), so, the default _mcount will introduce very little overhead. after enabling ftrace in user-space, it will jump to a real tracing function and do static function tracing for us. Commit message from Wu Zhangjin Signed-off-by: Michal Simek --- arch/microblaze/kernel/Makefile | 11 ++++ arch/microblaze/kernel/cpu/Makefile | 4 ++ arch/microblaze/kernel/mcount.S | 105 ++++++++++++++++++++++++++++++ arch/microblaze/kernel/microblaze_ksyms.c | 5 ++ 4 files changed, 125 insertions(+) create mode 100644 arch/microblaze/kernel/mcount.S (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index c465a5c4669c..d5ee3264cd7d 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -2,6 +2,16 @@ # Makefile # +ifdef CONFIG_FUNCTION_TRACER +# Do not trace early boot code and low level code +CFLAGS_REMOVE_timer.o = -pg +CFLAGS_REMOVE_intc.o = -pg +CFLAGS_REMOVE_early_printk.o = -pg +CFLAGS_REMOVE_selfmod.o = -pg +CFLAGS_REMOVE_heartbeat.o = -pg +CFLAGS_REMOVE_ftrace.o = -pg +endif + extra-y := head.o vmlinux.lds obj-y += exceptions.o \ @@ -17,5 +27,6 @@ obj-$(CONFIG_HEART_BEAT) += heartbeat.o obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o obj-$(CONFIG_MMU) += misc.o obj-$(CONFIG_STACKTRACE) += stacktrace.o +obj-$(CONFIG_FUNCTION_TRACER) += mcount.o obj-y += entry$(MMU).o diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile index 20646e549271..59cc7bceaf8c 100644 --- a/arch/microblaze/kernel/cpu/Makefile +++ b/arch/microblaze/kernel/cpu/Makefile @@ -2,6 +2,10 @@ # Build the appropriate CPU version support # +ifdef CONFIG_FUNCTION_TRACER +CFLAGS_REMOVE_cache.o = -pg +endif + EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ -DCPU_REV=$(CPU_REV) diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S new file mode 100644 index 000000000000..a257a1b75ed2 --- /dev/null +++ b/arch/microblaze/kernel/mcount.S @@ -0,0 +1,105 @@ +/* + * Low-level ftrace handling + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. + */ + +#include + +#define NOALIGN_ENTRY(name) .globl name; name: + +/* FIXME MS: I think that I don't need to save all regs */ +#define SAVE_REGS \ + addik r1, r1, -120; \ + swi r2, r1, 4; \ + swi r3, r1, 8; \ + swi r4, r1, 12; \ + swi r5, r1, 116; \ + swi r6, r1, 16; \ + swi r7, r1, 20; \ + swi r8, r1, 24; \ + swi r9, r1, 28; \ + swi r10, r1, 32; \ + swi r11, r1, 36; \ + swi r12, r1, 40; \ + swi r13, r1, 44; \ + swi r14, r1, 48; \ + swi r16, r1, 52; \ + swi r17, r1, 56; \ + swi r18, r1, 60; \ + swi r19, r1, 64; \ + swi r20, r1, 68; \ + swi r21, r1, 72; \ + swi r22, r1, 76; \ + swi r23, r1, 80; \ + swi r24, r1, 84; \ + swi r25, r1, 88; \ + swi r26, r1, 92; \ + swi r27, r1, 96; \ + swi r28, r1, 100; \ + swi r29, r1, 104; \ + swi r30, r1, 108; \ + swi r31, r1, 112; + +#define RESTORE_REGS \ + lwi r2, r1, 4; \ + lwi r3, r1, 8; \ + lwi r4, r1, 12; \ + lwi r5, r1, 116; \ + lwi r6, r1, 16; \ + lwi r7, r1, 20; \ + lwi r8, r1, 24; \ + lwi r9, r1, 28; \ + lwi r10, r1, 32; \ + lwi r11, r1, 36; \ + lwi r12, r1, 40; \ + lwi r13, r1, 44; \ + lwi r14, r1, 48; \ + lwi r16, r1, 52; \ + lwi r17, r1, 56; \ + lwi r18, r1, 60; \ + lwi r19, r1, 64; \ + lwi r20, r1, 68; \ + lwi r21, r1, 72; \ + lwi r22, r1, 76; \ + lwi r23, r1, 80; \ + lwi r24, r1, 84; \ + lwi r25, r1, 88; \ + lwi r26, r1, 92; \ + lwi r27, r1, 96; \ + lwi r28, r1, 100; \ + lwi r29, r1, 104; \ + lwi r30, r1, 108; \ + lwi r31, r1, 112; \ + addik r1, r1, 120; + +ENTRY(ftrace_stub) + rtsd r15, 8; + nop; + +ENTRY(_mcount) + SAVE_REGS + swi r15, r1, 0; + /* MS: test function trace if is taken or not */ + lwi r20, r0, ftrace_trace_function; + addik r6, r0, ftrace_stub; + cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */ + beqid r5, end; /* MS: not taken -> jump over */ + nop; +/* static normal trace */ + lwi r6, r1, 120; /* MS: load parent addr */ + addik r5, r15, 0; /* MS: load current function addr */ + /* MS: here is dependency on previous code */ + brald r15, r20; /* MS: jump to ftrace handler */ + nop; +end: + lwi r15, r1, 0; + RESTORE_REGS + + rtsd r15, 8; /* MS: jump back */ + nop; diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index 59ff20e33e0c..bc4dcb7d3861 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* @@ -47,3 +48,7 @@ extern void __umodsi3(void); EXPORT_SYMBOL(__umodsi3); extern char *_ebss; EXPORT_SYMBOL_GPL(_ebss); +#ifdef CONFIG_FUNCTION_TRACER +extern void _mcount(void); +EXPORT_SYMBOL(_mcount); +#endif -- cgit v1.2.2 From 6d9e60ce30a1be35491c74df00aaa25d869f8a02 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 16 Nov 2009 09:55:08 +0100 Subject: microblaze: ftrace: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST Implement MCOUNT_TEST in asm code - it is faster than use generic code Signed-off-by: Michal Simek --- arch/microblaze/kernel/mcount.S | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S index a257a1b75ed2..97eef3eea944 100644 --- a/arch/microblaze/kernel/mcount.S +++ b/arch/microblaze/kernel/mcount.S @@ -85,6 +85,11 @@ ENTRY(ftrace_stub) ENTRY(_mcount) SAVE_REGS swi r15, r1, 0; + /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */ + lwi r5, r0, function_trace_stop; + bneid r5, end; + nop; + /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ /* MS: test function trace if is taken or not */ lwi r20, r0, ftrace_trace_function; addik r6, r0, ftrace_stub; -- cgit v1.2.2 From 7d241ff0567b9503d79ee775c40927d09b509f83 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 10 Dec 2009 14:15:44 +0100 Subject: microblaze: ftrace: Add dynamic trace support With dynamic function tracer, by default, _mcount is defined as an "empty" function, it returns directly without any more action. When enabling it in user-space, it will jump to a real tracing function(ftrace_caller), and do the real job for us. Differ from the static function tracer, dynamic function tracer provides two functions ftrace_make_call()/ftrace_make_nop() to enable/disable the tracing of some indicated kernel functions(set_ftrace_filter). In the kernel version, there is only one "_mcount" string for every kernel function, so, we just need to match this one in mcount_regex of scripts/recordmcount.pl. For more information please look at code and Documentation/trace folder. Steven ACK that scripts/recordmcount.pl part. Acked-by: Steven Rostedt Signed-off-by: Michal Simek --- arch/microblaze/kernel/Makefile | 2 +- arch/microblaze/kernel/ftrace.c | 151 ++++++++++++++++++++++++++++++++++++++++ arch/microblaze/kernel/mcount.S | 13 ++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 arch/microblaze/kernel/ftrace.c (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index d5ee3264cd7d..b07594eccf9b 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -27,6 +27,6 @@ obj-$(CONFIG_HEART_BEAT) += heartbeat.o obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o obj-$(CONFIG_MMU) += misc.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_FUNCTION_TRACER) += mcount.o +obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o obj-y += entry$(MMU).o diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c new file mode 100644 index 000000000000..c1889b101cb8 --- /dev/null +++ b/arch/microblaze/kernel/ftrace.c @@ -0,0 +1,151 @@ +/* + * Ftrace support for Microblaze. + * + * Copyright (C) 2009 Michal Simek + * Copyright (C) 2009 PetaLogix + * + * Based on MIPS and PowerPC ftrace code + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include + +#ifdef CONFIG_DYNAMIC_FTRACE +/* save value to addr - it is save to do it in asm */ +static int ftrace_modify_code(unsigned long addr, unsigned int value) +{ + int faulted = 0; + + __asm__ __volatile__(" 1: swi %2, %1, 0; \ + addik %0, r0, 0; \ + 2: \ + .section .fixup, \"ax\"; \ + 3: brid 2b; \ + addik %0, r0, 1; \ + .previous; \ + .section __ex_table,\"a\"; \ + .word 1b,3b; \ + .previous;" \ + : "=r" (faulted) + : "r" (addr), "r" (value) + ); + + if (unlikely(faulted)) + return -EFAULT; + + return 0; +} + +#define MICROBLAZE_NOP 0x80000000 +#define MICROBLAZE_BRI 0xb800000C + +static unsigned int recorded; /* if save was or not */ +static unsigned int imm; /* saving whole imm instruction */ + +/* There are two approaches howto solve ftrace_make nop function - look below */ +#undef USE_FTRACE_NOP + +#ifdef USE_FTRACE_NOP +static unsigned int bralid; /* saving whole bralid instruction */ +#endif + +int ftrace_make_nop(struct module *mod, + struct dyn_ftrace *rec, unsigned long addr) +{ + /* we have this part of code which we are working with + * b000c000 imm -16384 + * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> + * 80000000 or r0, r0, r0 + * + * The first solution (!USE_FTRACE_NOP-could be called branch solution) + * b000c000 bri 12 (0xC - jump to any other instruction) + * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> + * 80000000 or r0, r0, r0 + * any other instruction + * + * The second solution (USE_FTRACE_NOP) - no jump just nops + * 80000000 or r0, r0, r0 + * 80000000 or r0, r0, r0 + * 80000000 or r0, r0, r0 + */ + int ret = 0; + + if (recorded == 0) { + recorded = 1; + imm = *(unsigned int *)rec->ip; + pr_debug("%s: imm:0x%x\n", __func__, imm); +#ifdef USE_FTRACE_NOP + bralid = *(unsigned int *)(rec->ip + 4); + pr_debug("%s: bralid 0x%x\n", __func__, bralid); +#endif /* USE_FTRACE_NOP */ + } + +#ifdef USE_FTRACE_NOP + ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP); + ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP); +#else /* USE_FTRACE_NOP */ + ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI); +#endif /* USE_FTRACE_NOP */ + return ret; +} + +static int ret_addr; /* initialized as 0 by default */ + +/* I believe that first is called ftrace_make_nop before this function */ +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + int ret; + ret_addr = addr; /* saving where the barrier jump is */ + pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n", + __func__, (unsigned int)addr, (unsigned int)rec->ip, imm); + ret = ftrace_modify_code(rec->ip, imm); +#ifdef USE_FTRACE_NOP + pr_debug("%s: bralid:0x%x\n", __func__, bralid); + ret += ftrace_modify_code(rec->ip + 4, bralid); +#endif /* USE_FTRACE_NOP */ + return ret; +} + +int __init ftrace_dyn_arch_init(void *data) +{ + /* The return code is retured via data */ + *(unsigned long *)data = 0; + + return 0; +} + +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + unsigned long ip = (unsigned long)(&ftrace_call); + unsigned int upper = (unsigned int)func; + unsigned int lower = (unsigned int)func; + int ret = 0; + + /* create proper saving to ftrace_call poll */ + upper = 0xb0000000 + (upper >> 16); /* imm func_upper */ + lower = 0x32800000 + (lower & 0xFFFF); /* addik r20, r0, func_lower */ + + pr_debug("%s: func=0x%x, ip=0x%x, upper=0x%x, lower=0x%x\n", + __func__, (unsigned int)func, (unsigned int)ip, upper, lower); + + /* save upper and lower code */ + ret = ftrace_modify_code(ip, upper); + ret += ftrace_modify_code(ip + 4, lower); + + /* We just need to remove the rtsd r15, 8 by NOP */ + BUG_ON(!ret_addr); + if (ret_addr) + ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP); + else + ret = 1; /* fault */ + + /* All changes are done - lets do caches consistent */ + flush_icache(); + return ret; +} + +#endif /* CONFIG_DYNAMIC_FTRACE */ diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S index 97eef3eea944..30aaf8fb55b2 100644 --- a/arch/microblaze/kernel/mcount.S +++ b/arch/microblaze/kernel/mcount.S @@ -83,6 +83,12 @@ ENTRY(ftrace_stub) nop; ENTRY(_mcount) +#ifdef CONFIG_DYNAMIC_FTRACE +ENTRY(ftrace_caller) + /* MS: It is just barrier which is removed from C code */ + rtsd r15, 8 + nop +#endif /* CONFIG_DYNAMIC_FTRACE */ SAVE_REGS swi r15, r1, 0; /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */ @@ -90,12 +96,19 @@ ENTRY(_mcount) bneid r5, end; nop; /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ +#ifndef CONFIG_DYNAMIC_FTRACE /* MS: test function trace if is taken or not */ lwi r20, r0, ftrace_trace_function; addik r6, r0, ftrace_stub; cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */ beqid r5, end; /* MS: not taken -> jump over */ nop; +#else /* CONFIG_DYNAMIC_FTRACE */ +NOALIGN_ENTRY(ftrace_call) +/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */ + nop + nop +#endif /* CONFIG_DYNAMIC_FTRACE */ /* static normal trace */ lwi r6, r1, 120; /* MS: load parent addr */ addik r5, r15, 0; /* MS: load current function addr */ -- cgit v1.2.2 From a0d3e66522e8f6119f002cf31e5d92d7ae73b409 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 16 Nov 2009 10:32:10 +0100 Subject: microblaze: ftrace: add function graph support For more information look at Documentation/trace folder. Signed-off-by: Michal Simek --- arch/microblaze/kernel/ftrace.c | 58 +++++++++++++++++++++++++++++++++++++++++ arch/microblaze/kernel/mcount.S | 41 +++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c index c1889b101cb8..0952a8b52c35 100644 --- a/arch/microblaze/kernel/ftrace.c +++ b/arch/microblaze/kernel/ftrace.c @@ -14,6 +14,64 @@ #include #include +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + unsigned long old; + int faulted, err; + struct ftrace_graph_ent trace; + unsigned long return_hooker = (unsigned long) + &return_to_handler; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + /* + * Protect against fault, even if it shouldn't + * happen. This tool is too much intrusive to + * ignore such a protection. + */ + asm volatile(" 1: lwi %0, %2, 0; \ + 2: swi %3, %2, 0; \ + addik %1, r0, 0; \ + 3: \ + .section .fixup, \"ax\"; \ + 4: brid 3b; \ + addik %1, r0, 1; \ + .previous; \ + .section __ex_table,\"a\"; \ + .word 1b,4b; \ + .word 2b,4b; \ + .previous;" \ + : "=&r" (old), "=r" (faulted) + : "r" (parent), "r" (return_hooker) + ); + + if (unlikely(faulted)) { + ftrace_graph_stop(); + WARN_ON(1); + return; + } + + err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0); + if (err == -EBUSY) { + *parent = old; + return; + } + + trace.func = self_addr; + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + *parent = old; + } +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + #ifdef CONFIG_DYNAMIC_FTRACE /* save value to addr - it is save to do it in asm */ static int ftrace_modify_code(unsigned long addr, unsigned int value) diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S index 30aaf8fb55b2..84a19458c74d 100644 --- a/arch/microblaze/kernel/mcount.S +++ b/arch/microblaze/kernel/mcount.S @@ -96,6 +96,27 @@ ENTRY(ftrace_caller) bneid r5, end; nop; /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + lwi r5, r0, ftrace_graph_return; + addik r6, r0, ftrace_stub; /* asm implementation */ + cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */ + beqid r5, end_graph_tracer; + nop; + + lwi r6, r0, ftrace_graph_entry; + addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */ + cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */ + beqid r5, end_graph_tracer; + nop; + addik r5, r1, 120; /* MS: load parent addr */ + addik r6, r15, 0; /* MS: load current function addr */ + bralid r15, prepare_ftrace_return; + nop; + /* MS: graph was taken that's why - can jump over function trace */ + brid end; + nop; +end_graph_tracer: +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #ifndef CONFIG_DYNAMIC_FTRACE /* MS: test function trace if is taken or not */ lwi r20, r0, ftrace_trace_function; @@ -121,3 +142,23 @@ end: rtsd r15, 8; /* MS: jump back */ nop; + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(return_to_handler) + nop; /* MS: just barrier for rtsd r15, 8 */ + nop; + SAVE_REGS + swi r15, r1, 0; + + /* MS: find out returning address */ + bralid r15, ftrace_return_to_handler; + nop; + + /* MS: return value from ftrace_return_to_handler is my returning addr + * must be before restore regs because I have to restore r3 content */ + addik r15, r3, 0; + RESTORE_REGS + + rtsd r15, 8; /* MS: jump back */ + nop; +#endif /* CONFIG_FUNCTION_TRACER */ -- cgit v1.2.2 From 4f911b0daf0f7028a4fe792b701a48d10da36d84 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 16 Nov 2009 10:34:15 +0100 Subject: microblaze: ftrace: Add dynamic function graph tracer This patch add support for dynamic function graph tracer. There is one my expactation that I can do flush_icache after all code modification. On microblaze is this safer than do flush for every entry. For icache is used name flush but correct should be invalidation - this will be fix in upcomming new cache implementaion and WB support. Signed-off-by: Michal Simek --- arch/microblaze/kernel/ftrace.c | 28 ++++++++++++++++++++++++++++ arch/microblaze/kernel/mcount.S | 6 ++++++ 2 files changed, 34 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c index 0952a8b52c35..388b31ca65a1 100644 --- a/arch/microblaze/kernel/ftrace.c +++ b/arch/microblaze/kernel/ftrace.c @@ -206,4 +206,32 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; } +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +unsigned int old_jump; /* saving place for jump instruction */ + +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned int ret; + unsigned long ip = (unsigned long)(&ftrace_call_graph); + + old_jump = *(unsigned int *)ip; /* save jump over instruction */ + ret = ftrace_modify_code(ip, MICROBLAZE_NOP); + flush_icache(); + + pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump); + return ret; +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + unsigned int ret; + unsigned long ip = (unsigned long)(&ftrace_call_graph); + + ret = ftrace_modify_code(ip, old_jump); + flush_icache(); + + pr_debug("%s\n", __func__); + return ret; +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #endif /* CONFIG_DYNAMIC_FTRACE */ diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S index 84a19458c74d..e7eaa7a8cbd3 100644 --- a/arch/microblaze/kernel/mcount.S +++ b/arch/microblaze/kernel/mcount.S @@ -97,6 +97,7 @@ ENTRY(ftrace_caller) nop; /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER +#ifndef CONFIG_DYNAMIC_FTRACE lwi r5, r0, ftrace_graph_return; addik r6, r0, ftrace_stub; /* asm implementation */ cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */ @@ -108,6 +109,11 @@ ENTRY(ftrace_caller) cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */ beqid r5, end_graph_tracer; nop; +#else /* CONFIG_DYNAMIC_FTRACE */ +NOALIGN_ENTRY(ftrace_call_graph) + /* MS: jump over graph function - replaced from C code */ + bri end_graph_tracer +#endif /* CONFIG_DYNAMIC_FTRACE */ addik r5, r1, 120; /* MS: load parent addr */ addik r6, r15, 0; /* MS: load current function addr */ bralid r15, prepare_ftrace_return; -- cgit v1.2.2 From f7816e284b72820b295b2d377cc635d7305f6728 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 13 Nov 2009 08:26:49 +0100 Subject: microblaze: Remove saving and restoring before calling signal code Saving is done in SAVE_STATE macros that's why another save discard previous saved value. This change has no effect to normal programs because they ends in any exception and they are killed. On the other side has effect on debugging. Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index e3ecb36dd554..7417d9ad0d18 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -711,15 +711,11 @@ C_ENTRY(ret_from_exc): * (in a possibly modified form) after do_signal returns. * store return registers separately because this macros is use * for others exceptions */ - swi r3, r1, PTO + PT_R3; - swi r4, r1, PTO + PT_R4; la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ addi r7, r0, 0; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; /* Finally, return to user state. */ 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ -- cgit v1.2.2 From 753758304019fc7c2ef3af674f52a193b1606d15 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 29 Oct 2009 08:58:15 +0100 Subject: microblaze: Fix announce message for reset gpio I had to change message for gpio-reset because I always not to see it. Prefix RESET is big and visible. Signed-off-by: Michal Simek --- arch/microblaze/kernel/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index ce74a6f436e3..789af930d72c 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -87,7 +87,7 @@ void of_platform_reset_gpio_probe(void) /* Setup output direction */ gpio_set_value(handle, 0); - printk(KERN_INFO "Registered reset device: %d\n", handle); + printk(KERN_INFO "RESET: Registered gpio device: %d\n", handle); return; err: gpio_free(handle); -- cgit v1.2.2 From 67bf87665466c4ea93e2c54d66dfd4cdac011a4b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 29 Oct 2009 10:12:59 +0100 Subject: microblaze: Support both levels for reset Till this patch reset always perform writen to 1. Now we can use negative logic and perform reset write to 0. It is opposite level than is currently read from that pin Signed-off-by: Michal Simek --- arch/microblaze/kernel/reset.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index 789af930d72c..a1721a33042e 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -17,6 +17,7 @@ #include static int handle; /* reset pin handle */ +static unsigned int reset_val; static int of_reset_gpio_handle(void) { @@ -75,9 +76,9 @@ void of_platform_reset_gpio_probe(void) } /* get current setup value */ - ret = gpio_get_value(handle); + reset_val = gpio_get_value(handle); /* FIXME maybe worth to perform any action */ - pr_debug("Reset: Gpio output state: 0x%x\n", ret); + pr_debug("Reset: Gpio output state: 0x%x\n", reset_val); /* Setup GPIO as output */ ret = gpio_direction_output(handle, 0); @@ -87,7 +88,8 @@ void of_platform_reset_gpio_probe(void) /* Setup output direction */ gpio_set_value(handle, 0); - printk(KERN_INFO "RESET: Registered gpio device: %d\n", handle); + printk(KERN_INFO "RESET: Registered gpio device: %d, current val: %d\n", + handle, reset_val); return; err: gpio_free(handle); @@ -97,7 +99,7 @@ err: static void gpio_system_reset(void) { - gpio_set_value(handle, 1); + gpio_set_value(handle, 1 - reset_val); } #else #define gpio_system_reset() do {} while (0) -- cgit v1.2.2 From 6cec713b1629228527fb8f813003522817f55da1 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 15 Oct 2009 13:34:31 +0200 Subject: microblaze: Detect new 7.20.d version Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 3539babc1c18..a9aa5cf11c39 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -29,6 +29,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"7.20.a", 0x0c}, {"7.20.b", 0x0d}, {"7.20.c", 0x0e}, + {"7.20.d", 0x0f}, /* FIXME There is no keycode defined in MBV for these versions */ {"2.10.a", 0x10}, {"3.00.a", 0x20}, -- cgit v1.2.2 From 44e4e196a9b3a703ebe273ffe3fb6cda326fe5d3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 8 Oct 2009 13:06:42 +0200 Subject: microblaze: Fix cache_line_lenght We used cache_line as cache_line_lenght. For this reason we did cache flushing 4 times longer than was necessary. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 16 ++++++++-------- arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c | 4 ++-- arch/microblaze/kernel/cpu/cpuinfo-static.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index af866a450125..538f1df6761d 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -140,7 +140,7 @@ void __invalidate_icache_all(void) /* Just loop through cache size and invalidate, no need to add CACHE_BASE address */ for (i = 0; i < cpuinfo.icache_size; - i += cpuinfo.icache_line) + i += cpuinfo.icache_line_length) __invalidate_icache(i); __enable_icache(); @@ -160,15 +160,15 @@ void __invalidate_icache_range(unsigned long start, unsigned long end) * just cover cache footprint */ end = min(start + cpuinfo.icache_size, end); - align = ~(cpuinfo.icache_line - 1); + align = ~(cpuinfo.icache_line_length - 1); start &= align; /* Make sure we are aligned */ /* Push end up to the next cache line */ - end = ((end & align) + cpuinfo.icache_line); + end = ((end & align) + cpuinfo.icache_line_length); local_irq_save(flags); __disable_icache(); - for (i = start; i < end; i += cpuinfo.icache_line) + for (i = start; i < end; i += cpuinfo.icache_line_length) __invalidate_icache(i); __enable_icache(); @@ -207,7 +207,7 @@ void __invalidate_dcache_all(void) * no need to add CACHE_BASE address */ for (i = 0; i < cpuinfo.dcache_size; - i += cpuinfo.dcache_line) + i += cpuinfo.dcache_line_length) __invalidate_dcache(i); __enable_dcache(); @@ -227,14 +227,14 @@ void __invalidate_dcache_range(unsigned long start, unsigned long end) * just cover cache footprint */ end = min(start + cpuinfo.dcache_size, end); - align = ~(cpuinfo.dcache_line - 1); + align = ~(cpuinfo.dcache_line_length - 1); start &= align; /* Make sure we are aligned */ /* Push end up to the next cache line */ - end = ((end & align) + cpuinfo.dcache_line); + end = ((end & align) + cpuinfo.dcache_line_length); local_irq_save(flags); __disable_dcache(); - for (i = start; i < end; i += cpuinfo.dcache_line) + for (i = start; i < end; i += cpuinfo.dcache_line_length) __invalidate_dcache(i); __enable_dcache(); diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index c259786e7faa..c5acf2b56eed 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -70,7 +70,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) CI(use_icache, USE_ICACHE); CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); CI(icache_write, ICACHE_ALLOW_WR); - CI(icache_line, ICACHE_LINE_LEN); + ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2; CI(icache_size, ICACHE_BYTE_SIZE); CI(icache_base, ICACHE_BASEADDR); CI(icache_high, ICACHE_HIGHADDR); @@ -78,7 +78,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) CI(use_dcache, USE_DCACHE); CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); CI(dcache_write, DCACHE_ALLOW_WR); - CI(dcache_line, DCACHE_LINE_LEN); + ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2; CI(dcache_size, DCACHE_BYTE_SIZE); CI(dcache_base, DCACHE_BASEADDR); CI(dcache_high, DCACHE_HIGHADDR); diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index adb448f93d5f..6558429eb973 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -72,12 +72,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) ci->use_icache = fcpu(cpu, "xlnx,use-icache"); ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits"); ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr"); - ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2; - if (!ci->icache_line) { + ci->icache_line_length = fcpu(cpu, "xlnx,icache-line-len") << 2; + if (!ci->icache_line_length) { if (fcpu(cpu, "xlnx,icache-use-fsl")) - ci->icache_line = 4 << 2; + ci->icache_line_length = 4 << 2; else - ci->icache_line = 1 << 2; + ci->icache_line_length = 1 << 2; } ci->icache_size = fcpu(cpu, "i-cache-size"); ci->icache_base = fcpu(cpu, "i-cache-baseaddr"); @@ -86,12 +86,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) ci->use_dcache = fcpu(cpu, "xlnx,use-dcache"); ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag"); ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr"); - ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2; - if (!ci->dcache_line) { + ci->dcache_line_length = fcpu(cpu, "xlnx,dcache-line-len") << 2; + if (!ci->dcache_line_length) { if (fcpu(cpu, "xlnx,dcache-use-fsl")) - ci->dcache_line = 4 << 2; + ci->dcache_line_length = 4 << 2; else - ci->dcache_line = 1 << 2; + ci->dcache_line_length = 1 << 2; } ci->dcache_size = fcpu(cpu, "d-cache-size"); ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); -- cgit v1.2.2 From e051af576a414b6fcfe6589e99b2357522718050 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 14 Oct 2009 11:12:50 +0200 Subject: microblaze: Extend cpuinfo for support write-back caches There is missing checking agains PVR but this is not important for now. There are some missing checking too. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo-static.c | 1 + arch/microblaze/kernel/cpu/mb.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index 6558429eb973..6095aa6b5c88 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -96,6 +96,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) ci->dcache_size = fcpu(cpu, "d-cache-size"); ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); ci->dcache_high = fcpu(cpu, "d-cache-highaddr"); + ci->dcache_wb = fcpu(cpu, "xlnx,dcache-use-writeback"); ci->use_dopb = fcpu(cpu, "xlnx,d-opb"); ci->use_iopb = fcpu(cpu, "xlnx,i-opb"); diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c index 4dcfccdbc364..0c912b2a8e03 100644 --- a/arch/microblaze/kernel/cpu/mb.c +++ b/arch/microblaze/kernel/cpu/mb.c @@ -103,11 +103,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) else count += seq_printf(m, "Icache:\t\tno\n"); - if (cpuinfo.use_dcache) + if (cpuinfo.use_dcache) { count += seq_printf(m, "Dcache:\t\t%ukB\n", cpuinfo.dcache_size >> 10); - else + if (cpuinfo.dcache_wb) + count += seq_printf(m, "\t\twrite-back\n"); + else + count += seq_printf(m, "\t\twrite-through\n"); + } else count += seq_printf(m, "Dcache:\t\tno\n"); count += seq_printf(m, -- cgit v1.2.2 From a01523cdcd2439b553086127be3d30ac9c3cb651 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 15 Oct 2009 11:32:25 +0200 Subject: microblaze: Ptrace notifying from signal code After the signal frame is set up on the userspace stack, ptrace() should be given an opportunity to single-step into the signal handler FRV, Blackfin, mn10300 and UM. Worth to look at that patches. Signed-off-by: Michal Simek --- arch/microblaze/kernel/signal.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 1c80e4fc40ce..0c96ac34c316 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -233,6 +233,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, set_fs(USER_DS); + /* the tracer may want to single-step inside the handler */ + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + #ifdef DEBUG_SIG printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", current->comm, current->pid, frame, regs->pc); -- cgit v1.2.2 From a1f55113ca2130f775eeebe799a401619bfd0295 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 15 Oct 2009 15:18:13 +0200 Subject: microblaze: Move cache macro from cache.h to cacheflush.h Signed-off-by: Michal Simek --- arch/microblaze/kernel/process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index c592d475b3d8..812f1bf06c9e 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -15,6 +15,7 @@ #include #include #include +#include void show_regs(struct pt_regs *regs) { -- cgit v1.2.2 From 6d858535be59b220c0f8dc335e030c2e3f3a3032 Mon Sep 17 00:00:00 2001 From: John Linn Date: Fri, 5 Jun 2009 11:36:31 -0600 Subject: microblaze: Fix the heartbeat gpio to be more robust The device tree handling for the gpio in the heart beat was not handling the system when there was no gpio and it wasn't working with a newer version of the gpio core which does not have the is-bidir property. Signed-off-by: John Linn Signed-off-by: Michal Simek --- arch/microblaze/kernel/heartbeat.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c index 1bdf20222b92..522751737cfa 100644 --- a/arch/microblaze/kernel/heartbeat.c +++ b/arch/microblaze/kernel/heartbeat.c @@ -45,6 +45,7 @@ void heartbeat(void) void setup_heartbeat(void) { struct device_node *gpio = NULL; + int *prop; int j; char *gpio_list[] = { "xlnx,xps-gpio-1.00.a", @@ -58,10 +59,14 @@ void setup_heartbeat(void) break; } - base_addr = *(int *) of_get_property(gpio, "reg", NULL); - base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); - printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); + if (gpio) { + base_addr = *(int *) of_get_property(gpio, "reg", NULL); + base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); + printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); - if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL)) - out_be32(base_addr + 4, 0); /* GPIO is configured as output */ + /* GPIO is configured as output */ + prop = (int *) of_get_property(gpio, "xlnx,is-bidir", NULL); + if (prop) + out_be32(base_addr + 4, 0); + } } -- cgit v1.2.2 From f6e1f1b4809b6a63e22f82358ba2e750c7e1c1a2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 21 Oct 2009 12:29:46 +0200 Subject: microblaze: Checking DTS against PVR for write-back cache WB cache has special flag in PVR. There is added checking mechanism for PVR and DTS. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index c5acf2b56eed..f72dbd66c844 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -21,8 +21,14 @@ */ #define CI(c, p) { ci->c = PVR_##p(pvr); } + +#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE) #define err_printk(x) \ early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n"); +#else +#define err_printk(x) \ + printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n"); +#endif void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) { @@ -83,6 +89,11 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) CI(dcache_base, DCACHE_BASEADDR); CI(dcache_high, DCACHE_HIGHADDR); + temp = PVR_DCACHE_USE_WRITEBACK(pvr); + if (ci->dcache_wb != temp) + err_printk("DCACHE WB"); + ci->dcache_wb = temp; + CI(use_dopb, D_OPB); CI(use_iopb, I_OPB); CI(use_dlmb, D_LMB); -- cgit v1.2.2 From 833d0d8da41b80e5f7c3b34cb187b12c33ef66c8 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 19 Oct 2009 13:50:02 +0200 Subject: microblaze: Enable futimesat syscall Futimesat was disabled. LTP testing shows that MB has no problem with this syscall. Signed-off-by: Michal Simek --- arch/microblaze/kernel/syscall_table.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index b96f365ea6b1..4e666d9c1261 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -303,7 +303,7 @@ ENTRY(sys_call_table) .long sys_mkdirat .long sys_mknodat .long sys_fchownat - .long sys_ni_syscall + .long sys_futimesat .long sys_fstatat64 /* 300 */ .long sys_unlinkat .long sys_renameat -- cgit v1.2.2 From 33d9ff5985ff015cbaaef85285d19fe580487cf3 Mon Sep 17 00:00:00 2001 From: "steve@digidescorp.com" Date: Tue, 17 Nov 2009 08:43:39 -0600 Subject: microblaze: Fix level interrupt ACKing Level interrupts need to be ack'd in the unmask handler, as in powerpc. Among other issues, this bug causes the system clock to appear to run at double-speed. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/intc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 6eea6f92b84e..03172c1da770 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -42,8 +42,16 @@ unsigned int nr_irq; static void intc_enable_or_unmask(unsigned int irq) { + unsigned long mask = 1 << irq; pr_debug("enable_or_unmask: %d\n", irq); - out_be32(INTC_BASE + SIE, 1 << irq); + out_be32(INTC_BASE + SIE, mask); + + /* ack level irqs because they can't be acked during + * ack function since the handle_level_irq function + * acks the irq before calling the interrupt handler + */ + if (irq_desc[irq].status & IRQ_LEVEL) + out_be32(INTC_BASE + IAR, mask); } static void intc_disable_or_mask(unsigned int irq) -- cgit v1.2.2 From 11d5136043424ec6980293210ae774d3ab9646b2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 7 Dec 2009 08:21:34 +0100 Subject: microblaze: Do not count system calls in default There is not necessary to count system calls that's why I added DEBUG macro Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 7417d9ad0d18..b061d98a3218 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -31,6 +31,8 @@ #include #include +#undef DEBUG + /* The size of a state save frame. */ #define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE) @@ -352,10 +354,12 @@ C_ENTRY(_user_exception): add r12, r12, r12; /* convert num -> ptr */ add r12, r12, r12; +#ifdef DEBUG /* Trac syscalls and stored them to r0_ram */ lwi r3, r12, 0x400 + r0_ram addi r3, r3, 1 swi r3, r12, 0x400 + r0_ram +#endif # Find and jump into the syscall handler. lwi r12, r12, sys_call_table -- cgit v1.2.2 From 5de23446300a4b2170efd048ae2ec65022650650 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 8 Dec 2009 17:49:21 +0100 Subject: microblaze: Remove panic_timeout init value panic_timeout is in BSS section and it is cleared with BSS section. This means that value is setup to 0. Signed-off-by: Michal Simek --- arch/microblaze/kernel/setup.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index acd70fe30a71..1c3f18ba8af1 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -58,8 +58,6 @@ void __init setup_arch(char **cmdline_p) __invalidate_dcache_all(); __enable_dcache(); - panic_timeout = 120; - setup_memory(); #if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER) -- cgit v1.2.2 From 81ab0dfd9444eabdfd64fb007b0f81cde6b153da Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 8 Dec 2009 17:51:06 +0100 Subject: microblaze: Remove ancient and fake microblaze version from cpu_ver table We need to continue with next microblaze PVR version that's why I have to remove that ancient version. These version strings not match any versions. From Microblaze v5.00.a is possible to use this style. I believe that none use ancients versions. If yes they will be just labeled as unknown version. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index a9aa5cf11c39..852ff056ee8f 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -30,11 +30,6 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"7.20.b", 0x0d}, {"7.20.c", 0x0e}, {"7.20.d", 0x0f}, - /* FIXME There is no keycode defined in MBV for these versions */ - {"2.10.a", 0x10}, - {"3.00.a", 0x20}, - {"4.00.a", 0x30}, - {"4.00.b", 0x40}, {NULL, 0}, }; -- cgit v1.2.2 From c8983a5c6ecc5ca68a871c44bc35f714663a4dfa Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 8 Dec 2009 17:54:07 +0100 Subject: microblaze: Add PVR for Microblaze v7.30.a Microblaze v7.30.a will have 0x10 version string. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 852ff056ee8f..991d71311b0e 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -30,6 +30,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"7.20.b", 0x0d}, {"7.20.c", 0x0e}, {"7.20.d", 0x0f}, + {"7.30.a", 0x10}, {NULL, 0}, }; -- cgit v1.2.2 From 2ee2ff875a4d3bdb941e2bb1173cd927c09d5a67 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 10 Dec 2009 11:43:57 +0100 Subject: microblaze: Support for WB cache Microblaze version 7.20.d is the first MB version which can be run on MMU linux. Please do not used previous version because they contain HW bug. Based on WB support was necessary to redesign whole cache design. Microblaze versions from 7.20.a don't need to disable IRQ and cache before working with them that's why there are special structures for it. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 663 ++++++++++++++++++++++++++----------- arch/microblaze/kernel/setup.c | 9 +- arch/microblaze/kernel/signal.c | 30 +- 3 files changed, 510 insertions(+), 192 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 538f1df6761d..d9d63831cc2f 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -3,7 +3,7 @@ * * Copyright (C) 2007-2009 Michal Simek * Copyright (C) 2007-2009 PetaLogix - * Copyright (C) 2007 John Williams + * Copyright (C) 2007-2009 John Williams * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -13,243 +13,534 @@ #include #include #include +#include -/* Exported functions */ +static inline void __invalidate_flush_icache(unsigned int addr) +{ + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (addr)); +} + +static inline void __flush_dcache(unsigned int addr) +{ + __asm__ __volatile__ ("wdc.flush %0, r0;" \ + : : "r" (addr)); +} + +static inline void __invalidate_dcache(unsigned int baseaddr, + unsigned int offset) +{ + __asm__ __volatile__ ("wdc.clear %0, %1;" \ + : : "r" (baseaddr), "r" (offset)); +} -void _enable_icache(void) +static inline void __enable_icache_msr(void) { - if (cpuinfo.use_icache) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrset r0, %0; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ + __asm__ __volatile__ (" msrset r0, %0; \ + nop; " \ + : : "i" (MSR_ICE) : "memory"); +} + +static inline void __disable_icache_msr(void) +{ + __asm__ __volatile__ (" msrclr r0, %0; \ + nop; " \ + : : "i" (MSR_ICE) : "memory"); +} + +static inline void __enable_dcache_msr(void) +{ + __asm__ __volatile__ (" msrset r0, %0; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - ori r12, r12, %0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ - : "memory", "r12"); -#endif - } } -void _disable_icache(void) +static inline void __disable_dcache_msr(void) { - if (cpuinfo.use_icache) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrclr r0, %0; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ + __asm__ __volatile__ (" msrclr r0, %0; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - andi r12, r12, ~%0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_ICE) \ +} + +static inline void __enable_icache_nomsr(void) +{ + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ : "memory", "r12"); -#endif - } } -void _invalidate_icache(unsigned int addr) +static inline void __disable_icache_nomsr(void) { - if (cpuinfo.use_icache) { - __asm__ __volatile__ (" \ - wic %0, r0" \ - : \ - : "r" (addr)); - } + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ + : "memory", "r12"); } -void _enable_dcache(void) +static inline void __enable_dcache_nomsr(void) { - if (cpuinfo.use_dcache) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrset r0, %0; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ - : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - ori r12, r12, %0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory", "r12"); -#endif - } } -void _disable_dcache(void) +static inline void __disable_dcache_nomsr(void) { -#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR - __asm__ __volatile__ (" \ - msrclr r0, %0; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ - : "memory"); -#else - __asm__ __volatile__ (" \ - mfs r12, rmsr; \ - nop; \ - andi r12, r12, ~%0; \ - mts rmsr, r12; \ - nop; " \ - : \ - : "i" (MSR_DCE) \ + __asm__ __volatile__ (" mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ : "memory", "r12"); -#endif } -void _invalidate_dcache(unsigned int addr) + +/* Helper macro for computing the limits of cache range loops */ +#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \ +do { \ + int align = ~(cache_line_length - 1); \ + end = min(start + cache_size, end); \ + start &= align; \ + end = ((end & align) + cache_line_length); \ +} while (0); + +/* + * Helper macro to loop over the specified cache_size/line_length and + * execute 'op' on that cacheline + */ +#define CACHE_ALL_LOOP(cache_size, line_length, op) \ +do { \ + unsigned int len = cache_size; \ + int step = -line_length; \ + BUG_ON(step >= 0); \ + \ + __asm__ __volatile__ (" 1: " #op " %0, r0; \ + bgtid %0, 1b; \ + addk %0, %0, %1; \ + " : : "r" (len), "r" (step) \ + : "memory"); \ +} while (0); + + +#define CACHE_ALL_LOOP2(cache_size, line_length, op) \ +do { \ + unsigned int len = cache_size; \ + int step = -line_length; \ + BUG_ON(step >= 0); \ + \ + __asm__ __volatile__ (" 1: " #op " r0, %0; \ + bgtid %0, 1b; \ + addk %0, %0, %1; \ + " : : "r" (len), "r" (step) \ + : "memory"); \ +} while (0); + +/* for wdc.flush/clear */ +#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \ +do { \ + int step = -line_length; \ + int count = end - start; \ + BUG_ON(count <= 0); \ + \ + __asm__ __volatile__ (" 1: " #op " %0, %1; \ + bgtid %1, 1b; \ + addk %1, %1, %2; \ + " : : "r" (start), "r" (count), \ + "r" (step) : "memory"); \ +} while (0); + +/* It is used only first parameter for OP - for wic, wdc */ +#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ +do { \ + int step = -line_length; \ + int count = end - start; \ + BUG_ON(count <= 0); \ + \ + __asm__ __volatile__ (" 1: addk %0, %0, %1; \ + " #op " %0, r0; \ + bgtid %1, 1b; \ + addk %1, %1, %2; \ + " : : "r" (start), "r" (count), \ + "r" (step) : "memory"); \ +} while (0); + +static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) { - __asm__ __volatile__ (" \ - wdc %0, r0" \ - : \ - : "r" (addr)); + unsigned long flags; + + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.icache_line_length, cpuinfo.icache_size); + + local_irq_save(flags); + __disable_icache_msr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); + + __enable_icache_msr(); + local_irq_restore(flags); } -void __invalidate_icache_all(void) +static void __flush_icache_range_nomsr_irq(unsigned long start, + unsigned long end) { - unsigned int i; - unsigned flags; + unsigned long flags; - if (cpuinfo.use_icache) { - local_irq_save(flags); - __disable_icache(); + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); - /* Just loop through cache size and invalidate, no need to add - CACHE_BASE address */ - for (i = 0; i < cpuinfo.icache_size; - i += cpuinfo.icache_line_length) - __invalidate_icache(i); + CACHE_LOOP_LIMITS(start, end, + cpuinfo.icache_line_length, cpuinfo.icache_size); - __enable_icache(); - local_irq_restore(flags); - } + local_irq_save(flags); + __disable_icache_nomsr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); + + __enable_icache_nomsr(); + local_irq_restore(flags); } -void __invalidate_icache_range(unsigned long start, unsigned long end) +static void __flush_icache_range_noirq(unsigned long start, + unsigned long end) { - unsigned int i; - unsigned flags; - unsigned int align; - - if (cpuinfo.use_icache) { - /* - * No need to cover entire cache range, - * just cover cache footprint - */ - end = min(start + cpuinfo.icache_size, end); - align = ~(cpuinfo.icache_line_length - 1); - start &= align; /* Make sure we are aligned */ - /* Push end up to the next cache line */ - end = ((end & align) + cpuinfo.icache_line_length); - - local_irq_save(flags); - __disable_icache(); - - for (i = start; i < end; i += cpuinfo.icache_line_length) - __invalidate_icache(i); - - __enable_icache(); - local_irq_restore(flags); - } + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.icache_line_length, cpuinfo.icache_size); + CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); +} + +static void __flush_icache_all_msr_irq(void) +{ + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_icache_msr(); + + CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); + + __enable_icache_msr(); + local_irq_restore(flags); +} + +static void __flush_icache_all_nomsr_irq(void) +{ + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_icache_nomsr(); + + CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); + + __enable_icache_nomsr(); + local_irq_restore(flags); } -void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) +static void __flush_icache_all_noirq(void) { - __invalidate_icache_all(); + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); } -void __invalidate_icache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long adr, - int len) +static void __invalidate_dcache_all_msr_irq(void) { - __invalidate_icache_all(); + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_dcache_msr(); + + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_msr(); + local_irq_restore(flags); } -void __invalidate_cache_sigtramp(unsigned long addr) +static void __invalidate_dcache_all_nomsr_irq(void) { - __invalidate_icache_range(addr, addr + 8); + unsigned long flags; + + pr_debug("%s\n", __func__); + + local_irq_save(flags); + __disable_dcache_nomsr(); + + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_nomsr(); + local_irq_restore(flags); } -void __invalidate_dcache_all(void) +static void __invalidate_dcache_all_noirq_wt(void) { - unsigned int i; - unsigned flags; - - if (cpuinfo.use_dcache) { - local_irq_save(flags); - __disable_dcache(); - - /* - * Just loop through cache size and invalidate, - * no need to add CACHE_BASE address - */ - for (i = 0; i < cpuinfo.dcache_size; - i += cpuinfo.dcache_line_length) - __invalidate_dcache(i); - - __enable_dcache(); - local_irq_restore(flags); - } + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc) } -void __invalidate_dcache_range(unsigned long start, unsigned long end) +/* FIXME this is weird - should be only wdc but not work + * MS: I am getting bus errors and other weird things */ +static void __invalidate_dcache_all_wb(void) { + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, + wdc.clear) + +#if 0 unsigned int i; - unsigned flags; - unsigned int align; - - if (cpuinfo.use_dcache) { - /* - * No need to cover entire cache range, - * just cover cache footprint - */ - end = min(start + cpuinfo.dcache_size, end); - align = ~(cpuinfo.dcache_line_length - 1); - start &= align; /* Make sure we are aligned */ - /* Push end up to the next cache line */ - end = ((end & align) + cpuinfo.dcache_line_length); - local_irq_save(flags); - __disable_dcache(); - - for (i = start; i < end; i += cpuinfo.dcache_line_length) - __invalidate_dcache(i); - - __enable_dcache(); - local_irq_restore(flags); - } + + pr_debug("%s\n", __func__); + + /* Just loop through cache size and invalidate it */ + for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) + __invalidate_dcache(0, i); +#endif +} + +static void __invalidate_dcache_range_wb(unsigned long start, + unsigned long end) +{ + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear); +} + +static void __invalidate_dcache_range_nomsr_wt(unsigned long start, + unsigned long end) +{ + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); } -void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) +static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, + unsigned long end) { - __invalidate_dcache_all(); + unsigned long flags; + + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + + local_irq_save(flags); + __disable_dcache_msr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_msr(); + local_irq_restore(flags); +} + +static void __invalidate_dcache_range_nomsr_irq(unsigned long start, + unsigned long end) +{ + unsigned long flags; + + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + + local_irq_save(flags); + __disable_dcache_nomsr(); + + CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); + + __enable_dcache_nomsr(); + local_irq_restore(flags); +} + +static void __flush_dcache_all_wb(void) +{ + pr_debug("%s\n", __func__); + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, + wdc.flush); } -void __invalidate_dcache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long adr, - int len) +static void __flush_dcache_range_wb(unsigned long start, unsigned long end) { - __invalidate_dcache_all(); + pr_debug("%s: start 0x%x, end 0x%x\n", __func__, + (unsigned int)start, (unsigned int) end); + + CACHE_LOOP_LIMITS(start, end, + cpuinfo.dcache_line_length, cpuinfo.dcache_size); + CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush); +} + +/* struct for wb caches and for wt caches */ +struct scache *mbc; + +/* new wb cache model */ +const struct scache wb_msr = { + .ie = __enable_icache_msr, + .id = __disable_icache_msr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_msr, + .dd = __disable_dcache_msr, + .dfl = __flush_dcache_all_wb, + .dflr = __flush_dcache_range_wb, + .din = __invalidate_dcache_all_wb, + .dinr = __invalidate_dcache_range_wb, +}; + +/* There is only difference in ie, id, de, dd functions */ +const struct scache wb_nomsr = { + .ie = __enable_icache_nomsr, + .id = __disable_icache_nomsr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_nomsr, + .dd = __disable_dcache_nomsr, + .dfl = __flush_dcache_all_wb, + .dflr = __flush_dcache_range_wb, + .din = __invalidate_dcache_all_wb, + .dinr = __invalidate_dcache_range_wb, +}; + +/* Old wt cache model with disabling irq and turn off cache */ +const struct scache wt_msr = { + .ie = __enable_icache_msr, + .id = __disable_icache_msr, + .ifl = __flush_icache_all_msr_irq, + .iflr = __flush_icache_range_msr_irq, + .iin = __flush_icache_all_msr_irq, + .iinr = __flush_icache_range_msr_irq, + .de = __enable_dcache_msr, + .dd = __disable_dcache_msr, + .dfl = __invalidate_dcache_all_msr_irq, + .dflr = __invalidate_dcache_range_msr_irq_wt, + .din = __invalidate_dcache_all_msr_irq, + .dinr = __invalidate_dcache_range_msr_irq_wt, +}; + +const struct scache wt_nomsr = { + .ie = __enable_icache_nomsr, + .id = __disable_icache_nomsr, + .ifl = __flush_icache_all_nomsr_irq, + .iflr = __flush_icache_range_nomsr_irq, + .iin = __flush_icache_all_nomsr_irq, + .iinr = __flush_icache_range_nomsr_irq, + .de = __enable_dcache_nomsr, + .dd = __disable_dcache_nomsr, + .dfl = __invalidate_dcache_all_nomsr_irq, + .dflr = __invalidate_dcache_range_nomsr_irq, + .din = __invalidate_dcache_all_nomsr_irq, + .dinr = __invalidate_dcache_range_nomsr_irq, +}; + +/* New wt cache model for newer Microblaze versions */ +const struct scache wt_msr_noirq = { + .ie = __enable_icache_msr, + .id = __disable_icache_msr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_msr, + .dd = __disable_dcache_msr, + .dfl = __invalidate_dcache_all_noirq_wt, + .dflr = __invalidate_dcache_range_nomsr_wt, + .din = __invalidate_dcache_all_noirq_wt, + .dinr = __invalidate_dcache_range_nomsr_wt, +}; + +const struct scache wt_nomsr_noirq = { + .ie = __enable_icache_nomsr, + .id = __disable_icache_nomsr, + .ifl = __flush_icache_all_noirq, + .iflr = __flush_icache_range_noirq, + .iin = __flush_icache_all_noirq, + .iinr = __flush_icache_range_noirq, + .de = __enable_dcache_nomsr, + .dd = __disable_dcache_nomsr, + .dfl = __invalidate_dcache_all_noirq_wt, + .dflr = __invalidate_dcache_range_nomsr_wt, + .din = __invalidate_dcache_all_noirq_wt, + .dinr = __invalidate_dcache_range_nomsr_wt, +}; + +/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */ +#define CPUVER_7_20_A 0x0c +#define CPUVER_7_20_D 0x0f + +#define INFO(s) printk(KERN_INFO "cache: " s " \n"); + +void microblaze_cache_init(void) +{ + if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) { + if (cpuinfo.dcache_wb) { + INFO("wb_msr"); + mbc = (struct scache *)&wb_msr; + if (cpuinfo.ver_code < CPUVER_7_20_D) { + /* MS: problem with signal handling - hw bug */ + INFO("WB won't work properly"); + } + } else { + if (cpuinfo.ver_code >= CPUVER_7_20_A) { + INFO("wt_msr_noirq"); + mbc = (struct scache *)&wt_msr_noirq; + } else { + INFO("wt_msr"); + mbc = (struct scache *)&wt_msr; + } + } + } else { + if (cpuinfo.dcache_wb) { + INFO("wb_nomsr"); + mbc = (struct scache *)&wb_nomsr; + if (cpuinfo.ver_code < CPUVER_7_20_D) { + /* MS: problem with signal handling - hw bug */ + INFO("WB won't work properly"); + } + } else { + if (cpuinfo.ver_code >= CPUVER_7_20_A) { + INFO("wt_nomsr_noirq"); + mbc = (struct scache *)&wt_nomsr_noirq; + } else { + INFO("wt_nomsr"); + mbc = (struct scache *)&wt_nomsr; + } + } + } } diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 1c3f18ba8af1..5372b24ad049 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -52,11 +52,12 @@ void __init setup_arch(char **cmdline_p) /* irq_early_init(); */ setup_cpuinfo(); - __invalidate_icache_all(); - __enable_icache(); + microblaze_cache_init(); - __invalidate_dcache_all(); - __enable_dcache(); + enable_dcache(); + + invalidate_icache(); + enable_icache(); setup_memory(); diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 0c96ac34c316..6de3db04b1a4 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -176,6 +176,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; int err = 0; int signal; + unsigned long address = 0; +#ifdef CONFIG_MMU + pmd_t *pmdp; + pte_t *ptep; +#endif frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -216,8 +221,29 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, Negative 8 offset because return is rtsd r15, 8 */ regs->r15 = ((unsigned long)frame->tramp)-8; - __invalidate_cache_sigtramp((unsigned long)frame->tramp); - + address = ((unsigned long)frame->tramp); +#ifdef CONFIG_MMU + pmdp = pmd_offset(pud_offset( + pgd_offset(current->mm, address), + address), address); + + preempt_disable(); + ptep = pte_offset_map(pmdp, address); + if (pte_present(*ptep)) { + address = (unsigned long) page_address(pte_page(*ptep)); + /* MS: I need add offset in page */ + address += ((unsigned long)frame->tramp) & ~PAGE_MASK; + /* MS address is virtual */ + address = virt_to_phys(address); + invalidate_icache_range(address, address + 8); + flush_dcache_range(address, address + 8); + } + pte_unmap(ptep); + preempt_enable(); +#else + flush_icache_range(address, address + 8); + flush_dcache_range(address, address + 8); +#endif if (err) goto give_sigsegv; -- cgit v1.2.2 From 825c9a359ecd6ba2569e6c38199e7d072ab388e3 Mon Sep 17 00:00:00 2001 From: "steve@digidescorp.com" Date: Wed, 9 Dec 2009 17:13:42 -0600 Subject: microblaze: nommu: Don't clobber R11 on syscalls The noMMU syscall trap has a bug that causes R11 to be zero on return to userland. Remove the extra "save" of R11 responsible for the bug. Remove reloading of mode indicator because r11 already contains it. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry-nommu.S | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 9083d85376a4..95b0855802df 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -208,8 +208,6 @@ ENTRY(_user_exception) lwi r1, r1, TS_THREAD_INFO /* get the thread info */ /* calculate kernel stack pointer */ addik r1, r1, THREAD_SIZE - PT_SIZE - swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ - lwi r11, r0, PER_CPU(KM) /* load mode indicator */ 2: swi r11, r1, PT_MODE /* store the mode */ lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ -- cgit v1.2.2 From 571202f50fad0aeb36661c79de9beed052347df8 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 11 Dec 2009 12:54:04 +0100 Subject: microblaze: Remove rt_sigsuspend wrapper Generic rt_sigsuspend syscalls doesn't need any asm wrapper. Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 11 ----------- arch/microblaze/kernel/signal.c | 1 - arch/microblaze/kernel/syscall_table.S | 2 +- 3 files changed, 1 insertion(+), 13 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index b061d98a3218..3bad4ff49471 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -500,17 +500,6 @@ C_ENTRY(sys_execve): brid microblaze_execve; /* Do real work (tail-call).*/ nop; -C_ENTRY(sys_rt_sigsuspend_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - la r7, r1, PTO; /* add user context as 3rd arg */ - brlid r15, sys_rt_sigsuspend; /* Do real work.*/ - nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ - nop; - C_ENTRY(sys_rt_sigreturn_wrapper): swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ swi r4, r1, PTO+PT_R4; diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 6de3db04b1a4..d8d3bb396cd6 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -44,7 +44,6 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); - asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 4e666d9c1261..4088be7d4e29 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -183,7 +183,7 @@ ENTRY(sys_call_table) .long sys_rt_sigpending .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend_wrapper + .long sys_rt_sigsuspend .long sys_pread64 /* 180 */ .long sys_pwrite64 .long sys_chown -- cgit v1.2.2 From 239007b8440abff689632f50cdf0f2b9e895b534 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Nov 2009 16:46:45 +0100 Subject: genirq: Convert irq_desc.lock to raw_spinlock Convert locks which cannot be sleeping locks in preempt-rt to raw_spinlocks. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra Acked-by: Ingo Molnar --- arch/microblaze/kernel/irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index 7d5ddd62d4d2..0f06034d1fe0 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -68,7 +68,7 @@ int show_interrupts(struct seq_file *p, void *v) } if (i < nr_irq) { - spin_lock_irqsave(&irq_desc[i].lock, flags); + raw_spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) goto skip; @@ -89,7 +89,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); + raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } -- cgit v1.2.2 From 4a3bb9a90083c064031f15c2ac38bcf68c3487e6 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 28 Dec 2009 14:24:21 +0100 Subject: microblaze: Enable accept4 syscall We had wrong name in unistd.h + I wire up this syscall in syscall table. Signed-off-by: Michal Simek --- arch/microblaze/kernel/syscall_table.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 4088be7d4e29..03376dc814c9 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -366,7 +366,7 @@ ENTRY(sys_call_table) .long sys_shutdown .long sys_sendmsg /* 360 */ .long sys_recvmsg - .long sys_ni_syscall + .long sys_accept4 .long sys_ni_syscall .long sys_ni_syscall .long sys_rt_tgsigqueueinfo /* 365 */ -- cgit v1.2.2 From 878194c8237e4fc5276685ec59cb3bfb9341988c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 13 Jan 2010 15:29:52 +0100 Subject: microblaze: pci_controller->arch_data really is a struct device_node * we are follow powerpc change: 44ef339073f67d4abcc62ae52a5fbc069d7a4d29 Signed-off-by: Michal Simek --- arch/microblaze/kernel/prom_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c index ae0352ecd5a9..bf7e6c27e318 100644 --- a/arch/microblaze/kernel/prom_parse.c +++ b/arch/microblaze/kernel/prom_parse.c @@ -256,7 +256,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) if (ppdev == NULL) { struct pci_controller *host; host = pci_bus_to_host(pdev->bus); - ppnode = host ? host->arch_data : NULL; + ppnode = host ? host->dn : NULL; /* No node for host bridge ? give up */ if (ppnode == NULL) return -EINVAL; -- cgit v1.2.2 From 1f43cfb9474d1c4f22598b6e3213ec035be6dd56 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 28 Jan 2010 13:47:25 -0700 Subject: of: merge machine_is_compatible() Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 5505bcffd7dd..16a001c71e2e 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -318,24 +318,6 @@ void __init early_init_devtree(void *params) pr_debug(" <- early_init_devtree()\n"); } -/** - * Indicates whether the root node has a given value in its - * compatible property. - */ -int machine_is_compatible(const char *compat) -{ - struct device_node *root; - int rc = 0; - - root = of_find_node_by_path("/"); - if (root) { - rc = of_device_is_compatible(root, compat); - of_node_put(root); - } - return rc; -} -EXPORT_SYMBOL(machine_is_compatible); - /******* * * New implementation of the OF "find" APIs, return a refcounted -- cgit v1.2.2 From 923f7e30b480438f1e86e01e5cde814248b59a39 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 28 Jan 2010 13:52:53 -0700 Subject: of: Merge of_node_get() and of_node_put() Merge common code between PowerPC and MicroBlaze Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 74 ------------------------------------------- 1 file changed, 74 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 16a001c71e2e..46407e643926 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -350,80 +350,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -/** - * of_node_get - Increment refcount of a node - * @node: Node to inc refcount, NULL is supported to - * simplify writing of callers - * - * Returns node. - */ -struct device_node *of_node_get(struct device_node *node) -{ - if (node) - kref_get(&node->kref); - return node; -} -EXPORT_SYMBOL(of_node_get); - -static inline struct device_node *kref_to_device_node(struct kref *kref) -{ - return container_of(kref, struct device_node, kref); -} - -/** - * of_node_release - release a dynamically allocated node - * @kref: kref element of the node to be released - * - * In of_node_put() this function is passed to kref_put() - * as the destructor. - */ -static void of_node_release(struct kref *kref) -{ - struct device_node *node = kref_to_device_node(kref); - struct property *prop = node->properties; - - /* We should never be releasing nodes that haven't been detached. */ - if (!of_node_check_flag(node, OF_DETACHED)) { - printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n", - node->full_name); - dump_stack(); - kref_init(&node->kref); - return; - } - - if (!of_node_check_flag(node, OF_DYNAMIC)) - return; - - while (prop) { - struct property *next = prop->next; - kfree(prop->name); - kfree(prop->value); - kfree(prop); - prop = next; - - if (!prop) { - prop = node->deadprops; - node->deadprops = NULL; - } - } - kfree(node->full_name); - kfree(node->data); - kfree(node); -} - -/** - * of_node_put - Decrement refcount of a node - * @node: Node to dec refcount, NULL is supported to - * simplify writing of callers - * - */ -void of_node_put(struct device_node *node) -{ - if (node) - kref_put(&node->kref, of_node_release); -} -EXPORT_SYMBOL(of_node_put); - /* * Plug a device node into the tree and global list. */ -- cgit v1.2.2 From 6016a363f6b56b46b24655bcfc0499b715851cf3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 28 Jan 2010 14:06:53 -0700 Subject: of: unify phandle name in struct device_node In struct device_node, the phandle is named 'linux_phandle' for PowerPC and MicroBlaze, and 'node' for SPARC. There is no good reason for the difference, it is just an artifact of the code diverging over a couple of years. This patch renames both to simply .phandle. Note: the .node also existed in PowerPC/MicroBlaze, but the only user seems to be arch/powerpc/platforms/powermac/pfunc_core.c. It doesn't look like the assignment between .linux_phandle and .node is significantly different enough to warrant the separate code paths unless ibm,phandle properties actually appear in Apple device trees. I think it is safe to eliminate the old .node property and use phandle everywhere. Signed-off-by: Grant Likely Acked-by: David S. Miller Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/of_platform.c | 2 +- arch/microblaze/kernel/prom.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c index acf4574d0f18..1c6d684996d7 100644 --- a/arch/microblaze/kernel/of_platform.c +++ b/arch/microblaze/kernel/of_platform.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL(of_find_device_by_node); static int of_dev_phandle_match(struct device *dev, void *data) { phandle *ph = data; - return to_of_device(dev)->node->linux_phandle == *ph; + return to_of_device(dev)->node->phandle == *ph; } struct of_device *of_find_device_by_phandle(phandle ph) diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 46407e643926..6eff83a71218 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -342,7 +342,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) read_lock(&devtree_lock); for (np = allnodes; np != NULL; np = np->allnext) - if (np->linux_phandle == handle) + if (np->phandle == handle) break; of_node_get(np); read_unlock(&devtree_lock); -- cgit v1.2.2 From 58424a49cb99c4ad9386b47f885b352476313a02 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Mon, 1 Feb 2010 06:34:45 -0600 Subject: microblaze: fix interrupt state restore Interrupts must be disabled while an interrupt state restore (prep for interrupt return) is in progress. Code to do this was lost in the port to the mainline kernel. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry-nommu.S | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 95b0855802df..391d6197fc3b 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -122,7 +122,7 @@ ENTRY(_interrupt) ret_from_intr: lwi r11, r1, PT_MODE - bneid r11, 3f + bneid r11, no_intr_resched lwi r6, r31, TS_THREAD_INFO /* get thread info */ lwi r19, r6, TI_FLAGS /* get flags in thread info */ @@ -133,16 +133,18 @@ ret_from_intr: bralid r15, schedule nop 1: andi r11, r19, _TIF_SIGPENDING - beqid r11, no_intr_reshed + beqid r11, no_intr_resched addk r5, r1, r0 addk r7, r0, r0 bralid r15, do_signal addk r6, r0, r0 -no_intr_reshed: +no_intr_resched: + /* Disable interrupts, we are now committed to the state restore */ + disable_irq + /* save mode indicator */ lwi r11, r1, PT_MODE -3: swi r11, r0, PER_CPU(KM) /* save r31 */ -- cgit v1.2.2 From a6013411118a6c8c34f1bd8b047b36fdf9711590 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 1 Feb 2010 12:15:58 +0100 Subject: microblaze: Invalidate dcache before enabling it We found that on write-trough kernel is necessary to do that invalidation. One WB is possible to use invalidation too. Signed-off-by: Michal Simek --- arch/microblaze/kernel/setup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 5372b24ad049..bb8c4b9ccb80 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -54,6 +54,7 @@ void __init setup_arch(char **cmdline_p) microblaze_cache_init(); + invalidate_dcache(); enable_dcache(); invalidate_icache(); -- cgit v1.2.2 From 580537140568caddbc8a727d4c2f238d38707f68 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 28 Jan 2010 22:18:56 -0700 Subject: microblaze: remove early_init_dt_scan_cpus() and phyp_dump_*() Microblaze only has one CPU, it isn't SMP at all. early_init_dt_scan_cpus() is effectively just a no-op, so remove it. Microblaze doesn't support hypervisor assisted dump either, so the phyp stuff can also go. Signed-off-by: Grant Likely Acked-by: Michal Simek --- arch/microblaze/kernel/prom.c | 153 ------------------------------------------ 1 file changed, 153 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 6eff83a71218..cd158ef5b583 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -47,67 +47,6 @@ struct device_node *of_chosen; #define early_init_dt_scan_drconf_memory(node) 0 -static int __init early_init_dt_scan_cpus(unsigned long node, - const char *uname, int depth, - void *data) -{ - static int logical_cpuid; - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - const u32 *intserv; - int i, nthreads; - int found = 0; - - /* We are scanning "cpu" nodes only */ - if (type == NULL || strcmp(type, "cpu") != 0) - return 0; - - /* Get physical cpuid */ - intserv = of_get_flat_dt_prop(node, "reg", NULL); - nthreads = 1; - - /* - * Now see if any of these threads match our boot cpu. - * NOTE: This must match the parsing done in smp_setup_cpu_maps. - */ - for (i = 0; i < nthreads; i++) { - /* - * version 2 of the kexec param format adds the phys cpuid of - * booted proc. - */ - if (initial_boot_params && initial_boot_params->version >= 2) { - if (intserv[i] == - initial_boot_params->boot_cpuid_phys) { - found = 1; - break; - } - } else { - /* - * Check if it's the boot-cpu, set it's hw index now, - * unfortunately this format did not support booting - * off secondary threads. - */ - if (of_get_flat_dt_prop(node, - "linux,boot-cpu", NULL) != NULL) { - found = 1; - break; - } - } - -#ifdef CONFIG_SMP - /* logical cpu id is always 0 on UP kernels */ - logical_cpuid++; -#endif - } - - if (found) { - pr_debug("boot cpu: logical %d physical %d\n", logical_cpuid, - intserv[i]); - boot_cpuid = logical_cpuid; - } - - return 0; -} - void __init early_init_dt_scan_chosen_arch(unsigned long node) { /* No Microblaze specific code here */ @@ -163,86 +102,6 @@ static int __init early_init_dt_scan_memory(unsigned long node, return 0; } -#ifdef CONFIG_PHYP_DUMP -/** - * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg - * - * Function to find the largest size we need to reserve - * during early boot process. - * - * It either looks for boot param and returns that OR - * returns larger of 256 or 5% rounded down to multiples of 256MB. - * - */ -static inline unsigned long phyp_dump_calculate_reserve_size(void) -{ - unsigned long tmp; - - if (phyp_dump_info->reserve_bootvar) - return phyp_dump_info->reserve_bootvar; - - /* divide by 20 to get 5% of value */ - tmp = lmb_end_of_DRAM(); - do_div(tmp, 20); - - /* round it down in multiples of 256 */ - tmp = tmp & ~0x0FFFFFFFUL; - - return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END); -} - -/** - * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory - * - * This routine may reserve memory regions in the kernel only - * if the system is supported and a dump was taken in last - * boot instance or if the hardware is supported and the - * scratch area needs to be setup. In other instances it returns - * without reserving anything. The memory in case of dump being - * active is freed when the dump is collected (by userland tools). - */ -static void __init phyp_dump_reserve_mem(void) -{ - unsigned long base, size; - unsigned long variable_reserve_size; - - if (!phyp_dump_info->phyp_dump_configured) { - printk(KERN_ERR "Phyp-dump not supported on this hardware\n"); - return; - } - - if (!phyp_dump_info->phyp_dump_at_boot) { - printk(KERN_INFO "Phyp-dump disabled at boot time\n"); - return; - } - - variable_reserve_size = phyp_dump_calculate_reserve_size(); - - if (phyp_dump_info->phyp_dump_is_active) { - /* Reserve *everything* above RMR.Area freed by userland tools*/ - base = variable_reserve_size; - size = lmb_end_of_DRAM() - base; - - /* XXX crashed_ram_end is wrong, since it may be beyond - * the memory_limit, it will need to be adjusted. */ - lmb_reserve(base, size); - - phyp_dump_info->init_reserve_start = base; - phyp_dump_info->init_reserve_size = size; - } else { - size = phyp_dump_info->cpu_state_size + - phyp_dump_info->hpte_region_size + - variable_reserve_size; - base = lmb_end_of_DRAM() - size; - lmb_reserve(base, size); - phyp_dump_info->init_reserve_start = base; - phyp_dump_info->init_reserve_size = size; - } -} -#else -static inline void __init phyp_dump_reserve_mem(void) {} -#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ - #ifdef CONFIG_EARLY_PRINTK /* MS this is Microblaze specifig function */ static int __init early_init_dt_scan_serial(unsigned long node, @@ -284,11 +143,6 @@ void __init early_init_devtree(void *params) /* Setup flat device-tree pointer */ initial_boot_params = params; -#ifdef CONFIG_PHYP_DUMP - /* scan tree to see if dump occured during last boot */ - of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL); -#endif - /* Retrieve various informations from the /chosen node of the * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... @@ -308,13 +162,6 @@ void __init early_init_devtree(void *params) pr_debug("Phys. mem: %lx\n", (unsigned long) lmb_phys_mem_size()); - pr_debug("Scanning CPUs ...\n"); - - /* Retreive CPU related informations from the flat tree - * (altivec support, boot CPU ID, ...) - */ - of_scan_flat_dt(early_init_dt_scan_cpus, NULL); - pr_debug(" <- early_init_devtree()\n"); } -- cgit v1.2.2 From fcdeb7fedf89f4bbc2e11959794968080cd8426e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 29 Jan 2010 05:04:33 -0700 Subject: of: merge of_attach_node() & of_detach_node() Merge common code between PowerPC and Microblaze Signed-off-by: Grant Likely Tested-by: Wolfram Sang Acked-by: Benjamin Herrenschmidt --- arch/microblaze/kernel/prom.c | 59 ------------------------------------------- 1 file changed, 59 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index cd158ef5b583..8171282a0b0d 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -197,65 +197,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -/* - * Plug a device node into the tree and global list. - */ -void of_attach_node(struct device_node *np) -{ - unsigned long flags; - - write_lock_irqsave(&devtree_lock, flags); - np->sibling = np->parent->child; - np->allnext = allnodes; - np->parent->child = np; - allnodes = np; - write_unlock_irqrestore(&devtree_lock, flags); -} - -/* - * "Unplug" a node from the device tree. The caller must hold - * a reference to the node. The memory associated with the node - * is not freed until its refcount goes to zero. - */ -void of_detach_node(struct device_node *np) -{ - struct device_node *parent; - unsigned long flags; - - write_lock_irqsave(&devtree_lock, flags); - - parent = np->parent; - if (!parent) - goto out_unlock; - - if (allnodes == np) - allnodes = np->allnext; - else { - struct device_node *prev; - for (prev = allnodes; - prev->allnext != np; - prev = prev->allnext) - ; - prev->allnext = np->allnext; - } - - if (parent->child == np) - parent->child = np->sibling; - else { - struct device_node *prevsib; - for (prevsib = np->parent->child; - prevsib->sibling != np; - prevsib = prevsib->sibling) - ; - prevsib->sibling = np->sibling; - } - - of_node_set_flag(np, OF_DETACHED); - -out_unlock: - write_unlock_irqrestore(&devtree_lock, flags); -} - #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) static struct debugfs_blob_wrapper flat_dt_blob; -- cgit v1.2.2 From 89751a7cb70a20f0d604dd7c4be29dd7b0011718 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 1 Feb 2010 21:34:11 -0700 Subject: of: merge of_find_node_by_phandle Merge common function between powerpc, sparc and microblaze. Code is identical for powerpc and microblaze, but adds a lock (and release) of the devtree_lock on sparc. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- arch/microblaze/kernel/prom.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 8171282a0b0d..f7bd0ee8d481 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -176,27 +176,6 @@ void __init early_init_devtree(void *params) * *******/ -/** - * of_find_node_by_phandle - Find a node given a phandle - * @handle: phandle of the node to find - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - read_lock(&devtree_lock); - for (np = allnodes; np != NULL; np = np->allnext) - if (np->phandle == handle) - break; - of_node_get(np); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) static struct debugfs_blob_wrapper flat_dt_blob; -- cgit v1.2.2 From 51975db0b7333cf389b64b5040c2a910341d241a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Feb 2010 21:34:14 -0700 Subject: of/flattree: merge early_init_dt_scan_memory() common code Merge common code between PowerPC and Microblaze architectures. Signed-off-by: Grant Likely Acked-by: Michal Simek --- arch/microblaze/kernel/prom.c | 51 ++----------------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index f7bd0ee8d481..459c32e4a5fe 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -45,61 +45,14 @@ /* export that to outside world */ struct device_node *of_chosen; -#define early_init_dt_scan_drconf_memory(node) 0 - void __init early_init_dt_scan_chosen_arch(unsigned long node) { /* No Microblaze specific code here */ } -static int __init early_init_dt_scan_memory(unsigned long node, - const char *uname, int depth, void *data) +void __init early_init_dt_add_memory_arch(u64 base, u64 size) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *reg, *endp; - unsigned long l; - - /* Look for the ibm,dynamic-reconfiguration-memory node */ -/* if (depth == 1 && - strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) - return early_init_dt_scan_drconf_memory(node); -*/ - /* We are scanning "memory" nodes only */ - if (type == NULL) { - /* - * The longtrail doesn't have a device_type on the - * /memory node, so look for the node called /memory@0. - */ - if (depth != 1 || strcmp(uname, "memory@0") != 0) - return 0; - } else if (strcmp(type, "memory") != 0) - return 0; - - reg = (__be32 *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); - if (reg == NULL) - reg = (__be32 *)of_get_flat_dt_prop(node, "reg", &l); - if (reg == NULL) - return 0; - - endp = reg + (l / sizeof(__be32)); - - pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", - uname, l, reg[0], reg[1], reg[2], reg[3]); - - while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { - u64 base, size; - - base = dt_mem_next_cell(dt_root_addr_cells, ®); - size = dt_mem_next_cell(dt_root_size_cells, ®); - - if (size == 0) - continue; - pr_debug(" - %llx , %llx\n", (unsigned long long)base, - (unsigned long long)size); - - lmb_add(base, size); - } - return 0; + lmb_add(base, size); } #ifdef CONFIG_EARLY_PRINTK -- cgit v1.2.2 From 1406bc2f57787797d1f6a3675c019a7093769275 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sat, 30 Jan 2010 01:31:21 -0700 Subject: of/flattree: use callback to setup initrd from /chosen At present, the fdt code sets the kernel-wide initrd_start and initrd_end variables when parsing /chosen. On ARM, we only set these once the bootmem has been reserved. This change adds an arch hook to setup the initrd from the device tree: void early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end); The arch-specific code can then setup the initrd however it likes. Compiled on powerpc, with CONFIG_BLK_DEV_INITRD=y and =n. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely --- arch/microblaze/kernel/prom.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 459c32e4a5fe..050b7993c51c 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -118,6 +118,16 @@ void __init early_init_devtree(void *params) pr_debug(" <- early_init_devtree()\n"); } +#ifdef CONFIG_BLK_DEV_INITRD +void __init early_init_dt_setup_initrd_arch(unsigned long start, + unsigned long end) +{ + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; +} +#endif + /******* * * New implementation of the OF "find" APIs, return a refcounted -- cgit v1.2.2 From 4ef7b373df330bc0ff037dc4792d373c9346375f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sun, 14 Feb 2010 07:13:47 -0700 Subject: of/flattree: Don't assume HAVE_LMB We don't always have lmb available, so make arches provide an early_init_dt_alloc_memory_arch() to handle the allocation of memory in the fdt code. When we don't have lmb.h included, we need asm/page.h for __va. Signed-off-by: Jeremy Kerr Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Acked-by: Michal Simek --- arch/microblaze/kernel/prom.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 050b7993c51c..a7dcaf092200 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -55,6 +55,11 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) lmb_add(base, size); } +u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +{ + return lmb_alloc(size, align); +} + #ifdef CONFIG_EARLY_PRINTK /* MS this is Microblaze specifig function */ static int __init early_init_dt_scan_serial(unsigned long node, -- cgit v1.2.2 From fc0bdae49d810e4cb32d7b547bc6d4dfb08f9e2e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sun, 14 Feb 2010 07:13:55 -0700 Subject: of: move definition of of_chosen into common code. Rather than defining of_chosen in each arch, it can be defined for all in driver/of/base.c Signed-off-by: Grant Likely Acked-by: Benjamin Herrenschmidt Acked-by: Michal Simek --- arch/microblaze/kernel/prom.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index a7dcaf092200..a15ef6d67ca9 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -42,9 +42,6 @@ #include #include -/* export that to outside world */ -struct device_node *of_chosen; - void __init early_init_dt_scan_chosen_arch(unsigned long node) { /* No Microblaze specific code here */ -- cgit v1.2.2 From 0d670b24729be268eba98b3920b8571f60798d8d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 15 Feb 2010 10:50:42 +0100 Subject: microblaze: Fix cache loop function for cache range I create wrong asm code but none test shows that this part of code is wrong. I am not convinces that were good idea to create asm optimized macros for caches. The reason is that there is not optimization with previous code that's why make sense to add old code and do some benchmarking which functions are faster. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index d9d63831cc2f..2a56bccce4e0 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -172,16 +172,15 @@ do { \ /* It is used only first parameter for OP - for wic, wdc */ #define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ do { \ - int step = -line_length; \ - int count = end - start; \ - BUG_ON(count <= 0); \ + int volatile temp; \ + BUG_ON(end - start <= 0); \ \ - __asm__ __volatile__ (" 1: addk %0, %0, %1; \ - " #op " %0, r0; \ - bgtid %1, 1b; \ - addk %1, %1, %2; \ - " : : "r" (start), "r" (count), \ - "r" (step) : "memory"); \ + __asm__ __volatile__ (" 1: " #op " %1, r0; \ + cmpu %0, %1, %2; \ + bgtid %0, 1b; \ + addk %1, %1, %3; \ + " : : "r" (temp), "r" (start), "r" (end),\ + "r" (line_length) : "memory"); \ } while (0); static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) @@ -313,16 +312,6 @@ static void __invalidate_dcache_all_wb(void) pr_debug("%s\n", __func__); CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc.clear) - -#if 0 - unsigned int i; - - pr_debug("%s\n", __func__); - - /* Just loop through cache size and invalidate it */ - for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) - __invalidate_dcache(0, i); -#endif } static void __invalidate_dcache_range_wb(unsigned long start, -- cgit v1.2.2 From ccfe27d7000668b02d10fc3e06aa49e3e3603162 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 14 Jan 2010 11:21:02 +0100 Subject: microblaze: Support DMA Add DMA support for Microblaze. There are some part of this new feature: 1. Basic DMA support 2. Enable DMA debug option 3. Setup notifier Ad 1. dma-mapping come from powerpc and x86 version and it is based on generic dma-mapping-common.h Ad 2. DMA support debug features which is used in generic file. For more information please look at Documentation/DMA-API.txt Ad 3. notifier is very important to setup dma_ops. Without this part for example ll_temac driver failed because there are no setup dma operations. Signed-off-by: Michal Simek --- arch/microblaze/kernel/Makefile | 2 +- arch/microblaze/kernel/dma.c | 124 ++++++++++++++++++++++++++++++++++++++++ arch/microblaze/kernel/setup.c | 36 ++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 arch/microblaze/kernel/dma.c (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index b07594eccf9b..e51bc1520825 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -14,7 +14,7 @@ endif extra-y := head.o vmlinux.lds -obj-y += exceptions.o \ +obj-y += dma.o exceptions.o \ hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ of_platform.o process.o prom.o prom_parse.o ptrace.o \ setup.o signal.o sys_microblaze.o timer.o traps.o reset.o diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c new file mode 100644 index 000000000000..300fea46737e --- /dev/null +++ b/arch/microblaze/kernel/dma.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009-2010 PetaLogix + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation + * + * Provide default implementations of the DMA mapping callbacks for + * directly mapped busses. + */ + +#include +#include +#include +#include + +/* + * Generic direct DMA implementation + * + * This implementation supports a per-device offset that can be applied if + * the address at which memory is visible to devices is not 0. Platform code + * can set archdata.dma_data to an unsigned long holding the offset. By + * default the offset is PCI_DRAM_OFFSET. + */ + +static unsigned long get_dma_direct_offset(struct device *dev) +{ + if (dev) + return (unsigned long)dev->archdata.dma_data; + + return PCI_DRAM_OFFSET; /* FIXME Not sure if is correct */ +} + +void *dma_direct_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + void *ret; + struct page *page; + int node = dev_to_node(dev); + + /* ignore region specifiers */ + flag &= ~(__GFP_HIGHMEM); + + page = alloc_pages_node(node, flag, get_order(size)); + if (page == NULL) + return NULL; + ret = page_address(page); + memset(ret, 0, size); + *dma_handle = virt_to_phys(ret) + get_dma_direct_offset(dev); + + return ret; +} + +void dma_direct_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, + int nents, enum dma_data_direction direction, + struct dma_attrs *attrs) +{ + struct scatterlist *sg; + int i; + + for_each_sg(sgl, sg, nents, i) { + sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); + sg->dma_length = sg->length; + __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction); + } + + return nents; +} + +static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction, + struct dma_attrs *attrs) +{ +} + +static int dma_direct_dma_supported(struct device *dev, u64 mask) +{ + return 1; +} + +static inline dma_addr_t dma_direct_map_page(struct device *dev, + struct page *page, + unsigned long offset, + size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + BUG_ON(dir == DMA_NONE); + __dma_sync_page(page, offset, size, dir); + return page_to_phys(page) + offset + get_dma_direct_offset(dev); +} + +static inline void dma_direct_unmap_page(struct device *dev, + dma_addr_t dma_address, + size_t size, + enum dma_data_direction direction, + struct dma_attrs *attrs) +{ +} + +struct dma_map_ops dma_direct_ops = { + .alloc_coherent = dma_direct_alloc_coherent, + .free_coherent = dma_direct_free_coherent, + .map_sg = dma_direct_map_sg, + .unmap_sg = dma_direct_unmap_sg, + .dma_supported = dma_direct_dma_supported, + .map_page = dma_direct_map_page, + .unmap_page = dma_direct_unmap_page, +}; +EXPORT_SYMBOL(dma_direct_ops); + +/* Number of entries preallocated for DMA-API debugging */ +#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) + +static int __init dma_init(void) +{ + dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); + + return 0; +} +fs_initcall(dma_init); diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index bb8c4b9ccb80..bc325ac4efd3 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -188,3 +190,37 @@ static int microblaze_debugfs_init(void) } arch_initcall(microblaze_debugfs_init); #endif + +static int dflt_bus_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + + /* We are only intereted in device addition */ + if (action != BUS_NOTIFY_ADD_DEVICE) + return 0; + + set_dma_ops(dev, &dma_direct_ops); + + return NOTIFY_DONE; +} + +static struct notifier_block dflt_plat_bus_notifier = { + .notifier_call = dflt_bus_notify, + .priority = INT_MAX, +}; + +static struct notifier_block dflt_of_bus_notifier = { + .notifier_call = dflt_bus_notify, + .priority = INT_MAX, +}; + +static int __init setup_bus_notifier(void) +{ + bus_register_notifier(&platform_bus_type, &dflt_plat_bus_notifier); + bus_register_notifier(&of_platform_bus_type, &dflt_of_bus_notifier); + + return 0; +} + +arch_initcall(setup_bus_notifier); -- cgit v1.2.2 From 2549edd353196d7de9c18e08146d7a8836f97235 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 20 Jan 2010 14:36:24 +0100 Subject: microblaze: Implement __dma_sync_page There is necessary to do some cache handling for dma operations. Signed-off-by: Michal Simek --- arch/microblaze/kernel/dma.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index 300fea46737e..64bc39f40ba7 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -10,6 +10,7 @@ #include #include #include +#include /* * Generic direct DMA implementation @@ -20,6 +21,23 @@ * default the offset is PCI_DRAM_OFFSET. */ +static inline void __dma_sync_page(void *vaddr, unsigned long offset, + size_t size, enum dma_data_direction direction) +{ + unsigned long start = virt_to_phys(vaddr); + + switch (direction) { + case DMA_TO_DEVICE: + flush_dcache_range(start + offset, start + offset + size); + break; + case DMA_FROM_DEVICE: + invalidate_dcache_range(start + offset, start + offset + size); + break; + default: + BUG(); + } +} + static unsigned long get_dma_direct_offset(struct device *dev) { if (dev) @@ -85,11 +103,11 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, - enum dma_data_direction dir, + enum dma_data_direction direction, struct dma_attrs *attrs) { - BUG_ON(dir == DMA_NONE); - __dma_sync_page(page, offset, size, dir); + BUG_ON(direction == DMA_NONE); + __dma_sync_page(page, offset, size, direction); return page_to_phys(page) + offset + get_dma_direct_offset(dev); } @@ -99,6 +117,8 @@ static inline void dma_direct_unmap_page(struct device *dev, enum dma_data_direction direction, struct dma_attrs *attrs) { +/* There is not necessary to do cache cleanup */ + /* __dma_sync_page(dma_address, 0 , size, direction); */ } struct dma_map_ops dma_direct_ops = { -- cgit v1.2.2 From c6ba01a4c7806d134c8d483525997559071d0990 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 14 Jan 2010 15:16:31 +0100 Subject: microblaze: Add irq_create_{of_,}mapping functions Support function for PCI. We don't use any advance mapping mechanism that's why implementation is simple. Signed-off-by: Michal Simek --- arch/microblaze/kernel/irq.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index 0f06034d1fe0..6f39e2c001f3 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -93,3 +93,18 @@ skip: } return 0; } + +/* MS: There is no any advance mapping mechanism. We are using simple 32bit + intc without any cascades or any connection that's why mapping is 1:1 */ +unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) +{ + return hwirq; +} +EXPORT_SYMBOL_GPL(irq_create_mapping); + +unsigned int irq_create_of_mapping(struct device_node *controller, + u32 *intspec, unsigned int intsize) +{ + return intspec[0]; +} +EXPORT_SYMBOL_GPL(irq_create_of_mapping); -- cgit v1.2.2 From 733cc2183116b216abb52e709709bb0e626c9a75 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 18 Jan 2010 15:27:11 +0100 Subject: microblaze: Add support for Xilinx PCI host bridge This patch is based on powerpc patch 64f16502475ddf663169369fffff6da9b10ea9fb We did some cleanups and removed powerpc parts. There is one new debug early listing function too. Exclude function is only in Debug options. We tested in on custom board. Signed-off-by: Michal Simek --- arch/microblaze/kernel/setup.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index bc325ac4efd3..cd68e988b48c 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,8 @@ void __init setup_arch(char **cmdline_p) setup_memory(); + xilinx_pci_init(); + #if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER) printk(KERN_NOTICE "Self modified code enable\n"); #endif -- cgit v1.2.2 From 777537905744c28b02c283692e7f75f5445c1afa Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 12 Jan 2010 09:55:10 +0100 Subject: microblaze: Add support from PREEMPT This patch add core PREEMPT support for Microblaze. I tried to trace it via tracers and I was able to see any output. I also added low level debug functions to see if that code is called. Signed-off-by: Michal Simek --- arch/microblaze/kernel/asm-offsets.c | 1 + arch/microblaze/kernel/entry.S | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c index 7bc7b68f97db..0071260a672c 100644 --- a/arch/microblaze/kernel/asm-offsets.c +++ b/arch/microblaze/kernel/asm-offsets.c @@ -90,6 +90,7 @@ int main(int argc, char *argv[]) DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); DEFINE(TI_CPU_CONTEXT, offsetof(struct thread_info, cpu_context)); + DEFINE(TI_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count)); BLANK(); /* struct cpu_context */ diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 3bad4ff49471..1a6729dde49e 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -853,7 +853,30 @@ no_intr_resched: lwi r1, r1, PT_R1 - PT_SIZE; bri 6f; /* MS: Return to kernel state. */ -2: VM_OFF /* MS: turn off MMU */ +2: +#ifdef CONFIG_PREEMPT + add r11, r0, CURRENT_TASK; + lwi r11, r11, TS_THREAD_INFO; + /* MS: get preempt_count from thread info */ + lwi r5, r11, TI_PREEMPT_COUNT; + bgti r5, restore; + + lwi r5, r11, TI_FLAGS; /* get flags in thread info */ + andi r5, r5, _TIF_NEED_RESCHED; + beqi r5, restore /* if zero jump over */ + +preempt: + /* interrupts are off that's why I am calling preempt_chedule_irq */ + bralid r15, preempt_schedule_irq + nop + add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ + lwi r11, r11, TS_THREAD_INFO; /* get thread info */ + lwi r5, r11, TI_FLAGS; /* get flags in thread info */ + andi r5, r5, _TIF_NEED_RESCHED; + bnei r5, preempt /* if non zero jump to resched */ +restore: +#endif + VM_OFF /* MS: turn off MMU */ tophys(r1,r1) lwi r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */ lwi r4, r1, PTO + PT_R4; -- cgit v1.2.2 From 407c1da07d5afa001ed0fdb8f379c00bbd09990a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 12 Jan 2010 14:51:04 +0100 Subject: microblaze: Move cache function to cache.c It is better to have init cache handling on one place. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 5 +++++ arch/microblaze/kernel/setup.c | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 2a56bccce4e0..5425f89335ed 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -532,4 +532,9 @@ void microblaze_cache_init(void) } } } + invalidate_dcache(); + enable_dcache(); + + invalidate_icache(); + enable_icache(); } diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index cd68e988b48c..f974ec7aa357 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -57,12 +57,6 @@ void __init setup_arch(char **cmdline_p) microblaze_cache_init(); - invalidate_dcache(); - enable_dcache(); - - invalidate_icache(); - enable_icache(); - setup_memory(); xilinx_pci_init(); -- cgit v1.2.2 From d79f3b06a9e40b382bd5d5ae8dea9b3210eda9ce Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 8 Feb 2010 12:13:10 +0100 Subject: microblaze: Preliminary support for dma drivers I found several problems for ll_temac driver and on system with WB. This early fix should fix it. I will clean this patch before I will add it to mainline Signed-off-by: Michal Simek --- arch/microblaze/kernel/dma.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index 64bc39f40ba7..f230a8de0bcd 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -21,10 +21,10 @@ * default the offset is PCI_DRAM_OFFSET. */ -static inline void __dma_sync_page(void *vaddr, unsigned long offset, +static inline void __dma_sync_page(void *paddr, unsigned long offset, size_t size, enum dma_data_direction direction) { - unsigned long start = virt_to_phys(vaddr); + unsigned long start = (unsigned long)paddr; switch (direction) { case DMA_TO_DEVICE: @@ -79,10 +79,12 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, struct scatterlist *sg; int i; + /* FIXME this part of code is untested */ for_each_sg(sgl, sg, nents, i) { sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); sg->dma_length = sg->length; - __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction); + __dma_sync_page(page_to_phys(sg_page(sg)), sg->offset, + sg->length, direction); } return nents; @@ -107,7 +109,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev, struct dma_attrs *attrs) { BUG_ON(direction == DMA_NONE); - __dma_sync_page(page, offset, size, direction); + __dma_sync_page(page_to_phys(page), offset, size, direction); return page_to_phys(page) + offset + get_dma_direct_offset(dev); } @@ -117,8 +119,12 @@ static inline void dma_direct_unmap_page(struct device *dev, enum dma_data_direction direction, struct dma_attrs *attrs) { -/* There is not necessary to do cache cleanup */ - /* __dma_sync_page(dma_address, 0 , size, direction); */ +/* There is not necessary to do cache cleanup + * + * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and + * dma_address is physical address + */ + __dma_sync_page((void *)dma_address, 0 , size, direction); } struct dma_map_ops dma_direct_ops = { -- cgit v1.2.2 From 137d0795a72786fa33e6900cb2ac2eae81f4b6ee Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 4 Feb 2010 11:42:24 +0100 Subject: microblaze: Change temp register for cmdline For copy was used r7 register when CONFIG_CMDLINE_BOOL option is enabled. But r7 stores pointer to fdt that's why machine_early_init not detect compiled-in DTB. I also moved kernel PID setup to have TLB init in one block Signed-off-by: Michal Simek --- arch/microblaze/kernel/head.S | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index 30916193fcc7..cb7815cfe5ab 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -99,8 +99,8 @@ no_fdt_arg: tophys(r4,r4) /* convert to phys address */ ori r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */ _copy_command_line: - lbu r7, r5, r6 /* r7=r5+r6 - r5 contain pointer to command line */ - sb r7, r4, r6 /* addr[r4+r6]= r7*/ + lbu r2, r5, r6 /* r7=r5+r6 - r5 contain pointer to command line */ + sb r2, r4, r6 /* addr[r4+r6]= r7*/ addik r6, r6, 1 /* increment counting */ bgtid r3, _copy_command_line /* loop for all entries */ addik r3, r3, -1 /* descrement loop */ @@ -136,6 +136,11 @@ _invalidate: addik r3, r3, -1 /* sync */ + /* Setup the kernel PID */ + mts rpid,r0 /* Load the kernel PID */ + nop + bri 4 + /* * We should still be executing code at physical address area * RAM_BASEADDR at this point. However, kernel code is at @@ -146,10 +151,6 @@ _invalidate: addik r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */ tophys(r4,r3) /* Load the kernel physical address */ - mts rpid,r0 /* Load the kernel PID */ - nop - bri 4 - /* * Configure and load two entries into TLB slots 0 and 1. * In case we are pinning TLBs, these are reserved in by the -- cgit v1.2.2 From 4c912c1a33abb67aefecb5ed8bd73d91887c4977 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Sat, 6 Feb 2010 18:47:12 +0100 Subject: microblaze: remove trailing space in messages Signed-off-by: Frans Pop Cc: microblaze-uclinux@itee.uq.edu.au Cc: Michal Simek Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 5425f89335ed..13f0c1de3234 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -493,7 +493,7 @@ const struct scache wt_nomsr_noirq = { #define CPUVER_7_20_A 0x0c #define CPUVER_7_20_D 0x0f -#define INFO(s) printk(KERN_INFO "cache: " s " \n"); +#define INFO(s) printk(KERN_INFO "cache: " s "\n"); void microblaze_cache_init(void) { -- cgit v1.2.2 From dcbae4be907488df5e1cc8a89b7df1a0565c257c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 9 Feb 2010 09:25:08 +0100 Subject: microblaze: Preliminary support for dma drivers I found several problems for ll_temac driver and on system with WB. This early fix should fix it. I will clean this patch before I will add it to mainline Signed-off-by: Michal Simek --- arch/microblaze/kernel/dma.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index f230a8de0bcd..fbe1e8184eff 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -20,18 +20,15 @@ * can set archdata.dma_data to an unsigned long holding the offset. By * default the offset is PCI_DRAM_OFFSET. */ - -static inline void __dma_sync_page(void *paddr, unsigned long offset, +static inline void __dma_sync_page(unsigned long paddr, unsigned long offset, size_t size, enum dma_data_direction direction) { - unsigned long start = (unsigned long)paddr; - switch (direction) { case DMA_TO_DEVICE: - flush_dcache_range(start + offset, start + offset + size); + flush_dcache_range(paddr + offset, paddr + offset + size); break; case DMA_FROM_DEVICE: - invalidate_dcache_range(start + offset, start + offset + size); + invalidate_dcache_range(paddr + offset, paddr + offset + size); break; default: BUG(); -- cgit v1.2.2 From 22607a28213068af113b46862eafa785f00a482e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 15 Feb 2010 16:41:40 +0100 Subject: microblaze: Add define for ASM_LOOP It is default option but both options must be measured. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 204 +++++++++++++++++++++++++++++-------- 1 file changed, 161 insertions(+), 43 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 13f0c1de3234..f04d8a86dead 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -15,25 +15,6 @@ #include #include -static inline void __invalidate_flush_icache(unsigned int addr) -{ - __asm__ __volatile__ ("wic %0, r0;" \ - : : "r" (addr)); -} - -static inline void __flush_dcache(unsigned int addr) -{ - __asm__ __volatile__ ("wdc.flush %0, r0;" \ - : : "r" (addr)); -} - -static inline void __invalidate_dcache(unsigned int baseaddr, - unsigned int offset) -{ - __asm__ __volatile__ ("wdc.clear %0, %1;" \ - : : "r" (baseaddr), "r" (offset)); -} - static inline void __enable_icache_msr(void) { __asm__ __volatile__ (" msrset r0, %0; \ @@ -148,9 +129,9 @@ do { \ int step = -line_length; \ BUG_ON(step >= 0); \ \ - __asm__ __volatile__ (" 1: " #op " r0, %0; \ - bgtid %0, 1b; \ - addk %0, %0, %1; \ + __asm__ __volatile__ (" 1: " #op " r0, %0; \ + bgtid %0, 1b; \ + addk %0, %0, %1; \ " : : "r" (len), "r" (step) \ : "memory"); \ } while (0); @@ -162,9 +143,9 @@ do { \ int count = end - start; \ BUG_ON(count <= 0); \ \ - __asm__ __volatile__ (" 1: " #op " %0, %1; \ - bgtid %1, 1b; \ - addk %1, %1, %2; \ + __asm__ __volatile__ (" 1: " #op " %0, %1; \ + bgtid %1, 1b; \ + addk %1, %1, %2; \ " : : "r" (start), "r" (count), \ "r" (step) : "memory"); \ } while (0); @@ -175,7 +156,7 @@ do { \ int volatile temp; \ BUG_ON(end - start <= 0); \ \ - __asm__ __volatile__ (" 1: " #op " %1, r0; \ + __asm__ __volatile__ (" 1: " #op " %1, r0; \ cmpu %0, %1, %2; \ bgtid %0, 1b; \ addk %1, %1, %3; \ @@ -183,10 +164,14 @@ do { \ "r" (line_length) : "memory"); \ } while (0); +#define ASM_LOOP + static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); @@ -196,8 +181,13 @@ static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) local_irq_save(flags); __disable_icache_msr(); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); - +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (i)); +#endif __enable_icache_msr(); local_irq_restore(flags); } @@ -206,7 +196,9 @@ static void __flush_icache_range_nomsr_irq(unsigned long start, unsigned long end) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); @@ -216,7 +208,13 @@ static void __flush_icache_range_nomsr_irq(unsigned long start, local_irq_save(flags); __disable_icache_nomsr(); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (i)); +#endif __enable_icache_nomsr(); local_irq_restore(flags); @@ -225,25 +223,41 @@ static void __flush_icache_range_nomsr_irq(unsigned long start, static void __flush_icache_range_noirq(unsigned long start, unsigned long end) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (i)); +#endif } static void __flush_icache_all_msr_irq(void) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_icache_msr(); - +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); - +#else + for (i = 0; i < cpuinfo.icache_size; + i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (i)); +#endif __enable_icache_msr(); local_irq_restore(flags); } @@ -251,35 +265,59 @@ static void __flush_icache_all_msr_irq(void) static void __flush_icache_all_nomsr_irq(void) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_icache_nomsr(); - +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); - +#else + for (i = 0; i < cpuinfo.icache_size; + i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (i)); +#endif __enable_icache_nomsr(); local_irq_restore(flags); } static void __flush_icache_all_noirq(void) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); +#else + for (i = 0; i < cpuinfo.icache_size; + i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wic %0, r0;" \ + : : "r" (i)); +#endif } static void __invalidate_dcache_all_msr_irq(void) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_dcache_msr(); - +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); - +#else + for (i = 0; i < cpuinfo.dcache_size; + i += cpuinfo.dcache_line_length) + __asm__ __volatile__ ("wdc %0, r0;" \ + : : "r" (i)); +#endif __enable_dcache_msr(); local_irq_restore(flags); } @@ -287,60 +325,107 @@ static void __invalidate_dcache_all_msr_irq(void) static void __invalidate_dcache_all_nomsr_irq(void) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_dcache_nomsr(); - +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); - +#else + for (i = 0; i < cpuinfo.dcache_size; + i += cpuinfo.dcache_line_length) + __asm__ __volatile__ ("wdc %0, r0;" \ + : : "r" (i)); +#endif __enable_dcache_nomsr(); local_irq_restore(flags); } static void __invalidate_dcache_all_noirq_wt(void) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc) +#else + for (i = 0; i < cpuinfo.dcache_size; + i += cpuinfo.dcache_line_length) + __asm__ __volatile__ ("wdc %0, r0;" \ + : : "r" (i)); +#endif } /* FIXME this is weird - should be only wdc but not work * MS: I am getting bus errors and other weird things */ static void __invalidate_dcache_all_wb(void) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); +#ifdef ASM_LOOP CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc.clear) +#else + for (i = 0; i < cpuinfo.dcache_size; + i += cpuinfo.dcache_line_length) + __asm__ __volatile__ ("wdc.clear %0, r0;" \ + : : "r" (i)); +#endif } static void __invalidate_dcache_range_wb(unsigned long start, unsigned long end) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wdc.clear %0, r0;" \ + : : "r" (i)); +#endif } static void __invalidate_dcache_range_nomsr_wt(unsigned long start, unsigned long end) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wdc %0, r0;" \ + : : "r" (i)); +#endif } static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, unsigned long end) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, @@ -349,7 +434,13 @@ static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, local_irq_save(flags); __disable_dcache_msr(); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wdc %0, r0;" \ + : : "r" (i)); +#endif __enable_dcache_msr(); local_irq_restore(flags); @@ -359,7 +450,9 @@ static void __invalidate_dcache_range_nomsr_irq(unsigned long start, unsigned long end) { unsigned long flags; - +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); @@ -369,7 +462,13 @@ static void __invalidate_dcache_range_nomsr_irq(unsigned long start, local_irq_save(flags); __disable_dcache_nomsr(); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wdc %0, r0;" \ + : : "r" (i)); +#endif __enable_dcache_nomsr(); local_irq_restore(flags); @@ -377,19 +476,38 @@ static void __invalidate_dcache_range_nomsr_irq(unsigned long start, static void __flush_dcache_all_wb(void) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s\n", __func__); +#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc.flush); +#else + for (i = 0; i < cpuinfo.dcache_size; + i += cpuinfo.dcache_line_length) + __asm__ __volatile__ ("wdc.flush %0, r0;" \ + : : "r" (i)); +#endif } static void __flush_dcache_range_wb(unsigned long start, unsigned long end) { +#ifndef ASM_LOOP + int i; +#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); +#ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush); +#else + for (i = start; i < end; i += cpuinfo.icache_line_length) + __asm__ __volatile__ ("wdc.flush %0, r0;" \ + : : "r" (i)); +#endif } /* struct for wb caches and for wt caches */ -- cgit v1.2.2 From 1be53e084a5bd8f59850348e1066d25aa0200031 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 11 Mar 2010 14:15:48 +0100 Subject: microblaze: Fix dma alloc and free coherent dma functions We have to use consistent code to be able to do coherent dma function. In consistent code is used cache inhibit page mapping. Xilinx reported that there is bug in Microblaze for WB and d-cache_always use option. Microblaze 7.30.a should be first version where is this bug removed. Signed-off-by: Michal Simek --- arch/microblaze/kernel/dma.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index fbe1e8184eff..b1084974fccd 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -43,9 +43,14 @@ static unsigned long get_dma_direct_offset(struct device *dev) return PCI_DRAM_OFFSET; /* FIXME Not sure if is correct */ } -void *dma_direct_alloc_coherent(struct device *dev, size_t size, +#define NOT_COHERENT_CACHE + +static void *dma_direct_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { +#ifdef NOT_COHERENT_CACHE + return consistent_alloc(flag, size, dma_handle); +#else void *ret; struct page *page; int node = dev_to_node(dev); @@ -61,12 +66,17 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size, *dma_handle = virt_to_phys(ret) + get_dma_direct_offset(dev); return ret; +#endif } -void dma_direct_free_coherent(struct device *dev, size_t size, +static void dma_direct_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { +#ifdef NOT_COHERENT_CACHE + consistent_free(vaddr); +#else free_pages((unsigned long)vaddr, get_order(size)); +#endif } static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, @@ -105,7 +115,6 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev, enum dma_data_direction direction, struct dma_attrs *attrs) { - BUG_ON(direction == DMA_NONE); __dma_sync_page(page_to_phys(page), offset, size, direction); return page_to_phys(page) + offset + get_dma_direct_offset(dev); } @@ -121,7 +130,7 @@ static inline void dma_direct_unmap_page(struct device *dev, * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and * dma_address is physical address */ - __dma_sync_page((void *)dma_address, 0 , size, direction); + __dma_sync_page(dma_address, 0 , size, direction); } struct dma_map_ops dma_direct_ops = { -- cgit v1.2.2 From b1d70c62fff3e8b6224699801c610c244882685a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 22 Jan 2010 10:24:06 +0100 Subject: microblaze: Simplify entry.S - save/restore r3/r4 - ret_from_trap There is possible to save r3/r4 at the beggining of user part before calling handlers and at the end restore it. Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 78 ++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 48 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 1a6729dde49e..772fe7415f82 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -305,7 +305,7 @@ C_ENTRY(_user_exception): swi r11, r1, PTO+PT_R1; /* Store user SP. */ addi r11, r0, 1; swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode. */ -2: lwi r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ +2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* Save away the syscall number. */ swi r12, r1, PTO+PT_R0; tovirt(r1,r1) @@ -322,8 +322,7 @@ C_ENTRY(_user_exception): rtid r11, 0 nop 3: - add r11, r0, CURRENT_TASK /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO /* get thread info */ + lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */ lwi r11, r11, TI_FLAGS /* get flags in thread info */ andi r11, r11, _TIF_WORK_SYSCALL_MASK beqi r11, 4f @@ -382,58 +381,50 @@ C_ENTRY(ret_from_trap): /* See if returning to kernel mode, if so, skip resched &c. */ bnei r11, 2f; + swi r3, r1, PTO + PT_R3 + swi r4, r1, PTO + PT_R4 + /* We're returning to user mode, so check for various conditions that * trigger rescheduling. */ - # FIXME: Restructure all these flag checks. - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ + /* FIXME: Restructure all these flag checks. */ + lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_WORK_SYSCALL_MASK beqi r11, 1f - swi r3, r1, PTO + PT_R3 - swi r4, r1, PTO + PT_R4 brlid r15, do_syscall_trace_leave addik r5, r1, PTO + PT_R0 - lwi r3, r1, PTO + PT_R3 - lwi r4, r1, PTO + PT_R4 1: - /* We're returning to user mode, so check for various conditions that * trigger rescheduling. */ - /* Get current task ptr into r11 */ - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ + /* get thread info from current task */ + lwi r11, CURRENT_TASK, TS_THREAD_INFO; lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_NEED_RESCHED; beqi r11, 5f; - swi r3, r1, PTO + PT_R3; /* store syscall result */ - swi r4, r1, PTO + PT_R4; bralid r15, schedule; /* Call scheduler */ nop; /* delay slot */ - lwi r3, r1, PTO + PT_R3; /* restore syscall result */ - lwi r4, r1, PTO + PT_R4; /* Maybe handle a signal */ -5: add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ +5: /* get thread info from current task*/ + lwi r11, CURRENT_TASK, TS_THREAD_INFO; lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_SIGPENDING; beqi r11, 1f; /* Signals to handle, handle them */ - swi r3, r1, PTO + PT_R3; /* store syscall result */ - swi r4, r1, PTO + PT_R4; la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ addi r7, r0, 1; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ nop; + +/* Finally, return to user state. */ +1: lwi r3, r1, PTO + PT_R3; /* restore syscall result */ lwi r4, r1, PTO + PT_R4; -/* Finally, return to user state. */ -1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ + swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ swi r11, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; @@ -565,7 +556,7 @@ C_ENTRY(sys_rt_sigreturn_wrapper): swi r11, r1, PTO+PT_R1; /* Store user SP. */ \ addi r11, r0, 1; \ swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode.*/\ -2: lwi r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\ +2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); \ /* Save away the syscall number. */ \ swi r0, r1, PTO+PT_R0; \ tovirt(r1,r1) @@ -673,9 +664,7 @@ C_ENTRY(ret_from_exc): /* We're returning to user mode, so check for various conditions that trigger rescheduling. */ - /* Get current task ptr into r11 */ - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ + lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_NEED_RESCHED; beqi r11, 5f; @@ -685,8 +674,7 @@ C_ENTRY(ret_from_exc): nop; /* delay slot */ /* Maybe handle a signal */ -5: add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ +5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_SIGPENDING; beqi r11, 1f; /* Signals to handle, handle them */ @@ -802,7 +790,7 @@ C_ENTRY(_interrupt): swi r11, r0, TOPHYS(PER_CPU(KM)); 2: - lwi r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); + lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); swi r0, r1, PTO + PT_R0; tovirt(r1,r1) la r5, r1, PTO; @@ -817,8 +805,7 @@ ret_from_irq: lwi r11, r1, PTO + PT_MODE; bnei r11, 2f; - add r11, r0, CURRENT_TASK; - lwi r11, r11, TS_THREAD_INFO; + lwi r11, CURRENT_TASK, TS_THREAD_INFO; lwi r11, r11, TI_FLAGS; /* MS: get flags from thread info */ andi r11, r11, _TIF_NEED_RESCHED; beqi r11, 5f @@ -826,8 +813,7 @@ ret_from_irq: nop; /* delay slot */ /* Maybe handle a signal */ -5: add r11, r0, CURRENT_TASK; - lwi r11, r11, TS_THREAD_INFO; /* MS: get thread info */ +5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */ lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_SIGPENDING; beqid r11, no_intr_resched @@ -855,8 +841,7 @@ no_intr_resched: /* MS: Return to kernel state. */ 2: #ifdef CONFIG_PREEMPT - add r11, r0, CURRENT_TASK; - lwi r11, r11, TS_THREAD_INFO; + lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get preempt_count from thread info */ lwi r5, r11, TI_PREEMPT_COUNT; bgti r5, restore; @@ -869,8 +854,7 @@ preempt: /* interrupts are off that's why I am calling preempt_chedule_irq */ bralid r15, preempt_schedule_irq nop - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ + lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ lwi r5, r11, TI_FLAGS; /* get flags in thread info */ andi r5, r5, _TIF_NEED_RESCHED; bnei r5, preempt /* if non zero jump to resched */ @@ -938,7 +922,7 @@ C_ENTRY(_debug_exception): swi r11, r1, PTO+PT_R1; /* Store user SP. */ addi r11, r0, 1; swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode. */ -2: lwi r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ +2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* Save away the syscall number. */ swi r0, r1, PTO+PT_R0; tovirt(r1,r1) @@ -958,8 +942,7 @@ dbtrap_call: rtbd r11, 0; bnei r11, 2f; /* Get current task ptr into r11 */ - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ + lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_NEED_RESCHED; beqi r11, 5f; @@ -972,8 +955,7 @@ dbtrap_call: rtbd r11, 0; /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here. */ /* Maybe handle a signal */ -5: add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - lwi r11, r11, TS_THREAD_INFO; /* get thread info */ +5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ lwi r11, r11, TI_FLAGS; /* get flags in thread info */ andi r11, r11, _TIF_SIGPENDING; beqi r11, 1f; /* Signals to handle, handle them */ @@ -1030,7 +1012,7 @@ DBTRAP_return: /* Make global symbol for debugging */ ENTRY(_switch_to) /* prepare return value */ - addk r3, r0, r31 + addk r3, r0, CURRENT_TASK /* save registers in cpu_context */ /* use r11 and r12, volatile registers, as temp register */ @@ -1074,10 +1056,10 @@ ENTRY(_switch_to) nop swi r12, r11, CC_FSR - /* update r31, the current */ - lwi r31, r6, TI_TASK/* give me pointer to task which will be next */ + /* update r31, the current-give me pointer to task which will be next */ + lwi CURRENT_TASK, r6, TI_TASK /* stored it to current_save too */ - swi r31, r0, PER_CPU(CURRENT_SAVE) + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE) /* get new process' cpu context and restore */ /* give me start where start context of next task */ -- cgit v1.2.2 From 8633bebc63ba5752254925f8b49a19102df1a0ff Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 22 Feb 2010 13:24:43 +0100 Subject: microblaze: Save current task directly Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 772fe7415f82..cc9885d441d5 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -425,8 +425,7 @@ C_ENTRY(ret_from_trap): lwi r4, r1, PTO + PT_R4; swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - swi r11, r0, PER_CPU(CURRENT_SAVE); /* save current */ + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); RESTORE_REGS; @@ -700,8 +699,7 @@ C_ENTRY(ret_from_exc): /* Finally, return to user state. */ 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - swi r11, r0, PER_CPU(CURRENT_SAVE); /* save current */ + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); @@ -828,8 +826,7 @@ no_intr_resched: /* Disable interrupts, we are now committed to the state restore */ disable_irq swi r0, r0, PER_CPU(KM); /* MS: Now officially in user state. */ - add r11, r0, CURRENT_TASK; - swi r11, r0, PER_CPU(CURRENT_SAVE); + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); VM_OFF; tophys(r1,r1); lwi r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */ @@ -979,8 +976,7 @@ dbtrap_call: rtbd r11, 0; /* Finally, return to user state. */ 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ - add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ - swi r11, r0, PER_CPU(CURRENT_SAVE); /* save current */ + swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); -- cgit v1.2.2 From 841d6e8c4e969b2cdd80f7216af34d932c41b1a6 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 22 Jan 2010 14:28:36 +0100 Subject: microblaze: entry.S use delay slot for return handlers Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index cc9885d441d5..c0ede25c5b99 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -414,10 +414,9 @@ C_ENTRY(ret_from_trap): beqi r11, 1f; /* Signals to handle, handle them */ la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ - add r6, r0, r0; /* Arg 2: sigset_t *oldset */ addi r7, r0, 1; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ - nop; + add r6, r0, r0; /* Arg 2: sigset_t *oldset */ /* Finally, return to user state. */ 1: @@ -692,10 +691,9 @@ C_ENTRY(ret_from_exc): * store return registers separately because this macros is use * for others exceptions */ la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ - add r6, r0, r0; /* Arg 2: sigset_t *oldset */ addi r7, r0, 0; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ - nop; + add r6, r0, r0; /* Arg 2: sigset_t *oldset */ /* Finally, return to user state. */ 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ @@ -968,10 +966,9 @@ dbtrap_call: rtbd r11, 0; (in a possibly modified form) after do_signal returns. */ la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ - add r6, r0, r0; /* Arg 2: sigset_t *oldset */ addi r7, r0, 0; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ - nop; + add r6, r0, r0; /* Arg 2: sigset_t *oldset */ /* Finally, return to user state. */ -- cgit v1.2.2 From b3c1e01a09d6af2dd7811a066ffcfc5171be2bed Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Mar 2010 15:22:44 -0800 Subject: ptrace: use ptrace_request() in the remaining architectures Use ptrace_request() in the three remaining architectures that didn't use it (m68knommu, h8300, microblaze). This means: - ptrace_request now handles PTRACE_{PEEK,POKE}{TEXT,DATA} and PTRACE_DETATCH calls that were previously called directly, or in case of h8300 even open coded. - adds new support for PTRACE_SETOPTIONS/PTRACE_GETEVENTMSG/ PTRACE_GETSIGINFO/PTRACE_SETSIGINFO Signed-off-by: Christoph Hellwig Cc: Geert Uytterhoeven Cc: Yoshinori Sato Cc: Oleg Nesterov Cc: Michal Simek Acked-by: Greg Ungerer Acked-by: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/microblaze/kernel/ptrace.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index 4b3ac32754de..8c21d8b3cb0c 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -78,26 +78,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) unsigned long copied; switch (request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: - pr_debug("PEEKTEXT/PEEKDATA at %08lX\n", addr); - copied = access_process_vm(child, addr, &val, sizeof(val), 0); - rval = -EIO; - if (copied != sizeof(val)) - break; - rval = put_user(val, (unsigned long *)data); - break; - - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - pr_debug("POKETEXT/POKEDATA to %08lX\n", addr); - rval = 0; - if (access_process_vm(child, addr, &data, sizeof(data), 1) - == sizeof(data)) - break; - rval = -EIO; - break; - /* Read/write the word at location ADDR in the registers. */ case PTRACE_PEEKUSR: case PTRACE_POKEUSR: @@ -167,13 +147,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); break; - case PTRACE_DETACH: /* detach a process that was attached. */ - pr_debug("PTRACE_DETACH\n"); - rval = ptrace_detach(child, data); - break; default: - /* rval = ptrace_request(child, request, addr, data); noMMU */ - rval = -EIO; + rval = ptrace_request(child, request, addr, data); } return rval; } -- cgit v1.2.2 From fa1ac57a317f927b8fb901e6270fc41fdaae8e1c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Mar 2010 15:22:54 -0800 Subject: microblaze: use generic ptrace_resume code Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT and PTRACE_KILL. This also makes PTRACE_SINGLESTEP return -EIO while it previously succeeded despite not actually causing any kind of single stepping. Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL which it previously wasn't which is consistent with all architectures using the modern ptrace code. Signed-off-by: Christoph Hellwig Cc: Oleg Nesterov Cc: Roland McGrath Acked-by: Michal Simek Cc: John Williams Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/microblaze/kernel/ptrace.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index 8c21d8b3cb0c..6d6349a145f9 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -110,43 +110,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (rval == 0 && request == PTRACE_PEEKUSR) rval = put_user(val, (unsigned long *)data); break; - /* Continue and stop at next (return from) syscall */ - case PTRACE_SYSCALL: - pr_debug("PTRACE_SYSCALL\n"); - case PTRACE_SINGLESTEP: - pr_debug("PTRACE_SINGLESTEP\n"); - /* Restart after a signal. */ - case PTRACE_CONT: - pr_debug("PTRACE_CONT\n"); - rval = -EIO; - if (!valid_signal(data)) - break; - - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - child->exit_code = data; - pr_debug("wakeup_process\n"); - wake_up_process(child); - rval = 0; - break; - - /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: - pr_debug("PTRACE_KILL\n"); - rval = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - default: rval = ptrace_request(child, request, addr, data); } -- cgit v1.2.2 From 5a0e3ad6af8660be21ca98a971cd00f331318c05 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Mar 2010 17:04:11 +0900 Subject: include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h percpu.h is included by sched.h and module.h and thus ends up being included when building most .c files. percpu.h includes slab.h which in turn includes gfp.h making everything defined by the two files universally available and complicating inclusion dependencies. percpu.h -> slab.h dependency is about to be removed. Prepare for this change by updating users of gfp and slab facilities include those headers directly instead of assuming availability. As this conversion needs to touch large number of source files, the following script is used as the basis of conversion. http://userweb.kernel.org/~tj/misc/slabh-sweep.py The script does the followings. * Scan files for gfp and slab usages and update includes such that only the necessary includes are there. ie. if only gfp is used, gfp.h, if slab is used, slab.h. * When the script inserts a new include, it looks at the include blocks and try to put the new include such that its order conforms to its surrounding. It's put in the include block which contains core kernel includes, in the same order that the rest are ordered - alphabetical, Christmas tree, rev-Xmas-tree or at the end if there doesn't seem to be any matching order. * If the script can't find a place to put a new include (mostly because the file doesn't have fitting include block), it prints out an error message indicating which .h file needs to be added to the file. The conversion was done in the following steps. 1. The initial automatic conversion of all .c files updated slightly over 4000 files, deleting around 700 includes and adding ~480 gfp.h and ~3000 slab.h inclusions. The script emitted errors for ~400 files. 2. Each error was manually checked. Some didn't need the inclusion, some needed manual addition while adding it to implementation .h or embedding .c file was more appropriate for others. This step added inclusions to around 150 files. 3. The script was run again and the output was compared to the edits from #2 to make sure no file was left behind. 4. Several build tests were done and a couple of problems were fixed. e.g. lib/decompress_*.c used malloc/free() wrappers around slab APIs requiring slab.h to be added manually. 5. The script was run on all .h files but without automatically editing them as sprinkling gfp.h and slab.h inclusions around .h files could easily lead to inclusion dependency hell. Most gfp.h inclusion directives were ignored as stuff from gfp.h was usually wildly available and often used in preprocessor macros. Each slab.h inclusion directive was examined and added manually as necessary. 6. percpu.h was updated not to include slab.h. 7. Build test were done on the following configurations and failures were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my distributed build env didn't work with gcov compiles) and a few more options had to be turned off depending on archs to make things build (like ipr on powerpc/64 which failed due to missing writeq). * x86 and x86_64 UP and SMP allmodconfig and a custom test config. * powerpc and powerpc64 SMP allmodconfig * sparc and sparc64 SMP allmodconfig * ia64 SMP allmodconfig * s390 SMP allmodconfig * alpha SMP allmodconfig * um on x86_64 SMP allmodconfig 8. percpu.h modifications were reverted so that it could be applied as a separate patch and serve as bisection point. Given the fact that I had only a couple of failures from tests on step 6, I'm fairly confident about the coverage of this conversion patch. If there is a breakage, it's likely to be something in one of the arch headers which should be easily discoverable easily on most builds of the specific arch. Signed-off-by: Tejun Heo Guess-its-ok-by: Christoph Lameter Cc: Ingo Molnar Cc: Lee Schermerhorn --- arch/microblaze/kernel/cpu/cpuinfo.c | 1 - arch/microblaze/kernel/dma.c | 1 + arch/microblaze/kernel/module.c | 1 - arch/microblaze/kernel/of_platform.c | 1 - arch/microblaze/kernel/sys_microblaze.c | 1 + 5 files changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 991d71311b0e..255ef880351e 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -9,7 +9,6 @@ */ #include -#include #include #include diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index b1084974fccd..9d69ca4b9635 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c index 5a45b1adfef1..cbecf110dc30 100644 --- a/arch/microblaze/kernel/module.c +++ b/arch/microblaze/kernel/module.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c index 1c6d684996d7..0dc755286d38 100644 --- a/arch/microblaze/kernel/of_platform.c +++ b/arch/microblaze/kernel/of_platform.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 9f3c205fb75b..f4e00b7f1259 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -30,6 +30,7 @@ #include #include #include +#include #include -- cgit v1.2.2 From 0c4ec16b86e6a823bc6e9fbe08a724d517eb3c24 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Wed, 24 Feb 2010 14:54:15 -0600 Subject: microblaze: Fix "kstack=" parsing The "kstack=" command line parameter is not parsed correctly. All proper values are interpreted as zero. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/traps.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c index eaaaf805f31b..5e4570ef515c 100644 --- a/arch/microblaze/kernel/traps.c +++ b/arch/microblaze/kernel/traps.c @@ -22,13 +22,11 @@ void trap_init(void) __enable_hw_exceptions(); } -static int kstack_depth_to_print = 24; +static unsigned long kstack_depth_to_print = 24; static int __init kstack_setup(char *s) { - kstack_depth_to_print = strict_strtoul(s, 0, NULL); - - return 1; + return !strict_strtoul(s, 0, &kstack_depth_to_print); } __setup("kstack=", kstack_setup); -- cgit v1.2.2 From 40db0834337ef0cde586feeb5588e45f0349098b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 5 Mar 2010 15:34:12 +0100 Subject: microblaze: Remove segment.h I would like to use asm-generic uaccess.h where are segment macros defined. This is just first step. Signed-off-by: Michal Simek --- arch/microblaze/kernel/process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 812f1bf06c9e..35efb2f42d50 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -15,6 +15,7 @@ #include #include #include +#include /* for USER_DS macros */ #include void show_regs(struct pt_regs *regs) -- cgit v1.2.2 From ee68f1745e7734a55c8bf680f6f464205f1f15da Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 15 Mar 2010 08:48:27 +0100 Subject: microblaze: Support systems without lmb bram When the system has no lmb bram, main memory should be start from zero because of microblaze vectors. DTS fragment could look like: DDR2_SDRAM: memory@0 { device_type = "memory"; reg = < 0x0 0x10000000 >; } ; Then you have to setup CONFIG_KERNEL_BASE_ADDR=0 which caused that kernel physical start address will be zero. On reset vector place will be jump to 0x100 and on 0x100 starts kernel text. You have to solve how to load the kernel before cpu starts. Tested with XMD. Signed-off-by: Michal Simek --- arch/microblaze/kernel/head.S | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index cb7815cfe5ab..e397d5d52571 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -51,6 +51,12 @@ swapper_pg_dir: .text ENTRY(_start) +#if CONFIG_KERNEL_BASE_ADDR == 0 + brai TOPHYS(real_start) + .org 0x100 +real_start: +#endif + mfs r1, rmsr andi r1, r1, ~2 mts rmsr, r1 -- cgit v1.2.2 From 708e7153d6fc4d2e5fe15c6ccc5d2907fe8a9c8d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Mar 2010 07:23:04 +0100 Subject: microblaze: Add DEBUG option Disable debug option in asm code. Signed-off-by: Michal Simek --- arch/microblaze/kernel/hw_exception_handler.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index 2b86c03aa841..6651bb437db2 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -334,6 +334,7 @@ not_in_delay_slot: addk r6, r5, r5; /* << 1 */ addk r6, r6, r6; /* << 2 */ +#ifdef DEBUG /* counting which exception happen */ lwi r5, r0, 0x200 + TOPHYS(r0_ram) addi r5, r5, 1 @@ -341,6 +342,7 @@ not_in_delay_slot: lwi r5, r6, 0x200 + TOPHYS(r0_ram) addi r5, r5, 1 swi r5, r6, 0x200 + TOPHYS(r0_ram) +#endif /* end */ /* Load the HW Exception vector */ lwi r6, r6, TOPHYS(_MB_HW_ExceptionVectorTable) -- cgit v1.2.2 From 7a6bbdc9304b45cc759e03623cbe63d81aff7337 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 22 Mar 2010 20:37:23 +0100 Subject: microblaze: Prepare work for optimization in exception code Any sync branch must follow mts instructions not mfs. Signed-off-by: Michal Simek --- arch/microblaze/kernel/hw_exception_handler.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index 6651bb437db2..ad6dbf029e6b 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -562,7 +562,6 @@ ex_handler_done: */ mfs r11, rpid nop - bri 4 mfs r3, rear /* Get faulting address */ nop /* If we are faulting a kernel address, we have to use the @@ -679,18 +678,17 @@ ex_handler_done: */ handle_data_tlb_miss_exception: /* Working registers already saved: R3, R4, R5, R6 - * R3 = ESR + * R3 = EAR, R4 = ESR */ mfs r11, rpid nop - bri 4 mfs r3, rear /* Get faulting address */ nop /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - ori r4, r0, CONFIG_KERNEL_START - cmpu r4, r3, r4 + ori r6, r0, CONFIG_KERNEL_START + cmpu r4, r3, r6 bgti r4, ex5 ori r4, r0, swapper_pg_dir mts rpid, r0 /* TLB will have 0 TID */ @@ -756,7 +754,6 @@ ex_handler_done: */ mfs r11, rpid nop - bri 4 mfs r3, rear /* Get faulting address */ nop -- cgit v1.2.2 From b175bcfe31cba846d8bfa35a3a4820667f7af383 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 19 Mar 2010 12:44:40 +0100 Subject: microblaze: Change register usage for ESR and EAR This change synchronize register usage in code. ESR = R4 EAR = R3 Signed-off-by: Michal Simek --- arch/microblaze/kernel/hw_exception_handler.S | 70 +++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index ad6dbf029e6b..a652addb9321 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -313,13 +313,13 @@ _hw_exception_handler: mfs r5, rmsr; nop swi r5, r1, 0; - mfs r3, resr + mfs r4, resr nop - mfs r4, rear; + mfs r3, rear; nop #ifndef CONFIG_MMU - andi r5, r3, 0x1000; /* Check ESR[DS] */ + andi r5, r4, 0x1000; /* Check ESR[DS] */ beqi r5, not_in_delay_slot; /* Branch if ESR[DS] not set */ mfs r17, rbtr; /* ESR[DS] set - return address in BTR */ nop @@ -327,7 +327,7 @@ not_in_delay_slot: swi r17, r1, PT_R17 #endif - andi r5, r3, 0x1F; /* Extract ESR[EXC] */ + andi r5, r4, 0x1F; /* Extract ESR[EXC] */ #ifdef CONFIG_MMU /* Calculate exception vector offset = r5 << 2 */ @@ -378,7 +378,7 @@ handle_other_ex: /* Handle Other exceptions here */ swi r18, r1, PT_R18 or r5, r1, r0 - andi r6, r3, 0x1F; /* Load ESR[EC] */ + andi r6, r4, 0x1F; /* Load ESR[EC] */ lwi r7, r0, PER_CPU(KM) /* MS: saving current kernel mode to regs */ swi r7, r1, PT_MODE mfs r7, rfsr @@ -428,11 +428,11 @@ handle_other_ex: /* Handle Other exceptions here */ */ handle_unaligned_ex: /* Working registers already saved: R3, R4, R5, R6 - * R3 = ESR - * R4 = EAR + * R4 = ESR + * R3 = EAR */ #ifdef CONFIG_MMU - andi r6, r3, 0x1000 /* Check ESR[DS] */ + andi r6, r4, 0x1000 /* Check ESR[DS] */ beqi r6, _no_delayslot /* Branch if ESR[DS] not set */ mfs r17, rbtr; /* ESR[DS] set - return address in BTR */ nop @@ -441,7 +441,7 @@ _no_delayslot: RESTORE_STATE; bri unaligned_data_trap #endif - andi r6, r3, 0x3E0; /* Mask and extract the register operand */ + andi r6, r4, 0x3E0; /* Mask and extract the register operand */ srl r6, r6; /* r6 >> 5 */ srl r6, r6; srl r6, r6; @@ -450,33 +450,33 @@ _no_delayslot: /* Store the register operand in a temporary location */ sbi r6, r0, TOPHYS(ex_reg_op); - andi r6, r3, 0x400; /* Extract ESR[S] */ + andi r6, r4, 0x400; /* Extract ESR[S] */ bnei r6, ex_sw; ex_lw: - andi r6, r3, 0x800; /* Extract ESR[W] */ + andi r6, r4, 0x800; /* Extract ESR[W] */ beqi r6, ex_lhw; - lbui r5, r4, 0; /* Exception address in r4 */ + lbui r5, r3, 0; /* Exception address in r3 */ /* Load a word, byte-by-byte from destination address and save it in tmp space */ sbi r5, r0, TOPHYS(ex_tmp_data_loc_0); - lbui r5, r4, 1; + lbui r5, r3, 1; sbi r5, r0, TOPHYS(ex_tmp_data_loc_1); - lbui r5, r4, 2; + lbui r5, r3, 2; sbi r5, r0, TOPHYS(ex_tmp_data_loc_2); - lbui r5, r4, 3; + lbui r5, r3, 3; sbi r5, r0, TOPHYS(ex_tmp_data_loc_3); - /* Get the destination register value into r3 */ - lwi r3, r0, TOPHYS(ex_tmp_data_loc_0); + /* Get the destination register value into r4 */ + lwi r4, r0, TOPHYS(ex_tmp_data_loc_0); bri ex_lw_tail; ex_lhw: - lbui r5, r4, 0; /* Exception address in r4 */ + lbui r5, r3, 0; /* Exception address in r3 */ /* Load a half-word, byte-by-byte from destination address and save it in tmp space */ sbi r5, r0, TOPHYS(ex_tmp_data_loc_0); - lbui r5, r4, 1; + lbui r5, r3, 1; sbi r5, r0, TOPHYS(ex_tmp_data_loc_1); - /* Get the destination register value into r3 */ - lhui r3, r0, TOPHYS(ex_tmp_data_loc_0); + /* Get the destination register value into r4 */ + lhui r4, r0, TOPHYS(ex_tmp_data_loc_0); ex_lw_tail: /* Get the destination register number into r5 */ lbui r5, r0, TOPHYS(ex_reg_op); @@ -504,25 +504,25 @@ ex_sw_tail: andi r6, r6, 0x800; /* Extract ESR[W] */ beqi r6, ex_shw; /* Get the word - delay slot */ - swi r3, r0, TOPHYS(ex_tmp_data_loc_0); + swi r4, r0, TOPHYS(ex_tmp_data_loc_0); /* Store the word, byte-by-byte into destination address */ - lbui r3, r0, TOPHYS(ex_tmp_data_loc_0); - sbi r3, r4, 0; - lbui r3, r0, TOPHYS(ex_tmp_data_loc_1); - sbi r3, r4, 1; - lbui r3, r0, TOPHYS(ex_tmp_data_loc_2); - sbi r3, r4, 2; - lbui r3, r0, TOPHYS(ex_tmp_data_loc_3); - sbi r3, r4, 3; + lbui r4, r0, TOPHYS(ex_tmp_data_loc_0); + sbi r4, r3, 0; + lbui r4, r0, TOPHYS(ex_tmp_data_loc_1); + sbi r4, r3, 1; + lbui r4, r0, TOPHYS(ex_tmp_data_loc_2); + sbi r4, r3, 2; + lbui r4, r0, TOPHYS(ex_tmp_data_loc_3); + sbi r4, r3, 3; bri ex_handler_done; ex_shw: /* Store the lower half-word, byte-by-byte into destination address */ - swi r3, r0, TOPHYS(ex_tmp_data_loc_0); - lbui r3, r0, TOPHYS(ex_tmp_data_loc_2); - sbi r3, r4, 0; - lbui r3, r0, TOPHYS(ex_tmp_data_loc_3); - sbi r3, r4, 1; + swi r4, r0, TOPHYS(ex_tmp_data_loc_0); + lbui r4, r0, TOPHYS(ex_tmp_data_loc_2); + sbi r4, r3, 0; + lbui r4, r0, TOPHYS(ex_tmp_data_loc_3); + sbi r4, r3, 1; ex_sw_end: /* Exception handling of store word, ends. */ ex_handler_done: -- cgit v1.2.2 From bd1637d63e82aaf732ffbe907ba887fa12e82df4 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 19 Mar 2010 12:50:35 +0100 Subject: microblaze: Remove additional resr and rear loading RESR and REAR uses the same regs in whole file. Signed-off-by: Michal Simek --- arch/microblaze/kernel/hw_exception_handler.S | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index a652addb9321..5d8c3de58b0c 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -562,20 +562,16 @@ ex_handler_done: */ mfs r11, rpid nop - mfs r3, rear /* Get faulting address */ - nop /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - ori r4, r0, CONFIG_KERNEL_START - cmpu r4, r3, r4 - bgti r4, ex3 + ori r5, r0, CONFIG_KERNEL_START + cmpu r5, r3, r5 + bgti r5, ex3 /* First, check if it was a zone fault (which means a user * tried to access a kernel or read-protected page - always * a SEGV). All other faults here must be stores, so no * need to check ESR_S as well. */ - mfs r4, resr - nop andi r4, r4, 0x800 /* ESR_Z - zone protection */ bnei r4, ex2 @@ -590,8 +586,6 @@ ex_handler_done: * tried to access a kernel or read-protected page - always * a SEGV). All other faults here must be stores, so no * need to check ESR_S as well. */ - mfs r4, resr - nop andi r4, r4, 0x800 /* ESR_Z */ bnei r4, ex2 /* get current task address */ @@ -666,8 +660,6 @@ ex_handler_done: * R3 = ESR */ - mfs r3, rear /* Get faulting address */ - nop RESTORE_STATE; bri page_fault_instr_trap @@ -682,8 +674,6 @@ ex_handler_done: */ mfs r11, rpid nop - mfs r3, rear /* Get faulting address */ - nop /* If we are faulting a kernel address, we have to use the * kernel page tables. */ @@ -754,8 +744,6 @@ ex_handler_done: */ mfs r11, rpid nop - mfs r3, rear /* Get faulting address */ - nop /* If we are faulting a kernel address, we have to use the * kernel page tables. -- cgit v1.2.2 From 3765d6958dfff34a15588e23c5d1274e1f6ba200 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 22 Mar 2010 20:43:27 +0100 Subject: microblaze: Use instruction with delay slot Sync labels. Signed-off-by: Michal Simek --- arch/microblaze/kernel/hw_exception_handler.S | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index 5d8c3de58b0c..995a2123635b 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -721,9 +721,8 @@ ex_handler_done: * Many of these bits are software only. Bits we don't set * here we (properly should) assume have the appropriate value. */ + brid finish_tlb_load andni r4, r4, 0x0ce2 /* Make sure 20, 21 are zero */ - - bri finish_tlb_load ex7: /* The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. @@ -779,7 +778,7 @@ ex_handler_done: lwi r4, r5, 0 /* Get Linux PTE */ andi r6, r4, _PAGE_PRESENT - beqi r6, ex7 + beqi r6, ex10 ori r4, r4, _PAGE_ACCESSED swi r4, r5, 0 @@ -792,9 +791,8 @@ ex_handler_done: * Many of these bits are software only. Bits we don't set * here we (properly should) assume have the appropriate value. */ + brid finish_tlb_load andni r4, r4, 0x0ce2 /* Make sure 20, 21 are zero */ - - bri finish_tlb_load ex10: /* The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. @@ -824,9 +822,9 @@ ex_handler_done: andi r5, r5, (MICROBLAZE_TLB_SIZE-1) ori r6, r0, 1 cmp r31, r5, r6 - blti r31, sem + blti r31, ex12 addik r5, r6, 1 - sem: + ex12: /* MS: save back current TLB index */ swi r5, r0, TOPHYS(tlb_index) @@ -846,7 +844,6 @@ ex_handler_done: nop /* Done...restore registers and get out of here. */ - ex12: mts rpid, r11 nop bri 4 -- cgit v1.2.2 From 13851966da54be8e37863aa93ee2c8f3d3a3186a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Mar 2010 08:09:32 +0100 Subject: microblaze: Add .type and .size to ASM functions Cachegrind analysis need this fix to be able to log asm functions. Signed-off-by: Michal Simek --- arch/microblaze/kernel/misc.S | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S index df16c6287a8e..18681eed5ec7 100644 --- a/arch/microblaze/kernel/misc.S +++ b/arch/microblaze/kernel/misc.S @@ -26,6 +26,7 @@ * We avoid flushing the pinned 0, 1 and possibly 2 entries. */ .globl _tlbia; +.type _tlbia, @function .align 4; _tlbia: addik r12, r0, 63 /* flush all entries (63 - 3) */ @@ -41,11 +42,13 @@ _tlbia_1: /* sync */ rtsd r15, 8 nop + .size _tlbia, . - _tlbia /* * Flush MMU TLB for a particular address (in r5) */ .globl _tlbie; +.type _tlbie, @function .align 4; _tlbie: mts rtlbsx, r5 /* look up the address in TLB */ @@ -59,10 +62,13 @@ _tlbie_1: rtsd r15, 8 nop + .size _tlbie, . - _tlbie + /* * Allocate TLB entry for early console */ .globl early_console_reg_tlb_alloc; +.type early_console_reg_tlb_alloc, @function .align 4; early_console_reg_tlb_alloc: /* @@ -86,6 +92,8 @@ early_console_reg_tlb_alloc: rtsd r15, 8 nop + .size early_console_reg_tlb_alloc, . - early_console_reg_tlb_alloc + /* * Copy a whole page (4096 bytes). */ @@ -104,6 +112,7 @@ early_console_reg_tlb_alloc: #define DCACHE_LINE_BYTES (4 * 4) .globl copy_page; +.type copy_page, @function .align 4; copy_page: ori r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1 @@ -118,3 +127,5 @@ _copy_page_loop: addik r11, r11, -1 rtsd r15, 8 nop + + .size copy_page, . - copy_page -- cgit v1.2.2 From 78ebfa884bcef125464399f8d1cb05937bfeb6e1 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Mar 2010 15:37:02 +0100 Subject: microblaze: Adding likely macros On the base on GCOV analytics is helpful to add likely/unlikely macros. Signed-off-by: Michal Simek --- arch/microblaze/kernel/dma.c | 2 +- arch/microblaze/kernel/process.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index b1084974fccd..4d5b0311601b 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -37,7 +37,7 @@ static inline void __dma_sync_page(unsigned long paddr, unsigned long offset, static unsigned long get_dma_direct_offset(struct device *dev) { - if (dev) + if (likely(dev)) return (unsigned long)dev->archdata.dma_data; return PCI_DRAM_OFFSET; /* FIXME Not sure if is correct */ diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 35efb2f42d50..09bed44dfcd3 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -75,7 +75,10 @@ __setup("hlt", hlt_setup); void default_idle(void) { - if (!hlt_counter) { + if (likely(hlt_counter)) { + while (!need_resched()) + cpu_relax(); + } else { clear_thread_flag(TIF_POLLING_NRFLAG); smp_mb__after_clear_bit(); local_irq_disable(); @@ -83,9 +86,7 @@ void default_idle(void) cpu_sleep(); local_irq_enable(); set_thread_flag(TIF_POLLING_NRFLAG); - } else - while (!need_resched()) - cpu_relax(); + } } void cpu_idle(void) -- cgit v1.2.2 From 0691c97d74cbdfd49333ef01939ecaef158ebe1b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Mar 2010 10:09:17 +0100 Subject: microblaze: Use MICROBLAZE_TLB_SIZE in asm code TLB size was hardcoded in asm code. This patch brings ability to change TLB size only in one place. (mmu.h). Signed-off-by: Michal Simek --- arch/microblaze/kernel/head.S | 2 +- arch/microblaze/kernel/misc.S | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index e397d5d52571..ba2c0333c6bb 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -134,7 +134,7 @@ _copy_bram: * virtual to physical. */ nop - addik r3, r0, 63 /* Invalidate all TLB entries */ + addik r3, r0, MICROBLAZE_TLB_SIZE -1 /* Invalidate all TLB entries */ _invalidate: mts rtlbx, r3 mts rtlbhi, r0 /* flush: ensure V is clear */ diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S index 18681eed5ec7..7cf86498326c 100644 --- a/arch/microblaze/kernel/misc.S +++ b/arch/microblaze/kernel/misc.S @@ -29,7 +29,7 @@ .type _tlbia, @function .align 4; _tlbia: - addik r12, r0, 63 /* flush all entries (63 - 3) */ + addik r12, r0, MICROBLAZE_TLB_SIZE - 1 /* flush all entries (63 - 3) */ /* isync */ _tlbia_1: mts rtlbx, r12 @@ -75,7 +75,7 @@ early_console_reg_tlb_alloc: * Load a TLB entry for the UART, so that microblaze_progress() can use * the UARTs nice and early. We use a 4k real==virtual mapping. */ - ori r4, r0, 63 + ori r4, r0, MICROBLAZE_TLB_SIZE - 1 mts rtlbx, r4 /* TLB slot 2 */ or r4,r5,r0 -- cgit v1.2.2 From 3f2189358666b6fa09d41f527be07b3cc8026050 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Mar 2010 11:06:23 +0100 Subject: microblaze: head.S typo fix I forget to change register name in comments. Signed-off-by: Michal Simek --- arch/microblaze/kernel/head.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index ba2c0333c6bb..da6a5f5dc766 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -105,8 +105,8 @@ no_fdt_arg: tophys(r4,r4) /* convert to phys address */ ori r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */ _copy_command_line: - lbu r2, r5, r6 /* r7=r5+r6 - r5 contain pointer to command line */ - sb r2, r4, r6 /* addr[r4+r6]= r7*/ + lbu r2, r5, r6 /* r2=r5+r6 - r5 contain pointer to command line */ + sb r2, r4, r6 /* addr[r4+r6]= r2*/ addik r6, r6, 1 /* increment counting */ bgtid r3, _copy_command_line /* loop for all entries */ addik r3, r3, -1 /* descrement loop */ -- cgit v1.2.2 From 6059b3cbeb27a38e3ca9ac9d2827f7b5be32e2ba Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Mar 2010 11:07:10 +0100 Subject: microblaze: Print early printk information to log buffer If early printk console is not enabled then all messages are written to log buffer. Signed-off-by: Michal Simek --- arch/microblaze/kernel/setup.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index f974ec7aa357..17c98dbcec88 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -92,6 +92,12 @@ inline unsigned get_romfs_len(unsigned *addr) } #endif /* CONFIG_MTD_UCLINUX_EBSS */ +#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE) +#define eprintk early_printk +#else +#define eprintk printk +#endif + void __init machine_early_init(const char *cmdline, unsigned int ram, unsigned int fdt, unsigned int msr) { @@ -139,32 +145,32 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, setup_early_printk(NULL); #endif - early_printk("Ramdisk addr 0x%08x, ", ram); + eprintk("Ramdisk addr 0x%08x, ", ram); if (fdt) - early_printk("FDT at 0x%08x\n", fdt); + eprintk("FDT at 0x%08x\n", fdt); else - early_printk("Compiled-in FDT at 0x%08x\n", + eprintk("Compiled-in FDT at 0x%08x\n", (unsigned int)_fdt_start); #ifdef CONFIG_MTD_UCLINUX - early_printk("Found romfs @ 0x%08x (0x%08x)\n", + eprintk("Found romfs @ 0x%08x (0x%08x)\n", romfs_base, romfs_size); - early_printk("#### klimit %p ####\n", old_klimit); + eprintk("#### klimit %p ####\n", old_klimit); BUG_ON(romfs_size < 0); /* What else can we do? */ - early_printk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n", + eprintk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n", romfs_size, romfs_base, (unsigned)&_ebss); - early_printk("New klimit: 0x%08x\n", (unsigned)klimit); + eprintk("New klimit: 0x%08x\n", (unsigned)klimit); #endif #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR if (msr) - early_printk("!!!Your kernel has setup MSR instruction but " + eprintk("!!!Your kernel has setup MSR instruction but " "CPU don't have it %d\n", msr); #else if (!msr) - early_printk("!!!Your kernel not setup MSR instruction but " + eprintk("!!!Your kernel not setup MSR instruction but " "CPU have it %d\n", msr); #endif -- cgit v1.2.2 From d2bf98e6fc2612cbd2fc40f75a1e2c5d60262331 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Fri, 2 Apr 2010 13:29:39 -0500 Subject: microblaze: Fix ftrace_update_ftrace_func panic The Microblaze dynamic ftrace code assumes a call ordering that is not met in all scenarios. Specifically, executing a command similar to: echo 105 > /sys/kernel/debug/tracing/set_ftrace_pid before any other tracing-related commands results in a kernel panic: BUG: failure at arch/microblaze/kernel/ftrace.c:198/ftrace_update_ftrace_func()! Recoding ftrace_update_ftrace_func() to use &ftrace_caller directly eliminates the need to capture its address elsewhere (and thus rely on a particular call sequence). Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/ftrace.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c index 388b31ca65a1..515feb404555 100644 --- a/arch/microblaze/kernel/ftrace.c +++ b/arch/microblaze/kernel/ftrace.c @@ -151,13 +151,10 @@ int ftrace_make_nop(struct module *mod, return ret; } -static int ret_addr; /* initialized as 0 by default */ - /* I believe that first is called ftrace_make_nop before this function */ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { int ret; - ret_addr = addr; /* saving where the barrier jump is */ pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n", __func__, (unsigned int)addr, (unsigned int)rec->ip, imm); ret = ftrace_modify_code(rec->ip, imm); @@ -194,12 +191,9 @@ int ftrace_update_ftrace_func(ftrace_func_t func) ret = ftrace_modify_code(ip, upper); ret += ftrace_modify_code(ip + 4, lower); - /* We just need to remove the rtsd r15, 8 by NOP */ - BUG_ON(!ret_addr); - if (ret_addr) - ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP); - else - ret = 1; /* fault */ + /* We just need to replace the rtsd r15, 8 with NOP */ + ret += ftrace_modify_code((unsigned long)&ftrace_caller, + MICROBLAZE_NOP); /* All changes are done - lets do caches consistent */ flush_icache(); -- cgit v1.2.2 From af2b021fd6dc3e145d20f5eb927af9590c80bc44 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 7 Apr 2010 11:44:00 +0200 Subject: microblaze: Remove unused variable from ptrace Patch b3c1e01a09d6af2dd7811a066ffcfc5171be2bed should do it. Signed-off-by: Michal Simek --- arch/microblaze/kernel/ptrace.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index 6d6349a145f9..a4a7770c6140 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -75,7 +75,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int rval; unsigned long val = 0; - unsigned long copied; switch (request) { /* Read/write the word at location ADDR in the registers. */ -- cgit v1.2.2 From e6d7961e5be0a259ba87411370f8be7f7da4c0f6 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Mon, 12 Apr 2010 16:01:36 -0500 Subject: microblaze: Fix IRQ entry/exit ftracing Function traces on Microblaze don't include IRQ entry and exit arrows, i.e. 0) | memcpy_toiovec() { 0) ==========> | 0) | do_IRQ() { ... 0) <========== | 0) ! 5414.000 us | } ...because do_IRQ() doesn't have the proper attributes. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index 6f39e2c001f3..8f120aca123d 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -32,7 +33,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); static u32 concurrent_irq; -void do_IRQ(struct pt_regs *regs) +void __irq_entry do_IRQ(struct pt_regs *regs) { unsigned int irq; struct pt_regs *old_regs = set_irq_regs(regs); -- cgit v1.2.2 From 7a0248e819ddaf2c2f28e6edd287b90aa930702a Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Fri, 9 Apr 2010 22:03:37 -0500 Subject: microblaze: Quiet section mismatch warnings _start is located in .text, which causes mismatch warnings with machine_early_init() and start_kernel() in .init.text. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/head.S | 3 ++- arch/microblaze/kernel/vmlinux.lds.S | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index da6a5f5dc766..1bf739888260 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -28,6 +28,7 @@ * for more details. */ +#include #include #include #include @@ -49,7 +50,7 @@ swapper_pg_dir: #endif /* CONFIG_MMU */ - .text + __HEAD ENTRY(_start) #if CONFIG_KERNEL_BASE_ADDR == 0 brai TOPHYS(real_start) diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index 5ef619aad634..db72d7124602 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -24,7 +24,8 @@ SECTIONS { .text : AT(ADDR(.text) - LOAD_OFFSET) { _text = . ; _stext = . ; - *(.text .text.*) + HEAD_TEXT + TEXT_TEXT *(.fixup) EXIT_TEXT EXIT_CALL -- cgit v1.2.2 From e7682231092d1d1dd49bc590d6d3b7f0ddc07e74 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 09:41:07 +0200 Subject: microblaze: Remove ancient code I found several function which we don't use that's why I am removing them. Signed-off-by: Michal Simek --- arch/microblaze/kernel/traps.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c index 5e4570ef515c..75e49202a5ed 100644 --- a/arch/microblaze/kernel/traps.c +++ b/arch/microblaze/kernel/traps.c @@ -95,37 +95,3 @@ void dump_stack(void) show_stack(NULL, NULL); } EXPORT_SYMBOL(dump_stack); - -#ifdef CONFIG_MMU -void __bug(const char *file, int line, void *data) -{ - if (data) - printk(KERN_CRIT "kernel BUG at %s:%d (data = %p)!\n", - file, line, data); - else - printk(KERN_CRIT "kernel BUG at %s:%d!\n", file, line); - - machine_halt(); -} - -int bad_trap(int trap_num, struct pt_regs *regs) -{ - printk(KERN_CRIT - "unimplemented trap %d called at 0x%08lx, pid %d!\n", - trap_num, regs->pc, current->pid); - return -ENOSYS; -} - -int debug_trap(struct pt_regs *regs) -{ - int i; - printk(KERN_CRIT "debug trap\n"); - for (i = 0; i < 32; i++) { - /* printk("r%i:%08X\t",i,regs->gpr[i]); */ - if ((i % 4) == 3) - printk(KERN_CRIT "\n"); - } - printk(KERN_CRIT "pc:%08lX\tmsr:%08lX\n", regs->pc, regs->msr); - return -ENOSYS; -} -#endif -- cgit v1.2.2 From f3ff8212a24f1935b44a3fcdd81c787428f053a6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 21 Apr 2010 14:11:34 -0700 Subject: microblaze: fix divide by zero exception message Fix divide exception message to say "divide by zero". Signed-off-by: Randy Dunlap Cc: Michal Simek Cc: microblaze-uclinux@itee.uq.edu.au Signed-off-by: Michal Simek --- arch/microblaze/kernel/exceptions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c index d9f70f83097f..02cbdfe5aa8d 100644 --- a/arch/microblaze/kernel/exceptions.c +++ b/arch/microblaze/kernel/exceptions.c @@ -121,7 +121,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, } printk(KERN_WARNING "Divide by zero exception " \ "in kernel mode.\n"); - die("Divide by exception", regs, SIGBUS); + die("Divide by zero exception", regs, SIGBUS); break; case MICROBLAZE_FPU_EXCEPTION: pr_debug(KERN_WARNING "FPU exception\n"); -- cgit v1.2.2 From 43f2a6e8b122378b9ad20cd8ea449cdb38f5d829 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 22 Apr 2010 07:28:48 +0200 Subject: microblaze: Remove "cache" optimized copy_page function Current implementation doesn't handle dcache_line_length correctly that's why is better to use generic memcpy. Cache optimized function could be good way howto improve performance but must be based on benchmarking not blind function like this. Signed-off-by: Michal Simek --- arch/microblaze/kernel/asm-offsets.c | 1 + arch/microblaze/kernel/misc.S | 36 ------------------------------------ 2 files changed, 1 insertion(+), 36 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c index 0071260a672c..c1b459c97571 100644 --- a/arch/microblaze/kernel/asm-offsets.c +++ b/arch/microblaze/kernel/asm-offsets.c @@ -16,6 +16,7 @@ #include #include #include +#include int main(int argc, char *argv[]) { diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S index 7cf86498326c..0fb5fc6c1fc2 100644 --- a/arch/microblaze/kernel/misc.S +++ b/arch/microblaze/kernel/misc.S @@ -93,39 +93,3 @@ early_console_reg_tlb_alloc: nop .size early_console_reg_tlb_alloc, . - early_console_reg_tlb_alloc - -/* - * Copy a whole page (4096 bytes). - */ -#define COPY_16_BYTES \ - lwi r7, r6, 0; \ - lwi r8, r6, 4; \ - lwi r9, r6, 8; \ - lwi r10, r6, 12; \ - swi r7, r5, 0; \ - swi r8, r5, 4; \ - swi r9, r5, 8; \ - swi r10, r5, 12 - - -/* FIXME DCACHE_LINE_BYTES (CONFIG_XILINX_MICROBLAZE0_DCACHE_LINE_LEN * 4)*/ -#define DCACHE_LINE_BYTES (4 * 4) - -.globl copy_page; -.type copy_page, @function -.align 4; -copy_page: - ori r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1 -_copy_page_loop: - COPY_16_BYTES -#if DCACHE_LINE_BYTES >= 32 - COPY_16_BYTES -#endif - addik r6, r6, DCACHE_LINE_BYTES - addik r5, r5, DCACHE_LINE_BYTES - bneid r11, _copy_page_loop - addik r11, r11, -1 - rtsd r15, 8 - nop - - .size copy_page, . - copy_page -- cgit v1.2.2 From f1525765fb9c432f5dc5d0d18102fbe9980a14ae Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Sat, 10 Apr 2010 17:34:06 +0200 Subject: microblaze: Fix consistent code This patch fix consistent code which had problems with consistent_free function. I am not sure if we need to call flush_tlb_all after it but it keeps tlbs synced. I added noMMU and MMU version together. Uncached shadow feature is not tested. Signed-off-by: Michal Simek --- arch/microblaze/kernel/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index ce72dd4967cf..9dcd90b5df55 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -74,7 +74,7 @@ static void dma_direct_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { #ifdef NOT_COHERENT_CACHE - consistent_free(vaddr); + consistent_free(size, vaddr); #else free_pages((unsigned long)vaddr, get_order(size)); #endif -- cgit v1.2.2 From c17e1a1cedb723d48d4822cae1af1c010b608b5c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 23 Apr 2010 11:38:43 +0200 Subject: microblaze: Fix typo fault in cache code Copy & paste error. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index f04d8a86dead..19dae71dbaaf 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -393,7 +393,7 @@ static void __invalidate_dcache_range_wb(unsigned long start, #ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear); #else - for (i = start; i < end; i += cpuinfo.icache_line_length) + for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc.clear %0, r0;" \ : : "r" (i)); #endif @@ -413,7 +413,7 @@ static void __invalidate_dcache_range_nomsr_wt(unsigned long start, #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); #else - for (i = start; i < end; i += cpuinfo.icache_line_length) + for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif @@ -437,7 +437,7 @@ static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); #else - for (i = start; i < end; i += cpuinfo.icache_line_length) + for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif @@ -465,7 +465,7 @@ static void __invalidate_dcache_range_nomsr_irq(unsigned long start, #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); #else - for (i = start; i < end; i += cpuinfo.icache_line_length) + for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif @@ -504,7 +504,7 @@ static void __flush_dcache_range_wb(unsigned long start, unsigned long end) #ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush); #else - for (i = start; i < end; i += cpuinfo.icache_line_length) + for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc.flush %0, r0;" \ : : "r" (i)); #endif -- cgit v1.2.2 From 77543cebab7387eab7d482e90018a64d6f2ced1e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 26 Apr 2010 13:53:04 +0200 Subject: microblaze: cpuinfo shows cache line length Show cache line length in /proc/cpuinfo. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/mb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c index 0c912b2a8e03..4216eb1eaa32 100644 --- a/arch/microblaze/kernel/cpu/mb.c +++ b/arch/microblaze/kernel/cpu/mb.c @@ -98,15 +98,17 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpuinfo.use_icache) count += seq_printf(m, - "Icache:\t\t%ukB\n", - cpuinfo.icache_size >> 10); + "Icache:\t\t%ukB\tline length:\t%dB\n", + cpuinfo.icache_size >> 10, + cpuinfo.icache_line_length); else count += seq_printf(m, "Icache:\t\tno\n"); if (cpuinfo.use_dcache) { count += seq_printf(m, - "Dcache:\t\t%ukB\n", - cpuinfo.dcache_size >> 10); + "Dcache:\t\t%ukB\tline length:\t%dB\n", + cpuinfo.dcache_size >> 10, + cpuinfo.dcache_line_length); if (cpuinfo.dcache_wb) count += seq_printf(m, "\t\twrite-back\n"); else -- cgit v1.2.2 From 3274c5707c22221574b396d140d0db3480a2027a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 26 Apr 2010 08:54:13 +0200 Subject: microblaze: Optimize CACHE_LOOP_LIMITS and CACHE_RANGE_LOOP macros 1. Remove CACHE_ALL_LOOP2 macro because it is identical to CACHE_ALL_LOOP 2. Change BUG_ON to WARN_ON 3. Remove end aligned from CACHE_LOOP_LIMITS. C implementation do not need aligned end address and ASM code do aligned in their macros 4. ASM optimized CACHE_RANGE_LOOP_1/2 macros needs to get aligned end address. Because end address is compound from start + size, end address is the first address which is exclude. Here is the corresponding code which describe it. + int align = ~(line_length - 1); + end = ((end & align) == end) ? end - line_length : end & align; a) end is aligned: it is necessary to subtruct line length because we don't want to work with next cacheline b) end address is not aligned: Just align it to be ready for ASM code. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 62 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 19dae71dbaaf..21c3a92394de 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -96,13 +96,16 @@ static inline void __disable_dcache_nomsr(void) } -/* Helper macro for computing the limits of cache range loops */ +/* Helper macro for computing the limits of cache range loops + * + * End address can be unaligned which is OK for C implementation. + * ASM implementation align it in ASM macros + */ #define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \ do { \ int align = ~(cache_line_length - 1); \ end = min(start + cache_size, end); \ start &= align; \ - end = ((end & align) + cache_line_length); \ } while (0); /* @@ -111,9 +114,9 @@ do { \ */ #define CACHE_ALL_LOOP(cache_size, line_length, op) \ do { \ - unsigned int len = cache_size; \ + unsigned int len = cache_size - line_length; \ int step = -line_length; \ - BUG_ON(step >= 0); \ + WARN_ON(step >= 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, r0; \ bgtid %0, 1b; \ @@ -122,26 +125,21 @@ do { \ : "memory"); \ } while (0); - -#define CACHE_ALL_LOOP2(cache_size, line_length, op) \ -do { \ - unsigned int len = cache_size; \ - int step = -line_length; \ - BUG_ON(step >= 0); \ - \ - __asm__ __volatile__ (" 1: " #op " r0, %0; \ - bgtid %0, 1b; \ - addk %0, %0, %1; \ - " : : "r" (len), "r" (step) \ - : "memory"); \ -} while (0); - -/* for wdc.flush/clear */ +/* Used for wdc.flush/clear which can use rB for offset which is not possible + * to use for simple wdc or wic. + * + * start address is cache aligned + * end address is not aligned, if end is aligned then I have to substract + * cacheline length because I can't flush/invalidate the next cacheline. + * If is not, I align it because I will flush/invalidate whole line. + */ #define CACHE_RANGE_LOOP_2(start, end, line_length, op) \ do { \ int step = -line_length; \ + int align = ~(line_length - 1); \ + end = ((end & align) == end) ? end - line_length : end & align; \ int count = end - start; \ - BUG_ON(count <= 0); \ + WARN_ON(count < 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, %1; \ bgtid %1, 1b; \ @@ -154,7 +152,9 @@ do { \ #define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ do { \ int volatile temp; \ - BUG_ON(end - start <= 0); \ + int align = ~(line_length - 1); \ + end = ((end & align) == end) ? end - line_length : end & align; \ + WARN_ON(end - start < 0); \ \ __asm__ __volatile__ (" 1: " #op " %1, r0; \ cmpu %0, %1, %2; \ @@ -360,8 +360,12 @@ static void __invalidate_dcache_all_noirq_wt(void) #endif } -/* FIXME this is weird - should be only wdc but not work - * MS: I am getting bus errors and other weird things */ +/* FIXME It is blindly invalidation as is expected + * but can't be called on noMMU in microblaze_cache_init below + * + * MS: noMMU kernel won't boot if simple wdc is used + * The reason should be that there are discared data which kernel needs + */ static void __invalidate_dcache_all_wb(void) { #ifndef ASM_LOOP @@ -369,12 +373,12 @@ static void __invalidate_dcache_all_wb(void) #endif pr_debug("%s\n", __func__); #ifdef ASM_LOOP - CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, - wdc.clear) + CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, + wdc) #else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) - __asm__ __volatile__ ("wdc.clear %0, r0;" \ + __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif } @@ -650,7 +654,11 @@ void microblaze_cache_init(void) } } } - invalidate_dcache(); +/* FIXME Invalidation is done in U-BOOT + * WT cache: Data is already written to main memory + * WB cache: Discard data on noMMU which caused that kernel doesn't boot + */ + /* invalidate_dcache(); */ enable_dcache(); invalidate_icache(); -- cgit v1.2.2 From 0d5961b7f612f8f54fd6fbe1942cdfb141cddfb9 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Tue, 27 Apr 2010 13:00:23 -0500 Subject: microblaze: re-enable interrupts before calling schedule schedule() should not be called with interrupts disabled. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/entry-nommu.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 391d6197fc3b..8cc18cd2cce6 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -476,6 +476,8 @@ ENTRY(ret_from_fork) nop work_pending: + enable_irq + andi r11, r19, _TIF_NEED_RESCHED beqi r11, 1f bralid r15, schedule -- cgit v1.2.2 From e1733d2c397476c245a681ba0b54c88858b7a0be Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Tue, 27 Apr 2010 13:00:35 -0500 Subject: microblaze: export assembly functions used by modules Modules that use copy_{to,from}_user(), memcpy(), and memset() fail to build in certain circumstances. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek --- arch/microblaze/kernel/microblaze_ksyms.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index bc4dcb7d3861..ecfb852cd1c5 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -52,3 +52,13 @@ EXPORT_SYMBOL_GPL(_ebss); extern void _mcount(void); EXPORT_SYMBOL(_mcount); #endif + +/* + * Assembly functions that may be used (directly or indirectly) by modules + */ +EXPORT_SYMBOL(__copy_tofrom_user); + +#ifdef CONFIG_OPT_LIB_ASM +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +#endif -- cgit v1.2.2 From ddfbc935eae68294834dc29998f93147a5422a0d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 May 2010 10:55:47 +0200 Subject: microblaze: Remove compilation warnings in cache macro CC arch/microblaze/kernel/cpu/cache.o arch/microblaze/kernel/cpu/cache.c: In function '__invalidate_dcache_range_wb': arch/microblaze/kernel/cpu/cache.c:398: warning: ISO C90 forbids mixed declarations and code arch/microblaze/kernel/cpu/cache.c: In function '__flush_dcache_range_wb': arch/microblaze/kernel/cpu/cache.c:509: warning: ISO C90 forbids mixed declara Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 21c3a92394de..109876e8d643 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -137,8 +137,9 @@ do { \ do { \ int step = -line_length; \ int align = ~(line_length - 1); \ + int count; \ end = ((end & align) == end) ? end - line_length : end & align; \ - int count = end - start; \ + count = end - start; \ WARN_ON(count < 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, %1; \ -- cgit v1.2.2 From ee4bcdf1d248c4ebe5f73e11631c3bd3f76d777b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 May 2010 12:11:42 +0200 Subject: microblaze: export assembly functions used by modules Export __strncpy_user, memory_size, ioremap_bot for modules. Signed-off-by: Michal Simek --- arch/microblaze/kernel/microblaze_ksyms.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index ecfb852cd1c5..ff85f7718035 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -57,6 +57,7 @@ EXPORT_SYMBOL(_mcount); * Assembly functions that may be used (directly or indirectly) by modules */ EXPORT_SYMBOL(__copy_tofrom_user); +EXPORT_SYMBOL(__strncpy_user); #ifdef CONFIG_OPT_LIB_ASM EXPORT_SYMBOL(memcpy); -- cgit v1.2.2 From a5e48b88da225580394f825ffe67e444b050074b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 14 May 2010 07:40:46 +0200 Subject: microblaze: Fix module loading on system with WB cache There is necessary to flush whole dcache. Icache work should be done in kernel/module.c. Signed-off-by: Michal Simek --- arch/microblaze/kernel/module.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/microblaze/kernel') diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c index cbecf110dc30..0e73f6606547 100644 --- a/arch/microblaze/kernel/module.c +++ b/arch/microblaze/kernel/module.c @@ -16,6 +16,7 @@ #include #include +#include void *module_alloc(unsigned long size) { @@ -151,6 +152,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *module) { + flush_dcache(); return 0; } -- cgit v1.2.2