···19192020#include <asm/page.h>21212222+#ifndef __tilegx__2223/* Maximum physical address we can use pages from. */2324#define KEXEC_SOURCE_MEMORY_LIMIT TASK_SIZE2425/* Maximum address we can reach in physical address mode. */2526#define KEXEC_DESTINATION_MEMORY_LIMIT TASK_SIZE2627/* Maximum address we can use for the control code buffer. */2728#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE2929+#else3030+/* We need to limit the memory below PGDIR_SIZE since3131+ * we only setup page table for [0, PGDIR_SIZE) before final kexec.3232+ */3333+/* Maximum physical address we can use pages from. */3434+#define KEXEC_SOURCE_MEMORY_LIMIT PGDIR_SIZE3535+/* Maximum address we can reach in physical address mode. */3636+#define KEXEC_DESTINATION_MEMORY_LIMIT PGDIR_SIZE3737+/* Maximum address we can use for the control code buffer. */3838+#define KEXEC_CONTROL_MEMORY_LIMIT PGDIR_SIZE3939+#endif28402941#define KEXEC_CONTROL_PAGE_SIZE PAGE_SIZE3042
···3131#include <asm/pgalloc.h>3232#include <asm/cacheflush.h>3333#include <asm/checksum.h>3434+#include <asm/tlbflush.h>3535+#include <asm/homecache.h>3436#include <hv/hypervisor.h>35373638···224222 return alloc_pages_node(0, gfp_mask, order);225223}226224225225+/*226226+ * Address range in which pa=va mapping is set in setup_quasi_va_is_pa().227227+ * For tilepro, PAGE_OFFSET is used since this is the largest possbile value228228+ * for tilepro, while for tilegx, we limit it to entire middle level page229229+ * table which we assume has been allocated and is undoubtedly large enough.230230+ */231231+#ifndef __tilegx__232232+#define QUASI_VA_IS_PA_ADDR_RANGE PAGE_OFFSET233233+#else234234+#define QUASI_VA_IS_PA_ADDR_RANGE PGDIR_SIZE235235+#endif236236+227237static void setup_quasi_va_is_pa(void)228238{229229- HV_PTE *pgtable;230239 HV_PTE pte;231231- int i;240240+ unsigned long i;232241233242 /*234243 * Flush our TLB to prevent conflicts between the previous contents···247234 */248235 local_flush_tlb_all();249236250250- /* setup VA is PA, at least up to PAGE_OFFSET */251251-252252- pgtable = (HV_PTE *)current->mm->pgd;237237+ /*238238+ * setup VA is PA, at least up to QUASI_VA_IS_PA_ADDR_RANGE.239239+ * Note here we assume that level-1 page table is defined by240240+ * HPAGE_SIZE.241241+ */253242 pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE);254243 pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3);255255-256256- for (i = 0; i < pgd_index(PAGE_OFFSET); i++) {244244+ for (i = 0; i < (QUASI_VA_IS_PA_ADDR_RANGE >> HPAGE_SHIFT); i++) {245245+ unsigned long vaddr = i << HPAGE_SHIFT;246246+ pgd_t *pgd = pgd_offset(current->mm, vaddr);247247+ pud_t *pud = pud_offset(pgd, vaddr);248248+ pte_t *ptep = (pte_t *) pmd_offset(pud, vaddr);257249 unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT);250250+258251 if (pfn_valid(pfn))259259- __set_pte(&pgtable[i], pfn_pte(pfn, pte));252252+ __set_pte(ptep, pfn_pte(pfn, pte));260253 }261254}262255
···11+/*22+ * Copyright 2011 Tilera Corporation. All Rights Reserved.33+ *44+ * This program is free software; you can redistribute it and/or55+ * modify it under the terms of the GNU General Public License66+ * as published by the Free Software Foundation, version 2.77+ *88+ * This program is distributed in the hope that it will be useful, but99+ * WITHOUT ANY WARRANTY; without even the implied warranty of1010+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or1111+ * NON INFRINGEMENT. See the GNU General Public License for1212+ * more details.1313+ *1414+ * copy new kernel into place and then call hv_reexec1515+ *1616+ */1717+1818+#include <linux/linkage.h>1919+#include <arch/chip.h>2020+#include <asm/page.h>2121+#include <hv/hypervisor.h>2222+2323+#undef RELOCATE_NEW_KERNEL_VERBOSE2424+2525+STD_ENTRY(relocate_new_kernel)2626+2727+ move r30, r0 /* page list */2828+ move r31, r1 /* address of page we are on */2929+ move r32, r2 /* start address of new kernel */3030+3131+ shrui r1, r1, PAGE_SHIFT3232+ addi r1, r1, 13333+ shli sp, r1, PAGE_SHIFT3434+ addi sp, sp, -83535+ /* we now have a stack (whether we need one or not) */3636+3737+ moveli r40, hw2_last(hv_console_putc)3838+ shl16insli r40, r40, hw1(hv_console_putc)3939+ shl16insli r40, r40, hw0(hv_console_putc)4040+4141+#ifdef RELOCATE_NEW_KERNEL_VERBOSE4242+ moveli r0, 'r'4343+ jalr r404444+4545+ moveli r0, '_'4646+ jalr r404747+4848+ moveli r0, 'n'4949+ jalr r405050+5151+ moveli r0, '_'5252+ jalr r405353+5454+ moveli r0, 'k'5555+ jalr r405656+5757+ moveli r0, '\n'5858+ jalr r405959+#endif6060+6161+ /*6262+ * Throughout this code r30 is pointer to the element of page6363+ * list we are working on.6464+ *6565+ * Normally we get to the next element of the page list by6666+ * incrementing r30 by eight. The exception is if the element6767+ * on the page list is an IND_INDIRECTION in which case we use6868+ * the element with the low bits masked off as the new value6969+ * of r30.7070+ *7171+ * To get this started, we need the value passed to us (which7272+ * will always be an IND_INDIRECTION) in memory somewhere with7373+ * r30 pointing at it. To do that, we push the value passed7474+ * to us on the stack and make r30 point to it.7575+ */7676+7777+ st sp, r307878+ move r30, sp7979+ addi sp, sp, -168080+8181+#if CHIP_HAS_CBOX_HOME_MAP()8282+ /*8383+ * On TILE-GX, we need to flush all tiles' caches, since we may8484+ * have been doing hash-for-home caching there. Note that we8585+ * must do this _after_ we're completely done modifying any memory8686+ * other than our output buffer (which we know is locally cached).8787+ * We want the caches to be fully clean when we do the reexec,8888+ * because the hypervisor is going to do this flush again at that8989+ * point, and we don't want that second flush to overwrite any memory.9090+ */9191+ {9292+ move r0, zero /* cache_pa */9393+ moveli r1, hw2_last(HV_FLUSH_EVICT_L2)9494+ }9595+ {9696+ shl16insli r1, r1, hw1(HV_FLUSH_EVICT_L2)9797+ movei r2, -1 /* cache_cpumask; -1 means all client tiles */9898+ }9999+ {100100+ shl16insli r1, r1, hw0(HV_FLUSH_EVICT_L2) /* cache_control */101101+ move r3, zero /* tlb_va */102102+ }103103+ {104104+ move r4, zero /* tlb_length */105105+ move r5, zero /* tlb_pgsize */106106+ }107107+ {108108+ move r6, zero /* tlb_cpumask */109109+ move r7, zero /* asids */110110+ }111111+ {112112+ moveli r20, hw2_last(hv_flush_remote)113113+ move r8, zero /* asidcount */114114+ }115115+ shl16insli r20, r20, hw1(hv_flush_remote)116116+ shl16insli r20, r20, hw0(hv_flush_remote)117117+118118+ jalr r20119119+#endif120120+121121+ /* r33 is destination pointer, default to zero */122122+123123+ moveli r33, 0124124+125125+.Lloop: ld r10, r30126126+127127+ andi r9, r10, 0xf /* low 4 bits tell us what type it is */128128+ xor r10, r10, r9 /* r10 is now value with low 4 bits stripped */129129+130130+ cmpeqi r0, r9, 0x1 /* IND_DESTINATION */131131+ beqzt r0, .Ltry2132132+133133+ move r33, r10134134+135135+#ifdef RELOCATE_NEW_KERNEL_VERBOSE136136+ moveli r0, 'd'137137+ jalr r40138138+#endif139139+140140+ addi r30, r30, 8141141+ j .Lloop142142+143143+.Ltry2:144144+ cmpeqi r0, r9, 0x2 /* IND_INDIRECTION */145145+ beqzt r0, .Ltry4146146+147147+ move r30, r10148148+149149+#ifdef RELOCATE_NEW_KERNEL_VERBOSE150150+ moveli r0, 'i'151151+ jalr r40152152+#endif153153+154154+ j .Lloop155155+156156+.Ltry4:157157+ cmpeqi r0, r9, 0x4 /* IND_DONE */158158+ beqzt r0, .Ltry8159159+160160+ mf161161+162162+#ifdef RELOCATE_NEW_KERNEL_VERBOSE163163+ moveli r0, 'D'164164+ jalr r40165165+ moveli r0, '\n'166166+ jalr r40167167+#endif168168+169169+ move r0, r32170170+171171+ moveli r41, hw2_last(hv_reexec)172172+ shl16insli r41, r41, hw1(hv_reexec)173173+ shl16insli r41, r41, hw0(hv_reexec)174174+175175+ jalr r41176176+177177+ /* we should not get here */178178+179179+ moveli r0, '?'180180+ jalr r40181181+ moveli r0, '\n'182182+ jalr r40183183+184184+ j .Lhalt185185+186186+.Ltry8: cmpeqi r0, r9, 0x8 /* IND_SOURCE */187187+ beqz r0, .Lerr /* unknown type */188188+189189+ /* copy page at r10 to page at r33 */190190+191191+ move r11, r33192192+193193+ moveli r0, hw2_last(PAGE_SIZE)194194+ shl16insli r0, r0, hw1(PAGE_SIZE)195195+ shl16insli r0, r0, hw0(PAGE_SIZE)196196+ add r33, r33, r0197197+198198+ /* copy word at r10 to word at r11 until r11 equals r33 */199199+200200+ /* We know page size must be multiple of 8, so we can unroll201201+ * 8 times safely without any edge case checking.202202+ *203203+ * Issue a flush of the destination every 8 words to avoid204204+ * incoherence when starting the new kernel. (Now this is205205+ * just good paranoia because the hv_reexec call will also206206+ * take care of this.)207207+ */208208+209209+1:210210+ { ld r0, r10; addi r10, r10, 8 }211211+ { st r11, r0; addi r11, r11, 8 }212212+ { ld r0, r10; addi r10, r10, 8 }213213+ { st r11, r0; addi r11, r11, 8 }214214+ { ld r0, r10; addi r10, r10, 8 }215215+ { st r11, r0; addi r11, r11, 8 }216216+ { ld r0, r10; addi r10, r10, 8 }217217+ { st r11, r0; addi r11, r11, 8 }218218+ { ld r0, r10; addi r10, r10, 8 }219219+ { st r11, r0; addi r11, r11, 8 }220220+ { ld r0, r10; addi r10, r10, 8 }221221+ { st r11, r0; addi r11, r11, 8 }222222+ { ld r0, r10; addi r10, r10, 8 }223223+ { st r11, r0; addi r11, r11, 8 }224224+ { ld r0, r10; addi r10, r10, 8 }225225+ { st r11, r0 }226226+ { flush r11 ; addi r11, r11, 8 }227227+228228+ cmpeq r0, r33, r11229229+ beqzt r0, 1b230230+231231+#ifdef RELOCATE_NEW_KERNEL_VERBOSE232232+ moveli r0, 's'233233+ jalr r40234234+#endif235235+236236+ addi r30, r30, 8237237+ j .Lloop238238+239239+240240+.Lerr: moveli r0, 'e'241241+ jalr r40242242+ moveli r0, 'r'243243+ jalr r40244244+ moveli r0, 'r'245245+ jalr r40246246+ moveli r0, '\n'247247+ jalr r40248248+.Lhalt:249249+ moveli r41, hw2_last(hv_halt)250250+ shl16insli r41, r41, hw1(hv_halt)251251+ shl16insli r41, r41, hw0(hv_halt)252252+253253+ jalr r41254254+ STD_ENDPROC(relocate_new_kernel)255255+256256+ .section .rodata,"a"257257+258258+ .globl relocate_new_kernel_size259259+relocate_new_kernel_size:260260+ .long .Lend_relocate_new_kernel - relocate_new_kernel