mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
This is the source for the MMUHACK 2.4 kernel module is included with the GP2X backend. This is the code used to build the mmuhack.o module that ships with the GP2X binaries.
-- line, and those below, will be ignored-- A gp2x/mmuhack AM gp2x/mmuhack/flush_uppermem_cache.s AM gp2x/mmuhack/flush_uppermem_cache.h AM gp2x/mmuhack/mmuhack.c AM gp2x/mmuhack/readme.txt AM gp2x/mmuhack/Makefile svn-id: r40449
This commit is contained in:
parent
2cb051a394
commit
911556a824
11
backends/platform/gp2x/mmuhack/Makefile
Executable file
11
backends/platform/gp2x/mmuhack/Makefile
Executable file
@ -0,0 +1,11 @@
|
||||
TARGET = mmuhack
|
||||
INCLUDE = -I/opt/gcc-3.4.4-glibc-2.3.6/arm-open2x-linux/sys-include
|
||||
CFLAGS = -O2 -DMODULE -D__KERNEL__ ${INCLUDE}
|
||||
CC = arm-open2x-linux-gcc
|
||||
|
||||
all: ${TARGET}.o
|
||||
|
||||
${TARGET}.o: ${TARGET}.c
|
||||
|
||||
clean:
|
||||
rm -rf ${TARGET}.o
|
11
backends/platform/gp2x/mmuhack/flush_uppermem_cache.h
Executable file
11
backends/platform/gp2x/mmuhack/flush_uppermem_cache.h
Executable file
@ -0,0 +1,11 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void flush_uppermem_cache(void *start_address, void *end_address, int flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
6
backends/platform/gp2x/mmuhack/flush_uppermem_cache.s
Executable file
6
backends/platform/gp2x/mmuhack/flush_uppermem_cache.s
Executable file
@ -0,0 +1,6 @@
|
||||
.global flush_uppermem_cache @ void *start_address, void *end_address, int flags
|
||||
|
||||
flush_uppermem_cache:
|
||||
swi #0x9f0002
|
||||
bx lr
|
||||
|
129
backends/platform/gp2x/mmuhack/mmuhack.c
Executable file
129
backends/platform/gp2x/mmuhack/mmuhack.c
Executable file
@ -0,0 +1,129 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/gp2x/gp2x-mem.cpp $
|
||||
* $Id: gp2x-mem.cpp 39708 2009-03-27 14:12:42Z dhewg $
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
#define MMUHACK_MINOR 225
|
||||
#define DEVICE_NAME "mmuhack"
|
||||
|
||||
#if __GNUC__ == 3
|
||||
#include <linux/version.h>
|
||||
static const char __module_kernel_version_gcc3[] __attribute__((__used__)) __attribute__((section(".modinfo"))) =
|
||||
"kernel_version=" UTS_RELEASE;
|
||||
#endif
|
||||
|
||||
static ssize_t mmuhack_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
unsigned int *pgtable;
|
||||
unsigned int *cpt;
|
||||
int i, j;
|
||||
int ttb;
|
||||
int ret = -EFAULT;
|
||||
|
||||
// get the pointer to the translation table base...
|
||||
asm volatile(
|
||||
"stmdb sp!, {r0}\n\t"
|
||||
"mrc p15, 0, r0, c2, c0, 0\n\t"
|
||||
"mov %0, r0\n\t"
|
||||
"ldmia sp!, {r0}\n\t": "=r"(ttb)
|
||||
);
|
||||
|
||||
pgtable = __va(ttb);
|
||||
|
||||
for (i = 0; i < 4096; i ++) if ( (pgtable[i] & 3) == 1 ) {
|
||||
cpt = __va(pgtable[i] & 0xfffffc00);
|
||||
|
||||
for (j = 0; j < 256; j ++) {/*
|
||||
if ( (cpt[j] & 0xfe00000f) == 0x02000002 ) {
|
||||
// set C and B bits in upper 32MB memory area...
|
||||
printk("Set C&B bits %08x\n",cpt[j]);
|
||||
cpt[j] |= 0xFFC;
|
||||
ret = 0;
|
||||
}
|
||||
*/
|
||||
if (((cpt[j] & 0xff000000) == 0x02000000) && ((cpt[j] & 12)==0) )
|
||||
{
|
||||
//printk("Set C&B bits %08x\n",cpt[j]);
|
||||
cpt[j] |= 0xFFC;
|
||||
}
|
||||
//if ((a>=0x31 && a<=0x36) && ((cpt[i] & 12)==0))
|
||||
if (((cpt[j] & 0xff000000) == 0x03000000) && ((cpt[j] & 12)==0))
|
||||
{
|
||||
//printk("Set C&B bits %08x\n",cpt[j]);
|
||||
//printf("SDL c and b bits not set, overwriting\n");
|
||||
cpt[j] |= 0xFFC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drain the write buffer and flush the tlb caches...
|
||||
asm volatile(
|
||||
"stmdb sp!, {r0}\n\t"
|
||||
"mov r0, #0\n\t"
|
||||
"mcr 15, 0, r0, cr7, cr10, 4\n\t"
|
||||
"mcr 15, 0, r0, cr8, cr7, 0\n\t"
|
||||
"ldmia sp!, {r0}\n\t"
|
||||
);
|
||||
|
||||
if (ret == 0)
|
||||
printk("MMU hack applied.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations mmuhack_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: mmuhack_open,
|
||||
};
|
||||
|
||||
|
||||
static struct miscdevice mmuhack = {
|
||||
MMUHACK_MINOR, DEVICE_NAME, &mmuhack_fops
|
||||
};
|
||||
|
||||
static int __init mmuhack_init(void)
|
||||
{
|
||||
misc_register(&mmuhack);
|
||||
/*
|
||||
printk("MMSP2 MMU Hack module.\n");
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit mmuhack_exit(void)
|
||||
{
|
||||
misc_deregister(&mmuhack);
|
||||
/*
|
||||
printk(KERN_ALERT "MMU Hack module removed.\n");
|
||||
*/
|
||||
}
|
||||
|
||||
module_init(mmuhack_init);
|
||||
module_exit(mmuhack_exit);
|
110
backends/platform/gp2x/mmuhack/readme.txt
Executable file
110
backends/platform/gp2x/mmuhack/readme.txt
Executable file
@ -0,0 +1,110 @@
|
||||
About
|
||||
-----
|
||||
|
||||
This is a module for GP2X 2.4 based Linux kernel, created for developers to use in their
|
||||
programs.
|
||||
|
||||
Normally the upper 32MB is uncached. This means that reads/writes on the memory
|
||||
are always done via the physical memory modules rather than the much faster
|
||||
memory built into the processor (called 'cache'). Access to the upper 32MB can
|
||||
be sped up by Squidge's MMU hack. The easiest way to use the MMU hack is to add
|
||||
and load the MMU hack kernel module into your program.
|
||||
|
||||
Note: Building this module requries a GP2X 'kernel' toolchain (i.e. GCC 2.95.*
|
||||
for the GP2X stock, 3.* for Open2X).
|
||||
|
||||
You can't build this module with the GCC 4 based application toolchains.
|
||||
|
||||
Operation
|
||||
---------
|
||||
|
||||
When loaded into kernel, this module creates /dev/mmuhack device. Whenever
|
||||
a program opens that device using open() call, the module traverses all
|
||||
memory, which was allocated in 0x02000000-0x03ffffff range by the program via
|
||||
using mmap() system call. While doing that, it marks all encountered memory
|
||||
as bufferable and cacheable.
|
||||
|
||||
The most common use of this is to remove the framebuffer access bottleneck.
|
||||
Note that, however, by making the framebuffer cacheable you can cause display
|
||||
artifacts. This can happen because parts of your framebuffer may stay in CPU
|
||||
cache and not to be written back to the physical memory. The display
|
||||
controller only fetches data from the physical memory, so you get incomplete
|
||||
image (the memory will most likely contain data from previous frame, so these
|
||||
artifacts are better visible during fade effects). The easy way to fix this
|
||||
is by using a special ARM Linux system call, which flushes the cache (forces
|
||||
the CPU to write data in cache to the physical memory (see section "Flushing
|
||||
the cache")).
|
||||
|
||||
Using this module affects the whole upper memory area. But in some situations
|
||||
this may be not desirable, for example when using ARM940 core in your program
|
||||
(ether using 940 libraries like ogg940 and gpu940, or using your custom code,
|
||||
which needs uncacheable memory for communication and such). If you need part
|
||||
of your upper memory to be cached, and other part not, you should mmap() that
|
||||
memory (which you want to be uncached) _after_ doing open("/dev/mmuhack").
|
||||
Another way is to modify mmuhack.c to suit your needs and rebuild the module.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The very first thing to do is to load the kernel module (mmuhack.o) into the
|
||||
running kernel. But before that you should try to unload mmuhack module,
|
||||
because other program might have left a different version loaded with
|
||||
different memory configuration, which may not suit your program.
|
||||
|
||||
system("/sbin/rmmod mmuhack");
|
||||
system("/sbin/insmod mmuhack.o");
|
||||
|
||||
Now you can assume the module is loaded into kernel and open /dev/mmuhack
|
||||
device. You don't need to worry about previous calls failing, because in that
|
||||
case open() will simply fail and nothing bad will happen.
|
||||
|
||||
IMPORTANT: you _must_ do the open() call _after_ you initialize your graphics
|
||||
library or allocate your memory, because it can only work with memory which is
|
||||
already allocated, it won't affect memory you or your lib allocates after the
|
||||
open() call.
|
||||
|
||||
int mmufd = open("/dev/mmuhack", O_RDWR);
|
||||
if(mmufd < 0)
|
||||
{
|
||||
printf("MMU hack failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("MMU hack loaded");
|
||||
close(mmufd);
|
||||
}
|
||||
|
||||
If the above call succeeded, you are all done.
|
||||
I recommend to unload the module when your program exits, because the other
|
||||
program may want to load a different mmuhack.o and may fail, because you left
|
||||
your mmuhack.o loaded (it does not get unloaded automatically on exit).
|
||||
|
||||
system("/sbin/rmmod mmuhack");
|
||||
|
||||
|
||||
Flushing the cache
|
||||
------------------
|
||||
|
||||
If using mmuhack.o causes your program to display artifacts (see "Operation"
|
||||
section for explanation), you will need to flush the CPU cache. This should
|
||||
be done after finishing every frame and just before flipping your display
|
||||
buffer/surface. You will need to add flush_uppermem_cache.s file to your
|
||||
Makefile/project and add a call to flush_uppermem_cache() just before final
|
||||
framebuffer flip or blit.
|
||||
|
||||
flush_uppermem_cache() has 3 parameters. First param is the start address,
|
||||
second param is the end address, third one should always be 0. The addresses
|
||||
should be virtual ones (most often pointers to the start/end of your
|
||||
framebuffer). Example:
|
||||
|
||||
flush_uppermem_cache(screen_surface->pixels, screen_surface->pixels + 320*240, 0);
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
Original idea/implementation: Squidge (this whole thing is also known as squidgehack)
|
||||
Kernel module: NK
|
||||
Documentation: notaz
|
||||
|
Loading…
Reference in New Issue
Block a user