diff options
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r-- | mm/vmalloc.c | 223 |
1 files changed, 189 insertions, 34 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 204b8243d8ab..69511e663234 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/rcupdate.h> | 25 | #include <linux/rcupdate.h> |
26 | #include <linux/pfn.h> | 26 | #include <linux/pfn.h> |
27 | #include <linux/kmemleak.h> | 27 | #include <linux/kmemleak.h> |
28 | 28 | #include <linux/highmem.h> | |
29 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <asm/tlbflush.h> | 31 | #include <asm/tlbflush.h> |
@@ -168,11 +168,9 @@ static int vmap_page_range_noflush(unsigned long start, unsigned long end, | |||
168 | next = pgd_addr_end(addr, end); | 168 | next = pgd_addr_end(addr, end); |
169 | err = vmap_pud_range(pgd, addr, next, prot, pages, &nr); | 169 | err = vmap_pud_range(pgd, addr, next, prot, pages, &nr); |
170 | if (err) | 170 | if (err) |
171 | break; | 171 | return err; |
172 | } while (pgd++, addr = next, addr != end); | 172 | } while (pgd++, addr = next, addr != end); |
173 | 173 | ||
174 | if (unlikely(err)) | ||
175 | return err; | ||
176 | return nr; | 174 | return nr; |
177 | } | 175 | } |
178 | 176 | ||
@@ -186,7 +184,7 @@ static int vmap_page_range(unsigned long start, unsigned long end, | |||
186 | return ret; | 184 | return ret; |
187 | } | 185 | } |
188 | 186 | ||
189 | static inline int is_vmalloc_or_module_addr(const void *x) | 187 | int is_vmalloc_or_module_addr(const void *x) |
190 | { | 188 | { |
191 | /* | 189 | /* |
192 | * ARM, x86-64 and sparc64 put modules in a special place, | 190 | * ARM, x86-64 and sparc64 put modules in a special place, |
@@ -1272,17 +1270,21 @@ struct vm_struct *remove_vm_area(const void *addr) | |||
1272 | if (va && va->flags & VM_VM_AREA) { | 1270 | if (va && va->flags & VM_VM_AREA) { |
1273 | struct vm_struct *vm = va->private; | 1271 | struct vm_struct *vm = va->private; |
1274 | struct vm_struct *tmp, **p; | 1272 | struct vm_struct *tmp, **p; |
1275 | 1273 | /* | |
1276 | vmap_debug_free_range(va->va_start, va->va_end); | 1274 | * remove from list and disallow access to this vm_struct |
1277 | free_unmap_vmap_area(va); | 1275 | * before unmap. (address range confliction is maintained by |
1278 | vm->size -= PAGE_SIZE; | 1276 | * vmap.) |
1279 | 1277 | */ | |
1280 | write_lock(&vmlist_lock); | 1278 | write_lock(&vmlist_lock); |
1281 | for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next) | 1279 | for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next) |
1282 | ; | 1280 | ; |
1283 | *p = tmp->next; | 1281 | *p = tmp->next; |
1284 | write_unlock(&vmlist_lock); | 1282 | write_unlock(&vmlist_lock); |
1285 | 1283 | ||
1284 | vmap_debug_free_range(va->va_start, va->va_end); | ||
1285 | free_unmap_vmap_area(va); | ||
1286 | vm->size -= PAGE_SIZE; | ||
1287 | |||
1286 | return vm; | 1288 | return vm; |
1287 | } | 1289 | } |
1288 | return NULL; | 1290 | return NULL; |
@@ -1384,7 +1386,7 @@ void *vmap(struct page **pages, unsigned int count, | |||
1384 | 1386 | ||
1385 | might_sleep(); | 1387 | might_sleep(); |
1386 | 1388 | ||
1387 | if (count > num_physpages) | 1389 | if (count > totalram_pages) |
1388 | return NULL; | 1390 | return NULL; |
1389 | 1391 | ||
1390 | area = get_vm_area_caller((count << PAGE_SHIFT), flags, | 1392 | area = get_vm_area_caller((count << PAGE_SHIFT), flags, |
@@ -1491,7 +1493,7 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot, | |||
1491 | unsigned long real_size = size; | 1493 | unsigned long real_size = size; |
1492 | 1494 | ||
1493 | size = PAGE_ALIGN(size); | 1495 | size = PAGE_ALIGN(size); |
1494 | if (!size || (size >> PAGE_SHIFT) > num_physpages) | 1496 | if (!size || (size >> PAGE_SHIFT) > totalram_pages) |
1495 | return NULL; | 1497 | return NULL; |
1496 | 1498 | ||
1497 | area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END, | 1499 | area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END, |
@@ -1641,10 +1643,120 @@ void *vmalloc_32_user(unsigned long size) | |||
1641 | } | 1643 | } |
1642 | EXPORT_SYMBOL(vmalloc_32_user); | 1644 | EXPORT_SYMBOL(vmalloc_32_user); |
1643 | 1645 | ||
1646 | /* | ||
1647 | * small helper routine , copy contents to buf from addr. | ||
1648 | * If the page is not present, fill zero. | ||
1649 | */ | ||
1650 | |||
1651 | static int aligned_vread(char *buf, char *addr, unsigned long count) | ||
1652 | { | ||
1653 | struct page *p; | ||
1654 | int copied = 0; | ||
1655 | |||
1656 | while (count) { | ||
1657 | unsigned long offset, length; | ||
1658 | |||
1659 | offset = (unsigned long)addr & ~PAGE_MASK; | ||
1660 | length = PAGE_SIZE - offset; | ||
1661 | if (length > count) | ||
1662 | length = count; | ||
1663 | p = vmalloc_to_page(addr); | ||
1664 | /* | ||
1665 | * To do safe access to this _mapped_ area, we need | ||
1666 | * lock. But adding lock here means that we need to add | ||
1667 | * overhead of vmalloc()/vfree() calles for this _debug_ | ||
1668 | * interface, rarely used. Instead of that, we'll use | ||
1669 | * kmap() and get small overhead in this access function. | ||
1670 | */ | ||
1671 | if (p) { | ||
1672 | /* | ||
1673 | * we can expect USER0 is not used (see vread/vwrite's | ||
1674 | * function description) | ||
1675 | */ | ||
1676 | void *map = kmap_atomic(p, KM_USER0); | ||
1677 | memcpy(buf, map + offset, length); | ||
1678 | kunmap_atomic(map, KM_USER0); | ||
1679 | } else | ||
1680 | memset(buf, 0, length); | ||
1681 | |||
1682 | addr += length; | ||
1683 | buf += length; | ||
1684 | copied += length; | ||
1685 | count -= length; | ||
1686 | } | ||
1687 | return copied; | ||
1688 | } | ||
1689 | |||
1690 | static int aligned_vwrite(char *buf, char *addr, unsigned long count) | ||
1691 | { | ||
1692 | struct page *p; | ||
1693 | int copied = 0; | ||
1694 | |||
1695 | while (count) { | ||
1696 | unsigned long offset, length; | ||
1697 | |||
1698 | offset = (unsigned long)addr & ~PAGE_MASK; | ||
1699 | length = PAGE_SIZE - offset; | ||
1700 | if (length > count) | ||
1701 | length = count; | ||
1702 | p = vmalloc_to_page(addr); | ||
1703 | /* | ||
1704 | * To do safe access to this _mapped_ area, we need | ||
1705 | * lock. But adding lock here means that we need to add | ||
1706 | * overhead of vmalloc()/vfree() calles for this _debug_ | ||
1707 | * interface, rarely used. Instead of that, we'll use | ||
1708 | * kmap() and get small overhead in this access function. | ||
1709 | */ | ||
1710 | if (p) { | ||
1711 | /* | ||
1712 | * we can expect USER0 is not used (see vread/vwrite's | ||
1713 | * function description) | ||
1714 | */ | ||
1715 | void *map = kmap_atomic(p, KM_USER0); | ||
1716 | memcpy(map + offset, buf, length); | ||
1717 | kunmap_atomic(map, KM_USER0); | ||
1718 | } | ||
1719 | addr += length; | ||
1720 | buf += length; | ||
1721 | copied += length; | ||
1722 | count -= length; | ||
1723 | } | ||
1724 | return copied; | ||
1725 | } | ||
1726 | |||
1727 | /** | ||
1728 | * vread() - read vmalloc area in a safe way. | ||
1729 | * @buf: buffer for reading data | ||
1730 | * @addr: vm address. | ||
1731 | * @count: number of bytes to be read. | ||
1732 | * | ||
1733 | * Returns # of bytes which addr and buf should be increased. | ||
1734 | * (same number to @count). Returns 0 if [addr...addr+count) doesn't | ||
1735 | * includes any intersect with alive vmalloc area. | ||
1736 | * | ||
1737 | * This function checks that addr is a valid vmalloc'ed area, and | ||
1738 | * copy data from that area to a given buffer. If the given memory range | ||
1739 | * of [addr...addr+count) includes some valid address, data is copied to | ||
1740 | * proper area of @buf. If there are memory holes, they'll be zero-filled. | ||
1741 | * IOREMAP area is treated as memory hole and no copy is done. | ||
1742 | * | ||
1743 | * If [addr...addr+count) doesn't includes any intersects with alive | ||
1744 | * vm_struct area, returns 0. | ||
1745 | * @buf should be kernel's buffer. Because this function uses KM_USER0, | ||
1746 | * the caller should guarantee KM_USER0 is not used. | ||
1747 | * | ||
1748 | * Note: In usual ops, vread() is never necessary because the caller | ||
1749 | * should know vmalloc() area is valid and can use memcpy(). | ||
1750 | * This is for routines which have to access vmalloc area without | ||
1751 | * any informaion, as /dev/kmem. | ||
1752 | * | ||
1753 | */ | ||
1754 | |||
1644 | long vread(char *buf, char *addr, unsigned long count) | 1755 | long vread(char *buf, char *addr, unsigned long count) |
1645 | { | 1756 | { |
1646 | struct vm_struct *tmp; | 1757 | struct vm_struct *tmp; |
1647 | char *vaddr, *buf_start = buf; | 1758 | char *vaddr, *buf_start = buf; |
1759 | unsigned long buflen = count; | ||
1648 | unsigned long n; | 1760 | unsigned long n; |
1649 | 1761 | ||
1650 | /* Don't allow overflow */ | 1762 | /* Don't allow overflow */ |
@@ -1652,7 +1764,7 @@ long vread(char *buf, char *addr, unsigned long count) | |||
1652 | count = -(unsigned long) addr; | 1764 | count = -(unsigned long) addr; |
1653 | 1765 | ||
1654 | read_lock(&vmlist_lock); | 1766 | read_lock(&vmlist_lock); |
1655 | for (tmp = vmlist; tmp; tmp = tmp->next) { | 1767 | for (tmp = vmlist; count && tmp; tmp = tmp->next) { |
1656 | vaddr = (char *) tmp->addr; | 1768 | vaddr = (char *) tmp->addr; |
1657 | if (addr >= vaddr + tmp->size - PAGE_SIZE) | 1769 | if (addr >= vaddr + tmp->size - PAGE_SIZE) |
1658 | continue; | 1770 | continue; |
@@ -1665,32 +1777,72 @@ long vread(char *buf, char *addr, unsigned long count) | |||
1665 | count--; | 1777 | count--; |
1666 | } | 1778 | } |
1667 | n = vaddr + tmp->size - PAGE_SIZE - addr; | 1779 | n = vaddr + tmp->size - PAGE_SIZE - addr; |
1668 | do { | 1780 | if (n > count) |
1669 | if (count == 0) | 1781 | n = count; |
1670 | goto finished; | 1782 | if (!(tmp->flags & VM_IOREMAP)) |
1671 | *buf = *addr; | 1783 | aligned_vread(buf, addr, n); |
1672 | buf++; | 1784 | else /* IOREMAP area is treated as memory hole */ |
1673 | addr++; | 1785 | memset(buf, 0, n); |
1674 | count--; | 1786 | buf += n; |
1675 | } while (--n > 0); | 1787 | addr += n; |
1788 | count -= n; | ||
1676 | } | 1789 | } |
1677 | finished: | 1790 | finished: |
1678 | read_unlock(&vmlist_lock); | 1791 | read_unlock(&vmlist_lock); |
1679 | return buf - buf_start; | 1792 | |
1793 | if (buf == buf_start) | ||
1794 | return 0; | ||
1795 | /* zero-fill memory holes */ | ||
1796 | if (buf != buf_start + buflen) | ||
1797 | memset(buf, 0, buflen - (buf - buf_start)); | ||
1798 | |||
1799 | return buflen; | ||
1680 | } | 1800 | } |
1681 | 1801 | ||
1802 | /** | ||
1803 | * vwrite() - write vmalloc area in a safe way. | ||
1804 | * @buf: buffer for source data | ||
1805 | * @addr: vm address. | ||
1806 | * @count: number of bytes to be read. | ||
1807 | * | ||
1808 | * Returns # of bytes which addr and buf should be incresed. | ||
1809 | * (same number to @count). | ||
1810 | * If [addr...addr+count) doesn't includes any intersect with valid | ||
1811 | * vmalloc area, returns 0. | ||
1812 | * | ||
1813 | * This function checks that addr is a valid vmalloc'ed area, and | ||
1814 | * copy data from a buffer to the given addr. If specified range of | ||
1815 | * [addr...addr+count) includes some valid address, data is copied from | ||
1816 | * proper area of @buf. If there are memory holes, no copy to hole. | ||
1817 | * IOREMAP area is treated as memory hole and no copy is done. | ||
1818 | * | ||
1819 | * If [addr...addr+count) doesn't includes any intersects with alive | ||
1820 | * vm_struct area, returns 0. | ||
1821 | * @buf should be kernel's buffer. Because this function uses KM_USER0, | ||
1822 | * the caller should guarantee KM_USER0 is not used. | ||
1823 | * | ||
1824 | * Note: In usual ops, vwrite() is never necessary because the caller | ||
1825 | * should know vmalloc() area is valid and can use memcpy(). | ||
1826 | * This is for routines which have to access vmalloc area without | ||
1827 | * any informaion, as /dev/kmem. | ||
1828 | * | ||
1829 | * The caller should guarantee KM_USER1 is not used. | ||
1830 | */ | ||
1831 | |||
1682 | long vwrite(char *buf, char *addr, unsigned long count) | 1832 | long vwrite(char *buf, char *addr, unsigned long count) |
1683 | { | 1833 | { |
1684 | struct vm_struct *tmp; | 1834 | struct vm_struct *tmp; |
1685 | char *vaddr, *buf_start = buf; | 1835 | char *vaddr; |
1686 | unsigned long n; | 1836 | unsigned long n, buflen; |
1837 | int copied = 0; | ||
1687 | 1838 | ||
1688 | /* Don't allow overflow */ | 1839 | /* Don't allow overflow */ |
1689 | if ((unsigned long) addr + count < count) | 1840 | if ((unsigned long) addr + count < count) |
1690 | count = -(unsigned long) addr; | 1841 | count = -(unsigned long) addr; |
1842 | buflen = count; | ||
1691 | 1843 | ||
1692 | read_lock(&vmlist_lock); | 1844 | read_lock(&vmlist_lock); |
1693 | for (tmp = vmlist; tmp; tmp = tmp->next) { | 1845 | for (tmp = vmlist; count && tmp; tmp = tmp->next) { |
1694 | vaddr = (char *) tmp->addr; | 1846 | vaddr = (char *) tmp->addr; |
1695 | if (addr >= vaddr + tmp->size - PAGE_SIZE) | 1847 | if (addr >= vaddr + tmp->size - PAGE_SIZE) |
1696 | continue; | 1848 | continue; |
@@ -1702,18 +1854,21 @@ long vwrite(char *buf, char *addr, unsigned long count) | |||
1702 | count--; | 1854 | count--; |
1703 | } | 1855 | } |
1704 | n = vaddr + tmp->size - PAGE_SIZE - addr; | 1856 | n = vaddr + tmp->size - PAGE_SIZE - addr; |
1705 | do { | 1857 | if (n > count) |
1706 | if (count == 0) | 1858 | n = count; |
1707 | goto finished; | 1859 | if (!(tmp->flags & VM_IOREMAP)) { |
1708 | *addr = *buf; | 1860 | aligned_vwrite(buf, addr, n); |
1709 | buf++; | 1861 | copied++; |
1710 | addr++; | 1862 | } |
1711 | count--; | 1863 | buf += n; |
1712 | } while (--n > 0); | 1864 | addr += n; |
1865 | count -= n; | ||
1713 | } | 1866 | } |
1714 | finished: | 1867 | finished: |
1715 | read_unlock(&vmlist_lock); | 1868 | read_unlock(&vmlist_lock); |
1716 | return buf - buf_start; | 1869 | if (!copied) |
1870 | return 0; | ||
1871 | return buflen; | ||
1717 | } | 1872 | } |
1718 | 1873 | ||
1719 | /** | 1874 | /** |