* [PATCH 0/8] Move closer to upstream
@ 2009-07-08 13:08 Glauber Costa
2009-07-08 13:08 ` [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM Glauber Costa
2009-07-08 13:27 ` [PATCH 0/8] Move closer to upstream Avi Kivity
0 siblings, 2 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:08 UTC (permalink / raw)
To: kvm; +Cc: avi
Hi,
This is another step at getting us closer to qemu upstream. I'm moving
our code to kvm-all.c and kvm.c, and relying on the fact that we use
USE_KVM, while upstream qemu uses CONFIG_KVM, to keep us isolated.
The goal is to slowly reduce that isolation. To demonstrate what I aim
for, the last patches of the series shares code for breakpoint handling.
next in my radar are ioctl functions and cpuid trimming.
Have fun
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM
2009-07-08 13:08 [PATCH 0/8] Move closer to upstream Glauber Costa
@ 2009-07-08 13:08 ` Glauber Costa
2009-07-08 13:22 ` Avi Kivity
[not found] ` <1247058542-31211-3-git-send-email-glommer@redhat.com>
2009-07-08 13:27 ` [PATCH 0/8] Move closer to upstream Avi Kivity
1 sibling, 2 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:08 UTC (permalink / raw)
To: kvm; +Cc: avi
This will allow qemu-kvm to refer to the structure, since qemu-kvm relies
on USE_KVM, not CONFIG_KVM. This should be sent to qemu.git as well
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
kvm.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/kvm.h b/kvm.h
index d9723d7..7648c49 100644
--- a/kvm.h
+++ b/kvm.h
@@ -18,6 +18,9 @@
#include "sys-queue.h"
#include "libkvm-all.h"
+struct KVMState;
+typedef struct KVMState KVMState;
+
#ifdef KVM_UPSTREAM
#ifdef CONFIG_KVM
@@ -65,9 +68,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
/* internal API */
-struct KVMState;
-typedef struct KVMState KVMState;
-
int kvm_ioctl(KVMState *s, int type, ...);
int kvm_vm_ioctl(KVMState *s, int type, ...);
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 3/8] put qemu-kvm-x86.c into kvm.c
[not found] ` <1247058542-31211-3-git-send-email-glommer@redhat.com>
@ 2009-07-08 13:08 ` Glauber Costa
2009-07-08 13:08 ` [PATCH 4/8] replace malloc with qemu_malloc Glauber Costa
` (2 more replies)
2009-07-08 13:23 ` [PATCH 2/8] move qemu-kvm.c to kvm-all.c Avi Kivity
1 sibling, 3 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:08 UTC (permalink / raw)
To: kvm; +Cc: avi
big plan to start sharing code with upstream.
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
Makefile.target | 4 +-
qemu-kvm-x86.c | 1590 -----------------------------------------------------
target-i386/kvm.c | 1582 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1584 insertions(+), 1592 deletions(-)
delete mode 100644 qemu-kvm-x86.c
diff --git a/Makefile.target b/Makefile.target
index 5a54b78..aa79141 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -174,7 +174,7 @@ libobj-y += op_helper.o helper.o
ifeq ($(TARGET_ARCH), i386)
libobj-y += helper.o
ifeq ($(USE_KVM), 1)
-libobj-y += qemu-kvm-x86.o kvm-tpr-opt.o
+libobj-y += kvm.o kvm-tpr-opt.o
libobj-y += qemu-kvm-helper.o
endif
endif
@@ -182,7 +182,7 @@ endif
ifeq ($(TARGET_ARCH), x86_64)
libobj-y += helper.o
ifeq ($(USE_KVM), 1)
-libobj-y += qemu-kvm-x86.o kvm-tpr-opt.o
+libobj-y += kvm.o kvm-tpr-opt.o
libobj-y += qemu-kvm-helper.o
endif
endif
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
deleted file mode 100644
index 8ba3b6e..0000000
--- a/qemu-kvm-x86.c
+++ /dev/null
@@ -1,1590 +0,0 @@
-/*
- * qemu/kvm integration, x86 specific code
- *
- * Copyright (C) 2006-2008 Qumranet Technologies
- *
- * Licensed under the terms of the GNU GPL version 2 or higher.
- */
-
-#include "config.h"
-#include "config-host.h"
-
-#include <string.h>
-#include "hw/hw.h"
-#include "gdbstub.h"
-#include <sys/io.h>
-
-#include "qemu-kvm.h"
-#include "libkvm-all.h"
-#include "libkvm.h"
-#include <pthread.h>
-#include <sys/utsname.h>
-#include <linux/kvm_para.h>
-#include <sys/ioctl.h>
-
-#include "kvm.h"
-#include "hw/pc.h"
-
-#define MSR_IA32_TSC 0x10
-
-static struct kvm_msr_list *kvm_msr_list;
-extern unsigned int kvm_shadow_memory;
-static int kvm_has_msr_star;
-static int kvm_has_vm_hsave_pa;
-
-static int lm_capable_kernel;
-
-int kvm_set_tss_addr(kvm_context_t kvm, unsigned long addr)
-{
-#ifdef KVM_CAP_SET_TSS_ADDR
- int r;
-
- r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
- if (r > 0) {
- r = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, addr);
- if (r == -1) {
- fprintf(stderr, "kvm_set_tss_addr: %m\n");
- return -errno;
- }
- return 0;
- }
-#endif
- return -ENOSYS;
-}
-
-static int kvm_init_tss(kvm_context_t kvm)
-{
-#ifdef KVM_CAP_SET_TSS_ADDR
- int r;
-
- r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
- if (r > 0) {
- /*
- * this address is 3 pages before the bios, and the bios should present
- * as unavaible memory
- */
- r = kvm_set_tss_addr(kvm, 0xfffbd000);
- if (r < 0) {
- fprintf(stderr, "kvm_init_tss: unable to set tss addr\n");
- return r;
- }
-
- }
-#endif
- return 0;
-}
-
-static int kvm_create_pit(kvm_context_t kvm)
-{
-#ifdef KVM_CAP_PIT
- int r;
-
- kvm->pit_in_kernel = 0;
- if (!kvm->no_pit_creation) {
- r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_PIT);
- if (r > 0) {
- r = ioctl(kvm->vm_fd, KVM_CREATE_PIT);
- if (r >= 0)
- kvm->pit_in_kernel = 1;
- else {
- fprintf(stderr, "Create kernel PIC irqchip failed\n");
- return r;
- }
- }
- }
-#endif
- return 0;
-}
-
-int kvm_arch_create(kvm_context_t kvm, unsigned long phys_mem_bytes,
- void **vm_mem)
-{
- int r = 0;
-
- r = kvm_init_tss(kvm);
- if (r < 0)
- return r;
-
- r = kvm_create_pit(kvm);
- if (r < 0)
- return r;
-
- r = kvm_init_coalesced_mmio(kvm);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-#ifdef KVM_EXIT_TPR_ACCESS
-
-static int kvm_handle_tpr_access(kvm_vcpu_context_t vcpu)
-{
- struct kvm_run *run = vcpu->run;
- kvm_tpr_access_report(cpu_single_env,
- run->tpr_access.rip,
- run->tpr_access.is_write);
- return 0;
-}
-
-
-int kvm_enable_vapic(kvm_vcpu_context_t vcpu, uint64_t vapic)
-{
- int r;
- struct kvm_vapic_addr va = {
- .vapic_addr = vapic,
- };
-
- r = ioctl(vcpu->fd, KVM_SET_VAPIC_ADDR, &va);
- if (r == -1) {
- r = -errno;
- perror("kvm_enable_vapic");
- return r;
- }
- return 0;
-}
-
-#endif
-
-int kvm_arch_run(kvm_vcpu_context_t vcpu)
-{
- int r = 0;
- struct kvm_run *run = vcpu->run;
-
-
- switch (run->exit_reason) {
-#ifdef KVM_EXIT_SET_TPR
- case KVM_EXIT_SET_TPR:
- break;
-#endif
-#ifdef KVM_EXIT_TPR_ACCESS
- case KVM_EXIT_TPR_ACCESS:
- r = kvm_handle_tpr_access(vcpu);
- break;
-#endif
- default:
- r = 1;
- break;
- }
-
- return r;
-}
-
-#define MAX_ALIAS_SLOTS 4
-static struct {
- uint64_t start;
- uint64_t len;
-} kvm_aliases[MAX_ALIAS_SLOTS];
-
-static int get_alias_slot(uint64_t start)
-{
- int i;
-
- for (i=0; i<MAX_ALIAS_SLOTS; i++)
- if (kvm_aliases[i].start == start)
- return i;
- return -1;
-}
-static int get_free_alias_slot(void)
-{
- int i;
-
- for (i=0; i<MAX_ALIAS_SLOTS; i++)
- if (kvm_aliases[i].len == 0)
- return i;
- return -1;
-}
-
-static void register_alias(int slot, uint64_t start, uint64_t len)
-{
- kvm_aliases[slot].start = start;
- kvm_aliases[slot].len = len;
-}
-
-int kvm_create_memory_alias(kvm_context_t kvm,
- uint64_t phys_start,
- uint64_t len,
- uint64_t target_phys)
-{
- struct kvm_memory_alias alias = {
- .flags = 0,
- .guest_phys_addr = phys_start,
- .memory_size = len,
- .target_phys_addr = target_phys,
- };
- int fd = kvm->vm_fd;
- int r;
- int slot;
-
- slot = get_alias_slot(phys_start);
- if (slot < 0)
- slot = get_free_alias_slot();
- if (slot < 0)
- return -EBUSY;
- alias.slot = slot;
-
- r = ioctl(fd, KVM_SET_MEMORY_ALIAS, &alias);
- if (r == -1)
- return -errno;
-
- register_alias(slot, phys_start, len);
- return 0;
-}
-
-int kvm_destroy_memory_alias(kvm_context_t kvm, uint64_t phys_start)
-{
- return kvm_create_memory_alias(kvm, phys_start, 0, 0);
-}
-
-#ifdef KVM_CAP_IRQCHIP
-
-int kvm_get_lapic(kvm_vcpu_context_t vcpu, struct kvm_lapic_state *s)
-{
- int r;
- if (!kvm_irqchip_in_kernel(vcpu->kvm))
- return 0;
- r = ioctl(vcpu->fd, KVM_GET_LAPIC, s);
- if (r == -1) {
- r = -errno;
- perror("kvm_get_lapic");
- }
- return r;
-}
-
-int kvm_set_lapic(kvm_vcpu_context_t vcpu, struct kvm_lapic_state *s)
-{
- int r;
- if (!kvm_irqchip_in_kernel(vcpu->kvm))
- return 0;
- r = ioctl(vcpu->fd, KVM_SET_LAPIC, s);
- if (r == -1) {
- r = -errno;
- perror("kvm_set_lapic");
- }
- return r;
-}
-
-#endif
-
-#ifdef KVM_CAP_PIT
-
-int kvm_get_pit(kvm_context_t kvm, struct kvm_pit_state *s)
-{
- int r;
- if (!kvm->pit_in_kernel)
- return 0;
- r = ioctl(kvm->vm_fd, KVM_GET_PIT, s);
- if (r == -1) {
- r = -errno;
- perror("kvm_get_pit");
- }
- return r;
-}
-
-int kvm_set_pit(kvm_context_t kvm, struct kvm_pit_state *s)
-{
- int r;
- if (!kvm->pit_in_kernel)
- return 0;
- r = ioctl(kvm->vm_fd, KVM_SET_PIT, s);
- if (r == -1) {
- r = -errno;
- perror("kvm_set_pit");
- }
- return r;
-}
-
-#endif
-
-void kvm_show_code(kvm_vcpu_context_t vcpu)
-{
-#define SHOW_CODE_LEN 50
- int fd = vcpu->fd;
- struct kvm_regs regs;
- struct kvm_sregs sregs;
- int r, n;
- int back_offset;
- unsigned char code;
- char code_str[SHOW_CODE_LEN * 3 + 1];
- unsigned long rip;
- kvm_context_t kvm = vcpu->kvm;
-
- r = ioctl(fd, KVM_GET_SREGS, &sregs);
- if (r == -1) {
- perror("KVM_GET_SREGS");
- return;
- }
- r = ioctl(fd, KVM_GET_REGS, ®s);
- if (r == -1) {
- perror("KVM_GET_REGS");
- return;
- }
- rip = sregs.cs.base + regs.rip;
- back_offset = regs.rip;
- if (back_offset > 20)
- back_offset = 20;
- *code_str = 0;
- for (n = -back_offset; n < SHOW_CODE_LEN-back_offset; ++n) {
- if (n == 0)
- strcat(code_str, " -->");
- r = kvm_mmio_read(kvm->opaque, rip + n, &code, 1);
- if (r < 0) {
- strcat(code_str, " xx");
- continue;
- }
- sprintf(code_str + strlen(code_str), " %02x", code);
- }
- fprintf(stderr, "code:%s\n", code_str);
-}
-
-
-/*
- * Returns available msr list. User must free.
- */
-struct kvm_msr_list *kvm_get_msr_list(kvm_context_t kvm)
-{
- struct kvm_msr_list sizer, *msrs;
- int r, e;
-
- sizer.nmsrs = 0;
- r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, &sizer);
- if (r == -1 && errno != E2BIG)
- return NULL;
- /* Old kernel modules had a bug and could write beyond the provided
- memory. Allocate at least a safe amount of 1K. */
- msrs = malloc(MAX(1024, sizeof(*msrs) +
- sizer.nmsrs * sizeof(*msrs->indices)));
- if (!msrs) {
- errno = ENOMEM;
- return NULL;
- }
- msrs->nmsrs = sizer.nmsrs;
- r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, msrs);
- if (r == -1) {
- e = errno;
- free(msrs);
- errno = e;
- return NULL;
- }
- return msrs;
-}
-
-int kvm_get_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
-{
- struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs);
- int r, e;
-
- if (!kmsrs) {
- errno = ENOMEM;
- return -1;
- }
- kmsrs->nmsrs = n;
- memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
- r = ioctl(vcpu->fd, KVM_GET_MSRS, kmsrs);
- e = errno;
- memcpy(msrs, kmsrs->entries, n * sizeof *msrs);
- free(kmsrs);
- errno = e;
- return r;
-}
-
-int kvm_set_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
-{
- struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs);
- int r, e;
-
- if (!kmsrs) {
- errno = ENOMEM;
- return -1;
- }
- kmsrs->nmsrs = n;
- memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
- r = ioctl(vcpu->fd, KVM_SET_MSRS, kmsrs);
- e = errno;
- free(kmsrs);
- errno = e;
- return r;
-}
-
-static void print_seg(FILE *file, const char *name, struct kvm_segment *seg)
-{
- fprintf(stderr,
- "%s %04x (%08llx/%08x p %d dpl %d db %d s %d type %x l %d"
- " g %d avl %d)\n",
- name, seg->selector, seg->base, seg->limit, seg->present,
- seg->dpl, seg->db, seg->s, seg->type, seg->l, seg->g,
- seg->avl);
-}
-
-static void print_dt(FILE *file, const char *name, struct kvm_dtable *dt)
-{
- fprintf(stderr, "%s %llx/%x\n", name, dt->base, dt->limit);
-}
-
-void kvm_show_regs(kvm_vcpu_context_t vcpu)
-{
- int fd = vcpu->fd;
- struct kvm_regs regs;
- struct kvm_sregs sregs;
- int r;
-
- r = ioctl(fd, KVM_GET_REGS, ®s);
- if (r == -1) {
- perror("KVM_GET_REGS");
- return;
- }
- fprintf(stderr,
- "rax %016llx rbx %016llx rcx %016llx rdx %016llx\n"
- "rsi %016llx rdi %016llx rsp %016llx rbp %016llx\n"
- "r8 %016llx r9 %016llx r10 %016llx r11 %016llx\n"
- "r12 %016llx r13 %016llx r14 %016llx r15 %016llx\n"
- "rip %016llx rflags %08llx\n",
- regs.rax, regs.rbx, regs.rcx, regs.rdx,
- regs.rsi, regs.rdi, regs.rsp, regs.rbp,
- regs.r8, regs.r9, regs.r10, regs.r11,
- regs.r12, regs.r13, regs.r14, regs.r15,
- regs.rip, regs.rflags);
- r = ioctl(fd, KVM_GET_SREGS, &sregs);
- if (r == -1) {
- perror("KVM_GET_SREGS");
- return;
- }
- print_seg(stderr, "cs", &sregs.cs);
- print_seg(stderr, "ds", &sregs.ds);
- print_seg(stderr, "es", &sregs.es);
- print_seg(stderr, "ss", &sregs.ss);
- print_seg(stderr, "fs", &sregs.fs);
- print_seg(stderr, "gs", &sregs.gs);
- print_seg(stderr, "tr", &sregs.tr);
- print_seg(stderr, "ldt", &sregs.ldt);
- print_dt(stderr, "gdt", &sregs.gdt);
- print_dt(stderr, "idt", &sregs.idt);
- fprintf(stderr, "cr0 %llx cr2 %llx cr3 %llx cr4 %llx cr8 %llx"
- " efer %llx\n",
- sregs.cr0, sregs.cr2, sregs.cr3, sregs.cr4, sregs.cr8,
- sregs.efer);
-}
-
-uint64_t kvm_get_apic_base(kvm_vcpu_context_t vcpu)
-{
- return vcpu->run->apic_base;
-}
-
-void kvm_set_cr8(kvm_vcpu_context_t vcpu, uint64_t cr8)
-{
- vcpu->run->cr8 = cr8;
-}
-
-__u64 kvm_get_cr8(kvm_vcpu_context_t vcpu)
-{
- return vcpu->run->cr8;
-}
-
-int kvm_setup_cpuid(kvm_vcpu_context_t vcpu, int nent,
- struct kvm_cpuid_entry *entries)
-{
- struct kvm_cpuid *cpuid;
- int r;
-
- cpuid = malloc(sizeof(*cpuid) + nent * sizeof(*entries));
- if (!cpuid)
- return -ENOMEM;
-
- cpuid->nent = nent;
- memcpy(cpuid->entries, entries, nent * sizeof(*entries));
- r = ioctl(vcpu->fd, KVM_SET_CPUID, cpuid);
-
- free(cpuid);
- return r;
-}
-
-int kvm_setup_cpuid2(kvm_vcpu_context_t vcpu, int nent,
- struct kvm_cpuid_entry2 *entries)
-{
- struct kvm_cpuid2 *cpuid;
- int r;
-
- cpuid = malloc(sizeof(*cpuid) + nent * sizeof(*entries));
- if (!cpuid)
- return -ENOMEM;
-
- cpuid->nent = nent;
- memcpy(cpuid->entries, entries, nent * sizeof(*entries));
- r = ioctl(vcpu->fd, KVM_SET_CPUID2, cpuid);
- if (r == -1) {
- fprintf(stderr, "kvm_setup_cpuid2: %m\n");
- return -errno;
- }
- free(cpuid);
- return r;
-}
-
-int kvm_set_shadow_pages(kvm_context_t kvm, unsigned int nrshadow_pages)
-{
-#ifdef KVM_CAP_MMU_SHADOW_CACHE_CONTROL
- int r;
-
- r = ioctl(kvm->fd, KVM_CHECK_EXTENSION,
- KVM_CAP_MMU_SHADOW_CACHE_CONTROL);
- if (r > 0) {
- r = ioctl(kvm->vm_fd, KVM_SET_NR_MMU_PAGES, nrshadow_pages);
- if (r == -1) {
- fprintf(stderr, "kvm_set_shadow_pages: %m\n");
- return -errno;
- }
- return 0;
- }
-#endif
- return -1;
-}
-
-int kvm_get_shadow_pages(kvm_context_t kvm, unsigned int *nrshadow_pages)
-{
-#ifdef KVM_CAP_MMU_SHADOW_CACHE_CONTROL
- int r;
-
- r = ioctl(kvm->fd, KVM_CHECK_EXTENSION,
- KVM_CAP_MMU_SHADOW_CACHE_CONTROL);
- if (r > 0) {
- *nrshadow_pages = ioctl(kvm->vm_fd, KVM_GET_NR_MMU_PAGES);
- return 0;
- }
-#endif
- return -1;
-}
-
-#ifdef KVM_CAP_VAPIC
-
-static int tpr_access_reporting(kvm_vcpu_context_t vcpu, int enabled)
-{
- int r;
- struct kvm_tpr_access_ctl tac = {
- .enabled = enabled,
- };
-
- r = ioctl(vcpu->kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_VAPIC);
- if (r == -1 || r == 0)
- return -ENOSYS;
- r = ioctl(vcpu->fd, KVM_TPR_ACCESS_REPORTING, &tac);
- if (r == -1) {
- r = -errno;
- perror("KVM_TPR_ACCESS_REPORTING");
- return r;
- }
- return 0;
-}
-
-int kvm_enable_tpr_access_reporting(kvm_vcpu_context_t vcpu)
-{
- return tpr_access_reporting(vcpu, 1);
-}
-
-int kvm_disable_tpr_access_reporting(kvm_vcpu_context_t vcpu)
-{
- return tpr_access_reporting(vcpu, 0);
-}
-
-#endif
-
-#ifdef KVM_CAP_EXT_CPUID
-
-static struct kvm_cpuid2 *try_get_cpuid(kvm_context_t kvm, int max)
-{
- struct kvm_cpuid2 *cpuid;
- int r, size;
-
- size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
- cpuid = (struct kvm_cpuid2 *)malloc(size);
- cpuid->nent = max;
- r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, cpuid);
- if (r == -1)
- r = -errno;
- else if (r == 0 && cpuid->nent >= max)
- r = -E2BIG;
- if (r < 0) {
- if (r == -E2BIG) {
- free(cpuid);
- return NULL;
- } else {
- fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
- strerror(-r));
- exit(1);
- }
- }
- return cpuid;
-}
-
-#define R_EAX 0
-#define R_ECX 1
-#define R_EDX 2
-#define R_EBX 3
-#define R_ESP 4
-#define R_EBP 5
-#define R_ESI 6
-#define R_EDI 7
-
-uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg)
-{
- struct kvm_cpuid2 *cpuid;
- int i, max;
- uint32_t ret = 0;
- uint32_t cpuid_1_edx;
-
- if (!kvm_check_extension(kvm, KVM_CAP_EXT_CPUID)) {
- return -1U;
- }
-
- max = 1;
- while ((cpuid = try_get_cpuid(kvm, max)) == NULL) {
- max *= 2;
- }
-
- for (i = 0; i < cpuid->nent; ++i) {
- if (cpuid->entries[i].function == function) {
- switch (reg) {
- case R_EAX:
- ret = cpuid->entries[i].eax;
- break;
- case R_EBX:
- ret = cpuid->entries[i].ebx;
- break;
- case R_ECX:
- ret = cpuid->entries[i].ecx;
- break;
- case R_EDX:
- ret = cpuid->entries[i].edx;
- if (function == 1) {
- /* kvm misreports the following features
- */
- ret |= 1 << 12; /* MTRR */
- ret |= 1 << 16; /* PAT */
- ret |= 1 << 7; /* MCE */
- ret |= 1 << 14; /* MCA */
- }
-
- /* On Intel, kvm returns cpuid according to
- * the Intel spec, so add missing bits
- * according to the AMD spec:
- */
- if (function == 0x80000001) {
- cpuid_1_edx = kvm_get_supported_cpuid(kvm, 1, R_EDX);
- ret |= cpuid_1_edx & 0xdfeff7ff;
- }
- break;
- }
- }
- }
-
- free(cpuid);
-
- return ret;
-}
-
-#else
-
-uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg)
-{
- return -1U;
-}
-
-#endif
-int kvm_qemu_create_memory_alias(uint64_t phys_start,
- uint64_t len,
- uint64_t target_phys)
-{
- return kvm_create_memory_alias(kvm_context, phys_start, len, target_phys);
-}
-
-int kvm_qemu_destroy_memory_alias(uint64_t phys_start)
-{
- return kvm_destroy_memory_alias(kvm_context, phys_start);
-}
-
-int kvm_arch_qemu_create_context(void)
-{
- int i;
- struct utsname utsname;
-
- uname(&utsname);
- lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
-
- if (kvm_shadow_memory)
- kvm_set_shadow_pages(kvm_context, kvm_shadow_memory);
-
- kvm_msr_list = kvm_get_msr_list(kvm_context);
- if (!kvm_msr_list)
- return -1;
- for (i = 0; i < kvm_msr_list->nmsrs; ++i) {
- if (kvm_msr_list->indices[i] == MSR_STAR)
- kvm_has_msr_star = 1;
- if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA)
- kvm_has_vm_hsave_pa = 1;
- }
-
- return 0;
-}
-
-static void set_msr_entry(struct kvm_msr_entry *entry, uint32_t index,
- uint64_t data)
-{
- entry->index = index;
- entry->data = data;
-}
-
-/* returns 0 on success, non-0 on failure */
-static int get_msr_entry(struct kvm_msr_entry *entry, CPUState *env)
-{
- switch (entry->index) {
- case MSR_IA32_SYSENTER_CS:
- env->sysenter_cs = entry->data;
- break;
- case MSR_IA32_SYSENTER_ESP:
- env->sysenter_esp = entry->data;
- break;
- case MSR_IA32_SYSENTER_EIP:
- env->sysenter_eip = entry->data;
- break;
- case MSR_STAR:
- env->star = entry->data;
- break;
-#ifdef TARGET_X86_64
- case MSR_CSTAR:
- env->cstar = entry->data;
- break;
- case MSR_KERNELGSBASE:
- env->kernelgsbase = entry->data;
- break;
- case MSR_FMASK:
- env->fmask = entry->data;
- break;
- case MSR_LSTAR:
- env->lstar = entry->data;
- break;
-#endif
- case MSR_IA32_TSC:
- env->tsc = entry->data;
- break;
- case MSR_VM_HSAVE_PA:
- env->vm_hsave = entry->data;
- break;
- default:
- printf("Warning unknown msr index 0x%x\n", entry->index);
- return 1;
- }
- return 0;
-}
-
-#ifdef TARGET_X86_64
-#define MSR_COUNT 9
-#else
-#define MSR_COUNT 5
-#endif
-
-static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
-{
- lhs->selector = rhs->selector;
- lhs->base = rhs->base;
- lhs->limit = rhs->limit;
- lhs->type = 3;
- lhs->present = 1;
- lhs->dpl = 3;
- lhs->db = 0;
- lhs->s = 1;
- lhs->l = 0;
- lhs->g = 0;
- lhs->avl = 0;
- lhs->unusable = 0;
-}
-
-static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
-{
- unsigned flags = rhs->flags;
- lhs->selector = rhs->selector;
- lhs->base = rhs->base;
- lhs->limit = rhs->limit;
- lhs->type = (flags >> DESC_TYPE_SHIFT) & 15;
- lhs->present = (flags & DESC_P_MASK) != 0;
- lhs->dpl = rhs->selector & 3;
- lhs->db = (flags >> DESC_B_SHIFT) & 1;
- lhs->s = (flags & DESC_S_MASK) != 0;
- lhs->l = (flags >> DESC_L_SHIFT) & 1;
- lhs->g = (flags & DESC_G_MASK) != 0;
- lhs->avl = (flags & DESC_AVL_MASK) != 0;
- lhs->unusable = 0;
-}
-
-static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
-{
- lhs->selector = rhs->selector;
- lhs->base = rhs->base;
- lhs->limit = rhs->limit;
- lhs->flags =
- (rhs->type << DESC_TYPE_SHIFT)
- | (rhs->present * DESC_P_MASK)
- | (rhs->dpl << DESC_DPL_SHIFT)
- | (rhs->db << DESC_B_SHIFT)
- | (rhs->s * DESC_S_MASK)
- | (rhs->l << DESC_L_SHIFT)
- | (rhs->g * DESC_G_MASK)
- | (rhs->avl * DESC_AVL_MASK);
-}
-
-void kvm_arch_load_regs(CPUState *env)
-{
- struct kvm_regs regs;
- struct kvm_fpu fpu;
- struct kvm_sregs sregs;
- struct kvm_msr_entry msrs[MSR_COUNT];
- int rc, n, i;
-
- regs.rax = env->regs[R_EAX];
- regs.rbx = env->regs[R_EBX];
- regs.rcx = env->regs[R_ECX];
- regs.rdx = env->regs[R_EDX];
- regs.rsi = env->regs[R_ESI];
- regs.rdi = env->regs[R_EDI];
- regs.rsp = env->regs[R_ESP];
- regs.rbp = env->regs[R_EBP];
-#ifdef TARGET_X86_64
- regs.r8 = env->regs[8];
- regs.r9 = env->regs[9];
- regs.r10 = env->regs[10];
- regs.r11 = env->regs[11];
- regs.r12 = env->regs[12];
- regs.r13 = env->regs[13];
- regs.r14 = env->regs[14];
- regs.r15 = env->regs[15];
-#endif
-
- regs.rflags = env->eflags;
- regs.rip = env->eip;
-
- kvm_set_regs(env->kvm_cpu_state.vcpu_ctx, ®s);
-
- memset(&fpu, 0, sizeof fpu);
- fpu.fsw = env->fpus & ~(7 << 11);
- fpu.fsw |= (env->fpstt & 7) << 11;
- fpu.fcw = env->fpuc;
- for (i = 0; i < 8; ++i)
- fpu.ftwx |= (!env->fptags[i]) << i;
- memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
- memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
- fpu.mxcsr = env->mxcsr;
- kvm_set_fpu(env->kvm_cpu_state.vcpu_ctx, &fpu);
-
- memcpy(sregs.interrupt_bitmap, env->interrupt_bitmap, sizeof(sregs.interrupt_bitmap));
-
- if ((env->eflags & VM_MASK)) {
- set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
- set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
- set_v8086_seg(&sregs.es, &env->segs[R_ES]);
- set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
- set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
- set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
- } else {
- set_seg(&sregs.cs, &env->segs[R_CS]);
- set_seg(&sregs.ds, &env->segs[R_DS]);
- set_seg(&sregs.es, &env->segs[R_ES]);
- set_seg(&sregs.fs, &env->segs[R_FS]);
- set_seg(&sregs.gs, &env->segs[R_GS]);
- set_seg(&sregs.ss, &env->segs[R_SS]);
-
- if (env->cr[0] & CR0_PE_MASK) {
- /* force ss cpl to cs cpl */
- sregs.ss.selector = (sregs.ss.selector & ~3) |
- (sregs.cs.selector & 3);
- sregs.ss.dpl = sregs.ss.selector & 3;
- }
- }
-
- set_seg(&sregs.tr, &env->tr);
- set_seg(&sregs.ldt, &env->ldt);
-
- sregs.idt.limit = env->idt.limit;
- sregs.idt.base = env->idt.base;
- sregs.gdt.limit = env->gdt.limit;
- sregs.gdt.base = env->gdt.base;
-
- sregs.cr0 = env->cr[0];
- sregs.cr2 = env->cr[2];
- sregs.cr3 = env->cr[3];
- sregs.cr4 = env->cr[4];
-
- sregs.cr8 = cpu_get_apic_tpr(env);
- sregs.apic_base = cpu_get_apic_base(env);
-
- sregs.efer = env->efer;
-
- kvm_set_sregs(env->kvm_cpu_state.vcpu_ctx, &sregs);
-
- /* msrs */
- n = 0;
- set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
- set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
- set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
- if (kvm_has_msr_star)
- set_msr_entry(&msrs[n++], MSR_STAR, env->star);
- if (kvm_has_vm_hsave_pa)
- set_msr_entry(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
-#ifdef TARGET_X86_64
- if (lm_capable_kernel) {
- set_msr_entry(&msrs[n++], MSR_CSTAR, env->cstar);
- set_msr_entry(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase);
- set_msr_entry(&msrs[n++], MSR_FMASK, env->fmask);
- set_msr_entry(&msrs[n++], MSR_LSTAR , env->lstar);
- }
-#endif
-
- rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n);
- if (rc == -1)
- perror("kvm_set_msrs FAILED");
-}
-
-void kvm_load_tsc(CPUState *env)
-{
- int rc;
- struct kvm_msr_entry msr;
-
- set_msr_entry(&msr, MSR_IA32_TSC, env->tsc);
-
- rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, &msr, 1);
- if (rc == -1)
- perror("kvm_set_tsc FAILED.\n");
-}
-
-void kvm_arch_save_mpstate(CPUState *env)
-{
-#ifdef KVM_CAP_MP_STATE
- int r;
- struct kvm_mp_state mp_state;
-
- r = kvm_get_mpstate(env->kvm_cpu_state.vcpu_ctx, &mp_state);
- if (r < 0)
- env->mp_state = -1;
- else
- env->mp_state = mp_state.mp_state;
-#endif
-}
-
-void kvm_arch_load_mpstate(CPUState *env)
-{
-#ifdef KVM_CAP_MP_STATE
- struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
-
- /*
- * -1 indicates that the host did not support GET_MP_STATE ioctl,
- * so don't touch it.
- */
- if (env->mp_state != -1)
- kvm_set_mpstate(env->kvm_cpu_state.vcpu_ctx, &mp_state);
-#endif
-}
-
-void kvm_arch_save_regs(CPUState *env)
-{
- struct kvm_regs regs;
- struct kvm_fpu fpu;
- struct kvm_sregs sregs;
- struct kvm_msr_entry msrs[MSR_COUNT];
- uint32_t hflags;
- uint32_t i, n, rc;
-
- kvm_get_regs(env->kvm_cpu_state.vcpu_ctx, ®s);
-
- env->regs[R_EAX] = regs.rax;
- env->regs[R_EBX] = regs.rbx;
- env->regs[R_ECX] = regs.rcx;
- env->regs[R_EDX] = regs.rdx;
- env->regs[R_ESI] = regs.rsi;
- env->regs[R_EDI] = regs.rdi;
- env->regs[R_ESP] = regs.rsp;
- env->regs[R_EBP] = regs.rbp;
-#ifdef TARGET_X86_64
- env->regs[8] = regs.r8;
- env->regs[9] = regs.r9;
- env->regs[10] = regs.r10;
- env->regs[11] = regs.r11;
- env->regs[12] = regs.r12;
- env->regs[13] = regs.r13;
- env->regs[14] = regs.r14;
- env->regs[15] = regs.r15;
-#endif
-
- env->eflags = regs.rflags;
- env->eip = regs.rip;
-
- kvm_get_fpu(env->kvm_cpu_state.vcpu_ctx, &fpu);
- env->fpstt = (fpu.fsw >> 11) & 7;
- env->fpus = fpu.fsw;
- env->fpuc = fpu.fcw;
- for (i = 0; i < 8; ++i)
- env->fptags[i] = !((fpu.ftwx >> i) & 1);
- memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
- memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs);
- env->mxcsr = fpu.mxcsr;
-
- kvm_get_sregs(env->kvm_cpu_state.vcpu_ctx, &sregs);
-
- memcpy(env->interrupt_bitmap, sregs.interrupt_bitmap, sizeof(env->interrupt_bitmap));
-
- get_seg(&env->segs[R_CS], &sregs.cs);
- get_seg(&env->segs[R_DS], &sregs.ds);
- get_seg(&env->segs[R_ES], &sregs.es);
- get_seg(&env->segs[R_FS], &sregs.fs);
- get_seg(&env->segs[R_GS], &sregs.gs);
- get_seg(&env->segs[R_SS], &sregs.ss);
-
- get_seg(&env->tr, &sregs.tr);
- get_seg(&env->ldt, &sregs.ldt);
-
- env->idt.limit = sregs.idt.limit;
- env->idt.base = sregs.idt.base;
- env->gdt.limit = sregs.gdt.limit;
- env->gdt.base = sregs.gdt.base;
-
- env->cr[0] = sregs.cr0;
- env->cr[2] = sregs.cr2;
- env->cr[3] = sregs.cr3;
- env->cr[4] = sregs.cr4;
-
- cpu_set_apic_base(env, sregs.apic_base);
-
- env->efer = sregs.efer;
- //cpu_set_apic_tpr(env, sregs.cr8);
-
-#define HFLAG_COPY_MASK ~( \
- HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
- HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
- HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
- HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
-
-
-
- hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
- hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
- hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
- (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
- hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
- hflags |= (env->cr[4] & CR4_OSFXSR_MASK) <<
- (HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT);
-
- if (env->efer & MSR_EFER_LMA) {
- hflags |= HF_LMA_MASK;
- }
-
- if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
- hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
- } else {
- hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
- (DESC_B_SHIFT - HF_CS32_SHIFT);
- hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
- (DESC_B_SHIFT - HF_SS32_SHIFT);
- if (!(env->cr[0] & CR0_PE_MASK) ||
- (env->eflags & VM_MASK) ||
- !(hflags & HF_CS32_MASK)) {
- hflags |= HF_ADDSEG_MASK;
- } else {
- hflags |= ((env->segs[R_DS].base |
- env->segs[R_ES].base |
- env->segs[R_SS].base) != 0) <<
- HF_ADDSEG_SHIFT;
- }
- }
- env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags;
-
- /* msrs */
- n = 0;
- msrs[n++].index = MSR_IA32_SYSENTER_CS;
- msrs[n++].index = MSR_IA32_SYSENTER_ESP;
- msrs[n++].index = MSR_IA32_SYSENTER_EIP;
- if (kvm_has_msr_star)
- msrs[n++].index = MSR_STAR;
- msrs[n++].index = MSR_IA32_TSC;
- if (kvm_has_vm_hsave_pa)
- msrs[n++].index = MSR_VM_HSAVE_PA;
-#ifdef TARGET_X86_64
- if (lm_capable_kernel) {
- msrs[n++].index = MSR_CSTAR;
- msrs[n++].index = MSR_KERNELGSBASE;
- msrs[n++].index = MSR_FMASK;
- msrs[n++].index = MSR_LSTAR;
- }
-#endif
- rc = kvm_get_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n);
- if (rc == -1) {
- perror("kvm_get_msrs FAILED");
- }
- else {
- n = rc; /* actual number of MSRs */
- for (i=0 ; i<n; i++) {
- if (get_msr_entry(&msrs[i], env))
- return;
- }
- }
-}
-
-static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function,
- uint32_t count, CPUState *env)
-{
- env->regs[R_EAX] = function;
- env->regs[R_ECX] = count;
- qemu_kvm_cpuid_on_env(env);
- e->function = function;
- e->flags = 0;
- e->index = 0;
- e->eax = env->regs[R_EAX];
- e->ebx = env->regs[R_EBX];
- e->ecx = env->regs[R_ECX];
- e->edx = env->regs[R_EDX];
-}
-
-struct kvm_para_features {
- int cap;
- int feature;
-} para_features[] = {
-#ifdef KVM_CAP_CLOCKSOURCE
- { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
-#endif
-#ifdef KVM_CAP_NOP_IO_DELAY
- { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
-#endif
-#ifdef KVM_CAP_PV_MMU
- { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
-#endif
-#ifdef KVM_CAP_CR3_CACHE
- { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE },
-#endif
- { -1, -1 }
-};
-
-static int get_para_features(kvm_context_t kvm_context)
-{
- int i, features = 0;
-
- for (i = 0; i < ARRAY_SIZE(para_features)-1; i++) {
- if (kvm_check_extension(kvm_context, para_features[i].cap))
- features |= (1 << para_features[i].feature);
- }
-
- return features;
-}
-
-static void kvm_trim_features(uint32_t *features, uint32_t supported)
-{
- int i;
- uint32_t mask;
-
- for (i = 0; i < 32; ++i) {
- mask = 1U << i;
- if ((*features & mask) && !(supported & mask)) {
- *features &= ~mask;
- }
- }
-}
-
-int kvm_arch_qemu_init_env(CPUState *cenv)
-{
- struct kvm_cpuid_entry2 cpuid_ent[100];
-#ifdef KVM_CPUID_SIGNATURE
- struct kvm_cpuid_entry2 *pv_ent;
- uint32_t signature[3];
-#endif
- int cpuid_nent = 0;
- CPUState copy;
- uint32_t i, j, limit;
-
- qemu_kvm_load_lapic(cenv);
-
-
-#ifdef KVM_CPUID_SIGNATURE
- /* Paravirtualization CPUIDs */
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
- pv_ent = &cpuid_ent[cpuid_nent++];
- memset(pv_ent, 0, sizeof(*pv_ent));
- pv_ent->function = KVM_CPUID_SIGNATURE;
- pv_ent->eax = 0;
- pv_ent->ebx = signature[0];
- pv_ent->ecx = signature[1];
- pv_ent->edx = signature[2];
-
- pv_ent = &cpuid_ent[cpuid_nent++];
- memset(pv_ent, 0, sizeof(*pv_ent));
- pv_ent->function = KVM_CPUID_FEATURES;
- pv_ent->eax = get_para_features(kvm_context);
-#endif
-
- kvm_trim_features(&cenv->cpuid_features,
- kvm_arch_get_supported_cpuid(cenv, 1, R_EDX));
-
- /* prevent the hypervisor bit from being cleared by the kernel */
- i = cenv->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
- kvm_trim_features(&cenv->cpuid_ext_features,
- kvm_arch_get_supported_cpuid(cenv, 1, R_ECX));
- cenv->cpuid_ext_features |= i;
-
- kvm_trim_features(&cenv->cpuid_ext2_features,
- kvm_arch_get_supported_cpuid(cenv, 0x80000001, R_EDX));
- kvm_trim_features(&cenv->cpuid_ext3_features,
- kvm_arch_get_supported_cpuid(cenv, 0x80000001, R_ECX));
-
- copy = *cenv;
-
- copy.regs[R_EAX] = 0;
- qemu_kvm_cpuid_on_env(©);
- limit = copy.regs[R_EAX];
-
- for (i = 0; i <= limit; ++i) {
- if (i == 4 || i == 0xb || i == 0xd) {
- for (j = 0; ; ++j) {
- do_cpuid_ent(&cpuid_ent[cpuid_nent], i, j, ©);
-
- cpuid_ent[cpuid_nent].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
- cpuid_ent[cpuid_nent].index = j;
-
- cpuid_nent++;
-
- if (i == 4 && copy.regs[R_EAX] == 0)
- break;
- if (i == 0xb && !(copy.regs[R_ECX] & 0xff00))
- break;
- if (i == 0xd && copy.regs[R_EAX] == 0)
- break;
- }
- } else
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
- }
-
- copy.regs[R_EAX] = 0x80000000;
- qemu_kvm_cpuid_on_env(©);
- limit = copy.regs[R_EAX];
-
- for (i = 0x80000000; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
-
- kvm_setup_cpuid2(cenv->kvm_cpu_state.vcpu_ctx, cpuid_nent, cpuid_ent);
-
- return 0;
-}
-
-int kvm_arch_halt(void *opaque, kvm_vcpu_context_t vcpu)
-{
- CPUState *env = cpu_single_env;
-
- if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) &&
- !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
- env->halted = 1;
- }
- return 1;
-}
-
-void kvm_arch_pre_kvm_run(void *opaque, CPUState *env)
-{
- if (!kvm_irqchip_in_kernel(kvm_context))
- kvm_set_cr8(env->kvm_cpu_state.vcpu_ctx, cpu_get_apic_tpr(env));
-}
-
-void kvm_arch_post_kvm_run(void *opaque, CPUState *env)
-{
- cpu_single_env = env;
-
- env->eflags = kvm_get_interrupt_flag(env->kvm_cpu_state.vcpu_ctx)
- ? env->eflags | IF_MASK : env->eflags & ~IF_MASK;
-
- cpu_set_apic_tpr(env, kvm_get_cr8(env->kvm_cpu_state.vcpu_ctx));
- cpu_set_apic_base(env, kvm_get_apic_base(env->kvm_cpu_state.vcpu_ctx));
-}
-
-int kvm_arch_has_work(CPUState *env)
-{
- if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) ||
- (env->interrupt_request & CPU_INTERRUPT_NMI))
- return 1;
- return 0;
-}
-
-int kvm_arch_try_push_interrupts(void *opaque)
-{
- CPUState *env = cpu_single_env;
- int r, irq;
-
- if (kvm_is_ready_for_interrupt_injection(env->kvm_cpu_state.vcpu_ctx) &&
- (env->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) {
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
- irq = cpu_get_pic_interrupt(env);
- if (irq >= 0) {
- r = kvm_inject_irq(env->kvm_cpu_state.vcpu_ctx, irq);
- if (r < 0)
- printf("cpu %d fail inject %x\n", env->cpu_index, irq);
- }
- }
-
- return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
-}
-
-#ifdef KVM_CAP_USER_NMI
-void kvm_arch_push_nmi(void *opaque)
-{
- CPUState *env = cpu_single_env;
- int r;
-
- if (likely(!(env->interrupt_request & CPU_INTERRUPT_NMI)))
- return;
-
- env->interrupt_request &= ~CPU_INTERRUPT_NMI;
- r = kvm_inject_nmi(env->kvm_cpu_state.vcpu_ctx);
- if (r < 0)
- printf("cpu %d fail inject NMI\n", env->cpu_index);
-}
-#endif /* KVM_CAP_USER_NMI */
-
-void kvm_arch_update_regs_for_sipi(CPUState *env)
-{
- SegmentCache cs = env->segs[R_CS];
-
- kvm_arch_save_regs(env);
- env->segs[R_CS] = cs;
- env->eip = 0;
- kvm_arch_load_regs(env);
-}
-
-void kvm_arch_cpu_reset(CPUState *env)
-{
- kvm_arch_load_regs(env);
- if (!cpu_is_bsp(env)) {
- if (kvm_irqchip_in_kernel(kvm_context)) {
-#ifdef KVM_CAP_MP_STATE
- kvm_reset_mpstate(env->kvm_cpu_state.vcpu_ctx);
-#endif
- } else {
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
- env->halted = 1;
- }
- }
-}
-
-int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
-{
- uint8_t int3 = 0xcc;
-
- if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
- cpu_memory_rw_debug(env, bp->pc, &int3, 1, 1))
- return -EINVAL;
- return 0;
-}
-
-int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
-{
- uint8_t int3;
-
- if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
- return -EINVAL;
- return 0;
-}
-
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-static struct {
- target_ulong addr;
- int len;
- int type;
-} hw_breakpoint[4];
-
-static int nb_hw_breakpoint;
-
-static int find_hw_breakpoint(target_ulong addr, int len, int type)
-{
- int n;
-
- for (n = 0; n < nb_hw_breakpoint; n++)
- if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
- (hw_breakpoint[n].len == len || len == -1))
- return n;
- return -1;
-}
-
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- switch (type) {
- case GDB_BREAKPOINT_HW:
- len = 1;
- break;
- case GDB_WATCHPOINT_WRITE:
- case GDB_WATCHPOINT_ACCESS:
- switch (len) {
- case 1:
- break;
- case 2:
- case 4:
- case 8:
- if (addr & (len - 1))
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- return -ENOSYS;
- }
-
- if (nb_hw_breakpoint == 4)
- return -ENOBUFS;
-
- if (find_hw_breakpoint(addr, len, type) >= 0)
- return -EEXIST;
-
- hw_breakpoint[nb_hw_breakpoint].addr = addr;
- hw_breakpoint[nb_hw_breakpoint].len = len;
- hw_breakpoint[nb_hw_breakpoint].type = type;
- nb_hw_breakpoint++;
-
- return 0;
-}
-
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- int n;
-
- n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
- if (n < 0)
- return -ENOENT;
-
- nb_hw_breakpoint--;
- hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
-
- return 0;
-}
-
-void kvm_arch_remove_all_hw_breakpoints(void)
-{
- nb_hw_breakpoint = 0;
-}
-
-static CPUWatchpoint hw_watchpoint;
-
-int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
-{
- int handle = 0;
- int n;
-
- if (arch_info->exception == 1) {
- if (arch_info->dr6 & (1 << 14)) {
- if (cpu_single_env->singlestep_enabled)
- handle = 1;
- } else {
- for (n = 0; n < 4; n++)
- if (arch_info->dr6 & (1 << n))
- switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
- case 0x0:
- handle = 1;
- break;
- case 0x1:
- handle = 1;
- cpu_single_env->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_WRITE;
- break;
- case 0x3:
- handle = 1;
- cpu_single_env->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_ACCESS;
- break;
- }
- }
- } else if (kvm_find_sw_breakpoint(arch_info->pc))
- handle = 1;
-
- if (!handle)
- kvm_update_guest_debug(cpu_single_env,
- (arch_info->exception == 1) ?
- KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
-
- return handle;
-}
-
-void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
-{
- const uint8_t type_code[] = {
- [GDB_BREAKPOINT_HW] = 0x0,
- [GDB_WATCHPOINT_WRITE] = 0x1,
- [GDB_WATCHPOINT_ACCESS] = 0x3
- };
- const uint8_t len_code[] = {
- [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
- };
- int n;
-
- if (!TAILQ_EMPTY(&kvm_sw_breakpoints))
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
-
- if (nb_hw_breakpoint > 0) {
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
- dbg->arch.debugreg[7] = 0x0600;
- for (n = 0; n < nb_hw_breakpoint; n++) {
- dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
- dbg->arch.debugreg[7] |= (2 << (n * 2)) |
- (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
- (len_code[hw_breakpoint[n].len] << (18 + n*4));
- }
- }
-}
-#endif
-
-void kvm_arch_do_ioperm(void *_data)
-{
- struct ioperm_data *data = _data;
- ioperm(data->start_port, data->num, data->turn_on);
-}
-
-/*
- * Setup x86 specific IRQ routing
- */
-int kvm_arch_init_irq_routing(void)
-{
- int i, r;
-
- if (kvm_irqchip && kvm_has_gsi_routing(kvm_context)) {
- kvm_clear_gsi_routes(kvm_context);
- for (i = 0; i < 8; ++i) {
- if (i == 2)
- continue;
- r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_PIC_MASTER, i);
- if (r < 0)
- return r;
- }
- for (i = 8; i < 16; ++i) {
- r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
- if (r < 0)
- return r;
- }
- for (i = 0; i < 24; ++i) {
- r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, i);
- if (r < 0)
- return r;
- }
- kvm_commit_irq_routes(kvm_context);
- }
- return 0;
-}
-
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
- int reg)
-{
- return kvm_get_supported_cpuid(kvm_context, function, reg);
-}
-
-void kvm_arch_process_irqchip_events(CPUState *env)
-{
- kvm_arch_save_regs(env);
- if (env->interrupt_request & CPU_INTERRUPT_INIT)
- do_cpu_init(env);
- if (env->interrupt_request & CPU_INTERRUPT_SIPI)
- do_cpu_sipi(env);
- kvm_arch_load_regs(env);
-}
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0af2f55..4c3948c 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -14,15 +14,28 @@
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/io.h>
#include <sys/mman.h>
+#include <sys/utsname.h>
+#include <pthread.h>
#include <linux/kvm.h>
+#include <linux/kvm_para.h>
#include "qemu-common.h"
#include "sysemu.h"
#include "kvm.h"
#include "cpu.h"
#include "gdbstub.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+
+
+#include "qemu-kvm.h"
+#include "libkvm-all.h"
+#include "libkvm.h"
+
+#ifdef CONFIG_KVM
//#define DEBUG_KVM
@@ -959,3 +972,1572 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
}
}
#endif /* KVM_CAP_SET_GUEST_DEBUG */
+
+#endif /* CONFIG_KVM */
+#ifdef USE_KVM
+
+#define MSR_IA32_TSC 0x10
+
+static struct kvm_msr_list *kvm_msr_list;
+extern unsigned int kvm_shadow_memory;
+static int kvm_has_msr_star;
+static int kvm_has_vm_hsave_pa;
+
+static int lm_capable_kernel;
+
+int kvm_set_tss_addr(kvm_context_t kvm, unsigned long addr)
+{
+#ifdef KVM_CAP_SET_TSS_ADDR
+ int r;
+
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
+ if (r > 0) {
+ r = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, addr);
+ if (r == -1) {
+ fprintf(stderr, "kvm_set_tss_addr: %m\n");
+ return -errno;
+ }
+ return 0;
+ }
+#endif
+ return -ENOSYS;
+}
+
+static int kvm_init_tss(kvm_context_t kvm)
+{
+#ifdef KVM_CAP_SET_TSS_ADDR
+ int r;
+
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
+ if (r > 0) {
+ /*
+ * this address is 3 pages before the bios, and the bios should present
+ * as unavaible memory
+ */
+ r = kvm_set_tss_addr(kvm, 0xfffbd000);
+ if (r < 0) {
+ fprintf(stderr, "kvm_init_tss: unable to set tss addr\n");
+ return r;
+ }
+
+ }
+#endif
+ return 0;
+}
+
+static int kvm_create_pit(kvm_context_t kvm)
+{
+#ifdef KVM_CAP_PIT
+ int r;
+
+ kvm->pit_in_kernel = 0;
+ if (!kvm->no_pit_creation) {
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_PIT);
+ if (r > 0) {
+ r = ioctl(kvm->vm_fd, KVM_CREATE_PIT);
+ if (r >= 0)
+ kvm->pit_in_kernel = 1;
+ else {
+ fprintf(stderr, "Create kernel PIC irqchip failed\n");
+ return r;
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+int kvm_arch_create(kvm_context_t kvm, unsigned long phys_mem_bytes,
+ void **vm_mem)
+{
+ int r = 0;
+
+ r = kvm_init_tss(kvm);
+ if (r < 0)
+ return r;
+
+ r = kvm_create_pit(kvm);
+ if (r < 0)
+ return r;
+
+ r = kvm_init_coalesced_mmio(kvm);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+#ifdef KVM_EXIT_TPR_ACCESS
+
+static int kvm_handle_tpr_access(kvm_vcpu_context_t vcpu)
+{
+ struct kvm_run *run = vcpu->run;
+ kvm_tpr_access_report(cpu_single_env,
+ run->tpr_access.rip,
+ run->tpr_access.is_write);
+ return 0;
+}
+
+
+int kvm_enable_vapic(kvm_vcpu_context_t vcpu, uint64_t vapic)
+{
+ int r;
+ struct kvm_vapic_addr va = {
+ .vapic_addr = vapic,
+ };
+
+ r = ioctl(vcpu->fd, KVM_SET_VAPIC_ADDR, &va);
+ if (r == -1) {
+ r = -errno;
+ perror("kvm_enable_vapic");
+ return r;
+ }
+ return 0;
+}
+
+#endif
+
+int kvm_arch_run(kvm_vcpu_context_t vcpu)
+{
+ int r = 0;
+ struct kvm_run *run = vcpu->run;
+
+
+ switch (run->exit_reason) {
+#ifdef KVM_EXIT_SET_TPR
+ case KVM_EXIT_SET_TPR:
+ break;
+#endif
+#ifdef KVM_EXIT_TPR_ACCESS
+ case KVM_EXIT_TPR_ACCESS:
+ r = kvm_handle_tpr_access(vcpu);
+ break;
+#endif
+ default:
+ r = 1;
+ break;
+ }
+
+ return r;
+}
+
+#define MAX_ALIAS_SLOTS 4
+static struct {
+ uint64_t start;
+ uint64_t len;
+} kvm_aliases[MAX_ALIAS_SLOTS];
+
+static int get_alias_slot(uint64_t start)
+{
+ int i;
+
+ for (i=0; i<MAX_ALIAS_SLOTS; i++)
+ if (kvm_aliases[i].start == start)
+ return i;
+ return -1;
+}
+static int get_free_alias_slot(void)
+{
+ int i;
+
+ for (i=0; i<MAX_ALIAS_SLOTS; i++)
+ if (kvm_aliases[i].len == 0)
+ return i;
+ return -1;
+}
+
+static void register_alias(int slot, uint64_t start, uint64_t len)
+{
+ kvm_aliases[slot].start = start;
+ kvm_aliases[slot].len = len;
+}
+
+int kvm_create_memory_alias(kvm_context_t kvm,
+ uint64_t phys_start,
+ uint64_t len,
+ uint64_t target_phys)
+{
+ struct kvm_memory_alias alias = {
+ .flags = 0,
+ .guest_phys_addr = phys_start,
+ .memory_size = len,
+ .target_phys_addr = target_phys,
+ };
+ int fd = kvm->vm_fd;
+ int r;
+ int slot;
+
+ slot = get_alias_slot(phys_start);
+ if (slot < 0)
+ slot = get_free_alias_slot();
+ if (slot < 0)
+ return -EBUSY;
+ alias.slot = slot;
+
+ r = ioctl(fd, KVM_SET_MEMORY_ALIAS, &alias);
+ if (r == -1)
+ return -errno;
+
+ register_alias(slot, phys_start, len);
+ return 0;
+}
+
+int kvm_destroy_memory_alias(kvm_context_t kvm, uint64_t phys_start)
+{
+ return kvm_create_memory_alias(kvm, phys_start, 0, 0);
+}
+
+#ifdef KVM_CAP_IRQCHIP
+
+int kvm_get_lapic(kvm_vcpu_context_t vcpu, struct kvm_lapic_state *s)
+{
+ int r;
+ if (!kvm_irqchip_in_kernel(vcpu->kvm))
+ return 0;
+ r = ioctl(vcpu->fd, KVM_GET_LAPIC, s);
+ if (r == -1) {
+ r = -errno;
+ perror("kvm_get_lapic");
+ }
+ return r;
+}
+
+int kvm_set_lapic(kvm_vcpu_context_t vcpu, struct kvm_lapic_state *s)
+{
+ int r;
+ if (!kvm_irqchip_in_kernel(vcpu->kvm))
+ return 0;
+ r = ioctl(vcpu->fd, KVM_SET_LAPIC, s);
+ if (r == -1) {
+ r = -errno;
+ perror("kvm_set_lapic");
+ }
+ return r;
+}
+
+#endif
+
+#ifdef KVM_CAP_PIT
+
+int kvm_get_pit(kvm_context_t kvm, struct kvm_pit_state *s)
+{
+ int r;
+ if (!kvm->pit_in_kernel)
+ return 0;
+ r = ioctl(kvm->vm_fd, KVM_GET_PIT, s);
+ if (r == -1) {
+ r = -errno;
+ perror("kvm_get_pit");
+ }
+ return r;
+}
+
+int kvm_set_pit(kvm_context_t kvm, struct kvm_pit_state *s)
+{
+ int r;
+ if (!kvm->pit_in_kernel)
+ return 0;
+ r = ioctl(kvm->vm_fd, KVM_SET_PIT, s);
+ if (r == -1) {
+ r = -errno;
+ perror("kvm_set_pit");
+ }
+ return r;
+}
+
+#endif
+
+void kvm_show_code(kvm_vcpu_context_t vcpu)
+{
+#define SHOW_CODE_LEN 50
+ int fd = vcpu->fd;
+ struct kvm_regs regs;
+ struct kvm_sregs sregs;
+ int r, n;
+ int back_offset;
+ unsigned char code;
+ char code_str[SHOW_CODE_LEN * 3 + 1];
+ unsigned long rip;
+ kvm_context_t kvm = vcpu->kvm;
+
+ r = ioctl(fd, KVM_GET_SREGS, &sregs);
+ if (r == -1) {
+ perror("KVM_GET_SREGS");
+ return;
+ }
+ r = ioctl(fd, KVM_GET_REGS, ®s);
+ if (r == -1) {
+ perror("KVM_GET_REGS");
+ return;
+ }
+ rip = sregs.cs.base + regs.rip;
+ back_offset = regs.rip;
+ if (back_offset > 20)
+ back_offset = 20;
+ *code_str = 0;
+ for (n = -back_offset; n < SHOW_CODE_LEN-back_offset; ++n) {
+ if (n == 0)
+ strcat(code_str, " -->");
+ r = kvm_mmio_read(kvm->opaque, rip + n, &code, 1);
+ if (r < 0) {
+ strcat(code_str, " xx");
+ continue;
+ }
+ sprintf(code_str + strlen(code_str), " %02x", code);
+ }
+ fprintf(stderr, "code:%s\n", code_str);
+}
+
+
+/*
+ * Returns available msr list. User must free.
+ */
+struct kvm_msr_list *kvm_get_msr_list(kvm_context_t kvm)
+{
+ struct kvm_msr_list sizer, *msrs;
+ int r, e;
+
+ sizer.nmsrs = 0;
+ r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, &sizer);
+ if (r == -1 && errno != E2BIG)
+ return NULL;
+ /* Old kernel modules had a bug and could write beyond the provided
+ memory. Allocate at least a safe amount of 1K. */
+ msrs = malloc(MAX(1024, sizeof(*msrs) +
+ sizer.nmsrs * sizeof(*msrs->indices)));
+ if (!msrs) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ msrs->nmsrs = sizer.nmsrs;
+ r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, msrs);
+ if (r == -1) {
+ e = errno;
+ free(msrs);
+ errno = e;
+ return NULL;
+ }
+ return msrs;
+}
+
+int kvm_get_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
+{
+ struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs);
+ int r, e;
+
+ if (!kmsrs) {
+ errno = ENOMEM;
+ return -1;
+ }
+ kmsrs->nmsrs = n;
+ memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
+ r = ioctl(vcpu->fd, KVM_GET_MSRS, kmsrs);
+ e = errno;
+ memcpy(msrs, kmsrs->entries, n * sizeof *msrs);
+ free(kmsrs);
+ errno = e;
+ return r;
+}
+
+int kvm_set_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
+{
+ struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs);
+ int r, e;
+
+ if (!kmsrs) {
+ errno = ENOMEM;
+ return -1;
+ }
+ kmsrs->nmsrs = n;
+ memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
+ r = ioctl(vcpu->fd, KVM_SET_MSRS, kmsrs);
+ e = errno;
+ free(kmsrs);
+ errno = e;
+ return r;
+}
+
+static void print_seg(FILE *file, const char *name, struct kvm_segment *seg)
+{
+ fprintf(stderr,
+ "%s %04x (%08llx/%08x p %d dpl %d db %d s %d type %x l %d"
+ " g %d avl %d)\n",
+ name, seg->selector, seg->base, seg->limit, seg->present,
+ seg->dpl, seg->db, seg->s, seg->type, seg->l, seg->g,
+ seg->avl);
+}
+
+static void print_dt(FILE *file, const char *name, struct kvm_dtable *dt)
+{
+ fprintf(stderr, "%s %llx/%x\n", name, dt->base, dt->limit);
+}
+
+void kvm_show_regs(kvm_vcpu_context_t vcpu)
+{
+ int fd = vcpu->fd;
+ struct kvm_regs regs;
+ struct kvm_sregs sregs;
+ int r;
+
+ r = ioctl(fd, KVM_GET_REGS, ®s);
+ if (r == -1) {
+ perror("KVM_GET_REGS");
+ return;
+ }
+ fprintf(stderr,
+ "rax %016llx rbx %016llx rcx %016llx rdx %016llx\n"
+ "rsi %016llx rdi %016llx rsp %016llx rbp %016llx\n"
+ "r8 %016llx r9 %016llx r10 %016llx r11 %016llx\n"
+ "r12 %016llx r13 %016llx r14 %016llx r15 %016llx\n"
+ "rip %016llx rflags %08llx\n",
+ regs.rax, regs.rbx, regs.rcx, regs.rdx,
+ regs.rsi, regs.rdi, regs.rsp, regs.rbp,
+ regs.r8, regs.r9, regs.r10, regs.r11,
+ regs.r12, regs.r13, regs.r14, regs.r15,
+ regs.rip, regs.rflags);
+ r = ioctl(fd, KVM_GET_SREGS, &sregs);
+ if (r == -1) {
+ perror("KVM_GET_SREGS");
+ return;
+ }
+ print_seg(stderr, "cs", &sregs.cs);
+ print_seg(stderr, "ds", &sregs.ds);
+ print_seg(stderr, "es", &sregs.es);
+ print_seg(stderr, "ss", &sregs.ss);
+ print_seg(stderr, "fs", &sregs.fs);
+ print_seg(stderr, "gs", &sregs.gs);
+ print_seg(stderr, "tr", &sregs.tr);
+ print_seg(stderr, "ldt", &sregs.ldt);
+ print_dt(stderr, "gdt", &sregs.gdt);
+ print_dt(stderr, "idt", &sregs.idt);
+ fprintf(stderr, "cr0 %llx cr2 %llx cr3 %llx cr4 %llx cr8 %llx"
+ " efer %llx\n",
+ sregs.cr0, sregs.cr2, sregs.cr3, sregs.cr4, sregs.cr8,
+ sregs.efer);
+}
+
+uint64_t kvm_get_apic_base(kvm_vcpu_context_t vcpu)
+{
+ return vcpu->run->apic_base;
+}
+
+void kvm_set_cr8(kvm_vcpu_context_t vcpu, uint64_t cr8)
+{
+ vcpu->run->cr8 = cr8;
+}
+
+__u64 kvm_get_cr8(kvm_vcpu_context_t vcpu)
+{
+ return vcpu->run->cr8;
+}
+
+int kvm_setup_cpuid(kvm_vcpu_context_t vcpu, int nent,
+ struct kvm_cpuid_entry *entries)
+{
+ struct kvm_cpuid *cpuid;
+ int r;
+
+ cpuid = malloc(sizeof(*cpuid) + nent * sizeof(*entries));
+ if (!cpuid)
+ return -ENOMEM;
+
+ cpuid->nent = nent;
+ memcpy(cpuid->entries, entries, nent * sizeof(*entries));
+ r = ioctl(vcpu->fd, KVM_SET_CPUID, cpuid);
+
+ free(cpuid);
+ return r;
+}
+
+int kvm_setup_cpuid2(kvm_vcpu_context_t vcpu, int nent,
+ struct kvm_cpuid_entry2 *entries)
+{
+ struct kvm_cpuid2 *cpuid;
+ int r;
+
+ cpuid = malloc(sizeof(*cpuid) + nent * sizeof(*entries));
+ if (!cpuid)
+ return -ENOMEM;
+
+ cpuid->nent = nent;
+ memcpy(cpuid->entries, entries, nent * sizeof(*entries));
+ r = ioctl(vcpu->fd, KVM_SET_CPUID2, cpuid);
+ if (r == -1) {
+ fprintf(stderr, "kvm_setup_cpuid2: %m\n");
+ return -errno;
+ }
+ free(cpuid);
+ return r;
+}
+
+int kvm_set_shadow_pages(kvm_context_t kvm, unsigned int nrshadow_pages)
+{
+#ifdef KVM_CAP_MMU_SHADOW_CACHE_CONTROL
+ int r;
+
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION,
+ KVM_CAP_MMU_SHADOW_CACHE_CONTROL);
+ if (r > 0) {
+ r = ioctl(kvm->vm_fd, KVM_SET_NR_MMU_PAGES, nrshadow_pages);
+ if (r == -1) {
+ fprintf(stderr, "kvm_set_shadow_pages: %m\n");
+ return -errno;
+ }
+ return 0;
+ }
+#endif
+ return -1;
+}
+
+int kvm_get_shadow_pages(kvm_context_t kvm, unsigned int *nrshadow_pages)
+{
+#ifdef KVM_CAP_MMU_SHADOW_CACHE_CONTROL
+ int r;
+
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION,
+ KVM_CAP_MMU_SHADOW_CACHE_CONTROL);
+ if (r > 0) {
+ *nrshadow_pages = ioctl(kvm->vm_fd, KVM_GET_NR_MMU_PAGES);
+ return 0;
+ }
+#endif
+ return -1;
+}
+
+#ifdef KVM_CAP_VAPIC
+
+static int tpr_access_reporting(kvm_vcpu_context_t vcpu, int enabled)
+{
+ int r;
+ struct kvm_tpr_access_ctl tac = {
+ .enabled = enabled,
+ };
+
+ r = ioctl(vcpu->kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_VAPIC);
+ if (r == -1 || r == 0)
+ return -ENOSYS;
+ r = ioctl(vcpu->fd, KVM_TPR_ACCESS_REPORTING, &tac);
+ if (r == -1) {
+ r = -errno;
+ perror("KVM_TPR_ACCESS_REPORTING");
+ return r;
+ }
+ return 0;
+}
+
+int kvm_enable_tpr_access_reporting(kvm_vcpu_context_t vcpu)
+{
+ return tpr_access_reporting(vcpu, 1);
+}
+
+int kvm_disable_tpr_access_reporting(kvm_vcpu_context_t vcpu)
+{
+ return tpr_access_reporting(vcpu, 0);
+}
+
+#endif
+
+#ifdef KVM_CAP_EXT_CPUID
+
+static struct kvm_cpuid2 *try_get_cpuid(kvm_context_t kvm, int max)
+{
+ struct kvm_cpuid2 *cpuid;
+ int r, size;
+
+ size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
+ cpuid = (struct kvm_cpuid2 *)malloc(size);
+ cpuid->nent = max;
+ r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, cpuid);
+ if (r == -1)
+ r = -errno;
+ else if (r == 0 && cpuid->nent >= max)
+ r = -E2BIG;
+ if (r < 0) {
+ if (r == -E2BIG) {
+ free(cpuid);
+ return NULL;
+ } else {
+ fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
+ strerror(-r));
+ exit(1);
+ }
+ }
+ return cpuid;
+}
+
+#define R_EAX 0
+#define R_ECX 1
+#define R_EDX 2
+#define R_EBX 3
+#define R_ESP 4
+#define R_EBP 5
+#define R_ESI 6
+#define R_EDI 7
+
+uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg)
+{
+ struct kvm_cpuid2 *cpuid;
+ int i, max;
+ uint32_t ret = 0;
+ uint32_t cpuid_1_edx;
+
+ if (!kvm_check_extension(kvm, KVM_CAP_EXT_CPUID)) {
+ return -1U;
+ }
+
+ max = 1;
+ while ((cpuid = try_get_cpuid(kvm, max)) == NULL) {
+ max *= 2;
+ }
+
+ for (i = 0; i < cpuid->nent; ++i) {
+ if (cpuid->entries[i].function == function) {
+ switch (reg) {
+ case R_EAX:
+ ret = cpuid->entries[i].eax;
+ break;
+ case R_EBX:
+ ret = cpuid->entries[i].ebx;
+ break;
+ case R_ECX:
+ ret = cpuid->entries[i].ecx;
+ break;
+ case R_EDX:
+ ret = cpuid->entries[i].edx;
+ if (function == 1) {
+ /* kvm misreports the following features
+ */
+ ret |= 1 << 12; /* MTRR */
+ ret |= 1 << 16; /* PAT */
+ ret |= 1 << 7; /* MCE */
+ ret |= 1 << 14; /* MCA */
+ }
+
+ /* On Intel, kvm returns cpuid according to
+ * the Intel spec, so add missing bits
+ * according to the AMD spec:
+ */
+ if (function == 0x80000001) {
+ cpuid_1_edx = kvm_get_supported_cpuid(kvm, 1, R_EDX);
+ ret |= cpuid_1_edx & 0xdfeff7ff;
+ }
+ break;
+ }
+ }
+ }
+
+ free(cpuid);
+
+ return ret;
+}
+
+#else
+
+uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, int reg)
+{
+ return -1U;
+}
+
+#endif
+int kvm_qemu_create_memory_alias(uint64_t phys_start,
+ uint64_t len,
+ uint64_t target_phys)
+{
+ return kvm_create_memory_alias(kvm_context, phys_start, len, target_phys);
+}
+
+int kvm_qemu_destroy_memory_alias(uint64_t phys_start)
+{
+ return kvm_destroy_memory_alias(kvm_context, phys_start);
+}
+
+int kvm_arch_qemu_create_context(void)
+{
+ int i;
+ struct utsname utsname;
+
+ uname(&utsname);
+ lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
+
+ if (kvm_shadow_memory)
+ kvm_set_shadow_pages(kvm_context, kvm_shadow_memory);
+
+ kvm_msr_list = kvm_get_msr_list(kvm_context);
+ if (!kvm_msr_list)
+ return -1;
+ for (i = 0; i < kvm_msr_list->nmsrs; ++i) {
+ if (kvm_msr_list->indices[i] == MSR_STAR)
+ kvm_has_msr_star = 1;
+ if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA)
+ kvm_has_vm_hsave_pa = 1;
+ }
+
+ return 0;
+}
+
+static void set_msr_entry(struct kvm_msr_entry *entry, uint32_t index,
+ uint64_t data)
+{
+ entry->index = index;
+ entry->data = data;
+}
+
+/* returns 0 on success, non-0 on failure */
+static int get_msr_entry(struct kvm_msr_entry *entry, CPUState *env)
+{
+ switch (entry->index) {
+ case MSR_IA32_SYSENTER_CS:
+ env->sysenter_cs = entry->data;
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ env->sysenter_esp = entry->data;
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ env->sysenter_eip = entry->data;
+ break;
+ case MSR_STAR:
+ env->star = entry->data;
+ break;
+#ifdef TARGET_X86_64
+ case MSR_CSTAR:
+ env->cstar = entry->data;
+ break;
+ case MSR_KERNELGSBASE:
+ env->kernelgsbase = entry->data;
+ break;
+ case MSR_FMASK:
+ env->fmask = entry->data;
+ break;
+ case MSR_LSTAR:
+ env->lstar = entry->data;
+ break;
+#endif
+ case MSR_IA32_TSC:
+ env->tsc = entry->data;
+ break;
+ case MSR_VM_HSAVE_PA:
+ env->vm_hsave = entry->data;
+ break;
+ default:
+ printf("Warning unknown msr index 0x%x\n", entry->index);
+ return 1;
+ }
+ return 0;
+}
+
+#ifdef TARGET_X86_64
+#define MSR_COUNT 9
+#else
+#define MSR_COUNT 5
+#endif
+
+static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
+{
+ lhs->selector = rhs->selector;
+ lhs->base = rhs->base;
+ lhs->limit = rhs->limit;
+ lhs->type = 3;
+ lhs->present = 1;
+ lhs->dpl = 3;
+ lhs->db = 0;
+ lhs->s = 1;
+ lhs->l = 0;
+ lhs->g = 0;
+ lhs->avl = 0;
+ lhs->unusable = 0;
+}
+
+static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
+{
+ unsigned flags = rhs->flags;
+ lhs->selector = rhs->selector;
+ lhs->base = rhs->base;
+ lhs->limit = rhs->limit;
+ lhs->type = (flags >> DESC_TYPE_SHIFT) & 15;
+ lhs->present = (flags & DESC_P_MASK) != 0;
+ lhs->dpl = rhs->selector & 3;
+ lhs->db = (flags >> DESC_B_SHIFT) & 1;
+ lhs->s = (flags & DESC_S_MASK) != 0;
+ lhs->l = (flags >> DESC_L_SHIFT) & 1;
+ lhs->g = (flags & DESC_G_MASK) != 0;
+ lhs->avl = (flags & DESC_AVL_MASK) != 0;
+ lhs->unusable = 0;
+}
+
+static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
+{
+ lhs->selector = rhs->selector;
+ lhs->base = rhs->base;
+ lhs->limit = rhs->limit;
+ lhs->flags =
+ (rhs->type << DESC_TYPE_SHIFT)
+ | (rhs->present * DESC_P_MASK)
+ | (rhs->dpl << DESC_DPL_SHIFT)
+ | (rhs->db << DESC_B_SHIFT)
+ | (rhs->s * DESC_S_MASK)
+ | (rhs->l << DESC_L_SHIFT)
+ | (rhs->g * DESC_G_MASK)
+ | (rhs->avl * DESC_AVL_MASK);
+}
+
+void kvm_arch_load_regs(CPUState *env)
+{
+ struct kvm_regs regs;
+ struct kvm_fpu fpu;
+ struct kvm_sregs sregs;
+ struct kvm_msr_entry msrs[MSR_COUNT];
+ int rc, n, i;
+
+ regs.rax = env->regs[R_EAX];
+ regs.rbx = env->regs[R_EBX];
+ regs.rcx = env->regs[R_ECX];
+ regs.rdx = env->regs[R_EDX];
+ regs.rsi = env->regs[R_ESI];
+ regs.rdi = env->regs[R_EDI];
+ regs.rsp = env->regs[R_ESP];
+ regs.rbp = env->regs[R_EBP];
+#ifdef TARGET_X86_64
+ regs.r8 = env->regs[8];
+ regs.r9 = env->regs[9];
+ regs.r10 = env->regs[10];
+ regs.r11 = env->regs[11];
+ regs.r12 = env->regs[12];
+ regs.r13 = env->regs[13];
+ regs.r14 = env->regs[14];
+ regs.r15 = env->regs[15];
+#endif
+
+ regs.rflags = env->eflags;
+ regs.rip = env->eip;
+
+ kvm_set_regs(env->kvm_cpu_state.vcpu_ctx, ®s);
+
+ memset(&fpu, 0, sizeof fpu);
+ fpu.fsw = env->fpus & ~(7 << 11);
+ fpu.fsw |= (env->fpstt & 7) << 11;
+ fpu.fcw = env->fpuc;
+ for (i = 0; i < 8; ++i)
+ fpu.ftwx |= (!env->fptags[i]) << i;
+ memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
+ memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
+ fpu.mxcsr = env->mxcsr;
+ kvm_set_fpu(env->kvm_cpu_state.vcpu_ctx, &fpu);
+
+ memcpy(sregs.interrupt_bitmap, env->interrupt_bitmap, sizeof(sregs.interrupt_bitmap));
+
+ if ((env->eflags & VM_MASK)) {
+ set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
+ set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
+ set_v8086_seg(&sregs.es, &env->segs[R_ES]);
+ set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
+ set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
+ set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
+ } else {
+ set_seg(&sregs.cs, &env->segs[R_CS]);
+ set_seg(&sregs.ds, &env->segs[R_DS]);
+ set_seg(&sregs.es, &env->segs[R_ES]);
+ set_seg(&sregs.fs, &env->segs[R_FS]);
+ set_seg(&sregs.gs, &env->segs[R_GS]);
+ set_seg(&sregs.ss, &env->segs[R_SS]);
+
+ if (env->cr[0] & CR0_PE_MASK) {
+ /* force ss cpl to cs cpl */
+ sregs.ss.selector = (sregs.ss.selector & ~3) |
+ (sregs.cs.selector & 3);
+ sregs.ss.dpl = sregs.ss.selector & 3;
+ }
+ }
+
+ set_seg(&sregs.tr, &env->tr);
+ set_seg(&sregs.ldt, &env->ldt);
+
+ sregs.idt.limit = env->idt.limit;
+ sregs.idt.base = env->idt.base;
+ sregs.gdt.limit = env->gdt.limit;
+ sregs.gdt.base = env->gdt.base;
+
+ sregs.cr0 = env->cr[0];
+ sregs.cr2 = env->cr[2];
+ sregs.cr3 = env->cr[3];
+ sregs.cr4 = env->cr[4];
+
+ sregs.cr8 = cpu_get_apic_tpr(env);
+ sregs.apic_base = cpu_get_apic_base(env);
+
+ sregs.efer = env->efer;
+
+ kvm_set_sregs(env->kvm_cpu_state.vcpu_ctx, &sregs);
+
+ /* msrs */
+ n = 0;
+ set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
+ set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
+ set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
+ if (kvm_has_msr_star)
+ set_msr_entry(&msrs[n++], MSR_STAR, env->star);
+ if (kvm_has_vm_hsave_pa)
+ set_msr_entry(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
+#ifdef TARGET_X86_64
+ if (lm_capable_kernel) {
+ set_msr_entry(&msrs[n++], MSR_CSTAR, env->cstar);
+ set_msr_entry(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase);
+ set_msr_entry(&msrs[n++], MSR_FMASK, env->fmask);
+ set_msr_entry(&msrs[n++], MSR_LSTAR , env->lstar);
+ }
+#endif
+
+ rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n);
+ if (rc == -1)
+ perror("kvm_set_msrs FAILED");
+}
+
+void kvm_load_tsc(CPUState *env)
+{
+ int rc;
+ struct kvm_msr_entry msr;
+
+ set_msr_entry(&msr, MSR_IA32_TSC, env->tsc);
+
+ rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, &msr, 1);
+ if (rc == -1)
+ perror("kvm_set_tsc FAILED.\n");
+}
+
+void kvm_arch_save_mpstate(CPUState *env)
+{
+#ifdef KVM_CAP_MP_STATE
+ int r;
+ struct kvm_mp_state mp_state;
+
+ r = kvm_get_mpstate(env->kvm_cpu_state.vcpu_ctx, &mp_state);
+ if (r < 0)
+ env->mp_state = -1;
+ else
+ env->mp_state = mp_state.mp_state;
+#endif
+}
+
+void kvm_arch_load_mpstate(CPUState *env)
+{
+#ifdef KVM_CAP_MP_STATE
+ struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
+
+ /*
+ * -1 indicates that the host did not support GET_MP_STATE ioctl,
+ * so don't touch it.
+ */
+ if (env->mp_state != -1)
+ kvm_set_mpstate(env->kvm_cpu_state.vcpu_ctx, &mp_state);
+#endif
+}
+
+void kvm_arch_save_regs(CPUState *env)
+{
+ struct kvm_regs regs;
+ struct kvm_fpu fpu;
+ struct kvm_sregs sregs;
+ struct kvm_msr_entry msrs[MSR_COUNT];
+ uint32_t hflags;
+ uint32_t i, n, rc;
+
+ kvm_get_regs(env->kvm_cpu_state.vcpu_ctx, ®s);
+
+ env->regs[R_EAX] = regs.rax;
+ env->regs[R_EBX] = regs.rbx;
+ env->regs[R_ECX] = regs.rcx;
+ env->regs[R_EDX] = regs.rdx;
+ env->regs[R_ESI] = regs.rsi;
+ env->regs[R_EDI] = regs.rdi;
+ env->regs[R_ESP] = regs.rsp;
+ env->regs[R_EBP] = regs.rbp;
+#ifdef TARGET_X86_64
+ env->regs[8] = regs.r8;
+ env->regs[9] = regs.r9;
+ env->regs[10] = regs.r10;
+ env->regs[11] = regs.r11;
+ env->regs[12] = regs.r12;
+ env->regs[13] = regs.r13;
+ env->regs[14] = regs.r14;
+ env->regs[15] = regs.r15;
+#endif
+
+ env->eflags = regs.rflags;
+ env->eip = regs.rip;
+
+ kvm_get_fpu(env->kvm_cpu_state.vcpu_ctx, &fpu);
+ env->fpstt = (fpu.fsw >> 11) & 7;
+ env->fpus = fpu.fsw;
+ env->fpuc = fpu.fcw;
+ for (i = 0; i < 8; ++i)
+ env->fptags[i] = !((fpu.ftwx >> i) & 1);
+ memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
+ memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs);
+ env->mxcsr = fpu.mxcsr;
+
+ kvm_get_sregs(env->kvm_cpu_state.vcpu_ctx, &sregs);
+
+ memcpy(env->interrupt_bitmap, sregs.interrupt_bitmap, sizeof(env->interrupt_bitmap));
+
+ get_seg(&env->segs[R_CS], &sregs.cs);
+ get_seg(&env->segs[R_DS], &sregs.ds);
+ get_seg(&env->segs[R_ES], &sregs.es);
+ get_seg(&env->segs[R_FS], &sregs.fs);
+ get_seg(&env->segs[R_GS], &sregs.gs);
+ get_seg(&env->segs[R_SS], &sregs.ss);
+
+ get_seg(&env->tr, &sregs.tr);
+ get_seg(&env->ldt, &sregs.ldt);
+
+ env->idt.limit = sregs.idt.limit;
+ env->idt.base = sregs.idt.base;
+ env->gdt.limit = sregs.gdt.limit;
+ env->gdt.base = sregs.gdt.base;
+
+ env->cr[0] = sregs.cr0;
+ env->cr[2] = sregs.cr2;
+ env->cr[3] = sregs.cr3;
+ env->cr[4] = sregs.cr4;
+
+ cpu_set_apic_base(env, sregs.apic_base);
+
+ env->efer = sregs.efer;
+ //cpu_set_apic_tpr(env, sregs.cr8);
+
+#define HFLAG_COPY_MASK ~( \
+ HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
+ HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
+ HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
+ HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
+
+
+
+ hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
+ hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
+ hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
+ (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
+ hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
+ hflags |= (env->cr[4] & CR4_OSFXSR_MASK) <<
+ (HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT);
+
+ if (env->efer & MSR_EFER_LMA) {
+ hflags |= HF_LMA_MASK;
+ }
+
+ if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
+ hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
+ } else {
+ hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
+ (DESC_B_SHIFT - HF_CS32_SHIFT);
+ hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
+ (DESC_B_SHIFT - HF_SS32_SHIFT);
+ if (!(env->cr[0] & CR0_PE_MASK) ||
+ (env->eflags & VM_MASK) ||
+ !(hflags & HF_CS32_MASK)) {
+ hflags |= HF_ADDSEG_MASK;
+ } else {
+ hflags |= ((env->segs[R_DS].base |
+ env->segs[R_ES].base |
+ env->segs[R_SS].base) != 0) <<
+ HF_ADDSEG_SHIFT;
+ }
+ }
+ env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags;
+
+ /* msrs */
+ n = 0;
+ msrs[n++].index = MSR_IA32_SYSENTER_CS;
+ msrs[n++].index = MSR_IA32_SYSENTER_ESP;
+ msrs[n++].index = MSR_IA32_SYSENTER_EIP;
+ if (kvm_has_msr_star)
+ msrs[n++].index = MSR_STAR;
+ msrs[n++].index = MSR_IA32_TSC;
+ if (kvm_has_vm_hsave_pa)
+ msrs[n++].index = MSR_VM_HSAVE_PA;
+#ifdef TARGET_X86_64
+ if (lm_capable_kernel) {
+ msrs[n++].index = MSR_CSTAR;
+ msrs[n++].index = MSR_KERNELGSBASE;
+ msrs[n++].index = MSR_FMASK;
+ msrs[n++].index = MSR_LSTAR;
+ }
+#endif
+ rc = kvm_get_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n);
+ if (rc == -1) {
+ perror("kvm_get_msrs FAILED");
+ }
+ else {
+ n = rc; /* actual number of MSRs */
+ for (i=0 ; i<n; i++) {
+ if (get_msr_entry(&msrs[i], env))
+ return;
+ }
+ }
+}
+
+static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function,
+ uint32_t count, CPUState *env)
+{
+ env->regs[R_EAX] = function;
+ env->regs[R_ECX] = count;
+ qemu_kvm_cpuid_on_env(env);
+ e->function = function;
+ e->flags = 0;
+ e->index = 0;
+ e->eax = env->regs[R_EAX];
+ e->ebx = env->regs[R_EBX];
+ e->ecx = env->regs[R_ECX];
+ e->edx = env->regs[R_EDX];
+}
+
+struct kvm_para_features {
+ int cap;
+ int feature;
+} para_features[] = {
+#ifdef KVM_CAP_CLOCKSOURCE
+ { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
+#endif
+#ifdef KVM_CAP_NOP_IO_DELAY
+ { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
+#endif
+#ifdef KVM_CAP_PV_MMU
+ { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
+#endif
+#ifdef KVM_CAP_CR3_CACHE
+ { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE },
+#endif
+ { -1, -1 }
+};
+
+static int get_para_features(kvm_context_t kvm_context)
+{
+ int i, features = 0;
+
+ for (i = 0; i < ARRAY_SIZE(para_features)-1; i++) {
+ if (kvm_check_extension(kvm_context, para_features[i].cap))
+ features |= (1 << para_features[i].feature);
+ }
+
+ return features;
+}
+
+static void kvm_trim_features(uint32_t *features, uint32_t supported)
+{
+ int i;
+ uint32_t mask;
+
+ for (i = 0; i < 32; ++i) {
+ mask = 1U << i;
+ if ((*features & mask) && !(supported & mask)) {
+ *features &= ~mask;
+ }
+ }
+}
+
+int kvm_arch_qemu_init_env(CPUState *cenv)
+{
+ struct kvm_cpuid_entry2 cpuid_ent[100];
+#ifdef KVM_CPUID_SIGNATURE
+ struct kvm_cpuid_entry2 *pv_ent;
+ uint32_t signature[3];
+#endif
+ int cpuid_nent = 0;
+ CPUState copy;
+ uint32_t i, j, limit;
+
+ qemu_kvm_load_lapic(cenv);
+
+
+#ifdef KVM_CPUID_SIGNATURE
+ /* Paravirtualization CPUIDs */
+ memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+ pv_ent = &cpuid_ent[cpuid_nent++];
+ memset(pv_ent, 0, sizeof(*pv_ent));
+ pv_ent->function = KVM_CPUID_SIGNATURE;
+ pv_ent->eax = 0;
+ pv_ent->ebx = signature[0];
+ pv_ent->ecx = signature[1];
+ pv_ent->edx = signature[2];
+
+ pv_ent = &cpuid_ent[cpuid_nent++];
+ memset(pv_ent, 0, sizeof(*pv_ent));
+ pv_ent->function = KVM_CPUID_FEATURES;
+ pv_ent->eax = get_para_features(kvm_context);
+#endif
+
+ kvm_trim_features(&cenv->cpuid_features,
+ kvm_arch_get_supported_cpuid(cenv, 1, R_EDX));
+
+ /* prevent the hypervisor bit from being cleared by the kernel */
+ i = cenv->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
+ kvm_trim_features(&cenv->cpuid_ext_features,
+ kvm_arch_get_supported_cpuid(cenv, 1, R_ECX));
+ cenv->cpuid_ext_features |= i;
+
+ kvm_trim_features(&cenv->cpuid_ext2_features,
+ kvm_arch_get_supported_cpuid(cenv, 0x80000001, R_EDX));
+ kvm_trim_features(&cenv->cpuid_ext3_features,
+ kvm_arch_get_supported_cpuid(cenv, 0x80000001, R_ECX));
+
+ copy = *cenv;
+
+ copy.regs[R_EAX] = 0;
+ qemu_kvm_cpuid_on_env(©);
+ limit = copy.regs[R_EAX];
+
+ for (i = 0; i <= limit; ++i) {
+ if (i == 4 || i == 0xb || i == 0xd) {
+ for (j = 0; ; ++j) {
+ do_cpuid_ent(&cpuid_ent[cpuid_nent], i, j, ©);
+
+ cpuid_ent[cpuid_nent].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ cpuid_ent[cpuid_nent].index = j;
+
+ cpuid_nent++;
+
+ if (i == 4 && copy.regs[R_EAX] == 0)
+ break;
+ if (i == 0xb && !(copy.regs[R_ECX] & 0xff00))
+ break;
+ if (i == 0xd && copy.regs[R_EAX] == 0)
+ break;
+ }
+ } else
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
+ }
+
+ copy.regs[R_EAX] = 0x80000000;
+ qemu_kvm_cpuid_on_env(©);
+ limit = copy.regs[R_EAX];
+
+ for (i = 0x80000000; i <= limit; ++i)
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
+
+ kvm_setup_cpuid2(cenv->kvm_cpu_state.vcpu_ctx, cpuid_nent, cpuid_ent);
+
+ return 0;
+}
+
+int kvm_arch_halt(void *opaque, kvm_vcpu_context_t vcpu)
+{
+ CPUState *env = cpu_single_env;
+
+ if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->eflags & IF_MASK)) &&
+ !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
+ env->halted = 1;
+ }
+ return 1;
+}
+
+void kvm_arch_pre_kvm_run(void *opaque, CPUState *env)
+{
+ if (!kvm_irqchip_in_kernel(kvm_context))
+ kvm_set_cr8(env->kvm_cpu_state.vcpu_ctx, cpu_get_apic_tpr(env));
+}
+
+void kvm_arch_post_kvm_run(void *opaque, CPUState *env)
+{
+ cpu_single_env = env;
+
+ env->eflags = kvm_get_interrupt_flag(env->kvm_cpu_state.vcpu_ctx)
+ ? env->eflags | IF_MASK : env->eflags & ~IF_MASK;
+
+ cpu_set_apic_tpr(env, kvm_get_cr8(env->kvm_cpu_state.vcpu_ctx));
+ cpu_set_apic_base(env, kvm_get_apic_base(env->kvm_cpu_state.vcpu_ctx));
+}
+
+int kvm_arch_has_work(CPUState *env)
+{
+ if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->eflags & IF_MASK)) ||
+ (env->interrupt_request & CPU_INTERRUPT_NMI))
+ return 1;
+ return 0;
+}
+
+int kvm_arch_try_push_interrupts(void *opaque)
+{
+ CPUState *env = cpu_single_env;
+ int r, irq;
+
+ if (kvm_is_ready_for_interrupt_injection(env->kvm_cpu_state.vcpu_ctx) &&
+ (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->eflags & IF_MASK)) {
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ irq = cpu_get_pic_interrupt(env);
+ if (irq >= 0) {
+ r = kvm_inject_irq(env->kvm_cpu_state.vcpu_ctx, irq);
+ if (r < 0)
+ printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+ }
+ }
+
+ return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
+}
+
+#ifdef KVM_CAP_USER_NMI
+void kvm_arch_push_nmi(void *opaque)
+{
+ CPUState *env = cpu_single_env;
+ int r;
+
+ if (likely(!(env->interrupt_request & CPU_INTERRUPT_NMI)))
+ return;
+
+ env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+ r = kvm_inject_nmi(env->kvm_cpu_state.vcpu_ctx);
+ if (r < 0)
+ printf("cpu %d fail inject NMI\n", env->cpu_index);
+}
+#endif /* KVM_CAP_USER_NMI */
+
+void kvm_arch_update_regs_for_sipi(CPUState *env)
+{
+ SegmentCache cs = env->segs[R_CS];
+
+ kvm_arch_save_regs(env);
+ env->segs[R_CS] = cs;
+ env->eip = 0;
+ kvm_arch_load_regs(env);
+}
+
+void kvm_arch_cpu_reset(CPUState *env)
+{
+ kvm_arch_load_regs(env);
+ if (!cpu_is_bsp(env)) {
+ if (kvm_irqchip_in_kernel(kvm_context)) {
+#ifdef KVM_CAP_MP_STATE
+ kvm_reset_mpstate(env->kvm_cpu_state.vcpu_ctx);
+#endif
+ } else {
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ env->halted = 1;
+ }
+ }
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+ uint8_t int3 = 0xcc;
+
+ if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
+ cpu_memory_rw_debug(env, bp->pc, &int3, 1, 1))
+ return -EINVAL;
+ return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+ uint8_t int3;
+
+ if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
+ cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
+ return -EINVAL;
+ return 0;
+}
+
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+static struct {
+ target_ulong addr;
+ int len;
+ int type;
+} hw_breakpoint[4];
+
+static int nb_hw_breakpoint;
+
+static int find_hw_breakpoint(target_ulong addr, int len, int type)
+{
+ int n;
+
+ for (n = 0; n < nb_hw_breakpoint; n++)
+ if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
+ (hw_breakpoint[n].len == len || len == -1))
+ return n;
+ return -1;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ switch (type) {
+ case GDB_BREAKPOINT_HW:
+ len = 1;
+ break;
+ case GDB_WATCHPOINT_WRITE:
+ case GDB_WATCHPOINT_ACCESS:
+ switch (len) {
+ case 1:
+ break;
+ case 2:
+ case 4:
+ case 8:
+ if (addr & (len - 1))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ if (nb_hw_breakpoint == 4)
+ return -ENOBUFS;
+
+ if (find_hw_breakpoint(addr, len, type) >= 0)
+ return -EEXIST;
+
+ hw_breakpoint[nb_hw_breakpoint].addr = addr;
+ hw_breakpoint[nb_hw_breakpoint].len = len;
+ hw_breakpoint[nb_hw_breakpoint].type = type;
+ nb_hw_breakpoint++;
+
+ return 0;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ int n;
+
+ n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
+ if (n < 0)
+ return -ENOENT;
+
+ nb_hw_breakpoint--;
+ hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
+
+ return 0;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+ nb_hw_breakpoint = 0;
+}
+
+static CPUWatchpoint hw_watchpoint;
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+{
+ int handle = 0;
+ int n;
+
+ if (arch_info->exception == 1) {
+ if (arch_info->dr6 & (1 << 14)) {
+ if (cpu_single_env->singlestep_enabled)
+ handle = 1;
+ } else {
+ for (n = 0; n < 4; n++)
+ if (arch_info->dr6 & (1 << n))
+ switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
+ case 0x0:
+ handle = 1;
+ break;
+ case 0x1:
+ handle = 1;
+ cpu_single_env->watchpoint_hit = &hw_watchpoint;
+ hw_watchpoint.vaddr = hw_breakpoint[n].addr;
+ hw_watchpoint.flags = BP_MEM_WRITE;
+ break;
+ case 0x3:
+ handle = 1;
+ cpu_single_env->watchpoint_hit = &hw_watchpoint;
+ hw_watchpoint.vaddr = hw_breakpoint[n].addr;
+ hw_watchpoint.flags = BP_MEM_ACCESS;
+ break;
+ }
+ }
+ } else if (kvm_find_sw_breakpoint(arch_info->pc))
+ handle = 1;
+
+ if (!handle)
+ kvm_update_guest_debug(cpu_single_env,
+ (arch_info->exception == 1) ?
+ KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
+
+ return handle;
+}
+
+void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
+{
+ const uint8_t type_code[] = {
+ [GDB_BREAKPOINT_HW] = 0x0,
+ [GDB_WATCHPOINT_WRITE] = 0x1,
+ [GDB_WATCHPOINT_ACCESS] = 0x3
+ };
+ const uint8_t len_code[] = {
+ [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
+ };
+ int n;
+
+ if (!TAILQ_EMPTY(&kvm_sw_breakpoints))
+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
+
+ if (nb_hw_breakpoint > 0) {
+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
+ dbg->arch.debugreg[7] = 0x0600;
+ for (n = 0; n < nb_hw_breakpoint; n++) {
+ dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
+ dbg->arch.debugreg[7] |= (2 << (n * 2)) |
+ (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
+ (len_code[hw_breakpoint[n].len] << (18 + n*4));
+ }
+ }
+}
+#endif
+
+void kvm_arch_do_ioperm(void *_data)
+{
+ struct ioperm_data *data = _data;
+ ioperm(data->start_port, data->num, data->turn_on);
+}
+
+/*
+ * Setup x86 specific IRQ routing
+ */
+int kvm_arch_init_irq_routing(void)
+{
+ int i, r;
+
+ if (kvm_irqchip && kvm_has_gsi_routing(kvm_context)) {
+ kvm_clear_gsi_routes(kvm_context);
+ for (i = 0; i < 8; ++i) {
+ if (i == 2)
+ continue;
+ r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_PIC_MASTER, i);
+ if (r < 0)
+ return r;
+ }
+ for (i = 8; i < 16; ++i) {
+ r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
+ if (r < 0)
+ return r;
+ }
+ for (i = 0; i < 24; ++i) {
+ r = kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, i);
+ if (r < 0)
+ return r;
+ }
+ kvm_commit_irq_routes(kvm_context);
+ }
+ return 0;
+}
+
+uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
+ int reg)
+{
+ return kvm_get_supported_cpuid(kvm_context, function, reg);
+}
+
+void kvm_arch_process_irqchip_events(CPUState *env)
+{
+ kvm_arch_save_regs(env);
+ if (env->interrupt_request & CPU_INTERRUPT_INIT)
+ do_cpu_init(env);
+ if (env->interrupt_request & CPU_INTERRUPT_SIPI)
+ do_cpu_sipi(env);
+ kvm_arch_load_regs(env);
+}
+
+#endif /* USE_KVM */
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 4/8] replace malloc with qemu_malloc
2009-07-08 13:08 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Glauber Costa
@ 2009-07-08 13:08 ` Glauber Costa
2009-07-08 13:08 ` [PATCH 5/8] move kvm_context inside KVMState Glauber Costa
2009-07-08 13:23 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Avi Kivity
2009-07-08 13:28 ` Gleb Natapov
2 siblings, 1 reply; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:08 UTC (permalink / raw)
To: kvm; +Cc: avi
This patch replaces both malloc and malloc+memset sequences
with qemu_malloc and qemu_mallocz. Target is upstream integration
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
kvm-all.c | 26 +++++---------------------
target-i386/kvm.c | 31 ++++++++-----------------------
2 files changed, 13 insertions(+), 44 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index fd68f4c..034ae52 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1469,10 +1469,7 @@ kvm_context_t kvm_init(void *opaque)
}
kvm_abi = r;
kvm_page_size = getpagesize();
- kvm = malloc(sizeof(*kvm));
- if (kvm == NULL)
- goto out_close;
- memset(kvm, 0, sizeof(*kvm));
+ kvm = qemu_mallocz(sizeof(*kvm));
kvm->fd = fd;
kvm->vm_fd = -1;
kvm->opaque = opaque;
@@ -1486,10 +1483,7 @@ kvm_context_t kvm_init(void *opaque)
/* Round up so we can search ints using ffs */
gsi_bits = ALIGN(gsi_count, 32);
- kvm->used_gsi_bitmap = malloc(gsi_bits / 8);
- if (!kvm->used_gsi_bitmap)
- goto out_close;
- memset(kvm->used_gsi_bitmap, 0, gsi_bits / 8);
+ kvm->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8);
kvm->max_gsi = gsi_bits;
/* Mark any over-allocated bits as already in use */
@@ -1529,12 +1523,7 @@ kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, int id)
{
long mmap_size;
int r;
- kvm_vcpu_context_t vcpu_ctx = malloc(sizeof(struct kvm_vcpu_context));
-
- if (!vcpu_ctx) {
- errno = ENOMEM;
- return NULL;
- }
+ kvm_vcpu_context_t vcpu_ctx = qemu_malloc(sizeof(struct kvm_vcpu_context));
vcpu_ctx->kvm = kvm;
vcpu_ctx->id = id;
@@ -1581,10 +1570,7 @@ int kvm_create_vm(kvm_context_t kvm)
int fd = kvm->fd;
#ifdef KVM_CAP_IRQ_ROUTING
- kvm->irq_routes = malloc(sizeof(*kvm->irq_routes));
- if (!kvm->irq_routes)
- return -ENOMEM;
- memset(kvm->irq_routes, 0, sizeof(*kvm->irq_routes));
+ kvm->irq_routes = qemu_mallocz(sizeof(*kvm->irq_routes));
kvm->nr_allocated_irq_routes = 0;
#endif
@@ -2189,9 +2175,7 @@ int kvm_set_signal_mask(kvm_vcpu_context_t vcpu, const sigset_t *sigset)
r = -errno;
return r;
}
- sigmask = malloc(sizeof(*sigmask) + sizeof(*sigset));
- if (!sigmask)
- return -ENOMEM;
+ sigmask = qemu_malloc(sizeof(*sigmask) + sizeof(*sigset));
sigmask->len = 8;
memcpy(sigmask->sigset, sigset, sizeof(*sigset));
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 4c3948c..ab324f6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1303,12 +1303,9 @@ struct kvm_msr_list *kvm_get_msr_list(kvm_context_t kvm)
return NULL;
/* Old kernel modules had a bug and could write beyond the provided
memory. Allocate at least a safe amount of 1K. */
- msrs = malloc(MAX(1024, sizeof(*msrs) +
- sizer.nmsrs * sizeof(*msrs->indices)));
- if (!msrs) {
- errno = ENOMEM;
- return NULL;
- }
+ msrs = qemu_malloc(MAX(1024, sizeof(*msrs) +
+ sizer.nmsrs * sizeof(*msrs->indices)));
+
msrs->nmsrs = sizer.nmsrs;
r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, msrs);
if (r == -1) {
@@ -1322,13 +1319,9 @@ struct kvm_msr_list *kvm_get_msr_list(kvm_context_t kvm)
int kvm_get_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
{
- struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs);
+ struct kvm_msrs *kmsrs = qemu_malloc(sizeof *kmsrs + n * sizeof *msrs);
int r, e;
- if (!kmsrs) {
- errno = ENOMEM;
- return -1;
- }
kmsrs->nmsrs = n;
memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
r = ioctl(vcpu->fd, KVM_GET_MSRS, kmsrs);
@@ -1341,13 +1334,9 @@ int kvm_get_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
int kvm_set_msrs(kvm_vcpu_context_t vcpu, struct kvm_msr_entry *msrs, int n)
{
- struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs);
+ struct kvm_msrs *kmsrs = qemu_malloc(sizeof *kmsrs + n * sizeof *msrs);
int r, e;
- if (!kmsrs) {
- errno = ENOMEM;
- return -1;
- }
kmsrs->nmsrs = n;
memcpy(kmsrs->entries, msrs, n * sizeof *msrs);
r = ioctl(vcpu->fd, KVM_SET_MSRS, kmsrs);
@@ -1437,9 +1426,7 @@ int kvm_setup_cpuid(kvm_vcpu_context_t vcpu, int nent,
struct kvm_cpuid *cpuid;
int r;
- cpuid = malloc(sizeof(*cpuid) + nent * sizeof(*entries));
- if (!cpuid)
- return -ENOMEM;
+ cpuid = qemu_malloc(sizeof(*cpuid) + nent * sizeof(*entries));
cpuid->nent = nent;
memcpy(cpuid->entries, entries, nent * sizeof(*entries));
@@ -1455,9 +1442,7 @@ int kvm_setup_cpuid2(kvm_vcpu_context_t vcpu, int nent,
struct kvm_cpuid2 *cpuid;
int r;
- cpuid = malloc(sizeof(*cpuid) + nent * sizeof(*entries));
- if (!cpuid)
- return -ENOMEM;
+ cpuid = qemu_malloc(sizeof(*cpuid) + nent * sizeof(*entries));
cpuid->nent = nent;
memcpy(cpuid->entries, entries, nent * sizeof(*entries));
@@ -1545,7 +1530,7 @@ static struct kvm_cpuid2 *try_get_cpuid(kvm_context_t kvm, int max)
int r, size;
size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
- cpuid = (struct kvm_cpuid2 *)malloc(size);
+ cpuid = qemu_malloc(size);
cpuid->nent = max;
r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, cpuid);
if (r == -1)
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 5/8] move kvm_context inside KVMState
2009-07-08 13:08 ` [PATCH 4/8] replace malloc with qemu_malloc Glauber Costa
@ 2009-07-08 13:08 ` Glauber Costa
2009-07-08 13:09 ` [PATCH 6/8] provide env->kvm_fd Glauber Costa
0 siblings, 1 reply; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:08 UTC (permalink / raw)
To: kvm; +Cc: avi
To make transition smooth, we still keep a global variable kvm_context
pointing to its position inside the global KVMState. This way we don't
need to hurry about changing all callers.
kvm_init() and kvm_finalize are changed, though, since they have now to
deal with the creation/destruction of a global KVMState
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
kvm-all.c | 98 +++++++++++++++++++++++++--------------------------------
kvm.h | 3 +-
libkvm-all.h | 3 +-
3 files changed, 47 insertions(+), 57 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 034ae52..15bd429 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -35,23 +35,6 @@
#include "libkvm-all.h"
#include "libkvm.h"
-
-#ifdef CONFIG_KVM
-
-
-/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
-#define PAGE_SIZE TARGET_PAGE_SIZE
-
-//#define DEBUG_KVM
-
-#ifdef DEBUG_KVM
-#define dprintf(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define dprintf(fmt, ...) \
- do { } while (0)
-#endif
-
typedef struct KVMSlot
{
target_phys_addr_t start_addr;
@@ -63,8 +46,6 @@ typedef struct KVMSlot
typedef struct kvm_dirty_log KVMDirtyLog;
-int kvm_allowed = 0;
-
struct KVMState
{
KVMSlot slots[32];
@@ -76,9 +57,28 @@ struct KVMState
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
+ struct kvm_context kvm_context;
};
static KVMState *kvm_state;
+kvm_context_t kvm_context;
+
+#ifdef CONFIG_KVM
+
+/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
+#define PAGE_SIZE TARGET_PAGE_SIZE
+
+//#define DEBUG_KVM
+
+#ifdef DEBUG_KVM
+#define dprintf(fmt, ...) \
+ do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+ do { } while (0)
+#endif
+
+int kvm_allowed = 0;
static KVMSlot *kvm_alloc_slot(KVMState *s)
{
@@ -1065,7 +1065,6 @@ int kvm_irqchip = 1;
int kvm_pit = 1;
int kvm_pit_reinject = 1;
int kvm_nested = 0;
-kvm_context_t kvm_context;
pthread_mutex_t qemu_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t qemu_vcpu_cond = PTHREAD_COND_INITIALIZER;
@@ -1439,16 +1438,15 @@ int kvm_dirty_pages_log_reset(kvm_context_t kvm)
}
-kvm_context_t kvm_init(void *opaque)
+int kvm_qemu_init()
{
int fd;
- kvm_context_t kvm;
int r, gsi_count;
fd = open("/dev/kvm", O_RDWR);
if (fd == -1) {
perror("open /dev/kvm");
- return NULL;
+ return -1;
}
r = ioctl(fd, KVM_GET_API_VERSION, 0);
if (r == -1) {
@@ -1469,35 +1467,37 @@ kvm_context_t kvm_init(void *opaque)
}
kvm_abi = r;
kvm_page_size = getpagesize();
- kvm = qemu_mallocz(sizeof(*kvm));
- kvm->fd = fd;
- kvm->vm_fd = -1;
- kvm->opaque = opaque;
- kvm->dirty_pages_log_all = 0;
- kvm->no_irqchip_creation = 0;
- kvm->no_pit_creation = 0;
-
- gsi_count = kvm_get_gsi_count(kvm);
+ kvm_state = qemu_mallocz(sizeof(*kvm_state));
+ kvm_context = &kvm_state->kvm_context;
+ kvm_context->fd = fd;
+ kvm_context->vm_fd = -1;
+ kvm_context->opaque = cpu_single_env;
+ kvm_context->dirty_pages_log_all = 0;
+ kvm_context->no_irqchip_creation = 0;
+ kvm_context->no_pit_creation = 0;
+
+ gsi_count = kvm_get_gsi_count(kvm_context);
if (gsi_count > 0) {
int gsi_bits, i;
/* Round up so we can search ints using ffs */
gsi_bits = ALIGN(gsi_count, 32);
- kvm->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8);
- kvm->max_gsi = gsi_bits;
+ kvm_context->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8);
+ kvm_context->max_gsi = gsi_bits;
/* Mark any over-allocated bits as already in use */
for (i = gsi_count; i < gsi_bits; i++)
- set_gsi(kvm, i);
+ set_gsi(kvm_context, i);
}
- return kvm;
- out_close:
+ pthread_mutex_lock(&qemu_mutex);
+ return 0;
+out_close:
close(fd);
- return NULL;
+ return -1;
}
-void kvm_finalize(kvm_context_t kvm)
+void kvm_finalize(KVMState *kvm_state)
{
/* FIXME
if (kvm->vcpu_fd[0] != -1)
@@ -1505,8 +1505,8 @@ void kvm_finalize(kvm_context_t kvm)
if (kvm->vm_fd != -1)
close(kvm->vm_fd);
*/
- close(kvm->fd);
- free(kvm);
+ close(kvm_state->kvm_context.fd);
+ free(kvm_state);
}
void kvm_disable_irqchip_creation(kvm_context_t kvm)
@@ -3220,18 +3220,6 @@ int kvm_main_loop(void)
return 0;
}
-int kvm_qemu_init()
-{
- /* Try to initialize kvm */
- kvm_context = kvm_init(cpu_single_env);
- if (!kvm_context) {
- return -1;
- }
- pthread_mutex_lock(&qemu_mutex);
-
- return 0;
-}
-
#ifdef TARGET_I386
static int destroy_region_works = 0;
#endif
@@ -3255,12 +3243,12 @@ int kvm_qemu_create_context(void)
kvm_disable_pit_creation(kvm_context);
}
if (kvm_create(kvm_context, 0, NULL) < 0) {
- kvm_finalize(kvm_context);
+ kvm_finalize(kvm_state);
return -1;
}
r = kvm_arch_qemu_create_context();
if(r <0)
- kvm_finalize(kvm_context);
+ kvm_finalize(kvm_state);
if (kvm_pit && !kvm_pit_reinject) {
if (kvm_reinject_control(kvm_context, 0)) {
fprintf(stderr, "failure to disable in-kernel PIT reinjection\n");
diff --git a/kvm.h b/kvm.h
index 7648c49..31ebce2 100644
--- a/kvm.h
+++ b/kvm.h
@@ -16,11 +16,12 @@
#include "config.h"
#include "sys-queue.h"
-#include "libkvm-all.h"
struct KVMState;
typedef struct KVMState KVMState;
+#include "libkvm-all.h"
+
#ifdef KVM_UPSTREAM
#ifdef CONFIG_KVM
diff --git a/libkvm-all.h b/libkvm-all.h
index e16646c..7857532 100644
--- a/libkvm-all.h
+++ b/libkvm-all.h
@@ -21,6 +21,7 @@
#include <signal.h>
+
/* FIXME: share this number with kvm */
/* FIXME: or dynamically alloc/realloc regions */
#ifdef __s390__
@@ -189,7 +190,7 @@ kvm_context_t kvm_init(void *opaque);
*
* \param kvm Pointer to the kvm_context that is to be freed
*/
-void kvm_finalize(kvm_context_t kvm);
+void kvm_finalize(KVMState *s);
/*!
* \brief Disable the in-kernel IRQCHIP creation
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 6/8] provide env->kvm_fd
2009-07-08 13:08 ` [PATCH 5/8] move kvm_context inside KVMState Glauber Costa
@ 2009-07-08 13:09 ` Glauber Costa
2009-07-08 13:09 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Glauber Costa
2009-07-08 13:32 ` [PATCH 6/8] provide env->kvm_fd Gleb Natapov
0 siblings, 2 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:09 UTC (permalink / raw)
To: kvm; +Cc: avi
qemu upstream puts kvm information on env. Do that too, since it will
allow us to use CPUState in cpu-specific functions, instead of kvm-specific
types.
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
kvm-all.c | 12 ++++++++----
libkvm-all.h | 12 ------------
2 files changed, 8 insertions(+), 16 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 15bd429..b404f76 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1519,21 +1519,25 @@ void kvm_disable_pit_creation(kvm_context_t kvm)
kvm->no_pit_creation = 1;
}
-kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, int id)
+static kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, CPUState *env)
{
long mmap_size;
int r;
kvm_vcpu_context_t vcpu_ctx = qemu_malloc(sizeof(struct kvm_vcpu_context));
vcpu_ctx->kvm = kvm;
- vcpu_ctx->id = id;
+ vcpu_ctx->id = env->cpu_index;
- r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, id);
+ r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, env->cpu_index);
if (r == -1) {
fprintf(stderr, "kvm_create_vcpu: %m\n");
goto err;
}
vcpu_ctx->fd = r;
+
+ env->kvm_fd = r;
+ env->kvm_state = kvm_state;
+
mmap_size = ioctl(kvm->fd, KVM_GET_VCPU_MMAP_SIZE, 0);
if (mmap_size == -1) {
fprintf(stderr, "get vcpu mmap size: %m\n");
@@ -3029,7 +3033,7 @@ static void *ap_main_loop(void *_env)
env->thread_id = kvm_get_thread_id();
sigfillset(&signals);
sigprocmask(SIG_BLOCK, &signals, NULL);
- env->kvm_cpu_state.vcpu_ctx = kvm_create_vcpu(kvm_context, env->cpu_index);
+ env->kvm_cpu_state.vcpu_ctx = kvm_create_vcpu(kvm_context, env);
#ifdef USE_KVM_DEVICE_ASSIGNMENT
/* do ioperm for io ports of assigned devices */
diff --git a/libkvm-all.h b/libkvm-all.h
index 7857532..9c018eb 100644
--- a/libkvm-all.h
+++ b/libkvm-all.h
@@ -234,18 +234,6 @@ int kvm_check_extension(kvm_context_t kvm, int ext);
void kvm_create_irqchip(kvm_context_t kvm);
/*!
- * \brief Create a new virtual cpu
- *
- * This creates a new virtual cpu (the first vcpu is created by kvm_create()).
- * Should be called from a thread dedicated to the vcpu.
- *
- * \param kvm kvm context
- * \param slot vcpu number (> 0)
- * \return 0 on success, -errno on failure
- */
-kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, int id);
-
-/*!
* \brief Start the VCPU
*
* This starts the VCPU and virtualization is started.\n
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 13:09 ` [PATCH 6/8] provide env->kvm_fd Glauber Costa
@ 2009-07-08 13:09 ` Glauber Costa
2009-07-08 13:09 ` [PATCH 8/8] use upstream code for breakpoint handling Glauber Costa
2009-07-08 13:27 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Avi Kivity
2009-07-08 13:32 ` [PATCH 6/8] provide env->kvm_fd Gleb Natapov
1 sibling, 2 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:09 UTC (permalink / raw)
To: kvm; +Cc: avi
Signed-off-by: Glauber Costa <glommer@redhat.com>
---
kvm-all.c | 27 ++++++++++++++++++---------
qemu-kvm.h | 6 +++---
target-i386/kvm.c | 4 ++--
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index b404f76..6f92874 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1476,6 +1476,10 @@ int kvm_qemu_init()
kvm_context->no_irqchip_creation = 0;
kvm_context->no_pit_creation = 0;
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+ TAILQ_INIT(&kvm_state->kvm_sw_breakpoints);
+#endif
+
gsi_count = kvm_get_gsi_count(kvm_context);
if (gsi_count > 0) {
int gsi_bits, i;
@@ -3434,14 +3438,13 @@ int kvm_qemu_init_env(CPUState *cenv)
}
#ifdef KVM_CAP_SET_GUEST_DEBUG
-struct kvm_sw_breakpoint_head kvm_sw_breakpoints =
- TAILQ_HEAD_INITIALIZER(kvm_sw_breakpoints);
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(target_ulong pc)
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
+ target_ulong pc)
{
struct kvm_sw_breakpoint *bp;
- TAILQ_FOREACH(bp, &kvm_sw_breakpoints, entry) {
+ TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
if (bp->pc == pc)
return bp;
}
@@ -3476,6 +3479,11 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
return data.err;
}
+int kvm_sw_breakpoints_active(CPUState *env)
+{
+ return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
+}
+
int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
target_ulong len, int type)
{
@@ -3484,7 +3492,7 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
int err;
if (type == GDB_BREAKPOINT_SW) {
- bp = kvm_find_sw_breakpoint(addr);
+ bp = kvm_find_sw_breakpoint(current_env, addr);
if (bp) {
bp->use_count++;
return 0;
@@ -3502,7 +3510,8 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
return err;
}
- TAILQ_INSERT_HEAD(&kvm_sw_breakpoints, bp, entry);
+ TAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
+ bp, entry);
} else {
err = kvm_arch_insert_hw_breakpoint(addr, len, type);
if (err)
@@ -3525,7 +3534,7 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
int err;
if (type == GDB_BREAKPOINT_SW) {
- bp = kvm_find_sw_breakpoint(addr);
+ bp = kvm_find_sw_breakpoint(current_env, addr);
if (!bp)
return -ENOENT;
@@ -3538,7 +3547,7 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
if (err)
return err;
- TAILQ_REMOVE(&kvm_sw_breakpoints, bp, entry);
+ TAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
qemu_free(bp);
} else {
err = kvm_arch_remove_hw_breakpoint(addr, len, type);
@@ -3559,7 +3568,7 @@ void kvm_remove_all_breakpoints(CPUState *current_env)
struct kvm_sw_breakpoint *bp, *next;
CPUState *env;
- TAILQ_FOREACH_SAFE(bp, &kvm_sw_breakpoints, entry, next) {
+ TAILQ_FOREACH_SAFE(bp, ¤t_env->kvm_state->kvm_sw_breakpoints, entry, next) {
if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
/* Try harder to find a CPU that currently sees the breakpoint. */
for (env = first_cpu; env != NULL; env = env->next_cpu) {
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 4c185fd..bce80a2 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -88,12 +88,12 @@ struct kvm_sw_breakpoint {
int use_count;
TAILQ_ENTRY(kvm_sw_breakpoint) entry;
};
-TAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
-extern struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
+TAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info);
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(target_ulong pc);
+int kvm_sw_breakpoints_active(CPUState *env);
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env, target_ulong pc);
int kvm_arch_insert_sw_breakpoint(CPUState *current_env,
struct kvm_sw_breakpoint *bp);
int kvm_arch_remove_sw_breakpoint(CPUState *current_env,
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ab324f6..66da1ba 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -2433,7 +2433,7 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
break;
}
}
- } else if (kvm_find_sw_breakpoint(arch_info->pc))
+ } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
handle = 1;
if (!handle)
@@ -2456,7 +2456,7 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
};
int n;
- if (!TAILQ_EMPTY(&kvm_sw_breakpoints))
+ if (kvm_sw_breakpoints_active(env))
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
if (nb_hw_breakpoint > 0) {
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 8/8] use upstream code for breakpoint handling
2009-07-08 13:09 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Glauber Costa
@ 2009-07-08 13:09 ` Glauber Costa
2009-07-08 13:27 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Avi Kivity
1 sibling, 0 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:09 UTC (permalink / raw)
To: kvm; +Cc: avi
---
kvm-all.c | 422 +++++++++++++++-----------------------------
target-i386/kvm.c | 514 ++++++++++++++++++-----------------------------------
2 files changed, 314 insertions(+), 622 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 6f92874..a364d34 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -63,6 +63,148 @@ struct KVMState
static KVMState *kvm_state;
kvm_context_t kvm_context;
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
+ target_ulong pc)
+{
+ struct kvm_sw_breakpoint *bp;
+
+ TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
+ if (bp->pc == pc)
+ return bp;
+ }
+ return NULL;
+}
+
+int kvm_sw_breakpoints_active(CPUState *env)
+{
+ return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ struct kvm_sw_breakpoint *bp;
+ CPUState *env;
+ int err;
+
+ if (type == GDB_BREAKPOINT_SW) {
+ bp = kvm_find_sw_breakpoint(current_env, addr);
+ if (bp) {
+ bp->use_count++;
+ return 0;
+ }
+
+ bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
+ if (!bp)
+ return -ENOMEM;
+
+ bp->pc = addr;
+ bp->use_count = 1;
+ err = kvm_arch_insert_sw_breakpoint(current_env, bp);
+ if (err) {
+ free(bp);
+ return err;
+ }
+
+ TAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
+ bp, entry);
+ } else {
+ err = kvm_arch_insert_hw_breakpoint(addr, len, type);
+ if (err)
+ return err;
+ }
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ err = kvm_update_guest_debug(env, 0);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ struct kvm_sw_breakpoint *bp;
+ CPUState *env;
+ int err;
+
+ if (type == GDB_BREAKPOINT_SW) {
+ bp = kvm_find_sw_breakpoint(current_env, addr);
+ if (!bp)
+ return -ENOENT;
+
+ if (bp->use_count > 1) {
+ bp->use_count--;
+ return 0;
+ }
+
+ err = kvm_arch_remove_sw_breakpoint(current_env, bp);
+ if (err)
+ return err;
+
+ TAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
+ qemu_free(bp);
+ } else {
+ err = kvm_arch_remove_hw_breakpoint(addr, len, type);
+ if (err)
+ return err;
+ }
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ err = kvm_update_guest_debug(env, 0);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+ struct kvm_sw_breakpoint *bp, *next;
+ KVMState *s = current_env->kvm_state;
+ CPUState *env;
+
+ TAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
+ if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
+ /* Try harder to find a CPU that currently sees the breakpoint. */
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
+ break;
+ }
+ }
+ }
+ kvm_arch_remove_all_hw_breakpoints();
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu)
+ kvm_update_guest_debug(env, 0);
+}
+
+#else /* !KVM_CAP_SET_GUEST_DEBUG */
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+{
+ return -EINVAL;
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ return -EINVAL;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ return -EINVAL;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+}
+#endif /* !KVM_CAP_SET_GUEST_DEBUG */
+
#ifdef CONFIG_KVM
/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
@@ -885,24 +1027,6 @@ void kvm_setup_guest_memory(void *start, size_t size)
}
}
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
- target_ulong pc)
-{
- struct kvm_sw_breakpoint *bp;
-
- TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
- if (bp->pc == pc)
- return bp;
- }
- return NULL;
-}
-
-int kvm_sw_breakpoints_active(CPUState *env)
-{
- return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
-}
-
int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
{
struct kvm_guest_debug dbg;
@@ -917,129 +1041,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg);
}
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- struct kvm_sw_breakpoint *bp;
- CPUState *env;
- int err;
-
- if (type == GDB_BREAKPOINT_SW) {
- bp = kvm_find_sw_breakpoint(current_env, addr);
- if (bp) {
- bp->use_count++;
- return 0;
- }
-
- bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
- if (!bp)
- return -ENOMEM;
-
- bp->pc = addr;
- bp->use_count = 1;
- err = kvm_arch_insert_sw_breakpoint(current_env, bp);
- if (err) {
- free(bp);
- return err;
- }
-
- TAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
- bp, entry);
- } else {
- err = kvm_arch_insert_hw_breakpoint(addr, len, type);
- if (err)
- return err;
- }
-
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- err = kvm_update_guest_debug(env, 0);
- if (err)
- return err;
- }
- return 0;
-}
-
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- struct kvm_sw_breakpoint *bp;
- CPUState *env;
- int err;
-
- if (type == GDB_BREAKPOINT_SW) {
- bp = kvm_find_sw_breakpoint(current_env, addr);
- if (!bp)
- return -ENOENT;
-
- if (bp->use_count > 1) {
- bp->use_count--;
- return 0;
- }
-
- err = kvm_arch_remove_sw_breakpoint(current_env, bp);
- if (err)
- return err;
-
- TAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
- qemu_free(bp);
- } else {
- err = kvm_arch_remove_hw_breakpoint(addr, len, type);
- if (err)
- return err;
- }
-
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- err = kvm_update_guest_debug(env, 0);
- if (err)
- return err;
- }
- return 0;
-}
-
-void kvm_remove_all_breakpoints(CPUState *current_env)
-{
- struct kvm_sw_breakpoint *bp, *next;
- KVMState *s = current_env->kvm_state;
- CPUState *env;
-
- TAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
- if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
- /* Try harder to find a CPU that currently sees the breakpoint. */
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
- break;
- }
- }
- }
- kvm_arch_remove_all_hw_breakpoints();
-
- for (env = first_cpu; env != NULL; env = env->next_cpu)
- kvm_update_guest_debug(env, 0);
-}
-
-#else /* !KVM_CAP_SET_GUEST_DEBUG */
-
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
-{
- return -EINVAL;
-}
-
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- return -EINVAL;
-}
-
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- return -EINVAL;
-}
-
-void kvm_remove_all_breakpoints(CPUState *current_env)
-{
-}
-#endif /* !KVM_CAP_SET_GUEST_DEBUG */
#endif /* CONFIG_KVM */
#ifdef USE_KVM
@@ -3439,18 +3440,6 @@ int kvm_qemu_init_env(CPUState *cenv)
#ifdef KVM_CAP_SET_GUEST_DEBUG
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
- target_ulong pc)
-{
- struct kvm_sw_breakpoint *bp;
-
- TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
- if (bp->pc == pc)
- return bp;
- }
- return NULL;
-}
-
struct kvm_set_guest_debug_data {
struct kvm_guest_debug dbg;
int err;
@@ -3478,133 +3467,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
on_vcpu(env, kvm_invoke_set_guest_debug, &data);
return data.err;
}
-
-int kvm_sw_breakpoints_active(CPUState *env)
-{
- return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
-}
-
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- struct kvm_sw_breakpoint *bp;
- CPUState *env;
- int err;
-
- if (type == GDB_BREAKPOINT_SW) {
- bp = kvm_find_sw_breakpoint(current_env, addr);
- if (bp) {
- bp->use_count++;
- return 0;
- }
-
- bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
- if (!bp)
- return -ENOMEM;
-
- bp->pc = addr;
- bp->use_count = 1;
- err = kvm_arch_insert_sw_breakpoint(current_env, bp);
- if (err) {
- free(bp);
- return err;
- }
-
- TAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
- bp, entry);
- } else {
- err = kvm_arch_insert_hw_breakpoint(addr, len, type);
- if (err)
- return err;
- }
-
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- err = kvm_update_guest_debug(env, 0);
- if (err)
- return err;
- }
- return 0;
-}
-
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- struct kvm_sw_breakpoint *bp;
- CPUState *env;
- int err;
-
- if (type == GDB_BREAKPOINT_SW) {
- bp = kvm_find_sw_breakpoint(current_env, addr);
- if (!bp)
- return -ENOENT;
-
- if (bp->use_count > 1) {
- bp->use_count--;
- return 0;
- }
-
- err = kvm_arch_remove_sw_breakpoint(current_env, bp);
- if (err)
- return err;
-
- TAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
- qemu_free(bp);
- } else {
- err = kvm_arch_remove_hw_breakpoint(addr, len, type);
- if (err)
- return err;
- }
-
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- err = kvm_update_guest_debug(env, 0);
- if (err)
- return err;
- }
- return 0;
-}
-
-void kvm_remove_all_breakpoints(CPUState *current_env)
-{
- struct kvm_sw_breakpoint *bp, *next;
- CPUState *env;
-
- TAILQ_FOREACH_SAFE(bp, ¤t_env->kvm_state->kvm_sw_breakpoints, entry, next) {
- if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
- /* Try harder to find a CPU that currently sees the breakpoint. */
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
- break;
- }
- }
- }
- kvm_arch_remove_all_hw_breakpoints();
-
- for (env = first_cpu; env != NULL; env = env->next_cpu)
- kvm_update_guest_debug(env, 0);
-}
-
-#else /* !KVM_CAP_SET_GUEST_DEBUG */
-
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
-{
- return -EINVAL;
-}
-
-int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- return -EINVAL;
-}
-
-int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
- target_ulong len, int type)
-{
- return -EINVAL;
-}
-
-void kvm_remove_all_breakpoints(CPUState *current_env)
-{
-}
#endif /* !KVM_CAP_SET_GUEST_DEBUG */
/*
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 66da1ba..54fc9dc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -35,6 +35,178 @@
#include "libkvm-all.h"
#include "libkvm.h"
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+ const static uint8_t int3 = 0xcc;
+
+ if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
+ cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&int3, 1, 1))
+ return -EINVAL;
+ return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+ uint8_t int3;
+
+ if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
+ cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
+ return -EINVAL;
+ return 0;
+}
+
+static struct {
+ target_ulong addr;
+ int len;
+ int type;
+} hw_breakpoint[4];
+
+static int nb_hw_breakpoint;
+
+static int find_hw_breakpoint(target_ulong addr, int len, int type)
+{
+ int n;
+
+ for (n = 0; n < nb_hw_breakpoint; n++)
+ if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
+ (hw_breakpoint[n].len == len || len == -1))
+ return n;
+ return -1;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ switch (type) {
+ case GDB_BREAKPOINT_HW:
+ len = 1;
+ break;
+ case GDB_WATCHPOINT_WRITE:
+ case GDB_WATCHPOINT_ACCESS:
+ switch (len) {
+ case 1:
+ break;
+ case 2:
+ case 4:
+ case 8:
+ if (addr & (len - 1))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ if (nb_hw_breakpoint == 4)
+ return -ENOBUFS;
+
+ if (find_hw_breakpoint(addr, len, type) >= 0)
+ return -EEXIST;
+
+ hw_breakpoint[nb_hw_breakpoint].addr = addr;
+ hw_breakpoint[nb_hw_breakpoint].len = len;
+ hw_breakpoint[nb_hw_breakpoint].type = type;
+ nb_hw_breakpoint++;
+
+ return 0;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ int n;
+
+ n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
+ if (n < 0)
+ return -ENOENT;
+
+ nb_hw_breakpoint--;
+ hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
+
+ return 0;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+ nb_hw_breakpoint = 0;
+}
+
+static CPUWatchpoint hw_watchpoint;
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+{
+ int handle = 0;
+ int n;
+
+ if (arch_info->exception == 1) {
+ if (arch_info->dr6 & (1 << 14)) {
+ if (cpu_single_env->singlestep_enabled)
+ handle = 1;
+ } else {
+ for (n = 0; n < 4; n++)
+ if (arch_info->dr6 & (1 << n))
+ switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
+ case 0x0:
+ handle = 1;
+ break;
+ case 0x1:
+ handle = 1;
+ cpu_single_env->watchpoint_hit = &hw_watchpoint;
+ hw_watchpoint.vaddr = hw_breakpoint[n].addr;
+ hw_watchpoint.flags = BP_MEM_WRITE;
+ break;
+ case 0x3:
+ handle = 1;
+ cpu_single_env->watchpoint_hit = &hw_watchpoint;
+ hw_watchpoint.vaddr = hw_breakpoint[n].addr;
+ hw_watchpoint.flags = BP_MEM_ACCESS;
+ break;
+ }
+ }
+ } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
+ handle = 1;
+
+ if (!handle)
+ kvm_update_guest_debug(cpu_single_env,
+ (arch_info->exception == 1) ?
+ KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
+
+ return handle;
+}
+
+void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
+{
+ const uint8_t type_code[] = {
+ [GDB_BREAKPOINT_HW] = 0x0,
+ [GDB_WATCHPOINT_WRITE] = 0x1,
+ [GDB_WATCHPOINT_ACCESS] = 0x3
+ };
+ const uint8_t len_code[] = {
+ [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
+ };
+ int n;
+
+ if (kvm_sw_breakpoints_active(env))
+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
+
+ if (nb_hw_breakpoint > 0) {
+ dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
+ dbg->arch.debugreg[7] = 0x0600;
+ for (n = 0; n < nb_hw_breakpoint; n++) {
+ dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
+ dbg->arch.debugreg[7] |= (2 << (n * 2)) |
+ (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
+ (len_code[hw_breakpoint[n].len] << (18 + n*4));
+ }
+ }
+}
+#endif /* KVM_CAP_SET_GUEST_DEBUG */
+
+
#ifdef CONFIG_KVM
//#define DEBUG_KVM
@@ -802,177 +974,6 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
return ret;
}
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
-{
- const static uint8_t int3 = 0xcc;
-
- if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&int3, 1, 1))
- return -EINVAL;
- return 0;
-}
-
-int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
-{
- uint8_t int3;
-
- if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
- return -EINVAL;
- return 0;
-}
-
-static struct {
- target_ulong addr;
- int len;
- int type;
-} hw_breakpoint[4];
-
-static int nb_hw_breakpoint;
-
-static int find_hw_breakpoint(target_ulong addr, int len, int type)
-{
- int n;
-
- for (n = 0; n < nb_hw_breakpoint; n++)
- if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
- (hw_breakpoint[n].len == len || len == -1))
- return n;
- return -1;
-}
-
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- switch (type) {
- case GDB_BREAKPOINT_HW:
- len = 1;
- break;
- case GDB_WATCHPOINT_WRITE:
- case GDB_WATCHPOINT_ACCESS:
- switch (len) {
- case 1:
- break;
- case 2:
- case 4:
- case 8:
- if (addr & (len - 1))
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- return -ENOSYS;
- }
-
- if (nb_hw_breakpoint == 4)
- return -ENOBUFS;
-
- if (find_hw_breakpoint(addr, len, type) >= 0)
- return -EEXIST;
-
- hw_breakpoint[nb_hw_breakpoint].addr = addr;
- hw_breakpoint[nb_hw_breakpoint].len = len;
- hw_breakpoint[nb_hw_breakpoint].type = type;
- nb_hw_breakpoint++;
-
- return 0;
-}
-
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- int n;
-
- n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
- if (n < 0)
- return -ENOENT;
-
- nb_hw_breakpoint--;
- hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
-
- return 0;
-}
-
-void kvm_arch_remove_all_hw_breakpoints(void)
-{
- nb_hw_breakpoint = 0;
-}
-
-static CPUWatchpoint hw_watchpoint;
-
-int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
-{
- int handle = 0;
- int n;
-
- if (arch_info->exception == 1) {
- if (arch_info->dr6 & (1 << 14)) {
- if (cpu_single_env->singlestep_enabled)
- handle = 1;
- } else {
- for (n = 0; n < 4; n++)
- if (arch_info->dr6 & (1 << n))
- switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
- case 0x0:
- handle = 1;
- break;
- case 0x1:
- handle = 1;
- cpu_single_env->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_WRITE;
- break;
- case 0x3:
- handle = 1;
- cpu_single_env->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_ACCESS;
- break;
- }
- }
- } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
- handle = 1;
-
- if (!handle)
- kvm_update_guest_debug(cpu_single_env,
- (arch_info->exception == 1) ?
- KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
-
- return handle;
-}
-
-void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
-{
- const uint8_t type_code[] = {
- [GDB_BREAKPOINT_HW] = 0x0,
- [GDB_WATCHPOINT_WRITE] = 0x1,
- [GDB_WATCHPOINT_ACCESS] = 0x3
- };
- const uint8_t len_code[] = {
- [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
- };
- int n;
-
- if (kvm_sw_breakpoints_active(env))
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
-
- if (nb_hw_breakpoint > 0) {
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
- dbg->arch.debugreg[7] = 0x0600;
- for (n = 0; n < nb_hw_breakpoint; n++) {
- dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
- dbg->arch.debugreg[7] |= (2 << (n * 2)) |
- (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
- (len_code[hw_breakpoint[n].len] << (18 + n*4));
- }
- }
-}
-#endif /* KVM_CAP_SET_GUEST_DEBUG */
-
#endif /* CONFIG_KVM */
#ifdef USE_KVM
@@ -2301,177 +2302,6 @@ void kvm_arch_cpu_reset(CPUState *env)
}
}
-int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
-{
- uint8_t int3 = 0xcc;
-
- if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
- cpu_memory_rw_debug(env, bp->pc, &int3, 1, 1))
- return -EINVAL;
- return 0;
-}
-
-int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
-{
- uint8_t int3;
-
- if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
- return -EINVAL;
- return 0;
-}
-
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-static struct {
- target_ulong addr;
- int len;
- int type;
-} hw_breakpoint[4];
-
-static int nb_hw_breakpoint;
-
-static int find_hw_breakpoint(target_ulong addr, int len, int type)
-{
- int n;
-
- for (n = 0; n < nb_hw_breakpoint; n++)
- if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
- (hw_breakpoint[n].len == len || len == -1))
- return n;
- return -1;
-}
-
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- switch (type) {
- case GDB_BREAKPOINT_HW:
- len = 1;
- break;
- case GDB_WATCHPOINT_WRITE:
- case GDB_WATCHPOINT_ACCESS:
- switch (len) {
- case 1:
- break;
- case 2:
- case 4:
- case 8:
- if (addr & (len - 1))
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- return -ENOSYS;
- }
-
- if (nb_hw_breakpoint == 4)
- return -ENOBUFS;
-
- if (find_hw_breakpoint(addr, len, type) >= 0)
- return -EEXIST;
-
- hw_breakpoint[nb_hw_breakpoint].addr = addr;
- hw_breakpoint[nb_hw_breakpoint].len = len;
- hw_breakpoint[nb_hw_breakpoint].type = type;
- nb_hw_breakpoint++;
-
- return 0;
-}
-
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- int n;
-
- n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
- if (n < 0)
- return -ENOENT;
-
- nb_hw_breakpoint--;
- hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
-
- return 0;
-}
-
-void kvm_arch_remove_all_hw_breakpoints(void)
-{
- nb_hw_breakpoint = 0;
-}
-
-static CPUWatchpoint hw_watchpoint;
-
-int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
-{
- int handle = 0;
- int n;
-
- if (arch_info->exception == 1) {
- if (arch_info->dr6 & (1 << 14)) {
- if (cpu_single_env->singlestep_enabled)
- handle = 1;
- } else {
- for (n = 0; n < 4; n++)
- if (arch_info->dr6 & (1 << n))
- switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
- case 0x0:
- handle = 1;
- break;
- case 0x1:
- handle = 1;
- cpu_single_env->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_WRITE;
- break;
- case 0x3:
- handle = 1;
- cpu_single_env->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = hw_breakpoint[n].addr;
- hw_watchpoint.flags = BP_MEM_ACCESS;
- break;
- }
- }
- } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
- handle = 1;
-
- if (!handle)
- kvm_update_guest_debug(cpu_single_env,
- (arch_info->exception == 1) ?
- KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
-
- return handle;
-}
-
-void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
-{
- const uint8_t type_code[] = {
- [GDB_BREAKPOINT_HW] = 0x0,
- [GDB_WATCHPOINT_WRITE] = 0x1,
- [GDB_WATCHPOINT_ACCESS] = 0x3
- };
- const uint8_t len_code[] = {
- [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
- };
- int n;
-
- if (kvm_sw_breakpoints_active(env))
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
-
- if (nb_hw_breakpoint > 0) {
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
- dbg->arch.debugreg[7] = 0x0600;
- for (n = 0; n < nb_hw_breakpoint; n++) {
- dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
- dbg->arch.debugreg[7] |= (2 << (n * 2)) |
- (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
- (len_code[hw_breakpoint[n].len] << (18 + n*4));
- }
- }
-}
-#endif
-
void kvm_arch_do_ioperm(void *_data)
{
struct ioperm_data *data = _data;
--
1.6.2.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM
2009-07-08 13:08 ` [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM Glauber Costa
@ 2009-07-08 13:22 ` Avi Kivity
[not found] ` <1247058542-31211-3-git-send-email-glommer@redhat.com>
1 sibling, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 13:22 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm
On 07/08/2009 04:08 PM, Glauber Costa wrote:
> This will allow qemu-kvm to refer to the structure, since qemu-kvm relies
> on USE_KVM, not CONFIG_KVM. This should be sent to qemu.git as well
>
> Signed-off-by: Glauber Costa<glommer@redhat.com>
> ---
> kvm.h | 6 +++---
> 1 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/kvm.h b/kvm.h
> index d9723d7..7648c49 100644
> --- a/kvm.h
> +++ b/kvm.h
> @@ -18,6 +18,9 @@
> #include "sys-queue.h"
> #include "libkvm-all.h"
>
> +struct KVMState;
> +typedef struct KVMState KVMState;
> +
> #ifdef KVM_UPSTREAM
>
> #ifdef CONFIG_KVM
> @@ -65,9 +68,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
>
> /* internal API */
>
> -struct KVMState;
> -typedef struct KVMState KVMState;
> -
> int kvm_ioctl(KVMState *s, int type, ...);
>
> int kvm_vm_ioctl(KVMState *s, int type, ...);
>
Not really needed - we can duplicate these two lines where we use them.
Since they'll later go away, we avoid some (minimal) churn.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/8] move qemu-kvm.c to kvm-all.c
[not found] ` <1247058542-31211-3-git-send-email-glommer@redhat.com>
2009-07-08 13:08 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Glauber Costa
@ 2009-07-08 13:23 ` Avi Kivity
2009-07-08 13:52 ` Glauber Costa
1 sibling, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 13:23 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm
On 07/08/2009 04:08 PM, Glauber Costa wrote:
> Big plan to start sharing code with upstream.
>
>
This patch is very brittle - if qemu-kvm.c changes, it won't apply. I
suggest to simply add #include "qemu-kvm.c" and remove it from the
makefile. After I apply it, I'll perform the #include and remove
qemu-kvm.c.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 3/8] put qemu-kvm-x86.c into kvm.c
2009-07-08 13:08 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Glauber Costa
2009-07-08 13:08 ` [PATCH 4/8] replace malloc with qemu_malloc Glauber Costa
@ 2009-07-08 13:23 ` Avi Kivity
2009-07-08 13:28 ` Gleb Natapov
2 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 13:23 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm
On 07/08/2009 04:08 PM, Glauber Costa wrote:
> big plan to start sharing code with upstream.
>
>
What's the big plan re qemu-kvm-ia64.c?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 13:09 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Glauber Costa
2009-07-08 13:09 ` [PATCH 8/8] use upstream code for breakpoint handling Glauber Costa
@ 2009-07-08 13:27 ` Avi Kivity
2009-07-08 13:39 ` Glauber Costa
1 sibling, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 13:27 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm
On 07/08/2009 04:09 PM, Glauber Costa wrote:
> Signed-off-by: Glauber Costa<glommer@redhat.com>
> ---
> kvm-all.c | 27 ++++++++++++++++++---------
> qemu-kvm.h | 6 +++---
> target-i386/kvm.c | 4 ++--
> 3 files changed, 23 insertions(+), 14 deletions(-)
>
>
Did you test the functionality to ensure we do not regress?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 0/8] Move closer to upstream
2009-07-08 13:08 [PATCH 0/8] Move closer to upstream Glauber Costa
2009-07-08 13:08 ` [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM Glauber Costa
@ 2009-07-08 13:27 ` Avi Kivity
1 sibling, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 13:27 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm
On 07/08/2009 04:08 PM, Glauber Costa wrote:
> Hi,
>
> This is another step at getting us closer to qemu upstream. I'm moving
> our code to kvm-all.c and kvm.c, and relying on the fact that we use
> USE_KVM, while upstream qemu uses CONFIG_KVM, to keep us isolated.
>
> The goal is to slowly reduce that isolation. To demonstrate what I aim
> for, the last patches of the series shares code for breakpoint handling.
> next in my radar are ioctl functions and cpuid trimming.
>
>
Overall this approach looks good.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 3/8] put qemu-kvm-x86.c into kvm.c
2009-07-08 13:08 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Glauber Costa
2009-07-08 13:08 ` [PATCH 4/8] replace malloc with qemu_malloc Glauber Costa
2009-07-08 13:23 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Avi Kivity
@ 2009-07-08 13:28 ` Gleb Natapov
2009-07-08 13:41 ` Glauber Costa
2 siblings, 1 reply; 24+ messages in thread
From: Gleb Natapov @ 2009-07-08 13:28 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm, avi
On Wed, Jul 08, 2009 at 09:08:57AM -0400, Glauber Costa wrote:
> big plan to start sharing code with upstream.
>
It is hard enough (for me at least) to distinguish between upstream code
and qemu-kvm when I have to look at the code. Having them separated in
different files is very helpful. Looking at the filename in a grep result
is enough to know if I should care about the result or not.
Can you simple include qemu-kvm-x86.c into kvm.c?
--
Gleb.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/8] provide env->kvm_fd
2009-07-08 13:09 ` [PATCH 6/8] provide env->kvm_fd Glauber Costa
2009-07-08 13:09 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Glauber Costa
@ 2009-07-08 13:32 ` Gleb Natapov
2009-07-08 13:44 ` Glauber Costa
1 sibling, 1 reply; 24+ messages in thread
From: Gleb Natapov @ 2009-07-08 13:32 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm, avi
On Wed, Jul 08, 2009 at 09:09:00AM -0400, Glauber Costa wrote:
> qemu upstream puts kvm information on env. Do that too, since it will
> allow us to use CPUState in cpu-specific functions, instead of kvm-specific
> types.
>
> Signed-off-by: Glauber Costa <glommer@redhat.com>
> ---
> kvm-all.c | 12 ++++++++----
> libkvm-all.h | 12 ------------
> 2 files changed, 8 insertions(+), 16 deletions(-)
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 15bd429..b404f76 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -1519,21 +1519,25 @@ void kvm_disable_pit_creation(kvm_context_t kvm)
> kvm->no_pit_creation = 1;
> }
>
> -kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, int id)
> +static kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, CPUState *env)
> {
> long mmap_size;
> int r;
> kvm_vcpu_context_t vcpu_ctx = qemu_malloc(sizeof(struct kvm_vcpu_context));
>
> vcpu_ctx->kvm = kvm;
> - vcpu_ctx->id = id;
> + vcpu_ctx->id = env->cpu_index;
>
> - r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, id);
> + r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, env->cpu_index);
This just reverts all my work to separate apic_id from env->cpu_index.
We want to bring good things from qemu-kvm to upstream not bad things
from upstream to qemu-kvm :) If anything you should use env->cpuid_apic_id
instead of env->cpu_index here.
--
Gleb.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/8] provide env->kvm_fd
2009-07-08 13:44 ` Glauber Costa
@ 2009-07-08 13:38 ` Gleb Natapov
0 siblings, 0 replies; 24+ messages in thread
From: Gleb Natapov @ 2009-07-08 13:38 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm, avi
On Wed, Jul 08, 2009 at 10:44:01AM -0300, Glauber Costa wrote:
> On Wed, Jul 08, 2009 at 04:32:37PM +0300, Gleb Natapov wrote:
> > On Wed, Jul 08, 2009 at 09:09:00AM -0400, Glauber Costa wrote:
> > > qemu upstream puts kvm information on env. Do that too, since it will
> > > allow us to use CPUState in cpu-specific functions, instead of kvm-specific
> > > types.
> > >
> > > Signed-off-by: Glauber Costa <glommer@redhat.com>
> > > ---
> > > kvm-all.c | 12 ++++++++----
> > > libkvm-all.h | 12 ------------
> > > 2 files changed, 8 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/kvm-all.c b/kvm-all.c
> > > index 15bd429..b404f76 100644
> > > --- a/kvm-all.c
> > > +++ b/kvm-all.c
> > > @@ -1519,21 +1519,25 @@ void kvm_disable_pit_creation(kvm_context_t kvm)
> > > kvm->no_pit_creation = 1;
> > > }
> > >
> > > -kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, int id)
> > > +static kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, CPUState *env)
> > > {
> > > long mmap_size;
> > > int r;
> > > kvm_vcpu_context_t vcpu_ctx = qemu_malloc(sizeof(struct kvm_vcpu_context));
> > >
> > > vcpu_ctx->kvm = kvm;
> > > - vcpu_ctx->id = id;
> > > + vcpu_ctx->id = env->cpu_index;
> > >
> > > - r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, id);
> > > + r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, env->cpu_index);
> > This just reverts all my work to separate apic_id from env->cpu_index.
> > We want to bring good things from qemu-kvm to upstream not bad things
> > from upstream to qemu-kvm :) If anything you should use env->cpuid_apic_id
> > instead of env->cpu_index here.
> cpuid_apic_id is fine.
> my bad here.
Actually I prefer to use id here and pass env->cpuid_apic_id to the
function.
--
Gleb.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 13:27 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Avi Kivity
@ 2009-07-08 13:39 ` Glauber Costa
2009-07-08 13:44 ` Avi Kivity
0 siblings, 1 reply; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:39 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, jan.kiszka
On Wed, Jul 08, 2009 at 04:27:27PM +0300, Avi Kivity wrote:
> On 07/08/2009 04:09 PM, Glauber Costa wrote:
>> Signed-off-by: Glauber Costa<glommer@redhat.com>
>> ---
>> kvm-all.c | 27 ++++++++++++++++++---------
>> qemu-kvm.h | 6 +++---
>> target-i386/kvm.c | 4 ++--
>> 3 files changed, 23 insertions(+), 14 deletions(-)
>>
>>
>
> Did you test the functionality to ensure we do not regress?
just briefly. To be honest, I'd feel much more confortable
if Jan could give it a try.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 3/8] put qemu-kvm-x86.c into kvm.c
2009-07-08 13:28 ` Gleb Natapov
@ 2009-07-08 13:41 ` Glauber Costa
0 siblings, 0 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:41 UTC (permalink / raw)
To: Gleb Natapov; +Cc: kvm, avi
On Wed, Jul 08, 2009 at 04:28:51PM +0300, Gleb Natapov wrote:
> On Wed, Jul 08, 2009 at 09:08:57AM -0400, Glauber Costa wrote:
> > big plan to start sharing code with upstream.
> >
> It is hard enough (for me at least) to distinguish between upstream code
> and qemu-kvm when I have to look at the code. Having them separated in
> different files is very helpful. Looking at the filename in a grep result
> is enough to know if I should care about the result or not.
>
> Can you simple include qemu-kvm-x86.c into kvm.c?
I could, but I believe this would make sharing, which is the ultimate goal,
a little bit cumbersome. Anyway, the goal is not to have it last long.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/8] provide env->kvm_fd
2009-07-08 13:32 ` [PATCH 6/8] provide env->kvm_fd Gleb Natapov
@ 2009-07-08 13:44 ` Glauber Costa
2009-07-08 13:38 ` Gleb Natapov
0 siblings, 1 reply; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:44 UTC (permalink / raw)
To: Gleb Natapov; +Cc: kvm, avi
On Wed, Jul 08, 2009 at 04:32:37PM +0300, Gleb Natapov wrote:
> On Wed, Jul 08, 2009 at 09:09:00AM -0400, Glauber Costa wrote:
> > qemu upstream puts kvm information on env. Do that too, since it will
> > allow us to use CPUState in cpu-specific functions, instead of kvm-specific
> > types.
> >
> > Signed-off-by: Glauber Costa <glommer@redhat.com>
> > ---
> > kvm-all.c | 12 ++++++++----
> > libkvm-all.h | 12 ------------
> > 2 files changed, 8 insertions(+), 16 deletions(-)
> >
> > diff --git a/kvm-all.c b/kvm-all.c
> > index 15bd429..b404f76 100644
> > --- a/kvm-all.c
> > +++ b/kvm-all.c
> > @@ -1519,21 +1519,25 @@ void kvm_disable_pit_creation(kvm_context_t kvm)
> > kvm->no_pit_creation = 1;
> > }
> >
> > -kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, int id)
> > +static kvm_vcpu_context_t kvm_create_vcpu(kvm_context_t kvm, CPUState *env)
> > {
> > long mmap_size;
> > int r;
> > kvm_vcpu_context_t vcpu_ctx = qemu_malloc(sizeof(struct kvm_vcpu_context));
> >
> > vcpu_ctx->kvm = kvm;
> > - vcpu_ctx->id = id;
> > + vcpu_ctx->id = env->cpu_index;
> >
> > - r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, id);
> > + r = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, env->cpu_index);
> This just reverts all my work to separate apic_id from env->cpu_index.
> We want to bring good things from qemu-kvm to upstream not bad things
> from upstream to qemu-kvm :) If anything you should use env->cpuid_apic_id
> instead of env->cpu_index here.
cpuid_apic_id is fine.
my bad here.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 13:39 ` Glauber Costa
@ 2009-07-08 13:44 ` Avi Kivity
2009-07-08 15:23 ` Jan Kiszka
0 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 13:44 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm, jan.kiszka
On 07/08/2009 04:39 PM, Glauber Costa wrote:
> On Wed, Jul 08, 2009 at 04:27:27PM +0300, Avi Kivity wrote:
>
>> On 07/08/2009 04:09 PM, Glauber Costa wrote:
>>
>>> Signed-off-by: Glauber Costa<glommer@redhat.com>
>>> ---
>>> kvm-all.c | 27 ++++++++++++++++++---------
>>> qemu-kvm.h | 6 +++---
>>> target-i386/kvm.c | 4 ++--
>>> 3 files changed, 23 insertions(+), 14 deletions(-)
>>>
>>>
>>>
>> Did you test the functionality to ensure we do not regress?
>>
> just briefly. To be honest, I'd feel much more confortable
> if Jan could give it a try.
>
A Jan try (+review) will definitely help.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/8] move qemu-kvm.c to kvm-all.c
2009-07-08 13:23 ` [PATCH 2/8] move qemu-kvm.c to kvm-all.c Avi Kivity
@ 2009-07-08 13:52 ` Glauber Costa
0 siblings, 0 replies; 24+ messages in thread
From: Glauber Costa @ 2009-07-08 13:52 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm
On Wed, Jul 08, 2009 at 04:23:39PM +0300, Avi Kivity wrote:
> On 07/08/2009 04:08 PM, Glauber Costa wrote:
>> Big plan to start sharing code with upstream.
>>
>>
>
> This patch is very brittle - if qemu-kvm.c changes, it won't apply. I
> suggest to simply add #include "qemu-kvm.c" and remove it from the
> makefile. After I apply it, I'll perform the #include and remove
> qemu-kvm.c.
ok.
I'll do the same with kvm.c
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 13:44 ` Avi Kivity
@ 2009-07-08 15:23 ` Jan Kiszka
2009-07-08 19:44 ` Jan Kiszka
0 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-07-08 15:23 UTC (permalink / raw)
To: Avi Kivity; +Cc: Glauber Costa, kvm
[-- Attachment #1: Type: text/plain, Size: 743 bytes --]
Avi Kivity wrote:
> On 07/08/2009 04:39 PM, Glauber Costa wrote:
>> On Wed, Jul 08, 2009 at 04:27:27PM +0300, Avi Kivity wrote:
>>
>>> On 07/08/2009 04:09 PM, Glauber Costa wrote:
>>>
>>>> Signed-off-by: Glauber Costa<glommer@redhat.com>
>>>> ---
>>>> kvm-all.c | 27 ++++++++++++++++++---------
>>>> qemu-kvm.h | 6 +++---
>>>> target-i386/kvm.c | 4 ++--
>>>> 3 files changed, 23 insertions(+), 14 deletions(-)
>>>>
>>>>
>>>>
>>> Did you test the functionality to ensure we do not regress?
>>>
>> just briefly. To be honest, I'd feel much more confortable
>> if Jan could give it a try.
>>
>
> A Jan try (+review) will definitely help.
>
Queued.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 15:23 ` Jan Kiszka
@ 2009-07-08 19:44 ` Jan Kiszka
2009-07-08 19:55 ` Avi Kivity
0 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-07-08 19:44 UTC (permalink / raw)
To: Avi Kivity, Glauber Costa; +Cc: kvm
[-- Attachment #1: Type: text/plain, Size: 1317 bytes --]
Jan Kiszka wrote:
> Avi Kivity wrote:
>> On 07/08/2009 04:39 PM, Glauber Costa wrote:
>>> On Wed, Jul 08, 2009 at 04:27:27PM +0300, Avi Kivity wrote:
>>>
>>>> On 07/08/2009 04:09 PM, Glauber Costa wrote:
>>>>
>>>>> Signed-off-by: Glauber Costa<glommer@redhat.com>
>>>>> ---
>>>>> kvm-all.c | 27 ++++++++++++++++++---------
>>>>> qemu-kvm.h | 6 +++---
>>>>> target-i386/kvm.c | 4 ++--
>>>>> 3 files changed, 23 insertions(+), 14 deletions(-)
>>>>>
>>>>>
>>>>>
>>>> Did you test the functionality to ensure we do not regress?
>>>>
>>> just briefly. To be honest, I'd feel much more confortable
>>> if Jan could give it a try.
>>>
>> A Jan try (+review) will definitely help.
>>
>
> Queued.
>
Deferred until v2. My first impression is that too much upstream code is
moved or touched.
Glauber, if you want to use some function that is currently under
KVM_UPSTREAM, don't move it, just drop the #ifdef around it. And when
done, have a look at the diff between upstream and qemu-kvm to avoid
unneeded variations.
Another question: What prevents using CONFIG_KVM also for qemu-kvm? I
would rather mask out yet unused upstream code via the well-known
KVM_UPSTREAM and drop the easily confusable USE_KVM defines.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 7/8] use kvm_upstream sw_breakpoints structure
2009-07-08 19:44 ` Jan Kiszka
@ 2009-07-08 19:55 ` Avi Kivity
0 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2009-07-08 19:55 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Glauber Costa, kvm
On 07/08/2009 10:44 PM, Jan Kiszka wrote:
>
> Deferred until v2. My first impression is that too much upstream code is
> moved or touched.
>
> Glauber, if you want to use some function that is currently under
> KVM_UPSTREAM, don't move it, just drop the #ifdef around it. And when
> done, have a look at the diff between upstream and qemu-kvm to avoid
> unneeded variations.
>
Yes. I though that's what we'd agreed, but forgot to verify it. The
only difference should be #endif/#ifdef pairs.
> Another question: What prevents using CONFIG_KVM also for qemu-kvm? I
> would rather mask out yet unused upstream code via the well-known
> KVM_UPSTREAM and drop the easily confusable USE_KVM defines.
>
Good idea, would simplify ./configure as well.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2009-07-08 19:54 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-08 13:08 [PATCH 0/8] Move closer to upstream Glauber Costa
2009-07-08 13:08 ` [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM Glauber Costa
2009-07-08 13:22 ` Avi Kivity
[not found] ` <1247058542-31211-3-git-send-email-glommer@redhat.com>
2009-07-08 13:08 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Glauber Costa
2009-07-08 13:08 ` [PATCH 4/8] replace malloc with qemu_malloc Glauber Costa
2009-07-08 13:08 ` [PATCH 5/8] move kvm_context inside KVMState Glauber Costa
2009-07-08 13:09 ` [PATCH 6/8] provide env->kvm_fd Glauber Costa
2009-07-08 13:09 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Glauber Costa
2009-07-08 13:09 ` [PATCH 8/8] use upstream code for breakpoint handling Glauber Costa
2009-07-08 13:27 ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Avi Kivity
2009-07-08 13:39 ` Glauber Costa
2009-07-08 13:44 ` Avi Kivity
2009-07-08 15:23 ` Jan Kiszka
2009-07-08 19:44 ` Jan Kiszka
2009-07-08 19:55 ` Avi Kivity
2009-07-08 13:32 ` [PATCH 6/8] provide env->kvm_fd Gleb Natapov
2009-07-08 13:44 ` Glauber Costa
2009-07-08 13:38 ` Gleb Natapov
2009-07-08 13:23 ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Avi Kivity
2009-07-08 13:28 ` Gleb Natapov
2009-07-08 13:41 ` Glauber Costa
2009-07-08 13:23 ` [PATCH 2/8] move qemu-kvm.c to kvm-all.c Avi Kivity
2009-07-08 13:52 ` Glauber Costa
2009-07-08 13:27 ` [PATCH 0/8] Move closer to upstream Avi Kivity
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.