aboutsummaryrefslogtreecommitdiff
#ifndef CP_REGS_H
#define CP_REGS_H

#include <stdint.h>

// SCTLR - System Control Register

// Wandering why I didn't typedef this struct with fields?
// That's because 
typedef union
{
  uint32_t raw;
  struct
  {
    uint32_t M        : 1; // bit  0
    uint32_t A        : 1; // bit  1
    uint32_t C        : 1; // bit  2
    uint32_t Bits_4_3 : 2; // bits 3:4
    uint32_t CP15BEN  : 1; // bit  5
    uint32_t Bit_6    : 1; // bit  6
    uint32_t B        : 1; // bit  7
    uint32_t Bits_9_8 : 2; // bits 9:8
    uint32_t SW       : 1; // bit  10
    uint32_t Z        : 1; // bit  11
    uint32_t I        : 1; // bit  12
    uint32_t V        : 1; // bit  13
    uint32_t RR       : 1; // bit  14
    uint32_t Bit_15   : 1; // bit  15
    uint32_t Bit_16   : 1; // bit  16
    uint32_t HA       : 1; // bit  17
    uint32_t Bit_18   : 1; // bit  18
    uint32_t WXN      : 1; // bit  19
    uint32_t UWXN     : 1; // bit  20
    uint32_t FI       : 1; // bit  21
    uint32_t U        : 1; // bit  22
    uint32_t Bit_23   : 1; // bit  23
    uint32_t VE       : 1; // bit  24
    uint32_t EE       : 1; // bit  25
    uint32_t Bit_26   : 1; // bit  26
    uint32_t NMFI     : 1; // bit  27
    uint32_t TRE      : 1; // bit  28
    uint32_t AFE      : 1; // bit  29
    uint32_t TE       : 1; // bit  30
    uint32_t Bit_31   : 1; // bit  31
  } fields;
} SCTLR_t;

// DACR - Domain Access Control Register
// DACR holds 16 pairs of bits; each pair represents access
// permissions to a respective memory domain. There's no point
// declaring a union for this.
typedef uint32_t DACR_t;

inline static uint8_t domain_permissions(DACR_t DACR_contents,
					 int domain)
{
  return (DACR_contents << (30 - 2 * domain)) >> 30;
}

inline static DACR_t set_domain_permissions(DACR_t DACR_contents,
					    int domain,
					    uint8_t permissions)
{
  uint32_t clear_domain_permissions_mask = ~(0b11 << (2 * domain));
  uint32_t new_domain_permissions_mask =
    ((uint32_t) permissions) << (2 * domain);
  
  return (DACR_contents & clear_domain_permissions_mask)
    | new_domain_permissions_mask;
}

#define DOMAIN_NO_ACCESS      0b00
#define DOMAIN_CLIENT_ACCESS  0b01
#define DOMAIN_RESERVED       0b10
#define DOMAIN_MANAGER_ACCESS 0b11

// TTBR - Translation Table Base Register (there're 2 of them with
// (almost) the same structure)

// A field in TTBCR determines how long the address field is in TTBR0,
// but here we'll ignore this and just assume the greatest possible
// length of this field (18 bits). In TTBR1 it's always 18 bits.
typedef union
{
  uint32_t raw;
  struct
  {

    uint32_t C          : 1;  // bit  0
    uint32_t S          : 1;  // bit  1
    uint32_t IMP        : 1;  // bit  2
    uint32_t RGN        : 2;  // bits 4:3
    uint32_t NOS        : 1;  // bit  5
    uint32_t IRGN_0     : 1;  // bit  6
    uint32_t Bits_13_6  : 7;  // bits 13:7
    uint32_t Bits_31_14 : 18; // bits 31:14
    // with multiprocessing extensions the cacheable bit becomes
    // upper IRGN bit
#define IRGN_1 C

    // i'm not sure 'interprocess region bits' is the right name,
    // I'm just guessing (by analogy to RGN -> region bits)
#define TTBR_CACHEABLE_BIT                  C
#define TTBR_INTERPROCESS_REGION_BITS_1     IRGN_1
#define TTBR_SHAREABLE_BIT                  S
#define TTBR_IMPLEMENTATION_DEFINED_BIT     IMP
#define TTBR_REGION_BITS_1_0                RGN
#define TTBR_INTERPROCESS_REGION_BITS_0     IRGN_0
#define TTBR_NON_OUTER_SHAREABLE_BIT        NOS
#define TTBR_TRANSLATION_TABLE_BASE_ADDRESS Bits_31_14
  } fields;
} TTBR_t;

#endif // CP_REGS_H