Skip to content

Commit 37cb0c7

Browse files
committed
Merge tag 'hyperv-fixes-signed-20241217' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv fixes from Wei Liu: - Various fixes to Hyper-V tools in the kernel tree (Dexuan Cui, Olaf Hering, Vitaly Kuznetsov) - Fix a bug in the Hyper-V TSC page based sched_clock() (Naman Jain) - Two bug fixes in the Hyper-V utility functions (Michael Kelley) - Convert open-coded timeouts to secs_to_jiffies() in Hyper-V drivers (Easwar Hariharan) * tag 'hyperv-fixes-signed-20241217' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: tools/hv: reduce resource usage in hv_kvp_daemon tools/hv: add a .gitignore file tools/hv: reduce resouce usage in hv_get_dns_info helper hv/hv_kvp_daemon: Pass NIC name to hv_get_dns_info as well Drivers: hv: util: Avoid accessing a ringbuffer not initialized yet Drivers: hv: util: Don't force error code to ENODEV in util_probe() tools/hv: terminate fcopy daemon if read from uio fails drivers: hv: Convert open-coded timeouts to secs_to_jiffies() tools: hv: change permissions of NetworkManager configuration file x86/hyperv: Fix hv tsc page based sched_clock for hibernation tools: hv: Fix a complier warning in the fcopy uio daemon
2 parents 349f008 + 175c71c commit 37cb0c7

File tree

15 files changed

+125
-25
lines changed

15 files changed

+125
-25
lines changed

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,63 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs)
223223
hyperv_cleanup();
224224
}
225225
#endif /* CONFIG_CRASH_DUMP */
226+
227+
static u64 hv_ref_counter_at_suspend;
228+
static void (*old_save_sched_clock_state)(void);
229+
static void (*old_restore_sched_clock_state)(void);
230+
231+
/*
232+
* Hyper-V clock counter resets during hibernation. Save and restore clock
233+
* offset during suspend/resume, while also considering the time passed
234+
* before suspend. This is to make sure that sched_clock using hv tsc page
235+
* based clocksource, proceeds from where it left off during suspend and
236+
* it shows correct time for the timestamps of kernel messages after resume.
237+
*/
238+
static void save_hv_clock_tsc_state(void)
239+
{
240+
hv_ref_counter_at_suspend = hv_read_reference_counter();
241+
}
242+
243+
static void restore_hv_clock_tsc_state(void)
244+
{
245+
/*
246+
* Adjust the offsets used by hv tsc clocksource to
247+
* account for the time spent before hibernation.
248+
* adjusted value = reference counter (time) at suspend
249+
* - reference counter (time) now.
250+
*/
251+
hv_adj_sched_clock_offset(hv_ref_counter_at_suspend - hv_read_reference_counter());
252+
}
253+
254+
/*
255+
* Functions to override save_sched_clock_state and restore_sched_clock_state
256+
* functions of x86_platform. The Hyper-V clock counter is reset during
257+
* suspend-resume and the offset used to measure time needs to be
258+
* corrected, post resume.
259+
*/
260+
static void hv_save_sched_clock_state(void)
261+
{
262+
old_save_sched_clock_state();
263+
save_hv_clock_tsc_state();
264+
}
265+
266+
static void hv_restore_sched_clock_state(void)
267+
{
268+
restore_hv_clock_tsc_state();
269+
old_restore_sched_clock_state();
270+
}
271+
272+
static void __init x86_setup_ops_for_tsc_pg_clock(void)
273+
{
274+
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
275+
return;
276+
277+
old_save_sched_clock_state = x86_platform.save_sched_clock_state;
278+
x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
279+
280+
old_restore_sched_clock_state = x86_platform.restore_sched_clock_state;
281+
x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
282+
}
226283
#endif /* CONFIG_HYPERV */
227284

228285
static uint32_t __init ms_hyperv_platform(void)
@@ -579,6 +636,7 @@ static void __init ms_hyperv_init_platform(void)
579636

580637
/* Register Hyper-V specific clocksource */
581638
hv_init_clocksource();
639+
x86_setup_ops_for_tsc_pg_clock();
582640
hv_vtl_init_platform();
583641
#endif
584642
/*

drivers/clocksource/hyperv_timer.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
#include <asm/mshyperv.h>
2828

2929
static struct clock_event_device __percpu *hv_clock_event;
30-
static u64 hv_sched_clock_offset __ro_after_init;
30+
/* Note: offset can hold negative values after hibernation. */
31+
static u64 hv_sched_clock_offset __read_mostly;
3132

