mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.119 (3e6c96c2opjGKDx0oCP831RfhP4uDw)
hypervisor.c, network.c: Added locing to page-table update code in Xenolinux. Network driver noew flushed the update queue before pushing new rx buffers.
This commit is contained in:
1 parent
fe98a95d91
commit
696f066a07
2 files changed
+45
-1
No files matched your search
@@ -240,6 +240,11 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
|
||||
np->net_ring->rx_event = RX_RING_INC(np->rx_idx);
|
||||
|
||||
/*
|
||||
* We may have allocated buffers which have entries outstanding in
|
||||
* the page update queue -- make sure we flush those first!
|
||||
*/
|
||||
flush_page_update_queue();
|
||||
HYPERVISOR_net_update();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/*
|
||||
* This suffices to protect us if we ever move to SMP domains.
|
||||
* Further, it protects us against interrupts. At the very least, this is
|
||||
* required for the network driver which flushes the update queue before
|
||||
* pushing new receive buffers.
|
||||
*/
|
||||
static spinlock_t update_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
#define QUEUE_SIZE 2048
|
||||
static page_update_request_t update_queue[QUEUE_SIZE];
|
||||
unsigned int pt_update_queue_idx = 0;
|
||||
@@ -79,7 +87,9 @@ unsigned long pt_baseptr;
|
||||
|
||||
void _flush_page_update_queue(void)
|
||||
{
|
||||
if ( idx == 0 ) return;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
if ( idx == 0 ) goto out;
|
||||
#if PT_UPDATE_DEBUG > 1
|
||||
printk("Flushing %d entries from pt update queue\n", idx);
|
||||
#endif
|
||||
@@ -88,6 +98,8 @@ void _flush_page_update_queue(void)
|
||||
#endif
|
||||
HYPERVISOR_pt_update(update_queue, idx);
|
||||
idx = 0;
|
||||
out:
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
static void increment_index(void)
|
||||
@@ -97,72 +109,99 @@ static void increment_index(void)
|
||||
|
||||
void queue_l1_entry_update(unsigned long ptr, unsigned long val)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
#if PT_UPDATE_DEBUG > 0
|
||||
DEBUG_disallow_pt_read(ptr);
|
||||
#endif
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].val = val;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_l2_entry_update(unsigned long ptr, unsigned long val)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].val = val;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_pt_switch(unsigned long ptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = PGEXT_NEW_BASEPTR;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_tlb_flush(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = PGEXT_TLB_FLUSH;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_invlpg(unsigned long ptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = ptr & PAGE_MASK;
|
||||
update_queue[idx].val |= PGEXT_INVLPG;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_pgd_pin(unsigned long ptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = PGEXT_PIN_L2_TABLE;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_pgd_unpin(unsigned long ptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = PGEXT_UNPIN_TABLE;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_pte_pin(unsigned long ptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = PGEXT_PIN_L1_TABLE;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||
|
||||
void queue_pte_unpin(unsigned long ptr)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&update_lock, flags);
|
||||
update_queue[idx].ptr = phys_to_machine(ptr);
|
||||
update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
|
||||
update_queue[idx].val = PGEXT_UNPIN_TABLE;
|
||||
increment_index();
|
||||
spin_unlock_irqrestore(&update_lock, flags);
|
||||
}
|
||||