Message ID | 166742685995.205987.1519185062889413335.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp168586wru; Wed, 2 Nov 2022 15:10:21 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4EGouW23CgnmUNJ2oqVY+Sl1PdAPssZNNhL+kZXramvMKiZwt4xewWjsnWY6Z3njmpmXAt X-Received: by 2002:a17:907:7203:b0:7a5:b062:2338 with SMTP id dr3-20020a170907720300b007a5b0622338mr26472053ejc.8.1667427021145; Wed, 02 Nov 2022 15:10:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667427021; cv=none; d=google.com; s=arc-20160816; b=OTqbxRbMQuNofGvJlb8ewzCKMBjZfBO5IItBYWwcBDhZSnp4oH9qvscr8twNxhLxQh ff2gKi+x2kJyjbTkK1pXLtu3Y2C5K7bxAEWqP/IO8s/zmTOWaBJi3xk/3xtlJ2vFJMhz /54s022T71Vf1HmYWQhJOTHzaqK7cKY1snLgopgP2Th8vtPRMpLEoZH+DZb8PnJRLTaM yZmhtR71UKo7HKLm2GJC8L26BgppKn5KEDr7r/XH+JRFh3LxmurOVuTfVLNoDwlwzc1q ndaC33y+49/HsLq4mcYXfEglfhKTF9NwU1lxQmH+yHTzveTMZMrAqwj0dWQLRFephqSv ofrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:to:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:from:subject :dkim-signature:dkim-filter; bh=/w1bIAu1uE35eBnnjmkdkpZrmD4gzFMKCaktzjEiFKw=; b=PFyW/No0x5lwz99Lupdd4AXR7J2WMpE2KOO7epKoAOmWVqm8WNWhZkS919idTefxes KQn8XOyYbZ1vT5BSRyajVGZrmJSHXTZMpbsTUsAqCzuNMM4XGffqM8cj0k8q8hnaDKkm rR5TFmIBlUMmkc+dxdq0WWDtUWvN5SL3qrMvxEjHEwdec2nmMuqfie3paKwG1MyAniKG pMM/M8gYl/nw6D4x8k6KKb3L91IRdyVD5JsPLLg6jY48xgb5Ta0W4a/zC9ahabvhe23P I+ttBIQfVYky13r2dUyXmqZy00QDVwUCu2ZTmLGdVZ4yVifg7kX8nl45yjaz2aWXLLCa PvPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=dkg+2GWG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o13-20020a170906974d00b0078e11e9286csi22163120ejy.195.2022.11.02.15.09.53; Wed, 02 Nov 2022 15:10:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=dkg+2GWG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231316AbiKBWIK (ORCPT <rfc822;yves.mi.zy@gmail.com> + 99 others); Wed, 2 Nov 2022 18:08:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231392AbiKBWHw (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 2 Nov 2022 18:07:52 -0400 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 6F11D101D5; Wed, 2 Nov 2022 15:07:40 -0700 (PDT) Received: from skinsburskii-cloud-desktop.internal.cloudapp.net (unknown [20.120.152.163]) by linux.microsoft.com (Postfix) with ESMTPSA id 0CA2020C333D; Wed, 2 Nov 2022 15:07:40 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 0CA2020C333D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1667426860; bh=/w1bIAu1uE35eBnnjmkdkpZrmD4gzFMKCaktzjEiFKw=; h=Subject:From:Cc:Date:In-Reply-To:References:From; b=dkg+2GWGEEjIBEpdjNlPAVmvIfzWgFYbWZ7tlZ6KiJ2c6xQs604sNbUZsOPJ3IdUI quVV0ndbH7I4T0D0nF02H8a3Nakh1gPhhjLOtABbAQD+sJKyJwGBh2PRkCjTNCCbXX wECnftPwDFChfEWPegi4df+w/XtFPgEcrC/58g9I= Subject: [PATCH v2 4/4] drivers/clocksource/hyper-v: Add TSC page support for root partition From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Cc: Stanislav Kinsburskiy <stanislav.kinsburskiy@gmail.com>, "K. Y. Srinivasan" <kys@microsoft.com>, Haiyang Zhang <haiyangz@microsoft.com>, Wei Liu <wei.liu@kernel.org>, Dexuan Cui <decui@microsoft.com>, Thomas Gleixner <tglx@linutronix.de>, Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>, Dave Hansen <dave.hansen@linux.intel.com>, x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>, Daniel Lezcano <daniel.lezcano@linaro.org>, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org Date: Wed, 02 Nov 2022 22:07:39 +0000 Message-ID: <166742685995.205987.1519185062889413335.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net> In-Reply-To: <166742670556.205987.18227942188746093700.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net> References: <166742670556.205987.18227942188746093700.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net> User-Agent: StGit/0.19 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-18.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,ENV_AND_HDR_SPF_MATCH,MISSING_HEADERS, RCVD_IN_DNSWL_MED,SPF_HELO_PASS,SPF_PASS,USER_IN_DEF_DKIM_WL, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748423956121264749?= X-GMAIL-MSGID: =?utf-8?q?1748423956121264749?= |
Series |
hyper-v: Introduce TSC page for root partition
|
|
Commit Message
Stanislav Kinsburskii
Nov. 2, 2022, 10:07 p.m. UTC
From: Stanislav Kinsburskiy <stanislav.kinsburskiy@gmail.com> Microsoft Hypervisor root partition has to map the TSC page specified by the hypervisor, instead of providing the page to the hypervisor like it's done in the guest partitions. However, it's too early to map the page when the clock is initialized, so, the actual mapping is happening later. Signed-off-by: Stanislav Kinsburskiy <stanislav.kinsburskiy@gmail.com> CC: "K. Y. Srinivasan" <kys@microsoft.com> CC: Haiyang Zhang <haiyangz@microsoft.com> CC: Wei Liu <wei.liu@kernel.org> CC: Dexuan Cui <decui@microsoft.com> CC: Thomas Gleixner <tglx@linutronix.de> CC: Ingo Molnar <mingo@redhat.com> CC: Borislav Petkov <bp@alien8.de> CC: Dave Hansen <dave.hansen@linux.intel.com> CC: x86@kernel.org CC: "H. Peter Anvin" <hpa@zytor.com> CC: Daniel Lezcano <daniel.lezcano@linaro.org> CC: linux-hyperv@vger.kernel.org CC: linux-kernel@vger.kernel.org --- arch/x86/hyperv/hv_init.c | 2 ++ drivers/clocksource/hyperv_timer.c | 37 +++++++++++++++++++++++++++--------- include/clocksource/hyperv_timer.h | 1 + 3 files changed, 31 insertions(+), 9 deletions(-)
Comments
From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Wednesday, November 2, 2022 3:08 PM > > Microsoft Hypervisor root partition has to map the TSC page specified > by the hypervisor, instead of providing the page to the hypervisor like > it's done in the guest partitions. > > However, it's too early to map the page when the clock is initialized, so, the > actual mapping is happening later. > > Signed-off-by: Stanislav Kinsburskiy <stanislav.kinsburskiy@gmail.com> > CC: "K. Y. Srinivasan" <kys@microsoft.com> > CC: Haiyang Zhang <haiyangz@microsoft.com> > CC: Wei Liu <wei.liu@kernel.org> > CC: Dexuan Cui <decui@microsoft.com> > CC: Thomas Gleixner <tglx@linutronix.de> > CC: Ingo Molnar <mingo@redhat.com> > CC: Borislav Petkov <bp@alien8.de> > CC: Dave Hansen <dave.hansen@linux.intel.com> > CC: x86@kernel.org > CC: "H. Peter Anvin" <hpa@zytor.com> > CC: Daniel Lezcano <daniel.lezcano@linaro.org> > CC: linux-hyperv@vger.kernel.org > CC: linux-kernel@vger.kernel.org > --- > arch/x86/hyperv/hv_init.c | 2 ++ > drivers/clocksource/hyperv_timer.c | 37 +++++++++++++++++++++++++++--------- > include/clocksource/hyperv_timer.h | 1 + > 3 files changed, 31 insertions(+), 9 deletions(-) > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > index f49bc3ec76e6..89954490af93 100644 > --- a/arch/x86/hyperv/hv_init.c > +++ b/arch/x86/hyperv/hv_init.c > @@ -464,6 +464,8 @@ void __init hyperv_init(void) > BUG_ON(!src); > memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE); > memunmap(src); > + > + hv_remap_tsc_clocksource(); > } else { > hypercall_msr.guest_physical_address = > vmalloc_to_pfn(hv_hypercall_pg); > wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); > diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c > index 635c14c1e3bf..ec76303b2a76 100644 > --- a/drivers/clocksource/hyperv_timer.c > +++ b/drivers/clocksource/hyperv_timer.c > @@ -508,9 +508,6 @@ static bool __init hv_init_tsc_clocksource(void) > if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) > return false; > > - if (hv_root_partition) > - return false; > - > /* > * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly > * handles frequency and offset changes due to live migration, > @@ -528,16 +525,22 @@ static bool __init hv_init_tsc_clocksource(void) > } > > hv_read_reference_counter = read_hv_clock_tsc; > - tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); > > /* > - * The Hyper-V TLFS specifies to preserve the value of reserved > - * bits in registers. So read the existing value, preserve the > - * low order 12 bits, and add in the guest physical address > - * (which already has at least the low 12 bits set to zero since > - * it is page aligned). Also set the "enable" bit, which is bit 0. > + * TSC page mapping works differently in root and guest partitions. > + * - In guest partition the guest PFN has to be passed to the > + * hypervisor. > + * - In root partition it's other way around: it has to map the PFN > + * provided by the hypervisor. > + * But it can't be mapped right here as it's too early and MMU isn't > + * ready yet. So, we only set the enable bit here and will remap the > + * page later in hv_remap_tsc_clocksource(). > */ > tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); > + if (hv_root_partition) > + tsc_pfn = tsc_msr.pfn; > + else > + tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); Same problem here with setting tsc_pfn to a guest PFN, which may be Different from what Hyper-V is expecting as a PFN two lines below. I know the above line was just carried over from Anirudh's previous patch set, but I was thinking you would fix this issue. :-) > tsc_msr.enable = 1; > tsc_msr.pfn = tsc_pfn; > hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); > @@ -572,3 +575,19 @@ void __init hv_init_clocksource(void) > hv_sched_clock_offset = hv_read_reference_counter(); > hv_setup_sched_clock(read_hv_sched_clock_msr); > } > + > +void __init hv_remap_tsc_clocksource(void) > +{ > + if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) > + return; > + > + if (!hv_root_partition) { > + WARN(1, "%s: attempt to remap TSC page in guest partition\n", > + __func__); > + return; > + } > + > + tsc_page = memremap(__pfn_to_phys(tsc_pfn), sizeof(tsc_pg), MEMREMAP_WB); Note that use of __pfn_to_phys() is at risk of being wrong depending on whether you decide to keep a guest PFN or a Hyper-V PFN in tsc_pfn. > + if (!tsc_page) > + pr_err("Failed to remap Hyper-V TSC page.\n"); > +} > diff --git a/include/clocksource/hyperv_timer.h > b/include/clocksource/hyperv_timer.h > index 3078d23faaea..783701a2102d 100644 > --- a/include/clocksource/hyperv_timer.h > +++ b/include/clocksource/hyperv_timer.h > @@ -31,6 +31,7 @@ extern void hv_stimer_global_cleanup(void); > extern void hv_stimer0_isr(void); > > extern void hv_init_clocksource(void); > +extern void hv_remap_tsc_clocksource(void); > > extern unsigned long hv_get_tsc_pfn(void); > extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void); >
O Wed, Nov 02, 2022 at 11:36:45PM +0000, Michael Kelley (LINUX) wrote: > From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Wednesday, November 2, 2022 3:08 PM > > > > Microsoft Hypervisor root partition has to map the TSC page specified > > by the hypervisor, instead of providing the page to the hypervisor like > > it's done in the guest partitions. > > > > However, it's too early to map the page when the clock is initialized, so, the > > actual mapping is happening later. > > > > Signed-off-by: Stanislav Kinsburskiy <stanislav.kinsburskiy@gmail.com> > > CC: "K. Y. Srinivasan" <kys@microsoft.com> > > CC: Haiyang Zhang <haiyangz@microsoft.com> > > CC: Wei Liu <wei.liu@kernel.org> > > CC: Dexuan Cui <decui@microsoft.com> > > CC: Thomas Gleixner <tglx@linutronix.de> > > CC: Ingo Molnar <mingo@redhat.com> > > CC: Borislav Petkov <bp@alien8.de> > > CC: Dave Hansen <dave.hansen@linux.intel.com> > > CC: x86@kernel.org > > CC: "H. Peter Anvin" <hpa@zytor.com> > > CC: Daniel Lezcano <daniel.lezcano@linaro.org> > > CC: linux-hyperv@vger.kernel.org > > CC: linux-kernel@vger.kernel.org > > --- > > arch/x86/hyperv/hv_init.c | 2 ++ > > drivers/clocksource/hyperv_timer.c | 37 +++++++++++++++++++++++++++--------- > > include/clocksource/hyperv_timer.h | 1 + > > 3 files changed, 31 insertions(+), 9 deletions(-) > > > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > > index f49bc3ec76e6..89954490af93 100644 > > --- a/arch/x86/hyperv/hv_init.c > > +++ b/arch/x86/hyperv/hv_init.c > > @@ -464,6 +464,8 @@ void __init hyperv_init(void) > > BUG_ON(!src); > > memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE); > > memunmap(src); > > + > > + hv_remap_tsc_clocksource(); > > } else { > > hypercall_msr.guest_physical_address = > > vmalloc_to_pfn(hv_hypercall_pg); > > wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); > > diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c > > index 635c14c1e3bf..ec76303b2a76 100644 > > --- a/drivers/clocksource/hyperv_timer.c > > +++ b/drivers/clocksource/hyperv_timer.c > > @@ -508,9 +508,6 @@ static bool __init hv_init_tsc_clocksource(void) > > if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) > > return false; > > > > - if (hv_root_partition) > > - return false; > > - > > /* > > * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly > > * handles frequency and offset changes due to live migration, > > @@ -528,16 +525,22 @@ static bool __init hv_init_tsc_clocksource(void) > > } > > > > hv_read_reference_counter = read_hv_clock_tsc; > > - tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); > > > > /* > > - * The Hyper-V TLFS specifies to preserve the value of reserved > > - * bits in registers. So read the existing value, preserve the > > - * low order 12 bits, and add in the guest physical address > > - * (which already has at least the low 12 bits set to zero since > > - * it is page aligned). Also set the "enable" bit, which is bit 0. > > + * TSC page mapping works differently in root and guest partitions. > > + * - In guest partition the guest PFN has to be passed to the > > + * hypervisor. > > + * - In root partition it's other way around: it has to map the PFN > > + * provided by the hypervisor. > > + * But it can't be mapped right here as it's too early and MMU isn't > > + * ready yet. So, we only set the enable bit here and will remap the > > + * page later in hv_remap_tsc_clocksource(). > > */ > > tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); > > + if (hv_root_partition) > > + tsc_pfn = tsc_msr.pfn; > > + else > > + tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); > > Same problem here with setting tsc_pfn to a guest PFN, which may be > Different from what Hyper-V is expecting as a PFN two lines below. I know > the above line was just carried over from Anirudh's previous patch set, > but I was thinking you would fix this issue. :-) > Fair call. I guess Anirudh has addressed it himself, so I'm going to rebase on his fix. > > tsc_msr.enable = 1; > > tsc_msr.pfn = tsc_pfn; > > hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); > > @@ -572,3 +575,19 @@ void __init hv_init_clocksource(void) > > hv_sched_clock_offset = hv_read_reference_counter(); > > hv_setup_sched_clock(read_hv_sched_clock_msr); > > } > > + > > +void __init hv_remap_tsc_clocksource(void) > > +{ > > + if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) > > + return; > > + > > + if (!hv_root_partition) { > > + WARN(1, "%s: attempt to remap TSC page in guest partition\n", > > + __func__); > > + return; > > + } > > + > > + tsc_page = memremap(__pfn_to_phys(tsc_pfn), sizeof(tsc_pg), MEMREMAP_WB); > > Note that use of __pfn_to_phys() is at risk of being wrong depending on whether > you decide to keep a guest PFN or a Hyper-V PFN in tsc_pfn. > It's Hyperv-V PFN that is stored in the variable (to match the MSR value for the root partition). I guess this approach will workd regardless of the guest page size. Stas
From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Thursday, November 3, 2022 10:01 AM > > O Wed, Nov 02, 2022 at 11:36:45PM +0000, Michael Kelley (LINUX) wrote: > > From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Sent: Wednesday, > November 2, 2022 3:08 PM > > > > > > Microsoft Hypervisor root partition has to map the TSC page specified > > > by the hypervisor, instead of providing the page to the hypervisor like > > > it's done in the guest partitions. > > > > > > However, it's too early to map the page when the clock is initialized, so, the > > > actual mapping is happening later. > > > > > > Signed-off-by: Stanislav Kinsburskiy <stanislav.kinsburskiy@gmail.com> > > > CC: "K. Y. Srinivasan" <kys@microsoft.com> > > > CC: Haiyang Zhang <haiyangz@microsoft.com> > > > CC: Wei Liu <wei.liu@kernel.org> > > > CC: Dexuan Cui <decui@microsoft.com> > > > CC: Thomas Gleixner <tglx@linutronix.de> > > > CC: Ingo Molnar <mingo@redhat.com> > > > CC: Borislav Petkov <bp@alien8.de> > > > CC: Dave Hansen <dave.hansen@linux.intel.com> > > > CC: x86@kernel.org > > > CC: "H. Peter Anvin" <hpa@zytor.com> > > > CC: Daniel Lezcano <daniel.lezcano@linaro.org> > > > CC: linux-hyperv@vger.kernel.org > > > CC: linux-kernel@vger.kernel.org > > > --- > > > arch/x86/hyperv/hv_init.c | 2 ++ > > > drivers/clocksource/hyperv_timer.c | 37 +++++++++++++++++++++++++++------ > --- > > > include/clocksource/hyperv_timer.h | 1 + > > > 3 files changed, 31 insertions(+), 9 deletions(-) > > > > > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > > > index f49bc3ec76e6..89954490af93 100644 > > > --- a/arch/x86/hyperv/hv_init.c > > > +++ b/arch/x86/hyperv/hv_init.c > > > @@ -464,6 +464,8 @@ void __init hyperv_init(void) > > > BUG_ON(!src); > > > memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE); > > > memunmap(src); > > > + > > > + hv_remap_tsc_clocksource(); > > > } else { > > > hypercall_msr.guest_physical_address = > > > vmalloc_to_pfn(hv_hypercall_pg); > > > wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); > > > diff --git a/drivers/clocksource/hyperv_timer.c > b/drivers/clocksource/hyperv_timer.c > > > index 635c14c1e3bf..ec76303b2a76 100644 > > > --- a/drivers/clocksource/hyperv_timer.c > > > +++ b/drivers/clocksource/hyperv_timer.c > > > @@ -508,9 +508,6 @@ static bool __init hv_init_tsc_clocksource(void) > > > if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) > > > return false; > > > > > > - if (hv_root_partition) > > > - return false; > > > - > > > /* > > > * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly > > > * handles frequency and offset changes due to live migration, > > > @@ -528,16 +525,22 @@ static bool __init hv_init_tsc_clocksource(void) > > > } > > > > > > hv_read_reference_counter = read_hv_clock_tsc; > > > - tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); > > > > > > /* > > > - * The Hyper-V TLFS specifies to preserve the value of reserved > > > - * bits in registers. So read the existing value, preserve the > > > - * low order 12 bits, and add in the guest physical address > > > - * (which already has at least the low 12 bits set to zero since > > > - * it is page aligned). Also set the "enable" bit, which is bit 0. > > > + * TSC page mapping works differently in root and guest partitions. > > > + * - In guest partition the guest PFN has to be passed to the > > > + * hypervisor. > > > + * - In root partition it's other way around: it has to map the PFN > > > + * provided by the hypervisor. > > > + * But it can't be mapped right here as it's too early and MMU isn't > > > + * ready yet. So, we only set the enable bit here and will remap the > > > + * page later in hv_remap_tsc_clocksource(). > > > */ > > > tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); > > > + if (hv_root_partition) > > > + tsc_pfn = tsc_msr.pfn; > > > + else > > > + tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); > > > > Same problem here with setting tsc_pfn to a guest PFN, which may be > > Different from what Hyper-V is expecting as a PFN two lines below. I know > > the above line was just carried over from Anirudh's previous patch set, > > but I was thinking you would fix this issue. :-) > > > > Fair call. I guess Anirudh has addressed it himself, so I'm going to > rebase on his fix. Sounds good. > > > > tsc_msr.enable = 1; > > > tsc_msr.pfn = tsc_pfn; > > > hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); > > > @@ -572,3 +575,19 @@ void __init hv_init_clocksource(void) > > > hv_sched_clock_offset = hv_read_reference_counter(); > > > hv_setup_sched_clock(read_hv_sched_clock_msr); > > > } > > > + > > > +void __init hv_remap_tsc_clocksource(void) > > > +{ > > > + if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) > > > + return; > > > + > > > + if (!hv_root_partition) { > > > + WARN(1, "%s: attempt to remap TSC page in guest partition\n", > > > + __func__); > > > + return; > > > + } > > > + > > > + tsc_page = memremap(__pfn_to_phys(tsc_pfn), sizeof(tsc_pg), MEMREMAP_WB); > > > > Note that use of __pfn_to_phys() is at risk of being wrong depending on whether > > you decide to keep a guest PFN or a Hyper-V PFN in tsc_pfn. > > > > It's Hyperv-V PFN that is stored in the variable (to match the MSR value for the root > partition). I guess this approach will workd regardless of the guest page size. I agree that it's best for tsc_pfn to contain a Hyper-V PFN. But if that's the case, the above use of __pfn_to_phys() won't work since it is expecting a guest PFN as input. Michael
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index f49bc3ec76e6..89954490af93 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -464,6 +464,8 @@ void __init hyperv_init(void) BUG_ON(!src); memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE); memunmap(src); + + hv_remap_tsc_clocksource(); } else { hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index 635c14c1e3bf..ec76303b2a76 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -508,9 +508,6 @@ static bool __init hv_init_tsc_clocksource(void) if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) return false; - if (hv_root_partition) - return false; - /* * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly * handles frequency and offset changes due to live migration, @@ -528,16 +525,22 @@ static bool __init hv_init_tsc_clocksource(void) } hv_read_reference_counter = read_hv_clock_tsc; - tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); /* - * The Hyper-V TLFS specifies to preserve the value of reserved - * bits in registers. So read the existing value, preserve the - * low order 12 bits, and add in the guest physical address - * (which already has at least the low 12 bits set to zero since - * it is page aligned). Also set the "enable" bit, which is bit 0. + * TSC page mapping works differently in root and guest partitions. + * - In guest partition the guest PFN has to be passed to the + * hypervisor. + * - In root partition it's other way around: it has to map the PFN + * provided by the hypervisor. + * But it can't be mapped right here as it's too early and MMU isn't + * ready yet. So, we only set the enable bit here and will remap the + * page later in hv_remap_tsc_clocksource(). */ tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC); + if (hv_root_partition) + tsc_pfn = tsc_msr.pfn; + else + tsc_pfn = __phys_to_pfn(virt_to_phys(tsc_page)); tsc_msr.enable = 1; tsc_msr.pfn = tsc_pfn; hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); @@ -572,3 +575,19 @@ void __init hv_init_clocksource(void) hv_sched_clock_offset = hv_read_reference_counter(); hv_setup_sched_clock(read_hv_sched_clock_msr); } + +void __init hv_remap_tsc_clocksource(void) +{ + if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) + return; + + if (!hv_root_partition) { + WARN(1, "%s: attempt to remap TSC page in guest partition\n", + __func__); + return; + } + + tsc_page = memremap(__pfn_to_phys(tsc_pfn), sizeof(tsc_pg), MEMREMAP_WB); + if (!tsc_page) + pr_err("Failed to remap Hyper-V TSC page.\n"); +} diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h index 3078d23faaea..783701a2102d 100644 --- a/include/clocksource/hyperv_timer.h +++ b/include/clocksource/hyperv_timer.h @@ -31,6 +31,7 @@ extern void hv_stimer_global_cleanup(void); extern void hv_stimer0_isr(void); extern void hv_init_clocksource(void); +extern void hv_remap_tsc_clocksource(void); extern unsigned long hv_get_tsc_pfn(void); extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void);