Всем привет!
Пытался завести smp, исходники брал
https://github.com/pdoane/osdev - не завелось) Но это другой разговор. И на какое время забросил все, пока не наткнулся на
http://stackoverflow.com/questions/9809 ... -look-likeТам в
камменте есть код запуска AP колхозным способом - без парсинга таблиц, напрямую писать в регистр(предполагая, что по этому адресу таки отражен регистр). Так делать нельзя
ICR_LOW = 0xFEE00300
Код:
MOV ESI, ICR_LOW ; Load address of ICR low dword into ESI.
MOV EAX, 000C4500H ; Load ICR encoding for broadcast INIT IPI
; to all APs into EAX.
MOV [ESI], EAX ; Broadcast INIT IPI to all APs
; 10-millisecond delay loop.
MOV EAX, 000C46XXH ; Load ICR encoding for broadcast SIPI IP
; to all APs into EAX, where xx is the vector computed in step 10.
MOV [ESI], EAX ; Broadcast SIPI IPI to all APs
; 200-microsecond delay loop
MOV [ESI], EAX ; Broadcast second SIPI IPI to all APs
; Waits for the timer interrupt until the timer expires
У меня получился такой код
Вот что он должен делать:
-копировать trampoline код для AP по известному адресу, у нас это 0x1000 - вектор 0x01 (это то, что мы отправляем SIPI IP)
-выполнять INIT-SIPI-SIPI
-AP должен выполнить trampoline код, который инкрементирует переменную по известному адресу - 0x2000
Код:
.equ STARTUP_CODE_ADDRESS, 0x1000
.equ SPINLOCK_ADDRESS, 0x2000
/* PIC */
.equ PIC_ICR_ADDRESS, 0xFEE00300
.equ IA32_APIC_BASE, 0x1B
/* Must come before they are used. */
.equ CODE_SEG, 8
.equ DATA_SEG, gdt_data - gdt_start /* 10 */
.code16
.global _start
_start:
cli
xor %ax, %ax
mov %ax, %ds
lgdt gdt_descriptor
mov %cr0, %eax
orl $0x1, %eax
mov %eax, %cr0
ljmp $CODE_SEG, $protected_mode
.code32
protected_mode:
mov $DATA_SEG, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
/*
Копируем trampoline код, теперь он доступен по адресу 0x1000
*/
cld
movl $init_len, %ecx
movl $init, %esi
movl $STARTUP_CODE_ADDRESS, %edi
rep movsb
/* Обнуляем SPINLOCK_ADDRESS - общая для всех процессоров переменная*/
movb $0x00, SPINLOCK_ADDRESS
/* Включаем APIC */
movl $IA32_APIC_BASE, %ecx
rdmsr
bts $11, %eax
wrmsr
/* Load address of ICR low dword into ESI. */
movl $PIC_ICR_ADDRESS, %esi
/* Load ICR encoding for broadcast INIT IPI to all APs. */
movl $0x000C4500, %eax
/* Broadcast INIT IPI to all APs */
movl %eax, (%esi)
/* 10-millisecond delay loop. */
movl $0x000fffff,%ecx
delay10:
dec %ecx
jnz delay10
/*
Load ICR encoding for broadcast SIPI IP to all APs.
The low byte of this is the vector which encodes the staring address for the processors!
This address is multiplied by 0x1000: processors start at CS = vector * 0x100 and IP = 0.
mov $0x000C4600 + STARTUP_CODE_ADDRESS / 0x1000, %eax
*/
movl $0x000C4601, %eax
/* Broadcast SIPI IPI to all APs. */
movl %eax, (%esi)
/* 200-microsecond delay loop. */
/* Broadcast second SIPI IPI to all APs */
movl %eax, (%esi)
/* Здесь ждем запуска 3-х процессоров */
not_started:
cmpb $3, SPINLOCK_ADDRESS
jne not_started
ok:
movl $0x254B254F, 0xb8000 //print 'OK'
hlt
/* Trampoline код */
.code16
init:
cli
cld
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
incb SPINLOCK_ADDRESS
wbinvd
hlt
.equ init_len, . - init
/* GDT */
gdt_start:
gdt_null:
.long 0x0
.long 0x0
gdt_code:
.word 0xffff
.word 0x0
.byte 0x0
.byte 0b10011010
.byte 0b11001111
.byte 0x0
gdt_data:
.word 0xffff
.word 0x0
.byte 0x0
.byte 0b10010010
.byte 0b11001111
.byte 0x0
gdt_end:
gdt_descriptor:
.word gdt_end - gdt_start
.long gdt_start
.org 510
.word 0xaa55
Makefile
Код:
MAIN := main.img
$(MAIN): main.S
$(AS) -o main.o '$<'
$(LD) --oformat binary -o '$@' -Ttext 0x7C00 main.o
clean:
rm -f '$(MAIN)'
run: $(MAIN)
qemu -smp 4 -fda '$(MAIN)'