mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.34 (3e4cfce1Ot4YJzJ4jwNjDthlFrZV5w)
conflict resolution.
This commit is contained in:
commit
ed22010809
32 files changed
+3594
-3645
No files matched your search
@@ -77,10 +77,8 @@
|
||||
3ddb79bdkDY1bSOYkToP1Cc49VdBxg xen-2.4.16/drivers/ide/ide.c
|
||||
3ddb79bdPyAvT_WZTAFhaX0jp-yXSw xen-2.4.16/drivers/ide/ide_modes.h
|
||||
3e4a8d401aSwOzCScQXR3lsmNlAwUQ xen-2.4.16/drivers/ide/piix.c
|
||||
3ddb79bfogeJNHTIepPjd8fy1TyoTw xen-2.4.16/drivers/net/3c509.c
|
||||
3ddb79bfMlOcWUwjtg6oMYhGySHDDw xen-2.4.16/drivers/net/3c59x.c
|
||||
3ddb79bfl_DWxZQFKiJ2BXrSedV4lg xen-2.4.16/drivers/net/8139cp.c
|
||||
3ddb79bfLVGtyXNJS4NQg-lP21rndA xen-2.4.16/drivers/net/8139too.c
|
||||
3ddb79c0tWiE8xIFHszxipeVCGKTSA xen-2.4.16/drivers/net/Makefile
|
||||
3ddb79bfU-H1Hms4BuJEPPydjXUEaQ xen-2.4.16/drivers/net/Space.c
|
||||
3e4540ccS4bfbx9rLiLElP0F1OVwZA xen-2.4.16/drivers/net/e1000/LICENSE
|
||||
@@ -160,6 +158,7 @@
|
||||
3e20b82fl1jmQiKdLy7fxMcutfpjWA xen-2.4.16/include/asm-i386/domain_page.h
|
||||
3ddb79c2O729EttZTYu1c8LcsUO_GQ xen-2.4.16/include/asm-i386/elf.h
|
||||
3ddb79c3NU8Zy40OTrq3D-i30Y3t4A xen-2.4.16/include/asm-i386/fixmap.h
|
||||
3e2d29944GI24gf7vOP_7x8EyuqxeA xen-2.4.16/include/asm-i386/flushtlb.h
|
||||
3ddb79c39o75zPP0T1aQQ4mNrCAN2w xen-2.4.16/include/asm-i386/hardirq.h
|
||||
3ddb79c3BFEIwXR4IsWbwp4BoL4DkA xen-2.4.16/include/asm-i386/hdreg.h
|
||||
3ddb79c3TMDjkxVndKFKnGiwY0HzDg xen-2.4.16/include/asm-i386/i387.h
|
||||
@@ -442,6 +441,7 @@
|
||||
3ddb79bbA52x94o6uwDYsbzrH2hjzA xenolinux-2.4.16-sparse/include/asm-xeno/xor.h
|
||||
3e4a8cb7ON8EclY3NN3YPXyMT941hA xenolinux-2.4.16-sparse/include/linux/blk.h
|
||||
3e4a8cb7GJrKD0z7EF0VZOhdEa01Mw xenolinux-2.4.16-sparse/include/linux/major.h
|
||||
3e37c39fVCSGQENtY6g7muaq_THliw xenolinux-2.4.16-sparse/include/linux/skbuff.h
|
||||
3ddb79bb_7YG4U75ZmEic9YXWTW7Vw xenolinux-2.4.16-sparse/include/linux/sunrpc/debug.h
|
||||
3e4a8cb7j05wwb1uPZgY16s68o7qAw xenolinux-2.4.16-sparse/init/main.c
|
||||
3ddb79bcxkVPfWlZ1PQKvDrfArzOVw xenolinux-2.4.16-sparse/kernel/panic.c
|
||||
@@ -449,3 +449,4 @@
|
||||
3e15d52e0_j129JPvo7xfYGndVFpwQ xenolinux-2.4.16-sparse/mm/memory.c
|
||||
3e15d535DLvpzTrLRUIerB69LpJD1g xenolinux-2.4.16-sparse/mm/mremap.c
|
||||
3e15d531m1Y1_W8ki64AFOU_ua4C4w xenolinux-2.4.16-sparse/mm/swapfile.c
|
||||
3e37c312QFuzIxXsuAgO6IRt3Tp96Q xenolinux-2.4.16-sparse/net/core/skbuff.c
|
||||
@@ -1,5 +1,6 @@
|
||||
akw27@boulderdash.cl.cam.ac.uk
|
||||
akw27@labyrinth.cl.cam.ac.uk
|
||||
akw27@plucky.localdomain
|
||||
bd240@boulderdash.cl.cam.ac.uk
|
||||
iap10@labyrinth.cl.cam.ac.uk
|
||||
kaf24@labyrinth.cl.cam.ac.uk
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <xeno/dom0_ops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/domain_page.h>
|
||||
#include <asm/flushtlb.h>
|
||||
#include <asm/msr.h>
|
||||
#include <xeno/multiboot.h>
|
||||
|
||||
@@ -175,10 +176,13 @@ unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
|
||||
struct pfn_info *pf;
|
||||
unsigned int alloc_pfns;
|
||||
unsigned int req_pages;
|
||||
unsigned long flags;
|
||||
|
||||
/* how many pages do we need to alloc? */
|
||||
req_pages = kbytes >> (PAGE_SHIFT - 10);
|
||||
|
||||
spin_lock_irqsave(&free_list_lock, flags);
|
||||
|
||||
/* is there enough mem to serve the request? */
|
||||
if ( req_pages > free_pfns ) return -1;
|
||||
|
||||
@@ -194,6 +198,8 @@ unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
|
||||
list_add_tail(&pf->list, &p->pg_head);
|
||||
free_pfns--;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&free_list_lock, flags);
|
||||
|
||||
p->tot_pages = req_pages;
|
||||
|
||||
@@ -350,6 +356,7 @@ static unsigned long alloc_page_from_domain(unsigned long * cur_addr,
|
||||
*/
|
||||
int setup_guestos(struct task_struct *p, dom0_newdomain_t *params)
|
||||
{
|
||||
|
||||
struct list_head *list_ent;
|
||||
char *src, *dst;
|
||||
int i, dom = p->domain;
|
||||
@@ -517,8 +524,7 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params)
|
||||
|
||||
/* Install the new page tables. */
|
||||
__cli();
|
||||
__asm__ __volatile__ (
|
||||
"mov %%eax,%%cr3" : : "a" (pagetable_val(p->mm.pagetable)));
|
||||
__write_cr3_counted(pagetable_val(p->mm.pagetable));
|
||||
|
||||
/* Copy the guest OS image. */
|
||||
src = (char *)__va(mod[0].mod_start + 12);
|
||||
@@ -594,8 +600,7 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params)
|
||||
}
|
||||
|
||||
/* Reinstate the caller's page tables. */
|
||||
__asm__ __volatile__ (
|
||||
"mov %%eax,%%cr3" : : "a" (pagetable_val(current->mm.pagetable)));
|
||||
__write_cr3_counted(pagetable_val(current->mm.pagetable));
|
||||
__sti();
|
||||
|
||||
new_thread(p,
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
typedef void (*hyp_event_callback_fn_t)(void);
|
||||
|
||||
extern void schedule(void);
|
||||
extern void flush_rx_queue(void);
|
||||
extern void flush_blk_queue(void);
|
||||
extern void update_shared_ring(void);
|
||||
|
||||
/* Ordering must match definitions of _HYP_EVENT_* in xeno/sched.h */
|
||||
static hyp_event_callback_fn_t event_call_fn[] =
|
||||
{
|
||||
schedule,
|
||||
flush_rx_queue,
|
||||
update_shared_ring,
|
||||
kill_domain,
|
||||
flush_blk_queue
|
||||
};
|
||||
|
||||
+31
-24
@@ -14,6 +14,7 @@
|
||||
#include <xeno/dom0_ops.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <asm/domain_page.h>
|
||||
|
||||
/* VGA text definitions. */
|
||||
#define COLUMNS 80
|
||||
@@ -301,11 +302,11 @@ void panic(const char *fmt, ...)
|
||||
char buf[1024], *p;
|
||||
unsigned long flags;
|
||||
extern void machine_restart(char *);
|
||||
|
||||
|
||||
va_start(args, fmt);
|
||||
(void)vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
/* Spit out multiline message in one go. */
|
||||
spin_lock_irqsave(&console_lock, flags);
|
||||
__putstr("\n****************************************\n");
|
||||
@@ -357,6 +358,7 @@ unsigned short compute_cksum(unsigned short *buf, int count)
|
||||
/* XXX SMH: below is rather vile; pulled in to allow network console */
|
||||
|
||||
extern int netif_rx(struct sk_buff *);
|
||||
extern struct net_device *the_dev;
|
||||
|
||||
typedef struct my_udphdr {
|
||||
__u16 source;
|
||||
@@ -407,17 +409,24 @@ int console_export(char *str, int len)
|
||||
struct my_udphdr *udph = NULL;
|
||||
struct my_ethhdr *ethh = NULL;
|
||||
int hdr_size = sizeof(struct my_iphdr) + sizeof(struct my_udphdr);
|
||||
|
||||
// Prepare console packet
|
||||
console_packet = alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len,
|
||||
GFP_KERNEL);
|
||||
u8 *skb_data;
|
||||
|
||||
// Prepare console packet - the grim + 20 in the alloc is for headroom.
|
||||
console_packet = dev_alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len + 20);
|
||||
if (!console_packet) return 0;
|
||||
//console_packet->security = 9; // hack to trace these packets.
|
||||
console_packet->dev = the_dev;
|
||||
skb_data = map_domain_mem((unsigned long)console_packet->head);
|
||||
skb_reserve(console_packet, 2); // ip header alignment.
|
||||
//printk("Eth is: %d\n", console_packet->data - console_packet->head);
|
||||
ethh = (struct my_ethhdr *) skb_data + (console_packet->data - console_packet->head);
|
||||
skb_reserve(console_packet, sizeof(struct my_ethhdr));
|
||||
ethh = (struct my_ethhdr *)console_packet->head;
|
||||
|
||||
skb_put(console_packet, hdr_size + len);
|
||||
iph = (struct my_iphdr *)console_packet->data;
|
||||
udph = (struct my_udphdr *)(iph + 1);
|
||||
memcpy((char *)(udph + 1), str, len);
|
||||
//printk("IP is: %d\n", console_packet->data - console_packet->head);
|
||||
iph = (struct my_iphdr *)skb_data + (console_packet->data - console_packet->head);
|
||||
udph = (struct my_udphdr *)(iph + 1);
|
||||
memcpy((char *)(udph + 1), str, len);
|
||||
|
||||
// Build IP header
|
||||
iph->version = 4;
|
||||
@@ -446,6 +455,13 @@ int console_export(char *str, int len)
|
||||
memcpy(ethh->h_dest, "000000", 6);
|
||||
ethh->h_proto = htons(ETH_P_IP);
|
||||
console_packet->mac.ethernet= (struct ethhdr *)ethh;
|
||||
|
||||
// Make the packet appear to come off the external NIC so that the
|
||||
// tables code doesn't get too confused.
|
||||
console_packet->src_vif = VIF_PHYSICAL_INTERFACE;
|
||||
console_packet->dst_vif = 0;
|
||||
|
||||
unmap_domain_mem(skb_data);
|
||||
|
||||
// Pass the packet to netif_rx
|
||||
(void)netif_rx(console_packet);
|
||||
@@ -481,23 +497,14 @@ long do_console_write(char *str, int count)
|
||||
|
||||
if ( !safe_str[i] ) break;
|
||||
putchar(prev = safe_str[i]);
|
||||
|
||||
if ( prev == '\n' )
|
||||
{
|
||||
exported_str[j]='\0';
|
||||
console_export(exported_str, j-1);
|
||||
j=0;
|
||||
}
|
||||
|
||||
}
|
||||
if ( prev != '\n' )
|
||||
{
|
||||
putchar('\n');
|
||||
exported_str[j]='\0';
|
||||
console_export(exported_str, j-1);
|
||||
}
|
||||
|
||||
if ( prev != '\n' ) putchar('\n');
|
||||
|
||||
spin_unlock_irqrestore(&console_lock, flags);
|
||||
|
||||
exported_str[j]='\0';
|
||||
console_export(exported_str, j-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -171,6 +171,7 @@
|
||||
#include <xeno/sched.h>
|
||||
#include <xeno/errno.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/flushtlb.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/domain_page.h>
|
||||
@@ -205,6 +206,7 @@ unsigned long frame_table_size;
|
||||
unsigned long max_page;
|
||||
|
||||
struct list_head free_list;
|
||||
spinlock_t free_list_lock = SPIN_LOCK_UNLOCKED;
|
||||
unsigned int free_pfns;
|
||||
|
||||
static int tlb_flush[NR_CPUS];
|
||||
@@ -218,6 +220,7 @@ void __init init_frametable(unsigned long nr_pages)
|
||||
{
|
||||
struct pfn_info *pf;
|
||||
unsigned long page_index;
|
||||
unsigned long flags;
|
||||
|
||||
memset(tlb_flush, 0, sizeof(tlb_flush));
|
||||
|
||||
@@ -230,6 +233,7 @@ void __init init_frametable(unsigned long nr_pages)
|
||||
free_pfns = 0;
|
||||
|
||||
/* Put all domain-allocatable memory on a free list. */
|
||||
spin_lock_irqsave(&free_list_lock, flags);
|
||||
INIT_LIST_HEAD(&free_list);
|
||||
for( page_index = (__pa(frame_table) + frame_table_size) >> PAGE_SHIFT;
|
||||
page_index < nr_pages;
|
||||
@@ -239,6 +243,7 @@ void __init init_frametable(unsigned long nr_pages)
|
||||
list_add_tail(&pf->list, &free_list);
|
||||
free_pfns++;
|
||||
}
|
||||
spin_unlock_irqrestore(&free_list_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -697,7 +702,6 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int do_process_page_updates(page_update_request_t *ureqs, int count)
|
||||
{
|
||||
page_update_request_t req;
|
||||
@@ -807,11 +811,10 @@ int do_process_page_updates(page_update_request_t *ureqs, int count)
|
||||
if ( tlb_flush[smp_processor_id()] )
|
||||
{
|
||||
tlb_flush[smp_processor_id()] = 0;
|
||||
__asm__ __volatile__ (
|
||||
"movl %%eax,%%cr3" : :
|
||||
"a" (pagetable_val(current->mm.pagetable)));
|
||||
__write_cr3_counted(pagetable_val(current->mm.pagetable));
|
||||
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
+61
-24
@@ -49,6 +49,7 @@ net_vif_t *create_net_vif(int domain)
|
||||
{
|
||||
net_vif_t *new_vif;
|
||||
net_ring_t *new_ring;
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
struct task_struct *dom_task;
|
||||
|
||||
if ( !(dom_task = find_domain_by_id(domain)) )
|
||||
@@ -64,7 +65,27 @@ net_vif_t *create_net_vif(int domain)
|
||||
new_ring = dom_task->net_ring_base + dom_task->num_net_vifs;
|
||||
memset(new_ring, 0, sizeof(net_ring_t));
|
||||
|
||||
// allocate the shadow ring.
|
||||
// maybe these should be kmem_cache instead of kmalloc?
|
||||
|
||||
shadow_ring = kmalloc(sizeof(net_shadow_ring_t), GFP_KERNEL);
|
||||
if (shadow_ring == NULL) goto fail;
|
||||
|
||||
shadow_ring->tx_ring = kmalloc(TX_RING_SIZE
|
||||
* sizeof(tx_shadow_entry_t), GFP_KERNEL);
|
||||
shadow_ring->rx_ring = kmalloc(RX_RING_SIZE
|
||||
* sizeof(rx_shadow_entry_t), GFP_KERNEL);
|
||||
if ((shadow_ring->tx_ring == NULL) || (shadow_ring->rx_ring == NULL))
|
||||
goto fail;
|
||||
|
||||
shadow_ring->rx_prod = shadow_ring->rx_cons = shadow_ring->rx_idx = 0;
|
||||
|
||||
// fill in the new vif struct.
|
||||
|
||||
new_vif->net_ring = new_ring;
|
||||
new_vif->shadow_ring = shadow_ring;
|
||||
|
||||
|
||||
skb_queue_head_init(&new_vif->skb_list);
|
||||
new_vif->domain = domain;
|
||||
|
||||
@@ -77,6 +98,10 @@ net_vif_t *create_net_vif(int domain)
|
||||
dom_task->num_net_vifs++;
|
||||
|
||||
return new_vif;
|
||||
|
||||
fail:
|
||||
printk("VIF allocation failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* delete_net_vif - Delete the last vif in the given domain.
|
||||
@@ -101,7 +126,10 @@ void destroy_net_vif(struct task_struct *p)
|
||||
write_lock(&sys_vif_lock);
|
||||
sys_vif_list[p->net_vif_list[i]->id] = NULL; // system vif list not gc'ed
|
||||
write_unlock(&sys_vif_lock);
|
||||
|
||||
|
||||
kfree(p->net_vif_list[i]->shadow_ring->tx_ring);
|
||||
kfree(p->net_vif_list[i]->shadow_ring->rx_ring);
|
||||
kfree(p->net_vif_list[i]->shadow_ring);
|
||||
kmem_cache_free(net_vif_cache, p->net_vif_list[i]);
|
||||
}
|
||||
|
||||
@@ -315,47 +343,56 @@ int net_find_rule(u8 nproto, u8 tproto, u32 src_addr, u32 dst_addr, u16 src_port
|
||||
* list.
|
||||
*/
|
||||
|
||||
int net_get_target_vif(struct sk_buff *skb)
|
||||
#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
|
||||
|
||||
int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
|
||||
{
|
||||
int target = VIF_DROP;
|
||||
skb->h.raw = skb->nh.raw = skb->data;
|
||||
if ( skb->len < 2 ) goto drop;
|
||||
switch ( ntohs(skb->mac.ethernet->h_proto) )
|
||||
u8 *h_raw, *nh_raw;
|
||||
|
||||
if ( len < 2 ) goto drop;
|
||||
|
||||
nh_raw = data + ETH_HLEN;
|
||||
switch ( ntohs(*(unsigned short *)(data + 12)) )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
if ( skb->len < 28 ) goto drop;
|
||||
target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(skb->nh.raw + 14)),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 24)), 0, 0,
|
||||
skb->src_vif);
|
||||
//printk("ARP!\n");
|
||||
if ( len < 28 ) goto drop;
|
||||
target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)),
|
||||
ntohl(*(u32 *)(nh_raw + 24)), 0, 0,
|
||||
src_vif);
|
||||
break;
|
||||
case ETH_P_IP:
|
||||
if ( skb->len < 20 ) goto drop;
|
||||
skb->h.raw += ((*(unsigned char *)(skb->nh.raw)) & 0x0f) * 4;
|
||||
switch ( *(unsigned char *)(skb->nh.raw + 9) )
|
||||
//printk("IP\n");
|
||||
if ( len < 20 ) goto drop;
|
||||
h_raw = data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4;
|
||||
switch ( *(unsigned char *)(nh_raw + 9) )
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(skb->nh.raw + 9),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 12)),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 16)),
|
||||
ntohs(*(u16 *)(skb->h.raw)),
|
||||
ntohs(*(u16 *)(skb->h.raw + 2)),
|
||||
skb->src_vif);
|
||||
//printk("UDP!\n");
|
||||
case IPPROTO_TCP:
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(nh_raw + 9),
|
||||
ntohl(*(u32 *)(nh_raw + 12)),
|
||||
ntohl(*(u32 *)(nh_raw + 16)),
|
||||
ntohs(*(u16 *)(h_raw)),
|
||||
ntohs(*(u16 *)(h_raw + 2)),
|
||||
src_vif);
|
||||
break;
|
||||
default: // ip-based protocol where we don't have ports.
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(skb->nh.raw + 9),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 12)),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 16)),
|
||||
//printk("Other IP!\n");
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(data + 9),
|
||||
ntohl(*(u32 *)(nh_raw + 12)),
|
||||
ntohl(*(u32 *)(nh_raw + 16)),
|
||||
0,
|
||||
0,
|
||||
skb->src_vif);
|
||||
src_vif);
|
||||
}
|
||||
break;
|
||||
}
|
||||
skb->dst_vif=target;
|
||||
return target;
|
||||
|
||||
drop:
|
||||
//printk("Drop case!\n");
|
||||
return VIF_DROP;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -188,13 +188,15 @@
|
||||
/* "Knobs" that adjust features and parameters. */
|
||||
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
|
||||
Setting to > 1512 effectively disables this feature. */
|
||||
#ifndef __arm__
|
||||
/*#ifndef __arm__
|
||||
static const int rx_copybreak = 200;
|
||||
#else
|
||||
#else*/
|
||||
/* ARM systems perform better by disregarding the bus-master
|
||||
transfer capability of these cards. -- rmk */
|
||||
static const int rx_copybreak = 1513;
|
||||
#endif
|
||||
/*static const int rx_copybreak = 1513;
|
||||
#endif*/
|
||||
static const int rx_copybreak = 0; /* Xen doesn't copybreak in drivers. */
|
||||
|
||||
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
|
||||
static const int mtu = 1500;
|
||||
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
|
||||
|
||||
@@ -78,13 +78,17 @@ MODULE_PARM (multicast_filter_limit, "i");
|
||||
MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered multicast addresses");
|
||||
|
||||
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
|
||||
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|
||||
/*#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|
||||
|| defined(__sparc_) || defined(__ia64__) \
|
||||
|| defined(__sh__) || defined(__mips__)
|
||||
static int rx_copybreak = 1518;
|
||||
#else
|
||||
static int rx_copybreak = 100;
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
/* Xen doesn't do rx_copybreak in drivers. */
|
||||
static int rx_copybreak = 0;
|
||||
|
||||
MODULE_PARM (rx_copybreak, "i");
|
||||
MODULE_PARM_DESC (rx_copybreak, "8139cp Breakpoint at which Rx packets are copied");
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -43,12 +43,15 @@ static int rxdmacount /* = 0 */;
|
||||
|
||||
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
|
||||
Lower values use more memory, but are faster. */
|
||||
#if defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
|
||||
/*#if defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
|
||||
defined(__arm__)
|
||||
static int rx_copybreak = 1518;
|
||||
#else
|
||||
static int rx_copybreak = 200;
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
/* Xen doesn't do rx_copybreak in drivers. */
|
||||
static int rx_copybreak = 0;
|
||||
|
||||
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
|
||||
static int max_interrupt_work = 20;
|
||||
|
||||
@@ -66,7 +66,7 @@ static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chi
|
||||
static struct net_device *pcnet32_dev;
|
||||
|
||||
static const int max_interrupt_work = 80;
|
||||
static const int rx_copybreak = 200;
|
||||
static const int rx_copybreak = 0; /* 200; Xen doesn't do in-driver copybreak. */
|
||||
|
||||
#define PORT_AUI 0x00
|
||||
#define PORT_10BT 0x01
|
||||
|
||||
@@ -4114,14 +4114,16 @@ static int tg3_reset_hw(struct tg3 *tp)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
tw32(HOSTCC_RXCOL_TICKS, 0);
|
||||
tw32(HOSTCC_RXMAX_FRAMES, 1);
|
||||
tw32(HOSTCC_RXCOAL_TICK_INT, 0);
|
||||
tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
|
||||
tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
|
||||
tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
|
||||
tw32(HOSTCC_TXCOAL_TICK_INT, 0);
|
||||
tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
|
||||
// akw: I have set these all back to default coalescing values.
|
||||
|
||||
tw32(HOSTCC_RXCOL_TICKS, DEFAULT_RXCOL_TICKS); //0);
|
||||
tw32(HOSTCC_RXMAX_FRAMES, DEFAULT_RXMAX_FRAMES); //1);
|
||||
tw32(HOSTCC_RXCOAL_TICK_INT, DEFAULT_RXCOAL_TICK_INT); //, 0);
|
||||
tw32(HOSTCC_RXCOAL_MAXF_INT, DEFAULT_RXCOAL_MAXF_INT); //, 1);
|
||||
tw32(HOSTCC_TXCOL_TICKS, DEFAULT_TXCOL_TICKS); //, LOW_TXCOL_TICKS);
|
||||
tw32(HOSTCC_TXMAX_FRAMES, DEFAULT_TXMAX_FRAMES); //, LOW_RXMAX_FRAMES);
|
||||
tw32(HOSTCC_TXCOAL_TICK_INT, DEFAULT_TXCOAL_TICK_INT); //, 0);
|
||||
tw32(HOSTCC_TXCOAL_MAXF_INT, DEFAULT_TXCOAL_MAXF_INT); //, 0);
|
||||
tw32(HOSTCC_STAT_COAL_TICKS,
|
||||
DEFAULT_STAT_COAL_TICKS);
|
||||
|
||||
@@ -6185,9 +6187,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
}
|
||||
|
||||
tp->rx_offset = 2;
|
||||
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
|
||||
(tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
|
||||
tp->rx_offset = 0;
|
||||
printk("WARNING: This card may not support unaligned receive pointers.\n");
|
||||
//tp->rx_offset = 0;
|
||||
|
||||
/* By default, disable wake-on-lan. User can change this
|
||||
* using ETHTOOL_SWOL.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */
|
||||
#define TG3_BDINFO_SIZE 0x10UL
|
||||
|
||||
#define RX_COPY_THRESHOLD 256
|
||||
#define RX_COPY_THRESHOLD 0 //256
|
||||
|
||||
#define RX_STD_MAX_SIZE 1536
|
||||
#define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */
|
||||
|
||||
@@ -172,6 +172,7 @@ static int tulip_rx(struct net_device *dev)
|
||||
to a minimally-sized skbuff. */
|
||||
if (pkt_len < tulip_rx_copybreak
|
||||
&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
|
||||
//if (0) {
|
||||
skb->dev = dev;
|
||||
skb_reserve(skb, 2); /* 16 byte align the IP header */
|
||||
pci_dma_sync_single(tp->pdev,
|
||||
|
||||
@@ -60,13 +60,16 @@ const char * const medianame[32] = {
|
||||
};
|
||||
|
||||
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
|
||||
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|
||||
/*#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|
||||
|| defined(__sparc_) || defined(__ia64__) \
|
||||
|| defined(__sh__) || defined(__mips__)
|
||||
static int rx_copybreak = 1518;
|
||||
#else
|
||||
static int rx_copybreak = 100;
|
||||
#endif
|
||||
*/
|
||||
/* Xen doesn't do rx_copybreak in drivers. */
|
||||
static int rx_copybreak = 0;
|
||||
|
||||
/*
|
||||
Set the bus performance register.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/******************************************************************************
|
||||
* flushtlb.h
|
||||
*
|
||||
* TLB flush macros that count flushes. Counting is used to enforce
|
||||
* zero-copy safety, particularily for the network code.
|
||||
*
|
||||
* akw - Jan 21, 2003
|
||||
*/
|
||||
|
||||
#ifndef __FLUSHTLB_H
|
||||
#define __FLUSHTLB_H
|
||||
|
||||
#include <xeno/smp.h>
|
||||
|
||||
unsigned long tlb_flush_count[NR_CPUS];
|
||||
//#if 0
|
||||
#define __read_cr3(__var) \
|
||||
do { \
|
||||
__asm__ __volatile ( \
|
||||
"movl %%cr3, %0;" \
|
||||
: "=r" (__var)); \
|
||||
} while (0)
|
||||
//#endif
|
||||
|
||||
#define __write_cr3_counted(__pa) \
|
||||
do { \
|
||||
__asm__ __volatile__ ( \
|
||||
"movl %0, %%cr3;" \
|
||||
:: "r" (__pa) \
|
||||
: "memory"); \
|
||||
tlb_flush_count[smp_processor_id()]++; \
|
||||
} while (0)
|
||||
|
||||
//#endif
|
||||
#define __flush_tlb_counted() \
|
||||
do { \
|
||||
unsigned int tmpreg; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"movl %%cr3, %0; # flush TLB \n" \
|
||||
"movl %0, %%cr3; " \
|
||||
: "=r" (tmpreg) \
|
||||
:: "memory"); \
|
||||
tlb_flush_count[smp_processor_id()]++; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -91,36 +91,36 @@ typedef struct { unsigned long pt_lo; } pagetable_t;
|
||||
#include <asm/processor.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/flushtlb.h>
|
||||
|
||||
extern l2_pgentry_t idle0_pg_table[ENTRIES_PER_L2_PAGETABLE];
|
||||
extern l2_pgentry_t *idle_pg_table[NR_CPUS];
|
||||
extern void paging_init(void);
|
||||
|
||||
#define __flush_tlb() \
|
||||
do { \
|
||||
unsigned int tmpreg; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"movl %%cr3, %0; # flush TLB \n" \
|
||||
"movl %0, %%cr3; \n" \
|
||||
: "=r" (tmpreg) \
|
||||
:: "memory"); \
|
||||
} while (0)
|
||||
#define __flush_tlb() __flush_tlb_counted()
|
||||
|
||||
/* Flush global pages as well. */
|
||||
|
||||
#define __pge_off() \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
"movl %0, %%cr4; # turn off PGE " \
|
||||
:: "r" (mmu_cr4_features & ~X86_CR4_PGE)); \
|
||||
} while (0)
|
||||
|
||||
#define __pge_on() \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
"movl %0, %%cr4; # turn off PGE " \
|
||||
:: "r" (mmu_cr4_features)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define __flush_tlb_all() \
|
||||
do { \
|
||||
unsigned int tmpreg; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"movl %1, %%cr4; # turn off PGE \n" \
|
||||
"movl %%cr3, %0; # flush TLB \n" \
|
||||
"movl %0, %%cr3; \n" \
|
||||
"movl %2, %%cr4; # turn PGE back on \n" \
|
||||
: "=&r" (tmpreg) \
|
||||
: "r" (mmu_cr4_features & ~X86_CR4_PGE), \
|
||||
"r" (mmu_cr4_features) \
|
||||
: "memory"); \
|
||||
__pge_off(); \
|
||||
__flush_tlb_counted(); \
|
||||
__pge_on(); \
|
||||
} while (0)
|
||||
|
||||
#define __flush_tlb_one(__addr) \
|
||||
|
||||
@@ -75,6 +75,7 @@ static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
flush_write_buffers();
|
||||
|
||||
return virt_to_bus(ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,11 +111,6 @@ typedef struct
|
||||
#define EVENT_NET_TX 0x20 /* packets for transmission. */
|
||||
#define EVENT_NET_RX 0x40 /* empty buffers for receive. */
|
||||
|
||||
/* should these macros and the ones below test for range violation? */
|
||||
#define EVENT_NET_TX_FOR_VIF(x) (EVENT_NET_TX << (2 * x))
|
||||
#define EVENT_NET_RX_FOR_VIF(x) (EVENT_NET_RX << (2 * x))
|
||||
|
||||
|
||||
/* Bit offsets, as opposed to the above masks. */
|
||||
#define _EVENT_BLK_TX 0
|
||||
#define _EVENT_BLK_RX 1
|
||||
@@ -125,9 +120,6 @@ typedef struct
|
||||
#define _EVENT_NET_RX 5
|
||||
#define _EVENT_DEBUG 6
|
||||
|
||||
#define _EVENT_NET_TX_FOR_VIF(x) (_EVENT_NET_TX + (2 * x))
|
||||
#define _EVENT_NET_RX_FOR_VIF(x) (_EVENT_NET_RX + (2 * x))
|
||||
|
||||
|
||||
/*
|
||||
* NB. We expect that this struct is smaller than a page.
|
||||
|
||||
@@ -15,17 +15,19 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
typedef struct tx_entry_st {
|
||||
unsigned long addr; /* virtual address */
|
||||
unsigned long size; /* in bytes */
|
||||
unsigned long addr; /* virtual address */
|
||||
unsigned long size; /* in bytes */
|
||||
int status; /* per descriptor status. */
|
||||
} tx_entry_t;
|
||||
|
||||
typedef struct rx_entry_st {
|
||||
unsigned long addr; /* virtual address */
|
||||
unsigned long size; /* in bytes */
|
||||
unsigned long addr; /* virtual address */
|
||||
unsigned long size; /* in bytes */
|
||||
int status; /* per descriptor status. */
|
||||
} rx_entry_t;
|
||||
|
||||
#define TX_RING_SIZE 1024
|
||||
#define RX_RING_SIZE 1024
|
||||
#define TX_RING_SIZE 256
|
||||
#define RX_RING_SIZE 256
|
||||
typedef struct net_ring_st {
|
||||
/*
|
||||
* Guest OS places packets into ring at tx_prod.
|
||||
@@ -111,4 +113,12 @@ typedef struct net_rule_ent_st
|
||||
/* Drop a new rule down to the network tables. */
|
||||
int add_net_rule(net_rule_t *rule);
|
||||
|
||||
|
||||
/* Descriptor status values:
|
||||
*/
|
||||
|
||||
#define RING_STATUS_OK 0 // Everything is gravy.
|
||||
#define RING_STATUS_ERR_CFU -1 // Copy from user problems.
|
||||
#define RING_STATUS_BAD_PAGE -2 // What they gave us was pure evil.
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <asm/desc.h>
|
||||
#include <xeno/list.h>
|
||||
#include <hypervisor-ifs/hypervisor-if.h>
|
||||
#include <xeno/spinlock.h>
|
||||
|
||||
/* XXX KAF: These may die eventually, but so many refs in slab.c :((( */
|
||||
|
||||
@@ -88,7 +89,7 @@ typedef struct pfn_info {
|
||||
* references exist of teh current type. A change in type can only occur
|
||||
* when type_count == 0.
|
||||
*/
|
||||
#define PG_type_mask (7<<24) /* bits 24-26 */
|
||||
#define PG_type_mask (15<<24) /* bits 24-27 */
|
||||
#define PGT_none (0<<24) /* no special uses of this page */
|
||||
#define PGT_l1_page_table (1<<24) /* using this page as an L1 page table? */
|
||||
#define PGT_l2_page_table (2<<24) /* using this page as an L2 page table? */
|
||||
@@ -97,6 +98,7 @@ typedef struct pfn_info {
|
||||
#define PGT_gdt_page (5<<24) /* using this page in a GDT? */
|
||||
#define PGT_ldt_page (6<<24) /* using this page in an LDT? */
|
||||
#define PGT_writeable_page (7<<24) /* has writable mappings of this page? */
|
||||
#define PGT_net_rx_buf (8<<24) /* this page has been pirated by the net code. */
|
||||
|
||||
#define PageSlab(page) test_bit(PG_slab, &(page)->flags)
|
||||
#define PageSetSlab(page) set_bit(PG_slab, &(page)->flags)
|
||||
@@ -108,6 +110,7 @@ typedef struct pfn_info {
|
||||
extern frame_table_t * frame_table;
|
||||
extern unsigned long frame_table_size;
|
||||
extern struct list_head free_list;
|
||||
extern spinlock_t free_list_lock;
|
||||
extern unsigned int free_pfns;
|
||||
extern unsigned long max_page;
|
||||
void init_frametable(unsigned long nr_pages);
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
#define VIF_DROP -3
|
||||
#define VIF_ANY_INTERFACE -4
|
||||
|
||||
//skb_type values:
|
||||
#define SKB_NORMAL 0
|
||||
#define SKB_ZERO_COPY 1
|
||||
|
||||
#define HAVE_ALLOC_SKB /* For the drivers to know */
|
||||
#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
|
||||
#define SLAB_SKB /* Slabified skbuffs */
|
||||
@@ -187,7 +191,7 @@ struct sk_buff {
|
||||
unsigned int data_len;
|
||||
unsigned int csum; /* Checksum */
|
||||
unsigned char __unused, /* Dead field, may be reused */
|
||||
cloned, /* head may be cloned (check refcnt to be sure). */
|
||||
cloned, /* head may be cloned (check refcnt to be sure) */
|
||||
pkt_type, /* Packet class */
|
||||
ip_summed; /* Driver fed us an IP checksum */
|
||||
__u32 priority; /* Packet queueing priority */
|
||||
@@ -203,8 +207,12 @@ struct sk_buff {
|
||||
|
||||
void (*destructor)(struct sk_buff *); /* Destruct function */
|
||||
|
||||
int src_vif; /* vif we came from */
|
||||
int dst_vif; /* vif we are bound for */
|
||||
unsigned int skb_type; /* SKB_NORMAL or SKB_ZERO_COPY */
|
||||
struct pfn_info *pf; /* record of physical pf address for freeing */
|
||||
int src_vif; /* vif we came from */
|
||||
int dst_vif; /* vif we are bound for */
|
||||
struct skb_shared_info shinfo; /* shared info is no longer shared in Xen. */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -244,6 +252,7 @@ struct sk_buff {
|
||||
|
||||
extern void __kfree_skb(struct sk_buff *skb);
|
||||
extern struct sk_buff * alloc_skb(unsigned int size, int priority);
|
||||
extern struct sk_buff * alloc_zc_skb(unsigned int size, int priority);
|
||||
extern void kfree_skbmem(struct sk_buff *skb);
|
||||
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
|
||||
extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority);
|
||||
@@ -259,7 +268,8 @@ extern void skb_over_panic(struct sk_buff *skb, int len, void *here);
|
||||
extern void skb_under_panic(struct sk_buff *skb, int len, void *here);
|
||||
|
||||
/* Internal */
|
||||
#define skb_shinfo(SKB) ((struct skb_shared_info *)((SKB)->end))
|
||||
//#define skb_shinfo(SKB) ((struct skb_shared_info *)((SKB)->end))
|
||||
#define skb_shinfo(SKB) ((struct skb_shared_info *)(&(SKB)->shinfo))
|
||||
|
||||
/**
|
||||
* skb_queue_empty - check if a queue is empty
|
||||
@@ -1045,7 +1055,8 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(length+16, gfp_mask);
|
||||
//skb = alloc_skb(length+16, gfp_mask);
|
||||
skb = alloc_zc_skb(length+16, gfp_mask);
|
||||
if (skb)
|
||||
skb_reserve(skb,16);
|
||||
return skb;
|
||||
|
||||
@@ -18,9 +18,37 @@
|
||||
#include <hypervisor-ifs/network.h>
|
||||
#include <xeno/skbuff.h>
|
||||
|
||||
/*
|
||||
* shadow ring structures are used to protect the descriptors from
|
||||
* tampering after they have been passed to the hypervisor.
|
||||
*
|
||||
* TX_RING_SIZE and RX_RING_SIZE are defined in the shared network.h.
|
||||
*/
|
||||
|
||||
typedef struct tx_shadow_entry_st {
|
||||
unsigned long addr;
|
||||
unsigned long size;
|
||||
int status;
|
||||
unsigned long flush_count;
|
||||
} tx_shadow_entry_t;
|
||||
|
||||
typedef struct rx_shadow_entry_st {
|
||||
unsigned long addr;
|
||||
unsigned long size;
|
||||
int status;
|
||||
unsigned long flush_count;
|
||||
} rx_shadow_entry_t;
|
||||
|
||||
typedef struct net_shadow_ring_st {
|
||||
tx_shadow_entry_t *tx_ring;
|
||||
rx_shadow_entry_t *rx_ring;
|
||||
unsigned int rx_prod, rx_cons, rx_idx;
|
||||
} net_shadow_ring_t;
|
||||
|
||||
typedef struct net_vif_st {
|
||||
net_ring_t *net_ring;
|
||||
int id;
|
||||
net_ring_t *net_ring;
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
int id;
|
||||
struct sk_buff_head skb_list;
|
||||
unsigned int domain;
|
||||
// rules table goes here in next revision.
|
||||
@@ -38,5 +66,11 @@ extern net_vif_t *sys_vif_list[];
|
||||
net_vif_t *create_net_vif(int domain);
|
||||
void destroy_net_vif(struct task_struct *p);
|
||||
void add_default_net_rule(int vif_id, u32 ipaddr);
|
||||
int net_get_target_vif(struct sk_buff *skb);
|
||||
int __net_get_target_vif(u8 *data, unsigned int len, int src_vif);
|
||||
void add_default_net_rule(int vif_id, u32 ipaddr);
|
||||
|
||||
#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
|
||||
/* status fields per-descriptor:
|
||||
*/
|
||||
|
||||
|
||||
+477
-72
@@ -30,6 +30,8 @@
|
||||
#include <linux/pkt_sched.h>
|
||||
|
||||
#include <linux/event.h>
|
||||
#include <asm/domain_page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
#define BUG_TRAP ASSERT
|
||||
#define notifier_call_chain(_a,_b,_c) ((void)0)
|
||||
@@ -38,6 +40,18 @@
|
||||
#define rtnl_unlock() ((void)0)
|
||||
#define dst_init() ((void)0)
|
||||
|
||||
#if 1
|
||||
#define DPRINTK(_f, _a...) printk(_f , ## _a)
|
||||
#else
|
||||
#define DPRINTK(_f, _a...) ((void)0)
|
||||
#endif
|
||||
|
||||
// Ring defines:
|
||||
#define TX_RING_INC(_i) (((_i)+1) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_INC(_i) (((_i)+1) & (RX_RING_SIZE-1))
|
||||
#define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_ADD(_i,_j) (((_i)+(_j)) & (RX_RING_SIZE-1))
|
||||
|
||||
struct net_device *the_dev = NULL;
|
||||
|
||||
/*
|
||||
@@ -47,11 +61,11 @@ struct net_device *the_dev = NULL;
|
||||
struct softnet_data softnet_data[NR_CPUS] __cacheline_aligned;
|
||||
|
||||
|
||||
/*****************************************************************************************
|
||||
/*********************************************************************************
|
||||
|
||||
Device Interface Subroutines
|
||||
|
||||
******************************************************************************************/
|
||||
**********************************************************************************/
|
||||
|
||||
/**
|
||||
* __dev_get_by_name - find a device by its name
|
||||
@@ -493,7 +507,7 @@ int dev_queue_xmit(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct Qdisc *q;
|
||||
|
||||
if (!(dev->features&NETIF_F_SG)) printk("NIC doesn't do SG!!!\n");
|
||||
if (skb_shinfo(skb)->frag_list &&
|
||||
!(dev->features&NETIF_F_FRAGLIST) &&
|
||||
skb_linearize(skb, GFP_ATOMIC) != 0) {
|
||||
@@ -661,7 +675,80 @@ static void get_sample_stats(int cpu)
|
||||
softnet_data[cpu].avg_blog = avg_blog;
|
||||
}
|
||||
|
||||
void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
|
||||
{
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
rx_shadow_entry_t *rx;
|
||||
unsigned long *g_pte; //tmp
|
||||
struct pfn_info *g_pfn, *h_pfn;
|
||||
unsigned int i; //, nvif;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Write the virtual MAC address into the destination field
|
||||
* of the ethernet packet. Furthermore, do the same for ARP
|
||||
* reply packets. This is easy because the virtual MAC address
|
||||
* is always 00-[nn]-00-00-00-00, where the second sixteen bits
|
||||
* of the MAC are the vif's id. This is to differentiate between
|
||||
* vifs on guests that have more than one.
|
||||
*
|
||||
* In zero copy, the data pointers for the packet have to have been
|
||||
* mapped in by the caller.
|
||||
*/
|
||||
|
||||
memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
|
||||
// *(unsigned int *)(skb->mac.ethernet->h_dest + 1) = nvif;
|
||||
if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
|
||||
{
|
||||
memset(skb->nh.raw + 18, 0, ETH_ALEN);
|
||||
// *(unsigned int *)(skb->nh.raw + 18 + 1) = nvif;
|
||||
}
|
||||
shadow_ring = vif->shadow_ring;
|
||||
|
||||
//Advance to next good buffer.
|
||||
for (i = shadow_ring->rx_cons;
|
||||
(i != shadow_ring->rx_prod)
|
||||
&& ( shadow_ring->rx_ring[i].status != RING_STATUS_OK );
|
||||
i = RX_RING_INC(i));
|
||||
|
||||
if (( i != shadow_ring->rx_prod ) &&
|
||||
( shadow_ring->rx_ring[i].status == RING_STATUS_OK ))
|
||||
{
|
||||
rx = shadow_ring->rx_ring+i;
|
||||
if ( (skb->len + ETH_HLEN) < rx->size )
|
||||
rx->size = skb->len + ETH_HLEN;
|
||||
|
||||
g_pte = map_domain_mem(rx->addr);
|
||||
|
||||
g_pfn = frame_table + (*g_pte >> PAGE_SHIFT);
|
||||
h_pfn = skb->pf;
|
||||
|
||||
h_pfn->tot_count = h_pfn->type_count = 1;
|
||||
g_pfn->tot_count = g_pfn->type_count = 0;
|
||||
h_pfn->flags = g_pfn->flags & (~PG_type_mask);
|
||||
|
||||
if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
|
||||
g_pfn->flags = 0;
|
||||
|
||||
//point guest pte at the new page:
|
||||
machine_to_phys_mapping[h_pfn - frame_table]
|
||||
= machine_to_phys_mapping[g_pfn - frame_table];
|
||||
|
||||
*g_pte = (*g_pte & ~PAGE_MASK)
|
||||
| (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
|
||||
*g_pte |= _PAGE_PRESENT;
|
||||
|
||||
unmap_domain_mem(g_pte);
|
||||
skb->pf = g_pfn; // return the guest pfn to be put on the free list
|
||||
|
||||
shadow_ring->rx_cons = RX_RING_INC(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deliver skb to an old protocol, which is not threaded well
|
||||
or which do not understand shared skbs.
|
||||
*/
|
||||
/**
|
||||
* netif_rx - post buffer to the network code
|
||||
* @skb: buffer to post
|
||||
@@ -686,32 +773,56 @@ int netif_rx(struct sk_buff *skb)
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned long cpu_mask;
|
||||
#endif
|
||||
|
||||
struct task_struct *p;
|
||||
int this_cpu = smp_processor_id();
|
||||
struct softnet_data *queue;
|
||||
unsigned long flags;
|
||||
net_vif_t *vif;
|
||||
|
||||
if (skb->stamp.tv_sec == 0)
|
||||
get_fast_time(&skb->stamp);
|
||||
local_irq_save(flags);
|
||||
|
||||
if (skb->skb_type != SKB_ZERO_COPY)
|
||||
BUG();
|
||||
|
||||
if (skb->stamp.tv_sec == 0)
|
||||
get_fast_time(&skb->stamp);
|
||||
|
||||
if ( (skb->data - skb->head) != (18 + ETH_HLEN) )
|
||||
printk("headroom was %lu!\n", (unsigned long)skb->data - (unsigned long)skb->head);
|
||||
// BUG();
|
||||
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
|
||||
|
||||
/* remapping this address really screws up all the skb pointers. We need
|
||||
* to map them all here sufficiently to get the packet demultiplexed.
|
||||
*/
|
||||
|
||||
skb->data = skb->head;
|
||||
skb_reserve(skb,18); // 18 is the 16 from dev_alloc_skb plus 2 for #
|
||||
// IP header alignment.
|
||||
skb->mac.raw = skb->data;
|
||||
skb->data += ETH_HLEN;
|
||||
skb->nh.raw = skb->data;
|
||||
|
||||
/* The code is rearranged so that the path is the most
|
||||
short when CPU is congested, but is still operating.
|
||||
*/
|
||||
queue = &softnet_data[this_cpu];
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
netdev_rx_stat[this_cpu].total++;
|
||||
|
||||
if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
|
||||
skb->src_vif = VIF_PHYSICAL_INTERFACE;
|
||||
|
||||
|
||||
if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
|
||||
net_get_target_vif(skb);
|
||||
skb->dst_vif = __net_get_target_vif(skb->mac.raw, skb->len, skb->src_vif);
|
||||
//if (skb->dst_vif == VIF_DROP)
|
||||
//printk("netif_rx target: %d (sec: %u)\n", skb->dst_vif, skb->security);
|
||||
|
||||
if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
|
||||
{
|
||||
//printk("No such vif! (%d).\n", skb->dst_vif);
|
||||
// the target vif does not exist.
|
||||
goto drop;
|
||||
}
|
||||
@@ -733,7 +844,7 @@ int netif_rx(struct sk_buff *skb)
|
||||
do {
|
||||
if ( p->domain != vif->domain ) continue;
|
||||
if ( vif->skb_list.qlen > 100 ) break;
|
||||
skb_queue_tail(&vif->skb_list, skb);
|
||||
deliver_packet(skb, vif);
|
||||
cpu_mask = mark_hyp_event(p, _HYP_EVENT_NET_RX);
|
||||
read_unlock(&tasklist_lock);
|
||||
goto found;
|
||||
@@ -745,20 +856,21 @@ int netif_rx(struct sk_buff *skb)
|
||||
|
||||
drop:
|
||||
netdev_rx_stat[this_cpu].dropped++;
|
||||
local_irq_restore(flags);
|
||||
|
||||
unmap_domain_mem(skb->head);
|
||||
kfree_skb(skb);
|
||||
local_irq_restore(flags);
|
||||
return NET_RX_DROP;
|
||||
|
||||
found:
|
||||
unmap_domain_mem(skb->head);
|
||||
skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
|
||||
kfree_skb(skb);
|
||||
hyp_event_notify(cpu_mask);
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Deliver skb to an old protocol, which is not threaded well
|
||||
or which do not understand shared skbs.
|
||||
*/
|
||||
|
||||
static int deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int last)
|
||||
{
|
||||
static spinlock_t net_bh_lock = SPIN_LOCK_UNLOCKED;
|
||||
@@ -873,15 +985,49 @@ static inline void handle_diverter(struct sk_buff *skb)
|
||||
}
|
||||
#endif /* CONFIG_NET_DIVERT */
|
||||
|
||||
void update_shared_ring(void)
|
||||
{
|
||||
rx_shadow_entry_t *rx;
|
||||
shared_info_t *s = current->shared_info;
|
||||
net_ring_t *net_ring;
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
unsigned int nvif;
|
||||
|
||||
clear_bit(_HYP_EVENT_NET_RX, ¤t->hyp_events);
|
||||
for (nvif = 0; nvif < current->num_net_vifs; nvif++)
|
||||
{
|
||||
net_ring = current->net_vif_list[nvif]->net_ring;
|
||||
shadow_ring = current->net_vif_list[nvif]->shadow_ring;
|
||||
while ((shadow_ring->rx_idx != shadow_ring->rx_cons)
|
||||
&& (net_ring->rx_cons != net_ring->rx_prod))
|
||||
{
|
||||
rx = shadow_ring->rx_ring+shadow_ring->rx_idx;
|
||||
copy_to_user(net_ring->rx_ring + net_ring->rx_cons, rx, sizeof(rx_entry_t));
|
||||
|
||||
shadow_ring->rx_idx = RX_RING_INC(shadow_ring->rx_idx);
|
||||
net_ring->rx_cons = RX_RING_INC(net_ring->rx_cons);
|
||||
|
||||
if (rx->flush_count == tlb_flush_count[smp_processor_id()])
|
||||
__flush_tlb();
|
||||
|
||||
if ( net_ring->rx_cons == net_ring->rx_event )
|
||||
set_bit(_EVENT_NET_RX, &s->events);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flush_rx_queue(void)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
shared_info_t *s = current->shared_info;
|
||||
net_ring_t *net_ring;
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
unsigned int i, nvif;
|
||||
rx_entry_t rx;
|
||||
|
||||
rx_shadow_entry_t *rx;
|
||||
unsigned long *g_pte, tmp;
|
||||
struct pfn_info *g_pfn, *h_pfn;
|
||||
|
||||
/* I have changed this to batch flush all vifs for a guest
|
||||
* at once, whenever this is called. Since the guest is about to be
|
||||
* scheduled and issued an RX interrupt for one nic, it might as well
|
||||
@@ -893,15 +1039,17 @@ void flush_rx_queue(void)
|
||||
* loop can be replaced with a translation to the specific NET
|
||||
* interrupt to serve. --akw
|
||||
*/
|
||||
|
||||
clear_bit(_HYP_EVENT_NET_RX, ¤t->hyp_events);
|
||||
|
||||
for (nvif = 0; nvif < current->num_net_vifs; nvif++)
|
||||
{
|
||||
net_ring = current->net_vif_list[nvif]->net_ring;
|
||||
shadow_ring = current->net_vif_list[nvif]->shadow_ring;
|
||||
while ( (skb = skb_dequeue(¤t->net_vif_list[nvif]->skb_list))
|
||||
!= NULL )
|
||||
{
|
||||
//temporary hack to stop processing non-zc skbs.
|
||||
if (skb->skb_type == SKB_NORMAL) continue;
|
||||
/*
|
||||
* Write the virtual MAC address into the destination field
|
||||
* of the ethernet packet. Furthermore, do the same for ARP
|
||||
@@ -912,6 +1060,16 @@ void flush_rx_queue(void)
|
||||
* second sixteen bits, which are the per-host vif id.
|
||||
* (so eth0 should be 00-00-..., eth1 is 00-01-...)
|
||||
*/
|
||||
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
|
||||
skb->data = skb->head;
|
||||
skb_reserve(skb,16);
|
||||
skb->mac.raw = skb->data;
|
||||
skb->data += ETH_HLEN;
|
||||
}
|
||||
|
||||
memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
|
||||
*(unsigned int *)(skb->mac.ethernet->h_dest + 1) = nvif;
|
||||
if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
|
||||
@@ -920,19 +1078,88 @@ void flush_rx_queue(void)
|
||||
*(unsigned int *)(skb->nh.raw + 18 + 1) = nvif;
|
||||
}
|
||||
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
unmap_domain_mem(skb->head);
|
||||
}
|
||||
|
||||
i = net_ring->rx_cons;
|
||||
if ( i != net_ring->rx_prod )
|
||||
{
|
||||
if ( !copy_from_user(&rx, net_ring->rx_ring+i, sizeof(rx)) )
|
||||
net_ring->rx_ring[i].status = shadow_ring->rx_ring[i].status;
|
||||
if ( shadow_ring->rx_ring[i].status == RING_STATUS_OK)
|
||||
{
|
||||
if ( (skb->len + ETH_HLEN) < rx.size )
|
||||
rx.size = skb->len + ETH_HLEN;
|
||||
copy_to_user((void *)rx.addr, skb->mac.raw, rx.size);
|
||||
copy_to_user(net_ring->rx_ring+i, &rx, sizeof(rx));
|
||||
rx = shadow_ring->rx_ring+i;
|
||||
if ( (skb->len + ETH_HLEN) < rx->size )
|
||||
rx->size = skb->len + ETH_HLEN;
|
||||
|
||||
/* remap the packet again. This is very temporary and will shortly be
|
||||
* replaced with a page swizzle.
|
||||
*/
|
||||
|
||||
/*if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
|
||||
skb->data = skb->head;
|
||||
skb_reserve(skb,16);
|
||||
skb->mac.raw = skb->data;
|
||||
skb->data += ETH_HLEN;
|
||||
}
|
||||
|
||||
copy_to_user((void *)rx->addr, skb->mac.raw, rx->size);
|
||||
copy_to_user(net_ring->rx_ring+i, rx, sizeof(rx));
|
||||
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
unmap_domain_mem(skb->head);
|
||||
skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
|
||||
}*/
|
||||
|
||||
//presumably I don't need to rewalk the guest page table
|
||||
//here.
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
// g_pfn is the frame FROM the guest being given up
|
||||
// h_pfn is the frame FROM the hypervisor, passing up.
|
||||
|
||||
if (rx->flush_count == tlb_flush_count[smp_processor_id()])
|
||||
{
|
||||
flush_tlb_all();
|
||||
}
|
||||
|
||||
g_pte = map_domain_mem(rx->addr);
|
||||
|
||||
//g_pfn = frame_table + (rx->addr >> PAGE_SHIFT);
|
||||
g_pfn = frame_table + (*g_pte >> PAGE_SHIFT);
|
||||
h_pfn = skb->pf;
|
||||
|
||||
|
||||
//tmp = g_pfn->next; g_pfn->next = h_pfn->next; h_pfn->next = tmp;
|
||||
//tmp = g_pfn->prev; g_pfn->prev = h_pfn->prev; h_pfn->prev = tmp;
|
||||
tmp = g_pfn->flags; g_pfn->flags = h_pfn->flags; h_pfn->flags = tmp;
|
||||
|
||||
h_pfn->tot_count = 1;
|
||||
h_pfn->type_count = g_pfn->type_count;
|
||||
g_pfn->tot_count = g_pfn->type_count = 0;
|
||||
|
||||
h_pfn->flags = current->domain | PGT_l1_page_table;
|
||||
g_pfn->flags = PGT_l1_page_table;
|
||||
|
||||
|
||||
*g_pte = (*g_pte & ~PAGE_MASK) | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
|
||||
|
||||
*g_pte |= _PAGE_PRESENT;
|
||||
unmap_domain_mem(g_pte);
|
||||
|
||||
skb->pf = g_pfn; // return the guest pfn to be put on the free list
|
||||
} else {
|
||||
BUG(); //got a non-zero copy skb. which is not good.
|
||||
}
|
||||
|
||||
}
|
||||
net_ring->rx_cons = (i+1) & (RX_RING_SIZE-1);
|
||||
if ( net_ring->rx_cons == net_ring->rx_event )
|
||||
set_bit(_EVENT_NET_RX_FOR_VIF(nvif), &s->events);
|
||||
set_bit(_EVENT_NET_RX, &s->events);
|
||||
}
|
||||
kfree_skb(skb);
|
||||
}
|
||||
@@ -1909,96 +2136,274 @@ int __init net_dev_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int init_tx_header(u8 *data, unsigned int len, struct net_device *dev)
|
||||
{
|
||||
memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch ( ntohs(*(unsigned short *)(data + 12)) )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
if ( len < 42 ) break;
|
||||
memcpy(data + 22, dev->dev_addr, 6);
|
||||
return ETH_P_ARP;
|
||||
case ETH_P_IP:
|
||||
return ETH_P_IP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tx_skb_release
|
||||
*
|
||||
* skb destructor function that is attached to zero-copy tx skbs before
|
||||
* they are passed to the device driver for transmission. The destructor
|
||||
* is responsible for unlinking the fragment pointer to the skb data that
|
||||
* is in guest memory, and decrementing the tot_count on the packet pages
|
||||
* pfn_info.
|
||||
*/
|
||||
|
||||
void tx_skb_release(struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i= 0; i < skb_shinfo(skb)->nr_frags; i++)
|
||||
skb_shinfo(skb)->frags[i].page->tot_count--;
|
||||
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_net_update:
|
||||
*
|
||||
* Called from guest OS to notify updates to its transmit and/or receive
|
||||
* descriptor rings.
|
||||
*/
|
||||
#define TX_RING_INC(_i) (((_i)+1) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_INC(_i) (((_i)+1) & (RX_RING_SIZE-1))
|
||||
#define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_ADD(_i,_j) (((_i)+(_j)) & (RX_RING_SIZE-1))
|
||||
#define PKT_PROT_LEN (ETH_HLEN + 8)
|
||||
|
||||
void print_range2(u8 *start, unsigned int len)
|
||||
{
|
||||
int i=0;
|
||||
while (i++ < len)
|
||||
{
|
||||
printk("%x:",start[i]);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
long do_net_update(void)
|
||||
{
|
||||
shared_info_t *shared = current->shared_info;
|
||||
net_ring_t *net_ring = current->net_ring_base;
|
||||
net_ring_t *net_ring;
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
net_vif_t *current_vif;
|
||||
unsigned int i, j;
|
||||
struct sk_buff *skb;
|
||||
tx_entry_t tx;
|
||||
|
||||
rx_shadow_entry_t *rx;
|
||||
unsigned long pfn;
|
||||
struct pfn_info *page;
|
||||
unsigned long *g_pte;
|
||||
|
||||
|
||||
for ( j = 0; j < current->num_net_vifs; j++)
|
||||
{
|
||||
current_vif = current->net_vif_list[j];
|
||||
net_ring = current_vif->net_ring;
|
||||
int target;
|
||||
u8 *g_data;
|
||||
unsigned short protocol;
|
||||
|
||||
/* First, we send out pending TX descriptors if they exist on this ring.
|
||||
*/
|
||||
|
||||
for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
|
||||
{
|
||||
if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
|
||||
continue;
|
||||
|
||||
if ( tx.size < PKT_PROT_LEN ) continue; // This should be reasonable.
|
||||
|
||||
// Packets must not cross page boundaries. For now, this is a
|
||||
// kernel panic, later it may become a continue -- silent fail.
|
||||
|
||||
if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE )
|
||||
{
|
||||
DPRINTK("tx.addr: %lx, size: %lu, end: %lu\n", tx.addr, tx.size,
|
||||
(tx.addr &~PAGE_MASK) + tx.size);
|
||||
continue;
|
||||
//BUG();
|
||||
}
|
||||
|
||||
if ( TX_RING_INC(i) == net_ring->tx_event )
|
||||
set_bit(_EVENT_NET_TX_FOR_VIF(j), &shared->events);
|
||||
set_bit(_EVENT_NET_TX, &shared->events);
|
||||
|
||||
skb = alloc_skb(tx.size, GFP_KERNEL);
|
||||
if ( skb == NULL ) continue;
|
||||
skb_put(skb, tx.size);
|
||||
if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
|
||||
{
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
skb->dev = the_dev;
|
||||
/* Map the skb in from the guest, and get it's delivery target.
|
||||
* We need this to know whether the packet is to be sent locally
|
||||
* or remotely.
|
||||
*/
|
||||
|
||||
g_data = map_domain_mem(tx.addr);
|
||||
|
||||
if ( skb->len < 16 )
|
||||
//print_range2(g_data, PKT_PROT_LEN);
|
||||
protocol = __constant_htons(init_tx_header(g_data, tx.size, the_dev));
|
||||
if ( protocol == 0 )
|
||||
{
|
||||
kfree_skb(skb);
|
||||
unmap_domain_mem(g_data);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
|
||||
target = __net_get_target_vif(g_data, tx.size, current_vif->id);
|
||||
//printk("Send to target: %d\n", target);
|
||||
if (target > VIF_PHYSICAL_INTERFACE )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
skb->protocol = __constant_htons(ETH_P_ARP);
|
||||
if ( skb->len < 42 ) break;
|
||||
memcpy(skb->data + 22, skb->dev->dev_addr, 6);
|
||||
break;
|
||||
case ETH_P_IP:
|
||||
skb->protocol = __constant_htons(ETH_P_IP);
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( skb != NULL )
|
||||
{
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
skb->src_vif = current_vif->id;
|
||||
net_get_target_vif(skb);
|
||||
if ( skb->dst_vif > VIF_PHYSICAL_INTERFACE )
|
||||
// Local delivery: Allocate an skb off the domain free list
|
||||
// fil it, and pass it to netif_rx as if it came off the NIC.
|
||||
//printk("LOCAL! (%d) \n", target);
|
||||
skb = dev_alloc_skb(tx.size);
|
||||
if (skb == NULL)
|
||||
{
|
||||
(void)netif_rx(skb);
|
||||
unmap_domain_mem(g_data);
|
||||
continue;
|
||||
}
|
||||
else if ( skb->dst_vif == VIF_PHYSICAL_INTERFACE )
|
||||
|
||||
skb->src_vif = current_vif->id;
|
||||
skb->dst_vif = target;
|
||||
skb->protocol = protocol;
|
||||
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
|
||||
skb->data = skb->head + 16;
|
||||
skb_reserve(skb,2);
|
||||
memcpy(skb->data, g_data, tx.size);
|
||||
skb->len = tx.size;
|
||||
unmap_domain_mem(skb->head);
|
||||
skb->data += ETH_HLEN; // so the assertion in netif_RX doesn't freak out.
|
||||
|
||||
(void)netif_rx(skb);
|
||||
|
||||
unmap_domain_mem(g_data);
|
||||
}
|
||||
else if ( target == VIF_PHYSICAL_INTERFACE )
|
||||
{
|
||||
// External delivery: Allocate a small skb to hold protected header info
|
||||
// and copy the eth header and IP address fields into that.
|
||||
// Set a frag link to the remaining data, and we will scatter-gather
|
||||
// in the device driver to send the two bits later.
|
||||
|
||||
/*unmap_domain_mem(g_data);*/
|
||||
|
||||
skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL); // Eth header + two IP addrs.
|
||||
if (skb == NULL)
|
||||
{
|
||||
skb_push(skb, skb->dev->hard_header_len);
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
else
|
||||
printk("Alloc skb failed!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_put(skb, PKT_PROT_LEN);
|
||||
/*if ( copy_from_user(skb->data, (void *)tx.addr, PKT_PROT_LEN) )
|
||||
{
|
||||
printk("Copy from user failed!\n");
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
memcpy(skb->data, g_data, PKT_PROT_LEN);
|
||||
unmap_domain_mem(g_data);
|
||||
//print_range2(g_data, PKT_PROT_LEN);
|
||||
skb->dev = the_dev;
|
||||
skb->src_vif = current_vif->id;
|
||||
skb->dst_vif = target;
|
||||
skb->protocol = protocol; // These next two lines abbreviate the call
|
||||
// to eth_type_trans as we already have our
|
||||
// protocol.
|
||||
//skb_pull(skb, skb->dev->hard_header_len);
|
||||
skb->mac.raw=skb->data;
|
||||
|
||||
// set tot_count++ in the guest data pfn.
|
||||
page = (tx.addr >> PAGE_SHIFT) + frame_table;
|
||||
page->tot_count++;
|
||||
|
||||
// place the remainder of the packet (which is in guest memory) into an
|
||||
// skb frag.
|
||||
skb_shinfo(skb)->frags[0].page = page;
|
||||
skb_shinfo(skb)->frags[0].size = tx.size - PKT_PROT_LEN;
|
||||
skb_shinfo(skb)->frags[0].page_offset
|
||||
= (tx.addr & ~PAGE_MASK) + PKT_PROT_LEN;
|
||||
skb_shinfo(skb)->nr_frags = 1;
|
||||
skb->data_len = tx.size - skb->len;
|
||||
skb->len = tx.size;
|
||||
|
||||
// assign a destructor to the skb that will unlink and dec the tot_count
|
||||
skb->destructor = &tx_skb_release;
|
||||
//skb_push(skb, skb->dev->hard_header_len);
|
||||
//printk("calling dev_queue_xmit!\n");
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
else
|
||||
{
|
||||
unmap_domain_mem(g_data);
|
||||
}
|
||||
}
|
||||
net_ring->tx_cons = i;
|
||||
}
|
||||
|
||||
/* Next, pull any new RX descriptors across to the shadow ring.
|
||||
*/
|
||||
|
||||
shadow_ring = current_vif->shadow_ring;
|
||||
|
||||
for (i = shadow_ring->rx_prod; i != net_ring->rx_prod; i = RX_RING_INC(i))
|
||||
{
|
||||
/* This copy assumes that rx_shadow_entry_t is an extension of
|
||||
* rx_net_entry_t extra fields must be tacked on to the end.
|
||||
*/
|
||||
if ( copy_from_user( shadow_ring->rx_ring+i, net_ring->rx_ring+i,
|
||||
sizeof (rx_entry_t) ) )
|
||||
{
|
||||
shadow_ring->rx_ring[i].status = RING_STATUS_ERR_CFU;
|
||||
continue;
|
||||
} else {
|
||||
|
||||
rx = shadow_ring->rx_ring + i;
|
||||
pfn = rx->addr >> PAGE_SHIFT;
|
||||
page = frame_table + pfn;
|
||||
|
||||
shadow_ring->rx_ring[i].status = RING_STATUS_BAD_PAGE;
|
||||
|
||||
if ( page->flags != (PGT_l1_page_table | current->domain) )
|
||||
{
|
||||
BUG();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
g_pte = map_domain_mem(rx->addr);
|
||||
|
||||
if (!(*g_pte & _PAGE_PRESENT))
|
||||
{
|
||||
BUG();
|
||||
unmap_domain_mem(g_pte);
|
||||
continue;
|
||||
}
|
||||
|
||||
page = (*g_pte >> PAGE_SHIFT) + frame_table;
|
||||
|
||||
if (page->tot_count != 1)
|
||||
{
|
||||
printk("!\n");
|
||||
unmap_domain_mem(g_pte);
|
||||
continue;
|
||||
}
|
||||
|
||||
// The pte they passed was good, so we take it away from them.
|
||||
shadow_ring->rx_ring[i].status = RING_STATUS_OK;
|
||||
*g_pte &= ~_PAGE_PRESENT;
|
||||
page->flags = (page->flags & ~PG_type_mask) | PGT_net_rx_buf;
|
||||
rx->flush_count = tlb_flush_count[smp_processor_id()];
|
||||
|
||||
unmap_domain_mem(g_pte);
|
||||
}
|
||||
}
|
||||
shadow_ring->rx_prod = net_ring->rx_prod;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+40
-30
@@ -161,52 +161,62 @@ unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||
struct ethhdr *eth;
|
||||
unsigned char *rawp;
|
||||
|
||||
skb->mac.raw=skb->data;
|
||||
skb_pull(skb,dev->hard_header_len);
|
||||
eth= skb->mac.ethernet;
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
skb_pull(skb,dev->hard_header_len);
|
||||
skb->mac.raw= (void *)0xdeadbeef;
|
||||
return htons(ETH_P_802_2);
|
||||
|
||||
} else { // SKB_NORMAL
|
||||
|
||||
skb->mac.raw=skb->data;
|
||||
skb_pull(skb,dev->hard_header_len);
|
||||
eth= skb->mac.ethernet;
|
||||
|
||||
if(*eth->h_dest&1)
|
||||
{
|
||||
if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
|
||||
if(*eth->h_dest&1)
|
||||
{
|
||||
if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
|
||||
skb->pkt_type=PACKET_BROADCAST;
|
||||
else
|
||||
skb->pkt_type=PACKET_MULTICAST;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This ALLMULTI check should be redundant by 1.4
|
||||
* so don't forget to remove it.
|
||||
*
|
||||
* Seems, you forgot to remove it. All silly devices
|
||||
* seems to set IFF_PROMISC.
|
||||
*/
|
||||
/*
|
||||
* This ALLMULTI check should be redundant by 1.4
|
||||
* so don't forget to remove it.
|
||||
*
|
||||
* Seems, you forgot to remove it. All silly devices
|
||||
* seems to set IFF_PROMISC.
|
||||
*/
|
||||
|
||||
else if(1 /*dev->flags&IFF_PROMISC*/)
|
||||
{
|
||||
else if(1 /*dev->flags&IFF_PROMISC*/)
|
||||
{
|
||||
if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
|
||||
skb->pkt_type=PACKET_OTHERHOST;
|
||||
}
|
||||
}
|
||||
|
||||
if (ntohs(eth->h_proto) >= 1536)
|
||||
if (ntohs(eth->h_proto) >= 1536)
|
||||
return eth->h_proto;
|
||||
|
||||
rawp = skb->data;
|
||||
rawp = skb->data;
|
||||
|
||||
/*
|
||||
* This is a magic hack to spot IPX packets. Older Novell breaks
|
||||
* the protocol design and runs IPX over 802.3 without an 802.2 LLC
|
||||
* layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
|
||||
* won't work for fault tolerant netware but does for the rest.
|
||||
*/
|
||||
if (*(unsigned short *)rawp == 0xFFFF)
|
||||
/*
|
||||
* This is a magic hack to spot IPX packets. Older Novell breaks
|
||||
* the protocol design and runs IPX over 802.3 without an 802.2 LLC
|
||||
* layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
|
||||
* won't work for fault tolerant netware but does for the rest.
|
||||
*/
|
||||
if (*(unsigned short *)rawp == 0xFFFF)
|
||||
return htons(ETH_P_802_3);
|
||||
|
||||
/*
|
||||
* Real 802.2 LLC
|
||||
*/
|
||||
return htons(ETH_P_802_2);
|
||||
/*
|
||||
* Real 802.2 LLC
|
||||
*/
|
||||
return htons(ETH_P_802_2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
|
||||
{
|
||||
struct ethhdr *eth = skb->mac.ethernet;
|
||||
|
||||
+118
-1
@@ -63,6 +63,7 @@
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define BUG_TRAP ASSERT
|
||||
|
||||
@@ -149,6 +150,114 @@ static __inline__ void skb_head_to_pool(struct sk_buff *skb)
|
||||
kmem_cache_free(skbuff_head_cache, skb);
|
||||
}
|
||||
|
||||
//static unsigned long skbpagesout=0, skbpagesin=0;
|
||||
|
||||
static inline u8 *alloc_skb_data_page(struct sk_buff *skb)
|
||||
{
|
||||
struct list_head *list_ptr;
|
||||
struct pfn_info *pf;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&free_list_lock, flags);
|
||||
|
||||
if (!free_pfns) return NULL;
|
||||
|
||||
list_ptr = free_list.next;
|
||||
pf = list_entry(list_ptr, struct pfn_info, list);
|
||||
pf->flags = 0; // owned by dom0
|
||||
list_del(&pf->list);
|
||||
//pf->next = pf->prev = (pf - frame_table);
|
||||
free_pfns--;
|
||||
|
||||
spin_unlock_irqrestore(&free_list_lock, flags);
|
||||
|
||||
skb->pf = pf;
|
||||
//if (skbpagesout++ % 100 == 0) printk("XEN-: skb allocs: %lu\n", skbpagesout);
|
||||
return (u8 *)((pf - frame_table) << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static inline void dealloc_skb_data_page(struct sk_buff *skb)
|
||||
{
|
||||
struct pfn_info *pf;
|
||||
unsigned long flags;
|
||||
|
||||
pf = skb->pf;
|
||||
|
||||
spin_lock_irqsave(&free_list_lock, flags);
|
||||
|
||||
list_add(&pf->list, &free_list);
|
||||
free_pfns++;
|
||||
|
||||
spin_unlock_irqrestore(&free_list_lock, flags);
|
||||
|
||||
//if (skbpagesin++ % 100 == 0) printk("XEN-: skb allocs: %lu\n", skbpagesin);
|
||||
}
|
||||
|
||||
struct sk_buff *alloc_zc_skb(unsigned int size,int gfp_mask)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u8 *data;
|
||||
|
||||
if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
|
||||
static int count = 0;
|
||||
if (++count < 5) {
|
||||
printk(KERN_ERR "alloc_skb called nonatomically "
|
||||
"from interrupt %p\n", NET_CALLER(size));
|
||||
BUG();
|
||||
}
|
||||
gfp_mask &= ~__GFP_WAIT;
|
||||
}
|
||||
|
||||
/* Get the HEAD */
|
||||
skb = skb_head_from_pool();
|
||||
if (skb == NULL) {
|
||||
skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask & ~__GFP_DMA);
|
||||
if (skb == NULL)
|
||||
goto nohead;
|
||||
}
|
||||
|
||||
/* Get the DATA. Size must match skb_add_mtu(). */
|
||||
size = SKB_DATA_ALIGN(size);
|
||||
data = alloc_skb_data_page(skb);
|
||||
|
||||
if (data == NULL)
|
||||
goto nodata;
|
||||
|
||||
// This is so that pci_map_single does the right thing in the driver.
|
||||
// If you want to ever use this pointer otherwise, you need to regenerate it
|
||||
// based on skb->pf.
|
||||
data = phys_to_virt((unsigned long)data);
|
||||
|
||||
/* XXX: does not include slab overhead */
|
||||
skb->truesize = size + sizeof(struct sk_buff);
|
||||
|
||||
/* Load the data pointers. */
|
||||
skb->head = data;
|
||||
skb->data = data;
|
||||
skb->tail = data;
|
||||
skb->end = data + size;
|
||||
|
||||
/* Set up other state */
|
||||
skb->len = 0;
|
||||
skb->cloned = 0;
|
||||
skb->data_len = 0;
|
||||
skb->src_vif = VIF_UNKNOWN_INTERFACE;
|
||||
skb->dst_vif = VIF_UNKNOWN_INTERFACE;
|
||||
skb->skb_type = SKB_ZERO_COPY;
|
||||
|
||||
atomic_set(&skb->users, 1);
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
return skb;
|
||||
|
||||
nodata:
|
||||
skb_head_to_pool(skb);
|
||||
nohead:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new skbuff. We do this ourselves so we can fill in a few
|
||||
* 'private' fields and also do memory statistics to find all the
|
||||
@@ -213,6 +322,7 @@ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
|
||||
skb->data_len = 0;
|
||||
skb->src_vif = VIF_UNKNOWN_INTERFACE;
|
||||
skb->dst_vif = VIF_UNKNOWN_INTERFACE;
|
||||
skb->skb_type = SKB_NORMAL;
|
||||
|
||||
atomic_set(&skb->users, 1);
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
@@ -284,6 +394,7 @@ static void skb_clone_fraglist(struct sk_buff *skb)
|
||||
|
||||
static void skb_release_data(struct sk_buff *skb)
|
||||
{
|
||||
|
||||
if (!skb->cloned ||
|
||||
atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) {
|
||||
if (skb_shinfo(skb)->nr_frags) {
|
||||
@@ -295,7 +406,12 @@ static void skb_release_data(struct sk_buff *skb)
|
||||
if (skb_shinfo(skb)->frag_list)
|
||||
skb_drop_fraglist(skb);
|
||||
|
||||
kfree(skb->head);
|
||||
if (skb->skb_type == SKB_NORMAL) {
|
||||
kfree(skb->head);
|
||||
} else if (skb->skb_type == SKB_ZERO_COPY) { dealloc_skb_data_page(skb);
|
||||
} else {
|
||||
BUG(); //skb_release_data called with unknown skb type!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,6 +449,7 @@ void __kfree_skb(struct sk_buff *skb)
|
||||
}
|
||||
skb->destructor(skb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETFILTER
|
||||
nf_conntrack_put(skb->nfct);
|
||||
#endif
|
||||
|
||||
@@ -21,14 +21,12 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#define NET_TX_IRQ _EVENT_NET_TX
|
||||
#define NET_RX_IRQ _EVENT_NET_RX
|
||||
|
||||
#define NET_TX_IRQ_FOR_VIF(x) _EVENT_NET_TX_FOR_VIF(x)
|
||||
#define NET_RX_IRQ_FOR_VIF(x) _EVENT_NET_RX_FOR_VIF(x)
|
||||
|
||||
#define TX_MAX_ENTRIES (TX_RING_SIZE - 2)
|
||||
#define RX_MAX_ENTRIES (RX_RING_SIZE - 2)
|
||||
|
||||
@@ -37,7 +35,7 @@
|
||||
#define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1))
|
||||
#define RX_RING_ADD(_i,_j) (((_i)+(_j)) & (RX_RING_SIZE-1))
|
||||
|
||||
#define RX_BUF_SIZE 1600 /* Ethernet MTU + plenty of slack! */
|
||||
#define RX_BUF_SIZE 2049 /* (was 1600) Ethernet MTU + plenty of slack! */
|
||||
|
||||
static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs);
|
||||
static void network_tx_int(int irq, void *dev_id, struct pt_regs *ptregs);
|
||||
@@ -48,6 +46,8 @@ static void cleanup_module(void);
|
||||
|
||||
static struct list_head dev_list;
|
||||
|
||||
static unsigned int net_countx;
|
||||
|
||||
/*
|
||||
* RX RING: RX_IDX <= rx_cons <= rx_prod
|
||||
* TX RING: TX_IDX <= tx_cons <= tx_prod
|
||||
@@ -72,16 +72,8 @@ struct net_private
|
||||
static int network_open(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
int error;
|
||||
char *rxlabel, *txlabel;
|
||||
int error = 0;
|
||||
|
||||
// This is inevitably not the right way to allocate a couple of static strings.
|
||||
rxlabel = kmalloc(sizeof("net-rx- "), GFP_KERNEL);
|
||||
txlabel = kmalloc(sizeof("net-tx- "), GFP_KERNEL);
|
||||
if ((rxlabel == NULL) || (txlabel == NULL)) goto fail;
|
||||
sprintf(rxlabel, "net-rx-%d", np->id);
|
||||
sprintf(txlabel, "net-tx-%d", np->id);
|
||||
|
||||
np->rx_idx = np->tx_idx = np->tx_full = 0;
|
||||
|
||||
memset(&np->stats, 0, sizeof(np->stats));
|
||||
@@ -113,8 +105,8 @@ static int network_open(struct net_device *dev)
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
error = request_irq(NET_RX_IRQ_FOR_VIF(np->id), network_rx_int, 0,
|
||||
rxlabel, dev);
|
||||
error = request_irq(NET_RX_IRQ, network_rx_int, 0,
|
||||
"net-rx", dev);
|
||||
if ( error )
|
||||
{
|
||||
printk(KERN_WARNING "%s: Could not allocate receive interrupt\n",
|
||||
@@ -122,13 +114,13 @@ static int network_open(struct net_device *dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = request_irq(NET_TX_IRQ_FOR_VIF(np->id), network_tx_int, 0,
|
||||
txlabel, dev);
|
||||
error = request_irq(NET_TX_IRQ, network_tx_int, 0,
|
||||
"net-tx", dev);
|
||||
if ( error )
|
||||
{
|
||||
printk(KERN_WARNING "%s: Could not allocate transmit interrupt\n",
|
||||
dev->name);
|
||||
free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev);
|
||||
free_irq(NET_RX_IRQ, dev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -141,8 +133,6 @@ static int network_open(struct net_device *dev)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if ( rxlabel ) kfree(rxlabel);
|
||||
if ( txlabel ) kfree(txlabel);
|
||||
if ( np->net_ring->rx_ring ) kfree(np->net_ring->rx_ring);
|
||||
if ( np->net_ring->tx_ring ) kfree(np->net_ring->tx_ring);
|
||||
if ( np->rx_skb_ring ) kfree(np->rx_skb_ring);
|
||||
@@ -179,13 +169,59 @@ static void network_tx_buf_gc(struct net_device *dev)
|
||||
spin_unlock_irqrestore(&np->tx_lock, flags);
|
||||
}
|
||||
|
||||
inline unsigned long get_ppte(unsigned long addr)
|
||||
{
|
||||
unsigned long ppte = 0xdeadbeef;
|
||||
pgd_t *pgd; pmd_t *pmd; pte_t *ptep;
|
||||
pgd = pgd_offset_k(addr);
|
||||
|
||||
if (pgd_none(*pgd) || pgd_bad(*pgd)) BUG();
|
||||
|
||||
pmd = pmd_offset(pgd, addr);
|
||||
if (pmd_none(*pmd)) BUG();
|
||||
if (pmd_bad(*pmd)) BUG();
|
||||
|
||||
ptep = pte_offset(pmd, addr);
|
||||
ppte = (unsigned long)phys_to_machine(virt_to_phys(ptep));
|
||||
|
||||
return ppte;
|
||||
}
|
||||
/*
|
||||
static void validate_free_list(void)
|
||||
{
|
||||
unsigned long addr, ppfn, mpfn, mpfn2, flags;
|
||||
struct list_head *i;
|
||||
struct net_page_info *np;
|
||||
|
||||
printk(KERN_ALERT "Walking free pages:\n");
|
||||
|
||||
spin_lock_irqsave(&net_page_list_lock, flags);
|
||||
|
||||
list_for_each(i, &net_page_list)
|
||||
{
|
||||
np = list_entry(i, struct net_page_info, list);
|
||||
addr = np->virt_addr;
|
||||
ppfn = virt_to_phys(addr) >> PAGE_SHIFT;
|
||||
mpfn = get_ppte(addr);
|
||||
mpfn2 = phys_to_machine_mapping[ppfn];
|
||||
|
||||
mpfn = (*(unsigned long *)phys_to_virt(machine_to_phys(mpfn))) >> PAGE_SHIFT;
|
||||
if (mpfn != mpfn2) printk(KERN_ALERT "mpfn %lu != %lu\n", mpfn, mpfn2);
|
||||
|
||||
if (machine_to_phys_mapping[mpfn] != ppfn) printk(KERN_ALERT "ppfn %lu != %lu\n", machine_to_phys_mapping[mpfn], ppfn);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&net_page_list_lock, flags);
|
||||
|
||||
}
|
||||
*/
|
||||
static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
unsigned int end = RX_RING_ADD(np->rx_idx, RX_MAX_ENTRIES);
|
||||
|
||||
|
||||
for ( i = np->net_ring->rx_prod; i != end; i = RX_RING_INC(i) )
|
||||
{
|
||||
@@ -194,8 +230,9 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
skb->dev = dev;
|
||||
skb_reserve(skb, 2); /* word align the IP header */
|
||||
np->rx_skb_ring[i] = skb;
|
||||
np->net_ring->rx_ring[i].addr = (unsigned long)skb->data;
|
||||
np->net_ring->rx_ring[i].addr = get_ppte(skb->head);
|
||||
np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
|
||||
//printk(KERN_ALERT "[%p]\n", phys_to_machine(virt_to_phys(skb->page_ptr)));
|
||||
}
|
||||
|
||||
np->net_ring->rx_prod = i;
|
||||
@@ -219,6 +256,14 @@ static void network_free_rx_buffers(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
void print_range(u8 *start, unsigned int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i++ < len)
|
||||
printk("%x:", start[i]);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
@@ -231,10 +276,23 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
netif_stop_queue(dev);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
//print_range(skb->data, ETH_HLEN + 8);
|
||||
//print_range(skb->data + ETH_HLEN + 8, 20);
|
||||
//printk("skb->len is %u in guestOS (expected fraglen: %u).\n", skb->len, skb->len - (ETH_HLEN + 8));
|
||||
i = np->net_ring->tx_prod;
|
||||
|
||||
if ( (((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= PAGE_SIZE )
|
||||
{
|
||||
struct sk_buff *new_skb = alloc_skb(RX_BUF_SIZE, GFP_KERNEL);
|
||||
skb_put(new_skb, skb->len);
|
||||
memcpy(new_skb->data, skb->data, skb->len);
|
||||
kfree_skb(skb);
|
||||
skb = new_skb;
|
||||
}
|
||||
|
||||
np->tx_skb_ring[i] = skb;
|
||||
np->net_ring->tx_ring[i].addr = (unsigned long)skb->data;
|
||||
np->net_ring->tx_ring[i].addr
|
||||
= (unsigned long)phys_to_machine(virt_to_phys(skb->data));
|
||||
np->net_ring->tx_ring[i].size = skb->len;
|
||||
np->net_ring->tx_prod = TX_RING_INC(i);
|
||||
atomic_inc(&np->tx_entries);
|
||||
@@ -273,13 +331,30 @@ static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/*if (net_countx++ % 100 == 0) validate_free_list();*/
|
||||
|
||||
again:
|
||||
for ( i = np->rx_idx; i != np->net_ring->rx_cons; i = RX_RING_INC(i) )
|
||||
{
|
||||
if (np->net_ring->rx_ring[i].status != RING_STATUS_OK)
|
||||
{
|
||||
printk("bad buffer on RX ring!(%d)\n",
|
||||
np->net_ring->rx_ring[i].status);
|
||||
continue;
|
||||
}
|
||||
skb = np->rx_skb_ring[i];
|
||||
|
||||
//printk(KERN_ALERT "[%u]: ptmm[%lx] old:(%lx) new:(%lx)\n", i , virt_to_phys(skb->head) >> PAGE_SHIFT, phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT], (*(unsigned long *)phys_to_virt(machine_to_phys(np->net_ring->rx_ring[i].addr))) >> PAGE_SHIFT);
|
||||
|
||||
phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] =
|
||||
(*(unsigned long *)phys_to_virt(
|
||||
machine_to_phys(np->net_ring->rx_ring[i].addr))
|
||||
) >> PAGE_SHIFT;
|
||||
|
||||
skb_put(skb, np->net_ring->rx_ring[i].size);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
np->stats.rx_packets++;
|
||||
|
||||
np->stats.rx_bytes += np->net_ring->rx_ring[i].size;
|
||||
netif_rx(skb);
|
||||
dev->last_rx = jiffies;
|
||||
@@ -309,8 +384,8 @@ int network_close(struct net_device *dev)
|
||||
struct net_private *np = dev->priv;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev);
|
||||
free_irq(NET_TX_IRQ_FOR_VIF(np->id), dev);
|
||||
free_irq(NET_RX_IRQ, dev);
|
||||
free_irq(NET_TX_IRQ, dev);
|
||||
network_free_rx_buffers(dev);
|
||||
kfree(np->net_ring->rx_ring);
|
||||
kfree(np->net_ring->tx_ring);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define _ASM_IO_H
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <asm/hypervisor.h>
|
||||
/*
|
||||
* This file contains the definitions for the x86 IO instructions
|
||||
* inb/inw/inl/outb/outw/outl and the "string versions" of the same
|
||||
@@ -73,6 +73,11 @@ static inline void * phys_to_virt(unsigned long address)
|
||||
return __va(address);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change virtual addresses to machine addresses and vv.
|
||||
* These are equally trivial.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Change "struct page" to physical address.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff