summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohpow01 <john.powell@arm.com>2021-10-13 13:56:51 -0500
committerJohn <john.powell@arm.com>2021-11-16 17:41:43 +0100
commit322b344e30cb87b9293060d5946b3c17fe3b9133 (patch)
tree76f0107b4638acbe61c4aa61bd359a84b4af1deb
parent55b2e6f0d3b6d822ce46e287dd4ba233be12d441 (diff)
fix(rme): fixes a shift by 64 bits bug in the RME GPT library
Under certain configurations of PPS and L0GPTSZ a macro could result in a right shift by 64 bits. This patch removes that possibility by limiting the total size of each shift to the maximum width of the L0 or L1 index field in a physical address. In addition, it adds more detail about how these values are calculated. Signed-off-by: John Powell <john.powell@arm.com> Change-Id: Ie71c8e6f922a5bb522a6169701bfc36fc99f765a
-rw-r--r--lib/gpt_rme/gpt_rme_private.h38
1 files changed, 30 insertions, 8 deletions
diff --git a/lib/gpt_rme/gpt_rme_private.h b/lib/gpt_rme/gpt_rme_private.h
index 5770bf7d6..4203bba28 100644
--- a/lib/gpt_rme/gpt_rme_private.h
+++ b/lib/gpt_rme/gpt_rme_private.h
@@ -117,11 +117,13 @@ typedef enum {
/******************************************************************************/
/*
+ * Width of the L0 index field.
+ *
* If S is greater than or equal to T then there is a single L0 region covering
* the entire protected space so there is no L0 index, so the width (and the
* derivative mask value) are both zero. If we don't specifically handle this
* special case we'll get a negative width value which does not make sense and
- * could cause a lot of problems.
+ * would cause problems.
*/
#define GPT_L0_IDX_WIDTH(_t) (((_t) > GPT_S_VAL) ? \
((_t) - GPT_S_VAL) : (0U))
@@ -129,9 +131,16 @@ typedef enum {
/* Bit shift for the L0 index field in a PA. */
#define GPT_L0_IDX_SHIFT (GPT_S_VAL)
-/* Mask for the L0 index field, must be shifted. */
-#define GPT_L0_IDX_MASK(_t) (0xFFFFFFFFFFFFFFFFUL >> \
- (64U - (GPT_L0_IDX_WIDTH(_t))))
+/*
+ * Mask for the L0 index field, must be shifted.
+ *
+ * The value 0x3FFFFF is 22 bits wide which is the maximum possible width of the
+ * L0 index within a physical address. This is calculated by
+ * ((t_max - 1) - s_min + 1) where t_max is 52 for 4PB, the largest PPS, and
+ * s_min is 30 for 1GB, the smallest L0GPTSZ.
+ */
+#define GPT_L0_IDX_MASK(_t) (0x3FFFFFUL >> (22U - \
+ (GPT_L0_IDX_WIDTH(_t))))
/* Total number of L0 regions. */
#define GPT_L0_REGION_COUNT(_t) ((GPT_L0_IDX_MASK(_t)) + 1U)
@@ -146,15 +155,28 @@ typedef enum {
/* L1 address attribute macros */
/******************************************************************************/
-/* Width of the L1 index field. */
+/*
+ * Width of the L1 index field.
+ *
+ * This field does not have a special case to handle widths less than zero like
+ * the L0 index field above since all valid combinations of PGS (p) and L0GPTSZ
+ * (s) will result in a positive width value.
+ */
#define GPT_L1_IDX_WIDTH(_p) ((GPT_S_VAL - 1U) - ((_p) + 3U))
/* Bit shift for the L1 index field. */
#define GPT_L1_IDX_SHIFT(_p) ((_p) + 4U)
-/* Mask for the L1 index field, must be shifted. */
-#define GPT_L1_IDX_MASK(_p) (0xFFFFFFFFFFFFFFFFUL >> \
- (64U - (GPT_L1_IDX_WIDTH(_p))))
+/*
+ * Mask for the L1 index field, must be shifted.
+ *
+ * The value 0x7FFFFF is 23 bits wide and is the maximum possible width of the
+ * L1 index within a physical address. It is calculated by
+ * ((s_max - 1) - (p_min + 4) + 1) where s_max is 39 for 512gb, the largest
+ * L0GPTSZ, and p_min is 12 for 4KB granules, the smallest PGS.
+ */
+#define GPT_L1_IDX_MASK(_p) (0x7FFFFFUL >> (23U - \
+ (GPT_L1_IDX_WIDTH(_p))))
/* Bit shift for the index of the L1 GPI in a PA. */
#define GPT_L1_GPI_IDX_SHIFT(_p) (_p)