summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'dev-util/stressapptest/files/stressapptest-1.0.6-channel-hash.patch')
-rw-r--r--dev-util/stressapptest/files/stressapptest-1.0.6-channel-hash.patch226
1 files changed, 226 insertions, 0 deletions
diff --git a/dev-util/stressapptest/files/stressapptest-1.0.6-channel-hash.patch b/dev-util/stressapptest/files/stressapptest-1.0.6-channel-hash.patch
new file mode 100644
index 000000000000..468d2d3b5101
--- /dev/null
+++ b/dev-util/stressapptest/files/stressapptest-1.0.6-channel-hash.patch
@@ -0,0 +1,226 @@
+From 7d1eaee59d311523757fb93ec59d8985ea15b54d Mon Sep 17 00:00:00 2001
+From: "nick.j.sanders" <nick.j.sanders@93e54ea4-8218-11de-8aaf-8d8425684b44>
+Date: Thu, 10 Jan 2013 23:42:36 +0000
+Subject: [PATCH] Replace interleave_size with channel_hash
+
+This patch replaces the previously introduced interleave_size memory
+channel decoding mechanism with a more powerful channel_hash. Decoding
+can now be based upon an arbitrary mask of address bits, which will be
+XORed together to determine the target channel. Note that this drops
+support for more than two channels, but TripleChannel controllers will
+probably use much more complicated decoding mechanisms anyway.
+
+It also includes the findmask program, which offers a crude method to
+guess the decoding mask from an unknown memory controller for enterprising
+users. Use at your own risk.
+
+Signed-off-by: Julius Werner <jwerner@chromium.org>
+
+
+git-svn-id: http://stressapptest.googlecode.com/svn/trunk@37 93e54ea4-8218-11de-8aaf-8d8425684b44
+---
+ src/Makefile.am | 2 +
+ src/Makefile.in | 68 +++++++++++++++++++--------
+ src/findmask.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/findmask.inc | 4 ++
+ src/os.cc | 17 +++----
+ src/os.h | 12 ++---
+ src/sat.cc | 55 +++++++++++-----------
+ src/sat.h | 5 +-
+ 8 files changed, 238 insertions(+), 63 deletions(-)
+ create mode 100644 src/findmask.c
+ create mode 100644 src/findmask.inc
+
+--- a/src/os.cc
++++ b/src/os.cc
+@@ -261,21 +261,22 @@ bool OsLayer::AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
+ }
+
+
+-// Translate physical address to memory module name.
+-// Assumes simple round-robin interleaving between memory channels of
+-// 'interleave_size_' sized chunks, with repeated 'channel_width_'
++// Translate physical address to memory module/chip name.
++// Assumes interleaving between two memory channels based on the XOR of
++// all address bits in the 'channel_hash' mask, with repeated 'channel_width_'
+ // blocks with bits distributed from each chip in that channel.
+ int OsLayer::FindDimm(uint64 addr, char *buf, int len) {
+ static const string unknown = "DIMM Unknown";
+- if (!modules_) {
++ if (!channels_) {
+ snprintf(buf, len, "%s", unknown.c_str());
+ return 0;
+ }
+
+- // Find channel by counting interleave units (typically cachelines),
+- // and mod by number of channels.
+- vector<string>& channel = (*modules_)[
+- (addr / interleave_size_) % modules_->size()];
++ // Find channel by XORing address bits in channel_hash mask.
++ uint32 low = (uint32)(addr & channel_hash_);
++ uint32 high = (uint32)((addr & channel_hash_) >> 32);
++ vector<string>& channel = (*channels_)[
++ __builtin_parity(high) ^ __builtin_parity(low)];
+
+ // Find dram chip by finding which byte within the channel
+ // by address mod channel width, then divide the channel
+--- a/src/os.h
++++ b/src/os.h
+@@ -58,11 +58,11 @@ class OsLayer {
+ }
+
+ // Set parameters needed to translate physical address to memory module.
+- void SetDramMappingParams(int interleave_size, int channel_width,
+- vector< vector<string> > *modules) {
+- interleave_size_ = interleave_size;
++ void SetDramMappingParams(uintptr_t channel_hash, int channel_width,
++ vector< vector<string> > *channels) {
++ channel_hash_ = channel_hash;
+ channel_width_ = channel_width;
+- modules_ = modules;
++ channels_ = channels;
+ }
+
+ // Initializes data strctures and open files.
+@@ -269,8 +269,8 @@ class OsLayer {
+ bool use_posix_shm_; // Use 4k page shmem?
+ bool dynamic_mapped_shmem_; // Conserve virtual address space.
+ int shmid_; // Handle to shmem
+- vector< vector<string> > *modules_; // Memory module names per channel.
+- int interleave_size_; // Channel interleaving chunk size.
++ vector< vector<string> > *channels_; // Memory module names per channel.
++ uint64 channel_hash_; // Mask of address bits XORed for channel.
+ int channel_width_; // Channel width in bits.
+
+ int64 regionsize_; // Size of memory "regions"
+--- a/src/sat.cc
++++ b/src/sat.cc
+@@ -572,12 +572,12 @@ bool Sat::Initialize() {
+
+ if (min_hugepages_mbytes_ > 0)
+ os_->SetMinimumHugepagesSize(min_hugepages_mbytes_ * kMegabyte);
+- if (modules_.size() > 0) {
++ if (channels_.size() > 0) {
+ logprintf(6, "Log: Decoding memory: %dx%d bit channels,"
+- " %d byte burst size, %d modules per channel (x%d)\n",
+- modules_.size(), channel_width_, interleave_size_, modules_[0].size(),
+- channel_width_/modules_[0].size());
+- os_->SetDramMappingParams(interleave_size_, channel_width_, &modules_);
++ "%d modules per channel (x%d), decoding hash 0x%x\n",
++ channels_.size(), channel_width_, channels_[0].size(),
++ channel_width_/channels_[0].size(), channel_hash_);
++ os_->SetDramMappingParams(channel_hash_, channel_width_, &channels_);
+ }
+
+ if (!os_->Initialize()) {
+@@ -650,7 +650,7 @@ Sat::Sat() {
+ min_hugepages_mbytes_ = 0;
+ freepages_ = 0;
+ paddr_base_ = 0;
+- interleave_size_ = kCacheLineSize;
++ channel_hash_ = kCacheLineSize;
+ channel_width_ = 64;
+
+ user_break_ = false;
+@@ -927,19 +927,19 @@ bool Sat::ParseArgs(int argc, char **argv) {
+ continue;
+ }
+
+- ARG_IVALUE("--interleave_size", interleave_size_);
++ ARG_IVALUE("--channel_hash", channel_hash_);
+ ARG_IVALUE("--channel_width", channel_width_);
+
+ if (!strcmp(argv[i], "--memory_channel")) {
+ i++;
+ if (i < argc) {
+- char *module = argv[i];
+- modules_.push_back(vector<string>());
+- while (char* next = strchr(module, ',')) {
+- modules_.back().push_back(string(module, next - module));
+- module = next + 1;
++ char *channel = argv[i];
++ channels_.push_back(vector<string>());
++ while (char* next = strchr(channel, ',')) {
++ channels_.back().push_back(string(channel, next - channel));
++ channel = next + 1;
+ }
+- modules_.back().push_back(string(module));
++ channels_.back().push_back(string(channel));
+ }
+ continue;
+ }
+@@ -990,22 +990,25 @@ bool Sat::ParseArgs(int argc, char **argv) {
+ }
+
+ // Validate memory channel parameters if supplied
+- if (modules_.size()) {
+- if (interleave_size_ <= 0 ||
+- interleave_size_ & (interleave_size_ - 1)) {
++ if (channels_.size()) {
++ if (channels_.size() == 1) {
++ channel_hash_ = 0;
++ logprintf(7, "Log: "
++ "Only one memory channel...deactivating interleave decoding.\n");
++ } else if (channels_.size() > 2) {
+ logprintf(6, "Process Error: "
+- "Interleave size %d is not a power of 2.\n", interleave_size_);
++ "Triple-channel mode not yet supported... sorry.\n");
+ bad_status();
+ return false;
+ }
+- for (uint i = 0; i < modules_.size(); i++)
+- if (modules_[i].size() != modules_[0].size()) {
++ for (uint i = 0; i < channels_.size(); i++)
++ if (channels_[i].size() != channels_[0].size()) {
+ logprintf(6, "Process Error: "
+- "Channels 0 and %d have a different amount of modules.\n",i);
++ "Channels 0 and %d have a different count of dram modules.\n",i);
+ bad_status();
+ return false;
+ }
+- if (modules_[0].size() & (modules_[0].size() - 1)) {
++ if (channels_[0].size() & (channels_[0].size() - 1)) {
+ logprintf(6, "Process Error: "
+ "Amount of modules per memory channel is not a power of 2.\n");
+ bad_status();
+@@ -1018,9 +1021,9 @@ bool Sat::ParseArgs(int argc, char **argv) {
+ bad_status();
+ return false;
+ }
+- if (channel_width_ / modules_[0].size() < 8) {
+- logprintf(6, "Process Error: "
+- "Chip width x%d must be x8 or greater.\n", channel_width_ / modules_[0].size());
++ if (channel_width_ / channels_[0].size() < 8) {
++ logprintf(6, "Process Error: Chip width x%d must be x8 or greater.\n",
++ channel_width_ / channels_[0].size());
+ bad_status();
+ return false;
+ }
+@@ -1095,8 +1098,8 @@ void Sat::PrintHelp() {
+ "each CPU to be tested by that CPU\n"
+ " --remote_numa choose memory regions not associated with "
+ "each CPU to be tested by that CPU\n"
+- " --interleave_size bytes size in bytes of each channel's data as interleaved "
+- "between memory channels\n"
++ " --channel_hash mask of address bits XORed to determine channel.\n"
++ " Mask 0x40 interleaves cachelines between channels\n"
+ " --channel_width bits width in bits of each memory channel\n"
+ " --memory_channel u1,u2 defines a comma-separated list of names\n"
+ " for dram packages in a memory channel.\n"
+--- a/src/sat.h
++++ b/src/sat.h
+@@ -151,9 +151,8 @@ class Sat {
+ int64 freepages_; // How many invalid pages we need.
+ int disk_pages_; // Number of pages per temp file.
+ uint64 paddr_base_; // Physical address base.
+- vector< vector<string> > modules_; // Memory module names per channel.
+- int interleave_size_; // Channel interleaving chunk size in bytes.
+- // Usually cacheline sized.
++ vector< vector<string> > channels_; // Memory module names per channel.
++ uint64 channel_hash_; // Mask of address bits XORed for channel.
+ int channel_width_; // Channel width in bits.
+
+ // Control flags.
+--
+2.0.0
+