blob: 85117147669efe9b2b3f1ad79ff23b7d857221ac [file] [log] [blame]
// 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