* [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).