mem-cache: Add multiple eviction stats
[gem5.git] / src / arch / x86 / process.cc
index cfec21f393aee00574a9ccb6ebf668b01db087ee..f270b2d8f258c0ca645b65e580ec20ed272d8639 100644 (file)
@@ -119,7 +119,7 @@ X86Process::X86Process(ProcessParams *params, ObjectFile *objFile,
 }
 
 void X86Process::clone(ThreadContext *old_tc, ThreadContext *new_tc,
-                       Process *p, TheISA::IntReg flags)
+                       Process *p, RegVal flags)
 {
     Process::clone(old_tc, new_tc, p, flags);
     X86Process *process = (X86Process*)p;
@@ -136,8 +136,7 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile,
     vsyscallPage.vtimeOffset = 0x400;
     vsyscallPage.vgettimeofdayOffset = 0x0;
 
-    Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() +
-                             objFile->bssSize(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     Addr stack_base = 0x7FFFFFFFF000ULL;
     Addr max_stack_size = 8 * 1024 * 1024;
     Addr next_thread_stack_base = stack_base - max_stack_size;
@@ -147,24 +146,14 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile,
                                      next_thread_stack_base, mmap_end);
 }
 
-void
-I386Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault)
-{
-    TheISA::PCState pc = tc->pcState();
-    Addr eip = pc.pc();
-    if (eip >= vsyscallPage.base &&
-            eip < vsyscallPage.base + vsyscallPage.size) {
-        pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset);
-        tc->pcState(pc);
-    }
-    X86Process::syscall(callnum, tc, fault);
-}
-
 
 I386Process::I386Process(ProcessParams *params, ObjectFile *objFile,
                          SyscallDesc *_syscallDescs, int _numSyscallDescs)
     : X86Process(params, objFile, _syscallDescs, _numSyscallDescs)
 {
+    if (kvmInSE)
+        panic("KVM CPU model does not support 32 bit processes");
+
     _gdtStart = ULL(0xffffd000);
     _gdtSize = PageBytes;
 
@@ -173,8 +162,7 @@ I386Process::I386Process(ProcessParams *params, ObjectFile *objFile,
     vsyscallPage.vsyscallOffset = 0x400;
     vsyscallPage.vsysexitOffset = 0x410;
 
-    Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() +
-                             objFile->bssSize(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     Addr stack_base = _gdtStart;
     Addr max_stack_size = 8 * 1024 * 1024;
     Addr next_thread_stack_base = stack_base - max_stack_size;
@@ -197,6 +185,9 @@ X86_64Process::initState()
 {
     X86Process::initState();
 
+    if (useForClone)
+        return;
+
     argsInit(PageBytes);
 
     // Set up the vsyscall page for this process.
@@ -233,7 +224,7 @@ X86_64Process::initState()
         uint8_t numGDTEntries = 0;
         uint64_t nullDescriptor = 0;
         physProxy.writeBlob(gdtPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&nullDescriptor), 8);
+                            &nullDescriptor, 8);
         numGDTEntries++;
 
         SegDescriptor initDesc = 0;
@@ -244,12 +235,10 @@ X86_64Process::initState()
         initDesc.p = 1;               // present
         initDesc.l = 1;               // longmode - 64 bit
         initDesc.d = 0;               // operand size
-        initDesc.g = 1;               // granularity
+        initDesc.g = 1;
         initDesc.s = 1;               // system segment
-        initDesc.limitHigh = 0xFFFF;
-        initDesc.limitLow = 0xF;
-        initDesc.baseHigh = 0x0;
-        initDesc.baseLow = 0x0;
+        initDesc.limit = 0xFFFFFFFF;
+        initDesc.base = 0;
 
         //64 bit code segment
         SegDescriptor csLowPLDesc = initDesc;
@@ -257,7 +246,7 @@ X86_64Process::initState()
         csLowPLDesc.dpl = 0;
         uint64_t csLowPLDescVal = csLowPLDesc;
         physProxy.writeBlob(gdtPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&csLowPLDescVal), 8);
+                            &csLowPLDescVal, 8);
 
         numGDTEntries++;
 
