// SPDX-License-Identifier: GPL-2.0 #include #include #include #include #include #include "mshv.h" #include "mshv_root.h" /* * Ports and connections are hypervisor struct used for inter-partition * communication. Port represents the source and connection represents * the destination. Partitions are responsible for managing the port and * connection ids. * */ #define PORTID_MIN 1 #define PORTID_MAX INT_MAX static DEFINE_IDR(port_table_idr); void mshv_port_table_fini(void) { struct port_table_info *port_info; unsigned long i, tmp; idr_lock(&port_table_idr); if (!idr_is_empty(&port_table_idr)) { idr_for_each_entry_ul(&port_table_idr, port_info, tmp, i) { port_info = idr_remove(&port_table_idr, i); kfree_rcu(port_info, portbl_rcu); } } idr_unlock(&port_table_idr); } int mshv_portid_alloc(struct port_table_info *info) { int ret = 0; idr_lock(&port_table_idr); ret = idr_alloc(&port_table_idr, info, PORTID_MIN, PORTID_MAX, GFP_KERNEL); idr_unlock(&port_table_idr); return ret; } void mshv_portid_free(int port_id) { struct port_table_info *info; idr_lock(&port_table_idr); info = idr_remove(&port_table_idr, port_id); WARN_ON(!info); idr_unlock(&port_table_idr); synchronize_rcu(); kfree(info); } int mshv_portid_lookup(int port_id, struct port_table_info *info) { struct port_table_info *_info; int ret = -ENOENT; rcu_read_lock(); _info = idr_find(&port_table_idr, port_id); rcu_read_unlock(); if (_info) { *info = *_info; ret = 0; } return ret; }