3233
/*
3334
* If false, we're using the old mechanism for stimer0 interrupts
@@ -470,6 +471,17 @@ static void resume_hv_clock_tsc(struct clocksource *arg)
470471
hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
471472
}
472473

474+
/*
475+
* Called during resume from hibernation, from overridden
476+
* x86_platform.restore_sched_clock_state routine. This is to adjust offsets
477+
* used to calculate time for hv tsc page based sched_clock, to account for
478+
* time spent before hibernation.
479+
*/
480+
void hv_adj_sched_clock_offset(u64 offset)
481+
{
482+
hv_sched_clock_offset -= offset;
483+
}
484+
473485
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
474486
static int hv_cs_enable(struct clocksource *cs)
475487
{

drivers/hv/hv_balloon.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
756756
* adding succeeded, it is ok to proceed even if the memory was
757757
* not onlined in time.
758758
*/
759-
wait_for_completion_timeout(&dm_device.ol_waitevent, 5 * HZ);
759+
wait_for_completion_timeout(&dm_device.ol_waitevent, secs_to_jiffies(5));
760760
post_status(&dm_device);
761761
}
762762
}
@@ -1373,7 +1373,8 @@ static int dm_thread_func(void *dm_dev)
13731373
struct hv_dynmem_device *dm = dm_dev;
13741374

13751375
while (!kthread_should_stop()) {
1376-
wait_for_completion_interruptible_timeout(&dm_device.config_event, 1 * HZ);
1376+
wait_for_completion_interruptible_timeout(&dm_device.config_event,
1377+
secs_to_jiffies(1));
13771378
/*
13781379
* The host expects us to post information on the memory
13791380
* pressure every second.
@@ -1748,7 +1749,7 @@ static int balloon_connect_vsp(struct hv_device *dev)
17481749
if (ret)
17491750
goto out;
17501751

1751-
t = wait_for_completion_timeout(&dm_device.host_event, 5 * HZ);
1752+
t = wait_for_completion_timeout(&dm_device.host_event, secs_to_jiffies(5));
17521753
if (t == 0) {
17531754
ret = -ETIMEDOUT;
17541755
goto out;
@@ -1806,7 +1807,7 @@ static int balloon_connect_vsp(struct hv_device *dev)
18061807
if (ret)
18071808
goto out;
18081809

1809-
t = wait_for_completion_timeout(&dm_device.host_event, 5 * HZ);
1810+
t = wait_for_completion_timeout(&dm_device.host_event, secs_to_jiffies(5));
18101811
if (t == 0) {
18111812
ret = -ETIMEDOUT;
18121813
goto out;

drivers/hv/hv_kvp.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ void hv_kvp_onchannelcallback(void *context)
655655
if (host_negotiatied == NEGO_NOT_STARTED) {
656656
host_negotiatied = NEGO_IN_PROGRESS;
657657
schedule_delayed_work(&kvp_host_handshake_work,
658-
HV_UTIL_NEGO_TIMEOUT * HZ);
658+
secs_to_jiffies(HV_UTIL_NEGO_TIMEOUT));
659659
}
660660
return;
661661
}
@@ -724,7 +724,7 @@ void hv_kvp_onchannelcallback(void *context)
724724
*/
725725
schedule_work(&kvp_sendkey_work);
726726
schedule_delayed_work(&kvp_timeout_work,
727-
HV_UTIL_TIMEOUT * HZ);
727+
secs_to_jiffies(HV_UTIL_TIMEOUT));
728728

729729
return;
730730

@@ -767,6 +767,12 @@ hv_kvp_init(struct hv_util_service *srv)
767767
*/
768768
kvp_transaction.state = HVUTIL_DEVICE_INIT;
769769

770+
return 0;
771+
}
772+
773+
int
774+
hv_kvp_init_transport(void)
775+
{
770776
hvt = hvutil_transport_init(kvp_devname, CN_KVP_IDX, CN_KVP_VAL,
771777
kvp_on_msg, kvp_on_reset);
772778
if (!hvt)

drivers/hv/hv_snapshot.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ static void vss_send_op(void)
193193
vss_transaction.state = HVUTIL_USERSPACE_REQ;
194194

195195
schedule_delayed_work(&vss_timeout_work, op == VSS_OP_FREEZE ?
196-
VSS_FREEZE_TIMEOUT * HZ : HV_UTIL_TIMEOUT * HZ);
196+
secs_to_jiffies(VSS_FREEZE_TIMEOUT) :
197+
secs_to_jiffies(HV_UTIL_TIMEOUT));
197198

