2004-11-30 15:42:06

by Hanson, Jonathan M

[permalink] [raw]
Subject: Walking all the physical memory in an x86 system

I've written a 2.4 kernel module where I'm trying to walk and
record all of the physical memory contents in an x86 system. I have the
following code fragment that does it but I suspect I'm missing a portion
of the memory:

unsigned long memory_address = PAGE_OFFSET;
struct sysinfo RC_sys_info;

si_meminfo(&RC_sys_info);

while (__pa(memory_address) < RC_sys_info.totalram * PAGE_SIZE)
{
/* Read and record memory contents here. */
memory_address += 4;
}

Is there a better way to record all of the contents of physical memory
since what I have above doesn't seem to get everything?


2004-11-30 15:55:23

by Jan Engelhardt

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

> I've written a 2.4 kernel module where I'm trying to walk and
>record all of the physical memory contents in an x86 system. I have the
>following code fragment that does it but I suspect I'm missing a portion
>of the memory:
>
>Is there a better way to record all of the contents of physical memory
>since what I have above doesn't seem to get everything?

Maybe something userspace based?

dd_rescue /dev/mem copyofmem



Jan Engelhardt
--
Gesellschaft für Wissenschaftliche Datenverarbeitung
Am Fassberg, 37077 Göttingen, http://www.gwdg.de

2004-11-30 16:02:09

by Pádraig Brady

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

Jan Engelhardt wrote:
>> I've written a 2.4 kernel module where I'm trying to walk and
>>record all of the physical memory contents in an x86 system. I have the
>>following code fragment that does it but I suspect I'm missing a portion
>>of the memory:
>>
>>Is there a better way to record all of the contents of physical memory
>>since what I have above doesn't seem to get everything?
>
>
> Maybe something userspace based?
>
> dd_rescue /dev/mem copyofmem

Doesn't equate to a power of 2
(nor does `grep MemTotal /proc/meminfo`)

Pádraig.

2004-11-30 16:10:21

by Hanson, Jonathan M

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system



-----Original Message-----
From: Jan Engelhardt [mailto:[email protected]]
Sent: Tuesday, November 30, 2004 8:55 AM
To: Hanson, Jonathan M
Cc: [email protected]
Subject: Re: Walking all the physical memory in an x86 system

> I've written a 2.4 kernel module where I'm trying to walk and
>record all of the physical memory contents in an x86 system. I have the
>following code fragment that does it but I suspect I'm missing a
portion
>of the memory:
>
>Is there a better way to record all of the contents of physical memory
>since what I have above doesn't seem to get everything?

Maybe something userspace based?

dd_rescue /dev/mem copyofmem


[Jon M. Hanson] I'm not sure what dd_rescue is as I've never heard of
it. However, I don't think such an operation can be done from userspace
because I need the physical addresses of memory not the virtual ones.

2004-11-30 16:13:39

by linux-os

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

On Tue, 30 Nov 2004 [email protected] wrote:

> Jan Engelhardt wrote:
>>> I've written a 2.4 kernel module where I'm trying to walk and
>>> record all of the physical memory contents in an x86 system. I have the
>>> following code fragment that does it but I suspect I'm missing a portion
>>> of the memory:
>>>
>>> Is there a better way to record all of the contents of physical memory
>>> since what I have above doesn't seem to get everything?
>>
>>
>> Maybe something userspace based?
>>
>> dd_rescue /dev/mem copyofmem
>
> Doesn't equate to a power of 2
> (nor does `grep MemTotal /proc/meminfo`)
>
> Pdraig.
> -


Kernel variable "num_physpages" tells how many pages the kernel
knows about.


Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

2004-11-30 16:13:15

by Jan Engelhardt

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system

>>dd_rescue /dev/mem copyofmem
>
>I'm not sure what dd_rescue is as I've never heard of
>it. However, I don't think such an operation can be done from userspace
>because I need the physical addresses of memory not the virtual ones.

/dev/mem *is* physical.



Jan Engelhardt
--
ENOSPC

2004-11-30 16:16:52

by Jan Engelhardt

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system

>>dd_rescue /dev/mem copyofmem
>
>[Jon M. Hanson] I'm not sure what dd_rescue is as I've never heard of
>it. However, I don't think such an operation can be done from userspace
>because I need the physical addresses of memory not the virtual ones.

what have They done with /dev/mem? ... one once could access e.g.
position 0x400 of /dev/mem (by seeking) and then read the LPT port value.

>
>

Jan Engelhardt
--
ENOSPC

2004-11-30 17:22:46

by Erik Mouw

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

