diff mbox series

[kvm-unit-tests] Remove the old api folder

Message ID 20200121174719.31156-1-thuth@redhat.com (mailing list archive)
State New, archived
Headers show
Series [kvm-unit-tests] Remove the old api folder | expand

Commit Message

Thomas Huth Jan. 21, 2020, 5:47 p.m. UTC
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

Comments

Andrew Jones Jan. 22, 2020, 8:16 a.m. UTC | #1
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>
David Hildenbrand Jan. 22, 2020, 9:21 a.m. UTC | #2
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, &regs);
> -    return regs;
> -}
> -
> -void vcpu::set_regs(const kvm_regs& regs)
> -{
> -    _fd.ioctlp(KVM_SET_REGS, const_cast<kvm_regs*>(&regs));
> -}
> -
> -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>
Paolo Bonzini Jan. 22, 2020, 2:27 p.m. UTC | #3
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, &regs);
> -    return regs;
> -}
> -
> -void vcpu::set_regs(const kvm_regs& regs)
> -{
> -    _fd.ioctlp(KVM_SET_REGS, const_cast<kvm_regs*>(&regs));
> -}
> -
> -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
diff mbox series

Patch

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, &regs);
-    return regs;
-}
-
-void vcpu::set_regs(const kvm_regs& regs)
-{
-    _fd.ioctlp(KVM_SET_REGS, const_cast<kvm_regs*>(&regs));
-}
-
-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