[PATCH kvm-unit-tests 6/6] x86: api: allocate TSS region dynamically

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Holes across the 3GB mark can occur on 64-bit machines.  Use posix_memalign
to reserve some space in the process's address space for the TSS, and
carve a second hole for it.  The memory itself is not used---it's only
that we want the process to not use that area while in guest context,
and the easiest way to do it is to allocate memory.

Allocations still are not allowed to go up to 4GB, because of the APIC
access page and EPT identity pagetable lie.  Detect the situation and
print a nice error message.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 api/identity.cc | 45 +++++++++++++++++++++++++++++++++++++--------
 api/identity.hh |  2 ++
 2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/api/identity.cc b/api/identity.cc
index f9e1830..a178f3a 100644
--- a/api/identity.cc
+++ b/api/identity.cc
@@ -1,5 +1,7 @@
 
 #include "identity.hh"
+#include "exception.hh"
+#include <stdlib.h>
 #include <stdio.h>
 
 namespace identity {
@@ -18,17 +20,44 @@ hole::hole(void* address, size_t size)
 
 vm::vm(kvm::vm& vm, mem_map& mmap, hole h)
 {
+    posix_memalign(&tss, 4096, 3 * 4096);
+    if (!tss) {
+        throw errno_exception(errno);
+    }
+
     uint64_t hole_gpa = reinterpret_cast<uintptr_t>(h.address);
     char* hole_hva = static_cast<char*>(h.address);
-    if (h.address) {
-        _slots.push_back(mem_slot_ptr(new mem_slot(mmap, 0, hole_gpa, NULL)));
-    }
+    uint64_t tss_addr = reinterpret_cast<uintptr_t>(tss);
+    uint64_t tss_end = tss_addr + 3 * 4096;
     uint64_t hole_end = hole_gpa + h.size;
-    uint64_t end = 3U << 30;
-    _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end,
-                                               end - hole_end,
-                                               hole_hva + h.size)));
-    vm.set_tss_addr(3UL << 30);
+    uint64_t top = 0xfe000000UL;
+
+    if (hole_end > top) {
+        puts("unlucky memory map :(");
+        throw std::exception();
+    }
+    if (hole_gpa < tss_addr) {
+        if (hole_gpa) {
+            _slots.push_back(mem_slot_ptr(new mem_slot(mmap, 0, hole_gpa, NULL)));
+        }
+        _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, tss_addr - hole_end,
+						   hole_hva + h.size)));
+        _slots.push_back(mem_slot_ptr(new mem_slot(mmap, tss_end, (uint32_t)top - tss_end,
+						   (char*)tss + 3 * 4096)));
+    } else {
+        _slots.push_back(mem_slot_ptr(new mem_slot(mmap, 0, tss_addr, NULL)));
+        _slots.push_back(mem_slot_ptr(new mem_slot(mmap, tss_end, hole_gpa - tss_end,
+						   (char*)tss + 3 * 4096)));
+        _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, (uint32_t)top - hole_end,
+						   hole_hva + h.size)));
+    }
+
+    vm.set_tss_addr(tss_addr);
+}
+
+vm::~vm()
+{
+    free(tss);
 }
 
 void vcpu::setup_sregs()
diff --git a/api/identity.hh b/api/identity.hh
index 4491043..2e75a08 100644
--- a/api/identity.hh
+++ b/api/identity.hh
@@ -19,7 +19,9 @@ struct hole {
 class vm {
 public:
     vm(kvm::vm& vm, mem_map& mmap, hole address_space_hole = hole());
+    ~vm();
 private:
+    void *tss;
     typedef std::tr1::shared_ptr<mem_slot> mem_slot_ptr;
     std::vector<mem_slot_ptr> _slots;
 };
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux