summaryrefslogtreecommitdiff
path: root/arch/loongarch/kernel/head.S
blob: aba548db244604f0667c5092e97602166c86fe26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
 */
#include <linux/init.h>
#include <linux/threads.h>

#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/bug.h>
#include <asm/regdef.h>
#include <asm/loongarch.h>
#include <asm/stackframe.h>

#ifdef CONFIG_EFI_STUB

#include "efi-header.S"

	__HEAD

_head:
	.word	IMAGE_DOS_SIGNATURE	/* "MZ", MS-DOS header */
	.org	0x8
	.dword	_kernel_entry		/* Kernel entry point (physical address) */
	.dword	_kernel_asize		/* Kernel image effective size */
	.quad	PHYS_LINK_KADDR		/* Kernel image load offset from start of RAM */
	.org	0x38			/* 0x20 ~ 0x37 reserved */
	.long	LINUX_PE_MAGIC
	.long	pe_header - _head	/* Offset to the PE header */

pe_header:
	__EFI_PE_HEADER

SYM_DATA(kernel_asize, .long _kernel_asize);
SYM_DATA(kernel_fsize, .long _kernel_fsize);

#endif

	__REF

	.align 12

SYM_CODE_START(kernel_entry)			# kernel entry point

	SETUP_TWINS
	SETUP_MODES	t0
	JUMP_VIRT_ADDR	t0, t1
	SETUP_DMWINS	t0

	la.pcrel	t0, __bss_start		# clear .bss
	LONG_S		zero, t0, 0
	la.pcrel	t1, __bss_stop - LONGSIZE
1:
	PTR_ADDI	t0, t0, LONGSIZE
	LONG_S		zero, t0, 0
	bne		t0, t1, 1b

	la.pcrel	t0, fw_arg0
	PTR_S		a0, t0, 0		# firmware arguments
	la.pcrel	t0, fw_arg1
	PTR_S		a1, t0, 0
	la.pcrel	t0, fw_arg2
	PTR_S		a2, t0, 0

#ifdef CONFIG_PAGE_SIZE_4KB
	LONG_LI		t0, 0
	LONG_LI		t1, CSR_STFILL
	csrxchg		t0, t1, LOONGARCH_CSR_IMPCTL1
#endif
	/* KSave3 used for percpu base, initialized as 0 */
	csrwr		zero, PERCPU_BASE_KS
	/* GPR21 used for percpu base (runtime), initialized as 0 */
	move		u0, zero

	la.pcrel	tp, init_thread_union
	/* Set the SP after an empty pt_regs.  */
	PTR_LI		sp, (_THREAD_SIZE - PT_SIZE)
	PTR_ADD		sp, sp, tp
	set_saved_sp	sp, t0, t1

#ifdef CONFIG_RELOCATABLE

	bl		relocate_kernel

#ifdef CONFIG_RANDOMIZE_BASE
	/* Repoint the sp into the new kernel */
	PTR_LI		sp, (_THREAD_SIZE - PT_SIZE)
	PTR_ADD		sp, sp, tp
	set_saved_sp	sp, t0, t1

	/* Jump to the new kernel: new_pc = current_pc + random_offset */
	pcaddi		t0, 0
	PTR_ADD		t0, t0, a0
	jirl		zero, t0, 0xc
#endif /* CONFIG_RANDOMIZE_BASE */

#endif /* CONFIG_RELOCATABLE */

#ifdef CONFIG_KASAN
	bl		kasan_early_init
#endif

	bl		start_kernel
	ASM_BUG()

SYM_CODE_END(kernel_entry)

#ifdef CONFIG_SMP

/*
 * SMP slave cpus entry point.	Board specific code for bootstrap calls this
 * function after setting up the stack and tp registers.
 */
SYM_CODE_START(smpboot_entry)

	SETUP_TWINS
	SETUP_MODES	t0
	JUMP_VIRT_ADDR	t0, t1
	SETUP_DMWINS	t0

#ifdef CONFIG_PAGE_SIZE_4KB
	LONG_LI		t0, 0
	LONG_LI		t1, CSR_STFILL
	csrxchg		t0, t1, LOONGARCH_CSR_IMPCTL1
#endif
	/* Enable PG */
	li.w		t0, 0xb0		# PLV=0, IE=0, PG=1
	csrwr		t0, LOONGARCH_CSR_CRMD
	li.w		t0, 0x04		# PLV=0, PIE=1, PWE=0
	csrwr		t0, LOONGARCH_CSR_PRMD
	li.w		t0, 0x00		# FPE=0, SXE=0, ASXE=0, BTE=0
	csrwr		t0, LOONGARCH_CSR_EUEN

	la.pcrel	t0, cpuboot_data
	ld.d		sp, t0, CPU_BOOT_STACK
	ld.d		tp, t0, CPU_BOOT_TINFO

	bl		start_secondary
	ASM_BUG()

SYM_CODE_END(smpboot_entry)

#endif /* CONFIG_SMP */

SYM_ENTRY(kernel_entry_end, SYM_L_GLOBAL, SYM_A_NONE)