aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-07-02 22:02:31 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-07-02 22:02:31 +0100
commit71faa1d6d8048c3ccee9810fd62b7d0eb212ba0a (patch)
tree63d06fb9008fc8d0a6b736d5cf8e1fa2b7deb181
parentabb57cc4236eb7e707608787167e4748a2265264 (diff)
downloadxen-71faa1d6d8048c3ccee9810fd62b7d0eb212ba0a.tar.gz
xen-71faa1d6d8048c3ccee9810fd62b7d0eb212ba0a.tar.bz2
xen-71faa1d6d8048c3ccee9810fd62b7d0eb212ba0a.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> xen-unstable changeset: 21703:2f3a68a0b55b xen-unstable date: Fri Jul 02 18:52:45 2010 +0100
-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 a87495287c..84e1d4c2f5 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -49,12 +49,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 */
@@ -74,13 +73,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));
}
/**
@@ -99,7 +114,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));
@@ -280,6 +295,10 @@ int trace_will_trace_event(u32 event)
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);