// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Manipulation of segment tables. // // Descriptor entry format for system call // is the native machine format, ugly as it is: // // 2-byte limit // 3-byte base // 1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type // 1-byte: 0x80=limit is *4k, 0x40=32-bit operand size, // 0x0F=4 more bits of limit // 1 byte: 8 more bits of base // Called to set up memory hardware. // Already running in 32-bit mode thanks to boot block, // but we need to install our new GDT that we can modify. TEXT runtime·msetup(SB), 7, $0 MOVL runtime·gdtptr(SB), GDTR MOVL $(1*8+0), AX MOVW AX, DS MOVW AX, ES MOVW AX, SS MOVW $0, AX MOVW AX, FS MOVW AX, GS // long jmp to cs:mret BYTE $0xEA LONG $runtime·mret(SB) WORD $(2*8+0) TEXT runtime·mret(SB), 7, $0 RET // GDT memory TEXT runtime·gdt(SB), 7, $0 // null segment LONG $0 LONG $0 // 4GB data segment LONG $0xFFFF LONG $0x00CF9200 // 4GB code segment LONG $0xFFFF LONG $0x00CF9A00 // null segment (will be thread-local storage segment) LONG $0 LONG $0 // GDT pseudo-descriptor TEXT runtime·gdtptr(SB), 7, $0 WORD $(4*8) LONG $runtime·gdt(SB) // Called to establish the per-thread segment. // Write to gdt[3] and reload the gdt register. // setldt(int entry, int address, int limit) TEXT runtime·setldt(SB),7,$32 MOVL address+4(FP), BX // aka base MOVL limit+8(FP), CX // set up segment descriptor LEAL gdt+(3*8)(SB), AX // gdt entry #3 MOVL $0, 0(AX) MOVL $0, 4(AX) MOVW BX, 2(AX) SHRL $16, BX MOVB BX, 4(AX) SHRL $8, BX MOVB BX, 7(AX) MOVW CX, 0(AX) SHRL $16, CX ANDL $0x0F, CX ORL $0x40, CX // 32-bit operand size MOVB CX, 6(AX) MOVB $0xF2, 5(AX) // r/w data descriptor, dpl=3, present MOVL runtime·gdtptr(SB), GDTR // Compute segment selector - (entry*8+0) MOVL $(3*8+0), AX MOVW AX, GS RET