arch/loongarch/kernel/relocate.c

Source file repositories/reference/linux-study-clean/arch/loongarch/kernel/relocate.c

File Facts

System
Linux kernel
Corpus path
arch/loongarch/kernel/relocate.c
Extension
.c
Size
9814 bytes
Lines
362
Domain
Architecture Layer
Bucket
arch/loongarch
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

#include <linux/start_kernel.h>
#include <asm/bootinfo.h>
#include <asm/early_ioremap.h>
#include <asm/inst.h>
#include <asm/io.h>
#include <asm/sections.h>
#include <asm/setup.h>

#define RELOCATED(x) ((void *)((long)x + reloc_offset))
#define RELOCATED_KASLR(x) ((void *)((long)x + random_offset))

static unsigned long reloc_offset;

static inline void __init relocate_relative(void)
{
	Elf64_Rela *rela, *rela_end;
	rela = (Elf64_Rela *)&__rela_dyn_begin;
	rela_end = (Elf64_Rela *)&__rela_dyn_end;

	for ( ; rela < rela_end; rela++) {
		Elf64_Addr addr = rela->r_offset;
		Elf64_Addr relocated_addr = rela->r_addend;

		if (rela->r_info != R_LARCH_RELATIVE)
			continue;

		relocated_addr = (Elf64_Addr)RELOCATED(relocated_addr);
		*(Elf64_Addr *)RELOCATED(addr) = relocated_addr;
	}

#ifdef CONFIG_RELR
	u64 *addr = NULL;
	u64 *relr = (u64 *)&__relr_dyn_begin;
	u64 *relr_end = (u64 *)&__relr_dyn_end;

	for ( ; relr < relr_end; relr++) {
		if ((*relr & 1) == 0) {
			addr = (u64 *)(*relr + reloc_offset);
			*addr++ += reloc_offset;
		} else {
			for (u64 *p = addr, r = *relr >> 1; r; p++, r >>= 1)
				if (r & 1)
					*p += reloc_offset;
			addr += 63;
		}
	}
#endif
}

static inline void __init relocate_absolute(long random_offset)
{
	void *begin, *end;
	struct rela_la_abs *p;

	begin = RELOCATED_KASLR(&__la_abs_begin);
	end   = RELOCATED_KASLR(&__la_abs_end);

	for (p = begin; (void *)p < end; p++) {
		long v = p->symvalue;
		uint32_t lu12iw, ori;
#ifdef CONFIG_64BIT
		uint32_t lu32id, lu52id;
#endif
		union loongarch_instruction *insn = (void *)p->pc;

		lu12iw = (v >> 12) & 0xfffff;
		ori    = v & 0xfff;
#ifdef CONFIG_64BIT
		lu32id = (v >> 32) & 0xfffff;
		lu52id = v >> 52;
#endif

		insn[0].reg1i20_format.immediate = lu12iw;
		insn[1].reg2i12_format.immediate = ori;
#ifdef CONFIG_64BIT
		insn[2].reg1i20_format.immediate = lu32id;
		insn[3].reg2i12_format.immediate = lu52id;
#endif
	}
}

#ifdef CONFIG_RANDOMIZE_BASE
static inline __init unsigned long rotate_xor(unsigned long hash,
					      const void *area, size_t size)
{
	size_t i, diff;
	const typeof(hash) *ptr = PTR_ALIGN(area, sizeof(hash));

	diff = (void *)ptr - area;
	if (size < diff + sizeof(hash))

Annotation

Implementation Notes