LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 04-17-2006, 02:44 PM   #1
anothershura
LQ Newbie
 
Registered: Apr 2006
Posts: 3

Rep: Reputation: 0
Safely accessing /dev/mem


Hi Gurus,

I want to access some certain amount of RAM directly, via /dev/mem. To do this I limit main memory size on boot (for example on 2G RAM machine, I limit memory to 1.6G, what leaves me 400M for my personal use). But I know that /dev/mem also maps other devices (like pci devices) to virtual address space. So I want to be sure, when accessing address at /dev/mem, I will not step on some other mapped device/entity. And my main question is:

How can I check which other devices/entities are mapped to /dev/mem and to what address space (like pci devices which I can see with lspci -vv)?

Besides that I'm curious to know, is it possible (even theoretically), that some device virtual address space (mapped into /dev/mem) will overlap physical memory address space which is outside of memory upper limit (for example on 2G RAM machine, I limit memory to 1.6G, and some device will be mapped starting at address 0x7F000000)?

Thanks in advance and best regards,
Alex.
 
Old 04-19-2006, 12:22 AM   #2
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,627
Blog Entries: 10

Rep: Reputation: 776Reputation: 776Reputation: 776Reputation: 776Reputation: 776Reputation: 776Reputation: 776
Hi,

And welcome to LQ!

I'll shuffle the post over to programming, chances are that the guys
there can give you better advice.

And just out of curiosity: what are you trying to achieve?


Cheers,
Tink
 
Old 04-19-2006, 02:02 AM   #3
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 361Reputation: 361Reputation: 361Reputation: 361
I don't have all the answers. In fact, most of what I say is "probably right" but I wo't guarantee it. I usually refrain from responding in those situations, but I thought I'd toss in some info.

First, Tinkster asks a good question: what are you trying to accomplish? When you say you want to access memory directly, but then limit memory to 1.6GiB, what does that mean? I can only see two possibilities:
1. You tell the kernel to pretend there is only 1.6GiB of RAM in the system
2. You tell the kernel it's allowed to consume only 1.6GiB of the whole 2GiB physical memory space

If the case is #1, then I don't think you can access the last 400MiB. Any requests to read/write memory will go through the kernel - the kernel thinks there's only 1.6GiB available - it will refuse, as an out-of-bounds address, anything over that 1.6GiB range (or do some virtual memory hocus pocus). Either way (hocus pocus or out-of-bounds), it's not what you want.

You might be able to do what you want with option #2, but I don't know what kernel option would allow that (if there is one).

About memory-mapped devices... it's complicated. Some devices are hard-coded to respond to a specific memory address. Some accept programmable memory mappings on bootup. And yes, devices can be mapped to a range beyond physical memory. The only way you can know with certainty what your entire system's memory map is: get the technical specs. The system's technical specs would have a default memory map as well as what devices have configurable address spaces. The problem is not just PCI/AGP expansion slots. The motherboard itself has embedded devices/chips on internal PCI/AGP/PLB/I2C/whatever buses. You need to know those internal bus mappings to physical RAM in addition to each expansion device you plug in. Then, you could finally figure out what addresses map directly to physical memory.

Last edited by Dark_Helmet; 04-19-2006 at 02:05 AM.
 
Old 04-20-2006, 01:42 AM   #4
anothershura
LQ Newbie
 
Registered: Apr 2006
Posts: 3

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Tinkster
And just out of curiosity: what are you trying to achieve?
It was my task as part of my job. Silicon Validation team needed continuous area of physical memory for their validation software. I guess when they testing new devices (e.g. network card) while driver for these devices does not exist yet, communicating (between testing application and tested device) directly via physical RAM is a reasonable choice.


Quote:
Originally Posted by Dark_Helmet
When you say you want to access memory directly, but then limit memory to 1.6GiB, what does that mean? I can only see two possibilities:
1. You tell the kernel to pretend there is only 1.6GiB of RAM in the system
2. You tell the kernel it's allowed to consume only 1.6GiB of the whole 2GiB physical memory space
Well, the differences between both choices is a question of wording. Better will be if I just tell what I've done. When kernel (SUSE 2.6.5) boots, before it recieves from BIOS map of physical RAM regions (if BIOS does not supplies such map, it generates default mapping). And right after such map was applied, but before any memory allocation done I just cut from the biggest region 400M. And it works - I mean I can successully read/write to address space 1.6G-2G, while /proc/meminfo shows me 1.6G total memory.



And now, I would like to return to my problem. Dark_Helmet, you helped me to sharpen my question: How can I retreive (from OS/BIOS/Unix utilitiy/Kernel source code) information about all devices or entities on the bus which are mapped to the /dev/mem? (information I mean to what adress space in /dev/mem such device is mapped)? Assume, I do not have any external documentation.

Thanks and regards,
Alex.
 
Old 04-20-2006, 02:30 AM   #5
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 361Reputation: 361Reputation: 361Reputation: 361
Just as a clarification for the two options I mentioned:

Option 1 would be the same as the kernel believing there truly was only 1.6GiB of RAM in the system. In other words, if the kernel received a request for an address beyond that range, it might error out saying "No such address"

Option 2 is different. The kernel knows 2GiB exists, but that the kernel is allowed to use only 1.6GiB. In this case, if the kernel sees an address beyond 1.6GiB, it may not report an error (because it knows the address will decode to physical RAM).

To your question... My experience is limited. I did some embedded development/testing at my last job. We had a system-on-chip design with multiple programmable sub-devices on the chip. Our on-chip memory map was static. So any cycles we initiated within the chip itself were deterministic.

For our system-level tests, we had PCI expansion boards with our prototype chip built on. We had the host computer run some rudimentary firmware to program up the device through PCI registers. Then, we could initiate reads and writes from within the host, out through the PCI expansion bus, and finally inside the chip.

So first, I don't know how you're planning to connect this device to the machine. I assume PCI since that's what you mentioned earlier. If that is the case, then yeah, you'll need to read and write the device's PCI registers to find out where the computer memory-mapped the device. As I recall, the PCI standard specifies a minimum register set that all PCI-compatible devices must follow. Any given device may have more programmable registers than the minimum, but if you don't have any documentation, then those extra registers don't do you a bit of good (even if the device implements them, because you don't know where they are or what they do).

So, first, get the PCI spec that matches the hardware you have. You can download the spec. from:
http://www.pcisig.com/specifications/conventional

Older specs look to be available for free, but the current ones have to be purchased. Then, with the spec. in hand, query the PCI devices attached to the system (perhaps with lspci). Then perform some reads and writes to the configuration registers detailed in the PCI spec.

That should give you the memory range the device is mapped to. From that point, you can start reading writing all you want.

Though, I've never read/written to /dev/mem directly. I stay within user space. To perform reads and writes to memory-mapped devices, use mmap() along with /dev/mem. For instance, something like this maybe:
Code:
volatile void *device_base_address;
int fd;
int status_register;

...

fd = open( "/dev/mem", O_RDWR );
device_base_address = mmap( 0,
                            DEVICE_WINDOW_SIZE,
                            PROT_READ | PROT_WRITE,
                            MAP_PRIVATE,
                            fd,
                            DEVICE_MAPPED_ADDRESS );

status_register = *(int *)(device_base_register + status_register_offset );

...

*(int *)(device_base_regiser + status_register_offset) = 0x001F0300;
The text in blue would need to be replaced with the memory window (in bytes) and the memory-mapped address you read from the PCI registers.

The last bit of code just shows a read and a write to a fictitious status register. At least, that's how we did things.

Here's a page that may be of some interest:
http://www.linuxjournal.com/node/5442/print

At the very least, it might help you find other interesting approaches.
 
Old 04-20-2006, 03:43 AM   #6
anothershura
LQ Newbie
 
Registered: Apr 2006
Posts: 3

Original Poster
Rep: Reputation: 0
Cool.
Thanks D.H.
 
  


Reply

Tags
space


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
What would happen if I where to cat /dev/mem > /dev/null Joey.Dale Linux - General 11 07-26-2009 12:46 PM
decoding /dev/mem EkantoApon Programming 2 02-10-2006 10:49 PM
decoding /dev/mem image using C EkantoApon Programming 2 02-10-2006 07:54 AM
How to open /dev/mem in kernl code? cyu021 Linux - Software 0 03-31-2005 12:28 PM
How can I safely trim down /dev ? tigermusti Linux - General 9 12-12-2002 04:33 PM


All times are GMT -5. The time now is 05:18 AM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration