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
|
* Copyright (c) 2012 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
|
@ -124,6 +125,16 @@ Kvm::capCoalescedMMIO() const
|
||||||
return checkExtension(KVM_CAP_COALESCED_MMIO);
|
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
|
bool
|
||||||
Kvm::capOneReg() const
|
Kvm::capOneReg() const
|
||||||
{
|
{
|
||||||
|
@ -288,6 +299,10 @@ KvmVM::KvmVM(KvmVMParams *params)
|
||||||
started(false),
|
started(false),
|
||||||
nextVCPUID(0)
|
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 */
|
/* Setup the coalesced MMIO regions */
|
||||||
for (int i = 0; i < params->coalescedMMIO.size(); ++i)
|
for (int i = 0; i < params->coalescedMMIO.size(); ++i)
|
||||||
coalesceMMIO(params->coalescedMMIO[i]);
|
coalesceMMIO(params->coalescedMMIO[i]);
|
||||||
|
@ -323,7 +338,13 @@ KvmVM::delayedStartup()
|
||||||
DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n",
|
DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n",
|
||||||
pmem, range.start(), range.size());
|
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 {
|
} else {
|
||||||
DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start());
|
DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start());
|
||||||
hack("KVM: Zero memory handled as IO\n");
|
hack("KVM: Zero memory handled as IO\n");
|
||||||
|
@ -331,17 +352,58 @@ KvmVM::delayedStartup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
const KvmVM::MemSlot
|
||||||
KvmVM::setUserMemoryRegion(uint32_t slot,
|
KvmVM::allocMemSlot(uint64_t size)
|
||||||
void *host_addr, AddrRange guest_range,
|
|
||||||
uint32_t flags)
|
|
||||||
{
|
{
|
||||||
if (guest_range.interleaved())
|
if (!size)
|
||||||
panic("Tried to map an interleaved memory range into a KVM VM.\n");
|
panic("Memory slots must have non-zero size.\n");
|
||||||
|
|
||||||
setUserMemoryRegion(slot, host_addr,
|
std::vector<MemorySlot>::iterator pos;
|
||||||
guest_range.start(), guest_range.size(),
|
for (pos = memorySlots.begin(); pos != memorySlots.end(); pos++) {
|
||||||
flags);
|
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::setupMemSlot(const KvmVM::MemSlot num, void *host_addr, Addr guest,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
MemorySlot &slot = memorySlots.at(num.num);
|
||||||
|
slot.active = true;
|
||||||
|
setUserMemoryRegion(num.num, host_addr, guest, slot.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
|
void
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright 2014 Google, Inc.
|
||||||
* Copyright (c) 2012 ARM Limited
|
* Copyright (c) 2012 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
|
@ -109,6 +110,12 @@ class Kvm
|
||||||
*/
|
*/
|
||||||
int capCoalescedMMIO() const;
|
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.
|
* Support for reading and writing single registers.
|
||||||
*
|
*
|
||||||
|
@ -331,6 +338,42 @@ class KvmVM : public SimObject
|
||||||
bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
|
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 */
|
/** Global KVM interface */
|
||||||
Kvm kvm;
|
Kvm kvm;
|
||||||
|
|
||||||
|
@ -366,16 +409,12 @@ class KvmVM : public SimObject
|
||||||
* @param slot KVM memory slot ID (must be unique)
|
* @param slot KVM memory slot ID (must be unique)
|
||||||
* @param host_addr Memory allocation backing the memory
|
* @param host_addr Memory allocation backing the memory
|
||||||
* @param guest_addr Address in the guest
|
* @param guest_addr Address in the guest
|
||||||
* @param guest_range Address range used by guest.
|
|
||||||
* @param len Size of the allocation in bytes
|
* @param len Size of the allocation in bytes
|
||||||
* @param flags Flags (see the KVM API documentation)
|
* @param flags Flags (see the KVM API documentation)
|
||||||
*/
|
*/
|
||||||
void setUserMemoryRegion(uint32_t slot,
|
void setUserMemoryRegion(uint32_t slot,
|
||||||
void *host_addr, Addr guest_addr,
|
void *host_addr, Addr guest_addr,
|
||||||
uint64_t len, uint32_t flags);
|
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 */
|
/** Next unallocated vCPU ID */
|
||||||
long nextVCPUID;
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue