# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1278104551 -3600
# Node ID e26d53eb32df6227d5e893edea9cb5a2bfa5818f
# Parent b3e6085141005bc3746dbf8149206da5d801fc70
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@xxxxxxxxxx>
Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
xen-unstable changeset: 21703:2f3a68a0b55b
xen-unstable date: Fri Jul 02 18:52:45 2010 +0100
---
xen/common/trace.c | 27 +++++++++++++++++++++++----
1 files changed, 23 insertions(+), 4 deletions(-)
diff -r b3e608514100 -r e26d53eb32df xen/common/trace.c
--- a/xen/common/trace.c Fri Jul 02 19:18:37 2010 +0100
+++ b/xen/common/trace.c Fri Jul 02 22:02:31 2010 +0100
@@ -49,12 +49,11 @@ static struct t_info *t_info;
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_
/* 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 @@ void __init init_trace_bufs(void)
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);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|