/* * 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 #include #include #include #include #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] << " " << 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(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 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(buffer[i]) & 0xff); } std::cout << std::endl; }