[gem5-dev] Change in gem5/gem5[develop]: arch-power: Add multi-mode support

2021-07-04 Thread Boris Shingarov (Gerrit) via gem5-dev
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 
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40944
Reviewed-by: Boris Shingarov 
Maintainer: Boris Shingarov 
Tested-by: kokoro 
---
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 , 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(PageBytes);
+if (objFile->getArch() == loader::Power)
+argsInit(PageBytes);
+else
+argsInit(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(), , 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, , 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, , 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 
@@ -91,6 +139,8 @@
 {
 int intSize = sizeof(IntType);
 ByteOrder byteOrder = objFile->getByteOrder();
+bool is64bit = (objFile->getArch() == loader::Power64);
+bool isLittleEndian = (byteOrder == 

[gem5-dev] Change in gem5/gem5[develop]: arch-power: Add multi-mode support

2021-02-07 Thread Sandipan Das (Gerrit) via gem5-dev
Sandipan Das has uploaded this change for review. (  
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 
---
M src/arch/power/PowerSeWorkload.py
M src/arch/power/linux/se_workload.cc
M src/arch/power/process.cc
M src/arch/power/registers.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(-)



diff --git a/src/arch/power/PowerSeWorkload.py  
b/src/arch/power/PowerSeWorkload.py

index 2d3d3cb..40e989c 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 864468f..091fd35 100644
--- a/src/arch/power/linux/se_workload.cc
+++ b/src/arch/power/linux/se_workload.cc
@@ -47,7 +47,9 @@
 Process *
 load(const ProcessParams , ::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();
@@ -57,7 +59,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 409f980..735b3d9 100644
--- a/src/arch/power/process.cc
+++ b/src/arch/power/process.cc
@@ -76,7 +76,55 @@
 {
 Process::initState();

-argsInit(PageBytes);
+if (objFile->getArch() == ::Loader::Power)
+argsInit(PageBytes);
+else
+argsInit(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(), , 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, , 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, , 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 
@@ -85,6 +133,8 @@
 {
 int intSize = sizeof(IntType);
 ByteOrder byteOrder = objFile->getByteOrder();
+bool is64bit = (objFile->getArch() == ::Loader::Power64);
+bool isLittleEndian = (byteOrder == ByteOrder::little);
 std::vector> auxv;

 std::string filename;
@@ -104,13 +154,21 @@
 //Auxilliary vectors are loaded only for elf formatted executables.
 auto *elfObject = dynamic_cast<::Loader::ElfObject