Commit b8878e5a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hyperv-next-signed-20230220' of...

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

Pull hyperv updates from Wei Liu:

 - allow Linux to run as the nested root partition for Microsoft
   Hypervisor (Jinank Jain and Nuno Das Neves)

 - clean up the return type of callback functions (Dawei Li)

* tag 'hyperv-next-signed-20230220' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
  x86/hyperv: Fix hv_get/set_register for nested bringup
  Drivers: hv: Make remove callback of hyperv driver void returned
  Drivers: hv: Enable vmbus driver for nested root partition
  x86/hyperv: Add an interface to do nested hypercalls
  Drivers: hv: Setup synic registers in case of nested root partition
  x86/hyperv: Add support for detecting nested hypervisor
parents 8bf1a529 b14033a3
...@@ -116,6 +116,9 @@ ...@@ -116,6 +116,9 @@
/* Recommend using the newer ExProcessorMasks interface */ /* Recommend using the newer ExProcessorMasks interface */
#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED BIT(11) #define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED BIT(11)
/* Indicates that the hypervisor is nested within a Hyper-V partition. */
#define HV_X64_HYPERV_NESTED BIT(12)
/* Recommend using enlightened VMCS */ /* Recommend using enlightened VMCS */
#define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED BIT(14) #define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED BIT(14)
...@@ -224,6 +227,17 @@ enum hv_isolation_type { ...@@ -224,6 +227,17 @@ enum hv_isolation_type {
#define HV_REGISTER_SINT14 0x4000009E #define HV_REGISTER_SINT14 0x4000009E
#define HV_REGISTER_SINT15 0x4000009F #define HV_REGISTER_SINT15 0x4000009F
/*
* Define synthetic interrupt controller model specific registers for
* nested hypervisor.
*/
#define HV_REGISTER_NESTED_SCONTROL 0x40001080
#define HV_REGISTER_NESTED_SVERSION 0x40001081
#define HV_REGISTER_NESTED_SIEFP 0x40001082
#define HV_REGISTER_NESTED_SIMP 0x40001083
#define HV_REGISTER_NESTED_EOM 0x40001084
#define HV_REGISTER_NESTED_SINT0 0x40001090
/* /*
* Synthetic Timer MSRs. Four timers per vcpu. * Synthetic Timer MSRs. Four timers per vcpu.
*/ */
...@@ -368,7 +382,8 @@ struct hv_nested_enlightenments_control { ...@@ -368,7 +382,8 @@ struct hv_nested_enlightenments_control {
__u32 reserved:31; __u32 reserved:31;
} features; } features;
struct { struct {
__u32 reserved; __u32 inter_partition_comm:1;
__u32 reserved:31;
} hypercallControls; } hypercallControls;
} __packed; } __packed;
......
...@@ -72,10 +72,16 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) ...@@ -72,10 +72,16 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
return hv_status; return hv_status;
} }
/* Hypercall to the L0 hypervisor */
static inline u64 hv_do_nested_hypercall(u64 control, void *input, void *output)
{
return hv_do_hypercall(control | HV_HYPERCALL_NESTED, input, output);
}
/* Fast hypercall with 8 bytes of input and no output */ /* Fast hypercall with 8 bytes of input and no output */
static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1)
{ {
u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT; u64 hv_status;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
{ {
...@@ -103,10 +109,24 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) ...@@ -103,10 +109,24 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
return hv_status; return hv_status;
} }
static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
{
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT;
return _hv_do_fast_hypercall8(control, input1);
}
static inline u64 hv_do_fast_nested_hypercall8(u16 code, u64 input1)
{
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED;
return _hv_do_fast_hypercall8(control, input1);
}
/* Fast hypercall with 16 bytes of input */ /* Fast hypercall with 16 bytes of input */
static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2) static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2)
{ {
u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT; u64 hv_status;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
{ {
...@@ -137,6 +157,20 @@ static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2) ...@@ -137,6 +157,20 @@ static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
return hv_status; return hv_status;
} }
static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
{
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT;
return _hv_do_fast_hypercall16(control, input1, input2);
}
static inline u64 hv_do_fast_nested_hypercall16(u16 code, u64 input1, u64 input2)
{
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED;
return _hv_do_fast_hypercall16(control, input1, input2);
}
extern struct hv_vp_assist_page **hv_vp_assist_page; extern struct hv_vp_assist_page **hv_vp_assist_page;
static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu) static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
...@@ -190,36 +224,20 @@ extern bool hv_isolation_type_snp(void); ...@@ -190,36 +224,20 @@ extern bool hv_isolation_type_snp(void);
static inline bool hv_is_synic_reg(unsigned int reg) static inline bool hv_is_synic_reg(unsigned int reg)
{ {
if ((reg >= HV_REGISTER_SCONTROL) && return (reg >= HV_REGISTER_SCONTROL) &&
(reg <= HV_REGISTER_SINT15)) (reg <= HV_REGISTER_SINT15);
return true;
return false;
} }
static inline u64 hv_get_register(unsigned int reg) static inline bool hv_is_sint_reg(unsigned int reg)
{ {
u64 value; return (reg >= HV_REGISTER_SINT0) &&
(reg <= HV_REGISTER_SINT15);
if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
hv_ghcb_msr_read(reg, &value);
else
rdmsrl(reg, value);
return value;
} }
static inline void hv_set_register(unsigned int reg, u64 value) u64 hv_get_register(unsigned int reg);
{ void hv_set_register(unsigned int reg, u64 value);
if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) { u64 hv_get_non_nested_register(unsigned int reg);
hv_ghcb_msr_write(reg, value); void hv_set_non_nested_register(unsigned int reg, u64 value);
/* Write proxy bit via wrmsl instruction */
if (reg >= HV_REGISTER_SINT0 &&
reg <= HV_REGISTER_SINT15)
wrmsrl(reg, value | 1 << 20);
} else {
wrmsrl(reg, value);
}
}
#else /* CONFIG_HYPERV */ #else /* CONFIG_HYPERV */
static inline void hyperv_init(void) {} static inline void hyperv_init(void) {}
...@@ -239,6 +257,8 @@ static inline int hyperv_flush_guest_mapping_range(u64 as, ...@@ -239,6 +257,8 @@ static inline int hyperv_flush_guest_mapping_range(u64 as,
} }
static inline void hv_set_register(unsigned int reg, u64 value) { } static inline void hv_set_register(unsigned int reg, u64 value) { }
static inline u64 hv_get_register(unsigned int reg) { return 0; } static inline u64 hv_get_register(unsigned int reg) { return 0; }
static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }
static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages, static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages,
bool visible) bool visible)
{ {
......
...@@ -37,9 +37,76 @@ ...@@ -37,9 +37,76 @@
/* Is Linux running as the root partition? */ /* Is Linux running as the root partition? */
bool hv_root_partition; bool hv_root_partition;
/* Is Linux running on nested Microsoft Hypervisor */
bool hv_nested;
struct ms_hyperv_info ms_hyperv; struct ms_hyperv_info ms_hyperv;
#if IS_ENABLED(CONFIG_HYPERV) #if IS_ENABLED(CONFIG_HYPERV)
static inline unsigned int hv_get_nested_reg(unsigned int reg)
{
if (hv_is_sint_reg(reg))
return reg - HV_REGISTER_SINT0 + HV_REGISTER_NESTED_SINT0;
switch (reg) {
case HV_REGISTER_SIMP:
return HV_REGISTER_NESTED_SIMP;
case HV_REGISTER_SIEFP:
return HV_REGISTER_NESTED_SIEFP;
case HV_REGISTER_SVERSION:
return HV_REGISTER_NESTED_SVERSION;
case HV_REGISTER_SCONTROL:
return HV_REGISTER_NESTED_SCONTROL;
case HV_REGISTER_EOM:
return HV_REGISTER_NESTED_EOM;
default:
return reg;
}
}
u64 hv_get_non_nested_register(unsigned int reg)
{
u64 value;
if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
hv_ghcb_msr_read(reg, &value);
else
rdmsrl(reg, value);
return value;
}
EXPORT_SYMBOL_GPL(hv_get_non_nested_register);
void hv_set_non_nested_register(unsigned int reg, u64 value)
{
if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) {
hv_ghcb_msr_write(reg, value);
/* Write proxy bit via wrmsl instruction */
if (hv_is_sint_reg(reg))
wrmsrl(reg, value | 1 << 20);
} else {
wrmsrl(reg, value);
}
}
EXPORT_SYMBOL_GPL(hv_set_non_nested_register);
u64 hv_get_register(unsigned int reg)
{
if (hv_nested)
reg = hv_get_nested_reg(reg);
return hv_get_non_nested_register(reg);
}
EXPORT_SYMBOL_GPL(hv_get_register);
void hv_set_register(unsigned int reg, u64 value)
{
if (hv_nested)
reg = hv_get_nested_reg(reg);
hv_set_non_nested_register(reg, value);
}
EXPORT_SYMBOL_GPL(hv_set_register);
static void (*vmbus_handler)(void); static void (*vmbus_handler)(void);
static void (*hv_stimer0_handler)(void); static void (*hv_stimer0_handler)(void);
static void (*hv_kexec_handler)(void); static void (*hv_kexec_handler)(void);
...@@ -301,6 +368,11 @@ static void __init ms_hyperv_init_platform(void) ...@@ -301,6 +368,11 @@ static void __init ms_hyperv_init_platform(void)
pr_info("Hyper-V: running as root partition\n"); pr_info("Hyper-V: running as root partition\n");
} }
if (ms_hyperv.hints & HV_X64_HYPERV_NESTED) {
hv_nested = true;
pr_info("Hyper-V: running on a nested hypervisor\n");
}
/* /*
* Extract host information. * Extract host information.
*/ */
......
...@@ -165,7 +165,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev, ...@@ -165,7 +165,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
return ret; return ret;
} }
static int hyperv_vmbus_remove(struct hv_device *hdev) static void hyperv_vmbus_remove(struct hv_device *hdev)
{ {
struct drm_device *dev = hv_get_drvdata(hdev); struct drm_device *dev = hv_get_drvdata(hdev);
struct hyperv_drm_device *hv = to_hv(dev); struct hyperv_drm_device *hv = to_hv(dev);
...@@ -176,8 +176,6 @@ static int hyperv_vmbus_remove(struct hv_device *hdev) ...@@ -176,8 +176,6 @@ static int hyperv_vmbus_remove(struct hv_device *hdev)
hv_set_drvdata(hdev, NULL); hv_set_drvdata(hdev, NULL);
vmbus_free_mmio(hv->mem->start, hv->fb_size); vmbus_free_mmio(hv->mem->start, hv->fb_size);
return 0;
} }
static int hyperv_vmbus_suspend(struct hv_device *hdev) static int hyperv_vmbus_suspend(struct hv_device *hdev)
......
...@@ -524,7 +524,7 @@ static int mousevsc_probe(struct hv_device *device, ...@@ -524,7 +524,7 @@ static int mousevsc_probe(struct hv_device *device,
} }
static int mousevsc_remove(struct hv_device *dev) static void mousevsc_remove(struct hv_device *dev)
{ {
struct mousevsc_dev *input_dev = hv_get_drvdata(dev); struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
...@@ -533,8 +533,6 @@ static int mousevsc_remove(struct hv_device *dev) ...@@ -533,8 +533,6 @@ static int mousevsc_remove(struct hv_device *dev)
hid_hw_stop(input_dev->hid_device); hid_hw_stop(input_dev->hid_device);
hid_destroy_device(input_dev->hid_device); hid_destroy_device(input_dev->hid_device);
mousevsc_free_device(input_dev); mousevsc_free_device(input_dev);
return 0;
} }
static int mousevsc_suspend(struct hv_device *dev) static int mousevsc_suspend(struct hv_device *dev)
......
...@@ -147,7 +147,7 @@ int hv_synic_alloc(void) ...@@ -147,7 +147,7 @@ int hv_synic_alloc(void)
* Synic message and event pages are allocated by paravisor. * Synic message and event pages are allocated by paravisor.
* Skip these pages allocation here. * Skip these pages allocation here.
*/ */
if (!hv_isolation_type_snp()) { if (!hv_isolation_type_snp() && !hv_root_partition) {
hv_cpu->synic_message_page = hv_cpu->synic_message_page =
(void *)get_zeroed_page(GFP_ATOMIC); (void *)get_zeroed_page(GFP_ATOMIC);
if (hv_cpu->synic_message_page == NULL) { if (hv_cpu->synic_message_page == NULL) {
...@@ -216,7 +216,7 @@ void hv_synic_enable_regs(unsigned int cpu) ...@@ -216,7 +216,7 @@ void hv_synic_enable_regs(unsigned int cpu)
simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP); simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
simp.simp_enabled = 1; simp.simp_enabled = 1;
if (hv_isolation_type_snp()) { if (hv_isolation_type_snp() || hv_root_partition) {
hv_cpu->synic_message_page hv_cpu->synic_message_page
= memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT, = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
HV_HYP_PAGE_SIZE, MEMREMAP_WB); HV_HYP_PAGE_SIZE, MEMREMAP_WB);
...@@ -233,7 +233,7 @@ void hv_synic_enable_regs(unsigned int cpu) ...@@ -233,7 +233,7 @@ void hv_synic_enable_regs(unsigned int cpu)
siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP); siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
siefp.siefp_enabled = 1; siefp.siefp_enabled = 1;
if (hv_isolation_type_snp()) { if (hv_isolation_type_snp() || hv_root_partition) {
hv_cpu->synic_event_page = hv_cpu->synic_event_page =
memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT, memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
HV_HYP_PAGE_SIZE, MEMREMAP_WB); HV_HYP_PAGE_SIZE, MEMREMAP_WB);
...@@ -315,20 +315,24 @@ void hv_synic_disable_regs(unsigned int cpu) ...@@ -315,20 +315,24 @@ void hv_synic_disable_regs(unsigned int cpu)
* addresses. * addresses.
*/ */
simp.simp_enabled = 0; simp.simp_enabled = 0;
if (hv_isolation_type_snp()) if (hv_isolation_type_snp() || hv_root_partition) {
memunmap(hv_cpu->synic_message_page); memunmap(hv_cpu->synic_message_page);
else hv_cpu->synic_message_page = NULL;
} else {
simp.base_simp_gpa = 0; simp.base_simp_gpa = 0;
}
hv_set_register(HV_REGISTER_SIMP, simp.as_uint64); hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP); siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
siefp.siefp_enabled = 0; siefp.siefp_enabled = 0;
if (hv_isolation_type_snp()) if (hv_isolation_type_snp() || hv_root_partition) {
memunmap(hv_cpu->synic_event_page); memunmap(hv_cpu->synic_event_page);
else hv_cpu->synic_event_page = NULL;
} else {
siefp.base_siefp_gpa = 0; siefp.base_siefp_gpa = 0;
}
hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64); hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
......
...@@ -2042,7 +2042,7 @@ static int balloon_probe(struct hv_device *dev, ...@@ -2042,7 +2042,7 @@ static int balloon_probe(struct hv_device *dev,
return ret; return ret;
} }
static int balloon_remove(struct hv_device *dev) static void balloon_remove(struct hv_device *dev)
{ {
struct hv_dynmem_device *dm = hv_get_drvdata(dev); struct hv_dynmem_device *dm = hv_get_drvdata(dev);
struct hv_hotadd_state *has, *tmp; struct hv_hotadd_state *has, *tmp;
...@@ -2083,8 +2083,6 @@ static int balloon_remove(struct hv_device *dev) ...@@ -2083,8 +2083,6 @@ static int balloon_remove(struct hv_device *dev)
kfree(has); kfree(has);
} }
spin_unlock_irqrestore(&dm_device.ha_lock, flags); spin_unlock_irqrestore(&dm_device.ha_lock, flags);
return 0;
} }
static int balloon_suspend(struct hv_device *hv_dev) static int balloon_suspend(struct hv_device *hv_dev)
......
...@@ -25,17 +25,20 @@ ...@@ -25,17 +25,20 @@
#include <asm/mshyperv.h> #include <asm/mshyperv.h>
/* /*
* hv_root_partition and ms_hyperv are defined here with other Hyper-V * hv_root_partition, ms_hyperv and hv_nested are defined here with other
* specific globals so they are shared across all architectures and are * Hyper-V specific globals so they are shared across all architectures and are
* built only when CONFIG_HYPERV is defined. But on x86, * built only when CONFIG_HYPERV is defined. But on x86,
* ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not * ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not
* defined, and it uses these two variables. So mark them as __weak * defined, and it uses these three variables. So mark them as __weak
* here, allowing for an overriding definition in the module containing * here, allowing for an overriding definition in the module containing
* ms_hyperv_init_platform(). * ms_hyperv_init_platform().
*/ */
bool __weak hv_root_partition; bool __weak hv_root_partition;
EXPORT_SYMBOL_GPL(hv_root_partition); EXPORT_SYMBOL_GPL(hv_root_partition);
bool __weak hv_nested;
EXPORT_SYMBOL_GPL(hv_nested);
struct ms_hyperv_info __weak ms_hyperv; struct ms_hyperv_info __weak ms_hyperv;
EXPORT_SYMBOL_GPL(ms_hyperv); EXPORT_SYMBOL_GPL(ms_hyperv);
......
...@@ -602,7 +602,7 @@ static int util_probe(struct hv_device *dev, ...@@ -602,7 +602,7 @@ static int util_probe(struct hv_device *dev,
return ret; return ret;
} }
static int util_remove(struct hv_device *dev) static void util_remove(struct hv_device *dev)
{ {
struct hv_util_service *srv = hv_get_drvdata(dev); struct hv_util_service *srv = hv_get_drvdata(dev);
...@@ -610,8 +610,6 @@ static int util_remove(struct hv_device *dev) ...@@ -610,8 +610,6 @@ static int util_remove(struct hv_device *dev)
srv->util_deinit(); srv->util_deinit();
vmbus_close(dev->channel); vmbus_close(dev->channel);
kfree(srv->recv_buffer); kfree(srv->recv_buffer);
return 0;
} }
/* /*
......
...@@ -2744,7 +2744,7 @@ static int __init hv_acpi_init(void) ...@@ -2744,7 +2744,7 @@ static int __init hv_acpi_init(void)
if (!hv_is_hyperv_initialized()) if (!hv_is_hyperv_initialized())
return -ENODEV; return -ENODEV;
if (hv_root_partition) if (hv_root_partition && !hv_nested)
return 0; return 0;
/* /*
......
...@@ -369,7 +369,7 @@ static int hv_kbd_probe(struct hv_device *hv_dev, ...@@ -369,7 +369,7 @@ static int hv_kbd_probe(struct hv_device *hv_dev,
return error; return error;
} }
static int hv_kbd_remove(struct hv_device *hv_dev) static void hv_kbd_remove(struct hv_device *hv_dev)
{ {
struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev); struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
...@@ -378,8 +378,6 @@ static int hv_kbd_remove(struct hv_device *hv_dev) ...@@ -378,8 +378,6 @@ static int hv_kbd_remove(struct hv_device *hv_dev)
kfree(kbd_dev); kfree(kbd_dev);
hv_set_drvdata(hv_dev, NULL); hv_set_drvdata(hv_dev, NULL);
return 0;
} }
static int hv_kbd_suspend(struct hv_device *hv_dev) static int hv_kbd_suspend(struct hv_device *hv_dev)
......
...@@ -2594,7 +2594,7 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -2594,7 +2594,7 @@ static int netvsc_probe(struct hv_device *dev,
return ret; return ret;
} }
static int netvsc_remove(struct hv_device *dev) static void netvsc_remove(struct hv_device *dev)
{ {
struct net_device_context *ndev_ctx; struct net_device_context *ndev_ctx;
struct net_device *vf_netdev, *net; struct net_device *vf_netdev, *net;
...@@ -2603,7 +2603,7 @@ static int netvsc_remove(struct hv_device *dev) ...@@ -2603,7 +2603,7 @@ static int netvsc_remove(struct hv_device *dev)
net = hv_get_drvdata(dev); net = hv_get_drvdata(dev);
if (net == NULL) { if (net == NULL) {
dev_err(&dev->device, "No net device to remove\n"); dev_err(&dev->device, "No net device to remove\n");
return 0; return;
} }
ndev_ctx = netdev_priv(net); ndev_ctx = netdev_priv(net);
...@@ -2637,7 +2637,6 @@ static int netvsc_remove(struct hv_device *dev) ...@@ -2637,7 +2637,6 @@ static int netvsc_remove(struct hv_device *dev)
free_percpu(ndev_ctx->vf_stats); free_percpu(ndev_ctx->vf_stats);
free_netdev(net); free_netdev(net);
return 0;
} }
static int netvsc_suspend(struct hv_device *dev) static int netvsc_suspend(struct hv_device *dev)
......
...@@ -3800,13 +3800,10 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) ...@@ -3800,13 +3800,10 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
/** /**
* hv_pci_remove() - Remove routine for this VMBus channel * hv_pci_remove() - Remove routine for this VMBus channel
* @hdev: VMBus's tracking struct for this root PCI bus * @hdev: VMBus's tracking struct for this root PCI bus
*
* Return: 0 on success, -errno on failure
*/ */
static int hv_pci_remove(struct hv_device *hdev) static void hv_pci_remove(struct hv_device *hdev)
{ {
struct hv_pcibus_device *hbus; struct hv_pcibus_device *hbus;
int ret;
hbus = hv_get_drvdata(hdev); hbus = hv_get_drvdata(hdev);
if (hbus->state == hv_pcibus_installed) { if (hbus->state == hv_pcibus_installed) {
...@@ -3829,7 +3826,7 @@ static int hv_pci_remove(struct hv_device *hdev) ...@@ -3829,7 +3826,7 @@ static int hv_pci_remove(struct hv_device *hdev)
pci_unlock_rescan_remove(); pci_unlock_rescan_remove();
} }
ret = hv_pci_bus_exit(hdev, false); hv_pci_bus_exit(hdev, false);
vmbus_close(hdev->channel); vmbus_close(hdev->channel);
...@@ -3842,7 +3839,6 @@ static int hv_pci_remove(struct hv_device *hdev) ...@@ -3842,7 +3839,6 @@ static int hv_pci_remove(struct hv_device *hdev)
hv_put_dom_num(hbus->bridge->domain_nr); hv_put_dom_num(hbus->bridge->domain_nr);
kfree(hbus); kfree(hbus);
return ret;
} }
static int hv_pci_suspend(struct hv_device *hdev) static int hv_pci_suspend(struct hv_device *hdev)
......
...@@ -2095,7 +2095,7 @@ static int storvsc_change_queue_depth(struct scsi_device *sdev, int queue_depth) ...@@ -2095,7 +2095,7 @@ static int storvsc_change_queue_depth(struct scsi_device *sdev, int queue_depth)
return scsi_change_queue_depth(sdev, queue_depth); return scsi_change_queue_depth(sdev, queue_depth);
} }
static int storvsc_remove(struct hv_device *dev) static void storvsc_remove(struct hv_device *dev)
{ {
struct storvsc_device *stor_device = hv_get_drvdata(dev); struct storvsc_device *stor_device = hv_get_drvdata(dev);
struct Scsi_Host *host = stor_device->host; struct Scsi_Host *host = stor_device->host;
...@@ -2111,8 +2111,6 @@ static int storvsc_remove(struct hv_device *dev) ...@@ -2111,8 +2111,6 @@ static int storvsc_remove(struct hv_device *dev)
scsi_remove_host(host); scsi_remove_host(host);
storvsc_dev_remove(dev); storvsc_dev_remove(dev);
scsi_host_put(host); scsi_host_put(host);
return 0;
} }
static int storvsc_suspend(struct hv_device *hv_dev) static int storvsc_suspend(struct hv_device *hv_dev)
......
...@@ -355,20 +355,19 @@ hv_uio_probe(struct hv_device *dev, ...@@ -355,20 +355,19 @@ hv_uio_probe(struct hv_device *dev,
return ret; return ret;
} }
static int static void
hv_uio_remove(struct hv_device *dev) hv_uio_remove(struct hv_device *dev)
{ {
struct hv_uio_private_data *pdata = hv_get_drvdata(dev); struct hv_uio_private_data *pdata = hv_get_drvdata(dev);
if (!pdata) if (!pdata)
return 0; return;
sysfs_remove_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr); sysfs_remove_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr);
uio_unregister_device(&pdata->info); uio_unregister_device(&pdata->info);
hv_uio_cleanup(dev, pdata); hv_uio_cleanup(dev, pdata);
vmbus_free_ring(dev->channel); vmbus_free_ring(dev->channel);
return 0;
} }
static struct hv_driver hv_uio_drv = { static struct hv_driver hv_uio_drv = {
......
...@@ -1239,8 +1239,7 @@ static int hvfb_probe(struct hv_device *hdev, ...@@ -1239,8 +1239,7 @@ static int hvfb_probe(struct hv_device *hdev,
return ret; return ret;
} }
static void hvfb_remove(struct hv_device *hdev)
static int hvfb_remove(struct hv_device *hdev)
{ {
struct fb_info *info = hv_get_drvdata(hdev); struct fb_info *info = hv_get_drvdata(hdev);
struct hvfb_par *par = info->par; struct hvfb_par *par = info->par;
...@@ -1261,8 +1260,6 @@ static int hvfb_remove(struct hv_device *hdev) ...@@ -1261,8 +1260,6 @@ static int hvfb_remove(struct hv_device *hdev)
hvfb_putmem(hdev, info); hvfb_putmem(hdev, info);
framebuffer_release(info); framebuffer_release(info);
return 0;
} }
static int hvfb_suspend(struct hv_device *hdev) static int hvfb_suspend(struct hv_device *hdev)
......
...@@ -194,6 +194,7 @@ enum HV_GENERIC_SET_FORMAT { ...@@ -194,6 +194,7 @@ enum HV_GENERIC_SET_FORMAT {
#define HV_HYPERCALL_VARHEAD_OFFSET 17 #define HV_HYPERCALL_VARHEAD_OFFSET 17
#define HV_HYPERCALL_VARHEAD_MASK GENMASK_ULL(26, 17) #define HV_HYPERCALL_VARHEAD_MASK GENMASK_ULL(26, 17)
#define HV_HYPERCALL_RSVD0_MASK GENMASK_ULL(31, 27) #define HV_HYPERCALL_RSVD0_MASK GENMASK_ULL(31, 27)
#define HV_HYPERCALL_NESTED BIT_ULL(31)
#define HV_HYPERCALL_REP_COMP_OFFSET 32 #define HV_HYPERCALL_REP_COMP_OFFSET 32
#define HV_HYPERCALL_REP_COMP_1 BIT_ULL(32) #define HV_HYPERCALL_REP_COMP_1 BIT_ULL(32)
#define HV_HYPERCALL_REP_COMP_MASK GENMASK_ULL(43, 32) #define HV_HYPERCALL_REP_COMP_MASK GENMASK_ULL(43, 32)
......
...@@ -48,6 +48,7 @@ struct ms_hyperv_info { ...@@ -48,6 +48,7 @@ struct ms_hyperv_info {
u64 shared_gpa_boundary; u64 shared_gpa_boundary;
}; };
extern struct ms_hyperv_info ms_hyperv; extern struct ms_hyperv_info ms_hyperv;
extern bool hv_nested;
extern void * __percpu *hyperv_pcpu_input_arg; extern void * __percpu *hyperv_pcpu_input_arg;
extern void * __percpu *hyperv_pcpu_output_arg; extern void * __percpu *hyperv_pcpu_output_arg;
......
...@@ -1273,7 +1273,7 @@ struct hv_driver { ...@@ -1273,7 +1273,7 @@ struct hv_driver {
} dynids; } dynids;
int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *); int (*probe)(struct hv_device *, const struct hv_vmbus_device_id *);
int (*remove)(struct hv_device *); void (*remove)(struct hv_device *dev);
void (*shutdown)(struct hv_device *); void (*shutdown)(struct hv_device *);
int (*suspend)(struct hv_device *); int (*suspend)(struct hv_device *);
......
...@@ -879,13 +879,11 @@ static int hvs_probe(struct hv_device *hdev, ...@@ -879,13 +879,11 @@ static int hvs_probe(struct hv_device *hdev,
return 0; return 0;
} }
static int hvs_remove(struct hv_device *hdev) static void hvs_remove(struct hv_device *hdev)
{ {
struct vmbus_channel *chan = hdev->channel; struct vmbus_channel *chan = hdev->channel;
vmbus_close(chan); vmbus_close(chan);
return 0;
} }
/* hv_sock connections can not persist across hibernation, and all the hv_sock /* hv_sock connections can not persist across hibernation, and all the hv_sock
......
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