Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/23447 )

Change subject: sparc: Use a SPARC specific GuestABI for system calls.
......................................................................

sparc: Use a SPARC specific GuestABI for system calls.

Change-Id: I41996cada5ccde7b265e5315829ac6690da8902f
---
M src/arch/sparc/linux/process.hh
M src/arch/sparc/linux/syscalls.cc
M src/arch/sparc/process.cc
M src/arch/sparc/process.hh
M src/arch/sparc/solaris/process.cc
M src/arch/sparc/solaris/process.hh
6 files changed, 91 insertions(+), 8 deletions(-)



diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh
index b7a4117..f16cc19 100644
--- a/src/arch/sparc/linux/process.hh
+++ b/src/arch/sparc/linux/process.hh
@@ -45,11 +45,11 @@
 {
   public:
      /// Array of syscall descriptors, indexed by call number.
-    static SyscallDescABI<DefaultSyscallABI> syscallDescs[];
+    static SyscallDescABI<Sparc64Process::SyscallABI> syscallDescs[];

      /// Array of 32 bit compatibility syscall descriptors,
      /// indexed by call number.
-    static SyscallDescABI<DefaultSyscallABI> syscall32Descs[];
+    static SyscallDescABI<Sparc32Process::SyscallABI> syscall32Descs[];

     SyscallDesc* getDesc(int callnum);
     SyscallDesc* getDesc32(int callnum);
diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc
index 6f8e646..1b8f400 100644
--- a/src/arch/sparc/linux/syscalls.cc
+++ b/src/arch/sparc/linux/syscalls.cc
@@ -83,7 +83,8 @@
     return 0;
 }

-SyscallDescABI<DefaultSyscallABI> SparcLinuxProcess::syscall32Descs[] = {
+SyscallDescABI<Sparc32Process::SyscallABI>
+    SparcLinuxProcess::syscall32Descs[] = {
     /*   0 */ { "restart_syscall" },
     /*   1 */ { "exit", exitFunc }, // 32 bit
     /*   2 */ { "fork" },
@@ -389,7 +390,8 @@
 const int SparcLinuxProcess::Num_Syscall32_Descs =
     sizeof(SparcLinuxProcess::syscall32Descs) / sizeof(SyscallDesc);

-SyscallDescABI<DefaultSyscallABI> SparcLinuxProcess::syscallDescs[] = {
+SyscallDescABI<Sparc64Process::SyscallABI>
+    SparcLinuxProcess::syscallDescs[] = {
     /*  0 */ { "restart_syscall" },
     /*  1 */ { "exit", exitFunc },
     /*  2 */ { "fork" },
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index d064de2..50167c7 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -51,8 +51,9 @@
 using namespace std;
 using namespace SparcISA;

-static const int FirstArgumentReg = 8;
-
+const std::vector<int> SparcProcess::SyscallABI::ArgumentRegs = {
+    INTREG_O0, INTREG_O1, INTREG_O2, INTREG_O3, INTREG_O4, INTREG_O5
+};

 SparcProcess::SparcProcess(ProcessParams *params, ObjectFile *objFile,
                            Addr _StackBias)
@@ -493,6 +494,8 @@
     tc->setMiscReg(MISCREG_CWP, origCWP);
 }

+static const int FirstArgumentReg = 8;
+
 RegVal
 Sparc32Process::getSyscallArg(ThreadContext *tc, int &i)
 {
diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh
index 2e5379b..d3d6866 100644
--- a/src/arch/sparc/process.hh
+++ b/src/arch/sparc/process.hh
@@ -37,10 +37,12 @@
 #include <vector>

 #include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/miscregs.hh"
 #include "base/loader/object_file.hh"
 #include "mem/page_table.hh"
 #include "sim/byteswap.hh"
 #include "sim/process.hh"
+#include "sim/syscall_abi.hh"

 class SparcProcess : public Process
 {
@@ -69,8 +71,52 @@

     virtual void flushWindows(ThreadContext *tc) = 0;
     void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
+
+    struct SyscallABI
+    {
+        static const std::vector<int> ArgumentRegs;
+    };
 };

+namespace GuestABI
+{
+
+template <typename ABI>
+struct Result<ABI, SyscallReturn,
+    typename std::enable_if<std::is_base_of<
+        SparcProcess::SyscallABI, ABI>::value>::type>
+{
+    static void
+    store(ThreadContext *tc, const SyscallReturn &ret)
+    {
+        if (ret.suppressed() || ret.needsRetry())
+            return;
+
+        // check for error condition.  SPARC syscall convention is to
+        // indicate success/failure in reg the carry bit of the ccr
+ // and put the return value itself in the standard return value reg.
+        SparcISA::PSTATE pstate =
+            tc->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE);
+        SparcISA::CCR ccr = tc->readIntReg(SparcISA::INTREG_CCR);
+        RegVal val;
+        if (ret.successful()) {
+            ccr.xcc.c = ccr.icc.c = 0;
+            val = ret.returnValue();
+        } else {
+            ccr.xcc.c = ccr.icc.c = 1;
+            val = ret.errnoValue();
+        }
+        tc->setIntReg(SparcISA::INTREG_CCR, ccr);
+        if (pstate.am)
+            val = bits(val, 31, 0);
+        tc->setIntReg(SparcISA::ReturnValueReg, val);
+        if (ret.count() == 2)
+            tc->setIntReg(SparcISA::SyscallPseudoReturnReg, ret.value2());
+    }
+};
+
+} // namespace GuestABI
+
 class Sparc32Process : public SparcProcess
 {
   protected:
@@ -111,8 +157,35 @@
     RegVal getSyscallArg(ThreadContext *tc, int &i);
     /// Explicitly import the otherwise hidden getSyscallArg
     using Process::getSyscallArg;
+
+    struct SyscallABI : public GenericSyscallABI32,
+                        public SparcProcess::SyscallABI
+    {};
 };

+namespace GuestABI
+{
+
+template <typename Arg>
+struct Argument<Sparc32Process::SyscallABI, Arg,
+    typename std::enable_if<
+        Sparc32Process::SyscallABI::IsWide<Arg>::value>::type>
+{
+    using ABI = Sparc32Process::SyscallABI;
+
+    static Arg
+    get(ThreadContext *tc, typename ABI::Position &position)
+    {
+        panic_if(position + 1 >= ABI::ArgumentRegs.size(),
+                "Ran out of syscall argument registers.");
+        auto high = ABI::ArgumentRegs[position++];
+        auto low = ABI::ArgumentRegs[position++];
+        return (Arg)ABI::mergeRegs(tc, low, high);
+    }
+};
+
+} // namespace GuestABI
+
 class Sparc64Process : public SparcProcess
 {
   protected:
@@ -152,6 +225,10 @@
     RegVal getSyscallArg(ThreadContext *tc, int &i);
     /// Explicitly import the otherwise hidden getSyscallArg
     using Process::getSyscallArg;
+
+    struct SyscallABI : public GenericSyscallABI64,
+                        public SparcProcess::SyscallABI
+    {};
 };

 #endif // __SPARC_PROCESS_HH__
diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc
index 84c332e..3255eee 100644
--- a/src/arch/sparc/solaris/process.cc
+++ b/src/arch/sparc/solaris/process.cc
@@ -89,7 +89,8 @@
 }


-SyscallDescABI<DefaultSyscallABI> SparcSolarisProcess::syscallDescs[] = {
+SyscallDescABI<Sparc64Process::SyscallABI>
+    SparcSolarisProcess::syscallDescs[] = {
     /* 0 */ { "syscall" },
     /* 1 */ { "exit", exitFunc },
     /* 2 */ { "fork" },
diff --git a/src/arch/sparc/solaris/process.hh b/src/arch/sparc/solaris/process.hh
index 424b0ec..d04fcc4 100644
--- a/src/arch/sparc/solaris/process.hh
+++ b/src/arch/sparc/solaris/process.hh
@@ -53,7 +53,7 @@
     void syscall(ThreadContext *tc, Fault *fault) override;

      /// Array of syscall descriptors, indexed by call number.
-    static SyscallDescABI<DefaultSyscallABI> syscallDescs[];
+    static SyscallDescABI<Sparc64Process::SyscallABI> syscallDescs[];

     const int Num_Syscall_Descs;
 };

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/23447
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I41996cada5ccde7b265e5315829ac6690da8902f
Gerrit-Change-Number: 23447
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabebl...@google.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to