About this site

this is a collection of shrik3's personal sys programming and tooling cheatsheet.

Contribute or Comments:

The source (+issue tracker & mailinglist) is hosted at sourcehut Comments and patches are appreciated.

mailinglist (discussion and patches)

~shrik3/syswiki@lists.sr.ht

subscribe here

contributing via email

  1. clone the code:
    git clone https://git.sr.ht/~shrik3/sys.shrik3.com
    
  2. make changes and commit
  3. send the patch
    git send-email --to="~shrik3/syswiki@lists.sr.ht" HEAD^
    

learn about git send-email workflow

issue tracker (tickets)
File an issue here, or send email to

~shrik3/syswiki@todo.sr.ht

"Powered by"

This site is generated with mdbook. The site is deployed to sourcehut pages.

Licensed under

CC BY-NC 4.0

GENERAL & USEFUL RESOURCES

Learn X in Y Minutes

man pages
Noteworthy man pages (archwiki)

  • ascii(7)
  • boot(7)
  • charsets(7)
  • chmod(1)
  • credentials(7)
  • fstab(5)
  • file-hierarchy(7)
  • systemd(1)
  • locale(1p), locale(5), locale(7)
  • printf(3)
  • proc(5)
  • regex(7)
  • signal(7)
  • term(5), term(7)
  • termcap(5)
  • terminfo(5)
  • utf-8(7)

USEFUL RESOURCES

aarch64 ESR, MIDR and SMCCC decoder

aarch64 register and instruction quick reference

instruction <=> hex en/decoder

x86 and aarch64 cpu timer (system counter) (WIP, explore more context)

4K Granule, 48bits OA, 40bits IPS

Table Descriptor (L0~2)

[63:59]     Attributes[4:0]
    -63     NSTable
    -62:61  APTable (see AP)
    -60     UXNTable / XNTable
    -59     PXNTable

[58:51]     IGNORED
[50:48]     RES0
[47:12]     Addr[47:12] of next level descriptor
[11:2 ]     INORED
[1    ]     1 (table)
[0    ]     1 (valid)

Block Descriptor (L1 and L2)

[63:50]     Upper Attributes (Block & Page)
[49:48]     RES0
[47:n ]     Output Address[47:n]  n=30 for L1, n=21 for L2
[n-1:17]    RES0
[16   ]     nT (FEAT-BBM)
[15:12]     RES0
[11:2 ]     Lower Attributes (Block & Page)
[1    ]     0 (block)
[0    ]     1 (valid)

Page Descriptor

[63:50]     Upper Attributes (Block & Page)
[49:48]     RES0
[47:12]     Output Address[47:n]  n=30 for L1, n=21 for L2
[11:2 ]     Lower Attributes (Block & Page)
[1    ]     1 (block)
[0    ]     1 (valid)

Descriptor [63:50] : Block & Page Upper Attributes

[63   ]     IGNORED
[62:59]     PBHA (FEAT_HPDS2)
[58:55]     SW Defined
[54   ]     UXN / XN
[53   ]     PXN
[52   ]     Contiguous
[51   ]     DBM (FEAT_HAFDBS)

Descriptor [11:2] : Block & Page Lower Attributes

[11 ]       NSE / NG
[10 ]       AF
[9:8]       SH[1:0]
[7:6]       AP[1:0] (see AP)
[5  ]       NS (Realm)
[4:2]       AttrIdx

AP[1:0] Access Permission

    EL1+    EL0
-----------------
00  RW      None
01  RW      RW
10  RO      None
11  RO      RO

Memory Type per MAIR_EL1 encoding.

AttrIdx     MemType
--------------------------
000         Device nGnRnE
001         Device nGnRE
010         Device GRE
011         Normal NC
100         Normal
101         Normal_WT
110         undefined
111         undefined

MAIR_EL1, Memory Attribute Indirection Register (EL1)

Provides the memory attribute encodings corresponding to the possible AttrIndx values in a Long-descriptor format translation table entry for stage 1 translations at EL1.

Contains 8x Attr fields. Each is 8 bits.

 64   56                       7     0
| Attr7 | Attr6 | Attr5 | ... | Attr0 |

>>>> Following are all in binary encoding <<<

Attr                meaning
---------------------------------
0b0000dd00          Device Memory
0booooiiii          Normal memory 
    oooo != 0000
    iiii != 0000

Following are NaN if FEAT_XS not implemented
0000dd01    Device Memory w. XS set to 0
10000000    Normal, Inner NC, Outer NC
10100000    Normal, Inner WT+C, Outer WT+C, RA, NWA, NT with XS=0
11110000    Normal, Tagged, Inner WB, Outer WB, RA, WA, NT;


dd                  meaning
---------------------------------
00                  Device-nGnRnE
01                  Device-nGnRE
10                  Device-nGRE
11                  Device-GRE

oooo                meaning
---------------------------------
0000                See Attr encoding
00RW (RW not 00)    Normal memory, outer write-through transient
0100                Normal memory, outer non-cacheable
01RW (RW not 00)    Normal memory, outer write-back transient
10RW                Normal memory, outer write-through non-transient
11RW                Normal memory, outer write-back non-transient


iiii        Meaning: Same for oooo, but "Inner"
-----------------------------------------------

R or W      Meaning (Read-Allocate / Write-Allocate policy)
-----------------------------------------------
0           No Allocate
1           Allocate

Misc:

(N)C        : Non-Cacheable
WA/WT/WB    : Write Allocate/Write Through/Write Back
NT          : Non-transient

(WIP)

TLB instructions

Invalidate TLB entries

TLBI  <type><level>{IS} {,<Xt>}

The following code example shows a sequence for writes to translation tables backed by inner shareable memory:

<< Writes to Translation Tables >>
DSB ISHST   // ensure write has completed
TLBI ALLE1  // invalidate all TLB entries
DSB ISH     // ensure completion of TLB invalidation
ISB         // synchronize context and ensure that no instructions are
            // fetched using the old translation

For a change to a single entry, for example, use the instruction:

TLBI VAE1, X0

which invalidates an entry associated with the address specified in the register X0.

AT instr: test address translation from VA.

AT S<m>E<n><R/W><P>, <Xt>
    <m>     translation stage
    <n>     Exception Level
    <R/W>   R or W, for Read / Write
    <P>     OPTIONAL: test with PAN when implemented
    <Xt>    Holds virtual address

PAR_EL1     Holds result
    MRS     <Xt>, PAR_EL1

PAR_EL1[63:0]

[63:56]     ATTR: Memory Attr, same as in MAIR_EL1
[55:52]     RES0
[51:48]     PA[51:48]   <OPT> / RES0
[47:12]     PA[47:12]
[11   ]     NSE         <OPT> / RES1
[10   ]     impl. defined
[9    ]     NS (Non Secure)
[8 : 7]     SH
[6 : 1]     RES0
[0    ]     F       (1==failure)

Memory Attr Encoding: also see this for details.

It's a 8 bits value:

Value       Meaning
---------------------------------
0000dd00    Device Memory
0000dd1x    NaN
ooooiiii    Normal Memory (oooo!=0000, iiii!=0000)


dd          Meaning
---------------------------------
00          Device nGnRnE
01          Device nGnRE
10          Device nGRE
11          Device GRE

oooo        Meaning: (Outer)
---------------------------------
0000        NaN
00RW        Normal Memory, outer WT Transient (RW!=00)
0100        Normal Memory, outer NC
01RW        Normal Memory, outer WB Transient (RW!=00)
10RW        Normal Memory, outer WT, NT
11RW        Normal Memory, Outer WB, NT


iiii        Meaning: Same for oooo, but "Inner"
-----------------------------------------------

R or W      Meaning (Read-Allocate / Write-Allocate policy)
-----------------------------------------------
0           No Allocate
1           Allocate

SH[1:0]

00          Non Shareable
10          Outer Shareable
11          Inner Shareable

NS/NSE

// TODO

NSE     NS      Meaning
------------------------
0       0       Res*
0       1       Non-Secure
1       0       Root
1       1       Realm

* if secure state is implemented: Secure. Otherwise reserved.
  This is obsoleted by Realm

ESR Decoder: https://esr.arm64.dev/

Aarch64 translation fault related stuffs.

ESR_EL1

/// TODO ADD ESR_EL1

ESR.EC

  • 0x20 - instr abort low
  • 0x21 - instr abort current
  • 0x24 - data abort low
  • 0x25 - data abort current

/// TODO ADD OTHER ECs /// TODO ADD DFSC AND IFSC

ESR.ISS for instr abort

BIT [xx:xx] .
BIT [24]     ISV Instruction Syndrome Valid
                - Following bits are only valid when isv=1
BITS[23:22]  SAS Syndrome Access Size
                - 0b00 : 1 x byte
                - 0b01 : 2 x byte
                - 0b10 : 3 x byte
                - 0b11 : 4 x byte
BIT [21]     SSE Syndrome Sign Extend
                - 0b0 Sign ext not required
                - 0b1 sign ext required
BITS[20:16]  SRT Syndrome Register Transfer
                - register number of Xt/Xt/Rt operands of faulting instr
BIT [15]     SF  Sixty Four bit general-purpsoe register transfer
                - 0b0 instr loads/stores 32-bit GPR
                - 0b1 instr loads/stores 64-bit GPR
BIT [14]     AR Acquire/Release
BIT [13]     VNCR indicates fault came from VNCR_EL2 in EL1 code
BITS[12:11]  SET Synchronous Error Type
                - When FEAT_RAS is implemented and DFSC == 0b010000
BITS[12:11]  LST Load/Store Type
                - When FEAT_LS64 is implemented and DFSC == 0b110101
BIT [10]     FnV FAR not valid
                - 0 FAR is valid
                - 1 FAR not valid, value unknown
BIT [9]      EA
BIT [8]      CM
BIT [7]      S1PTW
                - 0 Fault NOT on stage 2
                - 1 Fault on stage 2
BIT [6]      WnR
BITs[5:0]    DFSC Data Fault Status Code

ESR.ISS for data abort

BITs[24:13]  RES0
BITS[12:11]  SET Synchronous Error Type
                - When FEAT_RAS is implemented and IFSC == 0b010000
BITS[12:11]  LST Load/Store Type
                - When FEAT_LS64 is implemented and IFSC == 0b110101
BIT [10]     FnV FAR not valid
BIT [9]      EA
BIT [8]      RES0
BIT [7]      S1PTW
BIT [6]      RES0
BITs[5:0]    IFSC Data Fault Status Code

ESR.ISS.IFSC / DFSC See the documents, it sucks.

PARTIALLY:

// Access Size Fault L0~3
DFSC_ASF_L0      = 0x0;
DFSC_ASF_L1      = 0x1;
DFSC_ASF_L2      = 0x2;
DFSC_ASF_L3      = 0x3;

// Translation Fault L0~3
DFSC_TF_L0       = 0x4;
DFSC_TF_L1       = 0x5;
DFSC_TF_L2       = 0x6;
DFSC_TF_L3       = 0x7;

// Access Flag Fault L0~3
DFSC_AF_L0       = 0x8;      /* if FEAT_LPA2 is implmented */
DFSC_AF_L1       = 0x9;
DFSC_AF_L2       = 0xa;
DFSC_AF_L3       = 0xb;

// Permission Fault L0 ~ 3
DFSC_PF_L0       = 0xc;      /* if FEAT_LPA2 is implemented */
DFSC_PF_L1       = 0xd;
DFSC_PF_L2       = 0xe;
DFSC_PF_L3       = 0xf;

// Synchronous External Abort (SEA)
// not on translation table walk
DFSC_SEA          = 0x10;

// on translation table walk, L -1~3
DFSC_SEA_M1       = 0x13;     /* if FEAT_LPA2 is implemented*/
DFSC_SEA_L0      = 0x14;
DFSC_SEA_L1      = 0x15;
DFSC_SEA_L2      = 0x16;
DFSC_SEA_L3      = 0x17;

// Synchronous parity or ECC error when FEAT_RAS NOT implemented.
// not on table walk
DFSC_ECC          = 0x18;

// on table walk: L-1~3
DFSC_ECC_M1      = 0x1b;
DFSC_ECC_L0      = 0x1c;
DFSC_ECC_L1      = 0x1d;
DFSC_ECC_L2      = 0x1e;
DFSC_ECC_L3      = 0x1f;

pub const DFSC_ALIGN:u64    = 0x21;

// the Granule Protection Faults
// GPF on table walk, L-1~3
DFSC_GPF_M1      = 0x23;
DFSC_GPF_L0      = 0x23;
DFSC_GPF_L1      = 0x25;
DFSC_GPF_L2      = 0x26;
DFSC_GPF_L3      = 0x27;

// GPF not on table walk
pub const DFSC_GPF          = 0x28;

DFSC_ASF_M1       = 0x29;
DFSC_TF_M1        = 0x2b;

DFSC_TLB_CONFLICT     = 0x30;
// unsupported atomic hardware update
DFSC_UAHU         = 0x31;

https://developer.arm.com/documentation/ddi0595/2021-12/AArch64-Registers/ESR-EL1--Exception-Syndrome-Register--EL1-?lang=en#fieldset_0-24_0_13

ESR_EL1 (Exception Syndrome Register (EL1)

bit range is inclusive on both ends
-----------------------------------

BITS[63:37] RES0
BITS[36:32] ISS2    < when FEAT_LS64 implemented
BITS[31:26] EC      Exception Class
BIT [25]    IL      Instruction Length for sync exceptions
                    - 0 : 16bit instruction trapped
                    - 1 : 32bit Instruction trapped
BITS[24:0 ] ISS     Instruction Specific Syndrome

EC in ESR

taken from linux/arch/arm64/include/asm/esr.h

ESR_ELx_EC_UNKNOWN  (0x00)
ESR_ELx_EC_WFx      (0x01)
UNALLOCATED         (0x02)
ESR_ELx_EC_CP15_32  (0x03)
ESR_ELx_EC_CP15_64  (0x04)
ESR_ELx_EC_CP14_MR  (0x05)
ESR_ELx_EC_CP14_LS  (0x06)
ESR_ELx_EC_FP_ASIMD (0x07)
ESR_ELx_EC_CP10_ID  (0x08)  /* EL2 only */
ESR_ELx_EC_PAC      (0x09)  /* EL2 and above */
UNALLOCATED         (0x0A - 0x0B)
ESR_ELx_EC_CP14_64  (0x0C)
ESR_ELx_EC_BTI      (0x0D)
ESR_ELx_EC_ILL      (0x0E)
UNALLOCATED         (0x0F - 0x10)
ESR_ELx_EC_SVC32    (0x11)
ESR_ELx_EC_HVC32    (0x12)  /* EL2 only */
ESR_ELx_EC_SMC32    (0x13)  /* EL2 and above */
UNALLOCATED         (0x14)
ESR_ELx_EC_SVC64    (0x15)
ESR_ELx_EC_HVC64    (0x16)  /* EL2 and above */
ESR_ELx_EC_SMC64    (0x17)  /* EL2 and above */
ESR_ELx_EC_SYS64    (0x18)
ESR_ELx_EC_SVE      (0x19)
ESR_ELx_EC_ERET     (0x1a)  /* EL2 only */
UNALLOCATED         (0x1B)
ESR_ELx_EC_FPAC     (0x1C)  /* EL1 and above */
ESR_ELx_EC_SME      (0x1D)
UNALLOCATED         (0x1E)
ESR_ELx_EC_IMP_DEF  (0x1f)  /* EL3 only */
ESR_ELx_EC_IABT_LOW (0x20)
ESR_ELx_EC_IABT_CUR (0x21)
ESR_ELx_EC_PC_ALIGN (0x22)
UNALLOCATED         (0x23)
ESR_ELx_EC_DABT_LOW (0x24)
ESR_ELx_EC_DABT_CUR (0x25)
ESR_ELx_EC_SP_ALIGN (0x26)
ESR_ELx_EC_MOPS     (0x27)
ESR_ELx_EC_FP_EXC32 (0x28)
UNALLOCATED         (0x29 - 0x2B)
ESR_ELx_EC_FP_EXC64 (0x2C)
UNALLOCATED         (0x2D - 0x2E)
ESR_ELx_EC_SERROR   (0x2F)
ESR_ELx_EC_BREAKPT_LOW  (0x30)
ESR_ELx_EC_BREAKPT_CUR  (0x31)
ESR_ELx_EC_SOFTSTP_LOW  (0x32)
ESR_ELx_EC_SOFTSTP_CUR  (0x33)
ESR_ELx_EC_WATCHPT_LOW  (0x34)
ESR_ELx_EC_WATCHPT_CUR  (0x35)
UNALLOCATED         (0x36 - 0x37)
ESR_ELx_EC_BKPT32   (0x38)
UNALLOCATED         (0x39)
ESR_ELx_EC_VECTOR32 (0x3A)  /* EL2 only */
UNALLOCATED         (0x3B)
ESR_ELx_EC_BRK64    (0x3C)
UNALLOCATED         (0x3D - 0x3F)

ESR_ELx_EC_MAX      (0x3F)
ESR_ELx_EC_SHIFT    (26)
ESR_ELx_EC_WIDTH    (6)
ESR_ELx_EC_MASK     (UL(0x3F) << ESR_ELx_EC_SHIFT)
ESR_ELx_EC(esr)     (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)


footnotes, licenses

linux/arch/arm64/include/asm/esr.h
--------------------------------------------
SPDX-License-Identifier: GPL-2.0-only

Copyright (C) 2013 - ARM Ltd
Author: Marc Zyngier <marc.zyngier@arm.com>
each vector is aligned to 2^7 ie 0x80 bytes

TABLE_BASE
    CURRENT_EL + SP0    sync    // el1_t
    CURRENT_EL + SP0    irq
    CURRENT_EL + SP0    fiq
    CURRENT_EL + SP0    serror

    CURRENT_EL + SPX    sync    // el1_h
    CURRENT_EL + SPX    irq
    CURRENT_EL + SPX    fiq
    CURRENT_EL + SPX    serror

    LOWWER_EL  +        sync    // aarch64 // el0_
    LOWWER_EL  +        irq     
    LOWWER_EL  +        fiq     
    LOWWER_EL  +        Serror  

    LOWWER_EL  +        sync    // aarch32
    LOWWER_EL  +        irq     
    LOWWER_EL  +        fiq     
    LOWWER_EL  +        Serror  

arch/arm64/include/armreg.h from OpenBSD CODE. Lisence is at the end.

This is only for my own quick reference. Please look away XD

#ifndef _MACHINE_ARMREG_H_
#define	_MACHINE_ARMREG_H_

#define	INSN_SIZE		4

#define	READ_SPECIALREG(reg)						\
({	uint64_t val;							\
	__asm volatile("mrs	%0, " __STRING(reg) : "=&r" (val));	\
	val;								\
})
#define	WRITE_SPECIALREG(reg, val)					\
	__asm volatile("msr	" __STRING(reg) ", %0" : : "r"((uint64_t)val))

/* CCSIDR_EL1 - Current Cache Size ID Register */
#define	CCSIDR_SETS_MASK	0x0fffe000
#define	CCSIDR_SETS_SHIFT	13
#define	CCSIDR_SETS(reg)	\
    ((((reg) & CCSIDR_SETS_MASK) >> CCSIDR_SETS_SHIFT) + 1)
#define	CCSIDR_WAYS_MASK	0x00001ff8
#define	CCSIDR_WAYS_SHIFT	3
#define	CCSIDR_WAYS(reg)	\
    ((((reg) & CCSIDR_WAYS_MASK) >> CCSIDR_WAYS_SHIFT) + 1)
#define	CCSIDR_LINE_MASK	0x00000007
#define	CCSIDR_LINE_SIZE(reg)	(1 << (((reg) & CCSIDR_LINE_MASK) + 4))

/* CLIDR_EL1 - Cache Level ID Register */
#define	CLIDR_CTYPE_MASK	0x7
#define	CLIDR_CTYPE_INSN	0x1
#define	CLIDR_CTYPE_DATA	0x2
#define	CLIDR_CTYPE_UNIFIED	0x4

/* CNTHCTL_EL2 - Counter-timer Hypervisor Control Register */
#define	CNTHCTL_EVNTI_MASK	(0xf << 4) /* Bit to trigger event stream */
#define	CNTHCTL_EVNTDIR		(1 << 3) /* Control transition trigger bit */
#define	CNTHCTL_EVNTEN		(1 << 2) /* Enable event stream */
#define	CNTHCTL_EL1PCEN		(1 << 1) /* Allow EL0/1 physical timer access */
#define	CNTHCTL_EL1PCTEN	(1 << 0) /*Allow EL0/1 physical counter access*/

/* CNTKCTL_EL1 - Counter-timer Kernel Control Register */
#define	CNTKCTL_EL0VCTEN	(1 << 1) /* Allow EL0 virtual counter access */

/* CNTV_CTL_EL0 */
#define	CNTV_CTL_ENABLE		(1 << 0)
#define	CNTV_CTL_IMASK		(1 << 1)
#define	CNTV_CTL_ISTATUS	(1 << 2)

/* CPACR_EL1 */
#define	CPACR_FPEN_MASK		(0x3 << 20)
#define	 CPACR_FPEN_TRAP_ALL1	(0x0 << 20) /* Traps from EL0 and EL1 */
#define	 CPACR_FPEN_TRAP_EL0	(0x1 << 20) /* Traps from EL0 */
#define	 CPACR_FPEN_TRAP_ALL2	(0x2 << 20) /* Traps from EL0 and EL1 */
#define	 CPACR_FPEN_TRAP_NONE	(0x3 << 20) /* No traps */
#define	CPACR_TTA		(0x1 << 28)

/* CSSELR_EL1 - Cache Size Selection Register */
#define	CSSELR_IND		(1 << 0)
#define	CSSELR_LEVEL_SHIFT	1

/* CTR_EL0 - Cache Type Register */
#define	CTR_DLINE_SHIFT		16
#define	CTR_DLINE_MASK		(0xf << CTR_DLINE_SHIFT)
#define	CTR_DLINE_SIZE(reg)	(((reg) & CTR_DLINE_MASK) >> CTR_DLINE_SHIFT)
#define	CTR_IL1P_SHIFT		14
#define	CTR_IL1P_MASK		(0x3 << CTR_IL1P_SHIFT)
#define	CTR_IL1P_AIVIVT		(0x1 << CTR_IL1P_SHIFT)
#define	CTR_IL1P_VIPT		(0x2 << CTR_IL1P_SHIFT)
#define	CTR_IL1P_PIPT		(0x3 << CTR_IL1P_SHIFT)
#define	CTR_ILINE_SHIFT		0
#define	CTR_ILINE_MASK		(0xf << CTR_ILINE_SHIFT)
#define	CTR_ILINE_SIZE(reg)	(((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT)

/* MPIDR_EL1 - Multiprocessor Affinity Register */
#define MPIDR_AFF3		(0xFFULL << 32)
#define MPIDR_AFF2		(0xFFULL << 16)
#define MPIDR_AFF1		(0xFFULL << 8)
#define MPIDR_AFF0		(0xFFULL << 0)
#define MPIDR_AFF		(MPIDR_AFF3|MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0)

/* DCZID_EL0 - Data Cache Zero ID register */
#define DCZID_DZP		(1 << 4) /* DC ZVA prohibited if non-0 */
#define DCZID_BS_SHIFT		0
#define DCZID_BS_MASK		(0xf << DCZID_BS_SHIFT)
#define	DCZID_BS_SIZE(reg)	(((reg) & DCZID_BS_MASK) >> DCZID_BS_SHIFT)

/* ESR_ELx */
#define	ESR_ELx_ISS_MASK	0x00ffffff
#define	 ISS_INSN_FnV		(0x01 << 10)
#define	 ISS_INSN_EA		(0x01 << 9)
#define	 ISS_INSN_S1PTW		(0x01 << 7)
#define	 ISS_INSN_IFSC_MASK	(0x1f << 0)
#define	 ISS_DATA_ISV		(0x01 << 24)
#define	 ISS_DATA_SAS_MASK	(0x03 << 22)
#define	 ISS_DATA_SSE		(0x01 << 21)
#define	 ISS_DATA_SRT_MASK	(0x1f << 16)
#define	 ISS_DATA_SF		(0x01 << 15)
#define	 ISS_DATA_AR		(0x01 << 14)
#define	 ISS_DATA_FnV		(0x01 << 10)
#define	 ISS_DATA_EA		(0x01 << 9)
#define	 ISS_DATA_CM		(0x01 << 8)
#define	 ISS_INSN_S1PTW		(0x01 << 7)
#define	 ISS_DATA_WnR		(0x01 << 6)
#define	 ISS_DATA_DFSC_MASK	(0x3f << 0)
#define	 ISS_DATA_DFSC_ASF_L0	(0x00 << 0)
#define	 ISS_DATA_DFSC_ASF_L1	(0x01 << 0)
#define	 ISS_DATA_DFSC_ASF_L2	(0x02 << 0)
#define	 ISS_DATA_DFSC_ASF_L3	(0x03 << 0)
#define	 ISS_DATA_DFSC_TF_L0	(0x04 << 0)
#define	 ISS_DATA_DFSC_TF_L1	(0x05 << 0)
#define	 ISS_DATA_DFSC_TF_L2	(0x06 << 0)
#define	 ISS_DATA_DFSC_TF_L3	(0x07 << 0)
#define	 ISS_DATA_DFSC_AFF_L1	(0x09 << 0)
#define	 ISS_DATA_DFSC_AFF_L2	(0x0a << 0)
#define	 ISS_DATA_DFSC_AFF_L3	(0x0b << 0)
#define	 ISS_DATA_DFSC_PF_L1	(0x0d << 0)
#define	 ISS_DATA_DFSC_PF_L2	(0x0e << 0)
#define	 ISS_DATA_DFSC_PF_L3	(0x0f << 0)
#define	 ISS_DATA_DFSC_EXT	(0x10 << 0)
#define	 ISS_DATA_DFSC_EXT_L0	(0x14 << 0)
#define	 ISS_DATA_DFSC_EXT_L1	(0x15 << 0)
#define	 ISS_DATA_DFSC_EXT_L2	(0x16 << 0)
#define	 ISS_DATA_DFSC_EXT_L3	(0x17 << 0)
#define	 ISS_DATA_DFSC_ECC	(0x18 << 0)
#define	 ISS_DATA_DFSC_ECC_L0	(0x1c << 0)
#define	 ISS_DATA_DFSC_ECC_L1	(0x1d << 0)
#define	 ISS_DATA_DFSC_ECC_L2	(0x1e << 0)
#define	 ISS_DATA_DFSC_ECC_L3	(0x1f << 0)
#define	 ISS_DATA_DFSC_ALIGN	(0x21 << 0)
#define	 ISS_DATA_DFSC_TLB_CONFLICT (0x30 << 0)
#define	ESR_ELx_IL		(0x01 << 25)
#define	ESR_ELx_EC_SHIFT	26
#define	ESR_ELx_EC_MASK		(0x3f << 26)
#define	ESR_ELx_EXCEPTION(esr)	(((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)
#define	 EXCP_UNKNOWN		0x00	/* Unkwn exception */
#define	 EXCP_FP_SIMD		0x07	/* FP/SIMD trap */
#define	 EXCP_BRANCH_TGT	0x0d	/* Branch target exception */
#define	 EXCP_ILL_STATE		0x0e	/* Illegal execution state */
#define	 EXCP_SVC		0x15	/* SVC trap */
#define	 EXCP_MSR		0x18	/* MSR/MRS trap */
#define	 EXCP_FPAC		0x1c	/* Faulting PAC trap */
#define	 EXCP_INSN_ABORT_L	0x20	/* Instruction abort, from lower EL */
#define	 EXCP_INSN_ABORT	0x21	/* Instruction abort, from same EL */ 
#define	 EXCP_PC_ALIGN		0x22	/* PC alignment fault */
#define	 EXCP_DATA_ABORT_L	0x24	/* Data abort, from lower EL */
#define	 EXCP_DATA_ABORT	0x25	/* Data abort, from same EL */ 
#define	 EXCP_SP_ALIGN		0x26	/* SP alignment fault */
#define	 EXCP_TRAP_FP		0x2c	/* Trapped FP exception */
#define	 EXCP_SERROR		0x2f	/* SError interrupt */
#define	 EXCP_SOFTSTP_EL0	0x32	/* Software Step, from lower EL */
#define	 EXCP_SOFTSTP_EL1	0x33	/* Software Step, from same EL */
#define	 EXCP_WATCHPT_EL1	0x35	/* Watchpoint, from same EL */
#define	 EXCP_BRK		0x3c	/* Breakpoint */

/* ICC_CTLR_EL1 */
#define	ICC_CTLR_EL1_EOIMODE		(1U << 1)
#define	ICC_CTLR_EL1_PRIBITS_SHIFT	8
#define	ICC_CTLR_EL1_PRIBITS_MASK	(0x7UL << 8)
#define	ICC_CTLR_EL1_PRIBITS(reg)	\
    (((reg) & ICC_CTLR_EL1_PRIBITS_MASK) >> ICC_CTLR_EL1_PRIBITS_SHIFT)

/* ICC_IAR1_EL1 */
#define	ICC_IAR1_EL1_SPUR	(0x03ff)

/* ICC_IGRPEN0_EL1 */
#define	ICC_IGRPEN0_EL1_EN	(1U << 0)

/* ICC_PMR_EL1 */
#define	ICC_PMR_EL1_PRIO_MASK	(0xFFUL)

/* ICC_SGI1R_EL1 */
#define	ICC_SGI1R_EL1_TL_MASK		0xffffUL
#define	ICC_SGI1R_EL1_AFF1_SHIFT	16
#define	ICC_SGI1R_EL1_SGIID_SHIFT	24
#define	ICC_SGI1R_EL1_AFF2_SHIFT	32
#define	ICC_SGI1R_EL1_AFF3_SHIFT	48
#define	ICC_SGI1R_EL1_SGIID_MASK	0xfUL
#define	ICC_SGI1R_EL1_IRM		(0x1UL << 40)

/* ICC_SRE_EL1 */
#define	ICC_SRE_EL1_SRE		(1U << 0)

/* ICC_SRE_EL2 */
#define	ICC_SRE_EL2_SRE		(1U << 0)
#define	ICC_SRE_EL2_EN		(1U << 3)

/* ID_AA64DFR0_EL1 */
#define	ID_AA64DFR0_MASK		0x00000000f0f0ffffUL
#define	ID_AA64DFR0_DEBUG_VER_SHIFT	0
#define	ID_AA64DFR0_DEBUG_VER_MASK	(0xf << ID_AA64DFR0_DEBUG_VER_SHIFT)
#define	ID_AA64DFR0_DEBUG_VER(x)	((x) & ID_AA64DFR0_DEBUG_VER_MASK)
#define	 ID_AA64DFR0_DEBUG_VER_8	(0x6 << ID_AA64DFR0_DEBUG_VER_SHIFT)
#define	 ID_AA64DFR0_DEBUG_VER_8_VHE	(0x7 << ID_AA64DFR0_DEBUG_VER_SHIFT)
#define	ID_AA64DFR0_TRACE_VER_SHIFT	4
#define	ID_AA64DFR0_TRACE_VER_MASK	(0xf << ID_AA64DFR0_TRACE_VER_SHIFT)
#define	ID_AA64DFR0_TRACE_VER(x)	((x) & ID_AA64DFR0_TRACE_VER_MASK)
#define	 ID_AA64DFR0_TRACE_VER_NONE	(0x0 << ID_AA64DFR0_TRACE_VER_SHIFT)
#define	 ID_AA64DFR0_TRACE_VER_IMPL	(0x1 << ID_AA64DFR0_TRACE_VER_SHIFT)
#define	ID_AA64DFR0_PMU_VER_SHIFT	8
#define	ID_AA64DFR0_PMU_VER_MASK	(0xf << ID_AA64DFR0_PMU_VER_SHIFT)
#define	ID_AA64DFR0_PMU_VER(x)		((x) & ID_AA64DFR0_PMU_VER_MASK)
#define	 ID_AA64DFR0_PMU_VER_NONE	(0x0 << ID_AA64DFR0_PMU_VER_SHIFT)
#define	 ID_AA64DFR0_PMU_VER_3		(0x1 << ID_AA64DFR0_PMU_VER_SHIFT)
#define	 ID_AA64DFR0_PMU_VER_3_1	(0x4 << ID_AA64DFR0_PMU_VER_SHIFT)
#define	 ID_AA64DFR0_PMU_VER_IMPL	(0xf << ID_AA64DFR0_PMU_VER_SHIFT)
#define	ID_AA64DFR0_BRPS_SHIFT		12
#define	ID_AA64DFR0_BRPS_MASK		(0xf << ID_AA64DFR0_BRPS_SHIFT)
#define	ID_AA64DFR0_BRPS(x)		\
    ((((x) >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) + 1)
#define	ID_AA64DFR0_WRPS_SHIFT		20
#define	ID_AA64DFR0_WRPS_MASK		(0xf << ID_AA64DFR0_WRPS_SHIFT)
#define	ID_AA64DFR0_WRPS(x)		\
    ((((x) >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) + 1)
#define	ID_AA64DFR0_CTX_CMPS_SHIFT	28
#define	ID_AA64DFR0_CTX_CMPS_MASK	(0xf << ID_AA64DFR0_CTX_CMPS_SHIFT)
#define	ID_AA64DFR0_CTX_CMPS(x)		\
    ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1)

/* ID_AA64ISAR0_EL1 */
#define	ID_AA64ISAR0_MASK		0xfffffffff0fffff0ULL
#define	ID_AA64ISAR0_AES_SHIFT		4
#define	ID_AA64ISAR0_AES_MASK		(0xf << ID_AA64ISAR0_AES_SHIFT)
#define	ID_AA64ISAR0_AES(x)		((x) & ID_AA64ISAR0_AES_MASK)
#define	 ID_AA64ISAR0_AES_NONE		(0x0 << ID_AA64ISAR0_AES_SHIFT)
#define	 ID_AA64ISAR0_AES_BASE		(0x1 << ID_AA64ISAR0_AES_SHIFT)
#define	 ID_AA64ISAR0_AES_PMULL		(0x2 << ID_AA64ISAR0_AES_SHIFT)
#define	ID_AA64ISAR0_SHA1_SHIFT		8
#define	ID_AA64ISAR0_SHA1_MASK		(0xf << ID_AA64ISAR0_SHA1_SHIFT)
#define	ID_AA64ISAR0_SHA1(x)		((x) & ID_AA64ISAR0_SHA1_MASK)
#define	 ID_AA64ISAR0_SHA1_NONE		(0x0 << ID_AA64ISAR0_SHA1_SHIFT)
#define	 ID_AA64ISAR0_SHA1_BASE		(0x1 << ID_AA64ISAR0_SHA1_SHIFT)
#define	ID_AA64ISAR0_SHA2_SHIFT		12
#define	ID_AA64ISAR0_SHA2_MASK		(0xf << ID_AA64ISAR0_SHA2_SHIFT)
#define	ID_AA64ISAR0_SHA2(x)		((x) & ID_AA64ISAR0_SHA2_MASK)
#define	 ID_AA64ISAR0_SHA2_NONE		(0x0 << ID_AA64ISAR0_SHA2_SHIFT)
#define	 ID_AA64ISAR0_SHA2_BASE		(0x1 << ID_AA64ISAR0_SHA2_SHIFT)
#define	 ID_AA64ISAR0_SHA2_512		(0x2 << ID_AA64ISAR0_SHA2_SHIFT)
#define	ID_AA64ISAR0_CRC32_SHIFT	16
#define	ID_AA64ISAR0_CRC32_MASK		(0xf << ID_AA64ISAR0_CRC32_SHIFT)
#define	ID_AA64ISAR0_CRC32(x)		((x) & ID_AA64ISAR0_CRC32_MASK)
#define	 ID_AA64ISAR0_CRC32_NONE	(0x0 << ID_AA64ISAR0_CRC32_SHIFT)
#define	 ID_AA64ISAR0_CRC32_BASE	(0x1 << ID_AA64ISAR0_CRC32_SHIFT)
#define	ID_AA64ISAR0_ATOMIC_SHIFT	20
#define	ID_AA64ISAR0_ATOMIC_MASK	(0xf << ID_AA64ISAR0_ATOMIC_SHIFT)
#define	ID_AA64ISAR0_ATOMIC(x)		((x) & ID_AA64ISAR0_ATOMIC_MASK)
#define	 ID_AA64ISAR0_ATOMIC_NONE	(0x0 << ID_AA64ISAR0_ATOMIC_SHIFT)
#define	 ID_AA64ISAR0_ATOMIC_IMPL	(0x2 << ID_AA64ISAR0_ATOMIC_SHIFT)
#define	ID_AA64ISAR0_RDM_SHIFT		28
#define	ID_AA64ISAR0_RDM_MASK		(0xf << ID_AA64ISAR0_RDM_SHIFT)
#define	ID_AA64ISAR0_RDM(x)		((x) & ID_AA64ISAR0_RDM_MASK)
#define	 ID_AA64ISAR0_RDM_NONE		(0x0 << ID_AA64ISAR0_RDM_SHIFT)
#define	 ID_AA64ISAR0_RDM_IMPL		(0x1 << ID_AA64ISAR0_RDM_SHIFT)
#define	ID_AA64ISAR0_SHA3_SHIFT		32
#define	ID_AA64ISAR0_SHA3_MASK		(0xfULL << ID_AA64ISAR0_SHA3_SHIFT)
#define	ID_AA64ISAR0_SHA3(x)		((x) & ID_AA64ISAR0_SHA3_MASK)
#define	 ID_AA64ISAR0_SHA3_NONE		(0x0ULL << ID_AA64ISAR0_SHA3_SHIFT)
#define	 ID_AA64ISAR0_SHA3_IMPL		(0x1ULL << ID_AA64ISAR0_SHA3_SHIFT)
#define	ID_AA64ISAR0_SM3_SHIFT		36
#define	ID_AA64ISAR0_SM3_MASK		(0xfULL << ID_AA64ISAR0_SM3_SHIFT)
#define	ID_AA64ISAR0_SM3(x)		((x) & ID_AA64ISAR0_SM3_MASK)
#define	 ID_AA64ISAR0_SM3_NONE		(0x0ULL << ID_AA64ISAR0_SM3_SHIFT)
#define	 ID_AA64ISAR0_SM3_IMPL		(0x1ULL << ID_AA64ISAR0_SM3_SHIFT)
#define	ID_AA64ISAR0_SM4_SHIFT		40
#define	ID_AA64ISAR0_SM4_MASK		(0xfULL << ID_AA64ISAR0_SM4_SHIFT)
#define	ID_AA64ISAR0_SM4(x)		((x) & ID_AA64ISAR0_SM4_MASK)
#define	 ID_AA64ISAR0_SM4_NONE		(0x0ULL << ID_AA64ISAR0_SM4_SHIFT)
#define	 ID_AA64ISAR0_SM4_IMPL		(0x1ULL << ID_AA64ISAR0_SM4_SHIFT)
#define	ID_AA64ISAR0_DP_SHIFT		44
#define	ID_AA64ISAR0_DP_MASK		(0xfULL << ID_AA64ISAR0_DP_SHIFT)
#define	ID_AA64ISAR0_DP(x)		((x) & ID_AA64ISAR0_DP_MASK)
#define	 ID_AA64ISAR0_DP_NONE		(0x0ULL << ID_AA64ISAR0_DP_SHIFT)
#define	 ID_AA64ISAR0_DP_IMPL		(0x1ULL << ID_AA64ISAR0_DP_SHIFT)
#define	ID_AA64ISAR0_FHM_SHIFT		48
#define	ID_AA64ISAR0_FHM_MASK		(0xfULL << ID_AA64ISAR0_FHM_SHIFT)
#define	ID_AA64ISAR0_FHM(x)		((x) & ID_AA64ISAR0_FHM_MASK)
#define	 ID_AA64ISAR0_FHM_NONE		(0x0ULL << ID_AA64ISAR0_FHM_SHIFT)
#define	 ID_AA64ISAR0_FHM_IMPL		(0x1ULL << ID_AA64ISAR0_FHM_SHIFT)
#define	ID_AA64ISAR0_TS_SHIFT		52
#define	ID_AA64ISAR0_TS_MASK		(0xfULL << ID_AA64ISAR0_TS_SHIFT)
#define	ID_AA64ISAR0_TS(x)		((x) & ID_AA64ISAR0_TS_MASK)
#define	 ID_AA64ISAR0_TS_NONE		(0x0ULL << ID_AA64ISAR0_TS_SHIFT)
#define	 ID_AA64ISAR0_TS_BASE		(0x1ULL << ID_AA64ISAR0_TS_SHIFT)
#define	 ID_AA64ISAR0_TS_AXFLAG		(0x2ULL << ID_AA64ISAR0_TS_SHIFT)
#define	ID_AA64ISAR0_TLB_SHIFT		56
#define	ID_AA64ISAR0_TLB_MASK		(0xfULL << ID_AA64ISAR0_TLB_SHIFT)
#define	ID_AA64ISAR0_TLB(x)		((x) & ID_AA64ISAR0_TLB_MASK)
#define	 ID_AA64ISAR0_TLB_NONE		(0x0ULL << ID_AA64ISAR0_TLB_SHIFT)
#define	 ID_AA64ISAR0_TLB_IOS		(0x1ULL << ID_AA64ISAR0_TLB_SHIFT)
#define	 ID_AA64ISAR0_TLB_IRANGE	(0x2ULL << ID_AA64ISAR0_TLB_SHIFT)
#define	ID_AA64ISAR0_RNDR_SHIFT		60
#define	ID_AA64ISAR0_RNDR_MASK		(0xfULL << ID_AA64ISAR0_RNDR_SHIFT)
#define	ID_AA64ISAR0_RNDR(x)		((x) & ID_AA64ISAR0_RNDR_MASK)
#define	 ID_AA64ISAR0_RNDR_NONE		(0x0ULL << ID_AA64ISAR0_RNDR_SHIFT)
#define	 ID_AA64ISAR0_RNDR_IMPL		(0x1ULL << ID_AA64ISAR0_RNDR_SHIFT)

/* ID_AA64ISAR1_EL1 */
#define	ID_AA64ISAR1_MASK		0x00000fffffffffffULL
#define	ID_AA64ISAR1_DPB_SHIFT		0
#define	ID_AA64ISAR1_DPB_MASK		(0xf << ID_AA64ISAR1_DPB_SHIFT)
#define	ID_AA64ISAR1_DPB(x)		((x) & ID_AA64ISAR1_DPB_MASK)
#define	 ID_AA64ISAR1_DPB_NONE		(0x0 << ID_AA64ISAR1_DPB_SHIFT)
#define	 ID_AA64ISAR1_DPB_IMPL		(0x1 << ID_AA64ISAR1_DPB_SHIFT)
#define	ID_AA64ISAR1_APA_SHIFT		4
#define	ID_AA64ISAR1_APA_MASK		(0xf << ID_AA64ISAR1_APA_SHIFT)
#define	ID_AA64ISAR1_APA(x)		((x) & ID_AA64ISAR1_APA_MASK)
#define	 ID_AA64ISAR1_APA_NONE		(0x0 << ID_AA64ISAR1_APA_SHIFT)
#define	 ID_AA64ISAR1_APA_BASE		(0x1 << ID_AA64ISAR1_APA_SHIFT)
#define	 ID_AA64ISAR1_APA_PAC		(0x2 << ID_AA64ISAR1_APA_SHIFT)
#define	ID_AA64ISAR1_API_SHIFT		8
#define	ID_AA64ISAR1_API_MASK		(0xf << ID_AA64ISAR1_API_SHIFT)
#define	ID_AA64ISAR1_API(x)		((x) & ID_AA64ISAR1_API_MASK)
#define	 ID_AA64ISAR1_API_NONE		(0x0 << ID_AA64ISAR1_API_SHIFT)
#define	 ID_AA64ISAR1_API_BASE		(0x1 << ID_AA64ISAR1_API_SHIFT)
#define	 ID_AA64ISAR1_API_PAC		(0x2 << ID_AA64ISAR1_API_SHIFT)
#define	ID_AA64ISAR1_JSCVT_SHIFT	12
#define	ID_AA64ISAR1_JSCVT_MASK		(0xf << ID_AA64ISAR1_JSCVT_SHIFT)
#define	ID_AA64ISAR1_JSCVT(x)		((x) & ID_AA64ISAR1_JSCVT_MASK)
#define	 ID_AA64ISAR1_JSCVT_NONE	(0x0 << ID_AA64ISAR1_JSCVT_SHIFT)
#define	 ID_AA64ISAR1_JSCVT_IMPL	(0x1 << ID_AA64ISAR1_JSCVT_SHIFT)
#define	ID_AA64ISAR1_FCMA_SHIFT		16
#define	ID_AA64ISAR1_FCMA_MASK		(0xf << ID_AA64ISAR1_FCMA_SHIFT)
#define	ID_AA64ISAR1_FCMA(x)		((x) & ID_AA64ISAR1_FCMA_MASK)
#define	 ID_AA64ISAR1_FCMA_NONE		(0x0 << ID_AA64ISAR1_FCMA_SHIFT)
#define	 ID_AA64ISAR1_FCMA_IMPL		(0x1 << ID_AA64ISAR1_FCMA_SHIFT)
#define	ID_AA64ISAR1_LRCPC_SHIFT	20
#define	ID_AA64ISAR1_LRCPC_MASK		(0xf << ID_AA64ISAR1_LRCPC_SHIFT)
#define	ID_AA64ISAR1_LRCPC(x)		((x) & ID_AA64ISAR1_LRCPC_MASK)
#define	 ID_AA64ISAR1_LRCPC_NONE	(0x0 << ID_AA64ISAR1_LRCPC_SHIFT)
#define	 ID_AA64ISAR1_LRCPC_BASE	(0x1 << ID_AA64ISAR1_LRCPC_SHIFT)
#define	 ID_AA64ISAR1_LRCPC_LDAPUR	(0x2 << ID_AA64ISAR1_LRCPC_SHIFT)
#define	ID_AA64ISAR1_GPA_SHIFT		24
#define	ID_AA64ISAR1_GPA_MASK		(0xf << ID_AA64ISAR1_GPA_SHIFT)
#define	ID_AA64ISAR1_GPA(x)		((x) & ID_AA64ISAR1_GPA_MASK)
#define	 ID_AA64ISAR1_GPA_NONE		(0x0 << ID_AA64ISAR1_GPA_SHIFT)
#define	 ID_AA64ISAR1_GPA_IMPL		(0x1 << ID_AA64ISAR1_GPA_SHIFT)
#define	ID_AA64ISAR1_GPI_SHIFT		28
#define	ID_AA64ISAR1_GPI_MASK		(0xf << ID_AA64ISAR1_GPI_SHIFT)
#define	ID_AA64ISAR1_GPI(x)		((x) & ID_AA64ISAR1_GPI_MASK)
#define	 ID_AA64ISAR1_GPI_NONE		(0x0 << ID_AA64ISAR1_GPI_SHIFT)
#define	 ID_AA64ISAR1_GPI_IMPL		(0x1 << ID_AA64ISAR1_GPI_SHIFT)
#define	ID_AA64ISAR1_FRINTTS_SHIFT	32
#define	ID_AA64ISAR1_FRINTTS_MASK	(0xfULL << ID_AA64ISAR1_FRINTTS_SHIFT)
#define	ID_AA64ISAR1_FRINTTS(x)		((x) & ID_AA64ISAR1_FRINTTS_MASK)
#define	 ID_AA64ISAR1_FRINTTS_NONE	(0x0ULL << ID_AA64ISAR1_FRINTTS_SHIFT)
#define	 ID_AA64ISAR1_FRINTTS_IMPL	(0x1ULL << ID_AA64ISAR1_FRINTTS_SHIFT)
#define	ID_AA64ISAR1_SB_SHIFT		36
#define	ID_AA64ISAR1_SB_MASK		(0xfULL << ID_AA64ISAR1_SB_SHIFT)
#define	ID_AA64ISAR1_SB(x)		((x) & ID_AA64ISAR1_SB_MASK)
#define	 ID_AA64ISAR1_SB_NONE		(0x0ULL << ID_AA64ISAR1_SB_SHIFT)
#define	 ID_AA64ISAR1_SB_IMPL		(0x1ULL << ID_AA64ISAR1_SB_SHIFT)
#define	ID_AA64ISAR1_SPECRES_SHIFT	40
#define	ID_AA64ISAR1_SPECRES_MASK	(0xfULL << ID_AA64ISAR1_SPECRES_SHIFT)
#define	ID_AA64ISAR1_SPECRES(x)		((x) & ID_AA64ISAR1_SPECRES_MASK)
#define	 ID_AA64ISAR1_SPECRES_NONE	(0x0ULL << ID_AA64ISAR1_SPECRES_SHIFT)
#define	 ID_AA64ISAR1_SPECRES_IMPL	(0x1ULL << ID_AA64ISAR1_SPECRES_SHIFT)

/* ID_AA64ISAR2_EL1 */
#define	ID_AA64ISAR2_MASK		0x00000000f0000000ULL
#define	ID_AA64ISAR2_CLRBHB_SHIFT	28
#define	ID_AA64ISAR2_CLRBHB_MASK	(0xfULL << ID_AA64ISAR2_CLRBHB_SHIFT)
#define	ID_AA64ISAR2_CLRBHB(x)		((x) & ID_AA64ISAR2_CLRBHB_MASK)
#define	 ID_AA64ISAR2_CLRBHB_NONE	(0x0ULL << ID_AA64ISAR2_CLRBHB_SHIFT)
#define	 ID_AA64ISAR2_CLRBHB_IMPL	(0x1ULL << ID_AA64ISAR2_CLRBHB_SHIFT)

/* ID_AA64MMFR0_EL1 */
#define	ID_AA64MMFR0_MASK		0x00000000ffffffffULL
#define	ID_AA64MMFR0_PA_RANGE_SHIFT	0
#define	ID_AA64MMFR0_PA_RANGE_MASK	(0xf << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	ID_AA64MMFR0_PA_RANGE(x)	((x) & ID_AA64MMFR0_PA_RANGE_MASK)
#define	 ID_AA64MMFR0_PA_RANGE_4G	(0x0 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	 ID_AA64MMFR0_PA_RANGE_64G	(0x1 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	 ID_AA64MMFR0_PA_RANGE_1T	(0x2 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	 ID_AA64MMFR0_PA_RANGE_4T	(0x3 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	 ID_AA64MMFR0_PA_RANGE_16T	(0x4 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	 ID_AA64MMFR0_PA_RANGE_256T	(0x5 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define	ID_AA64MMFR0_ASID_BITS_SHIFT	4
#define	ID_AA64MMFR0_ASID_BITS_MASK	(0xf << ID_AA64MMFR0_ASID_BITS_SHIFT)
#define	ID_AA64MMFR0_ASID_BITS(x)	((x) & ID_AA64MMFR0_ASID_BITS_MASK)
#define	 ID_AA64MMFR0_ASID_BITS_8	(0x0 << ID_AA64MMFR0_ASID_BITS_SHIFT)
#define	 ID_AA64MMFR0_ASID_BITS_16	(0x2 << ID_AA64MMFR0_ASID_BITS_SHIFT)
#define	ID_AA64MMFR0_BIGEND_SHIFT	8
#define	ID_AA64MMFR0_BIGEND_MASK	(0xf << ID_AA64MMFR0_BIGEND_SHIFT)
#define	ID_AA64MMFR0_BIGEND(x)		((x) & ID_AA64MMFR0_BIGEND_MASK)
#define	 ID_AA64MMFR0_BIGEND_FIXED	(0x0 << ID_AA64MMFR0_BIGEND_SHIFT)
#define	 ID_AA64MMFR0_BIGEND_MIXED	(0x1 << ID_AA64MMFR0_BIGEND_SHIFT)
#define	ID_AA64MMFR0_S_NS_MEM_SHIFT	12
#define	ID_AA64MMFR0_S_NS_MEM_MASK	(0xf << ID_AA64MMFR0_S_NS_MEM_SHIFT)
#define	ID_AA64MMFR0_S_NS_MEM(x)	((x) & ID_AA64MMFR0_S_NS_MEM_MASK)
#define	 ID_AA64MMFR0_S_NS_MEM_NONE	(0x0 << ID_AA64MMFR0_S_NS_MEM_SHIFT)
#define	 ID_AA64MMFR0_S_NS_MEM_DISTINCT	(0x1 << ID_AA64MMFR0_S_NS_MEM_SHIFT)
#define	ID_AA64MMFR0_BIGEND_EL0_SHIFT	16
#define	ID_AA64MMFR0_BIGEND_EL0_MASK	(0xf << ID_AA64MMFR0_BIGEND_EL0_SHIFT)
#define	ID_AA64MMFR0_BIGEND_EL0(x)	((x) & ID_AA64MMFR0_BIGEND_EL0_MASK)
#define	 ID_AA64MMFR0_BIGEND_EL0_FIXED	(0x0 << ID_AA64MMFR0_BIGEND_EL0_SHIFT)
#define	 ID_AA64MMFR0_BIGEND_EL0_MIXED	(0x1 << ID_AA64MMFR0_BIGEND_EL0_SHIFT)
#define	ID_AA64MMFR0_TGRAN16_SHIFT	20
#define	ID_AA64MMFR0_TGRAN16_MASK	(0xf << ID_AA64MMFR0_TGRAN16_SHIFT)
#define	ID_AA64MMFR0_TGRAN16(x)		((x) & ID_AA64MMFR0_TGRAN16_MASK)
#define	 ID_AA64MMFR0_TGRAN16_NONE	(0x0 << ID_AA64MMFR0_TGRAN16_SHIFT)
#define	 ID_AA64MMFR0_TGRAN16_IMPL	(0x1 << ID_AA64MMFR0_TGRAN16_SHIFT)
#define	ID_AA64MMFR0_TGRAN64_SHIFT	24
#define	ID_AA64MMFR0_TGRAN64_MASK	(0xf << ID_AA64MMFR0_TGRAN64_SHIFT)
#define	ID_AA64MMFR0_TGRAN64(x)		((x) & ID_AA64MMFR0_TGRAN64_MASK)
#define	 ID_AA64MMFR0_TGRAN64_IMPL	(0x0 << ID_AA64MMFR0_TGRAN64_SHIFT)
#define	 ID_AA64MMFR0_TGRAN64_NONE	(0xf << ID_AA64MMFR0_TGRAN64_SHIFT)
#define	ID_AA64MMFR0_TGRAN4_SHIFT	28
#define	ID_AA64MMFR0_TGRAN4_MASK	(0xf << ID_AA64MMFR0_TGRAN4_SHIFT)
#define	ID_AA64MMFR0_TGRAN4(x)		((x) & ID_AA64MMFR0_TGRAN4_MASK)
#define	 ID_AA64MMFR0_TGRAN4_IMPL	(0x0 << ID_AA64MMFR0_TGRAN4_SHIFT)
#define	 ID_AA64MMFR0_TGRAN4_NONE	(0xf << ID_AA64MMFR0_TGRAN4_SHIFT)

/* ID_AA64MMFR1_EL1 */
#define	ID_AA64MMFR1_MASK		0xf0000000ffffffffULL
#define	ID_AA64MMFR1_HAFDBS_SHIFT	0
#define	ID_AA64MMFR1_HAFDBS_MASK	(0xf << ID_AA64MMFR1_HAFDBS_SHIFT)
#define	ID_AA64MMFR1_HAFDBS(x)		((x) & ID_AA64MMFR1_HAFDBS_MASK)
#define	 ID_AA64MMFR1_HAFDBS_NONE	(0x0 << ID_AA64MMFR1_HAFDBS_SHIFT)
#define	 ID_AA64MMFR1_HAFDBS_AF		(0x1 << ID_AA64MMFR1_HAFDBS_SHIFT)
#define	 ID_AA64MMFR1_HAFDBS_AF_DBS	(0x2 << ID_AA64MMFR1_HAFDBS_SHIFT)
#define	ID_AA64MMFR1_VMIDBITS_SHIFT	4
#define	ID_AA64MMFR1_VMIDBITS_MASK	(0xf << ID_AA64MMFR1_VMIDBITS_SHIFT)
#define	ID_AA64MMFR1_VMIDBITS(x)	((x) & ID_AA64MMFR1_VMIDBITS_MASK)
#define	 ID_AA64MMFR1_VMIDBITS_8	(0x0 << ID_AA64MMFR1_VMIDBITS_SHIFT)
#define	 ID_AA64MMFR1_VMIDBITS_16	(0x2 << ID_AA64MMFR1_VMIDBITS_SHIFT)
#define	ID_AA64MMFR1_VH_SHIFT		8
#define	ID_AA64MMFR1_VH_MASK		(0xf << ID_AA64MMFR1_VH_SHIFT)
#define	ID_AA64MMFR1_VH(x)		((x) & ID_AA64MMFR1_VH_MASK)
#define	 ID_AA64MMFR1_VH_NONE		(0x0 << ID_AA64MMFR1_VH_SHIFT)
#define	 ID_AA64MMFR1_VH_IMPL		(0x1 << ID_AA64MMFR1_VH_SHIFT)
#define	ID_AA64MMFR1_HPDS_SHIFT		12
#define	ID_AA64MMFR1_HPDS_MASK		(0xf << ID_AA64MMFR1_HPDS_SHIFT)
#define	ID_AA64MMFR1_HPDS(x)		((x) & ID_AA64MMFR1_HPDS_MASK)
#define	 ID_AA64MMFR1_HPDS_NONE		(0x0 << ID_AA64MMFR1_HPDS_SHIFT)
#define	 ID_AA64MMFR1_HPDS_IMPL		(0x1 << ID_AA64MMFR1_HPDS_SHIFT)
#define	ID_AA64MMFR1_LO_SHIFT		16
#define	ID_AA64MMFR1_LO_MASK		(0xf << ID_AA64MMFR1_LO_SHIFT)
#define	ID_AA64MMFR1_LO(x)		((x) & ID_AA64MMFR1_LO_MASK)
#define	 ID_AA64MMFR1_LO_NONE		(0x0 << ID_AA64MMFR1_LO_SHIFT)
#define	 ID_AA64MMFR1_LO_IMPL		(0x1 << ID_AA64MMFR1_LO_SHIFT)
#define	ID_AA64MMFR1_PAN_SHIFT		20
#define	ID_AA64MMFR1_PAN_MASK		(0xf << ID_AA64MMFR1_PAN_SHIFT)
#define	ID_AA64MMFR1_PAN(x)		((x) & ID_AA64MMFR1_PAN_MASK)
#define	 ID_AA64MMFR1_PAN_NONE		(0x0 << ID_AA64MMFR1_PAN_SHIFT)
#define	 ID_AA64MMFR1_PAN_IMPL		(0x1 << ID_AA64MMFR1_PAN_SHIFT)
#define	 ID_AA64MMFR1_PAN_ATS1E1	(0x2 << ID_AA64MMFR1_PAN_SHIFT)
#define	 ID_AA64MMFR1_PAN_EPAN		(0x3 << ID_AA64MMFR1_PAN_SHIFT)
#define	ID_AA64MMFR1_SPECSEI_SHIFT	24
#define	ID_AA64MMFR1_SPECSEI_MASK	(0xf << ID_AA64MMFR1_SPECSEI_SHIFT)
#define	ID_AA64MMFR1_SPECSEI(x)		((x) & ID_AA64MMFR1_SPECSEI_MASK)
#define	 ID_AA64MMFR1_SPECSEI_NONE	(0x0 << ID_AA64MMFR1_SPECSEI_SHIFT)
#define	 ID_AA64MMFR1_SPECSEI_IMPL	(0x1 << ID_AA64MMFR1_SPECSEI_SHIFT)
#define	ID_AA64MMFR1_XNX_SHIFT		28
#define	ID_AA64MMFR1_XNX_MASK		(0xf << ID_AA64MMFR1_XNX_SHIFT)
#define	ID_AA64MMFR1_XNX(x)		((x) & ID_AA64MMFR1_XNX_MASK)
#define	 ID_AA64MMFR1_XNX_NONE		(0x0 << ID_AA64MMFR1_XNX_SHIFT)
#define	 ID_AA64MMFR1_XNX_IMPL		(0x1 << ID_AA64MMFR1_XNX_SHIFT)
#define	ID_AA64MMFR1_ECBHB_SHIFT	60
#define	ID_AA64MMFR1_ECBHB_MASK		(0xfULL << ID_AA64MMFR1_ECBHB_SHIFT)
#define	ID_AA64MMFR1_ECBHB(x)		((x) & ID_AA64MMFR1_ECBHB_MASK)
#define	 ID_AA64MMFR1_ECBHB_NONE	(0x0ULL << ID_AA64MMFR1_ECBHB_SHIFT)
#define	 ID_AA64MMFR1_ECBHB_IMPL	(0x1ULL << ID_AA64MMFR1_ECBHB_SHIFT)

/* ID_AA64PFR0_EL1 */
#define	ID_AA64PFR0_MASK		0xff0fffffffffffffULL
#define	ID_AA64PFR0_EL0_SHIFT		0
#define	ID_AA64PFR0_EL0_MASK		(0xf << ID_AA64PFR0_EL0_SHIFT)
#define	ID_AA64PFR0_EL0(x)		((x) & ID_AA64PFR0_EL0_MASK)
#define	 ID_AA64PFR0_EL0_64		(1 << ID_AA64PFR0_EL0_SHIFT)
#define	 ID_AA64PFR0_EL0_64_32		(2 << ID_AA64PFR0_EL0_SHIFT)
#define	ID_AA64PFR0_EL1_SHIFT		4
#define	ID_AA64PFR0_EL1_MASK		(0xf << ID_AA64PFR0_EL1_SHIFT)
#define	ID_AA64PFR0_EL1(x)		((x) & ID_AA64PFR0_EL1_MASK)
#define	 ID_AA64PFR0_EL1_64		(1 << ID_AA64PFR0_EL1_SHIFT)
#define	 ID_AA64PFR0_EL1_64_32		(2 << ID_AA64PFR0_EL1_SHIFT)
#define	ID_AA64PFR0_EL2_SHIFT		8
#define	ID_AA64PFR0_EL2_MASK		(0xf << ID_AA64PFR0_EL2_SHIFT)
#define	ID_AA64PFR0_EL2(x)		((x) & ID_AA64PFR0_EL2_MASK)
#define	 ID_AA64PFR0_EL2_NONE		(0 << ID_AA64PFR0_EL2_SHIFT)
#define	 ID_AA64PFR0_EL2_64		(1 << ID_AA64PFR0_EL2_SHIFT)
#define	 ID_AA64PFR0_EL2_64_32		(2 << ID_AA64PFR0_EL2_SHIFT)
#define	ID_AA64PFR0_EL3_SHIFT		12
#define	ID_AA64PFR0_EL3_MASK		(0xf << ID_AA64PFR0_EL3_SHIFT)
#define	ID_AA64PFR0_EL3(x)		((x) & ID_AA64PFR0_EL3_MASK)
#define	 ID_AA64PFR0_EL3_NONE		(0 << ID_AA64PFR0_EL3_SHIFT)
#define	 ID_AA64PFR0_EL3_64		(1 << ID_AA64PFR0_EL3_SHIFT)
#define	 ID_AA64PFR0_EL3_64_32		(2 << ID_AA64PFR0_EL3_SHIFT)
#define	ID_AA64PFR0_FP_SHIFT		16
#define	ID_AA64PFR0_FP_MASK		(0xf << ID_AA64PFR0_FP_SHIFT)
#define	ID_AA64PFR0_FP(x)		((x) & ID_AA64PFR0_FP_MASK)
#define	 ID_AA64PFR0_FP_IMPL		(0x0 << ID_AA64PFR0_FP_SHIFT)
#define	 ID_AA64PFR0_FP_NONE		(0xf << ID_AA64PFR0_FP_SHIFT)
#define	ID_AA64PFR0_ADV_SIMD_SHIFT	20
#define	ID_AA64PFR0_ADV_SIMD_MASK	(0xf << ID_AA64PFR0_ADV_SIMD_SHIFT)
#define	ID_AA64PFR0_ADV_SIMD(x)		((x) & ID_AA64PFR0_ADV_SIMD_MASK)
#define	 ID_AA64PFR0_ADV_SIMD_IMPL	(0x0 << ID_AA64PFR0_ADV_SIMD_SHIFT)
#define	 ID_AA64PFR0_ADV_SIMD_NONE	(0xf << ID_AA64PFR0_ADV_SIMD_SHIFT)
#define	ID_AA64PFR0_GIC_BITS		0x4 /* Number of bits in GIC field */
#define	ID_AA64PFR0_GIC_SHIFT		24
#define	ID_AA64PFR0_GIC_MASK		(0xf << ID_AA64PFR0_GIC_SHIFT)
#define	ID_AA64PFR0_GIC(x)		((x) & ID_AA64PFR0_GIC_MASK)
#define	 ID_AA64PFR0_GIC_CPUIF_NONE	(0x0 << ID_AA64PFR0_GIC_SHIFT)
#define	 ID_AA64PFR0_GIC_CPUIF_EN	(0x1 << ID_AA64PFR0_GIC_SHIFT)
#define	ID_AA64PFR0_RAS_SHIFT		28
#define	ID_AA64PFR0_RAS_MASK		(0xfULL << ID_AA64PFR0_RAS_SHIFT)
#define	ID_AA64PFR0_RAS(x)		((x) & ID_AA64PFR0_RAS_MASK)
#define	 ID_AA64PFR0_RAS_NONE		(0x0ULL << ID_AA64PFR0_RAS_SHIFT)
#define	 ID_AA64PFR0_RAS_IMPL		(0x1ULL << ID_AA64PFR0_RAS_SHIFT)
#define	 ID_AA64PFR0_RAS_IMPL_V1P1	(0x2ULL << ID_AA64PFR0_RAS_SHIFT)
#define	ID_AA64PFR0_SVE_SHIFT		32
#define	ID_AA64PFR0_SVE_MASK		(0xfULL << ID_AA64PFR0_SVE_SHIFT)
#define	ID_AA64PFR0_SVE(x)		((x) & ID_AA64PFR0_SVE_MASK)
#define	 ID_AA64PFR0_SVE_NONE		(0x0ULL << ID_AA64PFR0_SVE_SHIFT)
#define	 ID_AA64PFR0_SVE_IMPL		(0x1ULL << ID_AA64PFR0_SVE_SHIFT)
#define	ID_AA64PFR0_SEL2_SHIFT		36
#define	ID_AA64PFR0_SEL2_MASK		(0xfULL << ID_AA64PFR0_SEL2_SHIFT)
#define	ID_AA64PFR0_SEL2(x)		((x) & ID_AA64PFR0_SEL2_MASK)
#define	 ID_AA64PFR0_SEL2_NONE		(0x0ULL << ID_AA64PFR0_SEL2_SHIFT)
#define	 ID_AA64PFR0_SEL2_IMPL		(0x1ULL << ID_AA64PFR0_SEL2_SHIFT)
#define	ID_AA64PFR0_MPAM_SHIFT		40
#define	ID_AA64PFR0_MPAM_MASK		(0xfULL << ID_AA64PFR0_MPAM_SHIFT)
#define	ID_AA64PFR0_MPAM(x)		((x) & ID_AA64PFR0_MPAM_MASK)
#define	 ID_AA64PFR0_MPAM_NONE		(0x0ULL << ID_AA64PFR0_MPAM_SHIFT)
#define	 ID_AA64PFR0_MPAM_IMPL		(0x1ULL << ID_AA64PFR0_MPAM_SHIFT)
#define	ID_AA64PFR0_AMU_SHIFT		44
#define	ID_AA64PFR0_AMU_MASK		(0xfULL << ID_AA64PFR0_AMU_SHIFT)
#define	ID_AA64PFR0_AMU(x)		((x) & ID_AA64PFR0_AMU_MASK)
#define	 ID_AA64PFR0_AMU_NONE		(0x0ULL << ID_AA64PFR0_AMU_SHIFT)
#define	 ID_AA64PFR0_AMU_IMPL		(0x1ULL << ID_AA64PFR0_AMU_SHIFT)
#define	ID_AA64PFR0_DIT_SHIFT		48
#define	ID_AA64PFR0_DIT_MASK		(0xfULL << ID_AA64PFR0_DIT_SHIFT)
#define	ID_AA64PFR0_DIT(x)		((x) & ID_AA64PFR0_DIT_MASK)
#define	 ID_AA64PFR0_DIT_UNKNOWN	(0x0ULL << ID_AA64PFR0_DIT_SHIFT)
#define	 ID_AA64PFR0_DIT_IMPL		(0x1ULL << ID_AA64PFR0_DIT_SHIFT)
#define	ID_AA64PFR0_CSV2_SHIFT		56
#define	ID_AA64PFR0_CSV2_MASK		(0xfULL << ID_AA64PFR0_CSV2_SHIFT)
#define	ID_AA64PFR0_CSV2(x)		((x) & ID_AA64PFR0_CSV2_MASK)
#define	 ID_AA64PFR0_CSV2_UNKNOWN	(0x0ULL << ID_AA64PFR0_CSV2_SHIFT)
#define	 ID_AA64PFR0_CSV2_IMPL		(0x1ULL << ID_AA64PFR0_CSV2_SHIFT)
#define	 ID_AA64PFR0_CSV2_SCXT		(0x2ULL << ID_AA64PFR0_CSV2_SHIFT)
#define	 ID_AA64PFR0_CSV2_HCXT		(0x3ULL << ID_AA64PFR0_CSV2_SHIFT)
#define	ID_AA64PFR0_CSV3_SHIFT		60
#define	ID_AA64PFR0_CSV3_MASK		(0xfULL << ID_AA64PFR0_CSV3_SHIFT)
#define	ID_AA64PFR0_CSV3(x)		((x) & ID_AA64PFR0_CSV3_MASK)
#define	 ID_AA64PFR0_CSV3_UNKNOWN	(0x0ULL << ID_AA64PFR0_CSV3_SHIFT)
#define	 ID_AA64PFR0_CSV3_IMPL		(0x1ULL << ID_AA64PFR0_CSV3_SHIFT)

/* ID_AA64PFR1_EL1 */
#define	ID_AA64PFR1_MASK		0x000000000000ffffULL
#define	ID_AA64PFR1_BT_SHIFT		0
#define	ID_AA64PFR1_BT_MASK		(0xf << ID_AA64PFR1_BT_SHIFT)
#define	ID_AA64PFR1_BT(x)		((x) & ID_AA64PFR1_BT_MASK)
#define	 ID_AA64PFR1_BT_NONE		(0 << ID_AA64PFR1_BT_SHIFT)
#define	 ID_AA64PFR1_BT_IMPL		(1 << ID_AA64PFR1_BT_SHIFT)
#define	ID_AA64PFR1_SBSS_SHIFT		4
#define	ID_AA64PFR1_SBSS_MASK		(0xf << ID_AA64PFR1_SBSS_SHIFT)
#define	ID_AA64PFR1_SBSS(x)		((x) & ID_AA64PFR1_SBSS_MASK)
#define	 ID_AA64PFR1_SBSS_NONE		(0 << ID_AA64PFR1_SBSS_SHIFT)
#define	 ID_AA64PFR1_SBSS_PSTATE	(1 << ID_AA64PFR1_SBSS_SHIFT)
#define	 ID_AA64PFR1_SBSS_PSTATE_MSR	(2 << ID_AA64PFR1_SBSS_SHIFT)
#define	ID_AA64PFR1_MTE_SHIFT		8
#define	ID_AA64PFR1_MTE_MASK		(0xf << ID_AA64PFR1_MTE_SHIFT)
#define	ID_AA64PFR1_MTE(x)		((x) & ID_AA64PFR1_MTE_MASK)
#define	 ID_AA64PFR1_MTE_NONE		(0 << ID_AA64PFR1_MTE_SHIFT)
#define	 ID_AA64PFR1_MTE_IMPL		(1 << ID_AA64PFR1_MTE_SHIFT)
#define	ID_AA64PFR1_RAS_FRAC_SHIFT	12
#define	ID_AA64PFR1_RAS_FRAC_MASK	(0xf << ID_AA64PFR1_RAS_FRAC_SHIFT)
#define	ID_AA64PFR1_RAS_FRAC(x)		((x) & ID_AA64PFR1_RAS_FRAC_MASK)
#define	 ID_AA64PFR1_RAS_FRAC_NONE	(0 << ID_AA64PFR1_RAS_FRAC_SHIFT)
#define	 ID_AA64PFR1_RAS_FRAC_IMPL	(1 << ID_AA64PFR1_RAS_FRAC_SHIFT)

/* MAIR_EL1 - Memory Attribute Indirection Register */
#define	MAIR_ATTR_MASK(idx)	(0xff << ((n)* 8))
#define	MAIR_ATTR(attr, idx) ((attr) << ((idx) * 8))
#define	 MAIR_DEVICE_nGnRnE	0x00
#define	 MAIR_NORMAL_NC		0x44
#define	 MAIR_NORMAL_WT		0x88
#define	 MAIR_NORMAL_WB		0xff

/* PAR_EL1 - Physical Address Register */
#define	PAR_F_SHIFT		0
#define	PAR_F			(0x1 << PAR_F_SHIFT)
#define	PAR_SUCCESS(x)		(((x) & PAR_F) == 0)
/* When PAR_F == 0 (success) */
#define	PAR_SH_SHIFT		7
#define	PAR_SH_MASK		(0x3 << PAR_SH_SHIFT)
#define	PAR_NS_SHIFT		9
#define	PAR_NS_MASK		(0x3 << PAR_NS_SHIFT)
#define	PAR_PA_SHIFT		12
#define	PAR_PA_MASK		0x0000fffffffff000
#define	PAR_ATTR_SHIFT		56
#define	PAR_ATTR_MASK		(0xff << PAR_ATTR_SHIFT)
/* When PAR_F == 1 (aborted) */
#define	PAR_FST_SHIFT		1
#define	PAR_FST_MASK		(0x3f << PAR_FST_SHIFT)
#define	PAR_PTW_SHIFT		8
#define	PAR_PTW_MASK		(0x1 << PAR_PTW_SHIFT)
#define	PAR_S_SHIFT		9
#define	PAR_S_MASK		(0x1 << PAR_S_SHIFT)

/* SCTLR_EL1 - System Control Register */
#define	SCTLR_RES0	0xffffffffc8222400	/* Reserved, write 0 */
#define	SCTLR_RES1	0x0000000030d00800	/* Reserved, write 1 */

#define	SCTLR_M		0x0000000000000001
#define	SCTLR_A		0x0000000000000002
#define	SCTLR_C		0x0000000000000004
#define	SCTLR_SA	0x0000000000000008
#define	SCTLR_SA0	0x0000000000000010
#define	SCTLR_CP15BEN	0x0000000000000020
#define	SCTLR_THEE	0x0000000000000040
#define	SCTLR_ITD	0x0000000000000080
#define	SCTLR_SED	0x0000000000000100
#define	SCTLR_UMA	0x0000000000000200
#define	SCTLR_I		0x0000000000001000
#define	SCTLR_EnDB	0x0000000000002000
#define	SCTLR_DZE	0x0000000000004000
#define	SCTLR_UCT	0x0000000000008000
#define	SCTLR_nTWI	0x0000000000010000
#define	SCTLR_nTWE	0x0000000000040000
#define	SCTLR_WXN	0x0000000000080000
#define	SCTLR_SPAN	0x0000000000800000
#define	SCTLR_EOE	0x0000000001000000
#define	SCTLR_EE	0x0000000002000000
#define	SCTLR_UCI	0x0000000004000000
#define	SCTLR_EnDA	0x0000000008000000
#define	SCTLR_EnIB	0x0000000040000000
#define	SCTLR_EnIA	0x0000000080000000

/* SPSR_EL1 */
/*
 * When the exception is taken in AArch64:
 * M[4]   is 0 for AArch64 mode
 * M[3:2] is the exception level
 * M[1]   is unused
 * M[0]   is the SP select:
 *         0: always SP0
 *         1: current ELs SP
 */
#define	PSR_M_EL0t	0x00000000
#define	PSR_M_EL1t	0x00000004
#define	PSR_M_EL1h	0x00000005
#define	PSR_M_EL2t	0x00000008
#define	PSR_M_EL2h	0x00000009
#define	PSR_M_MASK	0x0000001f

#define	PSR_F		0x00000040
#define	PSR_I		0x00000080
#define	PSR_A		0x00000100
#define	PSR_D		0x00000200
#define	PSR_BTYPE	0x00000c00
#define	PSR_SSBS	0x00001000
#define	PSR_IL		0x00100000
#define	PSR_SS		0x00200000
#define	PSR_PAN		0x00400000
#define	PSR_UAO		0x00800000
#define	PSR_DIT		0x01000000
#define	PSR_TCO		0x02000000
#define	PSR_V		0x10000000
#define	PSR_C		0x20000000
#define	PSR_Z		0x40000000
#define	PSR_N		0x80000000

/* TCR_EL1 - Translation Control Register */
#define	TCR_AS		(1UL << 36)

#define	TCR_IPS_SHIFT	32
#define	TCR_IPS_32BIT	(0UL << TCR_IPS_SHIFT)
#define	TCR_IPS_36BIT	(1UL << TCR_IPS_SHIFT)
#define	TCR_IPS_40BIT	(2UL << TCR_IPS_SHIFT)
#define	TCR_IPS_42BIT	(3UL << TCR_IPS_SHIFT)
#define	TCR_IPS_44BIT	(4UL << TCR_IPS_SHIFT)
#define	TCR_IPS_48BIT	(5UL << TCR_IPS_SHIFT)

#define	TCR_TG1_SHIFT	30
#define	TCR_TG1_16K	(1UL << TCR_TG1_SHIFT)
#define	TCR_TG1_4K	(2UL << TCR_TG1_SHIFT)
#define	TCR_TG1_64K	(3UL << TCR_TG1_SHIFT)

#define	TCR_SH1_SHIFT	28
#define	TCR_SH1_IS	(0x3UL << TCR_SH1_SHIFT)
#define	TCR_ORGN1_SHIFT	26
#define	TCR_ORGN1_WBWA	(0x1UL << TCR_ORGN1_SHIFT)
#define	TCR_IRGN1_SHIFT	24
#define	TCR_IRGN1_WBWA	(0x1UL << TCR_IRGN1_SHIFT)

#define	TCR_A1		(1UL << 22)

#define	TCR_TG0_SHIFT	14
#define	TCR_TG0_4K	(0UL << TCR_TG0_SHIFT)
#define	TCR_TG0_64K	(1UL << TCR_TG0_SHIFT)
#define	TCR_TG0_16K	(2UL << TCR_TG0_SHIFT)

#define	TCR_SH0_SHIFT	12
#define	TCR_SH0_IS	(0x3UL << TCR_SH0_SHIFT)
#define	TCR_ORGN0_SHIFT	10
#define	TCR_ORGN0_WBWA	(0x1UL << TCR_ORGN0_SHIFT)
#define	TCR_IRGN0_SHIFT	8
#define	TCR_IRGN0_WBWA	(0x1UL << TCR_IRGN0_SHIFT)

#define	TCR_CACHE_ATTRS	((TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) |\
				(TCR_ORGN0_WBWA | TCR_ORGN1_WBWA))
#define	TCR_SMP_ATTRS	(TCR_SH0_IS | TCR_SH1_IS)

#define	TCR_T1SZ_SHIFT	16
#define	TCR_T0SZ_SHIFT	0
#define	TCR_T1SZ(x)	((x) << TCR_T1SZ_SHIFT)
#define	TCR_T0SZ(x)	((x) << TCR_T0SZ_SHIFT)
#define	TCR_TxSZ(x)	(TCR_T1SZ(x) | TCR_T0SZ(x))

/* Monitor Debug System Control Register */
#define	DBG_MDSCR_SS	(0x1 << 0)
#define	DBG_MDSCR_TDCC	(0x1 << 12)
#define	DBG_MDSCR_KDE	(0x1 << 13)
#define	DBG_MDSCR_MDE	(0x1 << 15)

/* Performance Monitoring Counters */
#define	PMCR_E		(1 << 0) /* Enable all counters */
#define	PMCR_P		(1 << 1) /* Reset all counters */
#define	PMCR_C		(1 << 2) /* Clock counter reset */
#define	PMCR_D		(1 << 3) /* CNTR counts every 64 clk cycles */
#define	PMCR_X		(1 << 4) /* Export to ext. monitoring (ETM) */
#define	PMCR_DP		(1 << 5) /* Disable CCNT if non-invasive debug*/
#define	PMCR_LC		(1 << 6) /* Long cycle count enable */
#define	PMCR_IMP_SHIFT	24 /* Implementer code */
#define	PMCR_IMP_MASK	(0xff << PMCR_IMP_SHIFT)
#define	PMCR_IDCODE_SHIFT	16 /* Identification code */
#define	PMCR_IDCODE_MASK	(0xff << PMCR_IDCODE_SHIFT)
#define	 PMCR_IDCODE_CORTEX_A57	0x01
#define	 PMCR_IDCODE_CORTEX_A72	0x02
#define	 PMCR_IDCODE_CORTEX_A53	0x03
#define	PMCR_N_SHIFT	11       /* Number of counters implemented */
#define	PMCR_N_MASK	(0x1f << PMCR_N_SHIFT)

/* Individual CPUs are probably best IDed by everything but the revision. */
#define	CPU_ID_CPU_MASK		0xfffffff0

/* ARM64 CPUs */
#define	CPU_ID_CORTEX_A53	0x410fd030
#define	CPU_ID_CORTEX_A53_R1	0x411fd030
#define	CPU_ID_CORTEX_A53_MASK	0xff0ffff0
#define	CPU_ID_CORTEX_A57	0x410fd070
#define	CPU_ID_CORTEX_A57_R1	0x411fd070
#define	CPU_ID_CORTEX_A57_MASK	0xff0ffff0
#define	CPU_ID_CORTEX_A72	0x410fd080
#define	CPU_ID_CORTEX_A72_R1	0x411fd080
#define	CPU_ID_CORTEX_A57_MASK	0xff0ffff0

#define I_bit (1 << 7)		/* IRQ disable */
#define F_bit 0			/* FIQ disable - not actually used */

#endif /* !_MACHINE_ARMREG_H_ */




/* $OpenBSD: armreg.h,v 1.29 2023/06/10 19:30:48 kettenis Exp $ */
/*-
 * Copyright (c) 2013, 2014 Andrew Turner
 * Copyright (c) 2015 The FreeBSD Foundation
 * All rights reserved.
 *
 * This software was developed by Andrew Turner under
 * sponsorship from the FreeBSD Foundation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: head/sys/arm64/include/armreg.h 309248 2016-11-28 14:24:07Z andrew $
 */

aarch64 PSTATE and SPSR

(only for) when exception taken from AArch64 state:

SPSR_ELxPSTATENOTE
[63:32]-RESERVED 0
31N
30Z
29C
28V
[27:26]-RESERVED 0
25TCOFEAT_MTE
24DITFEAT_DIT
23UAOFEAT_UAO
22PANFEAT_PAN
21SS
20IL
[19:13]N/ARESERVED 0
12SSBS
[11:10]BTYPE [1:0]FEAT_BTI
9D
8A
7I
6F
5-RESERVED 0
4M [4]
[3:0]M [3:0]

general PSTATE bits NOTE: PSTATE is not a register. Also not all fields are preserved in the SPSR_ELx when an excaption is taken.

NAMEDESC
NZCVALU Condition {Neg, Zero, Carry, oVerflow}
DAIFmask bits {Debug, sError, IRQ, FIQ}
SSSoftware Step
ILillegal execution state
EL(2)exception level
nRWexecution state (0=64, 1=32)
SPstack pointer selector (0=SP_EL0, 1=SP_ELn)

feature PSTATE bits (TODO)

USEFUL RESOURCES

x86 and amd64 instruction reference

PAE paging Entry format

paging entry format

Intel SDM Figure 4-11

PAE paging with 1G PDPTE

+------------+
| PML4 Entry |
+------------+


0       PRESENT
1       R/W  (1 == writable)
2       U/S  (1 == user accessable)
3       PWD  (write-through)
4       PCD  (cache disable)
5       A    (Accessed)
6       IGN
7       RES0
8:10    IGN
11      R   (ign, or restart for HLAT paging)
M-1:12  next level table PA[M:12]
51:M    RES0
62:52   IGN
63      XD  (execute disable (if EFER.NXE=1)) otherwise RES0


+------------+
| PDPT ENtry | (level 3) with 1GiB Page (requires PS=1)
+------------+

0       PRESENT
1       R/W  (1 == writable)
2       U/S  (1 == user accessable)
3       PWD  (write-through)
4       PCD  (cache disable)
5       A    (Accessed)
6       D    (Dirty)
7       PS   (must be 1)*
8       G    (Global, if CR4.PGE=1), otherwise INR
10:9    IGR
11      R   (ign, or restart for HLAT paging)
12      PAT (indirectly determines memory type)
29:13   RES0
M-1:30  PA[M-1:30]
51:M    RES0
52:58   IGN
59:62   Protection key
63      XD  (execute disable (if EFER.NXE=1)) otherwise RES0

Setting up a provisional identical mapping for long mode, using 1G huge page on PDP(PUD).

x86_64 long mode mandates paging. Here we set up a provisional identical mapping for the early booting.

Math
Each PUD entry (on the 3rd level) maps to 1G memory region. We could set up 512 GiB mapping with only one single 3rd level table (i.e. no need for page directory or page table), this is ideal for a early boot provisional mapping.

We need:

  1. one PML4 table (and only 1 single entry pointing to the PUD table), that's 4KiB in size
  2. one PUD table, populated with 512 entries, each pointing to 1G memory region, this is another 4KiB in size.
  3. in total, we need to setup 2 tables and 1 + 512 = 513 entries.

assembly example

[SECTION .text]
[BITS 32]
; skipping other code.
setup_paging:
    ; PML4 (Page Map Level 4 / 1st level)
    mov    eax, pdp
    or     eax, 0xf
    mov    dword [pml4+0], eax
    mov    dword [pml4+4], 0
    ; PDPE flags
    ; start-address bytes bit [30:31] + flags
    mov    eax, 0x0 | 0x87    
    ; start-address bytes bit [32:38]
    mov    ebx, 0
    mov    ecx, 0
    fill_tables2:
    ; fill one single PDP table, with 1G pages, 
    ; 512 PDPE maps to 512 GB
    cmp    ecx, MAX_MEM
    je     fill_tables2_done
    ; low bytes
    mov    dword [pdp + 8*ecx + 0], eax
    ; high bytes
    mov    dword [pdp + 8*ecx + 4], ebx
    ; 1G per entry
    add    eax, 0x40000000
    ; increment bit[32:38] when eax overflows
    adc    ebx, 0
    inc    ecx
    ja     fill_tables2
    fill_tables2_done:
    ; set base pointer to PML4
    mov    eax, pml4
    mov    cr3, eax
    ret

[SECTION .pagetables]
[GLOBAL pml4]
[GLOBAL pdp]

pml4:
    resb   4096
    alignb 4096

pdp:
    resb   4096
    alignb 4096

Note that, each entry is 64bit, but when we are setting up the page tables, we are not in long mode yet, meaning that only 32bit registers/instructions are available. See how the code use both eax and ebx to keep the address with the carry flag (adc).

Also make sure to link and align the pagetables section properly. e.g.

/* global page table for 64-bit long mode */
.global_pagetable ALIGN(4096) (NOLOAD) :
{
    *(".global_pagetable")
}
https://wiki.osdev.org/Exceptions
https://wiki.osdev.org/Interrupts#General_IBM-PC_Compatible_Interrupt_Information

------------------------------------------------------
VectorNr.   Name                Type        ErrorCode
------------------------------------------------------
0x0     Division Error          Fault       -
0x1     Debug                   Fault/Trap  -
0x2     NMI                     Interrupt   -
0x3     Breakpoint              Trap        -
0x4     Overflow                Trap        -
0x5     Bound Range Exceeded    Fault       -
0x6     Invalid Opcode          Fault       -
0x7     Device Not Available    Fault       -
0x8     Double Fault            Abort       Yes (zero)
0x9     Legacy (CSO)            Fault       -
0xA     Invalid TSS             Fault       Yes
0xB     Segment Not Present     Fault       Yes
0xC     Stack Segment Fault     Fault       Yes
0xD     GPF                     Fault       Yes
0xE     Page Fault              Fault       Yes
0xF     RESERVED                -           -
0x10    x87 FP Exception        Fault       -
0x11    Alignment Check         Fault       Yes
0x12    Machine Check           Abort       -
0x13    SIMD FP Exception       Fault       -
0x14    Virt. Exception         Fault       -
0x15    Control Protection      Fault       Yes
0x16    RESERVED                -           -
0x17    RESERVED                -           -
0x18    RESERVED                -           -
0x19    RESERVED                -           -
0x1A    RESERVED                -           -
0x1B    RESERVED                -           -
0x1C    Hpervisor Injection     Fault       -
0x1D    VMM Communication       Fault       Yes
0x1E    Security Exception      Fault       Yes
0x1F    RESERVED
------------------------------------------------------
PIC1 (master) remapped from vector offset 0x20
------------------------------------------------------
0x20	PIT (Timer)
0x21    Keyboard
0x22    PIC internal (never raised)
0x23    COMM2 (if enabled)
0x24    COMM1 (if enabled)
0x25    LPT2 (if enabled)
0x26    Floppy Disk
0x27    LPT1 / Unreliable "spurious" interrupt (usually)
------------------------------------------------------
PIC2 (slave) remapped from vector offset 0x28
------------------------------------------------------
0x28    CMOS realtime-clock (if enabled)
0x29    Free for peripherals / SCSI / NIC
0x2A    Free for peripherals / SCSI / NIC
0x2B    Free for peripherals / SCSI / NIC
0x2C    PS2 Mouse
0x2D    FPU / Coprocessor / Inter-processor
0x2E    Primary ATA Hard Disk
0x2F    Secondary ATA Hard Disk
x86_64 (SysV) calling convention
https://uclibc.org/docs/psABI-x86_64.pdf

not including vector and FP registers

                        register usage
-----------------------------------------------------------------------
register        Usage                           preserved across calls
-----------------------------------------------------------------------
rax             1th return value                No
                temp (scratch) reg
-----------------------------------------------------------------------
rbx             callee saved                    Yes
-----------------------------------------------------------------------
rdi             fn parameter 1                  No
-----------------------------------------------------------------------
rsi             fn parameter 2                  No
-----------------------------------------------------------------------
rdx             fn parameter 3                  No
-----------------------------------------------------------------------
rcx             fn parameter 4                  No
-----------------------------------------------------------------------
r8              fn parameter 5                  No
-----------------------------------------------------------------------
r9              fn parameter 6                  No
-----------------------------------------------------------------------
r10             function static chain ptr       No
                temp (scratch) reg
-----------------------------------------------------------------------
r11             temp (scratch) reg              No
-----------------------------------------------------------------------
r12~r14         callee saved                    Yes
-----------------------------------------------------------------------
r15             callee saved                    Yes
                optionally GOT base pointer
-----------------------------------------------------------------------
rsp             stack pointer                   Yes
-----------------------------------------------------------------------
rbp             callee saved
                optionally frame pointer        Yes
-----------------------------------------------------------------------


                parameter passing (integer class only)
-----------------------------------------------------------------------
the first 6 parameters (left to right) are passed though register
rdi, rsi, rdx, rcx, r8, r9

further paramters are pushed to stack (right-to-left order)
                                       ^^^^^^^^^^^^^
-----------------------------------------------------------------------

TODO returning value

USEFUL RESOURCES

LKML

syscall table (+multi-arch)

Stack smashing debugging guide

Kernel module basic example: (from Linux Kernel Driver). Code from Douglas Su

hello_world.c

#include <linux/module.h>

static int __init m_init(void)
{
	printk(KERN_ALERT "Hello, world!\n");
	return 0;
}

static void __exit m_exit(void)
{
	printk(KERN_ALERT "Bye, world!\n");
}

module_init(m_init);
module_exit(m_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Douglas Su");
MODULE_DESCRIPTION("Hello World program");

Makefile

ifneq ($(KERNELRELEASE),)

# In kbuild context
module-objs := hello_world.o
obj-m := hello_world.o

CFLAGS_hello_world.o := -DDEBUG

else
# In normal make context
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

.PHONY: modules
modules:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

.PHONY: clean
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

endif

Notes on the Makefile

  • To build a module from multiple source (/objects):

    obj-m := module.o
    module-objs := file1.o file2.o
    
  • the module code can't build on its own. It must be built in the kernel tree (where a configured makefile can be found) e.g.

    /lib/modules/6.6.20-1-lts/build
    

    or

    /usr/src/linux-lts
    
  • the module Makefile idiom

    # If KERNELRELEASE is defined, we've been invoked from the
    # kernel build system and can use its language.
    ifneq ($(KERNELRELEASE),)
        obj-m := hello.o
    # Otherwise we were called directly from the command
    # line; invoke the kernel build system.
    else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)
    default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    endif
    

Quick Reference (LDD)

insmod
modprobe
rmmod
    User-space utilities that load modules into the running kernels and remove
    them.

#include <linux/init.h>
module_init(init_function);
module_exit(cleanup_function);
    Macros that designate a module’s initialization and cleanup functions.
__init
__initdata
__exit
__exitdata
    Markers for functions (__init and __exit) and data (__initdata and __exitdata)
    that are only used at module initialization or cleanup time. Items marked for ini-
    tialization may be discarded once initialization completes; the exit items may be
    discarded if module unloading has not been configured into the kernel. These
    markers work by causing the relevant objects to be placed in a special ELF sec-
    tion in the executable file.

#include <linux/sched.h>
    One of the most important header files. This file contains definitions of much of
    the kernel API used by the driver, including functions for sleeping and numer-
    ous variable declarations.
struct task_struct *current;
    The current process.
current->pid
current->comm
    The process ID and command name for the current process.

obj-m
    A makefile symbol used by the kernel build system to determine which modules
    should be built in the current directory.

/sys/module
/proc/modules
    /sys/module is a sysfs directory hierarchy containing information on currently-
    loaded modules. /proc/modules is the older, single-file version of that informa-
    tion. Entries contain the module name, the amount of memory each module
    occupies, and the usage count. Extra strings are appended to each line to specify
    flags that are currently active for the module.

vermagic.o
    An object file from the kernel source directory that describes the environment a
    module was built for.

#include <linux/module.h>
    Required header. It must be included by a module source.

#include <linux/version.h>
    A header file containing information on the version of the kernel being built.

LINUX_VERSION_CODE
    Integer macro, useful to #ifdef version dependencies.

EXPORT_SYMBOL (symbol);
EXPORT_SYMBOL_GPL (symbol);
    Macro used to export a symbol to the kernel. The second form exports without
    using versioning information, and the third limits the export to GPL-licensed
    modules.

MODULE_AUTHOR(author);
MODULE_DESCRIPTION(description);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
    Place documentation on the module in the object file.

module_init(init_function);
module_exit(exit_function);
    Macros that declare a module’s initialization and cleanup functions.
#include <linux/moduleparam.h>
module_param(variable, type, perm);
    Macro that creates a module parameter that can be adjusted by the user when
    the module is loaded (or at boot time for built-in code). The type can be one of
    bool, charp, int, invbool, long, short, ushort, uint, ulong, or intarray.

#include <linux/kernel.h>
int printk(const char * fmt, ...);
    The analogue of printf for kernel code.

man 2 syscall :

Arch/ABI    Instruction           System  Ret  Ret  Error    Notes 
                                  call #  val  val2
───────────────────────────────────────────────────────────────────
alpha       callsys               v0      v0   a4   a3       1, 6
arc         trap0                 r8      r0   -    -
arm/OABI    swi NR                -       r0   -    -        2
arm/EABI    swi 0x0               r7      r0   r1   -
arm64       svc #0                w8      x0   x1   -
blackfin    excpt 0x0             P0      R0   -    -
i386        int $0x80             eax     eax  edx  -
ia64        break 0x100000        r15     r8   r9   r10      1, 6
loongarch   syscall 0             a7      a0   -    -
m68k        trap #0               d0      d0   -    -
microblaze  brki r14,8            r12     r3   -    -
mips        syscall               v0      v0   v1   a3       1, 6
nios2       trap                  r2      r2   -    r7
parisc      ble 0x100(%sr2, %r0)  r20     r28  -    -
powerpc     sc                    r0      r3   -    r0       1
powerpc64   sc                    r0      r3   -    cr0.SO   1
riscv       ecall                 a7      a0   a1   -
s390        svc 0                 r1      r2   r3   -        3
s390x       svc 0                 r1      r2   r3   -        3
superh      trapa #31             r3      r0   r1   -        4, 6
sparc/32    t 0x10                g1      o0   o1   psr/csr  1, 6
sparc/64    t 0x6d                g1      o0   o1   psr/csr  1, 6
tile        swint1                R10     R00  -    R01      1
x86-64      syscall               rax     rax  rdx  -        5
x32         syscall               rax     rax  rdx  -        5
xtensa      syscall               a2      a2   -    -

Virtual Memory Areas (VMAs)

view memory maps:

$ cat /proc/<PID>/maps

the results correspond partiallty to area's linux/mm_types.h::vm_area_struct:

-------------------------------------------------------------
start~end   perm    offset      major:minor     inode   image
-------------------------------------------------------------
start~end:  start/end of the memory area
perm:       bit mask for area R/W/X permission; p for private and s for shared
offset:     offset into mapped file.
inode:      inode number of mapped file. (0 for anoymous mappings)
image:      file name of the mapped file. (empty for anoymous mappings)

view IO memory maps:

$ cat /proc/iomem

process memory map:

Each process has its mm_struct that contains its list of VMAs, pagetabkes, sync primitives, etc..

manually dumping memory w. GDB

  1. identify memory region start and end from maps
  2. connect gdb to running process with pid
    $ sudo gdb --pid <PID>
    
  3. dump memory in gdb
    $ dump memory <PATH-TO-DUMP-FILE> <START_ADDR> <END_ADDR>
    
  4. the dump can be viewed with e.g. hexdump

get_user_pages

Understanding the Linux Kernel, Chapter 11 Signals, Daniel P. Bovet & Marco Cesati, 3rd Edition, O'Reilly

man 7 signal (Linux manual page)

Standard signals
   "P1990" : POSIX.1-1990 standard
   "P2001" : the signal was added in SUSv2 and POSIX.1-2001.
    
    NOTE: Numbers for X86/ARM and most others; 
          For {Alpha/SPARC, MIPS, PARISC} they would be different)
   ────────────────────────────────────────────────────────────────────────
   Signal      Standard   Action   Comment
   ────────────────────────────────────────────────────────────────────────
