[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