@@ -271,7 +260,7 @@ X86_64Process::initState()
         dsLowPLDesc.dpl = 0;
         uint64_t dsLowPLDescVal = dsLowPLDesc;
         physProxy.writeBlob(gdtPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&dsLowPLDescVal), 8);
+                            &dsLowPLDescVal, 8);
 
         numGDTEntries++;
 
@@ -285,7 +274,7 @@ X86_64Process::initState()
         dsDesc.dpl = 3;
         uint64_t dsDescVal = dsDesc;
         physProxy.writeBlob(gdtPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&dsDescVal), 8);
+                            &dsDescVal, 8);
 
         numGDTEntries++;
 
@@ -299,7 +288,7 @@ X86_64Process::initState()
         csDesc.dpl = 3;
         uint64_t csDescVal = csDesc;
         physProxy.writeBlob(gdtPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&csDescVal), 8);
+                            &csDescVal, 8);
 
         numGDTEntries++;
 
@@ -320,11 +309,8 @@ X86_64Process::initState()
         TSSDescLow.type = 0xB;
         TSSDescLow.dpl = 0; // Privelege level 0
         TSSDescLow.p = 1; // Present
-        TSSDescLow.g = 1; // Page granularity
-        TSSDescLow.limitHigh = 0xF;
-        TSSDescLow.limitLow = 0xFFFF;
-        TSSDescLow.baseLow = bits(TSSVirtAddr, 23, 0);
-        TSSDescLow.baseHigh = bits(TSSVirtAddr, 31, 24);
+        TSSDescLow.limit = 0xFFFFFFFF;
+        TSSDescLow.base = bits(TSSVirtAddr, 31, 0);
 
         TSShigh TSSDescHigh = 0;
         TSSDescHigh.base = bits(TSSVirtAddr, 63, 32);
@@ -335,17 +321,15 @@ X86_64Process::initState()
         } tssDescVal = {TSSDescLow, TSSDescHigh};
 
         physProxy.writeBlob(gdtPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&tssDescVal), sizeof(tssDescVal));
+                            &tssDescVal, sizeof(tssDescVal));
 
         numGDTEntries++;
 
         SegSelector tssSel = 0;
         tssSel.si = numGDTEntries - 1;
 
-        uint64_t tss_base_addr = (TSSDescHigh.base << 32) |
-                                 (TSSDescLow.baseHigh << 24) |
-                                  TSSDescLow.baseLow;
-        uint64_t tss_limit = TSSDescLow.limitLow | (TSSDescLow.limitHigh << 16);
+        uint64_t tss_base_addr = (TSSDescHigh.base << 32) | TSSDescLow.base;
+        uint64_t tss_limit = TSSDescLow.limit;
 
         SegAttr tss_attr = 0;
 
@@ -393,8 +377,8 @@ X86_64Process::initState()
             efer.sce = 1; // Enable system call extensions.
             efer.lme = 1; // Enable long mode.
             efer.lma = 1; // Activate long mode.
-            efer.nxe = 0; // Enable nx support.
-            efer.svme = 1; // Enable svm support for now.
+            efer.nxe = 1; // Enable nx support.
+            efer.svme = 0; // Enable svm support for now.
             efer.ffxsr = 0; // Turn on fast fxsave and fxrstor.
             tc->setMiscReg(MISCREG_EFER, efer);
 
@@ -423,8 +407,8 @@ X86_64Process::initState()
 
             CR4 cr4 = 0;
             //Turn on pae.
-            cr4.osxsave = 1; // Enable XSAVE and Proc Extended States
-            cr4.osxmmexcpt = 1; // Operating System Unmasked Exception
+            cr4.osxsave = 0; // Enable XSAVE and Proc Extended States
+            cr4.osxmmexcpt = 0; // Operating System Unmasked Exception
             cr4.osfxsr = 1; // Operating System FXSave/FSRSTOR Support
             cr4.pce = 0; // Performance-Monitoring Counter Enable
             cr4.pge = 0; // Page-Global Enable