1  SIGHUP       P1990      Term    Hangup detected on controlling terminal
                                   or death of controlling process
2  SIGINT       P1990      Term    Interrupt from keyboard
3  SIGQUIT      P1990      Core    Quit from keyboard
4  SIGILL       P1990      Core    Illegal Instruction
5  SIGTRAP      P2001      Core    Trace/breakpoint trap
6  SIGABRT      P1990      Core    Abort signal from abort(3)
6  SIGIOT         -        Core    IOT trap. A synonym for SIGABRT
7  SIGBUS       P2001      Core    Bus error (bad memory access)
8  SIGFPE       P1990      Core    Floating-point exception
9  SIGKILL      P1990      Term    Kill signal
10 SIGUSR1      P1990      Term    User-defined signal 1
11 SIGSEGV      P1990      Core    Invalid memory reference
12 SIGUSR2      P1990      Term    User-defined signal 2
13 SIGPIPE      P1990      Term    Broken pipe: write to pipe with no
14 SIGALRM      P1990      Term    Timer signal from alarm(2)
15 SIGTERM      P1990      Term    Termination signal
16 SIGSTKFLT      -        Term    Stack fault on coprocessor (unused)
16 UNUSED       -----      ----    (in some cases..)
17 SIGCHLD      P1990      Ign     Child stopped or terminated
   SIGCLD         -        Ign     A synonym for SIGCHLD
