Commit 52e5070f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

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

Pull hyperv fixes from Wei Liu:

 - Some cosmetic changes (Erni Sri Satya Vennela, Li Zhijian)

 - Introduce hv_numa_node_to_pxm_info() (Nuno Das Neves)

 - Fix KVP daemon to handle IPv4 and IPv6 combination for keyfile format
   (Shradha Gupta)

 - Avoid freeing decrypted memory in a confidential VM (Rick Edgecombe
   and Michael Kelley)

* tag 'hyperv-fixes-signed-20240411' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
  Drivers: hv: vmbus: Don't free ring buffers that couldn't be re-encrypted
  uio_hv_generic: Don't free decrypted memory
  hv_netvsc: Don't free decrypted memory
  Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl
  Drivers: hv: vmbus: Leak pages if set_memory_encrypted() fails
  hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for keyfile format
  hv: vmbus: Convert sprintf() family to sysfs_emit() family
  mshyperv: Introduce hv_numa_node_to_pxm_info()
  x86/hyperv: Cosmetic changes for hv_apic.c
parents 00dcf5d8 30d18df6
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
	if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
		ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;

		nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask,
		nr_bank = cpumask_to_vpset_skip(&ipi_arg->vp_set, mask,
						exclude_self ? cpu_is_self : NULL);

		/*
@@ -181,7 +181,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
			return false;
	}

	if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
	if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
		return false;

	/*
@@ -241,7 +241,7 @@ static bool __send_ipi_one(int cpu, int vector)
			return false;
	}

	if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
	if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
		return false;

	if (vp >= 64)
+4 −18
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/clockchips.h>
#include <linux/acpi.h>
#include <linux/hyperv.h>
#include <linux/slab.h>
#include <linux/cpuhotplug.h>
@@ -116,12 +115,11 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)

int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
{
	struct hv_add_logical_processor_in *input;
	struct hv_add_logical_processor_out *output;
	struct hv_input_add_logical_processor *input;
	struct hv_output_add_logical_processor *output;
	u64 status;
	unsigned long flags;
	int ret = HV_STATUS_SUCCESS;
	int pxm = node_to_pxm(node);

	/*
	 * When adding a logical processor, the hypervisor may return
@@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)

		input->lp_index = lp_index;
		input->apic_id = apic_id;
		input->flags = 0;
		input->proximity_domain_info.domain_id = pxm;
		input->proximity_domain_info.flags.reserved = 0;
		input->proximity_domain_info.flags.proximity_info_valid = 1;
		input->proximity_domain_info.flags.proximity_preferred = 1;
		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
		status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
					 input, output);
		local_irq_restore(flags);
@@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
	u64 status;
	unsigned long irq_flags;
	int ret = HV_STATUS_SUCCESS;
	int pxm = node_to_pxm(node);

	/* Root VPs don't seem to need pages deposited */
	if (partition_id != hv_current_partition_id) {
@@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
		input->vp_index = vp_index;
		input->flags = flags;
		input->subnode_type = HvSubnodeAny;
		if (node != NUMA_NO_NODE) {
			input->proximity_domain_info.domain_id = pxm;
			input->proximity_domain_info.flags.reserved = 0;
			input->proximity_domain_info.flags.proximity_info_valid = 1;
			input->proximity_domain_info.flags.proximity_preferred = 1;
		} else {
			input->proximity_domain_info.as_uint64 = 0;
		}
		input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
		status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
		local_irq_restore(irq_flags);

+24 −5
Original line number Diff line number Diff line
@@ -153,6 +153,8 @@ void vmbus_free_ring(struct vmbus_channel *channel)
	hv_ringbuffer_cleanup(&channel->inbound);

	if (channel->ringbuffer_page) {
		/* In a CoCo VM leak the memory if it didn't get re-encrypted */
		if (!channel->ringbuffer_gpadlhandle.decrypted)
			__free_pages(channel->ringbuffer_page,
			     get_order(channel->ringbuffer_pagecount
				       << PAGE_SHIFT));
@@ -436,9 +438,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
		(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);

	ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
	if (ret)
	if (ret) {
		gpadl->decrypted = false;
		return ret;
	}

	/*
	 * Set the "decrypted" flag to true for the set_memory_decrypted()
	 * success case. In the failure case, the encryption state of the
	 * memory is unknown. Leave "decrypted" as true to ensure the
	 * memory will be leaked instead of going back on the free list.
	 */
	gpadl->decrypted = true;
	ret = set_memory_decrypted((unsigned long)kbuffer,
				   PFN_UP(size));
	if (ret) {
@@ -527,9 +538,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,

	kfree(msginfo);

	if (ret)
		set_memory_encrypted((unsigned long)kbuffer,
				     PFN_UP(size));
	if (ret) {
		/*
		 * If set_memory_encrypted() fails, the decrypted flag is
		 * left as true so the memory is leaked instead of being
		 * put back on the free list.
		 */
		if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
			gpadl->decrypted = false;
	}

	return ret;
}
@@ -850,6 +867,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad
	if (ret)
		pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);

	gpadl->decrypted = ret;

	return ret;
}
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
+22 −7
Original line number Diff line number Diff line
@@ -237,8 +237,17 @@ int vmbus_connect(void)
				vmbus_connection.monitor_pages[0], 1);
	ret |= set_memory_decrypted((unsigned long)
				vmbus_connection.monitor_pages[1], 1);
	if (ret)
	if (ret) {
		/*
		 * If set_memory_decrypted() fails, the encryption state
		 * of the memory is unknown. So leak the memory instead
		 * of risking returning decrypted memory to the free list.
		 * For simplicity, always handle both pages the same.
		 */
		vmbus_connection.monitor_pages[0] = NULL;
		vmbus_connection.monitor_pages[1] = NULL;
		goto cleanup;
	}

	/*
	 * Set_memory_decrypted() will change the memory contents if
@@ -337,14 +346,20 @@ void vmbus_disconnect(void)
		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[1], 1);

	if (vmbus_connection.monitor_pages[0]) {
		if (!set_memory_encrypted(
			(unsigned long)vmbus_connection.monitor_pages[0], 1))
			hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
	hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
		vmbus_connection.monitor_pages[0] = NULL;
	}

	if (vmbus_connection.monitor_pages[1]) {
		if (!set_memory_encrypted(
			(unsigned long)vmbus_connection.monitor_pages[1], 1))
			hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
		vmbus_connection.monitor_pages[1] = NULL;
	}
}

/*
 * relid2channel - Get the channel object given its
+42 −52
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n", hv_dev->channel->offermsg.child_relid);
	return sysfs_emit(buf, "%d\n", hv_dev->channel->offermsg.child_relid);
}
static DEVICE_ATTR_RO(id);

@@ -142,7 +142,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n", hv_dev->channel->state);
	return sysfs_emit(buf, "%d\n", hv_dev->channel->state);
}
static DEVICE_ATTR_RO(state);

@@ -153,7 +153,7 @@ static ssize_t monitor_id_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid);
	return sysfs_emit(buf, "%d\n", hv_dev->channel->offermsg.monitorid);
}
static DEVICE_ATTR_RO(monitor_id);

@@ -164,7 +164,7 @@ static ssize_t class_id_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "{%pUl}\n",
	return sysfs_emit(buf, "{%pUl}\n",
			  &hv_dev->channel->offermsg.offer.if_type);
}
static DEVICE_ATTR_RO(class_id);
@@ -176,7 +176,7 @@ static ssize_t device_id_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "{%pUl}\n",
	return sysfs_emit(buf, "{%pUl}\n",
			  &hv_dev->channel->offermsg.offer.if_instance);
}
static DEVICE_ATTR_RO(device_id);
@@ -186,7 +186,7 @@ static ssize_t modalias_show(struct device *dev,
{
	struct hv_device *hv_dev = device_to_hv_device(dev);

	return sprintf(buf, "vmbus:%*phN\n", UUID_SIZE, &hv_dev->dev_type);
	return sysfs_emit(buf, "vmbus:%*phN\n", UUID_SIZE, &hv_dev->dev_type);
}
static DEVICE_ATTR_RO(modalias);

@@ -199,7 +199,7 @@ static ssize_t numa_node_show(struct device *dev,
	if (!hv_dev->channel)
		return -ENODEV;

	return sprintf(buf, "%d\n", cpu_to_node(hv_dev->channel->target_cpu));
	return sysfs_emit(buf, "%d\n", cpu_to_node(hv_dev->channel->target_cpu));
}
static DEVICE_ATTR_RO(numa_node);
#endif
@@ -212,8 +212,7 @@ static ssize_t server_monitor_pending_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n",
		       channel_pending(hv_dev->channel,
	return sysfs_emit(buf, "%d\n", channel_pending(hv_dev->channel,
			  vmbus_connection.monitor_pages[0]));
}
static DEVICE_ATTR_RO(server_monitor_pending);
@@ -226,8 +225,7 @@ static ssize_t client_monitor_pending_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n",
		       channel_pending(hv_dev->channel,
	return sysfs_emit(buf, "%d\n", channel_pending(hv_dev->channel,
			  vmbus_connection.monitor_pages[1]));
}
static DEVICE_ATTR_RO(client_monitor_pending);
@@ -240,8 +238,7 @@ static ssize_t server_monitor_latency_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n",
		       channel_latency(hv_dev->channel,
	return sysfs_emit(buf, "%d\n", channel_latency(hv_dev->channel,
			  vmbus_connection.monitor_pages[0]));
}
static DEVICE_ATTR_RO(server_monitor_latency);
@@ -254,8 +251,7 @@ static ssize_t client_monitor_latency_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n",
		       channel_latency(hv_dev->channel,
	return sysfs_emit(buf, "%d\n", channel_latency(hv_dev->channel,
			  vmbus_connection.monitor_pages[1]));
}
static DEVICE_ATTR_RO(client_monitor_latency);
@@ -268,8 +264,7 @@ static ssize_t server_monitor_conn_id_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n",
		       channel_conn_id(hv_dev->channel,
	return sysfs_emit(buf, "%d\n", channel_conn_id(hv_dev->channel,
			  vmbus_connection.monitor_pages[0]));
}
static DEVICE_ATTR_RO(server_monitor_conn_id);
@@ -282,8 +277,7 @@ static ssize_t client_monitor_conn_id_show(struct device *dev,

	if (!hv_dev->channel)
		return -ENODEV;
	return sprintf(buf, "%d\n",
		       channel_conn_id(hv_dev->channel,
	return sysfs_emit(buf, "%d\n", channel_conn_id(hv_dev->channel,
			  vmbus_connection.monitor_pages[1]));
}
static DEVICE_ATTR_RO(client_monitor_conn_id);
@@ -303,7 +297,7 @@ static ssize_t out_intr_mask_show(struct device *dev,
	if (ret < 0)
		return ret;

	return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
	return sysfs_emit(buf, "%d\n", outbound.current_interrupt_mask);
}
static DEVICE_ATTR_RO(out_intr_mask);

@@ -321,7 +315,7 @@ static ssize_t out_read_index_show(struct device *dev,
					  &outbound);
	if (ret < 0)
		return ret;
	return sprintf(buf, "%d\n", outbound.current_read_index);
	return sysfs_emit(buf, "%d\n", outbound.current_read_index);
}
static DEVICE_ATTR_RO(out_read_index);

@@ -340,7 +334,7 @@ static ssize_t out_write_index_show(struct device *dev,
					  &outbound);
	if (ret < 0)
		return ret;
	return sprintf(buf, "%d\n", outbound.current_write_index);
	return sysfs_emit(buf, "%d\n", outbound.current_write_index);
}
static DEVICE_ATTR_RO(out_write_index);

@@ -359,7 +353,7 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
					  &outbound);
	if (ret < 0)
		return ret;
	return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
	return sysfs_emit(buf, "%d\n", outbound.bytes_avail_toread);
}
static DEVICE_ATTR_RO(out_read_bytes_avail);

@@ -378,7 +372,7 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
					  &outbound);
	if (ret < 0)
		return ret;
	return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
	return sysfs_emit(buf, "%d\n", outbound.bytes_avail_towrite);
}
static DEVICE_ATTR_RO(out_write_bytes_avail);

@@ -396,7 +390,7 @@ static ssize_t in_intr_mask_show(struct device *dev,
	if (ret < 0)
		return ret;

	return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
	return sysfs_emit(buf, "%d\n", inbound.current_interrupt_mask);
}
static DEVICE_ATTR_RO(in_intr_mask);

@@ -414,7 +408,7 @@ static ssize_t in_read_index_show(struct device *dev,
	if (ret < 0)
		return ret;

	return sprintf(buf, "%d\n", inbound.current_read_index);
	return sysfs_emit(buf, "%d\n", inbound.current_read_index);
}
static DEVICE_ATTR_RO(in_read_index);

@@ -432,7 +426,7 @@ static ssize_t in_write_index_show(struct device *dev,
	if (ret < 0)
		return ret;

	return sprintf(buf, "%d\n", inbound.current_write_index);
	return sysfs_emit(buf, "%d\n", inbound.current_write_index);
}
static DEVICE_ATTR_RO(in_write_index);

@@ -451,7 +445,7 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
	if (ret < 0)
		return ret;

	return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
	return sysfs_emit(buf, "%d\n", inbound.bytes_avail_toread);
}
static DEVICE_ATTR_RO(in_read_bytes_avail);

@@ -470,7 +464,7 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
	if (ret < 0)
		return ret;

	return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
	return sysfs_emit(buf, "%d\n", inbound.bytes_avail_towrite);
}
static DEVICE_ATTR_RO(in_write_bytes_avail);

@@ -480,7 +474,7 @@ static ssize_t channel_vp_mapping_show(struct device *dev,
{
	struct hv_device *hv_dev = device_to_hv_device(dev);
	struct vmbus_channel *channel = hv_dev->channel, *cur_sc;
	int buf_size = PAGE_SIZE, n_written, tot_written;
	int n_written;
	struct list_head *cur;

	if (!channel)
@@ -488,25 +482,21 @@ static ssize_t channel_vp_mapping_show(struct device *dev,

	mutex_lock(&vmbus_connection.channel_mutex);

	tot_written = snprintf(buf, buf_size, "%u:%u\n",
		channel->offermsg.child_relid, channel->target_cpu);
	n_written = sysfs_emit(buf, "%u:%u\n",
			       channel->offermsg.child_relid,
			       channel->target_cpu);

	list_for_each(cur, &channel->sc_list) {
		if (tot_written >= buf_size - 1)
			break;

		cur_sc = list_entry(cur, struct vmbus_channel, sc_list);
		n_written = scnprintf(buf + tot_written,
				     buf_size - tot_written,
				     "%u:%u\n",
		n_written += sysfs_emit_at(buf, n_written, "%u:%u\n",
					  cur_sc->offermsg.child_relid,
					  cur_sc->target_cpu);
		tot_written += n_written;
	}

	mutex_unlock(&vmbus_connection.channel_mutex);

	return tot_written;
	return n_written;
}
static DEVICE_ATTR_RO(channel_vp_mapping);

@@ -516,7 +506,7 @@ static ssize_t vendor_show(struct device *dev,
{
	struct hv_device *hv_dev = device_to_hv_device(dev);

	return sprintf(buf, "0x%x\n", hv_dev->vendor_id);
	return sysfs_emit(buf, "0x%x\n", hv_dev->vendor_id);
}
static DEVICE_ATTR_RO(vendor);

@@ -526,7 +516,7 @@ static ssize_t device_show(struct device *dev,
{
	struct hv_device *hv_dev = device_to_hv_device(dev);

	return sprintf(buf, "0x%x\n", hv_dev->device_id);
	return sysfs_emit(buf, "0x%x\n", hv_dev->device_id);
}
static DEVICE_ATTR_RO(device);

@@ -551,7 +541,7 @@ static ssize_t driver_override_show(struct device *dev,
	ssize_t len;

	device_lock(dev);
	len = snprintf(buf, PAGE_SIZE, "%s\n", hv_dev->driver_override);
	len = sysfs_emit(buf, "%s\n", hv_dev->driver_override);
	device_unlock(dev);

	return len;
Loading