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 54typedef 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 98struct 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 105static inline struct ls3a_kvm_extirq *ls3a_ext_irqchip(struct kvm *kvm) 106{ 107 return kvm->arch.v_extirq; 108} 109 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 119void ext_irq_handler(struct kvm *kvm, int irq, int level); 120int kvm_create_ls3a_ext_irq(struct kvm *kvm); 121int kvm_get_ls3a_extirq(struct kvm *kvm, 122 struct kvm_loongarch_ls3a_extirq_state *state); 123int kvm_set_ls3a_extirq(struct kvm *kvm, 124 struct kvm_loongarch_ls3a_extirq_state *state); 125void kvm_destroy_ls3a_ext_irq(struct kvm *kvm); 126void msi_irq_handler(struct kvm *kvm, int irq, int level); 127int kvm_setup_ls3a_extirq(struct kvm *kvm); 128void kvm_dump_ls3a_extirq_state(struct seq_file *m, struct ls3a_kvm_extirq *irqchip); 129#endif 130