18 SIGCONT      P1990      Cont    Continue if stopped
19 SIGSTOP      P1990      Stop    Stop process
20 SIGTSTP      P1990      Stop    Stop typed at terminal
21 SIGTTIN      P1990      Stop    Terminal input for background process
22 SIGTTOU      P1990      Stop    Terminal output for background process
23 SIGURG       P2001      Ign     Urgent condition on socket (4.2BSD)
24 SIGXCPU      P2001      Core    CPU time limit exceeded (4.2BSD);
25 SIGXFSZ      P2001      Core    File size limit exceeded (4.2BSD);
                                   see setrlimit(2)
26 SIGVTALRM    P2001      Term    Virtual alarm clock (4.2BSD)
27 SIGPROF      P2001      Term    Profiling timer expired
28 SIGWINCH       -        Ign     Window resize signal (4.3BSD, Sun)
29 SIGIO          -        Term    I/O now possible (4.2BSD)
29 SIGPOLL      P2001      Term    Pollable event (Sys V);
                                   synonym for SIGIO
30 SIGPWR         -        Term    Power failure (System V)
30 SIGINFO        -                A synonym for SIGPWR
31 SIGSYS       P2001      Core    Bad system call (SVr4);
                                   see also seccomp(2)
   SIGUNUSED      -        Core    Synonymous with SIGSYS
