diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-07-02 22:02:31 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-07-02 22:02:31 +0100 |
commit | 71faa1d6d8048c3ccee9810fd62b7d0eb212ba0a (patch) | |
tree | 63d06fb9008fc8d0a6b736d5cf8e1fa2b7deb181 | |
parent | abb57cc4236eb7e707608787167e4748a2265264 (diff) | |
download | xen-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.c | 27 |
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); |