diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 14 | ||||
-rw-r--r-- | lib/Makefile | 3 | ||||
-rw-r--r-- | lib/cpumask.c | 16 | ||||
-rw-r--r-- | lib/errno.c | 7 | ||||
-rw-r--r-- | lib/genalloc.c | 63 | ||||
-rw-r--r-- | lib/ioremap.c | 92 | ||||
-rw-r--r-- | lib/list_debug.c | 3 | ||||
-rw-r--r-- | lib/rbtree.c | 6 | ||||
-rw-r--r-- | lib/sort.c | 10 |
9 files changed, 183 insertions, 31 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f9ae75cc014..756a908c441 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -384,3 +384,17 @@ config RCU_TORTURE_TEST at boot time (you probably don't). Say M if you want the RCU torture tests to build as a module. Say N if you are unsure. + +config LKDTM + tristate "Linux Kernel Dump Test Tool Module" + depends on KPROBES + default n + help + This module enables testing of the different dumping mechanisms by + inducing system failures at predefined crash points. + If you don't need it: say N + Choose M here to compile this code as a module. The module will be + called lkdtm. + + Documentation on how to use the module can be found in + drivers/misc/lkdtm.c diff --git a/lib/Makefile b/lib/Makefile index 402762fead7..b0361756e22 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,11 +2,12 @@ # Makefile for some libs needed in the kernel. # -lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ +lib-y := ctype.o string.o vsprintf.o cmdline.o \ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \ idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \ sha1.o +lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o kobject_uevent.o klist.o diff --git a/lib/cpumask.c b/lib/cpumask.c index 3a67dc5ada7..7a2a73f88d5 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -43,3 +43,19 @@ int __any_online_cpu(const cpumask_t *mask) return cpu; } EXPORT_SYMBOL(__any_online_cpu); + +#if MAX_NUMNODES > 1 +/* + * Find the highest possible node id. + */ +int highest_possible_node_id(void) +{ + unsigned int node; + unsigned int highest = 0; + + for_each_node_mask(node, node_possible_map) + highest = node; + return highest; +} +EXPORT_SYMBOL(highest_possible_node_id); +#endif diff --git a/lib/errno.c b/lib/errno.c deleted file mode 100644 index 41cb9d76c05..00000000000 --- a/lib/errno.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * linux/lib/errno.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -int errno; diff --git a/lib/genalloc.c b/lib/genalloc.c index 71338b48e88..75ae68ce03e 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -14,11 +14,13 @@ #include <linux/genalloc.h> -/* - * Create a new special memory pool. - * +/** + * gen_pool_create - create a new special memory pool * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents * @nid: node id of the node the pool structure should be allocated on, or -1 + * + * Create a new special memory pool that can be used to manage special purpose + * memory not managed by the regular kmalloc/kfree interface. */ struct gen_pool *gen_pool_create(int min_alloc_order, int nid) { @@ -34,15 +36,15 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid) } EXPORT_SYMBOL(gen_pool_create); - -/* - * Add a new chunk of memory to the specified pool. - * +/** + * gen_pool_add - add a new chunk of special memory to the pool * @pool: pool to add new memory chunk to * @addr: starting address of memory chunk to add to pool * @size: size in bytes of the memory chunk to add to pool * @nid: node id of the node the chunk structure and bitmap should be * allocated on, or -1 + * + * Add a new chunk of special memory to the specified pool. */ int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, int nid) @@ -69,13 +71,44 @@ int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, } EXPORT_SYMBOL(gen_pool_add); - -/* - * Allocate the requested number of bytes from the specified pool. - * Uses a first-fit algorithm. +/** + * gen_pool_destroy - destroy a special memory pool + * @pool: pool to destroy * + * Destroy the specified special memory pool. Verifies that there are no + * outstanding allocations. + */ +void gen_pool_destroy(struct gen_pool *pool) +{ + struct list_head *_chunk, *_next_chunk; + struct gen_pool_chunk *chunk; + int order = pool->min_alloc_order; + int bit, end_bit; + + + write_lock(&pool->lock); + list_for_each_safe(_chunk, _next_chunk, &pool->chunks) { + chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); + list_del(&chunk->next_chunk); + + end_bit = (chunk->end_addr - chunk->start_addr) >> order; + bit = find_next_bit(chunk->bits, end_bit, 0); + BUG_ON(bit < end_bit); + + kfree(chunk); + } + kfree(pool); + return; +} +EXPORT_SYMBOL(gen_pool_destroy); + +/** + * gen_pool_alloc - allocate special memory from the pool * @pool: pool to allocate from * @size: number of bytes to allocate from the pool + * + * Allocate the requested number of bytes from the specified pool. + * Uses a first-fit algorithm. */ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) { @@ -127,13 +160,13 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) } EXPORT_SYMBOL(gen_pool_alloc); - -/* - * Free the specified memory back to the specified pool. - * +/** + * gen_pool_free - free allocated special memory back to the pool * @pool: pool to free to * @addr: starting address of memory to free back to pool * @size: size in bytes of memory to free + * + * Free previously allocated special memory back to the specified pool. */ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) { diff --git a/lib/ioremap.c b/lib/ioremap.c new file mode 100644 index 00000000000..99fa277f9f7 --- /dev/null +++ b/lib/ioremap.c @@ -0,0 +1,92 @@ +/* + * Re-map IO memory to kernel address space so that we can access it. + * This is needed for high PCI addresses that aren't mapped in the + * 640k-1MB IO memory area on PC's + * + * (C) Copyright 1995 1996 Linus Torvalds + */ +#include <linux/io.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> + +#include <asm/cacheflush.h> +#include <asm/pgtable.h> + +static int ioremap_pte_range(pmd_t *pmd, unsigned long addr, + unsigned long end, unsigned long phys_addr, pgprot_t prot) +{ + pte_t *pte; + unsigned long pfn; + + pfn = phys_addr >> PAGE_SHIFT; + pte = pte_alloc_kernel(pmd, addr); + if (!pte) + return -ENOMEM; + do { + BUG_ON(!pte_none(*pte)); + set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot)); + pfn++; + } while (pte++, addr += PAGE_SIZE, addr != end); + return 0; +} + +static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr, + unsigned long end, unsigned long phys_addr, pgprot_t prot) +{ + pmd_t *pmd; + unsigned long next; + + phys_addr -= addr; + pmd = pmd_alloc(&init_mm, pud, addr); + if (!pmd) + return -ENOMEM; + do { + next = pmd_addr_end(addr, end); + if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot)) + return -ENOMEM; + } while (pmd++, addr = next, addr != end); + return 0; +} + +static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr, + unsigned long end, unsigned long phys_addr, pgprot_t prot) +{ + pud_t *pud; + unsigned long next; + + phys_addr -= addr; + pud = pud_alloc(&init_mm, pgd, addr); + if (!pud) + return -ENOMEM; + do { + next = pud_addr_end(addr, end); + if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot)) + return -ENOMEM; + } while (pud++, addr = next, addr != end); + return 0; +} + +int ioremap_page_range(unsigned long addr, + unsigned long end, unsigned long phys_addr, pgprot_t prot) +{ + pgd_t *pgd; + unsigned long start; + unsigned long next; + int err; + + BUG_ON(addr >= end); + + start = addr; + phys_addr -= addr; + pgd = pgd_offset_k(addr); + do { + next = pgd_addr_end(addr, end); + err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot); + if (err) + break; + } while (pgd++, addr = next, addr != end); + + flush_cache_vmap(start, end); + + return err; +} diff --git a/lib/list_debug.c b/lib/list_debug.c index e80d27c9789..7ba9d823d38 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -59,9 +59,6 @@ EXPORT_SYMBOL(list_add); */ void list_del(struct list_head *entry) { - BUG_ON(entry->prev->next != entry); - BUG_ON(entry->next->prev != entry); - if (unlikely(entry->prev->next != entry)) { printk(KERN_ERR "list_del corruption. prev->next should be %p, " "but was %p\n", entry, entry->prev->next); diff --git a/lib/rbtree.c b/lib/rbtree.c index 1e55ba1c2ed..48499c2d88c 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -322,6 +322,9 @@ struct rb_node *rb_next(struct rb_node *node) { struct rb_node *parent; + if (rb_parent(node) == node) + return NULL; + /* If we have a right-hand child, go down and then left as far as we can. */ if (node->rb_right) { @@ -348,6 +351,9 @@ struct rb_node *rb_prev(struct rb_node *node) { struct rb_node *parent; + if (rb_parent(node) == node) + return NULL; + /* If we have a left-hand child, go down and then right as far as we can. */ if (node->rb_left) { diff --git a/lib/sort.c b/lib/sort.c index 5f3b51ffa1d..488788b341c 100644 --- a/lib/sort.c +++ b/lib/sort.c @@ -49,15 +49,15 @@ void sort(void *base, size_t num, size_t size, void (*swap)(void *, void *, int size)) { /* pre-scale counters for performance */ - int i = (num/2) * size, n = num * size, c, r; + int i = (num/2 - 1) * size, n = num * size, c, r; if (!swap) swap = (size == 4 ? u32_swap : generic_swap); /* heapify */ for ( ; i >= 0; i -= size) { - for (r = i; r * 2 < n; r = c) { - c = r * 2; + for (r = i; r * 2 + size < n; r = c) { + c = r * 2 + size; if (c < n - size && cmp(base + c, base + c + size) < 0) c += size; if (cmp(base + r, base + c) >= 0) @@ -69,8 +69,8 @@ void sort(void *base, size_t num, size_t size, /* sort */ for (i = n - size; i >= 0; i -= size) { swap(base, base + i, size); - for (r = 0; r * 2 < i; r = c) { - c = r * 2; + for (r = 0; r * 2 + size < i; r = c) { + c = r * 2 + size; if (c < i - size && cmp(base + c, base + c + size) < 0) c += size; if (cmp(base + r, base + c) >= 0) |