From patchwork Thu Dec 20 18:28:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Adalbert_Laz=C4=83r?= X-Patchwork-Id: 10739301 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2E5CA13B5 for ; Thu, 20 Dec 2018 18:36:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1A92E28F35 for ; Thu, 20 Dec 2018 18:36:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0F35128F3A; Thu, 20 Dec 2018 18:36:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 98C1828F35 for ; Thu, 20 Dec 2018 18:36:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389335AbeLTSgG (ORCPT ); Thu, 20 Dec 2018 13:36:06 -0500 Received: from mx01.bbu.dsd.mx.bitdefender.com ([91.199.104.161]:44324 "EHLO mx01.bbu.dsd.mx.bitdefender.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389306AbeLTSgG (ORCPT ); Thu, 20 Dec 2018 13:36:06 -0500 Received: from smtp.bitdefender.com (smtp02.buh.bitdefender.net [10.17.80.76]) by mx01.bbu.dsd.mx.bitdefender.com (Postfix) with ESMTPS id 72C9F305FFB1; Thu, 20 Dec 2018 20:29:37 +0200 (EET) Received: from host.bbu.bitdefender.biz (unknown [10.10.193.111]) by smtp.bitdefender.com (Postfix) with ESMTPSA id 699A9306E47C; Thu, 20 Dec 2018 20:29:37 +0200 (EET) From: =?utf-8?q?Adalbert_Laz=C4=83r?= To: kvm@vger.kernel.org Cc: Paolo Bonzini , =?utf-8?b?UmFkaW0gS3LEjW3DocWZ?= , =?utf-8?q?Mihai_Don?= =?utf-8?q?=C8=9Bu?= , =?utf-8?q?Adalbert_Laz=C4=83r?= , =?utf-8?b?Tmlj?= =?utf-8?b?dciZb3IgQ8OuyJt1?= , =?utf-8?q?Mircea_C?= =?utf-8?q?=C3=AErjaliu?= , Marian Rotariu Subject: [RFC PATCH v5 04/20] kvm: add the VM introspection API/ABI headers Date: Thu, 20 Dec 2018 20:28:34 +0200 Message-Id: <20181220182850.4579-5-alazar@bitdefender.com> In-Reply-To: <20181220182850.4579-1-alazar@bitdefender.com> References: <20181220182850.4579-1-alazar@bitdefender.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mihai DONTU And more KVM_E* error codes in kvm_para.h Signed-off-by: Mihai Donțu Signed-off-by: Adalbert Lazăr Signed-off-by: Nicușor Cîțu Signed-off-by: Mircea Cîrjaliu Signed-off-by: Marian Rotariu --- arch/x86/include/uapi/asm/kvmi.h | 234 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 12 ++ include/uapi/linux/kvm_para.h | 11 +- include/uapi/linux/kvmi.h | 192 +++++++++++++++++++++++++ 4 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 arch/x86/include/uapi/asm/kvmi.h create mode 100644 include/uapi/linux/kvmi.h diff --git a/arch/x86/include/uapi/asm/kvmi.h b/arch/x86/include/uapi/asm/kvmi.h new file mode 100644 index 000000000000..d114f82bc070 --- /dev/null +++ b/arch/x86/include/uapi/asm/kvmi.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_X86_KVMI_H +#define _UAPI_ASM_X86_KVMI_H + +/* + * KVMI x86 specific structures and definitions + * + */ + +#include +#include + +#define KVMI_EVENT_UNHOOK 0 +#define KVMI_EVENT_CR 1 /* control register was modified */ +#define KVMI_EVENT_MSR 2 /* model specific reg. was modified */ +#define KVMI_EVENT_XSETBV 3 /* ext. control register was modified */ +#define KVMI_EVENT_BREAKPOINT 4 /* breakpoint was reached */ +#define KVMI_EVENT_HYPERCALL 5 /* user hypercall */ +#define KVMI_EVENT_PF 6 /* hyp. page fault was encountered */ +#define KVMI_EVENT_TRAP 7 /* trap was injected */ +#define KVMI_EVENT_DESCRIPTOR 8 /* descriptor table access */ +#define KVMI_EVENT_CREATE_VCPU 9 +#define KVMI_EVENT_PAUSE_VCPU 10 +/* TODO: find a way to split the events between common and arch dependent */ +#define KVMI_NUM_EVENTS 11 /* increment with each added event */ + +#define KVMI_EVENT_UNHOOK_FLAG (1 << KVMI_EVENT_UNHOOK) +#define KVMI_EVENT_CR_FLAG (1 << KVMI_EVENT_CR) +#define KVMI_EVENT_MSR_FLAG (1 << KVMI_EVENT_MSR) +#define KVMI_EVENT_XSETBV_FLAG (1 << KVMI_EVENT_XSETBV) +#define KVMI_EVENT_BREAKPOINT_FLAG (1 << KVMI_EVENT_BREAKPOINT) +#define KVMI_EVENT_HYPERCALL_FLAG (1 << KVMI_EVENT_HYPERCALL) +#define KVMI_EVENT_PF_FLAG (1 << KVMI_EVENT_PF) +#define KVMI_EVENT_TRAP_FLAG (1 << KVMI_EVENT_TRAP) +#define KVMI_EVENT_DESCRIPTOR_FLAG (1 << KVMI_EVENT_DESCRIPTOR) +#define KVMI_EVENT_CREATE_VCPU_FLAG (1 << KVMI_EVENT_CREATE_VCPU) +#define KVMI_EVENT_PAUSE_VCPU_FLAG (1 << KVMI_EVENT_PAUSE_VCPU) + +#define KVMI_EVENT_ACTION_CONTINUE 0 +#define KVMI_EVENT_ACTION_RETRY 1 +#define KVMI_EVENT_ACTION_CRASH 2 + +#define KVMI_KNOWN_VCPU_EVENTS ( \ + KVMI_EVENT_CR_FLAG | \ + KVMI_EVENT_MSR_FLAG | \ + KVMI_EVENT_XSETBV_FLAG | \ + KVMI_EVENT_BREAKPOINT_FLAG | \ + KVMI_EVENT_HYPERCALL_FLAG | \ + KVMI_EVENT_PF_FLAG | \ + KVMI_EVENT_TRAP_FLAG | \ + KVMI_EVENT_DESCRIPTOR_FLAG | \ + KVMI_EVENT_PAUSE_VCPU_FLAG) + +#define KVMI_KNOWN_VM_EVENTS ( \ + KVMI_EVENT_CREATE_VCPU_FLAG | \ + KVMI_EVENT_UNHOOK_FLAG) + +#define KVMI_KNOWN_EVENTS (KVMI_KNOWN_VCPU_EVENTS | KVMI_KNOWN_VM_EVENTS) + +#define KVMI_ALLOWED_VM_EVENT(event_id, event_mask) \ + ((1 << (event_id)) & ((event_mask) & KVMI_KNOWN_VM_EVENTS)) +#define KVMI_ALLOWED_VCPU_EVENT(event_id, event_mask) \ + ((1 << (event_id)) & ((event_mask) & KVMI_KNOWN_VCPU_EVENTS)) + +#define KVMI_PAGE_ACCESS_R (1 << 0) +#define KVMI_PAGE_ACCESS_W (1 << 1) +#define KVMI_PAGE_ACCESS_X (1 << 2) + +struct kvmi_event_cr { + __u16 cr; + __u16 padding[3]; + __u64 old_value; + __u64 new_value; +}; + +struct kvmi_event_msr { + __u32 msr; + __u32 padding; + __u64 old_value; + __u64 new_value; +}; + +struct kvmi_event_breakpoint { + __u64 gpa; +}; + +struct kvmi_event_pf { + __u64 gva; + __u64 gpa; + __u32 mode; + __u32 padding; +}; + +struct kvmi_event_trap { + __u32 vector; + __u32 type; + __u32 error_code; + __u32 padding; + __u64 cr2; +}; + +#define KVMI_DESC_IDTR 1 +#define KVMI_DESC_GDTR 2 +#define KVMI_DESC_LDTR 3 +#define KVMI_DESC_TR 4 + +struct kvmi_event_descriptor { + union { + struct { + __u32 instr_info; + __u32 padding; + __u64 exit_qualification; + } vmx; + struct { + __u64 exit_info; + __u64 padding; + } svm; + } arch; + __u8 descriptor; + __u8 write; + __u8 padding[6]; +}; + +struct kvmi_event { + __u32 event; + __u16 vcpu; + __u8 mode; /* 2, 4 or 8 */ + __u8 padding; + struct kvm_regs regs; + struct kvm_sregs sregs; + struct { + __u64 sysenter_cs; + __u64 sysenter_esp; + __u64 sysenter_eip; + __u64 efer; + __u64 star; + __u64 lstar; + __u64 cstar; + __u64 pat; + __u64 shadow_gs; + } msrs; +}; + +struct kvmi_event_cr_reply { + __u64 new_val; +}; + +struct kvmi_event_msr_reply { + __u64 new_val; +}; + +struct kvmi_event_pf_reply { + __u8 singlestep; + __u8 rep_complete; + __u16 padding; + __u32 ctx_size; + __u8 ctx_data[256]; +}; + +struct kvmi_control_cr { + __u16 vcpu; + __u8 enable; + __u8 padding; + __u32 cr; +}; + +struct kvmi_control_msr { + __u16 vcpu; + __u8 enable; + __u8 padding; + __u32 msr; +}; + +struct kvmi_guest_info { + __u16 vcpu_count; + __u16 padding1; + __u32 padding2; + __u64 tsc_speed; +}; + +struct kvmi_inject_exception { + __u16 vcpu; + __u8 nr; + __u8 has_error; + __u16 error_code; + __u16 padding; + __u64 address; +}; + +struct kvmi_get_registers { + __u16 vcpu; + __u16 nmsrs; + __u16 padding[2]; + __u32 msrs_idx[0]; +}; + +struct kvmi_get_registers_reply { + __u32 mode; + __u32 padding; + struct kvm_regs regs; + struct kvm_sregs sregs; + struct kvm_msrs msrs; +}; + +struct kvmi_set_registers { + __u16 vcpu; + __u16 padding[3]; + struct kvm_regs regs; +}; + +struct kvmi_get_cpuid { + __u16 vcpu; + __u16 padding[3]; + __u32 function; + __u32 index; +}; + +struct kvmi_get_cpuid_reply { + __u32 eax; + __u32 ebx; + __u32 ecx; + __u32 edx; +}; + +struct kvmi_get_xsave { + __u16 vcpu; + __u16 padding[3]; +}; + +struct kvmi_get_xsave_reply { + __u32 region[0]; +}; + +#endif /* _UAPI_ASM_X86_KVMI_H */ diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 2b7a652c9fa4..f5028f20d441 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -976,6 +976,8 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_EXCEPTION_PAYLOAD 164 #define KVM_CAP_ARM_VM_IPA_SIZE 165 +#define KVM_CAP_INTROSPECTION 999 + #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing_irqchip { @@ -1501,6 +1503,16 @@ struct kvm_sev_dbg { __u32 len; }; +struct kvm_introspection { + int fd; + __u32 padding; + __u32 commands; + __u32 events; + __u8 uuid[16]; +}; +#define KVM_INTROSPECTION_HOOK _IOW(KVMIO, 0xff, struct kvm_introspection) +#define KVM_INTROSPECTION_UNHOOK _IO(KVMIO, 0xfe) + #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2) diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h index 6c0ce49931e5..2c2c32d99a5a 100644 --- a/include/uapi/linux/kvm_para.h +++ b/include/uapi/linux/kvm_para.h @@ -10,13 +10,18 @@ * - kvm_para_available */ -/* Return values for hypercalls */ +/* Return values for hypercalls and VM introspection */ #define KVM_ENOSYS 1000 #define KVM_EFAULT EFAULT #define KVM_EINVAL EINVAL #define KVM_E2BIG E2BIG #define KVM_EPERM EPERM #define KVM_EOPNOTSUPP 95 +#define KVM_EAGAIN 11 +#define KVM_EBUSY EBUSY +#define KVM_ENOENT ENOENT +#define KVM_ENOMEM ENOMEM +#define KVM_EACCES EACCES #define KVM_HC_VAPIC_POLL_IRQ 1 #define KVM_HC_MMU_OP 2 @@ -29,6 +34,10 @@ #define KVM_HC_CLOCK_PAIRING 9 #define KVM_HC_SEND_IPI 10 +#define KVM_HC_MEM_MAP 32 +#define KVM_HC_MEM_UNMAP 33 +#define KVM_HC_XEN_HVM_OP 34 /* Xen's __HYPERVISOR_hvm_op */ + /* * hypercalls use architecture specific */ diff --git a/include/uapi/linux/kvmi.h b/include/uapi/linux/kvmi.h new file mode 100644 index 000000000000..6b24825627bf --- /dev/null +++ b/include/uapi/linux/kvmi.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __UAPI_KVMI_H__ +#define __UAPI_KVMI_H__ + +/* + * KVMI specific structures and definitions + * + */ + +#include +#include +#include + +#define KVMI_VERSION 0x00000001 + +#define KVMI_GET_VERSION 1 +#define KVMI_GET_GUEST_INFO 3 +#define KVMI_GET_REGISTERS 6 +#define KVMI_SET_REGISTERS 7 +#define KVMI_GET_PAGE_ACCESS 10 +#define KVMI_SET_PAGE_ACCESS 11 +#define KVMI_INJECT_EXCEPTION 12 +#define KVMI_READ_PHYSICAL 13 +#define KVMI_WRITE_PHYSICAL 14 +#define KVMI_GET_MAP_TOKEN 15 +#define KVMI_CONTROL_EVENTS 17 +#define KVMI_CONTROL_CR 18 +#define KVMI_CONTROL_MSR 19 +#define KVMI_EVENT 23 +#define KVMI_EVENT_REPLY 24 +#define KVMI_GET_CPUID 25 +#define KVMI_GET_XSAVE 26 +#define KVMI_PAUSE_ALL_VCPUS 27 +#define KVMI_CONTROL_VM_EVENTS 28 + +/* TODO: find a way to split the commands between common and arch dependent */ + +#define KVMI_GET_VERSION_FLAG (1 << KVMI_GET_VERSION) +#define KVMI_GET_GUEST_INFO_FLAG (1 << KVMI_GET_GUEST_INFO) +#define KVMI_GET_REGISTERS_FLAG (1 << KVMI_GET_REGISTERS) +#define KVMI_SET_REGISTERS_FLAG (1 << KVMI_SET_REGISTERS) +#define KVMI_GET_PAGE_ACCESS_FLAG (1 << KVMI_GET_PAGE_ACCESS) +#define KVMI_SET_PAGE_ACCESS_FLAG (1 << KVMI_SET_PAGE_ACCESS) +#define KVMI_INJECT_EXCEPTION_FLAG (1 << KVMI_INJECT_EXCEPTION) +#define KVMI_READ_PHYSICAL_FLAG (1 << KVMI_READ_PHYSICAL) +#define KVMI_WRITE_PHYSICAL_FLAG (1 << KVMI_WRITE_PHYSICAL) +#define KVMI_GET_MAP_TOKEN_FLAG (1 << KVMI_GET_MAP_TOKEN) +#define KVMI_CONTROL_EVENTS_FLAG (1 << KVMI_CONTROL_EVENTS) +#define KVMI_CONTROL_CR_FLAG (1 << KVMI_CONTROL_CR) +#define KVMI_CONTROL_MSR_FLAG (1 << KVMI_CONTROL_MSR) +#define KVMI_EVENT_FLAG (1 << KVMI_EVENT) +#define KVMI_EVENT_REPLY_FLAG (1 << KVMI_EVENT_REPLY) +#define KVMI_GET_CPUID_FLAG (1 << KVMI_GET_CPUID) +#define KVMI_GET_XSAVE_FLAG (1 << KVMI_GET_XSAVE) +#define KVMI_PAUSE_ALL_VCPUS_FLAG (1 << KVMI_PAUSE_ALL_VCPUS) +#define KVMI_CONTROL_VM_EVENTS_FLAG (1 << KVMI_CONTROL_VM_EVENTS) + +#define KVMI_KNOWN_COMMANDS (\ + KVMI_GET_VERSION_FLAG | \ + KVMI_GET_GUEST_INFO_FLAG | \ + KVMI_GET_REGISTERS_FLAG | \ + KVMI_SET_REGISTERS_FLAG | \ + KVMI_GET_PAGE_ACCESS_FLAG | \ + KVMI_SET_PAGE_ACCESS_FLAG | \ + KVMI_INJECT_EXCEPTION_FLAG | \ + KVMI_READ_PHYSICAL_FLAG | \ + KVMI_WRITE_PHYSICAL_FLAG | \ + KVMI_GET_MAP_TOKEN_FLAG | \ + KVMI_CONTROL_EVENTS_FLAG | \ + KVMI_CONTROL_CR_FLAG | \ + KVMI_CONTROL_MSR_FLAG | \ + KVMI_EVENT_FLAG | \ + KVMI_EVENT_REPLY_FLAG | \ + KVMI_GET_CPUID_FLAG | \ + KVMI_GET_XSAVE_FLAG | \ + KVMI_PAUSE_ALL_VCPUS_FLAG | \ + KVMI_CONTROL_VM_EVENTS_FLAG) + +#define KVMI_ALLOWED_COMMAND(cmd_id, cmd_mask) \ + ((1 << (cmd_id)) & ((cmd_mask) & KVMI_KNOWN_COMMANDS)) + +#define KVMI_MSG_SIZE 4096 + +struct kvmi_msg_hdr { + __u16 id; + __u16 size; + __u32 seq; +}; + +struct kvmi_error_code { + __s32 err; + __u32 padding; +}; + +struct kvmi_get_version_reply { + __u32 version; + __u32 commands; + __u32 events; + __u32 padding; +}; + +struct kvmi_get_guest_info { + __u16 vcpu; + __u16 padding[3]; +}; + +struct kvmi_get_guest_info_reply { + __u32 vcpu_count; + __u32 padding; + __u64 tsc_speed; +}; + +struct kvmi_pause_all_vcpus_reply { + __u32 vcpu_count; + __u32 padding; +}; + +struct kvmi_event_reply { + __u32 action; + __u32 event; +}; + +struct kvmi_control_events { + __u16 vcpu; + __u16 padding; + __u32 events; +}; + +struct kvmi_control_vm_events { + __u32 events; + __u32 padding; +}; + +struct kvmi_get_page_access { + __u16 vcpu; + __u16 count; + __u16 view; + __u16 padding; + __u64 gpa[0]; +}; + +struct kvmi_get_page_access_reply { + __u8 access[0]; +}; + +struct kvmi_page_access_entry { + __u64 gpa; + __u8 access; + __u8 padding[7]; +}; + +struct kvmi_set_page_access { + __u16 vcpu; + __u16 count; + __u16 view; + __u16 padding; + struct kvmi_page_access_entry entries[0]; +}; + +struct kvmi_read_physical { + __u64 gpa; + __u64 size; +}; + +struct kvmi_write_physical { + __u64 gpa; + __u64 size; + __u8 data[0]; +}; + +struct kvmi_map_mem_token { + __u64 token[4]; +}; + +struct kvmi_get_map_token_reply { + struct kvmi_map_mem_token token; +}; + +/* Map other guest's gpa to local gva */ +struct kvmi_mem_map { + struct kvmi_map_mem_token token; + __u64 gpa; + __u64 gva; +}; + +/* + * ioctls for /dev/kvmmem + */ +#define KVM_INTRO_MEM_MAP _IOW('i', 0x01, struct kvmi_mem_map) +#define KVM_INTRO_MEM_UNMAP _IOW('i', 0x02, unsigned long) + +#endif /* __UAPI_KVMI_H__ */