History

arch/tile: support kexec() for tilegx

Chris Metcalf committed 14 years ago

Commit fc0c49f1 parent cd6f32a5 files · +300 −9Browse files

Unified · Split

5 files
  1. arch/tile/include/asm/kexec.h +12 −0
  2. arch/tile/kernel/Makefile +1 −1
  3. arch/tile/kernel/machine_kexec.c +27 −8
  4. arch/tile/kernel/relocate_kernel_32.S +0 −0
  5. arch/tile/kernel/relocate_kernel_64.S +260 −0
arch/tile/include/asm/kexec.h+12−0
@@ -19,12 +19,24 @@ · 18 unmodified lines
1919
2020 #include <asm/page.h>
2121
22+#ifndef __tilegx__
2223 /* Maximum physical address we can use pages from. */
2324 #define KEXEC_SOURCE_MEMORY_LIMIT TASK_SIZE
2425 /* Maximum address we can reach in physical address mode. */
2526 #define KEXEC_DESTINATION_MEMORY_LIMIT TASK_SIZE
2627 /* Maximum address we can use for the control code buffer. */
2728 #define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
29+#else
30+/* We need to limit the memory below PGDIR_SIZE since
31+ * we only setup page table for [0, PGDIR_SIZE) before final kexec.
32+ */
33+/* Maximum physical address we can use pages from. */
34+#define KEXEC_SOURCE_MEMORY_LIMIT PGDIR_SIZE
35+/* Maximum address we can reach in physical address mode. */
36+#define KEXEC_DESTINATION_MEMORY_LIMIT PGDIR_SIZE
37+/* Maximum address we can use for the control code buffer. */
38+#define KEXEC_CONTROL_MEMORY_LIMIT PGDIR_SIZE
39+#endif
2840
2941 #define KEXEC_CONTROL_PAGE_SIZE PAGE_SIZE
3042
arch/tile/kernel/Makefile+1−1
@@ -13,5 +13,5 @@ obj-$(CONFIG_COMPAT) += compat.o compat_signal.o · 12 unmodified lines
1313 obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o
1414 obj-$(CONFIG_MODULES) += module.o
1515 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
16−obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
16+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel_$(BITS).o
1717 obj-$(CONFIG_PCI) += pci.o
arch/tile/kernel/machine_kexec.c+27−8
@@ -31,6 +31,8 @@ · 30 unmodified lines
3131 #include <asm/pgalloc.h>
3232 #include <asm/cacheflush.h>
3333 #include <asm/checksum.h>
34+#include <asm/tlbflush.h>
35+#include <asm/homecache.h>
3436 #include <hv/hypervisor.h>
3537
3638
@@ -222,11 +224,22 @@ struct page *kimage_alloc_pages_arch(gfp_t gfp_mask, unsigned int order) · 185 unmodified lines
222224 return alloc_pages_node(0, gfp_mask, order);
223225 }
224226
227+/*
228+ * Address range in which pa=va mapping is set in setup_quasi_va_is_pa().
229+ * For tilepro, PAGE_OFFSET is used since this is the largest possbile value
230+ * for tilepro, while for tilegx, we limit it to entire middle level page
231+ * table which we assume has been allocated and is undoubtedly large enough.
232+ */
233+#ifndef __tilegx__
234+#define QUASI_VA_IS_PA_ADDR_RANGE PAGE_OFFSET
235+#else
236+#define QUASI_VA_IS_PA_ADDR_RANGE PGDIR_SIZE
237+#endif
238+
225239 static void setup_quasi_va_is_pa(void)
226240 {
227− HV_PTE *pgtable;
228241 HV_PTE pte;
229− int i;
242+ unsigned long i;
230243
231244 /*
232245 * Flush our TLB to prevent conflicts between the previous contents
@@ -234,16 +247,22 @@ static void setup_quasi_va_is_pa(void) · 1 unmodified line
234247 */
235248 local_flush_tlb_all();
236249
237− /* setup VA is PA, at least up to PAGE_OFFSET */
238−
239− pgtable = (HV_PTE *)current->mm->pgd;
250+ /*
251+ * setup VA is PA, at least up to QUASI_VA_IS_PA_ADDR_RANGE.
252+ * Note here we assume that level-1 page table is defined by
253+ * HPAGE_SIZE.
254+ */
240255 pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE);
241256 pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3);
242−
243− for (i = 0; i < pgd_index(PAGE_OFFSET); i++) {
257+ for (i = 0; i < (QUASI_VA_IS_PA_ADDR_RANGE >> HPAGE_SHIFT); i++) {
258+ unsigned long vaddr = i << HPAGE_SHIFT;
259+ pgd_t *pgd = pgd_offset(current->mm, vaddr);
260+ pud_t *pud = pud_offset(pgd, vaddr);
261+ pte_t *ptep = (pte_t *) pmd_offset(pud, vaddr);
244262 unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT);
263+
245264 if (pfn_valid(pfn))
246− __set_pte(&pgtable[i], pfn_pte(pfn, pte));
265+ __set_pte(ptep, pfn_pte(pfn, pte));
247266 }
248267 }
249268
arch/tile/kernel/relocate_kernel_32.Srenamed from arch/tile/kernel/relocate_kernel.S+0−0

File renamed without changes.

arch/tile/kernel/relocate_kernel_64.S+260−0
@@ -0,0 +1,260 @@
1+/*
2+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
3+ *
4+ * This program is free software; you can redistribute it and/or
5+ * modify it under the terms of the GNU General Public License
6+ * as published by the Free Software Foundation, version 2.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11+ * NON INFRINGEMENT. See the GNU General Public License for
12+ * more details.
13+ *
14+ * copy new kernel into place and then call hv_reexec
15+ *
16+ */
17+
18+#include <linux/linkage.h>
19+#include <arch/chip.h>
20+#include <asm/page.h>
21+#include <hv/hypervisor.h>
22+
23+#undef RELOCATE_NEW_KERNEL_VERBOSE
24+
25+STD_ENTRY(relocate_new_kernel)
26+
27+ move r30, r0 /* page list */
28+ move r31, r1 /* address of page we are on */
29+ move r32, r2 /* start address of new kernel */
30+
31+ shrui r1, r1, PAGE_SHIFT
32+ addi r1, r1, 1
33+ shli sp, r1, PAGE_SHIFT
34+ addi sp, sp, -8
35+ /* we now have a stack (whether we need one or not) */
36+
37+ moveli r40, hw2_last(hv_console_putc)
38+ shl16insli r40, r40, hw1(hv_console_putc)
39+ shl16insli r40, r40, hw0(hv_console_putc)
40+
41+#ifdef RELOCATE_NEW_KERNEL_VERBOSE
42+ moveli r0, 'r'
43+ jalr r40
44+
45+ moveli r0, '_'
46+ jalr r40
47+
48+ moveli r0, 'n'
49+ jalr r40
50+
51+ moveli r0, '_'
52+ jalr r40
53+
54+ moveli r0, 'k'
55+ jalr r40
56+
57+ moveli r0, '\n'
58+ jalr r40
59+#endif
60+
61+ /*
62+ * Throughout this code r30 is pointer to the element of page
63+ * list we are working on.
64+ *
65+ * Normally we get to the next element of the page list by
66+ * incrementing r30 by eight. The exception is if the element
67+ * on the page list is an IND_INDIRECTION in which case we use
68+ * the element with the low bits masked off as the new value
69+ * of r30.
70+ *
71+ * To get this started, we need the value passed to us (which
72+ * will always be an IND_INDIRECTION) in memory somewhere with
73+ * r30 pointing at it. To do that, we push the value passed
74+ * to us on the stack and make r30 point to it.
75+ */
76+
77+ st sp, r30
78+ move r30, sp
79+ addi sp, sp, -16
80+
81+#if CHIP_HAS_CBOX_HOME_MAP()
82+ /*
83+ * On TILE-GX, we need to flush all tiles' caches, since we may
84+ * have been doing hash-for-home caching there. Note that we
85+ * must do this _after_ we're completely done modifying any memory
86+ * other than our output buffer (which we know is locally cached).
87+ * We want the caches to be fully clean when we do the reexec,
88+ * because the hypervisor is going to do this flush again at that
89+ * point, and we don't want that second flush to overwrite any memory.
90+ */
91+ {
92+ move r0, zero /* cache_pa */
93+ moveli r1, hw2_last(HV_FLUSH_EVICT_L2)
94+ }
95+ {
96+ shl16insli r1, r1, hw1(HV_FLUSH_EVICT_L2)
97+ movei r2, -1 /* cache_cpumask; -1 means all client tiles */
98+ }
99+ {
100+ shl16insli r1, r1, hw0(HV_FLUSH_EVICT_L2) /* cache_control */
101+ move r3, zero /* tlb_va */
102+ }
103+ {
104+ move r4, zero /* tlb_length */
105+ move r5, zero /* tlb_pgsize */
106+ }
107+ {
108+ move r6, zero /* tlb_cpumask */
109+ move r7, zero /* asids */
110+ }
111+ {
112+ moveli r20, hw2_last(hv_flush_remote)
113+ move r8, zero /* asidcount */
114+ }
115+ shl16insli r20, r20, hw1(hv_flush_remote)
116+ shl16insli r20, r20, hw0(hv_flush_remote)
117+
118+ jalr r20
119+#endif
120+
121+ /* r33 is destination pointer, default to zero */
122+
123+ moveli r33, 0
124+
125+.Lloop: ld r10, r30
126+
127+ andi r9, r10, 0xf /* low 4 bits tell us what type it is */
128+ xor r10, r10, r9 /* r10 is now value with low 4 bits stripped */
129+
130+ cmpeqi r0, r9, 0x1 /* IND_DESTINATION */
131+ beqzt r0, .Ltry2
132+
133+ move r33, r10
134+
135+#ifdef RELOCATE_NEW_KERNEL_VERBOSE
136+ moveli r0, 'd'
137+ jalr r40
138+#endif
139+
140+ addi r30, r30, 8
141+ j .Lloop
142+
143+.Ltry2:
144+ cmpeqi r0, r9, 0x2 /* IND_INDIRECTION */
145+ beqzt r0, .Ltry4
146+
147+ move r30, r10
148+
149+#ifdef RELOCATE_NEW_KERNEL_VERBOSE
150+ moveli r0, 'i'
151+ jalr r40
152+#endif
153+
154+ j .Lloop
155+
156+.Ltry4:
157+ cmpeqi r0, r9, 0x4 /* IND_DONE */
158+ beqzt r0, .Ltry8
159+
160+ mf
161+
162+#ifdef RELOCATE_NEW_KERNEL_VERBOSE
163+ moveli r0, 'D'
164+ jalr r40
165+ moveli r0, '\n'
166+ jalr r40
167+#endif
168+
169+ move r0, r32
170+
171+ moveli r41, hw2_last(hv_reexec)
172+ shl16insli r41, r41, hw1(hv_reexec)
173+ shl16insli r41, r41, hw0(hv_reexec)
174+
175+ jalr r41
176+
177+ /* we should not get here */
178+
179+ moveli r0, '?'
180+ jalr r40
181+ moveli r0, '\n'
182+ jalr r40
183+
184+ j .Lhalt
185+
186+.Ltry8: cmpeqi r0, r9, 0x8 /* IND_SOURCE */
187+ beqz r0, .Lerr /* unknown type */
188+
189+ /* copy page at r10 to page at r33 */
190+
191+ move r11, r33
192+
193+ moveli r0, hw2_last(PAGE_SIZE)
194+ shl16insli r0, r0, hw1(PAGE_SIZE)
195+ shl16insli r0, r0, hw0(PAGE_SIZE)
196+ add r33, r33, r0
197+
198+ /* copy word at r10 to word at r11 until r11 equals r33 */
199+
200+ /* We know page size must be multiple of 8, so we can unroll
201+ * 8 times safely without any edge case checking.
202+ *
203+ * Issue a flush of the destination every 8 words to avoid
204+ * incoherence when starting the new kernel. (Now this is
205+ * just good paranoia because the hv_reexec call will also
206+ * take care of this.)
207+ */
208+
209+1:
210+ { ld r0, r10; addi r10, r10, 8 }
211+ { st r11, r0; addi r11, r11, 8 }
212+ { ld r0, r10; addi r10, r10, 8 }
213+ { st r11, r0; addi r11, r11, 8 }
214+ { ld r0, r10; addi r10, r10, 8 }
215+ { st r11, r0; addi r11, r11, 8 }
216+ { ld r0, r10; addi r10, r10, 8 }
217+ { st r11, r0; addi r11, r11, 8 }
218+ { ld r0, r10; addi r10, r10, 8 }
219+ { st r11, r0; addi r11, r11, 8 }
220+ { ld r0, r10; addi r10, r10, 8 }
221+ { st r11, r0; addi r11, r11, 8 }
222+ { ld r0, r10; addi r10, r10, 8 }
223+ { st r11, r0; addi r11, r11, 8 }
224+ { ld r0, r10; addi r10, r10, 8 }
225+ { st r11, r0 }
226+ { flush r11 ; addi r11, r11, 8 }
227+
228+ cmpeq r0, r33, r11
229+ beqzt r0, 1b
230+
231+#ifdef RELOCATE_NEW_KERNEL_VERBOSE
232+ moveli r0, 's'
233+ jalr r40
234+#endif
235+
236+ addi r30, r30, 8
237+ j .Lloop
238+
239+
240+.Lerr: moveli r0, 'e'
241+ jalr r40
242+ moveli r0, 'r'
243+ jalr r40
244+ moveli r0, 'r'
245+ jalr r40
246+ moveli r0, '\n'
247+ jalr r40
248+.Lhalt:
249+ moveli r41, hw2_last(hv_halt)
250+ shl16insli r41, r41, hw1(hv_halt)
251+ shl16insli r41, r41, hw0(hv_halt)
252+
253+ jalr r41
254+ STD_ENDPROC(relocate_new_kernel)
255+
256+ .section .rodata,"a"
257+
258+ .globl relocate_new_kernel_size
259+relocate_new_kernel_size:
260+ .long .Lend_relocate_new_kernel - relocate_new_kernel

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t