mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
bitkeeper revision 1.1159.33.1 (4120e700LNXbe5IhAOotAN5jyP0RJw)
suspend/resume fixes
This commit is contained in:
1 parent
9f57ca8fe5
commit
83b44e251e
6 files changed
+163
-17
No files matched your search
@@ -17,6 +17,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <asm/io.h>
|
||||
@@ -427,9 +428,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
*/
|
||||
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);
|
||||
printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
|
||||
np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
|
||||
wmb();
|
||||
np->rx->req_prod++;
|
||||
@@ -470,6 +469,15 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
mcl->args[2] = 0;
|
||||
mcl++;
|
||||
(void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
|
||||
#if 0
|
||||
if (unlikely(rx_mcl[0].args[5] != 0))
|
||||
printk(KERN_ALERT"Hypercall0 failed %u\n",np->rx->resp_prod);
|
||||
|
||||
if (unlikely(rx_mcl[1].args[5] != 0))
|
||||
printk(KERN_ALERT"Hypercall1 failed %u\n",np->rx->resp_prod);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
while ( (skb = __skb_dequeue(&rxq)) != NULL )
|
||||
@@ -595,6 +603,7 @@ static void network_connect(struct net_device *dev,
|
||||
printk(KERN_ALERT"Netfront recovered tx=%d rxfree=%d\n",
|
||||
np->tx->req_prod,np->rx->req_prod);
|
||||
|
||||
|
||||
/* 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
|
||||
@@ -916,6 +925,8 @@ void netif_resume(void)
|
||||
struct net_private *np = NULL;
|
||||
int i;
|
||||
|
||||
|
||||
|
||||
#if 1
|
||||
/* XXX THIS IS TEMPORARY */
|
||||
|
||||
@@ -932,6 +943,9 @@ void netif_resume(void)
|
||||
|
||||
// stop bad things from happening until we're back up
|
||||
np->backend_state = BEST_DISCONNECTED;
|
||||
|
||||
memset(np->tx,0,PAGE_SIZE);
|
||||
memset(np->rx,0,PAGE_SIZE);
|
||||
|
||||
cmsg.type = CMSG_NETIF_FE;
|
||||
cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT;
|
||||
|
||||
@@ -374,7 +374,8 @@ static inline int HYPERVISOR_dom_mem_op(unsigned int op,
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
|
||||
"b" (op), "c" (extent_list), "d" (nr_extents), "S" (extent_order)
|
||||
"b" (op), "c" (extent_list), "d" (nr_extents), "S" (extent_order),
|
||||
"D" (DOMID_SELF)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -504,6 +504,54 @@ printf("XXXXXXXXXXXXXXX pin L2\n");
|
||||
|
||||
xcio_info(ioctxt, "\b\b\b\b100%%\nMemory reloaded.\n");
|
||||
|
||||
/* Get the list of PFNs that are not in the psuedo-phys map */
|
||||
{
|
||||
unsigned int count, *pfntab;
|
||||
int rc;
|
||||
if ( xcio_read(ioctxt, &count, sizeof(count)) )
|
||||
{
|
||||
xcio_error(ioctxt, "Error when reading from state file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pfntab = malloc( sizeof(unsigned int) * count );
|
||||
if ( !pfntab )
|
||||
{
|
||||
xcio_error(ioctxt, "Out of memory");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( xcio_read(ioctxt, pfntab, sizeof(unsigned int)*count) )
|
||||
{
|
||||
xcio_error(ioctxt, "Error when reading pfntab from state file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(i=0;i<count;i++)
|
||||
{
|
||||
unsigned long pfn = pfntab[i];
|
||||
pfntab[i]=pfn_to_mfn_table[pfn];
|
||||
pfn_to_mfn_table[pfn] = 0x80000001; // not in pmap
|
||||
}
|
||||
|
||||
if ( count>0 )
|
||||
{
|
||||
if ( (rc = do_dom_mem_op( xc_handle,
|
||||
MEMOP_decrease_reservation,
|
||||
pfntab, count, 0, dom )) <0 )
|
||||
{
|
||||
xcio_error(ioctxt, "Could not decrease reservation : %d",rc);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Decreased reservation by %d pages\n", count);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( xcio_read(ioctxt, &ctxt, sizeof(ctxt)) ||
|
||||
xcio_read(ioctxt, shared_info, PAGE_SIZE) )
|
||||
|
||||
@@ -463,10 +463,6 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("SUSPPPPPPPP flags %08lx shinfo %08lx eip %08lx esi %08lx\n",
|
||||
op.u.getdomaininfo.flags, op.u.getdomaininfo.shared_info_frame,
|
||||
ctxt.cpu_ctxt.eip, ctxt.cpu_ctxt.esi );
|
||||
|
||||
}
|
||||
|
||||
/* calculate the power of 2 order of nr_pfns, e.g.
|
||||
@@ -866,9 +862,41 @@ printf("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("SUSPPPPPPPP flags %08lx shinfo %08lx eip %08lx esi %08lx\n",
|
||||
op.u.getdomaininfo.flags, op.u.getdomaininfo.shared_info_frame,
|
||||
ctxt.cpu_ctxt.eip, ctxt.cpu_ctxt.esi );
|
||||
/* Send through a list of all the PFNs that were not in map at the close */
|
||||
{
|
||||
unsigned int i,j;
|
||||
unsigned int pfntab[1024];
|
||||
|
||||
for ( i = 0, j = 0; i < nr_pfns; i++ )
|
||||
{
|
||||
if ( live_pfn_to_mfn_table[i] >= 0x80000000UL )
|
||||
j++;
|
||||
}
|
||||
|
||||
if ( xcio_write(ioctxt, &j, sizeof(unsigned int)) )
|
||||
{
|
||||
xcio_error(ioctxt, "Error when writing to state file (6a)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for ( i = 0, j = 0; i < nr_pfns; )
|
||||
{
|
||||
if ( live_pfn_to_mfn_table[i] >= 0x80000000UL )
|
||||
{
|
||||
pfntab[j++] = i;
|
||||
}
|
||||
i++;
|
||||
if ( j == 1024 || i == nr_pfns )
|
||||
{
|
||||
if ( xcio_write(ioctxt, &pfntab, sizeof(unsigned long)*j) )
|
||||
{
|
||||
xcio_error(ioctxt, "Error when writing to state file (6b)");
|
||||
goto out;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Map the suspend-record MFN to pin it. The page must be owned by
|
||||
domid for this to succeed. */
|
||||
|
||||
@@ -127,6 +127,42 @@ static inline int do_multicall_op(int xc_handle,
|
||||
out1: return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline int do_dom_mem_op(int xc_handle,
|
||||
unsigned int memop,
|
||||
unsigned int *extent_list,
|
||||
unsigned int nr_extents,
|
||||
unsigned int extent_order,
|
||||
domid_t domid)
|
||||
{
|
||||
privcmd_hypercall_t hypercall;
|
||||
long ret = -EINVAL;
|
||||
|
||||
hypercall.op = __HYPERVISOR_dom_mem_op;
|
||||
hypercall.arg[0] = (unsigned long)memop;
|
||||
hypercall.arg[1] = (unsigned long)extent_list;
|
||||
hypercall.arg[2] = (unsigned long)nr_extents;
|
||||
hypercall.arg[3] = (unsigned long)extent_order;
|
||||
hypercall.arg[4] = (unsigned long)domid;
|
||||
|
||||
if ( mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock memory for Xen hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
|
||||
" rebuild the user-space tool set?\n",ret,errno);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
out2: (void)munlock(extent_list, nr_extents*sizeof(unsigned long));
|
||||
out1: return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PFN mapping.
|
||||
*/
|
||||
|
||||
@@ -92,13 +92,32 @@ static long free_dom_mem(struct domain *d,
|
||||
long do_dom_mem_op(unsigned int op,
|
||||
unsigned long *extent_list,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order)
|
||||
unsigned int extent_order,
|
||||
domid_t domid)
|
||||
{
|
||||
if ( op == MEMOP_increase_reservation )
|
||||
return alloc_dom_mem(current, extent_list, nr_extents, extent_order);
|
||||
struct domain *d;
|
||||
long rc = -ENOSYS;
|
||||
|
||||
if ( op == MEMOP_decrease_reservation )
|
||||
return free_dom_mem(current, extent_list, nr_extents, extent_order);
|
||||
if (domid == DOMID_SELF)
|
||||
d = current;
|
||||
else
|
||||
d = find_domain_by_id(domid);
|
||||
|
||||
return -ENOSYS;
|
||||
if (d==NULL)
|
||||
return -ESRCH;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case MEMOP_increase_reservation:
|
||||
rc = alloc_dom_mem(d, extent_list, nr_extents, extent_order);
|
||||
break;
|
||||
case MEMOP_decrease_reservation:
|
||||
rc = free_dom_mem(d, extent_list, nr_extents, extent_order);
|
||||
break;
|
||||
}
|
||||
|
||||
if (domid!=DOMID_SELF)
|
||||
put_domain(d);
|
||||
|
||||
return rc;
|
||||
}
|
||||