9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] [PATCH] Adds a new configuration to the qemu kernel so that it can run with GIC v2.
@ 2024-01-08  0:20 cosarara
  0 siblings, 0 replies; only message in thread
From: cosarara @ 2024-01-08  0:20 UTC (permalink / raw)
  To: 9front; +Cc: cosarara

This makes it possible to use KVM on GICv2 hosts. Eg. on a raspberry pi4 linux host:

qemu-system-aarch64 -M virt-2.12,gic-version=2 \
  -cpu host -m 2G -smp 2 \
  -bios u-boot.bin \
  -drive file=9front-10277.arm64.qcow2,if=none,id=disk \
  -device virtio-blk-pci-non-transitional,drive=disk \
   -nic bridge,br=br0,model=virtio-net-pci-non-transitional,mac=52:54:28:86:30:47 \
   -nographic -accel kvm

Build instructions:

% cd /sys/src/9/arm64
% mk 'CONF=qemu2' install

Then copy /arm64/9qemu2.u over your kernel file:

% bind -b '#S' /dev  # if needed
% 9fs dos
% cp /arm64/9qemu2.u /n/dos/9qemu.u

(generating a new boot.scr to use the 9qemu2.u filename left as
an exercise to the reader)
---
 sys/src/9/arm64/gicv2.c | 273 ++++++++++++++++++++++++++++++++++++++++
 sys/src/9/arm64/mkfile  |   2 +-
 sys/src/9/arm64/qemu2   |  50 ++++++++
 3 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 sys/src/9/arm64/gicv2.c
 create mode 100644 sys/src/9/arm64/qemu2

