mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Remove page-scrub lists and async scrubbing.
The original user for this was domain destruction. Now that this is preemptible all the way back up to dom0 userspace, asynchrony is better iontroduced at that level, if at all, imo. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
1 parent
4cb90ae29a
commit
428dc303f5
8 files changed
+18
-153
No files matched your search
@@ -718,7 +718,7 @@ long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
|
||||
pi->nr_nodes = num_online_nodes();
|
||||
pi->total_pages = total_pages;
|
||||
pi->free_pages = avail_domheap_pages();
|
||||
pi->scrub_pages = avail_scrub_pages();
|
||||
pi->scrub_pages = 0;
|
||||
pi->cpu_khz = local_cpu_data->proc_freq / 1000;
|
||||
|
||||
pi->max_cpu_id = last_cpu(cpu_online_map);
|
||||
|
||||
@@ -360,7 +360,6 @@ static void continue_cpu_idle_loop(void)
|
||||
#else
|
||||
irq_stat[cpu].idle_timestamp = jiffies;
|
||||
#endif
|
||||
page_scrub_schedule_work();
|
||||
while ( !softirq_pending(cpu) )
|
||||
default_idle();
|
||||
raise_softirq(SCHEDULE_SOFTIRQ);
|
||||
|
||||
@@ -120,7 +120,6 @@ void idle_loop(void)
|
||||
{
|
||||
if ( cpu_is_offline(smp_processor_id()) )
|
||||
play_dead();
|
||||
page_scrub_schedule_work();
|
||||
(*pm_idle)();
|
||||
do_softirq();
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ long arch_do_sysctl(
|
||||
pi->nr_nodes = num_online_nodes();
|
||||
pi->total_pages = total_pages;
|
||||
pi->free_pages = avail_domheap_pages();
|
||||
pi->scrub_pages = avail_scrub_pages();
|
||||
pi->scrub_pages = 0;
|
||||
pi->cpu_khz = cpu_khz;
|
||||
memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
|
||||
if ( hvm_enabled )
|
||||
|
||||
@@ -394,7 +394,6 @@ int domain_kill(struct domain *d)
|
||||
/* fallthrough */
|
||||
case DOMDYING_dying:
|
||||
rc = domain_relinquish_resources(d);
|
||||
page_scrub_kick();
|
||||
if ( rc != 0 )
|
||||
{
|
||||
BUG_ON(rc != -EAGAIN);
|
||||
|
||||
+10
-129
@@ -64,18 +64,6 @@ integer_param("dma_bits", dma_bitsize);
|
||||
#define round_pgdown(_p) ((_p)&PAGE_MASK)
|
||||
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Avoid callers relying on allocations returning zeroed pages. */
|
||||
#define scrub_page(p) memset((p), 0xc2, PAGE_SIZE)
|
||||
#else
|
||||
/* For a production build, clear_page() is the fastest way to scrub. */
|
||||
#define scrub_page(p) clear_page(p)
|
||||
#endif
|
||||
|
||||
static DEFINE_SPINLOCK(page_scrub_lock);
|
||||
PAGE_LIST_HEAD(page_scrub_list);
|
||||
static unsigned long scrub_pages;
|
||||
|
||||
/* Offlined page list, protected by heap_lock. */
|
||||
PAGE_LIST_HEAD(page_offlined_list);
|
||||
/* Broken page list, protected by heap_lock. */
|
||||
@@ -945,7 +933,6 @@ void __init end_boot_allocator(void)
|
||||
*/
|
||||
void __init scrub_heap_pages(void)
|
||||
{
|
||||
void *p;
|
||||
unsigned long mfn;
|
||||
|
||||
if ( !opt_bootscrub )
|
||||
@@ -969,21 +956,7 @@ void __init scrub_heap_pages(void)
|
||||
|
||||
/* Re-check page status with lock held. */
|
||||
if ( !allocated_in_map(mfn) )
|
||||
{
|
||||
if ( is_xen_heap_mfn(mfn) )
|
||||
{
|
||||
p = page_to_virt(mfn_to_page(mfn));
|
||||
memguard_unguard_range(p, PAGE_SIZE);
|
||||
scrub_page(p);
|
||||
memguard_guard_range(p, PAGE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = map_domain_page(mfn);
|
||||
scrub_page(p);
|
||||
unmap_domain_page(p);
|
||||
}
|
||||
}
|
||||
scrub_one_page(mfn_to_page(mfn));
|
||||
|
||||
spin_unlock(&heap_lock);
|
||||
}
|
||||
@@ -1247,10 +1220,7 @@ void free_domheap_pages(struct page_info *pg, unsigned int order)
|
||||
for ( i = 0; i < (1 << order); i++ )
|
||||
{
|
||||
page_set_owner(&pg[i], NULL);
|
||||
spin_lock(&page_scrub_lock);
|
||||
page_list_add(&pg[i], &page_scrub_list);
|
||||
scrub_pages++;
|
||||
spin_unlock(&page_scrub_lock);
|
||||
scrub_one_page(&pg[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1322,98 +1292,21 @@ static __init int pagealloc_keyhandler_init(void)
|
||||
__initcall(pagealloc_keyhandler_init);
|
||||
|
||||
|
||||
|
||||
/*************************
|
||||
* PAGE SCRUBBING
|
||||
*/
|
||||
|
||||
static DEFINE_PER_CPU(struct timer, page_scrub_timer);
|
||||
|
||||
static void page_scrub_softirq(void)
|
||||
{
|
||||
PAGE_LIST_HEAD(list);
|
||||
struct page_info *pg;
|
||||
void *p;
|
||||
int i;
|
||||
s_time_t start = NOW();
|
||||
static spinlock_t serialise_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
/* free_heap_pages() does not parallelise well. Serialise this function. */
|
||||
if ( !spin_trylock(&serialise_lock) )
|
||||
{
|
||||
set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(1));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Aim to do 1ms of work every 10ms. */
|
||||
do {
|
||||
spin_lock(&page_scrub_lock);
|
||||
|
||||
/* Peel up to 16 pages from the list. */
|
||||
for ( i = 0; i < 16; i++ )
|
||||
{
|
||||
if ( !(pg = page_list_remove_head(&page_scrub_list)) )
|
||||
break;
|
||||
page_list_add_tail(pg, &list);
|
||||
}
|
||||
|
||||
if ( unlikely(i == 0) )
|
||||
{
|
||||
spin_unlock(&page_scrub_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
scrub_pages -= i;
|
||||
|
||||
spin_unlock(&page_scrub_lock);
|
||||
|
||||
/* Scrub each page in turn. */
|
||||
while ( (pg = page_list_remove_head(&list)) ) {
|
||||
p = map_domain_page(page_to_mfn(pg));
|
||||
scrub_page(p);
|
||||
unmap_domain_page(p);
|
||||
free_heap_pages(pg, 0);
|
||||
}
|
||||
} while ( (NOW() - start) < MILLISECS(1) );
|
||||
|
||||
set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10));
|
||||
|
||||
out:
|
||||
spin_unlock(&serialise_lock);
|
||||
}
|
||||
|
||||
void scrub_list_splice(struct page_list_head *list)
|
||||
{
|
||||
spin_lock(&page_scrub_lock);
|
||||
page_list_splice(list, &page_scrub_list);
|
||||
spin_unlock(&page_scrub_lock);
|
||||
}
|
||||
|
||||
void scrub_list_add(struct page_info *pg)
|
||||
{
|
||||
spin_lock(&page_scrub_lock);
|
||||
page_list_add(pg, &page_scrub_list);
|
||||
spin_unlock(&page_scrub_lock);
|
||||
}
|
||||
|
||||
void scrub_one_page(struct page_info *pg)
|
||||
{
|
||||
void *p = map_domain_page(page_to_mfn(pg));
|
||||
|
||||
scrub_page(p);
|
||||
#ifndef NDEBUG
|
||||
/* Avoid callers relying on allocations returning zeroed pages. */
|
||||
memset(p, 0xc2, PAGE_SIZE);
|
||||
#else
|
||||
/* For a production build, clear_page() is the fastest way to scrub. */
|
||||
clear_page(p);
|
||||
#endif
|
||||
|
||||
unmap_domain_page(p);
|
||||
}
|
||||
|
||||
static void page_scrub_timer_fn(void *unused)
|
||||
{
|
||||
page_scrub_schedule_work();
|
||||
}
|
||||
|
||||
unsigned long avail_scrub_pages(void)
|
||||
{
|
||||
return scrub_pages;
|
||||
}
|
||||
|
||||
static void dump_heap(unsigned char key)
|
||||
{
|
||||
s_time_t now = NOW();
|
||||
@@ -1439,18 +1332,6 @@ static __init int register_heap_trigger(void)
|
||||
}
|
||||
__initcall(register_heap_trigger);
|
||||
|
||||
|
||||
static __init int page_scrub_init(void)
|
||||
{
|
||||
int cpu;
|
||||
for_each_cpu ( cpu )
|
||||
init_timer(&per_cpu(page_scrub_timer, cpu),
|
||||
page_scrub_timer_fn, NULL, cpu);
|
||||
open_softirq(PAGE_SCRUB_SOFTIRQ, page_scrub_softirq);
|
||||
return 0;
|
||||
}
|
||||
__initcall(page_scrub_init);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -195,12 +195,14 @@ EXPORT unsigned long tmh_page_list_pages = 0;
|
||||
EXPORT void tmh_release_avail_pages_to_host(void)
|
||||
{
|
||||
spin_lock(&tmh_page_list_lock);
|
||||
if ( !page_list_empty(&tmh_page_list) )
|
||||
while ( !page_list_empty(&tmh_page_list) )
|
||||
{
|
||||
scrub_list_splice(&tmh_page_list);
|
||||
INIT_PAGE_LIST_HEAD(&tmh_page_list);
|
||||
tmh_page_list_pages = 0;
|
||||
struct page_info *pg = page_list_first(&tmh_page_list);
|
||||
scrub_one_page(pg);
|
||||
free_domheap_page(pg);
|
||||
}
|
||||
INIT_PAGE_LIST_HEAD(&tmh_page_list);
|
||||
tmh_page_list_pages = 0;
|
||||
spin_unlock(&tmh_page_list_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -299,22 +299,7 @@ page_list_splice(struct page_list_head *list, struct page_list_head *head)
|
||||
# define page_list_splice(list, hd) list_splice(list, hd)
|
||||
#endif
|
||||
|
||||
/* Automatic page scrubbing for dead domains. */
|
||||
extern struct page_list_head page_scrub_list;
|
||||
#define page_scrub_schedule_work() \
|
||||
do { \
|
||||
if ( !page_list_empty(&page_scrub_list) ) \
|
||||
raise_softirq(PAGE_SCRUB_SOFTIRQ); \
|
||||
} while ( 0 )
|
||||
#define page_scrub_kick() \
|
||||
do { \
|
||||
if ( !page_list_empty(&page_scrub_list) ) \
|
||||
cpumask_raise_softirq(cpu_online_map, PAGE_SCRUB_SOFTIRQ); \
|
||||
} while ( 0 )
|
||||
void scrub_list_splice(struct page_list_head *);
|
||||
void scrub_list_add(struct page_info *);
|
||||
void scrub_one_page(struct page_info *);
|
||||
unsigned long avail_scrub_pages(void);
|
||||
|
||||
int guest_remove_page(struct domain *d, unsigned long gmfn);
|
||||
|
||||
|
||||