xref: /linux/arch/loongarch/kvm/intc/pch_pic.c (revision 68a052239fc4b351e961f698b824f7654a346091)
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_pch_pic.h>
8 #include <asm/kvm_vcpu.h>
9 #include <linux/count_zeros.h>
10 
11 /* update the isr according to irq level and route irq to eiointc */
12 static void pch_pic_update_irq(struct loongarch_pch_pic *s, int irq, int level)
13 {
14 	u64 mask = BIT(irq);
15 
16 	/*
17 	 * set isr and route irq to eiointc and
18 	 * the route table is in htmsi_vector[]
19 	 */
20 	if (level) {
21 		if (mask & s->irr & ~s->mask) {
22 			s->isr |= mask;
23 			irq = s->htmsi_vector[irq];
24 			eiointc_set_irq(s->kvm->arch.eiointc, irq, level);
25 		}
26 	} else {
27 		if (mask & s->isr & ~s->irr) {
28 			s->isr &= ~mask;
29 			irq = s->htmsi_vector[irq];
30 			eiointc_set_irq(s->kvm->arch.eiointc, irq, level);
31 		}
32 	}
33 }
34 
35 /* update batch irqs, the irq_mask is a bitmap of irqs */
36 static void pch_pic_update_batch_irqs(struct loongarch_pch_pic *s, u64 irq_mask, int level)
37 {
38 	unsigned int irq;
39 	DECLARE_BITMAP(irqs, 64) = { BITMAP_FROM_U64(irq_mask) };
40 
41 	for_each_set_bit(irq, irqs, 64)
42 		pch_pic_update_irq(s, irq, level);
43 }
44 
45 /* called when a irq is triggered in pch pic */
46 void pch_pic_set_irq(struct loongarch_pch_pic *s, int irq, int level)
47 {
48 	u64 mask = BIT(irq);
49 
50 	spin_lock(&s->lock);
51 	if (level)
52 		s->irr |= mask; /* set irr */
53 	else {
54 		/*
55 		 * In edge triggered mode, 0 does not mean to clear irq
56 		 * The irr register variable is cleared when cpu writes to the
57 		 * PCH_PIC_CLEAR_START address area
58 		 */
59 		if (s->edge & mask) {
60 			spin_unlock(&s->lock);
61 			return;
62 		}
63 		s->irr &= ~mask;
64 	}
65 	pch_pic_update_irq(s, irq, level);
66 	spin_unlock(&s->lock);
67 }
68 
69 /* msi irq handler */
70 void pch_msi_set_irq(struct kvm *kvm, int irq, int level)
71 {
72 	eiointc_set_irq(kvm->arch.eiointc, irq, level);
73 }
74 
75 static int loongarch_pch_pic_read(struct loongarch_pch_pic *s, gpa_t addr, int len, void *val)
76 {
77 	int ret = 0, offset;
78 	u64 data = 0;
79 	void *ptemp;
80 
81 	offset = addr - s->pch_pic_base;
82 	offset -= offset & 7;
83 
84 	spin_lock(&s->lock);
85 	switch (offset) {
86 	case PCH_PIC_INT_ID_START ... PCH_PIC_INT_ID_END:
87 		data = s->id.data;
88 		break;
89 	case PCH_PIC_MASK_START ... PCH_PIC_MASK_END:
90 		data = s->mask;
91 		break;
92 	case PCH_PIC_HTMSI_EN_START ... PCH_PIC_HTMSI_EN_END:
93 		/* read htmsi enable reg */
94 		data = s->htmsi_en;
95 		break;
96 	case PCH_PIC_EDGE_START ... PCH_PIC_EDGE_END:
97 		/* read edge enable reg */
98 		data = s->edge;
99 		break;
100 	case PCH_PIC_AUTO_CTRL0_START ... PCH_PIC_AUTO_CTRL0_END:
101 	case PCH_PIC_AUTO_CTRL1_START ... PCH_PIC_AUTO_CTRL1_END:
102 		/* we only use default mode: fixed interrupt distribution mode */
103 		break;
104 	case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
105 		/* only route to int0: eiointc */
106 		ptemp = s->route_entry + (offset - PCH_PIC_ROUTE_ENTRY_START);
107 		data = *(u64 *)ptemp;
108 		break;
109 	case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
110 		/* read htmsi vector */
111 		ptemp = s->htmsi_vector + (offset - PCH_PIC_HTMSI_VEC_START);
112 		data = *(u64 *)ptemp;
113 		break;
114 	case PCH_PIC_POLARITY_START ... PCH_PIC_POLARITY_END:
115 		data = s->polarity;
116 		break;
117 	case PCH_PIC_INT_IRR_START:
118 		data = s->irr;
119 		break;
120 	case PCH_PIC_INT_ISR_START:
121 		data = s->isr;
122 		break;
123 	default:
124 		ret = -EINVAL;
125 	}
126 	spin_unlock(&s->lock);
127 
128 	if (ret == 0) {
129 		offset = (addr - s->pch_pic_base) & 7;
130 		data = data >> (offset * 8);
131 		memcpy(val, &data, len);
132 	}
133 
134 	return ret;
135 }
136 
137 static int kvm_pch_pic_read(struct kvm_vcpu *vcpu,
138 			struct kvm_io_device *dev,
139 			gpa_t addr, int len, void *val)
140 {
141 	int ret;
142 	struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic;
143 
144 	if (!s) {
145 		kvm_err("%s: pch pic irqchip not valid!\n", __func__);
146 		return -EINVAL;
147 	}
148 
149 	if (addr & (len - 1)) {
150 		kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len);
151 		return -EINVAL;
152 	}
153 
154 	/* statistics of pch pic reading */
155 	vcpu->stat.pch_pic_read_exits++;
156 	ret = loongarch_pch_pic_read(s, addr, len, val);
157 
158 	return ret;
159 }
160 
161 static int loongarch_pch_pic_write(struct loongarch_pch_pic *s, gpa_t addr,
162 					int len, const void *val)
163 {
164 	int ret = 0, offset;
165 	u64 old, data, mask;
166 	void *ptemp;
167 
168 	switch (len) {
169 	case 1:
170 		data = *(u8 *)val;
171 		mask = 0xFF;
172 		break;
173 	case 2:
174 		data = *(u16 *)val;
175 		mask = USHRT_MAX;
176 		break;
177 	case 4:
178 		data = *(u32 *)val;
179 		mask = UINT_MAX;
180 		break;
181 	case 8:
182 	default:
183 		data = *(u64 *)val;
184 		mask = ULONG_MAX;
185 		break;
186 	}
187 
188 	offset = (addr - s->pch_pic_base) & 7;
189 	mask = mask << (offset * 8);
190 	data = data << (offset * 8);
191 	offset = (addr - s->pch_pic_base) - offset;
192 
193 	spin_lock(&s->lock);
194 	switch (offset) {
195 	case PCH_PIC_MASK_START:
196 		old = s->mask;
197 		s->mask = (old & ~mask) | data;
198 		if (old & ~data)
199 			pch_pic_update_batch_irqs(s, old & ~data, 1);
200 		if (~old & data)
201 			pch_pic_update_batch_irqs(s, ~old & data, 0);
202 		break;
203 	case PCH_PIC_HTMSI_EN_START:
204 		s->htmsi_en = (s->htmsi_en & ~mask) | data;
205 		break;
206 	case PCH_PIC_EDGE_START:
207 		s->edge = (s->edge & ~mask) | data;
208 		break;
209 	case PCH_PIC_POLARITY_START:
210 		s->polarity = (s->polarity & ~mask) | data;
211 		break;
212 	case PCH_PIC_CLEAR_START:
213 		old = s->irr & s->edge & data;
214 		if (old) {
215 			s->irr &= ~old;
216 			pch_pic_update_batch_irqs(s, old, 0);
217 		}
218 		break;
219 	case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
220 		ptemp = s->htmsi_vector + (offset - PCH_PIC_HTMSI_VEC_START);
221 		*(u64 *)ptemp = (*(u64 *)ptemp & ~mask) | data;
222 		break;
223 	/* Not implemented */
224 	case PCH_PIC_AUTO_CTRL0_START:
225 	case PCH_PIC_AUTO_CTRL1_START:
226 	case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
227 		break;
228 	default:
229 		ret = -EINVAL;
230 		break;
231 	}
232 	spin_unlock(&s->lock);
233 
234 	return ret;
235 }
236 
237 static int kvm_pch_pic_write(struct kvm_vcpu *vcpu,
238 			struct kvm_io_device *dev,
239 			gpa_t addr, int len, const void *val)
240 {
241 	int ret;
242 	struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic;
243 
244 	if (!s) {
245 		kvm_err("%s: pch pic irqchip not valid!\n", __func__);
246 		return -EINVAL;
247 	}
248 
249 	if (addr & (len - 1)) {
250 		kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len);
251 		return -EINVAL;
252 	}
253 
254 	/* statistics of pch pic writing */
255 	vcpu->stat.pch_pic_write_exits++;
256 	ret = loongarch_pch_pic_write(s, addr, len, val);
257 
258 	return ret;
259 }
260 
261 static const struct kvm_io_device_ops kvm_pch_pic_ops = {
262 	.read	= kvm_pch_pic_read,
263 	.write	= kvm_pch_pic_write,
264 };
265 
266 static int kvm_pch_pic_init(struct kvm_device *dev, u64 addr)
267 {
268 	int ret;
269 	struct kvm *kvm = dev->kvm;
270 	struct kvm_io_device *device;
271 	struct loongarch_pch_pic *s = dev->kvm->arch.pch_pic;
272 
273 	s->pch_pic_base = addr;
274 	device = &s->device;
275 	/* init device by pch pic writing and reading ops */
276 	kvm_iodevice_init(device, &kvm_pch_pic_ops);
277 	mutex_lock(&kvm->slots_lock);
278 	/* register pch pic device */
279 	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, addr, PCH_PIC_SIZE, device);
280 	mutex_unlock(&kvm->slots_lock);
281 
282 	return (ret < 0) ? -EFAULT : 0;
283 }
284 
285 /* used by user space to get or set pch pic registers */
286 static int kvm_pch_pic_regs_access(struct kvm_device *dev,
287 				struct kvm_device_attr *attr,
288 				bool is_write)
289 {
290 	char buf[8];
291 	int addr, offset, len = 8, ret = 0;
292 	void __user *data;
293 	void *p = NULL;
294 	struct loongarch_pch_pic *s;
295 
296 	s = dev->kvm->arch.pch_pic;
297 	addr = attr->attr;
298 	data = (void __user *)attr->addr;
299 
300 	/* get pointer to pch pic register by addr */
301 	switch (addr) {
302 	case PCH_PIC_MASK_START:
303 		p = &s->mask;
304 		break;
305 	case PCH_PIC_HTMSI_EN_START:
306 		p = &s->htmsi_en;
307 		break;
308 	case PCH_PIC_EDGE_START:
309 		p = &s->edge;
310 		break;
311 	case PCH_PIC_AUTO_CTRL0_START:
312 		p = &s->auto_ctrl0;
313 		break;
314 	case PCH_PIC_AUTO_CTRL1_START:
315 		p = &s->auto_ctrl1;
316 		break;
317 	case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
318 		offset = addr - PCH_PIC_ROUTE_ENTRY_START;
319 		p = &s->route_entry[offset];
320 		len = 1;
321 		break;
322 	case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
323 		offset = addr - PCH_PIC_HTMSI_VEC_START;
324 		p = &s->htmsi_vector[offset];
325 		len = 1;
326 		break;
327 	case PCH_PIC_INT_IRR_START:
328 		p = &s->irr;
329 		break;
330 	case PCH_PIC_INT_ISR_START:
331 		p = &s->isr;
332 		break;
333 	case PCH_PIC_POLARITY_START:
334 		p = &s->polarity;
335 		break;
336 	default:
337 		return -EINVAL;
338 	}
339 
340 	if (is_write) {
341 		if (copy_from_user(buf, data, len))
342 			return -EFAULT;
343 	}
344 
345 	spin_lock(&s->lock);
346 	if (is_write)
347 		memcpy(p, buf, len);
348 	else
349 		memcpy(buf, p, len);
350 	spin_unlock(&s->lock);
351 
352 	if (!is_write) {
353 		if (copy_to_user(data, buf, len))
354 			return -EFAULT;
355 	}
356 
357 	return ret;
358 }
359 
360 static int kvm_pch_pic_get_attr(struct kvm_device *dev,
361 				struct kvm_device_attr *attr)
362 {
363 	switch (attr->group) {
364 	case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS:
365 		return kvm_pch_pic_regs_access(dev, attr, false);
366 	default:
367 		return -EINVAL;
368 	}
369 }
370 
371 static int kvm_pch_pic_set_attr(struct kvm_device *dev,
372 				struct kvm_device_attr *attr)
373 {
374 	u64 addr;
375 	void __user *uaddr = (void __user *)(long)attr->addr;
376 
377 	switch (attr->group) {
378 	case KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL:
379 		switch (attr->attr) {
380 		case KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT:
381 			if (copy_from_user(&addr, uaddr, sizeof(addr)))
382 				return -EFAULT;
383 
384 			if (!dev->kvm->arch.pch_pic) {
385 				kvm_err("%s: please create pch_pic irqchip first!\n", __func__);
386 				return -ENODEV;
387 			}
388 
389 			return kvm_pch_pic_init(dev, addr);
390 		default:
391 			kvm_err("%s: unknown group (%d) attr (%lld)\n", __func__, attr->group,
392 					attr->attr);
393 			return -EINVAL;
394 		}
395 	case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS:
396 		return kvm_pch_pic_regs_access(dev, attr, true);
397 	default:
398 		return -EINVAL;
399 	}
400 }
401 
402 static int kvm_setup_default_irq_routing(struct kvm *kvm)
403 {
404 	int i, ret;
405 	u32 nr = KVM_IRQCHIP_NUM_PINS;
406 	struct kvm_irq_routing_entry *entries;
407 
408 	entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL);
409 	if (!entries)
410 		return -ENOMEM;
411 
412 	for (i = 0; i < nr; i++) {
413 		entries[i].gsi = i;
414 		entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
415 		entries[i].u.irqchip.irqchip = 0;
416 		entries[i].u.irqchip.pin = i;
417 	}
418 	ret = kvm_set_irq_routing(kvm, entries, nr, 0);
419 	kfree(entries);
420 
421 	return ret;
422 }
423 
424 static int kvm_pch_pic_create(struct kvm_device *dev, u32 type)
425 {
426 	int i, ret, irq_num;
427 	struct kvm *kvm = dev->kvm;
428 	struct loongarch_pch_pic *s;
429 
430 	/* pch pic should not has been created */
431 	if (kvm->arch.pch_pic)
432 		return -EINVAL;
433 
434 	ret = kvm_setup_default_irq_routing(kvm);
435 	if (ret)
436 		return -ENOMEM;
437 
438 	s = kzalloc(sizeof(struct loongarch_pch_pic), GFP_KERNEL);
439 	if (!s)
440 		return -ENOMEM;
441 
442 	/*
443 	 * Interrupt controller identification register 1
444 	 *   Bit 24-31 Interrupt Controller ID
445 	 * Interrupt controller identification register 2
446 	 *   Bit  0-7  Interrupt Controller version number
447 	 *   Bit 16-23 The number of interrupt sources supported
448 	 */
449 	irq_num = 32;
450 	s->mask = -1UL;
451 	s->id.desc.id = PCH_PIC_INT_ID_VAL;
452 	s->id.desc.version = PCH_PIC_INT_ID_VER;
453 	s->id.desc.irq_num = irq_num - 1;
454 	for (i = 0; i < irq_num; i++) {
455 		s->route_entry[i] = 1;
456 		s->htmsi_vector[i] = i;
457 	}
458 	spin_lock_init(&s->lock);
459 	s->kvm = kvm;
460 	kvm->arch.pch_pic = s;
461 
462 	return 0;
463 }
464 
465 static void kvm_pch_pic_destroy(struct kvm_device *dev)
466 {
467 	struct kvm *kvm;
468 	struct loongarch_pch_pic *s;
469 
470 	if (!dev || !dev->kvm || !dev->kvm->arch.pch_pic)
471 		return;
472 
473 	kvm = dev->kvm;
474 	s = kvm->arch.pch_pic;
475 	/* unregister pch pic device and free it's memory */
476 	kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &s->device);
477 	kfree(s);
478 }
479 
480 static struct kvm_device_ops kvm_pch_pic_dev_ops = {
481 	.name = "kvm-loongarch-pch-pic",
482 	.create = kvm_pch_pic_create,
483 	.destroy = kvm_pch_pic_destroy,
484 	.set_attr = kvm_pch_pic_set_attr,
485 	.get_attr = kvm_pch_pic_get_attr,
486 };
487 
488 int kvm_loongarch_register_pch_pic_device(void)
489 {
490 	return kvm_register_device_ops(&kvm_pch_pic_dev_ops, KVM_DEV_TYPE_LOONGARCH_PCHPIC);
491 }
492