funny mmap() behaviour

Christian Groessler (cpg@aladdin.de)
Fri, 18 Sep 1998 17:02:47 +0200


Hi all!

Sorry, this is rather long.

I'm currently trying to fix a problem in svgalib's background
execution with linear frame buffers in use, and have come across a
weird effect.

In order to provide the application with a constant pointer to the
frame buffer, svgalib does the following:

a, Allocate a chunk of memory the same size as the display
memory size. This seems only to happen to provide a
destination address for subsequent mmap()s. The address of
this memory block is assigned to vmem_addr.
b, mmap() the physical frame buffer via /dev/mem and store the
pointer in physmem_addr (I've changed the variable names
here because the original names are rather long :-)
c, now mmap() the memory at address physmem_addr to vmem_addr
via /proc/<pid>/mem.

This should leave us with the frame buffer accessible thru
vmem_addr. If the application is put into the background (console
switch) svgalib allocates memory, copies the current frame buffer
contents into it and mmap()s it via /proc/<pid>/mem to vmem_addr;
the app shouldn't see a change...

So..... I don't know if the above stuff ever worked, because it's
broken in current svgalib versions (physmem_addr is used as ptr to
display buffer and the last mmap() [c,] is never made).

I tried to fix this but doing the [c,] mmap() gives funny effects:

- if the physical screen buffer address [used in b,] is low (e.g.
0x7c00000, my Mach32 VLB card) the mmap() seems to work fine.

- if the buffer address is high (e.g. 0xfd000000) funny things
happen:

2.0.33 oops (process killed)
2.0.35 seems to work, but oops later (no new processes started)
2.1.111 process doing the mmap() enters D state and stays there
2.1.122 seems to work, but system halts after some time
(keyboard + vc switch still working, but no new processes
are created)

I've written a test program which does the mmap()s as described above,
and on the kernels where it initially seems to work, things get worse
by repeated invocation of the program.

Basically, is this

- a kernel bug?
- a bug in my app/svgalib?
- not supposed to work at all?

Thanks for your patience and any input is welcome
chris

Attached: demo app

-------------------------
/*
*
* mmap() test
* -----------
*
* 18-Sep-98, cpg@aladdin.de
*
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

/*
* Address and size of
* framebuffer
*/
/*
#define MAP_ADDR 0xfb000000
#define MAP_ADDR 0x7c00000
*/
#define MAP_ADDR 0xfd000000
#define MAP_SIZE 0x200000

int main(void)
{
int mem_fd,vmem_fd;
int my_pid;
char tmp[128];
void *fb_addr,
*vmem_addr,
*physmem_addr;

/* open /dev/mem and /proc/<pid>/mem */

if ((mem_fd = open("/dev/mem", O_RDWR)) < 0) {
printf("mmaptest: Cannot open /dev/mem.\n");
exit(1);
}

my_pid=getpid();
sprintf(tmp,"/proc/%d/mem",my_pid);
if ((vmem_fd = open(tmp,O_RDWR)) < 0) {
printf("mmaptest: Cannot open /proc/%d/mem.\n",
my_pid);
exit(-1);
}

/* get final destination address */

if ((fb_addr = valloc(MAP_SIZE)) == NULL) {
printf("mmaptest: allocation error \n");
exit(-1);
}
vmem_addr=fb_addr;

/* try to mmap() the video buffer */

physmem_addr = (unsigned char *) mmap((caddr_t) 0,
MAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
mem_fd,
(off_t) MAP_ADDR );

if (physmem_addr == -1) {
printf("mmaptest: cannot mmap() framebuffer\n");
exit(-1);
}

/* now map this virtual address! */

fb_addr = mmap((caddr_t) fb_addr,
MAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED,
vmem_fd,
(int)physmem_addr);

if (fb_addr!=vmem_addr) {
printf("mmaptest: mmap error in linear screen memory.\n");
exit(-1);
}

printf("SUCCESS!!!!!!!\n");
return(0);
}

-------------------------
[end of mail] :-)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/