summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2019-11-25 01:07:41 -0800
committerGabe Black <gabeblack@google.com>2019-12-10 23:58:14 +0000
commitcb3457ccd17a89a4df3e70d35e0254c77a0b5782 (patch)
tree6693c6acb869246269906c5227f1331a78a6262d /src/arch/x86
parentd142a1547cfc7e06964e2cb34905f3e4304c93fd (diff)
downloadgem5-cb3457ccd17a89a4df3e70d35e0254c77a0b5782.tar.xz
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 <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa2
-rw-r--r--src/arch/x86/isa/decoder/two_byte_opcodes.isa4
-rw-r--r--src/arch/x86/linux/process.cc29
-rw-r--r--src/arch/x86/linux/process.hh2
-rw-r--r--src/arch/x86/process.cc13
-rw-r--r--src/arch/x86/process.hh2
-rw-r--r--src/arch/x86/pseudo_inst.cc2
7 files changed, 31 insertions, 23 deletions
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index 95bc7a5c1..1fbf32748 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 51154d5b8..43a62d76c 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 6befafde4..d58d965af 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 d4c9b0cf6..5f3135dd9 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 f0e8ead98..df22f238a 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 37545e9d9..4c424cd7d 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 62d8b25c5..68bc74acc 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);
}
/*