blob: c1de4af9996209c7fa272d90b6700440b41a1dff [file] [log] [blame]
/*
* Copyright 2022 Google, Inc.
*
* 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.
*/
#include <iomanip>
#include <iostream>
#include <random>
#include <string>
#include <unistd.h>
#include "shared_memory_client.hh"
/**
* Consider that
* 1. you have a SimpleMemory that spans from 0x0 to 0x10000
* 2. you have a SharedMemoryServer with server_path=ram.sock
* 3. The SHM server and the Mem is under the same System
*
* You should see a unix socket m5out/ram.sock, and you should be able to run
* our example with commands like:
* `./shared_memory_client_example m5out/ram.sock 0x1000 0x1010`
*
* The example will use the client to map the range 0x1000-0x1010 of the
* SimpleMemory into the address space of the example. As a result, the example
* will be able to access the backing store of the SimpleMemory with just a
* normal pointer.
*/
static void PrintAsHexString(char *buffer, uint64_t size);
int
main(int argc, char *argv[])
{
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " <shm_sock_path> <start> <end>"
<< std::endl;
return 1;
}
// Each SharedMemoryServer in gem5 will create a unix socket at the
// location specified in its server_path parameter, and the socket can be
// used by the client to communicate with the server.
gem5::util::memory::SharedMemoryClient shm_client(argv[1]);
// Before request access to the simulated physical memory in gem5, we need
// to first determine what's the range we'd like to access.
uint64_t start = std::stoull(argv[2], nullptr, 0);
uint64_t end = std::stoull(argv[3], nullptr, 0);
// One thing important is that, non-align request is not supported now, so
// we'll need to ensure the start address is on page boundary.
long page_size = sysconf(_SC_PAGESIZE);
if (page_size < 0) {
std::cerr << "Cannot determine page size" << std::endl;
return 1;
}
if (start % page_size != 0) {
std::cerr << "Start address must be aligned" << std::endl;
return 1;
}
// The Map request, if success, will return a void* pointer, which can then
// be used as a backdoor to the physical memory range in gem5. If there's
// any error, nullptr will be returned.
char *mem = reinterpret_cast<char *>(shm_client.MapMemory(start, end));
uint64_t size = end - start + 1;
if (mem == nullptr) {
std::cerr << "Unable to map memory" << std::endl;
return 1;
}
// A simple use case that print and randomly fill the memory.
std::cout << "Content was: ";
PrintAsHexString(mem, size);
// Override content with random value.
std::random_device rand_dev;
std::uniform_int_distribution<int> rand_dist(0, 255);
for (uint64_t i = 0; i < size; ++i) {
mem[i] = rand_dist(rand_dev);
}
std::cout << "Content is: ";
PrintAsHexString(mem, size);
}
static void
PrintAsHexString(char *buffer, uint64_t size)
{
for (uint64_t i = 0; i < size; ++i) {
std::cout << std::setw(2) << std::setfill('0') << std::hex
<< (static_cast<int>(buffer[i]) & 0xff);
}
std::cout << std::endl;
}