@@ -452,11 +436,11 @@ X86_64Process::initState()
             tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);
 
             /* enabling syscall and sysret */
-            MiscReg star = ((MiscReg)sret << 48) | ((MiscReg)scall << 32);
+            RegVal star = ((RegVal)sret << 48) | ((RegVal)scall << 32);
             tc->setMiscReg(MISCREG_STAR, star);
-            MiscReg lstar = (MiscReg)syscallCodeVirtAddr;
+            RegVal lstar = (RegVal)syscallCodeVirtAddr;
             tc->setMiscReg(MISCREG_LSTAR, lstar);
-            MiscReg sfmask = (1 << 8) | (1 << 10); // TF | DF
+            RegVal sfmask = (1 << 8) | (1 << 10); // TF | DF
             tc->setMiscReg(MISCREG_SF_MASK, sfmask);
         }
 
@@ -502,7 +486,7 @@ X86_64Process::initState()
         tss.RSP1_high = tss.IST1_high;
         tss.RSP2_low  = tss.IST1_low;
         tss.RSP2_high = tss.IST1_high;
-        physProxy.writeBlob(tssPhysAddr, (uint8_t *)(&tss), sizeof(tss));
+        physProxy.writeBlob(tssPhysAddr, &tss, sizeof(tss));
 
         /* Setting IDT gates */
         GateDescriptorLow PFGateLow = 0;
@@ -522,8 +506,7 @@ X86_64Process::initState()
             uint64_t high;
         } PFGate = {PFGateLow, PFGateHigh};
 
