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().
|
/// For mmap().
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x100;
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/// For getsysinfo().
|
/// For getsysinfo().
|
||||||
|
|
|
@ -64,6 +64,7 @@ class AlphaTru64 : public Tru64
|
||||||
|
|
||||||
/// For mmap().
|
/// For mmap().
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x100;
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/// For getsysinfo().
|
/// For getsysinfo().
|
||||||
|
|
|
@ -91,6 +91,7 @@ class ArmLinux : public Linux
|
||||||
|
|
||||||
/// For mmap().
|
/// For mmap().
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/// For getrusage().
|
/// For getrusage().
|
||||||
|
|
|
@ -65,6 +65,7 @@ class MipsLinux : public Linux
|
||||||
|
|
||||||
/// For mmap().
|
/// For mmap().
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x800;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x800;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/// For getsysinfo().
|
/// For getsysinfo().
|
||||||
|
|
|
@ -127,6 +127,7 @@ class PowerLinux : public Linux
|
||||||
|
|
||||||
/// For mmap().
|
/// For mmap().
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
/// ioctl() command codes.
|
/// ioctl() command codes.
|
||||||
|
|
|
@ -77,6 +77,7 @@ class SparcLinux : public Linux
|
||||||
static const int NUM_OPEN_FLAGS;
|
static const int NUM_OPEN_FLAGS;
|
||||||
|
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int64_t uptime; /* Seconds since boot */
|
int64_t uptime; /* Seconds since boot */
|
||||||
|
|
|
@ -59,6 +59,7 @@ class SparcSolaris : public Solaris
|
||||||
static const int NUM_OPEN_FLAGS;
|
static const int NUM_OPEN_FLAGS;
|
||||||
|
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x100;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x100;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -88,6 +88,7 @@ class X86Linux64 : public Linux
|
||||||
static const int NUM_OPEN_FLAGS;
|
static const int NUM_OPEN_FLAGS;
|
||||||
|
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t iov_base; // void *
|
uint64_t iov_base; // void *
|
||||||
|
@ -158,6 +159,7 @@ class X86Linux32 : public Linux
|
||||||
static const int NUM_OPEN_FLAGS;
|
static const int NUM_OPEN_FLAGS;
|
||||||
|
|
||||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||||
|
static const unsigned TGT_MAP_FIXED = 0x10;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t uptime; /* Seconds since boot */
|
int32_t uptime; /* Seconds since boot */
|
||||||
|
|
|
@ -67,7 +67,7 @@ PageTable::~PageTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PageTable::allocate(Addr vaddr, int64_t size)
|
PageTable::allocate(Addr vaddr, int64_t size, bool clobber)
|
||||||
{
|
{
|
||||||
// starting address must be page aligned
|
// starting address must be page aligned
|
||||||
assert(pageOffset(vaddr) == 0);
|
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);
|
DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size);
|
||||||
|
|
||||||
for (; size > 0; size -= pageSize, vaddr += pageSize) {
|
for (; size > 0; size -= pageSize, vaddr += pageSize) {
|
||||||
PTableItr iter = pTable.find(vaddr);
|
if (!clobber && (pTable.find(vaddr) != pTable.end())) {
|
||||||
|
|
||||||
if (iter != pTable.end()) {
|
|
||||||
// already mapped
|
// already mapped
|
||||||
fatal("PageTable::allocate: address 0x%x already mapped",
|
fatal("PageTable::allocate: address 0x%x already mapped", vaddr);
|
||||||
vaddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pTable[vaddr] = TheISA::TlbEntry(process->M5_pid, vaddr,
|
pTable[vaddr] = TheISA::TlbEntry(process->M5_pid, vaddr,
|
||||||
process->system->new_page());
|
process->system->new_page());
|
||||||
updateCache(vaddr, pTable[vaddr]);
|
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
|
bool
|
||||||
PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
|
PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,10 +79,18 @@ class PageTable
|
||||||
Addr pageAlign(Addr a) { return (a & ~offsetMask); }
|
Addr pageAlign(Addr a) { return (a & ~offsetMask); }
|
||||||
Addr pageOffset(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 remap(Addr vaddr, int64_t size, Addr new_vaddr);
|
||||||
void deallocate(Addr vaddr, int64_t size);
|
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
|
* Lookup function
|
||||||
* @param vaddr The virtual address.
|
* @param vaddr The virtual address.
|
||||||
|
|
|
@ -1027,20 +1027,45 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start != 0) {
|
// are we ok with clobbering existing mappings? only set this to
|
||||||
warn("mmap: ignoring suggested map address 0x%x, using 0x%x",
|
// true if the user has been warned.
|
||||||
start, p->mmap_end);
|
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 (!use_provided_address) {
|
||||||
if (OS::mmapGrowsDown()) {
|
// no address provided, or provided address unusable:
|
||||||
start = p->mmap_end - length;
|
// pick next address from our "mmap region"
|
||||||
p->mmap_end = start;
|
if (OS::mmapGrowsDown()) {
|
||||||
} else {
|
start = p->mmap_end - length;
|
||||||
start = p->mmap_end;
|
p->mmap_end = start;
|
||||||
p->mmap_end += length;
|
} else {
|
||||||
|
start = p->mmap_end;
|
||||||
|
p->mmap_end += length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p->pTable->allocate(start, length);
|
|
||||||
|
p->pTable->allocate(start, length, clobber);
|
||||||
|
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue