Commit 088af9a6e05d51e7c3dc85d45d8b7a52c3ee08d7
Committed by
Rusty Russell
1 parent
d1e99d7ae4
Exists in
master
and in
20 other branches
module: fix module loading failure of large kernel modules for parisc
When creating the final layout of a kernel module in memory, allow the module loader to reserve some additional memory in front of a given section. This is currently only needed for the parisc port which needs to put the stub entries there to fulfill the 17/22bit PCREL relocations with large kernel modules like xfs. Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (renamed fn)
Showing 2 changed files with 16 additions and 3 deletions Side-by-side Diff
include/linux/moduleloader.h
... | ... | @@ -13,6 +13,9 @@ |
13 | 13 | char *secstrings, |
14 | 14 | struct module *mod); |
15 | 15 | |
16 | +/* Additional bytes needed by arch in front of individual sections */ | |
17 | +unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section); | |
18 | + | |
16 | 19 | /* Allocator used for allocating struct module, core sections and init |
17 | 20 | sections. Returns NULL on failure. */ |
18 | 21 | void *module_alloc(unsigned long size); |
kernel/module.c
... | ... | @@ -1578,11 +1578,21 @@ |
1578 | 1578 | return ret; |
1579 | 1579 | } |
1580 | 1580 | |
1581 | +/* Additional bytes needed by arch in front of individual sections */ | |
1582 | +unsigned int __weak arch_mod_section_prepend(struct module *mod, | |
1583 | + unsigned int section) | |
1584 | +{ | |
1585 | + /* default implementation just returns zero */ | |
1586 | + return 0; | |
1587 | +} | |
1588 | + | |
1581 | 1589 | /* Update size with this section: return offset. */ |
1582 | -static long get_offset(unsigned int *size, Elf_Shdr *sechdr) | |
1590 | +static long get_offset(struct module *mod, unsigned int *size, | |
1591 | + Elf_Shdr *sechdr, unsigned int section) | |
1583 | 1592 | { |
1584 | 1593 | long ret; |
1585 | 1594 | |
1595 | + *size += arch_mod_section_prepend(mod, section); | |
1586 | 1596 | ret = ALIGN(*size, sechdr->sh_addralign ?: 1); |
1587 | 1597 | *size = ret + sechdr->sh_size; |
1588 | 1598 | return ret; |
... | ... | @@ -1622,7 +1632,7 @@ |
1622 | 1632 | || strncmp(secstrings + s->sh_name, |
1623 | 1633 | ".init", 5) == 0) |
1624 | 1634 | continue; |
1625 | - s->sh_entsize = get_offset(&mod->core_size, s); | |
1635 | + s->sh_entsize = get_offset(mod, &mod->core_size, s, i); | |
1626 | 1636 | DEBUGP("\t%s\n", secstrings + s->sh_name); |
1627 | 1637 | } |
1628 | 1638 | if (m == 0) |
... | ... | @@ -1640,7 +1650,7 @@ |
1640 | 1650 | || strncmp(secstrings + s->sh_name, |
1641 | 1651 | ".init", 5) != 0) |
1642 | 1652 | continue; |
1643 | - s->sh_entsize = (get_offset(&mod->init_size, s) | |
1653 | + s->sh_entsize = (get_offset(mod, &mod->init_size, s, i) | |
1644 | 1654 | | INIT_OFFSET_MASK); |
1645 | 1655 | DEBUGP("\t%s\n", secstrings + s->sh_name); |
1646 | 1656 | } |