Compare commits

...

143 Commits

Author SHA1 Message Date
Andreas Sandberg c7f92c43da scons: Fix hook installation error caused by stale cache
Due to the way SCons caches some file system state internally, it
sometimes "remembers" that a file or directory didn't exist at some
point. The git hook installation script sometimes needs to create a
hooks directory in the repository. Due to the cached state of the
hooks directory, the build system tries to create it twice. The second
mkdir operation leads to an error since the directory already exists.

Fix this issue by clearing the cached state of the hooks directory
after creating it.

Change-Id: I3f67f75c06ef928b439a0742f7619b7e92ed093b
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2660
Reviewed-by: Gabe Black <gabeblack@google.com>
2017-04-05 10:28:55 +00:00
Curtis Dunham 567a9b0a08 arm, kvm: implement GIC state transfer
This also allows checkpointing of a Kvm GIC via the Pl390 model.

Change-Id: Ic85d81cfefad630617491b732398f5e6a5f34c0b
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2444
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:51:46 +00:00
Curtis Dunham 60075068ea arm, dev: add basic support for GICC_BPR register
The Binary Point Register (BPR) specifies which bits belong to the
group priority field (which are used for preemption) and which to the
subpriority field (which are ignored for preemption).

Change-Id: If51e669d23b49047b69b82ab363dd01a936cc93b
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2443
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:51:46 +00:00
Curtis Dunham 2f14baaabc arm, dev: refactor GIC Pl390 GICD_ITARGETSRn handling
The aforementioned registers (Interrupt Processor Targets Registers) are
banked per-CPU, but are read-only.  This patch eliminates the per-CPU
storage of these values that are simply computed.

Change-Id: I52cafc2f58e87dd54239a71326c01f4923544689
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2442
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:51:46 +00:00
Curtis Dunham bbdd34d628 arm: refactor packet processing in Pl390 GIC
Change-Id: I696703418506522ba90df5c2c4ca45c95a6efbea
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2441
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:51:46 +00:00
Nikos Nikoleris 3384caf0fe arm: Don't panic when checking coprocessor read/write permissions
Instructions that use the coprocessor interface check the current
program status to determine whether the current context has the
priviledges to read from/write to the coprocessor. Some modes allow
the execution of coprocessor instructions, some others do not allow it,
while some other modes are unexpected (e.g., executing an AArch32 
instruction while being in an AArch64 mode).

Previously we would unconditionally trigger a panic if we were in an 
unexpected mode. This change removes the panic and replaces it
with an Undefined Instruction fault that triggers if and when a 
coprocessor instruction commits in an unexpected mode. This allows
speculative coprocessor instructions from unexpected modes to execute 
but prevents them from gettting committed.

Change-Id: If2776d5bae2471cdbaf76d0e1ae655f501bfbf01
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Rekai Gonzalez Alberquilla <rekai.gonzalezalberquilla@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2281
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:39:47 +00:00
Nikos Nikoleris 4b164f8382 arm: Treat Write-Through Normal memory as Non-Cacheable
A completed write to a memory location that is Write-Through Cacheable
has to be visible to an external observer without the need of explicit
cache maintenance. This change adds support for Write-Through
Cacheable Normal memory and treats it as Non-cacheable. This incurs a
small penalty as accesses to the memory do not fill in the cache but
does not violate the properties of the memory type.

Change-Id: Iee17ef9d952a550be9ad660b1e60e9f6c4ef2c2d
Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2280
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-04-03 16:39:00 +00:00
Andreas Sandberg 31199bba53 sim: Handle cases where Drainable::resume() creates objects
There are cases where Drainable objects need to create new objects in
Drainable::resume(). In such cases, the local drain state will be
inherited from the DrainManager. We currently set the state to Running
as soon as we start resuming the simulator. This means that new
objects are created in the Running state rather than the Drained
state, which the resume code assumes. Depending on the traversal order
in DrainManager::resume(), this sometimes triggers a panic because the
object being resumed is in the wrong state.

This change introduces a new drain state, Resuming, that the
DrainManager enters as soon as it starts resuming the
simulator. Objects that are created while resuming are created in this
state. Such objects are then resumed in a subsequent pass over the
list of Drainable objects that need to be resumed. Once all objects
have been resumed, the simulator enters the Running state.

Change-Id: Ieee8645351ffbdec477e9cd2ff86fc795e459617
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2600
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:38:26 +00:00
Andreas Sandberg 9a13acaa36 config, arm: Add multi-core KVM support to bL config
Add support for KVM in the big.LITTLE(tm) example configuration. This
replaces the --atomic option with a --cpu-type option that can be used
to switch between atomic, kvm, and timing simulation.

When running in KVM mode, the simulation script automatically assigns
separate event queues (threads) to each of the simulated CPUs. All
simulated devices, including CPU child devices (e.g., interrupt
controllers and caches), are assigned to event queue 0.

Change-Id: Ic9a3f564db91f5a3d3cb754c5a02fdd5c17d5fdf
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Gabor Dozsa <gabor.dozsa@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2561
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:37:55 +00:00
Andreas Sandberg 3547af6e44 config, arm: Unify checkpoint path handling in bL configs
The vanilla bL configuration file and the dist-gem5 configuration file
use slightly different code paths when restoring from
checkpoints. Unify this by passing the parsed options to the
instantiate() method and adding an optional checkpoint keyword
argument for checkpoint directories (only used by the dist-gem5
script).

Change-Id: I9943ec10bd7a256465e29c8de571142ec3fbaa0e
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Gabor Dozsa <gabor.dozsa@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2560
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:37:55 +00:00
Andreas Sandberg 66a1016a35 arm, kvm: Override the kernel's default MPIDR value
The kernel and gem5 derive MPIDR values from CPU IDs in slightly
different ways. This means that guests running in a multi-CPU setup
sometimes fail to bring up secondary CPUs. Fix this by overriding the
MPIDR value in virtual CPUs just after they have been instantiated.

Change-Id: I916d44978a9c855ab89c80a083af45b0cea6edac
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2461
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:37:55 +00:00
Andreas Sandberg d2254e034e dev, arm: Fix multi-core KVM race in the generic timer
The generic timer sometimes needs to access global state. This can
lead to race conditions when simulating a multi-core KVM system where
each core lives in its own thread. In that case, the setMiscReg and
readMiscReg methods are called from the thread owning the CPU and not
the global device thread.

Change-Id: Ie3e982258648c8562cce0b30a0c122dfbfaf42cd
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Gabor Dozsa <gabor.dozsa@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2460
Reviewed-by: Weiping Liao <weipingliao@google.com>
2017-04-03 16:37:55 +00:00
Sascha Bischoff d7aef8be96 dev: Align BAR0 size to power of 2 for VirtIO devices
When setting the size of a PCI BAR, the kernel only supports powers of
two (as per the PCI spec). Previously, the size was incorrectly read
by the kernel, and the address ranges assigned to the PCI devices
could overlap, resulting in gem5 crashes.  We now round up to the next
power of two.

Kudos to Sergei Trofimov who helped to debug this issue!

Change-Id: I54ca399b62ea07c09d4cd989b17dfa670e841bbe
Reviewed-by: Anouk Van Laer <anouk.vanlaer@arm.com>
Reviewed-by: Sergei Trofimov <sergei.trofimov@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2580
Reviewed-by: Paul Rosenfeld <prosenfeld@micron.com>
2017-04-03 16:36:15 +00:00
Andreas Sandberg ba00d7449d dev: Add a dummy VirtIO device
VirtIO transport interfaces always expect a VirtIO device
pointer. However, there are cases (in particular when using VirtIO's
MMIO interface) where we want to instantiate an interface without a
device. Add a dummy device using VirtIO device ID 0 and no queues to
handle this use case.

Change-Id: I6cbe12fd403903ef585be40279c3b1321fde48ff
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Sudhanshu Jha <sudhanshu.jha@arm.com>
Reviewed-by: Rekai Gonzalez Alberquilla <rekai.gonzalezalberquilla@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2325
Reviewed-by: Weiping Liao <weipingliao@google.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-04-03 16:36:15 +00:00
Andreas Sandberg cd9ca71b25 dev: Rename VirtIO PCI debug flag
Rename VIOPci -> VIOIface to avoid having a separate flag for the MMIO
interface.

Change-Id: I99f9210fa36ce33662c48537fd3992cd9a69d349
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Sudhanshu Jha <sudhanshu.jha@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Rekai Gonzalez Alberquilla <rekai.gonzalezalberquilla@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2324
Reviewed-by: Weiping Liao <weipingliao@google.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-04-03 16:36:15 +00:00
Matteo Andreozzi 626a0cc003 arm: fix template instantiation warning in clang
In arch/arm/faults.hh, template the static member vals require explicit
specialisation to avoid compiler warnings.

Change-Id: Ie404ccaa43269cb1bb819e33153e776abbf3a79b
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-04-03 13:53:17 +01:00
Gabe Black 9f3615d9c9 scons: Collapse symlinks when installing git hooks.
When naively computing the relative path between the git hooks directory and a
hook we want to install, that will generally start with a few ".." path
components to work back out of the .git directory into the working directory.'
If the hooks directory is actually a symlink, then following ".." directory
entries won't get us back to where we came from, they'll take us to the actual
parent directory of hooks. The relative path we computed would then try to go
forward from this other directory using a path that would have worked in the
working directory, hopefully going somewhere that doesn't exist, but
potentially going to a totally unrelated file with the same relative path.

To avoid this problem, we should expand any symlinks in both the hooks
directory path, and the path to the hook script. That way, any ".." components
will go where we'd expect them to, and the relative path will actually go from
hooks to the script we expect.

Change-Id: I64d51bc817351f89b1d60eceaf450cc0a4553415
Reviewed-on: https://gem5-review.googlesource.com/2542
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-26 17:40:57 +00:00
Gabe Black d82e59f74b scons: Use a relative symlink for git hooks more selectively.
If the hooks directory is a symlink, then there are at least two possible
scenarios to consider when installing a hook which is itself a symlink. The
first is that hooks is a relative symlink, and so is likely intended to stay
in place relative to .git and the git working directory. In that case, it's ok
for the symlinks inside of hooks to be relative to the working directory too,
since they should also stay in place relatively speaking.

The second situation is that the symlink is absolute. In that case, moving the
git working directory will move the hook relative to the hook directory, and
any relative symlink will become broken. In that case, the hook symlink needs
to be absolute.

The same logic likely applies to the .git directory itself, although I haven't
run into a situation in practice where the .git directory is actually a
symlink.

Change-Id: I047aa198094dd0fd5a841417d93b211ece02783f
Reviewed-on: https://gem5-review.googlesource.com/2541
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-26 17:39:33 +00:00
Gabe Black ed44b7f6e2 scons: Detect and remove broken git hook symlinks.
When installing a git hook, it's possible for the hook to not "exist" if it's
actually a symlink which points to a file that doesn't exist. Trying to create
a new symlink in its place without first removing the old one causes a build
failure in these cases.

If the hook doesn't "exist" but is still a link, that means it's actually a
broken link and should be deleted by the hook installation function before any
new symlink is created.

Change-Id: I59aa51feb5bd74ca33e51e89cde2ceabeb41bd76
Reviewed-on: https://gem5-review.googlesource.com/2540
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-26 17:33:57 +00:00
Gabe Black 03ea796a79 scons: Stop generating an a.out checking the "as" version.
Change-Id: I71d07fc64bdb3c6c3e93e2a1fd358cc899a70678
Reviewed-on: https://gem5-review.googlesource.com/2500
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-24 19:39:19 +00:00
Curtis Dunham 7d6f2c5050 arm: correct register read bug in Pl390 GIC
Change-Id: I4c0de7c2a5b40c1a9f009ca12062cb108b450b04
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-21 10:47:15 +00:00
Andreas Sandberg 7110d2313e python: Automatically disable listeners in batch setups
Determine if gem5 is running in a batch environment by checking if
STDIN is wired to a TTY or not. If the simulator is running in a batch
environment, disable all listeners by default. This behavior can be
overridden using the --enable-listeners option.

Change-Id: I404c709135339144216bf08a2769c016c543333c
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Sean McGoogan <sean.mcgoogan@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2322
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-21 10:30:02 +00:00
Andreas Sandberg 065bb8c655 util: Add a tool to list outgoing/incoming changes
Add a small Python script that uses Gerrit's Change-Id: tags to list
incoming and outgoing changes.

Change-Id: Iea1757b2d64a57a4c7b4e47718cfcaa725a99615
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2329
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-21 10:26:57 +00:00
Pierre-Yves Péneau a4060ab950 misc: add copyright/name information for contribution
Change-Id: I9242ce50b86b02ec1880d411627da11265cb8961
Signed-off-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-on: https://gem5-review.googlesource.com/2328
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-20 14:31:32 +00:00
Brandon Potter fcf94310eb syscall-emul: Hotfix for FreeBSD/Mac builds
The clone system call added in 236719892 relies on header files
from Linux systems. Obviously, this prevents compilation for
anyone using FreeBSD or Mac to compile the simulator. This
changeset is meant as a temporary fix to allow builds on
non-Linux systems until a proper solution is found.

Change-Id: I404cc41c588ed193dd2c1ca0c1aea35b0786fe4e
Reviewed-on: https://gem5-review.googlesource.com/2420
Maintainer: Brandon Potter <Brandon.Potter@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-17 18:40:33 +00:00
Brandon Potter 1991ff3bb2 syscall-emul: change NULL to nullptr in Process files
Change-Id: I9ff21092876593237f919e9f7fb7283bd865ba2e
Reviewed-on: https://gem5-review.googlesource.com/2421
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Brandon Potter <Brandon.Potter@amd.com>
2017-03-17 18:39:58 +00:00
Radhika Jagtap 48333e7e3f cpu: Print progress messages in Trace CPU
This change adds the ability to print a message at intervals
of committed instruction count to indicate progress in the
trace replay.

Change-Id: I8363502354c42bfc52936d2627986598b63a5797
Reviewed-by: Rekai Gonzalez Alberquilla <rekai.gonzalezalberquilla@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2321
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-16 13:52:40 +00:00
Nikos Nikoleris e2805f825a tests: Warn not fail when reading invalid pickle status files
With this change, the test script will output a warning when it reads
an incomplete (e.g., when a regression is still running) or corrupt
status file instead of throwing an exception. When the scipt is used
to show the results the corrupt file is skipped; when it is used to
test if all regressions run successfully it will return an error value
(2).

Change-Id: Ie7d9b457b200e3abc7ae6238e3efbf3d18cf4297
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2320
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-16 13:51:37 +00:00
Andreas Sandberg 083cd6da78 arm, dev: Add missing override in the Pl390 GIC model
The Pl390::getAddrRanges() method should have been flagged using the
override keyword. Other methods in this class already use the override
keyword, so this results in a warning about inconsistent override
usage when compiling using clang.

Change-Id: I17449687a8e074262232562487b58c96466bd54e
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-15 14:41:40 +00:00
Andreas Sandberg 3e200455bd dev, arm: Add draining to the GIC model
The GIC model currently adds a delay to interrupts when posting them
to a target CPU. This means that an interrupt signal will be
represented by an event for a short period of time. We currently
ignore this when draining and serialize the tick when the interrupt
will fire. Upon loading the checkpoint, the simulated GIC reschedules
the pending events. This behaviour is undesirable when we implement
support for switching between in-kernel GIC emulation and gem5 GIC
emulation. In that case, the (kernel) GIC model gets a lot simpler if
we don't need to worry about in-flight interrupts from the gem5 GIC.

This changeset adds a draining check to force the GIC into a state
where all interrupts have been delivered prior to checkpointing/CPU
switching. It also removes the now redundant serialization of
interrupt events.

Change-Id: I8b8b080aa291ca029a3a7bdd1777f1fcd5b01179
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2331
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-13 12:10:52 +00:00
Andreas Sandberg 35cb11f14e arm: Clean up the GIC implementation
Lots of minor cleaups:
  * Make cached params const
  * Don't serialize params
  * Use AddrRange to represent the distributor and CPU address spaces
  * Store a const AddrRangeList of all PIO ranges

Change-Id: I40a17bc3a38868fb3b8af247790e852cf99ddf1d
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2330
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-13 12:10:52 +00:00
Brandon Potter 011ddf96fa style: change NULL to nullptr in syscall files
Change-Id: I02719f3572f6665cace1eb5681f297dcde9e71ce
Reviewed-on: https://gem5-review.googlesource.com/2271
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-09 22:42:45 +00:00
Brandon Potter 691a4574b4 syscall-emul: Ignore unimplemented system calls
This changeset sets the implementation policy for a subset of
system calls to the ignoreFunc implementation (for x86 only).
The ignored system calls likely will never be implemented and
this allows a warning to be issued instead of the simulation
exiting with a fatal.

Change-Id: I8d9741ad683151e88cc71156d3602e2d0ccb0acf
Reviewed-on: https://gem5-review.googlesource.com/2270
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-09 22:42:45 +00:00
Brandon Potter 2c1286865f syscall-emul: Rewrite system call exit code
The changeset does a major refactor on the exit, exit_group, and
futex system calls regarding exit functionality.

A FutexMap class and related structures are added into a new
file. This increases code clarity by encapsulating the futex
operations and the futex state into an object.

Several exit conditions were added to allow the simulator to end
processes under certain conditions. Also, the simulation only
exits now when all processes have finished executing.

Change-Id: I1ee244caa9b5586fe7375e5b9b50fd3959b9655e
Reviewed-on: https://gem5-review.googlesource.com/2269
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-09 22:42:45 +00:00
Brandon Potter 6f7bf1b11f syscall-emul: Add the tgkill system call
This changeset adds support to kill a thread group by calling
the tgkill system call. The functionality is needed in some
pthread applications.

Change-Id: I0413a3331be69b74dfab30de95384113ec4efb63
Reviewed-on: https://gem5-review.googlesource.com/2268
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
2017-03-09 22:42:45 +00:00
Brandon Potter 8b85f950e5 syscall-emul: Adds SE mode signal feature
This changeset adds a simple class definition and a member
in the System object to track signals sent between processes.
The implementation cannot support all signals that might be
sent between processes, but it can support some of the simple
use cases like SIGCHLD.

Change-Id: Id5f95aa60e7f49da1c5b5596fbfa26e729453ac7
Reviewed-on: https://gem5-review.googlesource.com/2267
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-09 22:42:45 +00:00
Brandon Potter 198c515b97 syscall-emul: Add or extend dup, dup2, and pipe
This changeset extends the pipe system call to work with
architectures other than Alpha (and enables the syscall for
x86). For the dup system call, it sets the clone-on-exec
flag by default. For the dup2 system call, the changeset
adds an implementation (and enables it for x86).

Change-Id: I00ddb416744ee7dd61a5cd02c4c3d97f30543878
Reviewed-on: https://gem5-review.googlesource.com/2266
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
2017-03-09 22:42:45 +00:00
Brandon Potter acce7b0dc0 syscall-emul: Add functionality to open syscalls
This changeset adds refactors the existing open system call,
adds the openat variant (enabled for x86 builds), and adds
additional "special file" test cases for /proc/meminfo and
/etc/passwd.

Change-Id: I6f429db65bbf2a28ffa3fd12df518c2d0de49663
Reviewed-on: https://gem5-review.googlesource.com/2265
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
2017-03-09 22:42:45 +00:00
Brandon Potter e5fe2b82b7 style: Correct some style issues
This changeset fixes line alignment issues, spacing, spelling,
etc. for files that are used during SE Mode.

Change-Id: Ie61b8d0eb4ebb5af554d72f1297808027833616e
Reviewed-on: https://gem5-review.googlesource.com/2264
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
2017-03-09 22:42:45 +00:00
Brandon Potter 43418e7f81 syscall-emul: Move memState into its own file
The Process class is full of implementation details and
structures related to SE Mode. This changeset factors out an
internal class from Process and moves it into a separate file.
The purpose behind doing this is to clean up the code and make
it a bit more modular.

Change-Id: Ic6941a1657751e8d51d5b6b1dcc04f1195884280
Reviewed-on: https://gem5-review.googlesource.com/2263
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-09 19:19:38 +00:00
Pierre-Yves Péneau 71dd6c2c17 misc: add missing copyright/author information in previous commit
See a06a46f and a854373.

Change-Id: Id66427db22b7d7764c218b9cd78d95db929f4127
Signed-off-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-on: https://gem5-review.googlesource.com/2224
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-09 17:22:52 +00:00
Lena Olson b2669a7875 ruby: fix MOESI_hammer directory to work with > 3GB memory
The MOESI_hammer directory assumes a contiguous address space, but X86
has an IO gap from 3-4GB. This patch allows the directory to work with
more than 3GB of memory on X86.

Assumptions: the physical address space (range of possible physical
addresses) is 0-XGB when X <= 3GB, and 0-(X+1)GB when X > 3GB. If there
is no IO gap this patch should still work.

Change-Id: I5453a09e953643cada2c096a91d339a3676f55ee
Reviewed-on: https://gem5-review.googlesource.com/2169
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-09 11:20:05 -06:00
Lena Olson 620bf51ae7 ruby: fix and/or precedence in slicc
The slicc compiler currently treats && and || with the same precedence.
This is highly non-intuitive to people used to C, and was probably an
error. This patch makes && bind tighter than ||.

For example, previously:
if (A || B && C)
compiled to:
if ((A || B) && C)
With this patch, it compiles to:
if (A || (B && C))

Change-Id: Idbbd5b50cc86a8d6601045adc14a253284d7b791
Signed-off-by: Lena Olson (leolson@google.com)
Reviewed-on: https://gem5-review.googlesource.com/2168
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Joe Gross <criusx@gmail.com>
Reviewed-by: Sooraj Puthoor <puthoorsooraj@gmail.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>

Conflicts:
	COPYING
2017-03-09 11:18:55 -06:00
Jason Lowe-Power 138000796a misc: Add a CONTRIBUTING document
This document details how to contribute to gem5 based on our new
contribution flow with git and gerrit.

Change-Id: I0a7e15fd83a3ee3ab6c85c1192f46f1e1d33b7c2
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-on: http://reviews.gem5.org/r/3814/
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Pierre-Yves Peneau <pierre-yves.peneau@lirmm.fr>
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Reviewed-by: Brad Beckmann <brad.beckmann@amd.com>
Reviewed-by: Ali Saidi <Ali.Saidi@ARM.com>
2017-03-09 10:21:09 -06:00
Andreas Sandberg b043dcf58a gpu-compute: Fix Python/C++ object hierarchy discrepancies
The GPUCoalescer and the Shader classes have different base classes in
C++ and Python. This causes subtle bugs in SWIG and compilation errors
for PyBind.

Change-Id: I1ddd2a8ea43f083470538ddfea891347b21d14d8
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2228
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-by: Bradford Beckmann <brad.beckmann@amd.com>
2017-03-07 11:50:35 +00:00
Andreas Sandberg c07a2d68f3 power: Avoid forward declarations that confuse wrappers
The Python wrappers get confused by the forward declarations in the
power framework. This changeset restructures the code slightly to
avoid the troublesome forward declarations.

Change-Id: Id8c93224f1988edb5fdf9d3abc6237f2f688c02d
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2227
Reviewed-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-07 11:44:32 +00:00
Sudhanshu Jha 846a17308c dev, arm: Render HDLCD frames at a fixed rate in KVM
Use the new fast scan-out API in the PixelPump to render frames at a
fixed frame rate in KVM mode. The refresh rate when running in KVM can
be controlled by the virt_refresh_rate parameter.

Change-Id: Ib3c78f174e3f8f4ca8a9b723c4e5d311a433b8aa
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2242
Reviewed-by: Rahul Thakur <rjthakur@google.com>
2017-03-07 11:14:28 +00:00
Sudhanshu Jha 9dd54d10ab dev: Add support for single-pass scan out in the PixelPump
Add a helper function to scan out an entire frame in one time
step. This requires the public PixelPump to be changed somewhat to
separate timing updates from general PixelPump control. Instead of
calling PixelPump::start(timings), timings now need to be updated
using a separate call to PixelPump::updateTimings(timings) before
calling PixelPump::start().

Display controllers that don't need accurate timing (e.g., in KVM
mode), can use the new PixelPump::renderFrame() API to render an
entire frame in one step. This call results in the same callbacks
(e.g., calls to nextPixel()) as the timing calls, but they all happen
in immediately. Unlike the timing counterpart, renderFrame() doesn't
support buffer underruns and will panic if nextPixle() indicates an
underrun.

Change-Id: I76c84db04249b02d4207c5281d82aa693d0881be
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2241
Reviewed-by: Rahul Thakur <rjthakur@google.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-03-07 11:14:28 +00:00
Sudhanshu Jha 82a8230aa7 dev, kvm: Add a fast KVM-aware mode in DmaReadFifo
Use a fast, functional, read operations keep the DMA FIFO full when
running in KVM mode.

Change-Id: I5b378c2fb6a1d3e687cef15e807e63a0a53a60e2
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2226
Reviewed-by: Rahul Thakur <rjthakur@google.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-07 11:14:28 +00:00
Sudhanshu Jha 746e2f3c27 arm, kmi: Clear interrupts in KMI devices
Added functionality to check and clear interrupts for KMI
devices. This fixes a boot bug when using KVM and in-kernel GIC
emulation.

Change-Id: Ia3e91d07567b7faf3f82b0adfda4a165a502a339
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2225
Reviewed-by: Rahul Thakur <rjthakur@google.com>
2017-03-07 11:14:28 +00:00
Brandon Potter 46bfc14312 syscall-emul: Remove unused class and member
The WaitRec structure in the Process class is unnecessary. There
is a member declaration inside of the Process class, waitList,
that uses the WaitRec definition. However, waitList is unused so
they are both dead bits of code. This changeset removes both the
WaitRec struct and waitList member from Process.

Change-Id: Ia6ee7488b9f47fd0f0ae29c818fba6ea0710699c
Reviewed-on: https://gem5-review.googlesource.com/2262
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Michael LeBeane <Michael.Lebeane@amd.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
2017-03-06 18:15:07 +00:00
Nikos Nikoleris 83cabc6264 mem: Make blkAlign a common function between all tag classes
blkAlign was defined as a separate function in the base associative
and fully-associative tags classes although both functions implemented
identical functionality. This patch moves the blkAlign in the base
tags class.

Change-Id: I3d415d0e62bddeec7ce0d559667e40a8c5fdc2d4
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
2017-03-03 14:09:42 +00:00
Nikos Nikoleris ce2a0076c9 mem: Use pkt::getBlockAddr instead of BaseCace::blockAlign
Change-Id: I0ed4e528cb750a323facdc811dde7f0ed1ff228e
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
2017-03-03 14:09:37 +00:00
Rahul Thakur ceb3bd9733 arm, kvm: enable running 32-bit Guest under ARM KVM64
1) Pass KVM_ARM_VCPU_EL1_32BIT to kvmArmVCpuInit
   when running 32-bit OS

2) Correctly map 64-bit registers to banked 32-bit ones

Change-Id: I1dec6427d6f5c3bba599ccdd804f1dfe80d3e670
Reviewed-on: https://gem5-review.googlesource.com/2261
Maintainer: Rahul Thakur <rjthakur@google.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-03 04:56:45 +00:00
Rahul Thakur 0fc9dcf46b arm, kvm: fix saving/restoring conditional flags in ARM KVM64
The gem5 stores flags separately from other fields CPSR, so we need to
split them out and recombine on trips to/from KVM.

Change-Id: I28ed00eb6f0e2a1436adfbc51b6ccf056958afeb
Reviewed-on: https://gem5-review.googlesource.com/2260
Reviewed-by: Rahul Thakur <rjthakur@google.com>
Maintainer: Rahul Thakur <rjthakur@google.com>
2017-03-03 04:53:41 +00:00
Pierre-Yves Péneau f3e0ac2b06 config: exit with fatal() if error
If output redirection is activated, the error message is printed in
simout. This change ensure it will be printed in simerr.

Change-Id: Ie661ac6b6978bf2e4aaaccdf23134795d764d459
Signed-off-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-on: https://gem5-review.googlesource.com/2221
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-01 14:21:56 +00:00
Lena Olson efcd8ae024 ruby: fix and/or precedence in slicc
The slicc compiler currently treats && and || with the same precedence.
This is highly non-intuitive to people used to C, and was probably an
error. This patch makes && bind tighter than ||.

For example, previously:
if (A || B && C)
compiled to:
if ((A || B) && C)
With this patch, it compiles to:
if (A || (B && C))

Change-Id: Idbbd5b50cc86a8d6601045adc14a253284d7b791
Signed-off-by: Lena Olson (leolson@google.com)
Reviewed-on: https://gem5-review.googlesource.com/2168
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Joe Gross <criusx@gmail.com>
Reviewed-by: Sooraj Puthoor <puthoorsooraj@gmail.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
[ Rebased onto master ]
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-03-01 11:58:37 +00:00
Andreas Sandberg 93e20c9a73 scons: Automatically add a git commit message hook
Gerrit requires that all commit messages have a Change-Id tag. This
tag is added automatically by a commit message hook in Git. Include
the default Gerrit commit message hook and add it automatically using
scons to make life easier for everyone.

Change-Id: I1270fbaaadf6ed151bddf14521a38e0c1a02d131
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2166
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
2017-03-01 11:42:39 +00:00
Brandon Potter 2367198921 syscall_emul: [PATCH 15/22] add clone/execve for threading and multiprocess simulations
Modifies the clone system call and adds execve system call. Requires allowing
processes to steal thread contexts from other processes in the same system
object and the ability to detach pieces of process state (such as MemState)
to allow dynamic sharing.
2017-02-27 14:10:15 -05:00
Brandon Potter 073cb26607 syscall_emul: [patch 14/22] adds identifier system calls
This changeset add fields to the process object and adds the following
three system calls: setpgid, gettid, getpid.
2017-02-27 14:10:02 -05:00
Brandon Potter f5656738dc x86: remove unnecessary parameter from functions 2017-02-27 14:09:30 -05:00
Tony Gutierrez 8602aea4e5 gpu-compute: remove unnecessary member from class
The clang compiler complains that the wavefront member in
the GpuISA class is unused. This changeset removes the member,
because it does not appear serve a purpose.
2017-02-27 13:18:51 -05:00
Brandon Potter 833fb10ed4 gpu-compute: mark functions with override if replacing virtual
The clang compiler is more stringent than the recent versions of
GCC when dealing with overrides. This changeset adds the specifier
to the methods which need it to silence the compiler.
2017-02-27 13:18:38 -05:00
Andreas Sandberg 8d2c3735d9 arch: Include generated decoder header after normal headers
The generated decoder header defines macros that represent bit fields
within instructions. These fields typically have short names that
conflict with names in other header files. Include the generated
header after all normal header to avoid this issue.

Change-Id: I53d149b75432c20abdbf651e32c3c785d897973b
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-27 12:06:00 +00:00
Andreas Sandberg 60b26f1546 base: Refactor logging to make log level selection cleaner
It's currently possible to change the log level in gem5 by tweaking a
set of global variables. These variables are currently exposed to
Python using SWIG. This mechanism is far from ideal for two reasons:
First, changing the log level requires that the Python world enables
or disables individual levels. Ideally, this should be a single call
where a log level is selected. Second, exporting global variables is
poorly supported by most Python frameworks. SWIG puts variables in
their own namespace and PyBind doesn't seem to support it at all.

This changeset refactors the logging code to create a more abstract
interface. Each log level is associated with an instance of a Logger
class. This class contains common functionality, an enable flag, and a
verbose flag.

Available LogLevels are described by the LogLevel class. Lower log
levels are used for more critical messages (PANIC being level 0) and
higher levels for less critical messages. The highest log level that
is printed is controlled by calling Logger:setLevel().

Change-Id: I31e44299d242d953197a8e62679250c91d6ef776
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Gabor Dozsa <gabor.dozsa@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-27 11:25:01 +00:00
Andreas Sandberg bec4409add tests: Disable descriptions in stat files
Don't output verbose text descriptions in stat files when running
tests. This saves a lot of space when storing reference data.

Change-Id: I2a7ead4843586e800ecf83846694b73f0c356373
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
2017-02-27 11:25:00 +00:00
Andreas Sandberg 8b1ba9f99d python: Add a generalized mechanism to configure stats
Add a mechanism to configure the stat output format using a URL-like
syntax. This makes it possible to specify both an output format
(currently, only text is supported) and override default
parameters.

On the Python-side, this is implemented using a helper function
(m5.stats.addStatVisitor) that adds a visitor to the list of active
stat visitors. The helper function parses a URL-like stat
specification to determine the stat output type. Optional parameters
can be specified to change how stat visitors behave.

For example, to output stats in text format without stat descriptions:

    m5.stats.addStatVisitor("text://stats.txt?desc=False")

From the command line:

    gem5.opt --stats-file="text://stats.txt?desc=False"

Internally, the stat framework uses the _url_factory decorator
to wrap a Python function with the fn(path, **kwargs) signature in a
function that takes a parsed URL as its only argument. The path and
keyword arguments are automatically derived from the URL in the
wrapper function.

New output formats can be registered in the m5.stats.factories
dictionary. This dictionary contains a mapping between format names
(URL schemes) and factory methods.

To retain backwards compatibility, the code automatically assumes that
the user wants text output if no format has been specified (i.e., when
specifying a plain path).

Change-Id: Ic4dce93ab4ead07ffdf71e55a22ba0ae5a143061
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Ilias Vougioukas <ilias.vougioukas@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
2017-02-27 11:24:59 +00:00
Brandon Potter a5802c823f syscall_emul: [patch 13/22] add system call retry capability
This changeset adds functionality that allows system calls to retry without
affecting thread context state such as the program counter or register values
for the associated thread context (when system calls return with a retry
fault).

This functionality is needed to solve problems with blocking system calls
in multi-process or multi-threaded simulations where information is passed
between processes/threads. Blocking system calls can cause deadlock because
the simulator itself is single threaded. There is only a single thread
servicing the event queue which can cause deadlock if the thread hits a
blocking system call instruction.

