Skip to content

Commit 42e7a03

Browse files
committed
Merge tag 'hyperv-fixes-signed-20220407' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv fixes from Wei Liu: - Correctly propagate coherence information for VMbus devices (Michael Kelley) - Disable balloon and memory hot-add on ARM64 temporarily (Boqun Feng) - Use barrier to prevent reording when reading ring buffer (Michael Kelley) - Use virt_store_mb in favour of smp_store_mb (Andrea Parri) - Fix VMbus device object initialization (Andrea Parri) - Deactivate sysctl_record_panic_msg on isolated guest (Andrea Parri) - Fix a crash when unloading VMbus module (Guilherme G. Piccoli) * tag 'hyperv-fixes-signed-20220407' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: Drivers: hv: vmbus: Replace smp_store_mb() with virt_store_mb() Drivers: hv: balloon: Disable balloon and hot-add accordingly Drivers: hv: balloon: Support status report for larger page sizes Drivers: hv: vmbus: Prevent load re-ordering when reading ring buffer PCI: hv: Propagate coherence from VMbus device to PCI device Drivers: hv: vmbus: Propagate VMbus coherence to each VMbus device Drivers: hv: vmbus: Fix potential crash on module unload Drivers: hv: vmbus: Fix initialization of device object in vmbus_device_register() Drivers: hv: vmbus: Deactivate sysctl_record_panic_msg by default in isolated guests
2 parents 3638bd9 + eaa03d3 commit 42e7a03

File tree

7 files changed

+132
-20
lines changed

7 files changed

+132
-20
lines changed

drivers/hv/channel_mgmt.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ void vmbus_channel_map_relid(struct vmbus_channel *channel)
380380
* execute:
381381
*
382382
* (a) In the "normal (i.e., not resuming from hibernation)" path,
383-
* the full barrier in smp_store_mb() guarantees that the store
383+
* the full barrier in virt_store_mb() guarantees that the store
384384
* is propagated to all CPUs before the add_channel_work work
385385
* is queued. In turn, add_channel_work is queued before the
386386
* channel's ring buffer is allocated/initialized and the
@@ -392,14 +392,14 @@ void vmbus_channel_map_relid(struct vmbus_channel *channel)
392392
* recv_int_page before retrieving the channel pointer from the
393393
* array of channels.
394394
*
395-
* (b) In the "resuming from hibernation" path, the smp_store_mb()
395+
* (b) In the "resuming from hibernation" path, the virt_store_mb()
396396
* guarantees that the store is propagated to all CPUs before
397397
* the VMBus connection is marked as ready for the resume event
398398
* (cf. check_ready_for_resume_event()). The interrupt handler
399399
* of the VMBus driver and vmbus_chan_sched() can not run before
400400
* vmbus_bus_resume() has completed execution (cf. resume_noirq).
401401
*/
402-
smp_store_mb(
402+
virt_store_mb(
403403
vmbus_connection.channels[channel->offermsg.child_relid],
404404
channel);
405405
}

drivers/hv/hv_balloon.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/slab.h>
1818
#include <linux/kthread.h>
1919
#include <linux/completion.h>
20+
#include <linux/count_zeros.h>
2021
#include <linux/memory_hotplug.h>
2122
#include <linux/memory.h>
2223
#include <linux/notifier.h>
@@ -1130,6 +1131,7 @@ static void post_status(struct hv_dynmem_device *dm)
11301131
struct dm_status status;
11311132
unsigned long now = jiffies;
11321133
unsigned long last_post = last_post_time;
1134+
unsigned long num_pages_avail, num_pages_committed;
11331135

11341136
if (pressure_report_delay > 0) {
11351137
--pressure_report_delay;
@@ -1154,16 +1156,21 @@ static void post_status(struct hv_dynmem_device *dm)
11541156
* num_pages_onlined) as committed to the host, otherwise it can try
11551157
* asking us to balloon them out.
11561158
*/
1157-
status.num_avail = si_mem_available();
1158-
status.num_committed = vm_memory_committed() +
1159+
num_pages_avail = si_mem_available();
1160+
num_pages_committed = vm_memory_committed() +
11591161
dm->num_pages_ballooned +
11601162
(dm->num_pages_added > dm->num_pages_onlined ?
11611163
dm->num_pages_added - dm->num_pages_onlined : 0) +
11621164
compute_balloon_floor();
11631165

1164-
trace_balloon_status(status.num_avail, status.num_committed,
1166+
trace_balloon_status(num_pages_avail, num_pages_committed,
11651167
vm_memory_committed(), dm->num_pages_ballooned,
11661168
dm->num_pages_added, dm->num_pages_onlined);
1169+
1170+
/* Convert numbers of pages into numbers of HV_HYP_PAGEs. */
1171+
status.num_avail = num_pages_avail * NR_HV_HYP_PAGES_IN_PAGE;
1172+
status.num_committed = num_pages_committed * NR_HV_HYP_PAGES_IN_PAGE;
1173+
11671174
/*
11681175
* If our transaction ID is no longer current, just don't
11691176
* send the status. This can happen if we were interrupted
@@ -1653,6 +1660,38 @@ static void disable_page_reporting(void)
16531660
}
16541661
}
16551662

1663+
static int ballooning_enabled(void)
1664+
{
1665+
/*
1666+
* Disable ballooning if the page size is not 4k (HV_HYP_PAGE_SIZE),
1667+
* since currently it's unclear to us whether an unballoon request can
1668+
* make sure all page ranges are guest page size aligned.
1669+
*/
1670+
if (PAGE_SIZE != HV_HYP_PAGE_SIZE) {
1671+
pr_info("Ballooning disabled because page size is not 4096 bytes\n");
1672+
return 0;
1673+
}
1674+
1675+
return 1;
1676+
}
1677+
1678+
static int hot_add_enabled(void)
1679+
{
1680+
/*
1681+
* Disable hot add on ARM64, because we currently rely on
1682+
* memory_add_physaddr_to_nid() to get a node id of a hot add range,
1683+
* however ARM64's memory_add_physaddr_to_nid() always return 0 and
1684+
* DM_MEM_HOT_ADD_REQUEST doesn't have the NUMA node information for
1685+
* add_memory().
1686+
*/
1687+
if (IS_ENABLED(CONFIG_ARM64)) {
1688+
pr_info("Memory hot add disabled on ARM64\n");
1689+
return 0;
1690+
}
1691+
1692+
return 1;
1693+
}
1694+
16561695
static int balloon_connect_vsp(struct hv_device *dev)
16571696
{
16581697
struct dm_version_request version_req;
@@ -1724,8 +1763,8 @@ static int balloon_connect_vsp(struct hv_device *dev)
17241763
* currently still requires the bits to be set, so we have to add code
17251764
* to fail the host's hot-add and balloon up/down requests, if any.
17261765
*/
1727-
cap_msg.caps.cap_bits.balloon = 1;
1728-
cap_msg.caps.cap_bits.hot_add = 1;
1766+
cap_msg.caps.cap_bits.balloon = ballooning_enabled();
1767+
cap_msg.caps.cap_bits.hot_add = hot_add_enabled();
17291768

17301769
/*
17311770
* Specify our alignment requirements as it relates

drivers/hv/hv_common.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/panic_notifier.h>
2121
#include <linux/ptrace.h>
2222
#include <linux/slab.h>
23+
#include <linux/dma-map-ops.h>
2324
#include <asm/hyperv-tlfs.h>
2425
#include <asm/mshyperv.h>
2526

@@ -218,6 +219,16 @@ bool hv_query_ext_cap(u64 cap_query)
218219
}
219220
EXPORT_SYMBOL_GPL(hv_query_ext_cap);
220221

222+
void hv_setup_dma_ops(struct device *dev, bool coherent)
223+
{
224+
/*
225+
* Hyper-V does not offer a vIOMMU in the guest
226+
* VM, so pass 0/NULL for the IOMMU settings
227+
*/
228+
arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
229+
}
230+
EXPORT_SYMBOL_GPL(hv_setup_dma_ops);
231+
221232
bool hv_is_hibernation_supported(void)
222233
{
223234
return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);

drivers/hv/ring_buffer.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,16 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
439439
static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi)
440440
{
441441
u32 priv_read_loc = rbi->priv_read_index;
442-
u32 write_loc = READ_ONCE(rbi->ring_buffer->write_index);
442+
u32 write_loc;
443+
444+
/*
445+
* The Hyper-V host writes the packet data, then uses
446+
* store_release() to update the write_index. Use load_acquire()
447+
* here to prevent loads of the packet data from being re-ordered
448+
* before the read of the write_index and potentially getting
449+
* stale data.
450+
*/
451+
write_loc = virt_load_acquire(&rbi->ring_buffer->write_index);
443452

444453
if (write_loc >= priv_read_loc)
445454
return write_loc - priv_read_loc;

drivers/hv/vmbus_drv.c

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
7777

7878
/*
7979
* Hyper-V should be notified only once about a panic. If we will be
80-
* doing hyperv_report_panic_msg() later with kmsg data, don't do
81-
* the notification here.
80+
* doing hv_kmsg_dump() with kmsg data later, don't do the notification
81+
* here.
8282
*/
8383
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
8484
&& hyperv_report_reg()) {
@@ -100,8 +100,8 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
100100

101101
/*
102102
* Hyper-V should be notified only once about a panic. If we will be
103-
* doing hyperv_report_panic_msg() later with kmsg data, don't do
104-
* the notification here.
103+
* doing hv_kmsg_dump() with kmsg data later, don't do the notification
104+
* here.
105105
*/
106106
if (hyperv_report_reg())
107107
hyperv_report_panic(regs, val, true);
@@ -920,6 +920,21 @@ static int vmbus_probe(struct device *child_device)
920920
return ret;
921921
}
922922

923+
/*
924+
* vmbus_dma_configure -- Configure DMA coherence for VMbus device
925+
*/
926+
static int vmbus_dma_configure(struct device *child_device)
927+
{
928+
/*
929+
* On ARM64, propagate the DMA coherence setting from the top level
930+
* VMbus ACPI device to the child VMbus device being added here.
931+
* On x86/x64 coherence is assumed and these calls have no effect.
932+
*/
933+
hv_setup_dma_ops(child_device,
934+
device_get_dma_attr(&hv_acpi_dev->dev) == DEV_DMA_COHERENT);
935+
return 0;
936+
}
937+
923938
/*
924939
* vmbus_remove - Remove a vmbus device
925940
*/
@@ -1040,6 +1055,7 @@ static struct bus_type hv_bus = {
10401055
.remove = vmbus_remove,
10411056
.probe = vmbus_probe,
10421057
.uevent = vmbus_uevent,
1058+
.dma_configure = vmbus_dma_configure,
10431059
.dev_groups = vmbus_dev_groups,
10441060
.drv_groups = vmbus_drv_groups,
10451061
.bus_groups = vmbus_bus_groups,
@@ -1546,14 +1562,20 @@ static int vmbus_bus_init(void)
15461562
if (ret)
15471563
goto err_connect;
15481564

1565+
if (hv_is_isolation_supported())
1566+
sysctl_record_panic_msg = 0;
1567+
15491568
/*
15501569
* Only register if the crash MSRs are available
15511570
*/
15521571
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
15531572
u64 hyperv_crash_ctl;
15541573
/*
1555-
* Sysctl registration is not fatal, since by default
1556-
* reporting is enabled.
1574+
* Panic message recording (sysctl_record_panic_msg)
1575+
* is enabled by default in non-isolated guests and
1576+
* disabled by default in isolated guests; the panic
1577+
* message recording won't be available in isolated
1578+
* guests should the following registration fail.
15571579
*/
15581580
hv_ctl_table_hdr = register_sysctl_table(hv_root_table);
15591581
if (!hv_ctl_table_hdr)
@@ -2097,6 +2119,10 @@ int vmbus_device_register(struct hv_device *child_device_obj)
20972119
child_device_obj->device.parent = &hv_acpi_dev->dev;
20982120
child_device_obj->device.release = vmbus_device_release;
20992121

2122+
child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
2123+
child_device_obj->device.dma_mask = &child_device_obj->dma_mask;
2124+
dma_set_mask(&child_device_obj->device, DMA_BIT_MASK(64));
2125+
21002126
/*
21012127
* Register with the LDM. This will kick off the driver/device
21022128
* binding...which will eventually call vmbus_match() and vmbus_probe()
@@ -2122,9 +2148,6 @@ int vmbus_device_register(struct hv_device *child_device_obj)
21222148
}
21232149
hv_debug_add_dev_dir(child_device_obj);
21242150

2125-
child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
2126-
child_device_obj->device.dma_mask = &child_device_obj->dma_mask;
2127-
dma_set_mask(&child_device_obj->device, DMA_BIT_MASK(64));
21282151
return 0;
21292152

21302153
err_kset_unregister:
@@ -2428,6 +2451,21 @@ static int vmbus_acpi_add(struct acpi_device *device)
24282451

24292452
hv_acpi_dev = device;
24302453

2454+
/*
2455+
* Older versions of Hyper-V for ARM64 fail to include the _CCA
2456+
* method on the top level VMbus device in the DSDT. But devices
2457+
* are hardware coherent in all current Hyper-V use cases, so fix
2458+
* up the ACPI device to behave as if _CCA is present and indicates
2459+
* hardware coherence.
2460+
*/
2461+
ACPI_COMPANION_SET(&device->dev, device);
2462+
if (IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED) &&
2463+
device_get_dma_attr(&device->dev) == DEV_DMA_NOT_SUPPORTED) {
2464+
pr_info("No ACPI _CCA found; assuming coherent device I/O\n");
2465+
device->flags.cca_seen = true;
2466+
device->flags.coherent_dma = true;
2467+
}
2468+
24312469
result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
24322470
vmbus_walk_resources, NULL);
24332471

@@ -2780,10 +2818,15 @@ static void __exit vmbus_exit(void)
27802818
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
27812819
kmsg_dump_unregister(&hv_kmsg_dumper);
27822820
unregister_die_notifier(&hyperv_die_block);
2783-
atomic_notifier_chain_unregister(&panic_notifier_list,
2784-
&hyperv_panic_block);
27852821
}
27862822

2823+
/*
2824+
* The panic notifier is always registered, hence we should
2825+
* also unconditionally unregister it here as well.
2826+
*/
2827+
atomic_notifier_chain_unregister(&panic_notifier_list,
2828+
&hyperv_panic_block);
2829+
27872830
free_page((unsigned long)hv_panic_page);
27882831
unregister_sysctl_table(hv_ctl_table_hdr);
27892832
hv_ctl_table_hdr = NULL;

drivers/pci/controller/pci-hyperv.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3407,6 +3407,15 @@ static int hv_pci_probe(struct hv_device *hdev,
34073407
hbus->bridge->domain_nr = dom;
34083408
#ifdef CONFIG_X86
34093409
hbus->sysdata.domain = dom;
3410+
#elif defined(CONFIG_ARM64)
3411+
/*
3412+
* Set the PCI bus parent to be the corresponding VMbus
3413+
* device. Then the VMbus device will be assigned as the
3414+
* ACPI companion in pcibios_root_bridge_prepare() and
3415+
* pci_dma_configure() will propagate device coherence
3416+
* information to devices created on the bus.
3417+
*/
3418+
hbus->sysdata.parent = hdev->device.parent;
34103419
#endif
34113420

34123421
hbus->hdev = hdev;

include/asm-generic/mshyperv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ bool hv_isolation_type_snp(void);
269269
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
270270
void hyperv_cleanup(void);
271271
bool hv_query_ext_cap(u64 cap_query);
272+
void hv_setup_dma_ops(struct device *dev, bool coherent);
272273
void *hv_map_memory(void *addr, unsigned long size);
273274
void hv_unmap_memory(void *addr);
274275
#else /* CONFIG_HYPERV */

0 commit comments

Comments
 (0)