On Tue, Nov 30, 2004 at 05:12:01PM +0100, Jan Engelhardt wrote:
> what have They done with /dev/mem? ... one once could access e.g.
> position 0x400 of /dev/mem (by seeking) and then read the LPT port value.

For AFAIK, LPT ports have never been memory mapped on PCs. They live in
the IO space, usually at 0x378 (or 0x278).


Erik

--
+-- Erik Mouw -- http://www.harddisk-recovery.com -- +31 70 370 12 90 --
| Lab address: Delftechpark 26, 2628 XH, Delft, The Netherlands

2004-11-30 17:34:45

by Jan Engelhardt

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

>> what have They done with /dev/mem? ... one once could access e.g.
>> position 0x400 of /dev/mem (by seeking) and then read the LPT port value.
>
>Are you thinking of /dev/port ?

No, I was thinking of:

unsigned short p;
fd = open("/dev/mem", O_RDONLY | O_BINARY);
lseek(fd, 0x400, SEEK_SET);
read(fd, &p, 2);


Jan Engelhardt
--
ENOSPC

2004-11-30 19:59:25

by Alan

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

On Maw, 2004-11-30 at 17:34, Jan Engelhardt wrote:
> unsigned short p;
> fd = open("/dev/mem", O_RDONLY | O_BINARY);
> lseek(fd, 0x400, SEEK_SET);
> read(fd, &p, 2);

You want ports for that not mem, has always been the case since back
before Linux existed.

2004-11-30 20:26:04

by linux-os

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

On Tue, 30 Nov 2004, Alan Cox wrote:

> On Maw, 2004-11-30 at 17:34, Jan Engelhardt wrote:
>> unsigned short p;
>> fd = open("/dev/mem", O_RDONLY | O_BINARY);
>> lseek(fd, 0x400, SEEK_SET);
>> read(fd, &p, 2);
>
> You want ports for that not mem, has always been the case since back
> before Linux existed.
>

At offset 0 in the BIOS segment of 0x40, real address 0x400, are
the addresses of up to 4 ports for the serial communications
devices, followed by up to 4 port addresses of any parallel
communications devices found by the BIOS upon startup. This
is likely what he meant. The code shown will return the address
of the first RS-232 device (usually a 8250 UART) found.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

2004-11-30 20:46:20

by Jan Engelhardt

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

>>> unsigned short p;
>>> fd = open("/dev/mem", O_RDONLY | O_BINARY);
>>> lseek(fd, 0x400, SEEK_SET);
>>> read(fd, &p, 2);
>>
>> You want ports for that not mem, has always been the case since back
>> before Linux existed.

I want(ed) to find out which I/O port to use for inb() and stuff, and using the
BIOS's provided data. If you are referring to "ports", I could not find a
device node, but "port" maybe:

$ tailhex /dev/port
[...]
0x00000400 | ffff ffff ffff ffff ffff ffff ffff ffff |
[...]

Oh, look what /dev/mem found! (I retried haha)

$ tailhex /dev/mem
...
0x00000400 | f803 0000 0000 0000 7803 0000 0000 c09f |
...

0x3F8 and 0x378... we know those ones :)
BTW: What the BIOS does not seem to recognize is that PCI card that provides
more LPT ports (LPT2 and LPT3) (I literally fried the LPT1)

So, /dev/mem points to "physical" mem in a sense like DOS has. (Where, the
BIOS, is blend into, as you can see)

>At offset 0 in the BIOS segment of 0x40, real address 0x400, are
>the addresses of up to 4 ports for the serial communications
>devices, followed by up to 4 port addresses of any parallel
>communications devices found by the BIOS upon startup. This
>is likely what he meant. The code shown will return the address
>of the first RS-232 device (usually a 8250 UART) found.

Yes, (parallel / serial, I don't care, it's just something to show), or
in DOS-style:
*(unsigned short far *)0x400


Jan Engelhardt
--
ENOSPC

2004-11-30 21:16:29

by Hanson, Jonathan M

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system



-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Jan Engelhardt
Sent: Tuesday, November 30, 2004 9:10 AM
To: Hanson, Jonathan M
Cc: [email protected]
Subject: RE: Walking all the physical memory in an x86 system

>>dd_rescue /dev/mem copyofmem
>
>I'm not sure what dd_rescue is as I've never heard of
>it. However, I don't think such an operation can be done from userspace
>because I need the physical addresses of memory not the virtual ones.

/dev/mem *is* physical.

[Jon M. Hanson] I can read /dev/mem from a userspace application as root
with no problems and print out what it sees. However, things are not so
simple from a kernel module as I just can't call open() and read() on
/dev/mem because no such functions are exported from the kernel. Is
there a way to read the contents of /dev/mem from a kernel module?


2004-11-30 21:28:16

