* [kvm-unit-tests PATCH] Remove the old api folder
@ 2020-01-21 17:47 Thomas Huth
2020-01-22 8:16 ` Andrew Jones
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Thomas Huth @ 2020-01-21 17:47 UTC (permalink / raw)
To: kvm, Paolo Bonzini; +Cc: Drew Jones, David Hildenbrand
The api tests are quite neglected - the tests work for 32-bit i386 only
and there hasn't been any change in this folder since more than 2.5 years.
Additionally, there is nowadays another way of testing the KVM API - the
KVM selftests (as part of the Linux kernel sources) have a much higher
traction and feature much more tests already, so it's unlikely that the
API tests in the kvm-unit-tests repository will get much more attention
in the future. Thus let's delete the api folder now to remove the burder
from the kvm-unit-test maintainers of dragging this code along.
If someone still wants to run the dirty-log-perf test for example, they
can check out an older state of the repository (and then e.g. port the
code to the KVM selftests framework instead).
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
Makefile | 2 -
api/api-sample.cc | 30 -------
api/dirty-log-perf.cc | 146 -------------------------------
api/dirty-log.cc | 84 ------------------
api/exception.cc | 33 -------
api/exception.hh | 19 ----
api/identity.cc | 120 -------------------------
api/identity.hh | 45 ----------
api/kvmxx.cc | 199 ------------------------------------------
api/kvmxx.hh | 86 ------------------
api/memmap.cc | 96 --------------------
api/memmap.hh | 43 ---------
configure | 17 ----
x86/Makefile.common | 19 +---
14 files changed, 1 insertion(+), 938 deletions(-)
delete mode 100644 api/api-sample.cc
delete mode 100644 api/dirty-log-perf.cc
delete mode 100644 api/dirty-log.cc
delete mode 100644 api/exception.cc
delete mode 100644 api/exception.hh
delete mode 100644 api/identity.cc
delete mode 100644 api/identity.hh
delete mode 100644 api/kvmxx.cc
delete mode 100644 api/kvmxx.hh
delete mode 100644 api/memmap.cc
delete mode 100644 api/memmap.hh
diff --git a/Makefile b/Makefile
index 4c716da..6020b10 100644
--- a/Makefile
+++ b/Makefile
@@ -79,8 +79,6 @@ CFLAGS += $(wmissing_parameter_type)
CFLAGS += $(wold_style_declaration)
CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes
-CXXFLAGS += $(COMMON_CFLAGS)
-
autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
LDFLAGS += $(CFLAGS)
diff --git a/api/api-sample.cc b/api/api-sample.cc
deleted file mode 100644
index f523e47..0000000
--- a/api/api-sample.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-
-#include "kvmxx.hh"
-#include "identity.hh"
-#include "exception.hh"
-#include <stdio.h>
-
-static int global = 0;
-
-static void set_global()
-{
- global = 1;
-}
-
-int test_main(int ac, char** av)
-{
- kvm::system system;
- kvm::vm vm(system);
- mem_map memmap(vm);
- identity::vm ident_vm(vm, memmap);
- kvm::vcpu vcpu(vm, 0);
- identity::vcpu thread(vcpu, set_global);
- vcpu.run();
- printf("global %d\n", global);
- return global == 1 ? 0 : 1;
-}
-
-int main(int ac, char** av)
-{
- return try_main(test_main, ac, av);
-}
diff --git a/api/dirty-log-perf.cc b/api/dirty-log-perf.cc
deleted file mode 100644
index f87b4b4..0000000
--- a/api/dirty-log-perf.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-#include "kvmxx.hh"
-#include "exception.hh"
-#include "memmap.hh"
-#include "identity.hh"
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-
-namespace {
-
-const int page_size = 4096;
-int64_t nr_total_pages = 256 * 1024;
-int64_t nr_slot_pages = 256 * 1024;
-
-// Return the current time in nanoseconds.
-uint64_t time_ns()
-{
- struct timespec ts;
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return ts.tv_sec * (uint64_t)1000000000 + ts.tv_nsec;
-}
-
-// Update nr_to_write pages selected from nr_pages pages.
-void write_mem(void* slot_head, int64_t nr_to_write, int64_t nr_pages)
-{
- char* var = static_cast<char*>(slot_head);
- int64_t interval = nr_pages / nr_to_write;
-
- for (int64_t i = 0; i < nr_to_write; ++i) {
- ++(*var);
- var += interval * page_size;
- }
-}
-
-// Let the guest update nr_to_write pages selected from nr_pages pages.
-void do_guest_write(kvm::vcpu& vcpu, void* slot_head,
- int64_t nr_to_write, int64_t nr_pages)
-{
- identity::vcpu guest_write_thread(vcpu, std::bind(write_mem, slot_head,
- nr_to_write, nr_pages));
- vcpu.run();
-}
-
-// Check how long it takes to update dirty log.
-void check_dirty_log(kvm::vcpu& vcpu, mem_slot& slot, void* slot_head)
-{
- slot.set_dirty_logging(true);
- slot.update_dirty_log();
-
- for (int64_t i = 1; i <= nr_slot_pages; i *= 2) {
- do_guest_write(vcpu, slot_head, i, nr_slot_pages);
-
- uint64_t start_ns = time_ns();
- int n = slot.update_dirty_log();
- uint64_t end_ns = time_ns();
-
- printf("get dirty log: %10lld ns for %10d dirty pages (expected %lld)\n",
- end_ns - start_ns, n, i);
- }
-
- slot.set_dirty_logging(false);
-}
-
-}
-
-void parse_options(int ac, char **av)
-{
- int opt;
- char *endptr;
-
- while ((opt = getopt(ac, av, "n:m:")) != -1) {
- switch (opt) {
- case 'n':
- errno = 0;
- nr_slot_pages = strtol(optarg, &endptr, 10);
- if (errno || endptr == optarg) {
- printf("dirty-log-perf: Invalid number: -n %s\n", optarg);
- exit(1);
- }
- if (*endptr == 'k' || *endptr == 'K') {
- nr_slot_pages *= 1024;
- }
- break;
- case 'm':
- errno = 0;
- nr_total_pages = strtol(optarg, &endptr, 10);
- if (errno || endptr == optarg) {
- printf("dirty-log-perf: Invalid number: -m %s\n", optarg);
- exit(1);
- }
- if (*endptr == 'k' || *endptr == 'K') {
- nr_total_pages *= 1024;
- }
- break;
- default:
- printf("dirty-log-perf: Invalid option\n");
- exit(1);
- }
- }
-
- if (nr_slot_pages > nr_total_pages) {
- printf("dirty-log-perf: Invalid setting: slot %lld > mem %lld\n",
- nr_slot_pages, nr_total_pages);
- exit(1);
- }
- printf("dirty-log-perf: %lld slot pages / %lld mem pages\n",
- nr_slot_pages, nr_total_pages);
-}
-
-int test_main(int ac, char **av)
-{
- kvm::system sys;
- kvm::vm vm(sys);
- mem_map memmap(vm);
-
- parse_options(ac, av);
-
- void* mem_head;
- int64_t mem_size = nr_total_pages * page_size;
- if (posix_memalign(&mem_head, page_size, mem_size)) {
- printf("dirty-log-perf: Could not allocate guest memory.\n");
- exit(1);
- }
- uint64_t mem_addr = reinterpret_cast<uintptr_t>(mem_head);
-
- identity::hole hole(mem_head, mem_size);
- identity::vm ident_vm(vm, memmap, hole);
- kvm::vcpu vcpu(vm, 0);
-
- uint64_t slot_size = nr_slot_pages * page_size;
- uint64_t next_size = mem_size - slot_size;
- uint64_t next_addr = mem_addr + slot_size;
- mem_slot slot(memmap, mem_addr, slot_size, mem_head);
- mem_slot other_slot(memmap, next_addr, next_size, (void *)next_addr);
-
- // pre-allocate shadow pages
- do_guest_write(vcpu, mem_head, nr_total_pages, nr_total_pages);
- check_dirty_log(vcpu, slot, mem_head);
- return 0;
-}
-
-int main(int ac, char** av)
-{
- return try_main(test_main, ac, av);
-}
diff --git a/api/dirty-log.cc b/api/dirty-log.cc
deleted file mode 100644
index 9891e98..0000000
--- a/api/dirty-log.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "kvmxx.hh"
-#include "exception.hh"
-#include "memmap.hh"
-#include "identity.hh"
-#include <thread>
-#include <stdlib.h>
-#include <stdio.h>
-
-namespace {
-
-void delay_loop(unsigned n)
-{
- for (unsigned i = 0; i < n; ++i) {
- asm volatile("pause");
- }
- }
-
-void write_mem(volatile bool& running, volatile int* shared_var)
-{
- while (running) {
- ++*shared_var;
- delay_loop(1000);
- }
-}
-
-void check_dirty_log(mem_slot& slot,
- volatile bool& running,
- volatile int* shared_var,
- int& nr_fail)
-{
- uint64_t shared_var_gpa = reinterpret_cast<uint64_t>(shared_var);
- slot.set_dirty_logging(true);
- slot.update_dirty_log();
- for (int i = 0; i < 10000000; ++i) {
- int sample1 = *shared_var;
- delay_loop(600);
- int sample2 = *shared_var;
- slot.update_dirty_log();
- if (!slot.is_dirty(shared_var_gpa) && sample1 != sample2) {
- ++nr_fail;
- }
- }
- running = false;
- slot.set_dirty_logging(false);
-}
-
-}
-
-int test_main(int ac, char **av)
-{
- kvm::system sys;
- kvm::vm vm(sys);
- mem_map memmap(vm);
- void* logged_slot_virt;
- int ret = posix_memalign(&logged_slot_virt, 4096, 4096);
- if (ret) {
- throw errno_exception(ret);
- }
- volatile int* shared_var = static_cast<volatile int*>(logged_slot_virt);
- identity::hole hole(logged_slot_virt, 4096);
- identity::vm ident_vm(vm, memmap, hole);
- kvm::vcpu vcpu(vm, 0);
- bool running = true;
- int nr_fail = 0;
- mem_slot logged_slot(memmap,
- reinterpret_cast<uintptr_t>(logged_slot_virt),
- 4096, logged_slot_virt);
- std::thread host_poll_thread(check_dirty_log, std::ref(logged_slot),
- std::ref(running),
- shared_var, std::ref(nr_fail));
- identity::vcpu guest_write_thread(vcpu,
- std::bind(write_mem,
- std::ref(running),
- shared_var));
- vcpu.run();
- host_poll_thread.join();
- printf("Dirty bitmap failures: %d\n", nr_fail);
- return nr_fail == 0 ? 0 : 1;
-}
-
-int main(int ac, char** av)
-{
- return try_main(test_main, ac, av);
-}
diff --git a/api/exception.cc b/api/exception.cc
deleted file mode 100644
index 910bdff..0000000
--- a/api/exception.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "exception.hh"
-#include <cstdio>
-#include <cstring>
-
-errno_exception::errno_exception(int errno)
- : _errno(errno)
-{
-}
-
-int errno_exception::errno() const
-{
- return _errno;
-}
-
-const char *errno_exception::what()
-{
- std::snprintf(_buf, sizeof _buf, "error: %s (%d)",
- std::strerror(_errno), _errno);
- return _buf;
-}
-
-int try_main(int (*main)(int argc, char** argv), int argc, char** argv,
- int ret_on_exception)
-{
- try {
- return main(argc, argv);
- } catch (std::exception& e) {
- std::fprintf(stderr, "exception: %s\n", e.what());
- } catch (...) {
- std::fprintf(stderr, "unknown exception\n");
- }
- return ret_on_exception;
-}
diff --git a/api/exception.hh b/api/exception.hh
deleted file mode 100644
index f78d9a1..0000000
--- a/api/exception.hh
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef EXCEPTION_HH
-#define EXCEPTION_HH
-
-#include <exception>
-
-class errno_exception : public std::exception {
-public:
- explicit errno_exception(int err_no);
- int errno() const;
- virtual const char *what();
-private:
- int _errno;
- char _buf[1000];
-};
-
-int try_main(int (*main)(int argc, char** argv), int argc, char** argv,
- int ret_on_exception = 127);
-
-#endif
diff --git a/api/identity.cc b/api/identity.cc
deleted file mode 100644
index 24609ef..0000000
--- a/api/identity.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-
-#include "identity.hh"
-#include "exception.hh"
-#include <stdlib.h>
-#include <stdio.h>
-
-namespace identity {
-
-typedef unsigned long ulong;
-
-hole::hole()
- : address(), size()
-{
-}
-
-hole::hole(void* address, size_t size)
- : address(address), size(size)
-{
-}
-
-vm::vm(kvm::vm& vm, mem_map& mmap, hole h)
-{
- int ret = posix_memalign(&tss, 4096, 4 * 4096);
- if (ret) {
- throw errno_exception(ret);
- }
-
- uint64_t hole_gpa = reinterpret_cast<uintptr_t>(h.address);
- char* hole_hva = static_cast<char*>(h.address);
- uint64_t tss_addr = reinterpret_cast<uintptr_t>(tss);
- uint64_t tss_end = tss_addr + 4 * 4096;
- uint64_t hole_end = hole_gpa + h.size;
-
- 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)-tss_end,
- (char*)tss + 4 * 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 + 4 * 4096)));
- _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, (uint32_t)-hole_end,
- hole_hva + h.size)));
- }
-
- vm.set_tss_addr(tss_addr);
- vm.set_ept_identity_map_addr(tss_addr + 3 * 4096);
-}
-
-vm::~vm()
-{
- free(tss);
-}
-
-void vcpu::setup_sregs()
-{
- kvm_sregs sregs = { };
- kvm_segment dseg = { };
- dseg.base = 0; dseg.limit = -1U; dseg.type = 3; dseg.present = 1;
- dseg.dpl = 3; dseg.db = 1; dseg.s = 1; dseg.l = 0; dseg.g = 1;
- kvm_segment cseg = dseg;
- cseg.type = 11;
-
- sregs.cs = cseg; asm ("mov %%cs, %0" : "=rm"(sregs.cs.selector));
- sregs.ds = dseg; asm ("mov %%ds, %0" : "=rm"(sregs.ds.selector));
- sregs.es = dseg; asm ("mov %%es, %0" : "=rm"(sregs.es.selector));
- sregs.fs = dseg; asm ("mov %%fs, %0" : "=rm"(sregs.fs.selector));
- sregs.gs = dseg; asm ("mov %%gs, %0" : "=rm"(sregs.gs.selector));
- sregs.ss = dseg; asm ("mov %%ss, %0" : "=rm"(sregs.ss.selector));
-
- uint32_t gsbase;
- asm ("mov %%gs:0, %0" : "=r"(gsbase));
- sregs.gs.base = gsbase;
-
- sregs.tr.base = reinterpret_cast<uintptr_t>(&*_stack.begin());
- sregs.tr.type = 11;
- sregs.tr.s = 0;
- sregs.tr.present = 1;
-
- sregs.cr0 = 0x11; /* PE, ET, !PG */
- sregs.cr4 = 0;
- sregs.efer = 0;
- sregs.apic_base = 0xfee00000;
- _vcpu.set_sregs(sregs);
-}
-
-void vcpu::thunk(vcpu* zis)
-{
- zis->_guest_func();
- asm volatile("outb %%al, %%dx" : : "a"(0), "d"(0));
-}
-
-void vcpu::setup_regs()
-{
- kvm_regs regs = {};
- regs.rflags = 0x3202;
- regs.rsp = reinterpret_cast<ulong>(&*_stack.end());
- regs.rsp &= ~15UL;
- ulong* sp = reinterpret_cast<ulong *>(regs.rsp);
- *--sp = reinterpret_cast<ulong>((char*)this);
- *--sp = 0;
- regs.rsp = reinterpret_cast<ulong>(sp);
- regs.rip = reinterpret_cast<ulong>(&vcpu::thunk);
- printf("rip %llx\n", regs.rip);
- _vcpu.set_regs(regs);
-}
-
-vcpu::vcpu(kvm::vcpu& vcpu, std::function<void ()> guest_func,
- unsigned long stack_size)
- : _vcpu(vcpu), _guest_func(guest_func), _stack(stack_size)
-{
- setup_sregs();
- setup_regs();
-}
-
-}
diff --git a/api/identity.hh b/api/identity.hh
deleted file mode 100644
index b95cb15..0000000
--- a/api/identity.hh
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef API_IDENTITY_HH
-#define API_IDENTITY_HH
-
-#include "kvmxx.hh"
-#include "memmap.hh"
-#include <functional>
-#include <memory>
-#include <vector>
-
-namespace identity {
-
-struct hole {
- hole();
- hole(void* address, size_t size);
- void* address;
- size_t size;
-};
-
-class vm {
-public:
- vm(kvm::vm& vm, mem_map& mmap, hole address_space_hole = hole());
- ~vm();
-private:
- void *tss;
- typedef std::shared_ptr<mem_slot> mem_slot_ptr;
- std::vector<mem_slot_ptr> _slots;
-};
-
-class vcpu {
-public:
- vcpu(kvm::vcpu& vcpu, std::function<void ()> guest_func,
- unsigned long stack_size = 256 * 1024);
-private:
- static void thunk(vcpu* vcpu);
- void setup_regs();
- void setup_sregs();
-private:
- kvm::vcpu& _vcpu;
- std::function<void ()> _guest_func;
- std::vector<char> _stack;
-};
-
-}
-
-#endif
diff --git a/api/kvmxx.cc b/api/kvmxx.cc
deleted file mode 100644
index 313902e..0000000
--- a/api/kvmxx.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-#include "kvmxx.hh"
-#include "exception.hh"
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-#include <memory>
-#include <algorithm>
-
-namespace kvm {
-
-static long check_error(long r)
-{
- if (r == -1) {
- throw errno_exception(errno);
- }
- return r;
-}
-
-fd::fd(int fd)
- : _fd(fd)
-{
-}
-
-fd::fd(const fd& other)
- : _fd(::dup(other._fd))
-{
- check_error(_fd);
-}
-
-fd::fd(std::string device_node, int flags)
- : _fd(::open(device_node.c_str(), flags))
-{
- check_error(_fd);
-}
-
-long fd::ioctl(unsigned nr, long arg)
-{
- return check_error(::ioctl(_fd, nr, arg));
-}
-
-vcpu::vcpu(vm& vm, int id)
- : _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL)
- , _mmap_size(_vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0))
-
-{
- kvm_run *shared = static_cast<kvm_run*>(::mmap(NULL, _mmap_size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- _fd.get(), 0));
- if (shared == MAP_FAILED) {
- throw errno_exception(errno);
- }
- _shared = shared;
-}
-
-vcpu::~vcpu()
-{
- munmap(_shared, _mmap_size);
-}
-
-void vcpu::run()
-{
- _fd.ioctl(KVM_RUN, 0);
-}
-
-kvm_regs vcpu::regs()
-{
- kvm_regs regs;
- _fd.ioctlp(KVM_GET_REGS, ®s);
- return regs;
-}
-
-void vcpu::set_regs(const kvm_regs& regs)
-{
- _fd.ioctlp(KVM_SET_REGS, const_cast<kvm_regs*>(®s));
-}
-
-kvm_sregs vcpu::sregs()
-{
- kvm_sregs sregs;
- _fd.ioctlp(KVM_GET_SREGS, &sregs);
- return sregs;
-}
-
-void vcpu::set_sregs(const kvm_sregs& sregs)
-{
- _fd.ioctlp(KVM_SET_SREGS, const_cast<kvm_sregs*>(&sregs));
-}
-
-class vcpu::kvm_msrs_ptr {
-public:
- explicit kvm_msrs_ptr(size_t nmsrs);
- ~kvm_msrs_ptr() { ::free(_kvm_msrs); }
- kvm_msrs* operator->() { return _kvm_msrs; }
- kvm_msrs* get() { return _kvm_msrs; }
-private:
- kvm_msrs* _kvm_msrs;
-};
-
-vcpu::kvm_msrs_ptr::kvm_msrs_ptr(size_t nmsrs)
- : _kvm_msrs(0)
-{
- size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
- _kvm_msrs = static_cast<kvm_msrs*>(::malloc(size));
- if (!_kvm_msrs) {
- throw std::bad_alloc();
- }
-}
-
-std::vector<kvm_msr_entry> vcpu::msrs(std::vector<uint32_t> indices)
-{
- kvm_msrs_ptr msrs(indices.size());
- msrs->nmsrs = indices.size();
- for (unsigned i = 0; i < msrs->nmsrs; ++i) {
- msrs->entries[i].index = indices[i];
- }
- _fd.ioctlp(KVM_GET_MSRS, msrs.get());
- return std::vector<kvm_msr_entry>(msrs->entries,
- msrs->entries + msrs->nmsrs);
-}
-
-void vcpu::set_msrs(const std::vector<kvm_msr_entry>& msrs)
-{
- kvm_msrs_ptr _msrs(msrs.size());
- _msrs->nmsrs = msrs.size();
- std::copy(msrs.begin(), msrs.end(), _msrs->entries);
- _fd.ioctlp(KVM_SET_MSRS, _msrs.get());
-}
-
-void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep)
-{
- kvm_guest_debug gd;
-
- gd.control = 0;
- if (enabled) {
- gd.control |= KVM_GUESTDBG_ENABLE;
- }
- if (singlestep) {
- gd.control |= KVM_GUESTDBG_SINGLESTEP;
- }
- for (int i = 0; i < 8; ++i) {
- gd.arch.debugreg[i] = dr[i];
- }
- _fd.ioctlp(KVM_SET_GUEST_DEBUG, &gd);
-}
-
-vm::vm(system& system)
- : _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0))
-{
-}
-
-void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len,
- uint32_t flags)
-{
- struct kvm_userspace_memory_region umr;
-
- umr.slot = slot;
- umr.flags = flags;
- umr.guest_phys_addr = gpa;
- umr.memory_size = len;
- umr.userspace_addr = reinterpret_cast<uintptr_t>(addr);
- _fd.ioctlp(KVM_SET_USER_MEMORY_REGION, &umr);
-}
-
-void vm::get_dirty_log(int slot, void *log)
-{
- struct kvm_dirty_log kdl;
- kdl.slot = slot;
- kdl.dirty_bitmap = log;
- _fd.ioctlp(KVM_GET_DIRTY_LOG, &kdl);
-}
-
-void vm::set_tss_addr(uint32_t addr)
-{
- _fd.ioctl(KVM_SET_TSS_ADDR, addr);
-}
-
-void vm::set_ept_identity_map_addr(uint64_t addr)
-{
- _fd.ioctlp(KVM_SET_IDENTITY_MAP_ADDR, &addr);
-}
-
-system::system(std::string device_node)
- : _fd(device_node, O_RDWR)
-{
-}
-
-bool system::check_extension(int extension)
-{
- return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
-}
-
-int system::get_extension_int(int extension)
-{
- return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
-}
-
-};
diff --git a/api/kvmxx.hh b/api/kvmxx.hh
deleted file mode 100644
index e39bd5b..0000000
--- a/api/kvmxx.hh
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef KVMXX_H
-#define KVMXX_H
-
-#include <string>
-#include <signal.h>
-#include <unistd.h>
-#include <vector>
-#include <errno.h>
-#include <linux/kvm.h>
-#include <stdint.h>
-
-namespace kvm {
-
-class system;
-class vm;
-class vcpu;
-class fd;
-
-class fd {
-public:
- explicit fd(int n);
- explicit fd(std::string path, int flags);
- fd(const fd& other);
- ~fd() { ::close(_fd); }
- int get() { return _fd; }
- long ioctl(unsigned nr, long arg);
- long ioctlp(unsigned nr, void *arg) {
- return ioctl(nr, reinterpret_cast<long>(arg));
- }
-private:
- int _fd;
-};
-
-class vcpu {
-public:
- vcpu(vm& vm, int fd);
- ~vcpu();
- void run();
- kvm_run *shared();
- kvm_regs regs();
- void set_regs(const kvm_regs& regs);
- kvm_sregs sregs();
- void set_sregs(const kvm_sregs& sregs);
- std::vector<kvm_msr_entry> msrs(std::vector<uint32_t> indices);
- void set_msrs(const std::vector<kvm_msr_entry>& msrs);
- void set_debug(uint64_t dr[8], bool enabled, bool singlestep);
-private:
- class kvm_msrs_ptr;
-private:
- vm& _vm;
- fd _fd;
- kvm_run *_shared;
- unsigned _mmap_size;
- friend class vm;
-};
-
-class vm {
-public:
- explicit vm(system& system);
- void set_memory_region(int slot, void *addr, uint64_t gpa, size_t len,
- uint32_t flags = 0);
- void get_dirty_log(int slot, void *log);
- void set_tss_addr(uint32_t addr);
- void set_ept_identity_map_addr(uint64_t addr);
- system& sys() { return _system; }
-private:
- system& _system;
- fd _fd;
- friend class system;
- friend class vcpu;
-};
-
-class system {
-public:
- explicit system(std::string device_node = "/dev/kvm");
- bool check_extension(int extension);
- int get_extension_int(int extension);
-private:
- fd _fd;
- friend class vcpu;
- friend class vm;
-};
-
-};
-
-#endif
diff --git a/api/memmap.cc b/api/memmap.cc
deleted file mode 100644
index cf44824..0000000
--- a/api/memmap.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-
-#include "memmap.hh"
-#include <numeric>
-
-mem_slot::mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void* hva)
- : _map(map)
- , _slot(map._free_slots.top())
- , _gpa(gpa)
- , _size(size)
- , _hva(hva)
- , _dirty_log_enabled(false)
- , _log()
-{
- map._free_slots.pop();
- if (_size) {
- update();
- }
-}
-
-mem_slot::~mem_slot()
-{
- if (!_size) {
- return;
- }
- _size = 0;
- try {
- update();
- _map._free_slots.push(_slot);
- } catch (...) {
- // can't do much if we can't undo slot registration - leak the slot
- }
-}
-
-void mem_slot::set_dirty_logging(bool enabled)
-{
- if (_dirty_log_enabled != enabled) {
- _dirty_log_enabled = enabled;
- if (enabled) {
- int logsize = ((_size >> 12) + bits_per_word - 1) / bits_per_word;
- _log.resize(logsize);
- } else {
- _log.resize(0);
- }
- if (_size) {
- update();
- }
- }
-}
-
-void mem_slot::update()
-{
- uint32_t flags = 0;
- if (_dirty_log_enabled) {
- flags |= KVM_MEM_LOG_DIRTY_PAGES;
- }
- _map._vm.set_memory_region(_slot, _hva, _gpa, _size, flags);
-}
-
-bool mem_slot::dirty_logging() const
-{
- return _dirty_log_enabled;
-}
-
-static inline int hweight(uint64_t w)
-{
- w -= (w >> 1) & 0x5555555555555555;
- w = (w & 0x3333333333333333) + ((w >> 2) & 0x3333333333333333);
- w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0f;
- return (w * 0x0101010101010101) >> 56;
-}
-
-int mem_slot::update_dirty_log()
-{
- _map._vm.get_dirty_log(_slot, &_log[0]);
- return std::accumulate(_log.begin(), _log.end(), 0,
- [] (int prev, ulong elem) -> int {
- return prev + hweight(elem);
- });
-}
-
-bool mem_slot::is_dirty(uint64_t gpa) const
-{
- uint64_t pagenr = (gpa - _gpa) >> 12;
- ulong wordnr = pagenr / bits_per_word;
- ulong bit = 1ULL << (pagenr % bits_per_word);
- return _log[wordnr] & bit;
-}
-
-mem_map::mem_map(kvm::vm& vm)
- : _vm(vm)
-{
- int nr_slots = vm.sys().get_extension_int(KVM_CAP_NR_MEMSLOTS);
- for (int i = 0; i < nr_slots; ++i) {
- _free_slots.push(i);
- }
-}
diff --git a/api/memmap.hh b/api/memmap.hh
deleted file mode 100644
index 48711ae..0000000
--- a/api/memmap.hh
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef MEMMAP_HH
-#define MEMMAP_HH
-
-#include "kvmxx.hh"
-#include <stdint.h>
-#include <vector>
-#include <stack>
-
-class mem_map;
-class mem_slot;
-
-class mem_slot {
-public:
- mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void *hva);
- ~mem_slot();
- void set_dirty_logging(bool enabled);
- bool dirty_logging() const;
- int update_dirty_log();
- bool is_dirty(uint64_t gpa) const;
-private:
- void update();
-private:
- typedef unsigned long ulong;
- static const int bits_per_word = sizeof(ulong) * 8;
- mem_map& _map;
- int _slot;
- uint64_t _gpa;
- uint64_t _size;
- void *_hva;
- bool _dirty_log_enabled;
- std::vector<ulong> _log;
-};
-
-class mem_map {
-public:
- mem_map(kvm::vm& vm);
-private:
- kvm::vm& _vm;
- std::stack<int> _free_slots;
- friend class mem_slot;
-};
-
-#endif
diff --git a/configure b/configure
index e6b4ca1..5797651 100755
--- a/configure
+++ b/configure
@@ -3,7 +3,6 @@
srcdir=$(cd "$(dirname "$0")"; pwd)
prefix=/usr/local
cc=gcc
-cxx=g++
ld=ld
objcopy=objcopy
objdump=objdump
@@ -30,7 +29,6 @@ usage() {
or kvmtool, default is qemu) (arm/arm64 only)
--cross-prefix=PREFIX cross compiler prefix
--cc=CC c compiler to use ($cc)
- --cxx=CXX c++ compiler to use ($cxx)
--ld=LD ld linker to use ($ld)
--prefix=PREFIX where to install things ($prefix)
--endian=ENDIAN endianness to compile for (little or big, ppc64 only)
@@ -72,9 +70,6 @@ while [[ "$1" = -* ]]; do
--cc)
cc="$arg"
;;
- --cxx)
- cxx="$arg"
- ;;
--ld)
ld="$arg"
;;
@@ -149,16 +144,6 @@ EOF
u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
rm -f lib-test.c
-# api/: check for dependent 32 bit libraries and gnu++11 support
-if [ "$testdir" = "x86" ]; then
- echo 'int main () {}' > lib-test.c
- if $cc -m32 -o /dev/null -lstdc++ -lpthread -lrt lib-test.c &> /dev/null &&
- $cxx -m32 -o /dev/null -std=gnu++11 lib-test.c &> /dev/null; then
- api=yes
- fi
- rm -f lib-test.c
-fi
-
# Are we in a separate build tree? If so, link the Makefile
# and shared stuff so that 'make' and run_tests.sh work.
if test ! -e Makefile; then
@@ -199,13 +184,11 @@ ARCH=$arch
ARCH_NAME=$arch_name
PROCESSOR=$processor
CC=$cross_prefix$cc
-CXX=$cross_prefix$cxx
LD=$cross_prefix$ld
OBJCOPY=$cross_prefix$objcopy
OBJDUMP=$cross_prefix$objdump
AR=$cross_prefix$ar
ADDR2LINE=$cross_prefix$addr2line
-API=$api
TEST_DIR=$testdir
FIRMWARE=$firmware
ENDIAN=$endian
diff --git a/x86/Makefile.common b/x86/Makefile.common
index b157154..ab67ca0 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -60,13 +60,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
$(TEST_DIR)/hyperv_connections.flat \
$(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat
-ifdef API
-tests-api = api/api-sample api/dirty-log api/dirty-log-perf
-
-OBJDIRS += api
-endif
-
-test_cases: $(tests-common) $(tests) $(tests-api)
+test_cases: $(tests-common) $(tests)
$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I $(SRCDIR)/lib -I $(SRCDIR)/lib/x86 -I lib
@@ -86,14 +80,3 @@ $(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
arch_clean:
$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
$(TEST_DIR)/.*.d lib/x86/.*.d \
- $(tests-api) api/*.o api/*.a api/.*.d
-
-api/%.o: CXXFLAGS += -m32 -std=gnu++11
-
-api/%: LDLIBS += -lstdc++ -lpthread -lrt
-api/%: LDFLAGS += -m32
-
-api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
- $(AR) rcs $@ $^
-
-$(tests-api) : % : %.o api/libapi.a
--
2.18.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [kvm-unit-tests PATCH] Remove the old api folder
2020-01-21 17:47 [kvm-unit-tests PATCH] Remove the old api folder Thomas Huth
@ 2020-01-22 8:16 ` Andrew Jones
2020-01-22 9:21 ` David Hildenbrand
2020-01-22 14:27 ` Paolo Bonzini
2 siblings, 0 replies; 4+ messages in thread
From: Andrew Jones @ 2020-01-22 8:16 UTC (permalink / raw)
To: Thomas Huth; +Cc: kvm, Paolo Bonzini, David Hildenbrand
On Tue, Jan 21, 2020 at 06:47:19PM +0100, Thomas Huth wrote:
> The api tests are quite neglected - the tests work for 32-bit i386 only
> and there hasn't been any change in this folder since more than 2.5 years.
> Additionally, there is nowadays another way of testing the KVM API - the
> KVM selftests (as part of the Linux kernel sources) have a much higher
> traction and feature much more tests already, so it's unlikely that the
> API tests in the kvm-unit-tests repository will get much more attention
> in the future. Thus let's delete the api folder now to remove the burder
> from the kvm-unit-test maintainers of dragging this code along.
> If someone still wants to run the dirty-log-perf test for example, they
> can check out an older state of the repository (and then e.g. port the
> code to the KVM selftests framework instead).
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> Makefile | 2 -
> api/api-sample.cc | 30 -------
> api/dirty-log-perf.cc | 146 -------------------------------
> api/dirty-log.cc | 84 ------------------
> api/exception.cc | 33 -------
> api/exception.hh | 19 ----
> api/identity.cc | 120 -------------------------
> api/identity.hh | 45 ----------
> api/kvmxx.cc | 199 ------------------------------------------
> api/kvmxx.hh | 86 ------------------
> api/memmap.cc | 96 --------------------
> api/memmap.hh | 43 ---------
> configure | 17 ----
> x86/Makefile.common | 19 +---
> 14 files changed, 1 insertion(+), 938 deletions(-)
> delete mode 100644 api/api-sample.cc
> delete mode 100644 api/dirty-log-perf.cc
> delete mode 100644 api/dirty-log.cc
> delete mode 100644 api/exception.cc
> delete mode 100644 api/exception.hh
> delete mode 100644 api/identity.cc
> delete mode 100644 api/identity.hh
> delete mode 100644 api/kvmxx.cc
> delete mode 100644 api/kvmxx.hh
> delete mode 100644 api/memmap.cc
> delete mode 100644 api/memmap.hh
>
No objections from me.
Acked-by: Andrew Jones <drjones@redhat.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [kvm-unit-tests PATCH] Remove the old api folder
2020-01-21 17:47 [kvm-unit-tests PATCH] Remove the old api folder Thomas Huth
2020-01-22 8:16 ` Andrew Jones
@ 2020-01-22 9:21 ` David Hildenbrand
2020-01-22 14:27 ` Paolo Bonzini
2 siblings, 0 replies; 4+ messages in thread
From: David Hildenbrand @ 2020-01-22 9:21 UTC (permalink / raw)
To: Thomas Huth, kvm, Paolo Bonzini; +Cc: Drew Jones
On 21.01.20 18:47, Thomas Huth wrote:
> The api tests are quite neglected - the tests work for 32-bit i386 only
> and there hasn't been any change in this folder since more than 2.5 years.
> Additionally, there is nowadays another way of testing the KVM API - the
> KVM selftests (as part of the Linux kernel sources) have a much higher
> traction and feature much more tests already, so it's unlikely that the
> API tests in the kvm-unit-tests repository will get much more attention
> in the future. Thus let's delete the api folder now to remove the burder
> from the kvm-unit-test maintainers of dragging this code along.
> If someone still wants to run the dirty-log-perf test for example, they
> can check out an older state of the repository (and then e.g. port the
> code to the KVM selftests framework instead).
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> Makefile | 2 -
> api/api-sample.cc | 30 -------
> api/dirty-log-perf.cc | 146 -------------------------------
> api/dirty-log.cc | 84 ------------------
> api/exception.cc | 33 -------
> api/exception.hh | 19 ----
> api/identity.cc | 120 -------------------------
> api/identity.hh | 45 ----------
> api/kvmxx.cc | 199 ------------------------------------------
> api/kvmxx.hh | 86 ------------------
> api/memmap.cc | 96 --------------------
> api/memmap.hh | 43 ---------
> configure | 17 ----
> x86/Makefile.common | 19 +---
> 14 files changed, 1 insertion(+), 938 deletions(-)
> delete mode 100644 api/api-sample.cc
> delete mode 100644 api/dirty-log-perf.cc
> delete mode 100644 api/dirty-log.cc
> delete mode 100644 api/exception.cc
> delete mode 100644 api/exception.hh
> delete mode 100644 api/identity.cc
> delete mode 100644 api/identity.hh
> delete mode 100644 api/kvmxx.cc
> delete mode 100644 api/kvmxx.hh
> delete mode 100644 api/memmap.cc
> delete mode 100644 api/memmap.hh
>
> diff --git a/Makefile b/Makefile
> index 4c716da..6020b10 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -79,8 +79,6 @@ CFLAGS += $(wmissing_parameter_type)
> CFLAGS += $(wold_style_declaration)
> CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes
>
> -CXXFLAGS += $(COMMON_CFLAGS)
> -
> autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
>
> LDFLAGS += $(CFLAGS)
> diff --git a/api/api-sample.cc b/api/api-sample.cc
> deleted file mode 100644
> index f523e47..0000000
> --- a/api/api-sample.cc
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -
> -#include "kvmxx.hh"
> -#include "identity.hh"
> -#include "exception.hh"
> -#include <stdio.h>
> -
> -static int global = 0;
> -
> -static void set_global()
> -{
> - global = 1;
> -}
> -
> -int test_main(int ac, char** av)
> -{
> - kvm::system system;
> - kvm::vm vm(system);
> - mem_map memmap(vm);
> - identity::vm ident_vm(vm, memmap);
> - kvm::vcpu vcpu(vm, 0);
> - identity::vcpu thread(vcpu, set_global);
> - vcpu.run();
> - printf("global %d\n", global);
> - return global == 1 ? 0 : 1;
> -}
> -
> -int main(int ac, char** av)
> -{
> - return try_main(test_main, ac, av);
> -}
> diff --git a/api/dirty-log-perf.cc b/api/dirty-log-perf.cc
> deleted file mode 100644
> index f87b4b4..0000000
> --- a/api/dirty-log-perf.cc
> +++ /dev/null
> @@ -1,146 +0,0 @@
> -#include "kvmxx.hh"
> -#include "exception.hh"
> -#include "memmap.hh"
> -#include "identity.hh"
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <sys/time.h>
> -
> -namespace {
> -
> -const int page_size = 4096;
> -int64_t nr_total_pages = 256 * 1024;
> -int64_t nr_slot_pages = 256 * 1024;
> -
> -// Return the current time in nanoseconds.
> -uint64_t time_ns()
> -{
> - struct timespec ts;
> -
> - clock_gettime(CLOCK_MONOTONIC, &ts);
> - return ts.tv_sec * (uint64_t)1000000000 + ts.tv_nsec;
> -}
> -
> -// Update nr_to_write pages selected from nr_pages pages.
> -void write_mem(void* slot_head, int64_t nr_to_write, int64_t nr_pages)
> -{
> - char* var = static_cast<char*>(slot_head);
> - int64_t interval = nr_pages / nr_to_write;
> -
> - for (int64_t i = 0; i < nr_to_write; ++i) {
> - ++(*var);
> - var += interval * page_size;
> - }
> -}
> -
> -// Let the guest update nr_to_write pages selected from nr_pages pages.
> -void do_guest_write(kvm::vcpu& vcpu, void* slot_head,
> - int64_t nr_to_write, int64_t nr_pages)
> -{
> - identity::vcpu guest_write_thread(vcpu, std::bind(write_mem, slot_head,
> - nr_to_write, nr_pages));
> - vcpu.run();
> -}
> -
> -// Check how long it takes to update dirty log.
> -void check_dirty_log(kvm::vcpu& vcpu, mem_slot& slot, void* slot_head)
> -{
> - slot.set_dirty_logging(true);
> - slot.update_dirty_log();
> -
> - for (int64_t i = 1; i <= nr_slot_pages; i *= 2) {
> - do_guest_write(vcpu, slot_head, i, nr_slot_pages);
> -
> - uint64_t start_ns = time_ns();
> - int n = slot.update_dirty_log();
> - uint64_t end_ns = time_ns();
> -
> - printf("get dirty log: %10lld ns for %10d dirty pages (expected %lld)\n",
> - end_ns - start_ns, n, i);
> - }
> -
> - slot.set_dirty_logging(false);
> -}
> -
> -}
> -
> -void parse_options(int ac, char **av)
> -{
> - int opt;
> - char *endptr;
> -
> - while ((opt = getopt(ac, av, "n:m:")) != -1) {
> - switch (opt) {
> - case 'n':
> - errno = 0;
> - nr_slot_pages = strtol(optarg, &endptr, 10);
> - if (errno || endptr == optarg) {
> - printf("dirty-log-perf: Invalid number: -n %s\n", optarg);
> - exit(1);
> - }
> - if (*endptr == 'k' || *endptr == 'K') {
> - nr_slot_pages *= 1024;
> - }
> - break;
> - case 'm':
> - errno = 0;
> - nr_total_pages = strtol(optarg, &endptr, 10);
> - if (errno || endptr == optarg) {
> - printf("dirty-log-perf: Invalid number: -m %s\n", optarg);
> - exit(1);
> - }
> - if (*endptr == 'k' || *endptr == 'K') {
> - nr_total_pages *= 1024;
> - }
> - break;
> - default:
> - printf("dirty-log-perf: Invalid option\n");
> - exit(1);
> - }
> - }
> -
> - if (nr_slot_pages > nr_total_pages) {
> - printf("dirty-log-perf: Invalid setting: slot %lld > mem %lld\n",
> - nr_slot_pages, nr_total_pages);
> - exit(1);
> - }
> - printf("dirty-log-perf: %lld slot pages / %lld mem pages\n",
> - nr_slot_pages, nr_total_pages);
> -}
> -
> -int test_main(int ac, char **av)
> -{
> - kvm::system sys;
> - kvm::vm vm(sys);
> - mem_map memmap(vm);
> -
> - parse_options(ac, av);
> -
> - void* mem_head;
> - int64_t mem_size = nr_total_pages * page_size;
> - if (posix_memalign(&mem_head, page_size, mem_size)) {
> - printf("dirty-log-perf: Could not allocate guest memory.\n");
> - exit(1);
> - }
> - uint64_t mem_addr = reinterpret_cast<uintptr_t>(mem_head);
> -
> - identity::hole hole(mem_head, mem_size);
> - identity::vm ident_vm(vm, memmap, hole);
> - kvm::vcpu vcpu(vm, 0);
> -
> - uint64_t slot_size = nr_slot_pages * page_size;
> - uint64_t next_size = mem_size - slot_size;
> - uint64_t next_addr = mem_addr + slot_size;
> - mem_slot slot(memmap, mem_addr, slot_size, mem_head);
> - mem_slot other_slot(memmap, next_addr, next_size, (void *)next_addr);
> -
> - // pre-allocate shadow pages
> - do_guest_write(vcpu, mem_head, nr_total_pages, nr_total_pages);
> - check_dirty_log(vcpu, slot, mem_head);
> - return 0;
> -}
> -
> -int main(int ac, char** av)
> -{
> - return try_main(test_main, ac, av);
> -}
> diff --git a/api/dirty-log.cc b/api/dirty-log.cc
> deleted file mode 100644
> index 9891e98..0000000
> --- a/api/dirty-log.cc
> +++ /dev/null
> @@ -1,84 +0,0 @@
> -#include "kvmxx.hh"
> -#include "exception.hh"
> -#include "memmap.hh"
> -#include "identity.hh"
> -#include <thread>
> -#include <stdlib.h>
> -#include <stdio.h>
> -
> -namespace {
> -
> -void delay_loop(unsigned n)
> -{
> - for (unsigned i = 0; i < n; ++i) {
> - asm volatile("pause");
> - }
> - }
> -
> -void write_mem(volatile bool& running, volatile int* shared_var)
> -{
> - while (running) {
> - ++*shared_var;
> - delay_loop(1000);
> - }
> -}
> -
> -void check_dirty_log(mem_slot& slot,
> - volatile bool& running,
> - volatile int* shared_var,
> - int& nr_fail)
> -{
> - uint64_t shared_var_gpa = reinterpret_cast<uint64_t>(shared_var);
> - slot.set_dirty_logging(true);
> - slot.update_dirty_log();
> - for (int i = 0; i < 10000000; ++i) {
> - int sample1 = *shared_var;
> - delay_loop(600);
> - int sample2 = *shared_var;
> - slot.update_dirty_log();
> - if (!slot.is_dirty(shared_var_gpa) && sample1 != sample2) {
> - ++nr_fail;
> - }
> - }
> - running = false;
> - slot.set_dirty_logging(false);
> -}
> -
> -}
> -
> -int test_main(int ac, char **av)
> -{
> - kvm::system sys;
> - kvm::vm vm(sys);
> - mem_map memmap(vm);
> - void* logged_slot_virt;
> - int ret = posix_memalign(&logged_slot_virt, 4096, 4096);
> - if (ret) {
> - throw errno_exception(ret);
> - }
> - volatile int* shared_var = static_cast<volatile int*>(logged_slot_virt);
> - identity::hole hole(logged_slot_virt, 4096);
> - identity::vm ident_vm(vm, memmap, hole);
> - kvm::vcpu vcpu(vm, 0);
> - bool running = true;
> - int nr_fail = 0;
> - mem_slot logged_slot(memmap,
> - reinterpret_cast<uintptr_t>(logged_slot_virt),
> - 4096, logged_slot_virt);
> - std::thread host_poll_thread(check_dirty_log, std::ref(logged_slot),
> - std::ref(running),
> - shared_var, std::ref(nr_fail));
> - identity::vcpu guest_write_thread(vcpu,
> - std::bind(write_mem,
> - std::ref(running),
> - shared_var));
> - vcpu.run();
> - host_poll_thread.join();
> - printf("Dirty bitmap failures: %d\n", nr_fail);
> - return nr_fail == 0 ? 0 : 1;
> -}
> -
> -int main(int ac, char** av)
> -{
> - return try_main(test_main, ac, av);
> -}
> diff --git a/api/exception.cc b/api/exception.cc
> deleted file mode 100644
> index 910bdff..0000000
> --- a/api/exception.cc
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -#include "exception.hh"
> -#include <cstdio>
> -#include <cstring>
> -
> -errno_exception::errno_exception(int errno)
> - : _errno(errno)
> -{
> -}
> -
> -int errno_exception::errno() const
> -{
> - return _errno;
> -}
> -
> -const char *errno_exception::what()
> -{
> - std::snprintf(_buf, sizeof _buf, "error: %s (%d)",
> - std::strerror(_errno), _errno);
> - return _buf;
> -}
> -
> -int try_main(int (*main)(int argc, char** argv), int argc, char** argv,
> - int ret_on_exception)
> -{
> - try {
> - return main(argc, argv);
> - } catch (std::exception& e) {
> - std::fprintf(stderr, "exception: %s\n", e.what());
> - } catch (...) {
> - std::fprintf(stderr, "unknown exception\n");
> - }
> - return ret_on_exception;
> -}
> diff --git a/api/exception.hh b/api/exception.hh
> deleted file mode 100644
> index f78d9a1..0000000
> --- a/api/exception.hh
> +++ /dev/null
> @@ -1,19 +0,0 @@
> -#ifndef EXCEPTION_HH
> -#define EXCEPTION_HH
> -
> -#include <exception>
> -
> -class errno_exception : public std::exception {
> -public:
> - explicit errno_exception(int err_no);
> - int errno() const;
> - virtual const char *what();
> -private:
> - int _errno;
> - char _buf[1000];
> -};
> -
> -int try_main(int (*main)(int argc, char** argv), int argc, char** argv,
> - int ret_on_exception = 127);
> -
> -#endif
> diff --git a/api/identity.cc b/api/identity.cc
> deleted file mode 100644
> index 24609ef..0000000
> --- a/api/identity.cc
> +++ /dev/null
> @@ -1,120 +0,0 @@
> -
> -#include "identity.hh"
> -#include "exception.hh"
> -#include <stdlib.h>
> -#include <stdio.h>
> -
> -namespace identity {
> -
> -typedef unsigned long ulong;
> -
> -hole::hole()
> - : address(), size()
> -{
> -}
> -
> -hole::hole(void* address, size_t size)
> - : address(address), size(size)
> -{
> -}
> -
> -vm::vm(kvm::vm& vm, mem_map& mmap, hole h)
> -{
> - int ret = posix_memalign(&tss, 4096, 4 * 4096);
> - if (ret) {
> - throw errno_exception(ret);
> - }
> -
> - uint64_t hole_gpa = reinterpret_cast<uintptr_t>(h.address);
> - char* hole_hva = static_cast<char*>(h.address);
> - uint64_t tss_addr = reinterpret_cast<uintptr_t>(tss);
> - uint64_t tss_end = tss_addr + 4 * 4096;
> - uint64_t hole_end = hole_gpa + h.size;
> -
> - 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)-tss_end,
> - (char*)tss + 4 * 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 + 4 * 4096)));
> - _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, (uint32_t)-hole_end,
> - hole_hva + h.size)));
> - }
> -
> - vm.set_tss_addr(tss_addr);
> - vm.set_ept_identity_map_addr(tss_addr + 3 * 4096);
> -}
> -
> -vm::~vm()
> -{
> - free(tss);
> -}
> -
> -void vcpu::setup_sregs()
> -{
> - kvm_sregs sregs = { };
> - kvm_segment dseg = { };
> - dseg.base = 0; dseg.limit = -1U; dseg.type = 3; dseg.present = 1;
> - dseg.dpl = 3; dseg.db = 1; dseg.s = 1; dseg.l = 0; dseg.g = 1;
> - kvm_segment cseg = dseg;
> - cseg.type = 11;
> -
> - sregs.cs = cseg; asm ("mov %%cs, %0" : "=rm"(sregs.cs.selector));
> - sregs.ds = dseg; asm ("mov %%ds, %0" : "=rm"(sregs.ds.selector));
> - sregs.es = dseg; asm ("mov %%es, %0" : "=rm"(sregs.es.selector));
> - sregs.fs = dseg; asm ("mov %%fs, %0" : "=rm"(sregs.fs.selector));
> - sregs.gs = dseg; asm ("mov %%gs, %0" : "=rm"(sregs.gs.selector));
> - sregs.ss = dseg; asm ("mov %%ss, %0" : "=rm"(sregs.ss.selector));
> -
> - uint32_t gsbase;
> - asm ("mov %%gs:0, %0" : "=r"(gsbase));
> - sregs.gs.base = gsbase;
> -
> - sregs.tr.base = reinterpret_cast<uintptr_t>(&*_stack.begin());
> - sregs.tr.type = 11;
> - sregs.tr.s = 0;
> - sregs.tr.present = 1;
> -
> - sregs.cr0 = 0x11; /* PE, ET, !PG */
> - sregs.cr4 = 0;
> - sregs.efer = 0;
> - sregs.apic_base = 0xfee00000;
> - _vcpu.set_sregs(sregs);
> -}
> -
> -void vcpu::thunk(vcpu* zis)
> -{
> - zis->_guest_func();
> - asm volatile("outb %%al, %%dx" : : "a"(0), "d"(0));
> -}
> -
> -void vcpu::setup_regs()
> -{
> - kvm_regs regs = {};
> - regs.rflags = 0x3202;
> - regs.rsp = reinterpret_cast<ulong>(&*_stack.end());
> - regs.rsp &= ~15UL;
> - ulong* sp = reinterpret_cast<ulong *>(regs.rsp);
> - *--sp = reinterpret_cast<ulong>((char*)this);
> - *--sp = 0;
> - regs.rsp = reinterpret_cast<ulong>(sp);
> - regs.rip = reinterpret_cast<ulong>(&vcpu::thunk);
> - printf("rip %llx\n", regs.rip);
> - _vcpu.set_regs(regs);
> -}
> -
> -vcpu::vcpu(kvm::vcpu& vcpu, std::function<void ()> guest_func,
> - unsigned long stack_size)
> - : _vcpu(vcpu), _guest_func(guest_func), _stack(stack_size)
> -{
> - setup_sregs();
> - setup_regs();
> -}
> -
> -}
> diff --git a/api/identity.hh b/api/identity.hh
> deleted file mode 100644
> index b95cb15..0000000
> --- a/api/identity.hh
> +++ /dev/null
> @@ -1,45 +0,0 @@
> -#ifndef API_IDENTITY_HH
> -#define API_IDENTITY_HH
> -
> -#include "kvmxx.hh"
> -#include "memmap.hh"
> -#include <functional>
> -#include <memory>
> -#include <vector>
> -
> -namespace identity {
> -
> -struct hole {
> - hole();
> - hole(void* address, size_t size);
> - void* address;
> - size_t size;
> -};
> -
> -class vm {
> -public:
> - vm(kvm::vm& vm, mem_map& mmap, hole address_space_hole = hole());
> - ~vm();
> -private:
> - void *tss;
> - typedef std::shared_ptr<mem_slot> mem_slot_ptr;
> - std::vector<mem_slot_ptr> _slots;
> -};
> -
> -class vcpu {
> -public:
> - vcpu(kvm::vcpu& vcpu, std::function<void ()> guest_func,
> - unsigned long stack_size = 256 * 1024);
> -private:
> - static void thunk(vcpu* vcpu);
> - void setup_regs();
> - void setup_sregs();
> -private:
> - kvm::vcpu& _vcpu;
> - std::function<void ()> _guest_func;
> - std::vector<char> _stack;
> -};
> -
> -}
> -
> -#endif
> diff --git a/api/kvmxx.cc b/api/kvmxx.cc
> deleted file mode 100644
> index 313902e..0000000
> --- a/api/kvmxx.cc
> +++ /dev/null
> @@ -1,199 +0,0 @@
> -#include "kvmxx.hh"
> -#include "exception.hh"
> -#include <fcntl.h>
> -#include <sys/ioctl.h>
> -#include <sys/mman.h>
> -#include <stdlib.h>
> -#include <memory>
> -#include <algorithm>
> -
> -namespace kvm {
> -
> -static long check_error(long r)
> -{
> - if (r == -1) {
> - throw errno_exception(errno);
> - }
> - return r;
> -}
> -
> -fd::fd(int fd)
> - : _fd(fd)
> -{
> -}
> -
> -fd::fd(const fd& other)
> - : _fd(::dup(other._fd))
> -{
> - check_error(_fd);
> -}
> -
> -fd::fd(std::string device_node, int flags)
> - : _fd(::open(device_node.c_str(), flags))
> -{
> - check_error(_fd);
> -}
> -
> -long fd::ioctl(unsigned nr, long arg)
> -{
> - return check_error(::ioctl(_fd, nr, arg));
> -}
> -
> -vcpu::vcpu(vm& vm, int id)
> - : _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL)
> - , _mmap_size(_vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0))
> -
> -{
> - kvm_run *shared = static_cast<kvm_run*>(::mmap(NULL, _mmap_size,
> - PROT_READ | PROT_WRITE,
> - MAP_SHARED,
> - _fd.get(), 0));
> - if (shared == MAP_FAILED) {
> - throw errno_exception(errno);
> - }
> - _shared = shared;
> -}
> -
> -vcpu::~vcpu()
> -{
> - munmap(_shared, _mmap_size);
> -}
> -
> -void vcpu::run()
> -{
> - _fd.ioctl(KVM_RUN, 0);
> -}
> -
> -kvm_regs vcpu::regs()
> -{
> - kvm_regs regs;
> - _fd.ioctlp(KVM_GET_REGS, ®s);
> - return regs;
> -}
> -
> -void vcpu::set_regs(const kvm_regs& regs)
> -{
> - _fd.ioctlp(KVM_SET_REGS, const_cast<kvm_regs*>(®s));
> -}
> -
> -kvm_sregs vcpu::sregs()
> -{
> - kvm_sregs sregs;
> - _fd.ioctlp(KVM_GET_SREGS, &sregs);
> - return sregs;
> -}
> -
> -void vcpu::set_sregs(const kvm_sregs& sregs)
> -{
> - _fd.ioctlp(KVM_SET_SREGS, const_cast<kvm_sregs*>(&sregs));
> -}
> -
> -class vcpu::kvm_msrs_ptr {
> -public:
> - explicit kvm_msrs_ptr(size_t nmsrs);
> - ~kvm_msrs_ptr() { ::free(_kvm_msrs); }
> - kvm_msrs* operator->() { return _kvm_msrs; }
> - kvm_msrs* get() { return _kvm_msrs; }
> -private:
> - kvm_msrs* _kvm_msrs;
> -};
> -
> -vcpu::kvm_msrs_ptr::kvm_msrs_ptr(size_t nmsrs)
> - : _kvm_msrs(0)
> -{
> - size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
> - _kvm_msrs = static_cast<kvm_msrs*>(::malloc(size));
> - if (!_kvm_msrs) {
> - throw std::bad_alloc();
> - }
> -}
> -
> -std::vector<kvm_msr_entry> vcpu::msrs(std::vector<uint32_t> indices)
> -{
> - kvm_msrs_ptr msrs(indices.size());
> - msrs->nmsrs = indices.size();
> - for (unsigned i = 0; i < msrs->nmsrs; ++i) {
> - msrs->entries[i].index = indices[i];
> - }
> - _fd.ioctlp(KVM_GET_MSRS, msrs.get());
> - return std::vector<kvm_msr_entry>(msrs->entries,
> - msrs->entries + msrs->nmsrs);
> -}
> -
> -void vcpu::set_msrs(const std::vector<kvm_msr_entry>& msrs)
> -{
> - kvm_msrs_ptr _msrs(msrs.size());
> - _msrs->nmsrs = msrs.size();
> - std::copy(msrs.begin(), msrs.end(), _msrs->entries);
> - _fd.ioctlp(KVM_SET_MSRS, _msrs.get());
> -}
> -
> -void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep)
> -{
> - kvm_guest_debug gd;
> -
> - gd.control = 0;
> - if (enabled) {
> - gd.control |= KVM_GUESTDBG_ENABLE;
> - }
> - if (singlestep) {
> - gd.control |= KVM_GUESTDBG_SINGLESTEP;
> - }
> - for (int i = 0; i < 8; ++i) {
> - gd.arch.debugreg[i] = dr[i];
> - }
> - _fd.ioctlp(KVM_SET_GUEST_DEBUG, &gd);
> -}
> -
> -vm::vm(system& system)
> - : _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0))
> -{
> -}
> -
> -void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len,
> - uint32_t flags)
> -{
> - struct kvm_userspace_memory_region umr;
> -
> - umr.slot = slot;
> - umr.flags = flags;
> - umr.guest_phys_addr = gpa;
> - umr.memory_size = len;
> - umr.userspace_addr = reinterpret_cast<uintptr_t>(addr);
> - _fd.ioctlp(KVM_SET_USER_MEMORY_REGION, &umr);
> -}
> -
> -void vm::get_dirty_log(int slot, void *log)
> -{
> - struct kvm_dirty_log kdl;
> - kdl.slot = slot;
> - kdl.dirty_bitmap = log;
> - _fd.ioctlp(KVM_GET_DIRTY_LOG, &kdl);
> -}
> -
> -void vm::set_tss_addr(uint32_t addr)
> -{
> - _fd.ioctl(KVM_SET_TSS_ADDR, addr);
> -}
> -
> -void vm::set_ept_identity_map_addr(uint64_t addr)
> -{
> - _fd.ioctlp(KVM_SET_IDENTITY_MAP_ADDR, &addr);
> -}
> -
> -system::system(std::string device_node)
> - : _fd(device_node, O_RDWR)
> -{
> -}
> -
> -bool system::check_extension(int extension)
> -{
> - return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
> -}
> -
> -int system::get_extension_int(int extension)
> -{
> - return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
> -}
> -
> -};
> diff --git a/api/kvmxx.hh b/api/kvmxx.hh
> deleted file mode 100644
> index e39bd5b..0000000
> --- a/api/kvmxx.hh
> +++ /dev/null
> @@ -1,86 +0,0 @@
> -#ifndef KVMXX_H
> -#define KVMXX_H
> -
> -#include <string>
> -#include <signal.h>
> -#include <unistd.h>
> -#include <vector>
> -#include <errno.h>
> -#include <linux/kvm.h>
> -#include <stdint.h>
> -
> -namespace kvm {
> -
> -class system;
> -class vm;
> -class vcpu;
> -class fd;
> -
> -class fd {
> -public:
> - explicit fd(int n);
> - explicit fd(std::string path, int flags);
> - fd(const fd& other);
> - ~fd() { ::close(_fd); }
> - int get() { return _fd; }
> - long ioctl(unsigned nr, long arg);
> - long ioctlp(unsigned nr, void *arg) {
> - return ioctl(nr, reinterpret_cast<long>(arg));
> - }
> -private:
> - int _fd;
> -};
> -
> -class vcpu {
> -public:
> - vcpu(vm& vm, int fd);
> - ~vcpu();
> - void run();
> - kvm_run *shared();
> - kvm_regs regs();
> - void set_regs(const kvm_regs& regs);
> - kvm_sregs sregs();
> - void set_sregs(const kvm_sregs& sregs);
> - std::vector<kvm_msr_entry> msrs(std::vector<uint32_t> indices);
> - void set_msrs(const std::vector<kvm_msr_entry>& msrs);
> - void set_debug(uint64_t dr[8], bool enabled, bool singlestep);
> -private:
> - class kvm_msrs_ptr;
> -private:
> - vm& _vm;
> - fd _fd;
> - kvm_run *_shared;
> - unsigned _mmap_size;
> - friend class vm;
> -};
> -
> -class vm {
> -public:
> - explicit vm(system& system);
> - void set_memory_region(int slot, void *addr, uint64_t gpa, size_t len,
> - uint32_t flags = 0);
> - void get_dirty_log(int slot, void *log);
> - void set_tss_addr(uint32_t addr);
> - void set_ept_identity_map_addr(uint64_t addr);
> - system& sys() { return _system; }
> -private:
> - system& _system;
> - fd _fd;
> - friend class system;
> - friend class vcpu;
> -};
> -
> -class system {
> -public:
> - explicit system(std::string device_node = "/dev/kvm");
> - bool check_extension(int extension);
> - int get_extension_int(int extension);
> -private:
> - fd _fd;
> - friend class vcpu;
> - friend class vm;
> -};
> -
> -};
> -
> -#endif
> diff --git a/api/memmap.cc b/api/memmap.cc
> deleted file mode 100644
> index cf44824..0000000
> --- a/api/memmap.cc
> +++ /dev/null
> @@ -1,96 +0,0 @@
> -
> -#include "memmap.hh"
> -#include <numeric>
> -
> -mem_slot::mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void* hva)
> - : _map(map)
> - , _slot(map._free_slots.top())
> - , _gpa(gpa)
> - , _size(size)
> - , _hva(hva)
> - , _dirty_log_enabled(false)
> - , _log()
> -{
> - map._free_slots.pop();
> - if (_size) {
> - update();
> - }
> -}
> -
> -mem_slot::~mem_slot()
> -{
> - if (!_size) {
> - return;
> - }
> - _size = 0;
> - try {
> - update();
> - _map._free_slots.push(_slot);
> - } catch (...) {
> - // can't do much if we can't undo slot registration - leak the slot
> - }
> -}
> -
> -void mem_slot::set_dirty_logging(bool enabled)
> -{
> - if (_dirty_log_enabled != enabled) {
> - _dirty_log_enabled = enabled;
> - if (enabled) {
> - int logsize = ((_size >> 12) + bits_per_word - 1) / bits_per_word;
> - _log.resize(logsize);
> - } else {
> - _log.resize(0);
> - }
> - if (_size) {
> - update();
> - }
> - }
> -}
> -
> -void mem_slot::update()
> -{
> - uint32_t flags = 0;
> - if (_dirty_log_enabled) {
> - flags |= KVM_MEM_LOG_DIRTY_PAGES;
> - }
> - _map._vm.set_memory_region(_slot, _hva, _gpa, _size, flags);
> -}
> -
> -bool mem_slot::dirty_logging() const
> -{
> - return _dirty_log_enabled;
> -}
> -
> -static inline int hweight(uint64_t w)
> -{
> - w -= (w >> 1) & 0x5555555555555555;
> - w = (w & 0x3333333333333333) + ((w >> 2) & 0x3333333333333333);
> - w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0f;
> - return (w * 0x0101010101010101) >> 56;
> -}
> -
> -int mem_slot::update_dirty_log()
> -{
> - _map._vm.get_dirty_log(_slot, &_log[0]);
> - return std::accumulate(_log.begin(), _log.end(), 0,
> - [] (int prev, ulong elem) -> int {
> - return prev + hweight(elem);
> - });
> -}
> -
> -bool mem_slot::is_dirty(uint64_t gpa) const
> -{
> - uint64_t pagenr = (gpa - _gpa) >> 12;
> - ulong wordnr = pagenr / bits_per_word;
> - ulong bit = 1ULL << (pagenr % bits_per_word);
> - return _log[wordnr] & bit;
> -}
> -
> -mem_map::mem_map(kvm::vm& vm)
> - : _vm(vm)
> -{
> - int nr_slots = vm.sys().get_extension_int(KVM_CAP_NR_MEMSLOTS);
> - for (int i = 0; i < nr_slots; ++i) {
> - _free_slots.push(i);
> - }
> -}
> diff --git a/api/memmap.hh b/api/memmap.hh
> deleted file mode 100644
> index 48711ae..0000000
> --- a/api/memmap.hh
> +++ /dev/null
> @@ -1,43 +0,0 @@
> -#ifndef MEMMAP_HH
> -#define MEMMAP_HH
> -
> -#include "kvmxx.hh"
> -#include <stdint.h>
> -#include <vector>
> -#include <stack>
> -
> -class mem_map;
> -class mem_slot;
> -
> -class mem_slot {
> -public:
> - mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void *hva);
> - ~mem_slot();
> - void set_dirty_logging(bool enabled);
> - bool dirty_logging() const;
> - int update_dirty_log();
> - bool is_dirty(uint64_t gpa) const;
> -private:
> - void update();
> -private:
> - typedef unsigned long ulong;
> - static const int bits_per_word = sizeof(ulong) * 8;
> - mem_map& _map;
> - int _slot;
> - uint64_t _gpa;
> - uint64_t _size;
> - void *_hva;
> - bool _dirty_log_enabled;
> - std::vector<ulong> _log;
> -};
> -
> -class mem_map {
> -public:
> - mem_map(kvm::vm& vm);
> -private:
> - kvm::vm& _vm;
> - std::stack<int> _free_slots;
> - friend class mem_slot;
> -};
> -
> -#endif
> diff --git a/configure b/configure
> index e6b4ca1..5797651 100755
> --- a/configure
> +++ b/configure
> @@ -3,7 +3,6 @@
> srcdir=$(cd "$(dirname "$0")"; pwd)
> prefix=/usr/local
> cc=gcc
> -cxx=g++
> ld=ld
> objcopy=objcopy
> objdump=objdump
> @@ -30,7 +29,6 @@ usage() {
> or kvmtool, default is qemu) (arm/arm64 only)
> --cross-prefix=PREFIX cross compiler prefix
> --cc=CC c compiler to use ($cc)
> - --cxx=CXX c++ compiler to use ($cxx)
> --ld=LD ld linker to use ($ld)
> --prefix=PREFIX where to install things ($prefix)
> --endian=ENDIAN endianness to compile for (little or big, ppc64 only)
> @@ -72,9 +70,6 @@ while [[ "$1" = -* ]]; do
> --cc)
> cc="$arg"
> ;;
> - --cxx)
> - cxx="$arg"
> - ;;
> --ld)
> ld="$arg"
> ;;
> @@ -149,16 +144,6 @@ EOF
> u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
> rm -f lib-test.c
>
> -# api/: check for dependent 32 bit libraries and gnu++11 support
> -if [ "$testdir" = "x86" ]; then
> - echo 'int main () {}' > lib-test.c
> - if $cc -m32 -o /dev/null -lstdc++ -lpthread -lrt lib-test.c &> /dev/null &&
> - $cxx -m32 -o /dev/null -std=gnu++11 lib-test.c &> /dev/null; then
> - api=yes
> - fi
> - rm -f lib-test.c
> -fi
> -
> # Are we in a separate build tree? If so, link the Makefile
> # and shared stuff so that 'make' and run_tests.sh work.
> if test ! -e Makefile; then
> @@ -199,13 +184,11 @@ ARCH=$arch
> ARCH_NAME=$arch_name
> PROCESSOR=$processor
> CC=$cross_prefix$cc
> -CXX=$cross_prefix$cxx
> LD=$cross_prefix$ld
> OBJCOPY=$cross_prefix$objcopy
> OBJDUMP=$cross_prefix$objdump
> AR=$cross_prefix$ar
> ADDR2LINE=$cross_prefix$addr2line
> -API=$api
> TEST_DIR=$testdir
> FIRMWARE=$firmware
> ENDIAN=$endian
> diff --git a/x86/Makefile.common b/x86/Makefile.common
> index b157154..ab67ca0 100644
> --- a/x86/Makefile.common
> +++ b/x86/Makefile.common
> @@ -60,13 +60,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
> $(TEST_DIR)/hyperv_connections.flat \
> $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat
>
> -ifdef API
> -tests-api = api/api-sample api/dirty-log api/dirty-log-perf
> -
> -OBJDIRS += api
> -endif
> -
> -test_cases: $(tests-common) $(tests) $(tests-api)
> +test_cases: $(tests-common) $(tests)
>
> $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I $(SRCDIR)/lib -I $(SRCDIR)/lib/x86 -I lib
>
> @@ -86,14 +80,3 @@ $(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
> arch_clean:
> $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> $(TEST_DIR)/.*.d lib/x86/.*.d \
> - $(tests-api) api/*.o api/*.a api/.*.d
> -
> -api/%.o: CXXFLAGS += -m32 -std=gnu++11
> -
> -api/%: LDLIBS += -lstdc++ -lpthread -lrt
> -api/%: LDFLAGS += -m32
> -
> -api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
> - $(AR) rcs $@ $^
> -
> -$(tests-api) : % : %.o api/libapi.a
>
Acked-by: David Hildenbrand <david@redhat.com>
--
Thanks,
David / dhildenb
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [kvm-unit-tests PATCH] Remove the old api folder
2020-01-21 17:47 [kvm-unit-tests PATCH] Remove the old api folder Thomas Huth
2020-01-22 8:16 ` Andrew Jones
2020-01-22 9:21 ` David Hildenbrand
@ 2020-01-22 14:27 ` Paolo Bonzini
2 siblings, 0 replies; 4+ messages in thread
From: Paolo Bonzini @ 2020-01-22 14:27 UTC (permalink / raw)
To: Thomas Huth, kvm; +Cc: Drew Jones, David Hildenbrand
On 21/01/20 18:47, Thomas Huth wrote:
> The api tests are quite neglected - the tests work for 32-bit i386 only
> and there hasn't been any change in this folder since more than 2.5 years.
> Additionally, there is nowadays another way of testing the KVM API - the
> KVM selftests (as part of the Linux kernel sources) have a much higher
> traction and feature much more tests already, so it's unlikely that the
> API tests in the kvm-unit-tests repository will get much more attention
> in the future. Thus let's delete the api folder now to remove the burder
> from the kvm-unit-test maintainers of dragging this code along.
> If someone still wants to run the dirty-log-perf test for example, they
> can check out an older state of the repository (and then e.g. port the
> code to the KVM selftests framework instead).
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> Makefile | 2 -
> api/api-sample.cc | 30 -------
> api/dirty-log-perf.cc | 146 -------------------------------
> api/dirty-log.cc | 84 ------------------
> api/exception.cc | 33 -------
> api/exception.hh | 19 ----
> api/identity.cc | 120 -------------------------
> api/identity.hh | 45 ----------
> api/kvmxx.cc | 199 ------------------------------------------
> api/kvmxx.hh | 86 ------------------
> api/memmap.cc | 96 --------------------
> api/memmap.hh | 43 ---------
> configure | 17 ----
> x86/Makefile.common | 19 +---
> 14 files changed, 1 insertion(+), 938 deletions(-)
> delete mode 100644 api/api-sample.cc
> delete mode 100644 api/dirty-log-perf.cc
> delete mode 100644 api/dirty-log.cc
> delete mode 100644 api/exception.cc
> delete mode 100644 api/exception.hh
> delete mode 100644 api/identity.cc
> delete mode 100644 api/identity.hh
> delete mode 100644 api/kvmxx.cc
> delete mode 100644 api/kvmxx.hh
> delete mode 100644 api/memmap.cc
> delete mode 100644 api/memmap.hh
>
> diff --git a/Makefile b/Makefile
> index 4c716da..6020b10 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -79,8 +79,6 @@ CFLAGS += $(wmissing_parameter_type)
> CFLAGS += $(wold_style_declaration)
> CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes
>
> -CXXFLAGS += $(COMMON_CFLAGS)
> -
> autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
>
> LDFLAGS += $(CFLAGS)
> diff --git a/api/api-sample.cc b/api/api-sample.cc
> deleted file mode 100644
> index f523e47..0000000
> --- a/api/api-sample.cc
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -
> -#include "kvmxx.hh"
> -#include "identity.hh"
> -#include "exception.hh"
> -#include <stdio.h>
> -
> -static int global = 0;
> -
> -static void set_global()
> -{
> - global = 1;
> -}
> -
> -int test_main(int ac, char** av)
> -{
> - kvm::system system;
> - kvm::vm vm(system);
> - mem_map memmap(vm);
> - identity::vm ident_vm(vm, memmap);
> - kvm::vcpu vcpu(vm, 0);
> - identity::vcpu thread(vcpu, set_global);
> - vcpu.run();
> - printf("global %d\n", global);
> - return global == 1 ? 0 : 1;
> -}
> -
> -int main(int ac, char** av)
> -{
> - return try_main(test_main, ac, av);
> -}
> diff --git a/api/dirty-log-perf.cc b/api/dirty-log-perf.cc
> deleted file mode 100644
> index f87b4b4..0000000
> --- a/api/dirty-log-perf.cc
> +++ /dev/null
> @@ -1,146 +0,0 @@
> -#include "kvmxx.hh"
> -#include "exception.hh"
> -#include "memmap.hh"
> -#include "identity.hh"
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <sys/time.h>
> -
> -namespace {
> -
> -const int page_size = 4096;
> -int64_t nr_total_pages = 256 * 1024;
> -int64_t nr_slot_pages = 256 * 1024;
> -
> -// Return the current time in nanoseconds.
> -uint64_t time_ns()
> -{
> - struct timespec ts;
> -
> - clock_gettime(CLOCK_MONOTONIC, &ts);
> - return ts.tv_sec * (uint64_t)1000000000 + ts.tv_nsec;
> -}
> -
> -// Update nr_to_write pages selected from nr_pages pages.
> -void write_mem(void* slot_head, int64_t nr_to_write, int64_t nr_pages)
> -{
> - char* var = static_cast<char*>(slot_head);
> - int64_t interval = nr_pages / nr_to_write;
> -
> - for (int64_t i = 0; i < nr_to_write; ++i) {
> - ++(*var);
> - var += interval * page_size;
> - }
> -}
> -
> -// Let the guest update nr_to_write pages selected from nr_pages pages.
> -void do_guest_write(kvm::vcpu& vcpu, void* slot_head,
> - int64_t nr_to_write, int64_t nr_pages)
> -{
> - identity::vcpu guest_write_thread(vcpu, std::bind(write_mem, slot_head,
> - nr_to_write, nr_pages));
> - vcpu.run();
> -}
> -
> -// Check how long it takes to update dirty log.
> -void check_dirty_log(kvm::vcpu& vcpu, mem_slot& slot, void* slot_head)
> -{
> - slot.set_dirty_logging(true);
> - slot.update_dirty_log();
> -
> - for (int64_t i = 1; i <= nr_slot_pages; i *= 2) {
> - do_guest_write(vcpu, slot_head, i, nr_slot_pages);
> -
> - uint64_t start_ns = time_ns();
> - int n = slot.update_dirty_log();
> - uint64_t end_ns = time_ns();
> -
> - printf("get dirty log: %10lld ns for %10d dirty pages (expected %lld)\n",
> - end_ns - start_ns, n, i);
> - }
> -
> - slot.set_dirty_logging(false);
> -}
> -
> -}
> -
> -void parse_options(int ac, char **av)
> -{
> - int opt;
> - char *endptr;
> -
> - while ((opt = getopt(ac, av, "n:m:")) != -1) {
> - switch (opt) {
> - case 'n':
> - errno = 0;
> - nr_slot_pages = strtol(optarg, &endptr, 10);
> - if (errno || endptr == optarg) {
> - printf("dirty-log-perf: Invalid number: -n %s\n", optarg);
> - exit(1);
> - }
> - if (*endptr == 'k' || *endptr == 'K') {
> - nr_slot_pages *= 1024;
> - }
> - break;
> - case 'm':
> - errno = 0;
> - nr_total_pages = strtol(optarg, &endptr, 10);
> - if (errno || endptr == optarg) {
> - printf("dirty-log-perf: Invalid number: -m %s\n", optarg);
> - exit(1);
> - }
> - if (*endptr == 'k' || *endptr == 'K') {
> - nr_total_pages *= 1024;
> - }
> - break;
> - default:
> - printf("dirty-log-perf: Invalid option\n");
> - exit(1);
> - }
> - }
> -
> - if (nr_slot_pages > nr_total_pages) {
> - printf("dirty-log-perf: Invalid setting: slot %lld > mem %lld\n",
> - nr_slot_pages, nr_total_pages);
> - exit(1);
> - }
> - printf("dirty-log-perf: %lld slot pages / %lld mem pages\n",
> - nr_slot_pages, nr_total_pages);
> -}
> -
> -int test_main(int ac, char **av)
> -{
> - kvm::system sys;
> - kvm::vm vm(sys);
> - mem_map memmap(vm);
> -
> - parse_options(ac, av);
> -
> - void* mem_head;
> - int64_t mem_size = nr_total_pages * page_size;
> - if (posix_memalign(&mem_head, page_size, mem_size)) {
> - printf("dirty-log-perf: Could not allocate guest memory.\n");
> - exit(1);
> - }
> - uint64_t mem_addr = reinterpret_cast<uintptr_t>(mem_head);
> -
> - identity::hole hole(mem_head, mem_size);
> - identity::vm ident_vm(vm, memmap, hole);
> - kvm::vcpu vcpu(vm, 0);
> -
> - uint64_t slot_size = nr_slot_pages * page_size;
> - uint64_t next_size = mem_size - slot_size;
> - uint64_t next_addr = mem_addr + slot_size;
> - mem_slot slot(memmap, mem_addr, slot_size, mem_head);
> - mem_slot other_slot(memmap, next_addr, next_size, (void *)next_addr);
> -
> - // pre-allocate shadow pages
> - do_guest_write(vcpu, mem_head, nr_total_pages, nr_total_pages);
> - check_dirty_log(vcpu, slot, mem_head);
> - return 0;
> -}
> -
> -int main(int ac, char** av)
> -{
> - return try_main(test_main, ac, av);
> -}
> diff --git a/api/dirty-log.cc b/api/dirty-log.cc
> deleted file mode 100644
> index 9891e98..0000000
> --- a/api/dirty-log.cc
> +++ /dev/null
> @@ -1,84 +0,0 @@
> -#include "kvmxx.hh"
> -#include "exception.hh"
> -#include "memmap.hh"
> -#include "identity.hh"
> -#include <thread>
> -#include <stdlib.h>
> -#include <stdio.h>
> -
> -namespace {
> -
> -void delay_loop(unsigned n)
> -{
> - for (unsigned i = 0; i < n; ++i) {
> - asm volatile("pause");
> - }
> - }
> -
> -void write_mem(volatile bool& running, volatile int* shared_var)
> -{
> - while (running) {
> - ++*shared_var;
> - delay_loop(1000);
> - }
> -}
> -
> -void check_dirty_log(mem_slot& slot,
> - volatile bool& running,
> - volatile int* shared_var,
> - int& nr_fail)
> -{
> - uint64_t shared_var_gpa = reinterpret_cast<uint64_t>(shared_var);
> - slot.set_dirty_logging(true);
> - slot.update_dirty_log();
> - for (int i = 0; i < 10000000; ++i) {
> - int sample1 = *shared_var;
> - delay_loop(600);
> - int sample2 = *shared_var;
> - slot.update_dirty_log();
> - if (!slot.is_dirty(shared_var_gpa) && sample1 != sample2) {
> - ++nr_fail;
> - }
> - }
> - running = false;
> - slot.set_dirty_logging(false);
> -}
> -
> -}
> -
> -int test_main(int ac, char **av)
> -{
> - kvm::system sys;
> - kvm::vm vm(sys);
> - mem_map memmap(vm);
> - void* logged_slot_virt;
> - int ret = posix_memalign(&logged_slot_virt, 4096, 4096);
> - if (ret) {
> - throw errno_exception(ret);
> - }
> - volatile int* shared_var = static_cast<volatile int*>(logged_slot_virt);
> - identity::hole hole(logged_slot_virt, 4096);
> - identity::vm ident_vm(vm, memmap, hole);
> - kvm::vcpu vcpu(vm, 0);
> - bool running = true;
> - int nr_fail = 0;
> - mem_slot logged_slot(memmap,
> - reinterpret_cast<uintptr_t>(logged_slot_virt),
> - 4096, logged_slot_virt);
> - std::thread host_poll_thread(check_dirty_log, std::ref(logged_slot),
> - std::ref(running),
> - shared_var, std::ref(nr_fail));
> - identity::vcpu guest_write_thread(vcpu,
> - std::bind(write_mem,
> - std::ref(running),
> - shared_var));
> - vcpu.run();
> - host_poll_thread.join();
> - printf("Dirty bitmap failures: %d\n", nr_fail);
> - return nr_fail == 0 ? 0 : 1;
> -}
> -
> -int main(int ac, char** av)
> -{
> - return try_main(test_main, ac, av);
> -}
> diff --git a/api/exception.cc b/api/exception.cc
> deleted file mode 100644
> index 910bdff..0000000
> --- a/api/exception.cc
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -#include "exception.hh"
> -#include <cstdio>
> -#include <cstring>
> -
> -errno_exception::errno_exception(int errno)
> - : _errno(errno)
> -{
> -}
> -
> -int errno_exception::errno() const
> -{
> - return _errno;
> -}
> -
> -const char *errno_exception::what()
> -{
> - std::snprintf(_buf, sizeof _buf, "error: %s (%d)",
> - std::strerror(_errno), _errno);
> - return _buf;
> -}
> -
> -int try_main(int (*main)(int argc, char** argv), int argc, char** argv,
> - int ret_on_exception)
> -{
> - try {
> - return main(argc, argv);
> - } catch (std::exception& e) {
> - std::fprintf(stderr, "exception: %s\n", e.what());
> - } catch (...) {
> - std::fprintf(stderr, "unknown exception\n");
> - }
> - return ret_on_exception;
> -}
> diff --git a/api/exception.hh b/api/exception.hh
> deleted file mode 100644
> index f78d9a1..0000000
> --- a/api/exception.hh
> +++ /dev/null
> @@ -1,19 +0,0 @@
> -#ifndef EXCEPTION_HH
> -#define EXCEPTION_HH
> -
> -#include <exception>
> -
> -class errno_exception : public std::exception {
> -public:
> - explicit errno_exception(int err_no);
> - int errno() const;
> - virtual const char *what();
> -private:
> - int _errno;
> - char _buf[1000];
> -};
> -
> -int try_main(int (*main)(int argc, char** argv), int argc, char** argv,
> - int ret_on_exception = 127);
> -
> -#endif
> diff --git a/api/identity.cc b/api/identity.cc
> deleted file mode 100644
> index 24609ef..0000000
> --- a/api/identity.cc
> +++ /dev/null
> @@ -1,120 +0,0 @@
> -
> -#include "identity.hh"
> -#include "exception.hh"
> -#include <stdlib.h>
> -#include <stdio.h>
> -
> -namespace identity {
> -
> -typedef unsigned long ulong;
> -
> -hole::hole()
> - : address(), size()
> -{
> -}
> -
> -hole::hole(void* address, size_t size)
> - : address(address), size(size)
> -{
> -}
> -
> -vm::vm(kvm::vm& vm, mem_map& mmap, hole h)
> -{
> - int ret = posix_memalign(&tss, 4096, 4 * 4096);
> - if (ret) {
> - throw errno_exception(ret);
> - }
> -
> - uint64_t hole_gpa = reinterpret_cast<uintptr_t>(h.address);
> - char* hole_hva = static_cast<char*>(h.address);
> - uint64_t tss_addr = reinterpret_cast<uintptr_t>(tss);
> - uint64_t tss_end = tss_addr + 4 * 4096;
> - uint64_t hole_end = hole_gpa + h.size;
> -
> - 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)-tss_end,
> - (char*)tss + 4 * 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 + 4 * 4096)));
> - _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, (uint32_t)-hole_end,
> - hole_hva + h.size)));
> - }
> -
> - vm.set_tss_addr(tss_addr);
> - vm.set_ept_identity_map_addr(tss_addr + 3 * 4096);
> -}
> -
> -vm::~vm()
> -{
> - free(tss);
> -}
> -
> -void vcpu::setup_sregs()
> -{
> - kvm_sregs sregs = { };
> - kvm_segment dseg = { };
> - dseg.base = 0; dseg.limit = -1U; dseg.type = 3; dseg.present = 1;
> - dseg.dpl = 3; dseg.db = 1; dseg.s = 1; dseg.l = 0; dseg.g = 1;
> - kvm_segment cseg = dseg;
> - cseg.type = 11;
> -
> - sregs.cs = cseg; asm ("mov %%cs, %0" : "=rm"(sregs.cs.selector));
> - sregs.ds = dseg; asm ("mov %%ds, %0" : "=rm"(sregs.ds.selector));
> - sregs.es = dseg; asm ("mov %%es, %0" : "=rm"(sregs.es.selector));
> - sregs.fs = dseg; asm ("mov %%fs, %0" : "=rm"(sregs.fs.selector));
> - sregs.gs = dseg; asm ("mov %%gs, %0" : "=rm"(sregs.gs.selector));
> - sregs.ss = dseg; asm ("mov %%ss, %0" : "=rm"(sregs.ss.selector));
> -
> - uint32_t gsbase;
> - asm ("mov %%gs:0, %0" : "=r"(gsbase));
> - sregs.gs.base = gsbase;
> -
> - sregs.tr.base = reinterpret_cast<uintptr_t>(&*_stack.begin());
> - sregs.tr.type = 11;
> - sregs.tr.s = 0;
> - sregs.tr.present = 1;
> -
> - sregs.cr0 = 0x11; /* PE, ET, !PG */
> - sregs.cr4 = 0;
> - sregs.efer = 0;
> - sregs.apic_base = 0xfee00000;
> - _vcpu.set_sregs(sregs);
> -}
> -
> -void vcpu::thunk(vcpu* zis)
> -{
> - zis->_guest_func();
> - asm volatile("outb %%al, %%dx" : : "a"(0), "d"(0));
> -}
> -
> -void vcpu::setup_regs()
> -{
> - kvm_regs regs = {};
> - regs.rflags = 0x3202;
> - regs.rsp = reinterpret_cast<ulong>(&*_stack.end());
> - regs.rsp &= ~15UL;
> - ulong* sp = reinterpret_cast<ulong *>(regs.rsp);
> - *--sp = reinterpret_cast<ulong>((char*)this);
> - *--sp = 0;
> - regs.rsp = reinterpret_cast<ulong>(sp);
> - regs.rip = reinterpret_cast<ulong>(&vcpu::thunk);
> - printf("rip %llx\n", regs.rip);
> - _vcpu.set_regs(regs);
> -}
> -
> -vcpu::vcpu(kvm::vcpu& vcpu, std::function<void ()> guest_func,
> - unsigned long stack_size)
> - : _vcpu(vcpu), _guest_func(guest_func), _stack(stack_size)
> -{
> - setup_sregs();
> - setup_regs();
> -}
> -
> -}
> diff --git a/api/identity.hh b/api/identity.hh
> deleted file mode 100644
> index b95cb15..0000000
> --- a/api/identity.hh
> +++ /dev/null
> @@ -1,45 +0,0 @@
> -#ifndef API_IDENTITY_HH
> -#define API_IDENTITY_HH
> -
> -#include "kvmxx.hh"
> -#include "memmap.hh"
> -#include <functional>
> -#include <memory>
> -#include <vector>
> -
> -namespace identity {
> -
> -struct hole {
> - hole();
> - hole(void* address, size_t size);
> - void* address;
> - size_t size;
> -};
> -
> -class vm {
> -public:
> - vm(kvm::vm& vm, mem_map& mmap, hole address_space_hole = hole());
> - ~vm();
> -private:
> - void *tss;
> - typedef std::shared_ptr<mem_slot> mem_slot_ptr;
> - std::vector<mem_slot_ptr> _slots;
> -};
> -
> -class vcpu {
> -public:
> - vcpu(kvm::vcpu& vcpu, std::function<void ()> guest_func,
> - unsigned long stack_size = 256 * 1024);
> -private:
> - static void thunk(vcpu* vcpu);
> - void setup_regs();
> - void setup_sregs();
> -private:
> - kvm::vcpu& _vcpu;
> - std::function<void ()> _guest_func;
> - std::vector<char> _stack;
> -};
> -
> -}
> -
> -#endif
> diff --git a/api/kvmxx.cc b/api/kvmxx.cc
> deleted file mode 100644
> index 313902e..0000000
> --- a/api/kvmxx.cc
> +++ /dev/null
> @@ -1,199 +0,0 @@
> -#include "kvmxx.hh"
> -#include "exception.hh"
> -#include <fcntl.h>
> -#include <sys/ioctl.h>
> -#include <sys/mman.h>
> -#include <stdlib.h>
> -#include <memory>
> -#include <algorithm>
> -
> -namespace kvm {
> -
> -static long check_error(long r)
> -{
> - if (r == -1) {
> - throw errno_exception(errno);
> - }
> - return r;
> -}
> -
> -fd::fd(int fd)
> - : _fd(fd)
> -{
> -}
> -
> -fd::fd(const fd& other)
> - : _fd(::dup(other._fd))
> -{
> - check_error(_fd);
> -}
> -
> -fd::fd(std::string device_node, int flags)
> - : _fd(::open(device_node.c_str(), flags))
> -{
> - check_error(_fd);
> -}
> -
> -long fd::ioctl(unsigned nr, long arg)
> -{
> - return check_error(::ioctl(_fd, nr, arg));
> -}
> -
> -vcpu::vcpu(vm& vm, int id)
> - : _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL)
> - , _mmap_size(_vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0))
> -
> -{
> - kvm_run *shared = static_cast<kvm_run*>(::mmap(NULL, _mmap_size,
> - PROT_READ | PROT_WRITE,
> - MAP_SHARED,
> - _fd.get(), 0));
> - if (shared == MAP_FAILED) {
> - throw errno_exception(errno);
> - }
> - _shared = shared;
> -}
> -
> -vcpu::~vcpu()
> -{
> - munmap(_shared, _mmap_size);
> -}
> -
> -void vcpu::run()
> -{
> - _fd.ioctl(KVM_RUN, 0);
> -}
> -
> -kvm_regs vcpu::regs()
> -{
> - kvm_regs regs;
> - _fd.ioctlp(KVM_GET_REGS, ®s);
> - return regs;
> -}
> -
> -void vcpu::set_regs(const kvm_regs& regs)
> -{
> - _fd.ioctlp(KVM_SET_REGS, const_cast<kvm_regs*>(®s));
> -}
> -
> -kvm_sregs vcpu::sregs()
> -{
> - kvm_sregs sregs;
> - _fd.ioctlp(KVM_GET_SREGS, &sregs);
> - return sregs;
> -}
> -
> -void vcpu::set_sregs(const kvm_sregs& sregs)
> -{
> - _fd.ioctlp(KVM_SET_SREGS, const_cast<kvm_sregs*>(&sregs));
> -}
> -
> -class vcpu::kvm_msrs_ptr {
> -public:
> - explicit kvm_msrs_ptr(size_t nmsrs);
> - ~kvm_msrs_ptr() { ::free(_kvm_msrs); }
> - kvm_msrs* operator->() { return _kvm_msrs; }
> - kvm_msrs* get() { return _kvm_msrs; }
> -private:
> - kvm_msrs* _kvm_msrs;
> -};
> -
> -vcpu::kvm_msrs_ptr::kvm_msrs_ptr(size_t nmsrs)
> - : _kvm_msrs(0)
> -{
> - size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
> - _kvm_msrs = static_cast<kvm_msrs*>(::malloc(size));
> - if (!_kvm_msrs) {
> - throw std::bad_alloc();
> - }
> -}
> -
> -std::vector<kvm_msr_entry> vcpu::msrs(std::vector<uint32_t> indices)
> -{
> - kvm_msrs_ptr msrs(indices.size());
> - msrs->nmsrs = indices.size();
> - for (unsigned i = 0; i < msrs->nmsrs; ++i) {
> - msrs->entries[i].index = indices[i];
> - }
> - _fd.ioctlp(KVM_GET_MSRS, msrs.get());
> - return std::vector<kvm_msr_entry>(msrs->entries,
> - msrs->entries + msrs->nmsrs);
> -}
> -
> -void vcpu::set_msrs(const std::vector<kvm_msr_entry>& msrs)
> -{
> - kvm_msrs_ptr _msrs(msrs.size());
> - _msrs->nmsrs = msrs.size();
> - std::copy(msrs.begin(), msrs.end(), _msrs->entries);
> - _fd.ioctlp(KVM_SET_MSRS, _msrs.get());
> -}
> -
> -void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep)
> -{
> - kvm_guest_debug gd;
> -
> - gd.control = 0;
> - if (enabled) {
> - gd.control |= KVM_GUESTDBG_ENABLE;
> - }
> - if (singlestep) {
> - gd.control |= KVM_GUESTDBG_SINGLESTEP;
> - }
> - for (int i = 0; i < 8; ++i) {
> - gd.arch.debugreg[i] = dr[i];
> - }
> - _fd.ioctlp(KVM_SET_GUEST_DEBUG, &gd);
> -}
> -
> -vm::vm(system& system)
> - : _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0))
> -{
> -}
> -
> -void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len,
> - uint32_t flags)
> -{
> - struct kvm_userspace_memory_region umr;
> -
> - umr.slot = slot;
> - umr.flags = flags;
> - umr.guest_phys_addr = gpa;
> - umr.memory_size = len;
> - umr.userspace_addr = reinterpret_cast<uintptr_t>(addr);
> - _fd.ioctlp(KVM_SET_USER_MEMORY_REGION, &umr);
> -}
> -
> -void vm::get_dirty_log(int slot, void *log)
> -{
> - struct kvm_dirty_log kdl;
> - kdl.slot = slot;
> - kdl.dirty_bitmap = log;
> - _fd.ioctlp(KVM_GET_DIRTY_LOG, &kdl);
> -}
> -
> -void vm::set_tss_addr(uint32_t addr)
> -{
> - _fd.ioctl(KVM_SET_TSS_ADDR, addr);
> -}
> -
> -void vm::set_ept_identity_map_addr(uint64_t addr)
> -{
> - _fd.ioctlp(KVM_SET_IDENTITY_MAP_ADDR, &addr);
> -}
> -
> -system::system(std::string device_node)
> - : _fd(device_node, O_RDWR)
> -{
> -}
> -
> -bool system::check_extension(int extension)
> -{
> - return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
> -}
> -
> -int system::get_extension_int(int extension)
> -{
> - return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
> -}
> -
> -};
> diff --git a/api/kvmxx.hh b/api/kvmxx.hh
> deleted file mode 100644
> index e39bd5b..0000000
> --- a/api/kvmxx.hh
> +++ /dev/null
> @@ -1,86 +0,0 @@
> -#ifndef KVMXX_H
> -#define KVMXX_H
> -
> -#include <string>
> -#include <signal.h>
> -#include <unistd.h>
> -#include <vector>
> -#include <errno.h>
> -#include <linux/kvm.h>
> -#include <stdint.h>
> -
> -namespace kvm {
> -
> -class system;
> -class vm;
> -class vcpu;
> -class fd;
> -
> -class fd {
> -public:
> - explicit fd(int n);
> - explicit fd(std::string path, int flags);
> - fd(const fd& other);
> - ~fd() { ::close(_fd); }
> - int get() { return _fd; }
> - long ioctl(unsigned nr, long arg);
> - long ioctlp(unsigned nr, void *arg) {
> - return ioctl(nr, reinterpret_cast<long>(arg));
> - }
> -private:
> - int _fd;
> -};
> -
> -class vcpu {
> -public:
> - vcpu(vm& vm, int fd);
> - ~vcpu();
> - void run();
> - kvm_run *shared();
> - kvm_regs regs();
> - void set_regs(const kvm_regs& regs);
> - kvm_sregs sregs();
> - void set_sregs(const kvm_sregs& sregs);
> - std::vector<kvm_msr_entry> msrs(std::vector<uint32_t> indices);
> - void set_msrs(const std::vector<kvm_msr_entry>& msrs);
> - void set_debug(uint64_t dr[8], bool enabled, bool singlestep);
> -private:
> - class kvm_msrs_ptr;
> -private:
> - vm& _vm;
> - fd _fd;
> - kvm_run *_shared;
> - unsigned _mmap_size;
> - friend class vm;
> -};
> -
> -class vm {
> -public:
> - explicit vm(system& system);
> - void set_memory_region(int slot, void *addr, uint64_t gpa, size_t len,
> - uint32_t flags = 0);
> - void get_dirty_log(int slot, void *log);
> - void set_tss_addr(uint32_t addr);
> - void set_ept_identity_map_addr(uint64_t addr);
> - system& sys() { return _system; }
> -private:
> - system& _system;
> - fd _fd;
> - friend class system;
> - friend class vcpu;
> -};
> -
> -class system {
> -public:
> - explicit system(std::string device_node = "/dev/kvm");
> - bool check_extension(int extension);
> - int get_extension_int(int extension);
> -private:
> - fd _fd;
> - friend class vcpu;
> - friend class vm;
> -};
> -
> -};
> -
> -#endif
> diff --git a/api/memmap.cc b/api/memmap.cc
> deleted file mode 100644
> index cf44824..0000000
> --- a/api/memmap.cc
> +++ /dev/null
> @@ -1,96 +0,0 @@
> -
> -#include "memmap.hh"
> -#include <numeric>
> -
> -mem_slot::mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void* hva)
> - : _map(map)
> - , _slot(map._free_slots.top())
> - , _gpa(gpa)
> - , _size(size)
> - , _hva(hva)
> - , _dirty_log_enabled(false)
> - , _log()
> -{
> - map._free_slots.pop();
> - if (_size) {
> - update();
> - }
> -}
> -
> -mem_slot::~mem_slot()
> -{
> - if (!_size) {
> - return;
> - }
> - _size = 0;
> - try {
> - update();
> - _map._free_slots.push(_slot);
> - } catch (...) {
> - // can't do much if we can't undo slot registration - leak the slot
> - }
> -}
> -
> -void mem_slot::set_dirty_logging(bool enabled)
> -{
> - if (_dirty_log_enabled != enabled) {
> - _dirty_log_enabled = enabled;
> - if (enabled) {
> - int logsize = ((_size >> 12) + bits_per_word - 1) / bits_per_word;
> - _log.resize(logsize);
> - } else {
> - _log.resize(0);
> - }
> - if (_size) {
> - update();
> - }
> - }
> -}
> -
> -void mem_slot::update()
> -{
> - uint32_t flags = 0;
> - if (_dirty_log_enabled) {
> - flags |= KVM_MEM_LOG_DIRTY_PAGES;
> - }
> - _map._vm.set_memory_region(_slot, _hva, _gpa, _size, flags);
> -}
> -
> -bool mem_slot::dirty_logging() const
> -{
> - return _dirty_log_enabled;
> -}
> -
> -static inline int hweight(uint64_t w)
> -{
> - w -= (w >> 1) & 0x5555555555555555;
> - w = (w & 0x3333333333333333) + ((w >> 2) & 0x3333333333333333);
> - w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0f;
> - return (w * 0x0101010101010101) >> 56;
> -}
> -
> -int mem_slot::update_dirty_log()
> -{
> - _map._vm.get_dirty_log(_slot, &_log[0]);
> - return std::accumulate(_log.begin(), _log.end(), 0,
> - [] (int prev, ulong elem) -> int {
> - return prev + hweight(elem);
> - });
> -}
> -
> -bool mem_slot::is_dirty(uint64_t gpa) const
> -{
> - uint64_t pagenr = (gpa - _gpa) >> 12;
> - ulong wordnr = pagenr / bits_per_word;
> - ulong bit = 1ULL << (pagenr % bits_per_word);
> - return _log[wordnr] & bit;
> -}
> -
> -mem_map::mem_map(kvm::vm& vm)
> - : _vm(vm)
> -{
> - int nr_slots = vm.sys().get_extension_int(KVM_CAP_NR_MEMSLOTS);
> - for (int i = 0; i < nr_slots; ++i) {
> - _free_slots.push(i);
> - }
> -}
> diff --git a/api/memmap.hh b/api/memmap.hh
> deleted file mode 100644
> index 48711ae..0000000
> --- a/api/memmap.hh
> +++ /dev/null
> @@ -1,43 +0,0 @@
> -#ifndef MEMMAP_HH
> -#define MEMMAP_HH
> -
> -#include "kvmxx.hh"
> -#include <stdint.h>
> -#include <vector>
> -#include <stack>
> -
> -class mem_map;
> -class mem_slot;
> -
> -class mem_slot {
> -public:
> - mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void *hva);
> - ~mem_slot();
> - void set_dirty_logging(bool enabled);
> - bool dirty_logging() const;
> - int update_dirty_log();
> - bool is_dirty(uint64_t gpa) const;
> -private:
> - void update();
> -private:
> - typedef unsigned long ulong;
> - static const int bits_per_word = sizeof(ulong) * 8;
> - mem_map& _map;
> - int _slot;
> - uint64_t _gpa;
> - uint64_t _size;
> - void *_hva;
> - bool _dirty_log_enabled;
> - std::vector<ulong> _log;
> -};
> -
> -class mem_map {
> -public:
> - mem_map(kvm::vm& vm);
> -private:
> - kvm::vm& _vm;
> - std::stack<int> _free_slots;
> - friend class mem_slot;
> -};
> -
> -#endif
> diff --git a/configure b/configure
> index e6b4ca1..5797651 100755
> --- a/configure
> +++ b/configure
> @@ -3,7 +3,6 @@
> srcdir=$(cd "$(dirname "$0")"; pwd)
> prefix=/usr/local
> cc=gcc
> -cxx=g++
> ld=ld
> objcopy=objcopy
> objdump=objdump
> @@ -30,7 +29,6 @@ usage() {
> or kvmtool, default is qemu) (arm/arm64 only)
> --cross-prefix=PREFIX cross compiler prefix
> --cc=CC c compiler to use ($cc)
> - --cxx=CXX c++ compiler to use ($cxx)
> --ld=LD ld linker to use ($ld)
> --prefix=PREFIX where to install things ($prefix)
> --endian=ENDIAN endianness to compile for (little or big, ppc64 only)
> @@ -72,9 +70,6 @@ while [[ "$1" = -* ]]; do
> --cc)
> cc="$arg"
> ;;
> - --cxx)
> - cxx="$arg"
> - ;;
> --ld)
> ld="$arg"
> ;;
> @@ -149,16 +144,6 @@ EOF
> u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
> rm -f lib-test.c
>
> -# api/: check for dependent 32 bit libraries and gnu++11 support
> -if [ "$testdir" = "x86" ]; then
> - echo 'int main () {}' > lib-test.c
> - if $cc -m32 -o /dev/null -lstdc++ -lpthread -lrt lib-test.c &> /dev/null &&
> - $cxx -m32 -o /dev/null -std=gnu++11 lib-test.c &> /dev/null; then
> - api=yes
> - fi
> - rm -f lib-test.c
> -fi
> -
> # Are we in a separate build tree? If so, link the Makefile
> # and shared stuff so that 'make' and run_tests.sh work.
> if test ! -e Makefile; then
> @@ -199,13 +184,11 @@ ARCH=$arch
> ARCH_NAME=$arch_name
> PROCESSOR=$processor
> CC=$cross_prefix$cc
> -CXX=$cross_prefix$cxx
> LD=$cross_prefix$ld
> OBJCOPY=$cross_prefix$objcopy
> OBJDUMP=$cross_prefix$objdump
> AR=$cross_prefix$ar
> ADDR2LINE=$cross_prefix$addr2line
> -API=$api
> TEST_DIR=$testdir
> FIRMWARE=$firmware
> ENDIAN=$endian
> diff --git a/x86/Makefile.common b/x86/Makefile.common
> index b157154..ab67ca0 100644
> --- a/x86/Makefile.common
> +++ b/x86/Makefile.common
> @@ -60,13 +60,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
> $(TEST_DIR)/hyperv_connections.flat \
> $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat
>
> -ifdef API
> -tests-api = api/api-sample api/dirty-log api/dirty-log-perf
> -
> -OBJDIRS += api
> -endif
> -
> -test_cases: $(tests-common) $(tests) $(tests-api)
> +test_cases: $(tests-common) $(tests)
>
> $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I $(SRCDIR)/lib -I $(SRCDIR)/lib/x86 -I lib
>
> @@ -86,14 +80,3 @@ $(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
> arch_clean:
> $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
> $(TEST_DIR)/.*.d lib/x86/.*.d \
> - $(tests-api) api/*.o api/*.a api/.*.d
> -
> -api/%.o: CXXFLAGS += -m32 -std=gnu++11
> -
> -api/%: LDLIBS += -lstdc++ -lpthread -lrt
> -api/%: LDFLAGS += -m32
> -
> -api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
> - $(AR) rcs $@ $^
> -
> -$(tests-api) : % : %.o api/libapi.a
>
Queued, thanks.
Paolo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-01-22 14:27 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-21 17:47 [kvm-unit-tests PATCH] Remove the old api folder Thomas Huth
2020-01-22 8:16 ` Andrew Jones
2020-01-22 9:21 ` David Hildenbrand
2020-01-22 14:27 ` Paolo Bonzini
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.