To illustrate the problem, consider two processes using the producer/consumer
sharing model. The processes can use file descriptors and the read and write
calls to pass information to one another. If the consumer calls the blocking
read system call before the producer has produced anything, the call will
block the event queue (while executing the system call instruction) and
deadlock the simulation.

The solution implemented in this changeset is to recognize that the system
calls will block and then generate a special retry fault. The fault will
be sent back up through the function call chain until it is exposed to the
cpu model's pipeline where the fault becomes visible. The fault will trigger
the cpu model to replay the instruction at a future tick where the call has
a chance to succeed without actually going into a blocking state.

In subsequent patches, we recognize that a syscall will block by calling a
non-blocking poll (from inside the system call implementation) and checking
for events. When events show up during the poll, it signifies that the call
would not have blocked and the syscall is allowed to proceed (calling an
underlying host system call if necessary). If no events are returned from the
poll, we generate the fault and try the instruction for the thread context
at a distant tick. Note that retrying every tick is not efficient.

As an aside, the simulator has some multi-threading support for the event
queue, but it is not used by default and needs work. Even if the event queue
was completely multi-threaded, meaning that there is a hardware thread on
the host servicing a single simulator thread contexts with a 1:1 mapping
between them, it's still possible to run into deadlock due to the event queue
barriers on quantum boundaries. The solution of replaying at a later tick
is the simplest solution and solves the problem generally.
2015-07-20 09:15:21 -05:00
Brandon Potter a7a0fd2c58 style: [patch 12/22] fix preliminary style issues for subsequent fault patch
This changeset add spaces in a few spots and removes an unnecessary comment.
2015-07-20 09:15:21 -05:00
Brandon Potter 6f549419eb syscall_emul: [patch 11/22] extend functionality of fcntl
This changeset adds the ability to set a close-on-exec flag for a given
file descriptor. It also reworks some of the logic surrounding setting and
retrieving flags from the file description.
2015-07-20 09:15:21 -05:00
Brandon Potter 748b87fc36 x86: remove redundant condition check in tlb code 2017-02-23 13:27:48 -05:00
Brandon Potter a4c4b4188d base: fix small memory leak in the ELF loader 2017-02-23 13:27:38 -05:00
Nikos Nikoleris 41bc2886de mem: Remove unused size field from the CacheBlk class
Change-Id: I6149290d6d2ac1a4bd6165871c93d7b7d6a980ad
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:45 +00:00
Nikos Nikoleris 83028e730c mem: Remove the unused asid field from the CacheBlk class
Change-Id: I29f45733c5fad822bdd0d8dcc7939d86b2e8c97b
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:45 +00:00
Nikos Nikoleris cb97118d91 mem: Remove unused arguments (asid/contex_id) from accessBlock
Change-Id: I79c2662fc81630ab321db8a75be6cd15fa07d372
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris e8723310ef mem: Remove unused type BlkList from the cache and the tags
Change-Id: If9ebb8488e8db587482ecfa99d2c12cfe5734fb9
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris da1ddb9aa7 mem: Remove unused functions from the tag classes
Change-Id: I4f3c2c027b1acaaf791a4c71086f34a9b9fbf4df
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris a063a14905 mem: Always use the helper function to invalidate a block
Policies like the LRU need to be notified when a block is invalidated,
the helper function does this along with invalidating the block.

Change-Id: I3ed59cf07938caa7f394ee6054b0af9e00b267ea
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Sascha Bischoff 46b4c40277 mem: Fix MSHR assert triggering for invalidated prefetches
This changeset updates an assert in src/mem/cache/mshr.cc which was
erroneously catching invalidated prefetch requests. These requests can
become invalidated if another component writes (an exclusive access)
to this location during the time that the read request is in
flight. The original assert made the assumption that these cases can
only occur for reads generated by the CPU, and hence
prefetcher-generated requests would sometimes trip the assert.

Change-Id: If4f043273a688c2bab8f7a641192a2b583e7b20e
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris 767aed4534 mem: Populate the secure flag in the writeback visitor
Previously the writeback visitor would not consider and set the secure
flag for the blocks that are written back to memory. This patch fixes
this.

Change-Id: Ie1a425fa9211407a70a4343f2c6b3d073371378f
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris d37bdc7366 misc: Add dtb files to the ignore list for git and mercurial
Change-Id: Ifb135c60e050c55769914e853b07a387c06e4007
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris 8fe8836eea mem: Remove stale argument from a panic statement
Change-Id: I7ae5fa44a937f641a2ddd242a49e0cd23f68b9f2
Reviewed-by: Sudhanshu Jha <sudhanshu.jha@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris 3c005c0f0e arm: Fix DPRINTFs with arguments in the instruction declarations
Change-Id: I0e373536897aa5bb4501b00945c2a0836100ddf4
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Nikos Nikoleris 2213fba5c5 arm: Blame the right instruction address on a Prefetch Abort
CPU models (e.g., O3CPU) issue instruction fetches for the whole cache
block rather than a specific instruction. Consequently the TLB lookups
translate the cache block virtual address. When the TLB lookup fails,
however, the Prefetch Abort must be raised for the PC of the
instruction that caused the fault rather than for the address of the
block.

This change fixes the way we instantiate the PrefetchAbort faults to
use the PC of the request rather the address of the instruction fetch
request.

Change-Id: I8e45549da1c3be55ad204a060029c95ce822a851
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Rekai Gonzalez Alberquilla <rekai.gonzalezalberquilla@arm.com>
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-21 14:14:44 +00:00
Andreas Hansson f2e2410a50 stats: Get all stats updated to reflect current behaviour
Line everything up again.
2017-02-19 05:30:32 -05:00
Andreas Hansson 184c6d7ebd sim: Ensure draining is deterministic
The traversal of drainable objects could potentially be
non-deterministic when using an unordered set containing object
pointers. To ensure that the iteration is deterministic, we switch to
a vector. Note that the lookup and traversal of the drainable objects
is not performance critical, so the change has no negative consequences.
2017-02-19 05:30:31 -05:00
Andreas Hansson 912b20d02a mem: Ensure deferred snoops are cache-line aligned
This patch fixes a bug where a deferred snoop ended up being to a
partial cache line, and not cache-line aligned, all due to how we copy
the packet.
2017-02-19 05:30:31 -05:00
Andreas Hansson 4fc16544af mem: Fix memory footprint includes
Fix compilation errors due to missing include.
2017-02-19 05:30:31 -05:00
Brandon Potter d3d983caf9 syscall_emul: [patch 10/22] refactor fdentry and add fdarray class
Several large changes happen in this patch.

The FDEntry class is rewritten so that file descriptors now correspond to
types: 'File' which is normal file-backed file with the file open on the
host machine, 'Pipe' which is a pipe that has been opened on the host machine,
and 'Device' which does not have an open file on the host yet acts as a pseudo
device with which to issue ioctls. Other types which might be added in the
future are directory entries and sockets (off the top of my head).

The FDArray class was create to hold most of the file descriptor handling
that was stuffed into the Process class. It uses shared pointers and
the std::array type to hold the FDEntries mentioned above.

The changes to these two classes needed to be propagated out to the rest
of the code so there were quite a few changes for that. Also, comments were
added where I thought they were needed to help others and extend our
DOxygen coverage.
2016-11-09 14:27:42 -06:00
Brandon Potter 6c41181b8e syscall_emul: [patch 9/22] remove unused global variable (num_processes) 2016-11-09 14:27:42 -06:00
Brandon Potter 49009f170a syscall_emul: [patch 8/22] refactor process class
Moves aux_vector into its own .hh and .cc files just to get it out of the
already crowded Process files. Arguably, it could stay there, but it's
probably better just to move it and give it files.

The changeset looks ugly around the Process header file, but the goal here is
to move methods and members around so that they're not defined randomly
throughout the entire header file. I expect this is likely one of the reasons
why I several unused variables related to this class. So, the methods are
declared first followed by members. I've tried to aggregate them together
so that similar entries reside near one another.

There are other changes coming to this code so this is by no means the
final product.
2016-11-09 14:27:41 -06:00
Brandon Potter ea8461885f syscall_emul: [patch 7/22] remove numCpus method
The numCpus method is misleading in that it's not really a measure of
how many CPUs might be executing a process, but how many thread contexts
are assigned to the process at any given point in time.

It's nice to highlight this distinction because thread contexts are never
reused in the same way that a CPU can be reused for multiple processes.
The reason that there is no reuse is that there is no CPU scheduler for SE.

The tru64 code intends to use this method and the accompanying contextIDs
field to support SMT and track the number of threads with some system calls.
With the up coming clone and exec patches, this paradigm must change. There
needs to be a 1:1 mapping between the thread contexts and processes so that
the process state between threads is allowed to vary when needed by Linux.
This should not break SMT for tru64 if the Process class is refactored so that
multiple Processes can share state between themselves. The following patches
will do the refactoring incrementally as features are added.
2016-11-09 14:27:41 -06:00
Brandon Potter b792e9e43c syscall_emul: [patch 6/22] remove unused fields from Process class
It looks like tru64 has some nxm* system calls, but the two fields that
are defined in the Process class are unused by any of the code. There doesn't
appear to be any reference in the tru64 code.
2016-11-09 14:27:41 -06:00
Brandon Potter 3886c4a8f2 syscall_emul: [patch 5/22] remove LiveProcess class and use Process instead
The EIOProcess class was removed recently and it was the only other class
which derived from Process. Since every Process invocation is also a
LiveProcess invocation, it makes sense to simplify the organization by
combining the fields from LiveProcess into Process.
2016-11-09 14:27:40 -06:00
Brandon Potter 7b6cf951e2 sparc: fix bugs caused by cd7f3a1dbf55
Turns out that SPARC SE mode relied on M5_pid being "0" in
all cases. The entries in the SPARC TLBs are accessed with
M5_pid as their context. This is buggy in the sense that it
will never work with more than one process or any
initialization that doesn't have the M5_pid value passed in
as "0".

cd7f3a1dbf55 broke the SPARC build because it deletes M5_pid
and uses a _pid with a default of "100" instead. This caused
the SPARC TLB to never return any valid lookups for any
request; the program never moved past the first instruction
with SPARC SE in the regression tester.

The solution proposed in this changeset is to initialize
the address space identification register with the PID value
that is passed into the process class as a parameter from
Python. This should return the correct responses from the TLB
since the insertions and lookups into the page table will be
using the same PID.

Furthermore, there are corner cases in the code which elevate
privileges and revert to using context "0" as the context in
the TLB. I believe that these are related to kernel level
traps and hypervisor privilege escalations, but I'm not
completely sure. I've tried to address the corner cases
properly, but it would be beneficial to have someone who is
familiar with the SPARC architecture to take a look at this
fix.
2017-02-17 12:01:51 -05:00
Brandon Potter 96f8ff5702 sim: fix out-of-bounds error in syscall_desc 2017-02-17 12:01:50 -05:00
Pierre-Yves Péneau a854373d59 mem, stats: fix typos in CommMonitor and Stats
Signed-off-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>

Reviewed at http://reviews.gem5.org/r/3802/
2017-02-15 14:59:06 -06:00
Pierre-Yves Péneau a06a46f5d1 mem, misc: fix building issue with CommMonitor (unused variables)
Signed-off-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>

Reviewed at http://reviews.gem5.org/r/3801/
2017-02-15 14:56:54 -06:00
Wendy Elsasser ddc6931573 mem: fix assertion in respondEvent
Assertion in the respondEvent erroneously fired.
The assertion verifies that the controller has not moved to a low-power
state prior to receiving read data from the memory.
The original assertion triggered if the state was not:
	PWR_IDLE or PWR_ACT.

In the case that failed, a periodic refresh event occurred around the
read.  The REF is stalled until the final read burst is issued
and the subsequent PRE closes the bank.  While the PRE will temporarily
move the state to PWR_IDLE, state will immediately transition to PWR_REF
due to the pending refresh operation.  This state does not match the
assertion, which is subsequently triggered.

Fixed the assertion by explicitly checking that the state is not a low
power state
	!PWR_SREF && !PWR_PRE_PDN && !PWR_ACT_PDN


Change-Id: I82921a733bbeac2bcb5a487c2f981448d41ed50b
Reviewed-by: Radhika Jagtap <radhika.jagtap@arm.com>
2017-02-15 09:28:44 -06:00
Gabor Dozsa 4b8b9c0585 arm,config: Add dist-gem5 support to the big.LITTLE(tm) config
This patch extends the example big.LITTLE configuration to enable
dist-gem5 simulations of big.LITTLE systems.

Change-Id: I49c095ab3c737b6a082f7c6f15f514c269217756
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:36:15 -06:00
Gabor Dozsa 3bdd58ccb4 config: Refactor the network switch configuration file
This patch prevents the body of the script getting executed when
the script is imported as a module.

Change-Id: I70a50f6295f1e7a088398017f5fa9d06fe90476a
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Gabor Dozsa 54c478c0b8 arm,config: Refactor the example big.LITTLE(tm) configuration
This patch prepares future extensions and customisation of the example
big.LITTLE configuration script. It breaks out the major phases into
functions so they can be called from other python scripts.

Change-Id: I2cb7c207c410fe14602cf17af7482719abba6c24
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham 80c17d0a8d arm, kvm: remove KvmGic
KvmGic functionality has been subsumed within the new MuxingKvmGic
model, which has Pl390 fallback when not using KVM for fast emulation.
This simplifies configuration and will enable checkpointing between
KVM emulation and full-system simulation.

Change-Id: Ie61251720064c512843015c075e4ac419a4081e8
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Andreas Sandberg 092b06b745 arm, kvm: Automatically use the MuxingKvmGic
Automatically use the MuxingKvmGic in the VExpress_GEM5_V1
platform. This removes the need to patch the host kernel or the
platform configuration when using KVM on ARM.

Change-Id: Ib1ed9b3b849b80c449ef1b62b83748f3f54ada26
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham 0edf6dc956 arm, kvm: implement MuxingKvmGic
This device allows us to, when KVM support is detected and compiled in,
instantiate the same Gic device whether the actual simulation is with
KVM cores or simulated cores.  Checkpointing is not yet supported.

Change-Id: I67e4e0b6fb7ab5058e52c933f4f3d8e7ab24981e
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham 41beacce08 sim, kvm: make KvmVM a System parameter
A KVM VM is typically a child of the System object already, but for
solving future issues with configuration graph resolution, the most
logical way to keep track of this object is for it to be an actual
parameter of the System object.

Change-Id: I965ded22203ff8667db9ca02de0042ff1c772220
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham d3bfc03688 sim,kvm,arm: fix typos
Change-Id: Ifc65d42eebfd109c1c622c82c3c3b3e523819e85
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Wendy Elsasser ca0fd665dc mem: Update DRAM configuration names
Names of DRAM configurations were updated to reflect both
the channel and device data width.

Previous naming format was:
	<DEVICE_TYPE>_<DATA_RATE>_<CHANNEL_WIDTH>

The following nomenclature is now used:
	<DEVICE_TYPE>_<DATA_RATE>_<n>x<w>
where n = The number of devices per rank on the channel
      x = Device width

Total channel width can be calculated by n*w

Example:
A 64-bit DDR4, 2400 channel consisting of 4-bit devices:
	n = 16
	w = 4
The resulting configuration name is:
	DDR4_2400_16x4

Updated scripts to match new naming convention.

Added unique configurations for DDR4 for:
1) 16x4
2) 8x8
3) 4x16

Change-Id: Ibd7f763b7248835c624309143cb9fc29d56a69d1
Reviewed-by: Radhika Jagtap <radhika.jagtap@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham 94e6126650 tests: check for gem5 binary before tests
Provides a helpful error when tests.py is invoked without the gem5 binary.

Before:
Running 0 tests

After:
gem5 binary 'quick/...' not an executable file

Change-Id: I1566802206c9e21ca89bd03e91db22844168a085
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham 5638a074b9 sim: allow forward dependencies in checkpoint upgraders
The notion of forward dependencies is just expressing the same
dependency but at the other end of the dependency edge, i.e. at
the dependee rather than the depender.  As there is no more
'power' here, it's strictly a convenience feature for handling
dependencies with tags that are not in the upstream repository.

Change-Id: Ic7c68de6aff4094aaa12de62cdf690a5dc65ccb5
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Curtis Dunham 72e74aed0a sim: add support for checkpoint downgrading
This commit supports the use case of transitioning tags and their
associated checkpoint rewrites out of use for whatever reason.  Just
replace the upgrader() method with a downgrader() method that performs
the appropriate inverse operation.

The tag name is still used, but only in this negative, 'zombie' state,
as it will be removed from the tags in the checkpoint and gem5 binary.

Change-Id: If9d26cccfe8449e026762b1a72f0c2ae5a9cf2d7
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2017-02-14 15:09:18 -06:00
Alec Roelke e9311a59ed riscv: Remove ECALL tests from insttest
The system calls tested in rv64i.cpp in RISC-V's insttest suite have
different behavior depending on the operating system and file system they
are run on. This patch ignores the output of those tests and only
ensures that the instructions in RV64I complete successfully.

