mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/HVM: convert remaining hvm_funcs hook invocations to alt-call
The aim being to have as few indirect calls as possible (see [1]), whereas during initial conversion performance was the main aspect and hence rarely used hooks didn't get converted. Apparently one use of get_interrupt_shadow() was missed at the time. While doing this, drop NULL checks ahead of CPU management and .nhvm_*() calls when the hook is always present. Also convert the .nhvm_vcpu_reset() call to alternative_vcall(), as the return value is unused and the caller has currently no way of propagating it. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Tamas K Lengyel <tamas@tklengyel.com> [1] https://lists.xen.org/archives/html/xen-devel/2021-11/msg01822.html
This commit is contained in:
1 parent
299deb9dd9
commit
27a63cdac3
6 files changed
+42
-42
No files matched your search
@@ -2549,7 +2549,7 @@ static int hvmemul_vmfunc(
|
||||
|
||||
if ( !hvm_funcs.altp2m_vcpu_emulate_vmfunc )
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
rc = hvm_funcs.altp2m_vcpu_emulate_vmfunc(ctxt->regs);
|
||||
rc = alternative_call(hvm_funcs.altp2m_vcpu_emulate_vmfunc, ctxt->regs);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
x86_emul_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC, ctxt);
|
||||
|
||||
|
||||
+13
-12
@@ -126,14 +126,14 @@ static int cpu_callback(
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_UP_PREPARE:
|
||||
rc = hvm_funcs.cpu_up_prepare(cpu);
|
||||
rc = alternative_call(hvm_funcs.cpu_up_prepare, cpu);
|
||||
break;
|
||||
case CPU_DYING:
|
||||
hvm_cpu_down();
|
||||
break;
|
||||
case CPU_UP_CANCELED:
|
||||
case CPU_DEAD:
|
||||
hvm_funcs.cpu_dead(cpu);
|
||||
alternative_vcall(hvm_funcs.cpu_dead, cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -707,7 +707,7 @@ int hvm_domain_initialise(struct domain *d)
|
||||
if ( rc )
|
||||
goto fail2;
|
||||
|
||||
rc = hvm_funcs.domain_initialise(d);
|
||||
rc = alternative_call(hvm_funcs.domain_initialise, d);
|
||||
if ( rc != 0 )
|
||||
goto fail2;
|
||||
|
||||
@@ -740,7 +740,7 @@ void hvm_domain_relinquish_resources(struct domain *d)
|
||||
alternative_vcall(hvm_funcs.domain_relinquish_resources, d);
|
||||
|
||||
if ( hvm_funcs.nhvm_domain_relinquish_resources )
|
||||
hvm_funcs.nhvm_domain_relinquish_resources(d);
|
||||
alternative_vcall(hvm_funcs.nhvm_domain_relinquish_resources, d);
|
||||
|
||||
viridian_domain_deinit(d);
|
||||
|
||||
@@ -870,7 +870,7 @@ static int hvm_save_cpu_ctxt(struct vcpu *v, hvm_domain_context_t *h)
|
||||
return 0;
|
||||
|
||||
/* Architecture-specific vmcs/vmcb bits */
|
||||
hvm_funcs.save_cpu_ctxt(v, &ctxt);
|
||||
alternative_vcall(hvm_funcs.save_cpu_ctxt, v, &ctxt);
|
||||
|
||||
hvm_get_segment_register(v, x86_seg_idtr, &seg);
|
||||
ctxt.idtr_limit = seg.limit;
|
||||
@@ -1093,14 +1093,14 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
#undef UNFOLD_ARBYTES
|
||||
|
||||
/* Architecture-specific vmcs/vmcb bits */
|
||||
if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 )
|
||||
if ( alternative_call(hvm_funcs.load_cpu_ctxt, v, &ctxt) < 0 )
|
||||
return -EINVAL;
|
||||
|
||||
v->arch.hvm.guest_cr[2] = ctxt.cr2;
|
||||
hvm_update_guest_cr(v, 2);
|
||||
|
||||
if ( hvm_funcs.tsc_scaling.setup )
|
||||
hvm_funcs.tsc_scaling.setup(v);
|
||||
alternative_vcall(hvm_funcs.tsc_scaling.setup, v);
|
||||
|
||||
v->arch.msrs->tsc_aux = ctxt.msr_tsc_aux;
|
||||
|
||||
@@ -1563,7 +1563,8 @@ int hvm_vcpu_initialise(struct vcpu *v)
|
||||
if ( rc != 0 ) /* teardown: vlapic_destroy */
|
||||
goto fail2;
|
||||
|
||||
if ( (rc = hvm_funcs.vcpu_initialise(v)) != 0 ) /* teardown: hvm_funcs.vcpu_destroy */
|
||||
rc = alternative_call(hvm_funcs.vcpu_initialise, v);
|
||||
if ( rc != 0 ) /* teardown: hvm_funcs.vcpu_destroy */
|
||||
goto fail3;
|
||||
|
||||
softirq_tasklet_init(&v->arch.hvm.assert_evtchn_irq_tasklet,
|
||||
@@ -1611,7 +1612,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
|
||||
free_compat_arg_xlat(v);
|
||||
fail4:
|
||||
hvmemul_cache_destroy(v);
|
||||
hvm_funcs.vcpu_destroy(v);
|
||||
alternative_vcall(hvm_funcs.vcpu_destroy, v);
|
||||
fail3:
|
||||
vlapic_destroy(v);
|
||||
fail2:
|
||||
@@ -1635,7 +1636,7 @@ void hvm_vcpu_destroy(struct vcpu *v)
|
||||
free_compat_arg_xlat(v);
|
||||
|
||||
tasklet_kill(&v->arch.hvm.assert_evtchn_irq_tasklet);
|
||||
hvm_funcs.vcpu_destroy(v);
|
||||
alternative_vcall(hvm_funcs.vcpu_destroy, v);
|
||||
|
||||
vlapic_destroy(v);
|
||||
|
||||
@@ -3874,7 +3875,7 @@ enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack)
|
||||
!(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) )
|
||||
return hvm_intblk_rflags_ie;
|
||||
|
||||
intr_shadow = hvm_funcs.get_interrupt_shadow(v);
|
||||
intr_shadow = alternative_call(hvm_funcs.get_interrupt_shadow, v);
|
||||
|
||||
if ( intr_shadow & (HVM_INTR_SHADOW_STI|HVM_INTR_SHADOW_MOV_SS) )
|
||||
return hvm_intblk_shadow;
|
||||
@@ -3990,7 +3991,7 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip)
|
||||
hvm_set_segment_register(v, x86_seg_idtr, ®);
|
||||
|
||||
if ( hvm_funcs.tsc_scaling.setup )
|
||||
hvm_funcs.tsc_scaling.setup(v);
|
||||
alternative_vcall(hvm_funcs.tsc_scaling.setup, v);
|
||||
|
||||
/* Sync AP's TSC with BSP's. */
|
||||
v->arch.hvm.cache_tsc_offset =
|
||||
|
||||
@@ -54,8 +54,7 @@ nestedhvm_vcpu_reset(struct vcpu *v)
|
||||
|
||||
hvm_asid_flush_vcpu_asid(&nv->nv_n2asid);
|
||||
|
||||
if ( hvm_funcs.nhvm_vcpu_reset )
|
||||
hvm_funcs.nhvm_vcpu_reset(v);
|
||||
alternative_vcall(hvm_funcs.nhvm_vcpu_reset, v);
|
||||
|
||||
/* vcpu is in host mode */
|
||||
nestedhvm_vcpu_exit_guestmode(v);
|
||||
@@ -64,14 +63,14 @@ nestedhvm_vcpu_reset(struct vcpu *v)
|
||||
int
|
||||
nestedhvm_vcpu_initialise(struct vcpu *v)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
int rc;
|
||||
|
||||
if ( !shadow_io_bitmap[0] )
|
||||
return -ENOMEM;
|
||||
|
||||
if ( !hvm_funcs.nhvm_vcpu_initialise ||
|
||||
((rc = hvm_funcs.nhvm_vcpu_initialise(v)) != 0) )
|
||||
return rc;
|
||||
rc = alternative_call(hvm_funcs.nhvm_vcpu_initialise, v);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
nestedhvm_vcpu_reset(v);
|
||||
return 0;
|
||||
@@ -80,8 +79,7 @@ nestedhvm_vcpu_initialise(struct vcpu *v)
|
||||
void
|
||||
nestedhvm_vcpu_destroy(struct vcpu *v)
|
||||
{
|
||||
if ( hvm_funcs.nhvm_vcpu_destroy )
|
||||
hvm_funcs.nhvm_vcpu_destroy(v);
|
||||
alternative_vcall(hvm_funcs.nhvm_vcpu_destroy, v);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -561,13 +561,12 @@ static inline void hvm_invlpg(struct vcpu *v, unsigned long linear)
|
||||
|
||||
static inline int hvm_cpu_up(void)
|
||||
{
|
||||
return (hvm_funcs.cpu_up ? hvm_funcs.cpu_up() : 0);
|
||||
return alternative_call(hvm_funcs.cpu_up);
|
||||
}
|
||||
|
||||
static inline void hvm_cpu_down(void)
|
||||
{
|
||||
if ( hvm_funcs.cpu_down )
|
||||
hvm_funcs.cpu_down();
|
||||
alternative_vcall(hvm_funcs.cpu_down);
|
||||
}
|
||||
|
||||
static inline unsigned int hvm_get_insn_bytes(struct vcpu *v, uint8_t *buf)
|
||||
@@ -601,7 +600,7 @@ static inline void hvm_invalidate_regs_fields(struct cpu_user_regs *regs)
|
||||
static inline int nhvm_vcpu_vmexit_event(
|
||||
struct vcpu *v, const struct x86_event *event)
|
||||
{
|
||||
return hvm_funcs.nhvm_vcpu_vmexit_event(v, event);
|
||||
return alternative_call(hvm_funcs.nhvm_vcpu_vmexit_event, v, event);
|
||||
}
|
||||
|
||||
/* returns l1 guest's cr3 that points to the page table used to
|
||||
@@ -609,45 +608,46 @@ static inline int nhvm_vcpu_vmexit_event(
|
||||
*/
|
||||
static inline uint64_t nhvm_vcpu_p2m_base(struct vcpu *v)
|
||||
{
|
||||
return hvm_funcs.nhvm_vcpu_p2m_base(v);
|
||||
return alternative_call(hvm_funcs.nhvm_vcpu_p2m_base, v);
|
||||
}
|
||||
|
||||
/* returns true, when l1 guest intercepts the specified trap */
|
||||
static inline bool_t nhvm_vmcx_guest_intercepts_event(
|
||||
struct vcpu *v, unsigned int vector, int errcode)
|
||||
{
|
||||
return hvm_funcs.nhvm_vmcx_guest_intercepts_event(v, vector, errcode);
|
||||
return alternative_call(hvm_funcs.nhvm_vmcx_guest_intercepts_event, v,
|
||||
vector, errcode);
|
||||
}
|
||||
|
||||
/* returns true when l1 guest wants to use hap to run l2 guest */
|
||||
static inline bool_t nhvm_vmcx_hap_enabled(struct vcpu *v)
|
||||
{
|
||||
return hvm_funcs.nhvm_vmcx_hap_enabled(v);
|
||||
return alternative_call(hvm_funcs.nhvm_vmcx_hap_enabled, v);
|
||||
}
|
||||
|
||||
/* interrupt */
|
||||
static inline enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v)
|
||||
{
|
||||
return hvm_funcs.nhvm_intr_blocked(v);
|
||||
return alternative_call(hvm_funcs.nhvm_intr_blocked, v);
|
||||
}
|
||||
|
||||
static inline int nhvm_hap_walk_L1_p2m(
|
||||
struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa, unsigned int *page_order,
|
||||
uint8_t *p2m_acc, struct npfec npfec)
|
||||
{
|
||||
return hvm_funcs.nhvm_hap_walk_L1_p2m(
|
||||
return alternative_call(hvm_funcs.nhvm_hap_walk_L1_p2m,
|
||||
v, L2_gpa, L1_gpa, page_order, p2m_acc, npfec);
|
||||
}
|
||||
|
||||
static inline void hvm_enable_msr_interception(struct domain *d, uint32_t msr)
|
||||
{
|
||||
hvm_funcs.enable_msr_interception(d, msr);
|
||||
alternative_vcall(hvm_funcs.enable_msr_interception, d, msr);
|
||||
}
|
||||
|
||||
static inline bool_t hvm_is_singlestep_supported(void)
|
||||
{
|
||||
return (hvm_funcs.is_singlestep_supported &&
|
||||
hvm_funcs.is_singlestep_supported());
|
||||
alternative_call(hvm_funcs.is_singlestep_supported));
|
||||
}
|
||||
|
||||
static inline bool hvm_hap_supported(void)
|
||||
@@ -665,14 +665,14 @@ static inline bool hvm_altp2m_supported(void)
|
||||
static inline void altp2m_vcpu_update_p2m(struct vcpu *v)
|
||||
{
|
||||
if ( hvm_funcs.altp2m_vcpu_update_p2m )
|
||||
hvm_funcs.altp2m_vcpu_update_p2m(v);
|
||||
alternative_vcall(hvm_funcs.altp2m_vcpu_update_p2m, v);
|
||||
}
|
||||
|
||||
/* updates VMCS fields related to VMFUNC and #VE */
|
||||
static inline void altp2m_vcpu_update_vmfunc_ve(struct vcpu *v)
|
||||
{
|
||||
if ( hvm_funcs.altp2m_vcpu_update_vmfunc_ve )
|
||||
hvm_funcs.altp2m_vcpu_update_vmfunc_ve(v);
|
||||
alternative_vcall(hvm_funcs.altp2m_vcpu_update_vmfunc_ve, v);
|
||||
}
|
||||
|
||||
/* emulates #VE */
|
||||
@@ -680,7 +680,7 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v)
|
||||
{
|
||||
if ( hvm_funcs.altp2m_vcpu_emulate_ve )
|
||||
{
|
||||
hvm_funcs.altp2m_vcpu_emulate_ve(v);
|
||||
alternative_vcall(hvm_funcs.altp2m_vcpu_emulate_ve, v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -689,7 +689,7 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v)
|
||||
static inline int hvm_vmtrace_control(struct vcpu *v, bool enable, bool reset)
|
||||
{
|
||||
if ( hvm_funcs.vmtrace_control )
|
||||
return hvm_funcs.vmtrace_control(v, enable, reset);
|
||||
return alternative_call(hvm_funcs.vmtrace_control, v, enable, reset);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -698,7 +698,7 @@ static inline int hvm_vmtrace_control(struct vcpu *v, bool enable, bool reset)
|
||||
static inline int hvm_vmtrace_output_position(struct vcpu *v, uint64_t *pos)
|
||||
{
|
||||
if ( hvm_funcs.vmtrace_output_position )
|
||||
return hvm_funcs.vmtrace_output_position(v, pos);
|
||||
return alternative_call(hvm_funcs.vmtrace_output_position, v, pos);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -707,7 +707,7 @@ static inline int hvm_vmtrace_set_option(
|
||||
struct vcpu *v, uint64_t key, uint64_t value)
|
||||
{
|
||||
if ( hvm_funcs.vmtrace_set_option )
|
||||
return hvm_funcs.vmtrace_set_option(v, key, value);
|
||||
return alternative_call(hvm_funcs.vmtrace_set_option, v, key, value);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -716,7 +716,7 @@ static inline int hvm_vmtrace_get_option(
|
||||
struct vcpu *v, uint64_t key, uint64_t *value)
|
||||
{
|
||||
if ( hvm_funcs.vmtrace_get_option )
|
||||
return hvm_funcs.vmtrace_get_option(v, key, value);
|
||||
return alternative_call(hvm_funcs.vmtrace_get_option, v, key, value);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -724,7 +724,7 @@ static inline int hvm_vmtrace_get_option(
|
||||
static inline int hvm_vmtrace_reset(struct vcpu *v)
|
||||
{
|
||||
if ( hvm_funcs.vmtrace_reset )
|
||||
return hvm_funcs.vmtrace_reset(v);
|
||||
return alternative_call(hvm_funcs.vmtrace_reset, v);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@@ -270,7 +270,8 @@ int arch_monitor_domctl_event(struct domain *d,
|
||||
ad->monitor.descriptor_access_enabled = requested_status;
|
||||
|
||||
for_each_vcpu ( d, v )
|
||||
hvm_funcs.set_descriptor_access_exiting(v, requested_status);
|
||||
alternative_vcall(hvm_funcs.set_descriptor_access_exiting, v,
|
||||
requested_status);
|
||||
|
||||
domain_unpause(d);
|
||||
break;
|
||||
|
||||
@@ -204,7 +204,7 @@ void vm_event_fill_regs(vm_event_request_t *req)
|
||||
ASSERT(is_hvm_vcpu(curr));
|
||||
|
||||
/* Architecture-specific vmcs/vmcb bits */
|
||||
hvm_funcs.save_cpu_ctxt(curr, &ctxt);
|
||||
alternative_vcall(hvm_funcs.save_cpu_ctxt, curr, &ctxt);
|
||||
|
||||
req->data.regs.x86.rax = regs->rax;
|
||||
req->data.regs.x86.rcx = regs->rcx;
|
||||
|
||||