CS 635 PROJECT 3 Due Date: Noon Friday 03/28/2003 The purpose of this project is to increase our understanding of the way in which Linux application programs make use of services provided by kernel functions, and to overcome some shortcomings in our previous tool for studying memory-management in the Linux kernel. PROJECT STATEMENT Create an improved version of your 'physmem.c' device-driver (named 'ram.c') which can access ALL the physical memory that is installed on a workstation, including any so called 'high' memory which was not able to be directly mapped into the Linux kernel's address-space due to an 896MB upper limit on the physical addresses which are supported by that direct linear mapping. Use the kernel's 'kmap()' and 'kunmap()' functions: void * kmap( struct page * page ); void kunmap( struct page * page ); Kernel's virtual address-space: +--------+--------+--------+--------+--------+--------+--------+--------+ |<< contiguously-mapped pages of physical memory below 896MB >>| ++++++ | +--------+--------+--------+--------+--------+--------+--------+--------+ 0 896 1023 The 'kmap()' function accepts the address of a 'struct page' object for a page of physical memory, and returns a virtual address for this page that can be used by the code within your module for read/write accesses to any operands which lie entirely within that page-frame (i.e., page boundaries cannot necessarily be crossed); its implementation is as follows: void * kmap( struct page *page ) { if ( page < highmem_start_page ) return page->virtual; return kmap_high( page ); } Because machines having a gigabyte or more of installed physical memory do have enough virtual addresses in kernel-space for all physical pages to be mapped simultaneously, it is important for a module to call the 'kunmap()' function as soon it no longer needs access to any particular physical page that was 'mapped' using 'kmap()', so that another kernel component will be able to setup any mappings that it needs to use. Recall that the kernel's 'mem_map[]' array contains a 'struct page' object corresponding to every page of physical memory. So if you wanted to read, say, the highest byte in your physical memory, you could do it like this: unsigned long physaddr = (num_physpages * PAGE_SIZE) - 1; unsigned long page_number = physaddr / PAGE_SIZE; unsigned long page_offset = physaddr % PAGE_SIZE; unsigned char *last_page = kmap( mem_map[ page_number ] ); unsigned char last_byte = last_page[ page_offset ]; -------------------------------------------------------------------------- (c) Allan B. Cruse University of San Francisco Spring 2003