Let other objects set up memory like regions in a KVM VM.
This commit is contained in:
parent
9b7578d8c7
commit
70eb68beae
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright 2014 Google, Inc.
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
|
@ -124,6 +125,16 @@ Kvm::capCoalescedMMIO() const
|
|||
return checkExtension(KVM_CAP_COALESCED_MMIO);
|
||||
}
|
||||
|
||||
int
|
||||
Kvm::capNumMemSlots() const
|
||||
{
|
||||
#ifdef KVM_CAP_NR_MEMSLOTS
|
||||
return checkExtension(KVM_CAP_NR_MEMSLOTS);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
Kvm::capOneReg() const
|
||||
{
|
||||
|
@ -288,6 +299,10 @@ KvmVM::KvmVM(KvmVMParams *params)
|
|||
started(false),
|
||||
nextVCPUID(0)
|
||||
{
|
||||
maxMemorySlot = kvm.capNumMemSlots();
|
||||
/* If we couldn't determine how memory slots there are, guess 32. */
|
||||
if (!maxMemorySlot)
|
||||
maxMemorySlot = 32;
|
||||
/* Setup the coalesced MMIO regions */
|
||||
for (int i = 0; i < params->coalescedMMIO.size(); ++i)
|
||||
coalesceMMIO(params->coalescedMMIO[i]);
|
||||
|
@ -323,7 +338,13 @@ KvmVM::delayedStartup()
|
|||
DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n",
|
||||
pmem, range.start(), range.size());
|
||||
|
||||
setUserMemoryRegion(slot, pmem, range, 0 /* flags */);
|
||||
if (range.interleaved()) {
|
||||
panic("Tried to map an interleaved memory range into "
|
||||
"a KVM VM.\n");
|
||||
}
|
||||
|
||||
const MemSlot slot = allocMemSlot(range.size());
|
||||
setupMemSlot(slot, pmem, range.start(), 0/* flags */);
|
||||
} else {
|
||||
DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start());
|
||||
hack("KVM: Zero memory handled as IO\n");
|
||||
|
@ -331,17 +352,58 @@ KvmVM::delayedStartup()
|
|||
}
|
||||
}
|
||||
|
||||
const KvmVM::MemSlot
|
||||
KvmVM::allocMemSlot(uint64_t size)
|
||||
{
|
||||
if (!size)
|
||||
panic("Memory slots must have non-zero size.\n");
|
||||
|
||||
std::vector<MemorySlot>::iterator pos;
|
||||
for (pos = memorySlots.begin(); pos != memorySlots.end(); pos++) {
|
||||
if (!pos->size) {
|
||||
pos->size = size;
|
||||
pos->active = false;
|
||||
return pos->slot;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nextSlot = memorySlots.size();
|
||||
if (nextSlot > maxMemorySlot)
|
||||
panic("Out of memory slots.\n");
|
||||
|
||||
MemorySlot slot;
|
||||
slot.size = size;
|
||||
slot.slot = nextSlot;
|
||||
slot.active = false;
|
||||
|
||||
memorySlots.push_back(slot);
|
||||
return MemSlot(slot.slot);
|
||||
}
|
||||
|
||||
void
|
||||
KvmVM::setUserMemoryRegion(uint32_t slot,
|
||||
void *host_addr, AddrRange guest_range,
|
||||
KvmVM::setupMemSlot(const KvmVM::MemSlot num, void *host_addr, Addr guest,
|
||||
uint32_t flags)
|
||||
{
|
||||
if (guest_range.interleaved())
|
||||
panic("Tried to map an interleaved memory range into a KVM VM.\n");
|
||||
MemorySlot &slot = memorySlots.at(num.num);
|
||||
slot.active = true;
|
||||
setUserMemoryRegion(num.num, host_addr, guest, slot.size, flags);
|
||||
}
|
||||
|
||||
setUserMemoryRegion(slot, host_addr,
|
||||
guest_range.start(), guest_range.size(),
|
||||
flags);
|
||||
void
|
||||
KvmVM::disableMemSlot(const KvmVM::MemSlot num)
|
||||
{
|
||||
MemorySlot &slot = memorySlots.at(num.num);
|
||||
if (slot.active)
|
||||
setUserMemoryRegion(num.num, NULL, 0, 0, 0);
|
||||
slot.active = false;
|
||||
}
|
||||
|
||||
void
|
||||
KvmVM::freeMemSlot(const KvmVM::MemSlot num)
|
||||
{
|
||||
disableMemSlot(num.num);
|
||||
MemorySlot &slot = memorySlots.at(num.num);
|
||||
slot.size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright 2014 Google, Inc.
|
||||
* Copyright (c) 2012 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
|
@ -109,6 +110,12 @@ class Kvm
|
|||
*/
|
||||
int capCoalescedMMIO() const;
|
||||
|
||||
/**
|
||||
* Attempt to determine how many memory slots are available. If it can't
|
||||
* be determined, this function returns 0.
|
||||
*/
|
||||
int capNumMemSlots() const;
|
||||
|
||||
/**
|
||||
* Support for reading and writing single registers.
|
||||
*
|
||||
|
@ -331,6 +338,42 @@ class KvmVM : public SimObject
|
|||
bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
|
||||
/** @} */
|
||||
|
||||
struct MemSlot
|
||||
{
|
||||
MemSlot(uint32_t _num) : num(_num)
|
||||
{}
|
||||
MemSlot() : num(-1)
|
||||
{}
|
||||
|
||||
int32_t num;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate a memory slot within the VM.
|
||||
*/
|
||||
const MemSlot allocMemSlot(uint64_t size);
|
||||
|
||||
/**
|
||||
* Setup a region of physical memory in the guest
|
||||
*
|
||||
* @param slot KVM memory slot ID returned by allocMemSlot
|
||||
* @param host_addr Memory allocation backing the memory
|
||||
* @param guest_addr Address in the guest
|
||||
* @param flags Flags (see the KVM API documentation)
|
||||
*/
|
||||
void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Disable a memory slot.
|
||||
*/
|
||||
void disableMemSlot(const MemSlot slot);
|
||||
|
||||
/**
|
||||
* Free a previously allocated memory slot.
|
||||
*/
|
||||
void freeMemSlot(const MemSlot slot);
|
||||
|
||||
/** Global KVM interface */
|
||||
Kvm kvm;
|
||||
|
||||
|
@ -366,16 +409,12 @@ class KvmVM : public SimObject
|
|||
* @param slot KVM memory slot ID (must be unique)
|
||||
* @param host_addr Memory allocation backing the memory
|
||||
* @param guest_addr Address in the guest
|
||||
* @param guest_range Address range used by guest.
|
||||
* @param len Size of the allocation in bytes
|
||||
* @param flags Flags (see the KVM API documentation)
|
||||
*/
|
||||
void setUserMemoryRegion(uint32_t slot,
|
||||
void *host_addr, Addr guest_addr,
|
||||
uint64_t len, uint32_t flags);
|
||||
void setUserMemoryRegion(uint32_t slot,
|
||||
void *host_addr, AddrRange guest_range,
|
||||
uint32_t flags);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -437,6 +476,19 @@ class KvmVM : public SimObject
|
|||
|
||||
/** Next unallocated vCPU ID */
|
||||
long nextVCPUID;
|
||||
|
||||
/**
|
||||
* Structures tracking memory slots.
|
||||
*/
|
||||
class MemorySlot
|
||||
{
|
||||
public:
|
||||
uint64_t size;
|
||||
uint32_t slot;
|
||||
bool active;
|
||||
};
|
||||
std::vector<MemorySlot> memorySlots;
|
||||
uint32_t maxMemorySlot;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue