1867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
2867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright 2010 Tilera Corporation. All Rights Reserved.
3867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
4867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   This program is free software; you can redistribute it and/or
5867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   modify it under the terms of the GNU General Public License
6867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   as published by the Free Software Foundation, version 2.
7867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
8867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   This program is distributed in the hope that it will be useful, but
9867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   WITHOUT ANY WARRANTY; without even the implied warranty of
10867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   NON INFRINGEMENT.  See the GNU General Public License for
12867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   more details.
13867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
14867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * based on machine_kexec.c from other architectures in linux-2.6.18
15867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
16867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
17867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/mm.h>
18867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/kexec.h>
19867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/delay.h>
20867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/reboot.h>
21867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/errno.h>
22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/vmalloc.h>
23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/cpumask.h>
24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/kernel.h>
25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/elf.h>
26867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/highmem.h>
27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/mmu_context.h>
28867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/io.h>
29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/timex.h>
30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/pgtable.h>
31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/pgalloc.h>
32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/cacheflush.h>
33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/checksum.h>
34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <hv/hypervisor.h>
35867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
37867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This stuff is not in elf.h and is not in any other kernel include.
39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This stuff is needed below in the little boot notes parser to
40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * extract the command line so we can pass it to the hypervisor.
41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
42867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstruct Elf32_Bhdr {
43867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	Elf32_Word b_signature;
44867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	Elf32_Word b_size;
45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	Elf32_Half b_checksum;
46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	Elf32_Half b_records;
47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf};
48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define ELF_BOOT_MAGIC		0x0E1FB007
49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define EBN_COMMAND_LINE	0x00000004
50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define roundupsz(X) (((X) + 3) & ~3)
51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
52867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
53867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
54867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid machine_shutdown(void)
56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Normally we would stop all the other processors here, but
59867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * the check in machine_kexec_prepare below ensures we'll only
60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * get this far if we've been booted with "nosmp" on the
61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * command line or without CONFIG_SMP so there's nothing to do
62867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * here (for now).
63867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
64867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
65867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
66867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid machine_crash_shutdown(struct pt_regs *regs)
67867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
68867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Cannot happen.  This type of kexec is disabled on this
70867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * architecture (and enforced in machine_kexec_prepare below).
71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
72867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
73867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
74867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfint machine_kexec_prepare(struct kimage *image)
76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (num_online_cpus() > 1) {
780707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		pr_warning("%s: detected attempt to kexec "
79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       "with num_online_cpus() > 1\n",
80867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       __func__);
81867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		return -ENOSYS;
82867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
83867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (image->type != KEXEC_TYPE_DEFAULT) {
840707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		pr_warning("%s: detected attempt to kexec "
85867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       "with unsupported type: %d\n",
86867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       __func__,
87867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       image->type);
88867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		return -ENOSYS;
89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return 0;
91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid machine_kexec_cleanup(struct kimage *image)
94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * We did nothing in machine_kexec_prepare,
97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * so we have nothing to do here.
98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
100867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
102867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * If we can find elf boot notes on this page, return the command
103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * line.  Otherwise, silently return null.  Somewhat kludgy, but no
104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * good way to do this without significantly rearchitecting the
105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * architecture-independent kexec code.
106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
108867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic unsigned char *kexec_bn2cl(void *pg)
109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	struct Elf32_Bhdr *bhdrp;
111867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	Elf32_Nhdr *nhdrp;
112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned char *desc;
113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned char *command_line;
114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	__sum16 csum;
115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
116867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	bhdrp = (struct Elf32_Bhdr *) pg;
117867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
118867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
119867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * This routine is invoked for every source page, so make
120867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * sure to quietly ignore every impossible page.
121867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
122867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (bhdrp->b_signature != ELF_BOOT_MAGIC ||
123867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	    bhdrp->b_size > PAGE_SIZE)
124867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		return 0;
125867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
126867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
1270707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf	 * If we get a checksum mismatch, warn with the checksum
1280707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf	 * so we can diagnose better.
129867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
130867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	csum = ip_compute_csum(pg, bhdrp->b_size);
131867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (csum != 0) {
1320707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		pr_warning("%s: bad checksum %#x (size %d)\n",
1330707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf			   __func__, csum, bhdrp->b_size);
134867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		return 0;
135867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
136867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
137867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	nhdrp = (Elf32_Nhdr *) (bhdrp + 1);
138867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
139867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	while (nhdrp->n_type != EBN_COMMAND_LINE) {
140867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
141867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		desc = (unsigned char *) (nhdrp + 1);
142867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		desc += roundupsz(nhdrp->n_descsz);
143867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
144867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		nhdrp = (Elf32_Nhdr *) desc;
145867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
146867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		/* still in bounds? */
147867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		if ((unsigned char *) (nhdrp + 1) >
148867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		    ((unsigned char *) pg) + bhdrp->b_size) {
149867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
1500707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf			pr_info("%s: out of bounds\n", __func__);
151867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			return 0;
152867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		}
153867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
154867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
155867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	command_line = (unsigned char *) (nhdrp + 1);
156867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	desc = command_line;
157867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
158867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	while (*desc != '\0') {
159867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		desc++;
160867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		if (((unsigned long)desc & PAGE_MASK) != (unsigned long)pg) {
1610707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf			pr_info("%s: ran off end of page\n",
162867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			       __func__);
163867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			return 0;
164867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		}
165867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
166867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
167867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return command_line;
168867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
169867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
170867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic void kexec_find_and_set_command_line(struct kimage *image)
171867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
172867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	kimage_entry_t *ptr, entry;
173867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
174867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned char *command_line = 0;
175867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned char *r;
176867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	HV_Errno hverr;
177867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
178867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	for (ptr = &image->head;
179867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	     (entry = *ptr) && !(entry & IND_DONE);
180867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	     ptr = (entry & IND_INDIRECTION) ?
181867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		     phys_to_virt((entry & PAGE_MASK)) : ptr + 1) {
182867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
183867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		if ((entry & IND_SOURCE)) {
184867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			void *va =
18538a6f4266989c4dae68eccb1a5cb4580a48003e4Chris Metcalf				kmap_atomic_pfn(entry >> PAGE_SHIFT);
186867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			r = kexec_bn2cl(va);
187867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			if (r) {
188867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				command_line = r;
189867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				break;
190867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			}
19138a6f4266989c4dae68eccb1a5cb4580a48003e4Chris Metcalf			kunmap_atomic(va);
192867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		}
193867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
194867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
195867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (command_line != 0) {
1960707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		pr_info("setting new command line to \"%s\"\n",
197867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       command_line);
198867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
199867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		hverr = hv_set_command_line(
200867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			(HV_VirtAddr) command_line, strlen(command_line));
20138a6f4266989c4dae68eccb1a5cb4580a48003e4Chris Metcalf		kunmap_atomic(command_line);
202867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	} else {
2030707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		pr_info("%s: no command line found; making empty\n",
204867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		       __func__);
205867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		hverr = hv_set_command_line((HV_VirtAddr) command_line, 0);
206867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
2070707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf	if (hverr)
2080707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		pr_warning("%s: hv_set_command_line returned error: %d\n",
2090707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf			   __func__, hverr);
210867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
211867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
212867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
213867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * The kexec code range-checks all its PAs, so to avoid having it run
214867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * amok and allocate memory and then sequester it from every other
215867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * controller, we force it to come from controller zero.  We also
216867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * disable the oom-killer since if we do end up running out of memory,
217867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * that almost certainly won't help.
218867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
219867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstruct page *kimage_alloc_pages_arch(gfp_t gfp_mask, unsigned int order)
220867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
221867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	gfp_mask |= __GFP_THISNODE | __GFP_NORETRY;
222867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return alloc_pages_node(0, gfp_mask, order);
223867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
224867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
225867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic void setup_quasi_va_is_pa(void)
226867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
227867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	HV_PTE *pgtable;
228867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	HV_PTE pte;
229867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int i;
230867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
231867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
232867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Flush our TLB to prevent conflicts between the previous contents
233867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * and the new stuff we're about to add.
234867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
235867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	local_flush_tlb_all();
236867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
237867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* setup VA is PA, at least up to PAGE_OFFSET */
238867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
239867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	pgtable = (HV_PTE *)current->mm->pgd;
240867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE);
241867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3);
242867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
24376c567fbba50c3da2f4d40e2e551bab26cfd4381Chris Metcalf	for (i = 0; i < pgd_index(PAGE_OFFSET); i++) {
24476c567fbba50c3da2f4d40e2e551bab26cfd4381Chris Metcalf		unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT);
24576c567fbba50c3da2f4d40e2e551bab26cfd4381Chris Metcalf		if (pfn_valid(pfn))
24676c567fbba50c3da2f4d40e2e551bab26cfd4381Chris Metcalf			__set_pte(&pgtable[i], pfn_pte(pfn, pte));
24776c567fbba50c3da2f4d40e2e551bab26cfd4381Chris Metcalf	}
248867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
249867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
250867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
2519402c95f34a66e81eba473a2f7267bbae5a1dee2Joe Perchesvoid machine_kexec(struct kimage *image)
252867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
253867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	void *reboot_code_buffer;
2549402c95f34a66e81eba473a2f7267bbae5a1dee2Joe Perches	void (*rnk)(unsigned long, void *, unsigned long)
255ff2d8b19a3a62559afba1c53360c8577a7697714Joe Perches		__noreturn;
256867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
257867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Mask all interrupts before starting to reboot. */
258867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	interrupt_mask_set_mask(~0ULL);
259867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
260867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	kexec_find_and_set_command_line(image);
261867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
262867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
263867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Adjust the home caching of the control page to be cached on
264867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * this cpu, and copy the assembly helper into the control
265867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * code page, which we map in the vmalloc area.
266867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
267867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	homecache_change_page_home(image->control_code_page, 0,
268867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				   smp_processor_id());
269867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	reboot_code_buffer = vmap(&image->control_code_page, 1, 0,
270867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				  __pgprot(_PAGE_KERNEL | _PAGE_EXECUTABLE));
271867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	memcpy(reboot_code_buffer, relocate_new_kernel,
272867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	       relocate_new_kernel_size);
273867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	__flush_icache_range(
274867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		(unsigned long) reboot_code_buffer,
275867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		(unsigned long) reboot_code_buffer + relocate_new_kernel_size);
276867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
277867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	setup_quasi_va_is_pa();
278867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
279867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* now call it */
280867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	rnk = reboot_code_buffer;
281867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	(*rnk)(image->head, reboot_code_buffer, image->start);
282867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
283