Page 1 of 1

APIC problem

Posted: Sun Jul 10, 2011 10:22 am
by BOTOKILLER
Hi everyone!
I'm trying to implement SMP in my OS, but I wouldnt make this post if everything went OK #-o
Here is code:

Code: Select all

        USE16
        ORG 0h

        ;!!NOT ASSEMBLED!!
        CONSTANTS:
        CodeSeg_32 equ 50h
        GDS equ 48h
        SDA equ 800h

        CONSTANTS_END:
        ;!!ASSEMBLED!!

        BEGIN:

        jmp START

        DATASECT:

        DAP:
        DAP_Size             db 10h         ;1h
        DAP_Res1             db 0           ;2h
        DAP_Bytes2Transfer   db 1h          ;3h
        DAP_Res2             db 0           ;4h
        DAP_Buff_Addr1       dw 0h          ;6h
        DAP_Buff_Addr2       dw 1F0h        ;8h
        DAP_LBA              dq 3h          ;9h

        DAT_Disk_Num         db 80h         ;12h          number of device 80h-winchester
        DAT_Num_Of_Sects     dw 20h         ;13h          the number of 512byte sectors, that contain your kernel

        END_DAP:

        VID:
        VID_Cursor           dw 0h          ;15h
        END_VID:

        GDT:
        dw  GDT_ENDS - GDT_STARTS - 1h      ;17h
        dd  80000h + GDT_STARTS
        GDT_STARTS:

        ;Records:
        ; 1.-CER-00- Kernel Code segment
        ; 2.-DRW-00- Global Data Segment
        ; 3.-DRO-11- SDA
        ; 4.-DRW-00- NON Permanent Data
        ; 5.-DRW-00- System Stack
        ; 6.-DRW-00- Process Table
        ; 7.-DRO-00- FONT
        ; 8.-DRO-11- NON Permanent data area (For aplications)
        ; 9.-DRW-00- Process Space
        ;10.-CER-00- Temporary almight Code Segment


        REC0:
                             dq 0h
        REC1:
        Limit_0_15            dw 01000h
        Base_0_15             dw 02C00h
        Base_16_23            db 0h
        Access                db 10011010b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        LimAndFlags           db 01000000b;||Granularity||1||0||0||Limit 16-19||
        Base_24_31            db 0h

        REC2:
        aLimit_0_15           dw 0FFFFh
        aBase_0_15            dw 0h
        aBase_16_23           db 0h
        aAccess               db 10010010b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        aLimAndFlags          db 11001111b;||Granularity||1||0||0||Limit 16-19||
        aBase_24_31           db 0h

        REC3:
        bLimit_0_15           dw 1FFh
        bBase_0_15            dw 800h
        bBase_16_23           db 0h
        bAccess               db 11110000b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        bLimAndFlags          db 01000000b;||Granularity||1||0||0||Limit 16-19||
        bBase_24_31           db 0h

        REC4:                                                                       ;
        cLimit_0_15           dw 0FFFh
        cBase_0_15            dw 0A00h
        cBase_16_23           db 0h
        cAccess               db 10010010b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        cLimAndFlags          db 01000000b;||Granularity||1||0||0||Limit 16-19||
        cBase_24_31           db 0h

        REC5:
        dLimit_0_15           dw 04FFh
        dBase_0_15            dw 1A00h
        dBase_16_23           db 0h
        dAccess               db 10010010b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        dLimAndFlags          db 01000000b;||Granularity||1||0||0||Limit 16-19||
        dBase_24_31           db 0h

        REC6:
        eLimit_0_15           dw 03FFh
        eBase_0_15            dw 1F00h
        eBase_16_23           db 0h
        eAccess               db 10010010b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        eLimAndFlags          db 01000000b;||Granularity||1||0||0||Limit 16-19||
        eBase_24_31           db 0h

        REC7:
        fLimit_0_15           dw 0FFh
        fBase_0_15            dw 2300h
        fBase_16_23           db 0h
        fAccess               db 10010000b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        fLimAndFlags          db 01000000b;||Granularity||1||0||0||Limit 16-19||
        fBase_24_31           db 0h



        ; ______________________________________________
        ;| MEMORY HOLE OF 2048d BYTES FOR IDT           |
        ;|______________________________________________|


        REC8:
        gLimit_0_15           dw 0FFFh
        gBase_0_15            dw 0A00h
        gBase_16_23           db 0h
        gAccess               db 11110000b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        gLimAndFlags          db 01000000b;||Granularity||1||0||0||Limit 16-19||
        gBase_24_31           db 0h

        REC9:                      ; this segment will define memory space of programms depending on memory map
        iLimit_0_15           dw 0h
        iBase_0_15            dw 0h
        iBase_16_23           db 0h
        iAccess               db 10011010b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        iLimAndFlags          db 11000000b;||Granularity||1||0||0||Limit 16-19||
        iBase_24_31           db 0h



        REC10:
        hLimit_0_15           dw 0FFFFh
        hBase_0_15            dw 0h
        hBase_16_23           db 0h
        hAccess               db 10011000b;||Present bit||Priviligies||1||Code-1, Data - 0||if want to execute from low levels - 1, else 0|| can write here? yes=1||0||
        hLimAndFlags          db 11001111b;||Granularity||1||0||0||Limit 16-19||
        hBase_24_31           db 0h

        GDT_ENDS:


        ;FINALY OS IS MAPPED LIKE THIS
        ; 00000000h | 000007FFh | GDT (descriptor + 255 entries)
        ; 00000800h | 000009FFh | SDA(system data area)
        ; 00000A00h | 000019FFh | non permanent data area(cursor, mouse coords, time, config tables etc) in 2 segments 00 and 11 privl - 4096 bytes
        ; 00001A00h | 00001EFFh | SYSTEM STACK (1280 bytes)
        ; 00001F00h | 000022FFh | PT(process table)
        ; 00002300h | 000023FFh | FONT for keyboard to ASCII translation
        ; 00002400h | 00002BFFh | IDT (255 entries + descriptor)
        ; 00002C00h |     x     | kernel code(ints inside)
        ;
        ;
        ; 000A0000h | 000AFFFFh | Video Video Memory
        ; 000B8000h | 000BFFFFh | Text Video Memory


        END_DATASECT:

        ERROR:
        nop
        nop
        jmp ERROR

        START:
        mov ax, 8000h
        mov ds, ax
        xor ax, ax
        mov fs, ax
        mov ax, 9000h
        mov ss, ax
        mov esp, 0500h
        mov ax, 80h
        mov gs, ax
        mov bp, BEGIN

        ;here is it! everything prepared
        ;ds,cs - point to this segment
        ;es points to b800h
        ;ss points to higher place
        ;gs points to the first secto of kernel
        ;bp points to the start of datasect
        ;fs points to 0
        ; its time for action!

        LOAD_KERN:                              ; service for reading data from disk specified DAT_Disk_Num
        mov ah, 42h
        xor al, al
        mov dl, [cs:bp+12h]
        mov si, DAP
        mov cx, [cs:bp+13h]

        READ_LOOP:
        pusha
        int 13h
        jc ERROR
        popa
        add word [ds:si+6h], 20h
        inc byte [ds:si+8h]
        loop READ_LOOP                          ; service ends here
        END_LOAD_KERN:

        ;data loaded to 1F00h starting with process table
        ;
        mov ax, 80h
        mov gs, ax

        COLLECT_DATA:

        DETECT_VENDOR:
        xor eax, eax
        cpuid
        mov [gs:0h], ecx

        MEMORY_MAP:
        mov byte [gs:180h], 0h
        mov di, gs
        mov es, di
        mov di, 181h
        xor ebx, ebx
        mov edx, 534D4150h

        MM_LOOP:
        mov eax, 0E820h
        mov ecx, 24d
        int 15h
        jc ERROR
        add di, 24d
        inc byte [gs:180h]
        cmp ebx, 0h
        jne MM_LOOP


        ;here we loaded SDA(System Data Area) with following
        ;_SDA_________________________________________________
        ;800h(dd) vendor: 'ntel' - Intel
        ;804h(dd) ROOT COMPLEX BASE ADDRESS
        ;808h(dd) MP TABLE ADDRESS
        ;80Ch(db) !!??!!
        ;80Dh(dw) !!??!!
        ;80Fh(db) ACPI version number (WILL COLLECT IN PM)
        ;810h(dd) RSDT tables !PHYSICAL! address  (WILL COLLECT IN PM)
        ;814h(dd) FADT TABLE ADDRESS !PHYSICAL! (WILL COLLECT IN PM)
        ;818h(db) NUMBER OF IO APICS PRESENT
        ;819h(dd) IO APIC-1 CONFIG ADDRESS
        ;81Dh(db) IO APIC-1 ID
        ;81Eh(dd) IO APIC-2 CONFIG ADDRESS
        ;822h(db) IO APIC-2 ID
        ;823h(10b) RESERVED (for future additional io apics)
        ;82Dh(dd) LAPIC ADDRESS
        ;831h(db) NUMBER OF CPUS IN SYSTEM (UP TO 4 WILL BE SUPPORTED)
        ;832h(11b) CPU1
        ;83Dh(11b) CPU2
        ;848h(11b) CPU3
        ;853h(11b) CPU4
        ;85Eh(
        ;
        ;
        ;
        ;
        ;FREE SPACE...
        ;
        ;980h(db) number of memory map tables entries
        ;981h(  ) memory map
        ;______________________________________________________
        ;!!??!! == reserved
        ;done
        ; its time to set up our kernel for pmode

        PMJMP:
        cli

        lea eax, [cs:bp+17h]
        lgdt [eax]

        mov ax, 0x2401
        int 0x15

        mov eax, cr0
        or eax, 1h
        mov cr0, eax
        jmp pword CodeSeg_32:80000h+PMODE

        USE32
        PMODE:                                   ;congrates! we are in PM!


        ;!!!TEMPORARY!!!
;        PIC_CONFIG:                              ;configuring PIC
 ;       mov al, 11h
  ;      out 20h, al
   ;     out 0A0h, al
    ;    mov al, 20h                              ;IRQ0-7 = ints 20h-27h
     ;   out 21h, al                              ;IRQ8-16 = ints 28h-2Fh
      ;  mov al, 28h
       ; out 0A1h, al
        ;mov al, 4h                               ;some master/slave setup
;        out 21h, al
 ;       mov al, 2h
  ;      out 0A1h, al
   ;     mov al, 1h                               ;i dont know what this does
    ;    out 21h, al
     ;   out 0A1h, al
      ;  MASK:                                    ; mask ints to allow every int
       ; mov al, 0h
        ;out 0A1h, al
;        out 21h, al


        SETREG32:                                ; here it loads segment registers and esp
        mov ax, 10h
        mov ds, ax
        mov fs, ax
        mov es, ax
        mov gs, ax
        mov ax, 30h
        mov ss, ax
        mov esp, 4FFh
        ;ds,fs, es, gs = 10h
        ;ss = 30h
        ;esp = 4FFh
        ;cs = 50h(temporory 'almight' code segment)
        ;
        ;All right! Lets configure the rest of ****...


        MAKE_IT_WORK:                              ;sets up GDT table to its working location and loads IDT and sets IOPL to 00
        mov ebp, 80000h+17h
        xor esi, esi
        mov ecx, GDT_ENDS - GDT_STARTS + 6d
        call MOVE_BLOCK
        mov dword [ds:2h], 6h
        lgdt [0h]
        lidt [02400h]                                     ;relocate GDT and IDT to its working location

        SET_FLAGS_PRIVL:
        pushfw
        and word [ss:esp], 0CFFFh
        popfw


        ;LATER I WILL SCAN MEMORY HERE...

        ; NOW WE CONFIGURE HARDWARE........

        ACPI:                                           ; parsing ACPI tables
        RDSP:
        mov ax, [ds:40Eh]
        mov bx, 10h
        mul bx
        mov ebx, eax
        mov ecx, 100000h
        sub ecx, ebx
        mov eax, 'RSD '
        call ROM_SRC

        SAVE_RSDT:
        mov al, [ds:ebx+ecx+0Fh]
        mov [ds:80Fh], al
        mov eax, [ds:ebx+ecx+10h]
        mov [ds:810h], eax

        LOCATE_TABLES:
        mov ebx, [ds:810h]
        mov eax, [ds:ebx+4]
        sub eax, 32d
        mov ecx, 4h
        div cl
        xchg eax, ecx
        push ecx
        mov eax, 'FACP'
        call IDEN_TABLE
        mov [ds:SDA+14h], edi
        ; maybe more when I need ...

        _MP_:

        FPS:                              ;looking for floated point structure
        mov ax, [ds:40Eh]
        mov bx, 10h
        mul bx
        mov ebx, eax
        mov ecx, 100000h
        sub ecx, ebx
        mov eax, '_MP_'
        call ROM_SRC

        SAVE_FPS:
        mov eax, [ds:ebx+ecx+4h]
        mov [ds:SDA+8h], eax
        mov edx, [ds:eax+36d]
        mov [ds:SDA+2Dh], edx

        READ_MP_:                       ;parsing mp tables and place extracted data to system data area
        mov ebx, eax
        xor ecx, ecx
        mov cl, 44d
        call RMP_

        ENABLE_APIC:

        DISABLE_PIC:
        mov al, 0FFh
        out 21h, al
        out 0A1h, al          ; OSDEV wiki says thats the way to disable pic

        IMCR:
        mov al, 70h
        out 22h, al
        mov al, 1h
        out 23h, al          ;IMCR - in case BIOS didnt take care of it

        SPURIOUS_INTS_REG:       ;trying to enable APIC through Spurious ints reg
        mov ebx, [ds:SDA+2Dh]             ; lapic address
        or dword [ds:ebx+0F0h], 100h


        MSR_IA32_APIC_BASE_ENABLE_BT:   ;trying to enable LAPIC through MSR
        xor ecx, ecx
        mov cl, 1Bh
        rdmsr
        or edx, 800h
        wrmsr                                    

        ;now its time for IOAPIC.....
        RCBA:                                    ; getting root complex base address
        mov eax, 8000F8F0h
        call PCI_READ
        mov [ds:SDA+4h], eax             ; saving to System Data Area

        IOAPIC:         
        mov edi, [ds:SDA+4h]               ;ICH specs say that i have to set bit 1 of RCBA+31FFh to enable IO APIC
        add edi, 31FFh
        mov eax, [ds:edi]
        or eax, 1
        mov [ds:edi], eax
        mov eax, [ds:edi]                    ; and read that reg once again to ... I dont know - spec say I have to

        ASSIGN_IDS:
        cmp byte [ds:SDA+18h], 0h                 ; if no IO APICs - go to endless loop
        jz LOOLP
        xor ecx, ecx
        mov cl, [ds:SDA+18h]                         ; moving number of IO APICs to counter

        LP_ASSIGN:
        mov al, [ds:SDA+1Dh+(ecx*5)]            ;assigning APIC ID retrieved from MP
        shl eax, 16d
        mov ebx, [ds:SDA+19h+(ecx*5)]          ; getting address of current IO APIC
        xor edx, edx
        mov [ds:ebx], edx
        mov [ds:ebx+10h], eax                       ;configuring IO APIC ID
        loop LP_ASSIGN






        sti

        LOOLP:
        nop
        jmp LOOLP

        MOVE_BLOCK:                              ; function that moves block of data specified from ds:ebp to ds:esi with length ecx
        mov al, [ds:ebp+ecx-1]
        mov [ds:esi+ecx-1], al
        loop MOVE_BLOCK
        ret

        IDEN_TABLE:
        mov edi, [ds:ebx+((ecx-1)*4)+36d]
        cmp eax, [ds:edi]
        je RET_PT
        loop IDEN_TABLE
        jmp LOOLP
        RET_PT:
        ret


        ROM_SRC:
        cmp eax, [ds:ebx+ecx]
        je RET_PT_SRC
        loop ROM_SRC

        RET_PT_SRC:
        ret


        RMP_:                                     ;parsing MP tables
        cmp byte [ds:ebx+ecx], 1h
        jb FOUND_PROC
        je FOUND_BUS
        cmp byte [ds:ebx+ecx], 3h
        jb FOUND_IOAPIC
        jae FOUND_IRQSRC

        FOUND_PROC:
        cmp byte [ds:SDA+31h], 4h
        ja F_PR_OF
        xor eax, eax
        mov al, [ds:SDA+31h]
        mov dl, 11d
        mul dl
        xchg edx, eax
        mov eax, [ds:ebx+ecx+1]
        mov [ds:edx+SDA+32h], eax
        mov eax, [ds:ebx+ecx+5]
        mov [ds:edx+SDA+32h+4], eax
        mov eax, [ds:ebx+ecx+9]
        mov [ds:edx+SDA+32h+8], eax
        inc byte [ds:SDA+31h]

        F_PR_OF:
        add ecx, 14h
        jmp DEC_LOOP_RMP

        FOUND_BUS:
        jmp F_8BT

        FOUND_IOAPIC:
        cmp byte [ds:SDA+18h], 2h
        ja F_8BT
        bt word [ds:ebx+ecx+3], 0
        jae F_8BT
        xor edx, edx
        mov dl, [ds:SDA+18h]
        mov al, [ds:ebx+ecx+1]
        mov [ds:SDA+1Dh+edx*5], al
        mov eax, [ds:ebx+(ecx+4)]
        mov [ds:SDA+19h+(edx*5)], eax
        inc byte [ds:SDA+18h]
        jmp F_8BT

        FOUND_IRQSRC:
        jmp F_8BT

        F_8BT:
        add cx, 8h

        DEC_LOOP_RMP:
        cmp cx, [ds:ebx+4h]
        jb RMP_

        RET_PT_RMP:
        ret

        PCI_READ:                ;eax == address
        mov dx, 0CF8h
        out dx, eax
        mov dx, 0CFCh
        in eax, dx
        ret                      ;eax == input

        PCI_WRITE:               ;eax == address, ebx == output
        mov dx, 0CF8h
        out dx, eax
        mov dx, 0CFCh
        xchg ebx, eax
        in eax, dx
        ret                      ; no output...




        times 175d     db 0      ;total must be 1024d
        db 'F'

                                                                                           
It's second stage of bootloader(the kernel with IDT was working fine with PIC), I tryed every way of enabling APIC listed in wiki, ICH and other Intel specs but IRQs doent fire(It works till the end without error messages). What do I need to do so that IRQs work???

Re: APIC problem

Posted: Sun Jul 10, 2011 10:49 am
by Combuster
The Forum Rules wrote:You need to be precise and informative. This end is not served by simply dumping huge volumes of code or data into a help request. If you have a large, complicated test case that is breaking a program, try to trim it and make it as small as possible.

This is useful for at least three reasons. One: being seen to invest effort in simplifying the question makes it more likely you'll get an answer, Two: simplifying the question makes it more likely you'll get a useful answer. Three: In the process of refining your bug report, you may develop a fix or workaround yourself.
That said, I see that you assume an specific ICH10 version without a check, you do dword reads, you do that on an 8-bit register, and you even manage to access two different mmio ranges with the same access.

Re: APIC problem

Posted: Sun Jul 10, 2011 11:51 am
by BOTOKILLER
Combuster wrote:
The Forum Rules wrote:You need to be precise and informative. This end is not served by simply dumping huge volumes of code or data into a help request. If you have a large, complicated test case that is breaking a program, try to trim it and make it as small as possible.

This is useful for at least three reasons. One: being seen to invest effort in simplifying the question makes it more likely you'll get an answer, Two: simplifying the question makes it more likely you'll get a useful answer. Three: In the process of refining your bug report, you may develop a fix or workaround yourself.
That said, I see that you assume an specific ICH10 version without a check, you do dword reads, you do that on an 8-bit register, and you even manage to access two different mmio ranges with the same access.
The thing is not about ICH, its about implementing SMP and mapping IO APIC IRQs

Re: APIC problem

Posted: Sun Jul 10, 2011 12:32 pm
by Combuster
And giving you a chance only reminded me why you got banned. Sigh. :(