by Jan Engelhardt

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system

>[Jon M. Hanson] I can read /dev/mem from a userspace application as root
>with no problems and print out what it sees. However, things are not so
>simple from a kernel module as I just can't call open() and read() on
>/dev/mem because no such functions are exported from the kernel. Is
>there a way to read the contents of /dev/mem from a kernel module?

You can use filp_open().


Jan Engelhardt
--
ENOSPC

2004-11-30 21:28:09

by linux-os

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system

On Tue, 30 Nov 2004, Hanson, Jonathan M wrote:

>
>
> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf Of Jan Engelhardt
> Sent: Tuesday, November 30, 2004 9:10 AM
> To: Hanson, Jonathan M
> Cc: [email protected]
> Subject: RE: Walking all the physical memory in an x86 system
>
>>> dd_rescue /dev/mem copyofmem
>>
>> I'm not sure what dd_rescue is as I've never heard of
>> it. However, I don't think such an operation can be done from userspace
>> because I need the physical addresses of memory not the virtual ones.
>
> /dev/mem *is* physical.
>
> [Jon M. Hanson] I can read /dev/mem from a userspace application as root
> with no problems and print out what it sees. However, things are not so
> simple from a kernel module as I just can't call open() and read() on
> /dev/mem because no such functions are exported from the kernel. Is
> there a way to read the contents of /dev/mem from a kernel module?
>

You just read it directly (hint ioremap) ......


Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by John Ashcroft.
98.36% of all statistics are fiction.

2004-11-30 21:31:41

by Alan

[permalink] [raw]
Subject: Re: Walking all the physical memory in an x86 system

On Maw, 2004-11-30 at 20:46, Jan Engelhardt wrote:
> I want(ed) to find out which I/O port to use for inb() and stuff, and using the
> BIOS's provided data. If you are referring to "ports", I could not find a
> device node, but "port" maybe:

I didn't know that was in the BIOS page.

> Oh, look what /dev/mem found! (I retried haha)

> So, /dev/mem points to "physical" mem in a sense like DOS has. (Where, the
> BIOS, is blend into, as you can see)

The kernel also preserves the low 4K because some apps, APM and the like
turned out to need it.


2004-11-30 21:37:07

by Hanson, Jonathan M

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system



-----Original Message-----
From: Jan Engelhardt [mailto:[email protected]]
Sent: Tuesday, November 30, 2004 2:28 PM
To: Hanson, Jonathan M
Cc: [email protected]
Subject: RE: Walking all the physical memory in an x86 system

>[Jon M. Hanson] I can read /dev/mem from a userspace application as
root
>with no problems and print out what it sees. However, things are not so
>simple from a kernel module as I just can't call open() and read() on
>/dev/mem because no such functions are exported from the kernel. Is
>there a way to read the contents of /dev/mem from a kernel module?

You can use filp_open().


Jan Engelhardt
--
ENOSPC

[Jon M. Hanson] I tried the filp_open() approach like this:

struct file *mem_fd;

mem_fd = filp_open("/dev/mem", O_RDONLY | O_LARGEFILE, 0);

I then have a check if IS_ERR(mem_fd) is true immediately afterwards
along with a printk saying it failed. This condition is true when I ran
it.


2004-11-30 23:30:05

by Hanson, Jonathan M

[permalink] [raw]
Subject: RE: Walking all the physical memory in an x86 system


-----Original Message-----
From: Jan Engelhardt [mailto:[email protected]]
Sent: Tuesday, November 30, 2004 2:28 PM
To: Hanson, Jonathan M
Cc: [email protected]
Subject: RE: Walking all the physical memory in an x86 system

>[Jon M. Hanson] I can read /dev/mem from a userspace application as
root
>with no problems and print out what it sees. However, things are not so
>simple from a kernel module as I just can't call open() and read() on
>/dev/mem because no such functions are exported from the kernel. Is
>there a way to read the contents of /dev/mem from a kernel module?

You can use filp_open().


Jan Engelhardt
--
ENOSPC

[Jon M. Hanson] I tried the filp_open() approach like this:

struct file *mem_fd;

mem_fd = filp_open("/dev/mem", O_RDONLY | O_LARGEFILE, 0);

I then have a check if IS_ERR(mem_fd) is true immediately afterwards
along with a printk saying it failed. This condition is true when I ran
it. It seems to fail with -EACCES (permission denied) as the error code.

I can see the exact code that's causing the -EACCES in open_namei(). It
makes a check if the thing being opened is a character device and
returns the -EACCES, so obviously filp_open() can't do this.

I can run a program as root and open /dev/mem and read it without any
problems. Surely there is a way to do the same thing within a kernel
module.