1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 */ 5 6 #ifndef __LS3A_KVM_EXT_IRQ_H 7 #define __LS3A_KVM_EXT_IRQ_H 8 9 #include <linux/mm_types.h> 10 #include <linux/hrtimer.h> 11 #include <linux/kvm_host.h> 12 #include <linux/spinlock.h> 13 #include <linux/seq_file.h> 14 15 #include <kvm/iodev.h> 16 17 #define IOCSR_EXTIOI_ADDR KVM_IOCSR_EXTIOI_NODEMAP_BASE 18 19 #define EXTIOI_ADDR_OFF 0x10000 20 #define EXTIOI_REG_BASE (LOONGSON_VIRT_REG_BASE + EXTIOI_ADDR_OFF) 21 #define EXTIOI_REG_END (EXTIOI_REG_BASE + 0x20000) 22 #define EXTIOI_ADDR_SIZE (EXTIOI_REG_END - EXTIOI_REG_BASE) 23 #define EXTIOI_PERCORE_REG_OFF 0x10000 24 #define EXTIOI_PERCORE_REG_END (EXTIOI_PERCORE_REG_OFF + 0x10000) 25 26 #define EXTIOI_ADDR(off) (EXTIOI_REG_BASE + (off) - IOCSR_EXTIOI_ADDR) 27 #define EXTIOI_PERCORE_ADDR(id, off) \ 28 (EXTIOI_REG_BASE + EXTIOI_PERCORE_REG_OFF + ((id) << 8) + (off)) 29 30 #define EXTIOI_NODETYPE_START (KVM_IOCSR_EXTIOI_NODEMAP_BASE - IOCSR_EXTIOI_ADDR) 31 #define EXTIOI_NODETYPE_END (EXTIOI_NODETYPE_START + 0x20) 32 #define EXTIOI_IPMAP_START (KVM_IOCSR_EXTIOI_IPMAP_BASE - IOCSR_EXTIOI_ADDR) 33 #define EXTIOI_IPMAP_END (EXTIOI_IPMAP_START + 0x8) 34 #define EXTIOI_ENABLE_START (KVM_IOCSR_EXTIOI_EN_BASE - IOCSR_EXTIOI_ADDR) 35 #define EXTIOI_ENABLE_END (EXTIOI_ENABLE_START + 0x20) 36 #define EXTIOI_BOUNCE_START (KVM_IOCSR_EXTIOI_BOUNCE_BASE - IOCSR_EXTIOI_ADDR) 37 #define EXTIOI_BOUNCE_END (EXTIOI_BOUNCE_START + 0x20) 38 #define EXTIOI_ISR_START (0x1700 - IOCSR_EXTIOI_ADDR) 39 #define EXTIOI_ISR_END (EXTIOI_ISR_START + 0x20) 40 #define EXTIOI_COREMAP_START (KVM_IOCSR_EXTIOI_ROUTE_BASE - IOCSR_EXTIOI_ADDR) 41 #define EXTIOI_COREMAP_END (EXTIOI_COREMAP_START + 0x100) 42 #define EXTIOI_COREISR_START (EXTIOI_PERCORE_REG_OFF) 43 #define EXTIOI_COREISR_END (EXTIOI_PERCORE_REG_END) 44 45 #define LS3A_INTC_IP 8 46 #define EXTIOI_IRQS KVM_EXTIOI_IRQS 47 #define EXTIOI_IRQS_BITMAP_SIZE (EXTIOI_IRQS / 8) 48 /* map to ipnum per 32 irqs */ 49 #define EXTIOI_IRQS_IPMAP_SIZE (EXTIOI_IRQS / 32) 50 #define EXTIOI_IRQS_PER_GROUP KVM_EXTIOI_IRQS_PER_GROUP 51 #define EXTIOI_IRQS_COREMAP_SIZE (EXTIOI_IRQS) 52 #define EXTIOI_IRQS_NODETYPE_SIZE KVM_EXTIOI_IRQS_NODETYPE_SIZE 53 54 typedef struct kvm_ls3a_extirq_state { 55 union ext_en { 56 uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8]; 57 uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4]; 58 uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE]; 59 } ext_en; 60 union bounce { 61 uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8]; 62 uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4]; 63 uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE]; 64 } bounce; 65 union ext_isr { 66 uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8]; 67 uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4]; 68 uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE]; 69 } ext_isr; 70 union ext_core_isr { 71 uint64_t reg_u64[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE / 8]; 72 uint32_t reg_u32[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE / 4]; 73 uint8_t reg_u8[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE]; 74 } ext_core_isr; 75 union ip_map { 76 uint64_t reg_u64; 77 uint32_t reg_u32[EXTIOI_IRQS_IPMAP_SIZE / 4]; 78 uint8_t reg_u8[EXTIOI_IRQS_IPMAP_SIZE]; 79 } ip_map; 80 union core_map { 81 uint64_t reg_u64[EXTIOI_IRQS_COREMAP_SIZE / 8]; 82 uint32_t reg_u32[EXTIOI_IRQS_COREMAP_SIZE / 4]; 83 uint8_t reg_u8[EXTIOI_IRQS_COREMAP_SIZE]; 84 } core_map; 85 union node_type { 86 uint64_t reg_u64[EXTIOI_IRQS_NODETYPE_SIZE / 4]; 87 uint32_t reg_u32[EXTIOI_IRQS_NODETYPE_SIZE / 2]; 88 uint16_t reg_u16[EXTIOI_IRQS_NODETYPE_SIZE]; 89 uint8_t reg_u8[EXTIOI_IRQS_NODETYPE_SIZE * 2]; 90 } node_type; 91 92 /*software state */ 93 uint8_t ext_sw_ipmap[EXTIOI_IRQS]; 94 uint8_t ext_sw_coremap[EXTIOI_IRQS]; 95 uint8_t ext_sw_ipisr[KVM_MAX_VCPUS][LS3A_INTC_IP][EXTIOI_IRQS_BITMAP_SIZE]; 96 } LS3AExtirqState; 97 98 struct ls3a_kvm_extirq { 99 spinlock_t lock; 100 struct kvm *kvm; 101 struct kvm_io_device device; 102 struct kvm_ls3a_extirq_state ls3a_ext_irq; 103 }; 104 ls3a_ext_irqchip(struct kvm *kvm)105static inline struct ls3a_kvm_extirq *ls3a_ext_irqchip(struct kvm *kvm) 106 { 107 return kvm->arch.v_extirq; 108 } 109 ls3a_extirq_in_kernel(struct kvm *kvm)110static inline int ls3a_extirq_in_kernel(struct kvm *kvm) 111 { 112 int ret; 113 114 ret = (ls3a_ext_irqchip(kvm) != NULL); 115 return ret; 116 } 117 118 119 void ext_irq_handler(struct kvm *kvm, int irq, int level); 120 int kvm_create_ls3a_ext_irq(struct kvm *kvm); 121 int kvm_get_ls3a_extirq(struct kvm *kvm, 122 struct kvm_loongarch_ls3a_extirq_state *state); 123 int kvm_set_ls3a_extirq(struct kvm *kvm, 124 struct kvm_loongarch_ls3a_extirq_state *state); 125 void kvm_destroy_ls3a_ext_irq(struct kvm *kvm); 126 void msi_irq_handler(struct kvm *kvm, int irq, int level); 127 int kvm_setup_ls3a_extirq(struct kvm *kvm); 128 void kvm_dump_ls3a_extirq_state(struct seq_file *m, struct ls3a_kvm_extirq *irqchip); 129 #endif 130