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#include <linux/highmem.h> 78c2ecf20Sopenharmony_ci#include <linux/mm.h> 88c2ecf20Sopenharmony_ci#include <linux/bitops.h> 98c2ecf20Sopenharmony_ci#include "ls3a_ipi.h" 108c2ecf20Sopenharmony_ci#include "ls7a_irq.h" 118c2ecf20Sopenharmony_ci#include "ls3a_ext_irq.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_civoid ls7a_ioapic_lock(struct ls7a_kvm_ioapic *s, unsigned long *flags) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci unsigned long tmp; 168c2ecf20Sopenharmony_ci spin_lock_irqsave(&s->lock, tmp); 178c2ecf20Sopenharmony_ci *flags = tmp; 188c2ecf20Sopenharmony_ci} 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_civoid ls7a_ioapic_unlock(struct ls7a_kvm_ioapic *s, unsigned long *flags) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci unsigned long tmp; 238c2ecf20Sopenharmony_ci tmp = *flags; 248c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&s->lock, tmp); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void kvm_ls7a_ioapic_raise(struct kvm *kvm, unsigned long mask) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci unsigned long irqnum, val; 308c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s = ls7a_ioapic_irqchip(kvm); 318c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *state; 328c2ecf20Sopenharmony_ci struct kvm_loongarch_interrupt irq; 338c2ecf20Sopenharmony_ci int i; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci state = &s->ls7a_ioapic; 368c2ecf20Sopenharmony_ci irq.cpu = -1; 378c2ecf20Sopenharmony_ci val = mask & state->intirr & (~state->int_mask); 388c2ecf20Sopenharmony_ci val &= ~state->intisr; 398c2ecf20Sopenharmony_ci for_each_set_bit(i, &val, 64) { 408c2ecf20Sopenharmony_ci state->intisr |= 0x1ULL << i; 418c2ecf20Sopenharmony_ci irqnum = state->htmsi_vector[i]; 428c2ecf20Sopenharmony_ci kvm_debug("msi_irq_handler,%ld,up\n", irqnum); 438c2ecf20Sopenharmony_ci msi_irq_handler(kvm, irqnum, 1); 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci kvm->stat.ls7a_ioapic_update++; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void kvm_ls7a_ioapic_lower(struct kvm *kvm, unsigned long mask) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci unsigned long irqnum, val; 528c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s = ls7a_ioapic_irqchip(kvm); 538c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *state; 548c2ecf20Sopenharmony_ci struct kvm_loongarch_interrupt irq; 558c2ecf20Sopenharmony_ci int i; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci state = &s->ls7a_ioapic; 588c2ecf20Sopenharmony_ci irq.cpu = -1; 598c2ecf20Sopenharmony_ci val = mask & state->intisr; 608c2ecf20Sopenharmony_ci for_each_set_bit(i, &val, 64) { 618c2ecf20Sopenharmony_ci state->intisr &= ~(0x1ULL << i); 628c2ecf20Sopenharmony_ci irqnum = state->htmsi_vector[i]; 638c2ecf20Sopenharmony_ci kvm_debug("msi_irq_handler,%ld,down\n", irqnum); 648c2ecf20Sopenharmony_ci msi_irq_handler(kvm, irqnum, 0); 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci kvm->stat.ls7a_ioapic_update++; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciint kvm_ls7a_set_msi(struct kvm_kernel_irq_routing_entry *e, 718c2ecf20Sopenharmony_ci struct kvm *kvm, int irq_source_id, int level, bool line_status) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci if (!level) 748c2ecf20Sopenharmony_ci return -1; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci kvm_debug("msi data is 0x%x\n", e->msi.data); 778c2ecf20Sopenharmony_ci msi_irq_handler(kvm, e->msi.data, 1); 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciint kvm_ls7a_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct kvm_kernel_irq_routing_entry route; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (msi->flags != 0) 868c2ecf20Sopenharmony_ci return -EINVAL; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci kvm->stat.ls7a_msi_irq++; 898c2ecf20Sopenharmony_ci route.msi.address_lo = msi->address_lo; 908c2ecf20Sopenharmony_ci route.msi.address_hi = msi->address_hi; 918c2ecf20Sopenharmony_ci route.msi.data = msi->data; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci kvm_debug("msi data is 0x%x\n", route.msi.data); 948c2ecf20Sopenharmony_ci return kvm_ls7a_set_msi(&route, kvm, 958c2ecf20Sopenharmony_ci KVM_USERSPACE_IRQ_SOURCE_ID, 1, false); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciint kvm_ls7a_ioapic_set_irq(struct kvm *kvm, int irq, int level) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s; 1028c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *state; 1038c2ecf20Sopenharmony_ci uint64_t mask = 1ULL << irq; 1048c2ecf20Sopenharmony_ci s = ls7a_ioapic_irqchip(kvm); 1058c2ecf20Sopenharmony_ci state = &s->ls7a_ioapic; 1068c2ecf20Sopenharmony_ci BUG_ON(irq < 0 || irq >= LS7A_IOAPIC_NUM_PINS); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (state->intedge & mask) { 1098c2ecf20Sopenharmony_ci /* edge triggered */ 1108c2ecf20Sopenharmony_ci if (level) { 1118c2ecf20Sopenharmony_ci if ((state->last_intirr & mask) == 0) { 1128c2ecf20Sopenharmony_ci state->intirr |= mask; 1138c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_raise(kvm, mask); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci state->last_intirr |= mask; 1168c2ecf20Sopenharmony_ci } else 1178c2ecf20Sopenharmony_ci state->last_intirr &= ~mask; 1188c2ecf20Sopenharmony_ci } else { 1198c2ecf20Sopenharmony_ci /* level triggered */ 1208c2ecf20Sopenharmony_ci if (!!level) { 1218c2ecf20Sopenharmony_ci if ((state->intirr & mask) == 0) { 1228c2ecf20Sopenharmony_ci state->intirr |= mask; 1238c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_raise(kvm, mask); 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci } else { 1268c2ecf20Sopenharmony_ci if (state->intirr & mask) { 1278c2ecf20Sopenharmony_ci state->intirr &= ~mask; 1288c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_lower(kvm, mask); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci kvm->stat.ls7a_ioapic_set_irq++; 1338c2ecf20Sopenharmony_ci return 0; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic int ls7a_ioapic_reg_write(struct ls7a_kvm_ioapic *s, 1378c2ecf20Sopenharmony_ci gpa_t addr, int len, const void *val) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct kvm *kvm; 1408c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *state; 1418c2ecf20Sopenharmony_ci int64_t offset_tmp; 1428c2ecf20Sopenharmony_ci uint64_t offset; 1438c2ecf20Sopenharmony_ci uint64_t old, himask, lowmask; 1448c2ecf20Sopenharmony_ci unsigned long data, flags; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci offset = addr & 0xfff; 1478c2ecf20Sopenharmony_ci kvm = s->kvm; 1488c2ecf20Sopenharmony_ci state = &(s->ls7a_ioapic); 1498c2ecf20Sopenharmony_ci lowmask = 0xFFFFFFFFUL; 1508c2ecf20Sopenharmony_ci himask = lowmask << 32; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (offset & (len - 1)) { 1538c2ecf20Sopenharmony_ci printk("%s(%d):unaligned address access %llx size %d \n", 1548c2ecf20Sopenharmony_ci __FUNCTION__, __LINE__, addr, len); 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (8 == len) { 1598c2ecf20Sopenharmony_ci data = *(uint64_t *)val; 1608c2ecf20Sopenharmony_ci switch (offset) { 1618c2ecf20Sopenharmony_ci case LS7A_INT_MASK_OFFSET: 1628c2ecf20Sopenharmony_ci old = state->int_mask; 1638c2ecf20Sopenharmony_ci state->int_mask = data; 1648c2ecf20Sopenharmony_ci if (old & ~data) 1658c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_raise(kvm, old & ~data); 1668c2ecf20Sopenharmony_ci if (~old & data) 1678c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_lower(kvm, ~old & data); 1688c2ecf20Sopenharmony_ci break; 1698c2ecf20Sopenharmony_ci case LS7A_INT_STATUS_OFFSET: 1708c2ecf20Sopenharmony_ci state->intisr = data; 1718c2ecf20Sopenharmony_ci break; 1728c2ecf20Sopenharmony_ci case LS7A_INT_EDGE_OFFSET: 1738c2ecf20Sopenharmony_ci state->intedge = data; 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci case LS7A_INT_CLEAR_OFFSET: 1768c2ecf20Sopenharmony_ci /* 1778c2ecf20Sopenharmony_ci * For emulated device, only clear edge triggered irq 1788c2ecf20Sopenharmony_ci * on writing INTCLR reg no effect on level triggered 1798c2ecf20Sopenharmony_ci * irq 1808c2ecf20Sopenharmony_ci * However for pass-through device with level-triggered 1818c2ecf20Sopenharmony_ci * intx, here need clear interrupt 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci old = data; 1848c2ecf20Sopenharmony_ci data = data & state->intedge; 1858c2ecf20Sopenharmony_ci state->intirr &= ~data; 1868c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_lower(kvm, data); 1878c2ecf20Sopenharmony_ci state->intisr &= ~data; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci data = old & ~state->intedge; 1908c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(kvm->arch.v_ioapic, &flags); 1918c2ecf20Sopenharmony_ci for_each_set_bit(offset_tmp, &data, 64) 1928c2ecf20Sopenharmony_ci kvm_notify_acked_irq(kvm, 0, offset_tmp); 1938c2ecf20Sopenharmony_ci ls7a_ioapic_lock(kvm->arch.v_ioapic, &flags); 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci case LS7A_INT_POL_OFFSET: 1968c2ecf20Sopenharmony_ci state->int_polarity = data; 1978c2ecf20Sopenharmony_ci break; 1988c2ecf20Sopenharmony_ci case LS7A_HTMSI_EN_OFFSET: 1998c2ecf20Sopenharmony_ci state->htmsi_en = data; 2008c2ecf20Sopenharmony_ci break; 2018c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL0_OFFSET: 2028c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL1_OFFSET: 2038c2ecf20Sopenharmony_ci break; 2048c2ecf20Sopenharmony_ci default: 2058c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 2068c2ecf20Sopenharmony_ci break; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci } else if (4 == len) { 2098c2ecf20Sopenharmony_ci data = *(uint32_t *)val; 2108c2ecf20Sopenharmony_ci switch (offset) { 2118c2ecf20Sopenharmony_ci case LS7A_INT_MASK_OFFSET: 2128c2ecf20Sopenharmony_ci old = state->int_mask & lowmask; 2138c2ecf20Sopenharmony_ci state->int_mask = (state->int_mask & himask) | data; 2148c2ecf20Sopenharmony_ci if (old & ~data) 2158c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_raise(kvm, old & ~data); 2168c2ecf20Sopenharmony_ci if (~old & data) 2178c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_lower(kvm, ~old & data); 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci case LS7A_INT_MASK_OFFSET + 4: 2208c2ecf20Sopenharmony_ci data = data << 32; 2218c2ecf20Sopenharmony_ci old = state->int_mask & himask; 2228c2ecf20Sopenharmony_ci state->int_mask = (state->int_mask & lowmask) | data; 2238c2ecf20Sopenharmony_ci if (old & ~data) 2248c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_raise(kvm, old & ~data); 2258c2ecf20Sopenharmony_ci if (~old & data) 2268c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_lower(kvm, ~old & data); 2278c2ecf20Sopenharmony_ci break; 2288c2ecf20Sopenharmony_ci case LS7A_INT_STATUS_OFFSET: 2298c2ecf20Sopenharmony_ci state->intisr = (state->intisr & himask) | data; 2308c2ecf20Sopenharmony_ci break; 2318c2ecf20Sopenharmony_ci case LS7A_INT_STATUS_OFFSET + 4: 2328c2ecf20Sopenharmony_ci data = data << 32; 2338c2ecf20Sopenharmony_ci state->intisr = (state->intisr & lowmask) | data; 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci case LS7A_INT_EDGE_OFFSET: 2368c2ecf20Sopenharmony_ci state->intedge = (state->intedge & himask) | data; 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci case LS7A_INT_EDGE_OFFSET + 4: 2398c2ecf20Sopenharmony_ci data = data << 32; 2408c2ecf20Sopenharmony_ci state->intedge = (state->intedge & lowmask) | data; 2418c2ecf20Sopenharmony_ci break; 2428c2ecf20Sopenharmony_ci case LS7A_INT_CLEAR_OFFSET + 4: 2438c2ecf20Sopenharmony_ci data = data << 32; 2448c2ecf20Sopenharmony_ci fallthrough; 2458c2ecf20Sopenharmony_ci case LS7A_INT_CLEAR_OFFSET: 2468c2ecf20Sopenharmony_ci old = data; 2478c2ecf20Sopenharmony_ci data = data & state->intedge; 2488c2ecf20Sopenharmony_ci state->intirr &= ~data; 2498c2ecf20Sopenharmony_ci kvm_ls7a_ioapic_lower(kvm, data); 2508c2ecf20Sopenharmony_ci state->intisr &= ~data; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci data = old & ~state->intedge; 2538c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(kvm->arch.v_ioapic, &flags); 2548c2ecf20Sopenharmony_ci for_each_set_bit(offset_tmp, &data, 64) 2558c2ecf20Sopenharmony_ci kvm_notify_acked_irq(kvm, 0, offset_tmp); 2568c2ecf20Sopenharmony_ci ls7a_ioapic_lock(kvm->arch.v_ioapic, &flags); 2578c2ecf20Sopenharmony_ci break; 2588c2ecf20Sopenharmony_ci case LS7A_INT_POL_OFFSET: 2598c2ecf20Sopenharmony_ci state->int_polarity = (state->int_polarity & himask) | data; 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci case LS7A_INT_POL_OFFSET+4: 2628c2ecf20Sopenharmony_ci data = data << 32; 2638c2ecf20Sopenharmony_ci state->int_polarity = (state->int_polarity & lowmask) | data; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci case LS7A_HTMSI_EN_OFFSET: 2668c2ecf20Sopenharmony_ci state->htmsi_en = (state->htmsi_en & himask) | data; 2678c2ecf20Sopenharmony_ci break; 2688c2ecf20Sopenharmony_ci case LS7A_HTMSI_EN_OFFSET+4: 2698c2ecf20Sopenharmony_ci data = data << 32; 2708c2ecf20Sopenharmony_ci state->htmsi_en = (state->htmsi_en & lowmask) | data; 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL0_OFFSET: 2738c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL0_OFFSET+4: 2748c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL1_OFFSET: 2758c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL1_OFFSET+4: 2768c2ecf20Sopenharmony_ci break; 2778c2ecf20Sopenharmony_ci default: 2788c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 2798c2ecf20Sopenharmony_ci break; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci } else if (1 == len) { 2828c2ecf20Sopenharmony_ci data = *(unsigned char *)val; 2838c2ecf20Sopenharmony_ci if (offset >= LS7A_HTMSI_VEC_OFFSET) { 2848c2ecf20Sopenharmony_ci offset_tmp = offset - LS7A_HTMSI_VEC_OFFSET; 2858c2ecf20Sopenharmony_ci if (offset_tmp >= 0 && offset_tmp < 64) { 2868c2ecf20Sopenharmony_ci state->htmsi_vector[offset_tmp] = 2878c2ecf20Sopenharmony_ci (uint8_t)(data & 0xff); 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci } else if (offset >= LS7A_ROUTE_ENTRY_OFFSET) { 2908c2ecf20Sopenharmony_ci offset_tmp = offset - LS7A_ROUTE_ENTRY_OFFSET; 2918c2ecf20Sopenharmony_ci if (offset_tmp >= 0 && offset_tmp < 64) { 2928c2ecf20Sopenharmony_ci state->route_entry[offset_tmp] = 2938c2ecf20Sopenharmony_ci (uint8_t)(data & 0xff); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } else { 2968c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci } else { 2998c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci kvm->stat.ioapic_reg_write++; 3028c2ecf20Sopenharmony_ci return 0; 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic inline struct ls7a_kvm_ioapic *to_ioapic(struct kvm_io_device *dev) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci return container_of(dev, struct ls7a_kvm_ioapic, dev_ls7a_ioapic); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic int kvm_ls7a_ioapic_write(struct kvm_vcpu *vcpu, 3118c2ecf20Sopenharmony_ci struct kvm_io_device *this, 3128c2ecf20Sopenharmony_ci gpa_t addr, int len, const void *val) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s = to_ioapic(this); 3158c2ecf20Sopenharmony_ci unsigned long flags; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci ls7a_ioapic_lock(s->kvm->arch.v_ioapic, &flags); 3188c2ecf20Sopenharmony_ci ls7a_ioapic_reg_write(s, addr, len, val); 3198c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(s->kvm->arch.v_ioapic, &flags); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return 0; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int ls7a_ioapic_reg_read(struct ls7a_kvm_ioapic *s, 3258c2ecf20Sopenharmony_ci gpa_t addr, int len, void *val) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci uint64_t offset, offset_tmp; 3288c2ecf20Sopenharmony_ci struct kvm *kvm; 3298c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *state; 3308c2ecf20Sopenharmony_ci uint64_t result = 0, lowmask, himask; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci state = &(s->ls7a_ioapic); 3338c2ecf20Sopenharmony_ci kvm = s->kvm; 3348c2ecf20Sopenharmony_ci offset = addr & 0xfff; 3358c2ecf20Sopenharmony_ci lowmask = 0xFFFFFFFFUL; 3368c2ecf20Sopenharmony_ci himask = lowmask << 32; 3378c2ecf20Sopenharmony_ci if (offset & (len - 1)) { 3388c2ecf20Sopenharmony_ci printk("%s(%d):unaligned address access %llx size %d \n", 3398c2ecf20Sopenharmony_ci __FUNCTION__, __LINE__, addr, len); 3408c2ecf20Sopenharmony_ci return 0; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (8 == len) { 3448c2ecf20Sopenharmony_ci switch (offset) { 3458c2ecf20Sopenharmony_ci case LS7A_INT_MASK_OFFSET: 3468c2ecf20Sopenharmony_ci result = state->int_mask; 3478c2ecf20Sopenharmony_ci break; 3488c2ecf20Sopenharmony_ci case LS7A_INT_STATUS_OFFSET: 3498c2ecf20Sopenharmony_ci result = state->intisr & (~state->int_mask); 3508c2ecf20Sopenharmony_ci break; 3518c2ecf20Sopenharmony_ci case LS7A_INT_EDGE_OFFSET: 3528c2ecf20Sopenharmony_ci result = state->intedge; 3538c2ecf20Sopenharmony_ci break; 3548c2ecf20Sopenharmony_ci case LS7A_INT_POL_OFFSET: 3558c2ecf20Sopenharmony_ci result = state->int_polarity; 3568c2ecf20Sopenharmony_ci break; 3578c2ecf20Sopenharmony_ci case LS7A_HTMSI_EN_OFFSET: 3588c2ecf20Sopenharmony_ci result = state->htmsi_en; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL0_OFFSET: 3618c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL1_OFFSET: 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci case LS7A_INT_ID_OFFSET: 3648c2ecf20Sopenharmony_ci result = LS7A_INT_ID_VER; 3658c2ecf20Sopenharmony_ci result = (result << 32) + LS7A_INT_ID_VAL; 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci default: 3688c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 3698c2ecf20Sopenharmony_ci break; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci if (val != NULL) 3728c2ecf20Sopenharmony_ci *(uint64_t *)val = result; 3738c2ecf20Sopenharmony_ci } else if (4 == len) { 3748c2ecf20Sopenharmony_ci switch (offset) { 3758c2ecf20Sopenharmony_ci case LS7A_INT_MASK_OFFSET: 3768c2ecf20Sopenharmony_ci result = state->int_mask & lowmask; 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci case LS7A_INT_MASK_OFFSET + 4: 3798c2ecf20Sopenharmony_ci result = state->int_mask & himask; 3808c2ecf20Sopenharmony_ci result = result >> 32; 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci case LS7A_INT_STATUS_OFFSET: 3838c2ecf20Sopenharmony_ci result = state->intisr & (~state->int_mask) & lowmask; 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci case LS7A_INT_STATUS_OFFSET + 4: 3868c2ecf20Sopenharmony_ci result = state->intisr & (~state->int_mask) & himask; 3878c2ecf20Sopenharmony_ci result = result >> 32; 3888c2ecf20Sopenharmony_ci break; 3898c2ecf20Sopenharmony_ci case LS7A_INT_EDGE_OFFSET: 3908c2ecf20Sopenharmony_ci result = state->intedge & lowmask; 3918c2ecf20Sopenharmony_ci break; 3928c2ecf20Sopenharmony_ci case LS7A_INT_EDGE_OFFSET + 4: 3938c2ecf20Sopenharmony_ci result = state->intedge & himask; 3948c2ecf20Sopenharmony_ci result = result >> 32; 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci case LS7A_INT_POL_OFFSET: 3978c2ecf20Sopenharmony_ci result = state->int_polarity & lowmask; 3988c2ecf20Sopenharmony_ci break; 3998c2ecf20Sopenharmony_ci case LS7A_INT_POL_OFFSET + 4: 4008c2ecf20Sopenharmony_ci result = state->int_polarity & himask; 4018c2ecf20Sopenharmony_ci result = result >> 32; 4028c2ecf20Sopenharmony_ci break; 4038c2ecf20Sopenharmony_ci case LS7A_HTMSI_EN_OFFSET: 4048c2ecf20Sopenharmony_ci result = state->htmsi_en & lowmask; 4058c2ecf20Sopenharmony_ci break; 4068c2ecf20Sopenharmony_ci case LS7A_HTMSI_EN_OFFSET + 4: 4078c2ecf20Sopenharmony_ci result = state->htmsi_en & himask; 4088c2ecf20Sopenharmony_ci result = result >> 32; 4098c2ecf20Sopenharmony_ci break; 4108c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL0_OFFSET: 4118c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL0_OFFSET + 4: 4128c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL1_OFFSET: 4138c2ecf20Sopenharmony_ci case LS7A_AUTO_CTRL1_OFFSET + 4: 4148c2ecf20Sopenharmony_ci break; 4158c2ecf20Sopenharmony_ci case LS7A_INT_ID_OFFSET: 4168c2ecf20Sopenharmony_ci result = LS7A_INT_ID_VAL; 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci case LS7A_INT_ID_OFFSET + 4: 4198c2ecf20Sopenharmony_ci result = LS7A_INT_ID_VER; 4208c2ecf20Sopenharmony_ci break; 4218c2ecf20Sopenharmony_ci default: 4228c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 4238c2ecf20Sopenharmony_ci break; 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci if (val != NULL) 4268c2ecf20Sopenharmony_ci *(uint32_t *)val = result; 4278c2ecf20Sopenharmony_ci } else if (1 == len) { 4288c2ecf20Sopenharmony_ci if (offset >= LS7A_HTMSI_VEC_OFFSET) { 4298c2ecf20Sopenharmony_ci offset_tmp = offset - LS7A_HTMSI_VEC_OFFSET; 4308c2ecf20Sopenharmony_ci if (offset_tmp >= 0 && offset_tmp < 64) { 4318c2ecf20Sopenharmony_ci result = state->htmsi_vector[offset_tmp]; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci } else if (offset >= LS7A_ROUTE_ENTRY_OFFSET) { 4348c2ecf20Sopenharmony_ci offset_tmp = offset - LS7A_ROUTE_ENTRY_OFFSET; 4358c2ecf20Sopenharmony_ci if (offset_tmp >= 0 && offset_tmp < 64) { 4368c2ecf20Sopenharmony_ci result = state->route_entry[offset_tmp]; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci } else { 4398c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci if (val != NULL) 4428c2ecf20Sopenharmony_ci *(unsigned char *)val = result; 4438c2ecf20Sopenharmony_ci } else { 4448c2ecf20Sopenharmony_ci WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len); 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci kvm->stat.ioapic_reg_read++; 4478c2ecf20Sopenharmony_ci return result; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int kvm_ls7a_ioapic_read(struct kvm_vcpu *vcpu, 4518c2ecf20Sopenharmony_ci struct kvm_io_device *this, 4528c2ecf20Sopenharmony_ci gpa_t addr, int len, void *val) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s = to_ioapic(this); 4558c2ecf20Sopenharmony_ci unsigned long flags; 4568c2ecf20Sopenharmony_ci uint64_t result = 0; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci ls7a_ioapic_lock(s->kvm->arch.v_ioapic, &flags); 4598c2ecf20Sopenharmony_ci result = ls7a_ioapic_reg_read(s, addr, len, val); 4608c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(s->kvm->arch.v_ioapic, &flags); 4618c2ecf20Sopenharmony_ci return 0; 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic const struct kvm_io_device_ops kvm_ls7a_ioapic_ops = { 4658c2ecf20Sopenharmony_ci .read = kvm_ls7a_ioapic_read, 4668c2ecf20Sopenharmony_ci .write = kvm_ls7a_ioapic_write, 4678c2ecf20Sopenharmony_ci}; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic int kvm_ls7a_ioapic_alias_read(struct kvm_vcpu *vcpu, 4708c2ecf20Sopenharmony_ci struct kvm_io_device *this, gpa_t addr, int len, void *val) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s; 4738c2ecf20Sopenharmony_ci unsigned long flags; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci s = container_of(this, struct ls7a_kvm_ioapic, ls7a_ioapic_alias); 4768c2ecf20Sopenharmony_ci ls7a_ioapic_lock(s->kvm->arch.v_ioapic, &flags); 4778c2ecf20Sopenharmony_ci ls7a_ioapic_reg_read(s, addr, len, val); 4788c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(s->kvm->arch.v_ioapic, &flags); 4798c2ecf20Sopenharmony_ci return 0; 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic int kvm_ls7a_ioapic_alias_write(struct kvm_vcpu *vcpu, 4838c2ecf20Sopenharmony_ci struct kvm_io_device *this, gpa_t addr, int len, const void *val) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s; 4868c2ecf20Sopenharmony_ci unsigned long flags; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci s = container_of(this, struct ls7a_kvm_ioapic, ls7a_ioapic_alias); 4898c2ecf20Sopenharmony_ci ls7a_ioapic_lock(s->kvm->arch.v_ioapic, &flags); 4908c2ecf20Sopenharmony_ci ls7a_ioapic_reg_write(s, addr, len, val); 4918c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(s->kvm->arch.v_ioapic, &flags); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci return 0; 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic const struct kvm_io_device_ops kvm_ls7a_ioapic_ops_alias = { 4978c2ecf20Sopenharmony_ci .read = kvm_ls7a_ioapic_alias_read, 4988c2ecf20Sopenharmony_ci .write = kvm_ls7a_ioapic_alias_write, 4998c2ecf20Sopenharmony_ci}; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ciint kvm_create_ls7a_ioapic(struct kvm *kvm) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *s; 5048c2ecf20Sopenharmony_ci int ret; 5058c2ecf20Sopenharmony_ci unsigned long ls7a_ioapic_reg_base; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci s = kzalloc(sizeof(struct ls7a_kvm_ioapic), GFP_KERNEL); 5088c2ecf20Sopenharmony_ci if (!s) 5098c2ecf20Sopenharmony_ci return -ENOMEM; 5108c2ecf20Sopenharmony_ci spin_lock_init(&s->lock); 5118c2ecf20Sopenharmony_ci s->kvm = kvm; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci ls7a_ioapic_reg_base = LS7A_IOAPIC_GUEST_REG_BASE; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* 5168c2ecf20Sopenharmony_ci * Initialize MMIO device 5178c2ecf20Sopenharmony_ci */ 5188c2ecf20Sopenharmony_ci kvm_iodevice_init(&s->dev_ls7a_ioapic, &kvm_ls7a_ioapic_ops); 5198c2ecf20Sopenharmony_ci mutex_lock(&kvm->slots_lock); 5208c2ecf20Sopenharmony_ci ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, ls7a_ioapic_reg_base, 5218c2ecf20Sopenharmony_ci 0x1000, &s->dev_ls7a_ioapic); 5228c2ecf20Sopenharmony_ci if (ret < 0) { 5238c2ecf20Sopenharmony_ci kvm_err("Failed register ioapic, err:%d\n", ret); 5248c2ecf20Sopenharmony_ci goto fail_unlock; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci ls7a_ioapic_reg_base = LS7A_IOAPIC_GUEST_REG_BASE_ALIAS; 5288c2ecf20Sopenharmony_ci kvm_iodevice_init(&s->ls7a_ioapic_alias, &kvm_ls7a_ioapic_ops_alias); 5298c2ecf20Sopenharmony_ci ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, ls7a_ioapic_reg_base, 5308c2ecf20Sopenharmony_ci 0x1000, &s->ls7a_ioapic_alias); 5318c2ecf20Sopenharmony_ci if (ret < 0) { 5328c2ecf20Sopenharmony_ci kvm_err("Failed register alias ioapic, err:%d\n", ret); 5338c2ecf20Sopenharmony_ci kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, 5348c2ecf20Sopenharmony_ci &s->dev_ls7a_ioapic); 5358c2ecf20Sopenharmony_ci goto fail_unlock; 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci kvm->arch.v_ioapic = s; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci return 0; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cifail_unlock: 5448c2ecf20Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 5458c2ecf20Sopenharmony_ci kfree(s); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci return -EFAULT; 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ciint kvm_get_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *ls7a_ioapic = ls7a_ioapic_irqchip(kvm); 5548c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *ioapic_state = 5558c2ecf20Sopenharmony_ci &(ls7a_ioapic->ls7a_ioapic); 5568c2ecf20Sopenharmony_ci unsigned long flags; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci ls7a_ioapic_lock(ls7a_ioapic, &flags); 5598c2ecf20Sopenharmony_ci memcpy(state, ioapic_state, sizeof(struct kvm_ls7a_ioapic_state)); 5608c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(ls7a_ioapic, &flags); 5618c2ecf20Sopenharmony_ci kvm->stat.get_ls7a_ioapic++; 5628c2ecf20Sopenharmony_ci return 0; 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ciint kvm_set_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state) 5668c2ecf20Sopenharmony_ci{ 5678c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *ls7a_ioapic = ls7a_ioapic_irqchip(kvm); 5688c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *ioapic_state = 5698c2ecf20Sopenharmony_ci &(ls7a_ioapic->ls7a_ioapic); 5708c2ecf20Sopenharmony_ci unsigned long flags; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci if (!ls7a_ioapic) 5738c2ecf20Sopenharmony_ci return -EINVAL; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci ls7a_ioapic_lock(ls7a_ioapic, &flags); 5768c2ecf20Sopenharmony_ci memcpy(ioapic_state, state, sizeof(struct kvm_ls7a_ioapic_state)); 5778c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(ls7a_ioapic, &flags); 5788c2ecf20Sopenharmony_ci kvm->stat.set_ls7a_ioapic++; 5798c2ecf20Sopenharmony_ci return 0; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_civoid kvm_destroy_ls7a_ioapic(struct kvm *kvm) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *vpic = kvm->arch.v_ioapic; 5858c2ecf20Sopenharmony_ci if (!vpic) 5868c2ecf20Sopenharmony_ci return; 5878c2ecf20Sopenharmony_ci mutex_lock(&kvm->slots_lock); 5888c2ecf20Sopenharmony_ci kvm_io_bus_unregister_dev(vpic->kvm, KVM_MMIO_BUS, 5898c2ecf20Sopenharmony_ci &vpic->ls7a_ioapic_alias); 5908c2ecf20Sopenharmony_ci kvm_io_bus_unregister_dev(vpic->kvm, KVM_MMIO_BUS, 5918c2ecf20Sopenharmony_ci &vpic->dev_ls7a_ioapic); 5928c2ecf20Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 5938c2ecf20Sopenharmony_ci kfree(vpic); 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_civoid kvm_dump_ls7a_ioapic_state(struct seq_file *m, 5978c2ecf20Sopenharmony_ci struct ls7a_kvm_ioapic *ioapic) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state *ioapic_state; 6008c2ecf20Sopenharmony_ci unsigned long flags; 6018c2ecf20Sopenharmony_ci int i = 0; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci if (!ioapic) 6048c2ecf20Sopenharmony_ci return; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci seq_puts(m, "\nIOAPIC state:\n"); 6078c2ecf20Sopenharmony_ci ioapic_state = &(ioapic->ls7a_ioapic); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci ls7a_ioapic_lock(ioapic, &flags); 6108c2ecf20Sopenharmony_ci seq_puts(m, "irq masked: "); 6118c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 6128c2ecf20Sopenharmony_ci if (!test_bit(i, (void *)&ioapic_state->int_mask)) 6138c2ecf20Sopenharmony_ci seq_printf(m, "%d ", i); 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci seq_printf(m, "\nhtmsi_en:0x%016llx\n" 6168c2ecf20Sopenharmony_ci "intedge:0x%016llx", 6178c2ecf20Sopenharmony_ci ioapic_state->htmsi_en, 6188c2ecf20Sopenharmony_ci ioapic_state->intedge); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci seq_puts(m, "\nroute_entry: "); 6218c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 6228c2ecf20Sopenharmony_ci seq_printf(m, "%d ", ioapic_state->route_entry[i]); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci seq_puts(m, "\nhtmsi_vector: "); 6258c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 6268c2ecf20Sopenharmony_ci seq_printf(m, "%d ", ioapic_state->htmsi_vector[i]); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci seq_printf(m, "\nintirr:%016llx\n" 6298c2ecf20Sopenharmony_ci "intisr:%016llx\n", 6308c2ecf20Sopenharmony_ci ioapic_state->intirr, 6318c2ecf20Sopenharmony_ci ioapic_state->intisr); 6328c2ecf20Sopenharmony_ci ls7a_ioapic_unlock(ioapic, &flags); 6338c2ecf20Sopenharmony_ci} 634