mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
bitkeeper revision 1.1159.1.172 (41542610ZBPAMBCg2f-D1VTZ8pdChw)
Merge xenbk@gandalf:/var/bk/xeno-unstable.bk into wray-m-3.hpl.hp.com:/home/mjw/repos-bk/xeno-unstable.bk
This commit is contained in:
commit
5e782a40bc
14 files changed
+301
-188
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
+15
-7
@@ -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) &&
|
||||
|
||||
+213
-135
@@ -23,26 +23,17 @@
|
||||
#include <hypervisor-ifs/sched_ctl.h>
|
||||
#include <xen/trace.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
};
|
||||
@@ -321,6 +321,8 @@ static cache_sizes_t cache_sizes[] = {
|
||||
{ 4096, NULL},
|
||||
{ 8192, NULL},
|
||||
{ 16384, NULL},
|
||||
{ 32768, NULL},
|
||||
{ 65536, NULL},
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||