Commit 656be92f authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle
Browse files

[MIPS] Load modules to CKSEG0 if CONFIG_BUILD_ELF64=n



This is a patch to load 64-bit modules to CKSEG0 so that can be
compiled with -msym32 option.  This makes each module ~10% smaller.

* introduce MODULE_START and MODULE_END
* custom module_alloc()
* PGD for modules
* change XTLB refill handler synthesizer
* enable -msym32 for modules again
  (revert ca78b1a5c6a6e70e052d3ea253828e49b5d07c8a)

New XTLB refill handler looks like this:

80000080 dmfc0   k0,C0_BADVADDR
80000084 bltz    k0,800000e4			# goto l_module_alloc
80000088 lui     k1,0x8046			# %high(pgd_current)
8000008c ld      k1,24600(k1)			# %low(pgd_current)
80000090 dsrl    k0,k0,0x1b			# l_vmalloc_done:
80000094 andi    k0,k0,0x1ff8
80000098 daddu   k1,k1,k0
8000009c dmfc0   k0,C0_BADVADDR
800000a0 ld      k1,0(k1)
800000a4 dsrl    k0,k0,0x12
800000a8 andi    k0,k0,0xff8
800000ac daddu   k1,k1,k0
800000b0 dmfc0   k0,C0_XCONTEXT
800000b4 ld      k1,0(k1)
800000b8 andi    k0,k0,0xff0
800000bc daddu   k1,k1,k0
800000c0 ld      k0,0(k1)
800000c4 ld      k1,8(k1)
800000c8 dsrl    k0,k0,0x6
800000cc mtc0    k0,C0_ENTRYLO0
800000d0 dsrl    k1,k1,0x6
800000d4 mtc0    k1,C0_ENTRYL01
800000d8 nop
800000dc tlbwr
800000e0 eret
800000e4 dsll    k1,k0,0x2			# l_module_alloc:
800000e8 bgez    k1,80000008			# goto l_vmalloc
800000ec lui     k1,0xc000
800000f0 dsubu   k0,k0,k1
800000f4 lui     k1,0x8046			# %high(module_pg_dir)
800000f8 beq     zero,zero,80000000
800000fc nop
80000000 beq     zero,zero,80000090		# goto l_vmalloc_done
80000004 daddiu  k1,k1,0x4000
80000008 dsll32  k1,k1,0x0			# l_vmalloc:
8000000c dsubu   k0,k0,k1
80000010 beq     zero,zero,80000090		# goto l_vmalloc_done
80000014 lui     k1,0x8046			# %high(swapper_pg_dir)

Signed-off-by: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 56ae5833
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -63,9 +63,7 @@ cflags-y += -mabi=64
ifdef CONFIG_BUILD_ELF64
cflags-y		+= $(call cc-option,-mno-explicit-relocs)
else
# -msym32 can not be used for modules since they are loaded into XKSEG
CFLAGS_MODULE		+= $(call cc-option,-mno-explicit-relocs)
CFLAGS_KERNEL		+= $(call cc-option,-msym32)
cflags-y		+= $(call cc-option,-msym32)
endif
endif

+3 −0
Original line number Diff line number Diff line
@@ -250,6 +250,9 @@ NESTED(smp_bootstrap, 16, sp)
	 */
	page	swapper_pg_dir, _PGD_ORDER
#ifdef CONFIG_64BIT
#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64)
	page	module_pg_dir, _PGD_ORDER
#endif
	page	invalid_pmd_table, _PMD_ORDER
#endif
	page	invalid_pte_table, _PTE_ORDER
+15 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/pgtable.h>	/* MODULE_START */

struct mips_hi16 {
	struct mips_hi16 *next;
@@ -43,9 +44,23 @@ static DEFINE_SPINLOCK(dbe_lock);

void *module_alloc(unsigned long size)
{
#ifdef MODULE_START
	struct vm_struct *area;

	size = PAGE_ALIGN(size);
	if (!size)
		return NULL;

	area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
	if (!area)
		return NULL;

	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
#else
	if (size == 0)
		return NULL;
	return vmalloc(size);
#endif
}

/* Free memory returned from module_alloc */
+4 −0
Original line number Diff line number Diff line
@@ -60,6 +60,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
	 */
	if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END))
		goto vmalloc_fault;
#ifdef MODULE_START
	if (unlikely(address >= MODULE_START && address < MODULE_END))
		goto vmalloc_fault;
#endif

	/*
	 * If we're in an interrupt or have no user
+3 −0
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@ void __init pagetable_init(void)

	/* Initialize the entire pgd.  */
	pgd_init((unsigned long)swapper_pg_dir);
#ifdef MODULE_START
	pgd_init((unsigned long)module_pg_dir);
#endif
	pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);

	pgd_base = swapper_pg_dir;
Loading