From cb3457ccd17a89a4df3e70d35e0254c77a0b5782 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 25 Nov 2019 01:07:41 -0800 Subject: [PATCH] arch,cpu,sim: Push syscall number determination up to processes. The logic that determines which syscall to call was built into the implementation of faults/exceptions or even into the instruction decoder, but that logic can depend on what OS is being used, and sometimes even what version, for example 32bit vs. 64bit. This change pushes that logic up into the Process objects since those already handle a lot of the aspects of emulating the guest OS. Instead, the ISA or fault implementations just notify the rest of the system that a nebulous syscall has happened, and that gets propogated upward until the process does something with it. That's very analogous to how a system call would work on a real machine. When a system call happens, the low level component which detects that should call tc->syscall(&fault), where tc is the relevant thread (or execution) context, and fault is a Fault which can ultimately be set by the system call implementation. The TC implementor (probably a CPU) will then have a chance to do whatever it needs to to handle a system call. Currently only O3 does anything special here. That implementor will end up calling the Process's syscall() method. Once in Process::syscall, the process object will use it's contextual knowledge to determine what system call is being requested. It then calls Process::doSyscall with the right syscall number, where doSyscall centralizes the common mechanism for actually retrieving and calling into the system call implementation. Jira Issue: https://gem5.atlassian.net/browse/GEM5-187 Change-Id: I937ec1ef0576142c2a182ff33ca508d77ad0e7a1 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23176 Maintainer: Gabe Black Tested-by: kokoro Reviewed-by: Brandon Potter --- src/arch/alpha/isa/decoder.isa | 2 +- src/arch/alpha/linux/process.cc | 7 +++++ src/arch/alpha/linux/process.hh | 2 ++ src/arch/arm/fastmodel/iris/thread_context.hh | 2 +- src/arch/arm/faults.cc | 9 +----- src/arch/arm/freebsd/process.cc | 12 ++++++++ src/arch/arm/freebsd/process.hh | 3 ++ src/arch/arm/linux/process.cc | 12 ++++++++ src/arch/arm/linux/process.hh | 3 ++ src/arch/mips/isa/decoder.isa | 2 +- src/arch/mips/isa/operands.isa | 3 +- src/arch/mips/linux/process.cc | 9 +++--- src/arch/mips/linux/process.hh | 2 ++ src/arch/power/isa/decoder.isa | 2 +- src/arch/power/isa/operands.isa | 3 -- src/arch/power/linux/process.cc | 6 ++++ src/arch/power/linux/process.hh | 2 ++ src/arch/riscv/faults.cc | 2 +- src/arch/riscv/linux/process.cc | 12 ++++++++ src/arch/riscv/linux/process.hh | 4 +++ src/arch/sparc/linux/process.cc | 24 +++++++++++---- src/arch/sparc/linux/process.hh | 4 +++ src/arch/sparc/solaris/process.cc | 6 ++++ src/arch/sparc/solaris/process.hh | 2 ++ src/arch/x86/isa/decoder/one_byte_opcodes.isa | 2 +- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 4 +-- src/arch/x86/linux/process.cc | 29 ++++++++++++++++--- src/arch/x86/linux/process.hh | 2 ++ src/arch/x86/process.cc | 13 --------- src/arch/x86/process.hh | 2 -- src/arch/x86/pseudo_inst.cc | 2 +- src/cpu/checker/cpu.hh | 2 +- src/cpu/checker/thread_context.hh | 4 +-- src/cpu/exec_context.hh | 4 +-- src/cpu/minor/exec_context.hh | 4 +-- src/cpu/o3/cpu.cc | 4 +-- src/cpu/o3/cpu.hh | 2 +- src/cpu/o3/dyn_inst.hh | 2 +- src/cpu/o3/dyn_inst_impl.hh | 4 +-- src/cpu/o3/thread_context.hh | 4 +-- src/cpu/o3/thread_state.hh | 5 ++-- src/cpu/simple/exec_context.hh | 4 +-- src/cpu/simple_thread.hh | 5 ++-- src/cpu/thread_context.hh | 2 +- src/sim/process.cc | 2 +- src/sim/process.hh | 5 +++- 46 files changed, 165 insertions(+), 77 deletions(-) diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 020e43359f..abf6fb24a9 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -840,7 +840,7 @@ decode OPCODE default Unknown::unknown() { exitSimLoop("halt instruction encountered"); }}, IsNonSpeculative); 0x83: callsys({{ - xc->syscall(R0, &fault); + xc->syscall(&fault); }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); // Read uniq reg into ABI return value register (r0) 0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess); diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 1ac53a5a0f..26d5f26cda 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -620,3 +620,10 @@ AlphaLinuxProcess::getDesc(int callnum) return NULL; return &syscallDescs[callnum]; } + +void +AlphaLinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(0), tc, fault); +} + diff --git a/src/arch/alpha/linux/process.hh b/src/arch/alpha/linux/process.hh index 46c22d2884..991ddbd087 100644 --- a/src/arch/alpha/linux/process.hh +++ b/src/arch/alpha/linux/process.hh @@ -42,6 +42,8 @@ class AlphaLinuxProcess : public AlphaProcess /// Constructor. AlphaLinuxProcess(ProcessParams * params, ObjectFile *objFile); + void syscall(ThreadContext *tc, Fault *fault) override; + virtual SyscallDesc* getDesc(int callnum); /// Array of syscall descriptors, indexed by call number. diff --git a/src/arch/arm/fastmodel/iris/thread_context.hh b/src/arch/arm/fastmodel/iris/thread_context.hh index c0f40d76cd..d0e920e609 100644 --- a/src/arch/arm/fastmodel/iris/thread_context.hh +++ b/src/arch/arm/fastmodel/iris/thread_context.hh @@ -419,7 +419,7 @@ class ThreadContext : public ::ThreadContext } void - syscall(int64_t callnum, Fault *fault) override + syscall(Fault *fault) override { panic("%s not implemented.", __FUNCTION__); } diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 85e9fa7e9c..5a7b8e8eaf 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -845,15 +845,8 @@ SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst) // As of now, there isn't a 32 bit thumb version of this instruction. assert(!machInst.bigThumb); - uint32_t callNum; - CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); - OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode; - if (opModeIs64(mode)) - callNum = tc->readIntReg(INTREG_X8); - else - callNum = tc->readIntReg(INTREG_R7); Fault fault; - tc->syscall(callNum, &fault); + tc->syscall(&fault); // Advance the PC since that won't happen automatically. PCState pc = tc->pcState(); diff --git a/src/arch/arm/freebsd/process.cc b/src/arch/arm/freebsd/process.cc index 901b2411b5..a603777a15 100644 --- a/src/arch/arm/freebsd/process.cc +++ b/src/arch/arm/freebsd/process.cc @@ -1317,3 +1317,15 @@ ArmFreebsdProcess64::initState() ArmProcess64::initState(); // The 64 bit equivalent of the comm page would be set up here. } + +void +ArmFreebsdProcess32::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(INTREG_R7), tc, fault); +} + +void +ArmFreebsdProcess64::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(INTREG_X8), tc, fault); +} diff --git a/src/arch/arm/freebsd/process.hh b/src/arch/arm/freebsd/process.hh index 28504d7d87..5f4a89600a 100644 --- a/src/arch/arm/freebsd/process.hh +++ b/src/arch/arm/freebsd/process.hh @@ -63,6 +63,8 @@ class ArmFreebsdProcess32 : public ArmProcess32, public ArmFreebsdProcessBits void initState(); + void syscall(ThreadContext *tc, Fault *fault) override; + /// Explicitly import the otherwise hidden getSyscallArg using ArmProcess::getSyscallArg; @@ -80,6 +82,7 @@ class ArmFreebsdProcess64 : public ArmProcess64, public ArmFreebsdProcessBits ObjectFile::Arch _arch); void initState(); + void syscall(ThreadContext *tc, Fault *fault) override; SyscallDesc* getDesc(int callnum); }; diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index d3d0e85be3..bc41932b8b 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -1777,3 +1777,15 @@ ArmLinuxProcess64::initState() ArmProcess64::initState(); // The 64 bit equivalent of the comm page would be set up here. } + +void +ArmLinuxProcess32::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(INTREG_R7), tc, fault); +} + +void +ArmLinuxProcess64::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(INTREG_X8), tc, fault); +} diff --git a/src/arch/arm/linux/process.hh b/src/arch/arm/linux/process.hh index d4b7ca7d3f..8e2709fcdc 100644 --- a/src/arch/arm/linux/process.hh +++ b/src/arch/arm/linux/process.hh @@ -73,6 +73,8 @@ class ArmLinuxProcess32 : public ArmProcess32, public ArmLinuxProcessBits void initState(); + void syscall(ThreadContext *tc, Fault *fault) override; + /// Explicitly import the otherwise hidden getSyscallArg using ArmProcess::getSyscallArg; @@ -90,6 +92,7 @@ class ArmLinuxProcess64 : public ArmProcess64, public ArmLinuxProcessBits ObjectFile::Arch _arch); void initState(); + void syscall(ThreadContext *tc, Fault *fault) override; SyscallDesc* getDesc(int callnum); }; diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 3406ed5d2b..856a340834 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -163,7 +163,7 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }}); 0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }}); 0x4: decode FullSystemInt { - 0: syscall_se({{ xc->syscall(R2, &fault); }}, + 0: syscall_se({{ xc->syscall(&fault); }}, IsSerializeAfter, IsNonSpeculative); default: syscall({{ fault = std::make_shared(); }}); } diff --git a/src/arch/mips/isa/operands.isa b/src/arch/mips/isa/operands.isa index 2d44bb30ee..f81df73fd9 100644 --- a/src/arch/mips/isa/operands.isa +++ b/src/arch/mips/isa/operands.isa @@ -51,9 +51,8 @@ def operands {{ #Immediate Value operand 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), - #Operands used for Link or Syscall Insts + #Operands used for Link Insts 'R31': ('IntReg', 'uw','31','IsInteger', 4), - 'R2': ('IntReg', 'uw','2', 'IsInteger', 5), #Special Integer Reg operands 'LO0': ('IntReg', 'uw','INTREG_LO', 'IsInteger', 6), diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index adfbfd3f64..2dc1bcdaf8 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -509,7 +509,8 @@ MipsLinuxProcess::getDesc(int callnum) return &syscallDescs[m5_sys_idx]; } - - - - +void +MipsLinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(2), tc, fault); +} diff --git a/src/arch/mips/linux/process.hh b/src/arch/mips/linux/process.hh index cbf0d78ead..7fcb6f014c 100644 --- a/src/arch/mips/linux/process.hh +++ b/src/arch/mips/linux/process.hh @@ -51,6 +51,8 @@ class MipsLinuxProcess : public MipsProcess /// ID of the thread group leader for the process uint64_t __tgid; + void syscall(ThreadContext *tc, Fault *fault) override; + /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; const int Num_Syscall_Descs; diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 060d6a34d6..3f10fe48b0 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -517,7 +517,7 @@ decode OPCODE default Unknown::unknown() { 55: stfdu({{ Mem_df = Fs; }}); } - 17: IntOp::sc({{ xc->syscall(R0, &fault); }}, + 17: IntOp::sc({{ xc->syscall(&fault); }}, [ IsSyscall, IsNonSpeculative, IsSerializeAfter ]); format FloatArithOp { diff --git a/src/arch/power/isa/operands.isa b/src/arch/power/isa/operands.isa index a72a0714d4..117c8ad02f 100644 --- a/src/arch/power/isa/operands.isa +++ b/src/arch/power/isa/operands.isa @@ -75,7 +75,4 @@ def operands {{ 'Rsv': ('IntReg', 'uw', 'INTREG_RSV', 'IsInteger', 9), 'RsvLen': ('IntReg', 'uw', 'INTREG_RSV_LEN', 'IsInteger', 9), 'RsvAddr': ('IntReg', 'uw', 'INTREG_RSV_ADDR', 'IsInteger', 9), - - # Hack for non-full-system syscall emulation - 'R0': ('IntReg', 'uw', '0', None, 1), }}; diff --git a/src/arch/power/linux/process.cc b/src/arch/power/linux/process.cc index ac032275e4..a63d9a30c6 100644 --- a/src/arch/power/linux/process.cc +++ b/src/arch/power/linux/process.cc @@ -468,6 +468,12 @@ PowerLinuxProcess::initState() PowerProcess::initState(); } +void +PowerLinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(0), tc, fault); +} + RegVal PowerLinuxProcess::getSyscallArg(ThreadContext *tc, int &i) { diff --git a/src/arch/power/linux/process.hh b/src/arch/power/linux/process.hh index 5a2ad92a41..ef96dae5ff 100644 --- a/src/arch/power/linux/process.hh +++ b/src/arch/power/linux/process.hh @@ -45,6 +45,8 @@ class PowerLinuxProcess : public PowerProcess void initState(); + void syscall(ThreadContext *tc, Fault *fault) override; + RegVal getSyscallArg(ThreadContext *tc, int &i); /// Explicitly import the otherwise hidden getSyscallArg using Process::getSyscallArg; diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 6b79eb8383..83adcba69f 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -191,7 +191,7 @@ void SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) { Fault *fault = NoFault; - tc->syscall(tc->readIntReg(SyscallNumReg), fault); + tc->syscall(fault); } } // namespace RiscvISA diff --git a/src/arch/riscv/linux/process.cc b/src/arch/riscv/linux/process.cc index d6a41e2400..49e32de928 100644 --- a/src/arch/riscv/linux/process.cc +++ b/src/arch/riscv/linux/process.cc @@ -795,6 +795,12 @@ RiscvLinuxProcess64::getDesc(int callnum) &syscallDescs.at(callnum) : nullptr; } +void +RiscvLinuxProcess64::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(SyscallNumReg), tc, fault); +} + RiscvLinuxProcess32::RiscvLinuxProcess32(ProcessParams * params, ObjectFile *objFile) : RiscvProcess32(params, objFile) {} @@ -805,3 +811,9 @@ RiscvLinuxProcess32::getDesc(int callnum) return syscallDescs.find(callnum) != syscallDescs.end() ? &syscallDescs.at(callnum) : nullptr; } + +void +RiscvLinuxProcess32::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(SyscallNumReg), tc, fault); +} diff --git a/src/arch/riscv/linux/process.hh b/src/arch/riscv/linux/process.hh index 1256ac6673..65daca35e0 100644 --- a/src/arch/riscv/linux/process.hh +++ b/src/arch/riscv/linux/process.hh @@ -55,6 +55,8 @@ class RiscvLinuxProcess64 : public RiscvProcess64 /// ID of the thread group leader for the process uint64_t __tgid; + void syscall(ThreadContext *tc, Fault *fault) override; + /// Array of syscall descriptors, indexed by call number. static std::map syscallDescs; }; @@ -73,6 +75,8 @@ class RiscvLinuxProcess32 : public RiscvProcess32 /// ID of the thread group leader for the process uint64_t __tgid; + void syscall(ThreadContext *tc, Fault *fault) override; + /// Array of syscall descriptors, indexed by call number. static std::map syscallDescs; }; diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc index 5fb3b03484..530cf8512d 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -100,12 +100,18 @@ Sparc32LinuxProcess::Sparc32LinuxProcess(ProcessParams * params, : Sparc32Process(params, objFile) {} -void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, - Fault *fault) +void +Sparc32LinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(1), tc, fault); +} + +void +Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, Fault *fault) { switch (trapNum) { case 0x10: //Linux 32 bit syscall trap - tc->syscall(tc->readIntReg(1), fault); + tc->syscall(fault); break; default: SparcProcess::handleTrap(trapNum, tc, fault); @@ -117,13 +123,19 @@ Sparc64LinuxProcess::Sparc64LinuxProcess(ProcessParams * params, : Sparc64Process(params, objFile) {} -void Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, - Fault *fault) +void +Sparc64LinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(1), tc, fault); +} + +void +Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc, Fault *fault) { switch (trapNum) { // case 0x10: // Linux 32 bit syscall trap case 0x6d: // Linux 64 bit syscall trap - tc->syscall(tc->readIntReg(1), fault); + tc->syscall(fault); break; default: SparcProcess::handleTrap(trapNum, tc, fault); diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index f5260cdf13..5c673db260 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -70,6 +70,8 @@ class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32Process return SparcLinuxProcess::getDesc32(callnum); } + void syscall(ThreadContext *tc, Fault *fault) override; + void handleTrap(int trapNum, ThreadContext *tc, Fault *fault); }; @@ -86,6 +88,8 @@ class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64Process return SparcLinuxProcess::getDesc(callnum); } + void syscall(ThreadContext *tc, Fault *fault) override; + void handleTrap(int trapNum, ThreadContext *tc, Fault *fault); }; diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index 18f2316a26..d51b9519c9 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -368,3 +368,9 @@ SparcSolarisProcess::getDesc(int callnum) return NULL; return &syscallDescs[callnum]; } + +void +SparcSolarisProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(1), tc, fault); +} diff --git a/src/arch/sparc/solaris/process.hh b/src/arch/sparc/solaris/process.hh index 660802cefa..39e3aef177 100644 --- a/src/arch/sparc/solaris/process.hh +++ b/src/arch/sparc/solaris/process.hh @@ -49,6 +49,8 @@ class SparcSolarisProcess : public Sparc64Process /// The target system's hostname. static const char *hostname; + void syscall(ThreadContext *tc, Fault *fault) override; + /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 95bc7a5c1a..1fbf32748c 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -400,7 +400,7 @@ // will sign extend it, and there's no easy way to // specify only checking the first byte. 0xffffffffffffff80: - SyscallInst::int80('xc->syscall(Rax, &fault)', + SyscallInst::int80('xc->syscall(&fault)', IsSyscall, IsNonSpeculative, IsSerializeAfter); } diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 51154d5b84..43a62d76cd 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -235,7 +235,7 @@ } } 0x05: decode FullSystemInt { - 0: SyscallInst::syscall('xc->syscall(Rax, &fault)', + 0: SyscallInst::syscall('xc->syscall(&fault)', IsSyscall, IsNonSpeculative, IsSerializeAfter); default: decode MODE_MODE { @@ -429,7 +429,7 @@ 0x2: Inst::RDMSR(); 0x3: rdpmc(); 0x4: decode FullSystemInt { - 0: SyscallInst::sysenter('xc->syscall(Rax, &fault)', + 0: SyscallInst::sysenter('xc->syscall(&fault)', IsSyscall, IsNonSpeculative, IsSerializeAfter); default: sysenter(); diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc index 6befafde42..d58d965af6 100644 --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -584,8 +584,15 @@ X86_64LinuxProcess::X86_64LinuxProcess(ProcessParams * params, sizeof(syscallDescs64) / sizeof(SyscallDesc)) {} -void X86_64LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc, - Process *process, RegVal flags) +void +X86_64LinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + doSyscall(tc->readIntReg(INTREG_RAX), tc, fault); +} + +void +X86_64LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc, + Process *process, RegVal flags) { X86_64Process::clone(old_tc, new_tc, (X86_64Process*)process, flags); } @@ -926,8 +933,22 @@ I386LinuxProcess::I386LinuxProcess(ProcessParams * params, ObjectFile *objFile) sizeof(syscallDescs32) / sizeof(SyscallDesc)) {} -void I386LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc, - Process *process, RegVal flags) +void +I386LinuxProcess::syscall(ThreadContext *tc, Fault *fault) +{ + 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); + } + doSyscall(tc->readIntReg(INTREG_RAX), tc, fault); +} + +void +I386LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc, + Process *process, RegVal flags) { I386Process::clone(old_tc, new_tc, (I386Process*)process, flags); } diff --git a/src/arch/x86/linux/process.hh b/src/arch/x86/linux/process.hh index d4c9b0cf66..5f3135dd96 100644 --- a/src/arch/x86/linux/process.hh +++ b/src/arch/x86/linux/process.hh @@ -54,6 +54,7 @@ class X86_64LinuxProcess : public X86_64Process public: /// Constructor. X86_64LinuxProcess(ProcessParams * params, ObjectFile *objFile); + void syscall(ThreadContext *tc, Fault *fault) override; void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *process, RegVal flags); }; @@ -63,6 +64,7 @@ class I386LinuxProcess : public I386Process public: /// Constructor. I386LinuxProcess(ProcessParams * params, ObjectFile *objFile); + void syscall(ThreadContext *tc, Fault *fault) override; void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *process, RegVal flags); }; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index f0e8ead98a..df22f238a7 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -146,19 +146,6 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile, next_thread_stack_base, mmap_end); } -void -I386Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault) -{ - 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) diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index 37545e9d9a..4c424cd7d9 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -176,8 +176,6 @@ namespace X86ISA void argsInit(int pageSize); void initState() override; - void syscall(int64_t callnum, ThreadContext *tc, - Fault *fault) override; RegVal getSyscallArg(ThreadContext *tc, int &i) override; RegVal getSyscallArg(ThreadContext *tc, int &i, int width) override; void clone(ThreadContext *old_tc, ThreadContext *new_tc, diff --git a/src/arch/x86/pseudo_inst.cc b/src/arch/x86/pseudo_inst.cc index 62d8b25c53..68bc74acce 100644 --- a/src/arch/x86/pseudo_inst.cc +++ b/src/arch/x86/pseudo_inst.cc @@ -50,7 +50,7 @@ m5Syscall(ThreadContext *tc) DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n"); Fault fault; - tc->syscall(tc->readIntReg(INTREG_RAX), &fault); + tc->syscall(&fault); } /* diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 8db6aa3768..e50afebf5e 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -581,7 +581,7 @@ class CheckerCPU : public BaseCPU, public ExecContext void wakeup(ThreadID tid) override { } // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. - void syscall(int64_t callnum, Fault *fault) override { } + void syscall(Fault *fault) override { } void handleError() diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index dbdfa80cdd..0fb75562a5 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -184,9 +184,9 @@ class CheckerThreadContext : public ThreadContext /** Executes a syscall in SE mode. */ void - syscall(int64_t callnum, Fault *fault) override + syscall(Fault *fault) override { - return actualTC->syscall(callnum, fault); + return actualTC->syscall(fault); } Status status() const override { return actualTC->status(); } diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index a2b3924928..80f3edaee2 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -304,9 +304,9 @@ class ExecContext { */ /** - * Executes a syscall specified by the callnum. + * Executes a syscall. */ - virtual void syscall(int64_t callnum, Fault *fault) = 0; + virtual void syscall(Fault *fault) = 0; /** @} */ diff --git a/src/cpu/minor/exec_context.hh b/src/cpu/minor/exec_context.hh index 66e313eb37..184dd29101 100644 --- a/src/cpu/minor/exec_context.hh +++ b/src/cpu/minor/exec_context.hh @@ -387,9 +387,9 @@ class ExecContext : public ::ExecContext } void - syscall(int64_t callnum, Fault *fault) override + syscall(Fault *fault) override { - thread.syscall(callnum, fault); + thread.syscall(fault); } ThreadContext *tcBase() override { return thread.getTC(); } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index c843db3a01..996f6360bc 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -918,7 +918,7 @@ FullO3CPU::trap(const Fault &fault, ThreadID tid, template void -FullO3CPU::syscall(int64_t callnum, ThreadID tid, Fault *fault) +FullO3CPU::syscall(ThreadID tid, Fault *fault) { DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); @@ -929,7 +929,7 @@ FullO3CPU::syscall(int64_t callnum, ThreadID tid, Fault *fault) ++(this->thread[tid]->funcExeInst); // Execute the actual syscall. - this->thread[tid]->syscall(callnum, fault); + this->thread[tid]->syscall(fault); // Decrease funcExeInst by one as the normal commit will handle // incrementing it. diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index b06182d43d..7c0ea51662 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -284,7 +284,7 @@ class FullO3CPU : public BaseO3CPU /** Executes a syscall. * @todo: Determine if this needs to be virtual. */ - void syscall(int64_t callnum, ThreadID tid, Fault *fault); + void syscall(ThreadID tid, Fault *fault); /** Starts draining the CPU's pipeline of all instructions in * order to stop all memory accesses. */ diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 131ffd2589..a136e90196 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -252,7 +252,7 @@ class BaseO3DynInst : public BaseDynInst void trap(const Fault &fault); /** Emulates a syscall. */ - void syscall(int64_t callnum, Fault *fault) override; + void syscall(Fault *fault) override; public: diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 22d89ec0b9..a9fc990eca 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -192,13 +192,13 @@ BaseO3DynInst::trap(const Fault &fault) template void -BaseO3DynInst::syscall(int64_t callnum, Fault *fault) +BaseO3DynInst::syscall(Fault *fault) { // HACK: check CPU's nextPC before and after syscall. If it // changes, update this instruction's nextPC because the syscall // must have changed the nextPC. TheISA::PCState curPC = this->cpu->pcState(this->threadNumber); - this->cpu->syscall(callnum, this->threadNumber, fault); + this->cpu->syscall(this->threadNumber, fault); TheISA::PCState newPC = this->cpu->pcState(this->threadNumber); if (!(curPC == newPC)) { this->pcState(newPC); diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index c68f34c079..a01c054139 100644 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -448,9 +448,9 @@ class O3ThreadContext : public ThreadContext /** Executes a syscall in SE mode. */ void - syscall(int64_t callnum, Fault *fault) override + syscall(Fault *fault) override { - return cpu->syscall(callnum, thread->threadId(), fault); + return cpu->syscall(thread->threadId(), fault); } /** Reads the funcExeInst counter. */ diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index a0c3a8171b..024ebd074f 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -148,10 +148,9 @@ struct O3ThreadState : public ThreadState { ThreadContext *getTC() { return tc; } /** Handles the syscall. */ - void syscall(int64_t callnum, Fault *fault) + void syscall(Fault *fault) { - fatal_if(FullSystem, "System call emulation is unavailable!"); - process->syscall(callnum, tc, fault); + process->syscall(tc, fault); } void dumpFuncProfile() diff --git a/src/cpu/simple/exec_context.hh b/src/cpu/simple/exec_context.hh index 4d26dfe2aa..48a9f94232 100644 --- a/src/cpu/simple/exec_context.hh +++ b/src/cpu/simple/exec_context.hh @@ -497,9 +497,9 @@ class SimpleExecContext : public ExecContext { * Executes a syscall specified by the callnum. */ void - syscall(int64_t callnum, Fault *fault) override + syscall(Fault *fault) override { - thread->syscall(callnum, fault); + thread->syscall(fault); } /** Returns a pointer to the ThreadContext. */ diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 387e74546d..b4afcbbc84 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -609,10 +609,9 @@ class SimpleThread : public ThreadState, public ThreadContext } void - syscall(int64_t callnum, Fault *fault) override + syscall(Fault *fault) override { - fatal_if(FullSystem, "System call emulation is unavailable!"); - process->syscall(callnum, this, fault); + process->syscall(this, fault); } RegVal readIntRegFlat(RegIndex idx) const override { return intRegs[idx]; } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index a77ac48483..c14161d6f2 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -307,7 +307,7 @@ class ThreadContext : public PCEventScope // Same with st cond failures. virtual Counter readFuncExeInst() const = 0; - virtual void syscall(int64_t callnum, Fault *fault) = 0; + virtual void syscall(Fault *fault) = 0; // This function exits the thread context in the CPU and returns // 1 if the CPU has no more active threads (meaning it's OK to exit); diff --git a/src/sim/process.cc b/src/sim/process.cc index db013aee08..e7f682aada 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -437,7 +437,7 @@ Process::map(Addr vaddr, Addr paddr, int size, bool cacheable) } void -Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault) +Process::doSyscall(int64_t callnum, ThreadContext *tc, Fault *fault) { numSyscalls++; diff --git a/src/sim/process.hh b/src/sim/process.hh index 5d4a9672ed..70be3ab8ae 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -63,6 +63,9 @@ class ThreadContext; class Process : public SimObject { + protected: + void doSyscall(int64_t callnum, ThreadContext *tc, Fault *fault); + public: Process(ProcessParams *params, EmulationPageTable *pTable, ObjectFile *obj_file); @@ -74,7 +77,7 @@ class Process : public SimObject void initState() override; DrainState drain() override; - virtual void syscall(int64_t callnum, ThreadContext *tc, Fault *fault); + virtual void syscall(ThreadContext *tc, Fault *fault) = 0; virtual RegVal getSyscallArg(ThreadContext *tc, int &i) = 0; virtual RegVal getSyscallArg(ThreadContext *tc, int &i, int width); virtual void setSyscallReturn(ThreadContext *tc,