xref: /qemu/hw/intc/loongarch_extioi_kvm.c (revision d01d42ccc9510c039b2e4ec49af164e374eab154)
18bf8814aSBibo Mao /* SPDX-License-Identifier: GPL-2.0-or-later */
28bf8814aSBibo Mao /*
38bf8814aSBibo Mao  * LoongArch EXTIOI interrupt kvm support
48bf8814aSBibo Mao  *
58bf8814aSBibo Mao  * Copyright (C) 2025 Loongson Technology Corporation Limited
68bf8814aSBibo Mao  */
78bf8814aSBibo Mao 
88bf8814aSBibo Mao #include "qemu/osdep.h"
98bf8814aSBibo Mao #include "qemu/typedefs.h"
108bf8814aSBibo Mao #include "hw/intc/loongarch_extioi.h"
118bf8814aSBibo Mao #include "linux/kvm.h"
128bf8814aSBibo Mao #include "qapi/error.h"
138bf8814aSBibo Mao #include "system/kvm.h"
148bf8814aSBibo Mao 
kvm_extioi_access_reg(int fd,uint64_t addr,void * val,bool write)15228c5413SBibo Mao static void kvm_extioi_access_reg(int fd, uint64_t addr, void *val, bool write)
16228c5413SBibo Mao {
17228c5413SBibo Mao     kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS,
18228c5413SBibo Mao                       addr, val, write, &error_abort);
19228c5413SBibo Mao }
20228c5413SBibo Mao 
kvm_extioi_access_sw_state(int fd,uint64_t addr,void * val,bool write)21228c5413SBibo Mao static void kvm_extioi_access_sw_state(int fd, uint64_t addr,
22228c5413SBibo Mao                                        void *val, bool write)
23228c5413SBibo Mao {
24228c5413SBibo Mao     kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS,
25228c5413SBibo Mao                       addr, val, write, &error_abort);
26228c5413SBibo Mao }
27228c5413SBibo Mao 
kvm_extioi_access_sw_status(void * opaque,bool write)28228c5413SBibo Mao static void kvm_extioi_access_sw_status(void *opaque, bool write)
29228c5413SBibo Mao {
30228c5413SBibo Mao     LoongArchExtIOICommonState *lecs = LOONGARCH_EXTIOI_COMMON(opaque);
31228c5413SBibo Mao     LoongArchExtIOIState *les = LOONGARCH_EXTIOI(opaque);
32228c5413SBibo Mao     int addr;
33228c5413SBibo Mao 
34228c5413SBibo Mao     addr = KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE;
35228c5413SBibo Mao     kvm_extioi_access_sw_state(les->dev_fd, addr, &lecs->status, write);
36228c5413SBibo Mao }
37228c5413SBibo Mao 
kvm_extioi_access_regs(void * opaque,bool write)38228c5413SBibo Mao static void kvm_extioi_access_regs(void *opaque, bool write)
39228c5413SBibo Mao {
40228c5413SBibo Mao     LoongArchExtIOICommonState *lecs = LOONGARCH_EXTIOI_COMMON(opaque);
41228c5413SBibo Mao     LoongArchExtIOIState *les = LOONGARCH_EXTIOI(opaque);
42228c5413SBibo Mao     int fd = les->dev_fd;
43228c5413SBibo Mao     int addr, offset, cpu;
44228c5413SBibo Mao 
45228c5413SBibo Mao     for (addr = EXTIOI_NODETYPE_START; addr < EXTIOI_NODETYPE_END; addr += 4) {
46228c5413SBibo Mao         offset = (addr - EXTIOI_NODETYPE_START) / 4;
47228c5413SBibo Mao         kvm_extioi_access_reg(fd, addr, &lecs->nodetype[offset], write);
48228c5413SBibo Mao     }
49228c5413SBibo Mao 
50228c5413SBibo Mao     for (addr = EXTIOI_IPMAP_START; addr < EXTIOI_IPMAP_END; addr += 4) {
51228c5413SBibo Mao         offset = (addr - EXTIOI_IPMAP_START) / 4;
52228c5413SBibo Mao         kvm_extioi_access_reg(fd, addr, &lecs->ipmap[offset], write);
53228c5413SBibo Mao     }
54228c5413SBibo Mao 
55228c5413SBibo Mao     for (addr = EXTIOI_ENABLE_START; addr < EXTIOI_ENABLE_END; addr += 4) {
56228c5413SBibo Mao         offset = (addr - EXTIOI_ENABLE_START) / 4;
57228c5413SBibo Mao         kvm_extioi_access_reg(fd, addr, &lecs->enable[offset], write);
58228c5413SBibo Mao     }
59228c5413SBibo Mao 
60228c5413SBibo Mao     for (addr = EXTIOI_BOUNCE_START; addr < EXTIOI_BOUNCE_END; addr += 4) {
61228c5413SBibo Mao         offset = (addr - EXTIOI_BOUNCE_START) / 4;
62228c5413SBibo Mao         kvm_extioi_access_reg(fd, addr, &lecs->bounce[offset], write);
63228c5413SBibo Mao     }
64228c5413SBibo Mao 
65228c5413SBibo Mao     for (addr = EXTIOI_ISR_START; addr < EXTIOI_ISR_END; addr += 4) {
66228c5413SBibo Mao         offset = (addr - EXTIOI_ISR_START) / 4;
67228c5413SBibo Mao         kvm_extioi_access_reg(fd, addr, &lecs->isr[offset], write);
68228c5413SBibo Mao     }
69228c5413SBibo Mao 
70228c5413SBibo Mao     for (addr = EXTIOI_COREMAP_START; addr < EXTIOI_COREMAP_END; addr += 4) {
71228c5413SBibo Mao         offset = (addr - EXTIOI_COREMAP_START) / 4;
72228c5413SBibo Mao         kvm_extioi_access_reg(fd, addr, &lecs->coremap[offset], write);
73228c5413SBibo Mao     }
74228c5413SBibo Mao 
75228c5413SBibo Mao     for (cpu = 0; cpu < lecs->num_cpu; cpu++) {
76228c5413SBibo Mao         for (addr = EXTIOI_COREISR_START;
77228c5413SBibo Mao              addr < EXTIOI_COREISR_END; addr += 4) {
78228c5413SBibo Mao             offset = (addr - EXTIOI_COREISR_START) / 4;
79228c5413SBibo Mao             kvm_extioi_access_reg(fd, (cpu << 16) | addr,
80228c5413SBibo Mao                                   &lecs->cpu[cpu].coreisr[offset], write);
81228c5413SBibo Mao         }
82228c5413SBibo Mao     }
83228c5413SBibo Mao }
84228c5413SBibo Mao 
kvm_extioi_get(void * opaque)85228c5413SBibo Mao int kvm_extioi_get(void *opaque)
86228c5413SBibo Mao {
87228c5413SBibo Mao     kvm_extioi_access_regs(opaque, false);
88228c5413SBibo Mao     kvm_extioi_access_sw_status(opaque, false);
89228c5413SBibo Mao     return 0;
90228c5413SBibo Mao }
91228c5413SBibo Mao 
kvm_extioi_put(void * opaque,int version_id)92228c5413SBibo Mao int kvm_extioi_put(void *opaque, int version_id)
93228c5413SBibo Mao {
94228c5413SBibo Mao     LoongArchExtIOIState *les = LOONGARCH_EXTIOI(opaque);
95228c5413SBibo Mao     int fd = les->dev_fd;
96228c5413SBibo Mao 
97*c642ddf1SBibo Mao     if (fd == 0) {
98*c642ddf1SBibo Mao         return 0;
99*c642ddf1SBibo Mao     }
100*c642ddf1SBibo Mao 
101228c5413SBibo Mao     kvm_extioi_access_regs(opaque, true);
102228c5413SBibo Mao     kvm_extioi_access_sw_status(opaque, true);
103228c5413SBibo Mao     kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL,
104228c5413SBibo Mao                       KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED,
105228c5413SBibo Mao                       NULL, true, &error_abort);
106228c5413SBibo Mao     return 0;
107228c5413SBibo Mao }
108228c5413SBibo Mao 
kvm_extioi_realize(DeviceState * dev,Error ** errp)1098bf8814aSBibo Mao void kvm_extioi_realize(DeviceState *dev, Error **errp)
1108bf8814aSBibo Mao {
1118bf8814aSBibo Mao     LoongArchExtIOICommonState *lecs = LOONGARCH_EXTIOI_COMMON(dev);
1128bf8814aSBibo Mao     LoongArchExtIOIState *les = LOONGARCH_EXTIOI(dev);
1138bf8814aSBibo Mao     int ret;
1148bf8814aSBibo Mao 
1158bf8814aSBibo Mao     ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_LOONGARCH_EIOINTC, false);
1168bf8814aSBibo Mao     if (ret < 0) {
1178bf8814aSBibo Mao         fprintf(stderr, "create KVM_LOONGARCH_EIOINTC failed: %s\n",
1188bf8814aSBibo Mao                 strerror(-ret));
1198bf8814aSBibo Mao         abort();
1208bf8814aSBibo Mao     }
1218bf8814aSBibo Mao 
1228bf8814aSBibo Mao     les->dev_fd = ret;
1238bf8814aSBibo Mao     ret = kvm_device_access(les->dev_fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL,
1248bf8814aSBibo Mao                             KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU,
1258bf8814aSBibo Mao                             &lecs->num_cpu, true, NULL);
1268bf8814aSBibo Mao     if (ret < 0) {
1278bf8814aSBibo Mao         fprintf(stderr, "KVM_LOONGARCH_EXTIOI_INIT_NUM_CPU failed: %s\n",
1288bf8814aSBibo Mao                 strerror(-ret));
1298bf8814aSBibo Mao         abort();
1308bf8814aSBibo Mao     }
1318bf8814aSBibo Mao 
1328bf8814aSBibo Mao     ret = kvm_device_access(les->dev_fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL,
1338bf8814aSBibo Mao                             KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE,
1348bf8814aSBibo Mao                             &lecs->features, true, NULL);
1358bf8814aSBibo Mao     if (ret < 0) {
1368bf8814aSBibo Mao         fprintf(stderr, "KVM_LOONGARCH_EXTIOI_INIT_FEATURE failed: %s\n",
1378bf8814aSBibo Mao                 strerror(-ret));
1388bf8814aSBibo Mao         abort();
1398bf8814aSBibo Mao     }
1408bf8814aSBibo Mao }
141