# HG changeset patch # User cegger # Date 1287134038 -7200 add nestedhvm function hooks for svm/vmx specific code Signed-off-by: Christoph Egger diff -r 85aa977891b6 -r 0c2b398816b1 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3310,6 +3310,98 @@ int hvm_debug_op(struct vcpu *v, int32_t } +int nhvm_vcpu_initialise(struct vcpu *v) +{ + if (hvm_funcs.nhvm_vcpu_initialise) + return hvm_funcs.nhvm_vcpu_initialise(v); + return -EOPNOTSUPP; +} + +int nhvm_vcpu_destroy(struct vcpu *v) +{ + if (hvm_funcs.nhvm_vcpu_destroy) + return hvm_funcs.nhvm_vcpu_destroy(v); + return -EOPNOTSUPP; +} + +int nhvm_vcpu_reset(struct vcpu *v) +{ + if (hvm_funcs.nhvm_vcpu_reset) + return hvm_funcs.nhvm_vcpu_reset(v); + return -EOPNOTSUPP; +} + +int nhvm_vcpu_hostrestore(struct vcpu *v, struct cpu_user_regs *regs) +{ + if (hvm_funcs.nhvm_vcpu_hostrestore) + return hvm_funcs.nhvm_vcpu_hostrestore(v, regs); + return -EOPNOTSUPP; +} + +int nhvm_vcpu_vmentry(struct vcpu *v, struct cpu_user_regs *regs, + unsigned int inst_len) +{ + if (hvm_funcs.nhvm_vcpu_vmentry) + return hvm_funcs.nhvm_vcpu_vmentry(v, regs, inst_len); + return -EOPNOTSUPP; +} + +int nhvm_vcpu_vmexit(struct vcpu *v, struct cpu_user_regs *regs, + uint64_t exitcode) +{ + if (hvm_funcs.nhvm_vcpu_vmexit) + return hvm_funcs.nhvm_vcpu_vmexit(v, regs, exitcode); + return -EOPNOTSUPP; +} + +uint64_t nhvm_vmcx_exitcode_native2generic(struct vcpu *v, uint64_t exitcode) +{ + if (hvm_funcs.nhvm_vmcx_exitcode_native2generic) + return hvm_funcs.nhvm_vmcx_exitcode_native2generic(v, exitcode); + return -EOPNOTSUPP; +} + +int nhvm_vmcx_guest_intercepts_trap(struct vcpu *v, unsigned int trap) +{ + if (hvm_funcs.nhvm_vmcx_guest_intercepts_trap) + return hvm_funcs.nhvm_vmcx_guest_intercepts_trap(v, trap); + return -EOPNOTSUPP; +} + +int nhvm_vmcx_guest_intercepts_exitcode(struct vcpu *v, + struct cpu_user_regs *regs, uint64_t exitcode) +{ + if (hvm_funcs.nhvm_vmcx_guest_intercepts_exitcode) + return hvm_funcs.nhvm_vmcx_guest_intercepts_exitcode(v, regs, exitcode); + return -EOPNOTSUPP; +} + +int nhvm_vmcx_prepare4vmexit(struct vcpu *v) +{ + if (hvm_funcs.nhvm_vmcx_prepare4vmexit) + return hvm_funcs.nhvm_vmcx_prepare4vmexit(v); + return -EOPNOTSUPP; +} + +int nhvm_vmcx_isvalid(struct vcpu *v, uint64_t vmcxaddr) +{ + if (hvm_funcs.nhvm_vmcx_isvalid) + return hvm_funcs.nhvm_vmcx_isvalid(v, vmcxaddr); + return -EOPNOTSUPP; +} + +int +nhvm_vcpu_vmexit_trap(struct vcpu *v, unsigned int trapnr, + int errcode, unsigned long cr2) +{ + return hvm_funcs.nhvm_vcpu_vmexit_trap(v, trapnr, errcode, cr2); +} + +enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v) +{ + return hvm_funcs.nhvm_intr_blocked(v); +} + /* * Local variables: * mode: C diff -r 85aa977891b6 -r 0c2b398816b1 xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -145,6 +145,31 @@ struct hvm_function_table { void (*set_uc_mode)(struct vcpu *v); void (*set_info_guest)(struct vcpu *v); void (*set_rdtsc_exiting)(struct vcpu *v, bool_t); + + /* Nested HVM */ + int (*nhvm_vcpu_initialise)(struct vcpu *v); + int (*nhvm_vcpu_destroy)(struct vcpu *v); + int (*nhvm_vcpu_reset)(struct vcpu *v); + int (*nhvm_vcpu_hostrestore)(struct vcpu *v, + struct cpu_user_regs *regs); + int (*nhvm_vcpu_vmentry)(struct vcpu *v, struct cpu_user_regs *regs, + unsigned int inst_len); + int (*nhvm_vcpu_vmexit)(struct vcpu *v, struct cpu_user_regs *regs, + uint64_t exitcode); + int (*nhvm_vcpu_vmexit_trap)(struct vcpu *v, + unsigned int trapnr, + int errcode, + unsigned long cr2); + uint64_t (*nhvm_vmcx_exitcode_native2generic)(struct vcpu *v, + uint64_t exitcode); + int (*nhvm_vmcx_guest_intercepts_trap)(struct vcpu *v, unsigned int trapnr); + int (*nhvm_vmcx_guest_intercepts_exitcode)(struct vcpu *v, + struct cpu_user_regs *regs, + uint64_t exitcode); + int (*nhvm_vmcx_prepare4vmexit)(struct vcpu *v); + + int (*nhvm_vmcx_isvalid)(struct vcpu *v, uint64_t vmcxaddr); + enum hvm_intblk (*nhvm_intr_blocked)(struct vcpu *v); }; extern struct hvm_function_table hvm_funcs; @@ -365,4 +390,45 @@ bool_t hvm_hap_nested_page_fault(unsigne ? (u32)__d->arch.incarnation : (u32)(v)->arch.hvm_vcpu.msr_tsc_aux; \ }) +/* + * Nested HVM + */ + +/* Initialize vcpu's struct nestedhvm */ +int nhvm_vcpu_initialise(struct vcpu *v); +/* Destroy and free vcpu's struct nestedhvm */ +int nhvm_vcpu_destroy(struct vcpu *v); +/* Reset vcpu's state when l1 guest disables nested virtualization */ +int nhvm_vcpu_reset(struct vcpu *v); +/* Restores l1 guest state */ +int nhvm_vcpu_hostrestore(struct vcpu *v, struct cpu_user_regs *regs); +/* Fill struct nestedhvm with data provided by l1 guest's VMCB/VMCS, + * save l1 guest state as needed, + * prepare VMCB/VMCS to be ready for use with VMRUN/VMLAUNCH */ +int nhvm_vcpu_vmentry(struct vcpu *v, struct cpu_user_regs *regs, + unsigned int inst_len); +/* Fill l1 guest's VMCB/VMCS with data provided by generic exit codes + * (do conversion as needed), other misc SVM/VMX specific tweaks to make + * it work */ +int nhvm_vcpu_vmexit(struct vcpu *v, struct cpu_user_regs *regs, + uint64_t exitcode); +/* inject vmexit into l1 guest */ +int nhvm_vcpu_vmexit_trap(struct vcpu *v, + unsigned int trapnr, int errcode, unsigned long cr2); +/* convert native exitcode (= SVM/VMX specific) to generic exit code + * (used to inject vmexit into l1 guest. */ +uint64_t nhvm_vmcx_exitcode_native2generic(struct vcpu *v, uint64_t exitcode); +/* returns true, when l1 guest intercepts the specified trap */ +int nhvm_vmcx_guest_intercepts_trap(struct vcpu *v, unsigned int trapnr); +/* returns true, when l1 guest intercepts the specified native exitcode */ +int nhvm_vmcx_guest_intercepts_exitcode(struct vcpu *v, + struct cpu_user_regs *regs, uint64_t exitcode); +/* prepare l1 guest's VMCB/VMCS for VMEXIT injection (restore shadowed fields), + * (implementation might be empty or very small with shadow VMCB/VMCS) */ +int nhvm_vmcx_prepare4vmexit(struct vcpu *v); +/* Check virtual VMCB/VMCS if it is valid. Return TRAP_* in error case */ +int nhvm_vmcx_isvalid(struct vcpu *v, uint64_t vmcxaddr); +/* interrupt */ +enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v); + #endif /* __ASM_X86_HVM_HVM_H__ */