aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/trace.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-07-02 18:52:45 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-07-02 18:52:45 +0100
commit79fdc7a419bd9f4e46b0d24549e6a6ee894d19d9 (patch)
treeddb3594a6fd19c53e93bd5083bce43e1f95143d7 /xen/common/trace.c
parent6634a6768c1976ccc14aa1dbd59e1091efb73d9d (diff)
downloadxen-79fdc7a419bd9f4e46b0d24549e6a6ee894d19d9.tar.gz
xen-79fdc7a419bd9f4e46b0d24549e6a6ee894d19d9.tar.bz2
xen-79fdc7a419bd9f4e46b0d24549e6a6ee894d19d9.zip
trace: Fix T_INFO_FIRST_OFFSET calculation
This wasn't defined correctly, thus allowing in the num_online_cpus() == NR_CPUS case to pass a corrupted MFN to Dom0. Reported-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
Diffstat (limited to 'xen/common/trace.c')
-rw-r--r--xen/common/trace.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/xen/common/trace.c b/xen/common/trace.c
index 17819d0d69..caf9b7f621 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -50,12 +50,11 @@ integer_param("tbuf_size", opt_tbuf_size);
static struct t_info *t_info;
#define T_INFO_PAGES 2 /* Size fixed at 2 pages for now. */
#define T_INFO_SIZE ((T_INFO_PAGES)*(PAGE_SIZE))
-/* t_info.tbuf_size + list of mfn offsets + 1 to round up / sizeof uint32_t */
-#define T_INFO_FIRST_OFFSET ((sizeof(int16_t) + NR_CPUS * sizeof(int16_t) + 1) / sizeof(uint32_t))
static DEFINE_PER_CPU_READ_MOSTLY(struct t_buf *, t_bufs);
static DEFINE_PER_CPU_READ_MOSTLY(unsigned char *, t_data);
static DEFINE_PER_CPU_READ_MOSTLY(spinlock_t, t_lock);
static int data_size;
+static u32 t_info_first_offset __read_mostly;
/* High water mark for trace buffers; */
/* Send virtual interrupt when buffer level reaches this point */
@@ -75,13 +74,29 @@ static cpumask_t tb_cpu_mask = CPU_MASK_ALL;
/* which tracing events are enabled */
static u32 tb_event_mask = TRC_ALL;
+/* Return the number of elements _type necessary to store at least _x bytes of data
+ * i.e., sizeof(_type) * ans >= _x. */
+#define fit_to_type(_type, _x) (((_x)+sizeof(_type)-1) / sizeof(_type))
+
+static void calc_tinfo_first_offset(void)
+{
+ int offset_in_bytes;
+
+ offset_in_bytes = offsetof(struct t_info, mfn_offset[NR_CPUS]);
+
+ t_info_first_offset = fit_to_type(uint32_t, offset_in_bytes);
+
+ gdprintk(XENLOG_INFO, "%s: NR_CPUs %d, offset_in_bytes %d, t_info_first_offset %u\n",
+ __func__, NR_CPUS, offset_in_bytes, (unsigned)t_info_first_offset);
+}
+
/**
* check_tbuf_size - check to make sure that the proposed size will fit
* in the currently sized struct t_info.
*/
static inline int check_tbuf_size(int size)
{
- return (num_online_cpus() * size + T_INFO_FIRST_OFFSET) > (T_INFO_SIZE / sizeof(uint32_t));
+ return (num_online_cpus() * size + t_info_first_offset) > (T_INFO_SIZE / sizeof(uint32_t));
}
/**
@@ -100,7 +115,7 @@ static int alloc_trace_bufs(void)
unsigned long nr_pages;
/* Start after a fixed-size array of NR_CPUS */
uint32_t *t_info_mfn_list = (uint32_t *)t_info;
- int offset = T_INFO_FIRST_OFFSET;
+ int offset = t_info_first_offset;
BUG_ON(check_tbuf_size(opt_tbuf_size));
@@ -293,6 +308,10 @@ static struct notifier_block cpu_nfb = {
void __init init_trace_bufs(void)
{
int i;
+
+ /* Calculate offset in u32 of first mfn */
+ calc_tinfo_first_offset();
+
/* t_info size fixed at 2 pages for now. That should be big enough / small enough
* until it's worth making it dynamic. */
t_info = alloc_xenheap_pages(1, 0);