diff --git a/sys/src/9/arm64/gicv2.c b/sys/src/9/arm64/gicv2.c
new file mode 100644
index 000000000..c84cb4b4d
--- /dev/null
+++ b/sys/src/9/arm64/gicv2.c
@@ -0,0 +1,273 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/pci.h"
+#include "ureg.h"
+#include "sysreg.h"
+#include "../port/error.h"
+
+enum {
+	GICD_CTLR	= 0x000/4,	/* RW, Distributor Control Register */
+	GICD_TYPER	= 0x004/4,	/* RO, Interrupt Controller Type */
+	GICD_IIDR	= 0x008/4,	/* RO, Distributor Implementer Identification Register */
+
+	GICD_IGROUPR0	= 0x080/4,	/* RW, Interrupt Group Registers (0x80-0xBC) */
+
+	GICD_ISENABLER0	= 0x100/4,	/* RW, Interrupt Set-Enable Registers (0x100-0x13C) */
+	GICD_ICENABLER0	= 0x180/4,	/* RW, Interrupt Clear-Enable Registers (0x180-0x1BC) */
+
+	GICD_ISPENDR0	= 0x200/4,	/* RW, Interrupt Set-Pending Registers (0x200-0x23C) */
+	GICD_ICPENDR0	= 0x280/4,	/* RW, Interrupt Clear-Pending Registers (0x280-0x2BC) */
+
+	GICD_ISACTIVER0	= 0x300/4,	/* RW, Interrupt Set-Active Registers (0x300-0x33C) */
+	GICD_ICACTIVER0 = 0x380/4,	/* RW, Interrupt Clear-Active Registers (0x380-0x3BC) */
+
+	GICD_IPRIORITYR0= 0x400/4,	/* RW, Interrupt Priority Registers (0x400-0x5FC) */
+	GICD_TARGETSR0	= 0x800/4,	/* RW, Interrupt Target Registers (0x800-0x9FC) */
+	GICD_ICFGR0	= 0xC00/4,	/* RW, Interrupt Configuration Registers (0xC00-0xC7C) */
+
+	GICD_ISR0	= 0xD00/4,
+	GICD_PPISR	= GICD_ISR0,	/* RO, Private Peripheral Interrupt Status Register */
+	GICD_SPISR0	= GICD_ISR0+1,	/* RO, Shared Peripheral Interrupt Status Register */
+	GICD_SGIR	= 0xF00/4,	/* WO, Software Generated Interrupt Register */
+
+	GICD_CPENDSGIR0	= 0xF10/4,	/* RW, SGI Clear-Pending Registers (0xF10-0xF1C) */
+	GICD_SPENDSGIR0	= 0xF20/4,	/* RW, SGI Set-Pending Registers (0xF20-0xF2C) */
+
+	GICD_PIDR4	= 0xFD0/4,	/* RO, Perpheral ID Registers */
+	GICD_PIDR5	= 0xFD4/4,
+	GICD_PIDR6	= 0xFD8/4,
+	GICD_PIDR7	= 0xFDC/4,
+	GICD_PIDR0	= 0xFE0/4,
+	GICD_PIDR1	= 0xFE4/4,
+	GICD_PIDR2	= 0xFE8/4,
+	GICD_PIDR3	= 0xFEC/4,
+
+	GICD_CIDR0	= 0xFF0/4,	/* RO, Component ID Registers */
+	GICD_CIDR1	= 0xFF4/4,
+	GICD_CIDR2	= 0xFF8/4,
+	GICD_CIDR3	= 0xFFC/4,
+
+	GICC_CTLR	= 0x000/4,	/* RW, CPU Interace Control Register */
+	GICC_PMR	= 0x004/4,	/* RW, Interrupt Priority Mask Register */
+	GICC_BPR	= 0x008/4,	/* RW, Binary Point Register */
+	GICC_IAR	= 0x00C/4,	/* RO, Interrupt Acknowledge Register */
+	GICC_EOIR	= 0x010/4,	/* WO, End of Interrupt Register */
+	GICC_RPR	= 0x014/4,	/* RO, Running Priority Register */
+	GICC_HPPIR	= 0x018/4,	/* RO, Highest Priority Pending Interrupt Register */
+	GICC_ABPR	= 0x01C/4,	/* RW, Aliased Binary Point Register */
+	GICC_AIAR	= 0x020/4,	/* RO, Aliased Interrupt Acknowledge Register */
+	GICC_AEOIR	= 0x024/4,	/* WO, Aliased End of Interrupt Register */
+	GICC_AHPPIR	= 0x028/4,	/* RO, Aliased Highest Priority Pending Interrupt Register */
+	GICC_APR0	= 0x0D0/4,	/* RW, Active Priority Register */
+	GICC_NSAPR0	= 0x0E0/4,	/* RW, Non-Secure Active Priority Register */
+	GICC_IIDR	= 0x0FC/4,	/* RO, CPU Interface Identification Register */
+	GICC_DIR	= 0x1000/4,	/* WO, Deactivate Interrupt Register */
+
+	GICH_HCR	= 0x000/4,	/* RW, Hypervisor Control Register */
+	GICH_VTR	= 0x004/4,	/* RO, VGIC Type Register */
+	GICH_VMCR	= 0x008/4,	/* RW, Virtual Machine Control Register */
+	GICH_MISR	= 0x010/4,	/* RO, Maintenance Interrupt Status Register */
+	GICH_EISR0	= 0x020/4,	/* RO, End of Interrupt Status Register */
+	GICH_ELSR0	= 0x030/4,	/* RO, Empty List Register Status Register */
+	GICH_APR0	= 0x0F0/4,	/* RW, Active Priority Register */
+	GICH_LR0	= 0x100/4,	/* RW, List Registers (0x100-0x10C) */
+
+	GICV_CTLR	= 0x000/4,	/* RW, Virtual Machine Control Register */
+	GICV_PMR	= 0x004/4,	/* RW, VM Priority Mask Register */
+	GICV_BPR	= 0x008/4,	/* RW, VM Binary Point Register */
+	GICV_IAR	= 0x00C/4,	/* RO, VM Interrupt Acknowledge Register */
+	GICV_EOIR	= 0x010/4,	/* WO, VM End of Interrupt Register */
+	GICV_RPR	= 0x014/4,	/* RO, VM Running Priority Register */
+	GICV_HPPIR	= 0x018/4,	/* RO, VM Highest Piority Pending Interrupt Register */
+	GICV_ABPR	= 0x01C/4,	/* RW, VM Aliased Binary Point Register */
+	GICV_AIAR	= 0x020/4,	/* RO, VM Aliased Interrupt Acknowledge Register */
+	GICV_AEOIR	= 0x024/4,	/* WO, VM Aliased End of Interrupt Register */
+	GICV_AHPPIR	= 0x028/4,	/* RO, VM Aliaed Highest Piority Pending Interrupt Register */
+	GICV_APR0	= 0x0D0/4,	/* RW, VM Active Priority Register */
+	GICV_IIDR	= 0x0FC/4,	/* RO, VM CPU Interface Identification Register */
+	GICV_DIR	= 0x1000/4,	/* WO, VM Deactivate Interrupt Register */
+};
+
+typedef struct Vctl Vctl;
+struct Vctl {
+	Vctl	*next;
+	void	(*f)(Ureg*, void*);
+	void	*a;
+	int	irq;
+	u32int	intid;
+};
+
+static Lock vctllock;
+static Vctl *vctl[MAXMACH][32], *vfiq;
+static u32int *dregs = (u32int*)(VIRTIO + 0x0);
+static u32int *cregs = (u32int*)(VIRTIO + 0x10000);
+
+void
+intrcpushutdown(void)
+{
+	/* disable cpu interface */
+	cregs[GICC_CTLR] &= ~1;
+	coherence();
+}
+
+void
+intrsoff(void)
+{
+	/* disable distributor */
+	dregs[GICD_CTLR] &= ~1;
+	coherence();
+}
+
+void
+intrinit(void)
+{
+	int i, n;
+
+	if(m->machno == 0){
+		intrsoff();
+
+		/* clear all interrupts */
+		n = ((dregs[GICD_TYPER] & 0x1F)+1) << 5;
+		for(i = 0; i < n; i += 32){
+			dregs[GICD_ISENABLER0 + (i/32)] = -1;
+			coherence();
+			dregs[GICD_ICENABLER0 + (i/32)] = -1;
+			coherence();
+		}
+		for(i = 0; i < n; i += 4){
+			dregs[GICD_IPRIORITYR0 + (i/4)] = 0;
+			dregs[GICD_TARGETSR0 + (i/4)] = 0;
+		}
+		for(i = 32; i < n; i += 16)
+			dregs[GICD_ICFGR0 + (i/16)] = 0;
+		coherence();
+	}
+}
+
+
+/*
+ *  called by trap to handle irq interrupts.
+ *  returns true iff a clock interrupt, thus maybe reschedule.
+ */
+int
+irq(Ureg* ureg)
+{
+	Vctl *v;
+	int clockintr;
+	u32int intid;
+
+	m->intr++;
+	intid = cregs[GICC_IAR] & 0xFFFFFF;
+	if((intid & ~3) == 1020)
+		return 0; // spurious
+	clockintr = 0;
+	for(v = vctl[m->machno][intid%32]; v != nil; v = v->next)
+		if(v->intid == intid){
+			coherence();
+			v->f(ureg, v->a);
+			coherence();
+			if(v->irq == IRQcntvns)
+				clockintr = 1;
+		}
+	coherence();
+	cregs[GICC_EOIR] = intid;
+	return clockintr;
+}
+
+/*
+ * called direct from lexception.s to handle fiq interrupt.
+ */
+void
+fiq(Ureg *ureg)
+{
+	Vctl *v;
+	u32int intid;
+
+	m->intr++;
+	intid = cregs[GICC_IAR] & 0xFFFFFF;
+	if((intid & ~3) == 1020)
+		return;	// spurious
+	v = vfiq;
+	if(v != nil && v->intid == intid && m->machno == 0){
+		coherence();
+		v->f(ureg, v->a);
+		coherence();
+	}
+	cregs[GICC_EOIR] = intid;
+}
+
+void
+intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char*)
+{
+	Vctl *v;
+	u32int intid;
+	int cpu, prio;
+
+	if(BUSTYPE(tbdf) == BusPCI){
+		pciintrenable(tbdf, f, a);
+		return;
+	}
+
+	if(tbdf != BUSUNKNOWN)
+		return;
+
+	prio = 0x80;
+	intid = irq;
+
+	if((v = xalloc(sizeof(Vctl))) == nil)
+		panic("intrenable: no mem");
+	v->irq = irq;
+	v->intid = intid;
+	v->f = f;
+	v->a = a;
+
+	lock(&vctllock);
+	if(intid < SPI)
+		cpu = m->machno;
+	else
+		cpu = 0;
+	if(irq == IRQfiq){
+		vfiq = v;
+		prio = 0;
+	}else{
+		v->next = vctl[cpu][intid%32];
+		vctl[cpu][intid%32] = v;
+	}
+
+	/* enable cpu interface */
+	cregs[GICC_PMR] = 0xFF;
+	coherence();
+
+	cregs[GICC_CTLR] |= 1;
+	coherence();
+
+	cregs[GICC_EOIR] = intid;
+
+	/* enable distributor */
+	dregs[GICD_CTLR] |= 1;
+	coherence();
+
+	/* setup */
+	dregs[GICD_IPRIORITYR0 + (intid/4)] |= prio << ((intid%4) << 3);
+	dregs[GICD_TARGETSR0 + (intid/4)] |= (1<<cpu) << ((intid%4) << 3);
+	coherence();
+
+	/* turn on */
+	dregs[GICD_ISENABLER0 + (intid/32)] = 1 << (intid%32);
+	coherence();
+
+	unlock(&vctllock);
+}
+
+void
+intrdisable(int, void (*f)(Ureg*, void*), void *a, int tbdf, char*)
+{
+	if(BUSTYPE(tbdf) == BusPCI){
+		pciintrdisable(tbdf, f, a);
+		return;
+	}
+}
diff --git a/sys/src/9/arm64/mkfile b/sys/src/9/arm64/mkfile
index cbe7a1473..05100b2ff 100644
--- a/sys/src/9/arm64/mkfile
+++ b/sys/src/9/arm64/mkfile
@@ -1,5 +1,5 @@
 CONF=qemu
-CONFLIST=qemu
+CONFLIST=qemu qemu2
 
 kzero=0xffffffff80000000
 loadaddr=0xffffffffc0100000
diff --git a/sys/src/9/arm64/qemu2 b/sys/src/9/arm64/qemu2
new file mode 100644
index 000000000..1e70604e7
--- /dev/null
+++ b/sys/src/9/arm64/qemu2
@@ -0,0 +1,50 @@
+dev
+	root
+	cons
+	swap
+	env
+	pipe
+	proc
+	mnt
+	srv
+	shr
+	dup
+	tls
+	cap
+	fs
+	ether	netif
+	bridge	log
+	ip	arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
+	uart
+	rtc
+	pci	pci
+	sd
+
+link
+	ethervirtio10	pci
+	ethersink
+	ethermedium
+	loopbackmedium
+	netdevmedium
+	pciqemu		pci
+
+ip
+	tcp
+	udp
+	il
+	ipifc
+	icmp
+	icmp6
+	igmp
+	ipmux
+misc
+	gicv2
+	uartqemu
+	sdvirtio10	pci sdscsi
+port
+	int cpuserver = 0;
+bootdir
+	/$objtype/bin/paqfs
+	/$objtype/bin/auth/factotum
+	bootfs.paq
+	boot
-- 
2.43.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-08  0:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-08  0:20 [9front] [PATCH] Adds a new configuration to the qemu kernel so that it can run with GIC v2 cosarara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).