flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Understanding structure of Paging descriptor

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
Hello, at this moment, i learn about how to use paging.

In fact, i have understanding how paging work and the use of this. But when i try to make Directory Table and PageTable, i don't understand the address field (20bits), and how to align it into 4Ko.

I don't understand this part...

(i think it's different to the align assembly directive)

If you have good explanation for me, i have read OsDev explanation and wikipedia explanation, but it's very obscure for me

It's my test code:

Code:
format binary as "img"

use16
org 0x7C00

cli
lgdt [GDTR]

mov eax,PageDirectory
mov cr3,eax

mov eax,cr0
or eax,0x80000001
mov cr0,eax

jmp 0x8:ProtectedMode

use32

ProtectedMode:
.Initialize:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov es,ax
mov ss,ax

.ShowText:
mov byte [0xB8000],'*'
mov byte [0xB8001],00000010b
mov byte [0xB8002],' '
mov byte [0xB8003],00000111b
mov byte [0xB8004],'M'
mov byte [0xB8005],00000111b
mov byte [0xB8006],'a'
mov byte [0xB8007],00000111b
mov byte [0xB8008],'i'
mov byte [0xB8009],00000111b
mov byte [0xB800A],'n'
mov byte [0xB800B],00000111b

.Main:
hlt
jmp .Main

GDT: db 0, 0, 0, 0, 0, 0, 0, 0

GDTCS: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0

GDTDS: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0

GDTEND:

GDTR:
dw GDTEND-GDT-1
dd GDT

PageDirectory:
.Settings: dw 0111010000000000b
.Address: dw PageTable

PageTable:
.Settings: dw 0111011000000000b
.Address: dw 0x1000

db 510-($-$$) dup 0x90
dw 0xAA55    


This code work properly when i go to protected mode without paging, but when i enable paging, virtualbox stop my virtual machine...
Post 20 Jan 2020, 09:21
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
You need to fill page tables with enough entries so that all memory that you need is mapped, including your own code.

The most basic, classic 80386 paging divides the 32-bit address into three parts: two 10-bit ones, and one 12-bit one.

Let's say that you use linear address 0x000B8004. To find out what physical address corresponds to it, CPU first takes the uppermost 10 bits (in this case they are all 0) and this 10-bit number (with 10 bits you have range from 0 to 1023) is the number of entry in page directory.

( All entries in page directory or page table are 32-bit, so each one is 4 bytes and entire table has size 4*1024, which is nicely the same as the length of a single page. The physical address of page that contains this directory goes into CR3. )

So you take the entry in page directory that has number 0 (the very first one), and it gives you the address of the first page table.

( Every entry in page directories and tables gives an address of the page, and pages are 4096 bytes each, so their addresses always have the lowest 12 bits zeroed. Since this zeroing of the low bits is implied, the actual low 12 bits of each entry can be used for other purposes, so there are additional bits fields there. )

Now, CPU takes the second 10 bits of the original address, in this example they are 0x0B8. This is the number of one of the 1024 entries in the page table that was found by looking up the page directory. This entry defines the address of the actual page of memory that the original linear address points to.

Now all that is left is to take the low 12 bits of the original address, 0x004, and add them to the address of page, as these bits are simply an offset within the page.

Therefore, if you'd like to have linear address 0x000B8004 correspond to physical address 0x000B8004, you need to set up the first page table so that the entry number 0x0B8 points to page at 0x000B8000.

As you see, this means that to get your sample working, you have to fill at least the first page table with correct entries.

The simplest example of setting up paging that I have turns out to be my long mode example. So I took it and I removed all the long-mode-related stuff, to make this minimized demonstration. It fills the first 256 entries in the first page table with 1:1 linear-to-physical address mapping:
Code:
        format binary as 'bin'

        ORG     7C00h
        USE16

        cli                  
        lgdt    [cs:GDTR]               ; load GDT register
        mov     eax,cr0                 ; switch to protected mode
        or      al,1
        mov     cr0,eax
        jmp     CODE_SELECTOR:pm_start

NULL_SELECTOR = 0
DATA_SELECTOR = 1 shl 3                 ; flat data selector (ring 0)
CODE_SELECTOR = 2 shl 3                 ; 32-bit code selector (ring 0)

GDTR:                                   ; Global Descriptors Table Register
  dw 3*8-1                              ; limit of GDT (size minus one)
  dq GDT                                ; linear address of GDT

GDT rw 4                                ; null desciptor
    dw 0FFFFh,0,9200h,08Fh              ; flat data desciptor
    dw 0FFFFh,0,9A00h,0CFh              ; 32-bit code desciptor

        USE32

pm_start:

        mov     eax,DATA_SELECTOR       ; load 4 GB data descriptor
        mov     ds,ax                   ; to all data segment registers
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax

        mov     edi,70000h
        mov     ecx,1000h shr 2
        xor     eax,eax
        rep     stosd                   ; clear the page directory

        mov     dword [70000h],71000h + 111b ; first entry in page directory -> first page table

        mov     edi,71000h              ; address of first page table
        mov     eax,0 + 111b
        mov     ecx,256                 ; number of pages to map (1 MB)
  make_page_entries:
        stosd
        add     eax,1000h
        loop    make_page_entries

        mov     eax,70000h
        mov     cr3,eax                 ; load page directory address

        mov     eax,cr0
        or      eax,1 shl 31
        mov     cr0,eax                 ; enable paging

        jmp     CODE_SELECTOR:paged_start

paged_start:

        mov     eax,'P G '
        mov     [0B8000h],eax

        jmp     paged_start    
Post 20 Jan 2020, 10:57
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
If i understand good, paging is processor feature to translate linear address into physical address.

This feature split RAM and physical memory into many pages with fixed size, and extend all memory.

This memory is for data and code i think ?

But i don't understand your explanation about divides 32 bits address into three parts, what is the purpose if i would like to start with address 0x0, for example ? I just set all bits to 0 ?

I don't understand very well.

How can i put 32 bits code into page ?
Post 21 Jan 2020, 10:14
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
Fulgurance wrote:
But i don't understand your explanation about divides 32 bits address into three parts, what is the purpose if i would like to start with address 0x0, for example ? I just set all bits to 0 ?
We divide memory into 4096-byte pages, and we would like to be able to rearrange these pages, so that - for example - page visible to the program at address 0x1000 might physically be the page at address 0x2000, etc.

A 32-bit linear address has then 20 bits that are "the number of the page" and 12 bits (range 0-4095) that are the offset within the page.

Linear address 0x00001234: page number 0x00001 (20-bit number), offset within page: 0x234 (12-bit number).

In 32-bit addressing space we have 2^20 such pages. This is over a million. If we wanted to make a lookup table that for each page would tell us the actual physical address, it would be quite large - a few megabytes of memory. If you wanted to map some code in one part of memory, data in the other, and video/devices in yet another (perhaps above 0x80000000 address) you would end up with this huge table, but most of the space within it would be wasted for unused areas that do not need mapping anyway. And at the time 80386 was developed "few megabytes" was usually all the RAM PCs had.

Therefore, instead of a single huge table we have a tree-like structure, with main directory that contains entries for sub-directories (or page tables) only for the addresses that we need. All other places in directory can be zeroed, which means that there is no sub-table needed there and all addresses within that range are considered invalid (not present).

And thus, 20-bit number of page is split into two 10-bit numbers. A single page table has 1024 entries (numbered with 10 bits), and since each entry is 4 bytes long, entire table occupies a single 4096-byte page. It all works nicely together, the numbers have been chosen this way.

So the area of memory mapped by a single page table is 1024*4096 = 4 megabytes.
Therefore each entry in the page directory corresponds to 4 megabytes of mapped linear memory.

The conversion the goes as such: we split the address into ( 10 bits : 10 bits: 12 bits ). The upper 10 bits tell us which 4 MB block of memory is it, and this is the number of entry in page directory and this entry points to the physical address of the page table.

( In my example I map just initial 1 MB of memory addresses, so I need only a single entry in page directory. All other entries are zeroed and therefore they do not have page tables. )

The page table maps 4 MB of memory and the middle 10 bits of the linear address tell us the number of page within that 4M block. The corresponding entry in page table give the physical address of the page. And then the final 12 bits are the address of a byte within that page.

So, for example, let's say that we want to map video memory at 0x80001000 (so accessing [0x80001000] would end up accessing physical memory at 0xB8000).
First, we calculate which of 4M areas is it, taking the upper 10 bits of 0x80001000: 0x200. So in page directory we need to set up the entry at 0x200*4 and put the physical address of page table there:
Code:
[page_directory_address + 0x200*4] = page_table_address + 111b ; access bits    

Then then middle 10 bits of 0x80001000 tell us the number of 4K page within that 4M block: 0x001. In page table we need the entry that points to the physical address that this page should correspond to:
Code:
[page_table_address + 0x001*4] = 0xB8000 + 111b ; access bits    


And now a working demonstration:
Code:
        format binary as 'bin'

        ORG     7C00h
        USE16

        cli                  
        lgdt    [cs:GDTR]               ; load GDT register
        mov     eax,cr0                 ; switch to protected mode
        or      al,1
        mov     cr0,eax
        jmp     CODE_SELECTOR:pm_start

NULL_SELECTOR = 0
DATA_SELECTOR = 1 shl 3                 ; flat data selector (ring 0)
CODE_SELECTOR = 2 shl 3                 ; 32-bit code selector (ring 0)

GDTR:                                   ; Global Descriptors Table Register
  dw 3*8-1                              ; limit of GDT (size minus one)
  dq GDT                                ; linear address of GDT

GDT rw 4                                ; null desciptor
    dw 0FFFFh,0,9200h,08Fh              ; flat data desciptor
    dw 0FFFFh,0,9A00h,0CFh              ; 32-bit code desciptor

        USE32

pm_start:

        mov     eax,DATA_SELECTOR       ; load 4 GB data descriptor
        mov     ds,ax                   ; to all data segment registers
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax

        mov     edi,70000h
        mov     ecx,1000h shr 2
        xor     eax,eax
        rep     stosd                   ; clear the page directory

        mov     dword [70000h],71000h + 111b ; first entry in page directory -> first page table

        mov     edi,71000h              ; address of first page table
        mov     eax,0 + 111b
        mov     ecx,256                 ; number of pages to map (1 MB)
  make_page_entries:
        stosd
        add     eax,1000h
        loop    make_page_entries

        mov     eax,70000h
        mov     cr3,eax                 ; load page directory address

        mov     eax,cr0
        or      eax,1 shl 31
        mov     cr0,eax                 ; enable paging

; Added example: map video memory at 80001000h

page_directory_address = 70000h
page_table_address = 72000h

        mov     dword [page_directory_address + 0x200*4], page_table_address + 111b
        mov     dword [page_table_address + 0x001*4], 0B8000h + 111b

        jmp     CODE_SELECTOR:paged_start

paged_start:

        mov     [80001002h],dword '? ! '

        jmp     paged_start    
Post 21 Jan 2020, 10:52
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
Sorry, but i have problem with page directory structure. I have read page directory point to many table page, but when i look wiki or os dev, the example just show this structure point to just ONE page table.... I don't understand how i can make directory with MANY entry....

At this link: https://wiki.osdev.org/Paging
In directory page section, you have just one address. But if this directory point to multiple address, how can i do this ?

Do i need to update CR3 when i switch to other page ?
Post 21 Jan 2020, 16:57
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
In my second example above you already have a page directory that contains two entries. One at 0, which points to the page table that maps first 4M of memory (but I mapped only 1M there, by filling only 256 entries out of 1024), and then - added in the second example - an entry at 0x200*4, which points to the page table that maps range of addresses from 0x80000000 to 0x803FFFFF (and filled a single entry in that page table to map a single page at 0x80001000 to physical address 0xB8000 for the purpose of demonstration). Other entries in page directory remain zeroed (they were cleared with "rep stosd" instruction), which means that these memory ranges are considered not present (accessing them raises the "page fault" exception).

For every additional 4M block you'd need, you'd fill another entry in the page directory, pointing to a page table mapping 1024 4K pages within that 4M block. Every page table itself is a single page (and you need to somehow allocate them).

Every page is 4K bytes, every page table maps 1024 pages - 4M of memory. Page directory has 1024 entries for page tables, each one mapping 4M of memory, in total 4G - entire 32-bit addressing space.
Post 21 Jan 2020, 17:10
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
Okay. Sorry,your code at many line is difficult for me, i don't know some instruction you use.

To explain simply, if i have 2 entry in my page directory, i have two 32 bits entries they following himself, is it that ?

Can you just give me simple array page directory example, not with code plz. (same structure you use with your GDT it's more simple to read please)
Post 21 Jan 2020, 18:53
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
Fulgurance wrote:
Can you just give me simple array page directory example, not with code plz. (same structure you use with your GDT it's more simple to read please)
OK, but because each page table is 4096 bytes, this is no longer going to fit in boot sector, if this is how you test it.

I tested it from DOS using this loader (the same that comes with my long mode examples) to get the code at correct address and run it:
Code:
        org     100h

        cli
        push    0
        pop     es
        mov     di,7C00h
        mov     si,basecode
        mov     cx,basecode_length
        rep     movsb
        jmp     0:7C00h

basecode file 'EXAMPLE.BIN'
basecode_length = $ - basecode    
And you first need to assemble EXAMPLE.BIN containing the actual example:
Code:
        format binary as 'bin'

        ORG     7C00h
        USE16

        cli
        lgdt    [cs:GDTR]
        mov     eax,cr0                 ; switch to protected mode
        or      al,1
        mov     cr0,eax
        jmp     CODE_SELECTOR:pm_start

NULL_SELECTOR = 0
DATA_SELECTOR = 1 shl 3                 ; flat data selector (ring 0)
CODE_SELECTOR = 2 shl 3                 ; 32-bit code selector (ring 0)

GDTR:                                   ; Global Descriptors Table Register
  dw 3*8-1                              ; limit of GDT (size minus one)
  dq GDT                                ; linear address of GDT

GDT rw 4                                ; null desciptor
    dw 0FFFFh,0,9200h,08Fh              ; flat data desciptor
    dw 0FFFFh,0,9A00h,0CFh              ; 32-bit code desciptor

        USE32

pm_start:

        mov     eax,DATA_SELECTOR       ; load 4 GB data descriptor
        mov     ds,ax                   ; to all data segment registers
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax

        mov     eax,PageDirectory
        mov     cr3,eax                 ; load page directory address

        mov     eax,cr0
        or      eax,1 shl 31
        mov     cr0,eax                 ; enable paging

        jmp     CODE_SELECTOR:paged_start

align 1000h

PageDirectory:
        dd      PageTable1 + 111b       ; entry 0 (addresses 0x00000000 - 0x003FFFFF)
        dd      1FFh dup 0              ; 511 zeroed entries (area 0x00400000 - 0x7FFFFFFF not present)
        dd      PageTable2 + 111b       ; entry 0x200 (addresses 0x80000000 - 0x803FFFFF)
        dd      1FFh dup 0              ; 511 zeroed entries (area 0x80400000 - 0xFFFFFFFF not present)

align 1000h     ; not really needed if the above table constructed properly

PageTable1:     ; addresses 0x00000000 - 0x003FFFFF
        dd      0 + 111b                ; map page at 0x0000000 to physical page 0x00000000
    repeat 255
        dd      %*1000h + 111b          ; similarly map 255 next pages (entire first 1M) to the same physical addresses
    end repeat
        dd      300h dup 0              ; remaining entries zeroed (memory not present)

align 1000h     ; not really needed if the above table constructed properly

PageTable2:     ; addresses 0x80000000 - 0x803FFFFF
        dd      0                       ; page at 0x80000000 not present
        dd      0B8000h + 111b          ; page at 0x80001000 mapped to 0x000B8000 (video memory)
        dd      3FEh dup 0              ; remaining entries zeroed (memory not present)

paged_start:

        mov     [80001002h],dword '? ! '

        jmp     paged_start    
Post 21 Jan 2020, 19:31
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
I ask you if i don't understand something else.

I have question, is it mandatory to use paging in protected mode and long mode ? Or is it better to use other system coded by the OS developer ? Why split into 4kb or 4Mb, why not whit other size for example ? Are there any OS use different memory usage without paging ?

First question, at this line:
Code:
PageDirectory:
        dd      PageTable1 + 111b       ; entry 0 (addresses 0x00000000 - 0x003FFFFF)
        dd      1FFh dup 0              ; 511 zeroed entries (area 0x00400000 - 0x7FFFFFFF not present)
        dd      PageTable2 + 111b       ; entry 0x200 (addresses 0x80000000 - 0x803FFFFF)
        dd      1FFh dup 0     


Is it 1024 4 byte entries of page directory ? If i understand good, you have just 2 entries without zero entries ? But why this two entries ?

And what do you do when you write:
Code:
dd      PageTable1 + 111b    

Is it your Page directory entry ? When you do this addition, do you write 111b at the lower byte of the 32 bits value ? (20 bits address + settings ?)

What do exactly align 100h directive ? This directive write 4096 empty byte ? I don't understand good the purpose of align memory.

And, it's possible i have wrong, but if i understand good, your page table don't size 4Kib, no ?
Post 28 Jan 2020, 15:40
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
Fulgurance wrote:
I have question, is it mandatory to use paging in protected mode and long mode ?
It is mandatory in long mode, but it is not mandatory in protected mode (note that 286 did not have paging, but did have protected mode). But if you use flat memory model (with no segmentation), paging makes it much easier to manage.

Fulgurance wrote:
Why split into 4kb or 4Mb, why not whit other size for example ?
As I have mentioned above, this particular split (10:10:12 bits) gives everything nice symmetries, because every page table/directory fits exactly into a single page then.

Fulgurance wrote:
Are there any OS use different memory usage without paging ?
Any 16-bit OS that uses protected mode (like OS/2 1.x, for example). For 32-bit addressing an example might be a classic DOS with FRM enabled (HIMEM.SYS uses it on 386+).

Fulgurance wrote:
Is it 1024 4 byte entries of page directory ? If i understand good, you have just 2 entries without zero entries ? But why this two entries ?
As explained in the comments, these entries correspond to address ranges that I wanted to have mapped in this example.

Fulgurance wrote:
And what do you do when you write:
Code:
dd      PageTable1 + 111b    

Is it your Page directory entry ? When you do this addition, do you write 111b at the lower byte of the 32 bits value ? (20 bits address + settings ?)
Yes, this is an entry in page directory, which points to the physical address of page table. Because page table needs to occupy a single page, its address needs to be aligned to 1000h (4096) bytes, in other words low 12 bits of address need to be zero. CPU simply assumes that the low 12 bits of address are zero, and these bits in entry are actually used for different purposes. The three lowest bits are U-W-P. Bit P indicates that the page is present in memory, W indicates that page is writable and U indicates that it is accessible from user-level.

Fulgurance wrote:
What do exactly align 100h directive ? This directive write 4096 empty byte ? I don't understand good the purpose of align memory.
This is align 1000h (4096) so it ensures that the address of data that follows is aligned to the page boundary - in other words, that the address of the data has lowest 12 bits zeroed. This is needed to ensure that page tables are correctly placed in memory, each one needs to start exactly at the beginning of a page, which means that it should have address of form 0XXXXX000h.

Fulgurance wrote:
And, it's possible i have wrong, but if i understand good, your page table don't size 4Kib, no ?
There are three tables in this example - one page directory and two page tables. Each one of them contains 400h (1024) double words, which is exactly 1000h (4096) bytes.
Post 28 Jan 2020, 17:34
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
If i understand, if i set page to 4MiB size, in protected mode, i can address maximum of 4 GiB?
(1024 x 1024 x 4MiB (max page size) )

You mention it's possible to rearange pages. But is it possible for program to allow access to many pages ? For example if code need more than 4MiB (it's so big yes)

Now i have understand how to make all paging entries, my last question:
How can i allocate one or many pages for a program ?

After activate paging, where is kernel in memory ?
Post 28 Jan 2020, 21:24
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
Fulgurance wrote:
If i understand, if i set page to 4MiB size, in protected mode, i can address maximum of 4 GiB?
(1024 x 1024 x 4MiB (max page size) )
You get 4G with just regular 4K pages. 1024 x 1024 x 4K = 4G. What setting page size to 4M does is that it allows you to skip the "middle" page table and just point to a single large page directly from page directory.

Fulgurance wrote:
You mention it's possible to rearange pages. But is it possible for program to allow access to many pages ? For example if code need more than 4MiB (it's so big yes)
You can map any area in addressing space to any physical area, whatever you wish. You can also adjust read/write permissions for every page individually.

With standard 4K pages you need 1024 page tables to map entire memory. Note that it requires 4M of memory just for page mapping structures (plus 4K for page directory, which you always need).

Fulgurance wrote:
Now i have understand how to make all paging entries, my last question:
How can i allocate one or many pages for a program ?
If you write your own OS, you need to design your own scheme for maintaining a list of free pages. Also you need to know how much physical memory there is.

Fulgurance wrote:
After activate paging, where is kernel in memory ?
Wherever you mapped it. In my example I mapped first 1M of memory to the same physical addresses, so in that case the code is at the same address as before paging. But you could just as easily map it so that your code would be at address 0, or any other.
Post 29 Jan 2020, 19:28
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
Oh okay, i see.

Is it better to use 4k pages or 4M ? Or just different ?

If i understand good, pages are virtual ? It's just process for processor to translate address ? And extend RAM to disk ?

Are there any space where i mustn't to write into memory when i activate paging, or i can write all of 4G memory ? Are there any zone where for example graphic card use memory ? (for example, into 0xB8000 ?)
Post 30 Jan 2020, 18:22
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
Fulgurance wrote:
Is it better to use 4k pages or 4M ? Or just different ?
Use whichever one fits better what you're trying to do. When you have a program with small sections, obviously you need to use small pages to be able to set up attributes like "read only" for specific areas. When your program allocates a huge block of memory for some data processing, you may prefer to use 4M pages for that, for simplicity but also better performance.

Fulgurance wrote:
If i understand good, pages are virtual ? It's just process for processor to translate address ? And extend RAM to disk ?
Yes, this is just a concept used for address translation.

Fulgurance wrote:
Are there any space where i mustn't to write into memory when i activate paging, or i can write all of 4G memory ? Are there any zone where for example graphic card use memory ? (for example, into 0xB8000 ?)
In physical memory there may be various address ranges where some special things are mapped (like video memory), and also depending on the size of available RAM there may be a range of addresses where there is simply no memory - if you write a value there, you are not going to get it back when you try to read from that address.

In the linear addressing space ("virtual" addresses) you have a full control over everything. As in my example, where I map video memory to be accessible at address 80001000h. When you design your own OS, you can reserve any address ranges for any purposes you want.
Post 30 Jan 2020, 20:16
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17671
Location: In your JS exploiting you and your system
revolution
One fun thing to try with paging is to map all the addresses to a single page of RAM. It plays havoc with caching, of course, since the x86 uses VA for cache access. Write to one address and read the value back from a different address. And the really tricky part is to how to get all the page tables and the directory page, plus the program code all in the same physical 4kB RAM section.
Post 30 Jan 2020, 20:29
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
Okay, thanks Wink

And why you have right access for page table AND pages ? Rights access for pages are not sufficient ?
Post 01 Feb 2020, 18:43
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17671
Location: In your JS exploiting you and your system
revolution
Fulgurance wrote:
And why you have right access for page table AND pages ? Rights access for pages are not sufficient ?
For a secure OS it might be bad for a user process to alter page tables. Without access controls securing some things wouldn't be possible.

Your OS might not need to be secure, but most general OSes need to be to be useful.
Post 01 Feb 2020, 19:01
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
Oh okay, Thanks.

Question again Laughing

About the P bit.

I think it's to indicate if page is mapped into RAM or into internal memory ?
(I'm not sure, but i suppose it's possible to use something similar to swap, no ?) How this feature work ?
Post 01 Feb 2020, 22:48
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17671
Location: In your JS exploiting you and your system
revolution
If a page isn't present then when it is accessed it causes an exception. When the OS is processing the exception it can swap another page to disc and map the accessed page to the newly freed section of RAM.
Post 02 Feb 2020, 02:00
View user's profile Send private message Visit poster's website Reply with quote
Fulgurance



Joined: 27 Nov 2017
Posts: 200
Fulgurance
I have tried to apply paging into my test code for test paging.
But when i launch it into virtualbox, my code don't work, virtual machine is stopped by virtualbox.

I think something is bad, but what ? (code work without paging)

Code:
format binary as "img"

use16
org 0x7C00

xor al,al
xor dl,dl
int 0x13

mov ax,0x100
mov es,ax
mov ah,0x2
mov al,0x12
xor ch,ch
mov cl,0x2
xor dh,dh
xor dl,dl
xor bx,bx
int 0x13

jmp Kernel

db 510-($-$$) dup 0x90
dw 0xAA55

use16
org 0x1000

Kernel:

cli
lgdt [GDTR]

mov eax,PageDirectory
mov cr3,eax

mov eax,cr0
or eax,0x80000001
mov cr0,eax

;mov eax, cr4
;or eax, 0x00000010
;mov cr4, eax

jmp 0x8:ProtectedMode

use32

ProtectedMode:
.Initialize:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov es,ax
mov ss,ax

.ShowText:
mov byte [0x0000000],'*'
mov byte [0x0000001],00000010b
mov byte [0x0000002],' '
mov byte [0x0000003],00000111b
mov byte [0x0000004],'M'
mov byte [0x0000005],00000111b
mov byte [0x0000006],'a'
mov byte [0x0000007],00000111b
mov byte [0x0000008],'i'
mov byte [0x0000009],00000111b
mov byte [0x000000A],'n'
mov byte [0x000000B],00000111b

.Main:
hlt
jmp .Main

GDT: db 0, 0, 0, 0, 0, 0, 0, 0

GDTCS: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0

GDTDS: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0

GDTEND:

GDTR:
dw GDTEND-GDT-1
dd GDT

PageDirectory:
dd PageTable + 111b
dd 1023 dup 0x0

PageTable:
dd 0x0B8000 + 111b
dd 1023 dup 0x0

db 347 dup 0x90
    
Post 05 Feb 2020, 21:56
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< 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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.