linux-hyperv.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dexuan Cui <decui@microsoft.com>
To: Michael Kelley <mikelley@microsoft.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"tglx@linutronix.de" <tglx@linutronix.de>,
	"daniel.lezcano@linaro.org" <daniel.lezcano@linaro.org>,
	vkuznets <vkuznets@redhat.com>, KY Srinivasan <kys@microsoft.com>,
	Stephen Hemminger <sthemmin@microsoft.com>,
	"sashal@kernel.org" <sashal@kernel.org>,
	"mingo@redhat.com" <mingo@redhat.com>,
	"bp@alien8.de" <bp@alien8.de>, "hpa@zytor.com" <hpa@zytor.com>,
	"x86@kernel.org" <x86@kernel.org>,
	"will@kernel.org" <will@kernel.org>,
	"Ganapatrao.Kulkarni@cavium.com" <Ganapatrao.Kulkarni@cavium.com>,
	"james.morse@arm.com" <james.morse@arm.com>,
	"steven.price@arm.com" <steven.price@arm.com>,
	"josephl@nvidia.com" <josephl@nvidia.com>,
	"m.szyprowski@samsumg.com" <m.szyprowski@samsumg.com>,
	"linux-hyperv@vger.kernel.org" <linux-hyperv@vger.kernel.org>
Subject: RE: [PATCH 1/1] x86/hyperv: Initialize clockevents earlier in CPU onlining
Date: Tue, 29 Oct 2019 20:33:46 +0000	[thread overview]
Message-ID: <PU1P153MB0169592424FCCD3226B88BEFBF610@PU1P153MB0169.APCP153.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <1572228459-10550-1-git-send-email-mikelley@microsoft.com>

> From: Michael Kelley <mikelley@microsoft.com>
> Sent: Sunday, October 27, 2019 7:10 PM
> ...
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>

Should we add the 2 lines:

Cc: stable@vger.kernel.org
Fixes: fd1fea6834d0 ("clocksource/drivers: Make Hyper-V clocksource ISA agnostic")

fd1fea6834d0() removes the clockevents_unbind_device() call and this patch adds it back.

> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -323,8 +323,15 @@ void __init hyperv_init(void)
> 
>  	x86_init.pci.arch_init = hv_pci_init;
> 
> +	if (hv_stimer_alloc())
> +		goto remove_hypercall_page;
> +

The error handling is imperfect here: when I force hv_stimer_alloc() to return
-ENOMEM, I get a panic in hv_apic_eoi_write(). It looks it is because we have cleared 
the pointer 'hv_vp_assist_page' to NULL, but hv_apic_eoi_write() is still in-use.

In case hv_stimer_alloc() fails, can we set 'direct_mode_enabled' to false
and go on with the legacy Hyper-V timer or LAPIC timer? If not, maybe
we can use a BUG_ON() to explicitly panic?

>  	return;
> 
> +remove_hypercall_page:
> +	hypercall_msr.as_uint64 = 0;
> +	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
> +	hv_hypercall_pg = NULL;
>  remove_cpuhp_state:
>  	cpuhp_remove_state(cpuhp);
>  free_vp_assist_page:

> -void hv_stimer_cleanup(unsigned int cpu)
> +static int hv_stimer_cleanup(unsigned int cpu)
>  {
>  	struct clock_event_device *ce;
> 
>  	/* Turn off clockevent device */
>  	if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) {
>  		ce = per_cpu_ptr(hv_clock_event, cpu);
> +
> +		/*
> +		 * In the legacy case where Direct Mode is not enabled
> +		 * (which can only be on x86/64), stimer cleanup happens
> +		 * relatively early in the CPU offlining process. We
> +		 * must unbind the stimer-based clockevent device so
> +		 * that the LAPIC timer can take over until clockevents
> +		 * are no longer needed in the offlining process. The
> +		 * unbind should not be done when Direct Mode is enabled
> +		 * because we may be on an architecture where there are
> +		 * no other clockevents devices to fallback to.
> +		 */
> +		if (!direct_mode_enabled)
> +			clockevents_unbind_device(ce, cpu);
>  		hv_ce_shutdown(ce);

In the legacy stimer0 mode, IMO this hv_ce_shutdown() is unnecessary, 
because "clockevents_unbind_device(ce, cpu)" automatically calls 
ce->set_state_shutdown(), if ce is active:
clockevents_unbind
   __clockevents_unbind
    clockevents_replace
      tick_install_replacement
        clockevents_exchange_device
          clockevents_switch_state(old, CLOCK_EVT_STATE_DETACHED)
            __clockevents_switch_state

And, in both modes (legacy mode and direct mode), it looks incorrect to
call hv_ce_shutdown() if the current processid id != 'cpu', because
hv_ce_shutdown() -> hv_init_timer() can only access the current CPU's
MSR. Maybe we should use an IPI to run hv_ce_shutdown() on the target
CPU in direct mode?

> -int hv_stimer_alloc(int sint)
> +int hv_stimer_alloc(void)
> ...
> +		ret = cpuhp_setup_state(CPUHP_AP_HYPERV_TIMER_STARTING,
> +				"clockevents/hyperv/stimer:starting",
> +				hv_stimer_init, hv_stimer_cleanup);
> +		if (ret < 0)
> +			goto free_stimer0_irq;
> +		stimer0_cpuhp = ret;
>  	}
> +	return ret;

