http://devel.archefire.org/PRJ/OS/LowES ... 4--src.zip
Inside the source directory "dbg/externalProgs/paging/pgtst0/", I have this main function which detects the presence or absence of a 4096-byte physical memory page (with paging disabled, only flat code and data segments):
Code: Select all
;Inputs:
; AL -- initial sequential value to write
; WIDESI -- 4096 bytes page base address
; WIDEDI -- buffer to preserve original page contents
;
;;
check_page_existence__0000:
owide pushf
;INIT: Cache the original page contents
;INIT: Cache the original page contents
;INIT: Cache the original page contents
;INIT: Cache the original page contents
push widecx
push widesi
push widedi
xor widecx,widecx
mov cx,(4096/WIDEWORD_SZ)
rep movswide
pop widedi
pop widesi
pop widecx
;END: Cache the original page contents
;END: Cache the original page contents
;END: Cache the original page contents
;END: Cache the original page contents
;INIT: Write the page
;INIT: Write the page
;INIT: Write the page
;INIT: Write the page
;NOTE: Since the initial test value will be normally random,
; we could also normally call the function without setting
; AL/WIDEAX and using whatever initial value is there,
; but also saving it for being able to compare it later.
;;
push wideax
push widecx
push widesi
xor widecx,widecx
mov cx,4096
.l_alterpage:
;Prepare writing 4096 individual bytes
;from the original WIDESI, and increase
;the byte value and the address on each
;iteration to prove whether this physical
;page can maintain memory contents. It will
;probably be better to always allocate pages
;in this way even if it's slower overall for
;our system, but at least it will allow us to
;never use damaged memory even if it becomes
;damaged at run time under our OS, so this test
;for every time that we allocate or swap out
;a page will give us increased robustness.
;;
mov byte[widesi],al
inc widesi
inc al
dec widecx
jnz .l_alterpage
pop widesi
pop widecx
pop wideax
;END: Write the page
;END: Write the page
;END: Write the page
;END: Write the page
;INIT: See if it held its contents
;INIT: See if it held its contents
;INIT: See if it held its contents
;INIT: See if it held its contents
push widecx
push widesi
xor widecx,widecx
mov cx,4096
.l_checkpage:
;Prepare reading 4096 individual bytes
;from the original WIDESI, and increase
;the byte value and the address on each
;iteration to see whether this physical
;page can maintain memory contents.
;
;If the current byte doesn't contain the
;value that it should, end indicating that
;the page didn't hold its contents; otherwise
;continue the test of 4096 bytes:
;;
cmp byte[widesi],al
jne .l_checkpage_end_notequal
inc widesi
inc al
dec widecx
jnz .l_checkpage
.l_checkpage_end_equal:
xor wideax,wideax ;Indicate that the page held its contents
inc al
jmp .l_checkpage_END
.l_checkpage_end_notequal:
xor wideax,wideax ;Indicate that the page didn't hold its contents
.l_checkpage_END:
pop widesi
pop widecx
;At this point, WIDEAX contains TRUE or FALSE
;for this function:
;;
;END: See if it held its contents
;END: See if it held its contents
;END: See if it held its contents
;END: See if it held its contents
;INIT: Restore original page contents
;INIT: Restore original page contents
;INIT: Restore original page contents
;INIT: Restore original page contents
push widecx
push widesi
push widedi
;Make the cached page buffer the source memory
;and the original address the destination memory:
;;
xchg widesi,widedi
;Copy it to restore:
;;
xor widecx,widecx
mov cx,(4096/WIDEWORD_SZ)
rep movswide
pop widedi
pop widesi
pop widecx
;END: Restore original page contents
;END: Restore original page contents
;END: Restore original page contents
;END: Restore original page contents
owide popf
retwide
;Should implement RETWIDE to automatically select between 16, 32 or 64-bit stack
;return address POPs.
;EOF
Now what I want to know is why some people say that the presence of memory cannot be detected manually. It seems unreasonable to me. That would imply that we wouldn't be able to detect bad memory areas either.
As far as I have tested this really detects memory manually.
Now, in my program I have the measure to start reading from physical address 1048576*2 because I assume that the system will run in a 386+ with at least 2MB of RAM.
This code is perfectly fine as it is, and I know that I will need to read the configuration of PCI devices and other likely known holes to skip like the one around 16MB to simply skip those hardware-specific areas to keep detecting regular memory.
Maybe people who says that it's not possible to detect memory manually haven't considered skipping present hardware-reserved regions or read memory from the first Megabyte, and the result is that they don't detect it correctly.
I assume that when paging is disabled, then the CPU cache memory is disabled too. Is that so?
If so, I don't see how this function could fail to correctly detect memory manually if you help it with detector functions that skip hardware-reserved memory areas dynamically and at least the very first Megabyte which we have to assume that is present in a 386+ at least for a starting workspace-ground-creating code version (and is useful if you just want to allocate new paged memory without detecting how much memory really is at boot time... there could be some machines that could report say 2GB but really have usable 4GB... like the Thinkpad T43 that is supposed to support up to 2GB but I have found some supposed units with 4GB on eBay).