summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLisa Hsu <hsul@eecs.umich.edu>2009-02-16 17:47:39 -0500
committerLisa Hsu <hsul@eecs.umich.edu>2009-02-16 17:47:39 -0500
commit5d029ff11e88ba0ab89c88e500c5d0d2edaf744e (patch)
treea8a7a44ac0d2fb3dedf3b33ec887c3f7dc9ebdd7
parent89ea32325094665c16688212b5a2cd7b7bbf5f03 (diff)
downloadgem5-5d029ff11e88ba0ab89c88e500c5d0d2edaf744e.tar.xz
sycalls: implement mremap() and add DATA flag for getrlimit(). mremap has been tested on Alpha, compiles for the rest but not tested. I don't see why it wouldn't work though.
-rw-r--r--src/arch/alpha/linux/process.cc2
-rw-r--r--src/arch/alpha/pagetable.hh7
-rw-r--r--src/arch/mips/linux/process.cc2
-rw-r--r--src/arch/mips/tlb.hh3
-rw-r--r--src/arch/sparc/linux/syscalls.cc4
-rw-r--r--src/arch/sparc/pagetable.hh6
-rw-r--r--src/arch/x86/linux/syscalls.cc2
-rw-r--r--src/arch/x86/pagetable.hh6
-rw-r--r--src/mem/page_table.cc38
-rw-r--r--src/mem/page_table.hh2
-rw-r--r--src/sim/syscall_emul.hh55
11 files changed, 121 insertions, 6 deletions
diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc
index 6684051af..605e40627 100644
--- a/src/arch/alpha/linux/process.cc
+++ b/src/arch/alpha/linux/process.cc
@@ -463,7 +463,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 338 */ SyscallDesc("afs_syscall", unimplementedFunc),
/* 339 */ SyscallDesc("uname", unameFunc),
/* 340 */ SyscallDesc("nanosleep", unimplementedFunc),
- /* 341 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 341 */ SyscallDesc("mremap", mremapFunc<AlphaLinux>),
/* 342 */ SyscallDesc("nfsservctl", unimplementedFunc),
/* 343 */ SyscallDesc("setresuid", unimplementedFunc),
/* 344 */ SyscallDesc("getresuid", unimplementedFunc),
diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh
index 6cf11be56..59df93bef 100644
--- a/src/arch/alpha/pagetable.hh
+++ b/src/arch/alpha/pagetable.hh
@@ -123,6 +123,13 @@ struct TlbEntry
TlbEntry()
{}
+ void
+ updateVaddr(Addr new_vaddr)
+ {
+ VAddr vaddr(new_vaddr);
+ tag = vaddr.vpn();
+ }
+
Addr
pageStart()
{
diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc
index ce09e1628..9d9d33325 100644
--- a/src/arch/mips/linux/process.cc
+++ b/src/arch/mips/linux/process.cc
@@ -288,7 +288,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 164 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
/* 165 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
/* 166 */ SyscallDesc("nanosleep", unimplementedFunc),
- /* 167 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 167 */ SyscallDesc("mremap", mremapFunc<MipsLinux>),
/* 168 */ SyscallDesc("accept", unimplementedFunc),
/* 169 */ SyscallDesc("bind", unimplementedFunc),
/* 170 */ SyscallDesc("connect", unimplementedFunc),
diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh
index feb2509c5..4a8fc32ac 100644
--- a/src/arch/mips/tlb.hh
+++ b/src/arch/mips/tlb.hh
@@ -68,6 +68,9 @@ struct TlbEntry
return _pageStart;
}
+ void
+ updateVaddr(Addr new_vaddr) {}
+
void serialize(std::ostream &os)
{
SERIALIZE_SCALAR(_pageStart);
diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc
index 2845f7bec..3e8c603cd 100644
--- a/src/arch/sparc/linux/syscalls.cc
+++ b/src/arch/sparc/linux/syscalls.cc
@@ -339,7 +339,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
/* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), //32 bit
/* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), //32 bit
/* 249 */ SyscallDesc("nanosleep", unimplementedFunc),
- /* 250 */ SyscallDesc("mremap", unimplementedFunc), //32 bit
+ /* 250 */ SyscallDesc("mremap", mremapFunc<Sparc32Linux>), //32 bit
/* 251 */ SyscallDesc("_sysctl", unimplementedFunc), //32 bit
/* 252 */ SyscallDesc("getsid", unimplementedFunc), //32 bit
/* 253 */ SyscallDesc("fdatasync", unimplementedFunc),
@@ -642,7 +642,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
/* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
/* 249 */ SyscallDesc("nanosleep", unimplementedFunc),
- /* 250 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 250 */ SyscallDesc("mremap", mremapFunc<SparcLinux>),
/* 251 */ SyscallDesc("_sysctl", unimplementedFunc),
/* 252 */ SyscallDesc("getsid", unimplementedFunc),
/* 253 */ SyscallDesc("fdatasync", unimplementedFunc),
diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh
index ee4ca0c2c..cbdabe4c3 100644
--- a/src/arch/sparc/pagetable.hh
+++ b/src/arch/sparc/pagetable.hh
@@ -266,6 +266,12 @@ struct TlbEntry
return pte.paddr();
}
+ void
+ updateVaddr(Addr new_vaddr)
+ {
+ range.va = new_vaddr;
+ }
+
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc
index 754fb2eaf..ca35a5dd6 100644
--- a/src/arch/x86/linux/syscalls.cc
+++ b/src/arch/x86/linux/syscalls.cc
@@ -148,7 +148,7 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = {
/* 22 */ SyscallDesc("pipe", unimplementedFunc),
/* 23 */ SyscallDesc("select", unimplementedFunc),
/* 24 */ SyscallDesc("sched_yield", unimplementedFunc),
- /* 25 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 25 */ SyscallDesc("mremap", mremapFunc<X86Linux64>),
/* 26 */ SyscallDesc("msync", unimplementedFunc),
/* 27 */ SyscallDesc("mincore", unimplementedFunc),
/* 28 */ SyscallDesc("madvise", unimplementedFunc),
diff --git a/src/arch/x86/pagetable.hh b/src/arch/x86/pagetable.hh
index e42693c03..1a7a945e4 100644
--- a/src/arch/x86/pagetable.hh
+++ b/src/arch/x86/pagetable.hh
@@ -113,6 +113,12 @@ namespace X86ISA
TlbEntry(Addr asn, Addr _vaddr, Addr _paddr);
TlbEntry() {}
+ void
+ updateVaddr(Addr new_vaddr)
+ {
+ vaddr = new_vaddr;
+ }
+
Addr pageStart()
{
return paddr;
diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc
index 54165f293..bdcbbfec3 100644
--- a/src/mem/page_table.cc
+++ b/src/mem/page_table.cc
@@ -87,6 +87,44 @@ PageTable::allocate(Addr vaddr, int64_t size)
}
}
+void
+PageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
+{
+ assert(pageOffset(vaddr) == 0);
+ assert(pageOffset(new_vaddr) == 0);
+
+ DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
+ new_vaddr, size);
+
+ for (; size > 0; size -= pageSize, vaddr += pageSize, new_vaddr += pageSize) {
+ PTableItr iter = pTable.find(vaddr);
+
+ assert(iter != pTable.end());
+
+ pTable[new_vaddr] = pTable[vaddr];
+ pTable.erase(vaddr);
+ pTable[new_vaddr].updateVaddr(new_vaddr);
+ updateCache(new_vaddr, pTable[new_vaddr]);
+ }
+}
+
+void
+PageTable::deallocate(Addr vaddr, int64_t size)
+{
+ assert(pageOffset(vaddr) == 0);
+
+ DPRINTF(MMU, "Deallocating page: %#x-%#x\n", vaddr, vaddr+ size);
+
+ for (; size > 0; size -= pageSize, vaddr += pageSize) {
+ PTableItr iter = pTable.find(vaddr);
+
+ assert(iter != pTable.end());
+
+ pTable.erase(vaddr);
+ }
+
+}
+
bool
PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
{
diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh
index 6ff0be082..d4101c6bf 100644
--- a/src/mem/page_table.hh
+++ b/src/mem/page_table.hh
@@ -80,6 +80,8 @@ class PageTable
Addr pageOffset(Addr a) { return (a & offsetMask); }
void allocate(Addr vaddr, int64_t size);
+ void remap(Addr vaddr, int64_t size, Addr new_vaddr);
+ void deallocate(Addr vaddr, int64_t size);
/**
* Lookup function
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index c334c1e26..0e34a835e 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -607,6 +607,51 @@ fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return 0;
}
+/// Target mremap() handler.
+template <class OS>
+SyscallReturn
+mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
+{
+ Addr start = tc->getSyscallArg(0);
+ uint64_t old_length = tc->getSyscallArg(1);
+ uint64_t new_length = tc->getSyscallArg(2);
+ uint64_t flags = tc->getSyscallArg(3);
+
+ if ((start % TheISA::VMPageSize != 0) ||
+ (new_length % TheISA::VMPageSize != 0)) {
+ warn("mremap failing: arguments not page aligned");
+ return -EINVAL;
+ }
+
+ if (new_length > old_length) {
+ if ((start + old_length) == process->mmap_end) {
+ uint64_t diff = new_length - old_length;
+ process->pTable->allocate(process->mmap_end, diff);
+ process->mmap_end += diff;
+ return start;
+ } else {
+ // sys/mman.h defined MREMAP_MAYMOVE
+ if (!(flags & 1)) {
+ warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
+ return -ENOMEM;
+ } else {
+ process->pTable->remap(start, old_length, process->mmap_end);
+ warn("mremapping to totally new vaddr %08p-%08p, adding %d\n",
+ process->mmap_end, process->mmap_end + new_length, new_length);
+ start = process->mmap_end;
+ // add on the remaining unallocated pages
+ process->pTable->allocate(start + old_length, new_length - old_length);
+ process->mmap_end += new_length;
+ warn("returning %08p as start\n", start);
+ return start;
+ }
+ }
+ } else {
+ process->pTable->deallocate(start + new_length, old_length -
+ new_length);
+ return start;
+ }
+}
/// Target stat() handler.
template <class OS>
@@ -892,6 +937,7 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
// int fd = p->sim_fd(tc->getSyscallArg(4));
// int offset = tc->getSyscallArg(5);
+
if ((start % TheISA::VMPageSize) != 0 ||
(length % TheISA::VMPageSize) != 0) {
warn("mmap failing: arguments not page-aligned: "
@@ -929,12 +975,19 @@ getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
switch (resource) {
case OS::TGT_RLIMIT_STACK:
- // max stack size in bytes: make up a number (2MB for now)
+ // max stack size in bytes: make up a number (8MB for now)
rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
rlp->rlim_cur = htog(rlp->rlim_cur);
rlp->rlim_max = htog(rlp->rlim_max);
break;
+ case OS::TGT_RLIMIT_DATA:
+ // max data segment size in bytes: make up a number
+ rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
+ rlp->rlim_cur = htog(rlp->rlim_cur);
+ rlp->rlim_max = htog(rlp->rlim_max);
+ break;
+
default:
std::cerr << "getrlimitFunc: unimplemented resource " << resource
<< std::endl;