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