Commit 024ff300 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hyperv-fixes-signed-20230804' of...

Merge tag 'hyperv-fixes-signed-20230804' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv fixes from Wei Liu:

 - Fix a bug in a python script for Hyper-V (Ani Sinha)

 - Workaround a bug in Hyper-V when IBT is enabled (Michael Kelley)

 - Fix an issue parsing MP table when Linux runs in VTL2 (Saurabh
   Sengar)

 - Several cleanup patches (Nischala Yelchuri, Kameron Carr, YueHaibing,
   ZhiHu)

* tag 'hyperv-fixes-signed-20230804' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
  Drivers: hv: vmbus: Remove unused extern declaration vmbus_ontimer()
  x86/hyperv: add noop functions to x86_init mpparse functions
  vmbus_testing: fix wrong python syntax for integer value comparison
  x86/hyperv: fix a warning in mshyperv.h
  x86/hyperv: Disable IBT when hypercall page lacks ENDBR instruction
  x86/hyperv: Improve code for referencing hyperv_pcpu_input_arg
  Drivers: hv: Change hv_free_hyperv_page() to take void * argument
parents e661f98c 6ad0f2f9
...@@ -107,7 +107,6 @@ static bool cpu_is_self(int cpu) ...@@ -107,7 +107,6 @@ static bool cpu_is_self(int cpu)
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
bool exclude_self) bool exclude_self)
{ {
struct hv_send_ipi_ex **arg;
struct hv_send_ipi_ex *ipi_arg; struct hv_send_ipi_ex *ipi_arg;
unsigned long flags; unsigned long flags;
int nr_bank = 0; int nr_bank = 0;
...@@ -117,9 +116,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, ...@@ -117,9 +116,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
return false; return false;
local_irq_save(flags); local_irq_save(flags);
arg = (struct hv_send_ipi_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); ipi_arg = *this_cpu_ptr(hyperv_pcpu_input_arg);
ipi_arg = *arg;
if (unlikely(!ipi_arg)) if (unlikely(!ipi_arg))
goto ipi_mask_ex_done; goto ipi_mask_ex_done;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/sev.h> #include <asm/sev.h>
#include <asm/ibt.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/hyperv-tlfs.h> #include <asm/hyperv-tlfs.h>
#include <asm/mshyperv.h> #include <asm/mshyperv.h>
...@@ -471,6 +472,26 @@ void __init hyperv_init(void) ...@@ -471,6 +472,26 @@ void __init hyperv_init(void)
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
} }
/*
* Some versions of Hyper-V that provide IBT in guest VMs have a bug
* in that there's no ENDBR64 instruction at the entry to the
* hypercall page. Because hypercalls are invoked via an indirect call
* to the hypercall page, all hypercall attempts fail when IBT is
* enabled, and Linux panics. For such buggy versions, disable IBT.
*
* Fixed versions of Hyper-V always provide ENDBR64 on the hypercall
* page, so if future Linux kernel versions enable IBT for 32-bit
* builds, additional hypercall page hackery will be required here
* to provide an ENDBR32.
*/
#ifdef CONFIG_X86_KERNEL_IBT
if (cpu_feature_enabled(X86_FEATURE_IBT) &&
*(u32 *)hv_hypercall_pg != gen_endbr()) {
setup_clear_cpu_cap(X86_FEATURE_IBT);
pr_warn("Hyper-V: Disabling IBT because of Hyper-V bug\n");
}
#endif
/* /*
* hyperv_init() is called before LAPIC is initialized: see * hyperv_init() is called before LAPIC is initialized: see
* apic_intr_mode_init() -> x86_platform.apic_post_init() and * apic_intr_mode_init() -> x86_platform.apic_post_init() and
......
...@@ -25,6 +25,10 @@ void __init hv_vtl_init_platform(void) ...@@ -25,6 +25,10 @@ void __init hv_vtl_init_platform(void)
x86_init.irqs.pre_vector_init = x86_init_noop; x86_init.irqs.pre_vector_init = x86_init_noop;
x86_init.timers.timer_init = x86_init_noop; x86_init.timers.timer_init = x86_init_noop;
/* Avoid searching for BIOS MP tables */
x86_init.mpparse.find_smp_config = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
x86_platform.get_wallclock = get_rtc_noop; x86_platform.get_wallclock = get_rtc_noop;
x86_platform.set_wallclock = set_rtc_noop; x86_platform.set_wallclock = set_rtc_noop;
x86_platform.get_nmi_reason = hv_get_nmi_reason; x86_platform.get_nmi_reason = hv_get_nmi_reason;
......
...@@ -247,7 +247,7 @@ EXPORT_SYMBOL_GPL(hv_ghcb_msr_read); ...@@ -247,7 +247,7 @@ EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
enum hv_mem_host_visibility visibility) enum hv_mem_host_visibility visibility)
{ {
struct hv_gpa_range_for_visibility **input_pcpu, *input; struct hv_gpa_range_for_visibility *input;
u16 pages_processed; u16 pages_processed;
u64 hv_status; u64 hv_status;
unsigned long flags; unsigned long flags;
...@@ -263,9 +263,8 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], ...@@ -263,9 +263,8 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
} }
local_irq_save(flags); local_irq_save(flags);
input_pcpu = (struct hv_gpa_range_for_visibility **) input = *this_cpu_ptr(hyperv_pcpu_input_arg);
this_cpu_ptr(hyperv_pcpu_input_arg);
input = *input_pcpu;
if (unlikely(!input)) { if (unlikely(!input)) {
local_irq_restore(flags); local_irq_restore(flags);
return -EINVAL; return -EINVAL;
......
...@@ -61,7 +61,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, ...@@ -61,7 +61,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
const struct flush_tlb_info *info) const struct flush_tlb_info *info)
{ {
int cpu, vcpu, gva_n, max_gvas; int cpu, vcpu, gva_n, max_gvas;
struct hv_tlb_flush **flush_pcpu;
struct hv_tlb_flush *flush; struct hv_tlb_flush *flush;
u64 status; u64 status;
unsigned long flags; unsigned long flags;
...@@ -74,10 +73,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, ...@@ -74,10 +73,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
local_irq_save(flags); local_irq_save(flags);
flush_pcpu = (struct hv_tlb_flush **) flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
this_cpu_ptr(hyperv_pcpu_input_arg);
flush = *flush_pcpu;
if (unlikely(!flush)) { if (unlikely(!flush)) {
local_irq_restore(flags); local_irq_restore(flags);
...@@ -178,17 +174,13 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus, ...@@ -178,17 +174,13 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
const struct flush_tlb_info *info) const struct flush_tlb_info *info)
{ {
int nr_bank = 0, max_gvas, gva_n; int nr_bank = 0, max_gvas, gva_n;
struct hv_tlb_flush_ex **flush_pcpu;
struct hv_tlb_flush_ex *flush; struct hv_tlb_flush_ex *flush;
u64 status; u64 status;
if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
return HV_STATUS_INVALID_PARAMETER; return HV_STATUS_INVALID_PARAMETER;
flush_pcpu = (struct hv_tlb_flush_ex **) flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
this_cpu_ptr(hyperv_pcpu_input_arg);
flush = *flush_pcpu;
if (info->mm) { if (info->mm) {
/* /*
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
int hyperv_flush_guest_mapping(u64 as) int hyperv_flush_guest_mapping(u64 as)
{ {
struct hv_guest_mapping_flush **flush_pcpu;
struct hv_guest_mapping_flush *flush; struct hv_guest_mapping_flush *flush;
u64 status; u64 status;
unsigned long flags; unsigned long flags;
...@@ -30,10 +29,7 @@ int hyperv_flush_guest_mapping(u64 as) ...@@ -30,10 +29,7 @@ int hyperv_flush_guest_mapping(u64 as)
local_irq_save(flags); local_irq_save(flags);
flush_pcpu = (struct hv_guest_mapping_flush **) flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
this_cpu_ptr(hyperv_pcpu_input_arg);
flush = *flush_pcpu;
if (unlikely(!flush)) { if (unlikely(!flush)) {
local_irq_restore(flags); local_irq_restore(flags);
...@@ -90,7 +86,6 @@ EXPORT_SYMBOL_GPL(hyperv_fill_flush_guest_mapping_list); ...@@ -90,7 +86,6 @@ EXPORT_SYMBOL_GPL(hyperv_fill_flush_guest_mapping_list);
int hyperv_flush_guest_mapping_range(u64 as, int hyperv_flush_guest_mapping_range(u64 as,
hyperv_fill_flush_list_func fill_flush_list_func, void *data) hyperv_fill_flush_list_func fill_flush_list_func, void *data)
{ {
struct hv_guest_mapping_flush_list **flush_pcpu;
struct hv_guest_mapping_flush_list *flush; struct hv_guest_mapping_flush_list *flush;
u64 status; u64 status;
unsigned long flags; unsigned long flags;
...@@ -102,10 +97,8 @@ int hyperv_flush_guest_mapping_range(u64 as, ...@@ -102,10 +97,8 @@ int hyperv_flush_guest_mapping_range(u64 as,
local_irq_save(flags); local_irq_save(flags);
flush_pcpu = (struct hv_guest_mapping_flush_list **) flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
this_cpu_ptr(hyperv_pcpu_input_arg);
flush = *flush_pcpu;
if (unlikely(!flush)) { if (unlikely(!flush)) {
local_irq_restore(flags); local_irq_restore(flags);
goto fault; goto fault;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/nmi.h> #include <linux/nmi.h>
#include <linux/msi.h> #include <linux/msi.h>
#include <asm/io.h> #include <linux/io.h>
#include <asm/hyperv-tlfs.h> #include <asm/hyperv-tlfs.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include <asm/paravirt.h> #include <asm/paravirt.h>
......
...@@ -209,8 +209,7 @@ int vmbus_connect(void) ...@@ -209,8 +209,7 @@ int vmbus_connect(void)
* Setup the vmbus event connection for channel interrupt * Setup the vmbus event connection for channel interrupt
* abstraction stuff * abstraction stuff
*/ */
vmbus_connection.int_page = vmbus_connection.int_page = hv_alloc_hyperv_zeroed_page();
(void *)hv_alloc_hyperv_zeroed_page();
if (vmbus_connection.int_page == NULL) { if (vmbus_connection.int_page == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto cleanup; goto cleanup;
...@@ -225,8 +224,8 @@ int vmbus_connect(void) ...@@ -225,8 +224,8 @@ int vmbus_connect(void)
* Setup the monitor notification facility. The 1st page for * Setup the monitor notification facility. The 1st page for
* parent->child and the 2nd page for child->parent * parent->child and the 2nd page for child->parent
*/ */
vmbus_connection.monitor_pages[0] = (void *)hv_alloc_hyperv_page(); vmbus_connection.monitor_pages[0] = hv_alloc_hyperv_page();
vmbus_connection.monitor_pages[1] = (void *)hv_alloc_hyperv_page(); vmbus_connection.monitor_pages[1] = hv_alloc_hyperv_page();
if ((vmbus_connection.monitor_pages[0] == NULL) || if ((vmbus_connection.monitor_pages[0] == NULL) ||
(vmbus_connection.monitor_pages[1] == NULL)) { (vmbus_connection.monitor_pages[1] == NULL)) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -333,15 +332,15 @@ void vmbus_disconnect(void) ...@@ -333,15 +332,15 @@ void vmbus_disconnect(void)
destroy_workqueue(vmbus_connection.work_queue); destroy_workqueue(vmbus_connection.work_queue);
if (vmbus_connection.int_page) { if (vmbus_connection.int_page) {
hv_free_hyperv_page((unsigned long)vmbus_connection.int_page); hv_free_hyperv_page(vmbus_connection.int_page);
vmbus_connection.int_page = NULL; vmbus_connection.int_page = NULL;
} }
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1); set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1);
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1); set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1);
hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[0]); hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]); hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
vmbus_connection.monitor_pages[0] = NULL; vmbus_connection.monitor_pages[0] = NULL;
vmbus_connection.monitor_pages[1] = NULL; vmbus_connection.monitor_pages[1] = NULL;
} }
......
...@@ -1628,7 +1628,7 @@ static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info, ...@@ -1628,7 +1628,7 @@ static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info,
WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES); WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order)); WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order));
local_irq_save(flags); local_irq_save(flags);
hint = *(struct hv_memory_hint **)this_cpu_ptr(hyperv_pcpu_input_arg); hint = *this_cpu_ptr(hyperv_pcpu_input_arg);
if (!hint) { if (!hint) {
local_irq_restore(flags); local_irq_restore(flags);
return -ENOSPC; return -ENOSPC;
......
...@@ -115,12 +115,12 @@ void *hv_alloc_hyperv_zeroed_page(void) ...@@ -115,12 +115,12 @@ void *hv_alloc_hyperv_zeroed_page(void)
} }
EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page); EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page);
void hv_free_hyperv_page(unsigned long addr) void hv_free_hyperv_page(void *addr)
{ {
if (PAGE_SIZE == HV_HYP_PAGE_SIZE) if (PAGE_SIZE == HV_HYP_PAGE_SIZE)
free_page(addr); free_page((unsigned long)addr);
else else
kfree((void *)addr); kfree(addr);
} }
EXPORT_SYMBOL_GPL(hv_free_hyperv_page); EXPORT_SYMBOL_GPL(hv_free_hyperv_page);
...@@ -253,7 +253,7 @@ static void hv_kmsg_dump_unregister(void) ...@@ -253,7 +253,7 @@ static void hv_kmsg_dump_unregister(void)
atomic_notifier_chain_unregister(&panic_notifier_list, atomic_notifier_chain_unregister(&panic_notifier_list,
&hyperv_panic_report_block); &hyperv_panic_report_block);
hv_free_hyperv_page((unsigned long)hv_panic_page); hv_free_hyperv_page(hv_panic_page);
hv_panic_page = NULL; hv_panic_page = NULL;
} }
...@@ -270,7 +270,7 @@ static void hv_kmsg_dump_register(void) ...@@ -270,7 +270,7 @@ static void hv_kmsg_dump_register(void)
ret = kmsg_dump_register(&hv_kmsg_dumper); ret = kmsg_dump_register(&hv_kmsg_dumper);
if (ret) { if (ret) {
pr_err("Hyper-V: kmsg dump register error 0x%x\n", ret); pr_err("Hyper-V: kmsg dump register error 0x%x\n", ret);
hv_free_hyperv_page((unsigned long)hv_panic_page); hv_free_hyperv_page(hv_panic_page);
hv_panic_page = NULL; hv_panic_page = NULL;
} }
} }
......
...@@ -190,7 +190,7 @@ int hv_common_cpu_die(unsigned int cpu); ...@@ -190,7 +190,7 @@ int hv_common_cpu_die(unsigned int cpu);
void *hv_alloc_hyperv_page(void); void *hv_alloc_hyperv_page(void);
void *hv_alloc_hyperv_zeroed_page(void); void *hv_alloc_hyperv_zeroed_page(void);
void hv_free_hyperv_page(unsigned long addr); void hv_free_hyperv_page(void *addr);
/** /**
* hv_cpu_number_to_vp_number() - Map CPU to VP. * hv_cpu_number_to_vp_number() - Map CPU to VP.
......
...@@ -1239,9 +1239,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel, ...@@ -1239,9 +1239,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
u32 *buffer_actual_len, u32 *buffer_actual_len,
u64 *requestid); u64 *requestid);
extern void vmbus_ontimer(unsigned long data);
/* Base driver object */ /* Base driver object */
struct hv_driver { struct hv_driver {
const char *name; const char *name;
......
...@@ -164,7 +164,7 @@ def recursive_file_lookup(path, file_map): ...@@ -164,7 +164,7 @@ def recursive_file_lookup(path, file_map):
def get_all_devices_test_status(file_map): def get_all_devices_test_status(file_map):
for device in file_map: for device in file_map:
if (get_test_state(locate_state(device, file_map)) is 1): if (get_test_state(locate_state(device, file_map)) == 1):
print("Testing = ON for: {}" print("Testing = ON for: {}"
.format(device.split("/")[5])) .format(device.split("/")[5]))
else: else:
...@@ -203,7 +203,7 @@ def write_test_files(path, value): ...@@ -203,7 +203,7 @@ def write_test_files(path, value):
def set_test_state(state_path, state_value, quiet): def set_test_state(state_path, state_value, quiet):
write_test_files(state_path, state_value) write_test_files(state_path, state_value)
if (get_test_state(state_path) is 1): if (get_test_state(state_path) == 1):
if (not quiet): if (not quiet):
print("Testing = ON for device: {}" print("Testing = ON for device: {}"
.format(state_path.split("/")[5])) .format(state_path.split("/")[5]))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment