162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2011, Microsoft Corporation. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Authors: 762306a36Sopenharmony_ci * Haiyang Zhang <haiyangz@microsoft.com> 862306a36Sopenharmony_ci * Hank Janssen <hjanssen@microsoft.com> 962306a36Sopenharmony_ci * K. Y. Srinivasan <kys@microsoft.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifndef _HYPERV_VMBUS_H 1362306a36Sopenharmony_ci#define _HYPERV_VMBUS_H 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/list.h> 1662306a36Sopenharmony_ci#include <linux/bitops.h> 1762306a36Sopenharmony_ci#include <asm/sync_bitops.h> 1862306a36Sopenharmony_ci#include <asm/hyperv-tlfs.h> 1962306a36Sopenharmony_ci#include <linux/atomic.h> 2062306a36Sopenharmony_ci#include <linux/hyperv.h> 2162306a36Sopenharmony_ci#include <linux/interrupt.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "hv_trace.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* 2662306a36Sopenharmony_ci * Timeout for services such as KVP and fcopy. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci#define HV_UTIL_TIMEOUT 30 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Timeout for guest-host handshake for services. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci#define HV_UTIL_NEGO_TIMEOUT 55 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* Definitions for the monitored notification facility */ 3762306a36Sopenharmony_ciunion hv_monitor_trigger_group { 3862306a36Sopenharmony_ci u64 as_uint64; 3962306a36Sopenharmony_ci struct { 4062306a36Sopenharmony_ci u32 pending; 4162306a36Sopenharmony_ci u32 armed; 4262306a36Sopenharmony_ci }; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct hv_monitor_parameter { 4662306a36Sopenharmony_ci union hv_connection_id connectionid; 4762306a36Sopenharmony_ci u16 flagnumber; 4862306a36Sopenharmony_ci u16 rsvdz; 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciunion hv_monitor_trigger_state { 5262306a36Sopenharmony_ci u32 asu32; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci struct { 5562306a36Sopenharmony_ci u32 group_enable:4; 5662306a36Sopenharmony_ci u32 rsvdz:28; 5762306a36Sopenharmony_ci }; 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* struct hv_monitor_page Layout */ 6162306a36Sopenharmony_ci/* ------------------------------------------------------ */ 6262306a36Sopenharmony_ci/* | 0 | TriggerState (4 bytes) | Rsvd1 (4 bytes) | */ 6362306a36Sopenharmony_ci/* | 8 | TriggerGroup[0] | */ 6462306a36Sopenharmony_ci/* | 10 | TriggerGroup[1] | */ 6562306a36Sopenharmony_ci/* | 18 | TriggerGroup[2] | */ 6662306a36Sopenharmony_ci/* | 20 | TriggerGroup[3] | */ 6762306a36Sopenharmony_ci/* | 28 | Rsvd2[0] | */ 6862306a36Sopenharmony_ci/* | 30 | Rsvd2[1] | */ 6962306a36Sopenharmony_ci/* | 38 | Rsvd2[2] | */ 7062306a36Sopenharmony_ci/* | 40 | NextCheckTime[0][0] | NextCheckTime[0][1] | */ 7162306a36Sopenharmony_ci/* | ... | */ 7262306a36Sopenharmony_ci/* | 240 | Latency[0][0..3] | */ 7362306a36Sopenharmony_ci/* | 340 | Rsvz3[0] | */ 7462306a36Sopenharmony_ci/* | 440 | Parameter[0][0] | */ 7562306a36Sopenharmony_ci/* | 448 | Parameter[0][1] | */ 7662306a36Sopenharmony_ci/* | ... | */ 7762306a36Sopenharmony_ci/* | 840 | Rsvd4[0] | */ 7862306a36Sopenharmony_ci/* ------------------------------------------------------ */ 7962306a36Sopenharmony_cistruct hv_monitor_page { 8062306a36Sopenharmony_ci union hv_monitor_trigger_state trigger_state; 8162306a36Sopenharmony_ci u32 rsvdz1; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci union hv_monitor_trigger_group trigger_group[4]; 8462306a36Sopenharmony_ci u64 rsvdz2[3]; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci s32 next_checktime[4][32]; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci u16 latency[4][32]; 8962306a36Sopenharmony_ci u64 rsvdz3[32]; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci struct hv_monitor_parameter parameter[4][32]; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci u8 rsvdz4[1984]; 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define HV_HYPERCALL_PARAM_ALIGN sizeof(u64) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* Definition of the hv_post_message hypercall input structure. */ 9962306a36Sopenharmony_cistruct hv_input_post_message { 10062306a36Sopenharmony_ci union hv_connection_id connectionid; 10162306a36Sopenharmony_ci u32 reserved; 10262306a36Sopenharmony_ci u32 message_type; 10362306a36Sopenharmony_ci u32 payload_size; 10462306a36Sopenharmony_ci u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cienum { 10962306a36Sopenharmony_ci VMBUS_MESSAGE_CONNECTION_ID = 1, 11062306a36Sopenharmony_ci VMBUS_MESSAGE_CONNECTION_ID_4 = 4, 11162306a36Sopenharmony_ci VMBUS_MESSAGE_PORT_ID = 1, 11262306a36Sopenharmony_ci VMBUS_EVENT_CONNECTION_ID = 2, 11362306a36Sopenharmony_ci VMBUS_EVENT_PORT_ID = 2, 11462306a36Sopenharmony_ci VMBUS_MONITOR_CONNECTION_ID = 3, 11562306a36Sopenharmony_ci VMBUS_MONITOR_PORT_ID = 3, 11662306a36Sopenharmony_ci VMBUS_MESSAGE_SINT = 2, 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* 12062306a36Sopenharmony_ci * Per cpu state for channel handling 12162306a36Sopenharmony_ci */ 12262306a36Sopenharmony_cistruct hv_per_cpu_context { 12362306a36Sopenharmony_ci void *synic_message_page; 12462306a36Sopenharmony_ci void *synic_event_page; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * The page is only used in hv_post_message() for a TDX VM (with the 12862306a36Sopenharmony_ci * paravisor) to post a messages to Hyper-V: when such a VM calls 12962306a36Sopenharmony_ci * HVCALL_POST_MESSAGE, it can't use the hyperv_pcpu_input_arg (which 13062306a36Sopenharmony_ci * is encrypted in such a VM) as the hypercall input page, because 13162306a36Sopenharmony_ci * the input page for HVCALL_POST_MESSAGE must be decrypted in such a 13262306a36Sopenharmony_ci * VM, so post_msg_page (which is decrypted in hv_synic_alloc()) is 13362306a36Sopenharmony_ci * introduced for this purpose. See hyperv_init() for more comments. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci void *post_msg_page; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 13862306a36Sopenharmony_ci * Starting with win8, we can take channel interrupts on any CPU; 13962306a36Sopenharmony_ci * we will manage the tasklet that handles events messages on a per CPU 14062306a36Sopenharmony_ci * basis. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci struct tasklet_struct msg_dpc; 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistruct hv_context { 14662306a36Sopenharmony_ci /* We only support running on top of Hyper-V 14762306a36Sopenharmony_ci * So at this point this really can only contain the Hyper-V ID 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_ci u64 guestid; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci struct hv_per_cpu_context __percpu *cpu_context; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* 15462306a36Sopenharmony_ci * To manage allocations in a NUMA node. 15562306a36Sopenharmony_ci * Array indexed by numa node ID. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci struct cpumask *hv_numa_map; 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ciextern struct hv_context hv_context; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* Hv Interface */ 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciextern int hv_init(void); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciextern int hv_post_message(union hv_connection_id connection_id, 16762306a36Sopenharmony_ci enum hv_message_type message_type, 16862306a36Sopenharmony_ci void *payload, size_t payload_size); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ciextern int hv_synic_alloc(void); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciextern void hv_synic_free(void); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciextern void hv_synic_enable_regs(unsigned int cpu); 17562306a36Sopenharmony_ciextern int hv_synic_init(unsigned int cpu); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ciextern void hv_synic_disable_regs(unsigned int cpu); 17862306a36Sopenharmony_ciextern int hv_synic_cleanup(unsigned int cpu); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/* Interface */ 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_civoid hv_ringbuffer_pre_init(struct vmbus_channel *channel); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ciint hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, 18562306a36Sopenharmony_ci struct page *pages, u32 pagecnt, u32 max_pkt_size); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_civoid hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciint hv_ringbuffer_write(struct vmbus_channel *channel, 19062306a36Sopenharmony_ci const struct kvec *kv_list, u32 kv_count, 19162306a36Sopenharmony_ci u64 requestid, u64 *trans_id); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciint hv_ringbuffer_read(struct vmbus_channel *channel, 19462306a36Sopenharmony_ci void *buffer, u32 buflen, u32 *buffer_actual_len, 19562306a36Sopenharmony_ci u64 *requestid, bool raw); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * The Maximum number of channels (16384) is determined by the size of the 19962306a36Sopenharmony_ci * interrupt page, which is HV_HYP_PAGE_SIZE. 1/2 of HV_HYP_PAGE_SIZE is to 20062306a36Sopenharmony_ci * send endpoint interrupts, and the other is to receive endpoint interrupts. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci#define MAX_NUM_CHANNELS ((HV_HYP_PAGE_SIZE >> 1) << 3) 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci/* The value here must be in multiple of 32 */ 20562306a36Sopenharmony_ci#define MAX_NUM_CHANNELS_SUPPORTED 256 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define MAX_CHANNEL_RELIDS \ 20862306a36Sopenharmony_ci max(MAX_NUM_CHANNELS_SUPPORTED, HV_EVENT_FLAGS_COUNT) 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cienum vmbus_connect_state { 21162306a36Sopenharmony_ci DISCONNECTED, 21262306a36Sopenharmony_ci CONNECTING, 21362306a36Sopenharmony_ci CONNECTED, 21462306a36Sopenharmony_ci DISCONNECTING 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci#define MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* 22062306a36Sopenharmony_ci * The CPU that Hyper-V will interrupt for VMBUS messages, such as 22162306a36Sopenharmony_ci * CHANNELMSG_OFFERCHANNEL and CHANNELMSG_RESCIND_CHANNELOFFER. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci#define VMBUS_CONNECT_CPU 0 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistruct vmbus_connection { 22662306a36Sopenharmony_ci u32 msg_conn_id; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci atomic_t offer_in_progress; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci enum vmbus_connect_state conn_state; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci atomic_t next_gpadl_handle; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci struct completion unload_event; 23562306a36Sopenharmony_ci /* 23662306a36Sopenharmony_ci * Represents channel interrupts. Each bit position represents a 23762306a36Sopenharmony_ci * channel. When a channel sends an interrupt via VMBUS, it finds its 23862306a36Sopenharmony_ci * bit in the sendInterruptPage, set it and calls Hv to generate a port 23962306a36Sopenharmony_ci * event. The other end receives the port event and parse the 24062306a36Sopenharmony_ci * recvInterruptPage to see which bit is set 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_ci void *int_page; 24362306a36Sopenharmony_ci void *send_int_page; 24462306a36Sopenharmony_ci void *recv_int_page; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* 24762306a36Sopenharmony_ci * 2 pages - 1st page for parent->child notification and 2nd 24862306a36Sopenharmony_ci * is child->parent notification 24962306a36Sopenharmony_ci */ 25062306a36Sopenharmony_ci struct hv_monitor_page *monitor_pages[2]; 25162306a36Sopenharmony_ci struct list_head chn_msg_list; 25262306a36Sopenharmony_ci spinlock_t channelmsg_lock; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* List of channels */ 25562306a36Sopenharmony_ci struct list_head chn_list; 25662306a36Sopenharmony_ci struct mutex channel_mutex; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci /* Array of channels */ 25962306a36Sopenharmony_ci struct vmbus_channel **channels; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci /* 26262306a36Sopenharmony_ci * An offer message is handled first on the work_queue, and then 26362306a36Sopenharmony_ci * is further handled on handle_primary_chan_wq or 26462306a36Sopenharmony_ci * handle_sub_chan_wq. 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ci struct workqueue_struct *work_queue; 26762306a36Sopenharmony_ci struct workqueue_struct *handle_primary_chan_wq; 26862306a36Sopenharmony_ci struct workqueue_struct *handle_sub_chan_wq; 26962306a36Sopenharmony_ci struct workqueue_struct *rescind_work_queue; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* 27262306a36Sopenharmony_ci * On suspension of the vmbus, the accumulated offer messages 27362306a36Sopenharmony_ci * must be dropped. 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ci bool ignore_any_offer_msg; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* 27862306a36Sopenharmony_ci * The number of sub-channels and hv_sock channels that should be 27962306a36Sopenharmony_ci * cleaned up upon suspend: sub-channels will be re-created upon 28062306a36Sopenharmony_ci * resume, and hv_sock channels should not survive suspend. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_ci atomic_t nr_chan_close_on_suspend; 28362306a36Sopenharmony_ci /* 28462306a36Sopenharmony_ci * vmbus_bus_suspend() waits for "nr_chan_close_on_suspend" to 28562306a36Sopenharmony_ci * drop to zero. 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_ci struct completion ready_for_suspend_event; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* 29062306a36Sopenharmony_ci * The number of primary channels that should be "fixed up" 29162306a36Sopenharmony_ci * upon resume: these channels are re-offered upon resume, and some 29262306a36Sopenharmony_ci * fields of the channel offers (i.e. child_relid and connection_id) 29362306a36Sopenharmony_ci * can change, so the old offermsg must be fixed up, before the resume 29462306a36Sopenharmony_ci * callbacks of the VSC drivers start to further touch the channels. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci atomic_t nr_chan_fixup_on_resume; 29762306a36Sopenharmony_ci /* 29862306a36Sopenharmony_ci * vmbus_bus_resume() waits for "nr_chan_fixup_on_resume" to 29962306a36Sopenharmony_ci * drop to zero. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ci struct completion ready_for_resume_event; 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistruct vmbus_msginfo { 30662306a36Sopenharmony_ci /* Bookkeeping stuff */ 30762306a36Sopenharmony_ci struct list_head msglist_entry; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci /* The message itself */ 31062306a36Sopenharmony_ci unsigned char msg[]; 31162306a36Sopenharmony_ci}; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ciextern struct vmbus_connection vmbus_connection; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ciint vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic inline void vmbus_send_interrupt(u32 relid) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci sync_set_bit(relid, vmbus_connection.send_int_page); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cienum vmbus_message_handler_type { 32462306a36Sopenharmony_ci /* The related handler can sleep. */ 32562306a36Sopenharmony_ci VMHT_BLOCKING = 0, 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* The related handler must NOT sleep. */ 32862306a36Sopenharmony_ci VMHT_NON_BLOCKING = 1, 32962306a36Sopenharmony_ci}; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistruct vmbus_channel_message_table_entry { 33262306a36Sopenharmony_ci enum vmbus_channel_message_type message_type; 33362306a36Sopenharmony_ci enum vmbus_message_handler_type handler_type; 33462306a36Sopenharmony_ci void (*message_handler)(struct vmbus_channel_message_header *msg); 33562306a36Sopenharmony_ci u32 min_payload_len; 33662306a36Sopenharmony_ci}; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ciextern const struct vmbus_channel_message_table_entry 33962306a36Sopenharmony_ci channel_message_table[CHANNELMSG_COUNT]; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci/* General vmbus interface */ 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistruct hv_device *vmbus_device_create(const guid_t *type, 34562306a36Sopenharmony_ci const guid_t *instance, 34662306a36Sopenharmony_ci struct vmbus_channel *channel); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ciint vmbus_device_register(struct hv_device *child_device_obj); 34962306a36Sopenharmony_civoid vmbus_device_unregister(struct hv_device *device_obj); 35062306a36Sopenharmony_ciint vmbus_add_channel_kobj(struct hv_device *device_obj, 35162306a36Sopenharmony_ci struct vmbus_channel *channel); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_civoid vmbus_remove_channel_attr_group(struct vmbus_channel *channel); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_civoid vmbus_channel_map_relid(struct vmbus_channel *channel); 35662306a36Sopenharmony_civoid vmbus_channel_unmap_relid(struct vmbus_channel *channel); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistruct vmbus_channel *relid2channel(u32 relid); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_civoid vmbus_free_channels(void); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci/* Connection interface */ 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ciint vmbus_connect(void); 36562306a36Sopenharmony_civoid vmbus_disconnect(void); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ciint vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_civoid vmbus_on_event(unsigned long data); 37062306a36Sopenharmony_civoid vmbus_on_msg_dpc(unsigned long data); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ciint hv_kvp_init(struct hv_util_service *srv); 37362306a36Sopenharmony_civoid hv_kvp_deinit(void); 37462306a36Sopenharmony_ciint hv_kvp_pre_suspend(void); 37562306a36Sopenharmony_ciint hv_kvp_pre_resume(void); 37662306a36Sopenharmony_civoid hv_kvp_onchannelcallback(void *context); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ciint hv_vss_init(struct hv_util_service *srv); 37962306a36Sopenharmony_civoid hv_vss_deinit(void); 38062306a36Sopenharmony_ciint hv_vss_pre_suspend(void); 38162306a36Sopenharmony_ciint hv_vss_pre_resume(void); 38262306a36Sopenharmony_civoid hv_vss_onchannelcallback(void *context); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ciint hv_fcopy_init(struct hv_util_service *srv); 38562306a36Sopenharmony_civoid hv_fcopy_deinit(void); 38662306a36Sopenharmony_ciint hv_fcopy_pre_suspend(void); 38762306a36Sopenharmony_ciint hv_fcopy_pre_resume(void); 38862306a36Sopenharmony_civoid hv_fcopy_onchannelcallback(void *context); 38962306a36Sopenharmony_civoid vmbus_initiate_unload(bool crash); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic inline void hv_poll_channel(struct vmbus_channel *channel, 39262306a36Sopenharmony_ci void (*cb)(void *)) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci if (!channel) 39562306a36Sopenharmony_ci return; 39662306a36Sopenharmony_ci cb(channel); 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cienum hvutil_device_state { 40062306a36Sopenharmony_ci HVUTIL_DEVICE_INIT = 0, /* driver is loaded, waiting for userspace */ 40162306a36Sopenharmony_ci HVUTIL_READY, /* userspace is registered */ 40262306a36Sopenharmony_ci HVUTIL_HOSTMSG_RECEIVED, /* message from the host was received */ 40362306a36Sopenharmony_ci HVUTIL_USERSPACE_REQ, /* request to userspace was sent */ 40462306a36Sopenharmony_ci HVUTIL_USERSPACE_RECV, /* reply from userspace was received */ 40562306a36Sopenharmony_ci HVUTIL_DEVICE_DYING, /* driver unload is in progress */ 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cienum delay { 40962306a36Sopenharmony_ci INTERRUPT_DELAY = 0, 41062306a36Sopenharmony_ci MESSAGE_DELAY = 1, 41162306a36Sopenharmony_ci}; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ciextern const struct vmbus_device vmbus_devs[]; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic inline bool hv_is_perf_channel(struct vmbus_channel *channel) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci return vmbus_devs[channel->device_id].perf_device; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic inline bool hv_is_allocated_cpu(unsigned int cpu) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct vmbus_channel *channel, *sc; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci lockdep_assert_held(&vmbus_connection.channel_mutex); 42562306a36Sopenharmony_ci /* 42662306a36Sopenharmony_ci * List additions/deletions as well as updates of the target CPUs are 42762306a36Sopenharmony_ci * protected by channel_mutex. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { 43062306a36Sopenharmony_ci if (!hv_is_perf_channel(channel)) 43162306a36Sopenharmony_ci continue; 43262306a36Sopenharmony_ci if (channel->target_cpu == cpu) 43362306a36Sopenharmony_ci return true; 43462306a36Sopenharmony_ci list_for_each_entry(sc, &channel->sc_list, sc_list) { 43562306a36Sopenharmony_ci if (sc->target_cpu == cpu) 43662306a36Sopenharmony_ci return true; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci return false; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic inline void hv_set_allocated_cpu(unsigned int cpu) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci cpumask_set_cpu(cpu, &hv_context.hv_numa_map[cpu_to_node(cpu)]); 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic inline void hv_clear_allocated_cpu(unsigned int cpu) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci if (hv_is_allocated_cpu(cpu)) 45062306a36Sopenharmony_ci return; 45162306a36Sopenharmony_ci cpumask_clear_cpu(cpu, &hv_context.hv_numa_map[cpu_to_node(cpu)]); 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic inline void hv_update_allocated_cpus(unsigned int old_cpu, 45562306a36Sopenharmony_ci unsigned int new_cpu) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci hv_set_allocated_cpu(new_cpu); 45862306a36Sopenharmony_ci hv_clear_allocated_cpu(old_cpu); 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci#ifdef CONFIG_HYPERV_TESTING 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ciint hv_debug_add_dev_dir(struct hv_device *dev); 46462306a36Sopenharmony_civoid hv_debug_rm_dev_dir(struct hv_device *dev); 46562306a36Sopenharmony_civoid hv_debug_rm_all_dir(void); 46662306a36Sopenharmony_ciint hv_debug_init(void); 46762306a36Sopenharmony_civoid hv_debug_delay_test(struct vmbus_channel *channel, enum delay delay_type); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci#else /* CONFIG_HYPERV_TESTING */ 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic inline void hv_debug_rm_dev_dir(struct hv_device *dev) {}; 47262306a36Sopenharmony_cistatic inline void hv_debug_rm_all_dir(void) {}; 47362306a36Sopenharmony_cistatic inline void hv_debug_delay_test(struct vmbus_channel *channel, 47462306a36Sopenharmony_ci enum delay delay_type) {}; 47562306a36Sopenharmony_cistatic inline int hv_debug_init(void) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci return -1; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic inline int hv_debug_add_dev_dir(struct hv_device *dev) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci return -1; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci#endif /* CONFIG_HYPERV_TESTING */ 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci#endif /* _HYPERV_VMBUS_H */ 488