18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef __LS3A_KVM_EXT_IRQ_H 78c2ecf20Sopenharmony_ci#define __LS3A_KVM_EXT_IRQ_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/mm_types.h> 108c2ecf20Sopenharmony_ci#include <linux/hrtimer.h> 118c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 128c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 138c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <kvm/iodev.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define IOCSR_EXTIOI_ADDR KVM_IOCSR_EXTIOI_NODEMAP_BASE 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define EXTIOI_ADDR_OFF 0x10000 208c2ecf20Sopenharmony_ci#define EXTIOI_REG_BASE (LOONGSON_VIRT_REG_BASE + EXTIOI_ADDR_OFF) 218c2ecf20Sopenharmony_ci#define EXTIOI_REG_END (EXTIOI_REG_BASE + 0x20000) 228c2ecf20Sopenharmony_ci#define EXTIOI_ADDR_SIZE (EXTIOI_REG_END - EXTIOI_REG_BASE) 238c2ecf20Sopenharmony_ci#define EXTIOI_PERCORE_REG_OFF 0x10000 248c2ecf20Sopenharmony_ci#define EXTIOI_PERCORE_REG_END (EXTIOI_PERCORE_REG_OFF + 0x10000) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define EXTIOI_ADDR(off) (EXTIOI_REG_BASE + (off) - IOCSR_EXTIOI_ADDR) 278c2ecf20Sopenharmony_ci#define EXTIOI_PERCORE_ADDR(id, off) \ 288c2ecf20Sopenharmony_ci (EXTIOI_REG_BASE + EXTIOI_PERCORE_REG_OFF + ((id) << 8) + (off)) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define EXTIOI_NODETYPE_START (KVM_IOCSR_EXTIOI_NODEMAP_BASE - IOCSR_EXTIOI_ADDR) 318c2ecf20Sopenharmony_ci#define EXTIOI_NODETYPE_END (EXTIOI_NODETYPE_START + 0x20) 328c2ecf20Sopenharmony_ci#define EXTIOI_IPMAP_START (KVM_IOCSR_EXTIOI_IPMAP_BASE - IOCSR_EXTIOI_ADDR) 338c2ecf20Sopenharmony_ci#define EXTIOI_IPMAP_END (EXTIOI_IPMAP_START + 0x8) 348c2ecf20Sopenharmony_ci#define EXTIOI_ENABLE_START (KVM_IOCSR_EXTIOI_EN_BASE - IOCSR_EXTIOI_ADDR) 358c2ecf20Sopenharmony_ci#define EXTIOI_ENABLE_END (EXTIOI_ENABLE_START + 0x20) 368c2ecf20Sopenharmony_ci#define EXTIOI_BOUNCE_START (KVM_IOCSR_EXTIOI_BOUNCE_BASE - IOCSR_EXTIOI_ADDR) 378c2ecf20Sopenharmony_ci#define EXTIOI_BOUNCE_END (EXTIOI_BOUNCE_START + 0x20) 388c2ecf20Sopenharmony_ci#define EXTIOI_ISR_START (0x1700 - IOCSR_EXTIOI_ADDR) 398c2ecf20Sopenharmony_ci#define EXTIOI_ISR_END (EXTIOI_ISR_START + 0x20) 408c2ecf20Sopenharmony_ci#define EXTIOI_COREMAP_START (KVM_IOCSR_EXTIOI_ROUTE_BASE - IOCSR_EXTIOI_ADDR) 418c2ecf20Sopenharmony_ci#define EXTIOI_COREMAP_END (EXTIOI_COREMAP_START + 0x100) 428c2ecf20Sopenharmony_ci#define EXTIOI_COREISR_START (EXTIOI_PERCORE_REG_OFF) 438c2ecf20Sopenharmony_ci#define EXTIOI_COREISR_END (EXTIOI_PERCORE_REG_END) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define LS3A_INTC_IP 8 468c2ecf20Sopenharmony_ci#define EXTIOI_IRQS KVM_EXTIOI_IRQS 478c2ecf20Sopenharmony_ci#define EXTIOI_IRQS_BITMAP_SIZE (EXTIOI_IRQS / 8) 488c2ecf20Sopenharmony_ci/* map to ipnum per 32 irqs */ 498c2ecf20Sopenharmony_ci#define EXTIOI_IRQS_IPMAP_SIZE (EXTIOI_IRQS / 32) 508c2ecf20Sopenharmony_ci#define EXTIOI_IRQS_PER_GROUP KVM_EXTIOI_IRQS_PER_GROUP 518c2ecf20Sopenharmony_ci#define EXTIOI_IRQS_COREMAP_SIZE (EXTIOI_IRQS) 528c2ecf20Sopenharmony_ci#define EXTIOI_IRQS_NODETYPE_SIZE KVM_EXTIOI_IRQS_NODETYPE_SIZE 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_citypedef struct kvm_ls3a_extirq_state { 558c2ecf20Sopenharmony_ci union ext_en { 568c2ecf20Sopenharmony_ci uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8]; 578c2ecf20Sopenharmony_ci uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4]; 588c2ecf20Sopenharmony_ci uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE]; 598c2ecf20Sopenharmony_ci } ext_en; 608c2ecf20Sopenharmony_ci union bounce { 618c2ecf20Sopenharmony_ci uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8]; 628c2ecf20Sopenharmony_ci uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4]; 638c2ecf20Sopenharmony_ci uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE]; 648c2ecf20Sopenharmony_ci } bounce; 658c2ecf20Sopenharmony_ci union ext_isr { 668c2ecf20Sopenharmony_ci uint64_t reg_u64[EXTIOI_IRQS_BITMAP_SIZE / 8]; 678c2ecf20Sopenharmony_ci uint32_t reg_u32[EXTIOI_IRQS_BITMAP_SIZE / 4]; 688c2ecf20Sopenharmony_ci uint8_t reg_u8[EXTIOI_IRQS_BITMAP_SIZE]; 698c2ecf20Sopenharmony_ci } ext_isr; 708c2ecf20Sopenharmony_ci union ext_core_isr { 718c2ecf20Sopenharmony_ci uint64_t reg_u64[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE / 8]; 728c2ecf20Sopenharmony_ci uint32_t reg_u32[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE / 4]; 738c2ecf20Sopenharmony_ci uint8_t reg_u8[KVM_MAX_VCPUS][EXTIOI_IRQS_BITMAP_SIZE]; 748c2ecf20Sopenharmony_ci } ext_core_isr; 758c2ecf20Sopenharmony_ci union ip_map { 768c2ecf20Sopenharmony_ci uint64_t reg_u64; 778c2ecf20Sopenharmony_ci uint32_t reg_u32[EXTIOI_IRQS_IPMAP_SIZE / 4]; 788c2ecf20Sopenharmony_ci uint8_t reg_u8[EXTIOI_IRQS_IPMAP_SIZE]; 798c2ecf20Sopenharmony_ci } ip_map; 808c2ecf20Sopenharmony_ci union core_map { 818c2ecf20Sopenharmony_ci uint64_t reg_u64[EXTIOI_IRQS_COREMAP_SIZE / 8]; 828c2ecf20Sopenharmony_ci uint32_t reg_u32[EXTIOI_IRQS_COREMAP_SIZE / 4]; 838c2ecf20Sopenharmony_ci uint8_t reg_u8[EXTIOI_IRQS_COREMAP_SIZE]; 848c2ecf20Sopenharmony_ci } core_map; 858c2ecf20Sopenharmony_ci union node_type { 868c2ecf20Sopenharmony_ci uint64_t reg_u64[EXTIOI_IRQS_NODETYPE_SIZE / 4]; 878c2ecf20Sopenharmony_ci uint32_t reg_u32[EXTIOI_IRQS_NODETYPE_SIZE / 2]; 888c2ecf20Sopenharmony_ci uint16_t reg_u16[EXTIOI_IRQS_NODETYPE_SIZE]; 898c2ecf20Sopenharmony_ci uint8_t reg_u8[EXTIOI_IRQS_NODETYPE_SIZE * 2]; 908c2ecf20Sopenharmony_ci } node_type; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /*software state */ 938c2ecf20Sopenharmony_ci uint8_t ext_sw_ipmap[EXTIOI_IRQS]; 948c2ecf20Sopenharmony_ci uint8_t ext_sw_coremap[EXTIOI_IRQS]; 958c2ecf20Sopenharmony_ci uint8_t ext_sw_ipisr[KVM_MAX_VCPUS][LS3A_INTC_IP][EXTIOI_IRQS_BITMAP_SIZE]; 968c2ecf20Sopenharmony_ci} LS3AExtirqState; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistruct ls3a_kvm_extirq { 998c2ecf20Sopenharmony_ci spinlock_t lock; 1008c2ecf20Sopenharmony_ci struct kvm *kvm; 1018c2ecf20Sopenharmony_ci struct kvm_io_device device; 1028c2ecf20Sopenharmony_ci struct kvm_ls3a_extirq_state ls3a_ext_irq; 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic inline struct ls3a_kvm_extirq *ls3a_ext_irqchip(struct kvm *kvm) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci return kvm->arch.v_extirq; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline int ls3a_extirq_in_kernel(struct kvm *kvm) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci int ret; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci ret = (ls3a_ext_irqchip(kvm) != NULL); 1158c2ecf20Sopenharmony_ci return ret; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_civoid ext_irq_handler(struct kvm *kvm, int irq, int level); 1208c2ecf20Sopenharmony_ciint kvm_create_ls3a_ext_irq(struct kvm *kvm); 1218c2ecf20Sopenharmony_ciint kvm_get_ls3a_extirq(struct kvm *kvm, 1228c2ecf20Sopenharmony_ci struct kvm_loongarch_ls3a_extirq_state *state); 1238c2ecf20Sopenharmony_ciint kvm_set_ls3a_extirq(struct kvm *kvm, 1248c2ecf20Sopenharmony_ci struct kvm_loongarch_ls3a_extirq_state *state); 1258c2ecf20Sopenharmony_civoid kvm_destroy_ls3a_ext_irq(struct kvm *kvm); 1268c2ecf20Sopenharmony_civoid msi_irq_handler(struct kvm *kvm, int irq, int level); 1278c2ecf20Sopenharmony_ciint kvm_setup_ls3a_extirq(struct kvm *kvm); 1288c2ecf20Sopenharmony_civoid kvm_dump_ls3a_extirq_state(struct seq_file *m, struct ls3a_kvm_extirq *irqchip); 1298c2ecf20Sopenharmony_ci#endif 130