198199
rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
199200
if (rc) {
@@ -388,6 +389,12 @@ hv_vss_init(struct hv_util_service *srv)
388389
*/
389390
vss_transaction.state = HVUTIL_DEVICE_INIT;
390391

392+
return 0;
393+
}
394+
395+
int
396+
hv_vss_init_transport(void)
397+
{
391398
hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
392399
vss_on_msg, vss_on_reset);
393400
if (!hvt) {

drivers/hv/hv_util.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static struct hv_util_service util_heartbeat = {
141141
static struct hv_util_service util_kvp = {
142142
.util_cb = hv_kvp_onchannelcallback,
143143
.util_init = hv_kvp_init,
144+
.util_init_transport = hv_kvp_init_transport,
144145
.util_pre_suspend = hv_kvp_pre_suspend,
145146
.util_pre_resume = hv_kvp_pre_resume,
146147
.util_deinit = hv_kvp_deinit,
@@ -149,6 +150,7 @@ static struct hv_util_service util_kvp = {
149150
static struct hv_util_service util_vss = {
150151
.util_cb = hv_vss_onchannelcallback,
151152
.util_init = hv_vss_init,
153+
.util_init_transport = hv_vss_init_transport,
152154
.util_pre_suspend = hv_vss_pre_suspend,
153155
.util_pre_resume = hv_vss_pre_resume,
154156
.util_deinit = hv_vss_deinit,
@@ -590,10 +592,8 @@ static int util_probe(struct hv_device *dev,
590592
srv->channel = dev->channel;
591593
if (srv->util_init) {
592594
ret = srv->util_init(srv);
593-
if (ret) {
594-
ret = -ENODEV;
595+
if (ret)
595596
goto error1;
596-
}
597597
}
598598

599599
/*
@@ -613,6 +613,13 @@ static int util_probe(struct hv_device *dev,
613613
if (ret)
614614
goto error;
615615

616+
if (srv->util_init_transport) {
617+
ret = srv->util_init_transport();
618+
if (ret) {
619+
vmbus_close(dev->channel);
620+
goto error;
621+
}
622+
}
616623
return 0;
617624

618625
error:

drivers/hv/hyperv_vmbus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,14 @@ void vmbus_on_event(unsigned long data);
370370
void vmbus_on_msg_dpc(unsigned long data);
371371

372372
int hv_kvp_init(struct hv_util_service *srv);
373+
int hv_kvp_init_transport(void);
373374
void hv_kvp_deinit(void);
374375
int hv_kvp_pre_suspend(void);
375376
int hv_kvp_pre_resume(void);
376377
void hv_kvp_onchannelcallback(void *context);
377378

378379
int hv_vss_init(struct hv_util_service *srv);
380+
int hv_vss_init_transport(void);
379381
void hv_vss_deinit(void);
380382
int hv_vss_pre_suspend(void);
381383
int hv_vss_pre_resume(void);

drivers/hv/vmbus_drv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2507,7 +2507,7 @@ static int vmbus_bus_resume(struct device *dev)
25072507
vmbus_request_offers();
25082508

25092509
if (wait_for_completion_timeout(
2510-
&vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
2510+
&vmbus_connection.ready_for_resume_event, secs_to_jiffies(10)) == 0)
25112511
pr_err("Some vmbus device is missing after suspending?\n");
25122512

25132513
/* Reset the event for the next suspend. */

include/clocksource/hyperv_timer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ extern void hv_remap_tsc_clocksource(void);
3838
extern unsigned long hv_get_tsc_pfn(void);
3939
extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void);
4040

41+
extern void hv_adj_sched_clock_offset(u64 offset);
42+
4143
static __always_inline bool
4244
hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg,
4345
u64 *cur_tsc, u64 *time)

include/linux/hyperv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,7 @@ struct hv_util_service {
15591559
void *channel;
15601560
void (*util_cb)(void *);
15611561
int (*util_init)(struct hv_util_service *);
1562+
int (*util_init_transport)(void);
15621563
void (*util_deinit)(void);
15631564
int (*util_pre_suspend)(void);
15641565
int (*util_pre_resume)(void);

0 commit comments

Comments
 (0)