mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +00:00
hyperv-fixes for v6.13-rc4
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEIbPD0id6easf0xsudhRwX5BBoF4FAmdhxFsTHHdlaS5saXVA a2VybmVsLm9yZwAKCRB2FHBfkEGgXmGuB/0ZsXKBh9eCZnmVSZwdVkcSeE/HEHHc K5qeIxjqirAzajvLbAtgnTQpi5w0kLYYOT/X/8b6L1nnefcfk1cz5cbyQKxXx7J6 Zuob5KpjX7FtJbMc7QQtzrLyApw2k2OYe1QPCRxuWkYzQjaus/6kM27ivjjYFqDs Qv6IKCcebomAbJTN8IwF38KsFQ2JS3moWr+kcVyna7+Kg1ymEto2QlnI01Z+M1n7 BUYvLgYUD/5HzbNjqC0HysUuX5PsVQ45OsmTgjkvs/XzLcAGGEHJGrJHJkEccx7H AsiNzHoB6wUrFhCAX7IPCSE0g9vjtwI21ozqYllzOTa/Q5KnUE+q9fhJ =Fw3U -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
37cb0c76ac
@ -223,6 +223,63 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs)
|
||||
hyperv_cleanup();
|
||||
}
|
||||
#endif /* CONFIG_CRASH_DUMP */
|
||||
|
||||
static u64 hv_ref_counter_at_suspend;
|
||||
static void (*old_save_sched_clock_state)(void);
|
||||
static void (*old_restore_sched_clock_state)(void);
|
||||
|
||||
/*
|
||||
* Hyper-V clock counter resets during hibernation. Save and restore clock
|
||||
* offset during suspend/resume, while also considering the time passed
|
||||
* before suspend. This is to make sure that sched_clock using hv tsc page
|
||||
* based clocksource, proceeds from where it left off during suspend and
|
||||
* it shows correct time for the timestamps of kernel messages after resume.
|
||||
*/
|
||||
static void save_hv_clock_tsc_state(void)
|
||||
{
|
||||
hv_ref_counter_at_suspend = hv_read_reference_counter();
|
||||
}
|
||||
|
||||
static void restore_hv_clock_tsc_state(void)
|
||||
{
|
||||
/*
|
||||
* Adjust the offsets used by hv tsc clocksource to
|
||||
* account for the time spent before hibernation.
|
||||
* adjusted value = reference counter (time) at suspend
|
||||
* - reference counter (time) now.
|
||||
*/
|
||||
hv_adj_sched_clock_offset(hv_ref_counter_at_suspend - hv_read_reference_counter());
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to override save_sched_clock_state and restore_sched_clock_state
|
||||
* functions of x86_platform. The Hyper-V clock counter is reset during
|
||||
* suspend-resume and the offset used to measure time needs to be
|
||||
* corrected, post resume.
|
||||
*/
|
||||
static void hv_save_sched_clock_state(void)
|
||||
{
|
||||
old_save_sched_clock_state();
|
||||
save_hv_clock_tsc_state();
|
||||
}
|
||||
|
||||
static void hv_restore_sched_clock_state(void)
|
||||
{
|
||||
restore_hv_clock_tsc_state();
|
||||
old_restore_sched_clock_state();
|
||||
}
|
||||
|
||||
static void __init x86_setup_ops_for_tsc_pg_clock(void)
|
||||
{
|
||||
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
|
||||
return;
|
||||
|
||||
old_save_sched_clock_state = x86_platform.save_sched_clock_state;
|
||||
x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
|
||||
|
||||
old_restore_sched_clock_state = x86_platform.restore_sched_clock_state;
|
||||
x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
|
||||
}
|
||||
#endif /* CONFIG_HYPERV */
|
||||
|
||||
static uint32_t __init ms_hyperv_platform(void)
|
||||
@ -579,6 +636,7 @@ static void __init ms_hyperv_init_platform(void)
|
||||
|
||||
/* Register Hyper-V specific clocksource */
|
||||
hv_init_clocksource();
|
||||
x86_setup_ops_for_tsc_pg_clock();
|
||||
hv_vtl_init_platform();
|
||||
#endif
|
||||
/*
|
||||
|
@ -27,7 +27,8 @@
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
static struct clock_event_device __percpu *hv_clock_event;
|
||||
static u64 hv_sched_clock_offset __ro_after_init;
|
||||
/* Note: offset can hold negative values after hibernation. */
|
||||
static u64 hv_sched_clock_offset __read_mostly;
|
||||
|
||||
/*
|
||||
* If false, we're using the old mechanism for stimer0 interrupts
|
||||
@ -470,6 +471,17 @@ static void resume_hv_clock_tsc(struct clocksource *arg)
|
||||
hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during resume from hibernation, from overridden
|
||||
* x86_platform.restore_sched_clock_state routine. This is to adjust offsets
|
||||
* used to calculate time for hv tsc page based sched_clock, to account for
|
||||
* time spent before hibernation.
|
||||
*/
|
||||
void hv_adj_sched_clock_offset(u64 offset)
|
||||
{
|
||||
hv_sched_clock_offset -= offset;
|
||||
}
|
||||
|
||||
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
|
||||
static int hv_cs_enable(struct clocksource *cs)
|
||||
{
|
||||
|
@ -756,7 +756,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
|
||||
* adding succeeded, it is ok to proceed even if the memory was
|
||||
* not onlined in time.
|
||||
*/
|
||||
wait_for_completion_timeout(&dm_device.ol_waitevent, 5 * HZ);
|
||||
wait_for_completion_timeout(&dm_device.ol_waitevent, secs_to_jiffies(5));
|
||||
post_status(&dm_device);
|
||||
}
|
||||
}
|
||||
@ -1373,7 +1373,8 @@ static int dm_thread_func(void *dm_dev)
|
||||
struct hv_dynmem_device *dm = dm_dev;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
wait_for_completion_interruptible_timeout(&dm_device.config_event, 1 * HZ);
|
||||
wait_for_completion_interruptible_timeout(&dm_device.config_event,
|
||||
secs_to_jiffies(1));
|
||||
/*
|
||||
* The host expects us to post information on the memory
|
||||
* pressure every second.
|
||||
@ -1748,7 +1749,7 @@ static int balloon_connect_vsp(struct hv_device *dev)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
t = wait_for_completion_timeout(&dm_device.host_event, 5 * HZ);
|
||||
t = wait_for_completion_timeout(&dm_device.host_event, secs_to_jiffies(5));
|
||||
if (t == 0) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
@ -1806,7 +1807,7 @@ static int balloon_connect_vsp(struct hv_device *dev)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
t = wait_for_completion_timeout(&dm_device.host_event, 5 * HZ);
|
||||
t = wait_for_completion_timeout(&dm_device.host_event, secs_to_jiffies(5));
|
||||
if (t == 0) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
|
@ -655,7 +655,7 @@ void hv_kvp_onchannelcallback(void *context)
|
||||
if (host_negotiatied == NEGO_NOT_STARTED) {
|
||||
host_negotiatied = NEGO_IN_PROGRESS;
|
||||
schedule_delayed_work(&kvp_host_handshake_work,
|
||||
HV_UTIL_NEGO_TIMEOUT * HZ);
|
||||
secs_to_jiffies(HV_UTIL_NEGO_TIMEOUT));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -724,7 +724,7 @@ void hv_kvp_onchannelcallback(void *context)
|
||||
*/
|
||||
schedule_work(&kvp_sendkey_work);
|
||||
schedule_delayed_work(&kvp_timeout_work,
|
||||
HV_UTIL_TIMEOUT * HZ);
|
||||
secs_to_jiffies(HV_UTIL_TIMEOUT));
|
||||
|
||||
return;
|
||||
|
||||
@ -767,6 +767,12 @@ hv_kvp_init(struct hv_util_service *srv)
|
||||
*/
|
||||
kvp_transaction.state = HVUTIL_DEVICE_INIT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hv_kvp_init_transport(void)
|
||||
{
|
||||
hvt = hvutil_transport_init(kvp_devname, CN_KVP_IDX, CN_KVP_VAL,
|
||||
kvp_on_msg, kvp_on_reset);
|
||||
if (!hvt)
|
||||
|
@ -193,7 +193,8 @@ static void vss_send_op(void)
|
||||
vss_transaction.state = HVUTIL_USERSPACE_REQ;
|
||||
|
||||
schedule_delayed_work(&vss_timeout_work, op == VSS_OP_FREEZE ?
|
||||
VSS_FREEZE_TIMEOUT * HZ : HV_UTIL_TIMEOUT * HZ);
|
||||
secs_to_jiffies(VSS_FREEZE_TIMEOUT) :
|
||||
secs_to_jiffies(HV_UTIL_TIMEOUT));
|
||||
|
||||
rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
|
||||
if (rc) {
|
||||
@ -388,6 +389,12 @@ hv_vss_init(struct hv_util_service *srv)
|
||||
*/
|
||||
vss_transaction.state = HVUTIL_DEVICE_INIT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hv_vss_init_transport(void)
|
||||
{
|
||||
hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
|
||||
vss_on_msg, vss_on_reset);
|
||||
if (!hvt) {
|
||||
|
@ -141,6 +141,7 @@ static struct hv_util_service util_heartbeat = {
|
||||
static struct hv_util_service util_kvp = {
|
||||
.util_cb = hv_kvp_onchannelcallback,
|
||||
.util_init = hv_kvp_init,
|
||||
.util_init_transport = hv_kvp_init_transport,
|
||||
.util_pre_suspend = hv_kvp_pre_suspend,
|
||||
.util_pre_resume = hv_kvp_pre_resume,
|
||||
.util_deinit = hv_kvp_deinit,
|
||||
@ -149,6 +150,7 @@ static struct hv_util_service util_kvp = {
|
||||
static struct hv_util_service util_vss = {
|
||||
.util_cb = hv_vss_onchannelcallback,
|
||||
.util_init = hv_vss_init,
|
||||
.util_init_transport = hv_vss_init_transport,
|
||||
.util_pre_suspend = hv_vss_pre_suspend,
|
||||
.util_pre_resume = hv_vss_pre_resume,
|
||||
.util_deinit = hv_vss_deinit,
|
||||
@ -590,11 +592,9 @@ static int util_probe(struct hv_device *dev,
|
||||
srv->channel = dev->channel;
|
||||
if (srv->util_init) {
|
||||
ret = srv->util_init(srv);
|
||||
if (ret) {
|
||||
ret = -ENODEV;
|
||||
if (ret)
|
||||
goto error1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The set of services managed by the util driver are not performance
|
||||
@ -613,6 +613,13 @@ static int util_probe(struct hv_device *dev,
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (srv->util_init_transport) {
|
||||
ret = srv->util_init_transport();
|
||||
if (ret) {
|
||||
vmbus_close(dev->channel);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -370,12 +370,14 @@ void vmbus_on_event(unsigned long data);
|
||||
void vmbus_on_msg_dpc(unsigned long data);
|
||||
|
||||
int hv_kvp_init(struct hv_util_service *srv);
|
||||
int hv_kvp_init_transport(void);
|
||||
void hv_kvp_deinit(void);
|
||||
int hv_kvp_pre_suspend(void);
|
||||
int hv_kvp_pre_resume(void);
|
||||
void hv_kvp_onchannelcallback(void *context);
|
||||
|
||||
int hv_vss_init(struct hv_util_service *srv);
|
||||
int hv_vss_init_transport(void);
|
||||
void hv_vss_deinit(void);
|
||||
int hv_vss_pre_suspend(void);
|
||||
int hv_vss_pre_resume(void);
|
||||
|
@ -2507,7 +2507,7 @@ static int vmbus_bus_resume(struct device *dev)
|
||||
vmbus_request_offers();
|
||||
|
||||
if (wait_for_completion_timeout(
|
||||
&vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
|
||||
&vmbus_connection.ready_for_resume_event, secs_to_jiffies(10)) == 0)
|
||||
pr_err("Some vmbus device is missing after suspending?\n");
|
||||
|
||||
/* Reset the event for the next suspend. */
|
||||
|
@ -38,6 +38,8 @@ 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);
|
||||
|
||||
extern void hv_adj_sched_clock_offset(u64 offset);
|
||||
|
||||
static __always_inline bool
|
||||
hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg,
|
||||
u64 *cur_tsc, u64 *time)
|
||||
|
@ -1559,6 +1559,7 @@ struct hv_util_service {
|
||||
void *channel;
|
||||
void (*util_cb)(void *);
|
||||
int (*util_init)(struct hv_util_service *);
|
||||
int (*util_init_transport)(void);
|
||||
void (*util_deinit)(void);
|
||||
int (*util_pre_suspend)(void);
|
||||
int (*util_pre_resume)(void);
|
||||
|
3
tools/hv/.gitignore
vendored
Normal file
3
tools/hv/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
hv_fcopy_uio_daemon
|
||||
hv_kvp_daemon
|
||||
hv_vss_daemon
|
@ -35,8 +35,6 @@
|
||||
#define WIN8_SRV_MINOR 1
|
||||
#define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
|
||||
|
||||
#define MAX_FOLDER_NAME 15
|
||||
#define MAX_PATH_LEN 15
|
||||
#define FCOPY_UIO "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/uio"
|
||||
|
||||
#define FCOPY_VER_COUNT 1
|
||||
@ -51,7 +49,7 @@ static const int fw_versions[] = {
|
||||
|
||||
#define HV_RING_SIZE 0x4000 /* 16KB ring buffer size */
|
||||
|
||||
unsigned char desc[HV_RING_SIZE];
|
||||
static unsigned char desc[HV_RING_SIZE];
|
||||
|
||||
static int target_fd;
|
||||
static char target_fname[PATH_MAX];
|
||||
@ -409,8 +407,8 @@ int main(int argc, char *argv[])
|
||||
struct vmbus_br txbr, rxbr;
|
||||
void *ring;
|
||||
uint32_t len = HV_RING_SIZE;
|
||||
char uio_name[MAX_FOLDER_NAME] = {0};
|
||||
char uio_dev_path[MAX_PATH_LEN] = {0};
|
||||
char uio_name[NAME_MAX] = {0};
|
||||
char uio_dev_path[PATH_MAX] = {0};
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
@ -468,8 +466,10 @@ int main(int argc, char *argv[])
|
||||
*/
|
||||
ret = pread(fcopy_fd, &tmp, sizeof(int), 0);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "pread failed: %s", strerror(errno));
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
syslog(LOG_ERR, "pread failed: %s", strerror(errno));
|
||||
goto close;
|
||||
}
|
||||
|
||||
len = HV_RING_SIZE;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# This example script parses /etc/resolv.conf to retrive DNS information.
|
||||
# In the interest of keeping the KVP daemon code free of distro specific
|
||||
@ -10,4 +10,4 @@
|
||||
# this script can be based on the Network Manager APIs for retrieving DNS
|
||||
# entries.
|
||||
|
||||
cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }'
|
||||
exec awk '/^nameserver/ { print $2 }' /etc/resolv.conf 2>/dev/null
|
||||
|
@ -725,7 +725,7 @@ static void kvp_get_ipconfig_info(char *if_name,
|
||||
* .
|
||||
*/
|
||||
|
||||
sprintf(cmd, KVP_SCRIPTS_PATH "%s", "hv_get_dns_info");
|
||||
sprintf(cmd, "exec %s %s", KVP_SCRIPTS_PATH "hv_get_dns_info", if_name);
|
||||
|
||||
/*
|
||||
* Execute the command to gather DNS info.
|
||||
@ -742,7 +742,7 @@ static void kvp_get_ipconfig_info(char *if_name,
|
||||
* Enabled: DHCP enabled.
|
||||
*/
|
||||
|
||||
sprintf(cmd, KVP_SCRIPTS_PATH "%s %s", "hv_get_dhcp_info", if_name);
|
||||
sprintf(cmd, "exec %s %s", KVP_SCRIPTS_PATH "hv_get_dhcp_info", if_name);
|
||||
|
||||
file = popen(cmd, "r");
|
||||
if (file == NULL)
|
||||
@ -1606,8 +1606,9 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* invoke the external script to do its magic.
|
||||
*/
|
||||
|
||||
str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s",
|
||||
"hv_set_ifconfig", if_filename, nm_filename);
|
||||
str_len = snprintf(cmd, sizeof(cmd), "exec %s %s %s",
|
||||
KVP_SCRIPTS_PATH "hv_set_ifconfig",
|
||||
if_filename, nm_filename);
|
||||
/*
|
||||
* This is a little overcautious, but it's necessary to suppress some
|
||||
* false warnings from gcc 8.0.1.
|
||||
|
@ -81,7 +81,7 @@ echo "ONBOOT=yes" >> $1
|
||||
|
||||
cp $1 /etc/sysconfig/network-scripts/
|
||||
|
||||
chmod 600 $2
|
||||
umask 0177
|
||||
interface=$(echo $2 | awk -F - '{ print $2 }')
|
||||
filename="${2##*/}"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user