ia64/linux-2.6.18-xen.hg

view arch/mips/lib-32/r3k_dump_tlb.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * Dump R3000 TLB for debugging purposes.
3 *
4 * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
5 * Copyright (C) 1999 by Silicon Graphics, Inc.
6 * Copyright (C) 1999 by Harald Koerfgen
7 */
8 #include <linux/kernel.h>
9 #include <linux/mm.h>
10 #include <linux/sched.h>
11 #include <linux/string.h>
13 #include <asm/bootinfo.h>
14 #include <asm/cachectl.h>
15 #include <asm/cpu.h>
16 #include <asm/mipsregs.h>
17 #include <asm/page.h>
18 #include <asm/pgtable.h>
20 extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
22 void dump_tlb(int first, int last)
23 {
24 int i;
25 unsigned int asid;
26 unsigned long entryhi, entrylo0;
28 asid = read_c0_entryhi() & 0xfc0;
30 for (i = first; i <= last; i++) {
31 write_c0_index(i<<8);
32 __asm__ __volatile__(
33 ".set\tnoreorder\n\t"
34 "tlbr\n\t"
35 "nop\n\t"
36 ".set\treorder");
37 entryhi = read_c0_entryhi();
38 entrylo0 = read_c0_entrylo0();
40 /* Unused entries have a virtual address of KSEG0. */
41 if ((entryhi & 0xffffe000) != 0x80000000
42 && (entryhi & 0xfc0) == asid) {
43 /*
44 * Only print entries in use
45 */
46 printk("Index: %2d ", i);
48 printk("va=%08lx asid=%08lx"
49 " [pa=%06lx n=%d d=%d v=%d g=%d]",
50 (entryhi & 0xffffe000),
51 entryhi & 0xfc0,
52 entrylo0 & PAGE_MASK,
53 (entrylo0 & (1 << 11)) ? 1 : 0,
54 (entrylo0 & (1 << 10)) ? 1 : 0,
55 (entrylo0 & (1 << 9)) ? 1 : 0,
56 (entrylo0 & (1 << 8)) ? 1 : 0);
57 }
58 }
59 printk("\n");
61 write_c0_entryhi(asid);
62 }
64 void dump_tlb_all(void)
65 {
66 dump_tlb(0, current_cpu_data.tlbsize - 1);
67 }
69 void dump_tlb_wired(void)
70 {
71 int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
73 printk("Wired: %d", wired);
74 dump_tlb(0, wired - 1);
75 }
77 void dump_tlb_addr(unsigned long addr)
78 {
79 unsigned long flags, oldpid;
80 int index;
82 local_irq_save(flags);
83 oldpid = read_c0_entryhi() & 0xff;
84 write_c0_entryhi((addr & PAGE_MASK) | oldpid);
85 tlb_probe();
86 index = read_c0_index();
87 write_c0_entryhi(oldpid);
88 local_irq_restore(flags);
90 if (index < 0) {
91 printk("No entry for address 0x%08lx in TLB\n", addr);
92 return;
93 }
95 printk("Entry %d maps address 0x%08lx\n", index, addr);
96 dump_tlb(index, index);
97 }
99 void dump_tlb_nonwired(void)
100 {
101 int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
102 dump_tlb(wired, current_cpu_data.tlbsize - 1);
103 }
105 void dump_list_process(struct task_struct *t, void *address)
106 {
107 pgd_t *page_dir, *pgd;
108 pud_t *pud;
109 pmd_t *pmd;
110 pte_t *pte, page;
111 unsigned int addr;
112 unsigned long val;
114 addr = (unsigned int) address;
116 printk("Addr == %08x\n", addr);
117 printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
119 page_dir = pgd_offset(t->mm, 0);
120 printk("page_dir == %08x\n", (unsigned int) page_dir);
122 pgd = pgd_offset(t->mm, addr);
123 printk("pgd == %08x, ", (unsigned int) pgd);
125 pud = pud_offset(pgd, addr);
126 printk("pud == %08x, ", (unsigned int) pud);
128 pmd = pmd_offset(pud, addr);
129 printk("pmd == %08x, ", (unsigned int) pmd);
131 pte = pte_offset(pmd, addr);
132 printk("pte == %08x, ", (unsigned int) pte);
134 page = *pte;
135 printk("page == %08x\n", (unsigned int) pte_val(page));
137 val = pte_val(page);
138 if (val & _PAGE_PRESENT) printk("present ");
139 if (val & _PAGE_READ) printk("read ");
140 if (val & _PAGE_WRITE) printk("write ");
141 if (val & _PAGE_ACCESSED) printk("accessed ");
142 if (val & _PAGE_MODIFIED) printk("modified ");
143 if (val & _PAGE_GLOBAL) printk("global ");
144 if (val & _PAGE_VALID) printk("valid ");
145 printk("\n");
146 }
148 void dump_list_current(void *address)
149 {
150 dump_list_process(current, address);
151 }
153 unsigned int vtop(void *address)
154 {
155 pgd_t *pgd;
156 pud_t *pud;
157 pmd_t *pmd;
158 pte_t *pte;
159 unsigned int addr, paddr;
161 addr = (unsigned long) address;
162 pgd = pgd_offset(current->mm, addr);
163 pud = pud_offset(pgd, addr);
164 pmd = pmd_offset(pud, addr);
165 pte = pte_offset(pmd, addr);
166 paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
167 paddr |= (addr & ~PAGE_MASK);
169 return paddr;
170 }
172 void dump16(unsigned long *p)
173 {
174 int i;
176 for (i = 0; i < 8; i++) {
177 printk("*%08lx == %08lx, ", (unsigned long)p, *p);
178 p++;
179 printk("*%08lx == %08lx\n", (unsigned long)p, *p);
180 p++;
181 }
182 }