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