Boris Shingarov has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/40944 )

Change subject: arch-power: Add multi-mode support
......................................................................

arch-power: Add multi-mode support

This adds multi-mode support and allows the simulator to
read, interpret and execute 32bit and 64-bit, big and
little endian binaries in syscall emulation mode.

During process initialization, a minimal set of hardware
capabilities are also advertised by the simulator to show
support for 64-bit mode and little endian byte order.
This also adds some fixups specific to 64-bit ELF ABI v1
that readjust the entry point and symbol table due to the
use of function descriptors.

Change-Id: I124339eff7b70dbd14e50ff970340c88c13bd0ad
Signed-off-by: Sandipan Das <sandi...@linux.ibm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40944
Reviewed-by: Boris Shingarov <shinga...@labware.com>
Maintainer: Boris Shingarov <shinga...@labware.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/arch/power/PowerSeWorkload.py
M src/arch/power/linux/se_workload.cc
M src/arch/power/process.cc
M src/arch/power/regs/int.hh
M src/base/loader/elf_object.cc
M src/base/loader/object_file.cc
M src/base/loader/object_file.hh
7 files changed, 100 insertions(+), 18 deletions(-)

Approvals:
  Boris Shingarov: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/arch/power/PowerSeWorkload.py b/src/arch/power/PowerSeWorkload.py
index ef7bbb5..2b081f2 100644
--- a/src/arch/power/PowerSeWorkload.py
+++ b/src/arch/power/PowerSeWorkload.py
@@ -40,5 +40,5 @@

     @classmethod
     def _is_compatible_with(cls, obj):
-        return obj.get_arch() == 'power' and \
+        return obj.get_arch() in ('power', 'power64') and  \
                 obj.get_op_sys() in ('linux', 'unknown')
diff --git a/src/arch/power/linux/se_workload.cc b/src/arch/power/linux/se_workload.cc
index 75eb210..815a145 100644
--- a/src/arch/power/linux/se_workload.cc
+++ b/src/arch/power/linux/se_workload.cc
@@ -50,7 +50,9 @@
     Process *
     load(const ProcessParams &params, loader::ObjectFile *obj) override
     {
-        if (obj->getArch() != loader::Power)
+        auto arch = obj->getArch();
+
+        if (arch != loader::Power && arch != loader::Power64)
             return nullptr;

         auto opsys = obj->getOpSys();
@@ -60,7 +62,10 @@
             opsys = loader::Linux;
         }

-        if (opsys != loader::Linux)
+        if ((arch == loader::Power && opsys != loader::Linux) ||
+            (arch == loader::Power64 &&
+             opsys != loader::LinuxPower64ABIv1 &&
+             opsys != loader::LinuxPower64ABIv2))
             return nullptr;

         return new PowerProcess(params, obj);
diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc
index 688cc1e..8ac5946 100644
--- a/src/arch/power/process.cc
+++ b/src/arch/power/process.cc
@@ -82,7 +82,55 @@
 {
     Process::initState();

-    argsInit<uint32_t>(PageBytes);
+    if (objFile->getArch() == loader::Power)
+        argsInit<uint32_t>(PageBytes);
+    else
+        argsInit<uint64_t>(PageBytes);
+
+    // Fix up entry point and symbol table for 64-bit ELF ABI v1
+    if (objFile->getOpSys() != loader::LinuxPower64ABIv1)
+        return;
+
+    // Fix entry point address and the base TOC pointer by looking the
+    // the function descriptor in the .opd section
+    Addr entryPoint, tocBase;
+    ByteOrder byteOrder = objFile->getByteOrder();
+    ThreadContext *tc = system->threads[contextIds[0]];
+
+    // The first doubleword of the descriptor contains the address of the
+    // entry point of the function
+    initVirtMem->readBlob(getStartPC(), &entryPoint, sizeof(Addr));
+
+    // Update the PC state
+    auto pc = tc->pcState();
+    pc.byteOrder(byteOrder);
+    pc.set(gtoh(entryPoint, byteOrder));
+    tc->pcState(pc);
+
+    // The second doubleword of the descriptor contains the TOC base
+    // address for the function
+    initVirtMem->readBlob(getStartPC() + 8, &tocBase, sizeof(Addr));
+    tc->setIntReg(TOCPointerReg, gtoh(tocBase, byteOrder));
+
+    // Fix symbol table entries as they would otherwise point to the
+    // function descriptor rather than the actual entry point address
+    auto *symbolTable = new loader::SymbolTable;
+
+    for (auto sym : loader::debugSymbolTable) {
+        Addr entry;
+        loader::Symbol symbol = sym;
+
+        // Try to read entry point from function descriptor
+        if (initVirtMem->tryReadBlob(sym.address, &entry, sizeof(Addr)))
+            symbol.address = gtoh(entry, byteOrder);
+
+        symbolTable->insert(symbol);
+    }
+
+    // Replace the current debug symbol table
+    loader::debugSymbolTable.clear();
+    loader::debugSymbolTable.insert(*symbolTable);
+    delete symbolTable;
 }

 template <typename IntType>
