# HG changeset patch # User Sheng Yang # Date 1253085983 -28800 # Node ID 2d68b9d29b425f138345c7b9e0e8bc66b84c7ba1 # Parent f92ed10b9522a4dd83a5e31f7f1a8c83bd33d70d Add HVMOP_enable_hybrid hypercall As the entry of hybrid. diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2028,6 +2028,17 @@ HYPERCALL(hvm_op) }; +static hvm_hypercall_t *hvm_hypercall_hybrid64_table[NR_hypercalls] = { + [ __HYPERVISOR_memory_op ] = (hvm_hypercall_t *)hvm_memory_op, + [ __HYPERVISOR_grant_table_op ] = (hvm_hypercall_t *)hvm_grant_table_op, + HYPERCALL(xen_version), + HYPERCALL(console_io), + HYPERCALL(vcpu_op), + HYPERCALL(sched_op), + HYPERCALL(event_channel_op), + HYPERCALL(hvm_op), +}; + #endif /* defined(__x86_64__) */ int hvm_do_hypercall(struct cpu_user_regs *regs) @@ -2058,7 +2069,8 @@ if ( (eax & 0x80000000) && is_viridian_domain(curr->domain) ) return viridian_hypercall(regs); - if ( (eax >= NR_hypercalls) || !hvm_hypercall32_table[eax] ) + if ( (eax >= NR_hypercalls) || + (!hvm_hypercall32_table[eax] && !is_hybrid_vcpu(curr)) ) { regs->eax = -ENOSYS; return HVM_HCALL_completed; @@ -2073,11 +2085,18 @@ regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8); this_cpu(hvm_64bit_hcall) = 1; - regs->rax = hvm_hypercall64_table[eax](regs->rdi, - regs->rsi, - regs->rdx, - regs->r10, - regs->r8); + if (is_hybrid_vcpu(curr)) + regs->rax = hvm_hypercall_hybrid64_table[eax](regs->rdi, + regs->rsi, + regs->rdx, + regs->r10, + regs->r8); + else + regs->rax = hvm_hypercall64_table[eax](regs->rdi, + regs->rsi, + regs->rdx, + regs->r10, + regs->r8); this_cpu(hvm_64bit_hcall) = 0; } else @@ -2752,6 +2771,32 @@ break; } + case HVMOP_enable_hybrid: { + struct xen_hvm_hybrid_type a; + struct domain *d; + + if ( copy_from_guest(&a, arg, 1) ) + return -EFAULT; + + rc = rcu_lock_target_domain_by_id(a.domid, &d); + if ( rc != 0 ) + return rc; + + rc = -EINVAL; + if ( !is_hvm_domain(d) ) + goto param_fail5; + + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail5; + + d->hybrid_enabled = XEN_HYBRID_ENABLED; + printk("HVM: Hybrid domain enabled\n"); + param_fail5: + rcu_unlock_domain(d); + break; + } + default: { gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op); diff --git a/xen/include/public/arch-x86/cpuid.h b/xen/include/public/arch-x86/cpuid.h --- a/xen/include/public/arch-x86/cpuid.h +++ b/xen/include/public/arch-x86/cpuid.h @@ -66,6 +66,8 @@ #define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0) /* Mask unsupported CPUID specified by user */ -#define XEN_CPUID_FEAT2_MASK 0x0ul +#define XEN_CPUID_FEAT2_MASK 0x1ul +#define _XEN_CPUID_FEAT2_HYBRID 0 +#define XEN_CPUID_FEAT2_HYBRID (1u<<0) #endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */ diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h --- a/xen/include/public/hvm/hvm_op.h +++ b/xen/include/public/hvm/hvm_op.h @@ -125,6 +125,13 @@ typedef struct xen_hvm_set_mem_type xen_hvm_set_mem_type_t; DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t); +#define HVMOP_enable_hybrid 9 +struct xen_hvm_hybrid_type { + domid_t domid; + uint64_t flags; +#define HVM_HYBRID_TIMER (1ull<<1) +#define HVM_HYBRID_EVTCHN (1ull<<2) +}; #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -269,6 +269,11 @@ /* VRAM dirty support. */ struct sh_dirty_vram *dirty_vram; + +#define XEN_HYBRID_ENABLED (1u << 0) +#define XEN_HYBRID_TIMER_ENABLED (1u << 1) +#define XEN_HYBRID_EVTCHN_ENABLED (1u << 2) + uint64_t hybrid_enabled; }; struct domain_setup_info @@ -551,6 +556,12 @@ #define is_hvm_domain(d) ((d)->is_hvm) #define is_hvm_vcpu(v) (is_hvm_domain(v->domain)) #define need_iommu(d) ((d)->need_iommu && !(d)->is_hvm) +#define is_hybrid_domain(d) ((d)->hybrid_enabled & XEN_HYBRID_ENABLED) +#define is_hybrid_vcpu(v) (is_hybrid_domain(v->domain)) +#define is_hybrid_timer_enabled_domain(d) (is_hybrid_domain(d) && \ + (d)->hybrid_enabled & XEN_HYBRID_TIMER_ENABLED) +#define is_hybrid_evtchn_enabled_domain(d) (is_hybrid_domain(d) && \ + (d)->hybrid_enabled & XEN_HYBRID_EVTCHN_ENABLED) void set_vcpu_migration_delay(unsigned int delay); unsigned int get_vcpu_migration_delay(void);