Hi everybody !
I trying to make some sort of PCI server...
I applied patch to mmap.c and cons2 (from David's page) to make possible
to flags=MAP_PHYS |MAP_FIXED and write little test code thet search for
BIOS32 signature in memory...
It leads to very strange error: (under GDB, when trying to call last
printf()) "Hmmm, unexpected stop reason 0x4 Program received signal
SIGTRAP Trace/breakpoint trap 0x6000295a in ??()" But all before that
printf() work fine ...
When it occured first time i change patch (offset now is "where-to-map"
instead of "what-to-map"), rebuild libs, servers and ... all useless...
Help me please (if it possible) !
My code:
#include <stdlib.h>
#include <sys/mman.h>
#include <stdio.h>
#include <sys/param.h>
#define BIOS32_SIGNATURE (('_'<<0) + ('3'<<8) + ('2'<<16) + ('_'<<24))
void main()
{
unsigned long *base, *check;
unsigned short a;
size_t len = 0x100000-0xe0000;
int num = len/sizeof(*base);
base = mmap((void *)0xe0000, len, PROT_READ, MAP_PHYS|MAP_FIXED, 0,
0xe0000L);
if (base == (void *)0 || base == (void *)-1) {
perror("mmap failed");
} else {
printf("Maping Ok! at %p\n", (void *)base);
}
for (check = base; check < base+num; ++check) {
if (*check == BIOS32_SIGNATURE) printf("BIOS32 signature found at
%p\n", check);
}
munmap((void *)base, len);
asm("mov %%cs, %w0": "=r" (a));
printf("Current segmet is: %sx\n", a);
}
I attached last version of mmap.c...
Yuriy.
/*
* mmap.c
* Primary user interface to the VM system
*/
#include <sys/mman.h>
#include <sys/vas.h>
#include <sys/pview.h>
#include <sys/pset.h>
#include <sys/percpu.h>
#include <sys/proc.h>
#include <sys/thread.h>
#include <sys/fs.h>
#include <sys/port.h>
#include <sys/misc.h>
#include <hash.h>
#include "../mach/mutex.h"
#include "pset.h"
/* Flag that we're not allowing a map hash to be created */
#define NO_MAP_HASH ((struct hash *)1)
/*
* mmap()
* Map something into the address space
*
* Many combinations of options are not allowed.
*/
void *
mmap(caddr_t addr, ulong len, int prot, int flags,
port_t port, ulong offset)
{
struct proc *p = curthread->t_proc;
struct vas *vas = &p->p_vas;
struct pview *pv;
struct pset *ps;
void *vaddr;
/*
* Anonymous memory
*/
if (flags & MAP_ANON) {
/*
* Keep it simple, eh? Read-only ZFOD???
*/
if ((flags & (MAP_FILE|MAP_FIXED|MAP_PHYS)) ||
!(prot & PROT_WRITE)) {
err(EINVAL);
return(0);
}
/*
* Get view/set
*/
ps = alloc_pset_zfod(btorp(len));
pv = alloc_pview(ps);
/*
* Flag view as from mmap(). We use this to keep
* munmap() honest; it only works on views which
* were created by the user.
*/
pv->p_prot |= PROT_MMAP;
/*
* If shared, turn on bit
*/
if (flags & MAP_SHARED) {
ps->p_flags |= PF_SHARED;
}
/*
* Try to attach
*/
pv->p_vaddr = addr;
vaddr = attach_pview(vas, pv);
if (vaddr == 0) {
free_pview(pv);
}
return(vaddr);
}
/*
* Physical mapping
*/
if (flags & MAP_PHYS) {
/*
* Sanity
*/
if (flags & MAP_FILE) {
err(EINVAL);
return(0);
}
/*
* Protection
*/
if (!issys()) {
return(0);
}
/*
* Get a physical pset, create a view, map it in.
*/
ps = physmem_pset(btop(addr), btorp(len));
pv = alloc_pview(ps);
pv->p_prot = PROT_MMAP;
if (flags & MAP_FIXED) pv->p_vaddr = (void *)offset;
vaddr = attach_pview(vas, pv);
if (vaddr == 0) {
free_pview(pv);
}
return(vaddr);
}
/*
* Create read-only or copy-on-write view of a file
*/
if (flags & MAP_FILE) {
struct portref *pr;
/*
* If writing, make sure they're asking for COW; we
* don't support writing back to a server via mmap().
* It's nasty to do.
*/
if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE)) {
err(EINVAL);
return(0);
}
/*
* Get the portref. add_map() creates new portrefs
* as necessary, so just use the open file.
*/
pr = find_portref(p, port);
if (pr == 0) {
return(0);
}
v_lock(&pr->p_lock, SPL0_SAME);
/*
* Try to generate a view. Return address or error.
*/
addr = add_map(vas, pr, addr,
btorp(len + (offset - ptob(btop(offset)))),
btop(offset), !(prot & PROT_WRITE));
v_sema(&pr->p_sema);
if (addr) {
return(addr);
}
/* VVV fall down to common error case VVV */
}
err(EINVAL);
return(0);
}
/*
* munmap()
* Unmap a region given an address within
*/
int
munmap(caddr_t vaddr, ulong len)
{
struct vas *vas = &curthread->t_proc->p_vas;
struct pview *pv;
struct pset *ps;
/*
* Look for the view which matches
*/
pv = find_pview(vas, vaddr);
if (!pv) {
return(err(EINVAL));
}
ps = pv->p_set;
/*
* Make sure it's an mmap()'ed view. Turn off bit so once we
* release the lock and call detach_view(), we can't race with
* another thread coming into munmap().
*/
if ((pv->p_prot & PROT_MMAP) == 0) {
v_lock(&ps->p_lock, SPL0_SAME);
return(err(EBUSY));
}
pv->p_prot &= ~(PROT_MMAP);
v_lock(&ps->p_lock, SPL0_SAME);
/*
* Blow it away
*/
remove_pview(vas, vaddr);
return(0);
}
/*
* get_map_pset()
* Return pset view of named file
*
* Servers must support the FS_FID function in order to allow
* mapping of files.
*/
static struct pset *
get_map_pset(struct portref *pr)
{
struct pset *ps;
long args[3];
struct port *port;
/*
* Hold mutex so we're the only one searching/updating the
* cache of mappings. This also keeps the port from shutting
* on us.
*/
p_lock_void(&pr->p_lock, SPL0);
port = pr->p_port;
if (port) {
if ((port->p_flags & P_CLOSING) ||
(port->p_maps == NO_MAP_HASH)) {
v_lock(&pr->p_lock, SPL0_SAME);
port = 0;
} else {
p_sema_v_lock(&port->p_mapsema, PRIHI,
&pr->p_lock);
}
}
/*
* Try to get file ID. This also gets us the file's
* size.
*/
if (!port) {
return(0);
}
if (kernmsg_send(pr, FS_FID, args)) {
v_sema(&port->p_mapsema);
return(0);
}
/*
* If there's a hash already, search it for our ID. Otherwise
* create a new hash and flag that we didn't find the pset.
*/
if (port->p_maps) {
ps = hash_lookup(port->p_maps, args[0]);
} else {
/*
* New hash table. Is 32 a good number? Who knows?
*/
port->p_maps = hash_alloc(32);
ps = 0;
}
/*
* If the file's changed size, invalidate the old executable
* cache so we can set up the new one.
*/
if (ps && (ps->p_len != args[1])) {
(void)hash_delete(port->p_maps, args[0]);
deref_pset(ps);
ps = 0;
}
/*
* If no pset, create one and insert it. The mapping in
* the hash counts as a reference.
*/
if (ps == 0) {
struct portref *newpr;
newpr = dup_port(pr);
if (newpr == 0) {
v_sema(&port->p_mapsema);
return(0);
}
ps = alloc_pset_fod(newpr, args[1]);
(void)hash_insert(port->p_maps, args[0], ps);
ref_pset(ps);
}
/*
* Leave an extra ref on the pset so it won't go away
* while we add views to it. Our caller will release
* this ref once he's done his own refs.
*/
ref_pset(ps);
/*
* Release sema and return pset
*/
v_sema(&port->p_mapsema);
return(ps);
}
/*
* add_map()
* Add a mmap view of the given file
*
* Returns 0 on failure, attach address on success
*/
void *
add_map(struct vas *vas, struct portref *pr, caddr_t vaddr, ulong len,
ulong off, int readonly)
{
struct pset *ps;
struct pview *pv;
int err;
/*
* Get underlying pset; might be cached
*/
ps = get_map_pset(pr);
if (ps == 0) {
return(0);
}
/*
* Create a pview of the given size
*/
if (readonly) {
/*
* Read-only is a simple view into the pset
*/
pv = alloc_pview(ps);
pv->p_prot = PROT_RO;
if (pv->p_len > off) {
pv->p_off = off;
pv->p_len -= off;
}
} else {
struct pset *ps2;
/*
* Read/write means the view is copy-on-write;
* insert a COW pset on top of the straight
* view.
*/
ps2 = alloc_pset_cow(ps, off, len);
pv = alloc_pview(ps2);
pv->p_prot = 0;
pv->p_off = 0;
}
if (len < pv->p_len)
pv->p_len = len;
pv->p_vaddr = vaddr;
/*
* Try to attach. Throw away if it's rejected. Most
* likely this is a bogus filemap, with an address
* which the HAT rejected.
*/
err = (attach_pview(vas, pv) == 0);
if (err) {
free_pview(pv);
}
/*
* Drop "placeholder" ref to pset (see get_map_pset())
*/
deref_pset(ps);
return(err ? 0 : pv->p_vaddr);
}
/*
* do_derefport()
* Release a cached access to a port
*/
static int
do_derefport(long keydummy, struct pset *ps, void *dummy)
{
deref_pset(ps);
return(0);
}
/*
* mmap_cleanup()
* Clean up mapped file cache, if any
*/
void
mmap_cleanup(struct port *port)
{
/*
* Take map mutex
*/
p_sema(&port->p_mapsema, PRIHI);
/*
* No cache--nothing to do
*/
if (port->p_maps == 0) {
v_sema(&port->p_mapsema);
return;
}
/*
* Remove reference from pset for each entry
* in our cache.
*/
hash_foreach(port->p_maps, do_derefport, 0);
/*
* Free the hash storage, flag port as shutting down
*/
hash_dealloc(port->p_maps);
port->p_maps = NO_MAP_HASH;
v_sema(&port->p_mapsema);
}
/*
* unhash()
* Unhash any reference to the indicated hash #
*/
int
unhash(port_t arg_port, long arg_fid)
{
struct port *port;
struct proc *p = curthread->t_proc;
/*
* Verify range
*/
if (arg_port < PROCOPENS) {
return(err(EBADF));
}
arg_port -= PROCOPENS;
if (arg_port >= PROCPORTS) {
return(err(EBADF));
}
/*
* Interlock, get access to port, atomically switch
* to mapsema.
*/
if (p_sema(&p->p_sema, PRICATCH)) {
return(err(EINTR));
}
port = p->p_ports[arg_port];
if (port == 0) {
v_sema(&p->p_sema);
return(err(EBADF));
}
p_lock_void(&port->p_lock, SPLHI);
v_sema(&p->p_sema);
p_sema_v_lock(&port->p_mapsema, PRIHI, &port->p_lock);
/*
* If there's a map, delete entry from it
*/
if (port->p_maps && (port->p_maps != NO_MAP_HASH)) {
struct pset *ps;
ps = hash_lookup(port->p_maps, arg_fid);
if (ps) {
(void)hash_delete(port->p_maps, arg_fid);
deref_pset(ps);
}
}
/*
* Release mutex, return success
*/
v_sema(&port->p_mapsema);
return(0);
}
Received on Sat May 30 02:23:09 1998
This archive was generated by hypermail 2.1.8 : Thu Sep 22 2005 - 15:12:43 PDT