xref: /linux/arch/loongarch/kvm/intc/eiointc.c (revision 214f4aeb2255f2f9b5f5de1a15f650a429c43490)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2024 Loongson Technology Corporation Limited
4  */
5 
6 #include <asm/kvm_eiointc.h>
7 #include <asm/kvm_vcpu.h>
8 #include <linux/count_zeros.h>
9 
eiointc_set_sw_coreisr(struct loongarch_eiointc * s)10 static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
11 {
12 	int ipnum, cpu, cpuid, irq;
13 	struct kvm_vcpu *vcpu;
14 
15 	for (irq = 0; irq < EIOINTC_IRQS; irq++) {
16 		ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
17 		if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
18 			ipnum = count_trailing_zeros(ipnum);
19 			ipnum = ipnum < 4 ? ipnum : 0;
20 		} else
21 			ipnum = ipnum < LOONGSON_IP_NUM ? ipnum : 0;
22 
23 		cpuid = ((u8 *)s->coremap)[irq];
24 		vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid);
25 		if (!vcpu)
26 			continue;
27 
28 		cpu = vcpu->vcpu_id;
29 		if (test_bit(irq, (unsigned long *)s->coreisr[cpu]))
30 			__set_bit(irq, s->sw_coreisr[cpu][ipnum]);
31 		else
32 			__clear_bit(irq, s->sw_coreisr[cpu][ipnum]);
33 	}
34 }
35 
eiointc_update_irq(struct loongarch_eiointc * s,int irq,int level)36 static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
37 {
38 	int ipnum, cpu, found;
39 	struct kvm_vcpu *vcpu;
40 
41 	ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
42 	if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
43 		ipnum = count_trailing_zeros(ipnum);
44 		ipnum = ipnum < 4 ? ipnum : 0;
45 	} else
46 		ipnum = ipnum < LOONGSON_IP_NUM ? ipnum : 0;
47 
48 	cpu = s->sw_coremap[irq];
49 	vcpu = kvm_get_vcpu_by_id(s->kvm, cpu);
50 	if (unlikely(vcpu == NULL)) {
51 		kvm_pr_unimpl("%s: invalid target cpu: %d\n", __func__, cpu);
52 		return;
53 	}
54 
55 	if (level) {
56 		/* if not enable return false */
57 		if (!test_bit(irq, (unsigned long *)s->enable))
58 			return;
59 		__set_bit(irq, (unsigned long *)s->coreisr[cpu]);
60 		found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS);
61 		__set_bit(irq, s->sw_coreisr[cpu][ipnum]);
62 	} else {
63 		__clear_bit(irq, (unsigned long *)s->coreisr[cpu]);
64 		__clear_bit(irq, s->sw_coreisr[cpu][ipnum]);
65 		found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS);
66 	}
67 
68 	if (found < EIOINTC_IRQS)
69 		return; /* other irq is handling, needn't update parent irq */
70 
71 	if (level)
72 		kvm_queue_irq(vcpu, INT_HWI0 + ipnum);
73 	else
74 		kvm_dequeue_irq(vcpu, INT_HWI0 + ipnum);
75 	kvm_vcpu_kick(vcpu);
76 }
77 
eiointc_update_sw_coremap(struct loongarch_eiointc * s,int irq,u64 val,u32 len,bool notify)78 static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s,
79 					int irq, u64 val, u32 len, bool notify)
80 {
81 	int i, cpu, cpuid;
82 	struct kvm_vcpu *vcpu;
83 
84 	for (i = 0; i < len; i++) {
85 		cpuid = val & 0xff;
86 		val = val >> 8;
87 
88 		if (!(s->status & BIT(EIOINTC_ENABLE_CPU_ENCODE))) {
89 			cpuid = ffs(cpuid) - 1;
90 			cpuid = ((cpuid < 0) || (cpuid >= 4)) ? 0 : cpuid;
91 		}
92 
93 		vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid);
94 		if (!vcpu)
95 			continue;
96 
97 		cpu = vcpu->vcpu_id;
98 		if (s->sw_coremap[irq + i] == cpu)
99 			continue;
100 
101 		if (notify && test_bit(irq + i, (unsigned long *)s->isr)) {
102 			/* lower irq at old cpu and raise irq at new cpu */
103 			eiointc_update_irq(s, irq + i, 0);
104 			s->sw_coremap[irq + i] = cpu;
105 			eiointc_update_irq(s, irq + i, 1);
106 		} else {
107 			s->sw_coremap[irq + i] = cpu;
108 		}
109 	}
110 }
111 
eiointc_set_irq(struct loongarch_eiointc * s,int irq,int level)112 void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level)
113 {
114 	unsigned long flags;
115 	unsigned long *isr = (unsigned long *)s->isr;
116 
117 	spin_lock_irqsave(&s->lock, flags);
118 	level ? __set_bit(irq, isr) : __clear_bit(irq, isr);
119 	eiointc_update_irq(s, irq, level);
120 	spin_unlock_irqrestore(&s->lock, flags);
121 }
122 
loongarch_eiointc_read(struct kvm_vcpu * vcpu,struct loongarch_eiointc * s,gpa_t addr,unsigned long * val)123 static int loongarch_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s,
124 				gpa_t addr, unsigned long *val)
125 {
126 	int index;
127 	u64 data = 0;
128 	gpa_t offset;
129 
130 	offset = addr - EIOINTC_BASE;
131 	switch (offset) {
132 	case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
133 		index = (offset - EIOINTC_NODETYPE_START) >> 3;
134 		data = s->nodetype[index];
135 		break;
136 	case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
137 		index = (offset - EIOINTC_IPMAP_START) >> 3;
138 		data = s->ipmap;
139 		break;
140 	case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
141 		index = (offset - EIOINTC_ENABLE_START) >> 3;
142 		data = s->enable[index];
143 		break;
144 	case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
145 		index = (offset - EIOINTC_BOUNCE_START) >> 3;
146 		data = s->bounce[index];
147 		break;
148 	case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
149 		index = (offset - EIOINTC_COREISR_START) >> 3;
150 		data = s->coreisr[vcpu->vcpu_id][index];
151 		break;
152 	case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
153 		index = (offset - EIOINTC_COREMAP_START) >> 3;
154 		data = s->coremap[index];
155 		break;
156 	default:
157 		break;
158 	}
159 	*val = data;
160 
161 	return 0;
162 }
163 
kvm_eiointc_read(struct kvm_vcpu * vcpu,struct kvm_io_device * dev,gpa_t addr,int len,void * val)164 static int kvm_eiointc_read(struct kvm_vcpu *vcpu,
165 			struct kvm_io_device *dev,
166 			gpa_t addr, int len, void *val)
167 {
168 	unsigned long flags, data, offset;
169 	struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
170 
171 	if (!eiointc) {
172 		kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__);
173 		return 0;
174 	}
175 
176 	if (addr & (len - 1)) {
177 		kvm_pr_unimpl("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len);
178 		return 0;
179 	}
180 
181 	offset = addr & 0x7;
182 	addr -= offset;
183 	vcpu->stat.eiointc_read_exits++;
184 	spin_lock_irqsave(&eiointc->lock, flags);
185 	loongarch_eiointc_read(vcpu, eiointc, addr, &data);
186 	spin_unlock_irqrestore(&eiointc->lock, flags);
187 
188 	data = data >> (offset * 8);
189 	switch (len) {
190 	case 1:
191 		*(long *)val = (s8)data;
192 		break;
193 	case 2:
194 		*(long *)val = (s16)data;
195 		break;
196 	case 4:
197 		*(long *)val = (s32)data;
198 		break;
199 	default:
200 		*(long *)val = (long)data;
201 		break;
202 	}
203 
204 	return 0;
205 }
206 
loongarch_eiointc_write(struct kvm_vcpu * vcpu,struct loongarch_eiointc * s,gpa_t addr,u64 value,u64 field_mask)207 static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
208 				struct loongarch_eiointc *s,
209 				gpa_t addr, u64 value, u64 field_mask)
210 {
211 	int index, irq;
212 	u8 cpu;
213 	u64 data, old, mask;
214 	gpa_t offset;
215 
216 	offset = addr & 7;
217 	mask = field_mask << (offset * 8);
218 	data = (value & field_mask) << (offset * 8);
219 
220 	addr -= offset;
221 	offset = addr - EIOINTC_BASE;
222 
223 	switch (offset) {
224 	case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
225 		index = (offset - EIOINTC_NODETYPE_START) >> 3;
226 		old = s->nodetype[index];
227 		s->nodetype[index] = (old & ~mask) | data;
228 		break;
229 	case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
230 		/*
231 		 * ipmap cannot be set at runtime, can be set only at the beginning
232 		 * of irqchip driver, need not update upper irq level
233 		 */
234 		old = s->ipmap;
235 		s->ipmap = (old & ~mask) | data;
236 		break;
237 	case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
238 		index = (offset - EIOINTC_ENABLE_START) >> 3;
239 		old = s->enable[index];
240 		s->enable[index] = (old & ~mask) | data;
241 		/*
242 		 * 1: enable irq.
243 		 * update irq when isr is set.
244 		 */
245 		data = s->enable[index] & ~old & s->isr[index];
246 		while (data) {
247 			irq = __ffs(data);
248 			eiointc_update_irq(s, irq + index * 64, 1);
249 			data &= ~BIT_ULL(irq);
250 		}
251 		/*
252 		 * 0: disable irq.
253 		 * update irq when isr is set.
254 		 */
255 		data = ~s->enable[index] & old & s->isr[index];
256 		while (data) {
257 			irq = __ffs(data);
258 			eiointc_update_irq(s, irq + index * 64, 0);
259 			data &= ~BIT_ULL(irq);
260 		}
261 		break;
262 	case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
263 		/* do not emulate hw bounced irq routing */
264 		index = (offset - EIOINTC_BOUNCE_START) >> 3;
265 		old = s->bounce[index];
266 		s->bounce[index] = (old & ~mask) | data;
267 		break;
268 	case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
269 		index = (offset - EIOINTC_COREISR_START) >> 3;
270 		/* use attrs to get current cpu index */
271 		cpu = vcpu->vcpu_id;
272 		old = s->coreisr[cpu][index];
273 		/* write 1 to clear interrupt */
274 		s->coreisr[cpu][index] = old & ~data;
275 		data &= old;
276 		while (data) {
277 			irq = __ffs(data);
278 			eiointc_update_irq(s, irq + index * 64, 0);
279 			data &= ~BIT_ULL(irq);
280 		}
281 		break;
282 	case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
283 		index = (offset - EIOINTC_COREMAP_START) >> 3;
284 		old = s->coremap[index];
285 		s->coremap[index] = (old & ~mask) | data;
286 		data = s->coremap[index];
287 		eiointc_update_sw_coremap(s, index * 8, data, sizeof(data), true);
288 		break;
289 	default:
290 		break;
291 	}
292 
293 	return 0;
294 }
295 
kvm_eiointc_write(struct kvm_vcpu * vcpu,struct kvm_io_device * dev,gpa_t addr,int len,const void * val)296 static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
297 			struct kvm_io_device *dev,
298 			gpa_t addr, int len, const void *val)
299 {
300 	unsigned long flags, value;
301 	struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
302 
303 	if (!eiointc) {
304 		kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__);
305 		return 0;
306 	}
307 
308 	if (addr & (len - 1)) {
309 		kvm_pr_unimpl("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len);
310 		return 0;
311 	}
312 
313 	vcpu->stat.eiointc_write_exits++;
314 	spin_lock_irqsave(&eiointc->lock, flags);
315 	switch (len) {
316 	case 1:
317 		value = *(unsigned char *)val;
318 		loongarch_eiointc_write(vcpu, eiointc, addr, value, 0xFF);
319 		break;
320 	case 2:
321 		value = *(unsigned short *)val;
322 		loongarch_eiointc_write(vcpu, eiointc, addr, value, USHRT_MAX);
323 		break;
324 	case 4:
325 		value = *(unsigned int *)val;
326 		loongarch_eiointc_write(vcpu, eiointc, addr, value, UINT_MAX);
327 		break;
328 	default:
329 		value = *(unsigned long *)val;
330 		loongarch_eiointc_write(vcpu, eiointc, addr, value, ULONG_MAX);
331 		break;
332 	}
333 	spin_unlock_irqrestore(&eiointc->lock, flags);
334 
335 	return 0;
336 }
337 
338 static const struct kvm_io_device_ops kvm_eiointc_ops = {
339 	.read	= kvm_eiointc_read,
340 	.write	= kvm_eiointc_write,
341 };
342 
kvm_eiointc_virt_read(struct kvm_vcpu * vcpu,struct kvm_io_device * dev,gpa_t addr,int len,void * val)343 static int kvm_eiointc_virt_read(struct kvm_vcpu *vcpu,
344 				struct kvm_io_device *dev,
345 				gpa_t addr, int len, void *val)
346 {
347 	unsigned long flags;
348 	u32 *data = val;
349 	struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
350 
351 	if (!eiointc) {
352 		kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__);
353 		return 0;
354 	}
355 
356 	addr -= EIOINTC_VIRT_BASE;
357 	spin_lock_irqsave(&eiointc->lock, flags);
358 	switch (addr) {
359 	case EIOINTC_VIRT_FEATURES:
360 		*data = eiointc->features;
361 		break;
362 	case EIOINTC_VIRT_CONFIG:
363 		*data = eiointc->status;
364 		break;
365 	default:
366 		break;
367 	}
368 	spin_unlock_irqrestore(&eiointc->lock, flags);
369 
370 	return 0;
371 }
372 
kvm_eiointc_virt_write(struct kvm_vcpu * vcpu,struct kvm_io_device * dev,gpa_t addr,int len,const void * val)373 static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu,
374 				struct kvm_io_device *dev,
375 				gpa_t addr, int len, const void *val)
376 {
377 	unsigned long flags;
378 	u32 value = *(u32 *)val;
379 	struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
380 
381 	if (!eiointc) {
382 		kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__);
383 		return 0;
384 	}
385 
386 	addr -= EIOINTC_VIRT_BASE;
387 	spin_lock_irqsave(&eiointc->lock, flags);
388 	switch (addr) {
389 	case EIOINTC_VIRT_FEATURES:
390 		break;
391 	case EIOINTC_VIRT_CONFIG:
392 		/*
393 		 * eiointc features can only be set at disabled status
394 		 */
395 		if ((eiointc->status & BIT(EIOINTC_ENABLE)) && value) {
396 			break;
397 		}
398 		eiointc->status = value & eiointc->features;
399 		break;
400 	default:
401 		break;
402 	}
403 	spin_unlock_irqrestore(&eiointc->lock, flags);
404 
405 	return 0;
406 }
407 
408 static const struct kvm_io_device_ops kvm_eiointc_virt_ops = {
409 	.read	= kvm_eiointc_virt_read,
410 	.write	= kvm_eiointc_virt_write,
411 };
412 
kvm_eiointc_ctrl_access(struct kvm_device * dev,struct kvm_device_attr * attr)413 static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
414 					struct kvm_device_attr *attr)
415 {
416 	int ret = 0;
417 	unsigned long flags;
418 	unsigned long type = (unsigned long)attr->attr;
419 	u32 i, start_irq, val;
420 	void __user *data;
421 	struct loongarch_eiointc *s = dev->kvm->arch.eiointc;
422 
423 	data = (void __user *)attr->addr;
424 	switch (type) {
425 	case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
426 	case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
427 		if (copy_from_user(&val, data, 4))
428 			return -EFAULT;
429 		break;
430 	default:
431 		break;
432 	}
433 
434 	spin_lock_irqsave(&s->lock, flags);
435 	switch (type) {
436 	case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
437 		if (val > EIOINTC_ROUTE_MAX_VCPUS)
438 			ret = -EINVAL;
439 		else
440 			s->num_cpu = val;
441 		break;
442 	case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
443 		s->features = val;
444 		if (!(s->features & BIT(EIOINTC_HAS_VIRT_EXTENSION)))
445 			s->status |= BIT(EIOINTC_ENABLE);
446 		break;
447 	case KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED:
448 		eiointc_set_sw_coreisr(s);
449 		for (i = 0; i < (EIOINTC_IRQS / 8); i++) {
450 			start_irq = i * 8;
451 			eiointc_update_sw_coremap(s, start_irq,
452 					s->coremap[i], sizeof(u64), false);
453 		}
454 		break;
455 	default:
456 		break;
457 	}
458 	spin_unlock_irqrestore(&s->lock, flags);
459 
460 	return ret;
461 }
462 
kvm_eiointc_regs_access(struct kvm_device * dev,struct kvm_device_attr * attr,bool is_write,int * data)463 static int kvm_eiointc_regs_access(struct kvm_device *dev,
464 					struct kvm_device_attr *attr,
465 					bool is_write, int *data)
466 {
467 	int addr, cpu, offset, ret = 0;
468 	unsigned long flags;
469 	void *p = NULL;
470 	struct loongarch_eiointc *s;
471 
472 	s = dev->kvm->arch.eiointc;
473 	addr = attr->attr;
474 	cpu = addr >> 16;
475 	addr &= 0xffff;
476 	switch (addr) {
477 	case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
478 		offset = (addr - EIOINTC_NODETYPE_START) / 4;
479 		p = (void *)s->nodetype + offset * 4;
480 		break;
481 	case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
482 		offset = (addr - EIOINTC_IPMAP_START) / 4;
483 		p = (void *)&s->ipmap + offset * 4;
484 		break;
485 	case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
486 		offset = (addr - EIOINTC_ENABLE_START) / 4;
487 		p = (void *)s->enable + offset * 4;
488 		break;
489 	case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
490 		offset = (addr - EIOINTC_BOUNCE_START) / 4;
491 		p = (void *)s->bounce + offset * 4;
492 		break;
493 	case EIOINTC_ISR_START ... EIOINTC_ISR_END:
494 		offset = (addr - EIOINTC_ISR_START) / 4;
495 		p = (void *)s->isr + offset * 4;
496 		break;
497 	case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
498 		if (cpu >= s->num_cpu)
499 			return -EINVAL;
500 
501 		offset = (addr - EIOINTC_COREISR_START) / 4;
502 		p = (void *)s->coreisr[cpu] + offset * 4;
503 		break;
504 	case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
505 		offset = (addr - EIOINTC_COREMAP_START) / 4;
506 		p = (void *)s->coremap + offset * 4;
507 		break;
508 	default:
509 		kvm_pr_unimpl("%s: unknown eiointc register, addr = %d\n", __func__, addr);
510 		return -EINVAL;
511 	}
512 
513 	spin_lock_irqsave(&s->lock, flags);
514 	if (is_write)
515 		memcpy(p, data, 4);
516 	else
517 		memcpy(data, p, 4);
518 	spin_unlock_irqrestore(&s->lock, flags);
519 
520 	return ret;
521 }
522 
kvm_eiointc_sw_status_access(struct kvm_device * dev,struct kvm_device_attr * attr,bool is_write,int * data)523 static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
524 					struct kvm_device_attr *attr,
525 					bool is_write, int *data)
526 {
527 	int addr, ret = 0;
528 	unsigned long flags;
529 	void *p = NULL;
530 	struct loongarch_eiointc *s;
531 
532 	s = dev->kvm->arch.eiointc;
533 	addr = attr->attr;
534 	addr &= 0xffff;
535 
536 	switch (addr) {
537 	case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU:
538 		if (is_write)
539 			return ret;
540 
541 		p = &s->num_cpu;
542 		break;
543 	case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_FEATURE:
544 		if (is_write)
545 			return ret;
546 
547 		p = &s->features;
548 		break;
549 	case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE:
550 		p = &s->status;
551 		break;
552 	default:
553 		kvm_pr_unimpl("%s: unknown eiointc register, addr = %d\n", __func__, addr);
554 		return -EINVAL;
555 	}
556 	spin_lock_irqsave(&s->lock, flags);
557 	if (is_write)
558 		memcpy(p, data, 4);
559 	else
560 		memcpy(data, p, 4);
561 	spin_unlock_irqrestore(&s->lock, flags);
562 
563 	return ret;
564 }
565 
kvm_eiointc_get_attr(struct kvm_device * dev,struct kvm_device_attr * attr)566 static int kvm_eiointc_get_attr(struct kvm_device *dev,
567 				struct kvm_device_attr *attr)
568 {
569 	int ret, data;
570 
571 	switch (attr->group) {
572 	case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
573 		ret = kvm_eiointc_regs_access(dev, attr, false, &data);
574 		if (ret)
575 			return ret;
576 
577 		if (copy_to_user((void __user *)attr->addr, &data, 4))
578 			ret = -EFAULT;
579 
580 		return ret;
581 	case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
582 		ret = kvm_eiointc_sw_status_access(dev, attr, false, &data);
583 		if (ret)
584 			return ret;
585 
586 		if (copy_to_user((void __user *)attr->addr, &data, 4))
587 			ret = -EFAULT;
588 
589 		return ret;
590 	default:
591 		return -EINVAL;
592 	}
593 }
594 
kvm_eiointc_set_attr(struct kvm_device * dev,struct kvm_device_attr * attr)595 static int kvm_eiointc_set_attr(struct kvm_device *dev,
596 				struct kvm_device_attr *attr)
597 {
598 	int data;
599 
600 	switch (attr->group) {
601 	case KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL:
602 		return kvm_eiointc_ctrl_access(dev, attr);
603 	case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
604 		if (copy_from_user(&data, (void __user *)attr->addr, 4))
605 			return -EFAULT;
606 
607 		return kvm_eiointc_regs_access(dev, attr, true, &data);
608 	case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
609 		if (copy_from_user(&data, (void __user *)attr->addr, 4))
610 			return -EFAULT;
611 
612 		return kvm_eiointc_sw_status_access(dev, attr, true, &data);
613 	default:
614 		return -EINVAL;
615 	}
616 }
617 
kvm_eiointc_create(struct kvm_device * dev,u32 type)618 static int kvm_eiointc_create(struct kvm_device *dev, u32 type)
619 {
620 	int ret;
621 	struct loongarch_eiointc *s;
622 	struct kvm_io_device *device;
623 	struct kvm *kvm = dev->kvm;
624 
625 	/* eiointc has been created */
626 	if (kvm->arch.eiointc)
627 		return -EINVAL;
628 
629 	s = kzalloc_obj(struct loongarch_eiointc);
630 	if (!s)
631 		return -ENOMEM;
632 
633 	spin_lock_init(&s->lock);
634 	s->kvm = kvm;
635 
636 	/*
637 	 * Initialize IOCSR device
638 	 */
639 	device = &s->device;
640 	kvm_iodevice_init(device, &kvm_eiointc_ops);
641 	mutex_lock(&kvm->slots_lock);
642 	ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS,
643 			EIOINTC_BASE, EIOINTC_SIZE, device);
644 	mutex_unlock(&kvm->slots_lock);
645 	if (ret < 0) {
646 		kfree(s);
647 		return ret;
648 	}
649 
650 	device = &s->device_vext;
651 	kvm_iodevice_init(device, &kvm_eiointc_virt_ops);
652 	mutex_lock(&kvm->slots_lock);
653 	ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS,
654 			EIOINTC_VIRT_BASE, EIOINTC_VIRT_SIZE, device);
655 	mutex_unlock(&kvm->slots_lock);
656 	if (ret < 0) {
657 		mutex_lock(&kvm->slots_lock);
658 		kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &s->device);
659 		mutex_unlock(&kvm->slots_lock);
660 		kfree(s);
661 		return ret;
662 	}
663 	kvm->arch.eiointc = s;
664 
665 	return 0;
666 }
667 
kvm_eiointc_destroy(struct kvm_device * dev)668 static void kvm_eiointc_destroy(struct kvm_device *dev)
669 {
670 	struct kvm *kvm;
671 	struct loongarch_eiointc *eiointc;
672 
673 	if (!dev || !dev->kvm || !dev->kvm->arch.eiointc)
674 		return;
675 
676 	kvm = dev->kvm;
677 	eiointc = kvm->arch.eiointc;
678 	mutex_lock(&kvm->slots_lock);
679 	kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &eiointc->device);
680 	kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &eiointc->device_vext);
681 	mutex_unlock(&kvm->slots_lock);
682 	kfree(eiointc);
683 	kfree(dev);
684 }
685 
686 static struct kvm_device_ops kvm_eiointc_dev_ops = {
687 	.name = "kvm-loongarch-eiointc",
688 	.create = kvm_eiointc_create,
689 	.destroy = kvm_eiointc_destroy,
690 	.set_attr = kvm_eiointc_set_attr,
691 	.get_attr = kvm_eiointc_get_attr,
692 };
693 
kvm_loongarch_register_eiointc_device(void)694 int kvm_loongarch_register_eiointc_device(void)
695 {
696 	return kvm_register_device_ops(&kvm_eiointc_dev_ops, KVM_DEV_TYPE_LOONGARCH_EIOINTC);
697 }
698 
kvm_loongarch_unregister_eiointc_device(void)699 void kvm_loongarch_unregister_eiointc_device(void)
700 {
701 	kvm_unregister_device_ops(KVM_DEV_TYPE_LOONGARCH_EIOINTC);
702 }
703