[Bochs] Physical address not available

0

Przy włączeniu stronnicowania w BOCHS'ie następne ładowanie instrukcji odbywa się spod adresu ??? (physical address not available). Kod jest taki:

KERN.ASM

[BITS 32]
[global start]
[extern main]

[SECTION .text]

start:
    mov esp, 0xc0f00000
    mov ebp, esp
    push 0x20C00
    push 0xC007F400         ; Only first 32 MB is usable, say it to kernel
    call main
    cli
    hlt
[global storeb]   ; Reverse Order     ( Destination, Size, Value)
storeb:
        push ebp
        mov ebp, esp
        push edi
        push ecx
        push eax
        mov edi, [ebp+8]
        mov ecx, [ebp+12]
        mov al, byte [ebp+16]
        rep stosb
        pop eax
        pop ecx
        pop edi
        pop ebp
        ret
[global poked]
poked:              
    push ebp
    mov ebp, esp
    push eax
    push ebx
    mov ebx, [ebp+8]    
    mov eax, [ebp+12]
    mov dword [ds:ebx], eax
    pop ebx
    pop eax
    pop ebp
    ret
[global init_os]
init_os:
    push ebp
    mov ebp, esp
    push eax    
    mov eax, [ebp+8]
    mov cr3, eax
    mov eax, cr0
    or eax, 0x80000000          ; Set Paging Bit
    mov cr0, eax                ; Fire PAGING!

           <b> I tu właśnie fetch następuje spod ??? Stos nie jest mapowany do przestrzeni adresowej, ale jak wsadzi tu NOP'a to też nie działa</b>

    pop eax
    pop ebp
    ret

KERNEL.C

extern void init_os(unsigned int pgdir_addr);
extern void writecr3(unsigned int cr3);
extern unsigned int readcr3();
extern void pokeb(unsigned int address, unsigned char value);
extern void pokew(unsigned int address, unsigned short int value);
extern void poked(unsigned int address, unsigned int value);
extern unsigned char peekb(unsigned int address);
extern void memcpy(unsigned int start, unsigned int destination, unsigned int size);
extern void storeb(unsigned char value, unsigned int size, unsigned int destination);

void write_pe(unsigned int address, unsigned short int number, unsigned int pointer, unsigned char mode)
{   
    poked(address+number*4, 0);         // Format the Area
    poked(address+(number*4), (pointer*2048)+mode);

}

int main(unsigned int mem_start, unsigned int mem_size)
{
    storeb(0x00,0x20000,0xC007F000);        // Format VMM Table
    storeb(0xFF,0x00020,0xC007F000);        // Reserve first megabyte

        storeb(0xFF,mem_size,mem_start);            // Mark unavailable memory

    // Write Management Zone PGTBL #1 to PGDIR
    write_pe(0xC007E000,960,0x0007C000,11);

    // Write Kernel Code PGTBL #1 to PGDIR
    write_pe(0xC007E000,768,0x0007D000,11);

    // Write Kernel Page #1 to Kernel Code PGTBL
    write_pe(0xC007D000,000,0x00000000,9);

    init_os(0x0007E000);
}

Gdzie jest błąd? Może funkcja do zapisu PGE i PTE działa źle, czy coś innego tam siedzi?

0

Witam.
nie przeglądałem kodu, ale do wykonania skoku po włączeniu stronnicowania instrukcje pobierane są tak jak przed włączeniem. Nie popatrzyłem jak mapujesz kernel'a ale ja mapuje na 3 GB ramu i mam taki kodzik:

       call _init_paging
       mov cr3, eax
       mov eax, cr0
       ;or eax, 80000000h
       ;or eax,80010000h   ; set the 486 WP (page write protect) bit
       or eax,0C0010000h  ; set the 486 CE (cache enable) and WP bits
       mov cr0, eax
       jmp CODE_SEL:paging_enabled

paging_enabled: ;Już mamy jądro na 3 GB RAM'u

I też mi się procesor resetował gdy nie zmapowałem kernel'a tak że adres fizyczny = wirtualny. Aha i prawdź na innym emulatorze lub prawdziwym kompie. Mój OS nie chciał chodzić na VMware, a na Virtual PC i prawdziwym kompie chodził :>
Pozdro.

0

Kernel jest tak zmapowany przez selektory(segmentacja) że wykonuje się na 3 GB RAM'u. Także żadnych skoków nie wykonuję.

Nie piszę ze swojego accounta bo mam problemy z logowaniem(taki użytkownik jest już zalogowany w systemie!)

0

Z tego co wiem po włączeniu stronnicowania trzeba wykonać stok aby unieważnić cache procka.

0
Next at t=1049136
(0) [0x000000bc] 0008:c00000bc (unk. ctxt): mov cr0, eax              ; 0f22c0
<bochs:10>
Next at t=1049137
(0).[1049137] ??? (physical address not available)
<bochs:11>

Wydruk z debuggera jest taki. Więc on ŻADNEJ INSTRUKCJI POTEM NIE WYKONUJE

0

Aha - jeszcze jedno - kiedy kazałem BOCHS'owi(commandline debuggera) wyczytać mi pamięć linear(przed translacją) z 3 GB (tam gdzie kernel) to pokazywało pamięć dość dziwną(na pewno nie kernela), zaś kiedy kazałem z 0x0 czy innego adresu który powinien być błędny to prawidłowo wyskakiwał error.

/ dopisane /

Ten kod pełen jest szkolnych błędów :) ale mimo to chciałbym wiedziec o co chodzi w tym physical address not available.

/ dopisane /)

Problem został nieco uproszczony. Teraz nawalają te linijki(DS base=0x0 limit=0xffffffff):

mov [ds:SYS_PGDIR+0xC00], dword KERNEL_PGTBL | 3;
mov [ds:KERNEL_PGTBL]   , dword 3
            ; Configure PDBR and enable paging
mov eax, SYS_PGDIR
mov cr3, eax
mov eax, cr0
or eax, 0x80000000
mov cr0, eax

; i tu jest fajny fetch znikąd

jmp 08h:paging_ok  ;(skacz pod paging_ok(org 0x0)+0xc0000000)
paging_ok:

SYS_PGDIR equ 0x7E000
KERNEL_PGTBL equ 0x7D000

Co tu zdycha?

0

Może jestm ciemny, ale powiedz mi jak segmentacją mapujesz jądro na 3 GB :-/
A co do ostatniego pytania: błąd jest na pewno w struktyurach stronnicowania (na pewno jest to jakiś głupi błąd ;P ). Sprawdź czy adres PGDir jest poprawny i pamięć jest OK zmapowana.

0

Mapuję dosyć prosto. Jesli X jest bazą ( bo jest, popatrz na wzór )
Jeśli 0xC0000000 + x = 0x00000000
x = 0x40000000
bo 0xC0000000 + 0x40000000 = (zrobi się wraparound) 0x00000000
To nawet na Windowsowskim kalkulatorze(na 98 działa) można policzyć

 mov [ds:SYS_PGDIR+0xC00], dword KERNEL_PGTBL | 3 

Zapis adresu PageTable zawierającego jedną stronę kodu kernela, tak żeby pokazywała pod 0xC0000000(będzie to strona 0xC0000, po podzieleniu przez ilość stron per PageTable dostajemy 0x300, mnożąc razy rozmiar PDE dostajemy 0xC00). Najpierw zapisujemy adres z 12ma pierwszymi bitami wyzerowanymi, a potem dajemy Present i Read/Write.

 mov [ds:KERNEL_PGTBL], dword 3 

Nie potrzebujemy adresu bo ta strona wskazuje na 0x0 gdzie znajduje się kod kernela. Dajemy jej tylko Presenta i Read/Write.

 mov eax, SYS_PGDIR
mov cr3, eax 

Zapisujemy do CR3 adres katalogu z pierwszymi 12 bitami wyzerowanymi.

mov eax, cr0
or eax, 0x80000000
mov cr0, eax

Logicznie rzecz biorąc włączamy stronnicowanie ;)

SYS_PGDIR equ 0x7E000
KERNEL_PGTBL equ 0x7D000 

Ja naprawdę nie widzę tu błędu. Proszę, wskaż mi go.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0