syscall_emul: implement MAP_FIXED option to mmap()
This commit is contained in:
parent
c6dd122fee
commit
4d5f2c28a8
11 changed files with 73 additions and 19 deletions
|
@ -69,6 +69,7 @@ class AlphaLinux : public Linux
|
|||
|
||||
/// For mmap().
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
|
||||
static const unsigned TGT_MAP_FIXED = 0x100;
|
||||
|
||||
//@{
|
||||
/// For getsysinfo().
|
||||
|
|
|
@ -64,6 +64,7 @@ class AlphaTru64 : public Tru64
|
|||
|
||||
/// For mmap().
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
|
||||
static const unsigned TGT_MAP_FIXED = 0x100;
|
||||
|
||||
//@{
|
||||
/// For getsysinfo().
|
||||
|
|
|
@ -91,6 +91,7 @@ class ArmLinux : public Linux
|
|||
|
||||
/// For mmap().
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
|
||||
//@{
|
||||
/// For getrusage().
|
||||
|
|
|
@ -65,6 +65,7 @@ class MipsLinux : public Linux
|
|||
|
||||
/// For mmap().
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x800;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
|
||||
//@{
|
||||
/// For getsysinfo().
|
||||
|
|
|
@ -127,6 +127,7 @@ class PowerLinux : public Linux
|
|||
|
||||
/// For mmap().
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
|
||||
//@{
|
||||
/// ioctl() command codes.
|
||||
|
|
|
@ -77,6 +77,7 @@ class SparcLinux : public Linux
|
|||
static const int NUM_OPEN_FLAGS;
|
||||
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
|
||||
typedef struct {
|
||||
int64_t uptime; /* Seconds since boot */
|
||||
|
|
|
@ -59,6 +59,7 @@ class SparcSolaris : public Solaris
|
|||
static const int NUM_OPEN_FLAGS;
|
||||
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x100;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -88,6 +88,7 @@ class X86Linux64 : public Linux
|
|||
static const int NUM_OPEN_FLAGS;
|
||||
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
|
||||
typedef struct {
|
||||
uint64_t iov_base; // void *
|
||||
|
@ -158,6 +159,7 @@ class X86Linux32 : public Linux
|
|||
static const int NUM_OPEN_FLAGS;
|
||||
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||
|
||||
typedef struct {
|
||||
int32_t uptime; /* Seconds since boot */
|
||||
|
|
|
@ -67,7 +67,7 @@ PageTable::~PageTable()
|
|||
}
|
||||
|
||||
void
|
||||
PageTable::allocate(Addr vaddr, int64_t size)
|
||||
PageTable::allocate(Addr vaddr, int64_t size, bool clobber)
|
||||
{
|
||||
// starting address must be page aligned
|
||||
assert(pageOffset(vaddr) == 0);
|
||||
|
@ -75,16 +75,13 @@ PageTable::allocate(Addr vaddr, int64_t size)
|
|||
DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size);
|
||||
|
||||
for (; size > 0; size -= pageSize, vaddr += pageSize) {
|
||||
PTableItr iter = pTable.find(vaddr);
|
||||
|
||||
if (iter != pTable.end()) {
|
||||
if (!clobber && (pTable.find(vaddr) != pTable.end())) {
|
||||
// already mapped
|
||||
fatal("PageTable::allocate: address 0x%x already mapped",
|
||||
vaddr);
|
||||
fatal("PageTable::allocate: address 0x%x already mapped", vaddr);
|
||||
}
|
||||
|
||||
pTable[vaddr] = TheISA::TlbEntry(process->M5_pid, vaddr,
|
||||
process->system->new_page());
|
||||
process->system->new_page());
|
||||
updateCache(vaddr, pTable[vaddr]);
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +124,21 @@ PageTable::deallocate(Addr vaddr, int64_t size)
|
|||
|
||||
}
|
||||
|
||||
bool
|
||||
PageTable::isUnmapped(Addr vaddr, int64_t size)
|
||||
{
|
||||
// starting address must be page aligned
|
||||
assert(pageOffset(vaddr) == 0);
|
||||
|
||||
for (; size > 0; size -= pageSize, vaddr += pageSize) {
|
||||
if (pTable.find(vaddr) != pTable.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
|
||||
{
|
||||
|
|
|
@ -79,10 +79,18 @@ class PageTable
|
|||
Addr pageAlign(Addr a) { return (a & ~offsetMask); }
|
||||
Addr pageOffset(Addr a) { return (a & offsetMask); }
|
||||
|
||||
void allocate(Addr vaddr, int64_t size);
|
||||
void allocate(Addr vaddr, int64_t size, bool clobber = false);
|
||||
void remap(Addr vaddr, int64_t size, Addr new_vaddr);
|
||||
void deallocate(Addr vaddr, int64_t size);
|
||||
|
||||
/**
|
||||
* Check if any pages in a region are already allocated
|
||||
* @param vaddr The starting virtual address of the region.
|
||||
* @param size The length of the region.
|
||||
* @return True if no pages in the region are mapped.
|
||||
*/
|
||||
bool isUnmapped(Addr vaddr, int64_t size);
|
||||
|
||||
/**
|
||||
* Lookup function
|
||||
* @param vaddr The virtual address.
|
||||
|
|
|
@ -1027,20 +1027,45 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (start != 0) {
|
||||
warn("mmap: ignoring suggested map address 0x%x, using 0x%x",
|
||||
start, p->mmap_end);
|
||||
// are we ok with clobbering existing mappings? only set this to
|
||||
// true if the user has been warned.
|
||||
bool clobber = false;
|
||||
|
||||
// try to use the caller-provided address if there is one
|
||||
bool use_provided_address = (start != 0);
|
||||
|
||||
if (use_provided_address) {
|
||||
// check to see if the desired address is already in use
|
||||
if (!p->pTable->isUnmapped(start, length)) {
|
||||
// there are existing mappings in the desired range
|
||||
// whether we clobber them or not depends on whether the caller
|
||||
// specified MAP_FIXED
|
||||
if (flags & OS::TGT_MAP_FIXED) {
|
||||
// MAP_FIXED specified: clobber existing mappings
|
||||
warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n",
|
||||
start);
|
||||
clobber = true;
|
||||
} else {
|
||||
// MAP_FIXED not specified: ignore suggested start address
|
||||
warn("mmap: ignoring suggested map address 0x%x\n", start);
|
||||
use_provided_address = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pick next address from our "mmap region"
|
||||
if (OS::mmapGrowsDown()) {
|
||||
start = p->mmap_end - length;
|
||||
p->mmap_end = start;
|
||||
} else {
|
||||
start = p->mmap_end;
|
||||
p->mmap_end += length;
|
||||
if (!use_provided_address) {
|
||||
// no address provided, or provided address unusable:
|
||||
// pick next address from our "mmap region"
|
||||
if (OS::mmapGrowsDown()) {
|
||||
start = p->mmap_end - length;
|
||||
p->mmap_end = start;
|
||||
} else {
|
||||
start = p->mmap_end;
|
||||
p->mmap_end += length;
|
||||
}
|
||||
}
|
||||
p->pTable->allocate(start, length);
|
||||
|
||||
p->pTable->allocate(start, length, clobber);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue