diff --git a/.rootkeys b/.rootkeys index da6f19bdda..a0d47907cd 100644 --- a/.rootkeys +++ b/.rootkeys @@ -72,7 +72,6 @@ 4097ba837h2tuiweIWp-voNVzCRI6g linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c 4087cf0d5dudKw_DecIJgOhLlBF_0Q linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c 405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/Makefile -405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c 4097ba83Qy2eafeFUhGhm6_4iMIIDw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/netif.h 3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.26-xen-sparse/arch/xen/kernel/Makefile 4075806dE5mQwlVUf8-t3YXjiMMWDQ linux-2.4.26-xen-sparse/arch/xen/kernel/ctrl_if.c @@ -199,7 +198,7 @@ 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.7-xen-sparse/drivers/xen/evtchn/evtchn.c 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.7-xen-sparse/drivers/xen/net/Kconfig 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.7-xen-sparse/drivers/xen/net/Makefile -40f56239vUsbJCS9tGFfRVi1YZlGEg linux-2.6.7-xen-sparse/drivers/xen/net/network.c +405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.7-xen-sparse/drivers/xen/net/network.c 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/desc.h 40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/e820.h 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/fixmap.h @@ -366,6 +365,33 @@ 40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py 40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py 40c9c469ZqILEQ8x6yWy0_51jopiCg tools/python/xen/xend/server/params.py +40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/xend/sv/DomInfo.py +40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/xend/sv/DomList.py +40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/xend/sv/GenTabbed.py +40fcefb2QZAn3u3sX-M7NXBjOv5HGg tools/python/xen/xend/sv/HTMLBase.py +40fcefb2vnfDbl4w_yCTedROPuqs0g tools/python/xen/xend/sv/Main.py +40fcefb2K1xqVVT4D-p7nL2GzS4scg tools/python/xen/xend/sv/Main.rpy +40fcefb24h-04WaHag-Tg4nxWPhTig tools/python/xen/xend/sv/NodeInfo.py +40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/xend/sv/TabView.py +40fcefb23s0sQlDfl4sPP0Un8oZGhg tools/python/xen/xend/sv/XendClientDeferred.py +40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/xend/sv/__init__.py +40fcefb2Nhe-sT74KBB_3mYQg9Dl4Q tools/python/xen/xend/sv/images/internet copy.jpg +40fcefb2QmVa4xdjdnSTXEdF2fZCDA tools/python/xen/xend/sv/images/internet.jpg +40fcefb2g8Ez5jJIPHGN_KX7GtxV4w tools/python/xen/xend/sv/images/internet.psd +40fcefb3wXQMsl9WkgQAVtdrupm4sw tools/python/xen/xend/sv/images/left-end-highlight.jpg +40fcefb3K6ESt5sQhD9aCQRscQIlXQ tools/python/xen/xend/sv/images/left-end-no-highlight.jpg +40fcefb3BUT98zPzW8kAFKuxGdh4XA tools/python/xen/xend/sv/images/middle-highlight.jpg +40fcefb38OTgsUKHBpwshLLIsiIaCA tools/python/xen/xend/sv/images/middle-no-highlight.jpg +40fcefb32SPtrw36c4S6YGFlLvkKuw tools/python/xen/xend/sv/images/orb_01.jpg +40fcefb3Ok5qkX3iM7ZEPVkRInrUpg tools/python/xen/xend/sv/images/orb_02.jpg +40fcefb3JnT5XeKTuVF4yUMGOtuNZg tools/python/xen/xend/sv/images/right-end-highlight.jpg +40fcefb3-DuYOS7noo2W7b_0p7TOUg tools/python/xen/xend/sv/images/right-end-no-highlight.jpg +40fcefb3qNbAZR5FYGPAZ9sFPVMTDA tools/python/xen/xend/sv/images/seperator-left-highlight.jpg +40fcefb3dgsa24WLk_BJeYQHrDLuOg tools/python/xen/xend/sv/images/seperator-right-highlight.jpg +40fcefb3FtiX4Pd2kT8wDlp8u8xRhQ tools/python/xen/xend/sv/images/seperator.jpg +40fcefb3yMSrZvApO9ToIi-iQwnchA tools/python/xen/xend/sv/images/xen.png +40fcefb3zGC9XNBkSwTEobCoq8YClA tools/python/xen/xend/sv/inc/style.css +40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/xend/sv/util.py 40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py 40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py 40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c index 7d7b006cf2..5ee794bc17 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/main.c @@ -93,7 +93,8 @@ static void fast_flush_area(int idx, int nr_pages) } mcl[nr_pages-1].args[2] = UVMF_FLUSH_TLB; - (void)HYPERVISOR_multicall(mcl, nr_pages); + if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) ) + BUG(); } @@ -402,7 +403,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) phys_seg[i].buffer >> PAGE_SHIFT; } - (void)HYPERVISOR_multicall(mcl, nr_psegs); + if ( unlikely(HYPERVISOR_multicall(mcl, nr_psegs) != 0) ) + BUG(); for ( i = 0; i < nr_psegs; i++ ) { diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c index 851cc30285..4dd55168a2 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c @@ -73,10 +73,7 @@ static void __refresh_mfn_list(void) int ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC); if ( unlikely(ret != MAX_MFN_ALLOC) ) - { - printk(KERN_ALERT "Unable to increase memory reservation (%d)\n", ret); BUG(); - } alloc_index = MAX_MFN_ALLOC; } @@ -97,8 +94,8 @@ static void dealloc_mfn(unsigned long mfn) spin_lock_irqsave(&mfn_lock, flags); if ( alloc_index != MAX_MFN_ALLOC ) mfn_list[alloc_index++] = mfn; - else - (void)HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, &mfn, 1); + else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, &mfn, 1) != 1 ) + BUG(); spin_unlock_irqrestore(&mfn_lock, flags); } @@ -238,7 +235,8 @@ static void net_rx_action(unsigned long unused) return; mcl[-2].args[2] = UVMF_FLUSH_TLB; - (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); + if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) ) + BUG(); mcl = rx_mcl; mmu = rx_mmu; @@ -252,31 +250,27 @@ static void net_rx_action(unsigned long unused) mdata = ((mmu[2].ptr & PAGE_MASK) | ((unsigned long)skb->data & ~PAGE_MASK)); + phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn; + + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->frag_list = NULL; + + netif->stats.rx_bytes += size; + netif->stats.rx_packets++; + + /* The update_va_mapping() must not fail. */ + if ( unlikely(mcl[0].args[5] != 0) ) + BUG(); + /* Check the reassignment error code. */ + status = NETIF_RSP_OKAY; if ( unlikely(mcl[1].args[5] != 0) ) { - DPRINTK("Failed MMU update transferring to DOM%u\n", - netif->domid); - (void)HYPERVISOR_update_va_mapping( - (unsigned long)skb->head >> PAGE_SHIFT, - (pte_t) { (mdata & PAGE_MASK) | __PAGE_KERNEL }, - UVMF_INVLPG); - dealloc_mfn(new_mfn); + DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid); + dealloc_mfn(mdata >> PAGE_SHIFT); status = NETIF_RSP_ERROR; } - else - { - phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn; - - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; - - netif->stats.rx_bytes += size; - netif->stats.rx_packets++; - - status = NETIF_RSP_OKAY; - } evtchn = netif->evtchn; id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; @@ -380,14 +374,15 @@ static void net_tx_action(unsigned long unused) NETIF_RING_IDX i; struct page *page; multicall_entry_t *mcl; + PEND_RING_IDX dc, dp; - if ( (i = dealloc_cons) == dealloc_prod ) + if ( (dc = dealloc_cons) == (dp = dealloc_prod) ) goto skip_dealloc; mcl = tx_mcl; - while ( i != dealloc_prod ) + while ( dc != dp ) { - pending_idx = dealloc_ring[MASK_PEND_IDX(i++)]; + pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; mcl[0].op = __HYPERVISOR_update_va_mapping; mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT; mcl[0].args[1] = 0; @@ -396,10 +391,16 @@ static void net_tx_action(unsigned long unused) } mcl[-1].args[2] = UVMF_FLUSH_TLB; - (void)HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl); + if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) ) + BUG(); - while ( dealloc_cons != dealloc_prod ) + mcl = tx_mcl; + while ( dealloc_cons != dp ) { + /* The update_va_mapping() must not fail. */ + if ( unlikely(mcl[0].args[5] != 0) ) + BUG(); + pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; netif = pending_tx_info[pending_idx].netif; @@ -421,6 +422,8 @@ static void net_tx_action(unsigned long unused) add_to_net_schedule_list_tail(netif); netif_put(netif); + + mcl++; } skip_dealloc: @@ -495,7 +498,7 @@ static void net_tx_action(unsigned long unused) pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - if ( unlikely((skb = dev_alloc_skb(PKT_PROT_LEN)) == NULL) ) + if ( unlikely((skb = alloc_skb(PKT_PROT_LEN+16, GFP_ATOMIC)) == NULL) ) { DPRINTK("Can't allocate a skb in start_xmit.\n"); make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); @@ -503,6 +506,9 @@ static void net_tx_action(unsigned long unused) break; } + /* Packets passed to netif_rx() must have some headroom. */ + skb_reserve(skb, 16); + mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain; mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT; mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL; @@ -526,7 +532,8 @@ static void net_tx_action(unsigned long unused) if ( mcl == tx_mcl ) return; - (void)HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl); + if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) ) + BUG(); mcl = tx_mcl; while ( (skb = __skb_dequeue(&tx_queue)) != NULL ) diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c deleted file mode 100644 index ff75096bd8..0000000000 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c +++ /dev/null @@ -1,867 +0,0 @@ -/****************************************************************************** - * arch/xen/drivers/netif/frontend/main.c - * - * Virtual network driver for conversing with remote driver backends. - * - * Copyright (c) 2002-2004, K A Fraser - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include "../netif.h" - -#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */ - -static void network_tx_buf_gc(struct net_device *dev); -static void network_alloc_rx_buffers(struct net_device *dev); - -static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE]; -static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1]; -static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; - -static struct list_head dev_list; - -struct net_private -{ - struct list_head list; - struct net_device *dev; - - struct net_device_stats stats; - NETIF_RING_IDX rx_resp_cons, tx_resp_cons; - unsigned int tx_full; - - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; - - spinlock_t tx_lock; - spinlock_t rx_lock; - - unsigned int handle; - unsigned int evtchn; - unsigned int irq; - - /* What is the status of our connection to the remote backend? */ -#define BEST_CLOSED 0 -#define BEST_DISCONNECTED 1 -#define BEST_CONNECTED 2 - unsigned int backend_state; - - /* Is this interface open or closed (down or up)? */ -#define UST_CLOSED 0 -#define UST_OPEN 1 - unsigned int user_state; - - /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. - */ - struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; -}; - -/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ -#define ADD_ID_TO_FREELIST(_list, _id) \ - (_list)[(_id)] = (_list)[0]; \ - (_list)[0] = (void *)(unsigned long)(_id); -#define GET_ID_FROM_FREELIST(_list) \ - ({ unsigned long _id = (unsigned long)(_list)[0]; \ - (_list)[0] = (_list)[_id]; \ - (unsigned short)_id; }) - -static struct net_device *find_dev_by_handle(unsigned int handle) -{ - struct list_head *ent; - struct net_private *np; - list_for_each ( ent, &dev_list ) - { - np = list_entry(ent, struct net_private, list); - if ( np->handle == handle ) - return np->dev; - } - return NULL; -} - -/** Network interface info. */ -struct netif_ctrl { - /** Number of interfaces. */ - int interface_n; - /** Number of connected interfaces. */ - int connected_n; - /** Error code. */ - int err; -}; - -static struct netif_ctrl netctrl; - -static void netctrl_init(void) -{ - memset(&netctrl, 0, sizeof(netctrl)); - netctrl.interface_n = -1; -} - -/** Get or set a network interface error. - */ -static int netctrl_err(int err) -{ - if(err < 0 && !netctrl.err){ - netctrl.err = err; - printk(KERN_WARNING "%s> err=%d\n", __FUNCTION__, err); - } - return netctrl.err; -} - -/** Test if all network interfaces are connected. - * - * @return 1 if all connected, 0 if not, negative error code otherwise - */ -static int netctrl_connected(void) -{ - int ok = 0; - ok = (netctrl.err ? netctrl.err : - (netctrl.connected_n == netctrl.interface_n)); - return ok; -} - -/** Count the connected network interfaces. - * - * @return connected count - */ -static int netctrl_connected_count(void) -{ - - struct list_head *ent; - struct net_private *np; - unsigned int connected; - - connected = 0; - - list_for_each(ent, &dev_list) - { - np = list_entry(ent, struct net_private, list); - if ( np->backend_state == BEST_CONNECTED ) - connected++; - } - - netctrl.connected_n = connected; - return connected; -} - -static int network_open(struct net_device *dev) -{ - struct net_private *np = dev->priv; - - memset(&np->stats, 0, sizeof(np->stats)); - - np->user_state = UST_OPEN; - - network_alloc_rx_buffers(dev); - np->rx->event = np->rx_resp_cons + 1; - - netif_start_queue(dev); - - return 0; -} - - -static void network_tx_buf_gc(struct net_device *dev) -{ - NETIF_RING_IDX i, prod; - unsigned short id; - struct net_private *np = dev->priv; - struct sk_buff *skb; - - if ( np->backend_state != BEST_CONNECTED ) - return; - - do { - prod = np->tx->resp_prod; - - for ( i = np->tx_resp_cons; i != prod; i++ ) - { - id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; - skb = np->tx_skbs[id]; - ADD_ID_TO_FREELIST(np->tx_skbs, id); - dev_kfree_skb_any(skb); - } - - np->tx_resp_cons = prod; - - /* - * Set a new event, then check for race with update of tx_cons. Note - * that it is essential to schedule a callback, no matter how few - * buffers are pending. Even if there is space in the transmit ring, - * higher layers may be blocked because too much data is outstanding: - * in such cases notification from Xen is likely to be the only kick - * that we'll get. - */ - np->tx->event = - prod + ((np->tx->req_prod - prod) >> 1) + 1; - mb(); - } - while ( prod != np->tx->resp_prod ); - - if ( np->tx_full && - ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE) ) - { - np->tx_full = 0; - if ( np->user_state == UST_OPEN ) - netif_wake_queue(dev); - } -} - - -static void network_alloc_rx_buffers(struct net_device *dev) -{ - unsigned short id; - struct net_private *np = dev->priv; - struct sk_buff *skb; - NETIF_RING_IDX i = np->rx->req_prod; - int nr_pfns = 0; - - /* Make sure the batch is large enough to be worthwhile (1/2 ring). */ - if ( unlikely((i - np->rx_resp_cons) > (NETIF_RX_RING_SIZE/2)) || - unlikely(np->backend_state != BEST_CONNECTED) ) - return; - - do { - skb = dev_alloc_skb(RX_BUF_SIZE); - if ( unlikely(skb == NULL) ) - break; - - skb->dev = dev; - - if ( unlikely(((unsigned long)skb->head & (PAGE_SIZE-1)) != 0) ) - panic("alloc_skb needs to provide us page-aligned buffers."); - - id = GET_ID_FROM_FREELIST(np->rx_skbs); - - np->rx_skbs[id] = skb; - - np->rx->ring[MASK_NETIF_RX_IDX(i)].req.id = id; - - rx_pfn_array[nr_pfns] = virt_to_machine(skb->head) >> PAGE_SHIFT; - - rx_mcl[nr_pfns].op = __HYPERVISOR_update_va_mapping; - rx_mcl[nr_pfns].args[0] = (unsigned long)skb->head >> PAGE_SHIFT; - rx_mcl[nr_pfns].args[1] = 0; - rx_mcl[nr_pfns].args[2] = 0; - - nr_pfns++; - } - while ( (++i - np->rx_resp_cons) != NETIF_RX_RING_SIZE ); - - /* - * We may have allocated buffers which have entries outstanding in the page - * update queue -- make sure we flush those first! - */ - flush_page_update_queue(); - - /* After all PTEs have been zapped we blow away stale TLB entries. */ - rx_mcl[nr_pfns-1].args[2] = UVMF_FLUSH_TLB; - - /* Give away a batch of pages. */ - rx_mcl[nr_pfns].op = __HYPERVISOR_dom_mem_op; - rx_mcl[nr_pfns].args[0] = MEMOP_decrease_reservation; - rx_mcl[nr_pfns].args[1] = (unsigned long)rx_pfn_array; - rx_mcl[nr_pfns].args[2] = (unsigned long)nr_pfns; - - /* Zap PTEs and give away pages in one big multicall. */ - (void)HYPERVISOR_multicall(rx_mcl, nr_pfns+1); - - /* Check return status of HYPERVISOR_dom_mem_op(). */ - if ( rx_mcl[nr_pfns].args[5] != nr_pfns ) - panic("Unable to reduce memory reservation\n"); - - np->rx->req_prod = i; -} - - -static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned short id; - struct net_private *np = (struct net_private *)dev->priv; - netif_tx_request_t *tx; - NETIF_RING_IDX i; - - if ( unlikely(np->tx_full) ) - { - printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name); - netif_stop_queue(dev); - return -ENOBUFS; - } - - if ( unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= - PAGE_SIZE) ) - { - struct sk_buff *new_skb = dev_alloc_skb(RX_BUF_SIZE); - if ( unlikely(new_skb == NULL) ) - return 1; - skb_put(new_skb, skb->len); - memcpy(new_skb->data, skb->data, skb->len); - dev_kfree_skb(skb); - skb = new_skb; - } - - spin_lock_irq(&np->tx_lock); - - if ( np->backend_state != BEST_CONNECTED ) - { - spin_unlock_irq(&np->tx_lock); - return 1; - } - - i = np->tx->req_prod; - - id = GET_ID_FROM_FREELIST(np->tx_skbs); - np->tx_skbs[id] = skb; - - tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; - - tx->id = id; - tx->addr = virt_to_machine(skb->data); - tx->size = skb->len; - - wmb(); - np->tx->req_prod = i + 1; - - network_tx_buf_gc(dev); - - if ( (i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1) ) - { - np->tx_full = 1; - netif_stop_queue(dev); - } - - spin_unlock_irq(&np->tx_lock); - - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - - /* Only notify Xen if there are no outstanding responses. */ - mb(); - if ( np->tx->resp_prod == i ) - notify_via_evtchn(np->evtchn); - - return 0; -} - - -static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs) -{ - struct net_device *dev = dev_id; - struct net_private *np = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&np->tx_lock, flags); - network_tx_buf_gc(dev); - spin_unlock_irqrestore(&np->tx_lock, flags); - - if ( (np->rx_resp_cons != np->rx->resp_prod) && - (np->user_state == UST_OPEN) ) - netif_rx_schedule(dev); -} - - -static int netif_poll(struct net_device *dev, int *pbudget) -{ - struct net_private *np = dev->priv; - struct sk_buff *skb; - netif_rx_response_t *rx; - NETIF_RING_IDX i; - mmu_update_t *mmu = rx_mmu; - multicall_entry_t *mcl = rx_mcl; - int work_done, budget, more_to_do = 1; - struct sk_buff_head rxq; - unsigned long flags; - - spin_lock(&np->rx_lock); - - if ( np->backend_state != BEST_CONNECTED ) - { - spin_unlock(&np->rx_lock); - return 0; - } - - skb_queue_head_init(&rxq); - - if ( (budget = *pbudget) > dev->quota ) - budget = dev->quota; - - for ( i = np->rx_resp_cons, work_done = 0; - (i != np->rx->resp_prod) && (work_done < budget); - i++, work_done++ ) - { - rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; - - skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); - - if ( unlikely(rx->status <= 0) ) - { - /* Gate this error. We get a (valid) slew of them on suspend. */ - if ( np->user_state != UST_OPEN ) - printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status); - dev_kfree_skb(skb); - continue; - } - - skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK); - skb_put(skb, rx->status); - - np->stats.rx_packets++; - np->stats.rx_bytes += rx->status; - - /* Remap the page. */ - mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; - mmu->val = __pa(skb->head) >> PAGE_SHIFT; - mmu++; - mcl->op = __HYPERVISOR_update_va_mapping; - mcl->args[0] = (unsigned long)skb->head >> PAGE_SHIFT; - mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL; - mcl->args[2] = 0; - mcl++; - - phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = - rx->addr >> PAGE_SHIFT; - - __skb_queue_tail(&rxq, skb); - } - - /* Do all the remapping work, and M->P updates, in one big hypercall. */ - if ( likely((mcl - rx_mcl) != 0) ) - { - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; - mcl->args[2] = 0; - mcl++; - (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); - } - - while ( (skb = __skb_dequeue(&rxq)) != NULL ) - { - /* Set the shared-info area, which is hidden behind the real data. */ - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; - - /* Ethernet-specific work. Delayed to here as it peeks the header. */ - skb->protocol = eth_type_trans(skb, dev); - - /* Pass it up. */ - netif_rx(skb); - dev->last_rx = jiffies; - } - - np->rx_resp_cons = i; - - network_alloc_rx_buffers(dev); - - *pbudget -= work_done; - dev->quota -= work_done; - - if ( work_done < budget ) - { - local_irq_save(flags); - - np->rx->event = i + 1; - - /* Deal with hypervisor racing our resetting of rx_event. */ - mb(); - if ( np->rx->resp_prod == i ) - { - __netif_rx_complete(dev); - more_to_do = 0; - } - - local_irq_restore(flags); - } - - spin_unlock(&np->rx_lock); - - return more_to_do; -} - - -static int network_close(struct net_device *dev) -{ - struct net_private *np = dev->priv; - np->user_state = UST_CLOSED; - netif_stop_queue(np->dev); - return 0; -} - - -static struct net_device_stats *network_get_stats(struct net_device *dev) -{ - struct net_private *np = (struct net_private *)dev->priv; - return &np->stats; -} - - -static void network_connect(struct net_device *dev, - netif_fe_interface_status_changed_t *status) -{ - struct net_private *np; - int i, requeue_idx; - netif_tx_request_t *tx; - - np = dev->priv; - spin_lock_irq(&np->rx_lock); - spin_lock(&np->tx_lock); - - /* Recovery procedure: */ - - /* Step 1: Reinitialise variables. */ - np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; - np->rx->event = 1; - - /* Step 2: Rebuild the RX and TX ring contents. - * NB. We could just free the queued TX packets now but we hope - * that sending them out might do some good. We have to rebuild - * the RX ring because some of our pages are currently flipped out - * so we can't just free the RX skbs. - * NB2. Freelist index entries are always going to be less than - * __PAGE_OFFSET, whereas pointers to skbs will always be equal or - * greater than __PAGE_OFFSET: we use this property to distinguish - * them. - */ - - /* Rebuild the TX buffer freelist and the TX ring itself. - * NB. This reorders packets. We could keep more private state - * to avoid this but maybe it doesn't matter so much given the - * interface has been down. - */ - for ( requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++ ) - { - if ( (unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET ) - { - struct sk_buff *skb = np->tx_skbs[i]; - - tx = &np->tx->ring[requeue_idx++].req; - - tx->id = i; - tx->addr = virt_to_machine(skb->data); - tx->size = skb->len; - - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - } - } - wmb(); - np->tx->req_prod = requeue_idx; - - /* Rebuild the RX buffer freelist and the RX ring itself. */ - for ( requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++ ) - if ( (unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET ) - np->rx->ring[requeue_idx++].req.id = i; - wmb(); - np->rx->req_prod = requeue_idx; - - /* Step 3: All public and private state should now be sane. Get - * ready to start sending and receiving packets and give the driver - * domain a kick because we've probably just requeued some - * packets. - */ - np->backend_state = BEST_CONNECTED; - notify_via_evtchn(status->evtchn); - network_tx_buf_gc(dev); - - if ( np->user_state == UST_OPEN ) - netif_start_queue(dev); - - spin_unlock(&np->tx_lock); - spin_unlock_irq(&np->rx_lock); -} - -static void netif_status_change(netif_fe_interface_status_changed_t *status) -{ - ctrl_msg_t cmsg; - netif_fe_interface_connect_t up; - struct net_device *dev; - struct net_private *np; - - if ( netctrl.interface_n <= 0 ) - { - printk(KERN_WARNING "Status change: no interfaces\n"); - return; - } - - dev = find_dev_by_handle(status->handle); - if(!dev){ - printk(KERN_WARNING "Status change: invalid netif handle %u\n", - status->handle); - return; - } - np = dev->priv; - - switch ( status->status ) - { - case NETIF_INTERFACE_STATUS_DESTROYED: - printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n", - np->backend_state); - break; - - case NETIF_INTERFACE_STATUS_DISCONNECTED: - if ( np->backend_state != BEST_CLOSED ) - { - printk(KERN_WARNING "Unexpected netif-DISCONNECTED message" - " in state %d\n", np->backend_state); - printk(KERN_INFO "Attempting to reconnect network interface\n"); - - /* Begin interface recovery. - * - * NB. Whilst we're recovering, we turn the carrier state off. We - * take measures to ensure that this device isn't used for - * anything. We also stop the queue for this device. Various - * different approaches (e.g. continuing to buffer packets) have - * been tested but don't appear to improve the overall impact on - * TCP connections. - * - * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery - * is initiated by a special "RESET" message - disconnect could - * just mean we're not allowed to use this interface any more. - */ - - /* Stop old i/f to prevent errors whilst we rebuild the state. */ - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); - netif_stop_queue(dev); - np->backend_state = BEST_DISCONNECTED; - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); - - /* Free resources. */ - free_irq(np->irq, dev); - unbind_evtchn_from_irq(np->evtchn); - free_page((unsigned long)np->tx); - free_page((unsigned long)np->rx); - } - - /* Move from CLOSED to DISCONNECTED state. */ - np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); - np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); - memset(np->tx, 0, PAGE_SIZE); - memset(np->rx, 0, PAGE_SIZE); - np->backend_state = BEST_DISCONNECTED; - - /* Construct an interface-CONNECT message for the domain controller. */ - cmsg.type = CMSG_NETIF_FE; - cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT; - cmsg.length = sizeof(netif_fe_interface_connect_t); - up.handle = status->handle; - up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT; - up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT; - memcpy(cmsg.msg, &up, sizeof(up)); - - /* Tell the controller to bring up the interface. */ - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - break; - - case NETIF_INTERFACE_STATUS_CONNECTED: - if ( np->backend_state == BEST_CLOSED ) - { - printk(KERN_WARNING "Unexpected netif-CONNECTED message" - " in state %d\n", np->backend_state); - break; - } - - memcpy(dev->dev_addr, status->mac, ETH_ALEN); - - network_connect(dev, status); - - np->evtchn = status->evtchn; - np->irq = bind_evtchn_to_irq(np->evtchn); - (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, - dev->name, dev); - - netctrl_connected_count(); - break; - - default: - printk(KERN_WARNING "Status change to unknown value %d\n", - status->status); - break; - } -} - -/** Create a network device. - * @param handle device handle - * @param val return parameter for created device - * @return 0 on success, error code otherwise - */ -static int create_netdev(int handle, struct net_device **val) -{ - int i, err = 0; - struct net_device *dev = NULL; - struct net_private *np = NULL; - - if ( (dev = alloc_etherdev(sizeof(struct net_private))) == NULL ) - { - printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__); - err = -ENOMEM; - goto exit; - } - - np = dev->priv; - np->backend_state = BEST_CLOSED; - np->user_state = UST_CLOSED; - np->handle = handle; - - spin_lock_init(&np->tx_lock); - spin_lock_init(&np->rx_lock); - - /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ - for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ ) - np->tx_skbs[i] = (void *)(i+1); - for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ ) - np->rx_skbs[i] = (void *)(i+1); - - dev->open = network_open; - dev->hard_start_xmit = network_start_xmit; - dev->stop = network_close; - dev->get_stats = network_get_stats; - dev->poll = netif_poll; - dev->weight = 64; - - if ( (err = register_netdev(dev)) != 0 ) - { - printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err); - goto exit; - } - np->dev = dev; - list_add(&np->list, &dev_list); - - exit: - if ( (err != 0) && (dev != NULL ) ) - kfree(dev); - else if ( val != NULL ) - *val = dev; - return err; -} - -/* - * Initialize the network control interface. Set the number of network devices - * and create them. - */ -static void netif_driver_status_change( - netif_fe_driver_status_changed_t *status) -{ - int err = 0; - int i; - - netctrl.interface_n = status->nr_interfaces; - netctrl.connected_n = 0; - - for ( i = 0; i < netctrl.interface_n; i++ ) - { - if ( (err = create_netdev(i, NULL)) != 0 ) - { - netctrl_err(err); - break; - } - } -} - -static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - int respond = 1; - - switch ( msg->subtype ) - { - case CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED: - if ( msg->length != sizeof(netif_fe_interface_status_changed_t) ) - goto error; - netif_status_change((netif_fe_interface_status_changed_t *) - &msg->msg[0]); - break; - - case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED: - if ( msg->length != sizeof(netif_fe_driver_status_changed_t) ) - goto error; - netif_driver_status_change((netif_fe_driver_status_changed_t *) - &msg->msg[0]); - /* Message is a response */ - respond = 0; - break; - - error: - default: - msg->length = 0; - break; - } - - if ( respond ) - ctrl_if_send_response(msg); -} - - -static int __init netif_init(void) -{ - ctrl_msg_t cmsg; - netif_fe_driver_status_changed_t st; - int err = 0, wait_i, wait_n = 20; - - if ( (start_info.flags & SIF_INITDOMAIN) || - (start_info.flags & SIF_NET_BE_DOMAIN) ) - return 0; - - printk("Initialising Xen virtual ethernet frontend driver"); - - INIT_LIST_HEAD(&dev_list); - - netctrl_init(); - - (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); - - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_NETIF_FE; - cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED; - cmsg.length = sizeof(netif_fe_driver_status_changed_t); - st.status = NETIF_DRIVER_STATUS_UP; - st.nr_interfaces = 0; - memcpy(cmsg.msg, &st, sizeof(st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - - /* Wait for all interfaces to be connected. */ - for ( wait_i = 0; ; wait_i++) - { - if ( (err = (wait_i < wait_n) ? netctrl_connected() : -ENETDOWN) != 0 ) - { - err = (err > 0) ? 0 : err; - break; - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if ( err ) - ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx); - - return err; -} - -__initcall(netif_init); diff --git a/linux-2.4.26-xen-sparse/mkbuildtree b/linux-2.4.26-xen-sparse/mkbuildtree index 5dba6c03d5..7cdc0af60d 100755 --- a/linux-2.4.26-xen-sparse/mkbuildtree +++ b/linux-2.4.26-xen-sparse/mkbuildtree @@ -225,5 +225,5 @@ ln -sf ../../i386/mm/extable.c ln -sf ../../i386/mm/pageattr.c cd ../drivers/console ln -sf ../../../../${LINUX_26}/drivers/xen/console/console.c -#cd ../netif/frontend -#ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c +cd ../netif/frontend +ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c diff --git a/linux-2.6.7-xen-sparse/arch/xen/Kconfig b/linux-2.6.7-xen-sparse/arch/xen/Kconfig index 659a577755..b102b2e183 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/Kconfig +++ b/linux-2.6.7-xen-sparse/arch/xen/Kconfig @@ -16,6 +16,10 @@ config ARCH_XEN default y +config NO_IDLE_HZ + bool + default y + source "init/Kconfig" #config VT diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/time.c b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/time.c index 66b1aff9d9..c6fa43f378 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/time.c +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/time.c @@ -87,6 +87,17 @@ EXPORT_SYMBOL(i8253_lock); struct timer_opts *cur_timer = &timer_none; +/* These are peridically updated in shared_info, and then copied here. */ +static u32 shadow_tsc_stamp; +static u64 shadow_system_time; +static u32 shadow_time_version; +static struct timeval shadow_tv; + +/* Keep track of last time we did processing/updating of jiffies and xtime. */ +static u64 processed_system_time; /* System time (ns) at last processing. */ + +#define NS_PER_TICK (1000000000ULL/HZ) + /* * This version of gettimeofday has microsecond resolution * and better than microsecond precision on fast x86 machines with TSC. @@ -203,6 +214,24 @@ unsigned long long monotonic_clock(void) EXPORT_SYMBOL(monotonic_clock); +/* + * Reads a consistent set of time-base values from Xen, into a shadow data + * area. Must be called with the xtime_lock held for writing. + */ +static void __get_time_values_from_xen(void) +{ + do { + shadow_time_version = HYPERVISOR_shared_info->time_version2; + rmb(); + shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec; + shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec; + shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp.tsc_bits; + shadow_system_time = HYPERVISOR_shared_info->system_time; + rmb(); + } + while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 ); +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -210,6 +239,9 @@ EXPORT_SYMBOL(monotonic_clock); static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + s64 delta; + unsigned long ticks = 0; + #ifdef CONFIG_X86_IO_APIC if (timer_ack) { /* @@ -226,7 +258,23 @@ static inline void do_timer_interrupt(int irq, void *dev_id, } #endif - do_timer_interrupt_hook(regs); + __get_time_values_from_xen(); + + delta = (s64)(shadow_system_time - processed_system_time); + if (delta < 0) { + printk("Timer ISR: Time went backwards: %lld\n", delta); + return; + } + + /* Process elapsed jiffies since last call. */ + while (delta >= NS_PER_TICK) { + ticks++; + delta -= NS_PER_TICK; + processed_system_time += NS_PER_TICK; + + if (regs) + do_timer_interrupt_hook(regs); + } #if 0 /* XEN PRIV */ /* @@ -288,8 +336,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) cur_timer->mark_offset(); - if (regs) /* XXXcl check regs in do_timer_interrupt */ - do_timer_interrupt(irq, NULL, regs); + do_timer_interrupt(irq, NULL, regs); write_sequnlock(&xtime_lock); return IRQ_HANDLED; @@ -410,3 +457,45 @@ void __init time_init(void) (void)setup_irq(time_irq, &irq_timer); } + +/* Convert jiffies to system time. Call with xtime_lock held for reading. */ +static inline u64 __jiffies_to_st(unsigned long j) +{ + return processed_system_time + ((j - jiffies) * NS_PER_TICK); +} + +/* + * This function works out when the the next timer function has to be + * executed (by looking at the timer list) and sets the Xen one-shot + * domain timer to the appropriate value. This is typically called in + * cpu_idle() before the domain blocks. + * + * The function returns a non-0 value on error conditions. + * + * It must be called with interrupts disabled. + */ +extern spinlock_t timerlist_lock; +int set_timeout_timer(void) +{ + u64 alarm = 0; + int ret = 0; + int cpu = smp_processor_id(); + + spin_lock(&timerlist_lock); + + /* + * This is safe against long blocking (since calculations are not based on + * TSC deltas). It is also safe against warped system time since + * suspend-resume is cooperative and we would first get locked out. It is + * safe against normal updates of jiffies since interrupts are off. + */ + alarm = __jiffies_to_st(next_timer_interrupt()); + + /* Failure is pretty bad, but we'd best soldier on. */ + if ( HYPERVISOR_set_timer_op(alarm) != 0 ) + ret = -1; + + spin_unlock(&timerlist_lock); + + return ret; +} diff --git a/linux-2.6.7-xen-sparse/arch/xen/kernel/process.c b/linux-2.6.7-xen-sparse/arch/xen/kernel/process.c index a6930ee971..a9282773d6 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/kernel/process.c +++ b/linux-2.6.7-xen-sparse/arch/xen/kernel/process.c @@ -10,11 +10,16 @@ void xen_cpu_idle (void) { - // local_irq_disable(); - if (need_resched()) { - // local_irq_enable(); + local_irq_disable(); + if (need_resched() || !list_empty(&RCU_curlist(cpu))) + local_irq_enable(); return; } - // local_irq_enable(); + if (set_timeout_timer() == 0) { + /* NB. Blocking reenable events in a race-free manner. */ + HYPERVISOR_block(); + return; + } + local_irq_enable(); HYPERVISOR_yield(); } diff --git a/linux-2.6.7-xen-sparse/drivers/xen/net/network.c b/linux-2.6.7-xen-sparse/drivers/xen/net/network.c index d48192fd03..ea0fa45f03 100644 --- a/linux-2.6.7-xen-sparse/drivers/xen/net/network.c +++ b/linux-2.6.7-xen-sparse/drivers/xen/net/network.c @@ -1,6 +1,4 @@ /****************************************************************************** - * network.c - * * Virtual network driver for conversing with remote driver backends. * * Copyright (c) 2002-2004, K A Fraser @@ -8,13 +6,12 @@ #include #include - +#include #include #include #include #include #include - #include #include #include @@ -30,7 +27,13 @@ #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include +#else +#include "../netif.h" +#define irqreturn_t void +#define IRQ_HANDLED +#endif #define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */ @@ -368,7 +371,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) } -static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) +static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs) { struct net_device *dev = dev_id; struct net_private *np = dev->priv; @@ -381,8 +384,6 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) if ( (np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN) ) netif_rx_schedule(dev); - - return IRQ_HANDLED; } @@ -417,18 +418,25 @@ static int netif_poll(struct net_device *dev, int *pbudget) { rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; - skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); - + /* + * An error here is very odd. Usually indicates a backend bug, + * low-memory condition, or that we didn't have reservation headroom. + * Whatever - print an error and queue the id again straight away. + */ if ( unlikely(rx->status <= 0) ) { /* Gate this error. We get a (valid) slew of them on suspend. */ - if ( np->user_state != UST_OPEN ) + if ( np->user_state == UST_OPEN ) printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status); - dev_kfree_skb(skb); + np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; + wmb(); + np->rx->req_prod++; continue; } + skb = np->rx_skbs[rx->id]; + ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); + skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK); skb_put(skb, rx->status); diff --git a/tools/python/setup.py b/tools/python/setup.py index 93e7cad00c..d36f9177b9 100644 --- a/tools/python/setup.py +++ b/tools/python/setup.py @@ -41,6 +41,7 @@ setup(name = 'xen', 'xen.util', 'xen.xend', 'xen.xend.server', + 'xen.xend.sv', 'xen.xm', ], ext_package = "xen.lowlevel", diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index eb36c047d9..055746f328 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -100,7 +100,7 @@ def lookup_raw_partn(name): if line: return [ { 'device' : blkdev_name_to_number(p), 'start_sector' : long(0), - 'nr_sectors' : long(line) * 2, + 'nr_sectors' : long(1L<<63), 'type' : 'Disk' } ] else: # see if this is a hex device number diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py index 9bc42f4217..1ce3446058 100644 --- a/tools/python/xen/xend/server/SrvServer.py +++ b/tools/python/xen/xend/server/SrvServer.py @@ -25,8 +25,8 @@ # todo Support security settings etc. in the config file. # todo Support command-line args. -from twisted.web import server -from twisted.web import resource +from twisted.web import server, static +from twisted.web import resource, script from twisted.internet import reactor from xen.xend import XendRoot @@ -44,8 +44,12 @@ def create(port=None, interface=None, bridge=0): if bridge or xroot.rebooted: Vifctl.network('start') root = resource.Resource() + sv = static.File( "/usr/lib/python2.2/site-packages/xen/xend/sv/" ) + sv.indexNames=['Main.rpy'] + sv.processors={'.rpy':script.ResourceScript} xend = SrvRoot() root.putChild('xend', xend) + root.putChild('sv', sv) site = server.Site(root) reactor.listenTCP(port, site, interface=interface) diff --git a/tools/python/xen/xend/sv/DomInfo.py b/tools/python/xen/xend/sv/DomInfo.py new file mode 100755 index 0000000000..3c5642a770 --- /dev/null +++ b/tools/python/xen/xend/sv/DomInfo.py @@ -0,0 +1,99 @@ +from HTMLBase import HTMLBase +from XendClientDeferred import server +from xen.xend import PrettyPrint + +from xen.xend.sv.util import * +from xen.xend.sv.GenTabbed import * + +class DomInfo( GenTabbed ): + + def __init__( self, urlWriter, callback ): + + self.dom = 0; + + def tabUrlWriter( tab ): + return urlWriter( "mod=info&dom=%s%s" % ( self.dom, tab ) ) + + GenTabbed.__init__( self, tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGenTab, DomSXPTab, NullTab ], callback ) + + def write_BODY( self, request ): + dom = request.args.get('dom') + + if dom is None or len(dom) != 1: + request.write( "

Please Select a Domain

" ) + return None + else: + self.dom = dom[0] + + GenTabbed.write_BODY( self, request ) + +class DomGenTab( GeneralTab ): + + def __init__( self ): + + titles = {} + + titles[ 'ID' ] = 'dom' + titles[ 'Name' ] = 'name' + titles[ 'CPU' ] = 'cpu' + titles[ 'Memory' ] = ( 'mem', memoryFormatter ) + titles[ 'State' ] = ( 'state', stateFormatter ) + titles[ 'Total CPU' ] = ( 'cpu_time', smallTimeFormatter ) + titles[ 'Up Time' ] = ( 'up_time', bigTimeFormatter ) + + GeneralTab.__init__( self, "General Domain Info", {}, titles ) + + def write_BODY( self, request, callback ): + dom = request.args.get('dom') + + if dom is None or len(dom) != 1: + request.write( "

Please Select a Domain

" ) + return None + else: + self.dom = dom[0] + + deferred = getDomInfoHash( self.dom ) + deferred.addCallback( self.continue_BODY, request, callback ) + + def continue_BODY( self, dict, request, callback ): + + self.dict = dict + + GeneralTab.write_BODY( self, request, callback ) + +class DomSXPTab( PreTab ): + + def __init__( self ): + self.dom = 0 + PreTab.__init__( self, "" ) + + def fn( self, x, request ): + class tmp: + def __init__( self ): + self.str = "" + def write( self, str ): + self.str = self.str + str + temp = tmp() + PrettyPrint.prettyprint( x, out=temp ) + self.source = temp.str + return request + + def fn2( self, request, callback ): + PreTab.write_BODY( self, request, callback ) + + def write_BODY( self, request, callback ): + dom = request.args.get('dom') + + if dom is None or len(dom) != 1: + request.write( "

Please Select a Domain

" ) + return None + else: + self.dom = dom[0] + + deferred = server.xend_domain( self.dom ) + + deferred.addCallback( self.fn, request ) + deferred.addCallback( self.fn2, callback ) + def errback( x ): + print ">err ", x + deferred.addErrback( errback ) \ No newline at end of file diff --git a/tools/python/xen/xend/sv/DomList.py b/tools/python/xen/xend/sv/DomList.py new file mode 100755 index 0000000000..8fa74dff93 --- /dev/null +++ b/tools/python/xen/xend/sv/DomList.py @@ -0,0 +1,101 @@ +from twisted.web import resource +from twisted.web.server import NOT_DONE_YET + +from XendClientDeferred import server as XendServer +from xen.xend import sxp + +from xen.xend.sv.HTMLBase import HTMLBase +from xen.xend.sv.util import * + +from twisted.internet import reactor + +class DomList( HTMLBase ): + + isLeaf = True + + def __init__( self, urlWriter, callback ): + HTMLBase.__init__(self) + self.urlWriter = urlWriter + self.head = None + self.long = None + self.rendered_domains = {} + self.domCount = 0 + self.callback = callback + + def write_BODY( self, request, head=True, long=True ): + deferred = XendServer.xend_domains() + deferred.addCallback( self.get_domain_info, request ) + deferred.addErrback( self.errback ) + + self.head = head + self.long = long + + def errback( self, err ): + print 'errback>', err + + def get_domain_info( self, domains, request ): + + self.domCount = len( domains ) + + for domain in domains: + deferred = getDomInfoHash( domain ) + deferred.addCallback( self.render_domain, request ) + deferred.addErrback( self.errback ) + + def render_domain( self, domInfoHash, request ): + + domStr = "%(dom)-4d\n" % domInfoHash + + url = self.urlWriter( "mod=info&dom=%(dom)-4d" % domInfoHash ) + + domStr += "%s\n" % ( url, domInfoHash['name'] ) + + if self.long: + domStr += "%(mem)7d\n" % domInfoHash + domStr += "%(cpu)3d\n" % domInfoHash + + domStr += "%(state)5s\n" % domInfoHash + + if self.long: + domStr += "%(cpu_time)7.1f\n" % domInfoHash + + self.rendered_domains[ domInfoHash[ 'dom' ] ] = domStr + self.domCount -= 1 + + if self.domCount == 0: + self.finish_write_BODY( request ) + + def finish_write_BODY( self, request ): + + request.write( "\n\n" ) + + if self.head: + request.write( "" ) + self.write_DOMAIN_HEAD( request, self.long ) + request.write( "" ) + + odd = True + for domain in self.rendered_domains.values(): + if odd: + request.write( "\n" ) + odd = False + else: + request.write( "\n" ) + odd = True + request.write( domain ) + request.write( "\n" ) + + request.write( "
\n" ) + + self.callback( request ) + + def write_DOMAIN_HEAD( self, request, long=True ): + request.write( "Domain\n" ) + request.write( "Name\n" ) + if long: + request.write( "Memory / Mb\n" ) + request.write( "CPU\n" ) + request.write( "State\n" ) + if long: + request.write( "CPU time / s\n" ) + diff --git a/tools/python/xen/xend/sv/GenTabbed.py b/tools/python/xen/xend/sv/GenTabbed.py new file mode 100755 index 0000000000..4f34a0692c --- /dev/null +++ b/tools/python/xen/xend/sv/GenTabbed.py @@ -0,0 +1,103 @@ +import types + +from HTMLBase import HTMLBase +from TabView import TabView + +class GenTabbed( HTMLBase ): + + def __init__( self, urlWriter, tabStrings, tabObjects, callback ): + HTMLBase.__init__(self) + self.tab = 0; + self.tabStrings = tabStrings + self.tabObjects = tabObjects + self.urlWriter = urlWriter + self.callback = callback + + def write_BODY( self, request, urlWriter = None ): + tab = request.args.get('tab') + + if tab is None or len( tab) != 1: + self.tab = 0 + else: + self.tab = int( tab[0] ) + + request.write( "" ) + request.write( "
" ) + + TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( request ) + + request.write( "
" ) + + render_tab = self.tabObjects[ self.tab ]() + + if render_tab is None: + request.write( "

Bad Tab

" ) + self.finish_BODY( request ) + else: + render_tab.write_BODY( request, self.finish_BODY ) + + def finish_BODY( self, request ): + + request.write( "
" ) + + self.callback( request ) + +class PreTab( HTMLBase ): + + def __init__( self, source ): + HTMLBase.__init__( self ) + self.source = source + + def write_BODY( self, request, callback ): + + request.write( "
" )
+        
+        request.write( self.source )
+        
+        request.write( "
" ) + + callback( request ) + +class GeneralTab( HTMLBase ): + + def __init__( self, title, dict, titles ): + HTMLBase.__init__( self ) + self.title = title + self.dict = dict + self.titles = titles + + def write_BODY( self, request, callback ): + + request.write( "

%s

" % self.title ) + + request.write( "" ) + + def writeAttr( niceName, attr, formatter=None ): + if type( attr ) is types.TupleType: + ( attr, formatter ) = attr + + if attr in self.dict: + if formatter: + temp = formatter( self.dict[ attr ] ) + else: + temp = str( self.dict[ attr ] ) + request.write( "" % ( niceName, temp ) ) + + for niceName, attr in self.titles.items(): + writeAttr( niceName, attr ) + + request.write( "

%s:

%s

" ) + + callback( request ) + +class NullTab( HTMLBase ): + + def __init__( self ): + HTMLBase.__init__( self ) + self.title = "Null Tab" + + def write_BODY( self, request, callback ): + request.write( "

%s

" % self.title ) + callback( request ) + + \ No newline at end of file diff --git a/tools/python/xen/xend/sv/HTMLBase.py b/tools/python/xen/xend/sv/HTMLBase.py new file mode 100755 index 0000000000..e127dedac6 --- /dev/null +++ b/tools/python/xen/xend/sv/HTMLBase.py @@ -0,0 +1,27 @@ +from twisted.web import server, resource +from twisted.internet import reactor + +class HTMLBase( resource.Resource ): + + isLeaf = True + + def __init__( self ): + resource.Resource.__init__(self) + + def render_GET( self, request ): + self.write_TOP( request ) + return self.write_BODY( request, self.finish_render_GET ) + + def finish_render_GET( self, request ): + self.write_BOTTOM( request ) + request.finish() + + def write_BODY( self, request ): + request.write( "BODY" ) + + def write_TOP( self, request ): + request.write( 'Xen' ) + request.write( '' ) + + def write_BOTTOM( self, request ): + request.write( "" ) \ No newline at end of file diff --git a/tools/python/xen/xend/sv/Main.py b/tools/python/xen/xend/sv/Main.py new file mode 100755 index 0000000000..366e8a8124 --- /dev/null +++ b/tools/python/xen/xend/sv/Main.py @@ -0,0 +1,81 @@ +from twisted.web import resource +from twisted.web.server import NOT_DONE_YET + +from xen.xend.XendClient import server as XendServer +from xen.xend import sxp + +from HTMLBase import HTMLBase + +from xen.xend.sv import DomList, NodeInfo, DomInfo + +class Main( HTMLBase ): + + isLeaf = True + + def __init__( self ): + HTMLBase.__init__(self) + + def render_POST( self, request ): + return self.render_GET( request ) + + def mainUrlWriter( self, s ): + return "Main.rpy?%s" % s + + def write_BODY( self, request, callback ): + + self.callback = callback + + request.write( "\n\n" ) + request.write( "\n" ) + request.write( " " ) + request.write( " \n" ) + request.write( " " ) + request.write( " \n" ) + request.write( " " ) + request.write( "\n" ) + + request.write( "
 " ) + request.write( " " ) + request.write( " " ) + request.write( " " ) + request.write( "
" ) + request.write( "
" ) + + request.write( "

Node details

" ) + request.write( "

Domains summary

" ) + + DomList.DomList( self.mainUrlWriter, self.continue_BODY ).write_BODY( request, True, False ) + + return NOT_DONE_YET + + def continue_BODY( self, request ): + request.write( "
" ) + request.write( "  " ) + request.write( "
 " ) + request.write( " " ) + request.write( " " ) + request.write( " " ) + request.write( "
" ) + + mod = request.args.get('mod') + + if mod is None or len(mod) != 1: + request.write( '

Please select a module

' ) + self.finish_BODY( request ) + elif mod[0] == 'info': + DomInfo.DomInfo( self.mainUrlWriter, self.finish_BODY ).write_BODY( request ) + elif mod[0] == 'list': + DomList.DomList( self.mainUrlWriter, self.finish_BODY ).write_BODY( request ) + elif mod[0] == 'node': + NodeInfo.NodeInfo( self.mainUrlWriter, self.finish_BODY ).write_BODY( request ) + else: + request.write( '

Invalid module. Please select another

' ) + self.finish_BODY( request ) + + def finish_BODY( self, request ): + + request.write( "
" ) + request.write( "
 
\n" ) + + self.callback( request ) + \ No newline at end of file diff --git a/tools/python/xen/xend/sv/Main.rpy b/tools/python/xen/xend/sv/Main.rpy new file mode 100755 index 0000000000..90698027a6 --- /dev/null +++ b/tools/python/xen/xend/sv/Main.rpy @@ -0,0 +1,3 @@ +from xen.xend.sv.Main import * + +resource = Main() \ No newline at end of file diff --git a/tools/python/xen/xend/sv/NodeInfo.py b/tools/python/xen/xend/sv/NodeInfo.py new file mode 100755 index 0000000000..7d69f4eb50 --- /dev/null +++ b/tools/python/xen/xend/sv/NodeInfo.py @@ -0,0 +1,47 @@ +from xen.xend import XendDmesg +from xen.xend import XendNode + +from xen.xend.sv.util import * +from xen.xend.sv.GenTabbed import * +from xen.xend.sv.HTMLBase import HTMLBase + +class NodeInfo( GenTabbed ): + + def __init__( self, urlWriter, callback ): + + def newUrlWriter( url ): + return urlWriter( "mod=node%s" % url ) + + GenTabbed.__init__( self, newUrlWriter, [ 'General', 'Dmesg' ], [ NodeGeneralTab, NodeDmesgTab ], callback ) + +class NodeGeneralTab( GeneralTab ): + + def __init__( self ): + + nodeInfo = XendNode.instance().info() + + dictNodeInfo = {} + + for l in nodeInfo: + dictNodeInfo[ l[0] ] = l[1] + + dictTitles = {} + dictTitles[ 'System' ] = 'system' + dictTitles[ 'Hostname' ] = 'host' + dictTitles[ 'Release' ] = 'release' + dictTitles[ 'Version' ] ='version' + dictTitles[ 'Machine' ] = 'machine' + dictTitles[ 'Cores' ] = 'cores' + dictTitles[ 'Hyperthreading' ] = ( 'hyperthreads_per_core', hyperthreadFormatter ) + dictTitles[ 'CPU Speed' ] = ( 'cpu_mhz', cpuFormatter ) + dictTitles[ 'Memory' ] = ( 'memory', memoryFormatter ) + dictTitles[ 'Free Memory' ] = ( 'free_memory', memoryFormatter ) + + GeneralTab.__init__( self, title="General Node Info", dict=dictNodeInfo, titles=dictTitles ) + +class NodeDmesgTab( PreTab ): + + def __init__( self ): + self.xd = XendDmesg.instance() + PreTab.__init__( self, self.xd.info()[0] ) + \ No newline at end of file diff --git a/tools/python/xen/xend/sv/TabView.py b/tools/python/xen/xend/sv/TabView.py new file mode 100755 index 0000000000..70c485c329 --- /dev/null +++ b/tools/python/xen/xend/sv/TabView.py @@ -0,0 +1,49 @@ +from xen.xend.sv.HTMLBase import HTMLBase + +class TabView( HTMLBase ): + + def __init__( self, tab, tabs, urlWriter ): + HTMLBase.__init__(self) + self.tab = tab # interger - tab id + self.tabs = tabs + self.urlWriter = urlWriter + + def write_BODY( self, request ): + request.write( "" ) + request.write( "" ) + + if self.tab == 0: + image = "left-end-highlight.jpg" + else: + image = "left-end-no-highlight.jpg" + + request.write( "" % image ) + + count = len( self.tabs ) + + for i in range( count ): + + if i == self.tab: + image = "middle-highlight.jpg" + else: + image = "middle-no-highlight.jpg" + + request.write( "" % ( image, self.urlWriter( "&tab=%s" % i ), self.tabs[ i ] ) ) + + if i < count-1: + if i == self.tab: + image = "seperator-left-highlight.jpg" + elif self.tab == i+1: + image = "seperator-right-highlight.jpg" + else: + image = "seperator.jpg" + + request.write( "" % image ) + + if self.tab == count - 1: + image = "right-end-highlight.jpg" + else: + image = "right-end-no-highlight.jpg" + + request.write( "" % image ) + request.write( "

%s

" ) diff --git a/tools/python/xen/xend/sv/XendClientDeferred.py b/tools/python/xen/xend/sv/XendClientDeferred.py new file mode 100755 index 0000000000..9f8a16d129 --- /dev/null +++ b/tools/python/xen/xend/sv/XendClientDeferred.py @@ -0,0 +1,363 @@ +# Copyright (C) 2004 Tom Wilkie +# Copyright (C) 2004 Mike Wray +"""Client API for the HTTP interface on xend. +Callable as a script - see main(). + +This API is the 'control-plane' for xend. +The 'data-plane' is done separately. For example, consoles +are accessed via sockets on xend, but the list of consoles +is accessible via this API. + +This one is similar to mikes, but works in an async fashion +""" +import sys +import httplib +import types +from StringIO import StringIO +import urlparse + +from xen.xend.encode import * +from xen.xend.sxp import * +from xen.xend.PrettyPrint import prettyprint + +from twisted.protocols.http import HTTPClient +from twisted.internet.protocol import ClientCreator +from twisted.internet.defer import Deferred +from twisted.internet import reactor + +DEBUG = 0 + +class XendRequest( HTTPClient ): + def __init__(self, deferred, urls): + self.urls = urls + self.deferred = deferred + + def connectionMade(self): + self.sendCommand('GET', self.urls[2]) + self.sendHeader('Host', '%s:%d' % (self.urls[0], self.urls[1]) ) + self.endHeaders() + + def handleResponse(self, data): + self.deferred.callback( data ) + +def process_SXP( sexp ): + pin = Parser() + pin.input(sexp) + pin.input_eof() + return pin.get_val() + +def xend_request(url, method, data=None): + """Make a request to xend. + + url xend request url + method http method: POST or GET + data request argument data (dict) + """ + urlinfo = urlparse.urlparse(url) + (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo + (hdr, args) = encode_data(data) + if data and method == 'GET': + upath += '?' + args + args = None + if method == "POST" and upath.endswith('/'): + upath = upath[:-1] + + deferred = Deferred() + + clientCreator = ClientCreator( reactor, XendRequest, deferred, (ulocation, 8000, upath) ) + clientCreator.connectTCP( ulocation, 8000 ) + + deferred.addCallback( process_SXP ) + + return deferred + +class XendError(RuntimeError): + pass + +class Foo(httplib.HTTPResponse): + + def begin(self): + fin = self.fp + while(1): + buf = fin.readline() + print "***", buf + if buf == '': + print + sys.exit() + + +def sxprio(sxpr): + """Convert an sxpr to a string. + """ + io = StringIO() + sxp.show(sxpr, out=io) + print >> io + io.seek(0) + return io + +def fileof(val): + """Converter for passing configs. + Handles lists, files directly. + Assumes a string is a file name and passes its contents. + """ + if isinstance(val, types.ListType): + return sxprio(val) + if isinstance(val, types.StringType): + return file(val) + if hasattr(val, 'readlines'): + return val + +# todo: need to sort of what urls/paths are using for objects. +# e.g. for domains at the moment return '0'. +# should probably return abs path w.r.t. server, e.g. /xend/domain/0. +# As an arg, assume abs path is obj uri, otherwise just id. + +# Function to convert to full url: Xend.uri(path), e.g. +# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0 +# And should accept urls for ids? + +def urljoin(location, root, prefix='', rest=''): + prefix = str(prefix) + rest = str(rest) + base = 'http://' + location + root + prefix + url = urlparse.urljoin(base, rest) + return url + +def nodeurl(location, root, id=''): + return urljoin(location, root, 'node/', id) + +def domainurl(location, root, id=''): + return urljoin(location, root, 'domain/', id) + +def consoleurl(location, root, id=''): + return urljoin(location, root, 'console/', id) + +def deviceurl(location, root, id=''): + return urljoin(location, root, 'device/', id) + +def vneturl(location, root, id=''): + return urljoin(location, root, 'vnet/', id) + +def eventurl(location, root, id=''): + return urljoin(location, root, 'event/', id) + +def xend_get(url, args=None): + """Make a xend request using GET. + Requests using GET are 'safe' and may be repeated without + nasty side-effects. + """ + return xend_request(url, "GET", args) + +def xend_call(url, data): + """Make xend request using POST. + Requests using POST potentially cause side-effects and should + not be repeated unless it really is wanted to do the side + effect again. + """ + return xend_request(url, "POST", data) + +class Xend: + + """Default location of the xend server.""" + SRV_DEFAULT = "localhost" + + """Default path to the xend root on the server.""" + ROOT_DEFAULT = "/xend/" + + def __init__(self, srv=None, root=None): + self.bind(srv, root) + + def bind(self, srv=None, root=None): + """Bind to a given server. + + srv server location (host:port) + root server xend root path + """ + if srv is None: srv = self.SRV_DEFAULT + if root is None: root = self.ROOT_DEFAULT + if not root.endswith('/'): root += '/' + self.location = srv + self.root = root + + def nodeurl(self, id=''): + return nodeurl(self.location, self.root, id) + + def domainurl(self, id=''): + return domainurl(self.location, self.root, id) + + def consoleurl(self, id=''): + return consoleurl(self.location, self.root, id) + + def deviceurl(self, id=''): + return deviceurl(self.location, self.root, id) + + def vneturl(self, id=''): + return vneturl(self.location, self.root, id) + + def eventurl(self, id=''): + return eventurl(self.location, self.root, id) + + def xend(self): + return xend_get(urljoin(self.location, self.root)) + + def xend_node(self): + return xend_get(self.nodeurl()) + + def xend_node_cpu_rrobin_slice_set(self, slice): + return xend_call(self.nodeurl(), + {'op' : 'cpu_rrobin_slice_set', + 'slice' : slice }) + + def xend_node_cpu_bvt_slice_set(self, ctx_allow): + return xend_call(self.nodeurl(), + {'op' : 'cpu_bvt_slice_set', + 'ctx_allow' : ctx_allow }) + + def xend_node_cpu_fbvt_slice_set(self, ctx_allow): + return xend_call(self.nodeurl(), + {'op' : 'cpu_fbvt_slice_set', + 'ctx_allow' : ctx_allow }) + + def xend_domains(self): + return xend_get(self.domainurl()) + + def xend_domain_create(self, conf): + return xend_call(self.domainurl(), + {'op' : 'create', + 'config' : fileof(conf) }) + + def xend_domain(self, id): + return xend_get(self.domainurl(id)) + + def xend_domain_unpause(self, id): + return xend_call(self.domainurl(id), + {'op' : 'unpause'}) + + def xend_domain_pause(self, id): + return xend_call(self.domainurl(id), + {'op' : 'pause'}) + + def xend_domain_shutdown(self, id, reason): + return xend_call(self.domainurl(id), + {'op' : 'shutdown', + 'reason' : reason }) + + def xend_domain_destroy(self, id): + return xend_call(self.domainurl(id), + {'op' : 'destroy'}) + + def xend_domain_save(self, id, filename): + return xend_call(self.domainurl(id), + {'op' : 'save', + 'file' : filename}) + + def xend_domain_restore(self, id, filename): + return xend_call(self.domainurl(id), + {'op' : 'restore', + 'file' : filename }) + + def xend_domain_migrate(self, id, dst): + return xend_call(self.domainurl(id), + {'op' : 'migrate', + 'destination': dst}) + + def xend_domain_pincpu(self, id, cpu): + return xend_call(self.domainurl(id), + {'op' : 'pincpu', + 'cpu' : cpu}) + + def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu): + return xend_call(self.domainurl(id), + {'op' : 'cpu_bvt_set', + 'mcuadv' : mcuadv, + 'warp' : warp, + 'warpl' : warpl, + 'warpu' : warpu }) + + def xend_domain_cpu_fbvt_set(self, id, mcuadv, warp, warpl, warpu): + return xend_call(self.domainurl(id), + {'op' : 'cpu_fbvt_set', + 'mcuadv' : mcuadv, + 'warp' : warp, + 'warpl' : warpl, + 'warpu' : warpu }) + + + def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime): + return xend_call(self.domainurl(id), + {'op' : 'cpu_atropos_set', + 'period' : period, + 'slice' : slice, + 'latency' : latency, + 'xtratime': xtratime }) + + def xend_domain_vifs(self, id): + return xend_get(self.domainurl(id), + { 'op' : 'vifs' }) + + def xend_domain_vif_ip_add(self, id, vif, ipaddr): + return xend_call(self.domainurl(id), + {'op' : 'vif_ip_add', + 'vif' : vif, + 'ip' : ipaddr }) + + def xend_domain_vbds(self, id): + return xend_get(self.domainurl(id), + {'op' : 'vbds'}) + + def xend_domain_vbd(self, id, vbd): + return xend_get(self.domainurl(id), + {'op' : 'vbd', + 'vbd' : vbd}) + + def xend_consoles(self): + return xend_get(self.consoleurl()) + + def xend_console(self, id): + return xend_get(self.consoleurl(id)) + + def xend_vnets(self): + return xend_get(self.vneturl()) + + def xend_vnet_create(self, conf): + return xend_call(self.vneturl(), + {'op': 'create', 'config': fileof(conf) }) + + def xend_vnet(self, id): + return xend_get(self.vneturl(id)) + + def xend_vnet_delete(self, id): + return xend_call(self.vneturl(id), + {'op': 'delete'}) + + def xend_event_inject(self, sxpr): + val = xend_call(self.eventurl(), + {'op': 'inject', 'event': fileof(sxpr) }) + +def main(argv): + """Call an API function: + + python XendClient.py fn args... + + The leading 'xend_' on the function can be omitted. + Example: + + > python XendClient.py domains + (domain 0 8) + > python XendClient.py domain 0 + (domain (id 0) (name Domain-0) (memory 128)) + """ + server = Xend() + fn = argv[1] + if not fn.startswith('xend'): + fn = 'xend_' + fn + args = argv[2:] + deferred = getattr(server, fn)(*args) + deferred.addCallback( prettyprint ) + reactor.run() + print + +if __name__ == "__main__": + main(sys.argv) +else: + server = Xend() diff --git a/tools/python/xen/xend/sv/__init__.py b/tools/python/xen/xend/sv/__init__.py new file mode 100755 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/tools/python/xen/xend/sv/__init__.py @@ -0,0 +1 @@ + diff --git a/tools/python/xen/xend/sv/images/internet copy.jpg b/tools/python/xen/xend/sv/images/internet copy.jpg new file mode 100755 index 0000000000..92eafeb9fe Binary files /dev/null and b/tools/python/xen/xend/sv/images/internet copy.jpg differ diff --git a/tools/python/xen/xend/sv/images/internet.jpg b/tools/python/xen/xend/sv/images/internet.jpg new file mode 100755 index 0000000000..74a03c3a78 Binary files /dev/null and b/tools/python/xen/xend/sv/images/internet.jpg differ diff --git a/tools/python/xen/xend/sv/images/internet.psd b/tools/python/xen/xend/sv/images/internet.psd new file mode 100644 index 0000000000..a2e9d1754f Binary files /dev/null and b/tools/python/xen/xend/sv/images/internet.psd differ diff --git a/tools/python/xen/xend/sv/images/left-end-highlight.jpg b/tools/python/xen/xend/sv/images/left-end-highlight.jpg new file mode 100644 index 0000000000..3922eb593a Binary files /dev/null and b/tools/python/xen/xend/sv/images/left-end-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/left-end-no-highlight.jpg b/tools/python/xen/xend/sv/images/left-end-no-highlight.jpg new file mode 100644 index 0000000000..ded4e3933b Binary files /dev/null and b/tools/python/xen/xend/sv/images/left-end-no-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/middle-highlight.jpg b/tools/python/xen/xend/sv/images/middle-highlight.jpg new file mode 100644 index 0000000000..db9829d9bf Binary files /dev/null and b/tools/python/xen/xend/sv/images/middle-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/middle-no-highlight.jpg b/tools/python/xen/xend/sv/images/middle-no-highlight.jpg new file mode 100644 index 0000000000..da3b4f68a0 Binary files /dev/null and b/tools/python/xen/xend/sv/images/middle-no-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/orb_01.jpg b/tools/python/xen/xend/sv/images/orb_01.jpg new file mode 100755 index 0000000000..e30efc4985 Binary files /dev/null and b/tools/python/xen/xend/sv/images/orb_01.jpg differ diff --git a/tools/python/xen/xend/sv/images/orb_02.jpg b/tools/python/xen/xend/sv/images/orb_02.jpg new file mode 100755 index 0000000000..e5ebc8e4b1 Binary files /dev/null and b/tools/python/xen/xend/sv/images/orb_02.jpg differ diff --git a/tools/python/xen/xend/sv/images/right-end-highlight.jpg b/tools/python/xen/xend/sv/images/right-end-highlight.jpg new file mode 100644 index 0000000000..1ffee341ab Binary files /dev/null and b/tools/python/xen/xend/sv/images/right-end-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/right-end-no-highlight.jpg b/tools/python/xen/xend/sv/images/right-end-no-highlight.jpg new file mode 100644 index 0000000000..0ddd058d67 Binary files /dev/null and b/tools/python/xen/xend/sv/images/right-end-no-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/seperator-left-highlight.jpg b/tools/python/xen/xend/sv/images/seperator-left-highlight.jpg new file mode 100644 index 0000000000..c90f4ffd12 Binary files /dev/null and b/tools/python/xen/xend/sv/images/seperator-left-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/seperator-right-highlight.jpg b/tools/python/xen/xend/sv/images/seperator-right-highlight.jpg new file mode 100644 index 0000000000..f37e6cd546 Binary files /dev/null and b/tools/python/xen/xend/sv/images/seperator-right-highlight.jpg differ diff --git a/tools/python/xen/xend/sv/images/seperator.jpg b/tools/python/xen/xend/sv/images/seperator.jpg new file mode 100644 index 0000000000..c77e2c5500 Binary files /dev/null and b/tools/python/xen/xend/sv/images/seperator.jpg differ diff --git a/tools/python/xen/xend/sv/images/xen.png b/tools/python/xen/xend/sv/images/xen.png new file mode 100644 index 0000000000..344c361b3c Binary files /dev/null and b/tools/python/xen/xend/sv/images/xen.png differ diff --git a/tools/python/xen/xend/sv/inc/style.css b/tools/python/xen/xend/sv/inc/style.css new file mode 100644 index 0000000000..e819f9254e --- /dev/null +++ b/tools/python/xen/xend/sv/inc/style.css @@ -0,0 +1,30 @@ + +P {font-family: verdana, arial; font-size: 12px; color: black} +.small {font-size: 10px} + +TD.domainInfo {font-family: verdana, arial; font-size: 10px; color: black} +TD.domainInfoHead {font-family: verdana, arial; font-size: 10px; color: white; font-face: bold} + +TD.domainInfoHead {background-color: black} +TR.domainInfoOdd {background-color: white} +TR.domainInfoEven {background-color: lightgrey} + +body { + width: 670px; + margin: 0px; + padding: 0px; + background-color: #fff; + background-image: url(../images/orb_02.jpg); + background-repeat: repeat-y; + background-position: left top; + font-family: Arial, Helvetica, sans-serif; + font-weight: bold; + color: #333333; + letter-spacing: 0px; + scrollbar-base-color: #333333; + scrollbar-track-color: #666666; + scrollbar-face-color: #fff; + + + } + \ No newline at end of file diff --git a/tools/python/xen/xend/sv/util.py b/tools/python/xen/xend/sv/util.py new file mode 100755 index 0000000000..06b7017b0b --- /dev/null +++ b/tools/python/xen/xend/sv/util.py @@ -0,0 +1,64 @@ +from xen.xend.sv.XendClientDeferred import server +from xen.xend import sxp + +def getDomInfoHash( domain ): + deferred = server.xend_domain( int( domain ) ) + deferred.addCallback( procDomInfo, domain ) + return deferred + +def procDomInfo( domInfo, domain ): + d = {} + d['dom'] = int( domain ) + d['name'] = sxp.child_value( domInfo, 'name' ) + d['mem'] = int( sxp.child_value( domInfo, 'memory' ) ) + d['cpu'] = int( sxp.child_value( domInfo, 'cpu' ) ) + d['state'] = sxp.child_value( domInfo, 'state' ) + d['cpu_time'] = float( sxp.child_value( domInfo, 'cpu_time' ) ) + if( sxp.child_value( domInfo, 'up_time' ) ): + d['up_time'] = float( sxp.child_value( domInfo, 'up_time' ) ) + if( sxp.child_value( domInfo, 'start_time' ) ): + d['start_time'] = float( sxp.child_value( domInfo, 'start_time' ) ) + return d + +def bigTimeFormatter( time ): + weeks = time // 604800 + remainder = time % 604800 + days = remainder // 86400 + + remainder = remainder % 86400 + + hms = smallTimeFormatter( remainder ) + + return "%d weeks, %d days, %s" % ( weeks, days, hms ) + +def smallTimeFormatter( time ): + hours = time // 3600 + remainder = time % 3600 + mins = remainder // 60 + secs = time % 60 + return "%02d:%02d:%04.1f (hh:mm:ss.s)" % ( hours, mins, secs ) + +def stateFormatter( state ): + states = [ 'Running', 'Blocked', 'Paused', 'Shutdown', 'Crashed' ] + + for i in range( len( state ) ): + if state[i] != "-": + return states[ i ] + " (%s)" % state + + return state + +def memoryFormatter( mem ): + return "%7dMb" % mem + +def cpuFormatter( mhz ): + if mhz > 1000: + ghz = float( mhz ) / 1000.0 + return "%4.2fGHz" % ghz + else: + return "%4dMHz" % mhz + +def hyperthreadFormatter( threads ): + if int( threads ) > 1: + return "Yes (%d)" % threads + else: + return "No" \ No newline at end of file diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 5c1c544073..0dd523a32b 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -105,8 +105,23 @@ class Xm: def getprog(self, name, val=None): """Get a sub-program. + name Name of the sub-program (or optionally, an unambiguous + prefix of its name) + val Default return value if no (unique) match is found """ - return self.progs.get(name, val) + + match = None + for progname in self.progs.keys(): + if progname == name: + match = progname + break + if progname.startswith(name): + if not match: + match = progname + else: + return val # name is ambiguous - bail out + + return self.progs.get(match, val) def proglist(self): """Get a list of sub-programs, ordered by group. diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index f40c1688cb..960bf5aaf4 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -840,7 +840,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val) if ( unlikely((e = percpu_info[cpu].gps) == NULL) ) { - MEM_LOG("No GPS to reassign pfn %08lx to\n", pfn); + MEM_LOG("No GPS to reassign pfn %08lx to", pfn); okay = 0; break; } @@ -865,6 +865,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val) if ( unlikely(test_bit(DF_DYING, &e->flags)) || unlikely(IS_XEN_HEAP_FRAME(page)) ) { + MEM_LOG("Reassignment page is Xen heap, or dest dom is dying."); okay = 0; goto reassign_fail; } @@ -1051,8 +1052,8 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) * If in log-dirty mode, mark the corresponding pseudo-physical * page as dirty. */ - if( unlikely(current->mm.shadow_mode == SHM_logdirty) ) - mark_dirty( ¤t->mm, pfn ); + if ( unlikely(current->mm.shadow_mode == SHM_logdirty) ) + mark_dirty(¤t->mm, pfn); put_page(&frame_table[pfn]); break; diff --git a/xen/arch/x86/x86_32/emulate.c b/xen/arch/x86/x86_32/emulate.c index 3856f25ab1..08fb036cc0 100644 --- a/xen/arch/x86/x86_32/emulate.c +++ b/xen/arch/x86/x86_32/emulate.c @@ -30,6 +30,10 @@ #include #include +/* Make the scary benign errors go away. */ +#undef DPRINTK +#define DPRINTK(_f, _a...) ((void)0) + /* * Obtain the base and limit associated with the given segment selector. * The selector must identify a 32-bit code or data segment. Any segment that @@ -495,9 +499,34 @@ int gpf_emulate_4gb(struct pt_regs *regs) goto undecodeable; } +#if 0 + { + char str1[] = { 0x65,0x8b,0x00,0x8b,0x30 }; + char str2[] = { 0x65,0x8b,0x02,0x8b,0x40,0x0c }; + char str3[] = { 0x65,0x8b,0x30,0x85,0xf6 }; + char str4[] = { 0x65,0x8b,0x00,0x5d,0x8b,0x00 }; + char str5[] = { 0x65,0x89,0x30,0x8b,0x45,0x08 }; + char str6[] = { 0x65,0x8b,0x00,0x8b,0x50,0x0c }; + char str7[] = { 0x65,0x89,0x51,0x00,0x83,0xc8,0xff }; + if ( (memcmp(eip,str1,5) == 0) || + (memcmp(eip,str2,6) == 0) ) goto out; + if ( (memcmp(eip,str3,5) == 0) || + (memcmp(eip,str4,6) == 0) ) goto out; + if ( (memcmp(eip,str5,6) == 0) || + (memcmp(eip,str6,6) == 0) ) goto out; + if ( (memcmp(eip,str7,7) == 0) || + (memcmp(eip,str7,7) == 0) ) goto out; + } + printk(" .byte 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", + eip[-8],eip[-7],eip[-6],eip[-5],eip[-4],eip[-3],eip[-2],eip[-1]); + printk(" .byte 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", + eip[0],eip[1],eip[2],eip[3],eip[4],eip[5],eip[6],eip[7]); + printk(" @ %04x:%08lx\n", regs->xcs, regs->eip); +#endif + /* Success! */ - regs->eip += pb - eip; perfc_incrc(emulations); + regs->eip += pb - eip; return 1; undecodeable: @@ -530,5 +559,3 @@ int gpf_emulate_4gb(struct pt_regs *regs) d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; return 1; } - -