bitkeeper revision 1.34 (3e4cfce1Ot4YJzJ4jwNjDthlFrZV5w)

conflict resolution.
This commit is contained in:
akw27@boulderdash.cl.cam.ac.uk committed 2003-02-14 14:27:45 +00:00
commit ed22010809
32 files changed
+3594 -3645

No files matched your search

+3 -2
View File
@@ -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
View File
@@ -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
+9 -4
View File
@@ -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,
+2 -2
View File
@@ -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
View File
@@ -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);
}
+7 -4
View File
@@ -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
View File
@@ -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
+6 -4
View File
@@ -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. */
+6 -2
View File
@@ -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
+5 -2
View File
@@ -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;
+1 -1
View File
@@ -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
+13 -9
View File
@@ -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.
+1 -1
View File
@@ -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 */
+1
View File
@@ -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,
+4 -1
View File
@@ -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.
+48
View File
@@ -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
+21 -21
View File
@@ -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) \
+1
View File
@@ -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.
+16 -6
View File
@@ -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
+4 -1
View File
@@ -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);
+16 -5
View File
@@ -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;
+37 -3
View File
@@ -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
View File
@@ -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, &current->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, &current->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(&current->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
View File
@@ -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
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.