[Change deletion of ECALL test to block comment.]
[Restore ECALL test but remove test output to test only for completion
without error.]
[Update patch description and again try to push EMPTY files for rv64i
tests.]
2017-02-13 14:26:05 -06:00
Christian Menard 1f1388b6c8 misc: Clean up and complete the gem5<->SystemC-TLM bridge [6/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Update the README
2017-02-13 14:25:16 -06:00
Tushar Krishna 1be05afa06 ruby: fix round robin arbiter in garnet2.0
The rr arbiter pointer in garnet was getting updated on every request,
even if there is no grant. This was leading to a huge variance in wait
time at a router at high injection rates.
This patch corrects it to update upon a grant.
2017-02-12 15:00:03 -05:00
Bjoern A. Zeeb f3643c8a60 mem: fix printing of 1st cache tags line
Rather than having the 1st line on the Log line and every other line on its
own, add a new line to have a common format for all of them.  Makes parsing
a lot easier.

Reviewed at http://reviews.gem5.org/r/3808/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-11 11:11:48 -05:00
Jason Lowe-Power 153e5879c6 x86: Fix implicit stack addressing in 64-bit mode
When in 64-bit mode, if the stack is accessed implicitly by an instruction
the alternate address prefix should be ignored if present.

This patch adds an extra flag to the ldstop which signifies when the
address override should be ignored. Then, for all of the affected
instructions, this patch adds two options to the ld and st opcode to use
the current stack addressing mode for all addresses and to ignore the
AddressSizeFlagBit.  Finally, this patch updates the x86 TLB to not
truncate the address if it is in 64-bit mode and the IgnoreAddrSizeFlagBit
is set.

This fixes a problem when calling __libc_start_main with a binary that is
linked with a recent version of ld. This version of ld uses the address
override prefix (0x67) on the call instruction instead of a nop.

Note: This has not been tested in compatibility mode and only the call
instruction with the address override prefix has been tested.

See [1] page 9 (pdf page 45)

For instructions that are affected see [1] page 519 (pdf page 555).

[1] http://support.amd.com/TechDocs/24594.pdf

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-10 11:19:34 -05:00
Jason Lowe-Power 87b9f0b87b misc: Update #!env calls for python to explicit version
In some newer Linux distributions, env python default to Python 3.0. This
patch explicitly uses "python2" instead of just "python" for all scripts
that use #!

Reported-by: Sanchayan Maity <maitysanchayan@gmail.com>
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-10 10:00:18 -05:00
Jason Lowe-Power 76004f08f2 misc: Add Python.h header to pyevents.hh
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-10 10:00:18 -05:00
Christian Menard a309c2f343 misc: Clean up and complete the gem5<->SystemC-TLM bridge [10/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
  * Add callbacks for the Gem5SimControl that are called at before and
  * after simulate()

Reviewed at http://reviews.gem5.org/r/3799/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:51 -05:00
Christian Menard 78e4967b6a misc: Clean up and complete the gem5<->SystemC-TLM bridge [9/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
  * Pay for the header delay that the gem5 XBar annotates to packets.

Reviewed at http://reviews.gem5.org/r/3798/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:48 -05:00
Christian Menard 0c4a69bcbf misc: Clean up and complete the gem5<->SystemC-TLM bridge [8/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
  * bugfix: The BEGIN_RESP also needs to be handled when END_REQ was
  * skipped
	    and '&trans == blockingRequest && phase == tlm::BEGIN_RESP'
evaluates to true.

Reviewed at http://reviews.gem5.org/r/3797/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:46 -05:00
Christian Menard b5045005de misc: Clean up and complete the gem5<->SystemC-TLM bridge [7/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Implement 'pipe through' for gem5 Packets (see explanation below)

Basically, this patch ensures that all transactions that originated in the
gem5 world are converted back to the original packet when entering the gem5
world.  So far, this only worked for packets that are responded to by a
SyctemC component (e.g. when a gem5 CPU sends a request to a SystemC
memory). By implementing the 'pipe through' this patch ensures, that
packets that are responded to by a gem5 component (e.g. when a gem5 CPU
sends a request to a gem5 memory via a SystemC interconnect) are handled
properly.

Reviewed at http://reviews.gem5.org/r/3796/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:43 -05:00
Christian Menard 03f740664b misc: Clean up and complete the gem5<->SystemC-TLM bridge [5/10]
Changeset 11798:3a490c57058d
---------------------------
misc: Clean up and complete the gem5<->SystemC-TLM bridge [5/10]

The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Introduce transactor modules that represent the gem5 ports in the
 * SystemC world.
 * Update the SimControl module and let it keep track of the gem5 ports.

Reviewed at http://reviews.gem5.org/r/3775/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:41 -05:00
Christian Menard ccd9210e1a misc: Clean up and complete the gem5<->SystemC-TLM bridge [4/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Move common code of the example to a common directory.  Move the cli
 * parsing from the SimControl module to a separate example object.  Add
 * comments describing the Gem5SimControl module.

Testing Done: Examples compile and run.

Reviewed at http://reviews.gem5.org/r/3695/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:38 -05:00
Christian Menard d2b19d2732 misc: Clean up and complete the gem5<->SystemC-TLM bridge [3/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Simplify the Slave Port by using a simple_initiator_socket.

Testing Done: Example applications are still running.

Reviewed at http://reviews.gem5.org/r/3686/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:35 -05:00
Christian Menard 55f5c4dd8a misc: Clean up and complete the gem5<->SystemC-TLM bridge [2/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Add the Master Port.  Add an example application that isslustrates its
 * use.

Testing Done: A simple example application consisting of a TLM traffic
generator and a gem5 memory is part of the patch.

Reviewed at http://reviews.gem5.org/r/3528/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:33 -05:00
Christian Menard b25ea094d4 misc: Clean up and complete the gem5<->SystemC-TLM bridge [1/10]
The current TLM bridge only provides a Slave Port that allows the gem5
world to send request to the SystemC world. This patch series refractors
and cleans up the existing code, and adds a Master Port that allows the
SystemC world to send requests to the gem5 world.

This patch:
 * Restructure the existing sources in preparation of the addition of the
 * new
   Master Port.
 * Refractor names to allow for distinction of the slave and master port.
 * Replace the Makefile by a SConstruct.

Testing Done: The examples provided in util/tlm (now
util/tlm/examples/slave_port) still compile and run error free.

Reviewed at http://reviews.gem5.org/r/3527/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:15:30 -05:00
Christian Menard 41a6158954 misc: add a MasterId to the ExternalPort
The Request constructor requires a MasterID. However, an external
transactor has no chance of getting a MasterID as it does not have a
pointer to the System. This patch adds a MasterID to ExternalMaster to
allow external modules to easily genrerate new Requests.

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:14:58 -05:00
Christian Menard 164d9bd732 misc: fix includes in util/systemc
This fixes compilation errors with clang on OS X.

Reviewed at http://reviews.gem5.org/r/3807/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:11:29 -05:00
Christian Menard 5fd959260c misc: Fix order of object construction in the CxxConfigManager
The CxxConfigManager schould create objects by traversing the object tree
starting from the root object. However, currently objects are created in
aplphabetical order, which only works if the root object alphabetically
comes before any system object (e.g. 'root' < 'system'. Otherwise (e.g.
'a_system' < 'root'), object construction may fail. The reason for this
behaviour is, that the call to findObject() in the sorting code also
constructs the object if it is not yet existent. Then findTraversalOrder()
calls findObject("root") and subseqeuently calls findObject() on all the
children, and so on. However, the call to findTraversalOrder() is
redundant, since all objects are already created in alphabetical order.
This patch simply removes the alphabetical ordering, leading to the objects
being created starting from 'root'.

Reviewed at http://reviews.gem5.org/r/3778/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:11:23 -05:00
Christian Menard f4b14c73fc misc: Implement the Base SystemC Module as an sc_channel.
Implementing the Module as an sc_channel allows derived classes to provide
SystemC interfaces. Other SystemC modules can connect to these interfaces.
This meachanism can be used to control gem5 and acces gem5 components from
within arbitrary SystemC moduels. Since sc_channel is derived from
sc_module, this patch does not break compatibility with existing code.

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:10:25 -05:00
Bjoern A. Zeeb 0852f0cfc6 sim: fix build breakage in process.cc after brandon@11801
Seeing build breakage after brandon@11801:

 [     CXX] X86/sim/process.cc -> .o build/X86/sim/process.cc:137:64:
error: field '_pid' is uninitialized when used here
[-Werror,-Wuninitialized] static_cast<PageTableBase *>(new
ArchPageTable(name(), _pid, system)) : ^ build/X86/sim/process.cc:138:64:
error: field '_pid' is uninitialized when used here
[-Werror,-Wuninitialized] static_cast<PageTableBase *>(new
FuncPageTable(name(), _pid))), ^ 2 errors generated.

Testing Done: Compiles now on FreeBSD 10 with clang.

Reviewed at http://reviews.gem5.org/r/3804/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:03:58 -05:00
Bjoern A. Zeeb b673f2aaa4 sim: Patch to fix the statfs build
See developers mailing list.  Trying to unbreak statfs.

Testing Done:
Builds on FreeBSD now.

Reviewed at http://reviews.gem5.org/r/3803/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:03:55 -05:00
Bjoern A. Zeeb e07f0c5043 scons: make build better on FreeBSD
Various changes we found needed to build gem5 successfully on
FreeBSD.

Reviewed at http://reviews.gem5.org/r/3378/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 19:00:00 -05:00
Bjoern A. Zeeb d728f6786b dev: net/i8254xGBe add two more wakeup registers to ignore
There are drivers writing to WUFC uncondtionally of anything.  In order to
not panic gem5 in these cases, ignore writes to WUFC and WUS as we do for
WUC.  Similarly return 0 (default reset value) on reads.

Testing Done: Booted in FS with such a driver revision which would
previously panic and now boots fine.

Reviewed at http://reviews.gem5.org/r/3791/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 18:59:55 -05:00
Bjoern A. Zeeb f0786704db arm: AArch64 report cache size correctly when reading CTR_EL0
Trying to read MISCREG_CTR_EL0 on AArch64 returned 0 as is was not
implmemented.  With that an operating system relying on the cache line
sizes reported in order to manage the caches would (a) panic given the
returned value 0 is not valid (high bit is RES1) or (b) worst case would
assume a cache line size of 4 doing a tremendous amount of extra
instruction work (including fetching).  Return the same values as for ARMv7
as the fields seem to be the same, or RES0/1 seem to be reported
accordingly for AArch64

In collaboration with:  Andrew Turner

Testing Done: Checked on FreeBSD boots with extra printfs;  also observed a
reduction of a factor of about 10 in instruction fetches for a simple
micro-test.

Reviewed at http://reviews.gem5.org/r/3667/

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-02-09 18:54:28 -05:00
Andreas Sandberg 653b4657e6 style: Force Python.h to be included before main header
Python's header files set various compiler macros (e.g.,
_XOPEN_SOURCE) unconditionally. This triggers preprocessor warnings
that end up being treated as errors. The Python integration manual [1]
strongly recommends that Python.h is included before any system
header. The style guide used to mandate that Python.h is included
first in any file that needs it. This requirement was changed to
always include a source file's main header first, which ended up
triggering these errors.

This change updates the style checker to always include Python.h
before the main header file.

[1] https://docs.python.org/2/extending/extending.html

Change-Id: Id6a4f7fc64a336a8fd26691a0ca682abeb1d1579
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Pierre-Yves Péneau <pierre-yves.peneau@lirmm.fr>
2017-02-07 15:28:33 +00:00
Nikos Nikoleris 227bdde922 proto: Fix warnings for protoc v3
protoc v3 introduces a new syntax for proto files and warns when the
syntax is not explicitly stated.

protoc relies on the fact that undefined preprocessor symbols are
explanded to 0 but since we use -Wundef they end up generating
warnings.

Change-Id: If07abeb54e932469c8f2c4d38634a97fdae40f77
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-01-27 15:07:20 -06:00
Alec Roelke e4c57275d3 riscv: Fix crash when syscall argument reg index is too high
By default, doSyscall gets the values of six registers to be used for
system call arguments.  RISC-V, by convention, only has four.  Because
RISC-V's implementation of these indices is as arrays of integers rather
than as base indices plus offsets, trying to get the fifth argument
register's value will cause a crash.  This patch fixes that by returning 0
for any index higher than 3.

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-01-27 15:05:01 -06:00
Paul Rosenfeld c5df9308c9 misc: Add support for switching multiple cores in SystemC
This patch adds a '-n' flag to the gem5 SystemC driver which allows
multiple CPUs to be switched out to a new CPU. Primarily this involves
appending CPU numbers to the objects searched for in the config
manager if there are multiple CPUs in the system.

Note that an equivalent change should be made to the util/cxx_config driver,
but I wanted to get input on this first before making the same change over
there

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-01-27 15:03:17 -06:00
Rahul Thakur e9889c46ed mem: Refactor CommMonitor stats, add basic atomic mode stats
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-01-27 14:58:16 -06:00
Rahul Thakur 32d05d5fb6 mem: Add memory footprint probe
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
2017-01-27 14:58:15 -06:00
Andreas Sandberg 2974dc7a37 python: Move native wrappers to the _m5 namespace
Swig wrappers for native objects currently share the _m5.internal name
space with Python code. This is undesirable if we ever want to switch
from Swig to some other framework for native binding (e.g., PyBind11
or Boost::Python). This changeset moves all of such wrappers to the
_m5 namespace, which is now reserved for native code.

Change-Id: I2d2bc12dbc05b57b7c5a75f072e08124413d77f3
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
2017-01-27 12:40:01 +00:00
499 changed files with 59294 additions and 60992 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ m5out
/util/m5/*.o
/util/m5/*.a
/util/m5/m5
/system/arm/dt/*.dtb

View File

@ -14,3 +14,4 @@ ext/mcpat/regression/*/*.out
util/m5/*.o
util/m5/*.a
util/m5/m5
system/arm/dt/*.dtb

337
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,337 @@
Authors: Jason Lowe-Power
Andreas Sandberg
Steve Reinhardt
If you've made changes to gem5 that might benefit others, we strongly encourage
you to contribute those changes to the public gem5 repository. There are
several reasons to do this:
* Share your work with others, so that they can benefit from new functionality.
* Support the scientific principle by enabling others to evaluate your
suggestions without having to guess what you did.
* Once your changes are part of the main repo, you no longer have to merge
them back in every time you update your local repo. This can be a huge time
saving!
* Once your code is in the main repo, other people have to make their changes
work with your code, and not the other way around.
* Others may build on your contributions to make them even better, or extend
them in ways you did not have time to do.
* You will have the satisfaction of contributing back to the community.
The main method for contributing code to gem5 is via our code review website:
https://gem5-review.googlesource.com/. This documents describes the details of
how to create code changes, upload your changes, have your changes
reviewed, and finally push your changes to gem5. More information can be found
from the following sources:
* http://gem5.org/Submitting_Contributions
* https://gerrit-review.googlesource.com/Documentation/index.html
* https://git-scm.com/book
High-level flow for submitting changes
======================================
+-------------+
| Make change |
+------+------+
|
|
v
+------+------+
| Post review |
+------+------+
|
v
+--------+---------+
| Wait for reviews | <--------+
+--------+---------+ |
| |
| |
v |
+----+----+ No +------+------+
|Reviewers+--------->+ Update code |
|happy? | +------+------+
+----+----+ ^
| |
| Yes |
v |
+----+-----+ No |
|Maintainer+----------------+
|happy? |
+----+-----+
|
| Yes
v
+------+------+
| Submit code |
+-------------+
After creating your change to gem5, you can post a review on our Gerrit
code-review site: https://gem5-review.googlesource.com. Before being able to
submit your code to the mainline of gem5, the code is reviewed by others in the
community. Additionally, the maintainer for that part of the code must sign off
on it.
Cloning the gem5 repo to contribute
===================================
If you plan on contributing, it is strongly encouraged for you to clone the
repository directly from our gerrit instance at
https://gem5.googlesource.com/.
To clone the master gem5 repository:
> git clone https://gem5.googlesource.com/public/gem5
Other gem5 repositories
-----------------------
There are a few repositories other than the main gem5 development repository.
* public/m5threads: The code for a pthreads implementation that works with
gem5's syscall emulation mode.
Other gem5 branches
-------------------
None right now.
Making changes to gem5
======================
It is strongly encouraged to use git branches when making changes to gem5.
Additionally, keeping changes small and concise and only have a single logical
change per commit.
Unlike our previous flow with Mercurial and patch queues, when using git, you
will be committing changes to your local branch. By using separate branches in
git, you will be able to pull in and merge changes from mainline and simply
keep up with upstream changes.
Requirements for change descriptions
------------------------------------
To help reviewers and future contributors more easily understand and track
changes, we require all change descriptions be strictly formatted.
A canonical commit message consists of three parts:
* A short summary line describing the change. This line starts with one or
more keywords separated by commas followed by a colon and a description of
the change. This line should be no more than 65 characters long since
version control systems usually add a prefix that causes line-wrapping for
longer lines.
* (Optional, but highly recommended) A detailed description. This describes
what you have done and why. If the change isn't obvious, you might want to
motivate why it is needed. Lines need to be wrapped to 75 characters or
less.
* Tags describing patch metadata. You are highly recommended to use
tags to acknowledge reviewers for their work. Gerrit will automatically add
most tags.
The keyword should be one or more of the following separated by commas:
* Architecture name in lower case (e.g., arm or x86): Anything that is
target-architecture specific.
* base
* ext
* stats
* sim
* syscall_emul
* config:
* mem: Classic memory system. Ruby uses its own keyword.
* ruby: Ruby memory models.
* cpu: CPU-model specific (except for kvm)
* kvm: KVM-specific. Changes to host architecture specific components should
include an architecture keyword (e.g., arm or x86) as well.
* gpu-compute
* energy
* dev
* arch: General architecture support (src/arch/)
* scons: Build-system related. Trivial changes as a side effect of doing
something unrelated (e.g., adding a source file to a SConscript) don't
require this.
* tests
* style: Changes to the style checkers of style fixes.
* misc
Tags are an optional mechanism to store additional metadata about a patch and
acknowledge people who reported a bug or reviewed that patch. Tags are
generally appended to the end of the commit message in the order they happen.
We currently use the following tags:
* Signed-off-by: Added by the author and the submitter (if different).
This tag is a statement saying that you believe the patch to be correct and
have the right to submit the patch according to the license in the affected
files. Similarly, if you commit someone else's patch, this tells the rest
of the world that you have have the right to forward it to the main
repository. If you need to make any changes at all to submit the change,
these should be described within hard brackets just before your
Signed-off-by tag. By adding this line, the contributor certifies the
contribution is made under the terms of the Developer Certificate of Origin
(DCO) [https://developercertificate.org/].
* Reviewed-by: Used to acknowledge patch reviewers. It's generally considered
good form to add these. Added automatically.
* Reported-by: Used to acknowledge someone for finding and reporting a bug.
* Reviewed-on: Link to the review request corresponding to this patch. Added
automatically.
* Change-Id: Used by Gerrit to track changes across rebases. Added
automatically with a commit hook by git.
* Tested-by: Used to acknowledge people who tested a patch. Sometimes added
automatically by review systems that integrate with CI systems.
Other than the "Signed-off-by", "Reported-by", and "Tested-by" tags, you
generally don't need to add these manually as they are added automatically by
Gerrit.
It is encouraged for the author of the patch and the submitter to add a
Signed-off-by tag to the commit message. By adding this line, the contributor
certifies the contribution is made under the terms of the Developer Certificate
of Origin (DCO) [https://developercertificate.org/].
It is imperative that you use your real name and your real email address in
both tags and in the author field of the changeset.
For significant changes, authors are encouraged to add copyright information
and their names at the beginning of the file. The main purpose of the author
names on the file is to track who is most knowledgeable about the file (e.g.,
who has contributed a significant amount of code to the file).
Note: If you do not follow these guidelines, the gerrit review site will
automatically reject your patch.
If this happens, update your changeset descriptions to match the required style
and resubmit. The following is a useful git command to update the most recent
commit (HEAD).
> git commit --amend
Posting a review
================
If you have not signed up for an account on the Gerrit review site
(https://gem5-review.googlesource.com), you first have to create an account.
Setting up an account
---------------------
1. Go to https://gem5.googlesource.com/
2. Click "Sign In" in the upper right corner. Note: You will need a Google
account to contribute.
3. After signing in, click "Generate Password" and follow the instructions.
Submitting a change
-------------------
In gerrit, to submit a review request, you can simply push your git commits to
a special named branch. For more information on git push see
https://git-scm.com/docs/git-push.
There are three ways to push your changes to gerrit.
Push change to gerrit review
----------------------------
> git push origin HEAD:refs/for/master
Assuming origin is https://gem5.googlesource.com/public/gem5 and you want to
push the changeset at HEAD, this will create a new review request on top of the
master branch. More generally,
> git push <gem5 gerrit instance> <changeset>:refs/for/<branch>
See https://gerrit-review.googlesource.com/Documentation/user-upload.html for
more information.
Pushing your first change
--------------------------
The first time you push a change you may get the following error:
> remote: ERROR: [fb1366b] missing Change-Id in commit message footer
> ...
Within the error message, there is a command line you should run. For every new
clone of the git repo, you need to run the following command to automatically
insert the change id in the the commit (all on one line).
> curl -Lo `git rev-parse --git-dir`/hooks/commit-msg
https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x
`git rev-parse --git-dir`/hooks/commit-msg
If you receive the above error, simply run this command and then amend your
changeset.
> git commit --amend
Push change to gerrit as a draft
--------------------------------
> git push origin HEAD:refs/drafts/master
Push change bypassing gerrit
-----------------------------
Only maintainers can bypass gerrit review. This should very rarely be used.
> git push origin HEAD:refs/heads/master
Other gerrit push options
-------------------------
There are a number of options you can specify when uploading your changes to
gerrit (e.g., reviewers, labels). The gerrit documentation has more
information.
https://gerrit-review.googlesource.com/Documentation/user-upload.html
Reviewing patches
=================
Reviewing patches is done on our gerrit instance at
https://gem5-review.googlesource.com/.
After logging in with your Google account, you will be able to comment, review,
and push your own patches as well as review others' patches. All gem5 users are
encouraged to review patches. The only requirement to review patches is to be
polite and respectful of others.
There are multiple labels in Gerrit that can be applied to each review detailed
below.
* Code-review: This is used by any gem5 user to review patches. When reviewing
a patch you can give it a score of -2 to +2 with the following semantics.
* -2: This blocks the patch. You believe that this patch should never be
committed. This label should be very rarely used.
* -1: You would prefer this is not merged as is
* 0: No score
* +1: This patch seems good, but you aren't 100% confident that it should be
pushed.
* +2: This is a good patch and should be pushed as is.
* Maintainer: Currently only PMC members are maintainers. At least one
maintainer must review your patch and give it a +1 before it can be merged.
* Verified: This is automatically generated from the continuous integrated
(CI) tests. Each patch must receive at least a +1 from the CI tests before
the patch can be merged. The patch will receive a +1 if gem5 builds and
runs, and it will receive a +2 if the stats match.
* Style-Check: This is automatically generated and tests the patch against the
gem5 code style (http://www.gem5.org/Coding_Style). The patch must receive a
+1 from the style checker to be pushed.
Note: Whenever the patch creator updates the patch all reviewers must re-review
the patch. There is no longer a "Fix it, then Ship It" option.
Once you have received reviews for your patch, you will likely need to make
changes. To do this, you should update the original git changeset. Then, you
can simply push the changeset again to the same Gerrit branch to update the
review request.
> git push origin HEAD:refs/for/master
Note: If you have posted a patch and don't receive any reviews, you may need to
prod the reviewers. You can do this by adding a reply to your changeset review
on gerrit. It is expected that at least the maintainer will supply a review for
your patch.
Committing changes
==================
Each patch must meet the following criteria to be merged:
* At least one review with +2
* At least one maintainer with +1
* At least +1 from the CI tests (gem5 must build and run)
* At least +1 from the style checker
Once a patch meets the above criteria, the submitter of the patch will be able
to merge the patch by pressing the "Submit" button on Gerrit. When the patch is
submitted, it is merged into the public gem5 branch.

View File

@ -45,3 +45,4 @@ Copyright (c) 1994-1996 Carnegie-Mellon University.
Copyright (c) 1993-1994 Christopher G. Demetriou
Copyright (c) 1997-2002 Makoto Matsumoto and Takuji Nishimura
Copyright (c) 1998,2001 Manuel Bouyer.
Copyright (c) 2016-2017 Google Inc.

View File

@ -268,10 +268,17 @@ against the gem5 style rules on %s.
This script will now install the hook in your %s.
Press enter to continue, or ctrl-c to abort: """
mercurial_style_message = style_message % ("hg commit and qrefresh commands",
".hg/hgrc file")
git_style_message = style_message % ("'git commit'",
".git/hooks/ directory")
mercurial_style_message = """
You're missing the gem5 style hook, which automatically checks your code
against the gem5 style rules on hg commit and qrefresh commands.
This script will now install the hook in your .hg/hgrc file.
Press enter to continue, or ctrl-c to abort: """
git_style_message = """
You're missing the gem5 style or commit message hook. These hooks help
to ensure that your code follows gem5's style rules on git commit.
This script will now install the hook in your .git/hooks/ directory.
Press enter to continue, or ctrl-c to abort: """
mercurial_style_upgrade_message = """
Your Mercurial style hooks are not up-to-date. This script will now
@ -376,10 +383,43 @@ def install_git_style_hooks():
return
git_hooks = gitdir.Dir("hooks")
git_pre_commit_hook = git_hooks.File("pre-commit")
git_style_script = File("util/git-pre-commit.py")
def hook_exists(hook_name):
hook = git_hooks.File(hook_name)
return hook.exists()
if git_pre_commit_hook.exists():
def hook_install(hook_name, script):
hook = git_hooks.File(hook_name)
if hook.exists():
print "Warning: Can't install %s, hook already exists." % hook_name
return
if hook.islink():
print "Warning: Removing broken symlink for hook %s." % hook_name
os.unlink(hook.get_abspath())
if not git_hooks.exists():
mkdir(git_hooks.get_abspath())
git_hooks.clear()
abs_symlink_hooks = git_hooks.islink() and \
os.path.isabs(os.readlink(git_hooks.get_abspath()))
# Use a relative symlink if the hooks live in the source directory,
# and the hooks directory is not a symlink to an absolute path.
if hook.is_under(main.root) and not abs_symlink_hooks:
script_path = os.path.relpath(
os.path.realpath(script.get_abspath()),
os.path.realpath(hook.Dir(".").get_abspath()))
else:
script_path = script.get_abspath()
try:
os.symlink(script_path, hook.get_abspath())
except:
print "Error updating git %s hook" % hook_name
raise
if hook_exists("pre-commit") and hook_exists("commit-msg"):
return
print git_style_message,
@ -389,22 +429,11 @@ def install_git_style_hooks():
print "Input exception, exiting scons.\n"
sys.exit(1)
if not git_hooks.exists():
mkdir(git_hooks.get_abspath())
git_style_script = File("util/git-pre-commit.py")
git_msg_script = File("ext/git-commit-msg")
# Use a relative symlink if the hooks live in the source directory
if git_pre_commit_hook.is_under(main.root):
script_path = os.path.relpath(
git_style_script.get_abspath(),
git_pre_commit_hook.Dir(".").get_abspath())
else:
script_path = git_style_script.get_abspath()
try:
os.symlink(script_path, git_pre_commit_hook.get_abspath())
except:
print "Error updating git pre-commit hook"
raise
hook_install("pre-commit", git_style_script)
hook_install("commit-msg", git_msg_script)
# Try to wire up git to the style hooks
if not ignore_style and main.root.Entry(".git").exists():
@ -655,6 +684,9 @@ if main['GCC'] or main['CLANG']:
'-Wno-sign-compare', '-Wno-unused-parameter'])
# We always compile using C++11
main.Append(CXXFLAGS=['-std=c++11'])
if sys.platform.startswith('freebsd'):
main.Append(CCFLAGS=['-I/usr/local/include'])
main.Append(CXXFLAGS=['-I/usr/local/include'])
else:
print termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal,
print "Don't know what compiler options to use for your compiler."
@ -690,7 +722,8 @@ if main['GCC']:
# to avoid performance penalties on certain AMD chips. Older
# assemblers detect this as an error, "Error: expecting string
# instruction after `rep'"
as_version_raw = readCommand([main['AS'], '-v', '/dev/null'],
as_version_raw = readCommand([main['AS'], '-v', '/dev/null',
'-o', '/dev/null'],
exception=False).split()
# version strings may contain extra distro-specific
@ -771,6 +804,10 @@ elif main['CLANG']:
main.Append(CXXFLAGS=['-stdlib=libc++'])
main.Append(LIBS=['c++'])
# On FreeBSD we need libthr.
if sys.platform.startswith('freebsd'):
main.Append(LIBS=['thr'])
else:
print termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal,
print "Don't know what compiler options to use for your compiler."
@ -884,8 +921,12 @@ main.Append(SWIGFLAGS=swig_flags)
# Check for 'timeout' from GNU coreutils. If present, regressions will
# be run with a time limit. We require version 8.13 since we rely on
# support for the '--foreground' option.
timeout_lines = readCommand(['timeout', '--version'],
exception='').splitlines()
if sys.platform.startswith('freebsd'):
timeout_lines = readCommand(['gtimeout', '--version'],
exception='').splitlines()
else:
timeout_lines = readCommand(['timeout', '--version'],
exception='').splitlines()
# Get the first line and tokenize it
timeout_version = timeout_lines[0].split() if timeout_lines else []
main['TIMEOUT'] = timeout_version and \
@ -1083,6 +1124,11 @@ backtrace_impls = [ "none" ]
if conf.CheckLibWithHeader(None, 'execinfo.h', 'C',
'backtrace_symbols_fd((void*)0, 0, 0);'):
backtrace_impls.append("glibc")
elif conf.CheckLibWithHeader('execinfo', 'execinfo.h', 'C',
'backtrace_symbols_fd((void*)0, 0, 0);'):
# NetBSD and FreeBSD need libexecinfo.
backtrace_impls.append("glibc")
main.Append(LIBS=['execinfo'])
if backtrace_impls[-1] == "none":
default_backtrace_impl = "none"

View File

@ -58,7 +58,7 @@
# serial links, the main internal crossbar, and an external hmc controller.
#
# - VAULT CONTROLLERS:
# Instances of the HMC_2500_x32 class with their functionality specified in
# Instances of the HMC_2500_1x32 class with their functionality specified in
# dram_ctrl.cc
#
# - THE MAIN XBAR:

View File

@ -152,7 +152,7 @@ def config_mem(options, system):
them.
"""
if ( options.mem_type == "HMC_2500_x32"):
if ( options.mem_type == "HMC_2500_1x32"):
HMChost = HMC.config_host_hmc(options, system)
HMC.config_hmc(options, system, HMChost.hmc_host)
subsystem = system.hmc_dev
@ -163,7 +163,7 @@ def config_mem(options, system):
if options.tlm_memory:
system.external_memory = m5.objects.ExternalSlave(
port_type="tlm",
port_type="tlm_slave",
port_data=options.tlm_memory,
port=system.membus.master,
addr_ranges=system.mem_ranges)
@ -223,7 +223,7 @@ def config_mem(options, system):
# Connect the controllers to the membus
for i in xrange(len(subsystem.mem_ctrls)):
if (options.mem_type == "HMC_2500_x32"):
if (options.mem_type == "HMC_2500_1x32"):
subsystem.mem_ctrls[i].port = xbar[i/4].master
else:
subsystem.mem_ctrls[i].port = xbar.master

View File

@ -77,7 +77,7 @@ def addNoISAOptions(parser):
parser.add_option("--list-mem-types",
action="callback", callback=_listMemTypes,
help="List available memory types")
parser.add_option("--mem-type", type="choice", default="DDR3_1600_x64",
parser.add_option("--mem-type", type="choice", default="DDR3_1600_8x8",
choices=MemConfig.mem_names(),
help = "type of memory to use")
parser.add_option("--mem-channels", type="int", default=1,

View File

@ -1,6 +1,8 @@
# Copyright (c) 2012, 2015 ARM Limited
# All rights reserved.
#
# Copyright (c) 2017, Centre National de la Recherche Scientifique (CNRS)
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
@ -34,10 +36,12 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Andreas Sandberg
# Pierre-Yves Peneau
import m5.objects
import inspect
import sys
from m5.util import fatal
from textwrap import TextWrapper
# Dictionary of mapping names of real CPU models to classes.
@ -74,8 +78,7 @@ def get(name):
try:
return _platform_classes[real_name]
except KeyError:
print "%s is not a valid Platform model." % (name,)
sys.exit(1)
fatal("%s is not a valid Platform model." % (name,))
def print_platform_list():
"""Print a list of available Platform classes including their aliases."""

View File

@ -131,8 +131,8 @@ class Benchmark(object):
func(self, isa, os)
def makeLiveProcessArgs(self, **kwargs):
# set up default args for LiveProcess object
def makeProcessArgs(self, **kwargs):
# set up default args for Process object
process_args = {}
process_args['cmd'] = [ self.name ] + self.args
process_args['executable'] = self.executable
@ -147,11 +147,11 @@ class Benchmark(object):
return process_args
def makeLiveProcess(self, **kwargs):
process_args = self.makeLiveProcessArgs(**kwargs)
def makeProcess(self, **kwargs):
process_args = self.makeProcessArgs(**kwargs)
# figure out working directory: use m5's outdir unless
# overridden by LiveProcess's cwd param
# overridden by Process's cwd param
cwd = process_args.get('cwd')
if not cwd:
@ -163,9 +163,9 @@ class Benchmark(object):
# copy input files to working directory
for d in self.inputs_dir:
copyfiles(d, cwd)
# generate LiveProcess object
from m5.objects import LiveProcess
return LiveProcess(**process_args)
# generate Process object
from m5.objects import Process
return Process(**process_args)
def __str__(self):
return self.name
@ -750,5 +750,5 @@ if __name__ == '__main__':
print 'class: %s' % bench.__name__
x = bench('alpha', 'tru64', input_set)
print '%s: %s' % (x, input_set)
pprint(x.makeLiveProcessArgs())
pprint(x.makeProcessArgs())
print

20
configs/dist/sw.py vendored
View File

@ -63,13 +63,17 @@ def build_switch(options):
link.int0 = switch.interface[i]
return switch
# Add options
parser = optparse.OptionParser()
Options.addCommonOptions(parser)
Options.addFSOptions(parser)
(options, args) = parser.parse_args()
system = build_switch(options)
root = Root(full_system = True, system = system)
Simulation.run(options, root, None, None)
def main():
# Add options
parser = optparse.OptionParser()
Options.addCommonOptions(parser)
Options.addFSOptions(parser)
(options, args) = parser.parse_args()
system = build_switch(options)
root = Root(full_system = True, system = system)
Simulation.run(options, root, None, None)
if __name__ == "__m5_main__":
main()

View File

@ -80,7 +80,7 @@ except:
parser = optparse.OptionParser()
parser.add_option("--mem-type", type="choice", default="DDR3_1600_x64",
parser.add_option("--mem-type", type="choice", default="DDR3_1600_8x8",
choices=MemConfig.mem_names(),
help = "type of memory to use")
parser.add_option("--mem-size", action="store", type="string",
@ -252,6 +252,7 @@ system.tgen = TrafficGen(config_file = cfg_file_name,
# add a communication monitor
system.monitor = CommMonitor()
system.monitor.footprint = MemFootprintProbe()
# connect the traffic generator to the system
system.tgen.port = system.monitor.slave

View File

@ -53,8 +53,8 @@ from common import MemConfig
parser = optparse.OptionParser()
# Use a single-channel DDR3-1600 x64 by default
parser.add_option("--mem-type", type="choice", default="DDR3_1600_x64",
# Use a single-channel DDR3-1600 x64 (8x8 topology) by default
parser.add_option("--mem-type", type="choice", default="DDR3_1600_8x8",
choices=MemConfig.mem_names(),
help = "type of memory to use")

View File

@ -392,9 +392,9 @@ else:
# OpenCL driver
driver = ClDriver(filename="hsa", codefile=kernel_files)
for cpu in cpu_list:
cpu.workload = LiveProcess(executable = executable,
cmd = [options.cmd] + options.options.split(),
drivers = [driver])
cpu.workload = Process(executable = executable,
cmd = [options.cmd] + options.options.split(),
drivers = [driver])
for cp in cp_list:
cp.workload = host_cpu.workload

View File

@ -1,4 +1,4 @@
# Copyright (c) 2016 ARM Limited
# Copyright (c) 2016-2017 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
@ -44,6 +44,8 @@ m5.util.addToPath('../../')
from common.Caches import *
from common import CpuConfig
have_kvm = "kvm" in CpuConfig.cpu_names()
class L1I(L1_ICache):
tag_latency = 1
data_latency = 1
@ -170,6 +172,14 @@ class AtomicCluster(CpuCluster):
def addL1(self):
pass
class KvmCluster(CpuCluster):
def __init__(self, system, num_cpus, cpu_clock, cpu_voltage="1.0V"):
cpu_config = [ CpuConfig.get("kvm"), None, None, None, None ]
super(KvmCluster, self).__init__(system, num_cpus, cpu_clock,
cpu_voltage, *cpu_config)
def addL1(self):
pass
class SimpleSystem(LinuxArmSystem):
cache_line_size = 64

View File

@ -0,0 +1,140 @@
# Copyright (c) 2016-2017 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Gabor Dozsa
# This configuration file extends the example ARM big.LITTLE(tm)
# configuration to enabe dist-gem5 siulations of big.LITTLE systems.
import argparse
import os
import m5
from m5.objects import *
import fs_bigLITTLE as bL
m5.util.addToPath("../../dist")
import sw
def addOptions(parser):
# Options for distributed simulation (i.e. dist-gem5)
parser.add_argument("--dist", action="store_true", help="Distributed gem5"\
" simulation.")
parser.add_argument("--is-switch", action="store_true",
help="Select the network switch simulator process for"\
" a distributed gem5 run.")
parser.add_argument("--dist-rank", default=0, action="store", type=int,
help="Rank of this system within the dist gem5 run.")
parser.add_argument("--dist-size", default=0, action="store", type=int,
help="Number of gem5 processes within the dist gem5"\
" run.")
parser.add_argument("--dist-server-name",
default="127.0.0.1",
action="store", type=str,
help="Name of the message server host\nDEFAULT:"\
" localhost")
parser.add_argument("--dist-server-port",
default=2200,
action="store", type=int,
help="Message server listen port\nDEFAULT: 2200")
parser.add_argument("--dist-sync-repeat",
default="0us",
action="store", type=str,
help="Repeat interval for synchronisation barriers"\
" among dist-gem5 processes\nDEFAULT:"\
" --ethernet-linkdelay")
parser.add_argument("--dist-sync-start",
default="1000000000000t",
action="store", type=str,
help="Time to schedule the first dist synchronisation"\
" barrier\nDEFAULT:1000000000000t")
parser.add_argument("--ethernet-linkspeed", default="10Gbps",
action="store", type=str,
help="Link speed in bps\nDEFAULT: 10Gbps")
parser.add_argument("--ethernet-linkdelay", default="10us",
action="store", type=str,
help="Link delay in seconds\nDEFAULT: 10us")
parser.add_argument("--etherdump", action="store", type=str, default="",
help="Specify the filename to dump a pcap capture of"\
" the ethernet traffic")
# Used by util/dist/gem5-dist.sh
parser.add_argument("--checkpoint-dir", type=str,
default=m5.options.outdir,
help="Directory to save/read checkpoints")
def addEthernet(system, options):
# create NIC
dev = IGbE_e1000()
system.attach_pci(dev)
system.ethernet = dev
# create distributed ethernet link
system.etherlink = DistEtherLink(speed = options.ethernet_linkspeed,
delay = options.ethernet_linkdelay,
dist_rank = options.dist_rank,
dist_size = options.dist_size,
server_name = options.dist_server_name,
server_port = options.dist_server_port,
sync_start = options.dist_sync_start,
sync_repeat = options.dist_sync_repeat)
system.etherlink.int0 = Parent.system.ethernet.interface
if options.etherdump:
system.etherdump = EtherDump(file=options.etherdump)
system.etherlink.dump = system.etherdump
def main():
parser = argparse.ArgumentParser(
description="Generic ARM big.LITTLE configuration with "\
"dist-gem5 support")
bL.addOptions(parser)
addOptions(parser)
options = parser.parse_args()
if options.is_switch:
root = Root(full_system = True,
system = sw.build_switch(options))
else:
root = bL.build(options)
addEthernet(root.system, options)
bL.instantiate(options, checkpoint_dir=options.checkpoint_dir)
bL.run(options.checkpoint_dir)
if __name__ == "__m5_main__":
main()

View File

@ -1,4 +1,4 @@
# Copyright (c) 2016 ARM Limited
# Copyright (c) 2016-2017 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
@ -44,6 +44,7 @@ import argparse
import os
import sys
import m5
import m5.util
from m5.objects import *
m5.util.addToPath("../../")
@ -52,6 +53,7 @@ from common import SysPaths
from common import CpuConfig
import devices
from devices import AtomicCluster, KvmCluster
default_dtb = 'armv8_gem5_v1_big_little_2_2.dtb'
@ -61,6 +63,21 @@ default_rcs = 'bootscript.rcS'
default_mem_size= "2GB"
def _to_ticks(value):
"""Helper function to convert a latency from string format to Ticks"""
return m5.ticks.fromSeconds(m5.util.convert.anyToLatency(value))
def _using_pdes(root):
"""Determine if the simulator is using multiple parallel event queues"""
for obj in root.descendants():
if not m5.proxy.isproxy(obj.eventq_index) and \
obj.eventq_index != root.eventq_index:
return True
return False
class BigCluster(devices.CpuCluster):
def __init__(self, system, num_cpus, cpu_clock,
@ -107,11 +124,17 @@ def createSystem(caches, kernel, bootscript, disks=[]):
return sys
cpu_types = {
"atomic" : (AtomicCluster, AtomicCluster),
"timing" : (BigCluster, LittleCluster),
}
def main():
parser = argparse.ArgumentParser(
description="Generic ARM big.LITTLE configuration")
# Only add the KVM CPU if it has been compiled into gem5
if devices.have_kvm:
cpu_types["kvm"] = (KvmCluster, KvmCluster)
def addOptions(parser):
parser.add_argument("--restore-from", type=str, default=None,
help="Restore from checkpoint")
parser.add_argument("--dtb", type=str, default=default_dtb,
@ -122,8 +145,9 @@ def main():
help="Disks to instantiate")
parser.add_argument("--bootscript", type=str, default=default_rcs,
help="Linux bootscript")
parser.add_argument("--atomic", action="store_true", default=False,
help="Use atomic CPUs")
parser.add_argument("--cpu-type", type=str, choices=cpu_types.keys(),
default="timing",
help="CPU simulation mode. Default: %(default)s")
parser.add_argument("--kernel-init", type=str, default="/sbin/init",
help="Override init")
parser.add_argument("--big-cpus", type=int, default=1,
@ -138,11 +162,14 @@ def main():
help="Big CPU clock frequency")
parser.add_argument("--little-cpu-clock", type=str, default="1GHz",
help="Little CPU clock frequency")
parser.add_argument("--sim-quantum", type=str, default="1ms",
help="Simulation quantum for parallel simulation. " \
"Default: %(default)s")
return parser
def build(options):
m5.ticks.fixGlobalFrequency()
options = parser.parse_args()
kernel_cmd = [
"earlyprintk=pl011,0x1c090000",
"console=ttyAMA0",
@ -167,35 +194,31 @@ def main():
root.system = system
system.boot_osflags = " ".join(kernel_cmd)
AtomicCluster = devices.AtomicCluster
if options.big_cpus + options.little_cpus == 0:
m5.util.panic("Empty CPU clusters")
big_model, little_model = cpu_types[options.cpu_type]
all_cpus = []
# big cluster
if options.big_cpus > 0:
if options.atomic:
system.bigCluster = AtomicCluster(system, options.big_cpus,
options.big_cpu_clock)
else:
system.bigCluster = BigCluster(system, options.big_cpus,
options.big_cpu_clock)
mem_mode = system.bigCluster.memoryMode()
system.bigCluster = big_model(system, options.big_cpus,
options.big_cpu_clock)
system.mem_mode = system.bigCluster.memoryMode()
all_cpus += system.bigCluster.cpus
# little cluster
if options.little_cpus > 0:
if options.atomic:
system.littleCluster = AtomicCluster(system, options.little_cpus,
options.little_cpu_clock)
system.littleCluster = little_model(system, options.little_cpus,
options.little_cpu_clock)
system.mem_mode = system.littleCluster.memoryMode()
all_cpus += system.littleCluster.cpus
else:
system.littleCluster = LittleCluster(system, options.little_cpus,
options.little_cpu_clock)
mem_mode = system.littleCluster.memoryMode()
# Figure out the memory mode
if options.big_cpus > 0 and options.little_cpus > 0 and \
system.littleCluster.memoryMode() != system.littleCluster.memoryMode():
m5.util.panic("Memory mode missmatch among CPU clusters")
if options.big_cpus > 0 and options.little_cpus > 0:
if system.bigCluster.memoryMode() != system.littleCluster.memoryMode():
m5.util.panic("Memory mode missmatch among CPU clusters")
system.mem_mode = mem_mode
# create caches
system.addCaches(options.caches, options.last_cache_level)
@ -205,23 +228,65 @@ def main():
if options.little_cpus > 0 and system.littleCluster.requireCaches():
m5.util.panic("Little CPU model requires caches")
# Create a KVM VM and do KVM-specific configuration
if issubclass(big_model, KvmCluster):
_build_kvm(system, all_cpus)
# Linux device tree
system.dtb_filename = SysPaths.binary(options.dtb)
return root
def _build_kvm(system, cpus):
system.kvm_vm = KvmVM()
# Assign KVM CPUs to their own event queues / threads. This
# has to be done after creating caches and other child objects
# since these mustn't inherit the CPU event queue.
if len(cpus) > 1:
device_eq = 0
first_cpu_eq = 1
for idx, cpu in enumerate(cpus):
# Child objects usually inherit the parent's event
# queue. Override that and use the same event queue for
# all devices.
for obj in cpu.descendants():
obj.eventq_index = device_eq
cpu.eventq_index = first_cpu_eq + idx
def instantiate(options, checkpoint_dir=None):
# Setup the simulation quantum if we are running in PDES-mode
# (e.g., when using KVM)
root = Root.getInstance()
if root and _using_pdes(root):
m5.util.inform("Running in PDES mode with a %s simulation quantum.",
options.sim_quantum)
root.sim_quantum = _to_ticks(options.sim_quantum)
# Get and load from the chkpt or simpoint checkpoint
if options.restore_from is not None:
m5.instantiate(options.restore_from)
if options.restore_from:
if checkpoint_dir and not os.path.isabs(options.restore_from):
cpt = os.path.join(checkpoint_dir, options.restore_from)
else:
cpt = options.restore_from
m5.util.inform("Restoring from checkpoint %s", cpt)
m5.instantiate(cpt)
else:
m5.instantiate()
def run(checkpoint_dir=m5.options.outdir):
# start simulation (and drop checkpoints when requested)
while True:
event = m5.simulate()
exit_msg = event.getCause()
if exit_msg == "checkpoint":
print "Dropping checkpoint at tick %d" % m5.curTick()
cpt_dir = os.path.join(m5.options.outdir, "cpt.%d" % m5.curTick())
m5.checkpoint(os.path.join(cpt_dir))
cpt_dir = os.path.join(checkpoint_dir, "cpt.%d" % m5.curTick())
m5.checkpoint(cpt_dir)
print "Checkpoint done."
else:
print exit_msg, " @ ", m5.curTick()
@ -230,5 +295,15 @@ def main():
sys.exit(event.getCode())
def main():
parser = argparse.ArgumentParser(
description="Generic ARM big.LITTLE configuration")
addOptions(parser)
options = parser.parse_args()
root = build(options)
instantiate(options)
run()
if __name__ == "__m5_main__":
main()

View File

@ -143,7 +143,7 @@ def build_test_system(np):
for i in xrange(np)]
if is_kvm_cpu(TestCPUClass) or is_kvm_cpu(FutureClass):
test_sys.vm = KvmVM()
test_sys.kvm_vm = KvmVM()
if options.ruby:
# Check for timing mode because ruby does not support atomic accesses
@ -280,7 +280,7 @@ def build_drive_system(np):
drive_sys.kernel = binary(options.kernel)
if is_kvm_cpu(DriveCPUClass):
drive_sys.vm = KvmVM()
drive_sys.kvm_vm = KvmVM()
drive_sys.iobridge = Bridge(delay='50ns',
ranges = drive_sys.mem_ranges)

View File

@ -13,8 +13,8 @@ from common import HMC
parser = optparse.OptionParser()
# Use a HMC_2500_x32 by default
parser.add_option("--mem-type", type = "choice", default = "HMC_2500_x32",
# Use a HMC_2500_1x32 (1 channel, 32-bits wide) by default
parser.add_option("--mem-type", type = "choice", default = "HMC_2500_1x32",
choices = MemConfig.mem_names(),
help = "type of memory to use")

View File

@ -216,7 +216,7 @@ cfg_file.close()
proto_tester = TrafficGen(config_file = cfg_file_name)
# Set up the system along with a DRAM controller
system = System(physmem = DDR3_1600_x64())
system = System(physmem = DDR3_1600_8x8())
system.voltage_domain = VoltageDomain(voltage = '1V')

View File

@ -91,7 +91,7 @@ def get_processes(options):
idx = 0
for wrkld in workloads:
process = LiveProcess()
process = Process()
process.executable = wrkld
process.cwd = os.getcwd()
@ -154,7 +154,7 @@ if options.bench:
else:
exec("workload = %s(buildEnv['TARGET_ISA', 'linux', '%s')" % (
app, options.spec_input))
multiprocesses.append(workload.makeLiveProcess())
multiprocesses.append(workload.makeProcess())
except:
print >>sys.stderr, "Unable to find workload for %s: %s" % (
buildEnv['TARGET_ISA'], app)
@ -209,7 +209,7 @@ for cpu in system.cpu:
if is_kvm_cpu(CPUClass) or is_kvm_cpu(FutureClass):
if buildEnv['TARGET_ISA'] == 'x86':
system.vm = KvmVM()
system.kvm_vm = KvmVM()
for process in multiprocesses:
process.useArchPT = True
process.kvmInSE = True

View File

@ -75,7 +75,7 @@ if m5.defines.buildEnv['TARGET_ISA'] == "x86":
system.cpu.interrupts[0].int_slave = system.membus.master
# Create a DDR3 memory controller and connect it to the membus
system.mem_ctrl = DDR3_1600_x64()
system.mem_ctrl = DDR3_1600_8x8()
system.mem_ctrl.range = system.mem_ranges[0]
system.mem_ctrl.port = system.membus.master
@ -89,7 +89,7 @@ isa = str(m5.defines.buildEnv['TARGET_ISA']).lower()
binary = 'tests/test-progs/hello/bin/' + isa + '/linux/hello'
# Create a process for a simple "Hello World" application
process = LiveProcess()
process = Process()
# Set the command
# cmd is a list which begins with the executable (like argv)
process.cmd = [binary]

View File

@ -128,12 +128,12 @@ if m5.defines.buildEnv['TARGET_ISA'] == "x86":
system.system_port = system.membus.slave
# Create a DDR3 memory controller
system.mem_ctrl = DDR3_1600_x64()
system.mem_ctrl = DDR3_1600_8x8()
system.mem_ctrl.range = system.mem_ranges[0]
system.mem_ctrl.port = system.membus.master
# Create a process for a simple "Hello World" application
process = LiveProcess()
process = Process()
# Set the command
# cmd is a list which begins with the executable (like argv)
process.cmd = [binary]

View File

@ -76,56 +76,56 @@ if args:
# --------------------
# Define Splash2 Benchmarks
# ====================
class Cholesky(LiveProcess):
class Cholesky(Process):
executable = options.rootdir + '/kernels/cholesky/CHOLESKY'
cmd = 'CHOLESKY -p' + str(options.numcpus) + ' '\
+ options.rootdir + '/kernels/cholesky/inputs/tk23.O'
class FFT(LiveProcess):
class FFT(Process):
executable = options.rootdir + 'kernels/fft/FFT'
cmd = 'FFT -p' + str(options.numcpus) + ' -m18'
class LU_contig(LiveProcess):
class LU_contig(Process):
executable = options.rootdir + 'kernels/lu/contiguous_blocks/LU'
cmd = 'LU -p' + str(options.numcpus)
class LU_noncontig(LiveProcess):
class LU_noncontig(Process):
executable = options.rootdir + 'kernels/lu/non_contiguous_blocks/LU'
cmd = 'LU -p' + str(options.numcpus)
class Radix(LiveProcess):
class Radix(Process):
executable = options.rootdir + 'kernels/radix/RADIX'
cmd = 'RADIX -n524288 -p' + str(options.numcpus)
class Barnes(LiveProcess):
class Barnes(Process):
executable = options.rootdir + 'apps/barnes/BARNES'
cmd = 'BARNES'
input = options.rootdir + 'apps/barnes/input.p' + str(options.numcpus)
class FMM(LiveProcess):
class FMM(Process):
executable = options.rootdir + 'apps/fmm/FMM'
cmd = 'FMM'
input = options.rootdir + 'apps/fmm/inputs/input.2048.p' + str(options.numcpus)
class Ocean_contig(LiveProcess):
class Ocean_contig(Process):
executable = options.rootdir + 'apps/ocean/contiguous_partitions/OCEAN'
cmd = 'OCEAN -p' + str(options.numcpus)
class Ocean_noncontig(LiveProcess):
class Ocean_noncontig(Process):
executable = options.rootdir + 'apps/ocean/non_contiguous_partitions/OCEAN'
cmd = 'OCEAN -p' + str(options.numcpus)
class Raytrace(LiveProcess):
class Raytrace(Process):
executable = options.rootdir + 'apps/raytrace/RAYTRACE'
cmd = 'RAYTRACE -p' + str(options.numcpus) + ' ' \
+ options.rootdir + 'apps/raytrace/inputs/teapot.env'
class Water_nsquared(LiveProcess):
class Water_nsquared(Process):
executable = options.rootdir + 'apps/water-nsquared/WATER-NSQUARED'
cmd = 'WATER-NSQUARED'
input = options.rootdir + 'apps/water-nsquared/input.p' + str(options.numcpus)
class Water_spatial(LiveProcess):
class Water_spatial(Process):
executable = options.rootdir + 'apps/water-spatial/WATER-SPATIAL'
cmd = 'WATER-SPATIAL'
input = options.rootdir + 'apps/water-spatial/input.p' + str(options.numcpus)

View File

@ -77,39 +77,39 @@ if not options.numcpus:
# --------------------
# Define Splash2 Benchmarks
# ====================
class Cholesky(LiveProcess):
class Cholesky(Process):
cwd = options.rootdir + '/kernels/cholesky'
executable = options.rootdir + '/kernels/cholesky/CHOLESKY'
cmd = ['CHOLESKY', '-p' + str(options.numcpus),
options.rootdir + '/kernels/cholesky/inputs/tk23.O']
class FFT(LiveProcess):
class FFT(Process):
cwd = options.rootdir + '/kernels/fft'
executable = options.rootdir + '/kernels/fft/FFT'
cmd = ['FFT', '-p', str(options.numcpus), '-m18']
class LU_contig(LiveProcess):
class LU_contig(Process):
executable = options.rootdir + '/kernels/lu/contiguous_blocks/LU'
cmd = ['LU', '-p', str(options.numcpus)]
cwd = options.rootdir + '/kernels/lu/contiguous_blocks'
class LU_noncontig(LiveProcess):
class LU_noncontig(Process):
executable = options.rootdir + '/kernels/lu/non_contiguous_blocks/LU'
cmd = ['LU', '-p', str(options.numcpus)]
cwd = options.rootdir + '/kernels/lu/non_contiguous_blocks'
class Radix(LiveProcess):
class Radix(Process):
executable = options.rootdir + '/kernels/radix/RADIX'
cmd = ['RADIX', '-n524288', '-p', str(options.numcpus)]
cwd = options.rootdir + '/kernels/radix'
class Barnes(LiveProcess):
class Barnes(Process):
executable = options.rootdir + '/apps/barnes/BARNES'
cmd = ['BARNES']
input = options.rootdir + '/apps/barnes/input.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/barnes'
class FMM(LiveProcess):
class FMM(Process):
executable = options.rootdir + '/apps/fmm/FMM'
cmd = ['FMM']
if str(options.numcpus) == '1':
@ -118,23 +118,23 @@ class FMM(LiveProcess):
input = options.rootdir + '/apps/fmm/inputs/input.2048.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/fmm'
class Ocean_contig(LiveProcess):
class Ocean_contig(Process):
executable = options.rootdir + '/apps/ocean/contiguous_partitions/OCEAN'
cmd = ['OCEAN', '-p', str(options.numcpus)]
cwd = options.rootdir + '/apps/ocean/contiguous_partitions'
class Ocean_noncontig(LiveProcess):
class Ocean_noncontig(Process):
executable = options.rootdir + '/apps/ocean/non_contiguous_partitions/OCEAN'
cmd = ['OCEAN', '-p', str(options.numcpus)]
cwd = options.rootdir + '/apps/ocean/non_contiguous_partitions'
class Raytrace(LiveProcess):
class Raytrace(Process):
executable = options.rootdir + '/apps/raytrace/RAYTRACE'
cmd = ['RAYTRACE', '-p' + str(options.numcpus),
options.rootdir + '/apps/raytrace/inputs/teapot.env']
cwd = options.rootdir + '/apps/raytrace'
class Water_nsquared(LiveProcess):
class Water_nsquared(Process):
executable = options.rootdir + '/apps/water-nsquared/WATER-NSQUARED'
cmd = ['WATER-NSQUARED']
if options.numcpus==1:
@ -143,7 +143,7 @@ class Water_nsquared(LiveProcess):
input = options.rootdir + '/apps/water-nsquared/input.p' + str(options.numcpus)
cwd = options.rootdir + '/apps/water-nsquared'
class Water_spatial(LiveProcess):
class Water_spatial(Process):
executable = options.rootdir + '/apps/water-spatial/WATER-SPATIAL'
cmd = ['WATER-SPATIAL']
if options.numcpus==1:

191
ext/git-commit-msg Executable file
View File

@ -0,0 +1,191 @@
#!/bin/sh
# From Gerrit Code Review 2.13.5-2617-gba50ae91fd
#
# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unset GREP_OPTIONS
CHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed"
MSG="$1"
# Check for, and add if missing, a unique Change-Id
#
add_ChangeId() {
clean_message=`sed -e '
/^diff --git .*/{
s///
q
}
/^Signed-off-by:/d
/^#/d
' "$MSG" | git stripspace`
if test -z "$clean_message"
then
return
fi
# Do not add Change-Id to temp commits
if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!'
then
return
fi
if test "false" = "`git config --bool --get gerrit.createChangeId`"
then
return
fi
# Does Change-Id: already exist? if so, exit (no change).
if grep -i '^Change-Id:' "$MSG" >/dev/null
then
return
fi
id=`_gen_ChangeId`
T="$MSG.tmp.$$"
AWK=awk
if [ -x /usr/xpg4/bin/awk ]; then
# Solaris AWK is just too broken
AWK=/usr/xpg4/bin/awk
fi
# Get core.commentChar from git config or use default symbol
commentChar=`git config --get core.commentChar`
commentChar=${commentChar:-#}
# How this works:
# - parse the commit message as (textLine+ blankLine*)*
# - assume textLine+ to be a footer until proven otherwise
# - exception: the first block is not footer (as it is the title)
# - read textLine+ into a variable
# - then count blankLines
# - once the next textLine appears, print textLine+ blankLine* as these
# aren't footer
# - in END, the last textLine+ block is available for footer parsing
$AWK '
BEGIN {
# while we start with the assumption that textLine+
# is a footer, the first block is not.
isFooter = 0
footerComment = 0
blankLines = 0
}
# Skip lines starting with commentChar without any spaces before it.
/^'"$commentChar"'/ { next }
# Skip the line starting with the diff command and everything after it,
# up to the end of the file, assuming it is only patch data.
# If more than one line before the diff was empty, strip all but one.
/^diff --git / {
blankLines = 0
while (getline) { }
next
}
# Count blank lines outside footer comments
/^$/ && (footerComment == 0) {
blankLines++
next
}
# Catch footer comment
/^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
footerComment = 1
}
/]$/ && (footerComment == 1) {
footerComment = 2
}
# We have a non-blank line after blank lines. Handle this.
(blankLines > 0) {
print lines
for (i = 0; i < blankLines; i++) {
print ""
}
lines = ""
blankLines = 0
isFooter = 1
footerComment = 0
}
# Detect that the current block is not the footer
(footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
isFooter = 0
}
{
# We need this information about the current last comment line
if (footerComment == 2) {
footerComment = 0
}
if (lines != "") {
lines = lines "\n";
}
lines = lines $0
}
# Footer handling:
# If the last block is considered a footer, splice in the Change-Id at the
# right place.
# Look for the right place to inject Change-Id by considering
# CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
# then Change-Id, then everything else (eg. Signed-off-by:).
#
# Otherwise just print the last block, a new line and the Change-Id as a
# block of its own.
END {
unprinted = 1
if (isFooter == 0) {
print lines "\n"
lines = ""
}
changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):"
numlines = split(lines, footer, "\n")
for (line = 1; line <= numlines; line++) {
if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
unprinted = 0
print "Change-Id: I'"$id"'"
}
print footer[line]
}
if (unprinted) {
print "Change-Id: I'"$id"'"
}
}' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T"
}
_gen_ChangeIdInput() {
echo "tree `git write-tree`"
if parent=`git rev-parse "HEAD^0" 2>/dev/null`
then
echo "parent $parent"
fi
echo "author `git var GIT_AUTHOR_IDENT`"
echo "committer `git var GIT_COMMITTER_IDENT`"
echo
printf '%s' "$clean_message"
}
_gen_ChangeId() {
_gen_ChangeIdInput |
git hash-object -t commit --stdin
}
add_ChangeId

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
# All rights reserved.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
# All rights reserved.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# -----------------------------------------------------------------------------
# calc.py

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# -----------------------------------------------------------------------------
# calc.py

View File

@ -483,7 +483,7 @@ class DictImporter(object):
if fullname == 'm5.objects':
return self
if fullname.startswith('m5.internal'):
if fullname.startswith('_m5'):
return None
source = self.modules.get(fullname, None)
@ -588,14 +588,14 @@ def makeDefinesPyFile(target, source, env):
code = code_formatter()
code("""
import m5.internal
import _m5.core
import m5.util
buildEnv = m5.util.SmartDict($build_env)
compileDate = m5.internal.core.compileDate
compileDate = _m5.core.compileDate
_globals = globals()
for key,val in m5.internal.core.__dict__.iteritems():
for key,val in _m5.core.__dict__.iteritems():
if key.startswith('flag_'):
flag = key[5:]
_globals[flag] = val
@ -773,13 +773,13 @@ if GetOption('with_cxx_config'):
# Generate any needed param SWIG wrapper files
params_i_files = []
for name,param in sorted(params_to_swig.iteritems()):
i_file = File('python/m5/internal/%s.i' % (param.swig_module_name()))
i_file = File('python/_m5/%s.i' % (param.swig_module_name()))
params_i_files.append(i_file)
env.Command(i_file, Value(name),
MakeAction(createParamSwigWrapper, Transform("SW PARAM")))
env.Depends(i_file, depends)
env.Depends(SWIG, i_file)
SwigSource('m5.internal', i_file)
SwigSource('_m5', i_file)
# Generate all enum header files
for name,enum in sorted(all_enums.iteritems()):
@ -799,22 +799,22 @@ for name,enum in sorted(all_enums.iteritems()):
env.Depends(hh_file, depends + extra_deps)
env.Depends(SWIG, hh_file)
i_file = File('python/m5/internal/enum_%s.i' % name)
i_file = File('python/_m5/enum_%s.i' % name)
env.Command(i_file, Value(name),
MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG")))
env.Depends(i_file, depends + extra_deps)
env.Depends(SWIG, i_file)
SwigSource('m5.internal', i_file)
SwigSource('_m5', i_file)
# Generate SimObject SWIG wrapper files
for name,simobj in sorted(sim_objects.iteritems()):
py_source = PySource.modules[simobj.__module__]
extra_deps = [ py_source.tnode ]
i_file = File('python/m5/internal/param_%s.i' % name)
i_file = File('python/_m5/param_%s.i' % name)
env.Command(i_file, Value(name),
MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG")))
env.Depends(i_file, depends + extra_deps)
SwigSource('m5.internal', i_file)
SwigSource('_m5', i_file)
# Generate the main swig init file
def makeEmbeddedSwigInit(package):

View File

@ -840,7 +840,7 @@ decode OPCODE default Unknown::unknown() {
exitSimLoop("halt instruction encountered");
}}, IsNonSpeculative);
0x83: callsys({{
xc->syscall(R0);
xc->syscall(R0, &fault);
}}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
// Read uniq reg into ABI return value register (r0)
0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);

View File

@ -46,7 +46,7 @@ using namespace AlphaISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -66,7 +66,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
/// borrowed from Tru64, the subcases that get used appear to be
/// different in practice from those used by Tru64 processes.
static SyscallReturn
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -95,7 +95,7 @@ osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
/// Target osf_setsysinfo() handler.
static SyscallReturn
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -440,7 +440,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
/* 310 */ SyscallDesc("syslog", unimplementedFunc),
/* 311 */ SyscallDesc("reboot", unimplementedFunc),
/* 312 */ SyscallDesc("clone", cloneFunc),
/* 312 */ SyscallDesc("clone", cloneFunc<AlphaLinux>),
/* 313 */ SyscallDesc("uselib", unimplementedFunc),
/* 314 */ SyscallDesc("mlock", unimplementedFunc),
/* 315 */ SyscallDesc("munlock", unimplementedFunc),
@ -572,9 +572,9 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 441 */ SyscallDesc("keyctl", unimplementedFunc)
};
AlphaLinuxProcess::AlphaLinuxProcess(LiveProcessParams * params,
AlphaLinuxProcess::AlphaLinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: AlphaLiveProcess(params, objFile),
: AlphaProcess(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{
//init_regs->intRegFile[0] = 0;

View File

@ -36,11 +36,11 @@
namespace AlphaISA {
/// A process with emulated Alpha/Linux syscalls.
class AlphaLinuxProcess : public AlphaLiveProcess
class AlphaLinuxProcess : public AlphaProcess
{
public:
/// Constructor.
AlphaLinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
AlphaLinuxProcess(ProcessParams * params, ObjectFile *objFile);
virtual SyscallDesc* getDesc(int callnum);

View File

@ -38,6 +38,7 @@
#include "cpu/thread_context.hh"
#include "debug/Loader.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/byteswap.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
@ -46,28 +47,31 @@
using namespace AlphaISA;
using namespace std;
AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params,
ObjectFile *objFile)
: LiveProcess(params, objFile)
AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile)
: Process(params, objFile)
{
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
// Set up stack. On Alpha, stack goes below text section. This
// code should get moved to some architecture-specific spot.
stack_base = objFile->textBase() - (409600+4096);
Addr stack_base = objFile->textBase() - (409600+4096);
// Set up region for mmaps. Tru64 seems to start just above 0 and
// grow up from there.
mmap_end = 0x10000;
// Set up region for mmaps.
Addr mmap_end = 0x10000;
Addr max_stack_size = 8 * 1024 * 1024;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
Addr next_thread_stack_base = stack_base - max_stack_size;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
void
AlphaLiveProcess::argsInit(int intSize, int pageSize)
AlphaProcess::argsInit(int intSize, int pageSize)
{
// Patch the ld_bias for dynamic executables.
updateBias();
@ -130,15 +134,16 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
space_needed = 32*1024;
// set bottom of stack
stack_min = stack_base - space_needed;
memState->setStackMin(memState->getStackBase() - space_needed);
// align it
stack_min = roundDown(stack_min, pageSize);
stack_size = stack_base - stack_min;
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// map memory
allocateMem(stack_min, roundUp(stack_size, pageSize));
allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(),
pageSize));
// map out initial stack contents
Addr argv_array_base = stack_min + intSize; // room for argc
Addr argv_array_base = memState->getStackMin() + intSize; // room for argc
Addr envp_array_base = argv_array_base + argv_array_size;
Addr auxv_array_base = envp_array_base + envp_array_size;
Addr arg_data_base = auxv_array_base + auxv_array_size;
@ -153,7 +158,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
else
panic("Unknown int size");
initVirtMem.writeBlob(stack_min, (uint8_t*)&argc, intSize);
initVirtMem.writeBlob(memState->getStackMin(), (uint8_t*)&argc, intSize);
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
@ -170,13 +175,13 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
setSyscallArg(tc, 0, argc);
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
tc->setIntReg(StackPointerReg, memState->getStackMin());
tc->pcState(getStartPC());
}
void
AlphaLiveProcess::setupASNReg()
AlphaProcess::setupASNReg()
{
ThreadContext *tc = system->getThreadContext(contextIds[0]);
tc->setMiscRegNoEffect(IPR_DTB_ASN, _pid << 57);
@ -184,9 +189,9 @@ AlphaLiveProcess::setupASNReg()
void
AlphaLiveProcess::loadState(CheckpointIn &cp)
AlphaProcess::loadState(CheckpointIn &cp)
{
LiveProcess::loadState(cp);
Process::loadState(cp);
// need to set up ASN after unserialization since _pid value may
// come from checkpoint
setupASNReg();
@ -194,13 +199,13 @@ AlphaLiveProcess::loadState(CheckpointIn &cp)
void
AlphaLiveProcess::initState()
AlphaProcess::initState()
{
// need to set up ASN before further initialization since init
// will involve writing to virtual memory addresses
setupASNReg();
LiveProcess::initState();
Process::initState();
argsInit(MachineBytes, PageBytes);
@ -214,22 +219,21 @@ AlphaLiveProcess::initState()
}
AlphaISA::IntReg
AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
AlphaProcess::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i++);
}
void
AlphaLiveProcess::setSyscallArg(ThreadContext *tc,
int i, AlphaISA::IntReg val)
AlphaProcess::setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val)
{
assert(i < 6);
tc->setIntReg(FirstArgumentReg + i, val);
}
void
AlphaLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
AlphaProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
// check for error condition. Alpha syscall convention is to
// indicate success/failure in reg a3 (r19) and put the

View File

@ -35,13 +35,13 @@
#include "mem/page_table.hh"
#include "sim/process.hh"
class AlphaLiveProcess : public LiveProcess
class AlphaProcess : public Process
{
private:
void setupASNReg();
protected:
AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile);
AlphaProcess(ProcessParams *params, ObjectFile *objFile);
void loadState(CheckpointIn &cp) override;
void initState() override;
@ -51,12 +51,12 @@ class AlphaLiveProcess : public LiveProcess
public:
AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int &i) override;
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val) override;
void setSyscallReturn(ThreadContext *tc,
SyscallReturn return_value) override;
// override default implementation in LiveProcess as the mmap
// override default implementation in Process as the mmap
// region for Alpha platforms grows upward
virtual bool mmapGrowsDown() const override { return false; }
};

View File

@ -784,7 +784,8 @@ SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
callNum = tc->readIntReg(INTREG_X8);
else
callNum = tc->readIntReg(INTREG_R7);
tc->syscall(callNum);
Fault fault;
tc->syscall(callNum, &fault);
// Advance the PC since that won't happen automatically.
PCState pc = tc->pcState();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2013, 2016 ARM Limited
* Copyright (c) 2010, 2012-2013, 2016-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -566,6 +566,31 @@ class IllegalInstSetStateFault : public ArmFaultVals<IllegalInstSetStateFault>
IllegalInstSetStateFault();
};
/*
* Explicitly declare template static member variables avoid warnings in some clang versions
*/
template<> ArmFault::FaultVals ArmFaultVals<Reset>::vals;
template<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals;
template<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals;
template<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals;
template<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals;
template<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals;
template<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals;
template<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals;
template<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals;
template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals;
template<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals;
template<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals;
template<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals;
template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals;
} // namespace ArmISA
#endif // __ARM_FAULTS_HH__

View File

@ -53,7 +53,7 @@ using namespace std;
using namespace ArmISA;
static SyscallReturn
issetugidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
issetugidFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
@ -61,7 +61,7 @@ issetugidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
static SyscallReturn
sysctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
sysctlFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -1206,9 +1206,9 @@ static SyscallDesc syscallDescs64[] = {
/* 547 */ SyscallDesc("unused#547", unimplementedFunc),
};
ArmFreebsdProcess32::ArmFreebsdProcess32(LiveProcessParams * params,
ArmFreebsdProcess32::ArmFreebsdProcess32(ProcessParams * params,
ObjectFile *objFile, ObjectFile::Arch _arch)
: ArmLiveProcess32(params, objFile, _arch)
: ArmProcess32(params, objFile, _arch)
{
SyscallTable table;
@ -1218,9 +1218,9 @@ ArmFreebsdProcess32::ArmFreebsdProcess32(LiveProcessParams * params,
syscallTables.push_back(table);
}
ArmFreebsdProcess64::ArmFreebsdProcess64(LiveProcessParams * params,
ArmFreebsdProcess64::ArmFreebsdProcess64(ProcessParams * params,
ObjectFile *objFile, ObjectFile::Arch _arch)
: ArmLiveProcess64(params, objFile, _arch)
: ArmProcess64(params, objFile, _arch)
{
SyscallTable table;
@ -1269,13 +1269,13 @@ ArmFreebsdProcess64::getDesc(int callnum)
void
ArmFreebsdProcess32::initState()
{
ArmLiveProcess32::initState();
ArmProcess32::initState();
// The 32 bit equivalent of the comm page would be set up here.
}
void
ArmFreebsdProcess64::initState()
{
ArmLiveProcess64::initState();
ArmProcess64::initState();
// The 64 bit equivalent of the comm page would be set up here.
}

View File

@ -55,16 +55,16 @@ class ArmFreebsdProcessBits
};
/// A process with emulated Arm/Freebsd syscalls.
class ArmFreebsdProcess32 : public ArmLiveProcess32, public ArmFreebsdProcessBits
class ArmFreebsdProcess32 : public ArmProcess32, public ArmFreebsdProcessBits
{
public:
ArmFreebsdProcess32(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
ArmFreebsdProcess32(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
void initState();
/// Explicitly import the otherwise hidden getSyscallArg
using ArmLiveProcess::getSyscallArg;
using ArmProcess::getSyscallArg;
/// A page to hold "kernel" provided functions. The name might be wrong.
static const Addr commPage;
@ -73,11 +73,11 @@ class ArmFreebsdProcess32 : public ArmLiveProcess32, public ArmFreebsdProcessBit
};
/// A process with emulated Arm/Freebsd syscalls.
class ArmFreebsdProcess64 : public ArmLiveProcess64, public ArmFreebsdProcessBits
class ArmFreebsdProcess64 : public ArmProcess64, public ArmFreebsdProcessBits
{
public:
ArmFreebsdProcess64(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
ArmFreebsdProcess64(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
void initState();
SyscallDesc* getDesc(int callnum);

View File

@ -594,7 +594,8 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
warn_once("The ccsidr register isn't implemented and "
"always reads as 0.\n");
break;
case MISCREG_CTR:
case MISCREG_CTR: // AArch32, ARMv7, top bit set
case MISCREG_CTR_EL0: // AArch64
{
//all caches have the same line size in gem5
//4 byte words in ARM

View File

@ -50,7 +50,7 @@ let {{
_in = bits(resTemp, intWidth - 1);
_iz = ((resTemp & mask(intWidth)) == 0);
CondCodesNZ = (_in << 1) | _iz;
DPRINTF(Arm, "(in, iz) = (%%d, %%d)\\n", _in, _iz);
DPRINTF(Arm, "(in, iz) = (%d, %d)\\n", _in, _iz);
'''
if overflow and overflow != "none":
code += '''

View File

@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2013 ARM Limited
// Copyright (c) 2010-2013,2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@ -814,7 +814,9 @@ let {{
mrc14code = '''
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenMiscIndex(op1);
if (!canReadCoprocReg(miscReg, Scr, Cpsr, xc->tcBase())) {
bool can_read, undefined;
std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
if (!can_read || undefined) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
@ -836,7 +838,9 @@ let {{
mcr14code = '''
MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenMiscIndex(dest);
if (!canWriteCoprocReg(miscReg, Scr, Cpsr, xc->tcBase())) {
bool can_write, undefined;
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
if (undefined || !can_write) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
@ -861,12 +865,13 @@ let {{
xc->tcBase()->flattenMiscIndex(preFlatOp1);
bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
Hcptr, imm);
bool canRead = canReadCoprocReg(miscReg, Scr, Cpsr, xc->tcBase());
bool can_read, undefined;
std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
// if we're in non secure PL1 mode then we can trap regargless of whether
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (!canRead && !(hypTrap && !inUserMode(Cpsr) && !inSecureState(Scr, Cpsr))) {
if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) &&
!inSecureState(Scr, Cpsr)))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
@ -891,12 +896,14 @@ let {{
xc->tcBase()->flattenMiscIndex(preFlatDest);
bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr,
Hcptr, imm);
bool canWrite = canWriteCoprocReg(miscReg, Scr, Cpsr, xc->tcBase());
bool can_write, undefined;
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
// if we're in non secure PL1 mode then we can trap regargless of whether
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (!canWrite & !(hypTrap & !inUserMode(Cpsr) & !inSecureState(Scr, Cpsr))) {
if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) &&
!inSecureState(Scr, Cpsr)))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
@ -920,12 +927,13 @@ let {{
MiscRegIndex miscReg = (MiscRegIndex)
xc->tcBase()->flattenMiscIndex(preFlatOp1);
bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
bool canRead = canReadCoprocReg(miscReg, Scr, Cpsr, xc->tcBase());
bool can_read, undefined;
std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
// if we're in non secure PL1 mode then we can trap regargless of whether
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (!canRead && !(hypTrap && !inUserMode(Cpsr) && !inSecureState(Scr, Cpsr))) {
if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) &&
!inSecureState(Scr, Cpsr)))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}
@ -949,12 +957,14 @@ let {{
MiscRegIndex miscReg = (MiscRegIndex)
xc->tcBase()->flattenMiscIndex(preFlatDest);
bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
bool canWrite = canWriteCoprocReg(miscReg, Scr, Cpsr, xc->tcBase());
bool can_write, undefined;
std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
// if we're in non secure PL1 mode then we can trap regargless of whether
// the register is accessable, in other modes we trap if only if the register
// IS accessable.
if (!canWrite & !(hypTrap & !inUserMode(Cpsr) & !inSecureState(Scr, Cpsr))) {
if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) &&
!inSecureState(Scr, Cpsr)))) {
return std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
}

View File

@ -1,4 +1,4 @@
# Copyright (c) 2015 ARM Limited
# Copyright (c) 2015, 2017 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
@ -38,18 +38,8 @@
from m5.params import *
from m5.proxy import *
from Gic import BaseGic
from KvmVM import KvmVM
from System import System
from Gic import Pl390
class KvmGic(BaseGic):
type = 'KvmGic'
class MuxingKvmGic(Pl390):
type = 'MuxingKvmGic'
cxx_header = "arch/arm/kvm/gic.hh"
dist_addr = Param.Addr(0x1f001000, "Address for distributor")
cpu_addr = Param.Addr(0x1f000100, "Address for cpu")
it_lines = Param.UInt32(128, "Number of interrupt lines supported")
system = Param.System(Parent.any,
'System this interrupt controller belongs to')
kvmVM = Param.KvmVM(Parent.any, 'KVM VM (i.e., shared memory domain)')

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 ARM Limited
* Copyright (c) 2015, 2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -65,6 +65,8 @@ static_assert(NUM_QREGS == 32, "Unexpected number of aarch64 vector regs.");
#define INT_REG(name) CORE_REG(name, U64)
#define SIMD_REG(name) CORE_REG(name, U128)
#define SYS_MPIDR_EL1 ARM64_SYS_REG(0b11, 0b000, 0b0000, 0b0000, 0b101)
constexpr uint64_t
kvmXReg(const int num)
{
@ -102,7 +104,6 @@ const std::vector<ArmV8KvmCPU::IntRegInfo> ArmV8KvmCPU::intRegMap = {
};
const std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
MiscRegInfo(INT_REG(regs.pstate), MISCREG_CPSR, "PSTATE"),
MiscRegInfo(INT_REG(elr_el1), MISCREG_ELR_EL1, "ELR(EL1)"),
MiscRegInfo(INT_REG(spsr[KVM_SPSR_EL1]), MISCREG_SPSR_EL1, "SPSR(EL1)"),
MiscRegInfo(INT_REG(spsr[KVM_SPSR_ABT]), MISCREG_SPSR_ABT, "SPSR(ABT)"),
@ -113,6 +114,10 @@ const std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegMap = {
MiscRegInfo(INT_REG(fp_regs.fpcr), MISCREG_FPCR, "FPCR"),
};
const std::vector<ArmV8KvmCPU::MiscRegInfo> ArmV8KvmCPU::miscRegIdMap = {
MiscRegInfo(SYS_MPIDR_EL1, MISCREG_MPIDR_EL1, "MPIDR(EL1)"),
};
ArmV8KvmCPU::ArmV8KvmCPU(ArmV8KvmCPUParams *params)
: BaseArmKvmCPU(params)
{
@ -122,6 +127,19 @@ ArmV8KvmCPU::~ArmV8KvmCPU()
{
}
void
ArmV8KvmCPU::startup()
{
BaseArmKvmCPU::startup();
// Override ID registers that KVM should "inherit" from gem5.
for (const auto &ri : miscRegIdMap) {
const uint64_t value(tc->readMiscReg(ri.idx));
DPRINTF(KvmContext, " %s := 0x%x\n", ri.name, value);
setOneReg(ri.kvm, value);
}
}
void
ArmV8KvmCPU::dump() const
{
@ -136,9 +154,14 @@ ArmV8KvmCPU::dump() const
for (const auto &ri : intRegMap)
inform(" %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
inform(" %s: %s\n", "PSTATE", getAndFormatOneReg(INT_REG(regs.pstate)));
for (const auto &ri : miscRegMap)
inform(" %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
for (const auto &ri : miscRegIdMap)
inform(" %s: %s\n", ri.name, getAndFormatOneReg(ri.kvm));
for (const auto &reg : getRegList()) {
const uint64_t arch(reg & KVM_REG_ARCH_MASK);
if (arch != KVM_REG_ARM64) {
@ -188,6 +211,20 @@ void
ArmV8KvmCPU::updateKvmState()
{
DPRINTF(KvmContext, "In updateKvmState():\n");
// update pstate register state
CPSR cpsr(tc->readMiscReg(MISCREG_CPSR));
cpsr.nz = tc->readCCReg(CCREG_NZ);
cpsr.c = tc->readCCReg(CCREG_C);
cpsr.v = tc->readCCReg(CCREG_V);
if (cpsr.width) {
cpsr.ge = tc->readCCReg(CCREG_GE);
} else {
cpsr.ge = 0;
}
DPRINTF(KvmContext, " %s := 0x%x\n", "PSTATE", cpsr);
setOneReg(INT_REG(regs.pstate), cpsr);
for (const auto &ri : miscRegMap) {
const uint64_t value(tc->readMiscReg(ri.idx));
DPRINTF(KvmContext, " %s := 0x%x\n", ri.name, value);
@ -231,7 +268,18 @@ ArmV8KvmCPU::updateThreadContext()
{
DPRINTF(KvmContext, "In updateThreadContext():\n");
// Update core misc regs first as they (particularly PSTATE/CPSR)
// Update pstate thread context
const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
DPRINTF(KvmContext, " %s := 0x%x\n", "PSTATE", cpsr);
tc->setMiscRegNoEffect(MISCREG_CPSR, cpsr);
tc->setCCReg(CCREG_NZ, cpsr.nz);
tc->setCCReg(CCREG_C, cpsr.c);
tc->setCCReg(CCREG_V, cpsr.v);
if (cpsr.width) {
tc->setCCReg(CCREG_GE, cpsr.ge);
}
// Update core misc regs first as they
// affect how other registers are mapped.
for (const auto &ri : miscRegMap) {
const auto value(getOneRegU64(ri.kvm));
@ -242,7 +290,13 @@ ArmV8KvmCPU::updateThreadContext()
for (int i = 0; i < NUM_XREGS; ++i) {
const auto value(getOneRegU64(kvmXReg(i)));
DPRINTF(KvmContext, " X%i := 0x%x\n", i, value);
tc->setIntReg(INTREG_X0 + i, value);
// KVM64 returns registers in 64-bit layout. If we are in aarch32
// mode, we need to map these to banked ARM32 registers.
if (inAArch64(tc)) {
tc->setIntReg(INTREG_X0 + i, value);
} else {
tc->setIntRegFlat(IntReg64Map[INTREG_X0 + i], value);
}
}
for (const auto &ri : intRegMap) {
@ -266,7 +320,6 @@ ArmV8KvmCPU::updateThreadContext()
tc->setMiscRegNoEffect(ri.idx, value);
}
const CPSR cpsr(tc->readMiscRegNoEffect(MISCREG_CPSR));
PCState pc(getOneRegU64(INT_REG(regs.pc)));
pc.aarch64(inAArch64(tc));
pc.thumb(cpsr.t);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 ARM Limited
* Copyright (c) 2015, 2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -83,6 +83,8 @@ class ArmV8KvmCPU : public BaseArmKvmCPU
ArmV8KvmCPU(ArmV8KvmCPUParams *params);
virtual ~ArmV8KvmCPU();
void startup() override;
void dump() const override;
protected:
@ -132,6 +134,8 @@ class ArmV8KvmCPU : public BaseArmKvmCPU
static const std::vector<ArmV8KvmCPU::IntRegInfo> intRegMap;
/** Mapping between gem5 misc registers registers and registers in kvm */
static const std::vector<ArmV8KvmCPU::MiscRegInfo> miscRegMap;
/** Mapping between gem5 ID misc registers registers and registers in kvm */
static const std::vector<ArmV8KvmCPU::MiscRegInfo> miscRegIdMap;
/** Cached mapping between system registers in kvm and misc regs in gem5 */
mutable std::vector<ArmV8KvmCPU::MiscRegInfo> sysRegMap;

View File

@ -79,6 +79,9 @@ BaseArmKvmCPU::startup()
memset(&target_config, 0, sizeof(target_config));
vm.kvmArmPreferredTarget(target_config);
if (!((ArmSystem *)system)->highestELIs64()) {
target_config.features[0] |= (1 << KVM_ARM_VCPU_EL1_32BIT);
}
kvmArmVCpuInit(target_config);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2016 ARM Limited
* Copyright (c) 2015-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -35,14 +35,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Sandberg
* Curtis Dunham
*/
#include "arch/arm/kvm/gic.hh"
#include <linux/kvm.h>
#include "arch/arm/kvm/base_cpu.hh"
#include "debug/GIC.hh"
#include "debug/Interrupt.hh"
#include "params/KvmGic.hh"
#include "params/MuxingKvmGic.hh"
KvmKernelGicV2::KvmKernelGicV2(KvmVM &_vm, Addr cpu_addr, Addr dist_addr,
unsigned it_lines)
@ -102,83 +105,350 @@ KvmKernelGicV2::setIntState(unsigned type, unsigned vcpu, unsigned irq,
vm.setIRQLine(line, high);
}
uint32_t
KvmKernelGicV2::getGicReg(unsigned group, unsigned vcpu, unsigned offset)
{
uint64_t reg;
KvmGic::KvmGic(const KvmGicParams *p)
: BaseGic(p),
assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
const uint32_t attr(
(vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
(offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
kdev.getAttrPtr(group, attr, &reg);
return (uint32_t) reg;
}
void
KvmKernelGicV2::setGicReg(unsigned group, unsigned vcpu, unsigned offset,
unsigned value)
{
uint64_t reg = value;
assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
const uint32_t attr(
(vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) |
(offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT));
kdev.setAttrPtr(group, attr, &reg);
}
uint32_t
KvmKernelGicV2::readDistributor(ContextID ctx, Addr daddr)
{
auto vcpu = vm.contextIdToVCpuId(ctx);
return getGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr);
}
uint32_t
KvmKernelGicV2::readCpu(ContextID ctx, Addr daddr)
{
auto vcpu = vm.contextIdToVCpuId(ctx);
return getGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr);
}
void
KvmKernelGicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data)
{
auto vcpu = vm.contextIdToVCpuId(ctx);
setGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr, data);
}
void
KvmKernelGicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
{
auto vcpu = vm.contextIdToVCpuId(ctx);
setGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr, data);
}
MuxingKvmGic::MuxingKvmGic(const MuxingKvmGicParams *p)
: Pl390(p),
system(*p->system),
kernelGic(*p->kvmVM, p->cpu_addr, p->dist_addr, p->it_lines),
addrRanges{kernelGic.distRange, kernelGic.cpuRange}
kernelGic(nullptr),
usingKvm(false)
{
}
KvmGic::~KvmGic()
{
}
void
KvmGic::serialize(CheckpointOut &cp) const
{
panic("Checkpointing unsupported\n");
}
void
KvmGic::unserialize(CheckpointIn &cp)
{
panic("Checkpointing unsupported\n");
}
Tick
KvmGic::read(PacketPtr pkt)
{
panic("KvmGic: PIO from gem5 is currently unsupported\n");
}
Tick
KvmGic::write(PacketPtr pkt)
{
panic("KvmGic: PIO from gem5 is currently unsupported\n");
}
void
KvmGic::sendInt(uint32_t num)
{
DPRINTF(Interrupt, "Set SPI %d\n", num);
kernelGic.setSPI(num);
}
void
KvmGic::clearInt(uint32_t num)
{
DPRINTF(Interrupt, "Clear SPI %d\n", num);
kernelGic.clearSPI(num);
}
void
KvmGic::sendPPInt(uint32_t num, uint32_t cpu)
{
DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num);
kernelGic.setPPI(cpu, num);
}
void
KvmGic::clearPPInt(uint32_t num, uint32_t cpu)
{
DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num);
kernelGic.clearPPI(cpu, num);
}
void
KvmGic::verifyMemoryMode() const
{
if (!(system.isAtomicMode() && system.bypassCaches())) {
fatal("The in-kernel KVM GIC can only be used with KVM CPUs, but the "
"current memory mode does not support KVM.\n");
if (auto vm = system.getKvmVM()) {
kernelGic = new KvmKernelGicV2(*vm, p->cpu_addr, p->dist_addr,
p->it_lines);
}
}
KvmGic *
KvmGicParams::create()
MuxingKvmGic::~MuxingKvmGic()
{
return new KvmGic(this);
}
void
MuxingKvmGic::loadState(CheckpointIn &cp)
{
Pl390::loadState(cp);
}
void
MuxingKvmGic::startup()
{
Pl390::startup();
usingKvm = (kernelGic != nullptr) && validKvmEnvironment();
if (usingKvm)
fromPl390ToKvm();
}
DrainState
MuxingKvmGic::drain()
{
if (usingKvm)
fromKvmToPl390();
return Pl390::drain();
}
void
MuxingKvmGic::drainResume()
{
Pl390::drainResume();
bool use_kvm = (kernelGic != nullptr) && validKvmEnvironment();
if (use_kvm != usingKvm) {
// Should only occur due to CPU switches
if (use_kvm) // from simulation to KVM emulation
fromPl390ToKvm();
// otherwise, drain() already sync'd the state back to the Pl390
usingKvm = use_kvm;
}
}
void
MuxingKvmGic::serialize(CheckpointOut &cp) const
{
// drain() already ensured Pl390 updated with KvmGic state if necessary
Pl390::serialize(cp);
}
void
MuxingKvmGic::unserialize(CheckpointIn &cp)
{
Pl390::unserialize(cp);
}
Tick
MuxingKvmGic::read(PacketPtr pkt)
{
if (!usingKvm)
return Pl390::read(pkt);
panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n");
}
Tick
MuxingKvmGic::write(PacketPtr pkt)
{
if (!usingKvm)
return Pl390::write(pkt);
panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n");
}
void
MuxingKvmGic::sendInt(uint32_t num)
{
if (!usingKvm)
return Pl390::sendInt(num);
DPRINTF(Interrupt, "Set SPI %d\n", num);
kernelGic->setSPI(num);
}
void
MuxingKvmGic::clearInt(uint32_t num)
{
if (!usingKvm)
return Pl390::clearInt(num);
DPRINTF(Interrupt, "Clear SPI %d\n", num);
kernelGic->clearSPI(num);
}
void
MuxingKvmGic::sendPPInt(uint32_t num, uint32_t cpu)
{
if (!usingKvm)
return Pl390::sendPPInt(num, cpu);
DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num);
kernelGic->setPPI(cpu, num);
}
void
MuxingKvmGic::clearPPInt(uint32_t num, uint32_t cpu)
{
if (!usingKvm)
return Pl390::clearPPInt(num, cpu);
DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num);
kernelGic->clearPPI(cpu, num);
}
bool
MuxingKvmGic::validKvmEnvironment() const
{
if (system.threadContexts.empty())
return false;
for (auto tc : system.threadContexts) {
if (dynamic_cast<BaseArmKvmCPU*>(tc->getCpuPtr()) == nullptr) {
return false;
}
}
return true;
}
void
MuxingKvmGic::copyDistRegister(BaseGicRegisters* from, BaseGicRegisters* to,
ContextID ctx, Addr daddr)
{
auto val = from->readDistributor(ctx, daddr);
DPRINTF(GIC, "copy dist 0x%x 0x%08x\n", daddr, val);
to->writeDistributor(ctx, daddr, val);
}
void
MuxingKvmGic::copyCpuRegister(BaseGicRegisters* from, BaseGicRegisters* to,
ContextID ctx, Addr daddr)
{
auto val = from->readCpu(ctx, daddr);
DPRINTF(GIC, "copy cpu 0x%x 0x%08x\n", daddr, val);
to->writeCpu(ctx, daddr, val);
}
void
MuxingKvmGic::copyBankedDistRange(BaseGicRegisters* from, BaseGicRegisters* to,
Addr daddr, size_t size)
{
for (int ctx = 0; ctx < system._numContexts; ++ctx)
for (auto a = daddr; a < daddr + size; a += 4)
copyDistRegister(from, to, ctx, a);
}
void
MuxingKvmGic::clearBankedDistRange(BaseGicRegisters* to,
Addr daddr, size_t size)
{
for (int ctx = 0; ctx < system._numContexts; ++ctx)
for (auto a = daddr; a < daddr + size; a += 4)
to->writeDistributor(ctx, a, 0xFFFFFFFF);
}
void
MuxingKvmGic::copyDistRange(BaseGicRegisters* from, BaseGicRegisters* to,
Addr daddr, size_t size)
{
for (auto a = daddr; a < daddr + size; a += 4)
copyDistRegister(from, to, 0, a);
}
void
MuxingKvmGic::clearDistRange(BaseGicRegisters* to,
Addr daddr, size_t size)
{
for (auto a = daddr; a < daddr + size; a += 4)
to->writeDistributor(0, a, 0xFFFFFFFF);
}
void
MuxingKvmGic::copyGicState(BaseGicRegisters* from, BaseGicRegisters* to)
{
Addr set, clear;
size_t size;
/// CPU state (GICC_*)
// Copy CPU Interface Control Register (CTLR),
// Interrupt Priority Mask Register (PMR), and
// Binary Point Register (BPR)
for (int ctx = 0; ctx < system._numContexts; ++ctx) {
copyCpuRegister(from, to, ctx, GICC_CTLR);
copyCpuRegister(from, to, ctx, GICC_PMR);
copyCpuRegister(from, to, ctx, GICC_BPR);
}
/// Distributor state (GICD_*)
// Copy Distributor Control Register (CTLR)
copyDistRegister(from, to, 0, GICD_CTLR);
// Copy interrupt-enabled statuses (I[CS]ENABLERn; R0 is per-CPU banked)
set = Pl390::GICD_ISENABLER.start();
clear = Pl390::GICD_ICENABLER.start();
size = Pl390::itLines / 8;
clearBankedDistRange(to, clear, 4);
copyBankedDistRange(from, to, set, 4);
set += 4, clear += 4, size -= 4;
clearDistRange(to, clear, size);
copyDistRange(from, to, set, size);
// Copy pending interrupts (I[CS]PENDRn; R0 is per-CPU banked)
set = Pl390::GICD_ISPENDR.start();
clear = Pl390::GICD_ICPENDR.start();
size = Pl390::itLines / 8;
clearBankedDistRange(to, clear, 4);
copyBankedDistRange(from, to, set, 4);
set += 4, clear += 4, size -= 4;
clearDistRange(to, clear, size);
copyDistRange(from, to, set, size);
// Copy active interrupts (I[CS]ACTIVERn; R0 is per-CPU banked)
set = Pl390::GICD_ISACTIVER.start();
clear = Pl390::GICD_ICACTIVER.start();
size = Pl390::itLines / 8;
clearBankedDistRange(to, clear, 4);
copyBankedDistRange(from, to, set, 4);
set += 4, clear += 4, size -= 4;
clearDistRange(to, clear, size);
copyDistRange(from, to, set, size);
// Copy interrupt priorities (IPRIORITYRn; R0-7 are per-CPU banked)
set = Pl390::GICD_IPRIORITYR.start();
copyBankedDistRange(from, to, set, 32);
set += 32;
size = Pl390::itLines - 32;
copyDistRange(from, to, set, size);
// Copy interrupt processor target regs (ITARGETRn; R0-7 are read-only)
set = Pl390::GICD_ITARGETSR.start() + 32;
size = Pl390::itLines - 32;
copyDistRange(from, to, set, size);
// Copy interrupt configuration registers (ICFGRn)
set = Pl390::GICD_ICFGR.start();
size = Pl390::itLines / 4;
copyDistRange(from, to, set, size);
}
void
MuxingKvmGic::fromPl390ToKvm()
{
copyGicState(static_cast<Pl390*>(this), kernelGic);
}
void
MuxingKvmGic::fromKvmToPl390()
{
copyGicState(kernelGic, static_cast<Pl390*>(this));
// the values read for the Interrupt Priority Mask Register (PMR)
// have been shifted by three bits due to its having been emulated by
// a VGIC with only 5 PMR bits in its VMCR register. Presently the
// Linux kernel does not repair this inaccuracy, so we correct it here.
for (int cpu = 0; cpu < system._numContexts; ++cpu) {
cpuPriority[cpu] <<= 3;
assert((cpuPriority[cpu] & ~0xff) == 0);
}
}
MuxingKvmGic *
MuxingKvmGicParams::create()
{
return new MuxingKvmGic(this);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2016 ARM Limited
* Copyright (c) 2015-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -35,6 +35,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Sandberg
* Curtis Dunham
*/
#ifndef __ARCH_ARM_KVM_GIC_HH__
@ -43,7 +44,7 @@
#include "arch/arm/system.hh"
#include "cpu/kvm/device.hh"
#include "cpu/kvm/vm.hh"
#include "dev/arm/base_gic.hh"
#include "dev/arm/gic_pl390.hh"
#include "dev/platform.hh"
/**
@ -53,7 +54,7 @@
* model. It exposes an API that is similar to that of
* software-emulated GIC models in gem5.
*/
class KvmKernelGicV2
class KvmKernelGicV2 : public BaseGicRegisters
{
public:
/**
@ -65,7 +66,7 @@ class KvmKernelGicV2
* @param vm KVM VM representing this system
* @param cpu_addr GIC CPU interface base address
* @param dist_addr GIC distributor base address
* @param it_liens Number of interrupt lines to support
* @param it_lines Number of interrupt lines to support
*/
KvmKernelGicV2(KvmVM &vm, Addr cpu_addr, Addr dist_addr,
unsigned it_lines);
@ -116,6 +117,14 @@ class KvmKernelGicV2
/** Address range for the distributor interface */
const AddrRange distRange;
/** BaseGicRegisters interface */
uint32_t readDistributor(ContextID ctx, Addr daddr) override;
uint32_t readCpu(ContextID ctx, Addr daddr) override;
void writeDistributor(ContextID ctx, Addr daddr,
uint32_t data) override;
void writeCpu(ContextID ctx, Addr daddr, uint32_t data) override;
/* @} */
protected:
@ -129,6 +138,26 @@ class KvmKernelGicV2
*/
void setIntState(unsigned type, unsigned vcpu, unsigned irq, bool high);
/**
* Get value of GIC register "from" a cpu
*
* @param group Distributor or CPU (KVM_DEV_ARM_VGIC_GRP_{DIST,CPU}_REGS)
* @param vcpu CPU id within KVM
* @param offset register offset
*/
uint32_t getGicReg(unsigned group, unsigned vcpu, unsigned offset);
/**
* Set value of GIC register "from" a cpu
*
* @param group Distributor or CPU (KVM_DEV_ARM_VGIC_GRP_{DIST,CPU}_REGS)
* @param vcpu CPU id within KVM
* @param offset register offset
* @param value value to set register to
*/
void setGicReg(unsigned group, unsigned vcpu, unsigned offset,
unsigned value);
/** KVM VM in the parent system */
KvmVM &vm;
@ -136,48 +165,29 @@ class KvmKernelGicV2
KvmDevice kdev;
};
struct KvmGicParams;
/**
* In-kernel GIC model.
*
* When using a KVM-based CPU model, it is possible to offload GIC
* emulation to the kernel. This reduces some overheads when the guest
* accesses the GIC and makes it possible to use in-kernel
* architected/generic timer emulation.
*
* This device uses interfaces with the kernel GicV2 model that is
* documented in Documentation/virtual/kvm/devices/arm-vgic.txt in the
* Linux kernel sources.
*
* This GIC model has the following known limitations:
* <ul>
* <li>Checkpointing is not supported.
* <li>This model only works with kvm. Simulated CPUs are not
* supported since this would require the kernel to inject
* interrupt into the simulated CPU.
* </ul>
*
* @warn This GIC model cannot be used with simulated CPUs!
*/
class KvmGic : public BaseGic
struct MuxingKvmGicParams;
class MuxingKvmGic : public Pl390
{
public: // SimObject / Serializable / Drainable
KvmGic(const KvmGicParams *p);
~KvmGic();
MuxingKvmGic(const MuxingKvmGicParams *p);
~MuxingKvmGic();
void startup() override { verifyMemoryMode(); }
void drainResume() override { verifyMemoryMode(); }
void loadState(CheckpointIn &cp) override;
void startup() override;
DrainState drain() override;
void drainResume() override;
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
public: // PioDevice
AddrRangeList getAddrRanges() const { return addrRanges; }
Tick read(PacketPtr pkt) override;
Tick write(PacketPtr pkt) override;
public: // BaseGic
public: // Pl390
void sendInt(uint32_t num) override;
void clearInt(uint32_t num) override;
@ -185,24 +195,37 @@ class KvmGic : public BaseGic
void clearPPInt(uint32_t num, uint32_t cpu) override;
protected:
/**
* Do memory mode sanity checks
*
* This method only really exists to warn users that try to switch
* to a simulate CPU. There is no fool proof method to detect
* simulated CPUs, but checking that we're in atomic mode and
* bypassing caches should be robust enough.
*/
void verifyMemoryMode() const;
/** Verify gem5 configuration will support KVM emulation */
bool validKvmEnvironment() const;
/** System this interrupt controller belongs to */
System &system;
/** Kernel GIC device */
KvmKernelGicV2 kernelGic;
KvmKernelGicV2 *kernelGic;
/** Union of all memory */
const AddrRangeList addrRanges;
private:
bool usingKvm;
/** Multiplexing implementation */
void fromPl390ToKvm();
void fromKvmToPl390();
void copyGicState(BaseGicRegisters* from, BaseGicRegisters* to);
void copyDistRegister(BaseGicRegisters* from, BaseGicRegisters* to,
ContextID ctx, Addr daddr);
void copyCpuRegister(BaseGicRegisters* from, BaseGicRegisters* to,
ContextID ctx, Addr daddr);
void copyBankedDistRange(BaseGicRegisters* from, BaseGicRegisters* to,
Addr daddr, size_t size);
void clearBankedDistRange(BaseGicRegisters* to,
Addr daddr, size_t size);
void copyDistRange(BaseGicRegisters* from, BaseGicRegisters* to,
Addr daddr, size_t size);
void clearDistRange(BaseGicRegisters* to,
Addr daddr, size_t size);
};
#endif // __ARCH_ARM_KVM_GIC_HH__

View File

@ -61,7 +61,7 @@ using namespace ArmISA;
/// Target uname() handler.
static SyscallReturn
unameFunc32(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc32(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -79,7 +79,7 @@ unameFunc32(SyscallDesc *desc, int callnum, LiveProcess *process,
/// Target uname() handler.
static SyscallReturn
unameFunc64(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc64(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -97,7 +97,7 @@ unameFunc64(SyscallDesc *desc, int callnum, LiveProcess *process,
/// Target set_tls() handler.
static SyscallReturn
setTLSFunc32(SyscallDesc *desc, int callnum, LiveProcess *process,
setTLSFunc32(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -110,7 +110,7 @@ setTLSFunc32(SyscallDesc *desc, int callnum, LiveProcess *process,
}
static SyscallReturn
setTLSFunc64(SyscallDesc *desc, int callnum, LiveProcess *process,
setTLSFunc64(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -241,7 +241,7 @@ static SyscallDesc syscallDescs32[] = {
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
/* 120 */ SyscallDesc("clone", cloneFunc),
/* 120 */ SyscallDesc("clone", cloneFunc<ArmLinux32>),
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
/* 122 */ SyscallDesc("uname", unameFunc32),
/* 123 */ SyscallDesc("unused#123", unimplementedFunc),
@ -1589,9 +1589,9 @@ static SyscallDesc privSyscallDescs64[] = {
/* 5 */ SyscallDesc("set_tls", setTLSFunc64)
};
ArmLinuxProcess32::ArmLinuxProcess32(LiveProcessParams * params,
ArmLinuxProcess32::ArmLinuxProcess32(ProcessParams * params,
ObjectFile *objFile, ObjectFile::Arch _arch)
: ArmLiveProcess32(params, objFile, _arch)
: ArmProcess32(params, objFile, _arch)
{
SyscallTable table;
@ -1608,9 +1608,9 @@ ArmLinuxProcess32::ArmLinuxProcess32(LiveProcessParams * params,
syscallTables.push_back(table);
}
ArmLinuxProcess64::ArmLinuxProcess64(LiveProcessParams * params,
ArmLinuxProcess64::ArmLinuxProcess64(ProcessParams * params,
ObjectFile *objFile, ObjectFile::Arch _arch)
: ArmLiveProcess64(params, objFile, _arch)
: ArmProcess64(params, objFile, _arch)
{
SyscallTable table;
@ -1667,7 +1667,7 @@ ArmLinuxProcess64::getDesc(int callnum)
void
ArmLinuxProcess32::initState()
{
ArmLiveProcess32::initState();
ArmProcess32::initState();
allocateMem(commPage, PageBytes);
ThreadContext *tc = system->getThreadContext(contextIds[0]);
@ -1714,6 +1714,6 @@ ArmLinuxProcess32::initState()
void
ArmLinuxProcess64::initState()
{
ArmLiveProcess64::initState();
ArmProcess64::initState();
// The 64 bit equivalent of the comm page would be set up here.
}

View File

@ -65,16 +65,16 @@ class ArmLinuxProcessBits
};
/// A process with emulated Arm/Linux syscalls.
class ArmLinuxProcess32 : public ArmLiveProcess32, public ArmLinuxProcessBits
class ArmLinuxProcess32 : public ArmProcess32, public ArmLinuxProcessBits
{
public:
ArmLinuxProcess32(LiveProcessParams * params, ObjectFile *objFile,
ArmLinuxProcess32(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
void initState();
/// Explicitly import the otherwise hidden getSyscallArg
using ArmLiveProcess::getSyscallArg;
using ArmProcess::getSyscallArg;
/// A page to hold "kernel" provided functions. The name might be wrong.
static const Addr commPage;
@ -83,10 +83,10 @@ class ArmLinuxProcess32 : public ArmLiveProcess32, public ArmLinuxProcessBits
};
/// A process with emulated Arm/Linux syscalls.
class ArmLinuxProcess64 : public ArmLiveProcess64, public ArmLinuxProcessBits
class ArmLinuxProcess64 : public ArmProcess64, public ArmLinuxProcessBits
{
public:
ArmLinuxProcess64(LiveProcessParams * params, ObjectFile *objFile,
ArmLinuxProcess64(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
void initState();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013, 2015-2016 ARM Limited
* Copyright (c) 2010-2013, 2015-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -41,6 +41,8 @@
#include "arch/arm/miscregs.hh"
#include <tuple>
#include "arch/arm/isa.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
@ -1967,11 +1969,12 @@ decodeCP15Reg64(unsigned crm, unsigned opc1)
return MISCREG_CP15_UNIMPL;
}
bool
canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr, ThreadContext *tc)
std::tuple<bool, bool>
canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr)
{
bool secure = !scr.ns;
bool canRead;
bool canRead = false;
bool undefined = false;
switch (cpsr.mode) {
case MODE_USER:
@ -1995,18 +1998,19 @@ canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr, ThreadContext *tc)
canRead = miscRegInfo[reg][MISCREG_HYP_RD];
break;
default:
panic("Unrecognized mode setting in CPSR.\n");
undefined = true;
}
// can't do permissions checkes on the root of a banked pair of regs
assert(!miscRegInfo[reg][MISCREG_BANKED]);
return canRead;
return std::make_tuple(canRead, undefined);
}
bool
canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr, ThreadContext *tc)
std::tuple<bool, bool>
canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr)
{
bool secure = !scr.ns;
bool canWrite;
bool canWrite = false;
bool undefined = false;
switch (cpsr.mode) {
case MODE_USER:
@ -2030,11 +2034,11 @@ canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr, ThreadContext *tc)
canWrite = miscRegInfo[reg][MISCREG_HYP_WR];
break;
default:
panic("Unrecognized mode setting in CPSR.\n");
undefined = true;
}
// can't do permissions checkes on the root of a banked pair of regs
assert(!miscRegInfo[reg][MISCREG_BANKED]);
return canWrite;
return std::make_tuple(canWrite, undefined);
}
int

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2016 ARM Limited
* Copyright (c) 2010-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -44,6 +44,7 @@
#define __ARCH_ARM_MISCREGS_HH__
#include <bitset>
#include <tuple>
#include "base/bitunion.hh"
#include "base/compiler.hh"
@ -1847,13 +1848,37 @@ namespace ArmISA
EndBitUnion(CPTR)
// Checks read access permissions to coproc. registers
bool canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr,
ThreadContext *tc);
/**
* Check for permission to read coprocessor registers.
*
* Checks whether an instruction at the current program mode has
* permissions to read the coprocessor registers. This function
* returns whether the check is undefined and if not whether the
* read access is permitted.
*
* @param the misc reg indicating the coprocessor
* @param the SCR
* @param the CPSR
* @return a tuple of booleans: can_read, undefined
*/
std::tuple<bool, bool> canReadCoprocReg(MiscRegIndex reg, SCR scr,
CPSR cpsr);
// Checks write access permissions to coproc. registers
bool canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr,
ThreadContext *tc);
/**
* Check for permission to write coprocessor registers.
*
* Checks whether an instruction at the current program mode has
* permissions to write the coprocessor registers. This function
* returns whether the check is undefined and if not whether the
* write access is permitted.
*
* @param the misc reg indicating the coprocessor
* @param the SCR
* @param the CPSR
* @return a tuple of booleans: can_write, undefined
*/
std::tuple<bool, bool> canWriteCoprocReg(MiscRegIndex reg, SCR scr,
CPSR cpsr);
// Checks read access permissions to AArch64 system registers
bool canReadAArch64SysReg(MiscRegIndex reg, SCR scr, CPSR cpsr,

View File

@ -51,6 +51,7 @@
#include "cpu/thread_context.hh"
#include "debug/Stack.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/byteswap.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
@ -59,50 +60,46 @@
using namespace std;
using namespace ArmISA;
ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile,
ObjectFile::Arch _arch)
: LiveProcess(params, objFile), arch(_arch)
ArmProcess::ArmProcess(ProcessParams *params, ObjectFile *objFile,
ObjectFile::Arch _arch)
: Process(params, objFile), arch(_arch)
{
}
ArmLiveProcess32::ArmLiveProcess32(LiveProcessParams *params,
ObjectFile *objFile, ObjectFile::Arch _arch)
: ArmLiveProcess(params, objFile, _arch)
ArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile,
ObjectFile::Arch _arch)
: ArmProcess(params, objFile, _arch)
{
stack_base = 0xbf000000L;
Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() +
objFile->bssSize(), PageBytes);
Addr stack_base = 0xbf000000L;
Addr max_stack_size = 8 * 1024 * 1024;
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0x40000000L;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
// Set up region for mmaps. For now, start at bottom of kuseg space.
mmap_end = 0x40000000L;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
ArmLiveProcess64::ArmLiveProcess64(LiveProcessParams *params,
ObjectFile *objFile, ObjectFile::Arch _arch)
: ArmLiveProcess(params, objFile, _arch)
ArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile,
ObjectFile::Arch _arch)
: ArmProcess(params, objFile, _arch)
{
stack_base = 0x7fffff0000L;
Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() +
objFile->bssSize(), PageBytes);
Addr stack_base = 0x7fffff0000L;
Addr max_stack_size = 8 * 1024 * 1024;
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0x4000000000L;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
// Set up region for mmaps. For now, start at bottom of kuseg space.
mmap_end = 0x4000000000L;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
void
ArmLiveProcess32::initState()
ArmProcess32::initState()
{
LiveProcess::initState();
Process::initState();
argsInit<uint32_t>(PageBytes, INTREG_SP);
for (int i = 0; i < contextIds.size(); i++) {
ThreadContext * tc = system->getThreadContext(contextIds[i]);
@ -119,9 +116,9 @@ ArmLiveProcess32::initState()
}
void
ArmLiveProcess64::initState()
ArmProcess64::initState()
{
LiveProcess::initState();
Process::initState();
argsInit<uint64_t>(PageBytes, INTREG_SP0);
for (int i = 0; i < contextIds.size(); i++) {
ThreadContext * tc = system->getThreadContext(contextIds[i]);
@ -142,7 +139,7 @@ ArmLiveProcess64::initState()
template <class IntType>
void
ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
{
int intSize = sizeof(IntType);
@ -299,15 +296,16 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
int space_needed = frame_size + aux_padding;
stack_min = stack_base - space_needed;
stack_min = roundDown(stack_min, align);
stack_size = stack_base - stack_min;
memState->setStackMin(memState->getStackBase() - space_needed);
memState->setStackMin(roundDown(memState->getStackMin(), align));
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// map memory
allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize));
allocateMem(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents
IntType sentry_base = stack_base - sentry_size;
IntType sentry_base = memState->getStackBase() - sentry_size;
IntType aux_data_base = sentry_base - aux_data_size;
IntType env_data_base = aux_data_base - env_data_size;
IntType arg_data_base = env_data_base - arg_data_size;
@ -328,7 +326,7 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
DPRINTF(Stack, "0x%x - envp array\n", envp_array_base);
DPRINTF(Stack, "0x%x - argv array\n", argv_array_base);
DPRINTF(Stack, "0x%x - argc \n", argc_base);
DPRINTF(Stack, "0x%x - stack min\n", stack_min);
DPRINTF(Stack, "0x%x - stack min\n", memState->getStackMin());
// write contents to stack
@ -374,7 +372,7 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
ThreadContext *tc = system->getThreadContext(contextIds[0]);
//Set the stack pointer register
tc->setIntReg(spIndex, stack_min);
tc->setIntReg(spIndex, memState->getStackMin());
//A pointer to a function to run when the program exits. We'll set this
//to zero explicitly to make sure this isn't used.
tc->setIntReg(ArgumentReg0, 0);
@ -400,26 +398,26 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
pc.set(getStartPC() & ~mask(1));
tc->pcState(pc);
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
//Align the "stackMin" to a page boundary.
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
}
ArmISA::IntReg
ArmLiveProcess32::getSyscallArg(ThreadContext *tc, int &i)
ArmProcess32::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return tc->readIntReg(ArgumentReg0 + i++);
}
ArmISA::IntReg
ArmLiveProcess64::getSyscallArg(ThreadContext *tc, int &i)
ArmProcess64::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 8);
return tc->readIntReg(ArgumentReg0 + i++);
}
ArmISA::IntReg
ArmLiveProcess32::getSyscallArg(ThreadContext *tc, int &i, int width)
ArmProcess32::getSyscallArg(ThreadContext *tc, int &i, int width)
{
assert(width == 32 || width == 64);
if (width == 32)
@ -438,29 +436,28 @@ ArmLiveProcess32::getSyscallArg(ThreadContext *tc, int &i, int width)
}
ArmISA::IntReg
ArmLiveProcess64::getSyscallArg(ThreadContext *tc, int &i, int width)
ArmProcess64::getSyscallArg(ThreadContext *tc, int &i, int width)
{
return getSyscallArg(tc, i);
}
void
ArmLiveProcess32::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val)
ArmProcess32::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val)
{
assert(i < 6);
tc->setIntReg(ArgumentReg0 + i, val);
}
void
ArmLiveProcess64::setSyscallArg(ThreadContext *tc,
int i, ArmISA::IntReg val)
ArmProcess64::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val)
{
assert(i < 8);
tc->setIntReg(ArgumentReg0 + i, val);
}
void
ArmLiveProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
ArmProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
if (objFile->getOpSys() == ObjectFile::FreeBSD) {
@ -477,7 +474,7 @@ ArmLiveProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
}
void
ArmLiveProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
ArmProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
if (objFile->getOpSys() == ObjectFile::FreeBSD) {

View File

@ -51,25 +51,23 @@
#include "mem/page_table.hh"
#include "sim/process.hh"
class LiveProcess;
class ObjectFile;
class System;
class ArmLiveProcess : public LiveProcess
class ArmProcess : public Process
{
protected:
ObjectFile::Arch arch;
ArmLiveProcess(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
ArmProcess(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
template<class IntType>
void argsInit(int pageSize, ArmISA::IntRegIndex spIndex);
};
class ArmLiveProcess32 : public ArmLiveProcess
class ArmProcess32 : public ArmProcess
{
protected:
ArmLiveProcess32(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
ArmProcess32(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
void initState();
@ -81,11 +79,11 @@ class ArmLiveProcess32 : public ArmLiveProcess
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};
class ArmLiveProcess64 : public ArmLiveProcess
class ArmProcess64 : public ArmProcess
{
protected:
ArmLiveProcess64(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
ArmProcess64(ProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
void initState();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012-2016 ARM Limited
* Copyright (c) 2010, 2012-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -1342,7 +1342,10 @@ TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
attr_hi == 2 ? 2 : 1;
te.innerAttrs = attr_lo == 1 ? 0 :
attr_lo == 2 ? 6 : 5;
te.nonCacheable = (attr_hi == 1) || (attr_lo == 1);
// Treat write-through memory as uncacheable, this is safe
// but for performance reasons not optimal.
te.nonCacheable = (attr_hi == 1) || (attr_hi == 2) ||
(attr_lo == 1) || (attr_lo == 2);
}
} else {
uint8_t attrIndx = lDescriptor.attrIndx();
@ -1377,9 +1380,25 @@ TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
// Cacheability
te.nonCacheable = false;
if (te.mtype == TlbEntry::MemoryType::Device || // Device memory
attr_hi == 0x8 || // Normal memory, Outer Non-cacheable
attr_lo == 0x8) { // Normal memory, Inner Non-cacheable
if (te.mtype == TlbEntry::MemoryType::Device) { // Device memory
te.nonCacheable = true;
}
// Treat write-through memory as uncacheable, this is safe
// but for performance reasons not optimal.
switch (attr_hi) {
case 0x1 ... 0x3: // Normal Memory, Outer Write-through transient
case 0x4: // Normal memory, Outer Non-cacheable
case 0x8 ... 0xb: // Normal Memory, Outer Write-through non-transient
te.nonCacheable = true;
}
switch (attr_lo) {
case 0x1 ... 0x3: // Normal Memory, Inner Write-through transient
case 0x9 ... 0xb: // Normal Memory, Inner Write-through non-transient
warn_if(!attr_hi, "Unpredictable behavior");
case 0x4: // Device-nGnRE memory or
// Normal memory, Inner Non-cacheable
case 0x8: // Device-nGRE memory or
// Normal memory, Inner Write-through non-transient
te.nonCacheable = true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013, 2016 ARM Limited
* Copyright (c) 2010-2013, 2016-2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -642,12 +642,15 @@ TLB::checkPermissions(TlbEntry *te, RequestPtr req, Mode mode)
DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x"
" domain: %#x write:%d\n", dacr,
static_cast<uint8_t>(te->domain), is_write);
if (is_fetch)
if (is_fetch) {
// Use PC value instead of vaddr because vaddr might
// be aligned to cache line and should not be the
// address reported in FAR
return std::make_shared<PrefetchAbort>(
vaddr,
req->getPC(),
ArmFault::DomainLL + te->lookupLevel,
isStage2, tranMethod);
else
} else
return std::make_shared<DataAbort>(
vaddr, te->domain, is_write,
ArmFault::DomainLL + te->lookupLevel,
@ -735,8 +738,10 @@ TLB::checkPermissions(TlbEntry *te, RequestPtr req, Mode mode)
DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d "
"priv:%d write:%d ns:%d sif:%d sctlr.afe: %d \n",
ap, is_priv, is_write, te->ns, scr.sif,sctlr.afe);
// Use PC value instead of vaddr because vaddr might be aligned to
// cache line and should not be the address reported in FAR
return std::make_shared<PrefetchAbort>(
vaddr,
req->getPC(),
ArmFault::PermissionLL + te->lookupLevel,
isStage2, tranMethod);
} else if (abt | hapAbt) {

View File

@ -43,7 +43,9 @@
#ifndef __ARCH_GENERIC_MEMHELPERS_HH__
#define __ARCH_GENERIC_MEMHELPERS_HH__
#include "arch/isa_traits.hh"
#include "base/types.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
#include "sim/byteswap.hh"
#include "sim/insttracer.hh"

View File

@ -148,6 +148,12 @@ class SimplePCState : public PCStateBase
npc(val + sizeof(MachInst));
};
void
setNPC(Addr val)
{
npc(val);
}
SimplePCState() {}
SimplePCState(Addr val) { set(val); }

View File

@ -42,8 +42,6 @@
#include "base/misc.hh"
#include "gpu-compute/misc.hh"
class Wavefront;
namespace HsailISA
{
typedef uint64_t MiscReg;
@ -51,7 +49,7 @@ namespace HsailISA
class GPUISA
{
public:
GPUISA(Wavefront &wf) : wavefront(wf)
GPUISA()
{
}
@ -74,9 +72,6 @@ namespace HsailISA
{
return old_pc + sizeof(RawMachInst);
}
private:
Wavefront &wavefront;
};
}

View File

@ -54,7 +54,7 @@ namespace HsailISA
{
public:
HsailGPUStaticInst(const BrigObject *obj, const std::string &opcode);
void generateDisassembly();
void generateDisassembly() override;
int instSize() const override { return sizeof(RawMachInst); }
bool isValid() const override { return true; }

View File

@ -1318,8 +1318,6 @@ class ISAParser(Grammar):
print >>f, '#if !defined(__SPLIT) || (__SPLIT == 1)'
self.splits[f] = 1
# ensure requisite #include's
elif filename in ['decoder-g.cc.inc', 'exec-g.cc.inc']:
print >>f, '#include "decoder.hh"'
elif filename == 'decoder-g.hh.inc':
print >>f, '#include "base/bitfield.hh"'
@ -1360,12 +1358,15 @@ class ISAParser(Grammar):
f.write('#include "%s"\n' % fn)
inc.append(fn)
fn = 'decoder.hh'
f.write('#include "%s"\n' % fn)
inc.append(fn)
fn = 'decode-method.cc.inc'
# is guaranteed to have been written for parse to complete
f.write('#include "%s"\n' % fn)
inc.append(fn)
inc.append("decoder.hh")
print >>dep, file+':', ' '.join(inc)
extn = re.compile('(\.[^\.]+)$')
@ -1386,6 +1387,10 @@ class ISAParser(Grammar):
f.write('#include "%s"\n' % fn)
inc.append(fn)
fn = 'decoder.hh'
f.write('#include "%s"\n' % fn)
inc.append(fn)
fn = 'decoder-ns.cc.inc'
assert(fn in self.files)
print >>f, 'namespace %s {' % self.namespace
@ -1395,7 +1400,6 @@ class ISAParser(Grammar):
print >>f, '}'
inc.append(fn)
inc.append("decoder.hh")
print >>dep, file+':', ' '.join(inc)
# instruction execution per-CPU model
@ -1416,6 +1420,10 @@ class ISAParser(Grammar):
f.write(cpu.includes+"\n")
fn = 'decoder.hh'
f.write('#include "%s"\n' % fn)
inc.append(fn)
fn = 'exec-ns.cc.inc'
assert(fn in self.files)
print >>f, 'namespace %s {' % self.namespace

View File

@ -164,7 +164,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); }},
0: syscall_se({{ xc->syscall(R2, &fault); }},
IsSerializeAfter, IsNonSpeculative);
default: syscall({{ fault = std::make_shared<SystemCallFault>(); }});
}

View File

@ -49,7 +49,7 @@ using namespace MipsISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -69,7 +69,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
/// borrowed from Tru64, the subcases that get used appear to be
/// different in practice from those used by Tru64 processes.
static SyscallReturn
sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
sys_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -98,7 +98,7 @@ sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
/// Target sys_setsysinfo() handler.
static SyscallReturn
sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
sys_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -128,7 +128,7 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
static SyscallReturn
setThreadAreaFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
setThreadAreaFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -460,10 +460,10 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 319 */ SyscallDesc("eventfd", unimplementedFunc)
};
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
ObjectFile *objFile)
: MipsLiveProcess(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
MipsLinuxProcess::MipsLinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: MipsProcess(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{ }
SyscallDesc*

View File

@ -37,11 +37,11 @@
#include "sim/eventq.hh"
/// A process with emulated Mips/Linux syscalls.
class MipsLinuxProcess : public MipsLiveProcess
class MipsLinuxProcess : public MipsProcess
{
public:
/// Constructor.
MipsLinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
MipsLinuxProcess(ProcessParams * params, ObjectFile *objFile);
virtual SyscallDesc* getDesc(int callnum);

View File

@ -39,6 +39,7 @@
#include "cpu/thread_context.hh"
#include "debug/Loader.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
@ -47,36 +48,41 @@
using namespace std;
using namespace MipsISA;
MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params,
ObjectFile *objFile)
: LiveProcess(params, objFile)
MipsProcess::MipsProcess(ProcessParams * params, ObjectFile *objFile)
: Process(params, objFile)
{
// Set up stack. On MIPS, stack starts at the top of kuseg
// user address space. MIPS stack grows down from here
stack_base = 0x7FFFFFFF;
Addr stack_base = 0x7FFFFFFF;
Addr max_stack_size = 8 * 1024 * 1024;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
Addr next_thread_stack_base = stack_base - max_stack_size;
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
// Set up region for mmaps. Start it 1GB above the top of the heap.
mmap_end = brk_point + 0x40000000L;
Addr mmap_end = brk_point + 0x40000000L;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
void
MipsLiveProcess::initState()
MipsProcess::initState()
{
LiveProcess::initState();
Process::initState();
argsInit<uint32_t>(PageBytes);
}
template<class IntType>
void
MipsLiveProcess::argsInit(int pageSize)
MipsProcess::argsInit(int pageSize)
{
int intSize = sizeof(IntType);
@ -140,15 +146,16 @@ MipsLiveProcess::argsInit(int pageSize)
env_data_size;
// set bottom of stack
stack_min = stack_base - space_needed;
memState->setStackMin(memState->getStackBase() - space_needed);
// align it
stack_min = roundDown(stack_min, pageSize);
stack_size = stack_base - stack_min;
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// map memory
allocateMem(stack_min, roundUp(stack_size, pageSize));
allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(),
pageSize));
// map out initial stack contents
IntType argv_array_base = stack_min + intSize; // room for argc
// map out initial stack contents; leave room for argc
IntType argv_array_base = memState->getStackMin() + intSize;
IntType envp_array_base = argv_array_base + argv_array_size;
IntType auxv_array_base = envp_array_base + envp_array_size;
IntType arg_data_base = auxv_array_base + auxv_array_size;
@ -159,7 +166,7 @@ MipsLiveProcess::argsInit(int pageSize)
argc = htog((IntType)argc);
initVirtMem.writeBlob(stack_min, (uint8_t*)&argc, intSize);
initVirtMem.writeBlob(memState->getStackMin(), (uint8_t*)&argc, intSize);
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
@ -184,29 +191,28 @@ MipsLiveProcess::argsInit(int pageSize)
setSyscallArg(tc, 0, argc);
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
tc->setIntReg(StackPointerReg, memState->getStackMin());
tc->pcState(getStartPC());
}
MipsISA::IntReg
MipsLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
MipsProcess::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i++);
}
void
MipsLiveProcess::setSyscallArg(ThreadContext *tc,
int i, MipsISA::IntReg val)
MipsProcess::setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val)
{
assert(i < 6);
tc->setIntReg(FirstArgumentReg + i, val);
}
void
MipsLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
MipsProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
if (sysret.successful()) {
// no error

View File

@ -38,14 +38,12 @@
#include "mem/page_table.hh"
#include "sim/process.hh"
class LiveProcess;
class ObjectFile;
class System;
class MipsLiveProcess : public LiveProcess
class MipsProcess : public Process
{
protected:
MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
MipsProcess(ProcessParams * params, ObjectFile *objFile);
void initState();
@ -55,7 +53,7 @@ class MipsLiveProcess : public LiveProcess
public:
MipsISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};

View File

@ -512,7 +512,7 @@ decode OPCODE default Unknown::unknown() {
55: stfdu({{ Mem_df = Fs; }});
}
17: IntOp::sc({{ xc->syscall(R0); }},
17: IntOp::sc({{ xc->syscall(R0, &fault); }},
[ IsSyscall, IsNonSpeculative, IsSerializeAfter ]);
format FloatArithOp {

View File

@ -49,7 +49,7 @@ using namespace PowerISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -415,10 +415,10 @@ SyscallDesc PowerLinuxProcess::syscallDescs[] = {
/* 346 */ SyscallDesc("epoll_pwait", unimplementedFunc),
};
PowerLinuxProcess::PowerLinuxProcess(LiveProcessParams * params,
PowerLinuxProcess::PowerLinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: PowerLiveProcess(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
: PowerProcess(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{
}
@ -434,7 +434,7 @@ PowerLinuxProcess::getDesc(int callnum)
void
PowerLinuxProcess::initState()
{
PowerLiveProcess::initState();
PowerProcess::initState();
}
PowerISA::IntReg

View File

@ -36,10 +36,10 @@
#include "arch/power/process.hh"
/// A process with emulated PPC/Linux syscalls.
class PowerLinuxProcess : public PowerLiveProcess
class PowerLinuxProcess : public PowerProcess
{
public:
PowerLinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
PowerLinuxProcess(ProcessParams * params, ObjectFile *objFile);
virtual SyscallDesc* getDesc(int callnum);
@ -47,7 +47,7 @@ class PowerLinuxProcess : public PowerLiveProcess
PowerISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val);
/// Array of syscall descriptors, indexed by call number.

View File

@ -40,6 +40,7 @@
#include "cpu/thread_context.hh"
#include "debug/Stack.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@ -47,25 +48,30 @@
using namespace std;
using namespace PowerISA;
PowerLiveProcess::PowerLiveProcess(LiveProcessParams *params,
ObjectFile *objFile)
: LiveProcess(params, objFile)
PowerProcess::PowerProcess(ProcessParams *params, ObjectFile *objFile)
: Process(params, objFile)
{
stack_base = 0xbf000000L;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
Addr stack_base = 0xbf000000L;
Addr max_stack_size = 8 * 1024 * 1024;
// Set pointer for next thread stack. Reserve 8M for main stack.
Addr next_thread_stack_base = stack_base - max_stack_size;
// Set up region for mmaps. For now, start at bottom of kuseg space.
mmap_end = 0x70000000L;
Addr mmap_end = 0x70000000L;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
void
PowerLiveProcess::initState()
PowerProcess::initState()
{
Process::initState();
@ -73,7 +79,7 @@ PowerLiveProcess::initState()
}
void
PowerLiveProcess::argsInit(int intSize, int pageSize)
PowerProcess::argsInit(int intSize, int pageSize)
{
typedef AuxVector<uint32_t> auxv_t;
std::vector<auxv_t> auxv;
@ -185,15 +191,17 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
int space_needed = frame_size + aux_padding;
stack_min = stack_base - space_needed;
Addr stack_min = memState->getStackBase() - space_needed;
stack_min = roundDown(stack_min, align);
stack_size = stack_base - stack_min;
memState->setStackSize(memState->getStackBase() - stack_min);
// map memory
allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize));
allocateMem(roundDown(stack_min, pageSize),
roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents
uint32_t sentry_base = stack_base - sentry_size;
uint32_t sentry_base = memState->getStackBase() - sentry_size;
uint32_t aux_data_base = sentry_base - aux_data_size;
uint32_t env_data_base = aux_data_base - env_data_size;
uint32_t arg_data_base = env_data_base - arg_data_size;
@ -262,26 +270,25 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
tc->pcState(getStartPC());
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
memState->setStackMin(roundDown(stack_min, pageSize));
}
PowerISA::IntReg
PowerLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
PowerProcess::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 5);
return tc->readIntReg(ArgumentReg0 + i++);
}
void
PowerLiveProcess::setSyscallArg(ThreadContext *tc,
int i, PowerISA::IntReg val)
PowerProcess::setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val)
{
assert(i < 5);
tc->setIntReg(ArgumentReg0 + i, val);
}
void
PowerLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
PowerProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
Cr cr = tc->readIntReg(INTREG_CR);
if (sysret.successful()) {

View File

@ -39,14 +39,12 @@
#include "mem/page_table.hh"
#include "sim/process.hh"
class LiveProcess;
class ObjectFile;
class System;
class PowerLiveProcess : public LiveProcess
class PowerProcess : public Process
{
protected:
PowerLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
PowerProcess(ProcessParams * params, ObjectFile *objFile);
void initState();
@ -54,7 +52,7 @@ class PowerLiveProcess : public LiveProcess
void argsInit(int intSize, int pageSize);
PowerISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};

View File

@ -87,5 +87,6 @@ BreakpointFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
void
SyscallFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
{
tc->syscall(tc->readIntReg(SyscallNumReg));
Fault *fault = NoFault;
tc->syscall(tc->readIntReg(SyscallNumReg), fault);
}

View File

@ -53,7 +53,7 @@ using namespace RiscvISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -126,8 +126,8 @@ std::map<int, SyscallDesc> RiscvLinuxProcess::syscallDescs = {
{2011, SyscallDesc("getmainvars", unimplementedFunc)},
};
RiscvLinuxProcess::RiscvLinuxProcess(LiveProcessParams * params,
ObjectFile *objFile) : RiscvLiveProcess(params, objFile)
RiscvLinuxProcess::RiscvLinuxProcess(ProcessParams * params,
ObjectFile *objFile) : RiscvProcess(params, objFile)
{}
SyscallDesc*

View File

@ -41,11 +41,11 @@
#include "sim/eventq.hh"
/// A process with emulated Riscv/Linux syscalls.
class RiscvLinuxProcess : public RiscvLiveProcess
class RiscvLinuxProcess : public RiscvProcess
{
public:
/// Constructor.
RiscvLinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
RiscvLinuxProcess(ProcessParams * params, ObjectFile *objFile);
virtual SyscallDesc* getDesc(int callnum);

View File

@ -42,6 +42,7 @@
#include "cpu/thread_context.hh"
#include "debug/Loader.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
@ -50,33 +51,38 @@
using namespace std;
using namespace RiscvISA;
RiscvLiveProcess::RiscvLiveProcess(LiveProcessParams * params,
ObjectFile *objFile) : LiveProcess(params, objFile)
RiscvProcess::RiscvProcess(ProcessParams * params,
ObjectFile *objFile) : Process(params, objFile)
{
// Set up stack. On RISC-V, stack starts at the top of kuseg
// user address space. RISC-V stack grows down from here
stack_base = 0x7FFFFFFF;
Addr stack_base = 0x7FFFFFFF;
Addr max_stack_size = 8 * 1024 * 1024;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
Addr next_thread_stack_base = stack_base - max_stack_size;
// Set up break point (Top of Heap)
brk_point = objFile->bssBase() + objFile->bssSize();
Addr brk_point = objFile->bssBase() + objFile->bssSize();
// Set up region for mmaps. Start it 1GB above the top of the heap.
mmap_end = brk_point + 0x40000000L;
Addr mmap_end = brk_point + 0x40000000L;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
void
RiscvLiveProcess::initState()
RiscvProcess::initState()
{
LiveProcess::initState();
Process::initState();
argsInit<uint64_t>(PageBytes);
}
template<class IntType> void
RiscvLiveProcess::argsInit(int pageSize)
RiscvProcess::argsInit(int pageSize)
{
updateBias();
@ -123,18 +129,24 @@ RiscvLiveProcess::argsInit(int pageSize)
env_data_size += env.size() + 1;
int auxv_array_size = 2 * sizeof(IntType)*auxv.size();
stack_size = sizeof(IntType) + argv_array_size + 2 * sizeof(Addr) +
arg_data_size + 2 * sizeof(Addr);
Addr stack_size = sizeof(IntType) + argv_array_size + 2 * sizeof(Addr) +
sizeof(Addr) + arg_data_size + 2 * sizeof(Addr);
if (!envp.empty()) {
stack_size += 2 * sizeof(Addr) + envp_array_size + 2 * sizeof(Addr) +
env_data_size;
stack_size += 2 * sizeof(Addr) + envp_array_size + 2 *
sizeof(Addr) + env_data_size;
}
if (!auxv.empty())
stack_size += 2 * sizeof(Addr) + auxv_array_size;
stack_min = roundDown(stack_base - stack_size, pageSize);
allocateMem(stack_min, roundUp(stack_size, pageSize));
Addr argv_array_base = stack_min + sizeof(IntType);
memState->setStackSize(stack_size);
Addr stack_min = roundDown(memState->getStackBase() -
stack_size, pageSize);
allocateMem(stack_min, roundUp(memState->getStackSize(), pageSize));
memState->setStackMin(stack_min);
Addr argv_array_base = memState->getStackMin() + sizeof(IntType);
Addr arg_data_base = argv_array_base + argv_array_size + 2 * sizeof(Addr);
Addr envp_array_base = arg_data_base + arg_data_size;
if (!envp.empty())
@ -159,7 +171,7 @@ RiscvLiveProcess::argsInit(int pageSize)
}
}
Addr sp = stack_min;
Addr sp = memState->getStackMin();
initVirtMem.writeBlob(sp, (uint8_t *)&argc, sizeof(IntType));
sp += sizeof(IntType);
for (Addr arg_pointer: arg_pointers) {
@ -210,24 +222,30 @@ RiscvLiveProcess::argsInit(int pageSize)
}
ThreadContext *tc = system->getThreadContext(contextIds[0]);
tc->setIntReg(StackPointerReg, stack_min);
tc->setIntReg(StackPointerReg, memState->getStackMin());
tc->pcState(getStartPC());
}
RiscvISA::IntReg
RiscvLiveProcess::getSyscallArg(ThreadContext *tc, int &i)
RiscvProcess::getSyscallArg(ThreadContext *tc, int &i)
{
return tc->readIntReg(SyscallArgumentRegs[i++]);
// RISC-V only has four system call argument registers by convention, so
// if a larger index is requested return 0
RiscvISA::IntReg retval = 0;
if (i < 4)
retval = tc->readIntReg(SyscallArgumentRegs[i]);
i++;
return retval;
}
void
RiscvLiveProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val)
RiscvProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val)
{
tc->setIntReg(SyscallArgumentRegs[i], val);
}
void
RiscvLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
RiscvProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
if (sysret.successful()) {
// no error

View File

@ -38,14 +38,13 @@
#include "mem/page_table.hh"
#include "sim/process.hh"
class LiveProcess;
class ObjectFile;
class System;
class RiscvLiveProcess : public LiveProcess
class RiscvProcess : public Process
{
protected:
RiscvLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
RiscvProcess(ProcessParams * params, ObjectFile *objFile);
void initState();
@ -55,7 +54,7 @@ class RiscvLiveProcess : public LiveProcess
public:
RiscvISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};

View File

@ -50,9 +50,9 @@
#include <map>
#include <string>
#include "arch/isa_traits.hh"
#include "arch/riscv/generated/max_inst_regs.hh"
#include "base/types.hh"
#include "sim/system.hh"
namespace RiscvISA {

View File

@ -628,9 +628,43 @@ FastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
if (!success) {
panic("Tried to execute unmapped address %#x.\n", vaddr);
} else {
Addr alignedVaddr = p->pTable->pageAlign(vaddr);
tc->getITBPtr()->insert(alignedVaddr, 0 /*partition id*/,
p->_pid /*context id*/, false, entry.pte);
Addr alignedvaddr = p->pTable->pageAlign(vaddr);
// Grab fields used during instruction translation to figure out
// which context to use.
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
// Inside a VM, a real address is the address that guest OS would
// interpret to be a physical address. To map to the physical address,
// it still needs to undergo a translation. The instruction
// translation code in the SPARC ITLB code assumes that the context is
// zero (kernel-level) if real addressing is being used.
bool is_real_address = !bits(tlbdata, 4);
// The SPARC ITLB code assumes that traps are executed in context
// zero so we carry that assumption through here.
bool trapped = bits(tlbdata, 18, 16) > 0;
// The primary context acts as a PASID. It allows the MMU to
// distinguish between virtual addresses that would alias to the
// same physical address (if two or more processes shared the same
// virtual address mapping).
int primary_context = bits(tlbdata, 47, 32);
// The partition id distinguishes between virtualized environments.
int const partition_id = 0;
// Given the assumptions in the translateInst code in the SPARC ITLB,
// the logic works out to the following for the context.
int context_id = (is_real_address || trapped) ? 0 : primary_context;
// Insert the TLB entry.
// The entry specifying whether the address is "real" is set to
// false for syscall emulation mode regardless of whether the
// address is real in preceding code. Not sure sure that this is
// correct, but also not sure if it matters at all.
tc->getITBPtr()->insert(alignedvaddr, partition_id, context_id,
false, entry.pte);
}
}
@ -652,9 +686,73 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
if (!success) {
panic("Tried to access unmapped address %#x.\n", vaddr);
} else {
Addr alignedVaddr = p->pTable->pageAlign(vaddr);
tc->getDTBPtr()->insert(alignedVaddr, 0 /*partition id*/,
p->_pid /*context id*/, false, entry.pte);
Addr alignedvaddr = p->pTable->pageAlign(vaddr);
// Grab fields used during data translation to figure out
// which context to use.
uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
// The primary context acts as a PASID. It allows the MMU to
// distinguish between virtual addresses that would alias to the
// same physical address (if two or more processes shared the same
// virtual address mapping). There's a secondary context used in the
// DTLB translation code, but it should __probably__ be zero for
// syscall emulation code. (The secondary context is used by Solaris
// to allow kernel privilege code to access user space code:
// [ISBN 0-13-022496-0]:PG199.)
int primary_context = bits(tlbdata, 47, 32);
// "Hyper-Privileged Mode" is in use. There are three main modes of
// operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
// User Mode.
int hpriv = bits(tlbdata, 0);
// Reset, Error and Debug state is in use. Something horrible has
// happened or the system is operating in Reset Mode.
int red = bits(tlbdata, 1);
// Inside a VM, a real address is the address that guest OS would
// interpret to be a physical address. To map to the physical address,
// it still needs to undergo a translation. The instruction
// translation code in the SPARC ITLB code assumes that the context is
// zero (kernel-level) if real addressing is being used.
int is_real_address = !bits(tlbdata, 5);
// Grab the address space identifier register from the thread context.
// XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
// MISCREG_ASI causes me to think that the ASI register implementation
// might be bugged. The NoEffect variant changes the ASI register
// value in the architectural state while the normal variant changes
// the context field in the thread context's currently decoded request
// but does not directly affect the ASI register value in the
// architectural state. The ASI values and the context field in the
// request packet seem to have completely different uses.
MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI);
ASI asi = static_cast<ASI>(reg_asi);
// The SPARC DTLB code assumes that traps are executed in context
// zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
// an assumption that the nucleus address space is being used, but
// the context is the relevant issue since we need to pass it to TLB.
bool trapped = bits(tlbdata, 18, 16) > 0;
// Given the assumptions in the translateData code in the SPARC DTLB,
// the logic works out to the following for the context.
int context_id = ((!hpriv && !red && is_real_address) ||
asiIsReal(asi) ||
(trapped && asi == ASI_IMPLICIT))
? 0 : primary_context;
// The partition id distinguishes between virtualized environments.
int const partition_id = 0;
// Insert the TLB entry.
// The entry specifying whether the address is "real" is set to
// false for syscall emulation mode regardless of whether the
// address is real in preceding code. Not sure sure that this is
// correct, but also not sure if it matters at all.
tc->getDTBPtr()->insert(alignedvaddr, partition_id, context_id,
false, entry.pte);
}
}
@ -670,12 +768,11 @@ SpillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst)
Process *p = tc->getProcessPtr();
//XXX This will only work in faults from a SparcLiveProcess
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
assert(lp);
SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
assert(sp);
// Then adjust the PC and NPC
tc->pcState(lp->readSpillStart());
tc->pcState(sp->readSpillStart());
}
void
@ -690,12 +787,11 @@ FillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst)
Process *p = tc->getProcessPtr();
//XXX This will only work in faults from a SparcLiveProcess
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
assert(lp);
SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
assert(sp);
// Then adjust the PC and NPC
tc->pcState(lp->readFillStart());
tc->pcState(sp->readFillStart());
}
void
@ -712,10 +808,11 @@ TrapInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
Process *p = tc->getProcessPtr();
SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
assert(lp);
SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
assert(sp);
lp->handleTrap(_n, tc);
Fault fault;
sp->handleTrap(_n, tc, &fault);
// We need to explicitly advance the pc, since that's not done for us
// on a faulting instruction

View File

@ -60,35 +60,37 @@ SparcLinuxProcess::getDesc32(int callnum)
return &syscall32Descs[callnum];
}
Sparc32LinuxProcess::Sparc32LinuxProcess(LiveProcessParams * params,
Sparc32LinuxProcess::Sparc32LinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: Sparc32LiveProcess(params, objFile)
: Sparc32Process(params, objFile)
{}
void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc)
void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc,
Fault *fault)
{
switch (trapNum) {
case 0x10: //Linux 32 bit syscall trap
tc->syscall(tc->readIntReg(1));
tc->syscall(tc->readIntReg(1), fault);
break;
default:
SparcLiveProcess::handleTrap(trapNum, tc);
SparcProcess::handleTrap(trapNum, tc, fault);
}
}
Sparc64LinuxProcess::Sparc64LinuxProcess(LiveProcessParams * params,
Sparc64LinuxProcess::Sparc64LinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: Sparc64LiveProcess(params, objFile)
: Sparc64Process(params, objFile)
{}
void Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc)
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));
tc->syscall(tc->readIntReg(1), fault);
break;
default:
SparcLiveProcess::handleTrap(trapNum, tc);
SparcProcess::handleTrap(trapNum, tc, fault);
}
}

View File

@ -58,11 +58,11 @@ class SparcLinuxProcess
};
/// A process with emulated SPARC/Linux syscalls.
class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32LiveProcess
class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32Process
{
public:
/// Constructor.
Sparc32LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
Sparc32LinuxProcess(ProcessParams * params, ObjectFile *objFile);
SyscallDesc*
getDesc(int callnum)
@ -70,15 +70,15 @@ class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32LiveProcess
return SparcLinuxProcess::getDesc32(callnum);
}
void handleTrap(int trapNum, ThreadContext *tc);
void handleTrap(int trapNum, ThreadContext *tc, Fault *fault);
};
/// A process with emulated 32 bit SPARC/Linux syscalls.
class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64LiveProcess
class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64Process
{
public:
/// Constructor.
Sparc64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
Sparc64LinuxProcess(ProcessParams * params, ObjectFile *objFile);
SyscallDesc*
getDesc(int callnum)
@ -86,11 +86,11 @@ class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64LiveProcess
return SparcLinuxProcess::getDesc(callnum);
}
void handleTrap(int trapNum, ThreadContext *tc);
void handleTrap(int trapNum, ThreadContext *tc, Fault *fault);
};
SyscallReturn getresuidFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
Process *p, ThreadContext *tc);
} // namespace SparcISA
#endif // __SPARC_LINUX_PROCESS_HH__

View File

@ -32,15 +32,15 @@
#include "sim/syscall_desc.hh"
#include "sim/syscall_emul.hh"
class LiveProcess;
class Process;
class ThreadContext;
namespace SparcISA {
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
@ -58,7 +58,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
SyscallReturn
getresuidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
getresuidFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
const IntReg id = htog(100);
int index = 0;
@ -305,7 +305,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
/* 214 */ SyscallDesc("sysinfo", sysinfoFunc<Sparc32Linux>), // 32 bit
/* 215 */ SyscallDesc("ipc", unimplementedFunc), // 32 bit
/* 216 */ SyscallDesc("sigreturn", unimplementedFunc), // 32 bit
/* 217 */ SyscallDesc("clone", cloneFunc),
/* 217 */ SyscallDesc("clone", cloneFunc<Sparc32Linux>),
/* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), // 32 bit
/* 219 */ SyscallDesc("adjtimex", unimplementedFunc), // 32 bit
/* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), // 32 bit
@ -611,7 +611,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 214 */ SyscallDesc("sysinfo", sysinfoFunc<SparcLinux>),
/* 215 */ SyscallDesc("ipc", unimplementedFunc),
/* 216 */ SyscallDesc("sigreturn", unimplementedFunc),
/* 217 */ SyscallDesc("clone", cloneFunc),
/* 217 */ SyscallDesc("clone", cloneFunc<SparcLinux>),
/* 218 */ SyscallDesc("ioprio_get", unimplementedFunc),
/* 219 */ SyscallDesc("adjtimex", unimplementedFunc),
/* 220 */ SyscallDesc("sigprocmask", unimplementedFunc),

View File

@ -42,6 +42,7 @@
#include "cpu/thread_context.hh"
#include "debug/Stack.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@ -52,25 +53,17 @@ using namespace SparcISA;
static const int FirstArgumentReg = 8;
SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params,
ObjectFile *objFile, Addr _StackBias)
: LiveProcess(params, objFile), StackBias(_StackBias)
SparcProcess::SparcProcess(ProcessParams * params, ObjectFile *objFile,
Addr _StackBias)
: Process(params, objFile), StackBias(_StackBias)
{
// XXX all the below need to be updated for SPARC - Ali
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// Initialize these to 0s
fillStart = 0;
spillStart = 0;
}
void
SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
SparcProcess::handleTrap(int trapNum, ThreadContext *tc, Fault *fault)
{
PCState pc = tc->pcState();
switch (trapNum) {
@ -111,9 +104,9 @@ SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
}
void
SparcLiveProcess::initState()
SparcProcess::initState()
{
LiveProcess::initState();
Process::initState();
ThreadContext *tc = system->getThreadContext(contextIds[0]);
// From the SPARC ABI
@ -149,6 +142,9 @@ SparcLiveProcess::initState()
// Set the ASI register to something fixed
tc->setMiscReg(MISCREG_ASI, ASI_PRIMARY);
// Set the MMU Primary Context Register to hold the process' pid
tc->setMiscReg(MISCREG_MMU_P_CONTEXT, _pid);
/*
* T1 specific registers
*/
@ -157,9 +153,9 @@ SparcLiveProcess::initState()
}
void
Sparc32LiveProcess::initState()
Sparc32Process::initState()
{
SparcLiveProcess::initState();
SparcProcess::initState();
ThreadContext *tc = system->getThreadContext(contextIds[0]);
// The process runs in user mode with 32 bit addresses
@ -172,9 +168,9 @@ Sparc32LiveProcess::initState()
}
void
Sparc64LiveProcess::initState()
Sparc64Process::initState()
{
SparcLiveProcess::initState();
SparcProcess::initState();
ThreadContext *tc = system->getThreadContext(contextIds[0]);
// The process runs in user mode
@ -187,7 +183,7 @@ Sparc64LiveProcess::initState()
template<class IntType>
void
SparcLiveProcess::argsInit(int pageSize)
SparcProcess::argsInit(int pageSize)
{
int intSize = sizeof(IntType);
@ -320,15 +316,16 @@ SparcLiveProcess::argsInit(int pageSize)
aux_padding +
frame_size;
stack_min = stack_base - space_needed;
stack_min = roundDown(stack_min, align);
stack_size = stack_base - stack_min;
memState->setStackMin(memState->getStackBase() - space_needed);
memState->setStackMin(roundDown(memState->getStackMin(), align));
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// Allocate space for the stack
allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize));
allocateMem(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents
IntType sentry_base = stack_base - sentry_size;
IntType sentry_base = memState->getStackBase() - sentry_size;
IntType file_name_base = sentry_base - file_name_size;
IntType env_data_base = file_name_base - env_data_size;
IntType arg_data_base = env_data_base - arg_data_size;
@ -352,9 +349,9 @@ SparcLiveProcess::argsInit(int pageSize)
DPRINTF(Stack, "%#x - argv array\n", argv_array_base);
DPRINTF(Stack, "%#x - argc \n", argc_base);
DPRINTF(Stack, "%#x - window save\n", window_save_base);
DPRINTF(Stack, "%#x - stack min\n", stack_min);
DPRINTF(Stack, "%#x - stack min\n", memState->getStackMin());
assert(window_save_base == stack_min);
assert(window_save_base == memState->getStackMin());
// write contents to stack
@ -393,7 +390,7 @@ SparcLiveProcess::argsInit(int pageSize)
// Set up space for the trap handlers into the processes address space.
// Since the stack grows down and there is reserved address space abov
// it, we can put stuff above it and stay out of the way.
fillStart = stack_base;
fillStart = memState->getStackBase();
spillStart = fillStart + sizeof(MachInst) * numFillInsts;
ThreadContext *tc = system->getThreadContext(contextIds[0]);
@ -401,7 +398,7 @@ SparcLiveProcess::argsInit(int pageSize)
// assert(NumArgumentRegs >= 2);
// tc->setIntReg(ArgumentReg[0], argc);
// tc->setIntReg(ArgumentReg[1], argv_array_base);
tc->setIntReg(StackPointerReg, stack_min - StackBias);
tc->setIntReg(StackPointerReg, memState->getStackMin() - StackBias);
// %g1 is a pointer to a function that should be run at exit. Since we
// don't have anything like that, it should be set to 0.
@ -410,15 +407,13 @@ SparcLiveProcess::argsInit(int pageSize)
tc->pcState(getStartPC());
// Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
// num_processes++;
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
}
void
Sparc64LiveProcess::argsInit(int intSize, int pageSize)
Sparc64Process::argsInit(int intSize, int pageSize)
{
SparcLiveProcess::argsInit<uint64_t>(pageSize);
SparcProcess::argsInit<uint64_t>(pageSize);
// Stuff the trap handlers into the process address space
initVirtMem.writeBlob(fillStart,
@ -428,9 +423,9 @@ Sparc64LiveProcess::argsInit(int intSize, int pageSize)
}
void
Sparc32LiveProcess::argsInit(int intSize, int pageSize)
Sparc32Process::argsInit(int intSize, int pageSize)
{
SparcLiveProcess::argsInit<uint32_t>(pageSize);
SparcProcess::argsInit<uint32_t>(pageSize);
// Stuff the trap handlers into the process address space
initVirtMem.writeBlob(fillStart,
@ -439,7 +434,7 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
(uint8_t*)spillHandler32, sizeof(MachInst) * numSpillInsts);
}
void Sparc32LiveProcess::flushWindows(ThreadContext *tc)
void Sparc32Process::flushWindows(ThreadContext *tc)
{
IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);
IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4);
@ -474,7 +469,7 @@ void Sparc32LiveProcess::flushWindows(ThreadContext *tc)
}
void
Sparc64LiveProcess::flushWindows(ThreadContext *tc)
Sparc64Process::flushWindows(ThreadContext *tc)
{
IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);
IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4);
@ -509,35 +504,35 @@ Sparc64LiveProcess::flushWindows(ThreadContext *tc)
}
IntReg
Sparc32LiveProcess::getSyscallArg(ThreadContext *tc, int &i)
Sparc32Process::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return bits(tc->readIntReg(FirstArgumentReg + i++), 31, 0);
}
void
Sparc32LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val)
Sparc32Process::setSyscallArg(ThreadContext *tc, int i, IntReg val)
{
assert(i < 6);
tc->setIntReg(FirstArgumentReg + i, bits(val, 31, 0));
}
IntReg
Sparc64LiveProcess::getSyscallArg(ThreadContext *tc, int &i)
Sparc64Process::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < 6);
return tc->readIntReg(FirstArgumentReg + i++);
}
void
Sparc64LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val)
Sparc64Process::setSyscallArg(ThreadContext *tc, int i, IntReg val)
{
assert(i < 6);
tc->setIntReg(FirstArgumentReg + i, val);
}
void
SparcLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
SparcProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
// check for error condition. SPARC syscall convention is to
// indicate success/failure in reg the carry bit of the ccr

View File

@ -32,17 +32,17 @@
#ifndef __SPARC_PROCESS_HH__
#define __SPARC_PROCESS_HH__
#include <memory>
#include <string>
#include <vector>
#include "arch/sparc/isa_traits.hh"
#include "base/loader/object_file.hh"
#include "mem/page_table.hh"
#include "sim/byteswap.hh"
#include "sim/process.hh"
class ObjectFile;
class System;
class SparcLiveProcess : public LiveProcess
class SparcProcess : public Process
{
protected:
@ -51,8 +51,8 @@ class SparcLiveProcess : public LiveProcess
// The locations of the fill and spill handlers
Addr fillStart, spillStart;
SparcLiveProcess(LiveProcessParams * params,
ObjectFile *objFile, Addr _StackBias);
SparcProcess(ProcessParams * params, ObjectFile *objFile,
Addr _StackBias);
void initState();
@ -62,7 +62,7 @@ class SparcLiveProcess : public LiveProcess
public:
// Handles traps which request services from the operating system
virtual void handleTrap(int trapNum, ThreadContext *tc);
virtual void handleTrap(int trapNum, ThreadContext *tc, Fault *fault);
Addr readFillStart() { return fillStart; }
Addr readSpillStart() { return spillStart; }
@ -71,19 +71,34 @@ class SparcLiveProcess : public LiveProcess
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};
class Sparc32LiveProcess : public SparcLiveProcess
class Sparc32Process : public SparcProcess
{
protected:
Sparc32LiveProcess(LiveProcessParams * params, ObjectFile *objFile) :
SparcLiveProcess(params, objFile, 0)
Sparc32Process(ProcessParams * params, ObjectFile *objFile)
: SparcProcess(params, objFile, 0)
{
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
brk_point = roundUp(brk_point, SparcISA::PageBytes);
// Reserve 8M for main stack.
Addr max_stack_size = 8 * 1024 * 1024;
// Set up stack. On SPARC Linux, stack goes from the top of memory
// downward, less the hole for the kernel address space.
stack_base = (Addr)0xf0000000ULL;
Addr stack_base = 0xf0000000ULL;
// Set pointer for next thread stack.
Addr next_thread_stack_base = stack_base - max_stack_size;
// Set up region for mmaps.
mmap_end = 0x70000000;
Addr mmap_end = 0x70000000;
memState = std::make_shared<MemState>(brk_point, stack_base,
max_stack_size,
next_thread_stack_base,
mmap_end);
}
void initState();
@ -96,24 +111,38 @@ class Sparc32LiveProcess : public SparcLiveProcess
SparcISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val);
};
class Sparc64LiveProcess : public SparcLiveProcess
class Sparc64Process : public SparcProcess
{
protected:
Sparc64LiveProcess(LiveProcessParams * params, ObjectFile *objFile) :
SparcLiveProcess(params, objFile, 2047)
Sparc64Process(ProcessParams * params, ObjectFile *objFile)
: SparcProcess(params, objFile, 2047)
{
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
brk_point = roundUp(brk_point, SparcISA::PageBytes);
Addr max_stack_size = 8 * 1024 * 1024;
// Set up stack. On SPARC Linux, stack goes from the top of memory
// downward, less the hole for the kernel address space.
stack_base = (Addr)0x80000000000ULL;
Addr stack_base = 0x80000000000ULL;
// Set pointer for next thread stack. Reserve 8M for main stack.
Addr next_thread_stack_base = stack_base - max_stack_size;
// Set up region for mmaps.
mmap_end = 0xfffff80000000000ULL;
Addr mmap_end = 0xfffff80000000000ULL;
memState = std::make_shared<MemState>(brk_point, stack_base,
max_stack_size,
next_thread_stack_base,
mmap_end);
}
void initState();
@ -126,7 +155,7 @@ class Sparc64LiveProcess : public SparcLiveProcess
SparcISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val);
};

View File

@ -45,7 +45,7 @@ using namespace SparcISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -322,9 +322,9 @@ SyscallDesc SparcSolarisProcess::syscallDescs[] = {
/* 255 */ SyscallDesc("umount2", unimplementedFunc)
};
SparcSolarisProcess::SparcSolarisProcess(LiveProcessParams * params,
ObjectFile *objFile)
: Sparc64LiveProcess(params, objFile),
SparcSolarisProcess::SparcSolarisProcess(ProcessParams * params,
ObjectFile *objFile)
: Sparc64Process(params, objFile),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{
// The sparc syscall table must be <= 284 entries because that is all there

View File

@ -38,11 +38,11 @@
namespace SparcISA {
/// A process with emulated SPARC/Solaris syscalls.
class SparcSolarisProcess : public Sparc64LiveProcess
class SparcSolarisProcess : public Sparc64Process
{
public:
/// Constructor.
SparcSolarisProcess(LiveProcessParams * params, ObjectFile *objFile);
SparcSolarisProcess(ProcessParams * params, ObjectFile *objFile);
virtual SyscallDesc* getDesc(int callnum);

View File

@ -400,8 +400,9 @@
// will sign extend it, and there's no easy way to
// specify only checking the first byte.
0xffffffffffffff80:
SyscallInst::int80('xc->syscall(Rax)',
IsSyscall, IsNonSpeculative, IsSerializeAfter);
SyscallInst::int80('xc->syscall(Rax, &fault)',
IsSyscall, IsNonSpeculative,
IsSerializeAfter);
}
default: Inst::INT(Ib);

View File

@ -235,8 +235,9 @@
}
}
0x05: decode FullSystemInt {
0: SyscallInst::syscall('xc->syscall(Rax)',
IsSyscall, IsNonSpeculative, IsSerializeAfter);
0: SyscallInst::syscall('xc->syscall(Rax, &fault)',
IsSyscall, IsNonSpeculative,
IsSerializeAfter);
default: decode MODE_MODE {
0x0: decode MODE_SUBMODE {
0x0: Inst::SYSCALL_64();
@ -422,8 +423,9 @@
0x2: Inst::RDMSR();
0x3: rdpmc();
0x4: decode FullSystemInt {
0: SyscallInst::sysenter('xc->syscall(Rax)',
IsSyscall, IsNonSpeculative, IsSerializeAfter);
0: SyscallInst::sysenter('xc->syscall(Rax, &fault)',
IsSyscall, IsNonSpeculative,
IsSerializeAfter);
default: sysenter();
}
0x5: sysexit();

View File

@ -45,7 +45,7 @@ def macroop CALL_NEAR_I
limm t1, imm
rdip t7
# Check target of call
st t7, ss, [0, t0, rsp], "-env.dataSize"
stis t7, ss, [0, t0, rsp], "-env.dataSize"
subi rsp, rsp, ssz
wrip t7, t1
};
@ -58,7 +58,7 @@ def macroop CALL_NEAR_R
rdip t1
# Check target of call
st t1, ss, [0, t0, rsp], "-env.dataSize"
stis t1, ss, [0, t0, rsp], "-env.dataSize"
subi rsp, rsp, ssz
wripi reg, 0
};

View File

@ -40,7 +40,7 @@ def macroop POP_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
ld t1, ss, [1, t0, rsp], dataSize=ssz
ldis t1, ss, [1, t0, rsp], dataSize=ssz
addi rsp, rsp, ssz, dataSize=asz
mov reg, reg, t1
};
@ -49,7 +49,7 @@ def macroop POP_M {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
ld t1, ss, [1, t0, rsp], dataSize=ssz
ldis t1, ss, [1, t0, rsp], dataSize=ssz
cda seg, sib, disp, dataSize=ssz
addi rsp, rsp, ssz, dataSize=asz
st t1, seg, sib, disp, dataSize=ssz
@ -70,7 +70,7 @@ def macroop PUSH_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
st reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
stis reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
subi rsp, rsp, ssz
};
@ -79,7 +79,7 @@ def macroop PUSH_I {
.adjust_env oszIn64Override
limm t1, imm
st t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
stis t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
subi rsp, rsp, ssz
};
@ -138,7 +138,7 @@ def macroop LEAVE {
.adjust_env oszIn64Override
mov t1, t1, rbp, dataSize=ssz
ld rbp, ss, [1, t0, t1], dataSize=ssz
ldis rbp, ss, [1, t0, t1], dataSize=ssz
mov rsp, rsp, t1, dataSize=ssz
addi rsp, rsp, ssz, dataSize=ssz
};
@ -156,7 +156,7 @@ def macroop ENTER_I_I {
# t1 is now the masked nesting level, and t2 is the amount of storage.
# Push rbp.
st rbp, ss, [1, t0, rsp], "-env.dataSize"
stis rbp, ss, [1, t0, rsp], "-env.dataSize"
subi rsp, rsp, ssz
# Save the stack pointer for later
@ -172,8 +172,8 @@ def macroop ENTER_I_I {
limm t4, "ULL(-1)", dataSize=8
topOfLoop:
ld t5, ss, [dsz, t4, rbp]
st t5, ss, [1, t0, rsp], "-env.dataSize"
ldis t5, ss, [dsz, t4, rbp]
stis t5, ss, [1, t0, rsp], "-env.dataSize"
subi rsp, rsp, ssz
# If we're not done yet, loop
@ -183,7 +183,7 @@ topOfLoop:
bottomOfLoop:
# Push the old rbp onto the stack
st t6, ss, [1, t0, rsp], "-env.dataSize"
stis t6, ss, [1, t0, rsp], "-env.dataSize"
subi rsp, rsp, ssz
skipLoop:

View File

@ -315,7 +315,8 @@ def template MicroLdStSplitOpConstructor {{
let {{
class LdStOp(X86Microop):
def __init__(self, data, segment, addr, disp,
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
implicitStack):
self.data = data
[self.scale, self.index, self.base] = addr
self.disp = disp
@ -331,8 +332,11 @@ let {{
self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
if nonSpec:
self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
self.memFlags += " | (machInst.legacy.addr ? " + \
"(AddrSizeFlagBit << FlagShift) : 0)"
# For implicit stack operations, we should use *not* use the
# alternative addressing mode for loads/stores if the prefix is set
if not implicitStack:
self.memFlags += " | (machInst.legacy.addr ? " + \
"(AddrSizeFlagBit << FlagShift) : 0)"
def getAllocator(self, microFlags):
allocator = '''new %(class_name)s(machInst, macrocodeBlock,
@ -351,7 +355,8 @@ let {{
class BigLdStOp(X86Microop):
def __init__(self, data, segment, addr, disp,
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
implicitStack):
self.data = data
[self.scale, self.index, self.base] = addr
self.disp = disp
@ -367,8 +372,11 @@ let {{
self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
if nonSpec:
self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
self.memFlags += " | (machInst.legacy.addr ? " + \
"(AddrSizeFlagBit << FlagShift) : 0)"
# For implicit stack operations, we should use *not* use the
# alternative addressing mode for loads/stores if the prefix is set
if not implicitStack:
self.memFlags += " | (machInst.legacy.addr ? " + \
"(AddrSizeFlagBit << FlagShift) : 0)"
def getAllocator(self, microFlags):
allocString = '''
@ -395,9 +403,11 @@ let {{
class LdStSplitOp(LdStOp):
def __init__(self, data, segment, addr, disp,
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
implicitStack):
super(LdStSplitOp, self).__init__(0, segment, addr, disp,
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec)
dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
implicitStack)
(self.dataLow, self.dataHi) = data
def getAllocator(self, microFlags):
@ -435,7 +445,8 @@ let {{
calculateEA = 'EA = SegBase + ' + segmentEAExpr
def defineMicroLoadOp(mnemonic, code, bigCode='',
mem_flags="0", big=True, nonSpec=False):
mem_flags="0", big=True, nonSpec=False,
implicitStack=False):
global header_output
global decoder_output
global exec_output
@ -460,17 +471,26 @@ let {{
exec_output += MicroLoadInitiateAcc.subst(iop)
exec_output += MicroLoadCompleteAcc.subst(iop)
if implicitStack:
# For instructions that implicitly access the stack, the address
# size is the same as the stack segment pointer size, not the
# address size if specified by the instruction prefix
addressSize = "env.stackSize"
else:
addressSize = "env.addressSize"
base = LdStOp
if big:
base = BigLdStOp
class LoadOp(base):
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
atCPL0=False, prefetch=False, nonSpec=nonSpec):
addressSize=addressSize,
atCPL0=False, prefetch=False, nonSpec=nonSpec,
implicitStack=implicitStack):
super(LoadOp, self).__init__(data, segment, addr,
disp, dataSize, addressSize, mem_flags,
atCPL0, prefetch, nonSpec)
atCPL0, prefetch, nonSpec, implicitStack)
self.className = Name
self.mnemonic = name
@ -478,6 +498,9 @@ let {{
defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);',
'Data = Mem & mask(dataSize * 8);')
defineMicroLoadOp('Ldis', 'Data = merge(Data, Mem, dataSize);',
'Data = Mem & mask(dataSize * 8);',
implicitStack=True)
defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
'Data = Mem & mask(dataSize * 8);',
'(StoreCheck << FlagShift)')
@ -544,10 +567,11 @@ let {{
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
atCPL0=False, prefetch=False, nonSpec=nonSpec):
atCPL0=False, prefetch=False, nonSpec=nonSpec,
implicitStack=False):
super(LoadOp, self).__init__(data, segment, addr,
disp, dataSize, addressSize, mem_flags,
atCPL0, prefetch, nonSpec)
atCPL0, prefetch, nonSpec, implicitStack)
self.className = Name
self.mnemonic = name
@ -574,7 +598,8 @@ let {{
'(StoreCheck << FlagShift) | Request::LOCKED_RMW',
nonSpec=True)
def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"):
def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0",
implicitStack=False):
global header_output
global decoder_output
global exec_output
@ -594,20 +619,30 @@ let {{
exec_output += MicroStoreInitiateAcc.subst(iop)
exec_output += MicroStoreCompleteAcc.subst(iop)
if implicitStack:
# For instructions that implicitly access the stack, the address
# size is the same as the stack segment pointer size, not the
# address size if specified by the instruction prefix
addressSize = "env.stackSize"
else:
addressSize = "env.addressSize"
class StoreOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
atCPL0=False, nonSpec=False):
addressSize=addressSize,
atCPL0=False, nonSpec=False, implicitStack=implicitStack):
super(StoreOp, self).__init__(data, segment, addr, disp,
dataSize, addressSize, mem_flags, atCPL0, False,
nonSpec)
nonSpec, implicitStack)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
defineMicroStoreOp('Stis', 'Mem = pick(Data, 2, dataSize);',
implicitStack=True)
defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
mem_flags="Request::LOCKED_RMW")
@ -655,10 +690,10 @@ let {{
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize",
addressSize="env.addressSize",
atCPL0=False, nonSpec=False):
atCPL0=False, nonSpec=False, implicitStack=False):
super(StoreOp, self).__init__(data, segment, addr, disp,
dataSize, addressSize, mem_flags, atCPL0, False,
nonSpec)
nonSpec, implicitStack)
self.className = Name
self.mnemonic = name
@ -694,7 +729,7 @@ let {{
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize", addressSize="env.addressSize"):
super(LeaOp, self).__init__(data, segment, addr, disp,
dataSize, addressSize, "0", False, False, False)
dataSize, addressSize, "0", False, False, False, False)
self.className = "Lea"
self.mnemonic = "lea"
@ -715,7 +750,7 @@ let {{
addressSize="env.addressSize"):
super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
addr, disp, dataSize, addressSize, "0", False, False,
False)
False, False)
self.className = "Tia"
self.mnemonic = "tia"
@ -727,10 +762,9 @@ let {{
addressSize="env.addressSize", atCPL0=False):
super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
addr, disp, dataSize, addressSize, "Request::NO_ACCESS",
atCPL0, False, False)
atCPL0, False, False, False)
self.className = "Cda"
self.mnemonic = "cda"
microopClasses["cda"] = CdaOp
}};

View File

@ -54,7 +54,7 @@ using namespace X86ISA;
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
int index = 0;
@ -72,7 +72,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
static SyscallReturn
archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
archPrctlFunc(SyscallDesc *desc, int callnum, Process *process,
ThreadContext *tc)
{
enum ArchPrctlCodes
@ -83,7 +83,7 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
GetGS = 0x1004
};
//First argument is the code, second is the address
// First argument is the code, second is the address
int index = 0;
int code = process->getSyscallArg(tc, index);
uint64_t addr = process->getSyscallArg(tc, index);
@ -91,7 +91,7 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
SETranslatingPortProxy &p = tc->getMemProxy();
switch(code)
{
//Each of these valid options should actually check addr.
// Each of these valid options should actually check addr.
case SetFS:
tc->setMiscRegNoEffect(MISCREG_FS_BASE, addr);
tc->setMiscRegNoEffect(MISCREG_FS_EFF_BASE, addr);
@ -139,22 +139,22 @@ struct UserDesc64 {
static SyscallReturn
setThreadArea32Func(SyscallDesc *desc, int callnum,
LiveProcess *process, ThreadContext *tc)
Process *process, ThreadContext *tc)
{
const int minTLSEntry = 6;
const int numTLSEntries = 3;
const int maxTLSEntry = minTLSEntry + numTLSEntries - 1;
X86LiveProcess *x86lp = dynamic_cast<X86LiveProcess *>(process);
assert(x86lp);
X86Process *x86p = dynamic_cast<X86Process *>(process);
assert(x86p);
assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86lp->gdtSize());
assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86p->gdtSize());
int argIndex = 0;
TypedBufferArg<UserDesc32> userDesc(process->getSyscallArg(tc, argIndex));
TypedBufferArg<uint64_t>
gdt(x86lp->gdtStart() + minTLSEntry * sizeof(uint64_t),
numTLSEntries * sizeof(uint64_t));
gdt(x86p->gdtStart() + minTLSEntry * sizeof(uint64_t),
numTLSEntries * sizeof(uint64_t));
if (!userDesc.copyIn(tc->getMemProxy()))
return -EFAULT;
@ -242,18 +242,18 @@ static SyscallDesc syscallDescs64[] = {
/* 19 */ SyscallDesc("readv", unimplementedFunc),
/* 20 */ SyscallDesc("writev", writevFunc<X86Linux64>),
/* 21 */ SyscallDesc("access", ignoreFunc),
/* 22 */ SyscallDesc("pipe", unimplementedFunc),
/* 22 */ SyscallDesc("pipe", pipeFunc),
/* 23 */ SyscallDesc("select", unimplementedFunc),
/* 24 */ SyscallDesc("sched_yield", unimplementedFunc),
/* 24 */ SyscallDesc("sched_yield", ignoreFunc),
/* 25 */ SyscallDesc("mremap", mremapFunc<X86Linux64>),
/* 26 */ SyscallDesc("msync", unimplementedFunc),
/* 27 */ SyscallDesc("mincore", unimplementedFunc),
/* 28 */ SyscallDesc("madvise", unimplementedFunc),
/* 28 */ SyscallDesc("madvise", ignoreFunc),
/* 29 */ SyscallDesc("shmget", unimplementedFunc),
/* 30 */ SyscallDesc("shmat", unimplementedFunc),
/* 31 */ SyscallDesc("shmctl", unimplementedFunc),
/* 32 */ SyscallDesc("dup", dupFunc),
/* 33 */ SyscallDesc("dup2", unimplementedFunc),
/* 33 */ SyscallDesc("dup2", dup2Func),
/* 34 */ SyscallDesc("pause", unimplementedFunc),
/* 35 */ SyscallDesc("nanosleep", ignoreFunc, SyscallDesc::WarnOnce),
/* 36 */ SyscallDesc("getitimer", unimplementedFunc),
@ -276,10 +276,10 @@ static SyscallDesc syscallDescs64[] = {
/* 53 */ SyscallDesc("socketpair", unimplementedFunc),
/* 54 */ SyscallDesc("setsockopt", unimplementedFunc),
/* 55 */ SyscallDesc("getsockopt", unimplementedFunc),
/* 56 */ SyscallDesc("clone", cloneFunc),
/* 56 */ SyscallDesc("clone", cloneFunc<X86Linux64>),
/* 57 */ SyscallDesc("fork", unimplementedFunc),
/* 58 */ SyscallDesc("vfork", unimplementedFunc),
/* 59 */ SyscallDesc("execve", unimplementedFunc),
/* 59 */ SyscallDesc("execve", execveFunc<X86Linux64>),
/* 60 */ SyscallDesc("exit", exitFunc),
/* 61 */ SyscallDesc("wait4", unimplementedFunc),
/* 62 */ SyscallDesc("kill", unimplementedFunc),
@ -329,7 +329,7 @@ static SyscallDesc syscallDescs64[] = {
/* 106 */ SyscallDesc("setgid", unimplementedFunc),
/* 107 */ SyscallDesc("geteuid", geteuidFunc),
/* 108 */ SyscallDesc("getegid", getegidFunc),
/* 109 */ SyscallDesc("setpgid", unimplementedFunc),
/* 109 */ SyscallDesc("setpgid", setpgidFunc),
/* 110 */ SyscallDesc("getppid", getppidFunc),
/* 111 */ SyscallDesc("getpgrp", unimplementedFunc),
/* 112 */ SyscallDesc("setsid", unimplementedFunc),
@ -337,7 +337,7 @@ static SyscallDesc syscallDescs64[] = {
/* 114 */ SyscallDesc("setregid", unimplementedFunc),
/* 115 */ SyscallDesc("getgroups", unimplementedFunc),
/* 116 */ SyscallDesc("setgroups", unimplementedFunc),
/* 117 */ SyscallDesc("setresuid", unimplementedFunc),
/* 117 */ SyscallDesc("setresuid", ignoreFunc),
/* 118 */ SyscallDesc("getresuid", unimplementedFunc),
/* 119 */ SyscallDesc("setresgid", unimplementedFunc),
/* 120 */ SyscallDesc("getresgid", unimplementedFunc),
@ -361,7 +361,7 @@ static SyscallDesc syscallDescs64[] = {
/* 138 */ SyscallDesc("fstatfs", unimplementedFunc),
/* 139 */ SyscallDesc("sysfs", unimplementedFunc),
/* 140 */ SyscallDesc("getpriority", unimplementedFunc),
/* 141 */ SyscallDesc("setpriority", unimplementedFunc),
/* 141 */ SyscallDesc("setpriority", ignoreFunc),
/* 142 */ SyscallDesc("sched_setparam", unimplementedFunc),
/* 143 */ SyscallDesc("sched_getparam", unimplementedFunc),
/* 144 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
@ -406,7 +406,7 @@ static SyscallDesc syscallDescs64[] = {
/* 183 */ SyscallDesc("afs_syscall", unimplementedFunc),
/* 184 */ SyscallDesc("tuxcall", unimplementedFunc),
/* 185 */ SyscallDesc("security", unimplementedFunc),
/* 186 */ SyscallDesc("gettid", unimplementedFunc),
/* 186 */ SyscallDesc("gettid", gettidFunc),
/* 187 */ SyscallDesc("readahead", unimplementedFunc),
/* 188 */ SyscallDesc("setxattr", unimplementedFunc),
/* 189 */ SyscallDesc("lsetxattr", unimplementedFunc),
@ -424,7 +424,7 @@ static SyscallDesc syscallDescs64[] = {
/* 201 */ SyscallDesc("time", timeFunc<X86Linux64>),
/* 202 */ SyscallDesc("futex", futexFunc<X86Linux64>),
/* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
/* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
/* 204 */ SyscallDesc("sched_getaffinity", ignoreFunc),
/* 205 */ SyscallDesc("set_thread_area", unimplementedFunc),
/* 206 */ SyscallDesc("io_setup", unimplementedFunc),
/* 207 */ SyscallDesc("io_destroy", unimplementedFunc),
@ -438,7 +438,7 @@ static SyscallDesc syscallDescs64[] = {
/* 215 */ SyscallDesc("epoll_wait_old", unimplementedFunc),
/* 216 */ SyscallDesc("remap_file_pages", unimplementedFunc),
/* 217 */ SyscallDesc("getdents64", unimplementedFunc),
/* 218 */ SyscallDesc("set_tid_address", unimplementedFunc),
/* 218 */ SyscallDesc("set_tid_address", setTidAddressFunc),
/* 219 */ SyscallDesc("restart_syscall", unimplementedFunc),
/* 220 */ SyscallDesc("semtimedop", unimplementedFunc),
/* 221 */ SyscallDesc("fadvise64", unimplementedFunc),
@ -454,12 +454,12 @@ static SyscallDesc syscallDescs64[] = {
/* 231 */ SyscallDesc("exit_group", exitGroupFunc),
/* 232 */ SyscallDesc("epoll_wait", unimplementedFunc),
/* 233 */ SyscallDesc("epoll_ctl", unimplementedFunc),
/* 234 */ SyscallDesc("tgkill", unimplementedFunc),
/* 234 */ SyscallDesc("tgkill", tgkillFunc<X86Linux64>),
/* 235 */ SyscallDesc("utimes", unimplementedFunc),
/* 236 */ SyscallDesc("vserver", unimplementedFunc),
/* 237 */ SyscallDesc("mbind", unimplementedFunc),
/* 238 */ SyscallDesc("set_mempolicy", unimplementedFunc),
/* 239 */ SyscallDesc("get_mempolicy", unimplementedFunc),
/* 239 */ SyscallDesc("get_mempolicy", ignoreFunc),
/* 240 */ SyscallDesc("mq_open", unimplementedFunc),
/* 241 */ SyscallDesc("mq_unlink", unimplementedFunc),
/* 242 */ SyscallDesc("mq_timedsend", unimplementedFunc),
@ -477,7 +477,7 @@ static SyscallDesc syscallDescs64[] = {
/* 254 */ SyscallDesc("inotify_add_watch", unimplementedFunc),
/* 255 */ SyscallDesc("inotify_rm_watch", unimplementedFunc),
/* 256 */ SyscallDesc("migrate_pages", unimplementedFunc),
/* 257 */ SyscallDesc("openat", unimplementedFunc),
/* 257 */ SyscallDesc("openat", openatFunc<X86Linux64>),
/* 258 */ SyscallDesc("mkdirat", unimplementedFunc),
/* 259 */ SyscallDesc("mknodat", unimplementedFunc),
/* 260 */ SyscallDesc("fchownat", unimplementedFunc),
@ -493,7 +493,7 @@ static SyscallDesc syscallDescs64[] = {
/* 270 */ SyscallDesc("pselect6", unimplementedFunc),
/* 271 */ SyscallDesc("ppoll", unimplementedFunc),
/* 272 */ SyscallDesc("unshare", unimplementedFunc),
/* 273 */ SyscallDesc("set_robust_list", unimplementedFunc),
/* 273 */ SyscallDesc("set_robust_list", ignoreFunc),
/* 274 */ SyscallDesc("get_robust_list", unimplementedFunc),
/* 275 */ SyscallDesc("splice", unimplementedFunc),
/* 276 */ SyscallDesc("tee", unimplementedFunc),
@ -536,12 +536,18 @@ static SyscallDesc syscallDescs64[] = {
/* 313 */ SyscallDesc("finit_module", unimplementedFunc),
};
X86_64LinuxProcess::X86_64LinuxProcess(LiveProcessParams * params,
ObjectFile *objFile)
: X86_64LiveProcess(params, objFile, syscallDescs64,
sizeof(syscallDescs64) / sizeof(SyscallDesc))
X86_64LinuxProcess::X86_64LinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: X86_64Process(params, objFile, syscallDescs64,
sizeof(syscallDescs64) / sizeof(SyscallDesc))
{}
void X86_64LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, TheISA::IntReg flags)
{
X86_64Process::clone(old_tc, new_tc, (X86_64Process*)process, flags);
}
static SyscallDesc syscallDescs32[] = {
/* 0 */ SyscallDesc("restart_syscall", unimplementedFunc),
/* 1 */ SyscallDesc("exit", exitFunc),
@ -554,7 +560,7 @@ static SyscallDesc syscallDescs32[] = {
/* 8 */ SyscallDesc("creat", unimplementedFunc),
/* 9 */ SyscallDesc("link", unimplementedFunc),
/* 10 */ SyscallDesc("unlink", unimplementedFunc),
/* 11 */ SyscallDesc("execve", unimplementedFunc),
/* 11 */ SyscallDesc("execve", execveFunc<X86Linux32>),
/* 12 */ SyscallDesc("chdir", unimplementedFunc),
/* 13 */ SyscallDesc("time", timeFunc<X86Linux32>),
/* 14 */ SyscallDesc("mknod", unimplementedFunc),
@ -563,7 +569,7 @@ static SyscallDesc syscallDescs32[] = {
/* 17 */ SyscallDesc("break", unimplementedFunc),
/* 18 */ SyscallDesc("oldstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", unimplementedFunc),
/* 20 */ SyscallDesc("getpid", unimplementedFunc),
/* 20 */ SyscallDesc("getpid", getpidFunc),
/* 21 */ SyscallDesc("mount", unimplementedFunc),
/* 22 */ SyscallDesc("umount", unimplementedFunc),
/* 23 */ SyscallDesc("setuid", unimplementedFunc),
@ -585,7 +591,7 @@ static SyscallDesc syscallDescs32[] = {
/* 39 */ SyscallDesc("mkdir", unimplementedFunc),
/* 40 */ SyscallDesc("rmdir", unimplementedFunc),
/* 41 */ SyscallDesc("dup", dupFunc),
/* 42 */ SyscallDesc("pipe", unimplementedFunc),
/* 42 */ SyscallDesc("pipe", pipeFunc),
/* 43 */ SyscallDesc("times", timesFunc<X86Linux32>),
/* 44 */ SyscallDesc("prof", unimplementedFunc),
/* 45 */ SyscallDesc("brk", brkFunc),
@ -598,15 +604,15 @@ static SyscallDesc syscallDescs32[] = {
/* 52 */ SyscallDesc("umount2", unimplementedFunc),
/* 53 */ SyscallDesc("lock", unimplementedFunc),
/* 54 */ SyscallDesc("ioctl", ioctlFunc<X86Linux32>),
/* 55 */ SyscallDesc("fcntl", unimplementedFunc),
/* 55 */ SyscallDesc("fcntl", fcntlFunc),
/* 56 */ SyscallDesc("mpx", unimplementedFunc),
/* 57 */ SyscallDesc("setpgid", unimplementedFunc),
/* 57 */ SyscallDesc("setpgid", setpgidFunc),
/* 58 */ SyscallDesc("ulimit", unimplementedFunc),
/* 59 */ SyscallDesc("oldolduname", unimplementedFunc),
/* 60 */ SyscallDesc("umask", unimplementedFunc),
/* 61 */ SyscallDesc("chroot", unimplementedFunc),
/* 62 */ SyscallDesc("ustat", unimplementedFunc),
/* 63 */ SyscallDesc("dup2", unimplementedFunc),
/* 63 */ SyscallDesc("dup2", dup2Func),
/* 64 */ SyscallDesc("getppid", unimplementedFunc),
/* 65 */ SyscallDesc("getpgrp", unimplementedFunc),
/* 66 */ SyscallDesc("setsid", unimplementedFunc),
@ -640,9 +646,9 @@ static SyscallDesc syscallDescs32[] = {
/* 94 */ SyscallDesc("fchmod", unimplementedFunc),
/* 95 */ SyscallDesc("fchown", unimplementedFunc),
/* 96 */ SyscallDesc("getpriority", unimplementedFunc),
/* 97 */ SyscallDesc("setpriority", unimplementedFunc),
/* 97 */ SyscallDesc("setpriority", ignoreFunc),
/* 98 */ SyscallDesc("profil", unimplementedFunc),
/* 99 */ SyscallDesc("statfs", unimplementedFunc),
/* 99 */ SyscallDesc("statfs", ignoreFunc),
/* 100 */ SyscallDesc("fstatfs", unimplementedFunc),
/* 101 */ SyscallDesc("ioperm", unimplementedFunc),
/* 102 */ SyscallDesc("socketcall", unimplementedFunc),
@ -663,7 +669,7 @@ static SyscallDesc syscallDescs32[] = {
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
/* 120 */ SyscallDesc("clone", unimplementedFunc),
/* 120 */ SyscallDesc("clone", cloneFunc<X86Linux32>),
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
/* 122 */ SyscallDesc("uname", unameFunc),
/* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
@ -701,13 +707,13 @@ static SyscallDesc syscallDescs32[] = {
/* 155 */ SyscallDesc("sched_getparam", unimplementedFunc),
/* 156 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
/* 157 */ SyscallDesc("sched_getscheduler", unimplementedFunc),
/* 158 */ SyscallDesc("sched_yield", unimplementedFunc),
/* 158 */ SyscallDesc("sched_yield", ignoreFunc),
/* 159 */ SyscallDesc("sched_get_priority_max", unimplementedFunc),
/* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
/* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
/* 162 */ SyscallDesc("nanosleep", unimplementedFunc),
/* 162 */ SyscallDesc("nanosleep", ignoreFunc),
/* 163 */ SyscallDesc("mremap", unimplementedFunc),
/* 164 */ SyscallDesc("setresuid", unimplementedFunc),
/* 164 */ SyscallDesc("setresuid", ignoreFunc),
/* 165 */ SyscallDesc("getresuid", unimplementedFunc),
/* 166 */ SyscallDesc("vm86", unimplementedFunc),
/* 167 */ SyscallDesc("query_module", unimplementedFunc),
@ -762,12 +768,12 @@ static SyscallDesc syscallDescs32[] = {
/* 216 */ SyscallDesc("setfsgid32", unimplementedFunc),
/* 217 */ SyscallDesc("pivot_root", unimplementedFunc),
/* 218 */ SyscallDesc("mincore", unimplementedFunc),
/* 219 */ SyscallDesc("madvise", unimplementedFunc),
/* 219 */ SyscallDesc("madvise", ignoreFunc),
/* 220 */ SyscallDesc("madvise1", unimplementedFunc),
/* 221 */ SyscallDesc("getdents64", unimplementedFunc),
/* 222 */ SyscallDesc("fcntl64", unimplementedFunc),
/* 223 */ SyscallDesc("unused", unimplementedFunc),
/* 224 */ SyscallDesc("gettid", unimplementedFunc),
/* 224 */ SyscallDesc("gettid", gettidFunc),
/* 225 */ SyscallDesc("readahead", unimplementedFunc),
/* 226 */ SyscallDesc("setxattr", unimplementedFunc),
/* 227 */ SyscallDesc("lsetxattr", unimplementedFunc),
@ -785,7 +791,7 @@ static SyscallDesc syscallDescs32[] = {
/* 239 */ SyscallDesc("sendfile64", unimplementedFunc),
/* 240 */ SyscallDesc("futex", unimplementedFunc),
/* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
/* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
/* 242 */ SyscallDesc("sched_getaffinity", ignoreFunc),
/* 243 */ SyscallDesc("set_thread_area", setThreadArea32Func),
/* 244 */ SyscallDesc("get_thread_area", unimplementedFunc),
/* 245 */ SyscallDesc("io_setup", unimplementedFunc),
@ -801,7 +807,7 @@ static SyscallDesc syscallDescs32[] = {
/* 255 */ SyscallDesc("epoll_ctl", unimplementedFunc),
/* 256 */ SyscallDesc("epoll_wait", unimplementedFunc),
/* 257 */ SyscallDesc("remap_file_pages", unimplementedFunc),
/* 258 */ SyscallDesc("set_tid_address", unimplementedFunc),
/* 258 */ SyscallDesc("set_tid_address", setTidAddressFunc),
/* 259 */ SyscallDesc("timer_create", unimplementedFunc),
/* 260 */ SyscallDesc("timer_settime", unimplementedFunc),
/* 261 */ SyscallDesc("timer_gettime", unimplementedFunc),
@ -813,12 +819,12 @@ static SyscallDesc syscallDescs32[] = {
/* 267 */ SyscallDesc("clock_nanosleep", unimplementedFunc),
/* 268 */ SyscallDesc("statfs64", unimplementedFunc),
/* 269 */ SyscallDesc("fstatfs64", unimplementedFunc),
/* 270 */ SyscallDesc("tgkill", unimplementedFunc),
/* 270 */ SyscallDesc("tgkill", tgkillFunc<X86Linux32>),
/* 271 */ SyscallDesc("utimes", unimplementedFunc),
/* 272 */ SyscallDesc("fadvise64_64", unimplementedFunc),
/* 273 */ SyscallDesc("vserver", unimplementedFunc),
/* 274 */ SyscallDesc("mbind", unimplementedFunc),
/* 275 */ SyscallDesc("get_mempolicy", unimplementedFunc),
/* 275 */ SyscallDesc("get_mempolicy", ignoreFunc),
/* 276 */ SyscallDesc("set_mempolicy", unimplementedFunc),
/* 277 */ SyscallDesc("mq_open", unimplementedFunc),
/* 278 */ SyscallDesc("mq_unlink", unimplementedFunc),
@ -838,7 +844,7 @@ static SyscallDesc syscallDescs32[] = {
/* 292 */ SyscallDesc("inotify_add_watch", unimplementedFunc),
/* 293 */ SyscallDesc("inotify_rm_watch", unimplementedFunc),
/* 294 */ SyscallDesc("migrate_pages", unimplementedFunc),
/* 295 */ SyscallDesc("openat", unimplementedFunc),
/* 295 */ SyscallDesc("openat", openatFunc<X86Linux32>),
/* 296 */ SyscallDesc("mkdirat", unimplementedFunc),
/* 297 */ SyscallDesc("mknodat", unimplementedFunc),
/* 298 */ SyscallDesc("fchownat", unimplementedFunc),
@ -854,8 +860,8 @@ static SyscallDesc syscallDescs32[] = {
/* 308 */ SyscallDesc("pselect6", unimplementedFunc),
/* 309 */ SyscallDesc("ppoll", unimplementedFunc),
/* 310 */ SyscallDesc("unshare", unimplementedFunc),
/* 311 */ SyscallDesc("set_robust_list", unimplementedFunc),
/* 312 */ SyscallDesc("get_robust_list", unimplementedFunc),
/* 311 */ SyscallDesc("set_robust_list", ignoreFunc),
/* 312 */ SyscallDesc("get_robust_list", ignoreFunc),
/* 313 */ SyscallDesc("splice", unimplementedFunc),
/* 314 */ SyscallDesc("sync_file_range", unimplementedFunc),
/* 315 */ SyscallDesc("tee", unimplementedFunc),
@ -869,8 +875,13 @@ static SyscallDesc syscallDescs32[] = {
/* 323 */ SyscallDesc("eventfd", unimplementedFunc)
};
I386LinuxProcess::I386LinuxProcess(LiveProcessParams * params,
ObjectFile *objFile)
: I386LiveProcess(params, objFile, syscallDescs32,
sizeof(syscallDescs32) / sizeof(SyscallDesc))
I386LinuxProcess::I386LinuxProcess(ProcessParams * params, ObjectFile *objFile)
: I386Process(params, objFile, syscallDescs32,
sizeof(syscallDescs32) / sizeof(SyscallDesc))
{}
void I386LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, TheISA::IntReg flags)
{
I386Process::clone(old_tc, new_tc, (I386Process*)process, flags);
}

View File

@ -44,20 +44,27 @@
#include "arch/x86/process.hh"
#include "sim/process.hh"
struct ProcessParams;
struct ThreadContext;
namespace X86ISA {
class X86_64LinuxProcess : public X86_64LiveProcess
class X86_64LinuxProcess : public X86_64Process
{
public:
/// Constructor.
X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
X86_64LinuxProcess(ProcessParams * params, ObjectFile *objFile);
void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *process,
TheISA::IntReg flags);
};
class I386LinuxProcess : public I386LiveProcess
class I386LinuxProcess : public I386Process
{
public:
/// Constructor.
I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
I386LinuxProcess(ProcessParams * params, ObjectFile *objFile);
void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *process,
TheISA::IntReg flags);
};
} // namespace X86ISA

View File

@ -44,6 +44,9 @@
#include "arch/x86/process.hh"
#include <string>
#include <vector>
#include "arch/x86/isa_traits.hh"
#include "arch/x86/regs/misc.hh"
#include "arch/x86/regs/segment.hh"
@ -57,6 +60,7 @@
#include "debug/Stack.hh"
#include "mem/multi_level_page_table.hh"
#include "mem/page_table.hh"
#include "sim/aux_vector.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_desc.hh"
#include "sim/syscall_return.hh"
@ -69,9 +73,9 @@ static const int ArgumentReg[] = {
INTREG_RDI,
INTREG_RSI,
INTREG_RDX,
//This argument register is r10 for syscalls and rcx for C.
// This argument register is r10 for syscalls and rcx for C.
INTREG_R10W,
//INTREG_RCX,
// INTREG_RCX,
INTREG_R8W,
INTREG_R9W
};
@ -91,19 +95,24 @@ static const int ArgumentReg32[] = {
static const int NumArgumentRegs32 M5_VAR_USED =
sizeof(ArgumentReg) / sizeof(const int);
X86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs) :
LiveProcess(params, objFile), syscallDescs(_syscallDescs),
numSyscallDescs(_numSyscallDescs)
X86Process::X86Process(ProcessParams * params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs)
: Process(params, objFile), syscallDescs(_syscallDescs),
numSyscallDescs(_numSyscallDescs)
{
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
}
X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
ObjectFile *objFile, SyscallDesc *_syscallDescs,
int _numSyscallDescs) :
X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
void X86Process::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *p, TheISA::IntReg flags)
{
Process::clone(old_tc, new_tc, p, flags);
X86Process *process = (X86Process*)p;
*process = *this;
}
X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs)
: X86Process(params, objFile, _syscallDescs, _numSyscallDescs)
{
vsyscallPage.base = 0xffffffffff600000ULL;
@ -111,27 +120,19 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
vsyscallPage.vtimeOffset = 0x400;
vsyscallPage.vgettimeofdayOffset = 0x0;
// Set up stack. On X86_64 Linux, stack goes from the top of memory
// downward, less the hole for the kernel address space plus one page
// for undertermined purposes.
stack_base = (Addr)0x7FFFFFFFF000ULL;
Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() +
objFile->bssSize(), PageBytes);
Addr stack_base = 0x7FFFFFFFF000ULL;
Addr max_stack_size = 8 * 1024 * 1024;
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0x7FFFF7FFF000ULL;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// "mmap_base" is a function which defines where mmap region starts in
// the process address space.
// mmap_base: PAGE_ALIGN(TASK_SIZE-MIN_GAP-mmap_rnd())
// TASK_SIZE: (1<<47)-PAGE_SIZE
// MIN_GAP: 128*1024*1024+stack_maxrandom_size()
// We do not use any address space layout randomization in gem5
// therefore the random fields become zero; the smallest gap space was
// chosen but gap could potentially be much larger.
mmap_end = (Addr)0x7FFFF7FFF000ULL;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
void
I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
I386Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault)
{
TheISA::PCState pc = tc->pcState();
Addr eip = pc.pc();
@ -140,14 +141,13 @@ I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset);
tc->pcState(pc);
}
X86LiveProcess::syscall(callnum, tc);
X86Process::syscall(callnum, tc, fault);
}
I386LiveProcess::I386LiveProcess(LiveProcessParams *params,
ObjectFile *objFile, SyscallDesc *_syscallDescs,
int _numSyscallDescs) :
X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
I386Process::I386Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs)
: X86Process(params, objFile, _syscallDescs, _numSyscallDescs)
{
_gdtStart = ULL(0xffffd000);
_gdtSize = PageBytes;
@ -157,24 +157,19 @@ I386LiveProcess::I386LiveProcess(LiveProcessParams *params,
vsyscallPage.vsyscallOffset = 0x400;
vsyscallPage.vsysexitOffset = 0x410;
stack_base = _gdtStart;
Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() +
objFile->bssSize(), PageBytes);
Addr stack_base = _gdtStart;
Addr max_stack_size = 8 * 1024 * 1024;
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0xB7FFF000ULL;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
// "mmap_base" is a function which defines where mmap region starts in
// the process address space.
// mmap_base: PAGE_ALIGN(TASK_SIZE-MIN_GAP-mmap_rnd())
// TASK_SIZE: 0xC0000000
// MIN_GAP: 128*1024*1024+stack_maxrandom_size()
// We do not use any address space layout randomization in gem5
// therefore the random fields become zero; the smallest gap space was
// chosen but gap could potentially be much larger.
mmap_end = (Addr)0xB7FFF000ULL;
memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
next_thread_stack_base, mmap_end);
}
SyscallDesc*
X86LiveProcess::getDesc(int callnum)
X86Process::getDesc(int callnum)
{
if (callnum < 0 || callnum >= numSyscallDescs)
return NULL;
@ -182,13 +177,13 @@ X86LiveProcess::getDesc(int callnum)
}
void
X86_64LiveProcess::initState()
X86_64Process::initState()
{
X86LiveProcess::initState();
X86Process::initState();
argsInit(sizeof(uint64_t), PageBytes);
argsInit(PageBytes);
// Set up the vsyscall page for this process.
// Set up the vsyscall page for this process.
allocateMem(vsyscallPage.base, vsyscallPage.size);
uint8_t vtimeBlob[] = {
0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax
@ -571,7 +566,7 @@ X86_64LiveProcess::initState()
dataAttr.expandDown = 0;
dataAttr.system = 1;
//Initialize the segment registers.
// Initialize the segment registers.
for (int seg = 0; seg < NUM_SEGMENTREGS; seg++) {
tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0);
tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0);
@ -603,7 +598,7 @@ X86_64LiveProcess::initState()
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
tc->setMiscReg(MISCREG_EFER, efer);
//Set up the registers that describe the operating mode.
// Set up the registers that describe the operating mode.
CR0 cr0 = 0;
cr0.pg = 1; // Turn on paging.
cr0.cd = 0; // Don't disable caching.
@ -626,11 +621,11 @@ X86_64LiveProcess::initState()
}
void
I386LiveProcess::initState()
I386Process::initState()
{
X86LiveProcess::initState();
X86Process::initState();
argsInit(sizeof(uint32_t), PageBytes);
argsInit(PageBytes);
/*
* Set up a GDT for this process. The whole GDT wouldn't really be for
@ -682,7 +677,7 @@ I386LiveProcess::initState()
dataAttr.expandDown = 0;
dataAttr.system = 1;
//Initialize the segment registers.
// Initialize the segment registers.
for (int seg = 0; seg < NUM_SEGMENTREGS; seg++) {
tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0);
tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0);
@ -723,7 +718,7 @@ I386LiveProcess::initState()
efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
tc->setMiscReg(MISCREG_EFER, efer);
//Set up the registers that describe the operating mode.
// Set up the registers that describe the operating mode.
CR0 cr0 = 0;
cr0.pg = 1; // Turn on paging.
cr0.cd = 0; // Don't disable caching.
@ -746,8 +741,8 @@ I386LiveProcess::initState()
template<class IntType>
void
X86LiveProcess::argsInit(int pageSize,
std::vector<AuxVector<IntType> > extraAuxvs)
X86Process::argsInit(int pageSize,
std::vector<AuxVector<IntType> > extraAuxvs)
{
int intSize = sizeof(IntType);
@ -760,7 +755,7 @@ X86LiveProcess::argsInit(int pageSize,
else
filename = argv[0];
//We want 16 byte alignment
// We want 16 byte alignment
uint64_t align = 16;
// Patch the ld_bias for dynamic executables.
@ -846,13 +841,13 @@ X86LiveProcess::argsInit(int pageSize,
// X86_IA64Processor |
0;
//Bits which describe the system hardware capabilities
//XXX Figure out what these should be
// Bits which describe the system hardware capabilities
// XXX Figure out what these should be
auxv.push_back(auxv_t(M5_AT_HWCAP, features));
//The system page size
// The system page size
auxv.push_back(auxv_t(M5_AT_PAGESZ, X86ISA::PageBytes));
//Frequency at which times() increments
//Defined to be 100 in the kernel source.
// Frequency at which times() increments
// Defined to be 100 in the kernel source.
auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
// This is the virtual address of the program header tables if they
// appear in the executable image.
@ -865,32 +860,32 @@ X86LiveProcess::argsInit(int pageSize,
// zero for static executables or contain the base address for
// dynamic executables.
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
//XXX Figure out what this should be.
// XXX Figure out what this should be.
auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
//The entry point to the program
// The entry point to the program
auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
//Different user and group IDs
// Different user and group IDs
auxv.push_back(auxv_t(M5_AT_UID, uid()));
auxv.push_back(auxv_t(M5_AT_EUID, euid()));
auxv.push_back(auxv_t(M5_AT_GID, gid()));
auxv.push_back(auxv_t(M5_AT_EGID, egid()));
//Whether to enable "secure mode" in the executable
// Whether to enable "secure mode" in the executable
auxv.push_back(auxv_t(M5_AT_SECURE, 0));
//The address of 16 "random" bytes.
// The address of 16 "random" bytes.
auxv.push_back(auxv_t(M5_AT_RANDOM, 0));
//The name of the program
// The name of the program
auxv.push_back(auxv_t(M5_AT_EXECFN, 0));
//The platform string
// The platform string
auxv.push_back(auxv_t(M5_AT_PLATFORM, 0));
}
//Figure out how big the initial stack needs to be
// Figure out how big the initial stack needs to be
// A sentry NULL void pointer at the top of the stack.
int sentry_size = intSize;
//This is the name of the file which is present on the initial stack
//It's purpose is to let the user space linker examine the original file.
// This is the name of the file which is present on the initial stack
// It's purpose is to let the user space linker examine the original file.
int file_name_size = filename.size() + 1;
const int numRandomBytes = 16;
@ -906,10 +901,10 @@ X86LiveProcess::argsInit(int pageSize,
for (int i = 0; i < argv.size(); ++i)
arg_data_size += argv[i].size() + 1;
//The info_block needs to be padded so it's size is a multiple of the
//alignment mask. Also, it appears that there needs to be at least some
//padding, so if the size is already a multiple, we need to increase it
//anyway.
// The info_block needs to be padded so its size is a multiple of the
// alignment mask. Also, it appears that there needs to be at least some
// padding, so if the size is already a multiple, we need to increase it
// anyway.
int base_info_block_size =
sentry_size + file_name_size + env_data_size + arg_data_size;
@ -917,7 +912,7 @@ X86LiveProcess::argsInit(int pageSize,
int info_block_padding = info_block_size - base_info_block_size;
//Each auxilliary vector is two 8 byte words
// Each auxiliary vector is two 8 byte words
int aux_array_size = intSize * 2 * (auxv.size() + 1);
int envp_array_size = intSize * (envp.size() + 1);
@ -925,15 +920,15 @@ X86LiveProcess::argsInit(int pageSize,
int argc_size = intSize;
//Figure out the size of the contents of the actual initial frame
// Figure out the size of the contents of the actual initial frame
int frame_size =
aux_array_size +
envp_array_size +
argv_array_size +
argc_size;
//There needs to be padding after the auxiliary vector data so that the
//very bottom of the stack is aligned properly.
// There needs to be padding after the auxiliary vector data so that the
// very bottom of the stack is aligned properly.
int partial_size = frame_size + aux_data_size;
int aligned_partial_size = roundUp(partial_size, align);
int aux_padding = aligned_partial_size - partial_size;
@ -944,9 +939,14 @@ X86LiveProcess::argsInit(int pageSize,
aux_padding +
frame_size;
stack_min = stack_base - space_needed;
Addr stack_base = memState->getStackBase();
Addr stack_min = stack_base - space_needed;
stack_min = roundDown(stack_min, align);
stack_size = roundUp(stack_base - stack_min, pageSize);
unsigned stack_size = stack_base - stack_min;
stack_size = roundUp(stack_size, pageSize);
memState->setStackSize(stack_size);
// map memory
Addr stack_end = roundDown(stack_base - stack_size, pageSize);
@ -982,15 +982,14 @@ X86LiveProcess::argsInit(int pageSize,
IntType argc = argv.size();
IntType guestArgc = X86ISA::htog(argc);
//Write out the sentry void *
// Write out the sentry void *
IntType sentry_NULL = 0;
initVirtMem.writeBlob(sentry_base,
(uint8_t*)&sentry_NULL, sentry_size);
initVirtMem.writeBlob(sentry_base, (uint8_t*)&sentry_NULL, sentry_size);
//Write the file name
// Write the file name
initVirtMem.writeString(file_name_base, filename.c_str());
//Fix up the aux vectors which point to data
// Fix up the aux vectors which point to data
assert(auxv[auxv.size() - 3].a_type == M5_AT_RANDOM);
auxv[auxv.size() - 3].a_val = aux_data_base;
assert(auxv[auxv.size() - 2].a_type == M5_AT_EXECFN);
@ -998,14 +997,15 @@ X86LiveProcess::argsInit(int pageSize,
assert(auxv[auxv.size() - 1].a_type == M5_AT_PLATFORM);
auxv[auxv.size() - 1].a_val = aux_data_base + numRandomBytes;
//Copy the aux stuff
// Copy the aux stuff
for (int x = 0; x < auxv.size(); x++) {
initVirtMem.writeBlob(auxv_array_base + x * 2 * intSize,
(uint8_t*)&(auxv[x].a_type), intSize);
initVirtMem.writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
(uint8_t*)&(auxv[x].a_val), intSize);
}
//Write out the terminating zeroed auxilliary vector
// Write out the terminating zeroed auxiliary vector
const uint64_t zero = 0;
initVirtMem.writeBlob(auxv_array_base + auxv.size() * 2 * intSize,
(uint8_t*)&zero, intSize);
@ -1020,30 +1020,28 @@ X86LiveProcess::argsInit(int pageSize,
initVirtMem.writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
ThreadContext *tc = system->getThreadContext(contextIds[0]);
//Set the stack pointer register
// Set the stack pointer register
tc->setIntReg(StackPointerReg, stack_min);
// There doesn't need to be any segment base added in since we're dealing
// with the flat segmentation model.
tc->pcState(getStartPC());
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
// num_processes++;
// Align the "stack_min" to a page boundary.
memState->setStackMin(roundDown(stack_min, pageSize));
}
void
X86_64LiveProcess::argsInit(int intSize, int pageSize)
X86_64Process::argsInit(int pageSize)
{
std::vector<AuxVector<uint64_t> > extraAuxvs;
extraAuxvs.push_back(AuxVector<uint64_t>(M5_AT_SYSINFO_EHDR,
vsyscallPage.base));
X86LiveProcess::argsInit<uint64_t>(pageSize, extraAuxvs);
X86Process::argsInit<uint64_t>(pageSize, extraAuxvs);
}
void
I386LiveProcess::argsInit(int intSize, int pageSize)
I386Process::argsInit(int pageSize)
{
std::vector<AuxVector<uint32_t> > extraAuxvs;
//Tell the binary where the vsyscall part of the vsyscall page is.
@ -1051,38 +1049,46 @@ I386LiveProcess::argsInit(int intSize, int pageSize)
vsyscallPage.base + vsyscallPage.vsyscallOffset));
extraAuxvs.push_back(AuxVector<uint32_t>(M5_AT_SYSINFO_EHDR,
vsyscallPage.base));
X86LiveProcess::argsInit<uint32_t>(pageSize, extraAuxvs);
X86Process::argsInit<uint32_t>(pageSize, extraAuxvs);
}
void
X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn retval)
X86Process::setSyscallReturn(ThreadContext *tc, SyscallReturn retval)
{
tc->setIntReg(INTREG_RAX, retval.encodedValue());
}
X86ISA::IntReg
X86_64LiveProcess::getSyscallArg(ThreadContext *tc, int &i)
X86_64Process::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < NumArgumentRegs);
return tc->readIntReg(ArgumentReg[i++]);
}
void
X86_64LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
X86_64Process::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
{
assert(i < NumArgumentRegs);
return tc->setIntReg(ArgumentReg[i], val);
}
void
X86_64Process::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *p, TheISA::IntReg flags)
{
X86Process::clone(old_tc, new_tc, p, flags);
((X86_64Process*)p)->vsyscallPage = vsyscallPage;
}
X86ISA::IntReg
I386LiveProcess::getSyscallArg(ThreadContext *tc, int &i)
I386Process::getSyscallArg(ThreadContext *tc, int &i)
{
assert(i < NumArgumentRegs32);
return tc->readIntReg(ArgumentReg32[i++]);
}
X86ISA::IntReg
I386LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
I386Process::getSyscallArg(ThreadContext *tc, int &i, int width)
{
assert(width == 32 || width == 64);
assert(i < NumArgumentRegs);
@ -1093,8 +1099,16 @@ I386LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
}
void
I386LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
I386Process::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
{
assert(i < NumArgumentRegs);
return tc->setIntReg(ArgumentReg[i], val);
}
void
I386Process::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *p, TheISA::IntReg flags)
{
X86Process::clone(old_tc, new_tc, p, flags);
((I386Process*)p)->vsyscallPage = vsyscallPage;
}

View File

@ -43,6 +43,7 @@
#include <string>
#include <vector>
#include "sim/aux_vector.hh"
#include "sim/process.hh"
#include "mem/multi_level_page_table.hh"
@ -55,7 +56,7 @@ namespace X86ISA
M5_AT_SYSINFO_EHDR = 33
};
class X86LiveProcess : public LiveProcess
class X86Process : public Process
{
protected:
Addr _gdtStart;
@ -64,12 +65,12 @@ namespace X86ISA
SyscallDesc *syscallDescs;
const int numSyscallDescs;
X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
X86Process(ProcessParams * params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
template<class IntType>
void argsInit(int pageSize,
std::vector<AuxVector<IntType> > extraAuxvs);
std::vector<AuxVector<IntType> > extraAuxvs);
public:
Addr gdtStart()
@ -81,13 +82,28 @@ namespace X86ISA
SyscallDesc* getDesc(int callnum);
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
void clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, TheISA::IntReg flags);
X86Process &
operator=(const X86Process &in)
{
if (this == &in)
return *this;
_gdtStart = in._gdtStart;
_gdtSize = in._gdtSize;
syscallDescs = in.syscallDescs;
return *this;
}
};
class X86_64LiveProcess : public X86LiveProcess
class X86_64Process : public X86Process
{
protected:
X86_64LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
X86_64Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
class VSyscallPage
{
@ -96,24 +112,40 @@ namespace X86ISA
Addr size;
Addr vtimeOffset;
Addr vgettimeofdayOffset;
VSyscallPage &
operator=(const VSyscallPage &in)
{
if (this == &in)
return *this;
base = in.base;
size = in.size;
vtimeOffset = in.vtimeOffset;
vgettimeofdayOffset = in.vgettimeofdayOffset;
return *this;
}
};
VSyscallPage vsyscallPage;
public:
void argsInit(int intSize, int pageSize);
void argsInit(int pageSize);
void initState();
X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using LiveProcess::getSyscallArg;
using Process::getSyscallArg;
void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
void clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, TheISA::IntReg flags);
};
class I386LiveProcess : public X86LiveProcess
class I386Process : public X86Process
{
protected:
I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
I386Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
class VSyscallPage
{
@ -122,17 +154,33 @@ namespace X86ISA
Addr size;
Addr vsyscallOffset;
Addr vsysexitOffset;
VSyscallPage &
operator=(const VSyscallPage &in)
{
if (this == &in)
return *this;
base = in.base;
size = in.size;
vsyscallOffset = in.vsyscallOffset;
vsysexitOffset = in.vsysexitOffset;
return *this;
}
};
VSyscallPage vsyscallPage;
public:
void argsInit(int intSize, int pageSize);
void argsInit(int pageSize);
void initState();
void syscall(int64_t callnum, ThreadContext *tc);
void syscall(int64_t callnum, ThreadContext *tc, Fault *fault);
X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width);
void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
void clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, TheISA::IntReg flags);
};
/**

View File

@ -49,7 +49,9 @@ m5Syscall(ThreadContext *tc)
{
DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n");
tc->syscall(tc->readIntReg(INTREG_RAX));
Fault fault;
tc->syscall(tc->readIntReg(INTREG_RAX), &fault);
MiscReg rflags = tc->readMiscReg(MISCREG_RFLAGS);
rflags &= ~(1 << 16);
tc->setMiscReg(MISCREG_RFLAGS, rflags);

View File

@ -231,13 +231,10 @@ TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
AddrRange m5opRange(0xFFFF0000, 0xFFFFFFFF);
if (m5opRange.contains(paddr)) {
if (m5opRange.contains(paddr)) {
req->setFlags(Request::MMAPPED_IPR | Request::GENERIC_IPR |
Request::STRICT_ORDER);
req->setPaddr(GenericISA::iprAddressPseudoInst(
(paddr >> 8) & 0xFF,
paddr & 0xFF));
}
req->setFlags(Request::MMAPPED_IPR | Request::GENERIC_IPR |
Request::STRICT_ORDER);
req->setPaddr(GenericISA::iprAddressPseudoInst((paddr >> 8) & 0xFF,
paddr & 0xFF));
} else if (FullSystem) {
// Check for an access to the local APIC
LocalApicBase localApicBase =

View File

@ -305,6 +305,13 @@ namespace X86ISA
PCState() {}
PCState(Addr val) { set(val); }
void
setNPC(Addr val)
{
Base::setNPC(val);
_size = 0;
}
uint8_t size() const { return _size; }
void size(uint8_t newSize) { _size = newSize; }

View File

@ -1,4 +1,16 @@
/*
* Copyright (c) 2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
@ -211,4 +223,29 @@ popCount(uint64_t val) {
return (val * sum) >> 56; // horizontal sum
#endif // defined(__GNUC__) || (defined(__clang__) && __has_builtin(__builtin_popcountl))
}
/**
* Align to the next highest power of two.
*
* The number passed in is aligned to the next highest power of two,
* if it is not already a power of two. Please note that if 0 is
* passed in, 0 is returned.
*
* This code has been modified from the following:
* http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
*/
inline uint64_t alignToPowerOfTwo(uint64_t val)
{
val--;
val |= val >> 1;
val |= val >> 2;
val |= val >> 4;
val |= val >> 8;
val |= val >> 16;
val |= val >> 32;
val++;
return val;
};
#endif // __BASE_BITFIELD_HH__

View File

@ -545,6 +545,8 @@ ElfObject::getSections()
sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
section = elf_getscn(elf, ++sec_idx);
} // while sections
elf_end(elf);
}
bool

Some files were not shown because too many files have changed in this diff Show More