Skip to content

Commit

Permalink
Merge tag 'hyperv-next-signed-20210426' of git://git.kernel.org/pub/s…
Browse files Browse the repository at this point in the history
…cm/linux/kernel/git/hyperv/linux

Pull Hyper-V updates from Wei Liu:

 - VMBus enhancement

 - Free page reporting support for Hyper-V balloon driver

 - Some patches for running Linux as Arm64 Hyper-V guest

 - A few misc clean-up patches

* tag 'hyperv-next-signed-20210426' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: (30 commits)
  drivers: hv: Create a consistent pattern for checking Hyper-V hypercall status
  x86/hyperv: Move hv_do_rep_hypercall to asm-generic
  video: hyperv_fb: Add ratelimit on error message
  Drivers: hv: vmbus: Increase wait time for VMbus unload
  Drivers: hv: vmbus: Initialize unload_event statically
  Drivers: hv: vmbus: Check for pending channel interrupts before taking a CPU offline
  Drivers: hv: vmbus: Drivers: hv: vmbus: Introduce CHANNELMSG_MODIFYCHANNEL_RESPONSE
  Drivers: hv: vmbus: Introduce and negotiate VMBus protocol version 5.3
  Drivers: hv: vmbus: Use after free in __vmbus_open()
  Drivers: hv: vmbus: remove unused function
  Drivers: hv: vmbus: Remove unused linux/version.h header
  x86/hyperv: remove unused linux/version.h header
  x86/Hyper-V: Support for free page reporting
  x86/hyperv: Fix unused variable 'hi' warning in hv_apic_read
  x86/hyperv: Fix unused variable 'msr_val' warning in hv_qlock_wait
  hv: hyperv.h: a few mundane typo fixes
  drivers: hv: Fix EXPORT_SYMBOL and tab spaces issue
  Drivers: hv: vmbus: Drop error message when 'No request id available'
  asm-generic/hyperv: Add missing function prototypes per -W1 warnings
  clocksource/drivers/hyper-v: Move handling of STIMER0 interrupts
  ...
  • Loading branch information
torvalds committed Apr 26, 2021
2 parents 8e47c5f + 753ed9c commit 4d480db
Show file tree
Hide file tree
Showing 26 changed files with 973 additions and 445 deletions.
18 changes: 11 additions & 7 deletions arch/x86/hyperv/hv_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ static u32 hv_apic_read(u32 reg)
switch (reg) {
case APIC_EOI:
rdmsr(HV_X64_MSR_EOI, reg_val, hi);
(void)hi;
return reg_val;
case APIC_TASKPRI:
rdmsr(HV_X64_MSR_TPR, reg_val, hi);
(void)hi;
return reg_val;

default:
Expand Down Expand Up @@ -103,7 +105,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector)
struct hv_send_ipi_ex *ipi_arg;
unsigned long flags;
int nr_bank = 0;
int ret = 1;
u64 status = HV_STATUS_INVALID_PARAMETER;

if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
return false;
Expand All @@ -128,19 +130,19 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector)
if (!nr_bank)
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;

ret = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
ipi_arg, NULL);

ipi_mask_ex_done:
local_irq_restore(flags);
return ((ret == 0) ? true : false);
return hv_result_success(status);
}

static bool __send_ipi_mask(const struct cpumask *mask, int vector)
{
int cur_cpu, vcpu;
struct hv_send_ipi ipi_arg;
int ret = 1;
u64 status;

trace_hyperv_send_ipi_mask(mask, vector);

Expand Down Expand Up @@ -184,9 +186,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector)
__set_bit(vcpu, (unsigned long *)&ipi_arg.cpu_mask);
}

ret = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
ipi_arg.cpu_mask);
return ((ret == 0) ? true : false);
return hv_result_success(status);

do_ex_hypercall:
return __send_ipi_mask_ex(mask, vector);
Expand All @@ -195,6 +197,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector)
static bool __send_ipi_one(int cpu, int vector)
{
int vp = hv_cpu_number_to_vp_number(cpu);
u64 status;

trace_hyperv_send_ipi_one(cpu, vector);

Expand All @@ -207,7 +210,8 @@ static bool __send_ipi_one(int cpu, int vector)
if (vp >= 64)
return __send_ipi_mask_ex(cpumask_of(cpu), vector);

return !hv_do_fast_hypercall16(HVCALL_SEND_IPI, vector, BIT_ULL(vp));
status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, vector, BIT_ULL(vp));
return hv_result_success(status);
}

static void hv_send_ipi(int cpu, int vector)
Expand Down
106 changes: 53 additions & 53 deletions arch/x86/hyperv/hv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,28 +54,6 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);
u32 hv_max_vp_index;
EXPORT_SYMBOL_GPL(hv_max_vp_index);

void *hv_alloc_hyperv_page(void)
{
BUILD_BUG_ON(PAGE_SIZE != HV_HYP_PAGE_SIZE);

return (void *)__get_free_page(GFP_KERNEL);
}
EXPORT_SYMBOL_GPL(hv_alloc_hyperv_page);

void *hv_alloc_hyperv_zeroed_page(void)
{
BUILD_BUG_ON(PAGE_SIZE != HV_HYP_PAGE_SIZE);

return (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
}
EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page);

void hv_free_hyperv_page(unsigned long addr)
{
free_page(addr);
}
EXPORT_SYMBOL_GPL(hv_free_hyperv_page);

static int hv_cpu_init(unsigned int cpu)
{
u64 msr_vp_index;
Expand All @@ -97,7 +75,7 @@ static int hv_cpu_init(unsigned int cpu)
*output_arg = page_address(pg + 1);
}

hv_get_vp_index(msr_vp_index);
msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);

hv_vp_index[smp_processor_id()] = msr_vp_index;

Expand Down Expand Up @@ -349,7 +327,7 @@ static void __init hv_stimer_setup_percpu_clockev(void)
* Ignore any errors in setting up stimer clockevents
* as we can run with the LAPIC timer as a fallback.
*/
(void)hv_stimer_alloc();
(void)hv_stimer_alloc(false);

/*
* Still register the LAPIC timer, because the direct-mode STIMER is
Expand All @@ -369,7 +347,7 @@ static void __init hv_get_partition_id(void)
local_irq_save(flags);
output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page);
if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS) {
if (!hv_result_success(status)) {
/* No point in proceeding if this failed */
pr_err("Failed to get partition ID: %lld\n", status);
BUG();
Expand Down Expand Up @@ -520,6 +498,8 @@ void __init hyperv_init(void)
x86_init.irqs.create_pci_msi_domain = hv_create_pci_msi_domain;
#endif

/* Query the VMs extended capability once, so that it can be cached. */
hv_query_ext_cap(0);
return;

remove_cpuhp_state:
Expand Down Expand Up @@ -593,33 +573,6 @@ void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
}
EXPORT_SYMBOL_GPL(hyperv_report_panic);

/**
* hyperv_report_panic_msg - report panic message to Hyper-V
* @pa: physical address of the panic page containing the message
* @size: size of the message in the page
*/
void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
{
/*
* P3 to contain the physical address of the panic page & P4 to
* contain the size of the panic data in that page. Rest of the
* registers are no-op when the NOTIFY_MSG flag is set.
*/
wrmsrl(HV_X64_MSR_CRASH_P0, 0);
wrmsrl(HV_X64_MSR_CRASH_P1, 0);
wrmsrl(HV_X64_MSR_CRASH_P2, 0);
wrmsrl(HV_X64_MSR_CRASH_P3, pa);
wrmsrl(HV_X64_MSR_CRASH_P4, size);

/*
* Let Hyper-V know there is crash data available along with
* the panic message.
*/
wrmsrl(HV_X64_MSR_CRASH_CTL,
(HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
}
EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);

bool hv_is_hyperv_initialized(void)
{
union hv_x64_msr_hypercall_contents hypercall_msr;
Expand Down Expand Up @@ -650,7 +603,7 @@ EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);

enum hv_isolation_type hv_get_isolation_type(void)
{
if (!(ms_hyperv.features_b & HV_ISOLATION))
if (!(ms_hyperv.priv_high & HV_ISOLATION))
return HV_ISOLATION_TYPE_NONE;
return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
}
Expand All @@ -661,3 +614,50 @@ bool hv_is_isolation_supported(void)
return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
}
EXPORT_SYMBOL_GPL(hv_is_isolation_supported);

/* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */
bool hv_query_ext_cap(u64 cap_query)
{
/*
* The address of the 'hv_extended_cap' variable will be used as an
* output parameter to the hypercall below and so it should be
* compatible with 'virt_to_phys'. Which means, it's address should be
* directly mapped. Use 'static' to keep it compatible; stack variables
* can be virtually mapped, making them imcompatible with
* 'virt_to_phys'.
* Hypercall input/output addresses should also be 8-byte aligned.
*/
static u64 hv_extended_cap __aligned(8);
static bool hv_extended_cap_queried;
u64 status;

/*
* Querying extended capabilities is an extended hypercall. Check if the
* partition supports extended hypercall, first.
*/
if (!(ms_hyperv.priv_high & HV_ENABLE_EXTENDED_HYPERCALLS))
return false;

/* Extended capabilities do not change at runtime. */
if (hv_extended_cap_queried)
return hv_extended_cap & cap_query;

status = hv_do_hypercall(HV_EXT_CALL_QUERY_CAPABILITIES, NULL,
&hv_extended_cap);

/*
* The query extended capabilities hypercall should not fail under
* any normal circumstances. Avoid repeatedly making the hypercall, on
* error.
*/
hv_extended_cap_queried = true;
status &= HV_HYPERCALL_RESULT_MASK;
if (status != HV_STATUS_SUCCESS) {
pr_err("Hyper-V: Extended query capabilities hypercall failed 0x%llx\n",
status);
return false;
}

return hv_extended_cap & cap_query;
}
EXPORT_SYMBOL_GPL(hv_query_ext_cap);
26 changes: 10 additions & 16 deletions arch/x86/hyperv/hv_proc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/clockchips.h>
Expand Down Expand Up @@ -93,10 +92,9 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY,
page_count, 0, input_page, NULL);
local_irq_restore(flags);

if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS) {
if (!hv_result_success(status)) {
pr_err("Failed to deposit pages: %lld\n", status);
ret = status;
ret = hv_result(status);
goto err_free_allocations;
}

Expand All @@ -122,7 +120,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
struct hv_add_logical_processor_out *output;
u64 status;
unsigned long flags;
int ret = 0;
int ret = HV_STATUS_SUCCESS;
int pxm = node_to_pxm(node);

/*
Expand All @@ -148,13 +146,11 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
input, output);
local_irq_restore(flags);

status &= HV_HYPERCALL_RESULT_MASK;

if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
if (status != HV_STATUS_SUCCESS) {
if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
if (!hv_result_success(status)) {
pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
lp_index, apic_id, status);
ret = status;
ret = hv_result(status);
}
break;
}
Expand All @@ -169,7 +165,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
struct hv_create_vp *input;
u64 status;
unsigned long irq_flags;
int ret = 0;
int ret = HV_STATUS_SUCCESS;
int pxm = node_to_pxm(node);

/* Root VPs don't seem to need pages deposited */
Expand Down Expand Up @@ -200,13 +196,11 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
local_irq_restore(irq_flags);

status &= HV_HYPERCALL_RESULT_MASK;

if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
if (status != HV_STATUS_SUCCESS) {
if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
if (!hv_result_success(status)) {
pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
vp_index, flags, status);
ret = status;
ret = hv_result(status);
}
break;
}
Expand Down
8 changes: 6 additions & 2 deletions arch/x86/hyperv/hv_spinlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ static void hv_qlock_kick(int cpu)

static void hv_qlock_wait(u8 *byte, u8 val)
{
unsigned long msr_val;
unsigned long flags;

if (in_nmi())
Expand All @@ -48,8 +47,13 @@ static void hv_qlock_wait(u8 *byte, u8 val)
/*
* Only issue the rdmsrl() when the lock state has not changed.
*/
if (READ_ONCE(*byte) == val)
if (READ_ONCE(*byte) == val) {
unsigned long msr_val;

rdmsrl(HV_X64_MSR_GUEST_IDLE, msr_val);

(void)msr_val;
}
local_irq_restore(flags);
}

Expand Down
6 changes: 3 additions & 3 deletions arch/x86/hyperv/irqdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ static int hv_map_interrupt(union hv_device_id device_id, bool level,

local_irq_restore(flags);

if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS)
if (!hv_result_success(status))
pr_err("%s: hypercall failed, status %lld\n", __func__, status);

return status & HV_HYPERCALL_RESULT_MASK;
return hv_result(status);
}

static int hv_unmap_interrupt(u64 id, struct hv_interrupt_entry *old_entry)
Expand All @@ -88,7 +88,7 @@ static int hv_unmap_interrupt(u64 id, struct hv_interrupt_entry *old_entry)
status = hv_do_hypercall(HVCALL_UNMAP_DEVICE_INTERRUPT, input, NULL);
local_irq_restore(flags);

return status & HV_HYPERCALL_RESULT_MASK;
return hv_result(status);
}

#ifdef CONFIG_PCI_MSI
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/hyperv/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
int cpu, vcpu, gva_n, max_gvas;
struct hv_tlb_flush **flush_pcpu;
struct hv_tlb_flush *flush;
u64 status = U64_MAX;
u64 status;
unsigned long flags;

trace_hyperv_mmu_flush_tlb_others(cpus, info);
Expand Down Expand Up @@ -161,7 +161,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
check_status:
local_irq_restore(flags);

if (!(status & HV_HYPERCALL_RESULT_MASK))
if (hv_result_success(status))
return;
do_native:
native_flush_tlb_others(cpus, info);
Expand All @@ -176,7 +176,7 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
u64 status;

if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
return U64_MAX;
return HV_STATUS_INVALID_PARAMETER;

flush_pcpu = (struct hv_tlb_flush_ex **)
this_cpu_ptr(hyperv_pcpu_input_arg);
Expand All @@ -201,7 +201,7 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K;
nr_bank = cpumask_to_vpset(&(flush->hv_vp_set), cpus);
if (nr_bank < 0)
return U64_MAX;
return HV_STATUS_INVALID_PARAMETER;

/*
* We can flush not more than max_gvas with one hypercall. Flush the
Expand Down
Loading

0 comments on commit 4d480db

Please sign in to comment.