How to get aribtrary portion of a bitmap in Linux kernel program?

Viewed 28

I have this code snippet from a baremetal program(here printf is for baremetal).

  rd_data = *(__GICD + GICD_TYPER);
  printf("--- GICD Page Status (GICD_TYPER)----------------------\n");
  printf("ITLineNumber(=SPIS/32):   %d\n", BIT_FIELD_READER(rd_data, 3, 0)); 
  printf("SecurityExtn:             %d\n", BIT_FIELD_READER(rd_data,10,10));
  printf("MBIS:                     %d\n", BIT_FIELD_READER(rd_data,16,16));
  printf("LPIS:                     %d\n", BIT_FIELD_READER(rd_data,17,17));
  printf("DVIS:                     %d\n", BIT_FIELD_READER(rd_data,18,18));
  printf("IDbits:                   %d\n", BIT_FIELD_READER(rd_data,23,19));
  printf("A3V:                      %d\n", BIT_FIELD_READER(rd_data,24,24));
  printf("No1N:                     %d\n", BIT_FIELD_READER(rd_data,25,25));

The macro BIT_FIELD_READER(rd_data, end_bit, start_bit) looks very convenient.
And now I wish to print the some registers of a peripheral registers in kernel code (using printk), and searched the kernel code if there is something similar(to copy-paste and just replace the macro).
In include/linux/bitmap.h, there is bitmap_get_value8(map, start) but it's only for getting 8 bit value.
And in include/linux/bitfield.h, I found something like #define REG_FIELD_A GENMASK(6, 0) and a = FIELD_GET(REG_FIELD_A, reg);. But this requires defining every field which is cumbsersome and not succinct. Isn't there any macro getting arbitrary bit fields using start and end position(or length) in Linux kernel code?

1 Answers

The BIT_FIELD_READER macro described in the question could be defined using macros defined by #include <linux/bitfield.h> and #include <linux/bits.h> as follows:

#define BIT_FIELD_READER(_reg, _hi, _lo) FIELD_GET(GENMASK(_hi, _lo), _reg)

A restriction is that the _hi and _lo parameters need to be compile-time constants because the FIELD_GET(_mask, _reg) macro requires the _mask parameter to be a compile-time constant.

Similar wrappers around the FIELD_PREP(_mask, _val), FIELD_MAX(_mask), and FIELD_FIT(_mask, _val) macros may be useful:

#define BIT_FIELD_PREP(_val, _hi, _lo) FIELD_PREP(GENMASK(_hi, _lo), _val)
#define BIT_FIELD_MAX(_hi, _lo) FIELD_MAX(GENMASK(_hi, _lo)
#define BIT_FIELD_FIT(_val, _hi, _lo) FIELD_FIT(GENMASK(_hi, _lo), _val)

They have the same restriction that the _hi and _lo parameters need to be compile-time constants.

Related