Re: [RFC PATCH v2 1/1] kvm: Add documentation and ABI/API header for VM introspection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have a lot of comments, but it's a very good start.  Thanks for
writing down the specification.

On 07/07/2017 16:34, Adalbert Lazar wrote:
> +1. KVMI_GET_VERSION
> +-------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: {}
> +:Returns: ↴

What is this character? :)

> +::
> +
> +	struct kvmi_get_version_reply {
> +		__s32 err;
> +		__u32 version;
> +	};
> +
> +Returns the introspection API version (the KVMI_VERSION constant) and the
> +error code (zero). In case of an unlikely error, the version will have an
> +undefined value.

Would it make sense to return a few more information fields, for example
the set of supported KVMI_CONTROL_EVENTS events?

> +2. KVMI_GET_GUEST_INFO
> +----------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: {}
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_get_guest_info_reply {
> +		__s32 err;
> +		__u16 vcpu_count;
> +		__u16 padding;
> +		__u64 tsc_speed;
> +	};
> +
> +Returns the number of online vcpus, and the TSC frequency in HZ, if supported
> +by the architecture (otherwise is 0).

Can the TSC frequency be specified only if the guest is using TSC
scaling?  Defining the TSC frequency on older hosts is a bit tricky.  0
would be the host.

Maybe define the second padding to be

	__u16 arch;

(0 = x86) followed by an arch-specific payload.

> +3. KVMI_PAUSE_GUEST
> +-------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: {}
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +This command will pause all vcpus threads, by getting them out of guest mode
> +and put them in the "waiting introspection commands" state.

Pausing all threads synchronously is a tricky concept.  The main issue
is that the guest could be paused at the userspace level.  Then KVM
would not be running (userspace is stuck in pthread_cond_wait,
typically) and could not acknowledge the pause.

Worse, KVM is not able to distinguish userspace that has paused the VM
from userspace that is doing MMIO or userspace that has a bug and hung
somewhere.  And even worse, there are cases where userspace wants to
modify registers while doing port I/O (the awful VMware RPCI port).  So
I'd rather avoid this.

> +4. KVMI_UNPAUSE_GUEST
> +---------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: {}
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Resume the vcpu threads, or at least get them out of "waiting introspection
> +commands" state.

And this as well, of course.

> +5. KVMI_SHUTDOWN_GUEST
> +----------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: {}
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Ungracefully shutdown the guest.

Note that all KVM can do here is pass down a request asynchronously to
userspace, failing further KVM_RUN ioctls.  I'm suggesting below an
alternative action.

> +6. KVMI_GET_REGISTERS
> +---------------------
> +
> +:Architectures: x86 (could be all, but with different input/output)
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_get_registers_x86 {
> +		__u16 vcpu;
> +		__u16 nmsrs;
> +		__u32 msrs_idx[0];
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_get_registers_x86_reply {
> +		__s32 err;
> +		__u32 mode;
> +		struct kvm_regs  regs;
> +		struct kvm_sregs sregs;
> +		struct kvm_msrs  msrs;
> +	};
> +
> +For the given vcpu_id and the nmsrs sized array of MSRs registers, returns
> +the vCPU mode (in bytes: 2, 4 or 8), the general purpose registers,
> +the special registers and the requested set of MSR-s.
> +
> +7. KVMI_SET_REGISTERS
> +---------------------
> +
> +:Architectures: x86 (could be all, but with different input)
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_set_registers_x86 {
> +		__u16 vcpu;
> +		__u16 padding[3];
> +		struct kvm_regs regs;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Sets the general purpose registers for the given vcpu_id.
> +
> +8. KVMI_GET_MTRR_TYPE
> +---------------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_mtrr_type {
> +		__u64 gpa;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_mtrr_type_reply {
> +		__s32 err;
> +		__u32 type;
> +	};
> +
> +Returns the guest memory type for a specific physical address.

What is this used for?  KVM ignores the guest MTRRs, so if possible I'd
rather avoid it.

> +9. KVMI_GET_MTRRS
> +-----------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_mtrrs {
> +		__u16 vcpu;
> +		__u16 padding[3];
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_mtrrs_reply {
> +		__s32 err;
> +		__u32 padding;
> +		__u64 pat;
> +		__u64 cap;
> +		__u64 type;
> +	};
> +
> +Returns MSR_IA32_CR_PAT, MSR_MTRRcap and MSR_MTRRdefType for the specified
> +vCPU.

This could use KVM_GET_REGISTERS, couldn't it?

> +10. KVMI_GET_XSAVE_INFO
> +-----------------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_xsave_info {
> +		__u16 vcpu;
> +		__u16 padding[3];
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_xsave_info_reply {
> +		__s32 err;
> +		__u32 size;
> +	};
> +
> +Returns the xstate size for the specified vCPU.

Could this be replaced by a generic CPUID accessor?

> +11. KVMI_GET_PAGE_ACCESS
> +------------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_get_page_access {
> +		__u16 vcpu;
> +		__u16 padding[3];
> +		__u64 gpa;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_get_page_access_reply {
> +		__s32 err;
> +		__u32 access;
> +	};
> +
> +Returns the spte flags (rwx - present, write & user) for the specified
> +vCPU and guest physical address.
> +
> +12. KVMI_SET_PAGE_ACCESS
> +------------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_set_page_access {
> +		__u16 vcpu;
> +		__u16 padding;
> +		__u32 access;
> +		__u64 gpa;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Sets the spte flags (rwx - present, write & user) - access - for the specified
> +vCPU and guest physical address.

rwx or pwu?  I suppose RWX.  Maybe #define the constants in the
documentation.

Also, it should be noted here that the spte flags are ANDed with
whatever is provided by userspace, because there could be readonly
memslots, and that some access combinations could fail (--x) or will
surely fail (-wx for example).

> +13. KVMI_INJECT_PAGE_FAULT
> +--------------------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_page_fault {
> +		__u16 vcpu;
> +		__u16 padding;
> +		__u32 error;

error_code, I guess?  Why not a generic inject exception message?

> +		__u64 gva;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Injects a vCPU page fault with the specified guest virtual address and
> +error code.
> +
> +14. KVMI_INJECT_BREAKPOINT
> +--------------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_inject_breakpoint {
> +		__u16 vcpu;
> +		__u16 padding[3];
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Injects a breakpoint for the specified vCPU. This command is usually sent in
> +response to an event and as such the proper GPR-s will be set with the reply.

What is a "breakpoint" in this context?

> +15. KVMI_MAP_PHYSICAL_PAGE_TO_GUEST
> +-----------------------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_map_physical_page_to_guest {
> +		__u64 gpa_src;
> +		__u64 gfn_dest;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Maps a page from an introspected guest memory (gpa_src) to the guest running
> +the introspection tool. 'gfn_dest' points to an anonymous, locked mapping one
> +page in size.
> +
> +This command is used to "read" the introspected guest memory and potentially
> +place patches (eg. INT3-s).

Two problems here:

1) The gpa->hva mapping can change as the guest runs.  I'd prefer a
read/write API to map/unmap, where read replies and events provide a
"cookie" (generation count).  Write (including breakpoints?  it's not
clear to me who physically writes the 0xCC) then return an error if the
incoming generation count doesn't match the current one.

2) There can be multiple address spaces, notably SMM and non-SMM.

> +17. KVMI_CONTROL_EVENTS
> +-----------------------
> +
> +:Architectures: all
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_control_events {
> +		__u16 vcpu;
> +		__u16 padding;
> +		__u32 events;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Enables/disables vCPU introspection events, by setting/clearing one or more
> +of the following bits (see 'Events' below) :
> +
> +	KVMI_EVENT_CR
> +	KVMI_EVENT_MSR
> +	KVMI_EVENT_XSETBV
> +	KVMI_EVENT_BREAKPOINT
> +	KVMI_EVENT_USER_CALL
> +	KVMI_EVENT_PAGE_FAULT
> +	KVMI_EVENT_TRAP
> +
> +Trying to enable unsupported events (~KVMI_KNOWN_EVENTS) by the current
> +architecture would fail and -EINVAL will be returned.

I would prefer the interface to allow enable (set bits), disable (clear
bits) in addition to set (what you have here) the events.

The return value could indicate the set of enabled events.


> +19. KVMI_MSR_CONTROL
> +--------------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_msr_control {
> +		__u8 enable;
> +		__u8 padding[3];
> +		__u32 msr;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_error_code {
> +		__s32 err;
> +		__u32 padding;
> +	};
> +
> +Enables/disables introspection for a specific MSR, and must be used
> +in addition to KVMI_CONTROL_EVENTS with the KVMI_EVENT_MSR bit flag set.
> +
> +Currently, only MSRs within the following 3 ranges are supported. Trying
> +to control any other register will return -EINVAL. ::
> +
> +	0          ... 0x00001fff
> +	0x40000000 ... 0x40001fff
> +	0xc0000000 ... 0xc0001fff

Note that KVM custom MSRs fall in the range 0x4b564d00-0x4b564dff.

> +Events
> +------
> +
> +All vcpu events are sent using the KVMI_EVENT_VCPU message id. No event will
> +be sent unless enabled with a KVMI_CONTROL_EVENTS command.
> +
> +For x86, the message data starts with a common structure::
> +
> +	struct kvmi_event_x86 {
> +		__u16 vcpu;
> +		__u8 mode;
> +		__u8 padding1;
> +		__u32 event;
> +		struct kvm_regs regs;
> +		struct kvm_sregs sregs;
> +		struct {
> +			__u64 sysenter_cs;
> +			__u64 sysenter_esp;
> +			__u64 sysenter_eip;
> +			__u64 efer;
> +			__u64 star;
> +			__u64 lstar;

cstar too, for AMD CPUs.

> +		} msrs;
> +	};
> +
> +In order to help the introspection tool with the event analysis while
> +avoiding unnecessary introspection commands, the message data holds some
> +registers (kvm_regs, kvm_sregs and a couple of MSR-s) beside
> +the vCPU id, its mode (in bytes) and the event (one of the flags set
> +with the KVMI_CONTROL_EVENTS command).
> +
> +The replies to events also start with a common structure, having the
> +KVMI_EVENT_VCPU_REPLY message id::
> +
> +	struct kvmi_event_x86_reply {
> +		struct kvm_regs regs;

Put regs last?

> +		__u32 actions;
> +		__u32 padding;
> +	};
> +
> +The 'actions' member holds one or more flags. For example, if
> +KVMI_EVENT_ACTION_SET_REGS is set, the general purpose registers will
> +be overwritten with the new values (regs) from introspector.
> +
> +Specific data can follow these common structures.
> +
> +1. KVMI_EVENT_CR
> +----------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_event_x86;
> +	struct kvmi_event_cr {
> +		__u16 cr;
> +		__u16 padding[3];
> +		__u64 old_value;
> +		__u64 new_value;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_event_x86_reply;
> +	struct kvmi_event_cr_reply {
> +		__u64 new_val;
> +	};
> +
> +This event is sent when a CR register was modified and the introspection
> +has already been enabled for this kind of event (KVMI_CONTROL_EVENTS)
> +and for this specific register (KVMI_CR_CONTROL).
> +
> +kvmi_event_x86, the CR number, the old value and the new value are
> +sent to the introspector, which can respond with one or more action flags:
> +
> +   KVMI_EVENT_ACTION_SET_REGS - override the general purpose registers
> +   using the values from introspector (regs)

I think the action should be KVMI_EVENT_ACTION_SKIP.  Setting registers
can be done separately with a command.

> +   KVMI_EVENT_ACTION_ALLOW - allow the register modification with the
> +   value from introspector (new_val), otherwise deny the modification
> +   but allow the guest to proceed as if the register has been loaded
> +   with the desired value.

Maybe add an extra action for exit to userspace (which would presumably
shutdown the guest)?  This would apply to all events.

Also, a retry action can be useful in case e.g. the write cookie becomes
stale.

> +5. KVMI_EVENT_USER_CALL
> +-----------------------

Please rename this to KVMI_EVENT_HCALL or HYPERCALL or VMCALL.

> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_event_x86;
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_event_x86_reply;
> +
> +This event is sent on a user hypercall and the introspection has already
> +already been enabled for this kind of event (KVMI_CONTROL_EVENTS).
> +
> +kvmi_event_x86 is sent to the introspector, which can respond with the
> +KVMI_EVENT_ACTION_SET_REGS bit set in 'actions', instructing the host
> +kernel to override the general purpose registers using the values from
> +introspector (regs).

Does KVMI_EVENT_ACTION_SET_REGS bypass the hypercall?  Why is
KVMI_EVENT_ACTION_ALLOW not allowed?  As before, I'd prefer
SKIP/RETRY/ALLOW/CRASH as the actions.

> +6. KVMI_EVENT_PAGE_FAULT
> +------------------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_event_x86;
> +	struct kvmi_event_page_fault {
> +		__u64 gva;
> +		__u64 gpa;
> +		__u32 mode;
> +		__u32 padding;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_event_x86_reply;
> +	struct kvmi_event_page_fault_reply {
> +		__u32 ctx_size;
> +		__u8 ctx_data[256];
> +	};
> +
> +This event is sent if a hypervisor page fault was encountered, the
> +introspection has already enabled the reports for this kind of event
> +(KVMI_CONTROL_EVENTS), and it was generated for a page for which the
> +introspector has shown interest (ie. has previously touched it by
> +adjusting the permissions).

If the introspector sets permissions to r-- and you get a read page
fault because the page is swapped out, should the introspector get the
event?

> +kvmi_event_x86, guest virtual address, guest physical address and
> +the exit qualification (mode) are sent to the introspector, which
> +can respond with one or more action flags:
> +
> +   KVMI_EVENT_ACTION_SET_REGS - override the general purpose registers
> +   using the values from introspector (regs)
> +
> +   (KVMI_EVENT_ALLOW | KVMI_EVENT_NOEMU) - let the guest re-trigger
> +   the page fault

"re-execute the instruction"?  Maybe call it KVMI_EVENT_RETRY?

> +   (KVMI_EVENT_ALLOW | KVMI_EVENT_SET_CTX) - allow the page fault
> +   via emulation but with custom input (ctx_data, ctx_size). This is
> +   used to trick the guest software into believing it has read
> +   certain data. In practice it is used to hide the contents of certain
> +   memory areas

This is tricky.  The instruction could be, for example, a string read.
I think there should be a separate event for I/O from a trapping page
(so perhaps return KVMI_EVENT_ALLOW | KVMI_EVENT_TRAP_ACCESS).

> +   KVMI_EVENT_ALLOW - allow the page fault via emulation
>
> +If KVMI_EVENT_ALLOW is not set, it will fall back to the page fault handler
> +which usually implies overwriting any spte page access changes made before.
> +An introspection tool will always set this flag and prevent unwanted changes
> +to memory by skipping the instruction. It is up to the tool to adjust the
> +program counter in order to achieve this result.

I don't like this.  It should be what KVMI_EVENT_RETRY is for.  But
maybe I'm missing the difference between "0" and KVMI_EVENT_RETRY.

Here, the actions would be SKIP/RETRY/ALLOW/CRASH, with an optional
KVMI_EVENT_TRAP_ACCESS flag for "allow".


> +7. KVMI_EVENT_TRAP
> +------------------
> +
> +:Architectures: x86
> +:Versions: >= 1
> +:Parameters: ↴
> +
> +::
> +
> +	struct kvmi_event_x86;
> +	struct kvmi_event_trap {
> +		__u32 vector;
> +		__u32 type;
> +		__u32 err;

error_code?

> +		__u32 padding;
> +		__u64 cr2;
> +	};
> +
> +:Returns: ↴
> +
> +::
> +
> +	struct kvmi_event_x86_reply;
> +
> +This event is sent if a trap will be delivered to the guest (page fault,
> +breakpoint, etc.) and the introspection has already enabled the reports
> +for this kind of event (KVMI_CONTROL_EVENTS).
> +
> +This is used to inform the introspector of all pending traps giving it
> +a chance to determine if it should try again later in case a previous
> +KVMI_INJECT_PAGE_FAULT/KVMI_INJECT_BREAKPOINT command has been overwritten
> +by an interrupt picked up during guest reentry.
> +
> +kvmi_event_x86, exception/interrupt number (vector), exception/interrupt
> +type, exception code (err) and CR2 are sent to the introspector, which can
> +respond with the KVMI_EVENT_ACTION_SET_REGS bit set in 'actions', instructing
> +the host kernel to override the general purpose registers using the values
> +from introspector (regs).

Here I think the actions could be RETRY/ALLOW/CRASH only, with "set
regs" done as a separate command.

Some x86 exceptions are faults, others are traps.  Traps should not
allow RETRY as an action.  There should be an input telling the
introspector if retrying is allowed.

How are dr6/dr7 handled around breakpoints?

Thanks,

Paolo

> diff --git a/include/uapi/linux/kvmi.h b/include/uapi/linux/kvmi.h
> new file mode 100644
> index 000000000000..54a2d8ebf649
> --- /dev/null
> +++ b/include/uapi/linux/kvmi.h
> @@ -0,0 +1,310 @@
> +/*
> + * Copyright (C) 2017 Bitdefender S.R.L.
> + *
> + * The KVMI Library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the named License, or any later version.
> + *
> + * The KVMI Library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with the KVMI Library; if not, see <http://www.gnu.org/licenses/>
> + */
> +#ifndef __KVMI_H_INCLUDED__
> +#define __KVMI_H_INCLUDED__
> +
> +#include "asm/kvm.h"
> +#include <linux/types.h>
> +
> +#define KVMI_VERSION 0x00000001
> +
> +#define KVMI_EVENT_CR         (1 << 1)	/* control register was modified */
> +#define KVMI_EVENT_MSR        (1 << 2)	/* model specific reg. was modified */
> +#define KVMI_EVENT_XSETBV     (1 << 3)	/* ext. control register was modified */
> +#define KVMI_EVENT_BREAKPOINT (1 << 4)	/* breakpoint was reached */
> +#define KVMI_EVENT_USER_CALL  (1 << 5)	/* user hypercall */
> +#define KVMI_EVENT_PAGE_FAULT (1 << 6)	/* hyp. page fault was encountered */
> +#define KVMI_EVENT_TRAP       (1 << 7)	/* trap was injected */
> +
> +#define KVMI_KNOWN_EVENTS (KVMI_EVENT_CR | \
> +			   KVMI_EVENT_MSR | \
> +			   KVMI_EVENT_XSETBV | \
> +			   KVMI_EVENT_BREAKPOINT | \
> +			   KVMI_EVENT_USER_CALL | \
> +			   KVMI_EVENT_PAGE_FAULT | \
> +			   KVMI_EVENT_TRAP)
> +
> +#define KVMI_EVENT_ACTION_ALLOW      (1 << 0)	/* used in replies */
> +#define KVMI_EVENT_ACTION_SET_REGS   (1 << 1)	/* registers need to be written back */
> +#define KVMI_EVENT_ACTION_SET_CTX    (1 << 2)	/* set the emulation context */
> +#define KVMI_EVENT_ACTION_NOEMU      (1 << 3)	/* return to guest without emulation */
> +
> +#define KVMI_GET_VERSION                    1
> +#define KVMI_GET_GUESTS                     2 /* TODO: remove me */
> +#define KVMI_GET_GUEST_INFO                 3
> +#define KVMI_PAUSE_GUEST                    4
> +#define KVMI_UNPAUSE_GUEST                  5
> +#define KVMI_GET_REGISTERS                  6
> +#define KVMI_SET_REGISTERS                  7
> +#define KVMI_SHUTDOWN_GUEST                 8
> +#define KVMI_GET_MTRR_TYPE                  9
> +#define KVMI_GET_MTRRS                      10
> +#define KVMI_GET_XSAVE_INFO                 11
> +#define KVMI_GET_PAGE_ACCESS                12
> +#define KVMI_SET_PAGE_ACCESS                13
> +#define KVMI_INJECT_PAGE_FAULT              14
> +#define KVMI_READ_PHYSICAL                  15 /* TODO: remove me */
> +#define KVMI_WRITE_PHYSICAL                 16 /* TODO: remove me */
> +#define KVMI_MAP_PHYSICAL_PAGE_TO_GUEST     17
> +#define KVMI_UNMAP_PHYSICAL_PAGE_FROM_GUEST 18
> +#define KVMI_CONTROL_EVENTS                 19
> +#define KVMI_CR_CONTROL                     20
> +#define KVMI_MSR_CONTROL                    21
> +#define KVMI_INJECT_BREAKPOINT              22
> +#define KVMI_EVENT_GUEST_ON                 23 /* TODO: remove me */
> +#define KVMI_EVENT_GUEST_OFF                24 /* TODO: remove me */
> +#define KVMI_EVENT_VCPU                     25
> +#define KVMI_EVENT_VCPU_REPLY               26

Errnos values are not portable, I'd prefer to have them defined
explicitly in the header.

Paolo

> +/* TODO: remove me */
> +struct kvmi_guest {
> +	__u8 uuid[16];
> +};
> +
> +/* TODO: remove me */
> +struct kvmi_guests {
> +	__u32 size;		/* in: the size of the entire structure */
> +	struct kvmi_guest guests[1];
> +};
> +
> +/* TODO: remove me */
> +struct kvmi_read_physical {
> +	__u64 gpa;
> +	__u64 size;
> +};
> +
> +/* TODO: remove me */
> +struct kvmi_read_physical_reply {
> +	__s32 err;
> +	__u8 bytes[0];
> +};
> +
> +/* TODO: remove me */
> +struct kvmi_write_physical {
> +	__u64 gpa;
> +	__u64 size;
> +	__u8 bytes[0];
> +};
> +
> +
> +struct kvmi_socket_hdr {
> +	__u16 msg_id;
> +	__u16 size;
> +	__u32 seq;
> +};
> +
> +struct kvmi_error_code {
> +	__s32 err;
> +	__u32 padding;
> +};
> +
> +struct kvmi_get_version_reply {
> +	__s32 err;
> +	__u32 version;
> +};
> +
> +struct kvmi_get_guest_info_reply {
> +	__s32 err;
> +	__u16 vcpu_count;
> +	__u16 padding;
> +	__u64 tsc_speed;
> +};
> +
> +struct kvmi_get_registers_x86 {
> +	__u16 vcpu;
> +	__u16 nmsrs;
> +	__u32 msrs_idx[0];
> +};
> +
> +struct kvmi_get_registers_x86_reply {
> +	__s32 err;
> +	__u32 mode;
> +	struct kvm_regs regs;
> +	struct kvm_sregs sregs;
> +	struct kvm_msrs msrs;
> +};
> +
> +struct kvmi_set_registers_x86 {
> +	__u16 vcpu;
> +	__u16 padding[3];
> +	struct kvm_regs regs;
> +};
> +
> +struct kvmi_mtrr_type {
> +	__u64 gpa;
> +};
> +
> +struct kvmi_mtrr_type_reply {
> +	__s32 err;
> +	__u32 padding;
> +	__u64 type;
> +};
> +
> +struct kvmi_mtrrs {
> +	__u16 vcpu;
> +	__u16 padding[3];
> +};
> +
> +struct kvmi_mtrrs_reply {
> +	__s32 err;
> +	__u32 padding;
> +	__u64 pat;
> +	__u64 cap;
> +	__u64 type;
> +};
> +
> +struct kvmi_xsave_info {
> +	__u16 vcpu;
> +	__u16 padding[3];
> +};
> +
> +struct kvmi_xsave_info_reply {
> +	__s32 err;
> +	__u32 size;
> +};
> +
> +struct kvmi_get_page_access {
> +	__u16 vcpu;
> +	__u16 padding[3];
> +	__u64 gpa;
> +};
> +
> +struct kvmi_get_page_access_reply {
> +	__s32 err;
> +	__u32 access;
> +};
> +
> +struct kvmi_set_page_access {
> +	__u16 vcpu;
> +	__u16 padding;
> +	__u32 access;
> +	__u64 gpa;
> +};
> +
> +struct kvmi_page_fault {
> +	__u16 vcpu;
> +	__u16 padding;
> +	__u32 error;
> +	__u64 gva;
> +};
> +
> +struct kvmi_inject_breakpoint {
> +	__u16 vcpu;
> +	__u16 padding[3];
> +};
> +
> +struct kvmi_map_physical_page_to_guest {
> +	__u64 gpa_src;
> +	__u64 gfn_dest;
> +};
> +
> +struct kvmi_unmap_physical_page_from_guest {
> +	__u64 gfn_dest;
> +};
> +
> +struct kvmi_control_events {
> +	__u16 vcpu;
> +	__u16 padding;
> +	__u32 events;
> +};
> +
> +struct kvmi_cr_control {
> +	__u8 enable;
> +	__u8 padding[3];
> +	__u32 cr;
> +};
> +
> +struct kvmi_msr_control {
> +	__u8 enable;
> +	__u8 padding[3];
> +	__u32 msr;
> +};
> +
> +struct kvmi_event_x86 {
> +	__u16 vcpu;
> +	__u8 mode;
> +	__u8 padding1;
> +	__u32 event;
> +	struct kvm_regs regs;
> +	struct kvm_sregs sregs;
> +	struct {
> +		__u64 sysenter_cs;
> +		__u64 sysenter_esp;
> +		__u64 sysenter_eip;
> +		__u64 efer;
> +		__u64 star;
> +		__u64 lstar;
> +	} msrs;
> +};
> +
> +struct kvmi_event_x86_reply {
> +	struct kvm_regs regs;
> +	__u32 actions;
> +	__u32 padding;
> +};
> +
> +struct kvmi_event_cr {
> +	__u16 cr;
> +	__u16 padding[3];
> +	__u64 old_value;
> +	__u64 new_value;
> +};
> +
> +struct kvmi_event_cr_reply {
> +	__u64 new_val;
> +};
> +
> +struct kvmi_event_msr {
> +	__u32 msr;
> +	__u32 padding;
> +	__u64 old_value;
> +	__u64 new_value;
> +};
> +
> +struct kvmi_event_msr_reply {
> +	__u64 new_val;
> +};
> +
> +struct kvmi_event_xsetbv {
> +	__u64 xcr0;
> +};
> +
> +struct kvmi_event_breakpoint {
> +	__u64 gpa;
> +};
> +
> +struct kvmi_event_page_fault {
> +	__u64 gva;
> +	__u64 gpa;
> +	__u32 mode;
> +	__u32 padding;
> +};
> +
> +struct kvmi_event_page_fault_reply {
> +	__u32 ctx_size;
> +	__u8 ctx_data[256];
> +};
> +
> +struct kvmi_event_trap {
> +	__u32 vector;
> +	__u32 type;
> +	__u32 err;
> +	__u32 padding;
> +	__u64 cr2;
> +};
> +
> +#endif /* __KVMI_H_INCLUDED__ */



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux