If we create abstract memories with a sub-page size on a system with shared backstore, the offset of next mmap might become non-page-align and cause an invalid argument error. In this CL, we always upscale the range size to multiple of page before updating the offset, so the offset is always on page boundary. Change-Id: I3a6adf312f2cb5a09ee6a24a87adc62b630eac66 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/58289 Reviewed-by: Gabe Black <gabe.black@gmail.com> Maintainer: Gabe Black <gabe.black@gmail.com> Reviewed-by: Boris Shingarov <shingarov@labware.com> Tested-by: kokoro <noreply+kokoro@google.com>
305 lines
9.9 KiB
C++
305 lines
9.9 KiB
C++
/*
|
|
* Copyright (c) 2012 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.
|
|
*/
|
|
|
|
#ifndef __MEM_PHYSICAL_HH__
|
|
#define __MEM_PHYSICAL_HH__
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "base/addr_range.hh"
|
|
#include "base/addr_range_map.hh"
|
|
#include "mem/packet.hh"
|
|
#include "sim/serialize.hh"
|
|
|
|
namespace gem5
|
|
{
|
|
|
|
namespace memory
|
|
{
|
|
|
|
/**
|
|
* Forward declaration to avoid header dependencies.
|
|
*/
|
|
class AbstractMemory;
|
|
|
|
/**
|
|
* A single entry for the backing store.
|
|
*/
|
|
class BackingStoreEntry
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Create a backing store entry. Don't worry about managing the memory
|
|
* pointers, because PhysicalMemory is responsible for that.
|
|
*/
|
|
BackingStoreEntry(AddrRange range, uint8_t* pmem,
|
|
bool conf_table_reported, bool in_addr_map, bool kvm_map,
|
|
int shm_fd=-1, off_t shm_offset=0)
|
|
: range(range), pmem(pmem), confTableReported(conf_table_reported),
|
|
inAddrMap(in_addr_map), kvmMap(kvm_map), shmFd(shm_fd),
|
|
shmOffset(shm_offset)
|
|
{}
|
|
|
|
/**
|
|
* The address range covered in the guest.
|
|
*/
|
|
AddrRange range;
|
|
|
|
/**
|
|
* Pointer to the host memory this range maps to. This memory is the same
|
|
* size as the range field.
|
|
*/
|
|
uint8_t* pmem;
|
|
|
|
/**
|
|
* Whether this memory should be reported to the configuration table
|
|
*/
|
|
bool confTableReported;
|
|
|
|
/**
|
|
* Whether this memory should appear in the global address map
|
|
*/
|
|
bool inAddrMap;
|
|
|
|
/**
|
|
* Whether KVM should map this memory into the guest address space during
|
|
* acceleration.
|
|
*/
|
|
bool kvmMap;
|
|
|
|
/**
|
|
* If this backing store is based on a shared memory, this is the fd to
|
|
* the shared memory. Otherwise, it should be -1.
|
|
*/
|
|
int shmFd;
|
|
|
|
/**
|
|
* If this backing store is based on a shared memory, this is the offset
|
|
* of this backing store in the share memory. Otherwise, the value is 0.
|
|
*/
|
|
off_t shmOffset;
|
|
};
|
|
|
|
/**
|
|
* The physical memory encapsulates all memories in the system and
|
|
* provides basic functionality for accessing those memories without
|
|
* going through the memory system and interconnect.
|
|
*
|
|
* The physical memory is also responsible for providing the host
|
|
* system backingstore used by the memories in the simulated guest
|
|
* system. When the system is created, the physical memory allocates
|
|
* the backing store based on the address ranges that are populated in
|
|
* the system, and does so independent of how those map to actual
|
|
* memory controllers. Thus, the physical memory completely abstracts
|
|
* the mapping of the backing store of the host system and the address
|
|
* mapping in the guest system. This enables us to arbitrarily change
|
|
* the number of memory controllers, and their address mapping, as
|
|
* long as the ranges stay the same.
|
|
*/
|
|
class PhysicalMemory : public Serializable
|
|
{
|
|
|
|
private:
|
|
|
|
// Name for debugging
|
|
std::string _name;
|
|
|
|
// Global address map
|
|
AddrRangeMap<AbstractMemory*, 1> addrMap;
|
|
|
|
// All address-mapped memories
|
|
std::vector<AbstractMemory*> memories;
|
|
|
|
// The total memory size
|
|
uint64_t size;
|
|
|
|
// Let the user choose if we reserve swap space when calling mmap
|
|
const bool mmapUsingNoReserve;
|
|
|
|
const std::string sharedBackstore;
|
|
uint64_t sharedBackstoreSize;
|
|
|
|
long pageSize;
|
|
|
|
// The physical memory used to provide the memory in the simulated
|
|
// system
|
|
std::vector<BackingStoreEntry> backingStore;
|
|
|
|
// Prevent copying
|
|
PhysicalMemory(const PhysicalMemory&);
|
|
|
|
// Prevent assignment
|
|
PhysicalMemory& operator=(const PhysicalMemory&);
|
|
|
|
/**
|
|
* Create the memory region providing the backing store for a
|
|
* given address range that corresponds to a set of memories in
|
|
* the simulated system.
|
|
*
|
|
* @param range The address range covered
|
|
* @param memories The memories this range maps to
|
|
* @param kvm_map Should KVM map this memory for the guest
|
|
*/
|
|
void createBackingStore(AddrRange range,
|
|
const std::vector<AbstractMemory*>& _memories,
|
|
bool conf_table_reported,
|
|
bool in_addr_map, bool kvm_map);
|
|
|
|
public:
|
|
|
|
/**
|
|
* Create a physical memory object, wrapping a number of memories.
|
|
*/
|
|
PhysicalMemory(const std::string& _name,
|
|
const std::vector<AbstractMemory*>& _memories,
|
|
bool mmap_using_noreserve,
|
|
const std::string& shared_backstore,
|
|
bool auto_unlink_shared_backstore);
|
|
|
|
/**
|
|
* Unmap all the backing store we have used.
|
|
*/
|
|
~PhysicalMemory();
|
|
|
|
/**
|
|
* Return the name for debugging and for creation of sections for
|
|
* checkpointing.
|
|
*/
|
|
const std::string name() const { return _name; }
|
|
|
|
/**
|
|
* Check if a physical address is within a range of a memory that
|
|
* is part of the global address map.
|
|
*
|
|
* @param addr A physical address
|
|
* @return Whether the address corresponds to a memory
|
|
*/
|
|
bool isMemAddr(Addr addr) const;
|
|
|
|
/**
|
|
* Get the memory ranges for all memories that are to be reported
|
|
* to the configuration table. The ranges are merged before they
|
|
* are returned such that any interleaved ranges appear as a
|
|
* single range.
|
|
*
|
|
* @return All configuration table memory ranges
|
|
*/
|
|
AddrRangeList getConfAddrRanges() const;
|
|
|
|
/**
|
|
* Get the total physical memory size.
|
|
*
|
|
* @return The sum of all memory sizes
|
|
*/
|
|
uint64_t totalSize() const { return size; }
|
|
|
|
/**
|
|
* Get the pointers to the backing store for external host
|
|
* access. Note that memory in the guest should be accessed using
|
|
* access() or functionalAccess(). This interface is primarily
|
|
* intended for CPU models using hardware virtualization. Note
|
|
* that memories that are null are not present, and that the
|
|
* backing store may also contain memories that are not part of
|
|
* the OS-visible global address map and thus are allowed to
|
|
* overlap.
|
|
*
|
|
* @return Pointers to the memory backing store
|
|
*/
|
|
std::vector<BackingStoreEntry> getBackingStore() const
|
|
{ return backingStore; }
|
|
|
|
/**
|
|
* Perform an untimed memory access and update all the state
|
|
* (e.g. locked addresses) and statistics accordingly. The packet
|
|
* is turned into a response if required.
|
|
*
|
|
* @param pkt Packet performing the access
|
|
*/
|
|
void access(PacketPtr pkt);
|
|
|
|
/**
|
|
* Perform an untimed memory read or write without changing
|
|
* anything but the memory itself. No stats are affected by this
|
|
* access. In addition to normal accesses this also facilitates
|
|
* print requests.
|
|
*
|
|
* @param pkt Packet performing the access
|
|
*/
|
|
void functionalAccess(PacketPtr pkt);
|
|
|
|
/**
|
|
* Serialize all the memories in the system. This is independent
|
|
* of the logical memory layout, and the serialization only sees
|
|
* the contigous backing store, independent of how this maps to
|
|
* logical memories in the guest system.
|
|
*
|
|
* @param os stream to serialize to
|
|
*/
|
|
void serialize(CheckpointOut &cp) const override;
|
|
|
|
/**
|
|
* Serialize a specific store.
|
|
*
|
|
* @param store_id Unique identifier of this backing store
|
|
* @param range The address range of this backing store
|
|
* @param pmem The host pointer to this backing store
|
|
*/
|
|
void serializeStore(CheckpointOut &cp, unsigned int store_id,
|
|
AddrRange range, uint8_t* pmem) const;
|
|
|
|
/**
|
|
* Unserialize the memories in the system. As with the
|
|
* serialization, this action is independent of how the address
|
|
* ranges are mapped to logical memories in the guest system.
|
|
*/
|
|
void unserialize(CheckpointIn &cp) override;
|
|
|
|
/**
|
|
* Unserialize a specific backing store, identified by a section.
|
|
*/
|
|
void unserializeStore(CheckpointIn &cp);
|
|
|
|
};
|
|
|
|
} // namespace memory
|
|
} // namespace gem5
|
|
|
|
#endif //__MEM_PHYSICAL_HH__
|