qemu-kvm: Extended use of upstream code
cover qemu-kvm: Extended use of upstream code
Spin-off from my longer series as Marcelo asked for the last patch as the next step. I don't see any value in reordering the series, so I just but off the lower bits.
This part mostly cleans up common KVM code that is also present upstream. It also includes the fixed guest debug writeback, first for upstream (patch 8 should be queued into uq/master as well), then merged into qemu-kvm while dropping the qemu-kvm copy of the guest debugging code.
The differences to previous postings of the full series are:
- rebased over qemu-kvm
- fixed guest state writeback to avoid conflicts with SET_VCPU_EVENTS, rather use them on modern kernels (I know Gleb will hate me for this, but I'm convinced it's cleaner that way)
Pull URL is
git://git.kiszka.org/qemu-kvm.git queues/queues-kvm-merge
Jan Kiszka (9):
qemu-kvm: Drop vmport changes
qemu-kvm: Clean up register access API
qemu-kvm: Use upstream kvm_enabled and cpu_synchronize_state
qemu-kvm: Use upstream kvm_setup_guest_memory
qemu-kvm: Use some more upstream prototypes
qemu-kvm: Use upstream kvm_arch_get_supported_cpuid
qemu-kvm: Use upstream kvm_pit_in_kernel
KVM: Rework of guest debug state writing
qemu-kvm: Use upstream guest debug code
hw/i8254.c | 6 +- hw/i8259.c | 2 +- hw/ioapic.c | 2 +- hw/msix.c | 3 +- hw/pc.c | 4 +- hw/pcspk.c | 4 +- hw/piix_pci.c | 2 +- hw/vmport.c | 13 +-- kvm-all.c | 24 ++--- kvm.h | 11 +-- qemu-kvm-x86.c | 319 ++++++------------------------------------------- qemu-kvm.c | 110 ++---------------- qemu-kvm.h | 139 +-------------------- target-i386/kvm.c | 43 ++++++- target-ia64/machine.c | 4 +- vl.c | 3 +- 16 files changed, 114 insertions(+), 575 deletions(-)
PATCH 1/9 qemu-kvm: Drop vmport changes
Upstream has proper support now. Drop the old half-broken approach and all surrounding diffs.
--- hw/vmport.c | 13 +------------ 1 files changed, 1 insertions(+), 12 deletions(-)
hw/vmport.c +1 -12
@@ -21,12 +21,10 @@* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" #include "isa.h" #include "pc.h" #include "sysemu.h" -#include "qemu-kvm.h" #include "kvm.h" //#define VMPORT_DEBUG
@@ -60,10 +58,6 @@ static uint32_t vmport_ioport_read(void *opaque, uint32_t addr)CPUState *env = cpu_single_env;unsigned char command;uint32_t eax; -uint32_t ret; - -if (kvm_enabled ()) -kvm_save_registers (env);cpu_synchronize_state (env);
@@ -82,12 +76,7 @@ static uint32_t vmport_ioport_read(void *opaque, uint32_t addr)return eax; } - ret = s->func[command](s->opaque[command], addr); - -if (kvm_enabled ()) -kvm_load_registers (env); - -return ret; +return s->func[command](s->opaque[command], addr); }static void vmport_ioport_write (void *opaque,uint32_t addr,uint32_t val)
Signature · 1 line
1.6.0.2
PATCH 2/9 qemu-kvm: Clean up register access API
In reply to Jan Kiszkaqemu-kvm's functions for accessing the VCPU registers are kvm_arch_load/save_regs. Use them directly instead of going through various wrappers. Specifically, we do not need on_vcpu wrapping as all users either already run in the related thread or call while the vm is stopped. This is now also validated during runtime via asserts.
--- qemu-kvm-x86.c | 4 ++++ qemu-kvm.c | 46 ++++++++-------------------------------------- qemu-kvm.h | 14 +++----------- target-ia64/machine.c | 4 ++-- 4 files changed, 17 insertions(+), 51 deletions(-)
qemu-kvm-x86.c +4 -0
@@ -911,6 +911,8 @@ void kvm_arch_load_regs(CPUState *env)struct kvm_msr_entry msrs[100 ];int rc, n, i; +assert (kvm_cpu_is_stopped (env) || env->thread_id ==kvm_get_thread_id ()); + regs.rax = env->regs[R_EAX ]; regs.rbx = env->regs[R_EBX ]; regs.rcx = env->regs[R_ECX ];
@@ -1072,6 +1074,8 @@ void kvm_arch_save_regs(CPUState *env)uint32_t hflags;uint32_t i, n, rc, bit; +assert (kvm_cpu_is_stopped (env) || env->thread_id ==kvm_get_thread_id ()); +kvm_get_regs (env, ®s); env->regs[R_EAX ] = regs.rax;
qemu-kvm.c +8 -38
92 lines not on this page · raw message
qemu-kvm.h +3 -11
@@ -902,8 +902,6 @@ int kvm_main_loop(void);int kvm_init_ap (void );#ifndef QEMU_KVM_NO_CPU int kvm_vcpu_inited (CPUState *env); -void kvm_load_registers (CPUState *env); -void kvm_save_registers (CPUState *env);void kvm_load_mpstate (CPUState *env);void kvm_save_mpstate (CPUState *env);int kvm_cpu_exec (CPUState *env);
@@ -1069,8 +1067,6 @@ void kvm_load_tsc(CPUState *env);#ifdef TARGET_I386 #define qemu_kvm_has_pit_state2 () (0)#endif -#define kvm_load_registers (env) do {} while(0) -#define kvm_save_registers (env) do {} while(0)#define kvm_save_mpstate (env) do {} while(0)#define qemu_kvm_cpu_stop (env) do {} while(0)static inline void kvm_init_vcpu (CPUState *env)
@@ -1099,13 +1095,6 @@ static inline int kvm_sync_vcpus(void) }#ifndef QEMU_KVM_NO_CPU -void kvm_arch_get_registers (CPUState *env); - -static inline void kvm_arch_put_registers (CPUState *env) -{ -kvm_load_registers (env); -} -void kvm_cpu_synchronize_state (CPUState *env);static inline void cpu_synchronize_state (CPUState *env)
@@ -1168,6 +1157,9 @@ int kvm_check_extension(KVMState *s, unsigned int ext);int kvm_tpr_enable_vapic (CPUState *env); +unsigned long kvm_get_thread_id (void ); +int kvm_cpu_is_stopped (CPUState *env); +#endif #endif
target-ia64/machine.c +2 -2
@@ -9,7 +9,7 @@ void cpu_save(QEMUFile *f, void *opaque)CPUState *env = opaque;if (kvm_enabled ()) { -kvm_save_registers (env); +kvm_arch_save_regs (env);kvm_arch_save_mpstate (env); } }
@@ -19,7 +19,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)CPUState *env = opaque;if (kvm_enabled ()) { -kvm_load_registers (env); +kvm_arch_load_regs (env);kvm_arch_load_mpstate (env); }return 0 ;
Signature · 1 line
1.6.0.2
Re: [PATCH 2/9] qemu-kvm: Clean up register access API
Quoted 9 lines · Jan Kiszka
qemu-kvm's functions for accessing the VCPU registers are kvm_arch_load/save_regs. Use them directly instead of going through various wrappers. Specifically, we do not need
on_vcpuwrapping as all users either already run in the related thread or call while the vm is stopped. This is now also validated during runtime via asserts.+
assert(kvm_cpu_is_stopped(env) || env->thread_id == kvm_get_thread_id());
The kvm_cpu_is_stopped() part is wrong, for two reasons. First, a future ABI revolution might switch to syscalls and thus make the association between vcpu and thread implicit. This will allow us to drop vcpu->mutex, eventually. Second, kvm_cpu_is_stopped() will be racy in a threaded future version of qemu. All vcpu ioctls should be made from the vcpu thread.
Documentation/kvm/api.txt has this to say about the matter:
Quoted 5 lines
- vcpu ioctls: These query and set attributes that control the operation of a single virtual cpu.
Only run vcpu ioctls from the same thread that was used to create the vcpu.
So it isn't just me.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 3/9 qemu-kvm: Use upstream kvm_enabled and cpu_synchronize_state
In reply to Jan KiszkaThey are identical, no need for private copies. This requires replacing qemu-kvm.h includes with kvm.h, a good thing anyway, and reveals that there is no need for QEMU_KVM_NO_CPU protection.
--- hw/i8254.c | 2 +- hw/i8259.c | 2 +- hw/ioapic.c | 2 +- hw/msix.c | 3 +-- hw/pc.c | 2 +- hw/piix_pci.c | 2 +- kvm.h | 7 +++---- qemu-kvm.h | 41 ----------------------------------------- vl.c | 3 ++- 9 files changed, 11 insertions(+), 53 deletions(-)
hw/i8254.c +1 -1
@@ -25,7 +25,7 @@#include "pc.h" #include "isa.h" #include "qemu-timer.h" -#include "qemu-kvm.h" +#include "kvm.h" #include "i8254.h" //#define DEBUG_PIT
hw/i8259.c +1 -1
@@ -27,7 +27,7 @@#include "monitor.h" #include "qemu-timer.h" -#include "qemu-kvm.h" +#include "kvm.h" /* debug PIC */ //#define DEBUG_PIC
hw/ioapic.c +1 -1
@@ -26,7 +26,7 @@#include "qemu-timer.h" #include "host-utils.h" -#include "qemu-kvm.h" +#include "kvm.h" //#define DEBUG_IOAPIC
hw/msix.c +1 -2
@@ -14,8 +14,7 @@#include "hw.h" #include "msix.h" #include "pci.h" -#define QEMU_KVM_NO_CPU -#include "qemu-kvm.h" +#include "kvm.h" /* Declaration from linux/pci_regs.h */ #define PCI_CAP_ID_MSIX 0x11/* MSI-X */
hw/pc.c +1 -1
@@ -47,7 +47,7 @@#include "multiboot.h" #include "device-assignment.h" -#include "qemu-kvm.h" +#include "kvm.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS
hw/piix_pci.c +1 -1
@@ -28,7 +28,7 @@#include "pci_host.h" #include "isa.h" #include "sysbus.h" -#include "qemu-kvm.h" +#include "kvm.h" /* * I440FX chipset data sheet.
kvm.h +3 -4
@@ -18,8 +18,6 @@#include "qemu-queue.h" #include "qemu-kvm.h" -#ifdef KVM_UPSTREAM -#ifdef CONFIG_KVM extern int kvm_allowed;
@@ -28,6 +26,7 @@ extern int kvm_allowed;#define kvm_enabled () (0)#endif +#ifdef KVM_UPSTREAM struct kvm_run ;/* external API */
@@ -133,6 +132,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension);uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function,int reg); +#endif +void kvm_cpu_synchronize_state (CPUState *env);/* generic hooks - to be moved/refactored once there are more users */
@@ -145,5 +146,3 @@ static inline void cpu_synchronize_state(CPUState *env) }#endif - -#endif
qemu-kvm.h +0 -41
156 lines not on this page · raw message
vl.c +2 -1
@@ -157,7 +157,6 @@ int main(int argc, char **argv)#include "qemu-option.h" #include "qemu-config.h" #include "qemu-objects.h" -#include "qemu-kvm.h" #include "hw/device-assignment.h" #include "disas.h"
@@ -5825,8 +5824,10 @@ int main(int argc, char **argv, char **envp)fprintf (stderr,"failed to initialize KVM\n" );exit (1 );#endif +#ifdef CONFIG_KVM fprintf (stderr,"Could not initialize KVM, will disable KVM support\n" ); kvm_allowed =0 ; +#endif } }
Signature · 1 line
1.6.0.2
PATCH 4/9 qemu-kvm: Use upstream kvm_setup_guest_memory
In reply to Jan KiszkaNothing missing in upstream kvm_setup_guest_memory, it is even more careful about error handling.
--- kvm-all.c | 3 --- kvm.h | 3 +-- qemu-kvm.c | 15 --------------- qemu-kvm.h | 1 - 4 files changed, 1 insertions(+), 21 deletions(-)
kvm-all.c +0 -3
@@ -932,7 +932,6 @@ int kvm_has_vcpu_events(void)return kvm_state->vcpu_events; } -#ifdef KVM_UPSTREAM void kvm_setup_guest_memory (void *start,size_t size) {if (!kvm_has_sync_mmu ()) {
@@ -951,8 +950,6 @@ void kvm_setup_guest_memory(void *start, size_t size) } } -#endif /* KVM_UPSTREAM */ -#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef KVM_UPSTREAM
kvm.h +1 -2
@@ -48,10 +48,9 @@ int kvm_get_vcpu_events(CPUState *env);void kvm_cpu_register_phys_memory_client (void ); -#ifdef KVM_UPSTREAM -void kvm_setup_guest_memory (void *start,size_t size); +#ifdef KVM_UPSTREAM int kvm_coalesce_mmio_region (target_phys_addr_t start,ram_addr_t size);int kvm_uncoalesce_mmio_region (target_phys_addr_t start,ram_addr_t size);void kvm_flush_coalesced_mmio_buffer (void );
qemu-kvm.c +0 -15
@@ -2315,21 +2315,6 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,return ; } -int kvm_setup_guest_memory (void *area,unsigned long size) -{ -int ret =0 ; - -#ifdef MADV_DONTFORK -if (kvm_enabled () && !kvm_has_sync_mmu ()) - ret =madvise (area, size,MADV_DONTFORK ); -#endif - -if (ret) -perror ("madvise" ); - -return ret; -} -#ifdef KVM_CAP_SET_GUEST_DEBUG struct kvm_set_guest_debug_data {
qemu-kvm.h +0 -1
@@ -923,7 +923,6 @@ void kvm_cpu_destroy_phys_mem(target_phys_addr_t start_addr, unsigned long size);void kvm_qemu_log_memory (target_phys_addr_t start,target_phys_addr_t size,int log); -int kvm_setup_guest_memory (void *area,unsigned long size);int kvm_qemu_create_memory_alias (uint64_t phys_start,uint64_t len,uint64_t target_phys);int kvm_qemu_destroy_memory_alias (uint64_t phys_start);
Signature · 1 line
1.6.0.2
PATCH 5/9 qemu-kvm: Use some more upstream prototypes
In reply to Jan KiszkaDrop our private typedef of KVMState and use more identical upstream prototypes.
--- kvm.h | 8 +++++--- qemu-kvm.c | 4 +++- qemu-kvm.h | 28 +++------------------------- 3 files changed, 11 insertions(+), 29 deletions(-)
kvm.h +5 -3
@@ -32,6 +32,7 @@ struct kvm_run;/* external API */ int kvm_init (int smp_cpus); +#endif /* KVM_UPSTREAM */ int kvm_init_vcpu (CPUState *env);
@@ -41,7 +42,6 @@ int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size);int kvm_log_stop (target_phys_addr_t phys_addr,ram_addr_t size);int kvm_has_sync_mmu (void ); -#endif /* KVM_UPSTREAM */ int kvm_has_vcpu_events (void );int kvm_put_vcpu_events (CPUState *env);int kvm_get_vcpu_events (CPUState *env);
@@ -50,11 +50,11 @@ void kvm_cpu_register_phys_memory_client(void);void kvm_setup_guest_memory (void *start,size_t size); -#ifdef KVM_UPSTREAM int kvm_coalesce_mmio_region (target_phys_addr_t start,ram_addr_t size);int kvm_uncoalesce_mmio_region (target_phys_addr_t start,ram_addr_t size);void kvm_flush_coalesced_mmio_buffer (void ); +#ifdef KVM_UPSTREAM int kvm_insert_breakpoint (CPUState *current_env,target_ulong addr,target_ulong len,int type); int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
@@ -64,6 +64,7 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);int kvm_pit_in_kernel (void );int kvm_irqchip_in_kernel (void ); +#endif /* KVM_UPSTREAM */ /* internal API */
@@ -92,7 +93,6 @@ int kvm_arch_init(KVMState *s, int smp_cpus);int kvm_arch_init_vcpu (CPUState *env); -#endif void kvm_arch_reset_vcpu (CPUState *env);#ifdef KVM_UPSTREAM
@@ -126,9 +126,11 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,void kvm_arch_remove_all_hw_breakpoints (void );void kvm_arch_update_guest_debug (CPUState *env,struct kvm_guest_debug *dbg); +#endif int kvm_check_extension (KVMState *s,unsigned int extension); +#ifdef KVM_UPSTREAM uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function,int reg);#endif
qemu-kvm.c +3 -1
@@ -1919,12 +1919,14 @@ static void *ap_main_loop(void *_env)return NULL ; } -void kvm_init_vcpu (CPUState *env) +int kvm_init_vcpu (CPUState *env) {pthread_create (&env->kvm_cpu_state.thread,NULL , ap_main_loop, env);while (env->created ==0 )qemu_cond_wait (&qemu_vcpu_cond); + +return 0 ; }int kvm_vcpu_inited (CPUState *env)
qemu-kvm.h +3 -25
@@ -891,7 +891,6 @@ int kvm_init_ap(void);int kvm_vcpu_inited (CPUState *env);void kvm_load_mpstate (CPUState *env);void kvm_save_mpstate (CPUState *env); -int kvm_cpu_exec (CPUState *env);int kvm_insert_breakpoint (CPUState * current_env,target_ulong addr,target_ulong len,int type); int kvm_remove_breakpoint(CPUState * current_env, target_ulong addr,
@@ -933,9 +932,6 @@ void kvm_arch_save_regs(CPUState *env);void kvm_arch_load_regs (CPUState *env);void kvm_arch_load_mpstate (CPUState *env);void kvm_arch_save_mpstate (CPUState *env); -int kvm_arch_init_vcpu (CPUState *cenv); -int kvm_arch_pre_run (CPUState *env,struct kvm_run *run); -int kvm_arch_post_run (CPUState *env,struct kvm_run *run);int kvm_arch_has_work (CPUState *env);void kvm_arch_process_irqchip_events (CPUState *env);int kvm_arch_try_push_interrupts (void *opaque);
@@ -981,9 +977,6 @@ void kvm_tpr_access_report(CPUState *env, uint64_t rip, int is_write);void kvm_tpr_vcpu_start (CPUState *env);int qemu_kvm_get_dirty_pages (unsigned long phys_addr,void *buf); -int kvm_coalesce_mmio_region (target_phys_addr_t start,ram_addr_t size); -int kvm_uncoalesce_mmio_region (target_phys_addr_t start,ram_addr_t size); -void kvm_flush_coalesced_mmio_buffer (void );int kvm_arch_init_irq_routing (void );
@@ -1022,17 +1015,14 @@ void qemu_kvm_cpu_stop(CPUState *env);int kvm_arch_halt (CPUState *env);int handle_tpr_access (void *opaque,CPUState *env,uint64_t rip,int is_write); -int kvm_has_sync_mmu (void );#define qemu_kvm_pit_in_kernel () kvm_pit_in_kernel(kvm_context)#define qemu_kvm_has_gsi_routing () kvm_has_gsi_routing(kvm_context)#ifdef TARGET_I386 #define qemu_kvm_has_pit_state2 () kvm_has_pit_state2(kvm_context)#endif -void kvm_init_vcpu (CPUState *env);void kvm_load_tsc (CPUState *env);#else -#define kvm_has_sync_mmu () (0)#define kvm_nested 0#define qemu_kvm_pit_in_kernel () (0)#define qemu_kvm_has_gsi_routing () (0)
@@ -1041,10 +1031,6 @@ void kvm_load_tsc(CPUState *env);#endif #define kvm_save_mpstate (env) do {} while(0)#define qemu_kvm_cpu_stop (env) do {} while(0) -static inline void kvm_init_vcpu (CPUState *env) -{ -} -static inline void kvm_load_tsc (CPUState *env) { }
@@ -1056,9 +1042,6 @@ void kvm_mutex_lock(void);int kvm_physical_sync_dirty_bitmap (target_phys_addr_t start_addr,target_phys_addr_t end_addr); -int kvm_log_start (target_phys_addr_t phys_addr,target_phys_addr_t len); -int kvm_log_stop (target_phys_addr_t phys_addr,target_phys_addr_t len); -static inline int kvm_sync_vcpus (void ) {
@@ -1087,7 +1070,7 @@ typedef struct KVMSlot {typedef struct kvm_dirty_log KVMDirtyLog ; -typedef struct KVMState { +struct KVMState {KVMSlot slots[32 ];int fd;int vmfd;
@@ -1104,14 +1087,9 @@ typedef struct KVMState {int irqchip_in_kernel;struct kvm_context kvm_context; -} KVMState; - -extern KVMState *kvm_state; +}; -int kvm_ioctl (KVMState *s,int type, ...); -int kvm_vm_ioctl (KVMState *s,int type, ...); -int kvm_vcpu_ioctl (CPUState *env,int type, ...); -int kvm_check_extension (KVMState *s,unsigned int ext); +extern struct KVMState *kvm_state;int kvm_tpr_enable_vapic (CPUState *env);
Signature · 1 line
1.6.0.2
PATCH 6/9 qemu-kvm: Use upstream kvm_arch_get_supported_cpuid
In reply to Jan KiszkaIt is idential to our version now, so drop the copy.
--- kvm.h | 3 - qemu-kvm-x86.c | 106 ----------------------------------------------------- qemu-kvm.h | 5 -- target-i386/kvm.c | 4 +- 4 files changed, 2 insertions(+), 116 deletions(-)
kvm.h +0 -3
@@ -130,11 +130,8 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);int kvm_check_extension (KVMState *s,unsigned int extension); -#ifdef KVM_UPSTREAM uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function,int reg); -#endif -void kvm_cpu_synchronize_state (CPUState *env);/* generic hooks - to be moved/refactored once there are more users */
qemu-kvm-x86.c +0 -106
118 lines not on this page · raw message
qemu-kvm.h +0 -5
@@ -859,8 +859,6 @@ int kvm_assign_set_msix_entry(kvm_context_t kvm, struct kvm_assigned_msix_entry *entry);#endif -uint32_t kvm_get_supported_cpuid (kvm_context_t kvm,uint32_t function,int reg); -#else /* !CONFIG_KVM */ typedef struct kvm_context *kvm_context_t ;
@@ -1048,9 +1046,6 @@ static inline int kvm_sync_vcpus(void)return 0 ; } -uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function, -int reg); -static inline int kvm_set_migration_log (int enable) {return kvm_physical_memory_set_dirty_tracking (enable);
target-i386/kvm.c +2 -2
@@ -25,8 +25,6 @@#include "gdbstub.h" #include "host-utils.h" -#ifdef KVM_UPSTREAM -#ifdef CONFIG_KVM_PARA #include <linux/kvm_para.h> #endif
@@ -133,6 +131,8 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)#endif +#ifdef KVM_UPSTREAM +static void kvm_trim_features (uint32_t *features,uint32_t supported) {int i;
Signature · 1 line
1.6.0.2
PATCH 7/9 qemu-kvm: Use upstream kvm_pit_in_kernel
In reply to Jan KiszkaDrop private version in favor of recently added upstream service and track it state directly in KVMState.
--- hw/i8254.c | 4 ++-- hw/pc.c | 2 +- hw/pcspk.c | 4 ++-- kvm-all.c | 2 +- kvm.h | 2 +- qemu-kvm-x86.c | 12 ++++++------ qemu-kvm.c | 5 ----- qemu-kvm.h | 13 +------------ 8 files changed, 14 insertions(+), 30 deletions(-)
hw/i8254.c +2 -2
@@ -491,7 +491,7 @@ void hpet_disable_pit(void) {PITChannelState *s = &pit_state.channels[0 ]; -if (kvm_enabled () &&qemu_kvm_pit_in_kernel ()) { +if (kvm_enabled () &&kvm_pit_in_kernel ()) {if (qemu_kvm_has_pit_state2 ()) {kvm_hpet_disable_kpit (); }else {
@@ -515,7 +515,7 @@ void hpet_enable_pit(void)PITState *pit = &pit_state;PITChannelState *s = &pit->channels[0 ]; -if (kvm_enabled () &&qemu_kvm_pit_in_kernel ()) { +if (kvm_enabled () &&kvm_pit_in_kernel ()) {if (qemu_kvm_has_pit_state2 ()) {kvm_hpet_enable_kpit (); }else {
hw/pc.c +1 -1
@@ -950,7 +950,7 @@ static void pc_init1(ram_addr_t ram_size, ioapic_irq_hack = isa_irq; }#ifdef CONFIG_KVM_PIT -if (kvm_enabled () &&qemu_kvm_pit_in_kernel ()) +if (kvm_enabled () &&kvm_pit_in_kernel ()) pit =kvm_pit_init (0x40 ,isa_reserve_irq (0 )); else#endif
hw/pcspk.c +2 -2
@@ -56,7 +56,7 @@ static void kvm_get_pit_ch2(PITState *pit, {struct kvm_pit_state pit_state; -if (kvm_enabled () &&qemu_kvm_pit_in_kernel ()) { +if (kvm_enabled () &&kvm_pit_in_kernel ()) {kvm_get_pit (kvm_context, &pit_state); pit->channels[2 ].mode = pit_state.channels[2 ].mode; pit->channels[2 ].count = pit_state.channels[2 ].count;
@@ -71,7 +71,7 @@ static void kvm_get_pit_ch2(PITState *pit,static void kvm_set_pit_ch2 (PITState *pit,struct kvm_pit_state *inkernel_state) { -if (kvm_enabled () &&qemu_kvm_pit_in_kernel ()) { +if (kvm_enabled () &&kvm_pit_in_kernel ()) { inkernel_state->channels[2 ].mode = pit->channels[2 ].mode; inkernel_state->channels[2 ].count = pit->channels[2 ].count; inkernel_state->channels[2].count_load_time =
kvm-all.c +1 -1
@@ -167,13 +167,13 @@ int kvm_irqchip_in_kernel(void)return kvm_state->irqchip_in_kernel; } -#ifdef KVM_UPSTREAM int kvm_pit_in_kernel (void ) {return kvm_state->pit_in_kernel; } +#ifdef KVM_UPSTREAM int kvm_init_vcpu (CPUState *env) {KVMState *s = kvm_state;
kvm.h +1 -1
@@ -61,10 +61,10 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr, target_ulong len, int type);void kvm_remove_all_breakpoints (CPUState *current_env);int kvm_update_guest_debug (CPUState *env,unsigned long reinject_trap); +#endif /* KVM_UPSTREAM */ int kvm_pit_in_kernel (void );int kvm_irqchip_in_kernel (void ); -#endif /* KVM_UPSTREAM */ /* internal API */
qemu-kvm-x86.c +6 -6
@@ -119,13 +119,13 @@ static int kvm_create_pit(kvm_context_t kvm)#ifdef KVM_CAP_PIT int r; - kvm->pit_in_kernel =0 ; + kvm_state->pit_in_kernel =0 ;if (!kvm->no_pit_creation) { r =kvm_ioctl (kvm_state,KVM_CHECK_EXTENSION ,KVM_CAP_PIT );if (r >0 ) { r =kvm_vm_ioctl (kvm_state,KVM_CREATE_PIT );if (r >=0 ) - kvm->pit_in_kernel =1 ; + kvm_state->pit_in_kernel =1 ;else {fprintf (stderr,"Create kernel PIC irqchip failed\n" );return r;
@@ -311,14 +311,14 @@ int kvm_set_lapic(CPUState *env, struct kvm_lapic_state *s)int kvm_get_pit (kvm_context_t kvm,struct kvm_pit_state *s) { -if (!kvm->pit_in_kernel) +if (!kvm_pit_in_kernel ())return 0 ;return kvm_vm_ioctl (kvm_state,KVM_GET_PIT , s); }int kvm_set_pit (kvm_context_t kvm,struct kvm_pit_state *s) { -if (!kvm->pit_in_kernel) +if (!kvm_pit_in_kernel ())return 0 ;return kvm_vm_ioctl (kvm_state,KVM_SET_PIT , s); }
@@ -326,14 +326,14 @@ int kvm_set_pit(kvm_context_t kvm, struct kvm_pit_state *s)#ifdef KVM_CAP_PIT_STATE2 int kvm_get_pit2 (kvm_context_t kvm,struct kvm_pit_state2 *ps2) { -if (!kvm->pit_in_kernel) +if (!kvm_pit_in_kernel ())return 0 ;return kvm_vm_ioctl (kvm_state,KVM_GET_PIT2 , ps2); }int kvm_set_pit2 (kvm_context_t kvm,struct kvm_pit_state2 *ps2) { -if (!kvm->pit_in_kernel) +if (!kvm_pit_in_kernel ())return 0 ;return kvm_vm_ioctl (kvm_state,KVM_SET_PIT2 , ps2); }
qemu-kvm.c +0 -5
@@ -1049,11 +1049,6 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)return r; } -int kvm_pit_in_kernel (kvm_context_t kvm) -{ -return kvm->pit_in_kernel; -} -int kvm_inject_nmi (CPUState *env) {#ifdef KVM_CAP_USER_NMI
qemu-kvm.h +1 -12
@@ -64,8 +64,6 @@ struct kvm_context {int irqchip_inject_ioctl;/// do not create in-kernel pit if set int no_pit_creation; -/// in-kernel pit status -int pit_in_kernel;#ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes;int nr_allocated_irq_routes;
@@ -563,13 +561,6 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, int abort_on_error);/*! -* \brief Query wheather in kernel pit is used -* -* \param kvm Pointer to the current kvm_context -*/ -int kvm_pit_in_kernel (kvm_context_t kvm); - -/*! * \brief Initialize coalesced MMIO * * Check for coalesced MMIO capability and store in context
@@ -1014,7 +1005,6 @@ int kvm_arch_halt(CPUState *env);int handle_tpr_access (void *opaque,CPUState *env,uint64_t rip,int is_write); -#define qemu_kvm_pit_in_kernel () kvm_pit_in_kernel(kvm_context)#define qemu_kvm_has_gsi_routing () kvm_has_gsi_routing(kvm_context)#ifdef TARGET_I386 #define qemu_kvm_has_pit_state2 () kvm_has_pit_state2(kvm_context)
@@ -1022,7 +1012,6 @@ int handle_tpr_access(void *opaque, CPUState *env, uint64_t rip,void kvm_load_tsc (CPUState *env);#else #define kvm_nested 0 -#define qemu_kvm_pit_in_kernel () (0)#define qemu_kvm_has_gsi_routing () (0)#ifdef TARGET_I386 #define qemu_kvm_has_pit_state2 () (0)
@@ -1052,7 +1041,6 @@ static inline int kvm_set_migration_log(int enable) } -int kvm_irqchip_in_kernel (void ); #ifdef CONFIG_KVM typedef struct KVMSlot {
@@ -1080,6 +1068,7 @@ struct KVMState { QTAILQ_HEAD(, kvm_sw_breakpoint) kvm_sw_breakpoints;#endif int irqchip_in_kernel; +int pit_in_kernel;struct kvm_context kvm_context; };
Signature · 1 line
1.6.0.2
PATCH 8/9 KVM: Rework of guest debug state writing
In reply to Jan KiszkaSo far we synchronized any dirty VCPU state back into the kernel before updating the guest debug state. This was a tribute to a deficite in x86 kernels before 2.6.33. But as this is an arch-dependent issue, it is better handle in the x86 part of KVM and remove the writeback point for generic code. This also avoids overwriting the flushed state later on if user space decides to change some more registers before resuming the guest.
We furthermore need to reinject guest exceptions via the appropriate mechanism. That is KVM_SET_GUEST_DEBUG for older kernels and KVM_SET_VCPU_EVENTS for recent ones. Using both mechanisms at the same time will cause state corruptions.
--- kvm-all.c | 12 ++++-------- target-i386/kvm.c | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 12 deletions(-)
kvm-all.c +4 -8
@@ -994,10 +994,6 @@ static void kvm_invoke_set_guest_debug(void *data)struct kvm_set_guest_debug_data *dbg_data = data;CPUState *env = dbg_data->env; -if (env->kvm_vcpu_dirty) { -kvm_arch_put_registers (env); - env->kvm_vcpu_dirty =0 ; - } dbg_data->err =kvm_vcpu_ioctl (env,KVM_SET_GUEST_DEBUG , &dbg_data->dbg); }
@@ -1005,12 +1001,12 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap) {struct kvm_set_guest_debug_data data; - data.dbg.control =0 ; -if (env->singlestep_enabled) - data.dbg.control =KVM_GUESTDBG_ENABLE |KVM_GUESTDBG_SINGLESTEP ; + data.dbg.control = reinject_trap; +if (env->singlestep_enabled) { + data.dbg.control |=KVM_GUESTDBG_ENABLE |KVM_GUESTDBG_SINGLESTEP ; + }kvm_arch_update_guest_debug (env, &data.dbg); - data.dbg.control |= reinject_trap; data.env = env;on_vcpu (env, kvm_invoke_set_guest_debug, &data);
target-i386/kvm.c +33 -4
@@ -885,6 +885,32 @@ int kvm_arch_put_registers(CPUState *env)if (ret <0 )return ret; +/* +* Kernels before 2.6.33 (which correlates with !kvm_has_vcpu_events()) +* overwrote flags.TF injected via SET_GUEST_DEBUG while updating GP regs. +* Work around this by updating the debug state once again if +* single-stepping is on. +* Another reason to call kvm_update_guest_debug here is a pending debug +* trap raise by the guest. On kernels without SET_VCPU_EVENTS we have to +* reinject them via SET_GUEST_DEBUG. +*/ +if (!kvm_has_vcpu_events () && + (env->exception_injected !=-1 || env->singlestep_enabled)) { +unsigned long reinject_trap =0 ; + +if (env->exception_injected ==1 ) { + reinject_trap =KVM_GUESTDBG_INJECT_DB ; + }else if (env->exception_injected ==3 ) { + reinject_trap =KVM_GUESTDBG_INJECT_BP ; + } + env->exception_injected =-1 ; + + ret =kvm_update_guest_debug (env, reinject_trap); +if (ret <0 ) { +return ret; + } + } +return 0 ; }
@@ -1130,10 +1156,13 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info) }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 ); +if (!handle) { +cpu_synchronize_state (cpu_single_env); +assert (cpu_single_env->exception_injected ==-1 ); + + cpu_single_env->exception_injected = arch_info->exception; + cpu_single_env->has_error_code =0 ; + }return handle; }
Signature · 1 line
1.6.0.2
Re: [PATCH 8/9] KVM: Rework of guest debug state writing
Quoted 8 lines · Jan Kiszka
So far we synchronized any dirty VCPU state back into the kernel before updating the guest debug state. This was a tribute to a deficite in x86 kernels before 2.6.33. But as this is an arch-dependent issue, it is better handle in the x86 part of KVM and remove the writeback point for generic code. This also avoids overwriting the flushed state later on if user space decides to change some more registers before resuming the guest.
Inferring one property of kvm.ko from another is not good, since it creates problems with backports. Better to create a separate KVM_CAP_ for the issue you're testing (and we can retroactively apply it to 2.6.33).
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 9/9 qemu-kvm: Use upstream guest debug code
In reply to Jan KiszkaCode was absolute identical except for previous fixes and cleanup in upstream.
--- kvm-all.c | 7 +- kvm.h | 4 - qemu-kvm-x86.c | 197 +++++++---------------------------------------------- qemu-kvm.c | 44 ------------ qemu-kvm.h | 37 ---------- target-i386/kvm.c | 2 +- 6 files changed, 30 insertions(+), 261 deletions(-)
kvm-all.c +3 -4
@@ -962,7 +962,9 @@ static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)#endif func(data); } -#endif /* KVM_UPSTREAM */ +#else /* !KVM_UPSTREAM */ +static void on_vcpu (CPUState *env,void (*func)(void *data),void *data); +#endif /* !KVM_UPSTREAM */ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint (CPUState *env,target_ulong pc)
@@ -981,8 +983,6 @@ int kvm_sw_breakpoints_active(CPUState *env)return !QTAILQ_EMPTY (&env->kvm_state->kvm_sw_breakpoints); } -#ifdef KVM_UPSTREAM -struct kvm_set_guest_debug_data {struct kvm_guest_debug dbg;CPUState *env;
@@ -1012,7 +1012,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)on_vcpu (env, kvm_invoke_set_guest_debug, &data);return data.err; } -#endif int kvm_insert_breakpoint (CPUState *current_env,target_ulong addr,target_ulong len,int type)
kvm.h +0 -4
@@ -54,14 +54,12 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);int kvm_uncoalesce_mmio_region (target_phys_addr_t start,ram_addr_t size);void kvm_flush_coalesced_mmio_buffer (void ); -#ifdef KVM_UPSTREAM int kvm_insert_breakpoint (CPUState *current_env,target_ulong addr,target_ulong len,int type);int kvm_remove_breakpoint (CPUState *current_env,target_ulong addr,target_ulong len,int type);void kvm_remove_all_breakpoints (CPUState *current_env);int kvm_update_guest_debug (CPUState *env,unsigned long reinject_trap); -#endif /* KVM_UPSTREAM */ int kvm_pit_in_kernel (void );int kvm_irqchip_in_kernel (void );
@@ -94,7 +92,6 @@ int kvm_arch_init(KVMState *s, int smp_cpus);int kvm_arch_init_vcpu (CPUState *env);void kvm_arch_reset_vcpu (CPUState *env); -#ifdef KVM_UPSTREAM struct kvm_guest_debug ;struct kvm_debug_exit_arch ;
@@ -126,7 +123,6 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,void kvm_arch_remove_all_hw_breakpoints (void );void kvm_arch_update_guest_debug (CPUState *env,struct kvm_guest_debug *dbg); -#endif int kvm_check_extension (KVMState *s,unsigned int extension);
qemu-kvm-x86.c +26 -171
209 lines not on this page · raw message
qemu-kvm.c +0 -44
56 lines not on this page · raw message
qemu-kvm.h +0 -37
@@ -323,10 +323,6 @@ static inline int kvm_reset_mpstate(CPUState *env)*/ int kvm_inject_irq (CPUState *env,unsigned irq); -#ifdef KVM_CAP_SET_GUEST_DEBUG -int kvm_set_guest_debug (CPUState *env,struct kvm_guest_debug *dbg); -#endif -#if defined(__i386__) || defined(__x86_64__)/*! * \brief Setup a vcpu's cpuid instruction emulation
@@ -880,12 +876,6 @@ int kvm_init_ap(void);int kvm_vcpu_inited (CPUState *env);void kvm_load_mpstate (CPUState *env);void kvm_save_mpstate (CPUState *env); -int kvm_insert_breakpoint (CPUState * current_env,target_ulong addr, -target_ulong len,int type); -int kvm_remove_breakpoint (CPUState * current_env,target_ulong addr, -target_ulong len,int type); -void kvm_remove_all_breakpoints (CPUState * current_env); -int kvm_update_guest_debug (CPUState *env,unsigned long reinject_trap);void kvm_apic_init (CPUState *env);/* called from vcpu initialization */ void qemu_kvm_load_lapic (CPUState *env);
@@ -928,33 +918,6 @@ void kvm_arch_push_nmi(void *opaque);void kvm_arch_cpu_reset (CPUState *env);int kvm_set_boot_cpu_id (uint32_t id); -struct kvm_guest_debug ; -struct kvm_debug_exit_arch ; - -struct kvm_sw_breakpoint { -target_ulong pc; -target_ulong saved_insn; -int use_count; -QTAILQ_ENTRY (kvm_sw_breakpoint) entry; -}; - -QTAILQ_HEAD (kvm_sw_breakpoint_head, kvm_sw_breakpoint); - -int kvm_arch_debug (struct kvm_debug_exit_arch *arch_info); -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, -struct kvm_sw_breakpoint *bp); -int kvm_arch_insert_hw_breakpoint (target_ulong addr,target_ulong len, -int type); -int kvm_arch_remove_hw_breakpoint (target_ulong addr,target_ulong len, -int type); -void kvm_arch_remove_all_hw_breakpoints (void ); -void kvm_arch_update_guest_debug (CPUState *env,struct kvm_guest_debug *dbg); -void qemu_kvm_aio_wait_start (void );void qemu_kvm_aio_wait (void );void qemu_kvm_aio_wait_end (void );
target-i386/kvm.c +1 -1
@@ -1020,6 +1020,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) return ret; } +#endif #ifdef KVM_CAP_SET_GUEST_DEBUG int kvm_arch_insert_sw_breakpoint (CPUState *env,struct kvm_sw_breakpoint *bp)
@@ -1194,6 +1195,5 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg) } }#endif /* KVM_CAP_SET_GUEST_DEBUG */ -#endif #include "qemu-kvm-x86.c"
Signature · 1 line
1.6.0.2
Avi Kivity
AppliedQuoted 10 lines · Jan Kiszka
Spin-off from my longer series as Marcelo asked for the last patch as the next step. I don't see any value in reordering the series, so I just but off the lower bits.
This part mostly cleans up common KVM code that is also present upstream. It also includes the fixed guest debug writeback, first for upstream (patch 8 should be queued into uq/master as well), then merged into qemu-kvm while dropping the qemu-kvm copy of the guest debugging code.
Quoted 7 lines
The differences to previous postings of the full series are:
- rebased over qemu-kvm
- fixed guest state writeback to avoid conflicts withSET_VCPU_EVENTS, rather use them on modern kernels (I know Gleb will hate me for this, but I'm convinced it's cleaner that way)
Applied all, some issues pointed out as reply to individual patch.
Signature · 1 line
error compiling committee.c: too many arguments to function