@@ -91,6 +139,8 @@
 {
     int intSize = sizeof(IntType);
     ByteOrder byteOrder = objFile->getByteOrder();
+    bool is64bit = (objFile->getArch() == loader::Power64);
+    bool isLittleEndian = (byteOrder == ByteOrder::little);
     std::vector<gem5::auxv::AuxVector<IntType>> auxv;

     std::string filename;
@@ -110,13 +160,21 @@
     //Auxilliary vectors are loaded only for elf formatted executables.
     auto *elfObject = dynamic_cast<loader::ElfObject *>(objFile);
     if (elfObject) {
-        IntType features = 0;
+        IntType features = HWCAP_FEATURE_32;
+
+        // Check if running in 64-bit mode
+        if (is64bit)
+            features |= HWCAP_FEATURE_64;
+
+        // Check if running in little endian mode
+        if (isLittleEndian)
+            features |= HWCAP_FEATURE_PPC_LE | HWCAP_FEATURE_TRUE_LE;

         //Bits which describe the system hardware capabilities
         //XXX Figure out what these should be
         auxv.emplace_back(gem5::auxv::Hwcap, features);
         //The system page size
-        auxv.emplace_back(gem5::auxv::Pagesz, PowerISA::PageBytes);
+        auxv.emplace_back(gem5::auxv::Pagesz, pageSize);
         //Frequency at which times() increments
         auxv.emplace_back(gem5::auxv::Clktck, 0x64);
// For statically linked executables, this is the virtual address of
@@ -282,7 +340,7 @@

     //Set the machine status for a typical userspace
     Msr msr = 0;
-    msr.sf = (intSize == 8);
+    msr.sf = is64bit;
     msr.hv = 1;
     msr.ee = 1;
     msr.pr = 1;
@@ -290,10 +348,13 @@
     msr.ir = 1;
     msr.dr = 1;
     msr.ri = 1;
-    msr.le = (byteOrder == ByteOrder::little);
+    msr.le = isLittleEndian;
     tc->setIntReg(INTREG_MSR, msr);

-    tc->pcState(getStartPC());
+    auto pc = tc->pcState();
+    pc.set(getStartPC());
+    pc.byteOrder(byteOrder);
+    tc->pcState(pc);

     //Align the "stack_min" to a page boundary.
     memState->setStackMin(roundDown(stack_min, pageSize));
diff --git a/src/arch/power/regs/int.hh b/src/arch/power/regs/int.hh
index 11999e5..968b94f 100644
--- a/src/arch/power/regs/int.hh
+++ b/src/arch/power/regs/int.hh
@@ -53,6 +53,7 @@
 const int ArgumentReg4 = 7;
 const int ArgumentReg5 = 8;
 const int StackPointerReg = 1;
+const int TOCPointerReg = 2;

 enum MiscIntRegNums
 {
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
index 28721f5..31390cf 100644
--- a/src/base/loader/elf_object.cc
+++ b/src/base/loader/elf_object.cc
@@ -252,15 +252,8 @@
         arch = (eclass == ELFCLASS64) ? Riscv64 : Riscv32;
     } else if (emach == EM_PPC && eclass == ELFCLASS32) {
         arch = Power;
-        if (edata != ELFDATA2MSB) {
-            fatal("The binary you're trying to load is compiled for "
-                  "little endian Power.\ngem5 only supports big "
-                  "endian Power. Please recompile your binary.\n");
-        }
-    } else if (emach == EM_PPC64) {
-        fatal("The binary you're trying to load is compiled for 64-bit "
-              "Power. M5\n only supports 32-bit Power. Please "
-              "recompile your binary.\n");
+    } else if (emach == EM_PPC64 && eclass == ELFCLASS64) {
+        arch = Power64;
     } else {
         warn("Unknown architecture: %d\n", emach);
     }
@@ -269,6 +262,21 @@
 void
 ElfObject::determineOpSys()
 {
+    // For 64-bit Power, EI_OSABI and EI_ABIVERSION cannot be used to
+    // determine the ABI version used by the ELF object
+    if (ehdr.e_machine == EM_PPC64) {
+        switch (ehdr.e_flags & 0x3) {
+            case 0x1: opSys = LinuxPower64ABIv1; return;
+            case 0x2: opSys = LinuxPower64ABIv2; return;
+            default:
+                if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
+                    opSys = LinuxPower64ABIv1;
+                if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+                    opSys = LinuxPower64ABIv2;
+                return;
+        }
+    }
+
     // Detect the operating system
     switch (ehdr.e_ident[EI_OSABI]) {
       case ELFOSABI_LINUX:
diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc
index 2566853..bfa0a1d 100644
--- a/src/base/loader/object_file.cc
+++ b/src/base/loader/object_file.cc
@@ -66,6 +66,8 @@
         return "thumb";
       case Power:
         return "power";
+      case Power64:
+        return "power64";
       case Riscv64:
         return "riscv64";
       case Riscv32:
@@ -84,6 +86,8 @@
       case Tru64:
         return "tru64";
       case Linux:
+      case LinuxPower64ABIv1:
+      case LinuxPower64ABIv2:
         return "linux";
       case Solaris:
         return "solaris";
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
index 1079f16..e8a96dc 100644
--- a/src/base/loader/object_file.hh
+++ b/src/base/loader/object_file.hh
@@ -59,6 +59,7 @@
     Arm,
     Thumb,
     Power,
+    Power64,
     Riscv64,
     Riscv32
 };
@@ -72,6 +73,8 @@
     Linux,
     Solaris,
     LinuxArmOABI,
+    LinuxPower64ABIv1,
+    LinuxPower64ABIv2,
     FreeBSD
 };




10 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/40944
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I124339eff7b70dbd14e50ff970340c88c13bd0ad
Gerrit-Change-Number: 40944
Gerrit-PatchSet: 12
Gerrit-Owner: Sandipan Das <sandi...@linux.ibm.com>
Gerrit-Reviewer: Boris Shingarov <shinga...@labware.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to