1*621191d7SNuno Das Neves /* SPDX-License-Identifier: GPL-2.0-only */ 2*621191d7SNuno Das Neves /* 3*621191d7SNuno Das Neves * Copyright (c) 2023, Microsoft Corporation. 4*621191d7SNuno Das Neves */ 5*621191d7SNuno Das Neves 6*621191d7SNuno Das Neves #ifndef _MSHV_ROOT_H_ 7*621191d7SNuno Das Neves #define _MSHV_ROOT_H_ 8*621191d7SNuno Das Neves 9*621191d7SNuno Das Neves #include <linux/spinlock.h> 10*621191d7SNuno Das Neves #include <linux/mutex.h> 11*621191d7SNuno Das Neves #include <linux/semaphore.h> 12*621191d7SNuno Das Neves #include <linux/sched.h> 13*621191d7SNuno Das Neves #include <linux/srcu.h> 14*621191d7SNuno Das Neves #include <linux/wait.h> 15*621191d7SNuno Das Neves #include <linux/hashtable.h> 16*621191d7SNuno Das Neves #include <linux/dev_printk.h> 17*621191d7SNuno Das Neves #include <linux/build_bug.h> 18*621191d7SNuno Das Neves #include <uapi/linux/mshv.h> 19*621191d7SNuno Das Neves 20*621191d7SNuno Das Neves /* 21*621191d7SNuno Das Neves * Hypervisor must be between these version numbers (inclusive) 22*621191d7SNuno Das Neves * to guarantee compatibility 23*621191d7SNuno Das Neves */ 24*621191d7SNuno Das Neves #define MSHV_HV_MIN_VERSION (27744) 25*621191d7SNuno Das Neves #define MSHV_HV_MAX_VERSION (27751) 26*621191d7SNuno Das Neves 27*621191d7SNuno Das Neves static_assert(HV_HYP_PAGE_SIZE == MSHV_HV_PAGE_SIZE); 28*621191d7SNuno Das Neves 29*621191d7SNuno Das Neves #define MSHV_MAX_VPS 256 30*621191d7SNuno Das Neves 31*621191d7SNuno Das Neves #define MSHV_PARTITIONS_HASH_BITS 9 32*621191d7SNuno Das Neves 33*621191d7SNuno Das Neves #define MSHV_PIN_PAGES_BATCH_SIZE (0x10000000ULL / HV_HYP_PAGE_SIZE) 34*621191d7SNuno Das Neves 35*621191d7SNuno Das Neves struct mshv_vp { 36*621191d7SNuno Das Neves u32 vp_index; 37*621191d7SNuno Das Neves struct mshv_partition *vp_partition; 38*621191d7SNuno Das Neves struct mutex vp_mutex; 39*621191d7SNuno Das Neves struct hv_vp_register_page *vp_register_page; 40*621191d7SNuno Das Neves struct hv_message *vp_intercept_msg_page; 41*621191d7SNuno Das Neves void *vp_ghcb_page; 42*621191d7SNuno Das Neves struct hv_stats_page *vp_stats_pages[2]; 43*621191d7SNuno Das Neves struct { 44*621191d7SNuno Das Neves atomic64_t vp_signaled_count; 45*621191d7SNuno Das Neves struct { 46*621191d7SNuno Das Neves u64 intercept_suspend: 1; 47*621191d7SNuno Das Neves u64 root_sched_blocked: 1; /* root scheduler only */ 48*621191d7SNuno Das Neves u64 root_sched_dispatched: 1; /* root scheduler only */ 49*621191d7SNuno Das Neves u64 reserved: 61; 50*621191d7SNuno Das Neves } flags; 51*621191d7SNuno Das Neves unsigned int kicked_by_hv; 52*621191d7SNuno Das Neves wait_queue_head_t vp_suspend_queue; 53*621191d7SNuno Das Neves } run; 54*621191d7SNuno Das Neves }; 55*621191d7SNuno Das Neves 56*621191d7SNuno Das Neves #define vp_fmt(fmt) "p%lluvp%u: " fmt 57*621191d7SNuno Das Neves #define vp_devprintk(level, v, fmt, ...) \ 58*621191d7SNuno Das Neves do { \ 59*621191d7SNuno Das Neves const struct mshv_vp *__vp = (v); \ 60*621191d7SNuno Das Neves const struct mshv_partition *__pt = __vp->vp_partition; \ 61*621191d7SNuno Das Neves dev_##level(__pt->pt_module_dev, vp_fmt(fmt), __pt->pt_id, \ 62*621191d7SNuno Das Neves __vp->vp_index, ##__VA_ARGS__); \ 63*621191d7SNuno Das Neves } while (0) 64*621191d7SNuno Das Neves #define vp_emerg(v, fmt, ...) vp_devprintk(emerg, v, fmt, ##__VA_ARGS__) 65*621191d7SNuno Das Neves #define vp_crit(v, fmt, ...) vp_devprintk(crit, v, fmt, ##__VA_ARGS__) 66*621191d7SNuno Das Neves #define vp_alert(v, fmt, ...) vp_devprintk(alert, v, fmt, ##__VA_ARGS__) 67*621191d7SNuno Das Neves #define vp_err(v, fmt, ...) vp_devprintk(err, v, fmt, ##__VA_ARGS__) 68*621191d7SNuno Das Neves #define vp_warn(v, fmt, ...) vp_devprintk(warn, v, fmt, ##__VA_ARGS__) 69*621191d7SNuno Das Neves #define vp_notice(v, fmt, ...) vp_devprintk(notice, v, fmt, ##__VA_ARGS__) 70*621191d7SNuno Das Neves #define vp_info(v, fmt, ...) vp_devprintk(info, v, fmt, ##__VA_ARGS__) 71*621191d7SNuno Das Neves #define vp_dbg(v, fmt, ...) vp_devprintk(dbg, v, fmt, ##__VA_ARGS__) 72*621191d7SNuno Das Neves 73*621191d7SNuno Das Neves struct mshv_mem_region { 74*621191d7SNuno Das Neves struct hlist_node hnode; 75*621191d7SNuno Das Neves u64 nr_pages; 76*621191d7SNuno Das Neves u64 start_gfn; 77*621191d7SNuno Das Neves u64 start_uaddr; 78*621191d7SNuno Das Neves u32 hv_map_flags; 79*621191d7SNuno Das Neves struct { 80*621191d7SNuno Das Neves u64 large_pages: 1; /* 2MiB */ 81*621191d7SNuno Das Neves u64 range_pinned: 1; 82*621191d7SNuno Das Neves u64 reserved: 62; 83*621191d7SNuno Das Neves } flags; 84*621191d7SNuno Das Neves struct mshv_partition *partition; 85*621191d7SNuno Das Neves struct page *pages[]; 86*621191d7SNuno Das Neves }; 87*621191d7SNuno Das Neves 88*621191d7SNuno Das Neves struct mshv_irq_ack_notifier { 89*621191d7SNuno Das Neves struct hlist_node link; 90*621191d7SNuno Das Neves unsigned int irq_ack_gsi; 91*621191d7SNuno Das Neves void (*irq_acked)(struct mshv_irq_ack_notifier *mian); 92*621191d7SNuno Das Neves }; 93*621191d7SNuno Das Neves 94*621191d7SNuno Das Neves struct mshv_partition { 95*621191d7SNuno Das Neves struct device *pt_module_dev; 96*621191d7SNuno Das Neves 97*621191d7SNuno Das Neves struct hlist_node pt_hnode; 98*621191d7SNuno Das Neves u64 pt_id; 99*621191d7SNuno Das Neves refcount_t pt_ref_count; 100*621191d7SNuno Das Neves struct mutex pt_mutex; 101*621191d7SNuno Das Neves struct hlist_head pt_mem_regions; // not ordered 102*621191d7SNuno Das Neves 103*621191d7SNuno Das Neves u32 pt_vp_count; 104*621191d7SNuno Das Neves struct mshv_vp *pt_vp_array[MSHV_MAX_VPS]; 105*621191d7SNuno Das Neves 106*621191d7SNuno Das Neves struct mutex pt_irq_lock; 107*621191d7SNuno Das Neves struct srcu_struct pt_irq_srcu; 108*621191d7SNuno Das Neves struct hlist_head irq_ack_notifier_list; 109*621191d7SNuno Das Neves 110*621191d7SNuno Das Neves struct hlist_head pt_devices; 111*621191d7SNuno Das Neves 112*621191d7SNuno Das Neves /* 113*621191d7SNuno Das Neves * MSHV does not support more than one async hypercall in flight 114*621191d7SNuno Das Neves * for a single partition. Thus, it is okay to define per partition 115*621191d7SNuno Das Neves * async hypercall status. 116*621191d7SNuno Das Neves */ 117*621191d7SNuno Das Neves struct completion async_hypercall; 118*621191d7SNuno Das Neves u64 async_hypercall_status; 119*621191d7SNuno Das Neves 120*621191d7SNuno Das Neves spinlock_t pt_irqfds_lock; 121*621191d7SNuno Das Neves struct hlist_head pt_irqfds_list; 122*621191d7SNuno Das Neves struct mutex irqfds_resampler_lock; 123*621191d7SNuno Das Neves struct hlist_head irqfds_resampler_list; 124*621191d7SNuno Das Neves 125*621191d7SNuno Das Neves struct hlist_head ioeventfds_list; 126*621191d7SNuno Das Neves 127*621191d7SNuno Das Neves struct mshv_girq_routing_table __rcu *pt_girq_tbl; 128*621191d7SNuno Das Neves u64 isolation_type; 129*621191d7SNuno Das Neves bool import_completed; 130*621191d7SNuno Das Neves bool pt_initialized; 131*621191d7SNuno Das Neves }; 132*621191d7SNuno Das Neves 133*621191d7SNuno Das Neves #define pt_fmt(fmt) "p%llu: " fmt 134*621191d7SNuno Das Neves #define pt_devprintk(level, p, fmt, ...) \ 135*621191d7SNuno Das Neves do { \ 136*621191d7SNuno Das Neves const struct mshv_partition *__pt = (p); \ 137*621191d7SNuno Das Neves dev_##level(__pt->pt_module_dev, pt_fmt(fmt), __pt->pt_id, \ 138*621191d7SNuno Das Neves ##__VA_ARGS__); \ 139*621191d7SNuno Das Neves } while (0) 140*621191d7SNuno Das Neves #define pt_emerg(p, fmt, ...) pt_devprintk(emerg, p, fmt, ##__VA_ARGS__) 141*621191d7SNuno Das Neves #define pt_crit(p, fmt, ...) pt_devprintk(crit, p, fmt, ##__VA_ARGS__) 142*621191d7SNuno Das Neves #define pt_alert(p, fmt, ...) pt_devprintk(alert, p, fmt, ##__VA_ARGS__) 143*621191d7SNuno Das Neves #define pt_err(p, fmt, ...) pt_devprintk(err, p, fmt, ##__VA_ARGS__) 144*621191d7SNuno Das Neves #define pt_warn(p, fmt, ...) pt_devprintk(warn, p, fmt, ##__VA_ARGS__) 145*621191d7SNuno Das Neves #define pt_notice(p, fmt, ...) pt_devprintk(notice, p, fmt, ##__VA_ARGS__) 146*621191d7SNuno Das Neves #define pt_info(p, fmt, ...) pt_devprintk(info, p, fmt, ##__VA_ARGS__) 147*621191d7SNuno Das Neves #define pt_dbg(p, fmt, ...) pt_devprintk(dbg, p, fmt, ##__VA_ARGS__) 148*621191d7SNuno Das Neves 149*621191d7SNuno Das Neves struct mshv_lapic_irq { 150*621191d7SNuno Das Neves u32 lapic_vector; 151*621191d7SNuno Das Neves u64 lapic_apic_id; 152*621191d7SNuno Das Neves union hv_interrupt_control lapic_control; 153*621191d7SNuno Das Neves }; 154*621191d7SNuno Das Neves 155*621191d7SNuno Das Neves #define MSHV_MAX_GUEST_IRQS 4096 156*621191d7SNuno Das Neves 157*621191d7SNuno Das Neves /* representation of one guest irq entry, either msi or legacy */ 158*621191d7SNuno Das Neves struct mshv_guest_irq_ent { 159*621191d7SNuno Das Neves u32 girq_entry_valid; /* vfio looks at this */ 160*621191d7SNuno Das Neves u32 guest_irq_num; /* a unique number for each irq */ 161*621191d7SNuno Das Neves u32 girq_addr_lo; /* guest irq msi address info */ 162*621191d7SNuno Das Neves u32 girq_addr_hi; 163*621191d7SNuno Das Neves u32 girq_irq_data; /* idt vector in some cases */ 164*621191d7SNuno Das Neves }; 165*621191d7SNuno Das Neves 166*621191d7SNuno Das Neves struct mshv_girq_routing_table { 167*621191d7SNuno Das Neves u32 num_rt_entries; 168*621191d7SNuno Das Neves struct mshv_guest_irq_ent mshv_girq_info_tbl[]; 169*621191d7SNuno Das Neves }; 170*621191d7SNuno Das Neves 171*621191d7SNuno Das Neves struct hv_synic_pages { 172*621191d7SNuno Das Neves struct hv_message_page *synic_message_page; 173*621191d7SNuno Das Neves struct hv_synic_event_flags_page *synic_event_flags_page; 174*621191d7SNuno Das Neves struct hv_synic_event_ring_page *synic_event_ring_page; 175*621191d7SNuno Das Neves }; 176*621191d7SNuno Das Neves 177*621191d7SNuno Das Neves struct mshv_root { 178*621191d7SNuno Das Neves struct hv_synic_pages __percpu *synic_pages; 179*621191d7SNuno Das Neves spinlock_t pt_ht_lock; 180*621191d7SNuno Das Neves DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); 181*621191d7SNuno Das Neves }; 182*621191d7SNuno Das Neves 183*621191d7SNuno Das Neves /* 184*621191d7SNuno Das Neves * Callback for doorbell events. 185*621191d7SNuno Das Neves * NOTE: This is called in interrupt context. Callback 186*621191d7SNuno Das Neves * should defer slow and sleeping logic to later. 187*621191d7SNuno Das Neves */ 188*621191d7SNuno Das Neves typedef void (*doorbell_cb_t) (int doorbell_id, void *); 189*621191d7SNuno Das Neves 190*621191d7SNuno Das Neves /* 191*621191d7SNuno Das Neves * port table information 192*621191d7SNuno Das Neves */ 193*621191d7SNuno Das Neves struct port_table_info { 194*621191d7SNuno Das Neves struct rcu_head portbl_rcu; 195*621191d7SNuno Das Neves enum hv_port_type hv_port_type; 196*621191d7SNuno Das Neves union { 197*621191d7SNuno Das Neves struct { 198*621191d7SNuno Das Neves u64 reserved[2]; 199*621191d7SNuno Das Neves } hv_port_message; 200*621191d7SNuno Das Neves struct { 201*621191d7SNuno Das Neves u64 reserved[2]; 202*621191d7SNuno Das Neves } hv_port_event; 203*621191d7SNuno Das Neves struct { 204*621191d7SNuno Das Neves u64 reserved[2]; 205*621191d7SNuno Das Neves } hv_port_monitor; 206*621191d7SNuno Das Neves struct { 207*621191d7SNuno Das Neves doorbell_cb_t doorbell_cb; 208*621191d7SNuno Das Neves void *data; 209*621191d7SNuno Das Neves } hv_port_doorbell; 210*621191d7SNuno Das Neves }; 211*621191d7SNuno Das Neves }; 212*621191d7SNuno Das Neves 213*621191d7SNuno Das Neves int mshv_update_routing_table(struct mshv_partition *partition, 214*621191d7SNuno Das Neves const struct mshv_user_irq_entry *entries, 215*621191d7SNuno Das Neves unsigned int numents); 216*621191d7SNuno Das Neves void mshv_free_routing_table(struct mshv_partition *partition); 217*621191d7SNuno Das Neves 218*621191d7SNuno Das Neves struct mshv_guest_irq_ent mshv_ret_girq_entry(struct mshv_partition *partition, 219*621191d7SNuno Das Neves u32 irq_num); 220*621191d7SNuno Das Neves 221*621191d7SNuno Das Neves void mshv_copy_girq_info(struct mshv_guest_irq_ent *src_irq, 222*621191d7SNuno Das Neves struct mshv_lapic_irq *dest_irq); 223*621191d7SNuno Das Neves 224*621191d7SNuno Das Neves void mshv_irqfd_routing_update(struct mshv_partition *partition); 225*621191d7SNuno Das Neves 226*621191d7SNuno Das Neves void mshv_port_table_fini(void); 227*621191d7SNuno Das Neves int mshv_portid_alloc(struct port_table_info *info); 228*621191d7SNuno Das Neves int mshv_portid_lookup(int port_id, struct port_table_info *info); 229*621191d7SNuno Das Neves void mshv_portid_free(int port_id); 230*621191d7SNuno Das Neves 231*621191d7SNuno Das Neves int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, 232*621191d7SNuno Das Neves void *data, u64 gpa, u64 val, u64 flags); 233*621191d7SNuno Das Neves void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); 234*621191d7SNuno Das Neves 235*621191d7SNuno Das Neves void mshv_isr(void); 236*621191d7SNuno Das Neves int mshv_synic_init(unsigned int cpu); 237*621191d7SNuno Das Neves int mshv_synic_cleanup(unsigned int cpu); 238*621191d7SNuno Das Neves 239*621191d7SNuno Das Neves static inline bool mshv_partition_encrypted(struct mshv_partition *partition) 240*621191d7SNuno Das Neves { 241*621191d7SNuno Das Neves return partition->isolation_type == HV_PARTITION_ISOLATION_TYPE_SNP; 242*621191d7SNuno Das Neves } 243*621191d7SNuno Das Neves 244*621191d7SNuno Das Neves struct mshv_partition *mshv_partition_get(struct mshv_partition *partition); 245*621191d7SNuno Das Neves void mshv_partition_put(struct mshv_partition *partition); 246*621191d7SNuno Das Neves struct mshv_partition *mshv_partition_find(u64 partition_id) __must_hold(RCU); 247*621191d7SNuno Das Neves 248*621191d7SNuno Das Neves /* hypercalls */ 249*621191d7SNuno Das Neves 250*621191d7SNuno Das Neves int hv_call_withdraw_memory(u64 count, int node, u64 partition_id); 251*621191d7SNuno Das Neves int hv_call_create_partition(u64 flags, 252*621191d7SNuno Das Neves struct hv_partition_creation_properties creation_properties, 253*621191d7SNuno Das Neves union hv_partition_isolation_properties isolation_properties, 254*621191d7SNuno Das Neves u64 *partition_id); 255*621191d7SNuno Das Neves int hv_call_initialize_partition(u64 partition_id); 256*621191d7SNuno Das Neves int hv_call_finalize_partition(u64 partition_id); 257*621191d7SNuno Das Neves int hv_call_delete_partition(u64 partition_id); 258*621191d7SNuno Das Neves int hv_call_map_mmio_pages(u64 partition_id, u64 gfn, u64 mmio_spa, u64 numpgs); 259*621191d7SNuno Das Neves int hv_call_map_gpa_pages(u64 partition_id, u64 gpa_target, u64 page_count, 260*621191d7SNuno Das Neves u32 flags, struct page **pages); 261*621191d7SNuno Das Neves int hv_call_unmap_gpa_pages(u64 partition_id, u64 gpa_target, u64 page_count, 262*621191d7SNuno Das Neves u32 flags); 263*621191d7SNuno Das Neves int hv_call_delete_vp(u64 partition_id, u32 vp_index); 264*621191d7SNuno Das Neves int hv_call_assert_virtual_interrupt(u64 partition_id, u32 vector, 265*621191d7SNuno Das Neves u64 dest_addr, 266*621191d7SNuno Das Neves union hv_interrupt_control control); 267*621191d7SNuno Das Neves int hv_call_clear_virtual_interrupt(u64 partition_id); 268*621191d7SNuno Das Neves int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn, 269*621191d7SNuno Das Neves union hv_gpa_page_access_state_flags state_flags, 270*621191d7SNuno Das Neves int *written_total, 271*621191d7SNuno Das Neves union hv_gpa_page_access_state *states); 272*621191d7SNuno Das Neves int hv_call_get_vp_state(u32 vp_index, u64 partition_id, 273*621191d7SNuno Das Neves struct hv_vp_state_data state_data, 274*621191d7SNuno Das Neves /* Choose between pages and ret_output */ 275*621191d7SNuno Das Neves u64 page_count, struct page **pages, 276*621191d7SNuno Das Neves union hv_output_get_vp_state *ret_output); 277*621191d7SNuno Das Neves int hv_call_set_vp_state(u32 vp_index, u64 partition_id, 278*621191d7SNuno Das Neves /* Choose between pages and bytes */ 279*621191d7SNuno Das Neves struct hv_vp_state_data state_data, u64 page_count, 280*621191d7SNuno Das Neves struct page **pages, u32 num_bytes, u8 *bytes); 281*621191d7SNuno Das Neves int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type, 282*621191d7SNuno Das Neves union hv_input_vtl input_vtl, 283*621191d7SNuno Das Neves struct page **state_page); 284*621191d7SNuno Das Neves int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type, 285*621191d7SNuno Das Neves union hv_input_vtl input_vtl); 286*621191d7SNuno Das Neves int hv_call_create_port(u64 port_partition_id, union hv_port_id port_id, 287*621191d7SNuno Das Neves u64 connection_partition_id, struct hv_port_info *port_info, 288*621191d7SNuno Das Neves u8 port_vtl, u8 min_connection_vtl, int node); 289*621191d7SNuno Das Neves int hv_call_delete_port(u64 port_partition_id, union hv_port_id port_id); 290*621191d7SNuno Das Neves int hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id, 291*621191d7SNuno Das Neves u64 connection_partition_id, 292*621191d7SNuno Das Neves union hv_connection_id connection_id, 293*621191d7SNuno Das Neves struct hv_connection_info *connection_info, 294*621191d7SNuno Das Neves u8 connection_vtl, int node); 295*621191d7SNuno Das Neves int hv_call_disconnect_port(u64 connection_partition_id, 296*621191d7SNuno Das Neves union hv_connection_id connection_id); 297*621191d7SNuno Das Neves int hv_call_notify_port_ring_empty(u32 sint_index); 298*621191d7SNuno Das Neves int hv_call_map_stat_page(enum hv_stats_object_type type, 299*621191d7SNuno Das Neves const union hv_stats_object_identity *identity, 300*621191d7SNuno Das Neves void **addr); 301*621191d7SNuno Das Neves int hv_call_unmap_stat_page(enum hv_stats_object_type type, 302*621191d7SNuno Das Neves const union hv_stats_object_identity *identity); 303*621191d7SNuno Das Neves int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages, 304*621191d7SNuno Das Neves u64 page_struct_count, u32 host_access, 305*621191d7SNuno Das Neves u32 flags, u8 acquire); 306*621191d7SNuno Das Neves 307*621191d7SNuno Das Neves extern struct mshv_root mshv_root; 308*621191d7SNuno Das Neves extern enum hv_scheduler_type hv_scheduler_type; 309*621191d7SNuno Das Neves extern u8 * __percpu *hv_synic_eventring_tail; 310*621191d7SNuno Das Neves 311*621191d7SNuno Das Neves #endif /* _MSHV_ROOT_H_ */ 312