stimer0_cpuhp is 0 when the call is successful, so IMO the logic in 
hv_stimer_free() is incorrect. Please see below.

>  void hv_stimer_free(void)
>  {
> -	if (direct_mode_enabled && (stimer0_irq != 0)) {
> -		hv_remove_stimer0_irq(stimer0_irq);
> -		stimer0_irq = 0;
> +	if (direct_mode_enabled) {
> +		if (stimer0_cpuhp) {
> +			cpuhp_remove_state(stimer0_cpuhp);
> +			stimer0_cpuhp = 0;
> +		}
> +		if (stimer0_irq) {
> +			hv_remove_stimer0_irq(stimer0_irq);
> +			stimer0_irq = 0;
> +		}
>  	}

IMO this should be 
if (direct_mode_enabled) {
        if (stimer0_cpuhp == 0)
                cpuhp_remove_state(CPUHP_AP_HYPERV_TIMER_STARTING);

        if (stimer0_irq) {
                hv_remove_stimer0_irq(stimer0_irq);
                stimer0_irq = 0;
        }
}

BTW, the default value of 'stimer0_cpuhp' is 0, which means success.
Should we change the default value to a non-zero value, e.g. -1 ?

>  	free_percpu(hv_clock_event);
>  	hv_clock_event = NULL;
> @@ -190,14 +274,11 @@ void hv_stimer_free(void)
>  void hv_stimer_global_cleanup(void)
>  {
>  	int	cpu;
> -	struct clock_event_device *ce;
> 
> -	if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) {
> -		for_each_present_cpu(cpu) {
> -			ce = per_cpu_ptr(hv_clock_event, cpu);
> -			clockevents_unbind_device(ce, cpu);
> -		}
> +	for_each_present_cpu(cpu) {
> +		hv_stimer_cleanup(cpu);

hv_stimer_cleanup() -> hv_ce_shutdown() -> hv_init_timer() can not
access a remote CPU's MSR.

> @@ -2310,7 +2305,6 @@ static void hv_crash_handler(struct pt_regs *regs)
>  	 */
>  	vmbus_connection.conn_state = DISCONNECTED;
>  	cpu = smp_processor_id();
> -	hv_stimer_cleanup(cpu);
>  	hv_synic_cleanup(cpu);
>  	hyperv_cleanup();

Why should we remove the line hv_stimer_cleanup() in the crash handler?
In the crash handler, IMO we'd better disable the timer before we proceed.

Thanks,
-- Dexuan

  reply	other threads:[~2019-10-29 20:35 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-28  2:09 [PATCH 1/1] x86/hyperv: Initialize clockevents earlier in CPU onlining Michael Kelley
2019-10-29 20:33 ` Dexuan Cui [this message]
2019-10-30 20:50   ` Michael Kelley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=PU1P153MB0169592424FCCD3226B88BEFBF610@PU1P153MB0169.APCP153.PROD.OUTLOOK.COM \
    --to=decui@microsoft.com \
    --cc=Ganapatrao.Kulkarni@cavium.com \
    --cc=bp@alien8.de \
    --cc=daniel.lezcano@linaro.org \
    --cc=hpa@zytor.com \
    --cc=james.morse@arm.com \
    --cc=josephl@nvidia.com \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=m.szyprowski@samsumg.com \
    --cc=mikelley@microsoft.com \
    --cc=mingo@redhat.com \
    --cc=sashal@kernel.org \
    --cc=steven.price@arm.com \
    --cc=sthemmin@microsoft.com \
    --cc=tglx@linutronix.de \
    --cc=vkuznets@redhat.com \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).