[Berlin-wireless] [OT] Re: IPv6 Routing-Konzepte fuer Freifunk

Alina Friedrichsen x-alina
Do Nov 26 01:53:30 CET 2009


> Trotzdem gefaellt mir die AMD64-Architektur. Hab mal just4fun meinen
> Assembler-Code angehaengt um die Kiste in den Long-Mode zu schalten. :)

Ups, das war der 32-Bit Code...

-------------- nächster Teil --------------
#
# Xorix Microkernel - a operating system microkernel
# Copyright (C) 2007  Alina Friedrichsen
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

MULTIBOOT_HEADER_FLAGS = 0x00000003
MULTIBOOT_HEADER_MAGIC = 0x1BADB002
MULTIBOOT_BOOTLOADER_MAGIC = 0x2BADB002

.extern panic32
.globl _start

.text
_start:
	jmp 0f

# Multiboot-Header (fuer GRUB)
	.align 4
	.long MULTIBOOT_HEADER_MAGIC
	.long MULTIBOOT_HEADER_FLAGS
	.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

# Testen, ob die ELF wirklich mit GRUB gebootet wurde
0:	cmp $MULTIBOOT_BOOTLOADER_MAGIC,%eax
0:	jne 0b

# Stack initialisieren
	movl $(tmp_stack + 1024),%esp

# ...
	movb $' ',0xb800a
	movb $' ',0xb800c

# Timer initialisieren
# 100 Hz (1193180 / 100 = 11932 = 0x2e9c)
	movb $0x34,%al		# Binary, Mode 2, LSB/MSB, SC 0
	outb %al,$0x43		# in das Steuerregister schreiben
	movb $0x9c,%al		# LSB in den
	outb %al,$0x40		# Zaehler 0 schreiben
	movb $0x2e,%al		# MSB in den
	outb %al,$0x40		# Zaehler 0 schreiben

############################################################################
# Testen ob AMD64 bzw. Intel 64 unterstuetzt wird                          #
############################################################################

# Wird der CPUID-Befehl unterstuetzt?
# Er wird es, wenn sich das ID-Flag (Bit 21) aendern laest
	pushfl
	popl %eax
	movl %eax,%ebx
	xorl $0x200000,%eax
	pushl %eax
	popfl
	pushfl
	popl %eax
	xorl %ebx,%eax
	jz 8f

# Benoetigte CPU Features testen
	movl $0x00000000,%eax
	cpuid
	cmpl $0x00000000,%eax
	jbe 8f
	movl $0x00000001,%eax
	cpuid
	btl $0,%edx		# FPU
	jnc 8f
	btl $3,%edx		# PSE
	jnc 8f
	btl $4,%edx		# TSC
	jnc 8f
	btl $5,%edx		# MSR
	jnc 8f
	btl $6,%edx		# PAE
	jnc 8f
	btl $8,%edx		# CMPXCHG8B
	jnc 8f
	btl $9,%edx		# APIC
	jnc 8f
	btl $13,%edx		# PGE
	jnc 8f
	btl $15,%edx		# CMOV
	jnc 8f
#	btl $16,%edx		# PAT (unterstuetzt bochs nicht)
#	jnc 8f
#	btl $19,%edx		# CLFSH (unterstuetzt bochs nicht)
#	jnc 8f
	btl $23,%edx		# MMX
	jnc 8f
	btl $24,%edx		# FXSR
	jnc 8f
	btl $25,%edx		# SSE
	jnc 8f
	btl $26,%edx		# SSE2
	jnc 8f

# Wird Long Mode unterstuetzt?
	movl $0x80000000,%eax
	cpuid
	cmpl $0x80000000,%eax
	jbe 8f
	movl $0x80000001,%eax
	cpuid
	btl $11,%edx		# SysCallSysRet
	jnc 8f
	btl $20,%edx		# NX
	jnc 8f
	btl $29,%edx		# LM
	jnc 8f
	jmp 9f

# AMD64 bzw. Intel 64 wird nicht unterstuetzt
8:	pushl $0
	call panic32

############################################################################
# Long Mode initialisieren                                                 #
############################################################################

# PAE (und PGE) fuer Long Mode aktivieren
# Paging wird erst mit diesen aktiviert
9:	movl %cr4,%eax
	btsl $5,%eax		# PAE
	btsl $7,%eax		# PGE
	movl %eax,%cr4

# PML4 initialisieren
	movl $tmp_pml4,%edi
	movl $tmp_pdp,%eax
	btsl $0,%eax		# Present (P) Bit setzen
	movl %eax,0x000(%edi)
	movl %eax,0xff8(%edi)

# PDP initialisieren
	movl $tmp_pdp,%edi
	movl $tmp_pd,%eax
	btsl $0,%eax		# Present (P) Bit setzen
	movl %eax,0x000(%edi)
	movl %eax,0xff0(%edi)

# PD initialisieren
	movl $tmp_pd,%edi
	xorl %eax,%eax
	btsl $0,%eax		# Present (P) Bit setzen
	btsl $7,%eax		# Page Size (PS) Bit setzen
	movl %eax,0x000(%edi)

# CR3 mit PML4 laden
	movl $tmp_pml4,%eax
	movl %eax,%cr3

# Long Mode einschalten
	movl $0x0c0000080,%ecx
	rdmsr
	btsl $8,%eax		# LME Bit setzen
	wrmsr

# Mit dem Paging den Long Mode aktivieren
	movl %cr0,%eax		# Paging aktivieren
	btsl $31,%eax		# 3... 2... 1...
	movl %eax,%cr0		# LIFT OFF! ;-)

	movb $':',0xb8000
	movb $')',0xb8002

############################################################################
# In den 64-Bit Kernel springen :)                                         #
############################################################################

# GDTR laden
	lgdt tmp_gdt_descriptor

# Let's go!
	ljmp $0x08,$kernel64

.data
kernel64:
	.incbin "kernel64.bin"

# Page-Map Level-4 Table
.align 4096
tmp_pml4:
	.fill 512,8,0

# Page-Directory-Pointer
.align 4096
tmp_pdp:
	.fill 512,8,0

# Page-Directory
.align 4096
tmp_pd:
	.fill 512,8,0

# Global Descriptor Table (GDT)
.align 8
tmp_gdt:
	.quad 0x0000000000000000	# 0x00 NULL
	.quad 0x0020980000000000	# 0x08 temporaeres Codesegment
	.quad 0x0020920000000000	# 0x10 temporaeres Datensegment

.align 8
.word 0
tmp_gdt_descriptor:
	.word 3 * 8 - 1
	.long tmp_gdt

# Kernel-Stack
	.comm tmp_stack,1024
-------------- nächster Teil --------------
#
# Xorix Microkernel - a operating system microkernel
# Copyright (C) 2007  Alina Friedrichsen
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

PHYS_OFFSET	= 0xffff800000000000
IO_OFFSET	= 0xfffffffe00000000
KERNEL_OFFSET	= 0xffffffff80000000

.extern setup
.globl _start

.text
_start:

# In den virtuellen Kernel Adressraum springen
	movq $0f, %rax
	jmp *%rax
0:	nop

############################################################################
# GDT und IDT initialisieren                                               #
############################################################################

# GDTR laden
	lgdt gdt_descriptor

# IDTR laden
	lidt idt_descriptor

# Segment Register fuer Long Mode laden
	movw $0x0010, %ax
	movw %ax, %ds
	movw %ax, %es
	movw %ax, %ss
	movw %ax, %fs
	movw %ax, %gs

# Stack initialisieren
	movq $(stack + 4096), %rsp

############################################################################
# Paging initialisieren                                                    #
############################################################################

# Mother PML4 initialisieren
	movq $mother_pml4, %rdi
	movq $phys_pdp, %rax	# Phys PDP
	subq $KERNEL_OFFSET, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	movq %rax, 0x800(%rdi)
	movq $kernel_pdp, %rax	# Kernel PDP
	subq $KERNEL_OFFSET, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	movq %rax, 0xff8(%rdi)

# Werden 1 GByte Pages unterstuetzt?
	movl $0x80000001,%eax
	cpuid
	btl $26,%edx		# Page1GB
	jnc 0f

# Phys PDP initialisieren (1 GByte)
	movq $phys_pdp, %rdi
	xorq %rax, %rax		# 0 bis 1 GByte
	btsq $0, %rax		# Present (P) Bit setzen
	btsq $7, %rax		# Page Size (PS) Bit setzen
	btsq $8, %rax		# Global (G) Bit setzen
	movq %rax, 0x000(%rdi)
	movq $0x100000000, %rbx
	addq %rbx, %rax		# 1 bis 2 GByte
	movq %rax, 0x008(%rdi)
	addq %rbx, %rax		# 2 bis 3 GByte
	movq %rax, 0x010(%rdi)
	addq %rbx, %rax		# 3 bis 4 GByte
	movq %rax, 0x018(%rdi)

# Kernel PDP initialisieren (1 GByte)
	movq $kernel_pdp, %rdi
	xorq %rax, %rax		# IO 0 bis 1 GByte
	btsq $0, %rax		# Present (P) Bit setzen
	btsq $4, %rax		# Page-Level Cache Disable (PCD) Bit setzen
	btsq $7, %rax		# Page Size (PS) Bit setzen
	btsq $8, %rax		# Global (G) Bit setzen
	movq %rax, 0xfc0(%rdi)
	movq $0x100000000, %rbx
	addq %rbx, %rax		# IO 1 bis 2 GByte
	movq %rax, 0xfc8(%rdi)
	addq %rbx, %rax		# IO 2 bis 3 GByte
	movq %rax, 0xfd0(%rdi)
	addq %rbx, %rax		# IO 3 bis 4 GByte
	movq %rax, 0xfd8(%rdi)
	xorq %rax, %rax		# Kernel 0 bis 1 GByte
	btsq $0, %rax		# Present (P) Bit setzen
	btsq $7, %rax		# Page Size (PS) Bit setzen
	btsq $8, %rax		# Global (G) Bit setzen
	movq %rax, 0xff0(%rdi)
	movq $0x100000000, %rbx
	addq %rbx, %rax		# Kernel 1 bis 2 GByte
	movq %rax, 0xff8(%rdi)
	jmp 1f

