GIC

GIC Trace32

This document summarizes useful information regarding GIC when using the Trace32 debugger.
It is based on GICv3.

Peribrowser

Since the GIC CPU interface is part of the system registers in the ARMv8-A architecture,
it is possible to use Peribrowser as soon as the CPU is attached.
Besides that, Distributor or Redistributor registers require peri reprogramming.

Peri registration is as follows:

B:: sys.config.gicd type gic600
B:: sys.config.gicd base a:{gicd base address}
B:: sys.config.gicr base a:{gicr base address}
B:: per.reprogram


CMM script

CMM script to check GICv3 hardware interrupt operation

GIC ON script immediately after Chip boot (core0 only)


/////////////////////////////
// tcc807x gicv3 init script
//
// - for using gic
//     in bare-metal
/////////////////////////////


////////////////////////
// User Configuration //
////////////////////////
&gicd_base={gicd base addr}
&gicr_base={gicd base addr}
&gicr_num_of_regs=1.


////////////////
// GIC offset //
////////////////
&sgi_offset=0x10000


///////////// 
// Example // 
/////////////
GOSUB GICV3_DISTIF_INIT &gicd_base
GOSUB GICV3_RDISTIF_INIT &gicr_base &gicr_num_of_regs
GOSUB GICV3_CPUIF_INIT &gicr_base
ENDDO


///////////////
// functions //
///////////////
GICV3_DISTIF_INIT:
        ENTRY &arg_gicd_ctlr
        LOCAL &rwp_true
        LOCAL &index &value

        &value=D.Long(AD:&arg_gicd_ctlr)
        &value=&value|(1<<0) ;enable G0
        &value=&value|(1<<1) ;enable G1
        &value=&value|(1<<2) ;enable G1NS
        // enable G0, G1, G1NS before enable ARE_S //
        D.S AD:&arg_gicd_ctlr %LE %Long &value

        &value=&value|(1<<4)
        &value=&value|(1<<5)
        D.S AD:&arg_gicd_ctlr %LE %Long &value
        &rwp_true=1
        while &rwp_true==1
        (
                &rwp_true=D.Long(AD:&arg_gicd_ctlr)
                &rwp_true=&rwp_true>>31.
        )

        RETURN
GICV3_RDISTIF_INIT:
        ENTRY &arg_gicr_ctlr &arg_num_of_reg
        LOCAL &gicr_pwrr &pwrr_offset
        LOCAL &gicr_icenabler &enable_clr_offset
        LOCAL &rwp_true
        LOCAL &index

        &pwrr_offset=0x24
        &enable_clr_offset=&sgi_offset+0x180

        // Redistributor Power On //
        &gicr_pwrr=&arg_gicr_ctlr+&pwrr_offset
        D.S AD:&gicr_pwrr %LE %Long 0x0

        // All clear enable registers //
        &index=1.
        &gicr_icenabler=&arg_gicr_ctlr+&enable_clr_offset
        D.S AD:&gicr_icenabler %LE %Long 0xFFFFFFFF
        &rwp_true=1
        while &rwp_true==1
        (
                &rwp_true=D.Long(AD:&arg_gicr_ctlr)
                &rwp_true=&rwp_true>>31.
        )

        // Set Groups G1NS as default //
        &gicr_igroupr=&arg_gicr_ctlr+&sgi_offset+0x80
        D.S AD:&gicr_igroupr %LE %Long 0xFFFFFFFF

        RETURN

        GICV3_CPUIF_INIT:
        ENTRY &arg_gicr_ctlr
        LOCAL &gicr_waker
        LOCAL &icc_sre_el1 &icc_sre_el3
        LOCAL &icc_pmr_el1
        LOCAL &ca_bit

        &gicr_waker=&arg_gicr_ctlr+0x14

        // gicr core awake //
        &ca_bit=0.
        while &ca_bit==0
        (
                &ca_bit=D.Long(AD:&gicr_waker)
                &ca_bit=&ca_bit&0x7
                &ca_bit=&ca_bit>>2.
        )
        // clear PS bit and wait till ca_bit is 0 //
        D.S AD:&gicr_waker %LE %Long 0x4
        while &ca_bit!=0
                &ca_bit=D.Long(AD:&gicr_waker)

        // set SRE by exception levels //
        &icc_sre_el1=0x30CC5
        &icc_sre_el3=0x36CC5
        D.S SPR:&icc_sre_el3 %Quad 0xF ; auto set 0x7 in icc_sre_el1
        //////////////////////////////////////
        //                     //
        // scr_el3 <- SCR_NS_BIT            //
        // icc_sre_el2 <- read(icc_sre_el3) //
        // scr_el3 <- ~SCR_NS_BIT           //
        // icc_sre_el1 <- 0x7               //
        //////////////////////////////////////

        // set pmr //
        &icc_pmr_el1=0x30460
        D.S SPR:&icc_pmr_el1 %Quad 0xF0 ; num of priority level: 16

        // set group enable for virtual IRQ //
        &icc_igrpen0_el1=0x30CC6
        D.S SPR:&icc_igrpen0_el1 %Quad 0x1
        &icc_igrpen1_el1=0x30CC7
        D.S SPR:&icc_igrpen1_el1 %Quad 0x1
        &icc_igrpen1_el3=0x36CC7
        D.S SPR:&icc_igrpen1_el3 %Quad 0x3

        RETURN
  </code></pre>
Users only need to modify the User Configuration part.
User Configuration
gicd_base: Write the gicd base address.
gicr_base: Write the gicr core 0 lpi base address.
gicr_num_of_regs: Since only core 0 is on immediately after chip boot, it is almost fixed to 1.

</details>

GIC PPIs SPIs test script


/////////////////////////////
// gicv3 test script
//
// - delete WDT kernel configs
// B:: sys.config.gicd type gic600
// B:: sys.config.gicd base a:{GICD base address}
// B:: sys.config.gicr type a:{GICR base address}
// B:: per.reprogram
/////////////////////////////

&main=0x0
&sub=0x1

////////////////////////
// User Configuration //
////////////////////////
&num_of_chip=
&cluster=&main ; &main or &sub
&gicd_base_addr=
&gicr_base_addr=
&in_el3=0.
&eoi_mode=0.

//////////////////////////
// User Configuration 2 //
//////////////////////////
&start_irq=16. ; PPIs ~
&gic_max_irq=512.+1. ; 480(SPIs) + 32(SGIs, PPIs)

//////////////////////////
// User Configuration 3 //
//////////////////////////
&gic_target_core=0. 


////////////////////////////
// ARM-A System Registers //
// addr prefix: "spr"     //
////////////////////////////
// EL3 //
&scr_el3=0x36110
// GIC CPU Interfaces //
&icc_iar0_el1=0x30c80
&icc_iar1_el1=0x30cc0
&icc_hppir0_el1=0x30c82
&icc_hppir1_el1=0x30cc2
&icc_eoir0_el1=0x30c81
&icc_eoir1_el1=0x30cc1
&icc_dir_el1=0x30cb1
&icc_sgi0r_el1=0x30cb7
&icc_sgi1r_el1=0x30cb5
// System Counter //
&cntp_ctl_el0=0x33e21
&cntv_ctl_el0=0x33e31
&cntps_ctl_el1=0x37e21
&cnthp_ctl_el2=0x34e20
&cntkctl_el1=0x30e10
&cnthctl_el2=0x34e10

///////////////////
// GIC registers //
///////////////////
// GIC offsets //
&iroute_offset=0x6100
&enable_offset=0x100
&enable_clr_offset=0x180
&grp_offset=0x80
&grpmod_offset=0xd00
&pend_offset=0x200
&pend_clr_offset=0x280
&active_offset=0x300
&active_clr_offset=0x380
&sgi_offset=0x10000
&num_of_reg=((&active_clr_offset-&active_offset)/4)+1
&num_of_spi=(&gic_max_irq-32.)
// GIC interrupt registers //
Var.NEWLOCAL long [&num_of_reg] \gic_isenabler
Var.NEWLOCAL long [&num_of_reg] \gic_icenabler
Var.NEWLOCAL long [&num_of_reg] \gic_groupr
Var.NEWLOCAL long [&num_of_reg] \gic_grpmodr
Var.NEWLOCAL long [&num_of_reg] \gic_ispendr
Var.NEWLOCAL long [&num_of_reg] \gic_icpendr
Var.NEWLOCAL long [&num_of_reg] \gic_isactiver
Var.NEWLOCAL long [&num_of_reg] \gic_icactiver
// GICD //
&gicd_base_addr=&gicd_base_addr+(&cluster*0x20000)
&gicd_route_base_addr=&gicd_base_addr+&iroute_offset
&gicd_enable_base_addr=&gicd_base_addr+&enable_offset
&gicd_enable_clr_base_addr=&gicd_base_addr+&enable_clr_offset
&gicd_grp_base_addr=&gicd_base_addr+&grp_offset
&gicd_grpmod_base_addr=&gicd_base_addr+&grpmod_offset
&gicd_pend_base_addr=&gicd_base_addr+&pend_offset
&gicd_pend_clr_base_addr=&gicd_base_addr+&pend_clr_offset
&gicd_active_base_addr=&gicd_base_addr+&active_offset
&gicd_active_clr_base_addr=&gicd_base_addr+&active_clr_offset
// GICR //
&gicr_base_addr=&gicr_base_addr+(&cluster*0x20000)+(&gic_target_core*0x20000)
&gicr_lpi_base_addr=&gicr_base_addr
&gicr_sgi_base_addr=&gicr_base_addr+&sgi_offset
&gicr_isenabler=&gicr_sgi_base_addr+&enable_offset
&gicr_icenabler=&gicr_sgi_base_addr+&enable_clr_offset
&gicr_groupr=&gicr_sgi_base_addr+&grp_offset
&gicr_grpmodr=&gicr_sgi_base_addr+&grpmod_offset
&gicr_ispendr=&gicr_sgi_base_addr+&pend_offset
&gicr_icpendr=&gicr_sgi_base_addr+&pend_clr_offset
&gicr_isactiver=&gicr_sgi_base_addr+&active_offset
&gicr_icactiver=&gicr_sgi_base_addr+&active_clr_offset

//////////
// Etc. //
//////////
// common //
&addr=0x0
&index=0.
&irq=0.
// group //
Var.NEWLOCAL long [&gic_max_irq] \irq_group
&irq_group_flag=1.


GOSUB ENV_PRESET

// GIC Verification //
GOSUB GIC_SETUP
GOSUB GIC_STATUS_INIT
GOSUB GIC_SET_AFFINITY &gic_target_core

sys.log.ON
&irq=&start_irq
WHILE &irq<&gic_max_irq
(
	//////////////////////////////////////////////////
	// Use '> continue' in script debug mode        //
	// <---------------------- (Break.Set)          //
	//////////////////////////////////////////////////
	GOSUB GIC_IRQ_HANDLE &irq
	&irq=&irq+1.
)
sys.log.OFF

ENDDO


ENV_PRESET:
	LOCAL &cpsr
	LOCAL &cpsr_nzcv &cpsr_endian &cpsr_async &cpsr_int &cpsr_mode
	LOCAL &scr
	LOCAL &scr_irq &scr_fiq &scr_ns

	Core.select &gic_target_core

	&cpsr=0x0
	&cpsr_nzcv=(0x4<<28.)
	&cpsr_endian=(0x1<<9.)
	&cpsr_async=(0x1<<8.)
	&cpsr_int=(0x3<<6.)
	&cpsr_mode=0xd ; EL3h

	&secure=0x0
	&scr_irq=(0x1<<1.)
	&scr_fiq=(0x1<<2.)
	&scr_ns=(0x1<<0.)

	&cpsr=&cpsr_nzcv|&cpsr_endian|&cpsr_async|&cpsr_int|&cpsr_mode
	Register.Set CPSR &cpsr

	&secure=D.Long(SPR:&scr_el3)
	&secure=&secure|&scr_irq|&scr_fiq
	&secure=&secure&(~&scr_ns)
	Data.Set SPR:&scr_el3 &secure

	// EL3 -> EL1 //
	if &in_el3==0
	(
		&secure=D.Long(SPR:&scr_el3)
		&secure=&secure&(~&scr_irq)
		&secure=&secure&(~&scr_fiq)
		Data.Set SPR:&scr_el3 &secure

		&cpsr_mode=0x5 ; EL1h
		&cpsr=&cpsr&0xFFFFFFF0
		&cpsr=&cpsr|&cpsr_mode
		Register.Set CPSR &cpsr
	)

	RETURN


GIC_REG_SETUP:
	&index=0.
	WHILE &index<&num_of_reg
	(
		if &index==0.
		(
			Var.set \gic_isenabler[&index]=&gicr_isenabler
			Var.set \gic_icenabler[&index]=&gicr_icenabler
			Var.set \gic_groupr[&index]=&gicr_groupr
			Var.set \gic_grpmodr[&index]=&gicr_grpmodr
			Var.set \gic_ispendr[&index]=&gicr_ispendr
			Var.set \gic_icpendr[&index]=&gicr_icpendr
			Var.set \gic_isactiver[&index]=&gicr_isactiver
			Var.set \gic_icactiver[&index]=&gicr_icactiver
		)
		else
		(
			Var.set \gic_isenabler[&index]=&gicd_enable_base_addr+(&index*0x4)
			Var.set \gic_icenabler[&index]=&gicd_enable_clr_base_addr+(&index*0x4)
			Var.set \gic_groupr[&index]=&gicd_grp_base_addr+(&index*0x4)
			Var.set \gic_grpmodr[&index]=&gicd_grpmod_base_addr+(&index*0x4)
			Var.set \gic_ispendr[&index]=&gicd_pend_base_addr+(&index*0x4)
			Var.set \gic_icpendr[&index]=&gicd_pend_clr_base_addr+(&index*0x4)
			Var.set \gic_isactiver[&index]=&gicd_active_base_addr+(&index*0x4)
			Var.set \gic_icactiver[&index]=&gicd_active_clr_base_addr+(&index*0x4)
		)
		&index=&index+1.
	)

	RETURN


EOI_MODE_SETUP:
	ENTRY &arg_mode
	LOCAL &icc_ctlr_el1 &icc_ctlr_el3
	LOCAL &eoi_mode_el1 &eoi_mode_el3

	if &arg_mode==0
	(
		&icc_ctlr_el1=0x30cc4
		&eoi_mode_el1=D.Long(SPR:&icc_ctlr_el1)
		&eoi_mode_el1=&eoi_mode_el1&(~0x2)
		PER.Set.simple SPR:&icc_ctlr_el1 %Quad &eoi_mode_el1
		if &in_el3==1.
		(
			&icc_ctlr_el3=0x36cc4
			&eoi_mode_el3=D.Long(SPR:&icc_ctlr_el3)
			&eoi_mode_el3=&eoi_mode_el1&(~0x10)
			PER.Set.simple SPR:&icc_ctlr_el3 %Quad &eoi_mode_el3
		)
	)

	RETURN


IRQ_GROUP_SETUP: // GICD_CTLR.DS == 0
	ENTRY &arg_id &arg_index
	LOCAL &val_groupr &val_grpmodr

	&val_groupr=D.Long(ASD:Var.value(\gic_groupr[&arg_index]))
	&val_groupr=&val_groupr>>(&arg_id%32.)
	&val_groupr=&val_groupr&0x1
	&val_grpmodr=D.Long(ASD:Var.value(\gic_grpmodr[&arg_index]))
	&val_grpmodr=&val_grpmodr>>(&arg_id%32.)
	&val_grpmodr=&val_grpmodr&0x1

	if (&val_groupr|&val_grpmodr)==1
		Var.set \irq_group[&arg_id]=1.
	else
		Var.set \irq_group[&arg_id]=0.

	RETURN


DS_IRQ_GROUP_SETUP: // GICD_CTLR.DS == 1
	ENTRY &arg_id &arg_index
	LOCAL &val_groupr

	&val_groupr=D.Long(ASD:Var.value(\gic_groupr[&arg_index]))
	&val_groupr=&val_groupr>>(&arg_id%32.)
	&val_groupr=&val_groupr&0x1

	if &val_groupr==1
		Var.set \irq_group[&arg_id]=1.
	else
		Var.set \irq_group[&arg_id]=0.

	RETURN


GIC_SETUP:
	LOCAL &gicd_ctlr &gicd_ctlr_ds

	GOSUB EOI_MODE_SETUP &eoi_mode
	GOSUB GIC_REG_SETUP

	&gicd_ctlr=D.Long(ASD:&gicd_base_addr)
	&gicd_ctlr=&gicd_ctlr&(1<<6)
	&gicd_ctlr_ds=&gicd_ctlr>>6
	if &gicd_ctlr_ds==0
	(
		&index=0.
		&id=0.
		WHILE &id<&gic_max_irq
		(
			GOSUB IRQ_GROUP_SETUP &id &index
			&id=&id+1.
			&index=(&id/32.)
		)
	)
	else
	(
		&index=0.
		&id=0.
		WHILE &id<&gic_max_irq
		(
			GOSUB DS_IRQ_GROUP_SETUP &id &index
			&id=id+1.
			&index=(&id/32.)
		)
	)

	RETURN


GIC_SET_AFFINITY:
	ENTRY &arg_target
	LOCAL &aff

	&aff=(&arg_target<<8.)
	Data.Set ASD:&gicd_route_base_addr++(&num_of_spi*8) %LE %Long &aff

	RETURN


GIC_SET_IRQ:
	ENTRY &arg_id

	Data.Set ASD:Var.Value(\gic_isenabler[&arg_id/32.]) %LE %Long (1<<(&arg_id%32.))
	Data.Set ASD:Var.Value(\gic_ispendr[&arg_id/32.]) %LE %Long (1<<(&arg_id%32.))

	RETURN


GIC_CLR_IRQ:
	ENTRY &arg_id

	Data.Set ASD:Var.Value(\gic_icpendr[&arg_id/32.]) %LE %Long (1<<(&arg_id%32.))
	Data.Set ASD:Var.Value(\gic_icenabler[&arg_id/32.]) %LE %Long (1<<(&arg_id%32.))

	RETURN


GIC_IRQ_HANDLE:
	ENTRY &arg_irq
	LOCAL &iar &restore_iar
	LOCAL &icc_iar &icc_eoi
	LOCAL &val_enabler &val_pendr &val_activer
	LOCAL &special_id

	if &arg_irq==32.
		GOSUB OFF_SYS_COUNTER &gic_target_core

	&irq_group_flag=Var.value(\irq_group[&arg_irq])
	&special_id=0.
	&spurious_cnt=0.

	if &irq_group_flag==0.
	(
		&icc_iar=&icc_iar0_el1
		&icc_eoi=&icc_eoir0_el1
	)
	else
	(
		&icc_iar=&icc_iar1_el1
		&icc_eoi=&icc_eoir1_el1
	)

	GOSUB GIC_SET_IRQ &arg_irq

	&iar=D.Long(SPR:&icc_iar)

	if (&iar&(~0x3))==1020.
		&special_id=1
	else
		&special_id=0

	if &special_id==0
	(
		// Check active status //
		&val_activer=D.Long(ASD:Var.Value(\gic_isactiver[&iar/32.]))
		&val_activer=&val_activer>>(&iar%32.)
		&val_activer=&val_activer&0x1

		// Check interrupt life-cycle pending -> active //
		if &val_activer==1
		(
			PRINT "Pass interrupt active irq: &iar"
			GOSUB GIC_CLR_IRQ &iar

			PER.Set.simple SPR:&icc_eoi %Quad &iar

			// set dir (eoi mode 1) //
			if &eoi_mode==1
				PER.Set.simple SPR:&icc_dir_el1 %Quad &iar

			// Check active status //
			&val_activer=D.Long(ASD:Var.Value(\gic_isactiver[&iar/32.]))
			&val_activer=&val_activer>>(&iar%32.)
			&val_activer=&val_activer&0x1

			// Check interrupt life-cycle active -> end //
			if &val_activer==0
				PRINT "Pass interrupt handle irq: &iar"
			else
				PRINT "Fail interrupt handle irq: &iar"
		)
		else
		(
			PRINT "Fail interrupt active irq: &iar"
			GOSUB GIC_CLR_IRQ &iar
		)
	)
	else
	(
		PRINT "Spurious interrupt! Check GIC status and irq group"
		PRINT "Recommand RESET and SYStem.Down"
		ENDDO
	)

	RETURN


GIC_STATUS_INIT:
	&index=0.
	WHILE &index<&num_of_reg
	(
		Data.Set ASD:Var.Value(\gic_icenabler[&index]) %LE %Long 0xFFFFFFFF
		Data.Set ASD:Var.Value(\gic_icpendr[&index]) %LE %Long 0xFFFFFFFF
		Data.Set ASD:Var.Value(\gic_icactiver[&index]) %LE %Long 0xFFFFFFFF
		&index=&index+1.
	)

	RETURN


OFF_SYS_COUNTER:
	ENTRY &arg_chip

	Core.select &arg_chip

	Data.Set spr:&cntp_ctl_el0 %LE %Long 0x2
	Data.Set spr:&cntv_ctl_el0 %LE %Long 0x2
	Data.Set spr:&cntps_ctl_el1 %LE %Long 0x2
	Data.Set spr:&cnthp_ctl_el2 %LE %Long 0x2

	Data.Set spr:&cntkctl_el1 %LE %Long 0x3
	Data.Set spr:&cnthctl_el2 %LE %Long 0x303

	RETURN
  

Users only need to modify the User Configuration part.
User Configuration
num_of_chip: Write the maximum number of cores of the target chip using the debugger.
cluster: The default value is main if it is not a multi-cluster structure.
gicd_base_addr: Write the gicd starting address.
gicr_base_addr: Write the gicr core0 lpi starting address.
in_el3: Write 1. if testing in el3 environment, 0. if testing in el1 environment.
eoi_mode: Write 0. if eoi mode 0, 1. if eoi mode 1.

User Configuration 2
start_irq: Write the test start interrupt number. Usually, write 16 which is the start address of PPIs.
gic_max_irq: Write the maximum number of SPI interrupts provided by the SoC. +1. Do not modify.
User Configuration 3
gic_target_core: Write the target cpu number to test interrupt. It must not be greater than num_of_chip.


GIC SGIs GENERATE & ROUTING test script


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// gicv3 sgi generate script
//
// - kernel 6.1 or later
// - delete WDT kernel configs
//
// - As of T32 Debugger 2023,
//   there is a difference between triggering SGI generation through step execution and using debugger commands to write.
//   Since verification is conducted through step execution, it is essential to load the Linux ELF before running this script.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

&main=0x0
&sub=0x1

////////////////////////
// User Configuration //
////////////////////////
&num_of_chip=8.
&cluster=&main
&gicd_base_addr=
&gicr_base_addr=
&in_el3=0.
&eoi_mode=0.

//////////////////////////
// User Configuration 2 //
//////////////////////////
&remote_storage=1.
&vmlinux="Z:\work1\tcc807x\main\kernel-6.1\vmlinux"
&invalid_part="/home/user"
&correct_part="Z:"

//////////////////////////
// User Configuration 3 //
//////////////////////////
&sgi_create_core=0.
&sgi_target_core=1.

////////////////////////////
// ARM-A System Registers //
// addr prefix: "spr"     //
////////////////////////////
// EL3 //
&scr_el3=0x36110
// GIC CPU Interfaces //
&icc_iar0_el1=0x30c80
&icc_iar1_el1=0x30cc0
&icc_hppir0_el1=0x30c82
&icc_hppir1_el1=0x30cc2
&icc_eoir0_el1=0x30c81
&icc_eoir1_el1=0x30cc1
&icc_dir_el1=0x30cb1
&icc_sgi0r_el1=0x30cb7
&icc_sgi1r_el1=0x30cb5
// System Counter //
&cntp_ctl_el0=0x33e21
&cntv_ctl_el0=0x33e31
&cntps_ctl_el1=0x37e21
&cntkctl_el1=0x30e10
&cnthctl_el2=0x34e10

///////////////////
// GIC registers //
///////////////////
// GIC offsets //
&enable_offset=0x100
&enable_clr_offset=0x180
&grp_offset=0x80
&grpmod_offset=0xd00
&pend_offset=0x200
&pend_clr_offset=0x280
&active_offset=0x300
&active_clr_offset=0x380
&sgi_offset=0x10000
// GICR //
&gicr_base_addr=&gicr_base_addr+(&cluster*0x20000)+(&sgi_target_core*0x20000)
&gicr_lpi_base_addr=&gicr_base_addr
&gicr_sgi_base_addr=&gicr_base_addr+&sgi_offset
&gicr_isenabler=&gicr_sgi_base_addr+&enable_offset
&gicr_icenabler=&gicr_sgi_base_addr+&enable_clr_offset
&gicr_groupr=&gicr_sgi_base_addr+&grp_offset
&gicr_grpmodr=&gicr_sgi_base_addr+&grpmod_offset
&gicr_ispendr=&gicr_sgi_base_addr+&pend_offset
&gicr_icpendr=&gicr_sgi_base_addr+&pend_clr_offset
&gicr_isactiver=&gicr_sgi_base_addr+&active_offset
&gicr_icactiver=&gicr_sgi_base_addr+&active_clr_offset

///////////// 
// vmlinux // 
/////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c                            //
// index 11f7c53e4b63..7d5937c375a8 100644                                                             //
// --- a/drivers/irqchip/irq-gic-v3.c                                                                  //
// +++ b/drivers/irqchip/irq-gic-v3.c                                                                  //
// @@ -1298,7 +1298,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, //
//         (MPIDR_AFFINITY_LEVEL(cluster_id, level) \
//                 << ICC_SGI1R_AFFINITY_## level ##_SHIFT)                                            //
//                                                                                                     //
// -static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)                              //
// +void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)                                     //
//  {
//         u64 val;
/////////////////////////////////////////////////////////////////////////////////////////////////////////
&break_point=gic_send_sgi+0x40

//////////
// Etc. //
//////////
// common //
&addr=0x0
&core=0
&gic_max_irq=15.
&mpidr_el1=0x30005
&irq=0

GOSUB GIC_SGI_PRESET

sys.log.ON

// GIC SGI generate //
WHILE &irq<=&gic_max_irq
(
	//////////////////////////////////////////////////
	// Use '> continue' in script debug mode        //
	// <---------------------- (Break.Set)          //
	//////////////////////////////////////////////////

	GOSUB GIC_SGI_GENERATE &sgi_create_core &sgi_target_core &irq
	GOSUB GIC_SGI_HANDLE &sgi_target_core &irq
	&irq=&irq+1.
)

sys.log.OFF

ENDDO


GIC_SGI_PRESET:
	Data.LOAD.elf &vmlinux /NoCode
	if &remote_storage==1.
		sYmbol.sourcePATH.translate "&invalid_part" "&correct_part"

	WHILE &core<&num_of_chip
	(
		GOSUB OFF_SYS_COUNTER &core
		&core=&core+1.
	)

	Break.set &break_point

	RETURN


GIC_SGI_GENERATE:
	ENTRY &arg_dpt &arg_dst &arg_id
	LOCAL &aff1 &irq_id &tlist
	LOCAL &sgi_cmd &sgi_staus

	Core.select &arg_dst

	&irq_id=24.
	&aff1=16.
	&tlist=0x1
	&tlist=&tlist|D.Long(SPR:&mpidr_el1)&0xf

	Core.select &arg_dpt

	&sgi_cmd=(&arg_dst<<&aff1)
	&sgi_cmd=&sgi_cmd|(&arg_id<<&irq_id)
	&sgi_cmd=&sgi_cmd|&tlist

	Data.Set ASD:&gicr_isenabler %LE %Long (1<<&arg_id)
	Register.Set PC &break_point
	Register.Set X0 &sgi_cmd
	STEP

	&val_pendr=D.Long(ASD:&gicr_ispendr)>>&arg_id
	&val_pendr=&val_pendr&0x1

	if &val_pendr==1
		PRINT "Pass interrupt pending irq: &arg_id"
	else
		PRINT "Fail interrupt pending irq: &arg_id"

	RETURN


GIC_SET_IRQ:
	ENTRY &arg_id

	Data.Set ASD:&gicr_isenabler %LE %Long (1<<&arg_id)
	Data.Set ASD:&gicr_ispendr %LE %Long (1<<&arg_id)

	RETURN


GIC_CLR_IRQ:
	ENTRY &arg_id

	Data.Set ASD:&gicr_icenabler %LE %Long (1<<&arg_id)
	Data.Set ASD:&gicr_icpendr %LE %Long (1<<&arg_id)

	RETURN


GIC_SGI_HANDLE:
	ENTRY &arg_dst &arg_id

	Core.select &arg_dst
	&iar=D.Long(SPR:&icc_iar1_el1)
	// special ID: 1020 ~ 1023 //
	if (&iar&(~0x3))==1020.
		&special_id=1
	else
		&special_id=0

	if &special_id==0
	(
		&val_activer=D.Long(ASD:&gicr_isactiver)
		&val_activer=&val_activer>>&arg_id
		&val_activer=&val_activer&0x1

		if &val_activer==1
		(
			PRINT "Pass interrupt active irq: &iar"
			GOSUB GIC_CLR_IRQ &iar

			PER.Set.simple SPR:&icc_eoir1_el1 %Quad &iar

			// set dir (eoi mode 1) //
			if &eoi_mode==1.
				PER.Set.simple SPR:&icc_dir_el1 %Quad &iar

			&val_activer=D.Long(ASD:&gicr_isactiver)
			&val_activer=&val_activer>>&arg_id
			&val_activer=&val_activer&0x1

			// Check interrupt life-cycle active -> end //
			if &val_activer==0
			(
				PRINT "Pass interrupt handle irq: &iar"
				PRINT "Pass Core[&sgi_create_core] ===> Core[&sgi_target_core] [SGI:&iar]"
			)
			else
				PRINT "Fail interrupt handle irq: &iar"
		)
		else
		(
			PRINT "Fail interrupt active irq: &iar"
			GOSUB GIC_CLR_IRQ &iar
		)
	)
	else
	(
		PRINT "Spurious interrupt! Check GIC status and irq group"
		PRINT "Recommand RESET and SYStem.Down"
		ENDDO
	)

	RETURN


EOI_MODE_SETUP:
	ENTRY &arg_mode
	LOCAL &icc_ctlr_el1 &icc_ctlr_el3
	LOCAL &eoi_mode_el1 &eoi_mode_el3

	if &arg_mode==0
	(
		&icc_ctlr_el1=0x30cc4
		&eoi_mode_el1=D.Long(SPR:&icc_ctlr_el1)
		&eoi_mode_el1=&eoi_mode_el1&(~0x2)
		PER.Set.simple SPR:&icc_ctlr_el1 %Quad &eoi_mode_el1
		if &in_el3==1.
		(
			&icc_ctlr_el3=0x36cc4
			&eoi_mode_el3=D.Long(SPR:&icc_ctlr_el3)
			&eoi_mode_el3=&eoi_mode_el1&(~0x10)
			PER.Set.simple SPR:&icc_ctlr_el3 %Quad &eoi_mode_el3
		)
	)

	RETURN


GIC_RESET:
	ENTRY &arg_dst
	LOCAL &sgi_cenabler &sgi_cpendr &sgi_cactiver

	&sgi_cenabler=&gicr_icenabler+(0x20000*&arg_dst)
	&sgi_cpendr=&gicr_icpendr+(0x20000*&arg_dst)
	&sgi_cactiver=&gicr_icactiver+(0x20000*&arg_dst)

	Data.Set ASD:&sgi_cenabler %LE %Long 0xFFFFFFFF
	Data.Set ASD:&sgi_cpendr %LE %Long 0xFFFFFFFF
	Data.Set ASD:&sgi_cactiver %LE %Long 0xFFFFFFFF

	RETURN


OFF_SYS_COUNTER:
	ENTRY &arg_chip

	Core.select &arg_chip

	Data.Set spr:&cntp_ctl_el0 %LE %Long 0x2
	Data.Set spr:&cntv_ctl_el0 %LE %Long 0x2
	Data.Set spr:&cntps_ctl_el1 %LE %Long 0x2

	Data.Set spr:&cntkctl_el1 %LE %Long 0x3
	Data.Set spr:&cnthctl_el2 %LE %Long 0x303

	RETURN
  
Users only need to modify the User Configuration part.
User Configuration
num_of_chip: Write the maximum number of cores of the target chip using the debugger.
cluster: The default value is main if it is not a multi-cluster structure.
gicd_base_addr: Write the gicd starting address.
gicr_base_addr: Write the gicr core0 lpi starting address.
in_el3: Write 1. if testing in el3 environment, 0. if testing in el1 environment.
eoi_mode: Write 0. if eoi mode 0, 1. if eoi mode 1.

User Configuration 2
remote_storage: Write 1. if using remote environment like nfs or samaba, otherwise 0.
vmlinux: If remote_storage is 1, write the path of the built kernel vmlinux.
invalid_part: If remote_storage is 1, write the path that needs conversion from the remote perspective.
correct_part: If remote_storage is 1, write the path that needs conversion from the cmm script execution path perspective.
User Configuration 3
&sgi_create_core: Write the core number to trigger the SGI.
&sgi_target_core: Write the core number to process the SGI.


Updated: