Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arm64/sysreg: Support feature-specific fields with 'Prefix' descriptor

Some system register field encodings change based on, for example the
in-use architecture features, or the context in which they are
accessed. In order to support these different field encodings,
introduce the Prefix descriptor (Prefix, EndPrefix) for describing
such sysregs.

The Prefix descriptor can be used in the following way:

Sysreg EXAMPLE 0 1 2 3 4
Prefix FEAT_A
Field 63:0 Foo
EndPrefix
Prefix FEAT_B
Field 63:1 Bar
Res0 0
EndPrefix
Field 63:0 Baz
EndSysreg

This will generate a single set of system register encodings (REG_,
SYS_, ...), and then generate three sets of field definitions for the
system register called EXAMPLE. The first set is prefixed by FEAT_A,
e.g. FEAT_A_EXAMPLE_Foo. The second set is prefixed by FEAT_B, e.g.,
FEAT_B_EXAMPLE_Bar. The third set is not given a prefix at all,
e.g. EXAMPLE_BAZ. For each set, a corresponding set of defines for
Res0, Res1, and Unkn is generated.

The intent for the final prefix-less fields is to describe default or
legacy field encodings. This ensure that prefixed encodings can be
added to already-present sysregs without affecting existing legacy
code. Prefixed fields must be defined before those without a prefix,
and this is checked by the generator. This ensures consisnt ordering
within the sysregs definitions.

The Prefix descriptor can be used within Sysreg or SysregFields
blocks. Field, Res0, Res1, Unkn, Rax, SignedEnum, Enum can all be used
within a Prefix block. Fields and Mapping can not. Fields that vary
with features must be described as part of a SysregFields block,
instead. Mappings, which are just a code comment, make little sense in
this context, and have hence not been included.

There are no changes to the generated system register definitions as
part of this change.

Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Sascha Bischoff and committed by
Catalin Marinas
fe2ef469 0aab5772

+88 -38
+88 -38
arch/arm64/tools/gen-sysreg.awk
··· 44 44 45 45 # Print a CPP macro definition, padded with spaces so that the macro bodies 46 46 # line up in a column 47 - function define(name, val) { 48 - printf "%-56s%s\n", "#define " name, val 47 + function define(prefix, name, val) { 48 + printf "%-56s%s\n", "#define " prefix name, val 49 + } 50 + 51 + # Same as above, but without a prefix 52 + function define_reg(name, val) { 53 + define(null, name, val) 49 54 } 50 55 51 56 # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field 52 - function define_field(reg, field, msb, lsb) { 53 - define(reg "_" field, "GENMASK(" msb ", " lsb ")") 54 - define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")") 55 - define(reg "_" field "_SHIFT", lsb) 56 - define(reg "_" field "_WIDTH", msb - lsb + 1) 57 + function define_field(prefix, reg, field, msb, lsb) { 58 + define(prefix, reg "_" field, "GENMASK(" msb ", " lsb ")") 59 + define(prefix, reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")") 60 + define(prefix, reg "_" field "_SHIFT", lsb) 61 + define(prefix, reg "_" field "_WIDTH", msb - lsb + 1) 57 62 } 58 63 59 64 # Print a field _SIGNED definition for a field 60 - function define_field_sign(reg, field, sign) { 61 - define(reg "_" field "_SIGNED", sign) 65 + function define_field_sign(prefix, reg, field, sign) { 66 + define(prefix, reg "_" field "_SIGNED", sign) 62 67 } 63 68 64 69 # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb ··· 133 128 134 129 next_bit = 63 135 130 131 + delete seen_prefixes 132 + 136 133 next 137 134 } 138 135 ··· 143 136 if (next_bit >= 0) 144 137 fatal("Unspecified bits in " reg) 145 138 146 - define(reg "_RES0", "(" res0 ")") 147 - define(reg "_RES1", "(" res1 ")") 148 - define(reg "_UNKN", "(" unkn ")") 139 + define(prefix, reg "_RES0", "(" res0 ")") 140 + define(prefix, reg "_RES1", "(" res1 ")") 141 + define(prefix, reg "_UNKN", "(" unkn ")") 149 142 print "" 150 143 151 144 reg = null ··· 177 170 fatal("Duplicate Sysreg definition for " reg) 178 171 defined_regs[reg] = 1 179 172 180 - define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 181 - define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 173 + define_reg("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 174 + define_reg("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 182 175 183 - define("SYS_" reg "_Op0", op0) 184 - define("SYS_" reg "_Op1", op1) 185 - define("SYS_" reg "_CRn", crn) 186 - define("SYS_" reg "_CRm", crm) 187 - define("SYS_" reg "_Op2", op2) 176 + define_reg("SYS_" reg "_Op0", op0) 177 + define_reg("SYS_" reg "_Op1", op1) 178 + define_reg("SYS_" reg "_CRn", crn) 179 + define_reg("SYS_" reg "_CRm", crm) 180 + define_reg("SYS_" reg "_Op2", op2) 188 181 189 182 print "" 190 183 184 + prefix = null 191 185 next_bit = 63 186 + 187 + delete seen_prefixes 192 188 193 189 next 194 190 } ··· 202 192 fatal("Unspecified bits in " reg) 203 193 204 194 if (res0 != null) 205 - define(reg "_RES0", "(" res0 ")") 195 + define(prefix, reg "_RES0", "(" res0 ")") 206 196 if (res1 != null) 207 - define(reg "_RES1", "(" res1 ")") 197 + define(prefix, reg "_RES1", "(" res1 ")") 208 198 if (unkn != null) 209 - define(reg "_UNKN", "(" unkn ")") 199 + define(prefix, reg "_UNKN", "(" unkn ")") 210 200 if (res0 != null || res1 != null || unkn != null) 211 201 print "" 212 202 ··· 219 209 res0 = null 220 210 res1 = null 221 211 unkn = null 212 + prefix = null 222 213 223 214 block_pop() 224 215 next ··· 244 233 next 245 234 } 246 235 247 - 248 - $1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 236 + $1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 249 237 expect_fields(2) 250 238 parse_bitdef(reg, "RES0", $2) 251 239 field = "RES0_" msb "_" lsb ··· 254 244 next 255 245 } 256 246 257 - $1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 247 + $1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 258 248 expect_fields(2) 259 249 parse_bitdef(reg, "RES1", $2) 260 250 field = "RES1_" msb "_" lsb ··· 264 254 next 265 255 } 266 256 267 - $1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 257 + $1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 268 258 expect_fields(2) 269 259 parse_bitdef(reg, "UNKN", $2) 270 260 field = "UNKN_" msb "_" lsb ··· 274 264 next 275 265 } 276 266 277 - $1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 267 + $1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 278 268 expect_fields(3) 279 269 field = $3 280 270 parse_bitdef(reg, field, $2) 281 271 282 - define_field(reg, field, msb, lsb) 272 + define_field(prefix, reg, field, msb, lsb) 283 273 print "" 284 274 285 275 next 286 276 } 287 277 288 - $1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 278 + $1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 289 279 expect_fields(2) 290 280 parse_bitdef(reg, field, $2) 291 281 292 282 next 293 283 } 294 284 295 - $1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 285 + $1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 296 286 block_push("Enum") 297 287 298 288 expect_fields(3) 299 289 field = $3 300 290 parse_bitdef(reg, field, $2) 301 291 302 - define_field(reg, field, msb, lsb) 303 - define_field_sign(reg, field, "true") 292 + define_field(prefix, reg, field, msb, lsb) 293 + define_field_sign(prefix, reg, field, "true") 304 294 305 295 delete seen_enum_vals 306 296 307 297 next 308 298 } 309 299 310 - $1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 300 + $1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 311 301 block_push("Enum") 312 302 313 303 expect_fields(3) 314 304 field = $3 315 305 parse_bitdef(reg, field, $2) 316 306 317 - define_field(reg, field, msb, lsb) 318 - define_field_sign(reg, field, "false") 307 + define_field(prefix, reg, field, msb, lsb) 308 + define_field_sign(prefix, reg, field, "false") 319 309 320 310 delete seen_enum_vals 321 311 322 312 next 323 313 } 324 314 325 - $1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 315 + $1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 326 316 block_push("Enum") 327 317 328 318 expect_fields(3) 329 319 field = $3 330 320 parse_bitdef(reg, field, $2) 331 321 332 - define_field(reg, field, msb, lsb) 322 + define_field(prefix, reg, field, msb, lsb) 333 323 334 324 delete seen_enum_vals 335 325 ··· 359 349 fatal("Duplicate Enum value " val " for " name) 360 350 seen_enum_vals[val] = 1 361 351 362 - define(reg "_" field "_" name, "UL(" val ")") 352 + define(prefix, reg "_" field "_" name, "UL(" val ")") 353 + next 354 + } 355 + 356 + $1 == "Prefix" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 357 + block_push("Prefix") 358 + 359 + expect_fields(2) 360 + 361 + if (next_bit < 63) 362 + fatal("Prefixed fields must precede non-prefixed fields (" reg ")") 363 + 364 + prefix = $2 "_" 365 + 366 + if (prefix in seen_prefixes) 367 + fatal("Duplicate prefix " prefix " for " reg) 368 + seen_prefixes[prefix] = 1 369 + 370 + res0 = "UL(0)" 371 + res1 = "UL(0)" 372 + unkn = "UL(0)" 373 + next_bit = 63 374 + 375 + next 376 + } 377 + 378 + $1 == "EndPrefix" && block_current() == "Prefix" { 379 + expect_fields(1) 380 + if (next_bit >= 0) 381 + fatal("Unspecified bits in prefix " prefix " for " reg) 382 + 383 + define_resx_unkn(prefix, reg, res0, res1, unkn) 384 + 385 + prefix = null 386 + res0 = "UL(0)" 387 + res1 = "UL(0)" 388 + unkn = "UL(0)" 389 + next_bit = 63 390 + 391 + block_pop() 392 + 363 393 next 364 394 } 365 395