Skip to content

Commit

Permalink
target/mips: Avoid shift by negative number in page_table_walk_refill()
Browse files Browse the repository at this point in the history
Coverity points out that in page_table_walk_refill() we can
shift by a negative number, which is undefined behaviour
(CID 1452918, 1452920, 1452922).  We already catch the
negative directory_shift and leaf_shift as being a "bail
out early" case, but not until we've already used them to
calculated some offset values.

The shifts can be negative only if ptew > 1, so make the
bail-out-early check look directly at that, and only
calculate the shift amounts and the offsets based on them
after we have done that check. This allows
us to simplify the expressions used to calculate the
shift amounts, use an unsigned type, and avoids the
undefined behaviour.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
[PMD: Check for ptew > 1, use unsigned type]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20230717213504.24777-3-philmd@linaro.org>
  • Loading branch information
pm215 authored and philmd committed Jul 25, 2023
1 parent 60a38a3 commit 0fe4cac
Showing 1 changed file with 17 additions and 15 deletions.
32 changes: 17 additions & 15 deletions target/mips/tcg/sysemu/tlb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry,
static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
int directory_index, bool *huge_page, bool *hgpg_directory_hit,
uint64_t *pw_entrylo0, uint64_t *pw_entrylo1,
int directory_shift, int leaf_shift)
unsigned directory_shift, unsigned leaf_shift)
{
int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1;
int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F;
Expand Down Expand Up @@ -730,21 +730,11 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,

/* Other HTW configs */
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;

/* HTW Shift values (depend on entry size) */
int directory_shift = (ptew > 1) ? -1 :
(hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
int leaf_shift = (ptew > 1) ? -1 :
(ptew == 1) ? native_shift + 1 : native_shift;
unsigned directory_shift, leaf_shift;

/* Offsets into tables */
int goffset = gindex << directory_shift;
int uoffset = uindex << directory_shift;
int moffset = mindex << directory_shift;
int ptoffset0 = (ptindex >> 1) << (leaf_shift + 1);
int ptoffset1 = ptoffset0 | (1 << (leaf_shift));

uint32_t leafentry_size = 1 << (leaf_shift + 3);
unsigned goffset, uoffset, moffset, ptoffset0, ptoffset1;
uint32_t leafentry_size;

/* Starting address - Page Table Base */
uint64_t vaddr = env->CP0_PWBase;
Expand All @@ -766,10 +756,22 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address,
/* no structure to walk */
return false;
}
if ((directory_shift == -1) || (leaf_shift == -1)) {
if (ptew > 1) {
return false;
}

/* HTW Shift values (depend on entry size) */
directory_shift = (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
leaf_shift = (ptew == 1) ? native_shift + 1 : native_shift;

goffset = gindex << directory_shift;
uoffset = uindex << directory_shift;
moffset = mindex << directory_shift;
ptoffset0 = (ptindex >> 1) << (leaf_shift + 1);
ptoffset1 = ptoffset0 | (1 << (leaf_shift));

leafentry_size = 1 << (leaf_shift + 3);

/* Global Directory */
if (gdw > 0) {
vaddr |= goffset;
Expand Down

0 comments on commit 0fe4cac

Please sign in to comment.