Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5ad036f authored by Patrick Daly's avatar Patrick Daly Committed by Gerrit - the friendly Code Review server
Browse files

msm: rtb: Fix buffer corruption issue



Consider the case of a nentries==8 and 3 cpus.
Numbers in parenthesis are the equivalent location in the circular buffer.
CPU:   Index0:  Index1: Index2: Index3:
0      0        3       6       9(1)
1      1        4       7       10(2)
2      2        5       8(0)

The current design is only appropriate for the case where
nentries % nrcpus == 0.

Fix this issue by incrementing the index by (nentries % nrcpus)
each time circular buffer wraps around.

CPU:   Index0:  Index1: Index2:
0      0        3       6+2==8(0)
1      1        4       7+2==9(1)
2      2        5       8+2==10(2)

Change-Id: I4f96eb4c971cc18357e145dabcf4272e466dcda2
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 7ec67867
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -160,10 +160,20 @@ static void uncached_logk_timestamp(int idx)
}

#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
/*
 * Since it is not necessarily true that nentries % step_size == 0,
 * must make appropriate adjustments to the index when a "wraparound"
 * occurs to ensure that msm_rtb.rtb[x] always belongs to the same cpu.
 * It is desired to give all cpus the same number of entries; this leaves
 * (nentries % step_size) dead space at the end of the buffer.
 */
static int msm_rtb_get_idx(void)
{
	int cpu, i, offset;
	atomic_t *index;
	unsigned long flags;
	u32 unused_buffer_size = msm_rtb.nentries % msm_rtb.step_size;
	int adjusted_size;

	/*
	 * ideally we would use get_cpu but this is a close enough
@@ -173,17 +183,24 @@ static int msm_rtb_get_idx(void)

	index = &per_cpu(msm_rtb_idx_cpu, cpu);

	local_irq_save(flags);
	i = atomic_add_return(msm_rtb.step_size, index);
	i -= msm_rtb.step_size;

	/* Check if index has wrapped around */
	offset = (i & (msm_rtb.nentries - 1)) -
		 ((i - msm_rtb.step_size) & (msm_rtb.nentries - 1));
	/*
	 * Check if index has wrapped around or is in the unused region at the
	 * end of the buffer
	 */
	adjusted_size = atomic_read(index) + unused_buffer_size;
	offset = (adjusted_size & (msm_rtb.nentries - 1)) -
		 ((adjusted_size - msm_rtb.step_size) & (msm_rtb.nentries - 1));
	if (offset < 0) {
		uncached_logk_timestamp(i);
		i = atomic_add_return(msm_rtb.step_size, index);
		i = atomic_add_return(msm_rtb.step_size + unused_buffer_size,
									index);
		i -= msm_rtb.step_size;
	}
	local_irq_restore(flags);

	return i;
}