funny mmap() behaviour

Search this archive.

From: Christian Groessler (cpg@aladdin.de)
Date: Fri 18 Sep 1998 - 17:02:47 IST


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]  :-)


This archive was generated by hypermail 2.1.4 : Wed 21 Jan 2004 - 22:10:22 IST