* [9front] [PATCH] GIC driver in the qemu kernel is now GICv2
@ 2024-01-08 20:24 cosarara
0 siblings, 0 replies; only message in thread
From: cosarara @ 2024-01-08 20:24 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 \
-nographic -accel kvm
Trying to use gic-version=3 on the same host would give:
qemu-system-aarch64: KVM does not support GICv3 emulation
---
sys/src/9/arm64/gic.c | 191 ++++++++++++++++--------------------------
1 file changed, 72 insertions(+), 119 deletions(-)
diff --git a/sys/src/9/arm64/gic.c b/sys/src/9/arm64/gic.c
index 291f7e102..4f1b01ced 100644
--- a/sys/src/9/arm64/gic.c
+++ b/sys/src/9/arm64/gic.c
@@ -51,33 +51,45 @@ enum {
GICD_CIDR2 = 0xFF8/4,
GICD_CIDR3 = 0xFFC/4,
- RD_base = 0x00000,
- GICR_CTLR = (RD_base+0x000)/4,
- GICR_IIDR = (RD_base+0x004)/4,
- GICR_TYPER = (RD_base+0x008)/4,
- GICR_STATUSR = (RD_base+0x010)/4,
- GICR_WAKER = (RD_base+0x014)/4,
- GICR_SETLPIR = (RD_base+0x040)/4,
- GICR_CLRLPIR = (RD_base+0x048)/4,
- GICR_PROPBASER = (RD_base+0x070)/4,
- GICR_PENDBASER = (RD_base+0x078)/4,
- GICR_INVLPIR = (RD_base+0x0A0)/4,
- GICR_INVALLR = (RD_base+0x0B0)/4,
- GICR_SYNCR = (RD_base+0x0C0)/4,
-
- SGI_base = 0x10000,
- GICR_IGROUPR0 = (SGI_base+0x080)/4,
- GICR_ISENABLER0 = (SGI_base+0x100)/4,
- GICR_ICENABLER0 = (SGI_base+0x180)/4,
- GICR_ISPENDR0 = (SGI_base+0x200)/4,
- GICR_ICPENDR0 = (SGI_base+0x280)/4,
- GICR_ISACTIVER0 = (SGI_base+0x300)/4,
- GICR_ICACTIVER0 = (SGI_base+0x380)/4,
- GICR_IPRIORITYR0= (SGI_base+0x400)/4,
- GICR_ICFGR0 = (SGI_base+0xC00)/4,
- GICR_ICFGR1 = (SGI_base+0xC04)/4,
- GICR_IGRPMODR0 = (SGI_base+0xD00)/4,
- GICR_NSACR = (SGI_base+0xE00)/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;
@@ -91,30 +103,14 @@ struct Vctl {
static Lock vctllock;
static Vctl *vctl[MAXMACH][32], *vfiq;
-static u32int *dregs = (u32int*)VIRTIO;
-
-static u32int*
-getrregs(int machno)
-{
- u32int *rregs = (u32int*)(VIRTIO + 0xa0000);
-
- for(;;){
- if((rregs[GICR_TYPER] & 0xFFFF00) == (machno << 8))
- return rregs;
- if(rregs[GICR_TYPER] & (1<<4))
- break;
- rregs += (0x20000/4);
- }
- panic("getrregs: no re-distributor for cpu %d\n", machno);
- return nil;
-}
+static u32int *dregs = (u32int*)(VIRTIO);
+static u32int *cregs = (u32int*)(VIRTIO + 0x10000);
void
intrcpushutdown(void)
{
/* disable cpu interface */
- syswr(ICC_IGRPEN0_EL1, 0);
- syswr(ICC_IGRPEN1_EL1, 0);
+ cregs[GICC_CTLR] &= ~1;
coherence();
}
@@ -122,16 +118,13 @@ void
intrsoff(void)
{
/* disable distributor */
- dregs[GICD_CTLR] = 0;
+ dregs[GICD_CTLR] &= ~1;
coherence();
- while(dregs[GICD_CTLR]&(1<<31))
- ;
}
void
intrinit(void)
{
- u32int *rregs;
int i, n;
if(m->machno == 0){
@@ -139,58 +132,20 @@ intrinit(void)
/* clear all interrupts */
n = ((dregs[GICD_TYPER] & 0x1F)+1) << 5;
- for(i = 32; i < n; i += 32){
- dregs[GICD_IGROUPR0 + (i/32)] = -1;
-
+ for(i = 0; i < n; i += 32){
dregs[GICD_ISENABLER0 + (i/32)] = -1;
- while(dregs[GICD_CTLR]&(1<<31))
- ;
+ coherence();
dregs[GICD_ICENABLER0 + (i/32)] = -1;
- while(dregs[GICD_CTLR]&(1<<31))
- ;
- dregs[GICD_ICACTIVER0 + (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){
+ for(i = 32; i < n; i += 16)
dregs[GICD_ICFGR0 + (i/16)] = 0;
- }
coherence();
- while(dregs[GICD_CTLR]&(1<<31))
- ;
- dregs[GICD_CTLR] = (1<<0) | (1<<1) | (1<<4);
}
-
- rregs = getrregs(m->machno);
- n = 32;
- for(i = 0; i < n; i += 32){
- rregs[GICR_IGROUPR0 + (i/32)] = -1;
-
- rregs[GICR_ISENABLER0 + (i/32)] = -1;
- while(rregs[GICR_CTLR]&(1<<3))
- ;
- rregs[GICR_ICENABLER0 + (i/32)] = -1;
- while(dregs[GICD_CTLR]&(1<<31))
- ;
- rregs[GICR_ICACTIVER0 + (i/32)] = -1;
- }
- for(i = 0; i < n; i += 4){
- rregs[GICR_IPRIORITYR0 + (i/4)] = 0;
- }
- coherence();
- while(rregs[GICR_CTLR]&(1<<3))
- ;
-
- coherence();
-
- /* enable cpu interface */
- syswr(ICC_CTLR_EL1, 0);
- syswr(ICC_BPR1_EL1, 7);
- syswr(ICC_PMR_EL1, 0xFF);
-
- coherence();
}
@@ -206,8 +161,7 @@ irq(Ureg* ureg)
u32int intid;
m->intr++;
- intid = sysrd(ICC_IAR1_EL1) & 0xFFFFFF;
-// iprint("i<%d>", intid);
+ intid = cregs[GICC_IAR] & 0xFFFFFF;
if((intid & ~3) == 1020)
return 0; // spurious
clockintr = 0;
@@ -220,7 +174,7 @@ irq(Ureg* ureg)
clockintr = 1;
}
coherence();
- syswr(ICC_EOIR1_EL1, intid);
+ cregs[GICC_EOIR] = intid;
return clockintr;
}
@@ -234,8 +188,7 @@ fiq(Ureg *ureg)
u32int intid;
m->intr++;
- intid = sysrd(ICC_IAR1_EL1) & 0xFFFFFF;
-// iprint("f<%d>", intid);
+ intid = cregs[GICC_IAR] & 0xFFFFFF;
if((intid & ~3) == 1020)
return; // spurious
v = vfiq;
@@ -244,11 +197,11 @@ fiq(Ureg *ureg)
v->f(ureg, v->a);
coherence();
}
- syswr(ICC_EOIR1_EL1, intid);
+ cregs[GICC_EOIR] = intid;
}
void
-intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
+intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char*)
{
Vctl *v;
u32int intid;
@@ -264,6 +217,7 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
prio = 0x80;
intid = irq;
+
if((v = xalloc(sizeof(Vctl))) == nil)
panic("intrenable: no mem");
v->irq = irq;
@@ -283,35 +237,34 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
v->next = vctl[cpu][intid%32];
vctl[cpu][intid%32] = v;
}
- syswr(ICC_IGRPEN1_EL1, sysrd(ICC_IGRPEN1_EL1)|1);
+
+ /* enable cpu interface */
+ cregs[GICC_PMR] = 0xFF;
coherence();
- syswr(ICC_EOIR1_EL1, intid);
+ cregs[GICC_CTLR] |= 1;
+ coherence();
+
+ cregs[GICC_EOIR] = intid;
+
+ /* enable distributor */
+ dregs[GICD_CTLR] |= 1;
coherence();
/* setup */
- if(intid < 32){
- u32int *rregs = getrregs(cpu);
- rregs[GICR_IPRIORITYR0 + (intid/4)] |= prio << ((intid%4) << 3);
- coherence();
- rregs[GICR_ISENABLER0] = 1 << (intid%32);
- coherence();
- while(rregs[GICR_CTLR]&(1<<3))
- ;
- } else {
- dregs[GICD_IPRIORITYR0 + (intid/4)] |= prio << ((intid%4) << 3);
- dregs[GICD_TARGETSR0 + (intid/4)] |= (1<<cpu) << ((intid%4) << 3);
- coherence();
- dregs[GICD_ISENABLER0 + (intid/32)] = 1 << (intid%32);
- coherence();
- while(dregs[GICD_CTLR]&(1<<31))
- ;
- }
+ 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 tbdf, void (*f)(Ureg*, void*), void *a, int, char*)
+intrdisable(int, void (*f)(Ureg*, void*), void *a, int tbdf, char*)
{
if(BUSTYPE(tbdf) == BusPCI){
pciintrdisable(tbdf, f, a);
--
2.43.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2024-01-08 20:26 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-08 20:24 [9front] [PATCH] GIC driver in the qemu kernel is now GICv2 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).