ref: 5c1feb0ef0b795e5de71e956f9ccddcd5c4b7f21
dir: /sys/src/9/pc64/rebootcode.s/
#include "mem.h" MODE $64 /* * Turn off MMU, then memmove the new kernel to its correct location * in physical memory. Then jumps the to start of the kernel. */ TEXT main(SB), 1, $-4 MOVL RARG, DI /* destination */ MOVL p2+8(FP), SI /* source */ MOVL n+16(FP), BX /* byte count */ /* load zero length idt */ MOVL $_idtptr64p<>(SB), AX MOVL (AX), IDTR /* load temporary gdt */ MOVL $_gdtptr64p<>(SB), AX MOVL (AX), GDTR /* move stack below destination */ MOVL DI, SP /* load CS with 32bit code segment */ PUSHQ $SELECTOR(3, SELGDT, 0) PUSHQ $_warp32<>(SB) RETFQ MODE $32 TEXT _warp32<>(SB), 1, $-4 /* load 32bit data segments */ MOVL $SELECTOR(2, SELGDT, 0), AX MOVW AX, DS MOVW AX, ES MOVW AX, FS MOVW AX, GS MOVW AX, SS /* turn off paging */ MOVL CR0, AX ANDL $0x7fffffff, AX /* ~(PG) */ MOVL AX, CR0 MOVL $0, AX MOVL AX, CR3 /* disable long mode */ MOVL $0xc0000080, CX /* Extended Feature Enable */ RDMSR ANDL $0xfffffeff, AX /* Long Mode Disable */ WRMSR /* diable pae */ MOVL CR4, AX ANDL $0xffffff5f, AX /* ~(PAE|PGE) */ MOVL AX, CR4 MOVL BX, CX /* byte count */ MOVL DI, AX /* save entry point */ /* * the source and destination may overlap. * determine whether to copy forward or backwards */ CMPL SI, DI JGT _forward MOVL SI, DX ADDL CX, DX CMPL DX, DI JGT _back _forward: CLD REP; MOVSB _startkernel: /* jump to entry point */ JMP* AX _back: ADDL CX, DI ADDL CX, SI SUBL $1, DI SUBL $1, SI STD REP; MOVSB JMP _startkernel TEXT _gdt<>(SB), 1, $-4 /* null descriptor */ LONG $0 LONG $0 /* (KESEG) 64 bit long mode exec segment */ LONG $(0xFFFF) LONG $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR) /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */ LONG $(0xFFFF) LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */ LONG $(0xFFFF) LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) TEXT _gdtptr64p<>(SB), 1, $-4 WORD $(4*8-1) QUAD $_gdt<>(SB) TEXT _idtptr64p<>(SB), 1, $-4 WORD $0 QUAD $0