Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions arch/x86/include/asm/mshyperv.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ void hyperv_setup_mmu_ops(void);
void set_hv_tscchange_cb(void (*cb)(void));
void clear_hv_tscchange_cb(void);
void hyperv_stop_tsc_emulation(void);
void hv_save_sched_clock_state(void);
void hv_restore_sched_clock_state(void);
int hyperv_flush_guest_mapping(u64 as);
int hyperv_flush_guest_mapping_range(u64 as,
hyperv_fill_flush_list_func fill_func, void *data);
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/cpu/mshyperv.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,13 @@ static void restore_hv_clock_tsc_state(void)
* suspend-resume and the offset used to measure time needs to be
* corrected, post resume.
*/
static void hv_save_sched_clock_state(void)
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)
void hv_restore_sched_clock_state(void)
{
restore_hv_clock_tsc_state();
old_restore_sched_clock_state();
Expand Down
58 changes: 58 additions & 0 deletions drivers/hv/mshv_vtl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#ifdef CONFIG_X86_64
#include <linux/cleanup.h>
#include <linux/stop_machine.h>

#include <asm/apic.h>
#include <uapi/asm/mtrr.h>
Expand All @@ -42,6 +43,7 @@
#include <asm/vmx.h>

#include "../../kernel/fpu/legacy.h"
#include "../../kernel/time/timekeeping.h"

#endif

Expand Down Expand Up @@ -865,6 +867,55 @@ static int mshv_vtl_ioctl_add_vtl0_mem(struct mshv_vtl *vtl, void __user *arg)
return 0;
}

#ifdef CONFIG_X86_64
static int restore_partition_time_with_cpus_stopped(void *data)
{
struct mshv_partition_time *partition_time = data;
struct hv_input_restore_partition_time *input;
int result = 0;
u64 status;

/* Save current clock state. Other CPUs are waiting in stop code, so no locks are taken. */
sched_clock_suspend();
timekeeping_suspend();
hv_save_sched_clock_state();

/* Interrupts are disabled. Make the hypercall to update the TSC. */
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
input->partition_id = HV_PARTITION_ID_SELF;
input->tsc_sequence = partition_time->tsc_sequence;
input->reserved = 0;
input->reference_time_in_100_ns = partition_time->reference_time_in_100_ns;
input->tsc = partition_time->tsc;
status = hv_do_hypercall(HVCALL_RESTORE_PARTITION_TIME, input, NULL);
if (!hv_result_success(status)) {
pr_err("HVCALL_RESTORE_PARTITION_TIME failed with %#llx\n", status);
result = -EINVAL;
}

/* Restore clock state using current TSC value. */
hv_restore_sched_clock_state();
timekeeping_resume();
sched_clock_resume();

return result;
}

static int mshv_restore_partition_time(void __user *arg)
{
struct mshv_partition_time partition_time;
int ret;

if (copy_from_user(&partition_time, arg, sizeof(partition_time)))
return -EFAULT;

/* Stop other CPUs, using the current one to restore partition time. */
ret = stop_machine(restore_partition_time_with_cpus_stopped, &partition_time,
cpumask_of(raw_smp_processor_id()));
return ret;
}
#endif

static void mshv_vtl_cancel(int cpu)
{
int here = get_cpu();
Expand Down Expand Up @@ -2596,6 +2647,13 @@ mshv_vtl_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
case MSHV_VTL_ADD_VTL0_MEMORY:
ret = mshv_vtl_ioctl_add_vtl0_mem(vtl, (void __user *)arg);
break;

#if defined(CONFIG_X86_64)
case MSHV_RESTORE_PARTITION_TIME:
ret = mshv_restore_partition_time((void __user *)arg);
break;
#endif

#if defined(CONFIG_X86_64) && defined(CONFIG_INTEL_TDX_GUEST)
case MSHV_VTL_TDCALL:
ret = mshv_vtl_ioctl_tdcall((void __user *)arg);
Expand Down
12 changes: 12 additions & 0 deletions include/uapi/hyperv/hvgdk_mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ union hv_hypervisor_version_info {
#define HVCALL_GET_VP_CPUID_VALUES 0x00f4
#define HVCALL_START_VP 0x0099
#define HVCALL_GET_VP_INDEX_FROM_APIC_ID 0x009a
#define HVCALL_RESTORE_PARTITION_TIME 0x0103


/*
* Some macros - i.e. GENMASK_ULL and BIT_ULL - are not currently supported by
Expand Down Expand Up @@ -1310,4 +1312,14 @@ struct hv_input_install_intercept {
union hv_intercept_parameters intercept_parameter;
} __packed;

#if defined(__x86_64__)
struct hv_input_restore_partition_time {
__u64 partition_id;
__u32 tsc_sequence;
__u32 reserved;
__u64 reference_time_in_100_ns;
__u64 tsc;
} __packed;
#endif

#endif /* _UAPI_HV_HVGDK_MINI_H */
8 changes: 8 additions & 0 deletions include/uapi/linux/mshv.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,13 @@ struct mshv_map_device_intr {
__u8 padding[7];
} __packed;

struct mshv_partition_time {
__u32 tsc_sequence;
__u32 reserved;
__u64 reference_time_in_100_ns;
__u64 tsc;
} __packed;

#define MSHV_KICK_CPUS_FLAG_WAIT_FOR_CPUS (1 << 0)
#define MSHV_KICK_CPUS_FLAG_CANCEL_CPU_RUN (1 << 1)

Expand Down Expand Up @@ -371,6 +378,7 @@ struct mshv_map_device_intr {
struct mshv_map_device_intr)

/* For x86-64 only */
#define MSHV_RESTORE_PARTITION_TIME _IOW(MSHV_IOCTL, 0x13, struct mshv_partition_time)
#define MSHV_VTL_GUEST_VSM_VMSA_PFN _IOWR(MSHV_IOCTL, 0x34, __u64)

/* For x86-64 SEV-SNP only */
Expand Down