diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 519c80013f..125ee3ffd9 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -13,6 +13,7 @@ cl349@freefall.cl.cam.ac.uk cl349@labyrinth.cl.cam.ac.uk djm@kirby.fc.hp.com gm281@boulderdash.cl.cam.ac.uk +gm281@tetrapod.cl.cam.ac.uk iap10@freefall.cl.cam.ac.uk iap10@labyrinth.cl.cam.ac.uk iap10@nidd.cl.cam.ac.uk diff --git a/linux-2.4.27-xen-sparse/arch/xen/config.in b/linux-2.4.27-xen-sparse/arch/xen/config.in index 60b80dfd34..2ed848d505 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/config.in +++ b/linux-2.4.27-xen-sparse/arch/xen/config.in @@ -17,6 +17,8 @@ comment 'Xen' bool 'Support for privileged operations (domain 0)' CONFIG_XEN_PRIVILEGED_GUEST bool 'Device-driver domain (physical device access)' CONFIG_XEN_PHYSDEV_ACCESS bool 'Scrub memory before freeing it to Xen' CONFIG_XEN_SCRUB_PAGES +bool 'Network-device frontend driver' CONFIG_XEN_NETDEV_FRONTEND +bool 'Block-device frontend driver' CONFIG_XEN_BLKDEV_FRONTEND endmenu # The IBM S/390 patch needs this. define_bool CONFIG_NO_IDLE_HZ y diff --git a/linux-2.4.27-xen-sparse/arch/xen/defconfig-xen0 b/linux-2.4.27-xen-sparse/arch/xen/defconfig-xen0 index 21b0a99eab..fac68182d1 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/defconfig-xen0 +++ b/linux-2.4.27-xen-sparse/arch/xen/defconfig-xen0 @@ -13,6 +13,8 @@ CONFIG_UID16=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_PHYSDEV_ACCESS=y CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XEN_NETDEV_FRONTEND=y +CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_NO_IDLE_HZ=y CONFIG_FOREIGN_PAGES=y diff --git a/linux-2.4.27-xen-sparse/arch/xen/defconfig-xenU b/linux-2.4.27-xen-sparse/arch/xen/defconfig-xenU index 08f1619f2e..6e66c3c9af 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/defconfig-xenU +++ b/linux-2.4.27-xen-sparse/arch/xen/defconfig-xenU @@ -1,5 +1,5 @@ # -# Automatically generated make config: don't edit +# Automatically generated by make menuconfig: don't edit # CONFIG_XEN=y CONFIG_X86=y @@ -17,6 +17,8 @@ CONFIG_UID16=y CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XEN_NETDEV_FRONTEND=y +CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_NO_IDLE_HZ=y # CONFIG_FOREIGN_PAGES is not set CONFIG_NETDEVICES=y @@ -156,10 +158,6 @@ CONFIG_IP_NF_TARGET_ULOG=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set - -# -# -# # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -192,20 +190,12 @@ CONFIG_IP_NF_TARGET_ULOG=y # SCSI support # CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set @@ -317,10 +307,6 @@ CONFIG_PSMOUSE=y # CONFIG_INPUT_EMU10K1 is not set # CONFIG_INPUT_SERIO is not set # CONFIG_INPUT_SERPORT is not set - -# -# Joysticks -# # CONFIG_INPUT_ANALOG is not set # CONFIG_INPUT_A3D is not set # CONFIG_INPUT_ADI is not set diff --git a/linux-2.4.27-xen-sparse/arch/xen/drivers/blkif/Makefile b/linux-2.4.27-xen-sparse/arch/xen/drivers/blkif/Makefile index 20c8192d3d..7474e71fb4 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/drivers/blkif/Makefile +++ b/linux-2.4.27-xen-sparse/arch/xen/drivers/blkif/Makefile @@ -1,8 +1,8 @@ O_TARGET := drv.o -subdir-y += frontend -obj-y += frontend/drv.o +subdir-$(CONFIG_XEN_NETDEV_FRONTEND) += frontend +obj-$(CONFIG_XEN_NETDEV_FRONTEND) += frontend/drv.o subdir-$(CONFIG_XEN_PHYSDEV_ACCESS) += backend obj-$(CONFIG_XEN_PHYSDEV_ACCESS) += backend/drv.o diff --git a/linux-2.4.27-xen-sparse/arch/xen/drivers/netif/Makefile b/linux-2.4.27-xen-sparse/arch/xen/drivers/netif/Makefile index 20c8192d3d..7474e71fb4 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/drivers/netif/Makefile +++ b/linux-2.4.27-xen-sparse/arch/xen/drivers/netif/Makefile @@ -1,8 +1,8 @@ O_TARGET := drv.o -subdir-y += frontend -obj-y += frontend/drv.o +subdir-$(CONFIG_XEN_NETDEV_FRONTEND) += frontend +obj-$(CONFIG_XEN_NETDEV_FRONTEND) += frontend/drv.o subdir-$(CONFIG_XEN_PHYSDEV_ACCESS) += backend obj-$(CONFIG_XEN_PHYSDEV_ACCESS) += backend/drv.o diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netback/netback.c index ca12459175..d1524b1f6e 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netback/netback.c @@ -13,6 +13,7 @@ #include "common.h" static void netif_page_release(struct page *page); +static void netif_skb_release(struct sk_buff *skb); static void make_tx_response(netif_t *netif, u16 id, s8 st); @@ -40,7 +41,8 @@ static unsigned char rx_notify[NR_EVENT_CHANNELS]; static unsigned long mmap_vstart; #define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE)) -#define PKT_PROT_LEN (ETH_HLEN + 20) +#define PKT_MIN_LEN (ETH_HLEN + 20) +#define PKT_PROT_LEN 64 static struct { netif_tx_request_t req; @@ -385,6 +387,7 @@ static void net_tx_action(unsigned long unused) NETIF_RING_IDX i; multicall_entry_t *mcl; PEND_RING_IDX dc, dp; + unsigned int data_len; if ( (dc = dealloc_cons) == (dp = dealloc_prod) ) goto skip_dealloc; @@ -497,7 +500,7 @@ static void net_tx_action(unsigned long unused) netif_schedule_work(netif); - if ( unlikely(txreq.size <= PKT_PROT_LEN) || + if ( unlikely(txreq.size <= PKT_MIN_LEN) || unlikely(txreq.size > ETH_FRAME_LEN) ) { DPRINTK("Bad packet size: %d\n", txreq.size); @@ -519,7 +522,9 @@ static void net_tx_action(unsigned long unused) pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - if ( unlikely((skb = alloc_skb(PKT_PROT_LEN+16, GFP_ATOMIC)) == NULL) ) + data_len = txreq.size > PKT_PROT_LEN ? PKT_PROT_LEN : txreq.size; + + if ( unlikely((skb = alloc_skb(data_len+16, GFP_ATOMIC)) == NULL) ) { DPRINTK("Can't allocate a skb in start_xmit.\n"); make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); @@ -578,19 +583,28 @@ static void net_tx_action(unsigned long unused) phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] = FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT); - __skb_put(skb, PKT_PROT_LEN); + data_len = txreq.size > PKT_PROT_LEN ? PKT_PROT_LEN : txreq.size; + + __skb_put(skb, data_len); memcpy(skb->data, (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)), - PKT_PROT_LEN); + data_len); - /* Append the packet payload as a fragment. */ - skb_shinfo(skb)->frags[0].page = - virt_to_page(MMAP_VADDR(pending_idx)); - skb_shinfo(skb)->frags[0].size = txreq.size - PKT_PROT_LEN; - skb_shinfo(skb)->frags[0].page_offset = - (txreq.addr + PKT_PROT_LEN) & ~PAGE_MASK; - skb_shinfo(skb)->nr_frags = 1; - skb->data_len = txreq.size - PKT_PROT_LEN; + if (data_len < txreq.size) { + /* Append the packet payload as a fragment. */ + skb_shinfo(skb)->frags[0].page = + virt_to_page(MMAP_VADDR(pending_idx)); + skb_shinfo(skb)->frags[0].size = txreq.size - data_len; + skb_shinfo(skb)->frags[0].page_offset = + (txreq.addr + data_len) & ~PAGE_MASK; + skb_shinfo(skb)->nr_frags = 1; + } else { + skb_shinfo(skb)->frags[0].page = + virt_to_page(MMAP_VADDR(pending_idx)); + skb->destructor = netif_skb_release; + } + + skb->data_len = txreq.size - data_len; skb->len += skb->data_len; skb->dev = netif->dev; @@ -606,13 +620,9 @@ static void net_tx_action(unsigned long unused) } } -static void netif_page_release(struct page *page) +static void netif_idx_release(u16 pending_idx) { unsigned long flags; - u16 pending_idx = page - virt_to_page(mmap_vstart); - - /* Ready for next use. */ - set_page_count(page, 1); spin_lock_irqsave(&dealloc_lock, flags); dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx; @@ -621,6 +631,24 @@ static void netif_page_release(struct page *page) tasklet_schedule(&net_tx_tasklet); } +static void netif_page_release(struct page *page) +{ + u16 pending_idx = page - virt_to_page(mmap_vstart); + + /* Ready for next use. */ + set_page_count(page, 1); + + netif_idx_release(pending_idx); +} + +static void netif_skb_release(struct sk_buff *skb) +{ + struct page *page = skb_shinfo(skb)->frags[0].page; + u16 pending_idx = page - virt_to_page(mmap_vstart); + + netif_idx_release(pending_idx); +} + #if 0 long flush_bufs_for_netif(netif_t *netif) { diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c index ba57fd0d9f..fb1abec185 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c @@ -249,16 +249,14 @@ static int vif_wake(struct net_device *dev) { struct sk_buff *skb; u32 src_ip, dst_ip; - unsigned char dst_hw[ETH_ALEN]; - - memset(dst_hw, 0xff, ETH_ALEN); dst_ip = INADDR_BROADCAST; src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK); - skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, dst_ip, dev, src_ip, - dst_hw, dev->dev_addr, NULL); + /*dst_hw*/ NULL, /*src_hw*/ NULL, + /*target_hw*/ dev->dev_addr); if ( skb == NULL ) return -ENOMEM; diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index ec27a5eb8d..ade285129c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -223,12 +223,12 @@ void arch_do_createdomain(struct domain *d) virt_to_phys(&machine_to_phys_mapping[0])>>PAGE_SHIFT; SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); machine_to_phys_mapping[virt_to_phys(d->shared_info) >> - PAGE_SHIFT] = 0x80000000UL; /* debug */ + PAGE_SHIFT] = INVALID_P2M_ENTRY; d->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); memset(d->mm.perdomain_pt, 0, PAGE_SIZE); machine_to_phys_mapping[virt_to_phys(d->mm.perdomain_pt) >> - PAGE_SHIFT] = 0x0fffdeadUL; /* debug */ + PAGE_SHIFT] = INVALID_P2M_ENTRY; } int arch_final_setup_guestos(struct domain *d, full_execution_context_t *c) diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index ea73908a96..84c7ade98c 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1802,6 +1802,12 @@ static __init int ptwr_init(void) (void *)alloc_xenheap_page(); ptwr_info[i].ptinfo[PTWR_PT_INACTIVE].page = (void *)alloc_xenheap_page(); + machine_to_phys_mapping[virt_to_phys( + ptwr_info[i].ptinfo[PTWR_PT_ACTIVE].page)>>PAGE_SHIFT] = + INVALID_P2M_ENTRY; + machine_to_phys_mapping[virt_to_phys( + ptwr_info[i].ptinfo[PTWR_PT_INACTIVE].page)>>PAGE_SHIFT] = + INVALID_P2M_ENTRY; } return 0; diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 8f784a69e8..486fd94441 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -200,8 +200,6 @@ int shadow_mode_enable( struct domain *p, unsigned int mode ) struct shadow_status **fptr; int i; - m->shadow_mode = mode; - // allocate hashtable m->shadow_ht = xmalloc(shadow_ht_buckets * sizeof(struct shadow_status)); @@ -241,16 +239,25 @@ int shadow_mode_enable( struct domain *p, unsigned int mode ) if( m->shadow_dirty_bitmap == NULL ) { m->shadow_dirty_bitmap_size = 0; + BUG(); goto nomem; } memset(m->shadow_dirty_bitmap,0,m->shadow_dirty_bitmap_size/8); } + m->shadow_mode = mode; + // call shadow_mk_pagetable __shadow_mk_pagetable( m ); return 0; nomem: + if( m->shadow_ht ) { + xfree( m->shadow_ht ); m->shadow_ht = NULL; }; + + if( m->shadow_ht_extras ) { + xfree( m->shadow_ht_extras ); m->shadow_ht_extras = NULL; }; + return -ENOMEM; } @@ -285,7 +292,10 @@ void __shadow_mode_disable(struct domain *d) } // free the hashtable itself - xfree( &m->shadow_ht[0] ); + xfree( m->shadow_ht ); + + m->shadow_ht = NULL; + m->shadow_ht_extras = NULL; } static int shadow_mode_table_op(struct domain *d, @@ -314,8 +324,6 @@ static int shadow_mode_table_op(struct domain *d, switch(op) { case DOM0_SHADOW_CONTROL_OP_FLUSH: - // XXX THIS IS VERY DANGEROUS : MUST ENSURE THE PTs ARE NOT IN USE ON - // OTHER CPU -- fix when we get sched sync pause. __free_shadow_table( m ); break; @@ -452,12 +460,12 @@ int shadow_mode_control(struct domain *d, dom0_shadow_control_t *sc) else if ( cmd == DOM0_SHADOW_CONTROL_OP_ENABLE_TEST ) { shadow_mode_disable(d); - shadow_mode_enable(d, SHM_test); + rc = shadow_mode_enable(d, SHM_test); } else if ( cmd == DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY ) { shadow_mode_disable(d); - shadow_mode_enable(d, SHM_logdirty); + rc = shadow_mode_enable(d, SHM_logdirty); } else if ( shadow_mode(d) && (cmd >= DOM0_SHADOW_CONTROL_OP_FLUSH) && diff --git a/xen/common/sched_atropos.c b/xen/common/sched_atropos.c index 53e4519b9f..f9229528fe 100644 --- a/xen/common/sched_atropos.c +++ b/xen/common/sched_atropos.c @@ -23,26 +23,17 @@ #include #include -/* - * KAF -- Atropos is broken by the new scheduler interfaces. - * It'll need fixing to get rid of use of ATROPOS_TASK__* - */ -#ifdef KAF_KILLED - #define ATROPOS_TASK_UNBLOCKED 16 #define ATROPOS_TASK_WAIT 32 - -#define Activation_Reason_Allocated 1 -#define Activation_Reason_Preempted 2 -#define Activation_Reason_Extra 3 +#define ATROPOS_TASK_BLOCKED 48 /* Atropos-specific per-domain data */ struct at_dom_info { /* MAW Xen additions */ struct domain *owner; /* the domain this data belongs to */ + struct list_head run_list; /* runqueue */ struct list_head waitq; /* wait queue */ - int reason; /* reason domain was last scheduled */ /* (what remains of) the original fields */ @@ -57,26 +48,59 @@ struct at_dom_info s_time_t latency; /* Unblocking latency */ int xtratime; /* Prepared to accept extra time? */ + int state; /* Keeps Atropos domain state */ }; /* Atropos-specific per-CPU data */ struct at_cpu_info { + spinlock_t runq_lock; + struct list_head runq; /* run queue */ + spinlock_t waitq_lock; struct list_head waitq; /* wait queue*/ }; #define DOM_INFO(_p) ((struct at_dom_info *)((_p)->sched_priv)) -#define CPU_INFO(_c) ((struct at_cpu_info *)((_c).sched_priv)) -#define WAITQ(cpu) (&CPU_INFO(schedule_data[cpu])->waitq) -#define RUNQ(cpu) (&schedule_data[cpu].runqueue) +#define CPU_INFO(_c) ((struct at_cpu_info *)((schedule_data[_c]).sched_priv)) +#define WAITQ(cpu) (&CPU_INFO(cpu)->waitq) +#define RUNQ(cpu) (&CPU_INFO(cpu)->runq) +#define RUNLIST(_d) (&DOM_INFO(_d)->run_list) #define BESTEFFORT_QUANTUM MILLISECS(5) +static void at_dump_cpu_state(int cpu); + /* SLAB cache for struct at_dom_info objects */ static xmem_cache_t *dom_info_cache; +/* + * Wrappers for run-queue management. Must be called with the run_lock + * held. + */ +static inline void __add_to_runqueue_head(struct domain *d) +{ + list_add(RUNLIST(d), RUNQ(d->processor)); +} + +static inline void __add_to_runqueue_tail(struct domain *d) +{ + list_add_tail(RUNLIST(d), RUNQ(d->processor)); +} + +static inline void __del_from_runqueue(struct domain *d) +{ + struct list_head *runlist = RUNLIST(d); + list_del(runlist); + runlist->next = NULL; +} + +static inline int __task_on_runqueue(struct domain *d) +{ + return (RUNLIST(d))->next != NULL; +} + /** calculate the length of a linked list */ static int q_len(struct list_head *q) @@ -114,15 +138,17 @@ static inline struct domain *waitq_el(struct list_head *l) static void requeue(struct domain *sdom) { struct at_dom_info *inf = DOM_INFO(sdom); - struct list_head *prev = WAITQ(sdom->processor); + struct list_head *prev; struct list_head *next; - if(sdom->state == ATROPOS_TASK_WAIT || - sdom->state == ATROPOS_TASK_UNBLOCKED ) - { - /* insert into ordered wait queue */ + if(!domain_runnable(sdom)) return; + + if(inf->state == ATROPOS_TASK_WAIT || + inf->state == ATROPOS_TASK_UNBLOCKED) + { prev = WAITQ(sdom->processor); + list_for_each(next, WAITQ(sdom->processor)) { struct at_dom_info *i = @@ -144,16 +170,17 @@ static void requeue(struct domain *sdom) else if ( domain_runnable(sdom) ) { /* insert into ordered run queue */ + prev = RUNQ(sdom->processor); list_for_each(next, RUNQ(sdom->processor)) { - struct domain *p = list_entry(next, struct domain, + struct at_dom_info *p = list_entry(next, struct at_dom_info, run_list); - if( DOM_INFO(p)->deadline > inf->deadline || is_idle_task(p) ) + if( p->deadline > inf->deadline || is_idle_task(p->owner) ) { - __list_add(&sdom->run_list, prev, next); + __list_add(&inf->run_list, prev, next); break; } @@ -161,12 +188,27 @@ static void requeue(struct domain *sdom) } if ( next == RUNQ(sdom->processor) ) - list_add_tail(&sdom->run_list, RUNQ(sdom->processor)); + list_add_tail(&inf->run_list, RUNQ(sdom->processor)); + + } /* silently ignore tasks in other states like BLOCKED, DYING, STOPPED, etc * - they shouldn't be on any queue */ } +/** at_alloc_task - allocate private info for a task */ +static int at_alloc_task(struct domain *p) +{ + ASSERT(p != NULL); + + p->sched_priv = xmem_cache_alloc(dom_info_cache); + if( p->sched_priv == NULL ) + return -1; + + return 0; +} + + /* prepare a task to be added to scheduling */ static void at_add_task(struct domain *p) { @@ -199,14 +241,15 @@ static void at_add_task(struct domain *p) DOM_INFO(p)->slice = MILLISECS(10); DOM_INFO(p)->latency = SECONDS(10); DOM_INFO(p)->xtratime = 1; - DOM_INFO(p)->deadline = now + SECONDS(10); + DOM_INFO(p)->deadline = now; +// DOM_INFO(p)->deadline = now + SECONDS(10); DOM_INFO(p)->prevddln = 0; } + INIT_LIST_HEAD(&(DOM_INFO(p)->run_list)); INIT_LIST_HEAD(&(DOM_INFO(p)->waitq)); } - /** * dequeue - remove a domain from any queues it is on. * @sdom: the task to remove @@ -214,19 +257,16 @@ static void at_add_task(struct domain *p) static void dequeue(struct domain *sdom) { struct at_dom_info *inf = DOM_INFO(sdom); - + ASSERT(sdom->domain != IDLE_DOMAIN_ID); /* just delete it from all the queues! */ list_del(&inf->waitq); INIT_LIST_HEAD(&inf->waitq); + if(__task_on_runqueue(sdom)) __del_from_runqueue(sdom); - - sdom->run_list.next = NULL; - sdom->run_list.prev = NULL; - } @@ -254,44 +294,64 @@ static void unblock(struct domain *sdom) { s_time_t time = NOW(); struct at_dom_info *inf = DOM_INFO(sdom); - + dequeue(sdom); /* We distinguish two cases... short and long blocks */ - if ( inf->deadline < time ) { /* Long blocking case */ - /* The sdom has passed its deadline since it was blocked. - Give it its new deadline based on the latency value. */ - inf->prevddln = time; + /* The sdom has passed its deadline since it was blocked. + Give it its new deadline based on the latency value. */ + inf->prevddln = time; /* Scale the scheduling parameters as requested by the latency hint. */ - inf->deadline = time + inf->latency; + inf->deadline = time + inf->latency; inf->slice = inf->nat_slice / ( inf->nat_period / inf->latency ); inf->period = inf->latency; - inf->remain = inf->slice; + inf->remain = inf->slice; } - else + else { /* Short blocking case */ - /* We leave REMAIN intact, but put this domain on the WAIT - queue marked as recently unblocked. It will be given - priority over other domains on the wait queue until while - REMAIN>0 in a generous attempt to help it make up for its - own foolishness. */ - if(inf->remain > 0) - sdom->state = ATROPOS_TASK_UNBLOCKED; + /* We leave REMAIN intact, but put this domain on the WAIT + queue marked as recently unblocked. It will be given + priority over other domains on the wait queue until while + REMAIN>0 in a generous attempt to help it make up for its + own foolishness. */ + if(inf->remain > 0) + inf->state = ATROPOS_TASK_UNBLOCKED; else - sdom->state = ATROPOS_TASK_WAIT; + inf->state = ATROPOS_TASK_WAIT; } requeue(sdom); - } + +static int at_init_idle_task(struct domain *p) +{ + if(at_alloc_task(p) < 0) return -1; + + at_add_task(p); + + dequeue(p); + requeue(p); + + return 0; +} + + +static void block(struct domain* sdom) +{ + DOM_INFO(sdom)->state = ATROPOS_TASK_BLOCKED; + dequeue(sdom); + requeue(sdom); +} + + /** * ATROPOS - main scheduler function */ @@ -301,13 +361,13 @@ task_slice_t ksched_scheduler(s_time_t time) s_time_t newtime; s_time_t ranfor; /* How long the domain ran */ struct domain *sdom; /* tmp. scheduling domain */ - int reason; /* reason for reschedule */ int cpu = cur_sdom->processor; /* current CPU */ struct at_dom_info *cur_info; static unsigned long waitq_rrobin = 0; int i; task_slice_t ret; + cur_info = DOM_INFO(cur_sdom); ASSERT( cur_sdom != NULL); @@ -333,36 +393,35 @@ task_slice_t ksched_scheduler(s_time_t time) dequeue(cur_sdom); if ( domain_runnable(cur_sdom) || - (cur_sdom->state == ATROPOS_TASK_UNBLOCKED) ) + (cur_info->state == ATROPOS_TASK_UNBLOCKED) ) { - /* In this block, we are doing accounting for an sdom which has - been running in contracted time. Note that this could now happen - even if the domain is on the wait queue (i.e. if it blocked) */ + /* In this block, we are doing accounting for an sdom which has + been running in contracted time. Note that this could now happen + even if the domain is on the wait queue (i.e. if it blocked) */ - /* Deduct guaranteed time from the domain */ - cur_info->remain -= ranfor; + /* Deduct guaranteed time from the domain */ + cur_info->remain -= ranfor; - /* If guaranteed time has run out... */ - if ( cur_info->remain <= 0 ) + /* If guaranteed time has run out... */ + if ( cur_info->remain <= 0 ) { - /* Move domain to correct position in WAIT queue */ + /* Move domain to correct position in WAIT queue */ /* XXX sdom_unblocked doesn't need this since it is already in the correct place. */ - cur_sdom->state = ATROPOS_TASK_WAIT; - } + cur_info->state = ATROPOS_TASK_WAIT; + } } requeue(cur_sdom); - deschedule_done: - +deschedule_done: /***************************** * * We have now successfully descheduled the current sdom. * The next task is the allocate CPU time to any sdom it is due to. * - ****************************/ + ****************************/ cur_sdom = NULL; /***************************** @@ -371,13 +430,14 @@ task_slice_t ksched_scheduler(s_time_t time) * period deadline. If necessary, move them to run queue. * ****************************/ + while(!list_empty(WAITQ(cpu)) && - DOM_INFO(sdom = waitq_el(WAITQ(cpu)->next))->deadline <= time ) { - - struct at_dom_info *inf = DOM_INFO(sdom); + DOM_INFO(sdom = waitq_el(WAITQ(cpu)->next))->deadline <= time ) + { + struct at_dom_info *inf = DOM_INFO(sdom); dequeue(sdom); - + if ( inf->period != inf->nat_period ) { /* This domain has had its parameters adjusted as a result of @@ -392,22 +452,22 @@ task_slice_t ksched_scheduler(s_time_t time) } } - /* Domain begins a new period and receives a slice of CPU - * If this domain has been blocking then throw away the - * rest of it's remain - it can't be trusted */ - if (inf->remain > 0) - inf->remain = inf->slice; - else - inf->remain += inf->slice; + /* Domain begins a new period and receives a slice of CPU + * If this domain has been blocking then throw away the + * rest of it's remain - it can't be trusted */ + if (inf->remain > 0) + inf->remain = inf->slice; + else + inf->remain += inf->slice; - inf->prevddln = inf->deadline; - inf->deadline += inf->period; + inf->prevddln = inf->deadline; + inf->deadline += inf->period; if ( inf->remain <= 0 ) - sdom->state = ATROPOS_TASK_WAIT; + inf->state = ATROPOS_TASK_WAIT; - /* Place on the appropriate queue */ - requeue(sdom); + /* Place on the appropriate queue */ + requeue(sdom); } /***************************** @@ -421,13 +481,11 @@ task_slice_t ksched_scheduler(s_time_t time) ****************************/ /* we guarantee there's always something on the runqueue */ - cur_sdom = list_entry(RUNQ(cpu)->next, - struct domain, run_list); + cur_info = list_entry(RUNQ(cpu)->next, + struct at_dom_info, run_list); - cur_info = DOM_INFO(cur_sdom); + cur_sdom = cur_info->owner; newtime = time + cur_info->remain; - reason = (cur_info->prevddln > cur_sdom->lastschd) ? - Activation_Reason_Allocated : Activation_Reason_Preempted; /* MAW - the idle domain is always on the run queue. We run from the * runqueue if it's NOT the idle domain or if there's nothing on the wait @@ -436,12 +494,13 @@ task_slice_t ksched_scheduler(s_time_t time) { struct list_head *item; - /* Try running a domain on the WAIT queue - this part of the - scheduler isn't particularly efficient but then again, we - don't have any guaranteed domains to worry about. */ + /* Try running a domain on the WAIT queue - this part of the + scheduler isn't particularly efficient but then again, we + don't have any guaranteed domains to worry about. */ - /* See if there are any unblocked domains on the WAIT - queue who we can give preferential treatment to. */ + /* See if there are any unblocked domains on the WAIT + queue who we can give preferential treatment to. */ + list_for_each(item, WAITQ(cpu)) { struct at_dom_info *inf = @@ -449,23 +508,24 @@ task_slice_t ksched_scheduler(s_time_t time) sdom = inf->owner; - if (sdom->state == ATROPOS_TASK_UNBLOCKED) { - cur_sdom = sdom; - cur_info = inf; - newtime = time + inf->remain; - reason = Activation_Reason_Preempted; - goto found; + if (inf->state == ATROPOS_TASK_UNBLOCKED) + { + cur_sdom = sdom; + cur_info = inf; + newtime = time + inf->remain; + goto found; + } } - } /* init values needed to approximate round-robin for slack time */ i = 0; if ( waitq_rrobin >= q_len(WAITQ(cpu))) waitq_rrobin = 0; - /* Last chance: pick a domain on the wait queue with the XTRA - flag set. The NEXT_OPTM field is used to cheaply achieve - an approximation of round-robin order */ + + /* Last chance: pick a domain on the wait queue with the XTRA + flag set. The NEXT_OPTM field is used to cheaply achieve + an approximation of round-robin order */ list_for_each(item, WAITQ(cpu)) { struct at_dom_info *inf = @@ -473,11 +533,11 @@ task_slice_t ksched_scheduler(s_time_t time) sdom = inf->owner; - if (inf->xtratime && i >= waitq_rrobin) { + if (inf->xtratime && i >= waitq_rrobin) + { cur_sdom = sdom; cur_info = inf; newtime = time + BESTEFFORT_QUANTUM; - reason = Activation_Reason_Extra; waitq_rrobin = i + 1; /* set this value ready for next */ goto found; } @@ -502,7 +562,7 @@ task_slice_t ksched_scheduler(s_time_t time) /* exhausted its time, cut short the time allocation */ if (!list_empty(WAITQ(cpu))) { - newtime = MIN(newtime, + newtime = MIN(newtime, DOM_INFO(waitq_el(WAITQ(cpu)->next))->deadline); } @@ -512,9 +572,6 @@ task_slice_t ksched_scheduler(s_time_t time) ret.task = cur_sdom; ret.time = newtime - time; - cur_sdom->min_slice = newtime - time; - DOM_INFO(cur_sdom)->reason = reason; - TRACE_1D(0, cur_sdom->domain); return ret; @@ -531,8 +588,10 @@ static int at_init_scheduler() schedule_data[i].sched_priv = xmalloc(sizeof(struct at_cpu_info)); if ( schedule_data[i].sched_priv == NULL ) return -1; - WAITQ(i)->next = WAITQ(i); - WAITQ(i)->prev = WAITQ(i); + INIT_LIST_HEAD(WAITQ(i)); + INIT_LIST_HEAD(RUNQ(i)); + spin_lock_init(&CPU_INFO(i)->runq_lock); + spin_lock_init(&CPU_INFO(i)->waitq_lock); } dom_info_cache = xmem_cache_create("Atropos dom info", @@ -542,13 +601,6 @@ static int at_init_scheduler() return 0; } -/* dump relevant per-cpu state for a run queue dump */ -static void at_dump_cpu_state(int cpu) -{ - printk("Waitq len: %d Runq len: %d ", - q_len(WAITQ(cpu)), - q_len(RUNQ(cpu))); -} /* print relevant per-domain info for a run queue dump */ static void at_dump_runq_el(struct domain *p) @@ -558,6 +610,51 @@ static void at_dump_runq_el(struct domain *p) } +/* dump relevant per-cpu state for a run queue dump */ +static void at_dump_cpu_state(int cpu) +{ + struct list_head *list, *queue; + int loop = 0; + struct at_dom_info *d_inf; + struct domain *d; + + queue = RUNQ(cpu); + printk("\nRUNQUEUE rq %lx n: %lx, p: %lx\n", (unsigned long)queue, + (unsigned long) queue->next, (unsigned long) queue->prev); + + list_for_each ( list, queue ) + { + d_inf = list_entry(list, struct at_dom_info, run_list); + d = d_inf->owner; + printk("%3d: %d has=%c ", loop++, d->domain, + test_bit(DF_RUNNING, &d->flags) ? 'T':'F'); + at_dump_runq_el(d); + printk("c=0x%X%08X\n", (u32)(d->cpu_time>>32), (u32)d->cpu_time); + printk(" l: %lx n: %lx p: %lx\n", + (unsigned long)list, (unsigned long)list->next, + (unsigned long)list->prev); + } + + + queue = WAITQ(cpu); + printk("\nWAITQUEUE rq %lx n: %lx, p: %lx\n", (unsigned long)queue, + (unsigned long) queue->next, (unsigned long) queue->prev); + + list_for_each ( list, queue ) + { + d_inf = list_entry(list, struct at_dom_info, waitq); + d = d_inf->owner; + printk("%3d: %d has=%c ", loop++, d->domain, + test_bit(DF_RUNNING, &d->flags) ? 'T':'F'); + at_dump_runq_el(d); + printk("c=0x%X%08X\n", (u32)(d->cpu_time>>32), (u32)d->cpu_time); + printk(" l: %lx n: %lx p: %lx\n", + (unsigned long)list, (unsigned long)list->next, + (unsigned long)list->prev); + } + +} + /* set or fetch domain scheduling parameters */ static int at_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { @@ -585,22 +682,6 @@ static int at_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) return 0; } - -/** at_alloc_task - allocate private info for a task */ -static int at_alloc_task(struct domain *p) -{ - ASSERT(p != NULL); - - p->sched_priv = xmem_cache_alloc(dom_info_cache); - if( p->sched_priv == NULL ) - return -1; - - memset(p->sched_priv, 0, sizeof(struct at_dom_info)); - - return 0; -} - - /* free memory associated with a task */ static void at_free_task(struct domain *p) { @@ -627,23 +708,20 @@ static int at_prn_state(int state) return ret; } - -#endif /* KAF_KILLED */ struct scheduler sched_atropos_def = { .name = "Atropos Soft Real Time Scheduler", .opt_name = "atropos", .sched_id = SCHED_ATROPOS, -#ifdef KAF_KILLED .init_scheduler = at_init_scheduler, + .init_idle_task = at_init_idle_task, .alloc_task = at_alloc_task, .add_task = at_add_task, .free_task = at_free_task, - .wake_up = unblock, + .wake = unblock, + .sleep = block, .do_schedule = ksched_scheduler, .adjdom = at_adjdom, .dump_cpu_state = at_dump_cpu_state, - .dump_runq_el = at_dump_runq_el, .prn_state = at_prn_state, -#endif /* KAF_KILLED */ }; diff --git a/xen/common/slab.c b/xen/common/slab.c index 172b7ee117..3e91a6a058 100644 --- a/xen/common/slab.c +++ b/xen/common/slab.c @@ -321,6 +321,8 @@ static cache_sizes_t cache_sizes[] = { { 4096, NULL}, { 8192, NULL}, { 16384, NULL}, + { 32768, NULL}, + { 65536, NULL}, { 0, NULL} }; diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 2d399bded7..cd565d8dcc 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -116,6 +116,8 @@ struct pfn_info spin_unlock(&(_dom)->page_alloc_lock); \ } while ( 0 ) +#define INVALID_P2M_ENTRY (~0UL) + extern struct pfn_info *frame_table; extern unsigned long frame_table_size; extern unsigned long max_page;