flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Simple multicore INIT-SIPI-SIPI example

Author
Thread Post new topic Reply to topic
vitor19897



Joined: 24 May 2019
Posts: 2
vitor19897 24 May 2019, 23:32
Hello guys! I'm trying to use this simple example found at OsDev to enable all processor cores and execute code to print something at video memory.

That is the modified code i'm using. I want to power up in real mode, load the start APs code at address 07c0h:0400h = 0000:8000 and let all AP cores start at this address and print a letter.

You can note that i've put the BSP inside an infinite loop "jmp $". It is because i want to see if any core has woke up.

Could please anyone help me to understand why this is not working?
Thanks in advance!

////////////////////////////////
CODE
////////////////////////////////

Code:
format MZ

USE16
    
start:
        mov ax, cs
        mov ds, ax
        mov es, ax
        mov ss, ax
        xor sp, sp
        cld
        ;Clear screen         
           mov ax, 03h
           int 10h
        ;Move payload to the desired address
           mov si, payload
           mov cx, payload_end-payload + 1
           mov bx,es
           mov ax,7c0h
           mov es,ax
           mov di,400h                 ;07c0:400 = 8000h
           rep movsb
           mov es,bx
        ;Enable APIC table
           call enable_lapic
        ;Wakeup the other APs
          ;INIT
           call lapic_send_init
           mov cx, WAIT_10_ms
           call us_wait
          ;SIPI
           call lapic_send_sipi
           mov cx, WAIT_200_us
           call us_wait
          ;SIPI
           call lapic_send_sipi
           jmp $
         ; jmp 0000h:8000h ;jump to payload code


;Payload é o código que será movido para o endereço físico 0x08000
payload:
  mov ax, cs
  mov ds, ax
  xor sp, sp
  cld
  mov cx,0b800h
  mov es,cx
  mov di,00h
  mov al,41h
  stosb
  cli    ;retirado para debug
  hlt    ;retirado para debug

payload_end:

enable_lapic:
  mov ecx, IA32_APIC_BASE_MSR
  rdmsr
  or ah, 08h
  wrmsr
  and ah, 0f0h
  mov DWORD [APIC_BASE], eax
  shr eax,16
  mov bx,fs
  mov fs,ax
  mov ecx, DWORD [fs:APIC_REG_SIV]
  or ch, 01h    ;bit8: APIC SOFTWARE enable/disable
  mov DWORD [fs:APIC_REG_SIV], ecx
  mov fs,bx
  ret

IA32_APIC_BASE_MSR = 1bh
APIC_REG_SIV       = 0f0h
APIC_REG_ICR_LOW   = 300h
APIC_REG_ICR_HIGH  = 310h
APIC_REG_ID        = 20h

APIC_BASE         dd 00h

;CX = Wait (in ms) Max 65536 us (=0 on input)
us_wait:
  mov dx, 80h               ;POST Diagnose port, 1us per IO
  xor si, si
  rep outsb
  ret
  WAIT_10_ms     = 10000
  WAIT_200_us    = 200

lapic_send_init:
  mov eax, DWORD [APIC_BASE]
  xor ebx, ebx
  shr eax,16
  mov cx,fs
  mov fs,ax
  mov DWORD [fs:APIC_REG_ICR_HIGH], ebx
  mov ebx, 0c4500h
  mov DWORD [fs:APIC_REG_ICR_LOW], ebx  ;Writing the low DWORD sent the IPI
  mov fs,cx
  ret

lapic_send_sipi:
  mov eax, DWORD [APIC_BASE]
  xor ebx, ebx
  shr eax,16
  mov cx,fs
  mov fs,ax
  mov DWORD [fs:APIC_REG_ICR_HIGH], ebx
  mov ebx, 0c4608h
  mov DWORD [fs:APIC_REG_ICR_LOW], ebx  ;Writing the low DWORD sent the IPI
  mov fs,cx
  ret    
Edit by revolution: Added code tags
Post 24 May 2019, 23:32
View user's profile Send private message Send e-mail Reply with quote
Feryno



Joined: 23 Mar 2005
Posts: 514
Location: Czech republic, Slovak republic
Feryno 29 May 2019, 19:33
I think you can't access APIC in realmode as realmode limits address to 20 bits and APIC is usually at physical memory FEE00000 on poweron/reset.
So when you set FS to FEE0, then the mov dword [fs:...] is writing into physical memory FEE00 that's into region where BIOS is shadowed (usually E0000-FFFFF) and this mem region is usually readonly so any writing there is discarded.
I suggest you to switch to protected mode and map the PA of APIC into some VA. Note you should map it as noncacheable.
When you execute cli \ hlt this could be woken up by NMI so this is better:
Code:
@@:
cli
hlt
jmp @b    

Also note you sent INIT-SIPI to all but self so all APs start to run simultaneously at once so you can't execute any call either interrupt either anything which uses stack because you set all CPUs the same stack (SP=0, SS even not set). This could be solved by assigning unique stack for every AP. But your payload is simple enough and does not use any instruction which uses stack.
Your payload is the same for all APs so when (in the feature) your code starts to do what do you want it to do, you won't know which AP wrote the byte 41h to the upper left corner of your textmode screen. Instead of setting di to 0 (mov di,00h) for every AP, this is better:
Code:
mov di,2
lock xadd [position],di
mov al, 41h
mov ah,... ; also set AH register to some well visible color
stosw
@@:
cli
hlt
jmp @b
position dw 0 ; intially the position set to 0    

that way you will see the count of APs started

So simple answer to your question is: Code is not working due to realmode limitation.
Post 29 May 2019, 19:33
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
vitor19897



Joined: 24 May 2019
Posts: 2
vitor19897 30 May 2019, 12:09
Hi Feryno! Thank you very much for your reply!

I missed that the APIC base address is an absolute address because how I read the APIC_BASE_MSR and it returns FEE00000 in real mode, I assumed that it is a segment:offset address. Now I know why it is not working. I need to go to protected or unreal mode to do that.

1 - Could you please help me to understand why using "cli \ hlt" can be woken up by NMI? Probably I do not understand because I do not know what is "@@" and "@b".

2 - "PA of APIC into some VA". What is PA and VA?
Post 30 May 2019, 12:09
View user's profile Send private message Send e-mail Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 30 May 2019, 12:50
I’ll try to answer to possibly save your time.
vitor19897 wrote:
1 - Could you please help me to understand why using "cli \ hlt" can be woken up by NMI? Probably I do not understand because I do not know what is "@@" and "@b".

Because it’s the nature of NMI, what makes it a non-maskable interrupt: disabling interrupts by CLI (setting IF to zero) doesn’t disable NMI.

vitor19897 wrote:
2 - "PA of APIC into some VA". What is PA and VA?

From the context, PA stands for physical address, VA stands for virtual address.
Post 30 May 2019, 12:50
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.