xref: /qemu/hw/intc/loongarch_ipi_kvm.c (revision f936caa315750406f50feb1ac9c93770b47ebe96)
1412f6555SBibo Mao /* SPDX-License-Identifier: GPL-2.0-or-later */
2412f6555SBibo Mao /*
3412f6555SBibo Mao  * LoongArch IPI interrupt KVM support
4412f6555SBibo Mao  *
5412f6555SBibo Mao  * Copyright (C) 2025 Loongson Technology Corporation Limited
6412f6555SBibo Mao  */
7412f6555SBibo Mao 
8412f6555SBibo Mao #include "qemu/osdep.h"
9412f6555SBibo Mao #include "qapi/error.h"
10412f6555SBibo Mao #include "hw/intc/loongarch_ipi.h"
11412f6555SBibo Mao #include "system/kvm.h"
12412f6555SBibo Mao #include "target/loongarch/cpu.h"
13412f6555SBibo Mao 
14*f936caa3SBibo Mao static void kvm_ipi_access_reg(int fd, uint64_t addr, uint32_t *val, bool write)
15*f936caa3SBibo Mao {
16*f936caa3SBibo Mao     kvm_device_access(fd, KVM_DEV_LOONGARCH_IPI_GRP_REGS,
17*f936caa3SBibo Mao                       addr, val, write, &error_abort);
18*f936caa3SBibo Mao }
19*f936caa3SBibo Mao 
20*f936caa3SBibo Mao static void kvm_ipi_access_regs(void *opaque, bool write)
21*f936caa3SBibo Mao {
22*f936caa3SBibo Mao     LoongsonIPICommonState *ipi = (LoongsonIPICommonState *)opaque;
23*f936caa3SBibo Mao     LoongarchIPIState *lis = LOONGARCH_IPI(opaque);
24*f936caa3SBibo Mao     IPICore *core;
25*f936caa3SBibo Mao     uint64_t attr;
26*f936caa3SBibo Mao     int cpu, fd = lis->dev_fd;
27*f936caa3SBibo Mao 
28*f936caa3SBibo Mao     for (cpu = 0; cpu < ipi->num_cpu; cpu++) {
29*f936caa3SBibo Mao         core = &ipi->cpu[cpu];
30*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_STATUS_OFF;
31*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->status, write);
32*f936caa3SBibo Mao 
33*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_EN_OFF;
34*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->en, write);
35*f936caa3SBibo Mao 
36*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_SET_OFF;
37*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->set, write);
38*f936caa3SBibo Mao 
39*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_CLEAR_OFF;
40*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->clear, write);
41*f936caa3SBibo Mao 
42*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_BUF_20;
43*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->buf[0], write);
44*f936caa3SBibo Mao 
45*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_BUF_28;
46*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->buf[2], write);
47*f936caa3SBibo Mao 
48*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_BUF_30;
49*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->buf[4], write);
50*f936caa3SBibo Mao 
51*f936caa3SBibo Mao         attr = (cpu << 16) | CORE_BUF_38;
52*f936caa3SBibo Mao         kvm_ipi_access_reg(fd, attr, &core->buf[6], write);
53*f936caa3SBibo Mao     }
54*f936caa3SBibo Mao }
55*f936caa3SBibo Mao 
56*f936caa3SBibo Mao int kvm_ipi_get(void *opaque)
57*f936caa3SBibo Mao {
58*f936caa3SBibo Mao     kvm_ipi_access_regs(opaque, false);
59*f936caa3SBibo Mao     return 0;
60*f936caa3SBibo Mao }
61*f936caa3SBibo Mao 
62*f936caa3SBibo Mao int kvm_ipi_put(void *opaque, int version_id)
63*f936caa3SBibo Mao {
64*f936caa3SBibo Mao     kvm_ipi_access_regs(opaque, true);
65*f936caa3SBibo Mao     return 0;
66*f936caa3SBibo Mao }
67*f936caa3SBibo Mao 
68412f6555SBibo Mao void kvm_ipi_realize(DeviceState *dev, Error **errp)
69412f6555SBibo Mao {
70412f6555SBibo Mao     LoongarchIPIState *lis = LOONGARCH_IPI(dev);
71412f6555SBibo Mao     int ret;
72412f6555SBibo Mao 
73412f6555SBibo Mao     ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_LOONGARCH_IPI, false);
74412f6555SBibo Mao     if (ret < 0) {
75412f6555SBibo Mao         fprintf(stderr, "IPI KVM_CREATE_DEVICE failed: %s\n",
76412f6555SBibo Mao                 strerror(-ret));
77412f6555SBibo Mao         abort();
78412f6555SBibo Mao     }
79412f6555SBibo Mao 
80412f6555SBibo Mao     lis->dev_fd = ret;
81412f6555SBibo Mao }
82