-  SIGEMT         -        Term    Emulator trap
   SIGLOST        -        Term    File lock lost (unused)

   ────────────────────────────────────────────────────────────────────────

   The signals SIGKILL and SIGSTOP cannot be caught, blocked, or
   ignored.

   Up to and including Linux 2.2, the default behavior for SIGSYS,
   SIGXCPU, SIGXFSZ, and (on architectures other than SPARC and
   MIPS) SIGBUS was to terminate the process (without a core dump).
   (On some other UNIX systems the default action for SIGXCPU and
   SIGXFSZ is to terminate the process without a core dump.)  Linux
   2.4 conforms to the POSIX.1-2001 requirements for these signals,
   terminating the process with a core dump.

   SIGEMT is not specified in POSIX.1-2001, but nevertheless appears
   on most other UNIX systems, where its default action is typically
   to terminate the process with a core dump.

   SIGPWR (which is not specified in POSIX.1-2001) is typically
   ignored by default on those other UNIX systems where it appears.

   SIGIO (which is not specified in POSIX.1-2001) is ignored by
   default on several other UNIX systems.

POSIX Errno

from /include/linux/errno.h

NoERRDescNote
1EPERMOperation not permitted
2ENOENTNo such file or directory
3ESRCHNo such process
4EINTRInterrupted system call
5EIOInput/output error
6ENXIONo such device or address
7E2BIGArgument list too long
8ENOEXECExec format error
9EBADFBad file descriptor
10ECHILDNo child processes
11EAGAINResource temporarily unavailable
12ENOMEMCannot allocate memory
13EACCESPermission denied
14EFAULTBad address
15ENOTBLKBlock device required
16EBUSYDevice or resource busy
17EEXISTFile exists
18EXDEVInvalid cross-device link
19ENODEVNo such device
20ENOTDIRNot a directory
21EISDIRIs a directory
22EINVALInvalid argument
23ENFILEToo many open files in system
24EMFILEToo many open files
25ENOTTYInappropriate ioctl for device
26ETXTBSYText file busy
27EFBIGFile too large
28ENOSPCNo space left on device
29ESPIPEIllegal seek
30EROFSRead-only file system
31EMLINKToo many links
32EPIPEBroken pipe
33EDOMNumerical argument out of domain
34ERANGENumerical result out of range
35EDEADLKResource deadlock avoided
36ENAMETOOLONGFile name too long
37ENOLCKNo locks available
38ENOSYSFunction not implemented
39ENOTEMPTYDirectory not empty
40ELOOPToo many levels of symbolic links
41EWOULDBLOCKOperation would blockNon POSIX
42ENOMSGNo message of desired type
43EIDRMIdentifier removed
44ECHRNGChannel number out of range
45EL2NSYNCLevel 2 not synchronized
46EL3HLTLevel 3 halted
47EL3RSTLevel 3 reset
48ELNRNGLink number out of range
49EUNATCHProtocol driver not attached
50ENOCSINo CSI structure available
51EL2HLTLevel 2 halted
52EBADEInvalid exchange
53EBADRInvalid request descriptor
54EXFULLExchange full
55ENOANONo anode
56EBADRQCInvalid request code
57EBADSLTInvalid slot
58EDEADLOCKFile locking deadlock errorNon POSIX
59EBFONTBad font file format
60ENOSTRDevice not a stream
61ENODATANo data available
62ETIMETimer expired
63ENOSROut of streams resources
64ENONETMachine is not on the network
65ENOPKGPackage not installed
66EREMOTEObject is remote
67ENOLINKLink has been severed
68EADVAdvertise error
69ESRMNTSrmount error
70ECOMMCommunication error on send
71EPROTOProtocol error
72EMULTIHOPMultihop attempted
73EDOTDOTRFS specific error
74EBADMSGBad message
75EOVERFLOWValue too large for defined data type
76ENOTUNIQName not unique on network
77EBADFDFile descriptor in bad state
78EREMCHGRemote address changed
79ELIBACCCan not access a needed shared library
80ELIBBADAccessing a corrupted shared library
81ELIBSCN.lib section in a.out corrupted
82ELIBMAXAttempting to link in too many shared libraries
83ELIBEXECCannot exec a shared library directly
84EILSEQInvalid or incomplete multibyte or wide character
85ERESTARTInterrupted system call should be restarted
86ESTRPIPEStreams pipe error
87EUSERSToo many users
88ENOTSOCKSocket operation on non-socket
89EDESTADDRREQDestination address required
90EMSGSIZEMessage too long
91EPROTOTYPEProtocol wrong type for socket
92ENOPROTOOPTProtocol not available
93EPROTONOSUPPORTProtocol not supported
94ESOCKTNOSUPPORTSocket type not supported
95EOPNOTSUPPOperation not supported
96EPFNOSUPPORTProtocol family not supported
97EAFNOSUPPORTAddress family not supported by protocol
98EADDRINUSEAddress already in use
99EADDRNOTAVAILCannot assign requested address
100ENETDOWNNetwork is down
101ENETUNREACHNetwork is unreachable
102ENETRESETNetwork dropped connection on reset
103ECONNABORTEDSoftware caused connection abort
104ECONNRESETConnection reset by peer
105ENOBUFSNo buffer space available
106EISCONNTransport endpoint is already connected
107ENOTCONNTransport endpoint is not connected
108ESHUTDOWNCannot send after transport endpoint shutdown
109ETOOMANYREFSToo many references: cannot splice
110ETIMEDOUTConnection timed out
111ECONNREFUSEDConnection refused
112EHOSTDOWNHost is down
113EHOSTUNREACHNo route to host
114EALREADYOperation already in progress
115EINPROGRESSOperation now in progress
116ESTALEStale file handle
117EUCLEANStructure needs cleaning
118ENOTNAMNot a XENIX named type file
119ENAVAILNo XENIX semaphores available
120EISNAMIs a named type file
121EREMOTEIORemote I/O error
122EDQUOTDisk quota exceeded
123ENOMEDIUMNo medium found
124EMEDIUMTYPEWrong medium type
125ECANCELEDOperation canceled
126ENOKEYRequired key not available
127EKEYEXPIREDKey has expired
128EKEYREVOKEDKey has been revoked
129EKEYREJECTEDKey was rejected by service
130EOWNERDEADOwner died
131ENOTRECOVERABLEState not recoverable
135ERFKILLOperation not possible due to RF-kill
133EHWPOISONMemory page has hardware error

USEFUL RESOURCES

KVM APIs

KVM MMIO implementation

USEFUL RESOURCES

rustlings (tutorials and exercises)

rust programming language (official "the Book")

Crust of Rust (advanced) by Jon Gjengset

In this series we seek to understand intermediate Rust concepts by diving into real examples and working code, often by re-implementing functionality from the standard library.

the rustonomicon (unsafe rust)

cve-rs (unsafe rust)

(WIP)

https://doc.rust-lang.org/std/fmt/

https://doc.rust-lang.org/alloc/

https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/the-stack-and-the-heap.html

crate ::alloc::

  • Provides: smart pointer and heap management
  • use alloc::* with #![no_std]

Pointers

Box the smart pointer type (to objects in the heap):

  • there can only be one owner of Box
  • Owner can decide to mutate the content.
  • Restrive inherited mutability

Rc the reference counted pointer

  • reference counter is NOT THREAD SAFE, is meant for intra-thread sharing.
  • Rc wraps type T, only allows access to &T
  • Often paired with Cell or RefCell

Arc the atomic reference counted pointer

  • threadsafe equivalent of Rc type

Heap interfaces

alloc::alloc Memory allocation APIs

#![allow(unused)]
fn main() {
// trait GlobalAlloc
// Register memory allocator as std's default.

#[global_allocator]
pub static GLOBAL_ALLOCATOR: MyAllocator = MyAllocator::New();

impl GlobalAlloc for MyAllocator {
    // Required methods
    unsafe fn alloc(&self, layout: Layout) -> *mut u8;
    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);

    // Provided methods
    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { ... }
    unsafe fn realloc(
        &self,
        ptr: *mut u8,
        layout: Layout,
        new_size: usize
    ) -> *mut u8 { ... }
}
}

Enum into/from primitive types : with num_enum

[dependencies.num_enum]
version = "0.7.2"
default-features = false # to disable std feature
#![allow(unused)]
fn main() {
use num_enum::{IntoPrimitive, TryFromPrimitive};
#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq)]
#[repr(u8)]
enum Status {
	OUTB = 0x01,
	INPB = 0x02,
	AUXB = 0x20, // this may be wrong here.
}

// ...

if let Ok(s) = Status::try_from(var_uint8) {
    // deal with s::Status
} else {
    // deal with conversion error
}
```



### bitflags

https://docs.rs/bitflags/latest/bitflags/  
https://docs.rs/bitflags/latest/bitflags/trait.Flags.html  

**Cautions**  

- **Flags with no bits set should be avoided!!!*** Interact strangely with Flags::
contains and Flags::intersects. A zero-bit flag is always contained but never
intersected. The names of zero-bit flags are never formatted.

- **Flags that set multiple bits should be avoided unless each bit is also in a
single-bit flag**


**Usage**  

Cargo.toml
```
[dependencies.bitflags]
version = "2.4.2"
```

```rust
// basic
use bitflags::bitflags;

bitflags! {
    #[repr(transparent)]
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    pub struct Flags: u32 {
        const A = 0b00000001;
        const B = 0b00000010;
        const C = 0b00000100;
        
        // specify ALL bits as known bits.
        // use this for externally defined flags
        const _ = !0;
    }
}

// with custom methods:
impl Flags {
    pub fn as_u64(&self) -> u64 {
        self.bits() as u64
    }
}

// using:
let ab = Flags::A | Flags::B;   // union
let a  = ab & Flags::A;         // intersection
let b  = ab - Flags::A;         // difference
let c  = !ab;                   // complement

```

Derives: 
- Debug, Clone, Copy, PartialEq, Eq, Hash ...


**Terminology**  

```
bitflags! {
    struct FlagsType: u8 {
            |         |_ Bits type
            |
            +------- Flags type

        const A = 1;
              |____ Flag
    }
}

let flag = FlagsType::A;
    |___ Flags value
```


**Known and unknown bits**  
Defined bits are 'known bits', otherwise 'unknown bits'. Operators may **unset**
any unknown bits they encounter.

```rust
bitflags! {
    struct Flags: u8 {
        const A = 1;
        const B = 1 << 1;
        const C = 1 << 2;
    }
}

// known bits:      0b0000_0111
// unknown bits:    0b1111_1000
```



}

https://google.github.io/comprehensive-rust/
https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer

TODO :

  • automatic dereference
  • concurrency
  • smart pointer

Cheatsheet

&T      &mut T      Type: shared / mutable reference to type T
&       &mut        Operator: make a (mutable) reference value
*                   Operator: dereferences
*const T            Raw pointer to immutable T
*mut T              Raw pointer to mutable T

Reference

#![allow(unused)]
fn main() {
/// reference provides way to access another value without takine responsibility
/// for the value aka. borrowing. Shared references are read-only and the
/// referenced data cannot change.
fn shared_references() {
    let a = 'A';
    let b = 'B';
    let mut r: &char = &a;
    println!("r: {}", *r);
    r = &b;
    // a mutable reference be changed to point to other data
    // but the refrenced data itself cannot change in this case.
    // DIFFERENT than C++ !!
    // shared reference does NOT allow modifying the value it refers to,
    // EVEN IF the value is mutable
    println!("r: {}", *r);
    
    // auto dereferences: use *r or r are the same.
    println!("r: {}", r);
}

/// exclusive aka mutable references, allow changing the value they refer to.
/// they have type &mut T
/// differentiate the two:
///     let mut x_coord: &i32
///     let mut x_coord: &mut i32
fn exclusive_references() {
    // &mut T   a exclusive (mutable) reference to type T
    // NO other (shared or exclusive) reference can exist at the same time
    // the referenced value cannot be accessed while the exclusive reference
    // exists
    let mut point = (1, 2);
    let x_coord = &mut point.0;
    *x_coord = 20;
    // point.0 = 0;         // this is illegal while x_coord is alive
    println!("point: {point:?}");
}

}

Smart Pointers

TODO finish this

Raw Pointers

#![allow(unused)]
fn main() {
fn raw_pointer() {
    let mut num:i32 = 5;
    // declaring raw pointers is safe.
    let ptr1 = &mut num as *mut i32;
    let ptr2 = &mut num as *mut i32; // both are valid pointer to 
    // dereferencing raw pointers is unsafe
    unsafe {
        *ptr1 += 1;
        *ptr2 += 1;
    }
    println!("{}", num); // 7

    let num:i32 = 5;
    // illegal because num is not mutable
    let ptr3 = &mut num as *mut i32;
    // illegal because the different type
    let ptr3 = &num as *const u32;
    // "legal" cast with indirection
    let ptr = &(r as u32) as *const u32;
    // casting and reading is legal
    let ptr_mut = ptr as *mut u32;
    // but dereferencing is illega even in unsafe
    // TODO learn UnsafeCell
    unsafe{
        println!("{}", *ptr_mut);
        *ptr_mut ++;
        println!("{}", *ptr_mut);
    }
    // cast raw value into raw pointer:
    let addr:usize = 0xffff40;
    let wtf = unsafe{*(addr as *const u64)};
    println!("{}", wtf);    // segfault
    // TODO I think it's hackable to cast an address to usize,
    // then cast it to whatever you want. But it turns out that
    // &T as usize is illegal... are there other hacks?

}
}

https://doc.rust-lang.org/book/ch05-01-defining-structs.html

// Define

struct User {
    field1: <type>,
    field2: <type>,
    // ...
}

// Use:

fn main() {
    let user1 = User {field1: value1, 
                field2: value2,
                // ...
                }
}

// init fn
fn build_user(f1: <type>, f2: <type>, ...) -> User {
    User {
        field1: f1,
        field2: f2,
        // ...
    }
}

// Field Init shorthand: field names and parameter names are exactly the same

fn build_user(fleld1: <type>, fleld2: <type>, ...) -> User {
    User { field1, field2, ...}
}


// create instance from struct update (from another instance)

fn main() {
    // --snip--

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

methods

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

auto dereferencing
Rust doesn’t have an equivalent to the -> operator; instead, Rust has a feature called automatic referencing and dereferencing. Calling methods is one of the few places in Rust that has this behavior.

Here’s how it works: when you call a method with object.something(), Rust automatically adds in &, &mut, or * so object matches the signature of the method. In other words, the following are the same:

p1.distance(&p2);
(&p1).distance(&p2);

Option and Result

Takeaways from ...

code snippets from Logan Smith:
https://www.youtube.com/watch?v=s5S2Ed5T-dc

enum Result<T, E> {
    Ok(T),
    Err(E)
}

enum Option<T> {
    Some(T),
    None
}
  • Result is a generalization of Option.
  • For Result there is a custome Type E if the value is not valid. For Option there is only one represented by None (i.e. there is only one obvious reason that this function could fail)
                result.ok()
                -------------------------> 
Result<T, E>                                Option<T>
                <-------------------------
                opt.ok_or(e)
                opt.ok_or_else(|| f(x))

Operand?

match operand {
    Ok(x) => x,
    Err(e) => return Err(From::from(e)),
}

example:

#![allow(unused)]
fn main() {
struct W(String, String);

fn fallible(_: u8) -> Result<String, E> {
    todo!();
}

impl W {
    fn new(x: u8, y:u8) -> Result<Self, E> {
        // short circuit the function and returns the error
        // if either fallible() fails
        let x = fallible(x)?;
        let y = fallible(y)?;
        Ok(Self(x, y))
    }
    
    // does the same thing
    fn new_v2(x: u8, y:u8) -> Result<Self, E> {
        Ok(Self(fallible(x)?, fallible(y)?))
    }
}

// general:
struct W(Vec<String>);

impl W {
    fn new(v:&[u8]) -> Result<Self, E> {
        let v = v.iter()
                .map( |&x| fallible(x))
                .collect::<Result<Vec<_>, _>>();
        Ok(Self(v?))
    }
}

}

Example 2:

#![allow(unused)]

fn main() {
#[derive(Debug)]
struct Node { /**/ }

#[derive(Debug)]
enum GrandparentError{
    NoParent,
    NoGrandparent
}

// the derive_more::From allows to convert Either GrandparentError
// or IOError into LogGpError
// optionally use thiserror::Error
#[derive(Debug, derive_more::From)]
enum LogGpError {
    GrandparentError(GE),
    IOError(io::Error),
}

impl Node {
    fn parent(&self) -> Option<&Node> {
        todo!();
    }

    fn grandparent(n: &Node) -> Result<&Node, GrandparentError> {
        Ok(
            n.parent().ok_or(GrandparentError::NoParent)?
             .parent().ok_or(GrandparentError::NoGrandparent)?
        )
    }

    fn log_gp(n: &Node) -> Result<(), LogGpError> {
        let g = grandparent(n)?;    // may throw GrandparentError
        fs::write(/**/)?;           // may throw IOError
    }

    // anyhow::Result - dynamically works with any error type...
    // (with a cost ... with its own vtable)
    fn log_gp(n: &Node) -> anyhow::Result<()> {
        let g = grandparent(n)?;    // may throw GrandparentError
        fs::write(/**/)?;           // may throw IOError
    }
}
}

Infallible

#![allow(unused)]
fn main() {
// e.g.
enum Result<bool, Infallible> {
    Ok(bool),        // 2 possible values
    Err(Infallible), // ZERO possible value
}

// e.g.
impl FromStr for Wrapper {
    type Err = Infallible;
    // CAN NOT FAIL!
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self(s.into())) 
    }
}
}

References

Study of std::io::Error
https://www.youtube.com/watch?v=s5S2Ed5T-dc

USEFUL RESOURCES

git rebase in depth
Git branching - Rebasing
email + git workflow
How do I resolve merge conflicts in a Git repository?
Conventional Commits

most upvoted git questions on stackoverflow

Trivial question needs trivial solution

How to check out a pull (github) request locally

git fetch <remote> pull/<id>/head:<local branch>
git checkout <local branch>

# For example, to fetch the PR `#1234` from `origin` into local branch `test_pr_1234`

git fetch origin pull/1234/head:test_pr_1234
git checkout test_pr_11234

How do I delete a Git branch locally and remotely

git branch -d <branchname>
git push -d <remote> <branchname>

How can i rename a local Git branch

git branch -m <oldname (optional)> <newname>

Remove a file from a Git repository without deleting it from the local filesystem
How do I make Git forget about a file that was tracked, but is nore in .gitignore?

git rm --cached <file> # use `-r` for directory

How do I change the URI (URL) for a remote Git repository?

git remote set-url <remote> <url>

How do I remove a submodule?

git rm <path-to-submodule> # newer git version

Make an existing Git branch track a remote branch?

git branch -u <remote>/<remote_branch_name> <local_branch_name (optional)>

How do I discard unstaged changes in Git?

git restore <path-to-file or .> # newer git
git checkout -- <path-to-file or .> # older git

How do I clone all remote branches?
How can I delete a remote tag?
How do I remove local (untracked) files from the current Git working tree? (git clean)

Don't attempt to run before you learn to walk
How do I update or sync a forked repository on GitHub?
How do I checkout out a remote Git branch?
How to modify existing, unpushed commit messages?
How do I push a new local branch to a remote Git repository and track it too?

Interesting?
How do I find and restore a deleted file in a Git repository?
Move existing, uncommitted work to a new branch in Git
Move the most recent commit(s) to a new branch with Git
How do I add an empty directory to a Git repository?

Perhaps not the best thing to do
How do I delete a commit from a branch?

Understanding the concepts
What is the difference between 'git pull' and 'git fetch'?
What does cherry-picking a commit with Git mean?

Oops I fucked up
How do I undo the most recent local commits in Git
How do I undo 'git add' before commit?
How do I force 'git pull' to overwrite local files?
How do I revert a Git repository to a previous commit?
Undoing a git rebase
How can I reset or revert a file to a specific revision?
Reset local repository branch to be just like remote repository HEAD
Undo a Git merge that hasn't been pushed yet

Basic setup for git send-email

git config

Substitute *@email.provider with your own. Not that the sendemail.smtpuser, sendemail.from and user.email does not necessarily have to be the same. Note the differencenet.

git config --edit --global
[sendemail]
    verify = off
    annotate = yes
    smtpserver = smtp.email.provider
    smtpuser = your_account@email.provider
    smtpencryption = ssl
    smtpserverport = 465
    from = you@email.provider

git send-email and options

[COMMAND]
    git send-email --to="rec@email" <REF>

[REF]
    e.g. HEAD~ , HEAD^2, <commit id>

[EMAIL OPTS]
    -v<n> patch version (in the subject)
    --subject-prefix=<str> e.g. "PATCH v4"
    -l<n> log e.g. -l4 (changes since v1 etc..)
    --cc/--bcc=<addr>
    --from=<addr>
    --reply-to=<addr>
    --compose: invoke editor
    --reply-to=<addr>
    --in-reply-to=<id>
    --subject=<str>
    --to option, among others can be specified multiple times

clients (WIP)

(mutt): launch (neomutt) in the repo, select the patch from inbox, type | git am to apply the patch.

Comman gpg commands

Generate Keypair:

gpg --full-gen-key

generate revoke certificate:

gpg --gen-revoke [USER-ID]

list keys:

gpg --list-keys

option:

--keyid-format short/long

delete key:

gpg --delete-key [USER-ID]

output key:

gpg --armor --output public-key.txt --export [USER-ID]

upload key:

gpg --send-keys [USER-ID] --keyserver hkp://sybkeys.pgp.net

fingerprint:

gpg --fingerprint [USER-ID]

import key:

gpg --import [key-file]

search on server for key:

gpg --keyserver hkp://sybkeys.pgp.net --search-keys [USER-ID]

encrypt for someone:

gpg -r some@mail.x -e file

decrypt:

gpg -d file.gpg

sign data:

gpg --sign file
gpg --clearsign file
gpg --detach-sign file
gpg --armor --detach-sign file

verify sig:

gpg --verify [signature file] [file]

encrypt and sign:

gpg --local-user [sender id] --recipient [receiver id] --armor --sign --encrypt file

add additional email address:

gpg --edit-key [kei/user-id]
> adduid (and follow instructions)
> trust (optional)

private key export and import:

gpg --export-secret-keys --armor <USER-ID> privkey.asc
gpg --import privkey.asc

export subkeys:

gpg --list-secret-keys --with-subkey-fingerprint
gpg -a --export-secret-subkeys [subkey_id]! > /tmp/subkey.gpg

edit key:

gpg --edit-key <user-id>

edit key commands:

passwd      #change passphrase  
clean       #compact any user id that is no longer usable (revoked or expired)
revkey      #revoke a key
addkey      #add a subkey
expire      #change expiration time
addduid     # add additional names
addphoto    # add photo to key
save        # save change and quit

Fix gpg signing failed: Inappropriate ioctl for device

export GPG_TTY=$(tty)

ref https://github.com/keybase/keybase-issues/issues/2798

I mean, wtf is this error message???

The Lost Art of Structure Packing by Eric S. Raymond

http://www.catb.org/esr/structure-packing/

https://www.gnu.org/software/grub/manual/multiboot/multiboot.txt

        +-------------------+
0       | flags             |    (required)
        +-------------------+
4       | mem_lower         |    (present if flags[0] is set)
8       | mem_upper         |    (present if flags[0] is set)
        +-------------------+
12      | boot_device       |    (present if flags[1] is set)
        +-------------------+
16      | cmdline           |    (present if flags[2] is set)
        +-------------------+
20      | mods_count        |    (present if flags[3] is set)
24      | mods_addr         |    (present if flags[3] is set)
        +-------------------+
28 - 40 | syms              |    (present if flags[4] or
        |                   |                flags[5] is set)
        +-------------------+
44      | mmap_length       |    (present if flags[6] is set)
48      | mmap_addr         |    (present if flags[6] is set)
        +-------------------+
52      | drives_length     |    (present if flags[7] is set)
56      | drives_addr       |    (present if flags[7] is set)
        +-------------------+
60      | config_table      |    (present if flags[8] is set)
        +-------------------+
64      | boot_loader_name  |    (present if flags[9] is set)
        +-------------------+
68      | apm_table         |    (present if flags[10] is set)
        +-------------------+
72      | vbe_control_info  |    (present if flags[11] is set)
76      | vbe_mode_info     |
80      | vbe_mode          |
82      | vbe_interface_seg |
84      | vbe_interface_off |
86      | vbe_interface_len |
        +-------------------+
88      | framebuffer_addr  |    (present if flags[12] is set)
96      | framebuffer_pitch |
100     | framebuffer_width |
104     | framebuffer_height|
108     | framebuffer_bpp   |
109     | framebuffer_type  |
110-115 | color_info        |
        +-------------------+

An elf (PL: elves) is a type of humanoid supernatural being in Germanic folklore....ah I mean ELF the Executable and Linkable Format.

The structure:

+---------------------+
|   ELF  Header       |
+---------------------+
|   Prog Header Table |
+---------------------+
|   LOAD SECTIONS...  |
+---------------------+
|   LOAD SECTIONS...  |
+---------------------+
|   LOAD SECTIONS...  |
+---------------------+
| Section header Table|
+---------------------+

The ELF header is 64 bytes in length for 64 bits programs and 52 for 32 bits.

ELF file header

$ hexdump -C -n64 /usr/bin/ls
# hexdump of first 64 bytes

00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  03 00 3e 00 01 00 00 00  a0 5f 00 00 00 00 00 00  |..>......_......|
00000020  40 00 00 00 00 00 00 00  b8 13 02 00 00 00 00 00  |@...............|
00000030  00 00 00 00 40 00 38 00  0d 00 40 00 1b 00 1a 00  |....@.8...@.....|
00000040

(64b ver.)
Bit-offset  size Field          Purpose
----------------------------------------------------------------- Elf Ident.
0x00        4    MAG            The Magic number 0x7F E L F
0x04        1    CLASS          Format:     1 - 32bit   2 - 64bit
0x05        1    DATA           Endianness: 1 - LE      2 - BE
0x06        1    VERSION        Current version of ELF  1
0x07        1    OSABI          Target OS ABI (see appendix)
0x08        1    ABIVERSION     linux ignores it *
0x09        7    PAD            Padding , 0s
----------------------------------------------------------------- 
0x10        2    type           type of object file REL/EXEC/DYN/etc..
0x12        2    machine        ISA
0x14        4    version        1
----------------------------------------------------------------- 8/4 bytes
0x18        8(4) entry          Entry point 
0x20        8(4) phoff          offset of program header, usually 64 or 52
0x28        8(4) shoff          offset of section header table
------------------------------------------------------------------
0x30        4    flags          Depends on architecture
0x34        2    ehsize         size of this header, normally 64 or 52
0x36        2    phentsize      size of a program header entry
0x38        2    phnum          numbers of program header entries
0x3A        2    shentsize      size of section header entry
0x3C        2    shnum          humber of section header entries
0x3E        2    shstrndx       index of section header table entry
                                that contains the section names
0x40        -----------------END OF ELF FILE HEADER----------------

Program header table



(64b ver.)
Bit-offset  size Field          Purpose
-----------------------------------------------------------------
0x00        4    type           See appendix
0x04        4    flags          1-X 2-W 4-R
0x08        8    offset         offset of the segment in the file
0x10        8    vaddr          VA of the segment in memory
0x18        8    paddr          PA of segment - where applicable
0x20        8    filesz         size of segment in file   (bytes)
0x28        8    memsz          size of segment in memory (bytes)
0x30        8    align          0 and 1 - no align. Otherwise power of 2
0x38    ------------------------END OF PROGRAM HEADER ----(56)---

Let's use this example:

$ readelf -l /usr/bin/ls

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000002d8 0x00000000000002d8  R      0x8
  INTERP         0x0000000000000318 0x0000000000000318 0x0000000000000318
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000003638 0x0000000000003638  R      0x1000
  .....


$ hexdump -C /usr/bin/ls
# Size of program header entry is 0x38 = 56

00000000  |
...       | First 64 bytes ELF File header 
----------------------------------------------------------
00000040  06 00 00 00 04 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000050  40 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |@.......@.......|
00000060  d8 02 00 00 00 00 00 00  d8 02 00 00 00 00 00 00  |................|
00000070  08 00 00 00 00 00 00 00  -- -- -- -- -- -- -- --  |........ 
-split--  -- -- -- -- -- -- -- --  03 00 00 00 04 00 00 00           ........|
00000080  18 03 00 00 00 00 00 00  18 03 00 00 00 00 00 00  |................|
00000090  18 03 00 00 00 00 00 00  1c 00 00 00 00 00 00 00  |................|
000000a0  1c 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|

000000b0  01 00 00 00 04 00 00 00  00 00 00 00 00 00 00 00  |................|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  38 36 00 00 00 00 00 00  38 36 00 00 00 00 00 00  |86......86......|
000000e0  00 10 00 00 00 00 00 00  01 00 00 00 05 00 00 00  |................|
000000f0  00 40 00 00 00 00 00 00  00 40 00 00 00 00 00 00  |.@.......@......|

Note that this thing if little endian. The first program header

  • [40, 4] : Type is 6, this is PHDR
  • [44, 4] : Flags is 4, this is read only
  • [48, 8] : Offset is 0x40, this offset in file, i.e. THIS TABLE
  • [50, 16] : vaddr and paddr, they are the same : 0x40;
  • [60, 8] : filesz == 0x2d8 == 728. Here 728 == phnum * phentsize = 13 * 56. i.e.
  • [68, 8] : memsz == 0x2d8 == filesz, implying there is no BSS in this seg. the size of the program header table.
  • [70, 8] : align = 0x8 , i.e. 2^8 = 256 bytes

Appendix

EL_OSABI        OS
--------------------------------------------
0x00            System V
0x01            HP-UX
0x02            NetBSD
0x03            Linux
0x04            GNU Hurd
0x06            Solaris
0x07            AIX
0x08            IRIX
0x09            FreeBSD
0x0A            Tru64
0x0B            Novell ModestoA
0x0C            OpenBSD
0x0D            OpenVMS
0x0E            NonStop Kernel
0x0F            AROS
0x10            FnixOS
0x11            Nuxi CloudABI
0x12            Stratus Technologies OpenVOS

Types of Program Headers:

TYPE [0:3]      Name        Meaning
--------------------------------------------
0x0             NULL        program header table unused
0x1             LOAD        loadable segment
0x2             DYNAMIC     Dyn. linking info
0x3             INTERP      interpreter info
0x4             NOTE        Aux. info
0x5             SHLIB       Reserved
0x6             PHDR        Segment containing PH table itself
0x7             TLS         Thread-local storage template
0x60000000      LOOS        reserved inclusive range OS Specific
0x6FFFFFFF      HIOS         |_
0x70000000      LOPROC      reserved inclusive range Processor Specific
0x7FFFFFFF      HIPROC       |_

ABIVERSION: ABIVERSION is ignored for statically-linked executables.

Takeaways taken from the kernel's coding style guide. This is only for my own reference. Please read the original article instead.
https://www.kernel.org/doc/html/v4.10/process/coding-style.html

Indentation:

  • Tabs are Tabs, don't expand them into spaces.
  • Tabs are 8 characters.
  • No more than 3 levels of indentation should be necessary.
  • switch and case labels on the same level
  • Don’t put multiple statements on a single line

Breaking long lines and strings:

  • Textwidth = 80 chars
  • Never break user-visible strings such as printk messages, because that breaks the ability to grep for them.

Braces and Spaces:

  • For non function blocks put the opening brace last on the line, and put the closing brace first
  • For function blocks opening brace at the beginning of the next line, thus:
  • the closing brace is empty on a line of its own, except in the cases where it is followed by a continuation of the same statement
  • Do not unnecessarily use braces where a single statement will do.
  • The above DOES NOT apply if only one branch is a single statement.
  • Use a space after keywords: if, switch, case, for, do, while
  • No space after sizeof, __attribute__etc. because they look like functions.
  • Do not add spaces around (inside) parenthesized expressions.
  • * for pointers attach to the data name or function name, not to the type name.
  • One space around most binary and ternary operators: = + - < > * / % | & ^ <= >= == != ? :
  • No space after unary operators: & * + - ~ ! sizeof typeof alignof __attribute__ defined
  • No space before the postfix/prefix increment & decrement unary operators: ++ --
  • No space around the . and -> structure member operators.
  • No trailing whitespace at end of lines.

Naming

  • Do not encode type of a function into the name (Hungarian notation) - the compiler knows the types anyways.
  • GLOBAL variables need to have descriptive names, as do global functions.
  • LOCAL variable names should be short, and to the point

Typedefs

  • It’s a mistake to use typedef for structures and pointers. (let struct be struct and let pointers be pointers)
  • NEVER use a typedef UNLESS one of the following applies
    • totally opaque objects (where the typedef is actively used to hide what the object is). e.t. pte_t
    • Clear integer types, where the abstraction helps avoid confusion whether it is int or long.
    • when you use sparse to literally create a new type for type-checking.
    • New types which are identical to standard C99 types, in certain exceptional circumstances.
    • Types safe for use in userspace. e.t. __u32

Functions

  • In function prototypes, include parameter names with their data types.
  • In source files, separate functions with one blank line. If the function is exported, the EXPORT macro for it should follow immediately after the closing function brace line.

more like "you should" than "you must":

  • Functions should be short and sweet, and do just one thing (but it’s OK to have a longer function).
  • Use helper functions with descriptive names (you can ask the compiler to in-line them if you think it’s performance-critical)
  • the number of local variables. They shouldn’t exceed 5-10, or you’re doing something wrong.

Function return values and names

  • Don't mix the two practice:
    • error-code integer (-Exxx = failure, 0 = success) and
    • succeeded boolean (0 = failure, non-zero = success)
  • Convention:
    • error-code integer for action or imperative command (e.g. work() )
    • boolean for predicate (e.g. pci_dev_present() )
  • All EXPORTed and public functions must respect this convention

If the name of a function is an action or an imperative command, the function should return an error-code integer. If the name is a predicate, the function should return a "succeeded" boolean. [...] Functions whose return value is the actual result of a computation, rather than an indication of whether the computation succeeded, are not subject to this rule.

Centralized exiting of functions

  • just keep using gotos...
  • The goto statement comes in handy when a function exits from multiple locations and some common work such as cleanup has to be done. If there is no cleanup needed then just return directly.
  • Choose label names which say what the goto does or why the goto exists.

Commenting

  • Don't over-comment
  • NEVER try to explain HOW your code works in a comment.
  • Put the comments at the head of the function, telling people what it does, and possibly WHY it does it. NOT HOW.
  • Avoid putting comments inside a function body.
  • You can make small comments to note or warn about something particularly. clever (or ugly), but try to avoid excess.
  • Kernel-doc format for kernel API functions
  • Comment data, whether they are basic types or derived types.

Macros, Enums and RTL

  • Names of macros defining constants and labels in enums are capitalized.
  • CAPITALIZED macro names are appreciated but macros resembling functions may be named in lower case.
  • Generally, inline functions are preferable to macros resembling functions.
  • Macros with multiple statements should be enclosed in a do - while block:
  • macros defining constants using expressions must enclose the expression in parentheses. Beware of similar issues with macros using parameters.
  • Things to avoid when using macros:
    • macros that affect control flow:
    • macros that depend on having a local variable with a magic name: #define FOO(val) bar(index, val)
    • macros with arguments that are used as l-values: FOO(x) = y; will bite you if somebody e.g. turns FOO into an inline function.
    • namespace collisions when defining local variables in macros resembling functions:
  • Don’t re-invent the kernel macros (check include/linux/kernel.h).

inline asm

  • Don't use when C can do the same.
  • Large, non-trivial assembly functions should go in .S files, with corresponding C prototypes defined in C header files. The C prototypes for assembly functions should use asmlinkage.
  • mark asm statement as volatile, to prevent GCC from removing it if GCC does not notice any side effects. (not always necessarily)
  • each instruction on a separate line in a separate quoted string; end each string except the last with nt to properly indent the next instruction in the assembly output:

The inline disease

do not abuse inline - it's often not appropriate and it makes bigger program.

  • Bigger icache footprint
  • less memory available for pagecache.

A reasonable rule of thumb is to not put inline at functions that have more than 3 lines of code in them. An exception to this rule are the cases where a parameter is known to be a compiletime constant, and as a result of this constantness you know the compiler will be able to optimize most of your function away at compile time. For a good example of this later case, see the kmalloc() inline function.

Conditional Compilation

  • Wherever possible, don’t use preprocessor conditionals (#if, #ifdef) in .c files;

Instead, use such conditionals in a header file defining functions for use in those .c files, providing no-op stub versions in the #else case, and then call those functions unconditionally from .c files.

  • Prefer to compile out entire functions, rather than portions of functions or portions of expressions.
  • Rather than putting an ifdef in an expression, factor out part or all of the expression into a separate helper function and apply the conditional to that function.
  • mark variables __maybe_unused that go unused in a particular configuration.
  • where possible, use the IS_ENABLED macro to convert a Kconfig symbol into a C boolean expression, and use it in a normal C conditional:
  • close non-trivial #if and #ifdef block with comments:
#ifdef CONFIG_SOMETHING
...
#endif /* CONFIG_SOMETHING */

Not included here:

  • Kconfig
  • Data structures
  • Printing kernel messages
  • Allocating memory (TODO)

Snippets

Switch/case:

switch (suffix) {
case 'G':
case 'g':
        mem <<= 30;
        break;
case 'K':
case 'k':
        mem <<= 10;
        /* fall through */
default:
        break;
}

Non-function block:

if (x) {
        // do ...
}

Non-function block w. addition terms:

if (x == y) {
        // ..
} else if (x > y) {
        // ...
} else {
        // ....
}

Function block:

int function(int x)
{
        // body of function
}

Single branch cond, no brakckets:

if (condition)
        action();

Multi branch cond, some are not single stmt:

if (condition) {
        do_this();
        do_that();
} else {
        otherwise();
}

Do not add spaces around (inside) parenthesized expressions. This is bad practice:

s = sizeof( struct file );

Export a function w. Macro:

int system_is_up(void)
{
        return system_state == SYSTEM_RUNNING;
}
EXPORT_SYMBOL(system_is_up);

Macros with multiple statements should be enclosed in a do - while block:

#define macrofun(a, b, c)                       \
        do {                                    \
                if (a == 5)                     \
                        do_this(b, c);          \
        } while (0)

macros that affect control flow: BELOW IS BAD

#define FOO(x)                                  \
        do {                                    \
                if (blah(x) < 0)                \
                        return -EBUGGERED;      \
        } while (0)

enclose the expression (in macros) in parentheses:

#define CONSTANT 0x4000
#define CONSTEXP (CONSTANT | 3)

namespace collisions when defining local variables in macros resembling functions: ret is a common name for a local variable - __foo_ret is less likely to collide with an existing variable.:

#define FOO(x)                          \
({                                      \
        typeof(x) ret;                  \
        ret = calc_ret(x);              \
        (ret);                          \
})

multi-line inline asm example:

asm ("magic %reg1, #42\n\t"
     "more_magic %reg2, %reg3"
     : /* outputs */ : /* inputs */ : /* clobbers */);

where possible, use the IS_ENABLED macro to convert a Kconfig symbol into a C boolean expression, and use it in a normal C conditional. The compiler will constant-fold the conditional away, and include or exclude the block of code just as with an #ifdef, so this will not add any runtime overhead.

if (IS_ENABLED(CONFIG_SOMETHING)) {
        ...
}

MISC resources regarding licensing.

List of SPDX License Identifiers
https://spdx.org/licenses/

Re-using free software via writefreesoftware.org
https://writefreesoftware.org/learn/participate/derived-works/

Chossing a license via writefreesoftware.org
https://writefreesoftware.org/learn/participate/choose-a-license/

REUSE Specifications
https://reuse.software/

Intra-GPL compatibility matrix via gnu.org
https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility