aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2023-07-17 18:29:40 +0200
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2023-07-25 14:41:16 +0200
commit0fe4cac5dda1028c22ec3a6997e1b9155a768004 (patch)
treea40fb65668656fd8720dddcddf9f6896102a6540
parent60a38a3a57befec24a768cbda811d224f1ab89dd (diff)
downloadqemu-0fe4cac5dda1028c22ec3a6997e1b9155a768004.zip
qemu-0fe4cac5dda1028c22ec3a6997e1b9155a768004.tar.gz
qemu-0fe4cac5dda1028c22ec3a6997e1b9155a768004.tar.bz2
target/mips: Avoid shift by negative number in page_table_walk_refill()
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>
-rw-r--r--target/mips/tcg/sysemu/tlb_helper.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c
index e7be649..7dbc2e2 100644
--- a/target/mips/tcg/sysemu/tlb_helper.c
+++ b/target/mips/tcg/sysemu/tlb_helper.c
@@ -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;
@@ -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;
@@ -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;