-        physProxy.writeBlob(idtPhysAddr + 0xE0,
-                            (uint8_t *)(&PFGate), sizeof(PFGate));
+        physProxy.writeBlob(idtPhysAddr + 0xE0, &PFGate, sizeof(PFGate));
 
         /* System call handler */
         uint8_t syscallBlob[] = {
@@ -764,8 +747,7 @@ X86Process::argsInit(int pageSize,
 {
     int intSize = sizeof(IntType);
 
-    typedef AuxVector<IntType> auxv_t;
-    std::vector<auxv_t> auxv = extraAuxvs;
+    std::vector<AuxVector<IntType>> auxv = extraAuxvs;
 
     string filename;
     if (argv.size() < 1)
@@ -776,12 +758,6 @@ X86Process::argsInit(int pageSize,
     // We want 16 byte alignment
     uint64_t align = 16;
 
-    // Patch the ld_bias for dynamic executables.
-    updateBias();
-
-    // load object file into target memory
-    objFile->loadSections(initVirtMem);
-
     enum X86CpuFeature {
         X86_OnboardFPU = 1 << 0,
         X86_VirtualModeExtensions = 1 << 1,
@@ -861,40 +837,40 @@ X86Process::argsInit(int pageSize,
 
         // Bits which describe the system hardware capabilities
         // XXX Figure out what these should be
-        auxv.push_back(auxv_t(M5_AT_HWCAP, features));
+        auxv.emplace_back(M5_AT_HWCAP, features);
         // The system page size
-        auxv.push_back(auxv_t(M5_AT_PAGESZ, X86ISA::PageBytes));
+        auxv.emplace_back(M5_AT_PAGESZ, X86ISA::PageBytes);
         // Frequency at which times() increments
         // Defined to be 100 in the kernel source.
-        auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
+        auxv.emplace_back(M5_AT_CLKTCK, 100);
         // This is the virtual address of the program header tables if they
         // appear in the executable image.
-        auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
+        auxv.emplace_back(M5_AT_PHDR, elfObject->programHeaderTable());
         // This is the size of a program header entry from the elf file.
-        auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
+        auxv.emplace_back(M5_AT_PHENT, elfObject->programHeaderSize());
         // This is the number of program headers from the original elf file.
-        auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
+        auxv.emplace_back(M5_AT_PHNUM, elfObject->programHeaderCount());
         // This is the base address of the ELF interpreter; it should be
         // zero for static executables or contain the base address for
         // dynamic executables.
-        auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
+        auxv.emplace_back(M5_AT_BASE, getBias());
         // XXX Figure out what this should be.
-        auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
+        auxv.emplace_back(M5_AT_FLAGS, 0);
         // The entry point to the program
-        auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
+        auxv.emplace_back(M5_AT_ENTRY, objFile->entryPoint());
         // Different user and group IDs
-        auxv.push_back(auxv_t(M5_AT_UID, uid()));
-        auxv.push_back(auxv_t(M5_AT_EUID, euid()));
-        auxv.push_back(auxv_t(M5_AT_GID, gid()));
-        auxv.push_back(auxv_t(M5_AT_EGID, egid()));
+        auxv.emplace_back(M5_AT_UID, uid());
+        auxv.emplace_back(M5_AT_EUID, euid());
+        auxv.emplace_back(M5_AT_GID, gid());
+        auxv.emplace_back(M5_AT_EGID, egid());
         // Whether to enable "secure mode" in the executable
-        auxv.push_back(auxv_t(M5_AT_SECURE, 0));
+        auxv.emplace_back(M5_AT_SECURE, 0);
         // The address of 16 "random" bytes.
-        auxv.push_back(auxv_t(M5_AT_RANDOM, 0));
+        auxv.emplace_back(M5_AT_RANDOM, 0);
         // The name of the program
-        auxv.push_back(auxv_t(M5_AT_EXECFN, 0));
+        auxv.emplace_back(M5_AT_EXECFN, 0);
         // The platform string
-        auxv.push_back(auxv_t(M5_AT_PLATFORM, 0));
+        auxv.emplace_back(M5_AT_PLATFORM, 0);
     }
 
     // Figure out how big the initial stack needs to be
@@ -998,44 +974,43 @@ X86Process::argsInit(int pageSize,
 
     // figure out argc
     IntType argc = argv.size();
-    IntType guestArgc = X86ISA::htog(argc);
+    IntType guestArgc = htole(argc);
 
     // Write out the sentry void *
     IntType sentry_NULL = 0;
-    initVirtMem.writeBlob(sentry_base, (uint8_t*)&sentry_NULL, sentry_size);
+    initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
 
     // Write the file name
     initVirtMem.writeString(file_name_base, filename.c_str());
 
     // Fix up the aux vectors which point to data
-    assert(auxv[auxv.size() - 3].a_type == M5_AT_RANDOM);
-    auxv[auxv.size() - 3].a_val = aux_data_base;
-    assert(auxv[auxv.size() - 2].a_type == M5_AT_EXECFN);
-    auxv[auxv.size() - 2].a_val = argv_array_base;
-    assert(auxv[auxv.size() - 1].a_type == M5_AT_PLATFORM);
-    auxv[auxv.size() - 1].a_val = aux_data_base + numRandomBytes;
+    assert(auxv[auxv.size() - 3].type == M5_AT_RANDOM);
+    auxv[auxv.size() - 3].val = aux_data_base;
+    assert(auxv[auxv.size() - 2].type == M5_AT_EXECFN);
+    auxv[auxv.size() - 2].val = argv_array_base;
+    assert(auxv[auxv.size() - 1].type == M5_AT_PLATFORM);
+    auxv[auxv.size() - 1].val = aux_data_base + numRandomBytes;
 
 
     // Copy the aux stuff
-    for (int x = 0; x < auxv.size(); x++) {
-        initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize,
-                (uint8_t*)&(auxv[x].a_type), intSize);
-        initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
-                (uint8_t*)&(auxv[x].a_val), intSize);
+    Addr auxv_array_end = auxv_array_base;
+    for (const auto &aux: auxv) {
+        initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
+        auxv_array_end += sizeof(aux);
     }
     // Write out the terminating zeroed auxiliary vector
-    const uint64_t zero = 0;
-    initVirtMem.writeBlob(auxv_array_base + auxv.size() * 2 * intSize,
-                          (uint8_t*)&zero, intSize);
-    initVirtMem.writeBlob(auxv_array_base + (auxv.size() * 2 + 1) * intSize,
-                          (uint8_t*)&zero, intSize);
+    const AuxVector<uint64_t> zero(0, 0);
+    initVirtMem.write(auxv_array_end, zero);
+    auxv_array_end += sizeof(zero);
 
     initVirtMem.writeString(aux_data_base, platform.c_str());
 
-    copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
-    copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
+    copyStringArray(envp, envp_array_base, env_data_base,
+                    LittleEndianByteOrder, initVirtMem);
+    copyStringArray(argv, argv_array_base, arg_data_base,
+                    LittleEndianByteOrder, initVirtMem);
 
-    initVirtMem.writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
+    initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
 
     ThreadContext *tc = system->getThreadContext(contextIds[0]);
     // Set the stack pointer register
@@ -1053,8 +1028,7 @@ void
 X86_64Process::argsInit(int pageSize)
 {
     std::vector<AuxVector<uint64_t> > extraAuxvs;
-    extraAuxvs.push_back(AuxVector<uint64_t>(M5_AT_SYSINFO_EHDR,
-                vsyscallPage.base));
+    extraAuxvs.emplace_back(M5_AT_SYSINFO_EHDR, vsyscallPage.base);
     X86Process::argsInit<uint64_t>(pageSize, extraAuxvs);
 }
 
@@ -1063,10 +1037,9 @@ I386Process::argsInit(int pageSize)
 {
     std::vector<AuxVector<uint32_t> > extraAuxvs;
     //Tell the binary where the vsyscall part of the vsyscall page is.
-    extraAuxvs.push_back(AuxVector<uint32_t>(M5_AT_SYSINFO,
-                vsyscallPage.base + vsyscallPage.vsyscallOffset));
-    extraAuxvs.push_back(AuxVector<uint32_t>(M5_AT_SYSINFO_EHDR,
-                vsyscallPage.base));
+    extraAuxvs.emplace_back(M5_AT_SYSINFO,
+            vsyscallPage.base + vsyscallPage.vsyscallOffset);
+    extraAuxvs.emplace_back(M5_AT_SYSINFO_EHDR, vsyscallPage.base);
     X86Process::argsInit<uint32_t>(pageSize, extraAuxvs);
 }
 
@@ -1076,36 +1049,29 @@ X86Process::setSyscallReturn(ThreadContext *tc, SyscallReturn retval)
     tc->setIntReg(INTREG_RAX, retval.encodedValue());
 }
 
-X86ISA::IntReg
+RegVal
 X86_64Process::getSyscallArg(ThreadContext *tc, int &i)
 {
     assert(i < NumArgumentRegs);
     return tc->readIntReg(ArgumentReg[i++]);
 }
 
-void
-X86_64Process::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
-{
-    assert(i < NumArgumentRegs);
-    return tc->setIntReg(ArgumentReg[i], val);
-}
-
 void
 X86_64Process::clone(ThreadContext *old_tc, ThreadContext *new_tc,
-                     Process *p, TheISA::IntReg flags)
+                     Process *p, RegVal flags)
 {
     X86Process::clone(old_tc, new_tc, p, flags);
     ((X86_64Process*)p)->vsyscallPage = vsyscallPage;
 }
 
-X86ISA::IntReg
+RegVal
 I386Process::getSyscallArg(ThreadContext *tc, int &i)
 {
     assert(i < NumArgumentRegs32);
     return tc->readIntReg(ArgumentReg32[i++]);
 }
 
-X86ISA::IntReg
+RegVal
 I386Process::getSyscallArg(ThreadContext *tc, int &i, int width)
 {
     assert(width == 32 || width == 64);
@@ -1116,16 +1082,9 @@ I386Process::getSyscallArg(ThreadContext *tc, int &i, int width)
     return retVal;
 }
 
-void
-I386Process::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
-{
-    assert(i < NumArgumentRegs);
-    return tc->setIntReg(ArgumentReg[i], val);
-}
-
 void
 I386Process::clone(ThreadContext *old_tc, ThreadContext *new_tc,
-                   Process *p, TheISA::IntReg flags)
+                   Process *p, RegVal flags)
 {
     X86Process::clone(old_tc, new_tc, p, flags);
     ((I386Process*)p)->vsyscallPage = vsyscallPage;