aboutsummaryrefslogtreecommitdiffstats
path: root/xenolinux-2.4.26-sparse/arch
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-05-06 11:56:17 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-05-06 11:56:17 +0000
commitb7b3707b662a0335744644174ffb4de8c1847861 (patch)
treeb5e5118d885974ed30e9b0b9049497cb35a9084b /xenolinux-2.4.26-sparse/arch
parent482166667713508fda5a9ae483df974f367de756 (diff)
parent3b5b2188aa19c0f284b5289cd97acfdd81fa131c (diff)
downloadxen-b7b3707b662a0335744644174ffb4de8c1847861.tar.gz
xen-b7b3707b662a0335744644174ffb4de8c1847861.tar.bz2
xen-b7b3707b662a0335744644174ffb4de8c1847861.zip
bitkeeper revision 1.891.1.3 (409a27e1UZRfPLA6Sz-02GAVb3IlDw)
Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xeno
Diffstat (limited to 'xenolinux-2.4.26-sparse/arch')
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/defconfig-physdev169
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h16
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c204
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c293
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c335
-rw-r--r--xenolinux-2.4.26-sparse/arch/xen/mm/hypervisor.c105
6 files changed, 557 insertions, 565 deletions
diff --git a/xenolinux-2.4.26-sparse/arch/xen/defconfig-physdev b/xenolinux-2.4.26-sparse/arch/xen/defconfig-physdev
index 69aa6c0856..41b05aaaa7 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/defconfig-physdev
+++ b/xenolinux-2.4.26-sparse/arch/xen/defconfig-physdev
@@ -89,19 +89,7 @@ CONFIG_BINFMT_ELF=y
#
# Parallel port support
#
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_PC_PCMCIA is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_IP22 is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
+# CONFIG_PARPORT is not set
#
# Plug and Play configuration
@@ -112,7 +100,7 @@ CONFIG_PNP=y
#
# Block devices
#
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
@@ -131,14 +119,14 @@ CONFIG_BLK_DEV_INITRD=y
#
# Multi-device support (RAID and LVM)
#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_MULTIPATH=y
-CONFIG_BLK_DEV_LVM=y
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
#
# Networking options
@@ -234,7 +222,7 @@ CONFIG_IP_NF_TARGET_ULOG=y
#
# CONFIG_DEV_APPLETALK is not set
# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+CONFIG_BRIDGE=y
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_LLC is not set
@@ -380,14 +368,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_AHA1740 is not set
CONFIG_SCSI_AACRAID=y
# CONFIG_SCSI_AIC7XXX is not set
-CONFIG_SCSI_AIC79XX=y
-CONFIG_AIC79XX_CMDS_PER_DEVICE=32
-CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
-# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
-CONFIG_AIC79XX_DEBUG_ENABLE=y
-CONFIG_AIC79XX_DEBUG_MASK=0
-# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
@@ -397,9 +378,9 @@ CONFIG_SCSI_MEGARAID=y
# CONFIG_SCSI_MEGARAID2 is not set
CONFIG_SCSI_BUSLOGIC=y
# CONFIG_SCSI_OMIT_FLASHPOINT is not set
-CONFIG_SCSI_CPQFCTS=y
+# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
-CONFIG_SCSI_DTC3280=y
+# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
@@ -409,15 +390,11 @@ CONFIG_SCSI_DTC3280=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
@@ -510,9 +487,7 @@ CONFIG_PCNET32=y
# CONFIG_APRICOT is not set
# CONFIG_B44 is not set
# CONFIG_CS89x0 is not set
-CONFIG_TULIP=y
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP is not set
# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
@@ -545,8 +520,7 @@ CONFIG_TULIP=y
#
# Ethernet (1000 Mbit)
#
-CONFIG_ACENIC=y
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
@@ -621,9 +595,6 @@ CONFIG_VT_CONSOLE=y
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
#
# I2C support
@@ -869,107 +840,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-CONFIG_USB_UHCI=y
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=y
-# CONFIG_USB_SL811HS_ALT is not set
-# CONFIG_USB_SL811HS is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_MIDI is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-# CONFIG_USB_HID is not set
-
-#
-# Input core support is needed for USB HID input layer or HIDBP support
-#
-# CONFIG_USB_HIDINPUT is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_TIGL is not set
-# CONFIG_USB_BRLVGER is not set
-# CONFIG_USB_LCD is not set
+# CONFIG_USB is not set
#
# Support for USB gadgets
diff --git a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h
index 1e95d9f480..88881cdf66 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h
+++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h
@@ -16,6 +16,7 @@
#include <asm/ctrl_if.h>
#include <asm/io.h>
#include "../netif.h"
+#include "../../../../../net/bridge/br_private.h"
#ifndef NDEBUG
#define ASSERT(_p) \
@@ -28,7 +29,7 @@
#define DPRINTK(_f, _a...) ((void)0)
#endif
-typedef struct {
+typedef struct netif_st {
/* Unique identifier for this interface. */
domid_t domid;
unsigned int handle;
@@ -49,13 +50,7 @@ typedef struct {
NETIF_RING_IDX tx_req_cons;
NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */
- /* Usage accounting */
- long long total_bytes_sent;
- long long total_bytes_received;
- long long total_packets_sent;
- long long total_packets_received;
-
- /* Trasnmit shaping: allow 'credit_bytes' every 'credit_usec'. */
+ /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
unsigned long credit_bytes;
unsigned long credit_usec;
unsigned long remaining_credit;
@@ -72,7 +67,8 @@ typedef struct {
struct list_head list; /* scheduling list */
atomic_t refcnt;
spinlock_t rx_lock, tx_lock;
- unsigned char vmac[ETH_ALEN];
+ struct net_device *dev;
+ struct net_device_stats stats;
} netif_t;
void netif_create(netif_be_create_t *create);
@@ -93,6 +89,8 @@ void netif_ctrlif_init(void);
void netif_deschedule(netif_t *netif);
+int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
+struct net_device_stats *netif_be_get_stats(struct net_device *dev);
void netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
#endif /* __NETIF__BACKEND__COMMON_H__ */
diff --git a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c
index d12ca3057d..8623d8214b 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c
+++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c
@@ -12,8 +12,8 @@
#define NETIF_HASH(_d,_h) \
(((int)(_d)^(int)((_d)>>32)^(int)(_h))&(NETIF_HASHSZ-1))
-static kmem_cache_t *netif_cachep;
-static netif_t *netif_hash[NETIF_HASHSZ];
+static netif_t *netif_hash[NETIF_HASHSZ];
+static struct net_device *bridge_dev;
netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
{
@@ -35,7 +35,9 @@ void __netif_disconnect_complete(netif_t *netif)
* must still be notified to the remote driver.
*/
unbind_evtchn_from_irq(netif->evtchn);
- vfree(netif->net_ring_base);
+ vfree(netif->tx); /* Frees netif->rx as well. */
+ (void)br_del_if((struct net_bridge *)bridge_dev->priv, netif->dev);
+ (void)dev_close(netif->dev);
/* Construct the deferred response message. */
cmsg.type = CMSG_NETIF_BE;
@@ -66,24 +68,32 @@ void __netif_disconnect_complete(netif_t *netif)
void netif_create(netif_be_create_t *create)
{
- domid_t domid = create->domid;
- unsigned int handle = create->netif_handle;
- netif_t **pnetif, *netif;
+ domid_t domid = create->domid;
+ unsigned int handle = create->netif_handle;
+ struct net_device *dev;
+ netif_t **pnetif, *netif;
- if ( (netif = kmem_cache_alloc(netif_cachep, GFP_ATOMIC)) == NULL )
+ dev = alloc_netdev(sizeof(netif_t), "netif-be-%d", ether_setup);
+ if ( dev == NULL )
{
DPRINTK("Could not create netif: out of memory\n");
create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
return;
}
+ netif = dev->priv;
memset(netif, 0, sizeof(*netif));
netif->domid = domid;
netif->handle = handle;
netif->status = DISCONNECTED;
- spin_lock_init(&netif->vbd_lock);
- spin_lock_init(&netif->net_ring_lock);
+ spin_lock_init(&netif->rx_lock);
+ spin_lock_init(&netif->tx_lock);
atomic_set(&netif->refcnt, 0);
+ netif->dev = dev;
+
+ netif->credit_bytes = netif->remaining_credit = ~0UL;
+ netif->credit_usec = 0UL;
+ /*init_ac_timer(&new_vif->credit_timeout);*/
pnetif = &netif_hash[NETIF_HASH(domid, handle)];
while ( *pnetif != NULL )
@@ -92,12 +102,24 @@ void netif_create(netif_be_create_t *create)
{
DPRINTK("Could not create netif: already exists\n");
create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
- kmem_cache_free(netif_cachep, netif);
+ kfree(dev);
return;
}
pnetif = &(*pnetif)->hash_next;
}
+ dev->hard_start_xmit = netif_be_start_xmit;
+ dev->get_stats = netif_be_get_stats;
+ memcpy(dev->dev_addr, create->mac, ETH_ALEN);
+
+ if ( register_netdev(dev) != 0 )
+ {
+ DPRINTK("Could not register new net device\n");
+ create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+ kfree(dev);
+ return;
+ }
+
netif->hash_next = *pnetif;
*pnetif = netif;
@@ -132,8 +154,8 @@ void netif_destroy(netif_be_destroy_t *destroy)
destroy:
*pnetif = netif->hash_next;
- destroy_all_vbds(netif);
- kmem_cache_free(netif_cachep, netif);
+ unregister_netdev(netif->dev);
+ kfree(netif->dev);
destroy->status = NETIF_BE_STATUS_OKAY;
}
@@ -142,11 +164,13 @@ void netif_connect(netif_be_connect_t *connect)
domid_t domid = connect->domid;
unsigned int handle = connect->netif_handle;
unsigned int evtchn = connect->evtchn;
- unsigned long shmem_frame = connect->shmem_frame;
+ unsigned long tx_shmem_frame = connect->tx_shmem_frame;
+ unsigned long rx_shmem_frame = connect->rx_shmem_frame;
struct vm_struct *vma;
pgprot_t prot;
int error;
netif_t *netif;
+ struct net_device *eth0_dev;
netif = netif_find_by_handle(domid, handle);
if ( unlikely(netif == NULL) )
@@ -157,16 +181,27 @@ void netif_connect(netif_be_connect_t *connect)
return;
}
- if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+ if ( netif->status != DISCONNECTED )
+ {
+ connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
+ return;
+ }
+
+ if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL )
{
connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
return;
}
prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
- error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
- shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
+ error = direct_remap_area_pages(&init_mm,
+ VMALLOC_VMADDR(vma->addr),
+ tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+ prot, domid);
+ error |= direct_remap_area_pages(&init_mm,
+ VMALLOC_VMADDR(vma->addr) + PAGE_SIZE,
+ rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+ prot, domid);
if ( error != 0 )
{
if ( error == -ENOMEM )
@@ -179,21 +214,27 @@ void netif_connect(netif_be_connect_t *connect)
return;
}
- if ( netif->status != DISCONNECTED )
- {
- connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
- vfree(vma->addr);
- return;
- }
-
- netif->evtchn = evtchn;
- netif->irq = bind_evtchn_to_irq(evtchn);
- netif->shmem_frame = shmem_frame;
- netif->net_ring_base = (netif_ring_t *)vma->addr;
- netif->status = CONNECTED;
+ netif->evtchn = evtchn;
+ netif->irq = bind_evtchn_to_irq(evtchn);
+ netif->tx_shmem_frame = tx_shmem_frame;
+ netif->rx_shmem_frame = rx_shmem_frame;
+ netif->tx =
+ (netif_tx_interface_t *)vma->addr;
+ netif->rx =
+ (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
+ netif->status = CONNECTED;
netif_get(netif);
- request_irq(netif->irq, netif_be_int, 0, "netif-backend", netif);
+ (void)dev_open(netif->dev);
+ (void)br_add_if((struct net_bridge *)bridge_dev->priv, netif->dev);
+ /* At this point we try to ensure that eth0 is attached to the bridge. */
+ if ( (eth0_dev = __dev_get_by_name("eth0")) != NULL )
+ {
+ (void)dev_open(eth0_dev);
+ (void)br_add_if((struct net_bridge *)bridge_dev->priv, eth0_dev);
+ }
+ (void)request_irq(netif->irq, netif_be_int, 0, "netif-backend", netif);
+ netif_start_queue(netif->dev);
connect->status = NETIF_BE_STATUS_OKAY;
}
@@ -218,6 +259,7 @@ int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
netif->status = DISCONNECTING;
netif->disconnect_rspid = rsp_id;
wmb(); /* Let other CPUs see the status change. */
+ netif_stop_queue(netif->dev);
free_irq(netif->irq, NULL);
netif_deschedule(netif);
netif_put(netif);
@@ -226,105 +268,11 @@ int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
return 0; /* Caller should not send response message. */
}
-net_vif_t *create_net_vif(domid_t dom)
-{
- unsigned int idx;
- net_vif_t *new_vif = NULL;
- net_ring_t *new_ring = NULL;
- struct task_struct *p = NULL;
- unsigned long flags, vmac_hash;
- unsigned char vmac_key[ETH_ALEN + 2 + MAX_DOMAIN_NAME];
-
- if ( (p = find_domain_by_id(dom)) == NULL )
- return NULL;
-
- write_lock_irqsave(&tasklist_lock, flags);
-
- for ( idx = 0; idx < MAX_DOMAIN_VIFS; idx++ )
- if ( p->net_vif_list[idx] == NULL )
- break;
- if ( idx == MAX_DOMAIN_VIFS )
- goto fail;
-
- if ( (new_vif = kmem_cache_alloc(net_vif_cache, GFP_KERNEL)) == NULL )
- goto fail;
-
- memset(new_vif, 0, sizeof(*new_vif));
-
- if ( sizeof(net_ring_t) > PAGE_SIZE )
- BUG();
- new_ring = (net_ring_t *)get_free_page(GFP_KERNEL);
- clear_page(new_ring);
- SHARE_PFN_WITH_DOMAIN(virt_to_page(new_ring), p);
-
- /*
- * Fill in the new vif struct. Note that, while the vif's refcnt is
- * non-zero, we hold a reference to the task structure.
- */
- atomic_set(&new_vif->refcnt, 1);
- new_vif->shared_rings = new_ring;
- new_vif->shared_idxs = &p->shared_info->net_idx[idx];
- new_vif->domain = p;
- new_vif->idx = idx;
- new_vif->list.next = NULL;
- spin_lock_init(&new_vif->rx_lock);
- spin_lock_init(&new_vif->tx_lock);
-
- new_vif->credit_bytes = new_vif->remaining_credit = ~0UL;
- new_vif->credit_usec = 0UL;
- init_ac_timer(&new_vif->credit_timeout);
-
- if ( (p->domain == 0) && (idx == 0) )
- {
- /*
- * DOM0/VIF0 gets the real physical MAC address, so that users can
- * easily get a Xen-based machine up and running by using an existing
- * DHCP entry.
- */
- memcpy(new_vif->vmac, the_dev->dev_addr, ETH_ALEN);
- }
- else
- {
- /*
- * Most VIFs get a random MAC address with a "special" vendor id.
- * We try to get MAC addresses to be unique across multiple servers
- * by including the physical MAC address in the hash. The hash also
- * includes the vif index and the domain's name.
- *
- * NB. The vendor is currently an "obsolete" one that used to belong
- * to DEC (AA-00-00). Using it is probably a bit rude :-)
- *
- * NB2. The first bit of the first random octet is set to zero for
- * all dynamic MAC addresses. This may allow us to manually specify
- * MAC addresses for some VIFs with no fear of clashes.
- */
- memcpy(&vmac_key[0], the_dev->dev_addr, ETH_ALEN);
- *(__u16 *)(&vmac_key[ETH_ALEN]) = htons(idx);
- strcpy(&vmac_key[ETH_ALEN+2], p->name);
- vmac_hash = hash(vmac_key, ETH_ALEN + 2 + strlen(p->name));
- memcpy(new_vif->vmac, "\xaa\x00\x00", 3);
- new_vif->vmac[3] = (vmac_hash >> 16) & 0xef; /* First bit is zero. */
- new_vif->vmac[4] = (vmac_hash >> 8) & 0xff;
- new_vif->vmac[5] = (vmac_hash >> 0) & 0xff;
- }
-
- p->net_vif_list[idx] = new_vif;
-
- write_unlock_irqrestore(&tasklist_lock, flags);
- return new_vif;
-
- fail:
- write_unlock_irqrestore(&tasklist_lock, flags);
- if ( new_vif != NULL )
- kmem_cache_free(net_vif_cache, new_vif);
- if ( p != NULL )
- put_task_struct(p);
- return NULL;
-}
-
void netif_interface_init(void)
{
- netif_cachep = kmem_cache_create("netif_cache", sizeof(netif_t),
- 0, 0, NULL, NULL);
memset(netif_hash, 0, sizeof(netif_hash));
+ if ( br_add_bridge("netif-backend") != 0 )
+ BUG();
+ bridge_dev = __dev_get_by_name("netif-be-bridge");
+ (void)dev_open(bridge_dev);
}
diff --git a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c
index eb23384662..5b84eba9bc 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c
+++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c
@@ -11,7 +11,10 @@
*/
#include "common.h"
+#include <asm/hypervisor-ifs/dom_mem_ops.h>
+static void net_tx_action(unsigned long unused);
+static void tx_skb_release(struct sk_buff *skb);
static void make_tx_response(netif_t *netif,
u16 id,
s8 st);
@@ -21,38 +24,125 @@ static void make_rx_response(netif_t *netif,
netif_addr_t addr,
u16 size);
+static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
+
/* Don't currently gate addition of an interface to the tx scheduling list. */
#define tx_work_exists(_if) (1)
#define MAX_PENDING_REQS 256
-static struct vm_struct *mmap_vma;
-#define MMAP_VADDR(_req) ((unsigned long)mmap_vma->addr + ((_req) * PAGE_SIZE))
+unsigned long mmap_vstart;
+#define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE))
+
+#define PKT_PROT_LEN (ETH_HLEN + 20)
/*static pending_req_t pending_reqs[MAX_PENDING_REQS];*/
+static u16 pending_id[MAX_PENDING_REQS];
static u16 pending_ring[MAX_PENDING_REQS];
static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
-/* NB. We use a different index type to differentiate from shared blk rings. */
typedef unsigned int PEND_RING_IDX;
#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
static PEND_RING_IDX pending_prod, pending_cons;
#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+static struct list_head net_schedule_list;
+static spinlock_t net_schedule_list_lock;
+
+#define MAX_MFN_ALLOC 64
+static unsigned long mfn_list[MAX_MFN_ALLOC];
+static unsigned int alloc_index = 0;
+static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED;
+static void __refresh_mfn_list(void)
+{
+ int ret;
+ dom_mem_op_t op;
+ op.op = MEMOP_RESERVATION_INCREASE;
+ op.u.increase.size = MAX_MFN_ALLOC;
+ op.u.increase.pages = mfn_list;
+ if ( (ret = HYPERVISOR_dom_mem_op(&op)) != MAX_MFN_ALLOC )
+ {
+ printk(KERN_WARNING "Unable to increase memory reservation (%d)\n",
+ ret);
+ BUG();
+ }
+ alloc_index = MAX_MFN_ALLOC;
+}
+static unsigned long get_new_mfn(void)
+{
+ unsigned long mfn, flags;
+ spin_lock_irqsave(&mfn_lock, flags);
+ if ( alloc_index == 0 )
+ __refresh_mfn_list();
+ mfn = mfn_list[--alloc_index];
+ spin_unlock_irqrestore(&mfn_lock, flags);
+ return mfn;
+}
+static void dealloc_mfn(unsigned long mfn)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&mfn_lock, flags);
+ mfn_list[alloc_index++] = mfn;
+ spin_unlock_irqrestore(&mfn_lock, flags);
+}
+
+static inline void maybe_schedule_tx_action(void)
+{
+ smp_mb();
+ if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+ !list_empty(&net_schedule_list) )
+ tasklet_schedule(&net_tx_tasklet);
+}
+
/*
* This is the primary RECEIVE function for a network interface.
* Note that, from the p.o.v. of /this/ OS it looks like a transmit.
*/
-static void netif_start_xmit(struct sk_buff *skb, struct net_device *dev)
+int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
netif_t *netif = (netif_t *)dev->priv;
- s8 status = BLKIF_RSP_OKAY;
- u16 size;
- mmu_update_t mmu[4];
+ s8 status = NETIF_RSP_OKAY;
+ u16 size, id;
+ mmu_update_t mmu[6];
+ pgd_t *pgd; pmd_t *pmd; pte_t *pte;
+ unsigned long vdata, new_mfn;
+
+ /* Drop the packet if the target domain has no receive buffers. */
+ if ( (netif->rx_req_cons == netif->rx->req_prod) ||
+ ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) )
+ {
+ dev_kfree_skb(skb);
+ return 0;
+ }
- memcpy(skb->mac.ethernet->h_dest, netif->vmac, ETH_ALEN);
- if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
- memcpy(skb->nh.raw + 18, netif->vmac, ETH_ALEN);
+ id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_req_cons++)].req.id;
+
+ /*
+ * We do not copy the packet unless:
+ * 1. It is fragmented; or
+ * 2. It spans a page boundary; or
+ * 3. We cannot be sure the whole data page is allocated.
+ * The copying method is taken from skb_copy().
+ */
+ if ( (skb_shinfo(skb)->nr_frags != 0) ||
+ (((unsigned long)skb->end ^ (unsigned long)skb->head) & PAGE_MASK) ||
+ ((skb->end - skb->head) < (PAGE_SIZE/2)) )
+ {
+ struct sk_buff *nskb = dev_alloc_skb(PAGE_SIZE-1024);
+ int hlen = skb->data - skb->head;
+ skb_reserve(nskb, hlen);
+ skb_put(nskb, skb->len);
+ (void)skb_copy_bits(skb, -hlen, nskb->head, hlen + skb->len);
+ dev_kfree_skb(skb);
+ skb = nskb;
+ }
- spin_lock(&netif->rx_lock);
+ vdata = (unsigned long)skb->data;
+ size = skb->tail - skb->data;
+
+ new_mfn = get_new_mfn();
+
+ pgd = pgd_offset_k( (vdata & PAGE_MASK));
+ pmd = pmd_offset(pgd, (vdata & PAGE_MASK));
+ pte = pte_offset(pmd, (vdata & PAGE_MASK));
mmu[0].val = (unsigned long)(netif->domid<<16) & ~0xFFFFUL;
mmu[0].ptr = (unsigned long)(netif->domid<< 0) & ~0xFFFFUL;
@@ -63,49 +153,43 @@ static void netif_start_xmit(struct sk_buff *skb, struct net_device *dev)
mmu[1].ptr |= MMU_EXTENDED_COMMAND;
mmu[1].val |= MMUEXT_SET_SUBJECTDOM_H;
- mmu[2].ptr = ptr | MMU_EXTENDED_COMMAND;
+ mmu[2].ptr = virt_to_machine(vdata & PAGE_MASK) | MMU_EXTENDED_COMMAND;
mmu[2].val = MMUEXT_REASSIGN_PAGE;
- mmu[3].ptr = ppte;
- mmu[3].val = newpage;
+ mmu[3].ptr = MMU_EXTENDED_COMMAND;
+ mmu[3].val = MMUEXT_RESET_SUBJECTDOM;
- if ( unlikely(HYPERVISOR_mmu_update(mmu, 4) < 0) )
+ mmu[4].ptr = virt_to_machine(pte);
+ mmu[4].val = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL;
+
+ mmu[5].ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+ mmu[5].val = __pa(vdata) >> PAGE_SHIFT;
+
+ if ( unlikely(HYPERVISOR_mmu_update(mmu, 6) < 0) )
{
- status = BLKIF_RSP_ERROR;
+ dealloc_mfn(new_mfn);
+ status = NETIF_RSP_ERROR;
goto out;
}
- /* Record this so they can be billed. */
- netif->total_packets_received++;
- netif->total_bytes_received += size;
+ phys_to_machine_mapping[__pa(vdata) >> PAGE_SHIFT] = new_mfn;
+
+ netif->stats.tx_bytes += size;
+ netif->stats.tx_packets++;
out:
- make_rx_response(netif, rx->id, status, addr, size);
+ spin_lock(&netif->rx_lock);
+ make_rx_response(netif, id, status, virt_to_machine(vdata), size);
spin_unlock(&netif->rx_lock);
dev_kfree_skb(skb);
+ return 0;
}
-
-/*************************************************************
- * NEW TRANSMIT SCHEDULER
- *
- * NB. We ought also to only send a limited number of bytes to the NIC
- * for transmission at any one time (to avoid head-of-line blocking).
- * However, driver rings are small enough that they provide a reasonable
- * limit.
- *
- * eg. 3c905 has 16 descriptors == 8 packets, at 100Mbps
- * e1000 has 256 descriptors == 128 packets, at 1000Mbps
- * tg3 has 512 descriptors == 256 packets, at 1000Mbps
- *
- * So, worst case is tg3 with 256 1500-bytes packets == 375kB.
- * This would take 3ms, and represents our worst-case HoL blocking cost.
- *
- * We think this is reasonable.
- */
-
-struct list_head net_schedule_list;
-spinlock_t net_schedule_list_lock;
+struct net_device_stats *netif_be_get_stats(struct net_device *dev)
+{
+ netif_t *netif = dev->priv;
+ return &netif->stats;
+}
static int __on_net_schedule_list(netif_t *netif)
{
@@ -128,7 +212,7 @@ static void add_to_net_schedule_list_tail(netif_t *netif)
return;
spin_lock(&net_schedule_list_lock);
- if ( likely(!__on_net_schedule_list(netif)) )
+ if ( !__on_net_schedule_list(netif) && (netif->status == CONNECTED) )
{
list_add_tail(&netif->list, &net_schedule_list);
netif_get(netif);
@@ -136,34 +220,12 @@ static void add_to_net_schedule_list_tail(netif_t *netif)
spin_unlock(&net_schedule_list_lock);
}
-
-static void tx_skb_release(struct sk_buff *skb);
-
-static inline int init_tx_header(netif_t *netif, u8 *data,
- unsigned int len, struct net_device *dev)
+void netif_deschedule(netif_t *netif)
{
- int proto = ntohs(*(unsigned short *)(data + 12));
-
- memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
-
- switch ( proto )
- {
- case ETH_P_ARP:
- if ( len < 42 ) break;
- memcpy(data + 22, dev->dev_addr, ETH_ALEN);
- break;
- case ETH_P_IP:
- break;
- default:
- /* Unsupported protocols are onyl allowed to/from NETIF0/0. */
- if ( (netif->domain->domain != 0) || (netif->idx != 0) )
- proto = 0;
- break;
- }
- return proto;
+ remove_from_net_schedule_list(netif);
}
-
+#if 0
static void tx_credit_callback(unsigned long data)
{
netif_t *netif = (netif_t *)data;
@@ -176,6 +238,7 @@ static void tx_credit_callback(unsigned long data)
maybe_schedule_tx_action();
}
}
+#endif
static void net_tx_action(unsigned long unused)
{
@@ -184,6 +247,7 @@ static void net_tx_action(unsigned long unused)
netif_t *netif;
netif_tx_request_t txreq;
u16 pending_idx;
+ NETIF_RING_IDX i;
pgprot_t prot = __pgprot(_PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED);
while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
@@ -197,7 +261,7 @@ static void net_tx_action(unsigned long unused)
/* Work to do? */
i = netif->tx_req_cons;
- if ( (i == shared_idxs->tx_req_prod) &&
+ if ( (i == netif->tx->req_prod) &&
((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE) )
{
netif_put(netif);
@@ -246,7 +310,7 @@ static void net_tx_action(unsigned long unused)
/* No crossing a page boundary as the payload mustn't fragment. */
if ( unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >= PAGE_SIZE) )
{
- DPRINTK("tx.addr: %lx, size: %u, end: %lu\n",
+ DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n",
txreq.addr, txreq.size,
(txreq.addr &~PAGE_MASK) + txreq.size);
make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
@@ -262,42 +326,38 @@ static void net_tx_action(unsigned long unused)
PAGE_SIZE, prot, netif->domid) != 0 )
{
DPRINTK("Bad page frame\n");
- make_tx_response(netif, tx.id, NETIF_RSP_ERROR);
+ make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
netif_put(netif);
continue;
}
-
+ phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
+ txreq.addr >> PAGE_SHIFT;
+
if ( unlikely((skb = alloc_skb(PKT_PROT_LEN, GFP_ATOMIC)) == NULL) )
{
- make_tx_response(netif, tx.id, BLKIF_RSP_ERROR);
+ make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
netif_put(netif);
vmfree_area_pages(MMAP_VADDR(pending_idx), PAGE_SIZE);
break;
}
- __skb_put(PKT_PROT_LEN);
- memcpy(skb->data, src, PKT_PROT_LEN);
- protocol = __constant_htons(
- init_tx_header(netif, g_data, tx.size, the_dev));
- if ( protocol == 0 )
- {
- make_tx_response(netif, tx.id, NETIF_RSP_ERROR);
- netif_put(netif);
- dev_kfree_skb(skb);
- goto cleanup_and_continue;
- }
+ __skb_put(skb, PKT_PROT_LEN);
+ memcpy(skb->data,
+ (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
+ PKT_PROT_LEN);
skb->dev = netif->dev;
skb->protocol = eth_type_trans(skb, skb->dev);
/* Append the packet payload as a fragment. */
skb_shinfo(skb)->frags[0].page =
- &mem_map[txreq.addr >> PAGE_SHIFT];
- skb_shinfo(skb)->frags[0].size = txreq.size - PKT_PROT_LEN;
+ virt_to_page(MMAP_VADDR(pending_idx));
+ skb_shinfo(skb)->frags[0].size =
+ txreq.size - PKT_PROT_LEN;
skb_shinfo(skb)->frags[0].page_offset =
(txreq.addr + PKT_PROT_LEN) & ~PAGE_MASK;
skb_shinfo(skb)->nr_frags = 1;
- skb->data_len = tx->size - PKT_PROT_LEN;
+ skb->data_len = txreq.size - PKT_PROT_LEN;
skb->len += skb->data_len;
/* Destructor information. */
@@ -305,33 +365,22 @@ static void net_tx_action(unsigned long unused)
skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].page = (struct page *)netif;
skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].size = pending_idx;
- /* Record the transmission so they can be billed. */
- netif->total_packets_sent++;
- netif->total_bytes_sent += tx->size;
+ netif->stats.rx_bytes += txreq.size;
+ netif->stats.rx_packets++;
+ pending_id[pending_idx] = txreq.id;
pending_cons++;
+
netif_rx(skb);
netif->dev->last_rx = jiffies;
}
}
-DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
-
-
-static inline void maybe_schedule_tx_action(void)
-{
- smp_mb();
- if ( !netif_queue_stopped(the_dev) &&
- !list_empty(&net_schedule_list) )
- tasklet_schedule(&net_tx_tasklet);
-}
-
-
/* Destructor function for tx skbs. */
static void tx_skb_release(struct sk_buff *skb)
{
- int i;
- netif_t *netif = (netif_t)skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].page;
+ unsigned long flags;
+ netif_t *netif = (netif_t *)skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].page;
u16 pending_idx = skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].size;
vmfree_area_pages(MMAP_VADDR(pending_idx), PAGE_SIZE);
@@ -339,25 +388,19 @@ static void tx_skb_release(struct sk_buff *skb)
skb_shinfo(skb)->nr_frags = 0;
spin_lock(&netif->tx_lock);
- make_tx_response(netif, skb->guest_id, NETIF_RSP_OKAY);
+ make_tx_response(netif, pending_id[pending_idx], NETIF_RSP_OKAY);
spin_unlock(&netif->tx_lock);
- /*
- * Checks below must happen after the above response is posted. This avoids
- * a possible race with a guest OS on another CPU.
- */
- mb();
-
- if ( tx_work_exists(netif) )
- {
- add_to_net_schedule_list_tail(netif);
- maybe_schedule_tx_action();
- }
-
netif_put(netif);
+
+ spin_lock_irqsave(&pend_prod_lock, flags);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ spin_unlock_irqrestore(&pend_prod_lock, flags);
+
+ maybe_schedule_tx_action();
}
-
+#if 0
long flush_bufs_for_netif(netif_t *netif)
{
NET_RING_IDX i;
@@ -395,6 +438,7 @@ long flush_bufs_for_netif(netif_t *netif)
return 0;
}
+#endif
void netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -424,7 +468,6 @@ static void make_tx_response(netif_t *netif,
notify_via_evtchn(netif->evtchn);
}
-
static void make_rx_response(netif_t *netif,
u16 id,
s8 st,
@@ -448,28 +491,18 @@ static void make_rx_response(netif_t *netif,
notify_via_evtchn(netif->evtchn);
}
-
static int __init init_module(void)
{
netif_interface_init();
-
- if ( (mmap_vma = get_vm_area(MAX_PENDING_REQS * PAGE_SIZE,
- VM_IOREMAP)) == NULL )
- {
- printk(KERN_WARNING "Could not allocate VMA for netif backend.\n");
- return -ENOMEM;
- }
-
+ mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS);
netif_ctrlif_init();
-
return 0;
}
-
static void cleanup_module(void)
{
+ BUG();
}
-
module_init(init_module);
module_exit(cleanup_module);
diff --git a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c
index f2c36f1f88..af8e660b7c 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c
+++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c
@@ -25,6 +25,10 @@
#include <net/sock.h>
#include <net/pkt_sched.h>
+#include "../netif.h"
+
+static struct tq_struct netif_statechange_tq;
+
#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
static void network_interrupt(int irq, void *dev_id, struct pt_regs *ptregs);
@@ -44,17 +48,21 @@ struct net_private
struct net_device_stats stats;
NET_RING_IDX rx_resp_cons, tx_resp_cons;
- unsigned int net_ring_fixmap_idx, tx_full;
- net_ring_t *net_ring;
- net_idx_t *net_idx;
+ unsigned int tx_full;
+
+ netif_tx_interface_t *tx;
+ netif_rx_interface_t *rx;
+
spinlock_t tx_lock;
- unsigned int idx; /* Domain-specific index of this VIF. */
- unsigned int rx_bufs_to_notify;
+ unsigned int handle;
+ unsigned int evtchn;
+ unsigned int irq;
-#define STATE_ACTIVE 0
-#define STATE_SUSPENDED 1
-#define STATE_CLOSED 2
+#define NETIF_STATE_CLOSED 0
+#define NETIF_STATE_DISCONNECTED 1
+#define NETIF_STATE_CONNECTED 2
+#define NETIF_STATE_ACTIVE 3
unsigned int state;
/*
@@ -75,36 +83,17 @@ struct net_private
(unsigned short)_id; })
-static void _dbg_network_int(struct net_device *dev)
-{
- struct net_private *np = dev->priv;
-
- if ( np->state == STATE_CLOSED )
- return;
-
- printk(KERN_ALERT "net: tx_full=%d, tx_resp_cons=0x%08x,"
- " tx_req_prod=0x%08x\nnet: tx_resp_prod=0x%08x,"
- " tx_event=0x%08x, state=%d\n",
- np->tx_full, np->tx_resp_cons,
- np->net_idx->tx_req_prod, np->net_idx->tx_resp_prod,
- np->net_idx->tx_event,
- test_bit(__LINK_STATE_XOFF, &dev->state));
- printk(KERN_ALERT "net: rx_resp_cons=0x%08x,"
- " rx_req_prod=0x%08x\nnet: rx_resp_prod=0x%08x, rx_event=0x%08x\n",
- np->rx_resp_cons, np->net_idx->rx_req_prod,
- np->net_idx->rx_resp_prod, np->net_idx->rx_event);
-}
-
-
-static void dbg_network_int(int irq, void *unused, struct pt_regs *ptregs)
+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);
- _dbg_network_int(np->dev);
+ if ( np->handle == handle )
+ return np;
}
+ return NULL;
}
@@ -114,36 +103,12 @@ static int network_open(struct net_device *dev)
netop_t netop;
int i, ret;
- netop.cmd = NETOP_RESET_RINGS;
- netop.vif = np->idx;
- if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 )
- {
- printk(KERN_ALERT "Possible net trouble: couldn't reset ring idxs\n");
- return ret;
- }
-
- netop.cmd = NETOP_GET_VIF_INFO;
- netop.vif = np->idx;
- if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 )
- {
- printk(KERN_ALERT "Couldn't get info for vif %d\n", np->idx);
- return ret;
- }
-
- memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN);
+ if ( np->state != NETIF_STATE_CONNECTED )
+ return -EINVAL;
- set_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx,
- netop.u.get_vif_info.ring_mfn << PAGE_SHIFT);
- np->net_ring = (net_ring_t *)fix_to_virt(
- FIX_NETRING0_BASE + np->net_ring_fixmap_idx);
- np->net_idx = &HYPERVISOR_shared_info->net_idx[np->idx];
-
- np->rx_bufs_to_notify = 0;
np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
memset(&np->stats, 0, sizeof(np->stats));
spin_lock_init(&np->tx_lock);
- memset(np->net_ring, 0, sizeof(*np->net_ring));
- memset(np->net_idx, 0, sizeof(*np->net_idx));
/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
for ( i = 0; i <= XENNET_TX_RING_SIZE; i++ )
@@ -152,7 +117,7 @@ static int network_open(struct net_device *dev)
np->rx_skbs[i] = (void *)(i+1);
wmb();
- np->state = STATE_ACTIVE;
+ np->state = NETIF_STATE_ACTIVE;
network_alloc_rx_buffers(dev);
@@ -203,7 +168,7 @@ static void network_tx_buf_gc(struct net_device *dev)
((np->net_idx->tx_req_prod - prod) < XENNET_TX_RING_SIZE) )
{
np->tx_full = 0;
- if ( np->state == STATE_ACTIVE )
+ if ( np->state == NETIF_STATE_ACTIVE )
netif_wake_queue(dev);
}
}
@@ -228,7 +193,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
NET_RING_IDX i = np->net_idx->rx_req_prod;
if ( unlikely((i - np->rx_resp_cons) == XENNET_RX_RING_SIZE) ||
- unlikely(np->state != STATE_ACTIVE) )
+ unlikely(np->state != NETIF_STATE_ACTIVE) )
return;
do {
@@ -341,17 +306,15 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
-static inline void _network_interrupt(struct net_device *dev)
+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;
struct sk_buff *skb;
rx_resp_entry_t *rx;
NET_RING_IDX i;
- if ( unlikely(np->state == STATE_CLOSED) )
- return;
-
spin_lock_irqsave(&np->tx_lock, flags);
network_tx_buf_gc(dev);
spin_unlock_irqrestore(&np->tx_lock, flags);
@@ -367,7 +330,7 @@ static inline void _network_interrupt(struct net_device *dev)
if ( unlikely(rx->status != RING_STATUS_OK) )
{
/* Gate this error. We get a (valid) slew of them on suspend. */
- if ( np->state == STATE_ACTIVE )
+ if ( np->state == NETIF_STATE_ACTIVE )
printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
dev_kfree_skb_any(skb);
continue;
@@ -407,26 +370,11 @@ static inline void _network_interrupt(struct net_device *dev)
}
-static void network_interrupt(int irq, void *unused, struct pt_regs *ptregs)
-{
- struct list_head *ent;
- struct net_private *np;
- list_for_each ( ent, &dev_list )
- {
- np = list_entry(ent, struct net_private, list);
- _network_interrupt(np->dev);
- }
-}
-
-
static int network_close(struct net_device *dev)
{
struct net_private *np = dev->priv;
netop_t netop;
- np->state = STATE_SUSPENDED;
- wmb();
-
netif_stop_queue(np->dev);
netop.cmd = NETOP_FLUSH_BUFFERS;
@@ -442,12 +390,9 @@ static int network_close(struct net_device *dev)
}
wmb();
- np->state = STATE_CLOSED;
+ np->state = NETIF_STATE_CONNECTED;
wmb();
- /* Now no longer safe to take interrupts for this device. */
- clear_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx);
-
MOD_DEC_USE_COUNT;
return 0;
@@ -461,72 +406,181 @@ static struct net_device_stats *network_get_stats(struct net_device *dev)
}
-static int __init init_module(void)
+static void netif_bringup_phase1(void *unused)
{
-#if 0
- int i, fixmap_idx=-1, err;
+ ctrl_msg_t cmsg;
+ netif_fe_interface_connect_t up;
struct net_device *dev;
struct net_private *np;
- netop_t netop;
- INIT_LIST_HEAD(&dev_list);
+ dev = find_dev_by_handle(0);
+ np = dev->priv;
+
+ /* 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->state = NETIF_STATE_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 = 0;
+ 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);
+}
- network_irq = bind_virq_to_irq(VIRQ_NET);
- debug_irq = bind_virq_to_irq(VIRQ_DEBUG);
+static void netif_bringup_phase2(void *unused)
+{
+ struct net_device *dev;
+ struct net_private *np;
+
+ dev = find_dev_by_handle(0);
+ np = dev->priv;
+
+ np->irq = bind_evtchn_to_irq(np->evtchn);
+ (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM,
+ "netif", dev);
- err = request_irq(network_irq, network_interrupt,
- SA_SAMPLE_RANDOM, "network", NULL);
- if ( err )
+ np->state = NETIF_STATE_CONNECTED;
+}
+
+static void netif_status_change(netif_fe_interface_status_changed_t *status)
+{
+ struct net_device *dev;
+ struct net_private *np;
+
+ if ( status->handle != 0 )
{
- printk(KERN_WARNING "Could not allocate network interrupt\n");
- goto fail;
+ printk(KERN_WARNING "Status change on unsupported netif %d\n",
+ status->handle);
+ return;
}
-
- err = request_irq(debug_irq, dbg_network_int,
- SA_SHIRQ, "net_dbg", &dbg_network_int);
- if ( err )
- printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
- for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
+ dev = find_dev_by_handle(0);
+ np = dev->priv;
+
+ switch ( status->status )
{
- /* If the VIF is invalid then the query hypercall will fail. */
- netop.cmd = NETOP_GET_VIF_INFO;
- netop.vif = i;
- if ( HYPERVISOR_net_io_op(&netop) != 0 )
- continue;
+ case NETIF_INTERFACE_STATUS_DESTROYED:
+ printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n",
+ netif_state);
+ break;
- /* We actually only support up to 4 vifs right now. */
- if ( ++fixmap_idx == 4 )
+ case NETIF_INTERFACE_STATUS_DISCONNECTED:
+ if ( np->state != NETIF_STATE_CLOSED )
+ {
+ printk(KERN_WARNING "Unexpected netif-DISCONNECTED message"
+ " in state %d\n", netif_state);
break;
+ }
+ netif_statechange_tq.routine = netif_bringup_phase1;
+ schedule_task(&netif_statechange_tq);
+ break;
- dev = alloc_etherdev(sizeof(struct net_private));
- if ( dev == NULL )
+ case NETIF_INTERFACE_STATUS_CONNECTED:
+ if ( np->state == NETIF_STATE_CLOSED )
{
- err = -ENOMEM;
- goto fail;
+ printk(KERN_WARNING "Unexpected netif-CONNECTED message"
+ " in state %d\n", netif_state);
+ break;
}
+ np->evtchn = status->evtchn;
+ memcpy(dev->dev_addr, status->mac, ETH_ALEN);
+ netif_statechange_tq.routine = netif_bringup_phase2;
+ schedule_task(&netif_statechange_tq);
+ break;
+
+ default:
+ printk(KERN_WARNING "Status change to unknown value %d\n",
+ status->status);
+ break;
+ }
+}
+
+
+static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+{
+ switch ( msg->subtype )
+ {
+ case CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ if ( msg->length != sizeof(netif_fe_interface_status_changed_t) )
+ goto parse_error;
+ netif_status_change((netif_fe_interface_status_changed_t *)
+ &msg->msg[0]);
+ break;
+ default:
+ goto parse_error;
+ }
- np = dev->priv;
- np->state = STATE_CLOSED;
- np->net_ring_fixmap_idx = fixmap_idx;
- np->idx = i;
+ ctrl_if_send_response(msg);
+ return;
- SET_MODULE_OWNER(dev);
- dev->open = network_open;
- dev->hard_start_xmit = network_start_xmit;
- dev->stop = network_close;
- dev->get_stats = network_get_stats;
+ parse_error:
+ msg->length = 0;
+ ctrl_if_send_response(msg);
+}
- memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN);
- if ( (err = register_netdev(dev)) != 0 )
- {
- kfree(dev);
- goto fail;
- }
+static int __init init_module(void)
+{
+ ctrl_msg_t cmsg;
+ netif_fe_driver_status_changed_t st;
+ int i, err;
+ struct net_device *dev;
+ struct net_private *np;
+
+ INIT_LIST_HEAD(&dev_list);
- np->dev = dev;
- list_add(&np->list, &dev_list);
+ if ( (dev = alloc_etherdev(sizeof(struct net_private))) == NULL )
+ {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ np = dev->priv;
+ np->state = NETIF_STATE_CLOSED;
+ np->handle = 0;
+
+ dev->open = network_open;
+ dev->hard_start_xmit = network_start_xmit;
+ dev->stop = network_close;
+ dev->get_stats = network_get_stats;
+
+ if ( (err = register_netdev(dev)) != 0 )
+ {
+ kfree(dev);
+ goto fail;
+ }
+
+ np->dev = dev;
+ list_add(&np->list, &dev_list);
+
+ (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
+
+ /* 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;
+ memcpy(cmsg.msg, &st, sizeof(st));
+ ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+
+ /*
+ * We should read 'nr_interfaces' from response message and wait
+ * for notifications before proceeding. For now we assume that we
+ * will be notified of exactly one interface.
+ */
+ while ( np->state != NETIF_STATE_CONNECTED )
+ {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
}
return 0;
@@ -534,30 +588,13 @@ static int __init init_module(void)
fail:
cleanup_module();
return err;
-#endif
- return 0;
}
static void cleanup_module(void)
{
- struct net_private *np;
- struct net_device *dev;
-
- while ( !list_empty(&dev_list) )
- {
- np = list_entry(dev_list.next, struct net_private, list);
- list_del(&np->list);
- dev = np->dev;
- unregister_netdev(dev);
- kfree(dev);
- }
-
- free_irq(network_irq, NULL);
- free_irq(debug_irq, NULL);
-
- unbind_virq_from_irq(VIRQ_NET);
- unbind_virq_from_irq(VIRQ_DEBUG);
+ /* XXX FIXME */
+ BUG();
}
diff --git a/xenolinux-2.4.26-sparse/arch/xen/mm/hypervisor.c b/xenolinux-2.4.26-sparse/arch/xen/mm/hypervisor.c
index c6dc710576..e27616e4d4 100644
--- a/xenolinux-2.4.26-sparse/arch/xen/mm/hypervisor.c
+++ b/xenolinux-2.4.26-sparse/arch/xen/mm/hypervisor.c
@@ -8,7 +8,10 @@
#include <linux/config.h>
#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
#include <asm/hypervisor.h>
+#include <asm/hypervisor-ifs/dom_mem_ops.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/multicall.h>
@@ -242,3 +245,105 @@ void queue_set_ldt(unsigned long ptr, unsigned long len)
increment_index();
spin_unlock_irqrestore(&update_lock, flags);
}
+
+void queue_machphys_update(unsigned long mfn, unsigned long pfn)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&update_lock, flags);
+ update_queue[idx].ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+ update_queue[idx].val = pfn;
+ increment_index();
+ spin_unlock_irqrestore(&update_lock, flags);
+}
+
+#ifdef CONFIG_XEN_PHYSDEV_ACCESS
+
+unsigned long allocate_empty_lowmem_region(unsigned long pages)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long *pfn_array;
+ unsigned long vstart;
+ unsigned long i;
+ int ret;
+ unsigned int order = get_order(pages*PAGE_SIZE);
+ dom_mem_op_t dom_mem_op;
+
+ vstart = __get_free_pages(GFP_KERNEL, order);
+ if ( vstart == 0 )
+ return 0UL;
+
+ pfn_array = vmalloc((1<<order) * sizeof(*pfn_array));
+ if ( pfn_array == NULL )
+ BUG();
+
+ for ( i = 0; i < (1<<order); i++ )
+ {
+ pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE)));
+ pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE)));
+ pte = pte_offset(pmd, (vstart + (i*PAGE_SIZE)));
+ pfn_array[i] = pte->pte_low >> PAGE_SHIFT;
+ queue_l1_entry_update(pte, 0);
+ phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = 0xdeadbeef;
+ }
+
+ flush_page_update_queue();
+
+ dom_mem_op.op = MEMOP_RESERVATION_DECREASE;
+ dom_mem_op.u.decrease.size = 1<<order;
+ dom_mem_op.u.decrease.pages = pfn_array;
+ if ( (ret = HYPERVISOR_dom_mem_op(&dom_mem_op)) != (1<<order) )
+ {
+ printk(KERN_WARNING "Unable to reduce memory reservation (%d)\n", ret);
+ BUG();
+ }
+
+ vfree(pfn_array);
+
+ return vstart;
+}
+
+void deallocate_lowmem_region(unsigned long vstart, unsigned long pages)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long *pfn_array;
+ unsigned long i;
+ int ret;
+ unsigned int order = get_order(pages*PAGE_SIZE);
+ dom_mem_op_t dom_mem_op;
+
+ pfn_array = vmalloc((1<<order) * sizeof(*pfn_array));
+ if ( pfn_array == NULL )
+ BUG();
+
+ dom_mem_op.op = MEMOP_RESERVATION_INCREASE;
+ dom_mem_op.u.increase.size = 1<<order;
+ dom_mem_op.u.increase.pages = pfn_array;
+ if ( (ret = HYPERVISOR_dom_mem_op(&dom_mem_op)) != (1<<order) )
+ {
+ printk(KERN_WARNING "Unable to increase memory reservation (%d)\n",
+ ret);
+ BUG();
+ }
+
+ for ( i = 0; i < (1<<order); i++ )
+ {
+ pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE)));
+ pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE)));
+ pte = pte_offset(pmd, (vstart + (i*PAGE_SIZE)));
+ queue_l1_entry_update(pte, (pfn_array[i]<<PAGE_SHIFT)|__PAGE_KERNEL);
+ queue_machphys_update(pfn_array[i], __pa(vstart)>>PAGE_SHIFT);
+ phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = pfn_array[i];
+ }
+
+ flush_page_update_queue();
+
+ vfree(pfn_array);
+
+ free_pages(vstart, order);
+}
+
+#endif /* CONFIG_XEN_PHYSDEV_ACCESS */