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