2000-12-22 14:42:12

by Richard B. Johnson

[permalink] [raw]
Subject: Referencing PHYSICAL (what you see on the bus) memory?


I am finishing up a memory-test program. I want to get the
true linear address of some failing memory. I have obtained
the virtual (user-space) address.

Since going through all the PTEs seems to be a bitch, I thought
it would be easier to do the following:

(1) Mark the bad RAM with magic (0xdeadface).
(2) mmap() some low physical RAM where there is a 1:1 virt/phy
translation.
(2) Make an ioctl() to a module that copies some code to
the mmap()ed RAM.
(3) Call a procedure in that code living below 1 megabyte
from the module in kernel space.
So far this all ** works **. The code functions and
returns, when executed in the mmaped (.data) area.
The physical address chosen was 0x90000.

(4) The procedure is supposed to do:

Make a long-jump to its physical address so it's
CS:EIP is referencing the physical address.

Disable paging. You need 1:1 phys/virt before you do this.

Do a linear scan of all memory, looking for magic.
I need paging off so I can look at flat-model physical RAM.

Re-enable paging.

Make a long-jump to its virtual address.
Return to caller.


(5) So far, the code looks like:

LOAD_ADDRESS = 0x90000

pushl %registers_destroyed.
movl %cr0,%ebx # Save original.
ljmp $(__KERNEL_DS,$1f - PAGE_OFFSET + LOAD_ADDRESS
# Should now be 1:1
1: movl %ebx,%eax
andl $~0x80000000,%eax # Mask paging bit
movl %eax,%cr0 # Turn off paging

do_memory_scan

movl %ebx,%cr0 # Turn back on paging
ljmp $(__KERNEL_CS),%1f + PAGE_OFFSET + LOAD_ADDRESS
# Back to virtual address
1:
popl %registers_destroyed


(6) This obviously fails. It fails at the first 'ljmp'. This
seems to be because __KERNEL_DS doesn't reference the 1:1
stuff. Note, the code is executing out of allocated
(mmaped()) .data. I have played with __KERNEL_CS. This
produces an 'access violation', i.e., I wasn't even allowed
to try to execute something there.

Using __KERNEL_DS, the errors were related to executing
junk since I didn't jump to where I thought I should have
gone.

(7) So the question is: What executable segment will reference,
with a 1:1 virtual:physical relationship, stuff that has
already successfully been copied to low memory?

I can 'prove' that the code I want executed does actually
live at 0x90000, and if I don't do anything exciting,
I can call it (via pointer), it executes, and properly
returns to my module.


Cheers,
Dick Johnson

Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).

"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.



2000-12-22 15:47:51

by Werner Almesberger

[permalink] [raw]
Subject: Re: Referencing PHYSICAL (what you see on the bus) memory?

Richard B. Johnson wrote:
> I am finishing up a memory-test program. I want to get the
> true linear address of some failing memory. I have obtained
> the virtual (user-space) address.
>
> Since going through all the PTEs seems to be a bitch, I thought
> it would be easier to do the following:

Hmm, for some unusual definition of "easy", perhaps ...

For an ugly hack that works remarkably well, look at ptable.c in Andrew
Tridgell's capture program: http://samba.org/picturebook/

Note: you probably also want to check if you find multiple addresses
for the page, i.e. if the hack didn't quite work. (Due to odd
side-effects, incomplete address decoding, etc.)

- Werner

--
_________________________________________________________________________
/ Werner Almesberger, ICA, EPFL, CH [email protected] /
/_IN_N_032__Tel_+41_21_693_6621__Fax_+41_21_693_6610_____________________/