# Phys PDP initialisieren (2 MByte)
0:	movq $phys_pdp, %rdi
	movq $phys_pd, %rax	# Phys PD 0
	subq $KERNEL_OFFSET, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	movq %rax, 0x000(%rdi)
	addq $0x1000, %rax	# Phys PD 1
	movq %rax, 0x008(%rdi)
	addq $0x1000, %rax	# Phys PD 2
	movq %rax, 0x010(%rdi)
	addq $0x1000, %rax	# Phys PD 3
	movq %rax, 0x018(%rdi)

# Kernel PDP initialisieren (2 MByte)
	movq $kernel_pdp, %rdi
	movq $kernel_pd, %rax	# IO PD 0
	subq $KERNEL_OFFSET, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	movq %rax, 0xfc0(%rdi)
	addq $0x1000, %rax	# IO PD 1
	movq %rax, 0xfc8(%rdi)
	addq $0x1000, %rax	# IO PD 2
	movq %rax, 0xfd0(%rdi)
	addq $0x1000, %rax	# IO PD 3
	movq %rax, 0xfd8(%rdi)
	movq $kernel_pd, %rax	# Kernel PD 0
	subq $KERNEL_OFFSET, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	movq %rax, 0xff0(%rdi)
	addq $0x1000, %rax	# Kernel PD 1
	movq %rax, 0xff8(%rdi)

# Phys PDs bis 4 GByte initialisieren (2 MByte)
	movq $phys_pd, %rdi
	xorq %rax, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	btsq $7, %rax		# Page Size (PS) Bit setzen
	btsq $8, %rax		# Global (G) Bit setzen
	movl $2048, %ecx
	cld
0:	stosq
	addq $0x200000, %rax	# + 2 MByte
	decl %ecx
	jnz 0b

# IO PDs initialisieren (2 MByte)
	movq $io_pd, %rdi
	xorq %rax, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	btsq $4, %rax		# Page-Level Cache Disable (PCD) Bit setzen
	btsq $7, %rax		# Page Size (PS) Bit setzen
	btsq $8, %rax		# Global (G) Bit setzen
	movl $2048, %ecx
	cld
0:	stosq
	addq $0x200000, %rax	# + 2 MByte
	decl %ecx
	jnz 0b

# Kernel PDs initialisieren (2 MByte)
	movq $kernel_pd, %rdi
	xorq %rax, %rax
	btsq $0, %rax		# Present (P) Bit setzen
	btsq $7, %rax		# Page Size (PS) Bit setzen
	btsq $8, %rax		# Global (G) Bit setzen
	movl $1024, %ecx
	cld
0:	stosq
	addq $0x200000, %rax	# + 2 MByte
	decl %ecx
	jnz 0b

# CR3 mit PML4 laden
1:	movq $mother_pml4, %rax
	subq $KERNEL_OFFSET, %rax
	movq %rax, %cr3

############################################################################
# In den C-Code springen                                                   #
############################################################################

	movq $IO_OFFSET, %rdi
	movb $')', 0xb8004(%rdi)
	movb $')', 0xb8006(%rdi)
	call setup
	hlt

.data

# Mother Page-Map Level-4 Table
.align 4096
mother_pml4:
	.fill 512,8,0

# Kernel Page-Directory-Pointer
.align 4096
phys_pdp:
	.fill 512,8,0

.align 4096
kernel_pdp:
	.fill 512,8,0

# Page-Directorys
.align 4096
phys_pd:
	.fill 2048,8,0

.align 4096
io_pd:
	.fill 2048,8,0

.align 4096
kernel_pd:
	.fill 1024,8,0

# Global Descriptor Table (GDT)
.align 8
gdt:
	.quad 0x0000000000000000	# 0x00 NULL
	.quad 0x0020980000000000	# 0x08 Kernel Codesegment
	.quad 0x0020920000000000	# 0x10 Kernel Datensegment

.align 8
.word 0
gdt_descriptor:
	.word 3 * 8 - 1
	.quad gdt

# Interrupt Descriptor Table (IDT)
.align 8
idt:
	.fill 512, 8, 0

.align 8
.word 0
idt_descriptor:
	.word 256 * 16 - 1
	.quad idt

# Kernel Stack
	.comm stack, 4096, 4096



Mehr Informationen über die Mailingliste Berlin