linux/arch/i386/kernel/relocate_kernel.S
<<
>>
Prefs
   1/*
   2 * relocate_kernel.S - put the kernel image in place to boot
   3 * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
   4 *
   5 * This source code is licensed under the GNU General Public License,
   6 * Version 2.  See the file COPYING for more details.
   7 */
   8
   9#include <linux/linkage.h>
  10#include <asm/page.h>
  11#include <asm/kexec.h>
  12
  13/*
  14 * Must be relocatable PIC code callable as a C function
  15 */
  16
  17#define PTR(x) (x << 2)
  18#define PAGE_ALIGNED (1 << PAGE_SHIFT)
  19#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
  20#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
  21
  22        .text
  23        .align PAGE_ALIGNED
  24        .globl relocate_kernel
  25relocate_kernel:
  26        movl    8(%esp), %ebp /* list of pages */
  27
  28#ifdef CONFIG_X86_PAE
  29        /* map the control page at its virtual address */
  30
  31        movl    PTR(VA_PGD)(%ebp), %edi
  32        movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
  33        andl    $0xc0000000, %eax
  34        shrl    $27, %eax
  35        addl    %edi, %eax
  36
  37        movl    PTR(PA_PMD_0)(%ebp), %edx
  38        orl     $PAE_PGD_ATTR, %edx
  39        movl    %edx, (%eax)
  40
  41        movl    PTR(VA_PMD_0)(%ebp), %edi
  42        movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
  43        andl    $0x3fe00000, %eax
  44        shrl    $18, %eax
  45        addl    %edi, %eax
  46
  47        movl    PTR(PA_PTE_0)(%ebp), %edx
  48        orl     $PAGE_ATTR, %edx
  49        movl    %edx, (%eax)
  50
  51        movl    PTR(VA_PTE_0)(%ebp), %edi
  52        movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
  53        andl    $0x001ff000, %eax
  54        shrl    $9, %eax
  55        addl    %edi, %eax
  56
  57        movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
  58        orl     $PAGE_ATTR, %edx
  59        movl    %edx, (%eax)
  60
  61        /* identity map the control page at its physical address */
  62
  63        movl    PTR(VA_PGD)(%ebp), %edi
  64        movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
  65        andl    $0xc0000000, %eax
  66        shrl    $27, %eax
  67        addl    %edi, %eax
  68
  69        movl    PTR(PA_PMD_1)(%ebp), %edx
  70        orl     $PAE_PGD_ATTR, %edx
  71        movl    %edx, (%eax)
  72
  73        movl    PTR(VA_PMD_1)(%ebp), %edi
  74        movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
  75        andl    $0x3fe00000, %eax
  76        shrl    $18, %eax
  77        addl    %edi, %eax
  78
  79        movl    PTR(PA_PTE_1)(%ebp), %edx
  80        orl     $PAGE_ATTR, %edx
  81        movl    %edx, (%eax)
  82
  83        movl    PTR(VA_PTE_1)(%ebp), %edi
  84        movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
  85        andl    $0x001ff000, %eax
  86        shrl    $9, %eax
  87        addl    %edi, %eax
  88
  89        movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
  90        orl     $PAGE_ATTR, %edx
  91        movl    %edx, (%eax)
  92#else
  93        /* map the control page at its virtual address */
  94
  95        movl    PTR(VA_PGD)(%ebp), %edi
  96        movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
  97        andl    $0xffc00000, %eax
  98        shrl    $20, %eax
  99        addl    %edi, %eax
 100
 101        movl    PTR(PA_PTE_0)(%ebp), %edx
 102        orl     $PAGE_ATTR, %edx
 103        movl    %edx, (%eax)
 104
 105        movl    PTR(VA_PTE_0)(%ebp), %edi
 106        movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
 107        andl    $0x003ff000, %eax
 108        shrl    $10, %eax
 109        addl    %edi, %eax
 110
 111        movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
 112        orl     $PAGE_ATTR, %edx
 113        movl    %edx, (%eax)
 114
 115        /* identity map the control page at its physical address */
 116
 117        movl    PTR(VA_PGD)(%ebp), %edi
 118        movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
 119        andl    $0xffc00000, %eax
 120        shrl    $20, %eax
 121        addl    %edi, %eax
 122
 123        movl    PTR(PA_PTE_1)(%ebp), %edx
 124        orl     $PAGE_ATTR, %edx
 125        movl    %edx, (%eax)
 126
 127        movl    PTR(VA_PTE_1)(%ebp), %edi
 128        movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
 129        andl    $0x003ff000, %eax
 130        shrl    $10, %eax
 131        addl    %edi, %eax
 132
 133        movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
 134        orl     $PAGE_ATTR, %edx
 135        movl    %edx, (%eax)
 136#endif
 137
 138relocate_new_kernel:
 139        /* read the arguments and say goodbye to the stack */
 140        movl  4(%esp), %ebx /* page_list */
 141        movl  8(%esp), %ebp /* list of pages */
 142        movl  12(%esp), %edx /* start address */
 143        movl  16(%esp), %ecx /* cpu_has_pae */
 144
 145        /* zero out flags, and disable interrupts */
 146        pushl $0
 147        popfl
 148
 149        /* get physical address of control page now */
 150        /* this is impossible after page table switch */
 151        movl    PTR(PA_CONTROL_PAGE)(%ebp), %edi
 152
 153        /* switch to new set of page tables */
 154        movl    PTR(PA_PGD)(%ebp), %eax
 155        movl    %eax, %cr3
 156
 157        /* setup a new stack at the end of the physical control page */
 158        lea     4096(%edi), %esp
 159
 160        /* jump to identity mapped page */
 161        movl    %edi, %eax
 162        addl    $(identity_mapped - relocate_kernel), %eax
 163        pushl   %eax
 164        ret
 165
 166identity_mapped:
 167        /* store the start address on the stack */
 168        pushl   %edx
 169
 170        /* Set cr0 to a known state:
 171         * 31 0 == Paging disabled
 172         * 18 0 == Alignment check disabled
 173         * 16 0 == Write protect disabled
 174         * 3  0 == No task switch
 175         * 2  0 == Don't do FP software emulation.
 176         * 0  1 == Proctected mode enabled
 177         */
 178        movl    %cr0, %eax
 179        andl    $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
 180        orl     $(1<<0), %eax
 181        movl    %eax, %cr0
 182
 183        /* clear cr4 if applicable */
 184        testl   %ecx, %ecx
 185        jz      1f
 186        /* Set cr4 to a known state:
 187         * Setting everything to zero seems safe.
 188         */
 189        movl    %cr4, %eax
 190        andl    $0, %eax
 191        movl    %eax, %cr4
 192
 193        jmp 1f
 1941:
 195
 196        /* Flush the TLB (needed?) */
 197        xorl    %eax, %eax
 198        movl    %eax, %cr3
 199
 200        /* Do the copies */
 201        movl    %ebx, %ecx
 202        jmp     1f
 203
 2040:      /* top, read another word from the indirection page */
 205        movl    (%ebx), %ecx
 206        addl    $4, %ebx
 2071:
 208        testl   $0x1,   %ecx  /* is it a destination page */
 209        jz      2f
 210        movl    %ecx,   %edi
 211        andl    $0xfffff000, %edi
 212        jmp     0b
 2132:
 214        testl   $0x2,   %ecx  /* is it an indirection page */
 215        jz      2f
 216        movl    %ecx,   %ebx
 217        andl    $0xfffff000, %ebx
 218        jmp     0b
 2192:
 220        testl   $0x4,   %ecx /* is it the done indicator */
 221        jz      2f
 222        jmp     3f
 2232:
 224        testl   $0x8,   %ecx /* is it the source indicator */
 225        jz      0b           /* Ignore it otherwise */
 226        movl    %ecx,   %esi /* For every source page do a copy */
 227        andl    $0xfffff000, %esi
 228
 229        movl    $1024, %ecx
 230        rep ; movsl
 231        jmp     0b
 232
 2333:
 234
 235        /* To be certain of avoiding problems with self-modifying code
 236         * I need to execute a serializing instruction here.
 237         * So I flush the TLB, it's handy, and not processor dependent.
 238         */
 239        xorl    %eax, %eax
 240        movl    %eax, %cr3
 241
 242        /* set all of the registers to known values */
 243        /* leave %esp alone */
 244
 245        xorl    %eax, %eax
 246        xorl    %ebx, %ebx
 247        xorl    %ecx, %ecx
 248        xorl    %edx, %edx
 249        xorl    %esi, %esi
 250        xorl    %edi, %edi
 251        xorl    %ebp, %ebp
 252        ret
 253
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.