ia64/xen-unstable

view xen/arch/ia64/xen/vhpt.c @ 6864:aecdccb1a350

Add additional stats to track VHPT saturation
author djm@kirby.fc.hp.com
date Fri Sep 16 16:54:53 2005 -0600 (2005-09-16)
parents 3ca4ca7a9cc2
children 06d84bf87159
line source
1 /*
2 * Initialize VHPT support.
3 *
4 * Copyright (C) 2004 Hewlett-Packard Co
5 * Dan Magenheimer <dan.magenheimer@hp.com>
6 */
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
11 #include <asm/processor.h>
12 #include <asm/system.h>
13 #include <asm/pgalloc.h>
14 #include <asm/page.h>
15 #include <asm/dma.h>
16 #include <asm/vhpt.h>
18 unsigned long vhpt_paddr, vhpt_pend, vhpt_pte;
20 void vhpt_flush(void)
21 {
22 struct vhpt_lf_entry *v = (void *)VHPT_ADDR;
23 int i, cnt = 0;
24 #if 0
25 static int firsttime = 2;
27 if (firsttime) firsttime--;
28 else {
29 printf("vhpt_flush: *********************************************\n");
30 printf("vhpt_flush: *********************************************\n");
31 printf("vhpt_flush: *********************************************\n");
32 printf("vhpt_flush: flushing vhpt (seems to crash at rid wrap?)...\n");
33 printf("vhpt_flush: *********************************************\n");
34 printf("vhpt_flush: *********************************************\n");
35 printf("vhpt_flush: *********************************************\n");
36 }
37 #endif
38 for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) {
39 v->itir = 0;
40 v->CChain = 0;
41 v->page_flags = 0;
42 v->ti_tag = INVALID_TI_TAG;
43 }
44 // initialize cache too???
45 }
47 #ifdef VHPT_GLOBAL
48 void vhpt_flush_address(unsigned long vadr, unsigned long addr_range)
49 {
50 unsigned long ps;
51 struct vhpt_lf_entry *vlfe;
53 if ((vadr >> 61) == 7) {
54 // no vhpt for region 7 yet, see vcpu_itc_no_srlz
55 printf("vhpt_flush_address: region 7, spinning...\n");
56 while(1);
57 }
58 #if 0
59 // this only seems to occur at shutdown, but it does occur
60 if ((!addr_range) || addr_range & (addr_range - 1)) {
61 printf("vhpt_flush_address: weird range, spinning...\n");
62 while(1);
63 }
64 //printf("************** vhpt_flush_address(%p,%p)\n",vadr,addr_range);
65 #endif
66 while ((long)addr_range > 0) {
67 vlfe = (struct vhpt_lf_entry *)ia64_thash(vadr);
68 // FIXME: for now, just blow it away even if it belongs to
69 // another domain. Later, use ttag to check for match
70 //if (!(vlfe->ti_tag & INVALID_TI_TAG)) {
71 //printf("vhpt_flush_address: blowing away valid tag for vadr=%p\n",vadr);
72 //}
73 vlfe->ti_tag |= INVALID_TI_TAG;
74 addr_range -= PAGE_SIZE;
75 vadr += PAGE_SIZE;
76 }
77 }
78 #endif
80 void vhpt_map(void)
81 {
82 unsigned long psr;
84 psr = ia64_clear_ic();
85 ia64_itr(0x2, IA64_TR_VHPT, VHPT_ADDR, vhpt_pte, VHPT_SIZE_LOG2);
86 ia64_set_psr(psr);
87 ia64_srlz_i();
88 }
90 void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long logps)
91 {
92 unsigned long mask = (1L << logps) - 1;
93 extern long running_on_sim;
94 int i;
96 if (logps-PAGE_SHIFT > 10 && !running_on_sim) {
97 // if this happens, we may want to revisit this algorithm
98 printf("vhpt_multiple_insert:logps-PAGE_SHIFT>10,spinning..\n");
99 while(1);
100 }
101 if (logps-PAGE_SHIFT > 2) {
102 // FIXME: Should add counter here to see how often this
103 // happens (e.g. for 16MB pages!) and determine if it
104 // is a performance problem. On a quick look, it takes
105 // about 39000 instrs for a 16MB page and it seems to occur
106 // only a few times/second, so OK for now.
107 // An alternate solution would be to just insert the one
108 // 16KB in the vhpt (but with the full mapping)?
109 //printf("vhpt_multiple_insert: logps-PAGE_SHIFT==%d,"
110 //"va=%p, pa=%p, pa-masked=%p\n",
111 //logps-PAGE_SHIFT,vaddr,pte&_PFN_MASK,
112 //(pte&_PFN_MASK)&~mask);
113 }
114 vaddr &= ~mask;
115 pte = ((pte & _PFN_MASK) & ~mask) | (pte & ~_PFN_MASK);
116 for (i = 1L << (logps-PAGE_SHIFT); i > 0; i--) {
117 vhpt_insert(vaddr,pte,logps<<2);
118 vaddr += PAGE_SIZE;
119 }
120 }
122 void vhpt_init(void)
123 {
124 unsigned long vhpt_total_size, vhpt_alignment, vhpt_imva;
125 #if !VHPT_ENABLED
126 return;
127 #endif
128 // allocate a huge chunk of physical memory.... how???
129 vhpt_total_size = 1 << VHPT_SIZE_LOG2; // 4MB, 16MB, 64MB, or 256MB
130 vhpt_alignment = 1 << VHPT_SIZE_LOG2; // 4MB, 16MB, 64MB, or 256MB
131 printf("vhpt_init: vhpt size=%p, align=%p\n",vhpt_total_size,vhpt_alignment);
132 /* This allocation only holds true if vhpt table is unique for
133 * all domains. Or else later new vhpt table should be allocated
134 * from domain heap when each domain is created. Assume xen buddy
135 * allocator can provide natural aligned page by order?
136 */
137 vhpt_imva = alloc_xenheap_pages(VHPT_SIZE_LOG2 - PAGE_SHIFT);
138 if (!vhpt_imva) {
139 printf("vhpt_init: can't allocate VHPT!\n");
140 while(1);
141 }
142 vhpt_paddr = __pa(vhpt_imva);
143 vhpt_pend = vhpt_paddr + vhpt_total_size - 1;
144 printf("vhpt_init: vhpt paddr=%p, end=%p\n",vhpt_paddr,vhpt_pend);
145 vhpt_pte = pte_val(pfn_pte(vhpt_paddr >> PAGE_SHIFT, PAGE_KERNEL));
146 vhpt_map();
147 ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
148 VHPT_ENABLED);
149 vhpt_flush();
150 }
153 void zero_vhpt_stats(void)
154 {
155 return;
156 }
158 int dump_vhpt_stats(char *buf)
159 {
160 int i;
161 char *s = buf;
162 struct vhpt_lf_entry *v = (void *)VHPT_ADDR;
163 unsigned long vhpt_valid = 0, vhpt_chains = 0;
165 for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) {
166 if (!(v->ti_tag & INVALID_TI_TAG)) vhpt_valid++;
167 if (v->CChain) vhpt_chains++;
168 }
169 s += sprintf(s,"VHPT usage: %ld/%ld (%ld collision chains)\n",
170 vhpt_valid,VHPT_NUM_ENTRIES,vhpt_chains);
171 return s - buf;
172 }