summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--recipes-extended/xen/files/allow_disable_xend.patch75
-rw-r--r--recipes-extended/xen/files/ioemu-cross-gl-check.patch29
-rw-r--r--recipes-extended/xen/files/xend-config.sxp304
-rwxr-xr-xrecipes-extended/xen/files/xenminiinit.sh59
-rw-r--r--recipes-extended/xen/xen-4.1.2/allow_disable_xend.patch75
-rw-r--r--recipes-extended/xen/xen-hg/ioemu-cross-gl-check.patch29
-rw-r--r--recipes-extended/xen/xen-hg/tools_qemu_xen_remove_CFLAGS.patch48
-rw-r--r--recipes-extended/xen/xen-python.inc49
-rw-r--r--recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch6785
-rw-r--r--recipes-extended/xen/xen-rt_4.0.1.bb25
-rw-r--r--recipes-extended/xen/xen.inc305
-rw-r--r--recipes-extended/xen/xen_4.1.2.bb24
-rw-r--r--recipes-extended/xen/xen_hg.bb29
13 files changed, 7836 insertions, 0 deletions
diff --git a/recipes-extended/xen/files/allow_disable_xend.patch b/recipes-extended/xen/files/allow_disable_xend.patch
new file mode 100644
index 00000000..33187045
--- /dev/null
+++ b/recipes-extended/xen/files/allow_disable_xend.patch
@@ -0,0 +1,75 @@
1--- xen-4.1.2/config/StdGNU.mk.sav 2012-03-08 12:30:26.047303578 -0700
2+++ xen-4.1.2/config/StdGNU.mk 2012-03-08 12:31:48.826696508 -0700
3@@ -56,6 +56,9 @@
4 XEN_CONFIG_DIR = $(CONFIG_DIR)/xen
5 XEN_SCRIPT_DIR = $(XEN_CONFIG_DIR)/scripts
6
7+# Allow xend to be disabled in lieu of only libxl
8+CONFIG_ENABLE_XEND ?= y
9+
10 SOCKET_LIBS =
11 CURSES_LIBS = -lncurses
12 PTHREAD_LIBS = -lpthread
13--- xen-4.1.2/tools/Makefile.sav 2012-03-08 11:25:10.177301492 -0700
14+++ xen-4.1.2/tools/Makefile 2012-03-08 12:33:48.807302767 -0700
15@@ -15,7 +15,7 @@
16 SUBDIRS-$(CONFIG_X86) += firmware
17 SUBDIRS-$(ACM_SECURITY) += security
18 SUBDIRS-y += console
19-SUBDIRS-y += xenmon
20+SUBDIRS-$(CONFIG_ENABLE_XEND) += xenmon
21 SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
22 SUBDIRS-$(VTPM_TOOLS) += vtpm
23 SUBDIRS-y += xenstat
24@@ -36,17 +36,19 @@
25
26 SUBDIRS-y += xenpmd
27 SUBDIRS-y += libxl
28-SUBDIRS-y += remus
29+SUBDIRS-$(CONFIG_ENABLE_XEND) += remus
30 SUBDIRS-$(CONFIG_X86) += xenpaging
31 SUBDIRS-$(CONFIG_X86) += debugger/gdbsx
32 SUBDIRS-$(CONFIG_X86) += debugger/kdd
33
34 # These don't cross-compile
35 ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
36+ifneq ($(XEN_ENABLE_XEND),y)
37 SUBDIRS-$(PYTHON_TOOLS) += python
38 SUBDIRS-$(PYTHON_TOOLS) += pygrub
39 SUBDIRS-$(OCAML_TOOLS) += ocaml
40 endif
41+endif
42
43 # For the sake of linking, set the sys-root
44 ifneq ($(CROSS_COMPILE),)
45--- xen-4.1.2/tools/misc/Makefile.sav 2012-03-08 12:23:10.107321955 -0700
46+++ xen-4.1.2/tools/misc/Makefile 2012-03-08 12:34:54.466721729 -0700
47@@ -19,11 +19,13 @@
48 SUBDIRS-$(CONFIG_MINITERM) += miniterm
49 SUBDIRS := $(SUBDIRS-y)
50
51-INSTALL_BIN-y := xencons
52+INSTALL_BIN-y :=
53+INSTALL_BIN-$(CONFIG_ENABLE_XEND) += xencons
54 INSTALL_BIN-$(CONFIG_X86) += xen-detect
55 INSTALL_BIN := $(INSTALL_BIN-y)
56
57-INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd
58+INSTALL_SBIN-y := xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd
59+INSTALL_SBIN-$(CONFIG_ENABLE_XEND) += xm xend xsview xen-python-path xen-bugtool
60 INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash
61 INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool
62 INSTALL_SBIN := $(INSTALL_SBIN-y)
63--- xen-4.1.2/tools/hotplug/NetBSD/Makefile.sav 2012-03-08 12:54:56.247306596 -0700
64+++ xen-4.1.2/tools/hotplug/NetBSD/Makefile 2012-03-08 12:57:50.337339410 -0700
65@@ -8,7 +8,9 @@
66 XEN_SCRIPTS += vif-ip
67
68 XEN_SCRIPT_DATA =
69-XEN_RCD_PROG = rc.d/xencommons rc.d/xend rc.d/xendomains rc.d/xen-watchdog
70+XEN_RCD_PROG-y := rc.d/xencommons rc.d/xendomains rc.d/xen-watchdog
71+XEN_RCD_PROG-$(CONFIG_ENABLE_XEND) += rc.d/xend
72+XEN_RCD_PROG := $(XEN_RCD_PROG-y)
73
74 .PHONY: all
75 all:
diff --git a/recipes-extended/xen/files/ioemu-cross-gl-check.patch b/recipes-extended/xen/files/ioemu-cross-gl-check.patch
new file mode 100644
index 00000000..a1363ea0
--- /dev/null
+++ b/recipes-extended/xen/files/ioemu-cross-gl-check.patch
@@ -0,0 +1,29 @@
1--- qemu-xen-4.1-testing/configure 2012-02-20 09:01:08.219798969 -0700
2+++ xen-4.1-testing.hg/../git/configure 2012-02-20 09:03:27.876749305 -0700
3@@ -289,7 +289,7 @@
4 kqemu="yes"
5 fi
6 fi
7- if test -f /usr/include/sys/soundcard.h ; then
8+ if test -f ${CROSS_SYS_ROOT}/usr/include/sys/soundcard.h ; then
9 audio_drv_list="oss"
10 fi
11 audio_possible_drivers="oss sdl"
12@@ -872,7 +872,7 @@
13 #endif
14 int main( void ) { return (int) glGetString(GL_EXTENSIONS); }
15 EOF
16-if $cc $ARCH_CFLAGS -o $TMPE `$sdl_config --cflags --libs 2> /dev/null` -I/usr/include/GL $TMPC -lXext -lGL 2> /dev/null
17+if $cc $ARCH_CFLAGS -o $TMPE `$sdl_config --cflags --libs 2> /dev/null` -I${CROSS_SYS_ROOT}/usr/include/GL $TMPC -lXext -lGL 2> /dev/null
18 then
19 opengl="yes"
20 else
21@@ -1450,7 +1450,7 @@
22 then
23 echo "#define CONFIG_OPENGL 1" >> $config_h
24 echo "CONFIG_OPENGL=yes" >> $config_mak
25- echo "SDL_CFLAGS+=-I/usr/include/GL" >> $config_mak
26+ echo "SDL_CFLAGS+=-I${CROSS_SYS_ROOT}/usr/include/GL" >> $config_mak
27 echo "SDL_LIBS+=-lXext" >> $config_mak
28 echo "SDL_LIBS+=-lGL" >> $config_mak
29 fi
diff --git a/recipes-extended/xen/files/xend-config.sxp b/recipes-extended/xen/files/xend-config.sxp
new file mode 100644
index 00000000..096bb555
--- /dev/null
+++ b/recipes-extended/xen/files/xend-config.sxp
@@ -0,0 +1,304 @@
1# -*- sh -*-
2
3#
4# Xend configuration file.
5#
6
7# This example configuration is appropriate for an installation that
8# utilizes a bridged network configuration. Access to xend via http
9# is disabled.
10
11# Commented out entries show the default for that entry, unless otherwise
12# specified.
13
14#(logfile /var/log/xen/xend.log)
15#(loglevel DEBUG)
16
17# Uncomment the line below. Set the value to flask, acm, or dummy to
18# select a security module.
19
20#(xsm_module_name dummy)
21
22# The Xen-API server configuration.
23#
24# This value configures the ports, interfaces, and access controls for the
25# Xen-API server. Each entry in the list starts with either unix, a port
26# number, or an address:port pair. If this is "unix", then a UDP socket is
27# opened, and this entry applies to that. If it is a port, then Xend will
28# listen on all interfaces on that TCP port, and if it is an address:port
29# pair, then Xend will listen on the specified port, using the interface with
30# the specified address.
31#
32# The subsequent string configures the user-based access control for the
33# listener in question. This can be one of "none" or "pam", indicating either
34# that users should be allowed access unconditionally, or that the local
35# Pluggable Authentication Modules configuration should be used. If this
36# string is missing or empty, then "pam" is used.
37#
38# The final string gives the host-based access control for that listener. If
39# this is missing or empty, then all connections are accepted. Otherwise,
40# this should be a space-separated sequence of regular expressions; any host
41# with a fully-qualified domain name or an IP address that matches one of
42# these regular expressions will be accepted.
43#
44# Example: listen on TCP port 9363 on all interfaces, accepting connections
45# only from machines in example.com or localhost, and allow access through
46# the unix domain socket unconditionally:
47#
48# (xen-api-server ((9363 pam '^localhost$ example\\.com$')
49# (unix none)))
50#
51# Optionally, the TCP Xen-API server can use SSL by specifying the private
52# key and certificate location:
53#
54# (9367 pam '' xen-api.key xen-api.crt)
55#
56# Default:
57# (xen-api-server ((unix)))
58
59
60(xend-http-server yes)
61(xend-unix-server yes)
62(xend-tcp-xmlrpc-server yes)
63(xend-unix-xmlrpc-server yes)
64#(xend-relocation-server no)
65(xend-relocation-server yes)
66#(xend-relocation-ssl-server no)
67(xend-udev-event-server yes)
68
69#(xend-unix-path /var/lib/xend/xend-socket)
70
71
72# Address and port xend should use for the legacy TCP XMLRPC interface,
73# if xend-tcp-xmlrpc-server is set.
74#(xend-tcp-xmlrpc-server-address 'localhost')
75#(xend-tcp-xmlrpc-server-port 8006)
76
77# SSL key and certificate to use for the legacy TCP XMLRPC interface.
78# Setting these will mean that this port serves only SSL connections as
79# opposed to plaintext ones.
80#(xend-tcp-xmlrpc-server-ssl-key-file xmlrpc.key)
81#(xend-tcp-xmlrpc-server-ssl-cert-file xmlrpc.crt)
82
83
84# Port xend should use for the HTTP interface, if xend-http-server is set.
85#(xend-port 8000)
86
87# Port xend should use for the relocation interface, if xend-relocation-server
88# is set.
89#(xend-relocation-port 8002)
90
91# Port xend should use for the ssl relocation interface, if
92# xend-relocation-ssl-server is set.
93#(xend-relocation-ssl-port 8003)
94
95# SSL key and certificate to use for the ssl relocation interface, if
96# xend-relocation-ssl-server is set.
97#(xend-relocation-server-ssl-key-file xmlrpc.key)
98#(xend-relocation-server-ssl-cert-file xmlrpc.crt)
99
100# Whether to use ssl as default when relocating.
101#(xend-relocation-ssl no)
102
103# Address xend should listen on for HTTP connections, if xend-http-server is
104# set.
105# Specifying 'localhost' prevents remote connections.
106# Specifying the empty string '' (the default) allows all connections.
107#(xend-address '')
108#(xend-address localhost)
109
110# Address xend should listen on for relocation-socket connections, if
111# xend-relocation-server is set.
112# Meaning and default as for xend-address above.
113# Also, interface name is allowed (e.g. eth0) there to get the
114# relocation address to be bound on.
115#(xend-relocation-address '')
116
117# The hosts allowed to talk to the relocation port. If this is empty (the
118# default), then all connections are allowed (assuming that the connection
119# arrives on a port and interface on which we are listening; see
120# xend-relocation-port and xend-relocation-address above). Otherwise, this
121# should be a space-separated sequence of regular expressions. Any host with
122# a fully-qualified domain name or an IP address that matches one of these
123# regular expressions will be accepted.
124#
125# For example:
126# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$')
127#
128#(xend-relocation-hosts-allow '')
129(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$')
130
131# The limit (in kilobytes) on the size of the console buffer
132#(console-limit 1024)
133
134##
135# To bridge network traffic, like this:
136#
137# dom0: ----------------- bridge -> real eth0 -> the network
138# |
139# domU: fake eth0 -> vifN.0 -+
140#
141# use
142#
143# (network-script network-bridge)
144#
145# Your default ethernet device is used as the outgoing interface, by default.
146# To use a different one (e.g. eth1) use
147#
148# (network-script 'network-bridge netdev=eth1')
149#
150# The bridge is named eth0, by default (yes, really!)
151#
152
153# It is normally much better to create the bridge yourself in
154# /etc/network/interfaces. network-bridge start does nothing if you
155# already have a bridge, and network-bridge stop does nothing if the
156# default bridge name (normally eth0) is not a bridge. See
157# bridge-utils-interfaces(5) for full information on the syntax in
158# /etc/network/interfaces, but you probably want something like this:
159# iface xenbr0 inet static
160# address [etc]
161# netmask [etc]
162# [etc]
163# bridge_ports eth0
164#
165# To have network-bridge create a differently-named bridge, use:
166# (network-script 'network-bridge bridge=<name>')
167#
168# It is possible to use the network-bridge script in more complicated
169# scenarios, such as having two outgoing interfaces, with two bridges, and
170# two fake interfaces per guest domain. To do things like this, write
171# yourself a wrapper script, and call network-bridge from it, as appropriate.
172#
173(network-script network-bridge)
174
175# The script used to control virtual interfaces. This can be overridden on a
176# per-vif basis when creating a domain or a configuring a new vif. The
177# vif-bridge script is designed for use with the network-bridge script, or
178# similar configurations.
179#
180# If you have overridden the bridge name using
181# (network-script 'network-bridge bridge=<name>') then you may wish to do the
182# same here. The bridge name can also be set when creating a domain or
183# configuring a new vif, but a value specified here would act as a default.
184#
185# If you are using only one bridge, the vif-bridge script will discover that,
186# so there is no need to specify it explicitly. The default is to use
187# the bridge which is listed first in the output from brctl.
188#
189(vif-script vif-bridge)
190
191
192## Use the following if network traffic is routed, as an alternative to the
193# settings for bridged networking given above.
194#(network-script network-route)
195#(vif-script vif-route)
196
197
198## Use the following if network traffic is routed with NAT, as an alternative
199# to the settings for bridged networking given above.
200#(network-script network-nat)
201#(vif-script vif-nat)
202
203# dom0-min-mem is the lowest permissible memory level (in MB) for dom0.
204# This is a minimum both for auto-ballooning (as enabled by
205# enable-dom0-ballooning below) and for xm mem-set when applied to dom0.
206(dom0-min-mem 196)
207
208# Whether to enable auto-ballooning of dom0 to allow domUs to be created.
209# If enable-dom0-ballooning = no, dom0 will never balloon out.
210(enable-dom0-ballooning yes)
211
212# 32-bit paravirtual domains can only consume physical
213# memory below 168GB. On systems with memory beyond that address,
214# they'll be confined to memory below 128GB.
215# Using total_available_memory (in GB) to specify the amount of memory reserved
216# in the memory pool exclusively for 32-bit paravirtual domains.
217# Additionally you should use dom0_mem = <-Value> as a parameter in
218# xen kernel to reserve the memory for 32-bit paravirtual domains, default
219# is "0" (0GB).
220(total_available_memory 0)
221
222# In SMP system, dom0 will use dom0-cpus # of CPUS
223# If dom0-cpus = 0, dom0 will take all cpus available
224(dom0-cpus 0)
225
226# Whether to enable core-dumps when domains crash.
227#(enable-dump no)
228
229# The tool used for initiating virtual TPM migration
230#(external-migration-tool '')
231
232# The interface for VNC servers to listen on. Defaults
233# to 127.0.0.1 To restore old 'listen everywhere' behaviour
234# set this to 0.0.0.0
235#(vnc-listen '127.0.0.1')
236
237# The default password for VNC console on HVM domain.
238# Empty string is no authentication.
239(vncpasswd '')
240
241# The VNC server can be told to negotiate a TLS session
242# to encryption all traffic, and provide x509 cert to
243# clients enabling them to verify server identity. The
244# GTK-VNC widget, virt-viewer, virt-manager and VeNCrypt
245# all support the VNC extension for TLS used in QEMU. The
246# TightVNC/RealVNC/UltraVNC clients do not.
247#
248# To enable this create x509 certificates / keys in the
249# directory ${XEN_CONFIG_DIR} + vnc
250#
251# ca-cert.pem - The CA certificate
252# server-cert.pem - The Server certificate signed by the CA
253# server-key.pem - The server private key
254#
255# and then uncomment this next line
256# (vnc-tls 1)
257
258# The certificate dir can be pointed elsewhere..
259#
260# (vnc-x509-cert-dir vnc)
261
262# The server can be told to request & validate an x509
263# certificate from the client. Only clients with a cert
264# signed by the trusted CA will be able to connect. This
265# is more secure the password auth alone. Passwd auth can
266# used at the same time if desired. To enable client cert
267# checking uncomment this:
268#
269# (vnc-x509-verify 1)
270
271# The default keymap to use for the VM's virtual keyboard
272# when not specififed in VM's configuration
273#(keymap 'en-us')
274
275# Script to run when the label of a resource has changed.
276#(resource-label-change-script '')
277
278# Rotation count of qemu-dm log file.
279#(qemu-dm-logrotate-count 10)
280
281# Path where persistent domain configuration is stored.
282# Default is /var/lib/xend/domains/
283#(xend-domains-path /var/lib/xend/domains)
284
285# Number of seconds xend will wait for device creation and
286# destruction
287#(device-create-timeout 100)
288#(device-destroy-timeout 100)
289
290# When assigning device to HVM guest, we use the strict check for HVM guest by
291# default. (For PV guest, we use loose check automatically if necessary.)
292# When we assign device to HVM guest, if we meet with the co-assignment
293# issues or the ACS issue, we could try changing the option to 'no' -- however,
294# we have to realize this may incur security issue and we can't make sure the
295# device assignment could really work properly even after we do this.
296#(pci-passthrough-strict-check yes)
297
298# If we have a very big scsi device configuration, start of xend is slow,
299# because xend scans all the device paths to build its internal PSCSI device
300# list. If we need only a few devices for assigning to a guest, we can reduce
301# the scan to this device. Set list list of device paths in same syntax like in
302# command lsscsi, e.g. ('16:0:0:0' '15:0')
303# (pscsi-device-mask ('*'))
304
diff --git a/recipes-extended/xen/files/xenminiinit.sh b/recipes-extended/xen/files/xenminiinit.sh
new file mode 100755
index 00000000..22d5008f
--- /dev/null
+++ b/recipes-extended/xen/files/xenminiinit.sh
@@ -0,0 +1,59 @@
1#!/bin/sh
2
3# This is currently a very raw init script for xen-minimal
4# Feel free to expand and make more useful
5
6STARTDOMAINS="rtos freedos"
7
8# Shutdown Xen domains
9for foo in $STARTDOMAINS ; do
10 xl destroy $foo
11done
12
13# Stop and Startup Xen common
14if test -f /etc/init.d/xencommons ; then
15 echo Using Xen standard init scripts
16# /etc/init.d/libvirtd stop
17# /etc/init.d/xendomains stop
18# /etc/init.d/xencommons stop
19#
20# /etc/init.d/xencommons start
21# /etc/init.d/libvirtd start
22# /etc/init.d/xendomains start
23else
24 echo Skipping Xen standard init scripts
25
26 killall xenstored
27 killall xenconsoled
28 umount /proc/xen
29
30 # Fix up device nodes
31 if pidof udevd ; then
32 echo Udev running. Skipping mdev fixups
33 else
34 rm -rf /dev/xen
35 mkdir /dev/xen
36 for foo in /dev/xen!* ; do ln -s $foo /dev/xen/`echo $foo | cut -f 2 -d '!'` ; done
37 fi
38
39 mount -t xenfs xenfs /proc/xen
40 xenstored --pid-file=/var/run/xenstored.pid
41 xenstore-write "/local/domain/0/name" "Domain-0"
42 xenconsoled --pid-file=/var/run/xenconsoled.pid
43fi
44
45# Remove the images we have
46cd /tmp
47rm -rf xen
48
49# Grab and start the VM images
50mkdir xen
51cd xen
52for foo in $STARTDOMAINS ; do
53 wget http://candidates/xen/images/$foo.zip
54 unzip $foo.zip
55 xl create $foo.cfg
56done
57
58# Fix up the Webmin server with a new admin password
59test -f /usr/libexec/webmin/changepass.pl && /usr/libexec/webmin/changepass.pl /etc/webmin admin password
diff --git a/recipes-extended/xen/xen-4.1.2/allow_disable_xend.patch b/recipes-extended/xen/xen-4.1.2/allow_disable_xend.patch
new file mode 100644
index 00000000..33187045
--- /dev/null
+++ b/recipes-extended/xen/xen-4.1.2/allow_disable_xend.patch
@@ -0,0 +1,75 @@
1--- xen-4.1.2/config/StdGNU.mk.sav 2012-03-08 12:30:26.047303578 -0700
2+++ xen-4.1.2/config/StdGNU.mk 2012-03-08 12:31:48.826696508 -0700
3@@ -56,6 +56,9 @@
4 XEN_CONFIG_DIR = $(CONFIG_DIR)/xen
5 XEN_SCRIPT_DIR = $(XEN_CONFIG_DIR)/scripts
6
7+# Allow xend to be disabled in lieu of only libxl
8+CONFIG_ENABLE_XEND ?= y
9+
10 SOCKET_LIBS =
11 CURSES_LIBS = -lncurses
12 PTHREAD_LIBS = -lpthread
13--- xen-4.1.2/tools/Makefile.sav 2012-03-08 11:25:10.177301492 -0700
14+++ xen-4.1.2/tools/Makefile 2012-03-08 12:33:48.807302767 -0700
15@@ -15,7 +15,7 @@
16 SUBDIRS-$(CONFIG_X86) += firmware
17 SUBDIRS-$(ACM_SECURITY) += security
18 SUBDIRS-y += console
19-SUBDIRS-y += xenmon
20+SUBDIRS-$(CONFIG_ENABLE_XEND) += xenmon
21 SUBDIRS-$(VTPM_TOOLS) += vtpm_manager
22 SUBDIRS-$(VTPM_TOOLS) += vtpm
23 SUBDIRS-y += xenstat
24@@ -36,17 +36,19 @@
25
26 SUBDIRS-y += xenpmd
27 SUBDIRS-y += libxl
28-SUBDIRS-y += remus
29+SUBDIRS-$(CONFIG_ENABLE_XEND) += remus
30 SUBDIRS-$(CONFIG_X86) += xenpaging
31 SUBDIRS-$(CONFIG_X86) += debugger/gdbsx
32 SUBDIRS-$(CONFIG_X86) += debugger/kdd
33
34 # These don't cross-compile
35 ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
36+ifneq ($(XEN_ENABLE_XEND),y)
37 SUBDIRS-$(PYTHON_TOOLS) += python
38 SUBDIRS-$(PYTHON_TOOLS) += pygrub
39 SUBDIRS-$(OCAML_TOOLS) += ocaml
40 endif
41+endif
42
43 # For the sake of linking, set the sys-root
44 ifneq ($(CROSS_COMPILE),)
45--- xen-4.1.2/tools/misc/Makefile.sav 2012-03-08 12:23:10.107321955 -0700
46+++ xen-4.1.2/tools/misc/Makefile 2012-03-08 12:34:54.466721729 -0700
47@@ -19,11 +19,13 @@
48 SUBDIRS-$(CONFIG_MINITERM) += miniterm
49 SUBDIRS := $(SUBDIRS-y)
50
51-INSTALL_BIN-y := xencons
52+INSTALL_BIN-y :=
53+INSTALL_BIN-$(CONFIG_ENABLE_XEND) += xencons
54 INSTALL_BIN-$(CONFIG_X86) += xen-detect
55 INSTALL_BIN := $(INSTALL_BIN-y)
56
57-INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd
58+INSTALL_SBIN-y := xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd
59+INSTALL_SBIN-$(CONFIG_ENABLE_XEND) += xm xend xsview xen-python-path xen-bugtool
60 INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash
61 INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool
62 INSTALL_SBIN := $(INSTALL_SBIN-y)
63--- xen-4.1.2/tools/hotplug/NetBSD/Makefile.sav 2012-03-08 12:54:56.247306596 -0700
64+++ xen-4.1.2/tools/hotplug/NetBSD/Makefile 2012-03-08 12:57:50.337339410 -0700
65@@ -8,7 +8,9 @@
66 XEN_SCRIPTS += vif-ip
67
68 XEN_SCRIPT_DATA =
69-XEN_RCD_PROG = rc.d/xencommons rc.d/xend rc.d/xendomains rc.d/xen-watchdog
70+XEN_RCD_PROG-y := rc.d/xencommons rc.d/xendomains rc.d/xen-watchdog
71+XEN_RCD_PROG-$(CONFIG_ENABLE_XEND) += rc.d/xend
72+XEN_RCD_PROG := $(XEN_RCD_PROG-y)
73
74 .PHONY: all
75 all:
diff --git a/recipes-extended/xen/xen-hg/ioemu-cross-gl-check.patch b/recipes-extended/xen/xen-hg/ioemu-cross-gl-check.patch
new file mode 100644
index 00000000..23497e21
--- /dev/null
+++ b/recipes-extended/xen/xen-hg/ioemu-cross-gl-check.patch
@@ -0,0 +1,29 @@
1--- git/configure.sav 2012-04-06 12:08:07.891529546 -0600
2+++ xen-unstable.hg/../git/configure 2012-04-06 12:09:39.872923477 -0600
3@@ -289,7 +289,7 @@
4 kqemu="yes"
5 fi
6 fi
7- if test -f /usr/include/sys/soundcard.h ; then
8+ if test -f ${CROSS_SYS_ROOT}/usr/include/sys/soundcard.h ; then
9 audio_drv_list="oss"
10 fi
11 audio_possible_drivers="oss sdl"
12@@ -872,7 +872,7 @@
13 #endif
14 int main( void ) { return (int) glGetString(GL_EXTENSIONS); }
15 EOF
16-if $cc $ARCH_CFLAGS -o $TMPE `$sdl_config --cflags --libs 2> /dev/null` -I/usr/include/GL $TMPC -lXext -lGL 2> /dev/null
17+if $cc $ARCH_CFLAGS -o $TMPE `$sdl_config --cflags --libs 2> /dev/null` -I${CROSS_SYS_ROOT}/usr/include/GL $TMPC -lXext -lGL 2> /dev/null
18 then
19 opengl="yes"
20 else
21@@ -1450,7 +1450,7 @@
22 then
23 echo "#define CONFIG_OPENGL 1" >> $config_h
24 echo "CONFIG_OPENGL=yes" >> $config_mak
25- echo "SDL_CFLAGS+=-I/usr/include/GL" >> $config_mak
26+ echo "SDL_CFLAGS+=-I${CROSS_SYS_ROOT}/usr/include/GL" >> $config_mak
27 echo "SDL_LIBS+=-lXext" >> $config_mak
28 echo "SDL_LIBS+=-lGL" >> $config_mak
29 fi
diff --git a/recipes-extended/xen/xen-hg/tools_qemu_xen_remove_CFLAGS.patch b/recipes-extended/xen/xen-hg/tools_qemu_xen_remove_CFLAGS.patch
new file mode 100644
index 00000000..5fd01480
--- /dev/null
+++ b/recipes-extended/xen/xen-hg/tools_qemu_xen_remove_CFLAGS.patch
@@ -0,0 +1,48 @@
1# HG changeset patch
2# User Olaf Hering <olaf@xxxxxxxxx>
3# Date 1330015545 -3600
4# Node ID 5bdbdcb03d60a7b58f41306ef39cb988100efbe4
5# Parent 56214b978466914c1b9f8adb1158a3217a823e42
6tools/qemu-xen: remove CFLAGS for qemu build
7
8Currently qemu-xen gets build with CFLAGS only if CFLAGS was already in
9the environment during make invocation. If CFLAGS is in environment then
10make will append all of the various flags specified in xen Makefiles,
11which is then passed to qemu configure. If CFLAGS is not set, then
12configure will use just "-O2 -g" because make does not export its own
13CFLAGS variable.
14
15To make qemu-xen build consistent this change removes CFLAGS from the
16environment so that only the CFLAGS from qemu configure script will be
17used. This matches what is done in kvm.rpm and qemu.rpm where for
18example RPM_OPT_FLAGS is not passes as CFLAGS. Otherwise those packages
19would not build as well.
20
21Passing makes CFLAGS to configure will lead to build errors:
22- xen Makefiles append -std=gnu99, this breaks qemu build due to a bug
23 in header file:
24fpu/softfloat-specialize.h:107: error: initializer element is not constant
25- in 32bit builds, qemus configure script will append -mcpu=i486 in an
26 odd way, which leads to unknown gcc cmdline options due to a missing
27 space
28- xen Makefiles will append -Wall which will expose all sorts of style
29 issues in the qemu code
30- in one case some of the asm() blocks will not compile with gcc 4.6 in
31 openSuSE 12.1
32
33Until upstream qemu has fixed all these issues use no extra CFLAGS to
34configure qemu-xen.
35
36Signed-off-by: Olaf Hering <olaf@xxxxxxxxx>
37
38diff -r 56214b978466 -r 5bdbdcb03d60 tools/Makefile
39--- a/tools/Makefile
40+++ b/tools/Makefile
41@@ -146,6 +146,7 @@
42 source=.; \
43 fi; \
44 cd qemu-xen-dir; \
45+ env -u CFLAGS
46 $$source/configure --enable-xen --target-list=i386-softmmu \
47 --source-path=$$source \
48 --extra-cflags="-I$(XEN_ROOT)/tools/include \
diff --git a/recipes-extended/xen/xen-python.inc b/recipes-extended/xen/xen-python.inc
new file mode 100644
index 00000000..33b518d6
--- /dev/null
+++ b/recipes-extended/xen/xen-python.inc
@@ -0,0 +1,49 @@
1XEN_DISABLE_XEND=
2
3DEPENDS += "python python-native udev"
4RDEPENDS_${PN}-python = "xen python python-lang python-re python-fcntl python-shell python-io python-threading python-stringold python-math python-crypt python-logging python-pickle python-xmlrpc python-netclient python-mime python-unixadmin python-compression python-mmap python-textutils python-resource python-terminal python-pprint python-curses"
5
6INITSCRIPT_PACKAGES += "${PN}-python"
7INITSCRIPT_NAME_${PN}-python = "xend"
8INITSCRIPT_PARAMS_${PN}-python = "defaults 64"
9
10inherit python-dir
11
12PACKAGES =+ "${PN}-python-dbg ${PN}-python"
13FILES_${PN}-python = "\
14 ${sysconfdir}/init.d/xend \
15 ${sysconfdir}/xen/xend-config.sxp \
16 ${sysconfdir}/xen/xend-pci-permissive.sxp \
17 ${sysconfdir}/xen/xend-pci-quirks.sxp \
18 ${sysconfdir}/xen/xm-config.xml \
19 ${bindir}/xentrace_format \
20 ${bindir}/xencons \
21 ${bindir}/pygrub \
22 ${bindir}/remus \
23 ${sbindir}/xen-bugtool \
24 ${sbindir}/xend \
25 ${sbindir}/xenmon.py \
26 ${sbindir}/xm \
27 ${sbindir}/xen-python-path \
28 ${libdir}/${PYTHON_DIR} \
29 /var/run/xend"
30
31FILES_${PN}-python-dbg = "\
32 ${libdir}/${PYTHON_DIR}/site-packages/.debug \
33 ${libdir}/${PYTHON_DIR}/site-packages/xen/lowlevel/.debug"
34
35#EXTRA_OECONF="ac_cv_lib_python_PyArg_ParseTuple=yes"
36autotools_do_configure() {
37 export PYTHON=${STAGING_DIR_NATIVE}/usr/bin/python
38 export PREPEND_LIB="${STAGING_LIBDIR_NATIVE} ${STAGING_LIBDIR_NATIVE}/${PYTHON_DIR}"
39 export PREPEND_INCLUDES="${STAGING_INCDIR_NATIVE} ${STAGING_INCDIR_NATIVE}/${PYTHON_DIR}"
40
41 export STAGING_INCDIR=${STAGING_INCDIR}
42 export STAGING_LIBDIR=${STAGING_LIBDIR}
43 export STAGING_DIR=${STAGING_DIR}
44 export BUILD_SYS=${BUILD_SYS}
45 export HOST_SYS=${HOST_SYS}
46
47 oe_runconf
48}
49
diff --git a/recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch b/recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch
new file mode 100644
index 00000000..8a0034f5
--- /dev/null
+++ b/recipes-extended/xen/xen-rt/rt-xen_0.3_4.0.1.patch
@@ -0,0 +1,6785 @@
1Patch constructed from ZIP posted at developer site - https://sites.google.com/site/realtimexen/download
2
3http://students.cec.wustl.edu/~sx1/RT-XEN/xen0512.zip
4
5diff -ubrN xen/xen-4.0.1/tools/libxc/Makefile xen-4.0.1/tools/libxc/Makefile
6--- xen/xen-4.0.1/tools/libxc/Makefile 2010-08-25 04:22:09.000000000 -0600
7+++ xen-4.0.1/tools/libxc/Makefile 2011-04-24 20:29:11.000000000 -0600
8@@ -17,6 +17,7 @@
9 CTRL_SRCS-y += xc_private.c
10 CTRL_SRCS-y += xc_sedf.c
11 CTRL_SRCS-y += xc_csched.c
12+CTRL_SRCS-y += xc_rt.c
13 CTRL_SRCS-y += xc_tbuf.c
14 CTRL_SRCS-y += xc_pm.c
15 CTRL_SRCS-y += xc_cpu_hotplug.c
16diff -ubrN xen/xen-4.0.1/tools/libxc/xc_rt.c xen-4.0.1/tools/libxc/xc_rt.c
17--- xen/xen-4.0.1/tools/libxc/xc_rt.c 1969-12-31 17:00:00.000000000 -0700
18+++ xen-4.0.1/tools/libxc/xc_rt.c 2011-04-24 20:52:41.000000000 -0600
19@@ -0,0 +1,49 @@
20+/****************************************************************************
21+ * (C) 2006 - Emmanuel Ackaouy - XenSource Inc.
22+ ****************************************************************************
23+ *
24+ * File: xc_rt.c
25+ * Author: Sisu Xi
26+ *
27+ * Description: XC Interface to the ds scheduler
28+ *
29+ */
30+#include "xc_private.h"
31+
32+int
33+xc_sched_rt_domain_set(
34+ int xc_handle,
35+ uint32_t domid,
36+ struct xen_domctl_sched_rt *sdom)
37+{
38+ DECLARE_DOMCTL;
39+
40+ domctl.cmd = XEN_DOMCTL_scheduler_op;
41+ domctl.domain = (domid_t) domid;
42+ domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_RT;
43+ domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
44+ domctl.u.scheduler_op.u.rt = *sdom;
45+
46+ return do_domctl(xc_handle, &domctl);
47+}
48+
49+int
50+xc_sched_rt_domain_get(
51+ int xc_handle,
52+ uint32_t domid,
53+ struct xen_domctl_sched_rt *sdom)
54+{
55+ DECLARE_DOMCTL;
56+ int err;
57+
58+ domctl.cmd = XEN_DOMCTL_scheduler_op;
59+ domctl.domain = (domid_t) domid;
60+ domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_RT;
61+ domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
62+
63+ err = do_domctl(xc_handle, &domctl);
64+ if ( err == 0 )
65+ *sdom = domctl.u.scheduler_op.u.rt;
66+
67+ return err;
68+}
69diff -ubrN xen/xen-4.0.1/tools/libxc/xenctrl.h xen-4.0.1/tools/libxc/xenctrl.h
70--- xen/xen-4.0.1/tools/libxc/xenctrl.h 2010-08-25 04:22:09.000000000 -0600
71+++ xen-4.0.1/tools/libxc/xenctrl.h 2011-04-24 15:41:12.000000000 -0600
72@@ -465,6 +465,15 @@
73 uint32_t domid,
74 struct xen_domctl_sched_credit *sdom);
75
76+// added by Sisu Xi
77+int xc_sched_rt_domain_set(int xc_handle,
78+ uint32_t domid,
79+ struct xen_domctl_sched_rt *sdom);
80+
81+int xc_sched_rt_domain_get(int xc_handle,
82+ uint32_t domid,
83+ struct xen_domctl_sched_rt *sdom);
84+
85 /**
86 * This function sends a trigger to a domain.
87 *
88diff -ubrN xen/xen-4.0.1/tools/libxl/libxl.c xen-4.0.1/tools/libxl/libxl.c
89--- xen/xen-4.0.1/tools/libxl/libxl.c 2010-08-25 04:22:09.000000000 -0600
90+++ xen-4.0.1/tools/libxl/libxl.c 2011-04-24 15:50:49.000000000 -0600
91@@ -2766,6 +2766,64 @@
92 if (rc != 0)
93 return rc;
94
95+ return 0;
96+}
97+
98+// added by Sisu Xi
99+
100+int libxl_sched_rt_domain_get(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_rt *scinfo)
101+{
102+ struct xen_domctl_sched_rt sdom;
103+ int rc;
104+
105+ rc = xc_sched_rt_domain_get(ctx->xch, domid, &sdom);
106+ if (rc != 0)
107+ return rc;
108+
109+ scinfo->budget = sdom.budget;
110+ scinfo->period = sdom.period;
111+ scinfo->level = sdom.level;
112+
113+ return 0;
114+}
115+
116+int libxl_sched_rt_domain_set(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_rt *scinfo)
117+{
118+ struct xen_domctl_sched_rt sdom;
119+ xc_domaininfo_t domaininfo;
120+ int rc;
121+
122+ rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
123+ if (rc != 1 || domaininfo.domain != domid)
124+ return rc;
125+
126+
127+ if (scinfo->budget < 1 || scinfo->budget > 65535) {
128+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
129+ "Cpu budget out of range, valid values are within range from 1 to 65535");
130+ return -1;
131+ }
132+
133+ if (scinfo->period < 1 || scinfo->period > 65535) {
134+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
135+ "Cpu period out of range, valid values are within range from 1 to 65535");
136+ return -1;
137+ }
138+
139+ if (scinfo->level < 1 || scinfo->level > 65535) {
140+ XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
141+ "Cpu level out of range, valid values are within range from 1 to 65535");
142+ return -1;
143+ }
144+
145+ sdom.budget = scinfo->budget;
146+ sdom.period = scinfo->period;
147+ sdom.level = scinfo->level;
148+
149+ rc = xc_sched_rt_domain_set(ctx->xch, domid, &sdom);
150+ if (rc != 0)
151+ return rc;
152+
153 return 0;
154 }
155
156diff -ubrN xen/xen-4.0.1/tools/libxl/libxl.h xen-4.0.1/tools/libxl/libxl.h
157--- xen/xen-4.0.1/tools/libxl/libxl.h 2010-08-25 04:22:09.000000000 -0600
158+++ xen-4.0.1/tools/libxl/libxl.h 2011-04-24 15:47:43.000000000 -0600
159@@ -499,10 +499,23 @@
160 int cap;
161 };
162
163+// added by Sisu Xi
164+struct libxl_sched_rt {
165+ int budget;
166+ int period;
167+ int level;
168+};
169+
170 int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid,
171 struct libxl_sched_credit *scinfo);
172 int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid,
173 struct libxl_sched_credit *scinfo);
174+
175+// added by Sisu Xi
176+int libxl_sched_rt_domain_get(struct libxl_ctx *ctx, uint32_t domid,
177+ struct libxl_sched_rt *scinfo);
178+int libxl_sched_rt_domain_set(struct libxl_ctx *ctx, uint32_t domid,
179+ struct libxl_sched_rt *scinfo);
180 int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid,
181 char *trigger_name, uint32_t vcpuid);
182 int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq);
183diff -ubrN xen/xen-4.0.1/tools/libxl/xl_cmdimpl.c xen-4.0.1/tools/libxl/xl_cmdimpl.c
184--- xen/xen-4.0.1/tools/libxl/xl_cmdimpl.c 2010-08-25 04:22:10.000000000 -0600
185+++ xen-4.0.1/tools/libxl/xl_cmdimpl.c 2011-04-24 15:33:20.000000000 -0600
186@@ -2989,8 +2989,7 @@
187 printf("xen_minor : %d\n", info->xen_version_minor);
188 printf("xen_extra : %s\n", info->xen_version_extra);
189 printf("xen_caps : %s\n", info->capabilities);
190- printf("xen_scheduler : %s\n",
191- sched_id == XEN_SCHEDULER_SEDF ? "sedf" : "credit");
192+ printf("xen_scheduler : %d\n", sched_id);
193 printf("xen_pagesize : %lu\n", info->pagesize);
194 printf("platform_params : virt_start=0x%lx\n", info->virt_start);
195 printf("xen_changeset : %s\n", info->changeset);
196@@ -3190,6 +3189,242 @@
197 exit(0);
198 }
199
200+
201+//added by Sisu Xi
202+static int sched_rt_domain_get(
203+ int domid, struct libxl_sched_rt *scinfo)
204+{
205+ int rc;
206+
207+ rc = libxl_sched_rt_domain_get(&ctx, domid, scinfo);
208+ if (rc)
209+ fprintf(stderr, "libxl_sched_rt_domain_get failed.\n");
210+
211+ return rc;
212+}
213+
214+static int sched_rt_domain_set(
215+ int domid, struct libxl_sched_rt *scinfo)
216+{
217+ int rc;
218+
219+ rc = libxl_sched_rt_domain_set(&ctx, domid, scinfo);
220+ if (rc)
221+ fprintf(stderr, "libxl_sched_rt_domain_set failed.\n");
222+
223+ return rc;
224+}
225+
226+static void sched_rt_domain_output(
227+ int domid, struct libxl_sched_rt *scinfo)
228+{
229+ printf("%-33s %4d %6d %4d %4d\n",
230+ libxl_domid_to_name(&ctx, domid),
231+ domid,
232+ scinfo->budget,
233+ scinfo->period,
234+ scinfo->level);
235+}
236+
237+int main_sched_rt(int argc, char **argv)
238+{
239+ struct libxl_dominfo *info;
240+ struct libxl_sched_rt scinfo;
241+ int nb_domain, i;
242+ char *dom = NULL;
243+ int budget = 25, period = 50, level = 10, opt_w = 0, opt_c = 0, opt_l = 0;
244+ int opt, rc;
245+
246+ while ((opt = getopt(argc, argv, "hd:b:p:l:")) != -1) {
247+ switch (opt) {
248+ case 'd':
249+ dom = optarg;
250+ break;
251+ case 'b':
252+ budget = strtol(optarg, NULL, 10);
253+ opt_w = 1;
254+ break;
255+ case 'p':
256+ period = strtol(optarg, NULL, 10);
257+ opt_c = 1;
258+ break;
259+ case 'l':
260+ level = strtol(optarg, NULL, 10);
261+ opt_l = 1;
262+ break;
263+ case 'h':
264+ help("sched-rt");
265+ exit(0);
266+ default:
267+ fprintf(stderr, "option `%c' not supported.\n", opt);
268+ break;
269+ }
270+ }
271+
272+ if (!dom && (opt_w || opt_c || opt_l)) {
273+ fprintf(stderr, "Must specify a domain.\n");
274+ exit(1);
275+ }
276+
277+ if (!dom) { /* list all domain's ds scheduler info */
278+ info = libxl_list_domain(&ctx, &nb_domain);
279+ if (!info) {
280+ fprintf(stderr, "libxl_domain_infolist failed.\n");
281+ exit(1);
282+ }
283+
284+ printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Budget", "Period", "Level");
285+ for (i = 0; i < nb_domain; i++) {
286+ rc = sched_rt_domain_get(info[i].domid, &scinfo);
287+ if (rc)
288+ exit(-rc);
289+ sched_rt_domain_output(info[i].domid, &scinfo);
290+ }
291+ } else {
292+ find_domain(dom);
293+
294+ rc = sched_rt_domain_get(domid, &scinfo);
295+ if (rc)
296+ exit(-rc);
297+
298+ if (!opt_w && !opt_c && !opt_l) { /* output ds scheduler info */
299+ printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Budget", "Period", "Level");
300+ sched_rt_domain_output(domid, &scinfo);
301+ } else { /* set ds scheduler paramaters */
302+ if (opt_w)
303+ scinfo.budget = budget;
304+ if (opt_c)
305+ scinfo.period = period;
306+ if (opt_l)
307+ scinfo.level = level;
308+ rc = sched_rt_domain_set(domid, &scinfo);
309+ if (rc)
310+ exit(-rc);
311+ }
312+ }
313+
314+ exit(0);
315+}
316+
317+//
318+//
319+// static int sched_ps_domain_get(
320+// int domid, struct libxl_sched_ps *scinfo)
321+// {
322+// int rc;
323+//
324+// rc = libxl_sched_ps_domain_get(&ctx, domid, scinfo);
325+// if (rc)
326+// fprintf(stderr, "libxl_sched_ps_domain_get failed.\n");
327+//
328+// return rc;
329+// }
330+//
331+// static int sched_ps_domain_set(
332+// int domid, struct libxl_sched_ps *scinfo)
333+// {
334+// int rc;
335+//
336+// rc = libxl_sched_ps_domain_set(&ctx, domid, scinfo);
337+// if (rc)
338+// fprintf(stderr, "libxl_sched_ps_domain_set failed.\n");
339+//
340+// return rc;
341+// }
342+//
343+// static void sched_ps_domain_output(
344+// int domid, struct libxl_sched_ps *scinfo)
345+// {
346+// printf("%-33s %4d %6d %4d %4d\n",
347+// libxl_domid_to_name(&ctx, domid),
348+// domid,
349+// scinfo->cost,
350+// scinfo->period,
351+// scinfo->level);
352+// }
353+//
354+// int main_sched_ps(int argc, char **argv)
355+// {
356+// struct libxl_dominfo *info;
357+// struct libxl_sched_ps scinfo;
358+// int nb_domain, i;
359+// char *dom = NULL;
360+// int cost = 25, period = 50, level = 10, opt_w = 0, opt_c = 0, opt_l = 0;
361+// int opt, rc;
362+//
363+// while ((opt = getopt(argc, argv, "hd:c:p:l:")) != -1) {
364+// switch (opt) {
365+// case 'd':
366+// dom = optarg;
367+// break;
368+// case 'c':
369+// cost = strtol(optarg, NULL, 10);
370+// opt_w = 1;
371+// break;
372+// case 'p':
373+// period = strtol(optarg, NULL, 10);
374+// opt_c = 1;
375+// break;
376+// case 'l':
377+// level = strtol(optarg, NULL, 10);
378+// opt_l = 1;
379+// break;
380+// case 'h':
381+// help("sched-ps");
382+// exit(0);
383+// default:
384+// fprintf(stderr, "option `%c' not supported.\n", opt);
385+// break;
386+// }
387+// }
388+//
389+// if (!dom && (opt_w || opt_c || opt_l)) {
390+// fprintf(stderr, "Must specify a domain.\n");
391+// exit(1);
392+// }
393+//
394+// if (!dom) { /* list all domain's ps scheduler info */
395+// info = libxl_list_domain(&ctx, &nb_domain);
396+// if (!info) {
397+// fprintf(stderr, "libxl_domain_infolist failed.\n");
398+// exit(1);
399+// }
400+//
401+// printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Cost", "Period", "Level");
402+// for (i = 0; i < nb_domain; i++) {
403+// rc = sched_ps_domain_get(info[i].domid, &scinfo);
404+// if (rc)
405+// exit(-rc);
406+// sched_ps_domain_output(info[i].domid, &scinfo);
407+// }
408+// } else {
409+// find_domain(dom);
410+//
411+// rc = sched_ps_domain_get(domid, &scinfo);
412+// if (rc)
413+// exit(-rc);
414+//
415+// if (!opt_w && !opt_c && !opt_l) { /* output ps scheduler info */
416+// printf("%-33s %4s %6s %4s %4s\n", "Name", "ID", "Cost", "Period", "Level");
417+// sched_ps_domain_output(domid, &scinfo);
418+// } else { /* set ps scheduler paramaters */
419+// if (opt_w)
420+// scinfo.cost = cost;
421+// if (opt_c)
422+// scinfo.period = period;
423+// if (opt_l)
424+// scinfo.level = level;
425+// rc = sched_ps_domain_set(domid, &scinfo);
426+// if (rc)
427+// exit(-rc);
428+// }
429+// }
430+//
431+// exit(0);
432+// }
433+
434+
435+
436 int main_domid(int argc, char **argv)
437 {
438 int opt;
439diff -ubrN xen/xen-4.0.1/tools/libxl/xl_cmdtable.c xen-4.0.1/tools/libxl/xl_cmdtable.c
440--- xen/xen-4.0.1/tools/libxl/xl_cmdtable.c 2010-08-25 04:22:10.000000000 -0600
441+++ xen-4.0.1/tools/libxl/xl_cmdtable.c 2011-04-24 15:32:54.000000000 -0600
442@@ -175,6 +175,16 @@
443 "-w WEIGHT, --weight=WEIGHT Weight (int)\n"
444 "-c CAP, --cap=CAP Cap (int)"
445 },
446+ //added by Sisu Xi
447+ { "sched-rt",
448+ &main_sched_rt,
449+ "Get/Set RT scheduler parameters",
450+ "[-d <Domain> [-b[=BUDGET]|-p[=PERIOD]|-l[=LEVEL]]]",
451+ "-d DOMAIN, --domain = DOMAIN Domain to modify\n"
452+ "-b BUDGET, --budget = BUDGET Budget (int)\n"
453+ "-p PERIOD, --period = PERIOD Period (int)\n"
454+ "-l LEVEL, --level = LEVEL Level (int)"
455+ },
456 { "domid",
457 &main_domid,
458 "Convert a domain name to domain id",
459diff -ubrN xen/xen-4.0.1/tools/libxl/xl.h xen-4.0.1/tools/libxl/xl.h
460--- xen/xen-4.0.1/tools/libxl/xl.h 2010-08-25 04:22:09.000000000 -0600
461+++ xen-4.0.1/tools/libxl/xl.h 2011-04-24 15:24:44.000000000 -0600
462@@ -49,6 +49,8 @@
463 int main_memmax(int argc, char **argv);
464 int main_memset(int argc, char **argv);
465 int main_sched_credit(int argc, char **argv);
466+//added by Sisu Xi
467+int main_sched_rt(int argc, char **argv);
468 int main_domid(int argc, char **argv);
469 int main_domname(int argc, char **argv);
470 int main_rename(int argc, char **argv);
471diff -ubrN xen/xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c
472--- xen/xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c 2010-08-25 04:22:10.000000000 -0600
473+++ xen-4.0.1/tools/python/xen/lowlevel/xc/xc.c 2011-04-24 15:42:16.000000000 -0600
474@@ -1455,6 +1455,54 @@
475 "cap", sdom.cap);
476 }
477
478+// added by Sisu Xi
479+static PyObject *pyxc_sched_rt_domain_set(XcObject *self,
480+ PyObject *args,
481+ PyObject *kwds)
482+{
483+ uint32_t domid;
484+ uint16_t budget;
485+ uint16_t period;
486+ uint16_t level;
487+ static char *kwd_list[] = { "domid", "budget", "period", "level", NULL };
488+ static char kwd_type[] = "I|HHH";
489+ struct xen_domctl_sched_rt sdom;
490+
491+ budget = 25;
492+ period = 50;
493+ level = 10;
494+ if( !PyArg_ParseTupleAndKeywords(args, kwds, kwd_type, kwd_list,
495+ &domid, &budget, &period, &level) )
496+ return NULL;
497+
498+ sdom.budget = budget;
499+ sdom.period = period;
500+ sdom.level = level;
501+
502+ if ( xc_sched_rt_domain_set(self->xc_handle, domid, &sdom) != 0 )
503+ return pyxc_error_to_exception();
504+
505+ Py_INCREF(zero);
506+ return zero;
507+}
508+
509+static PyObject *pyxc_sched_rt_domain_get(XcObject *self, PyObject *args)
510+{
511+ uint32_t domid;
512+ struct xen_domctl_sched_rt sdom;
513+
514+ if( !PyArg_ParseTuple(args, "I", &domid) )
515+ return NULL;
516+
517+ if ( xc_sched_rt_domain_get(self->xc_handle, domid, &sdom) != 0 )
518+ return pyxc_error_to_exception();
519+
520+ return Py_BuildValue("{s:H,s:H,s:H}",
521+ "budget", sdom.budget,
522+ "period", sdom.period,
523+ "level", sdom.level);
524+}
525+
526 static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args)
527 {
528 uint32_t dom;
529@@ -2010,6 +2058,26 @@
530 "Returns: [dict]\n"
531 " weight [short]: domain's scheduling weight\n"},
532
533+// added by Sisu Xi
534+ { "sched_rt_domain_set",
535+ (PyCFunction)pyxc_sched_rt_domain_set,
536+ METH_KEYWORDS, "\n"
537+ "Set the scheduling parameters for a domain when running with the\n"
538+ "SMP ds scheduler.\n"
539+ " domid [int]: domain id to set\n"
540+ " budget [short]: domain's scheduling budget\n"
541+ "Returns: [int] 0 on success; -1 on error.\n" },
542+
543+ { "sched_rt_domain_get",
544+ (PyCFunction)pyxc_sched_rt_domain_get,
545+ METH_VARARGS, "\n"
546+ "Get the scheduling parameters for a domain when running with the\n"
547+ "SMP ds scheduler.\n"
548+ " domid [int]: domain id to get\n"
549+ "Returns: [dict]\n"
550+ " budget [short]: domain's scheduling budget\n"},
551+
552+
553 { "evtchn_alloc_unbound",
554 (PyCFunction)pyxc_evtchn_alloc_unbound,
555 METH_VARARGS | METH_KEYWORDS, "\n"
556@@ -2378,7 +2446,10 @@
557 /* Expose some libxc constants to Python */
558 PyModule_AddIntConstant(m, "XEN_SCHEDULER_SEDF", XEN_SCHEDULER_SEDF);
559 PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
560-
561+ // PyModule_AddIntConstant(m, "XEN_SCHEDULER_SS", XEN_SCHEDULER_SS);
562+ // added by Sisu Xi
563+ PyModule_AddIntConstant(m, "XEN_SCHEDULER_RT", XEN_SCHEDULER_RT);
564+ // PyModule_AddIntConstant(m, "XEN_SCHEDULER_PS", XEN_SCHEDULER_PS);
565 }
566
567
568diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py
569--- xen/xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py 2010-08-25 04:22:10.000000000 -0600
570+++ xen-4.0.1/tools/python/xen/xend/server/SrvDomain.py 2011-04-24 15:43:07.000000000 -0600
571@@ -163,6 +163,22 @@
572 val = fn(req.args, {'dom': self.dom.getName()})
573 return val
574
575+# added by Sisu Xi
576+ def op_domain_sched_rt_get(self, _, req):
577+ fn = FormFn(self.xd.domain_sched_rt_get,
578+ [['dom', 'str']])
579+ val = fn(req.args, {'dom': self.dom.getName()})
580+ return val
581+
582+ def op_domain_sched_rt_set(self, _, req):
583+ fn = FormFn(self.xd.domain_sched_rt_set,
584+ [['dom', 'str'],
585+ ['budget', 'int'],
586+ ['period', 'int'],
587+ ['level', 'int']])
588+ val = fn(req.args, {'dom': self.dom.getName()})
589+ return val
590+
591 def op_maxmem_set(self, _, req):
592 return self.call(self.dom.setMemoryMaximum,
593 [['memory', 'int']],
594diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendAPI.py xen-4.0.1/tools/python/xen/xend/XendAPI.py
595--- xen/xen-4.0.1/tools/python/xen/xend/XendAPI.py 2010-08-25 04:22:10.000000000 -0600
596+++ xen-4.0.1/tools/python/xen/xend/XendAPI.py 2011-04-24 15:40:40.000000000 -0600
597@@ -1629,6 +1629,16 @@
598 cap = xeninfo.info['vcpus_params']['cap']
599 xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
600
601+# added by Sisu Xi
602+ #need to update sched params aswell
603+ elif 'budget' in xeninfo.info['vcpus_params'] \
604+ and 'period' in xeninfo.info['vcpus_params'] \
605+ and 'level' in xeninfo.info['vcpus_params']:
606+ budget = xeninfo.info['vcpus_params']['budget']
607+ period = xeninfo.info['vcpus_params']['period']
608+ level = xeninfo.info['vcpus_params']['level']
609+ xendom.domain_sched_rt_set(xeninfo.getDomid(), budget, period, level)
610+
611 def VM_set_VCPUs_number_live(self, _, vm_ref, num):
612 dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
613 dom.setVCpuCount(int(num))
614diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendConfig.py xen-4.0.1/tools/python/xen/xend/XendConfig.py
615--- xen/xen-4.0.1/tools/python/xen/xend/XendConfig.py 2010-08-25 04:22:10.000000000 -0600
616+++ xen-4.0.1/tools/python/xen/xend/XendConfig.py 2011-01-13 09:50:30.000000000 -0700
617@@ -677,6 +677,15 @@
618 int(sxp.child_value(sxp_cfg, "cpu_weight", 256))
619 cfg["vcpus_params"]["cap"] = \
620 int(sxp.child_value(sxp_cfg, "cpu_cap", 0))
621+ cfg["vcpus_params"]["budget"] = \
622+ int(sxp.child_value(sxp_cfg, "cpu_budget", 25))
623+ cfg["vcpus_params"]["cost"] = \
624+ int(sxp.child_value(sxp_cfg, "cpu_cost", 25))
625+ cfg["vcpus_params"]["period"] = \
626+ int(sxp.child_value(sxp_cfg, "cpu_period", 50))
627+ cfg["vcpus_params"]["level"] = \
628+ int(sxp.child_value(sxp_cfg, "cpu_level", 10))
629+
630
631 # Only extract options we know about.
632 extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + \
633@@ -1057,6 +1066,14 @@
634 int(self['vcpus_params'].get('weight', 256))
635 self['vcpus_params']['cap'] = \
636 int(self['vcpus_params'].get('cap', 0))
637+ self['vcpus_params']['budget'] = \
638+ int(self['vcpus_params'].get('budget', 25))
639+ self['vcpus_params']['cost'] = \
640+ int(self['vcpus_params'].get('cost', 25))
641+ self['vcpus_params']['period'] = \
642+ int(self['vcpus_params'].get('period', 50))
643+ self['vcpus_params']['level'] = \
644+ int(self['vcpus_params'].get('level', 10))
645
646 for key, val in self['vcpus_params'].items():
647 if key.startswith('cpumap'):
648@@ -1098,6 +1115,10 @@
649 if legacy_only:
650 sxpr.append(['cpu_weight', int(self['vcpus_params'].get('weight', 256))])
651 sxpr.append(['cpu_cap', int(self['vcpus_params'].get('cap', 0))])
652+ sxpr.append(['cpu_budget', int(self['vcpus_params'].get('budget', 25))])
653+ sxpr.append(['cpu_cost', int(self['vcpus_params'].get('cost', 25))])
654+ sxpr.append(['cpu_period', int(self['vcpus_params'].get('period', 50))])
655+ sxpr.append(['cpu_level', int(self['vcpus_params'].get('level', 10))])
656 else:
657 for name, typ in XENAPI_CFG_TYPES.items():
658 if name in self and self[name] not in (None, []):
659diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py
660--- xen/xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py 2010-08-25 04:22:10.000000000 -0600
661+++ xen-4.0.1/tools/python/xen/xend/XendDomainInfo.py 2011-04-24 15:38:43.000000000 -0600
662@@ -2019,6 +2019,25 @@
663 def setWeight(self, cpu_weight):
664 self.info['vcpus_params']['weight'] = cpu_weight
665
666+# added by Sisu Xi
667+ def getBudget(self):
668+ return self.info['vcpus_params']['budget']
669+
670+ def setBudget(self, cpu_budget):
671+ self.info['vcpus_params']['budget'] = cpu_budget
672+
673+ def getPeriod(self):
674+ return self.info['vcpus_params']['period']
675+
676+ def setPeriod(self, cpu_period):
677+ self.info['vcpus_params']['period'] = cpu_period
678+
679+ def getLevel(self):
680+ return self.info['vcpus_params']['level']
681+
682+ def setLevel(self, cpu_level):
683+ self.info['vcpus_params']['level'] = cpu_level
684+
685 def getRestartCount(self):
686 return self._readVm('xend/restart_count')
687
688@@ -2616,6 +2635,26 @@
689 raise VmError("Cpu cap out of range, valid range is from 0 to %s for specified number of vcpus" %
690 (self.getVCpuCount() * 100))
691
692+ # added by Sisu Xi
693+ # Check for cpu_{period|budget} validity for ds scheduler
694+ if XendNode.instance().xenschedinfo() == 'rt':
695+ period = self.getPeriod()
696+ budget = self.getBudget()
697+ level = self.getLevel()
698+
699+ assert type(budget) == int
700+ assert type(period) == int
701+ assert type(level) == int
702+
703+ if budget < 1 or budget > 65535:
704+ raise VmError("Cpu budget out of range, valid values are within range from 1 to 65535")
705+
706+ if period < 1 or period > 65535:
707+ raise VmError("Cpu period out of range, valid values are within range from 1 to 65535")
708+
709+ if level < 1 or level > 65535:
710+ raise VmError("Cpu level out of range, valid values are within range from 1 to 65535")
711+
712 # Test whether the devices can be assigned with VT-d
713 self.info.update_platform_pci()
714 pci = self.info["platform"].get("pci")
715@@ -2811,6 +2850,14 @@
716 XendDomain.instance().domain_sched_credit_set(self.getDomid(),
717 self.getWeight(),
718 self.getCap())
719+# added by Sisu Xi
720+ def _setSchedParams(self):
721+ if XendNode.instance().xenschedinfo() == 'rt':
722+ from xen.xend import XendDomain
723+ XendDomain.instance().domain_sched_rt_set(self.getDomid(),
724+ self.getBudget(),
725+ self.getPeriod(),
726+ self.getLevel())
727
728 def _initDomain(self):
729 log.debug('XendDomainInfo.initDomain: %s %s',
730@@ -3574,7 +3621,11 @@
731 if self.getDomid() is None:
732 return self.info['vcpus_params']
733
734+ if XendNode.instance().xenschedinfo() == 'credit':
735 retval = xc.sched_credit_domain_get(self.getDomid())
736+ # added by Sisu Xi
737+ elif XendNode.instance().xenschedinfo() == 'rt':
738+ retval = xc.sched_rt_domain_get(self.getDomid())
739 return retval
740 def get_power_state(self):
741 return XEN_API_VM_POWER_STATE[self._stateGet()]
742diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendDomain.py xen-4.0.1/tools/python/xen/xend/XendDomain.py
743--- xen/xen-4.0.1/tools/python/xen/xend/XendDomain.py 2010-08-25 04:22:10.000000000 -0600
744+++ xen-4.0.1/tools/python/xen/xend/XendDomain.py 2011-04-24 15:39:47.000000000 -0600
745@@ -1757,6 +1757,90 @@
746 log.exception(ex)
747 raise XendError(str(ex))
748
749+# added by Sisu Xi
750+ def domain_sched_rt_get(self, domid):
751+ """Get ds scheduler parameters for a domain.
752+
753+ @param domid: Domain ID or Name
754+ @type domid: int or string.
755+ @rtype: dict with keys 'budget' and 'period'
756+ @return: ds scheduler parameters
757+ """
758+ dominfo = self.domain_lookup_nr(domid)
759+ if not dominfo:
760+ raise XendInvalidDomain(str(domid))
761+
762+ if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
763+ try:
764+ return xc.sched_rt_domain_get(dominfo.getDomid())
765+ except Exception, ex:
766+ raise XendError(str(ex))
767+ else:
768+ return {'budget' : dominfo.getBudget(),
769+ 'period' : dominfo.getPeriod(),
770+ 'level' : dominfo.getLevel()}
771+
772+ def domain_sched_rt_set(self, domid, budget = None, period = None, level = None):
773+ """Set ds scheduler parameters for a domain.
774+
775+ @param domid: Domain ID or Name
776+ @type domid: int or string.
777+ @type budget: int
778+ @type period: int
779+ @rtype: 0
780+ """
781+ set_budget = False
782+ set_period = False
783+ set_level = False
784+ dominfo = self.domain_lookup_nr(domid)
785+ if not dominfo:
786+ raise XendInvalidDomain(str(domid))
787+ try:
788+ if budget is None:
789+ budget = int(0)
790+ elif budget < 1 or budget > 65535:
791+ raise XendError("Cpu budget out of range, valid values are "
792+ "within range from 1 to 65535")
793+ else:
794+ set_budget = True
795+
796+ if period is None:
797+ period = int(0)
798+ elif period < 1 or period > 65535:
799+ raise XendError("Cpu period out of range, valid values are "
800+ "within range from 1 to 65535")
801+ else:
802+ set_period = True
803+
804+ if level is None:
805+ level = int(0)
806+ elif level < 1 or level > 65535:
807+ raise XendError("Cpu level out of range, valid values are "
808+ "within range from 1 to 65535")
809+ else:
810+ set_level = True
811+
812+ assert type(budget) == int
813+ assert type(period) == int
814+ assert type(level) == int
815+
816+ rc = 0
817+ if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
818+ rc = xc.sched_rt_domain_set(dominfo.getDomid(), budget, period, level)
819+ if rc == 0:
820+ if set_budget:
821+ dominfo.setBudget(budget)
822+ if set_period:
823+ dominfo.setPeriod(period)
824+ if set_level:
825+ dominfo.setLevel(level)
826+ self.managed_config_save(dominfo)
827+ return rc
828+ except Exception, ex:
829+ log.exception(ex)
830+ raise XendError(str(ex))
831+
832+
833 def domain_maxmem_set(self, domid, mem):
834 """Set the memory limit for a domain.
835
836diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendNode.py xen-4.0.1/tools/python/xen/xend/XendNode.py
837--- xen/xen-4.0.1/tools/python/xen/xend/XendNode.py 2010-08-25 04:22:10.000000000 -0600
838+++ xen-4.0.1/tools/python/xen/xend/XendNode.py 2011-04-24 15:35:48.000000000 -0600
839@@ -779,6 +779,9 @@
840 return 'sedf'
841 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
842 return 'credit'
843+ # added by Sisu Xi
844+ elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RT:
845+ return 'rt'
846 else:
847 return 'unknown'
848
849@@ -981,6 +984,9 @@
850 return 'sedf'
851 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
852 return 'credit'
853+ # added by Sisu Xi
854+ elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_RT:
855+ return 'rt'
856 else:
857 return 'unknown'
858
859diff -ubrN xen/xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py
860--- xen/xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py 2010-08-25 04:22:10.000000000 -0600
861+++ xen-4.0.1/tools/python/xen/xend/XendVMMetrics.py 2011-04-24 15:35:09.000000000 -0600
862@@ -129,7 +129,10 @@
863 params_live['cpumap%i' % i] = \
864 ",".join(map(str, info['cpumap']))
865
866+ if XendNode.instance().xenschedinfo() == 'credit':
867 params_live.update(xc.sched_credit_domain_get(domid))
868+ elif XendNode.instance().xenschedinfo() == 'rt':
869+ params_live.update(xc.sched_rt_domain_get(domid))
870
871 return params_live
872 else:
873diff -ubrN xen/xen-4.0.1/tools/python/xen/xm/main.py xen-4.0.1/tools/python/xen/xm/main.py
874--- xen/xen-4.0.1/tools/python/xen/xm/main.py 2010-08-25 04:22:10.000000000 -0600
875+++ xen-4.0.1/tools/python/xen/xm/main.py 2011-04-24 15:47:00.000000000 -0600
876@@ -151,6 +151,9 @@
877 'sched-sedf' : ('<Domain> [options]', 'Get/set EDF parameters.'),
878 'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
879 'Get/set credit scheduler parameters.'),
880+ # added by Sisu Xi
881+ 'sched-rt' : ('[-d <Domain> [-b[=BUDGET]|-p[=PERIOD]|-l[=LEVEL]]]',
882+ 'Get/set ds scheduler parameters.'),
883 'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
884 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
885 'trigger' : ('<Domain> <nmi|reset|init|s3resume|power> [<VCPU>]',
886@@ -277,6 +280,13 @@
887 ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
888 ('-c CAP', '--cap=CAP', 'Cap (int)'),
889 ),
890+ # added by Sisu Xi
891+ 'sched-rt': (
892+ ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
893+ ('-b BUDGET', '--budget=BUDGET', 'Budget (int)'),
894+ ('-p PERIOD', '--period=PERIOD', 'Period (int)'),
895+ ('-l LEVEL', '--level =LEVEL', 'Level (int)'),
896+ ),
897 'list': (
898 ('-l', '--long', 'Output all VM details in SXP'),
899 ('', '--label', 'Include security labels'),
900@@ -420,6 +430,8 @@
901 scheduler_commands = [
902 "sched-credit",
903 "sched-sedf",
904+ # added by Sisu Xi
905+ "sched-rt",
906 ]
907
908 device_commands = [
909@@ -1740,6 +1752,105 @@
910 if result != 0:
911 err(str(result))
912
913+# added by Sisu Xi
914+def xm_sched_rt(args):
915+ """Get/Set options for RT Scheduler."""
916+
917+ check_sched_type('rt')
918+
919+ try:
920+ opts, params = getopt.getopt(args, "d:b:p:l:",
921+ ["domain=", "budget=", "period=", "level="])
922+ except getopt.GetoptError, opterr:
923+ err(opterr)
924+ usage('sched-rt')
925+
926+ domid = None
927+ budget = None
928+ period = None
929+ level = None
930+
931+ for o, a in opts:
932+ if o in ["-d", "--domain"]:
933+ domid = a
934+ elif o in ["-b", "--budget"]:
935+ budget = int(a)
936+ elif o in ["-p", "--period"]:
937+ period = int(a);
938+ elif o in ["-l", "--level"]:
939+ level = int(a);
940+
941+ doms = filter(lambda x : domid_match(domid, x),
942+ [parse_doms_info(dom)
943+ for dom in getDomains(None, 'all')])
944+
945+ if budget is None and period is None and level is None:
946+ if domid is not None and doms == []:
947+ err("Domain '%s' does not exist." % domid)
948+ usage('sched-rt')
949+ # print header if we aren't setting any parameters
950+ print '%-33s %4s %6s %4s %4s' % ('Name','ID','Budget','Period', 'Level')
951+
952+ for d in doms:
953+ try:
954+ if serverType == SERVER_XEN_API:
955+ info = server.xenapi.VM_metrics.get_VCPUs_params(
956+ server.xenapi.VM.get_metrics(
957+ get_single_vm(d['name'])))
958+ else:
959+ info = server.xend.domain.sched_rt_get(d['name'])
960+ except xmlrpclib.Fault:
961+ pass
962+
963+ if 'budget' not in info or 'period' not in info or 'level' not in info:
964+ # domain does not support sched-rt?
965+ info = {'budget': -1, 'period': -1, 'level': -1}
966+
967+ info['budget'] = int(info['budget'])
968+ info['period'] = int(info['period'])
969+ info['level'] = int(info['level'])
970+
971+ info['name'] = d['name']
972+ info['domid'] = str(d['domid'])
973+ print( ("%(name)-32s %(domid)5s %(budget)6d %(period)6d %(level)6d") % info)
974+ else:
975+ if domid is None:
976+ # place holder for system-wide scheduler parameters
977+ err("No domain given.")
978+ usage('sched-rt')
979+
980+ if serverType == SERVER_XEN_API:
981+ if doms[0]['domid']:
982+ server.xenapi.VM.add_to_VCPUs_params_live(
983+ get_single_vm(domid),
984+ "budget",
985+ budget)
986+ server.xenapi.VM.add_to_VCPUs_params_live(
987+ get_single_vm(domid),
988+ "period",
989+ period)
990+ server.xenapi.VM.add_to_VCPUs_params_live(
991+ get_single_vm(domid),
992+ "level",
993+ level)
994+ else:
995+ server.xenapi.VM.add_to_VCPUs_params(
996+ get_single_vm(domid),
997+ "budget",
998+ budget)
999+ server.xenapi.VM.add_to_VCPUs_params(
1000+ get_single_vm(domid),
1001+ "period",
1002+ period)
1003+ server.xenapi.VM.add_to_VCPUs_params(
1004+ get_single_vm(domid),
1005+ "level",
1006+ level)
1007+ else:
1008+ result = server.xend.domain.sched_rt_set(domid, budget, period, level)
1009+ if result != 0:
1010+ err(str(result))
1011+
1012 def xm_info(args):
1013 arg_check(args, "info", 0, 1)
1014
1015@@ -3492,6 +3603,8 @@
1016 # scheduler
1017 "sched-sedf": xm_sched_sedf,
1018 "sched-credit": xm_sched_credit,
1019+ # added by Sisu Xi
1020+ "sched-rt": xm_sched_rt,
1021 # block
1022 "block-attach": xm_block_attach,
1023 "block-detach": xm_block_detach,
1024diff -ubrN xen/xen-4.0.1/xen/arch/ia64/xen/domain.c xen-4.0.1/xen/arch/ia64/xen/domain.c
1025--- xen/xen-4.0.1/xen/arch/ia64/xen/domain.c 2010-08-25 04:22:11.000000000 -0600
1026+++ xen-4.0.1/xen/arch/ia64/xen/domain.c 2011-01-18 01:03:45.000000000 -0700
1027@@ -228,7 +228,7 @@
1028 flush_vtlb_for_context_switch(prev, current);
1029 }
1030
1031-void context_switch(struct vcpu *prev, struct vcpu *next)
1032+void context_switch(int flag, struct vcpu *prev, struct vcpu *next)
1033 {
1034 uint64_t spsr;
1035
1036@@ -307,6 +307,9 @@
1037
1038 flush_vtlb_for_context_switch(prev, current);
1039 flush_cache_for_context_switch(current);
1040+ if (flag == 1) {
1041+ printk("%13lu ia64\n", NOW());
1042+ }
1043 context_saved(prev);
1044 }
1045
1046diff -ubrN xen/xen-4.0.1/xen/arch/x86/domain.c xen-4.0.1/xen/arch/x86/domain.c
1047--- xen/xen-4.0.1/xen/arch/x86/domain.c 2010-08-25 04:22:11.000000000 -0600
1048+++ xen-4.0.1/xen/arch/x86/domain.c 2011-01-18 01:13:02.000000000 -0700
1049@@ -1421,7 +1421,7 @@
1050 }
1051
1052
1053-void context_switch(struct vcpu *prev, struct vcpu *next)
1054+void context_switch(int flag, struct vcpu *prev, struct vcpu *next)
1055 {
1056 unsigned int cpu = smp_processor_id();
1057 cpumask_t dirty_mask = next->vcpu_dirty_cpumask;
1058@@ -1482,6 +1482,10 @@
1059 if (prev != next)
1060 update_runstate_area(next);
1061
1062+ if (flag == 1) {
1063+ printk("%13lu\n", NOW());
1064+ }
1065+
1066 schedule_tail(next);
1067 BUG();
1068 }
1069diff -ubrN xen/xen-4.0.1/xen/common/Makefile xen-4.0.1/xen/common/Makefile
1070--- xen/xen-4.0.1/xen/common/Makefile 2010-08-25 04:22:12.000000000 -0600
1071+++ xen-4.0.1/xen/common/Makefile 2011-04-25 14:44:37.000000000 -0600
1072@@ -14,6 +14,11 @@
1073 obj-y += rangeset.o
1074 obj-y += sched_credit.o
1075 obj-y += sched_sedf.o
1076+obj-y += sched_rt_wcps.o
1077+obj-y += sched_rt_periodic.o
1078+obj-y += sched_rt_ssps.o
1079+obj-y += sched_rt.o
1080+obj-y += sched_rt_deferrable.o
1081 obj-y += schedule.o
1082 obj-y += shutdown.o
1083 obj-y += softirq.o
1084diff -ubrN xen/xen-4.0.1/xen/common/sched_credit.c xen-4.0.1/xen/common/sched_credit.c
1085--- xen/xen-4.0.1/xen/common/sched_credit.c 2010-08-25 04:22:12.000000000 -0600
1086+++ xen-4.0.1/xen/common/sched_credit.c 2011-04-09 22:29:29.000000000 -0600
1087@@ -710,6 +710,9 @@
1088 sdom->cap = op->u.credit.cap;
1089
1090 spin_unlock_irqrestore(&csched_priv.lock, flags);
1091+ if ( d->domain_id == 0) {
1092+ return 1;
1093+ }
1094 }
1095
1096 return 0;
1097diff -ubrN xen/xen-4.0.1/xen/common/sched_ds_ecrts11.c xen-4.0.1/xen/common/sched_ds_ecrts11.c
1098--- xen/xen-4.0.1/xen/common/sched_ds_ecrts11.c 1969-12-31 17:00:00.000000000 -0700
1099+++ xen-4.0.1/xen/common/sched_ds_ecrts11.c 2011-01-22 13:05:56.000000000 -0700
1100@@ -0,0 +1,927 @@
1101+/******************************************************************************
1102+ * Periodic / Polling / Deferrable Server scheduler for xen
1103+ *
1104+ * by Sisu Xi (C) 2010 Washington University in St. Louis
1105+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
1106+ ******************************************************************************/
1107+
1108+#include <xen/config.h>
1109+#include <xen/init.h>
1110+#include <xen/lib.h>
1111+#include <xen/sched.h>
1112+#include <xen/domain.h>
1113+#include <xen/delay.h>
1114+#include <xen/event.h>
1115+#include <xen/time.h>
1116+#include <xen/perfc.h>
1117+#include <xen/sched-if.h>
1118+#include <xen/softirq.h>
1119+#include <asm/atomic.h>
1120+#include <xen/errno.h>
1121+#include <xen/keyhandler.h>
1122+
1123+#define DS_DOM(_dom) ((struct ds_dom *) (_dom)->sched_priv)
1124+#define DS_PCPU(_c) ((struct ds_pcpu *)per_cpu(schedule_data, _c).sched_priv)
1125+#define DS_VCPU(_vcpu) ((struct ds_vcpu *) (_vcpu)->sched_priv)
1126+#define RUNQ(_cpu) (&(DS_PCPU(_cpu)->runq))
1127+#define RDYQ(_cpu) (&(DS_PCPU(_cpu)->rdyq))
1128+#define DS_CUR(_cpu) DS_VCPU(per_cpu(schedule_data, _cpu).curr)
1129+#define BUDGET(_b) (MILLISECS(_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
1130+
1131+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
1132+
1133+#define DS_DOM_0_PERIOD 100
1134+#define DS_IDLE_PERIOD 200
1135+
1136+#define DS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
1137+#define DS_DOM_PERIOD 50
1138+
1139+//used for replenishment
1140+struct rep_elem {
1141+ s_time_t re_time;
1142+ struct ds_vcpu *dvc;
1143+};
1144+
1145+//physical cpu
1146+struct ds_pcpu {
1147+ struct list_head runq; // runQ on the pcpu, organized by linked list
1148+ struct list_head rdyq;
1149+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
1150+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
1151+ int rep_capacity; // upper limit
1152+ struct timer ticker; // for preemptive use, tick every budget
1153+};
1154+
1155+//virtual cpu
1156+struct ds_vcpu {
1157+ struct list_head runq_elem;
1158+ struct list_head rdyq_elem;
1159+ struct ds_dom *ddom;
1160+ struct vcpu *vcpu;
1161+
1162+ uint16_t budget;
1163+ uint16_t period;
1164+ uint16_t level;
1165+
1166+ uint16_t cur_budget;
1167+ s_time_t last_start_time; // used for burn_budget
1168+ int flag;
1169+};
1170+
1171+//domain
1172+struct ds_dom {
1173+ struct domain *dom;
1174+ uint16_t budget;
1175+ uint16_t period;
1176+ uint16_t level;
1177+};
1178+
1179+//global variable, records the number of cpus
1180+struct ds_private {
1181+ spinlock_t lock; // used for init
1182+ uint32_t ncpus; //number of physical cpus
1183+ int polling; // polling server or deferrable server?
1184+ int periodic;
1185+};
1186+static struct ds_private ds_priv;
1187+/*
1188+//used for record, overhead measurement
1189+#define RECORD 11000 // record 10s
1190+struct record_elem{
1191+ s_time_t dur;
1192+
1193+ int curr;
1194+ int next;
1195+ s_time_t enter; // enter schedule time
1196+ s_time_t leave; // leave schedule time
1197+
1198+};
1199+*/
1200+struct timer ds_start_timer; // would start after 10s, used only once
1201+int ds_start_flag = 0; // start to record or not
1202+int ds_wake = 0;
1203+/*
1204+int ds_idx = 0; //ds_idx to record
1205+int ds_idx_tick = 0;
1206+int ds_wake = 0;
1207+int ds_sleep = 0;
1208+struct record_elem ds_res[RECORD]; // domain_id, time in ms;
1209+struct record_elem ds_res_tick[RECORD];
1210+//finish for the record
1211+*/
1212+static void ds_tick(void *_cpu);
1213+
1214+//dump the repq
1215+static void
1216+ds_dump_repq(int cpu) {
1217+ int loop = 0;
1218+ struct ds_pcpu *ppc = DS_PCPU(cpu);
1219+
1220+ printk("\n# into %s on cpu %d, now is %lu, size: %d, the repQ is :\n", __func__, cpu, NOW(), ppc->rep_size);
1221+ for (loop = 0; loop < ppc->rep_size; loop++) {
1222+ printk("\t[%d. %d]: %d @ %lu\n",
1223+ ppc->repq[loop].dvc->vcpu->domain->domain_id,
1224+ ppc->repq[loop].dvc->vcpu->vcpu_id,
1225+ ppc->repq[loop].dvc->period,
1226+ ppc->repq[loop].re_time);
1227+ }
1228+}
1229+
1230+//dump the virtual cpu
1231+static void
1232+ds_dump_vcpu(struct ds_vcpu *dvc) {
1233+ printk("\t[%i, %i], (%i, %i), cpu: %i, cur_budget: %i, level: %d\n",
1234+ dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id, dvc->budget, dvc->period, dvc->vcpu->processor,
1235+ dvc->cur_budget, dvc->level);
1236+}
1237+
1238+//inlined code
1239+static inline struct ds_vcpu *
1240+__runq_elem(struct list_head *elem) {
1241+ return list_entry(elem, struct ds_vcpu, runq_elem);
1242+}
1243+
1244+//inlined code
1245+static inline struct ds_vcpu *
1246+__rdyq_elem(struct list_head *elem) {
1247+ return list_entry(elem, struct ds_vcpu, rdyq_elem);
1248+}
1249+
1250+//dump the physical cpu
1251+static void
1252+ds_dump_pcpu(int cpu) {
1253+ struct list_head *iter;
1254+ struct ds_pcpu *ppc = DS_PCPU(cpu);
1255+ struct list_head *runq = &ppc->runq;
1256+ struct list_head *rdyq = &ppc->rdyq;
1257+ struct ds_vcpu *dvc = DS_CUR(cpu);
1258+ int loop = 0;
1259+
1260+ printk("\n# into %s, on cpu: %d, now is: %lu\n", __func__, cpu, NOW());
1261+
1262+ if (dvc) {
1263+ printk("\trun: ");
1264+ ds_dump_vcpu(dvc);
1265+ }
1266+
1267+ printk("runq:\n");
1268+ list_for_each(iter, runq) {
1269+ dvc = __runq_elem(iter);
1270+ if (dvc) {
1271+ printk("\t%3d: ", ++loop);
1272+ ds_dump_vcpu(dvc);
1273+ }
1274+ }
1275+
1276+ printk("rdyq:\n");
1277+ list_for_each(iter, rdyq) {
1278+ dvc = __rdyq_elem(iter);
1279+ if (dvc) {
1280+ printk("\t%3d: ", ++loop);
1281+ ds_dump_vcpu(dvc);
1282+ }
1283+ }
1284+
1285+
1286+ ds_dump_repq(cpu);
1287+}
1288+/*
1289+//dump the record out.
1290+static void
1291+ds_dump_record(void) {
1292+ int i;
1293+
1294+ ds_start_flag = 0;
1295+
1296+ printk("For Schedule Function\n");
1297+
1298+ for (i = 1; i < ds_idx; i++) {
1299+ printk("%13lu\n", ds_res[i].dur);
1300+ }
1301+
1302+ printk("\n\nFor tick function\n");
1303+ for (i = 1; i < ds_idx_tick; i++) {
1304+ printk("%13lu\n", ds_res_tick[i].dur);
1305+ }
1306+
1307+ for (i = 0; i < RECORD; i++) {
1308+ ds_res[i].dur = 0;
1309+ ds_res_tick[i].dur = 0;
1310+ }
1311+
1312+ ds_wake = 0;
1313+ ds_sleep = 0;
1314+ ds_idx_tick = 0;
1315+ ds_idx = 0;
1316+}
1317+*/
1318+// the current vcpu is on runQ?
1319+static inline int
1320+__vcpu_on_runq(struct ds_vcpu *dvc) {
1321+ return !list_empty(&dvc->runq_elem);
1322+}
1323+
1324+// the current vcpu is on runQ?
1325+static inline int
1326+__vcpu_on_rdyq(struct ds_vcpu *dvc) {
1327+ return !list_empty(&dvc->rdyq_elem);
1328+}
1329+
1330+//pick the first vcpu whose budget is >0 from the runq
1331+static inline struct ds_vcpu *
1332+__runq_pick(unsigned int cpu) {
1333+ struct list_head * runq = RUNQ(cpu);
1334+ struct list_head * iter;
1335+
1336+ list_for_each(iter, runq) {
1337+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
1338+ if (iter_dvc->cur_budget > 0) {
1339+ return iter_dvc;
1340+ }
1341+ }
1342+
1343+ BUG_ON(1);
1344+ return NULL;
1345+}
1346+
1347+//insert into the runq, followed a FIFO way. sorted by period
1348+static inline void
1349+__runq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
1350+ struct list_head * runq = RUNQ(cpu);
1351+ struct list_head * iter;
1352+
1353+ BUG_ON(__vcpu_on_runq(dvc));
1354+ BUG_ON(cpu != dvc->vcpu->processor);
1355+
1356+ list_for_each(iter, runq) {
1357+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
1358+ if (dvc->level <= iter_dvc->level) {
1359+ break;
1360+ }
1361+ }
1362+
1363+ list_add_tail(&dvc->runq_elem, iter);
1364+}
1365+
1366+//insert into the runq, followed a FIFO way. sorted by period
1367+static inline void
1368+__rdyq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
1369+ struct list_head * rdyq = RDYQ(cpu);
1370+ struct list_head * iter;
1371+
1372+ BUG_ON(__vcpu_on_rdyq(dvc));
1373+ BUG_ON(cpu != dvc->vcpu->processor);
1374+
1375+ list_for_each(iter, rdyq) {
1376+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
1377+ if (dvc->level <= iter_dvc->level) {
1378+ break;
1379+ }
1380+ }
1381+
1382+ list_add_tail(&dvc->rdyq_elem, iter);
1383+}
1384+
1385+//remove it from runQ
1386+static inline void
1387+__runq_remove(struct ds_vcpu *dvc) {
1388+ BUG_ON(!__vcpu_on_runq(dvc));
1389+ list_del_init(&dvc->runq_elem);
1390+}
1391+
1392+//remove it from runQ
1393+static inline void
1394+__rdyq_remove(struct ds_vcpu *dvc) {
1395+ BUG_ON(!__vcpu_on_rdyq(dvc));
1396+ list_del_init(&dvc->rdyq_elem);
1397+}
1398+
1399+//used for the heap, repQ
1400+static inline int
1401+ds_rep_parent(int childIdx) {
1402+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
1403+}
1404+
1405+//insert into the repQ
1406+static inline void
1407+ds_repq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
1408+ struct ds_pcpu * ppc = DS_PCPU(cpu);
1409+ int childIdx, parentIdx;
1410+
1411+ if (ppc->rep_size == ppc->rep_capacity) {
1412+ printk("\n# into %s, repQ full!!\n", __func__);
1413+ BUG_ON(1);
1414+ }
1415+
1416+ childIdx = ppc->rep_size;
1417+ parentIdx = ds_rep_parent(childIdx);
1418+
1419+ while (childIdx > 0 && (NOW() + dvc->period*BUDGET(1)) < ppc->repq[parentIdx].re_time) {
1420+ ppc->repq[childIdx] = ppc->repq[parentIdx];
1421+ childIdx = parentIdx;
1422+ parentIdx = ds_rep_parent(childIdx);
1423+ }
1424+
1425+ ppc->repq[childIdx].re_time = NOW() + dvc->period*BUDGET(1);
1426+ ppc->repq[childIdx].dvc = dvc;
1427+ ppc->rep_size++;
1428+/*
1429+ printk("\t add a repl. now: %lu, cpu: %d, re_time: %lu, amount: %d, for cpu [%d, %d]\n",
1430+ NOW(), cpu, dvc->next_time, amount, dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id);
1431+ ds_dump_vcpu(dvc);
1432+*/
1433+}
1434+
1435+//remove from the repQ
1436+static inline void
1437+ds_repq_remove(unsigned int cpu) {
1438+ struct ds_pcpu * ppc = DS_PCPU(cpu);
1439+ int childIdx = 1;
1440+ int rightChildIdx;
1441+ int rootIdx = 0;
1442+ struct rep_elem temp;
1443+
1444+ BUG_ON(ppc->rep_size <= 0);
1445+
1446+ ppc->repq[0] = ppc->repq[ppc->rep_size - 1];
1447+ ppc->rep_size--;
1448+
1449+ temp = ppc->repq[0];
1450+
1451+ while (childIdx < ppc->rep_size) {
1452+ rightChildIdx = childIdx + 1;
1453+ if (rightChildIdx < ppc->rep_size && ppc->repq[rightChildIdx].re_time < ppc->repq[childIdx].re_time) {
1454+ childIdx = rightChildIdx;
1455+ }
1456+ if (ppc->repq[childIdx].re_time < temp.re_time) {
1457+ ppc->repq[rootIdx] = ppc->repq[childIdx];
1458+ rootIdx = childIdx;
1459+ childIdx = 2 * rootIdx + 1;
1460+ } else {
1461+ break;
1462+ }
1463+ }
1464+ ppc->repq[rootIdx] = temp;
1465+}
1466+
1467+//dump dump function
1468+static void
1469+ds_dump(void) {
1470+ printk("# into %s. Did Nothing\n", __func__);
1471+}
1472+
1473+//burn the scurr budget
1474+static void
1475+burn_budgets(struct ds_vcpu *dvc, s_time_t now) {
1476+ s_time_t delta;
1477+ unsigned int consume;
1478+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
1479+ struct list_head * iter;
1480+
1481+ BUG_ON(dvc != DS_CUR(dvc->vcpu->processor));
1482+
1483+ if (dvc->last_start_time == 0) {
1484+ dvc->last_start_time = now;
1485+ return;
1486+ }
1487+
1488+ delta = now - dvc->last_start_time;
1489+ BUG_ON(delta <= 0);
1490+
1491+ consume = ( delta/BUDGET(1) );
1492+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
1493+ if (consume > dvc->cur_budget) {
1494+ //printk("\n# into %s, consumed more than cur budget!\n", __func__);
1495+ consume = dvc->cur_budget;
1496+ }
1497+
1498+ dvc->cur_budget -= consume;
1499+
1500+ if (ds_priv.periodic == 1) {
1501+ list_for_each(iter, rdyq) {
1502+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
1503+ //rdyQ has higher priority
1504+ if (dvc->level > iter_dvc->level) {
1505+ iter_dvc->cur_budget -= consume;
1506+ if (iter_dvc->cur_budget < 0) {
1507+ iter_dvc->cur_budget = 0;
1508+ }
1509+ }
1510+ }
1511+ }
1512+}
1513+
1514+//init the physical cpu
1515+static int
1516+ds_pcpu_init(int cpu) {
1517+ struct ds_pcpu *ppc;
1518+ unsigned long flags;
1519+
1520+ /* Allocate per-PCPU info */
1521+ ppc = xmalloc(struct ds_pcpu);
1522+ if (ppc == NULL)
1523+ return -1;
1524+ memset(ppc, 0, sizeof (*ppc));
1525+
1526+ spin_lock_irqsave(&ds_priv.lock, flags);
1527+
1528+ if (ds_priv.ncpus < cpu)
1529+ ds_priv.ncpus = cpu + 1;
1530+
1531+ init_timer(&ppc->ticker, ds_tick, (void *) (unsigned long) cpu, cpu);
1532+ INIT_LIST_HEAD(&ppc->runq);
1533+ INIT_LIST_HEAD(&ppc->rdyq);
1534+ per_cpu(schedule_data, cpu).sched_priv = ppc;
1535+
1536+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
1537+
1538+ ppc->rep_capacity = REPQ_CAPACITY;
1539+ ppc->repq = xmalloc_array(struct rep_elem, ppc->rep_capacity);
1540+ BUG_ON(ppc->repq == NULL);
1541+ ppc->rep_size = 0;
1542+
1543+ spin_unlock_irqrestore(&ds_priv.lock, flags);
1544+
1545+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
1546+
1547+ return 0;
1548+}
1549+
1550+//check the vcpu
1551+static inline void
1552+__ds_vcpu_check(struct vcpu *vc) {
1553+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1554+ struct ds_dom * const ddom = dvc->ddom;
1555+
1556+ BUG_ON(dvc->vcpu != vc);
1557+ BUG_ON(ddom != DS_DOM(vc->domain));
1558+ if (ddom) {
1559+ BUG_ON(is_idle_vcpu(vc));
1560+ BUG_ON(ddom->dom != vc->domain);
1561+ } else {
1562+ BUG_ON(!is_idle_vcpu(vc));
1563+ }
1564+}
1565+#define DS_VCPU_CHECK(_vc) (__ds_vcpu_check(_vc))
1566+
1567+//pick a cpu to run, used to migrate from different cpus
1568+static int
1569+ds_cpu_pick(struct vcpu *vc) {
1570+ cpumask_t cpus;
1571+ int cpu;
1572+
1573+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
1574+
1575+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
1576+ return cycle_cpu(vc->processor, cpus);
1577+ }
1578+
1579+ cpu = cpu_isset(vc->processor, cpus)
1580+ ? vc->processor
1581+ : cycle_cpu(vc->processor, cpus);
1582+
1583+ return cpu;
1584+}
1585+
1586+//check the current repQ to see if a repl needs to happen
1587+static int
1588+check_cpu_for_repl(int cpu) {
1589+ struct ds_pcpu * ppc = DS_PCPU(cpu);
1590+ int flag = 0; //used for interrupt
1591+
1592+ while((ppc->rep_size != 0) && ppc->repq[0].re_time < NOW()) {
1593+ ppc->repq[0].dvc->cur_budget = ppc->repq[0].dvc->budget;
1594+ if (flag == 0 && ppc->repq[0].dvc->level < DS_CUR(cpu)->level) {
1595+ flag = 1; // need interrupt
1596+ }
1597+ ds_repq_insert(ppc->repq[0].dvc->vcpu->processor, ppc->repq[0].dvc);
1598+ ds_repq_remove(cpu);
1599+ }
1600+
1601+ return flag;
1602+}
1603+
1604+//init the virtual cpu
1605+static int
1606+ds_vcpu_init(struct vcpu *vc) {
1607+ struct domain * const dom = vc->domain;
1608+ struct ds_dom *ddom = DS_DOM(dom);
1609+ struct ds_vcpu *dvc;
1610+
1611+ /* Allocate per-VCPU info */
1612+ dvc = xmalloc(struct ds_vcpu);
1613+ if (dvc == NULL) {
1614+ return -1;
1615+ }
1616+ memset(dvc, 0, sizeof (*dvc));
1617+
1618+ INIT_LIST_HEAD(&dvc->runq_elem);
1619+ INIT_LIST_HEAD(&dvc->rdyq_elem);
1620+ dvc->ddom = ddom;
1621+ dvc->vcpu = vc;
1622+ dvc->budget = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->budget;
1623+ dvc->period = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->period;
1624+ dvc->level = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->level;
1625+ dvc->cur_budget = dvc->budget;
1626+
1627+ dvc->last_start_time = 0;
1628+ dvc->flag = 0;
1629+ vc->sched_priv = dvc;
1630+
1631+ /* Allocate per-PCPU info */
1632+ if (unlikely(!DS_PCPU(vc->processor))) {
1633+ if (ds_pcpu_init(vc->processor) != 0)
1634+ return -1;
1635+ }
1636+
1637+ DS_VCPU_CHECK(vc);
1638+
1639+ printk("\n# into %s, vcpu init: ", __func__);
1640+ ds_dump_vcpu(dvc);
1641+
1642+ return 0;
1643+}
1644+
1645+//destory the vcpu
1646+static void
1647+ds_vcpu_destroy(struct vcpu *vc) {
1648+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1649+ struct ds_dom * const ddom = dvc->ddom;
1650+
1651+ printk("\n# into %s, vcpu destroy: ", __func__);
1652+ ds_dump_vcpu(dvc);
1653+
1654+ BUG_ON(ddom == NULL);
1655+ BUG_ON(!list_empty(&dvc->runq_elem));
1656+
1657+ xfree(dvc);
1658+}
1659+
1660+//sleep the vcpu
1661+static void
1662+ds_vcpu_sleep(struct vcpu *vc) {
1663+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1664+
1665+ BUG_ON(is_idle_vcpu(vc));
1666+
1667+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
1668+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
1669+ } else if (__vcpu_on_runq(dvc)) {
1670+ //polling server
1671+ if (ds_priv.polling == 1) {
1672+ dvc->cur_budget = 0;
1673+ }
1674+ __runq_remove(dvc);
1675+ } else if (__vcpu_on_rdyq(dvc)) {
1676+ __rdyq_remove(dvc);
1677+ }
1678+}
1679+
1680+//wake up the vcpu, insert it into runq, raise a softirq
1681+static void
1682+ds_vcpu_wake(struct vcpu *vc) {
1683+ struct ds_vcpu * const dvc = DS_VCPU(vc);
1684+ const unsigned int cpu = vc->processor;
1685+
1686+ BUG_ON(is_idle_vcpu(vc));
1687+
1688+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
1689+ //printk("\n# why wake up running? migration?\n");
1690+ return;
1691+ }
1692+ if (unlikely(__vcpu_on_runq(dvc))) {
1693+ //printk("\n# why wake up on runq ones? migration?\n");
1694+ return;
1695+ }
1696+
1697+/*
1698+ if (smp_processor_id() == 1) {
1699+ printk("%s, domain %d, now %lu\n", __func__, vc->domain->domain_id, NOW()/1000000);
1700+ }
1701+*/
1702+
1703+ if (__vcpu_on_rdyq(dvc)) {
1704+ __rdyq_remove(dvc);
1705+ }
1706+
1707+ __runq_insert(cpu, dvc);
1708+ if (dvc->level < DS_CUR(cpu)->level) {
1709+ if (ds_start_flag == 1 && dvc->vcpu->processor == 1) {
1710+ ds_wake++;
1711+ }
1712+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
1713+ }
1714+}
1715+
1716+static void
1717+ds_ds_finish_timer(void * temp) {
1718+ ds_start_flag = 0;
1719+ printk("wake up %d times\n", ds_wake);
1720+ ds_wake = 0;
1721+}
1722+
1723+//used for record data, for overhead measurement
1724+static void
1725+ds_ds_start_timer(void * temp) {
1726+ ds_start_flag = 1;
1727+ init_timer(&ds_start_timer, ds_ds_finish_timer, (void *) (unsigned int) 1, 1);
1728+ set_timer(&ds_start_timer, NOW() + MILLISECS(10000));
1729+}
1730+
1731+//adjust the domain's budget & period, also used to trigger the record
1732+static int
1733+ds_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
1734+ struct ds_dom * const ddom = DS_DOM(d);
1735+ unsigned long flags;
1736+ struct ds_vcpu *dvc = DS_VCPU(d->vcpu[0]);
1737+
1738+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
1739+ op->u.ds.budget = ddom->budget;
1740+ op->u.ds.period = ddom->period;
1741+ op->u.ds.level = ddom->level;
1742+ //ds_dump_vcpu(dvc);
1743+ } else {
1744+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
1745+
1746+ spin_lock_irqsave(&ds_priv.lock, flags);
1747+ if (op->u.ds.budget != 0) {
1748+ ddom->budget = op->u.ds.budget;
1749+ dvc->budget = op->u.ds.budget;
1750+ }
1751+ if (op->u.ds.period != 0) {
1752+ ddom->period = op->u.ds.period;
1753+ dvc->period = op->u.ds.period;
1754+ }
1755+ if (op->u.ds.level != 0) {
1756+ ddom->level = op->u.ds.level;
1757+ dvc->level = op->u.ds.level;
1758+ }
1759+ dvc->cur_budget = dvc->budget;
1760+ spin_unlock_irqrestore(&ds_priv.lock, flags);
1761+
1762+ if (dvc->vcpu->domain->domain_id == 0) {
1763+ if (op->u.ds.budget == 100) {
1764+ if (ds_priv.polling == 0) {
1765+ ds_priv.polling = 1;
1766+ printk("running with the polling server!\n");
1767+ } else if (ds_priv.polling == 1) {
1768+ ds_priv.polling = 0;
1769+ printk("running with the deferrable server!\n");
1770+ }
1771+ } else if (op->u.ds.budget == 200) {
1772+ if (ds_priv.periodic == 0) {
1773+ ds_priv.periodic = 1;
1774+ ds_priv.polling = 0;
1775+ printk("running with the periodic server!\n");
1776+ } else if (ds_priv.periodic == 1) {
1777+ ds_priv.periodic = 0;
1778+ if (ds_priv.polling == 1) {
1779+ printk("running with the polling server!\n");
1780+ } else if (ds_priv.polling == 0) {
1781+ printk("running with the deferrable server!\n");
1782+ }
1783+ }
1784+ } else if (op->u.ds.budget == 300) {
1785+ init_timer(&ds_start_timer, ds_ds_start_timer, (void *) (unsigned int) 1, 1);
1786+ set_timer(&ds_start_timer, NOW() + MILLISECS(5000));
1787+ return 1;
1788+ }
1789+ }
1790+ }
1791+
1792+ return 0;
1793+}
1794+
1795+//init a dom
1796+static int
1797+ds_dom_init(struct domain *dom) {
1798+ struct ds_dom *ddom;
1799+
1800+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
1801+
1802+ if (is_idle_domain(dom)) {
1803+ printk("\t# init an idle domain\n");
1804+ return 0;
1805+ }
1806+
1807+ ddom = xmalloc(struct ds_dom);
1808+ if (ddom == NULL)
1809+ return -ENOMEM;
1810+ memset(ddom, 0, sizeof (*ddom));
1811+
1812+ /* Initialize budget and period */
1813+ ddom->dom = dom;
1814+
1815+ switch(dom->domain_id) {
1816+ case 32767:
1817+ ddom->budget = DS_IDLE_PERIOD;
1818+ ddom->period = DS_IDLE_PERIOD;
1819+ ddom->level = DS_IDLE_PERIOD;
1820+ break;
1821+ case 0:
1822+ ddom->budget = DS_DOM_0_PERIOD;
1823+ ddom->period = DS_DOM_0_PERIOD;
1824+ ddom->level = 1;
1825+ break;
1826+ default:
1827+ ddom->budget = DS_DOM_BUDGET;
1828+ ddom->period = DS_DOM_PERIOD;
1829+ ddom->level = 10;
1830+ break;
1831+ }
1832+
1833+ dom->sched_priv = ddom;
1834+
1835+ return 0;
1836+}
1837+
1838+//destory a domain
1839+static void
1840+ds_dom_destroy(struct domain *dom) {
1841+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
1842+ xfree(DS_DOM(dom));
1843+}
1844+
1845+//ticked by pcpu tick in pcpu.
1846+static void
1847+ds_tick(void *_cpu) {
1848+ unsigned int cpu = (unsigned long) _cpu;
1849+ struct ds_pcpu *ppc = DS_PCPU(cpu);
1850+/*
1851+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1852+ ds_res_tick[ds_idx_tick].enter = NOW();
1853+ }
1854+*/
1855+ BUG_ON(current->processor != cpu);
1856+
1857+ if (check_cpu_for_repl(cpu)) {
1858+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
1859+ }
1860+
1861+ if (ds_cpu_pick(current) != cpu) {
1862+ set_bit(_VPF_migrating, &current->pause_flags);
1863+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
1864+ }
1865+
1866+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
1867+/*
1868+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1869+ ds_res_tick[ds_idx_tick].leave = NOW();
1870+ if (ds_idx_tick++ >= RECORD) {
1871+ printk("tick full!\n");
1872+ ds_dump_record();
1873+ }
1874+ }
1875+ */
1876+}
1877+
1878+// most important function, called every budget time
1879+static struct task_slice
1880+ds_schedule(s_time_t now) {
1881+ const int cpu = smp_processor_id();
1882+ struct list_head *runq = RUNQ(cpu);
1883+ struct ds_vcpu *scurr = DS_VCPU(current);
1884+ struct ds_vcpu *snext;
1885+ struct task_slice ret;
1886+
1887+ DS_VCPU_CHECK(current);
1888+/*
1889+// for record
1890+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1891+ if(is_idle_vcpu(scurr->vcpu)) ds_res[ds_idx].curr = 10;
1892+ else ds_res[ds_idx].curr = scurr->vcpu->domain->domain_id;
1893+ ds_res[ds_idx].enter = NOW();
1894+ }
1895+*/
1896+ if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
1897+ //if (!is_idle_vcpu(scurr->vcpu)) {
1898+ burn_budgets(scurr, now);
1899+ if (scurr->flag == 0) {
1900+ scurr->flag = 1;
1901+ ds_repq_insert(scurr->vcpu->processor, scurr);
1902+ }
1903+ }
1904+
1905+ if (vcpu_runnable(current)) {
1906+ __runq_insert(cpu, scurr);
1907+ } else {
1908+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
1909+ // for the polling server
1910+ if (cpu == 1 && scurr->vcpu->domain->domain_id != 0 && ds_priv.polling == 1) {
1911+ scurr->cur_budget = 0;
1912+ }
1913+ __rdyq_insert(cpu, scurr);
1914+ }
1915+
1916+ snext = __runq_pick(cpu);
1917+
1918+ __runq_remove(snext);
1919+
1920+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
1921+ snext->last_start_time = NOW();
1922+ }
1923+
1924+ ret.time = (is_idle_vcpu(snext->vcpu) ? -1 : BUDGET(1));
1925+
1926+ //ret.time = BUDGET(1);
1927+ ret.task = snext->vcpu;
1928+
1929+ DS_VCPU_CHECK(ret.task);
1930+
1931+ BUG_ON(!vcpu_runnable(snext->vcpu));
1932+ //printk("now is %lu\n", now);
1933+/*
1934+// for record
1935+ if (smp_processor_id() == 1 && ds_start_flag == 1) {
1936+ if(is_idle_vcpu(snext->vcpu)) ds_res[ds_idx].next = 10;
1937+ else ds_res[ds_idx].next = snext->vcpu->domain->domain_id;
1938+ ds_res[ds_idx].leave = NOW();
1939+ if(ds_idx++ >= RECORD) {
1940+ printk("full!!\n");
1941+ ds_dump_record();
1942+ }
1943+ }
1944+ */
1945+
1946+ return ret;
1947+}
1948+
1949+//init the global data
1950+static void
1951+ds_init(void) {
1952+ printk("\n# into %s\n", __func__);
1953+ spin_lock_init(&ds_priv.lock);
1954+ ds_priv.ncpus = 0;
1955+ ds_priv.polling = 0;
1956+ ds_priv.periodic = 0;
1957+}
1958+
1959+/* Tickers cannot be kicked until SMP subsystem is alive. */
1960+static __init int
1961+ds_start_tickers(void) {
1962+ struct ds_pcpu *ppc;
1963+ unsigned int cpu;
1964+
1965+ printk("\n# into %s, start all tickers right now\n", __func__);
1966+
1967+ if (ds_priv.ncpus == 0)
1968+ return 0;
1969+
1970+ for_each_online_cpu(cpu) {
1971+ ppc = DS_PCPU(cpu);
1972+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
1973+ }
1974+
1975+ return 0;
1976+}
1977+__initcall(ds_start_tickers);
1978+
1979+static void ds_tick_suspend(void) {
1980+ struct ds_pcpu *ppc;
1981+
1982+ printk("\n# into %s, why is this called?\n", __func__);
1983+
1984+ ppc = DS_PCPU(smp_processor_id());
1985+
1986+ stop_timer(&ppc->ticker);
1987+}
1988+
1989+static void ds_tick_resume(void) {
1990+ struct ds_pcpu *ppc;
1991+ uint64_t now = NOW();
1992+
1993+ printk("\n# into %s, why is this called?\n", __func__);
1994+
1995+ ppc = DS_PCPU(smp_processor_id());
1996+
1997+ set_timer(&ppc->ticker, now + BUDGET(1));
1998+}
1999+
2000+const struct scheduler sched_ds_def = {
2001+ .name = "Deferrable Server Scheduler",
2002+ .opt_name = "ds",
2003+ .sched_id = XEN_SCHEDULER_DS,
2004+
2005+ .init_domain = ds_dom_init,
2006+ .destroy_domain = ds_dom_destroy,
2007+
2008+ .init_vcpu = ds_vcpu_init,
2009+ .destroy_vcpu = ds_vcpu_destroy,
2010+
2011+ .init = ds_init,
2012+
2013+ .pick_cpu = ds_cpu_pick,
2014+
2015+ .tick_suspend = ds_tick_suspend,
2016+ .tick_resume = ds_tick_resume,
2017+
2018+ .do_schedule = ds_schedule,
2019+
2020+ .sleep = ds_vcpu_sleep,
2021+ .wake = ds_vcpu_wake,
2022+
2023+ .adjust = ds_dom_cntl,
2024+
2025+ .dump_cpu_state = ds_dump_pcpu,
2026+ .dump_settings = ds_dump,
2027+};
2028diff -ubrN xen/xen-4.0.1/xen/common/sched_ds_emsoft11.c xen-4.0.1/xen/common/sched_ds_emsoft11.c
2029--- xen/xen-4.0.1/xen/common/sched_ds_emsoft11.c 1969-12-31 17:00:00.000000000 -0700
2030+++ xen-4.0.1/xen/common/sched_ds_emsoft11.c 2011-04-10 11:56:00.000000000 -0600
2031@@ -0,0 +1,1136 @@
2032+/******************************************************************************
2033+ * Periodic / Polling / Deferrable Server scheduler for xen
2034+ *
2035+ * by Sisu Xi (C) 2010 Washington University in St. Louis
2036+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
2037+ ******************************************************************************/
2038+
2039+#include <xen/config.h>
2040+#include <xen/init.h>
2041+#include <xen/lib.h>
2042+#include <xen/sched.h>
2043+#include <xen/domain.h>
2044+#include <xen/delay.h>
2045+#include <xen/event.h>
2046+#include <xen/time.h>
2047+#include <xen/perfc.h>
2048+#include <xen/sched-if.h>
2049+#include <xen/softirq.h>
2050+#include <asm/atomic.h>
2051+#include <xen/errno.h>
2052+#include <xen/keyhandler.h>
2053+
2054+#define DS_DOM(_dom) ((struct ds_dom *) (_dom)->sched_priv)
2055+#define DS_PCPU(_c) ((struct ds_pcpu *)per_cpu(schedule_data, _c).sched_priv)
2056+#define DS_VCPU(_vcpu) ((struct ds_vcpu *) (_vcpu)->sched_priv)
2057+#define RUNQ(_cpu) (&(DS_PCPU(_cpu)->runq))
2058+#define RDYQ(_cpu) (&(DS_PCPU(_cpu)->rdyq))
2059+#define DS_CUR(_cpu) DS_VCPU(per_cpu(schedule_data, _cpu).curr)
2060+#define BUDGET(_b) (MILLISECS(10*_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
2061+
2062+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
2063+
2064+#define DS_DOM_0_PERIOD 100
2065+#define DS_IDLE_PERIOD 200
2066+
2067+#define DS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
2068+#define DS_DOM_PERIOD 50
2069+
2070+//PES is the Simple PES, CS is the standard PES
2071+enum server_type {DS, POS, PES, CS, SS};
2072+
2073+//physical cpu
2074+struct ds_pcpu {
2075+ struct list_head runq; // runQ on the pcpu, organized by linked list
2076+ struct list_head rdyq;
2077+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
2078+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
2079+ int rep_capacity; // upper limit
2080+ struct timer ticker; // for preemptive use, tick every budget
2081+};
2082+
2083+//virtual cpu
2084+struct ds_vcpu {
2085+ struct list_head runq_elem;
2086+ struct list_head rdyq_elem;
2087+ struct list_head active_elem; //used to link all active vcpu except domain 0 and idle one!
2088+ struct ds_dom *ddom;
2089+ struct vcpu *vcpu;
2090+
2091+ uint16_t repq_pending; // used to calculate how many items are on repq
2092+
2093+ uint16_t budget;
2094+ uint16_t period;
2095+ uint16_t level;
2096+
2097+ uint16_t cur_budget;
2098+ s_time_t last_start_time; // used for burn_budget
2099+ s_time_t next_time; //the next repl time
2100+
2101+ int flag; // represent whether the vCPU has started or not
2102+
2103+ uint16_t burn_total; // used only for Sporadic Server
2104+};
2105+
2106+//used for replenishment
2107+struct rep_elem {
2108+ s_time_t re_time;
2109+ int16_t re_amount;
2110+ struct ds_vcpu *dvc;
2111+};
2112+
2113+//domain
2114+struct ds_dom {
2115+ struct domain *dom;
2116+ uint16_t budget;
2117+ uint16_t period;
2118+ uint16_t level;
2119+};
2120+
2121+//global variable, records the number of cpus
2122+struct ds_private {
2123+ spinlock_t lock; // used for init
2124+ uint32_t ncpus; //number of physical cpus
2125+ enum server_type type; // used for different type of servers
2126+ struct list_head active; //active_vcpu except domain 0 and idle vcpu!
2127+};
2128+static struct ds_private ds_priv;
2129+
2130+static void ds_tick(void *_cpu);
2131+
2132+//dump the repq
2133+static void
2134+ds_dump_repq(int cpu) {
2135+ int loop = 0;
2136+ struct ds_pcpu *ppc = DS_PCPU(cpu);
2137+
2138+ printk("repq: size: %d\n", ppc->rep_size);
2139+ for (loop = 0; loop < ppc->rep_size; loop++) {
2140+ printk("\t[%d, %d]: %d @ %lu\n",
2141+ ppc->repq[loop].dvc->vcpu->domain->domain_id,
2142+ ppc->repq[loop].dvc->vcpu->vcpu_id,
2143+ ppc->repq[loop].re_amount,
2144+ ppc->repq[loop].re_time);
2145+ }
2146+}
2147+
2148+//dump the virtual cpu
2149+static void
2150+ds_dump_vcpu(struct ds_vcpu *dvc) {
2151+ printk("\t[%i, %i], cur: %i, rep: %d, last: %lu, next: %lu, \n", dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id, dvc->cur_budget, dvc->repq_pending, dvc->last_start_time, dvc->next_time);
2152+}
2153+
2154+//inlined code
2155+static inline struct ds_vcpu *
2156+__runq_elem(struct list_head *elem) {
2157+ return list_entry(elem, struct ds_vcpu, runq_elem);
2158+}
2159+
2160+//inlined code
2161+static inline struct ds_vcpu *
2162+__rdyq_elem(struct list_head *elem) {
2163+ return list_entry(elem, struct ds_vcpu, rdyq_elem);
2164+}
2165+
2166+//dump the physical cpu
2167+static void
2168+ds_dump_pcpu(int cpu) {
2169+ struct list_head *iter;
2170+ struct ds_pcpu *ppc = DS_PCPU(cpu);
2171+ struct list_head *runq = &ppc->runq;
2172+ struct list_head *rdyq = &ppc->rdyq;
2173+ struct ds_vcpu *dvc = DS_CUR(cpu);
2174+ int loop = 0;
2175+
2176+ printk("### cpu: %d, now is: %lu\n", cpu, NOW());
2177+
2178+ if (dvc) {
2179+ printk("\trun: ");
2180+ ds_dump_vcpu(dvc);
2181+ }
2182+
2183+ printk("runq:\n");
2184+ list_for_each(iter, runq) {
2185+ dvc = __runq_elem(iter);
2186+ if (dvc) {
2187+ printk("\t%3d: ", ++loop);
2188+ ds_dump_vcpu(dvc);
2189+ }
2190+ }
2191+
2192+ printk("rdyq:\n");
2193+ list_for_each(iter, rdyq) {
2194+ dvc = __rdyq_elem(iter);
2195+ if (dvc) {
2196+ printk("\t%3d: ", ++loop);
2197+ ds_dump_vcpu(dvc);
2198+ }
2199+ }
2200+
2201+ ds_dump_repq(cpu);
2202+ printk("\n");
2203+}
2204+
2205+// the current vcpu is on runQ?
2206+static inline int
2207+__vcpu_on_runq(struct ds_vcpu *dvc) {
2208+ return !list_empty(&dvc->runq_elem);
2209+}
2210+
2211+// the current vcpu is on runQ?
2212+static inline int
2213+__vcpu_on_rdyq(struct ds_vcpu *dvc) {
2214+ return !list_empty(&dvc->rdyq_elem);
2215+}
2216+
2217+//pick the first vcpu whose budget is >0 from the runq
2218+static inline struct ds_vcpu *
2219+__runq_pick(unsigned int cpu) {
2220+ struct list_head * runq = RUNQ(cpu);
2221+ struct list_head * iter;
2222+
2223+ list_for_each(iter, runq) {
2224+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
2225+ if (iter_dvc->cur_budget > 0) {
2226+ return iter_dvc;
2227+ }
2228+ }
2229+
2230+ BUG_ON(1);
2231+ return NULL;
2232+}
2233+
2234+//pick the first one with budget > 0, regardless of runnable or not
2235+static inline struct ds_vcpu *
2236+__rdyq_pick(unsigned int cpu) {
2237+ struct list_head * rdyq = RDYQ(cpu);
2238+ struct list_head * iter;
2239+
2240+ list_for_each(iter, rdyq) {
2241+ struct ds_vcpu *iter_dvc = __rdyq_elem(iter);
2242+ if (iter_dvc->cur_budget > 0) {
2243+ return iter_dvc;
2244+ }
2245+ }
2246+
2247+ return NULL;
2248+}
2249+
2250+static inline struct ds_vcpu *
2251+__runq_pick_idle(unsigned int cpu) {
2252+ struct list_head * runq = RUNQ(cpu);
2253+ struct list_head * iter;
2254+
2255+ list_for_each(iter, runq) {
2256+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
2257+ if (is_idle_vcpu(iter_dvc->vcpu)) {
2258+ return iter_dvc;
2259+ }
2260+ }
2261+
2262+ BUG_ON(1);
2263+ return NULL;
2264+}
2265+
2266+//insert into the runq, followed a FIFO way. sorted by level
2267+static inline void
2268+__runq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
2269+ struct list_head * runq = RUNQ(cpu);
2270+ struct list_head * iter;
2271+
2272+ BUG_ON(__vcpu_on_runq(dvc));
2273+ BUG_ON(cpu != dvc->vcpu->processor);
2274+
2275+ list_for_each(iter, runq) {
2276+ struct ds_vcpu * iter_dvc = __runq_elem(iter);
2277+ if (dvc->level < iter_dvc->level) {
2278+ break;
2279+ }
2280+ }
2281+
2282+ list_add_tail(&dvc->runq_elem, iter);
2283+}
2284+
2285+//insert into the runq, followed a FIFO way. sorted by level
2286+static inline void
2287+__rdyq_insert(unsigned int cpu, struct ds_vcpu *dvc) {
2288+ struct list_head * rdyq = RDYQ(cpu);
2289+ struct list_head * iter;
2290+
2291+ BUG_ON(__vcpu_on_rdyq(dvc));
2292+ BUG_ON(cpu != dvc->vcpu->processor);
2293+
2294+ list_for_each(iter, rdyq) {
2295+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2296+ if (dvc->level <= iter_dvc->level) {
2297+ break;
2298+ }
2299+ }
2300+
2301+ list_add_tail(&dvc->rdyq_elem, iter);
2302+}
2303+
2304+//remove it from runQ
2305+static inline void
2306+__runq_remove(struct ds_vcpu *dvc) {
2307+ BUG_ON(!__vcpu_on_runq(dvc));
2308+ list_del_init(&dvc->runq_elem);
2309+}
2310+
2311+//remove it from runQ
2312+static inline void
2313+__rdyq_remove(struct ds_vcpu *dvc) {
2314+ BUG_ON(!__vcpu_on_rdyq(dvc));
2315+ list_del_init(&dvc->rdyq_elem);
2316+}
2317+
2318+//used for the heap, repQ
2319+static inline int
2320+ds_rep_parent(int childIdx) {
2321+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
2322+}
2323+
2324+//insert into the repQ
2325+static inline void
2326+ds_repq_insert(unsigned int cpu, struct ds_vcpu *dvc, int amount) {
2327+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2328+ int childIdx, parentIdx;
2329+
2330+ if (dvc->next_time == 0) {
2331+ printk("\n# in %s, ERROR! dvc is:", __func__);
2332+ ds_dump_vcpu(dvc);
2333+ ds_dump_pcpu(cpu);
2334+ dvc->next_time = NOW() + BUDGET(1) * dvc->period;
2335+ }
2336+
2337+ if (amount == 0) {
2338+ return;
2339+ }
2340+
2341+ if (ppc->rep_size == ppc->rep_capacity) {
2342+ printk("\n# into %s, repQ full!!\n", __func__);
2343+ BUG_ON(1);
2344+ }
2345+
2346+ childIdx = ppc->rep_size;
2347+ parentIdx = ds_rep_parent(childIdx);
2348+
2349+ while (childIdx > 0 && dvc->next_time < ppc->repq[parentIdx].re_time) {
2350+ ppc->repq[childIdx] = ppc->repq[parentIdx];
2351+ childIdx = parentIdx;
2352+ parentIdx = ds_rep_parent(childIdx);
2353+ }
2354+
2355+ ppc->repq[childIdx].re_time = dvc->next_time;
2356+ ppc->repq[childIdx].dvc = dvc;
2357+ ppc->repq[childIdx].re_amount = amount;
2358+ ppc->rep_size++;
2359+
2360+ // dvc->next_time = 0;
2361+ dvc->repq_pending++;
2362+}
2363+
2364+//remove from the repQ
2365+static inline void
2366+ds_repq_remove(unsigned int cpu) {
2367+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2368+ int childIdx = 1;
2369+ int rightChildIdx;
2370+ int rootIdx = 0;
2371+ struct rep_elem temp;
2372+
2373+ BUG_ON(ppc->rep_size <= 0);
2374+
2375+ ppc->repq[0].dvc->repq_pending--;
2376+ ppc->repq[0] = ppc->repq[ppc->rep_size - 1];
2377+ ppc->rep_size--;
2378+
2379+ temp = ppc->repq[0];
2380+
2381+ while (childIdx < ppc->rep_size) {
2382+ rightChildIdx = childIdx + 1;
2383+ if (rightChildIdx < ppc->rep_size && ppc->repq[rightChildIdx].re_time < ppc->repq[childIdx].re_time) {
2384+ childIdx = rightChildIdx;
2385+ }
2386+ if (ppc->repq[childIdx].re_time < temp.re_time) {
2387+ ppc->repq[rootIdx] = ppc->repq[childIdx];
2388+ rootIdx = childIdx;
2389+ childIdx = 2 * rootIdx + 1;
2390+ } else {
2391+ break;
2392+ }
2393+ }
2394+ ppc->repq[rootIdx] = temp;
2395+}
2396+
2397+//dump dump function
2398+static void
2399+ds_dump(void) {
2400+ printk("# into %s. Did Nothing\n", __func__);
2401+}
2402+
2403+//burn the scurr budget
2404+//dom != 0 && !is_idle_vcpu(dvc)
2405+static void
2406+burn_budgets(struct ds_vcpu *dvc, s_time_t now) {
2407+ s_time_t delta;
2408+ unsigned int consume;
2409+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
2410+ struct list_head * iter;
2411+
2412+ BUG_ON(dvc != DS_CUR(dvc->vcpu->processor));
2413+
2414+ if (dvc->last_start_time == 0) {
2415+ dvc->last_start_time = now;
2416+ printk("\nset last_start_time to 0 in %s\n", __func__);
2417+ return;
2418+ }
2419+
2420+ delta = now - dvc->last_start_time;
2421+ BUG_ON(delta <= 0);
2422+
2423+ consume = ( delta/BUDGET(1) );
2424+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
2425+
2426+ dvc->cur_budget -= consume;
2427+ if (dvc->cur_budget < 0) dvc->cur_budget = 0;
2428+
2429+ if(ds_priv.type == SS) {
2430+ dvc->burn_total += consume;
2431+ }
2432+
2433+ // printk("\n\t%d @ burn\n", consume);
2434+//used for simple PES, to burn all the VCPU's budget who has higher priority
2435+ if (ds_priv.type == PES) {
2436+ list_for_each(iter, rdyq) {
2437+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2438+ //rdyQ has higher priority
2439+ if (dvc->level > iter_dvc->level && iter_dvc->cur_budget > 0) {
2440+ iter_dvc->cur_budget -= consume;
2441+ if (iter_dvc->cur_budget < 0) {
2442+ iter_dvc->cur_budget = 0;
2443+ }
2444+ break; // the enhanced old periodic server
2445+ }
2446+ }
2447+ }
2448+}
2449+
2450+//used for PES and CS, the dvc is the IDLE VCPU
2451+//domain != 0, is_idle_vcpu(dvc)
2452+static void
2453+burn_extra(struct ds_vcpu *dvc, s_time_t now) {
2454+ s_time_t delta;
2455+ unsigned int consume;
2456+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
2457+ struct list_head * iter;
2458+
2459+ BUG_ON(dvc != DS_CUR(dvc->vcpu->processor));
2460+
2461+ if (dvc->last_start_time == 0) {
2462+ dvc->last_start_time = now;
2463+ return;
2464+ }
2465+
2466+ if (ds_priv.type == DS || ds_priv.type == POS || ds_priv.type == SS) {
2467+ return;
2468+ }
2469+
2470+ delta = now - dvc->last_start_time;
2471+ BUG_ON(delta <= 0);
2472+
2473+ consume = ( delta/BUDGET(1) );
2474+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
2475+
2476+ if (ds_priv.type == PES) {
2477+ list_for_each(iter, rdyq) {
2478+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2479+ //rdyQ has higher priority
2480+ if (iter_dvc->cur_budget > 0) {
2481+ iter_dvc->cur_budget -= consume;
2482+ if (iter_dvc->cur_budget < 0) {
2483+ iter_dvc->cur_budget = 0;
2484+ }
2485+ break; // the enhanced old periodic server
2486+ }
2487+ }
2488+ } else { // now for the CS, need to consume the budget of the first element on rdyq
2489+ list_for_each(iter, rdyq) {
2490+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2491+ //rdyQ has higher priority
2492+ if (iter_dvc->cur_budget > 0) {
2493+ iter_dvc->cur_budget -= consume;
2494+ if (iter_dvc->cur_budget < 0) {
2495+ iter_dvc->cur_budget = 0;
2496+ }
2497+ break;
2498+ }
2499+ }// if no one runs, also check the rdyQ, and then returns
2500+ }
2501+}
2502+
2503+//init the physical cpu
2504+static int
2505+ds_pcpu_init(int cpu) {
2506+ struct ds_pcpu *ppc;
2507+ unsigned long flags;
2508+
2509+ /* Allocate per-PCPU info */
2510+ ppc = xmalloc(struct ds_pcpu);
2511+ if (ppc == NULL)
2512+ return -1;
2513+ memset(ppc, 0, sizeof (*ppc));
2514+
2515+ spin_lock_irqsave(&ds_priv.lock, flags);
2516+
2517+ if (ds_priv.ncpus < cpu)
2518+ ds_priv.ncpus = cpu + 1;
2519+
2520+ init_timer(&ppc->ticker, ds_tick, (void *) (unsigned long) cpu, cpu);
2521+ INIT_LIST_HEAD(&ppc->runq);
2522+ INIT_LIST_HEAD(&ppc->rdyq);
2523+ per_cpu(schedule_data, cpu).sched_priv = ppc;
2524+
2525+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
2526+
2527+ ppc->rep_capacity = REPQ_CAPACITY;
2528+ ppc->repq = xmalloc_array(struct rep_elem, ppc->rep_capacity);
2529+ BUG_ON(ppc->repq == NULL);
2530+ ppc->rep_size = 0;
2531+
2532+ spin_unlock_irqrestore(&ds_priv.lock, flags);
2533+
2534+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
2535+
2536+ return 0;
2537+}
2538+
2539+//check the vcpu
2540+static inline void
2541+__ds_vcpu_check(struct vcpu *vc) {
2542+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2543+ struct ds_dom * const ddom = dvc->ddom;
2544+
2545+ BUG_ON(dvc->vcpu != vc);
2546+ BUG_ON(ddom != DS_DOM(vc->domain));
2547+ if (ddom) {
2548+ BUG_ON(is_idle_vcpu(vc));
2549+ BUG_ON(ddom->dom != vc->domain);
2550+ } else {
2551+ BUG_ON(!is_idle_vcpu(vc));
2552+ }
2553+}
2554+#define DS_VCPU_CHECK(_vc) (__ds_vcpu_check(_vc))
2555+
2556+//pick a cpu to run, used to migrate from different cpus
2557+static int
2558+ds_cpu_pick(struct vcpu *vc) {
2559+ cpumask_t cpus;
2560+ int cpu;
2561+
2562+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
2563+
2564+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
2565+ return cycle_cpu(vc->processor, cpus);
2566+ }
2567+
2568+ cpu = cpu_isset(vc->processor, cpus)
2569+ ? vc->processor
2570+ : cycle_cpu(vc->processor, cpus);
2571+
2572+ return cpu;
2573+}
2574+
2575+//for PES or CS, when the
2576+//check the current repQ to see if a repl needs to happen
2577+static int
2578+check_cpu_for_repl(int cpu) {
2579+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2580+ int flag = 0; //used for interrupt
2581+ struct list_head * rdyq = RDYQ(cpu);
2582+ struct list_head * iter;
2583+
2584+ while((ppc->rep_size != 0) && ppc->repq[0].re_time < NOW()) {
2585+ ppc->repq[0].dvc->cur_budget += ppc->repq[0].re_amount;
2586+ if (ppc->repq[0].dvc->cur_budget > ppc->repq[0].dvc->budget) {
2587+ ppc->repq[0].dvc->cur_budget = ppc->repq[0].dvc->budget;
2588+ }
2589+
2590+ if (ds_priv.type != SS) { // insert next repl
2591+ ppc->repq[0].dvc->next_time = NOW() + BUDGET(1) * ppc->repq[0].dvc->period;
2592+ ds_repq_insert(ppc->repq[0].dvc->vcpu->processor, ppc->repq[0].dvc, ppc->repq[0].dvc->budget);
2593+ }
2594+
2595+ if (ds_priv.type != CS) {
2596+ if (ppc->repq[0].dvc->level < DS_CUR(cpu)->level) {
2597+ flag = 1;
2598+ } // raise interrupt
2599+ } else { // for the CS type
2600+ if (!is_idle_vcpu(current)) {
2601+ if (ppc->repq[0].dvc->level < DS_CUR(cpu)->level) {
2602+ flag = 1;
2603+ }
2604+ } else { // the idle VCPU
2605+ list_for_each(iter, rdyq) {
2606+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2607+ //rdyQ has higher priority
2608+ if (iter_dvc->cur_budget > 0) {
2609+ if (ppc->repq[0].dvc->level < iter_dvc->level) {
2610+ flag = 1; // higher priority
2611+ }
2612+ break;
2613+ }
2614+ }
2615+ }
2616+ }
2617+
2618+ ds_repq_remove(cpu);
2619+ }
2620+
2621+ return flag;
2622+}
2623+
2624+//init the virtual cpu
2625+static int
2626+ds_vcpu_init(struct vcpu *vc) {
2627+ struct domain * const dom = vc->domain;
2628+ struct ds_dom *ddom = DS_DOM(dom);
2629+ struct ds_vcpu *dvc;
2630+
2631+ /* Allocate per-VCPU info */
2632+ dvc = xmalloc(struct ds_vcpu);
2633+ if (dvc == NULL) {
2634+ return -1;
2635+ }
2636+ memset(dvc, 0, sizeof (*dvc));
2637+
2638+ INIT_LIST_HEAD(&dvc->runq_elem);
2639+ INIT_LIST_HEAD(&dvc->rdyq_elem);
2640+ INIT_LIST_HEAD(&dvc->active_elem); // init for active list
2641+ dvc->ddom = ddom;
2642+ dvc->vcpu = vc;
2643+ dvc->budget = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->budget;
2644+ dvc->period = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->period;
2645+ dvc->level = is_idle_vcpu(vc)? DS_IDLE_PERIOD: ddom->level;
2646+ dvc->cur_budget = dvc->budget;
2647+ dvc->repq_pending = 0;
2648+
2649+ dvc->last_start_time = 0;
2650+ dvc->flag = 0;
2651+
2652+ dvc->burn_total = 0;
2653+ dvc->next_time = 0;
2654+
2655+ vc->sched_priv = dvc;
2656+
2657+ /* Allocate per-PCPU info */
2658+ if (unlikely(!DS_PCPU(vc->processor))) {
2659+ if (ds_pcpu_init(vc->processor) != 0)
2660+ return -1;
2661+ }
2662+
2663+ DS_VCPU_CHECK(vc);
2664+
2665+ printk("\n# into %s, vcpu init: ", __func__);
2666+ ds_dump_vcpu(dvc);
2667+
2668+ return 0;
2669+}
2670+
2671+//destory the vcpu
2672+static void
2673+ds_vcpu_destroy(struct vcpu *vc) {
2674+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2675+ struct ds_dom * const ddom = dvc->ddom;
2676+
2677+ printk("\n# into %s, vcpu destroy: ", __func__);
2678+ ds_dump_vcpu(dvc);
2679+
2680+ BUG_ON(ddom == NULL);
2681+ BUG_ON(!list_empty(&dvc->runq_elem));
2682+ list_del_init(&dvc->active_elem);
2683+
2684+ xfree(dvc);
2685+}
2686+
2687+//sleep the vcpu
2688+static void
2689+ds_vcpu_sleep(struct vcpu *vc) {
2690+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2691+
2692+ BUG_ON(is_idle_vcpu(vc));
2693+
2694+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
2695+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
2696+ } else if (__vcpu_on_runq(dvc)) {
2697+ //polling server
2698+ if (ds_priv.type == POS) {
2699+ dvc->cur_budget = 0;
2700+ }
2701+ __runq_remove(dvc);
2702+ } else if (__vcpu_on_rdyq(dvc)) {
2703+ __rdyq_remove(dvc);
2704+ }
2705+}
2706+
2707+//wake up the vcpu, insert it into runq, raise a softirq
2708+static void
2709+ds_vcpu_wake(struct vcpu *vc) {
2710+ struct ds_vcpu * const dvc = DS_VCPU(vc);
2711+ const unsigned int cpu = vc->processor;
2712+ struct list_head * rdyq = RDYQ(cpu);
2713+ struct list_head * iter;
2714+
2715+ BUG_ON(is_idle_vcpu(vc));
2716+
2717+ // if (vc->domain->domain_id != 0) {
2718+ // printk("wake vcpu: now %lu ", NOW());
2719+ // ds_dump_vcpu(dvc);
2720+ // }
2721+
2722+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
2723+ if (vc->domain->domain_id != 0) {
2724+ printk("\nrunning\n");
2725+ }
2726+ return;
2727+ }
2728+ if (unlikely(__vcpu_on_runq(dvc))) {
2729+ if (vc->domain->domain_id != 0) {
2730+ printk("\nrunq\n");
2731+ }
2732+ return;
2733+ }
2734+
2735+ if (__vcpu_on_rdyq(dvc)) {
2736+ __rdyq_remove(dvc);
2737+ }
2738+
2739+ if (!__vcpu_on_runq(dvc)) {
2740+ __runq_insert(cpu, dvc);
2741+ }
2742+
2743+ if (ds_priv.type != CS) {
2744+ if (dvc->level < DS_CUR(cpu)->level) {
2745+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2746+ return;
2747+ }
2748+ } else {
2749+ if (!is_idle_vcpu(current)) {
2750+ if (dvc->level < DS_CUR(cpu)->level) {
2751+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2752+ return;
2753+ }
2754+ } else {
2755+ list_for_each(iter, rdyq) {
2756+ struct ds_vcpu * iter_dvc = __rdyq_elem(iter);
2757+ //rdyQ has higher priority
2758+ if (iter_dvc->cur_budget > 0) {
2759+ if (dvc->level < iter_dvc->level) {
2760+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2761+ return;
2762+ }
2763+ break;
2764+ }
2765+ }
2766+ }
2767+ }
2768+
2769+ return;
2770+}
2771+
2772+static inline void
2773+ds_reset(int cpu) {
2774+ struct ds_pcpu * ppc = DS_PCPU(cpu);
2775+ struct list_head * iter;
2776+
2777+ printk("\nbefore reset\n");
2778+ ds_dump_pcpu(cpu);
2779+
2780+ // empty the RepQ
2781+ while(ppc->rep_size != 0) {
2782+ ds_repq_remove(cpu);
2783+ }
2784+
2785+ printk("\nvcpu on list is:\n");
2786+ //init each vcpu;
2787+ list_for_each(iter, &ds_priv.active) {
2788+ struct ds_vcpu * iter_dvc = list_entry(iter, struct ds_vcpu, active_elem);
2789+ if (__vcpu_on_runq(iter_dvc)) {
2790+ __runq_remove(iter_dvc);
2791+ }
2792+ if (__vcpu_on_rdyq(iter_dvc)) {
2793+ __rdyq_remove(iter_dvc);
2794+ }
2795+ iter_dvc->cur_budget = iter_dvc->budget;
2796+ iter_dvc->last_start_time = NOW();
2797+ iter_dvc->next_time = NOW() + BUDGET(1) * iter_dvc->period;
2798+ iter_dvc->burn_total = 0;
2799+ ds_dump_vcpu(iter_dvc);
2800+ }
2801+
2802+ printk("\nafter reset\n");
2803+ ds_dump_pcpu(cpu);
2804+
2805+ //insert into Queues
2806+ list_for_each(iter, &ds_priv.active) {
2807+ struct ds_vcpu * iter_dvc = list_entry(iter, struct ds_vcpu, active_elem);
2808+ if (vcpu_runnable(iter_dvc->vcpu)) {
2809+ if (!__vcpu_on_runq(iter_dvc)) {
2810+ __runq_insert(cpu, iter_dvc);
2811+ }
2812+ } else {
2813+ if (!__vcpu_on_rdyq(iter_dvc)) {
2814+ __rdyq_insert(cpu, iter_dvc);
2815+ }
2816+ }
2817+ if (ds_priv.type != SS) {
2818+ ds_repq_insert(iter_dvc->vcpu->processor, iter_dvc, iter_dvc->budget);
2819+ }
2820+ }
2821+
2822+ printk("\nafter insert\n");
2823+ ds_dump_pcpu(cpu);
2824+}
2825+
2826+//adjust the domain's budget & period, also used to trigger the record
2827+static int
2828+ds_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
2829+ struct ds_dom * const ddom = DS_DOM(d);
2830+ unsigned long flags;
2831+ struct ds_vcpu *dvc = DS_VCPU(d->vcpu[0]);
2832+ int flag = 0;
2833+
2834+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
2835+ op->u.ds.budget = ddom->budget;
2836+ op->u.ds.period = ddom->period;
2837+ op->u.ds.level = ddom->level;
2838+ //ds_dump_vcpu(dvc);
2839+ } else {
2840+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
2841+
2842+ spin_lock_irqsave(&ds_priv.lock, flags);
2843+ if (op->u.ds.budget != 0) {
2844+ ddom->budget = op->u.ds.budget;
2845+ dvc->budget = op->u.ds.budget;
2846+ }
2847+ if (op->u.ds.period != 0) {
2848+ ddom->period = op->u.ds.period;
2849+ dvc->period = op->u.ds.period;
2850+ }
2851+ if (op->u.ds.level != 0) {
2852+ ddom->level = op->u.ds.level;
2853+ dvc->level = op->u.ds.level;
2854+ }
2855+ dvc->cur_budget = dvc->budget;
2856+ spin_unlock_irqrestore(&ds_priv.lock, flags);
2857+
2858+ if (dvc->vcpu->domain->domain_id == 0) {
2859+ switch (op->u.ds.budget) {
2860+ case 100:
2861+ ds_priv.type = DS;
2862+ flag = 1;
2863+ break;
2864+ case 200:
2865+ ds_priv.type = CS;
2866+ flag = 1;
2867+ break;
2868+ case 300:
2869+ ds_priv.type = PES;
2870+ flag = 1;
2871+ break;
2872+ case 400:
2873+ ds_priv.type = POS;
2874+ flag = 1;
2875+ break;
2876+ case 500:
2877+ ds_priv.type = SS;
2878+ flag = 1;
2879+ break;
2880+ case 600:
2881+ return 1; // return to record the overhead!
2882+ break;
2883+ case 700:
2884+ ds_dump_pcpu(1);
2885+ break;
2886+ default:
2887+ printk("set budget of Domain-0 to : 100 (DS), 200 (CS), 300 (PES), 400 (POS), 500 (SS), 600 (record overhead), 700 (dump PCPU)\n");
2888+ break;
2889+ }
2890+ printk("Currently running with Scheduler ");
2891+ switch (ds_priv.type) {
2892+ case CS:
2893+ printk("CS\n");
2894+ break;
2895+ case POS:
2896+ printk("POS\n");
2897+ break;
2898+ case PES:
2899+ printk("PES\n");
2900+ break;
2901+ case DS:
2902+ printk("DS\n");
2903+ break;
2904+ case SS:
2905+ printk("SS\n");
2906+ break;
2907+ default:
2908+ printk("Wrong!!!\n");
2909+ break;
2910+ }
2911+ if (flag == 1) {
2912+ ds_reset(1);
2913+ cpu_raise_softirq(1, SCHEDULE_SOFTIRQ);
2914+ flag = 0;
2915+ }
2916+ }
2917+ }
2918+
2919+ return 0;
2920+}
2921+
2922+//init a dom
2923+static int
2924+ds_dom_init(struct domain *dom) {
2925+ struct ds_dom *ddom;
2926+
2927+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
2928+
2929+ if (is_idle_domain(dom)) {
2930+ printk("\t# init an idle domain\n");
2931+ return 0;
2932+ }
2933+
2934+ ddom = xmalloc(struct ds_dom);
2935+ if (ddom == NULL)
2936+ return -ENOMEM;
2937+ memset(ddom, 0, sizeof (*ddom));
2938+
2939+ /* Initialize budget and period */
2940+ ddom->dom = dom;
2941+
2942+ switch(dom->domain_id) {
2943+ case 32767:
2944+ ddom->budget = DS_IDLE_PERIOD;
2945+ ddom->period = DS_IDLE_PERIOD;
2946+ ddom->level = 100;
2947+ break;
2948+ case 0:
2949+ ddom->budget = DS_DOM_0_PERIOD;
2950+ ddom->period = DS_DOM_0_PERIOD;
2951+ ddom->level = 1;
2952+ break;
2953+ default:
2954+ ddom->budget = DS_DOM_BUDGET;
2955+ ddom->period = DS_DOM_PERIOD;
2956+ ddom->level = 10;
2957+ break;
2958+ }
2959+
2960+ dom->sched_priv = ddom;
2961+
2962+ return 0;
2963+}
2964+
2965+//destory a domain
2966+static void
2967+ds_dom_destroy(struct domain *dom) {
2968+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
2969+ xfree(DS_DOM(dom));
2970+}
2971+
2972+//ticked by pcpu tick in pcpu.
2973+static void
2974+ds_tick(void *_cpu) {
2975+ unsigned int cpu = (unsigned long) _cpu;
2976+ struct ds_pcpu *ppc = DS_PCPU(cpu);
2977+
2978+ BUG_ON(current->processor != cpu);
2979+
2980+ if (check_cpu_for_repl(cpu)) {
2981+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2982+ }
2983+
2984+ if (ds_cpu_pick(current) != cpu) {
2985+ set_bit(_VPF_migrating, &current->pause_flags);
2986+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
2987+ }
2988+
2989+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
2990+}
2991+
2992+// most important function, called every budget time
2993+static struct task_slice
2994+ds_schedule(s_time_t now) {
2995+ const int cpu = smp_processor_id();
2996+ struct list_head *runq = RUNQ(cpu);
2997+ // struct list_head *rdyq = RDYQ(cpu);
2998+ struct ds_vcpu *scurr = DS_VCPU(current);
2999+ struct ds_vcpu *snext;
3000+ struct task_slice ret;
3001+
3002+ DS_VCPU_CHECK(current);
3003+
3004+// need to consider idle_vcpu for CS and PES
3005+ if (scurr->vcpu->domain->domain_id != 0) {
3006+ if (!is_idle_vcpu(scurr->vcpu)) {
3007+ // for the first time the VCPU is executed
3008+ if (scurr->flag == 0) {
3009+ scurr->flag = 1;
3010+ BUG_ON(!list_empty(&scurr->active_elem));
3011+ list_add(&scurr->active_elem, &ds_priv.active);
3012+ scurr->next_time = now + BUDGET(1) * scurr->period;
3013+ ds_repq_insert(scurr->vcpu->processor, scurr, scurr->budget);
3014+ }
3015+ if (cpu == 1) {
3016+ burn_budgets(scurr, now);
3017+ }
3018+ } else if (cpu == 1) { // scurr is the IDLE VCPU, have to deal with specially in CS and PES
3019+ burn_extra(scurr, now);
3020+ }
3021+ }
3022+
3023+ if (vcpu_runnable(current)) {
3024+ if (!__vcpu_on_runq(scurr)) {
3025+ __runq_insert(cpu, scurr);
3026+ }
3027+ } else {
3028+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
3029+ //for POS server
3030+ if (cpu == 1 && scurr->vcpu->domain->domain_id != 0 && ds_priv.type == POS) {
3031+ scurr->cur_budget = 0;
3032+ }
3033+ if (!__vcpu_on_rdyq(scurr)) {
3034+ __rdyq_insert(cpu, scurr);
3035+ }
3036+ }
3037+
3038+ if (cpu != 1) {
3039+ snext = __runq_pick(cpu);
3040+ } else if (ds_priv.type != CS) {
3041+ snext = __runq_pick(cpu);
3042+ } else { // now runs CS scheduler
3043+ // printk("\n\trdy empty? %d, run: %d, rdy: %d\n", list_empty(rdyq), __runq_pick(cpu)->level, __rdyq_pick(cpu)->level);
3044+ if ( __rdyq_pick(cpu) == NULL || (__runq_pick(cpu)->level < __rdyq_pick(cpu)->level) ) {
3045+ snext = __runq_pick(cpu); //we are fine here
3046+ // printk("\npicked %d\n", snext->vcpu->domain->domain_id);
3047+ } else {
3048+ // if ( __rdyq_pick(cpu) == NULL ) {
3049+ // printk("\n\t\trdyq is null\n");
3050+ // } else {
3051+ // printk("\n\t\trun: %d, rdy: %d\n", __runq_pick(cpu)->level, __rdyq_pick(cpu)->level);
3052+ // }
3053+ snext = __runq_pick_idle(cpu); // pick the IDLE VCPU for the VCPU on the RdyQ
3054+ // ds_dump_pcpu(1);
3055+ }
3056+ }
3057+
3058+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
3059+ snext->last_start_time = NOW();
3060+ }
3061+
3062+ BUG_ON(!__vcpu_on_runq(snext));
3063+ __runq_remove(snext);
3064+
3065+ //context switch happens
3066+ if (cpu == 1 && snext != scurr) {
3067+ if (ds_priv.type == SS) {
3068+ if (!is_idle_vcpu(snext->vcpu)) {
3069+ snext->next_time = now + BUDGET(1) * snext->period;
3070+ }
3071+ if (!is_idle_vcpu(scurr->vcpu)) {
3072+ ds_repq_insert(cpu, scurr, scurr->burn_total);
3073+ scurr->burn_total = 0;
3074+ }
3075+ }
3076+ }
3077+
3078+ // ret.time = is_idle_vcpu(snext->vcpu) ? BUDGET(1) : BUDGET(1) * snext->cur_budget;
3079+ ret.time = BUDGET(1); // used to test the enhanced old periodic server
3080+ ret.task = snext->vcpu;
3081+
3082+ DS_VCPU_CHECK(ret.task);
3083+
3084+ BUG_ON(!vcpu_runnable(snext->vcpu));
3085+
3086+ return ret;
3087+}
3088+
3089+//init the global data
3090+static void
3091+ds_init(void) {
3092+ printk("\n# into %s\n", __func__);
3093+ spin_lock_init(&ds_priv.lock);
3094+ ds_priv.ncpus = 0;
3095+ ds_priv.type = DS;
3096+ INIT_LIST_HEAD(&ds_priv.active);
3097+}
3098+
3099+/* Tickers cannot be kicked until SMP subsystem is alive. */
3100+static __init int
3101+ds_start_tickers(void) {
3102+ struct ds_pcpu *ppc;
3103+ unsigned int cpu;
3104+
3105+ printk("\n# into %s, start all tickers right now\n", __func__);
3106+
3107+ if (ds_priv.ncpus == 0)
3108+ return 0;
3109+
3110+ for_each_online_cpu(cpu) {
3111+ ppc = DS_PCPU(cpu);
3112+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
3113+ }
3114+
3115+ return 0;
3116+}
3117+__initcall(ds_start_tickers);
3118+
3119+static void ds_tick_suspend(void) {
3120+ struct ds_pcpu *ppc;
3121+
3122+ printk("\n# into %s, why is this called?\n", __func__);
3123+
3124+ ppc = DS_PCPU(smp_processor_id());
3125+
3126+ stop_timer(&ppc->ticker);
3127+}
3128+
3129+static void ds_tick_resume(void) {
3130+ struct ds_pcpu *ppc;
3131+ uint64_t now = NOW();
3132+
3133+ printk("\n# into %s, why is this called?\n", __func__);
3134+
3135+ ppc = DS_PCPU(smp_processor_id());
3136+
3137+ set_timer(&ppc->ticker, now + BUDGET(1));
3138+}
3139+
3140+const struct scheduler sched_ds_def = {
3141+ .name = "Deferrable Server Scheduler",
3142+ .opt_name = "ds",
3143+ .sched_id = XEN_SCHEDULER_DS,
3144+
3145+ .init_domain = ds_dom_init,
3146+ .destroy_domain = ds_dom_destroy,
3147+
3148+ .init_vcpu = ds_vcpu_init,
3149+ .destroy_vcpu = ds_vcpu_destroy,
3150+
3151+ .init = ds_init,
3152+
3153+ .pick_cpu = ds_cpu_pick,
3154+
3155+ .tick_suspend = ds_tick_suspend,
3156+ .tick_resume = ds_tick_resume,
3157+
3158+ .do_schedule = ds_schedule,
3159+
3160+ .sleep = ds_vcpu_sleep,
3161+ .wake = ds_vcpu_wake,
3162+
3163+ .adjust = ds_dom_cntl,
3164+
3165+ .dump_cpu_state = ds_dump_pcpu,
3166+ .dump_settings = ds_dump,
3167+};
3168diff -ubrN xen/xen-4.0.1/xen/common/sched_rt.c xen-4.0.1/xen/common/sched_rt.c
3169--- xen/xen-4.0.1/xen/common/sched_rt.c 1969-12-31 17:00:00.000000000 -0700
3170+++ xen-4.0.1/xen/common/sched_rt.c 2011-05-01 00:42:25.000000000 -0600
3171@@ -0,0 +1,584 @@
3172+/******************************************************************************
3173+ * Real Time Xen scheduler Framework
3174+ *
3175+ * by Sisu Xi (C) 2010 Washington University in St. Louis
3176+ * based on code by Jaewoo Lee (C) 2010 University of Pennsylvania
3177+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
3178+ ******************************************************************************/
3179+
3180+#include <xen/config.h>
3181+#include <xen/init.h>
3182+#include <xen/lib.h>
3183+#include <xen/sched.h>
3184+#include <xen/domain.h>
3185+#include <xen/delay.h>
3186+#include <xen/event.h>
3187+#include <xen/time.h>
3188+#include <xen/perfc.h>
3189+#include <xen/sched-if.h>
3190+#include <xen/softirq.h>
3191+#include <asm/atomic.h>
3192+#include <xen/errno.h>
3193+#include <xen/keyhandler.h>
3194+#include "sched_rt.h"
3195+
3196+extern const struct rt_scheduler sched_deferrable_def;
3197+extern const struct rt_scheduler sched_periodic_def;
3198+extern const struct rt_scheduler sched_wcps_def;
3199+extern const struct rt_scheduler sched_ssps_def;
3200+//extern const struct rt_scheduler sched_polling_def;
3201+//extern const struct rt_scheduler sched_sporadic_def;
3202+
3203+static struct rt_private rt_priv;
3204+
3205+static void rt_tick(void *_cpu);
3206+
3207+
3208+//init the global data, picking schedulers!
3209+static void
3210+rt_init(void) {
3211+ printk("\n# into %s\n", __func__);
3212+
3213+ spin_lock_init(&rt_priv.lock);
3214+ rt_priv.ncpus = 0;
3215+ rt_priv.type = DS;
3216+ INIT_LIST_HEAD(&rt_priv.active);
3217+}
3218+
3219+//dump the physical cpu
3220+static void
3221+rt_dump_pcpu(int cpu) {
3222+ struct list_head *iter;
3223+ struct rt_pcpu *ppc = RT_PCPU(cpu);
3224+ struct list_head *runq = &ppc->runq;
3225+ struct list_head *rdyq = &ppc->rdyq;
3226+ struct rt_vcpu *dvc = RT_CUR(cpu);
3227+ int loop = 0;
3228+
3229+ printk("### cpu: %d, now is: %lu\n", cpu, NOW());
3230+
3231+ if (dvc) {
3232+ printk("\trun: ");
3233+ rt_dump_vcpu(dvc);
3234+ }
3235+
3236+ printk("runq:\n");
3237+ list_for_each(iter, runq) {
3238+ dvc = __runq_elem(iter);
3239+ if (dvc) {
3240+ printk("\t%3d: ", ++loop);
3241+ rt_dump_vcpu(dvc);
3242+ }
3243+ }
3244+
3245+ printk("rdyq:\n");
3246+ list_for_each(iter, rdyq) {
3247+ dvc = __rdyq_elem(iter);
3248+ if (dvc) {
3249+ printk("\t%3d: ", ++loop);
3250+ rt_dump_vcpu(dvc);
3251+ }
3252+ }
3253+
3254+ rt_dump_repq(cpu);
3255+ printk("\n");
3256+}
3257+
3258+//dump dump function
3259+static void
3260+rt_dump(void) {
3261+ rt_dump_pcpu(1);
3262+}
3263+
3264+//init the physical cpu
3265+static int
3266+rt_pcpu_init(int cpu) {
3267+ struct rt_pcpu *ppc;
3268+ unsigned long flags;
3269+
3270+ /* Allocate per-PCPU info */
3271+ ppc = xmalloc(struct rt_pcpu);
3272+ if (ppc == NULL)
3273+ return -1;
3274+ memset(ppc, 0, sizeof (*ppc));
3275+
3276+ spin_lock_irqsave(&rt_priv.lock, flags);
3277+
3278+ if (rt_priv.ncpus < cpu)
3279+ rt_priv.ncpus = cpu + 1;
3280+
3281+ init_timer(&ppc->ticker, rt_tick, (void *) (unsigned long) cpu, cpu);
3282+ INIT_LIST_HEAD(&ppc->runq);
3283+ INIT_LIST_HEAD(&ppc->rdyq);
3284+ per_cpu(schedule_data, cpu).sched_priv = ppc;
3285+
3286+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
3287+
3288+ ppc->rep_capacity = REPQ_CAPACITY;
3289+ ppc->repq = xmalloc_array(struct rep_elem, ppc->rep_capacity);
3290+ BUG_ON(ppc->repq == NULL);
3291+ ppc->rep_size = 0;
3292+
3293+ spin_unlock_irqrestore(&rt_priv.lock, flags);
3294+
3295+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
3296+
3297+ return 0;
3298+}
3299+
3300+//pick a cpu to run, used to migrate from different cpus
3301+static int
3302+rt_cpu_pick(struct vcpu *vc) {
3303+ cpumask_t cpus;
3304+ int cpu;
3305+
3306+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
3307+
3308+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
3309+ return cycle_cpu(vc->processor, cpus);
3310+ }
3311+
3312+ cpu = cpu_isset(vc->processor, cpus)
3313+ ? vc->processor
3314+ : cycle_cpu(vc->processor, cpus);
3315+
3316+ return cpu;
3317+}
3318+
3319+//init the virtual cpu
3320+static int
3321+rt_vcpu_init(struct vcpu *vc) {
3322+ struct domain * const dom = vc->domain;
3323+ struct rt_dom *ddom = RT_DOM(dom);
3324+ struct rt_vcpu *dvc;
3325+
3326+ /* Allocate per-VCPU info */
3327+ dvc = xmalloc(struct rt_vcpu);
3328+ if (dvc == NULL) {
3329+ return -1;
3330+ }
3331+ memset(dvc, 0, sizeof (*dvc));
3332+
3333+ INIT_LIST_HEAD(&dvc->runq_elem);
3334+ INIT_LIST_HEAD(&dvc->rdyq_elem);
3335+ INIT_LIST_HEAD(&dvc->active_elem); // init for active list
3336+ dvc->ddom = ddom;
3337+ dvc->vcpu = vc;
3338+ dvc->budget = is_idle_vcpu(vc)? RT_IDLE_PERIOD: ddom->budget;
3339+ dvc->period = is_idle_vcpu(vc)? RT_IDLE_PERIOD: ddom->period;
3340+ dvc->level = is_idle_vcpu(vc)? RT_IDLE_PERIOD: ddom->level;
3341+ dvc->cur_budget = dvc->budget;
3342+ dvc->repq_pending = 0;
3343+
3344+ dvc->last_start_time = 0;
3345+
3346+ dvc->burn_total = 0;
3347+ dvc->next_time = 0;
3348+
3349+ vc->sched_priv = dvc;
3350+
3351+ /* Allocate per-PCPU info */
3352+ if (unlikely(!RT_PCPU(vc->processor))) {
3353+ if (rt_pcpu_init(vc->processor) != 0)
3354+ return -1;
3355+ }
3356+
3357+ RT_VCPU_CHECK(vc);
3358+
3359+ BUG_ON(!list_empty(&dvc->active_elem));
3360+ list_add(&dvc->active_elem, &rt_priv.active);
3361+ dvc->next_time = NOW() + BUDGET(1) * dvc->period;
3362+ rt_repq_insert(dvc->vcpu->processor, dvc, dvc->budget);
3363+
3364+ printk("\n# into %s, vcpu init: ", __func__);
3365+ rt_dump_vcpu(dvc);
3366+
3367+ return 0;
3368+}
3369+
3370+//destory the vcpu
3371+static void
3372+rt_vcpu_destroy(struct vcpu *vc) {
3373+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3374+ struct rt_dom * const ddom = dvc->ddom;
3375+
3376+ printk("\n# into %s, vcpu destroy: ", __func__);
3377+ rt_dump_vcpu(dvc);
3378+
3379+ BUG_ON(ddom == NULL);
3380+ BUG_ON(!list_empty(&dvc->runq_elem));
3381+ list_del_init(&dvc->active_elem);
3382+
3383+ xfree(dvc);
3384+}
3385+
3386+//init a dom
3387+static int
3388+rt_dom_init(struct domain *dom) {
3389+ struct rt_dom *ddom;
3390+
3391+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
3392+
3393+ if (is_idle_domain(dom)) {
3394+ printk("\t# init an idle domain\n");
3395+ return 0;
3396+ }
3397+
3398+ ddom = xmalloc(struct rt_dom);
3399+ if (ddom == NULL)
3400+ return -ENOMEM;
3401+ memset(ddom, 0, sizeof (*ddom));
3402+
3403+ /* Initialize budget and period */
3404+ ddom->dom = dom;
3405+
3406+ switch(dom->domain_id) {
3407+ case 32767:
3408+ ddom->budget = RT_IDLE_PERIOD;
3409+ ddom->period = RT_IDLE_PERIOD;
3410+ ddom->level = 100;
3411+ break;
3412+ case 0:
3413+ ddom->budget = RT_DOM_0_PERIOD;
3414+ ddom->period = RT_DOM_0_PERIOD;
3415+ ddom->level = 1;
3416+ break;
3417+ default:
3418+ ddom->budget = RT_DOM_BUDGET;
3419+ ddom->period = RT_DOM_PERIOD;
3420+ ddom->level = 10;
3421+ break;
3422+ }
3423+
3424+ dom->sched_priv = ddom;
3425+
3426+ return 0;
3427+}
3428+
3429+//destory a domain
3430+static void
3431+rt_dom_destroy(struct domain *dom) {
3432+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
3433+ xfree(RT_DOM(dom));
3434+}
3435+
3436+/* Tickers cannot be kicked until SMP subsystem is alive. */
3437+static __init int
3438+rt_start_tickers(void) {
3439+ struct rt_pcpu *ppc;
3440+ unsigned int cpu;
3441+
3442+ printk("\n# into %s, start all tickers right now\n", __func__);
3443+
3444+ if (rt_priv.ncpus == 0)
3445+ return 0;
3446+
3447+ for_each_online_cpu(cpu) {
3448+ ppc = RT_PCPU(cpu);
3449+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
3450+ }
3451+
3452+ return 0;
3453+}
3454+__initcall(rt_start_tickers);
3455+
3456+static void rt_tick_suspend(void) {
3457+ struct rt_pcpu *ppc;
3458+
3459+ printk("\n# into %s, why is this called?\n", __func__);
3460+
3461+ ppc = RT_PCPU(smp_processor_id());
3462+
3463+ stop_timer(&ppc->ticker);
3464+}
3465+
3466+static void rt_tick_resume(void) {
3467+ struct rt_pcpu *ppc;
3468+ uint64_t now = NOW();
3469+
3470+ printk("\n# into %s, why is this called?\n", __func__);
3471+
3472+ ppc = RT_PCPU(smp_processor_id());
3473+
3474+ set_timer(&ppc->ticker, now + BUDGET(1));
3475+}
3476+
3477+
3478+/*********************************************
3479+ * Four Subscheduler Specific Functions
3480+*********************************************/
3481+
3482+//sleep the vcpu
3483+static void
3484+rt_vcpu_sleep(struct vcpu *vc) {
3485+ //SCHED_OP(vcpu_sleep, vc);
3486+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3487+
3488+ BUG_ON(is_idle_vcpu(vc));
3489+
3490+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
3491+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
3492+ } else if (__vcpu_on_runq(dvc)) {
3493+ __runq_remove(dvc);
3494+ } else if (__vcpu_on_rdyq(dvc)) {
3495+ __rdyq_remove(dvc);
3496+ }
3497+
3498+ return;
3499+}
3500+
3501+//wake up the vcpu, insert it into runq, raise a softirq
3502+static void
3503+rt_vcpu_wake(struct vcpu *vc) {
3504+ //SCHED_OP(vcpu_wake, vc);
3505+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3506+ const unsigned int cpu = vc->processor;
3507+
3508+ BUG_ON(is_idle_vcpu(vc));
3509+
3510+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
3511+ if (vc->domain->domain_id != 0) {
3512+ printk("\nwake running\n");
3513+ }
3514+ return;
3515+ }
3516+ if (unlikely(__vcpu_on_runq(dvc))) {
3517+ if (vc->domain->domain_id != 0) {
3518+ printk("\nwake on runq\n");
3519+ }
3520+ return;
3521+ }
3522+
3523+ if (__vcpu_on_rdyq(dvc)) {
3524+ __rdyq_remove(dvc);
3525+ }
3526+
3527+ if (!__vcpu_on_runq(dvc)) {
3528+ __runq_insert(cpu, dvc);
3529+ }
3530+
3531+ if (dvc->level < RT_CUR(cpu)->level) {
3532+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
3533+ }
3534+
3535+ return;
3536+}
3537+
3538+//ticked by pcpu tick in pcpu.
3539+static void
3540+rt_tick(void *_cpu) {
3541+ unsigned int cpu = (unsigned long) _cpu;
3542+ switch (rt_priv.type) {
3543+ case DS:
3544+ sched_deferrable_def.tick(_cpu);
3545+ break;
3546+ case PPS:
3547+ sched_periodic_def.tick(_cpu);
3548+ break;
3549+ case WCPS:
3550+ sched_wcps_def.tick(_cpu);
3551+ break;
3552+ case SSPS:
3553+ sched_ssps_def.tick(_cpu);
3554+ break;
3555+ default:
3556+ printk("Wrong in %s\n", __func__);
3557+ sched_deferrable_def.tick(_cpu);
3558+ break;
3559+ }
3560+
3561+ if (rt_cpu_pick(current) != cpu) {
3562+ set_bit(_VPF_migrating, &current->pause_flags);
3563+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
3564+ }
3565+}
3566+
3567+// most important function, called every budget time
3568+static struct task_slice
3569+rt_schedule(s_time_t now) {
3570+ switch (rt_priv.type) {
3571+ case DS:
3572+ return sched_deferrable_def.schedule(now);
3573+ break;
3574+ case PPS:
3575+ return sched_periodic_def.schedule(now);
3576+ break;
3577+ case WCPS:
3578+ return sched_wcps_def.schedule(now);
3579+ break;
3580+ case SSPS:
3581+ return sched_ssps_def.schedule(now);
3582+ break;
3583+ default:
3584+ printk("Wrong in %s\n", __func__);
3585+ return sched_deferrable_def.schedule(now);
3586+ break;
3587+ }
3588+}
3589+
3590+/*********************************************
3591+ * Used to Adjust Domain parameters and switch schedulers
3592+*********************************************/
3593+/*
3594+// !!! Need to consider SS! for the repl queue!! have not done yet!
3595+static inline void
3596+rt_reset(int cpu) {
3597+ struct rt_pcpu * ppc = RT_PCPU(cpu);
3598+ struct list_head * iter;
3599+
3600+ printk("\nBefore reset\n");
3601+ rt_dump_pcpu(cpu);
3602+
3603+ // empty the RepQ
3604+ while(ppc->rep_size != 0) {
3605+ rt_repq_remove(cpu);
3606+ }
3607+
3608+ printk("\nvcpu on list is:\n");
3609+ //init each vcpu;
3610+ list_for_each(iter, &rt_priv.active) {
3611+ struct rt_vcpu * iter_dvc = list_entry(iter, struct rt_vcpu, active_elem);
3612+ if (__vcpu_on_runq(iter_dvc)) {
3613+ __runq_remove(iter_dvc);
3614+ }
3615+ if (__vcpu_on_rdyq(iter_dvc)) {
3616+ __rdyq_remove(iter_dvc);
3617+ }
3618+ iter_dvc->cur_budget = iter_dvc->budget;
3619+ iter_dvc->last_start_time = NOW();
3620+ iter_dvc->next_time = NOW() + BUDGET(1) * iter_dvc->period;
3621+ iter_dvc->burn_total = 0;
3622+ rt_dump_vcpu(iter_dvc);
3623+ }
3624+
3625+ //insert into Queues
3626+ list_for_each(iter, &rt_priv.active) {
3627+ struct rt_vcpu * iter_dvc = list_entry(iter, struct rt_vcpu, active_elem);
3628+ if (vcpu_runnable(iter_dvc->vcpu)) {
3629+ if (!__vcpu_on_runq(iter_dvc)) {
3630+ __runq_insert(cpu, iter_dvc);
3631+ }
3632+ } else {
3633+ if (!__vcpu_on_rdyq(iter_dvc)) {
3634+ __rdyq_insert(cpu, iter_dvc);
3635+ }
3636+ }
3637+ }
3638+
3639+ printk("\nAfter Reset\n");
3640+ rt_dump_pcpu(cpu);
3641+}
3642+*/
3643+//adjust the domain's budget & period, also used to trigger the record
3644+static int
3645+rt_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
3646+ struct rt_dom * const ddom = RT_DOM(d);
3647+ unsigned long flags;
3648+ struct rt_vcpu *dvc = RT_VCPU(d->vcpu[0]);
3649+
3650+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
3651+ op->u.rt.budget = ddom->budget;
3652+ op->u.rt.period = ddom->period;
3653+ op->u.rt.level = ddom->level;
3654+ } else {
3655+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
3656+
3657+ spin_lock_irqsave(&rt_priv.lock, flags);
3658+
3659+ if (op->u.rt.budget != 0) {
3660+ ddom->budget = op->u.rt.budget;
3661+ dvc->budget = op->u.rt.budget;
3662+ }
3663+
3664+ if (op->u.rt.period != 0) {
3665+ ddom->period = op->u.rt.period;
3666+ dvc->period = op->u.rt.period;
3667+ }
3668+
3669+ if (op->u.rt.level != 0) {
3670+ ddom->level = op->u.rt.level;
3671+ dvc->level = op->u.rt.level;
3672+ }
3673+ dvc->cur_budget = dvc->budget; // reset its budget
3674+ spin_unlock_irqrestore(&rt_priv.lock, flags);
3675+
3676+ if (dvc->vcpu->domain->domain_id == 0) {
3677+ switch (op->u.rt.budget) {
3678+ case 100:
3679+ printk("############################\n100: dump info\n200: DS\n300: PPS\n400: WC-PS\n500: SS-PS\n\n");
3680+ rt_dump_pcpu(1);
3681+ break;
3682+ case 200:
3683+ rt_priv.type = DS; //change to DS;
3684+ //rt_reset(1);
3685+ break;
3686+ case 300:
3687+ rt_priv.type = PPS; // to PPS
3688+ //rt_reset(1);
3689+ break;
3690+ case 400:
3691+ rt_priv.type = WCPS; // WCPS
3692+ //rt_reset(1);
3693+ break;
3694+ case 500:
3695+ rt_priv.type = SSPS; // SSPS
3696+ //rt_reset(1);
3697+ break;
3698+ default:
3699+ printk("############################\n100: dump info\n200: DS\n300: PPS\n400: WC-PS\n500: SS-PS\n\n");
3700+ break;
3701+ }
3702+ printk("Current Scheduler: ");
3703+ switch (rt_priv.type) {
3704+ case DS:
3705+ printk("%s\n", sched_deferrable_def.name);
3706+ break;
3707+ case PPS:
3708+ printk("%s\n", sched_periodic_def.name);
3709+ break;
3710+ case WCPS:
3711+ printk("%s\n", sched_wcps_def.name);
3712+ break;
3713+ case SSPS:
3714+ printk("%s\n", sched_ssps_def.name);
3715+ break;
3716+ default:
3717+ printk("wrong, reset to DS\n");
3718+ rt_priv.type = DS;
3719+ break;
3720+ }
3721+
3722+ }
3723+ }
3724+
3725+ return 0;
3726+}
3727+
3728+const struct scheduler sched_rt_def = {
3729+ .name = "Real Time Scheduler",
3730+ .opt_name = "rt",
3731+ .sched_id = XEN_SCHEDULER_RT,
3732+
3733+ .init_domain = rt_dom_init,
3734+ .destroy_domain = rt_dom_destroy,
3735+
3736+ .init_vcpu = rt_vcpu_init,
3737+ .destroy_vcpu = rt_vcpu_destroy,
3738+
3739+ .init = rt_init,
3740+
3741+ .pick_cpu = rt_cpu_pick,
3742+
3743+ .tick_suspend = rt_tick_suspend,
3744+ .tick_resume = rt_tick_resume,
3745+
3746+ .do_schedule = rt_schedule,
3747+
3748+ .sleep = rt_vcpu_sleep,
3749+ .wake = rt_vcpu_wake,
3750+
3751+ .adjust = rt_dom_cntl,
3752+
3753+ .dump_cpu_state = rt_dump_pcpu,
3754+ .dump_settings = rt_dump,
3755+};
3756diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_deferrable.c xen-4.0.1/xen/common/sched_rt_deferrable.c
3757--- xen/xen-4.0.1/xen/common/sched_rt_deferrable.c 1969-12-31 17:00:00.000000000 -0700
3758+++ xen-4.0.1/xen/common/sched_rt_deferrable.c 2011-04-24 21:23:02.000000000 -0600
3759@@ -0,0 +1,79 @@
3760+/******************************************************************************
3761+ * Real Time Xen scheduler Framework
3762+ *
3763+ * by Sisu Xi (C) 2010 Washington University in St. Louis
3764+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
3765+ ******************************************************************************/
3766+
3767+#include <xen/config.h>
3768+#include <xen/init.h>
3769+#include <xen/lib.h>
3770+#include <xen/sched.h>
3771+#include <xen/domain.h>
3772+#include <xen/delay.h>
3773+#include <xen/event.h>
3774+#include <xen/time.h>
3775+#include <xen/perfc.h>
3776+#include <xen/sched-if.h>
3777+#include <xen/softirq.h>
3778+#include <asm/atomic.h>
3779+#include <xen/errno.h>
3780+#include <xen/keyhandler.h>
3781+#include "sched_rt.h"
3782+#include "sched_rt_repq.h"
3783+
3784+
3785+// most important function, called every budget time
3786+static struct task_slice
3787+deferrable_schedule(s_time_t now) {
3788+ const int cpu = smp_processor_id();
3789+ struct list_head *runq = RUNQ(cpu);
3790+ struct rt_vcpu *scurr = RT_VCPU(current);
3791+ struct rt_vcpu *snext;
3792+ struct task_slice ret;
3793+
3794+ RT_VCPU_CHECK(current);
3795+
3796+ if ((scurr->vcpu->domain->domain_id != 0) && (!is_idle_vcpu(scurr->vcpu))) {
3797+ repq_burn(scurr, now);
3798+ }
3799+
3800+ if (vcpu_runnable(current)) {
3801+ if (!__vcpu_on_runq(scurr)) {
3802+ __runq_insert(cpu, scurr);
3803+ }
3804+ } else {
3805+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
3806+ if (!__vcpu_on_rdyq(scurr)) {
3807+ __rdyq_insert(cpu, scurr);
3808+ }
3809+ }
3810+
3811+ snext = __runq_pick(cpu);
3812+
3813+ if (snext->vcpu->domain->domain_id != 0) {
3814+ snext->last_start_time = NOW();
3815+ }
3816+
3817+ BUG_ON(!__vcpu_on_runq(snext));
3818+ __runq_remove(snext);
3819+
3820+ ret.time = is_idle_vcpu(snext->vcpu) ? BUDGET(1) : BUDGET(1) * snext->cur_budget;
3821+ ret.task = snext->vcpu;
3822+
3823+ RT_VCPU_CHECK(ret.task);
3824+
3825+ BUG_ON(!vcpu_runnable(snext->vcpu));
3826+
3827+ return ret;
3828+}
3829+
3830+const struct rt_scheduler sched_deferrable_def = {
3831+ .name = "Deferrable Server Scheduler",
3832+ .opt_name = "ds",
3833+
3834+ .tick = repq_tick,
3835+ .vcpu_wake = NULL,
3836+ .vcpu_sleep = NULL,
3837+ .schedule = deferrable_schedule
3838+};
3839diff -ubrN xen/xen-4.0.1/xen/common/sched_rt.h xen-4.0.1/xen/common/sched_rt.h
3840--- xen/xen-4.0.1/xen/common/sched_rt.h 1969-12-31 17:00:00.000000000 -0700
3841+++ xen-4.0.1/xen/common/sched_rt.h 2011-04-24 22:23:43.000000000 -0600
3842@@ -0,0 +1,348 @@
3843+/******************************************************************************
3844+ * Real Time Xen scheduler Headfile, including the common data structures
3845+ *
3846+ * by Sisu Xi (C) 2010 Washington University in St. Louis
3847+ * based on code by Jaewoo Lee (C) 2010 University of Pennsylvania
3848+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
3849+ ******************************************************************************/
3850+
3851+#define RT_DOM(_dom) ((struct rt_dom *) (_dom)->sched_priv)
3852+#define RT_PCPU(_c) ((struct rt_pcpu *)per_cpu(schedule_data, _c).sched_priv)
3853+#define RT_VCPU(_vcpu) ((struct rt_vcpu *) (_vcpu)->sched_priv)
3854+#define RUNQ(_cpu) (&(RT_PCPU(_cpu)->runq))
3855+#define RDYQ(_cpu) (&(RT_PCPU(_cpu)->rdyq))
3856+#define RT_CUR(_cpu) RT_VCPU(per_cpu(schedule_data, _cpu).curr)
3857+#define BUDGET(_b) (MILLISECS(1*_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
3858+
3859+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
3860+
3861+#define RT_DOM_0_PERIOD 100
3862+#define RT_IDLE_PERIOD 200
3863+
3864+#define RT_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
3865+#define RT_DOM_PERIOD 50
3866+
3867+enum server_type {DS, PPS, WCPS, SSPS};
3868+
3869+
3870+/*********************************************
3871+ * Data Structure
3872+*********************************************/
3873+
3874+//physical cpu
3875+struct rt_pcpu {
3876+ struct list_head runq; // runQ on the pcpu, organized by linked list
3877+ struct list_head rdyq;
3878+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
3879+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
3880+ int rep_capacity; // upper limit
3881+ struct timer ticker; // for preemptive use, tick every budget
3882+};
3883+
3884+//virtual cpu
3885+struct rt_vcpu {
3886+ struct list_head runq_elem;
3887+ struct list_head rdyq_elem;
3888+ struct list_head active_elem; //used to link all active vcpu except domain 0 and idle one!
3889+ struct rt_dom *ddom;
3890+ struct vcpu *vcpu;
3891+
3892+ uint16_t repq_pending; // used to calculate how many items are on repq
3893+
3894+ uint16_t budget;
3895+ uint16_t period;
3896+ uint16_t level;
3897+
3898+ uint16_t cur_budget;
3899+ s_time_t last_start_time; // used for burn_budget
3900+ s_time_t next_time; //the next repl time
3901+
3902+ uint16_t burn_total; // used only for Sporadic Server
3903+};
3904+
3905+//used for replenishment
3906+struct rep_elem {
3907+ s_time_t re_time;
3908+ int16_t re_amount;
3909+ struct rt_vcpu *dvc;
3910+};
3911+
3912+//domain
3913+struct rt_dom {
3914+ struct domain *dom;
3915+ uint16_t budget;
3916+ uint16_t period;
3917+ uint16_t level;
3918+};
3919+
3920+//global variable, records the number of cpus
3921+struct rt_private {
3922+ spinlock_t lock; // used for init
3923+ uint32_t ncpus; //number of physical cpus
3924+ struct list_head active; //active_vcpu except domain 0 and idle vcpu!
3925+ enum server_type type; //used to represent scheduler
3926+};
3927+
3928+struct rt_scheduler {
3929+ char *name;
3930+ char *opt_name;
3931+
3932+ void (*vcpu_sleep)(struct vcpu *vc);
3933+ void (*tick)(void *_cpu);
3934+ struct task_slice (*schedule)(s_time_t);
3935+ void (*vcpu_wake)(struct vcpu *vc);
3936+};
3937+
3938+/*********************************************
3939+ * Common Code
3940+*********************************************/
3941+
3942+//check the vcpu
3943+static inline void
3944+__rt_vcpu_check(struct vcpu *vc) {
3945+ struct rt_vcpu * const dvc = RT_VCPU(vc);
3946+ struct rt_dom * const ddom = dvc->ddom;
3947+
3948+ BUG_ON(dvc->vcpu != vc);
3949+ BUG_ON(ddom != RT_DOM(vc->domain));
3950+ if (ddom) {
3951+ BUG_ON(is_idle_vcpu(vc));
3952+ BUG_ON(ddom->dom != vc->domain);
3953+ } else {
3954+ BUG_ON(!is_idle_vcpu(vc));
3955+ }
3956+}
3957+#define RT_VCPU_CHECK(_vc) (__rt_vcpu_check(_vc))
3958+
3959+//inlined code
3960+static inline struct rt_vcpu *
3961+__runq_elem(struct list_head *elem) {
3962+ return list_entry(elem, struct rt_vcpu, runq_elem);
3963+}
3964+
3965+//inlined code
3966+static inline struct rt_vcpu *
3967+__rdyq_elem(struct list_head *elem) {
3968+ return list_entry(elem, struct rt_vcpu, rdyq_elem);
3969+}
3970+
3971+// the current vcpu is on runQ?
3972+static inline int
3973+__vcpu_on_runq(struct rt_vcpu *dvc) {
3974+ return !list_empty(&dvc->runq_elem);
3975+}
3976+
3977+// the current vcpu is on runQ?
3978+static inline int
3979+__vcpu_on_rdyq(struct rt_vcpu *dvc) {
3980+ return !list_empty(&dvc->rdyq_elem);
3981+}
3982+
3983+/*********************************************
3984+ * Dump Settings Related
3985+*********************************************/
3986+
3987+//dump the repq
3988+static inline void
3989+rt_dump_repq(int cpu) {
3990+ int loop = 0;
3991+ struct rt_pcpu *ppc = RT_PCPU(cpu);
3992+
3993+ printk("repq: size: %d\n", ppc->rep_size);
3994+ for (loop = 0; loop < ppc->rep_size; loop++) {
3995+ printk("\t[%d, %d]: %d @ %lu\n",
3996+ ppc->repq[loop].dvc->vcpu->domain->domain_id,
3997+ ppc->repq[loop].dvc->vcpu->vcpu_id,
3998+ ppc->repq[loop].re_amount,
3999+ ppc->repq[loop].re_time);
4000+ }
4001+}
4002+
4003+//dump the virtual cpu
4004+static inline void
4005+rt_dump_vcpu(struct rt_vcpu *dvc) {
4006+ printk("\t[%i, %i], cur: %i, rep: %d, last: %lu, next: %lu, \n", dvc->vcpu->domain->domain_id, dvc->vcpu->vcpu_id, dvc->cur_budget, dvc->repq_pending, dvc->last_start_time, dvc->next_time);
4007+}
4008+
4009+/*********************************************
4010+ * RunQ, RdyQ, and RepQ Related
4011+*********************************************/
4012+
4013+//pick the first vcpu whose budget is >0 from the runq
4014+static inline struct rt_vcpu *
4015+__runq_pick(unsigned int cpu) {
4016+ struct list_head * runq = RUNQ(cpu);
4017+ struct list_head * iter;
4018+
4019+ list_for_each(iter, runq) {
4020+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4021+ if (iter_dvc->cur_budget > 0) {
4022+ return iter_dvc;
4023+ }
4024+ }
4025+
4026+ BUG_ON(1);
4027+ return NULL;
4028+}
4029+
4030+//pick the first one with budget > 0, regardless of runnable or not
4031+static inline struct rt_vcpu *
4032+__rdyq_pick(unsigned int cpu) {
4033+ struct list_head * rdyq = RDYQ(cpu);
4034+ struct list_head * iter;
4035+
4036+ list_for_each(iter, rdyq) {
4037+ struct rt_vcpu *iter_dvc = __rdyq_elem(iter);
4038+ if (iter_dvc->cur_budget > 0) {
4039+ return iter_dvc;
4040+ }
4041+ }
4042+
4043+ return NULL;
4044+}
4045+
4046+//pick the IDLE VCPU from RunQ, for Periodic Server
4047+static inline struct rt_vcpu *
4048+__runq_pick_idle(unsigned int cpu) {
4049+ struct list_head * runq = RUNQ(cpu);
4050+ struct list_head * iter;
4051+
4052+ list_for_each(iter, runq) {
4053+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4054+ if (is_idle_vcpu(iter_dvc->vcpu)) {
4055+ return iter_dvc;
4056+ }
4057+ }
4058+
4059+ BUG_ON(1);
4060+ return NULL;
4061+}
4062+
4063+//insert into the runq, followed a FIFO way. sorted by level
4064+static inline void
4065+__runq_insert(unsigned int cpu, struct rt_vcpu *dvc) {
4066+ struct list_head * runq = RUNQ(cpu);
4067+ struct list_head * iter;
4068+
4069+ BUG_ON(__vcpu_on_runq(dvc));
4070+ BUG_ON(cpu != dvc->vcpu->processor);
4071+
4072+ list_for_each(iter, runq) {
4073+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4074+ if (dvc->level < iter_dvc->level) {
4075+ break;
4076+ }
4077+ }
4078+
4079+ list_add_tail(&dvc->runq_elem, iter);
4080+}
4081+
4082+//insert into the runq, followed a FIFO way. sorted by level
4083+static inline void
4084+__rdyq_insert(unsigned int cpu, struct rt_vcpu *dvc) {
4085+ struct list_head * rdyq = RDYQ(cpu);
4086+ struct list_head * iter;
4087+
4088+ BUG_ON(__vcpu_on_rdyq(dvc));
4089+ BUG_ON(cpu != dvc->vcpu->processor);
4090+
4091+ list_for_each(iter, rdyq) {
4092+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4093+ if (dvc->level <= iter_dvc->level) {
4094+ break;
4095+ }
4096+ }
4097+
4098+ list_add_tail(&dvc->rdyq_elem, iter);
4099+}
4100+
4101+//remove it from runQ
4102+static inline void
4103+__runq_remove(struct rt_vcpu *dvc) {
4104+ BUG_ON(!__vcpu_on_runq(dvc));
4105+ list_del_init(&dvc->runq_elem);
4106+}
4107+
4108+//remove it from runQ
4109+static inline void
4110+__rdyq_remove(struct rt_vcpu *dvc) {
4111+ BUG_ON(!__vcpu_on_rdyq(dvc));
4112+ list_del_init(&dvc->rdyq_elem);
4113+}
4114+
4115+//used for the heap, repQ
4116+static inline int
4117+rt_rep_parent(int childIdx) {
4118+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
4119+}
4120+
4121+//insert into the repQ
4122+static inline void
4123+rt_repq_insert(unsigned int cpu, struct rt_vcpu *dvc, int amount) {
4124+ struct rt_pcpu * ppc = RT_PCPU(cpu);
4125+ int childIdx, parentIdx;
4126+
4127+ if (dvc->next_time == 0) {
4128+ return;
4129+ }
4130+
4131+ if (amount == 0) {
4132+ return;
4133+ }
4134+
4135+ if (ppc->rep_size == ppc->rep_capacity) {
4136+ printk("\n# into %s, repQ full!!\n", __func__);
4137+ BUG_ON(1);
4138+ }
4139+
4140+ childIdx = ppc->rep_size;
4141+ parentIdx = rt_rep_parent(childIdx);
4142+
4143+ while (childIdx > 0 && dvc->next_time < ppc->repq[parentIdx].re_time) {
4144+ ppc->repq[childIdx] = ppc->repq[parentIdx];
4145+ childIdx = parentIdx;
4146+ parentIdx = rt_rep_parent(childIdx);
4147+ }
4148+
4149+ ppc->repq[childIdx].re_time = dvc->next_time;
4150+ ppc->repq[childIdx].dvc = dvc;
4151+ ppc->repq[childIdx].re_amount = amount;
4152+ ppc->rep_size++;
4153+
4154+ // dvc->next_time = 0;
4155+ dvc->repq_pending++;
4156+}
4157+
4158+//remove from the repQ
4159+static inline void
4160+rt_repq_remove(unsigned int cpu) {
4161+ struct rt_pcpu * ppc = RT_PCPU(cpu);
4162+ int childIdx = 1;
4163+ int rightChildIdx;
4164+ int rootIdx = 0;
4165+ struct rep_elem temp;
4166+
4167+ BUG_ON(ppc->rep_size <= 0);
4168+
4169+ ppc->repq[0].dvc->repq_pending--;
4170+ ppc->repq[0] = ppc->repq[ppc->rep_size - 1];
4171+ ppc->rep_size--;
4172+
4173+ temp = ppc->repq[0];
4174+
4175+ while (childIdx < ppc->rep_size) {
4176+ rightChildIdx = childIdx + 1;
4177+ if (rightChildIdx < ppc->rep_size && ppc->repq[rightChildIdx].re_time < ppc->repq[childIdx].re_time) {
4178+ childIdx = rightChildIdx;
4179+ }
4180+ if (ppc->repq[childIdx].re_time < temp.re_time) {
4181+ ppc->repq[rootIdx] = ppc->repq[childIdx];
4182+ rootIdx = childIdx;
4183+ childIdx = 2 * rootIdx + 1;
4184+ } else {
4185+ break;
4186+ }
4187+ }
4188+ ppc->repq[rootIdx] = temp;
4189+}
4190+
4191diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_periodic.c xen-4.0.1/xen/common/sched_rt_periodic.c
4192--- xen/xen-4.0.1/xen/common/sched_rt_periodic.c 1969-12-31 17:00:00.000000000 -0700
4193+++ xen-4.0.1/xen/common/sched_rt_periodic.c 2011-04-24 21:23:44.000000000 -0600
4194@@ -0,0 +1,125 @@
4195+/******************************************************************************
4196+ * Real Time Xen scheduler Framework
4197+ *
4198+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4199+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4200+ ******************************************************************************/
4201+
4202+#include <xen/config.h>
4203+#include <xen/init.h>
4204+#include <xen/lib.h>
4205+#include <xen/sched.h>
4206+#include <xen/domain.h>
4207+#include <xen/delay.h>
4208+#include <xen/event.h>
4209+#include <xen/time.h>
4210+#include <xen/perfc.h>
4211+#include <xen/sched-if.h>
4212+#include <xen/softirq.h>
4213+#include <asm/atomic.h>
4214+#include <xen/errno.h>
4215+#include <xen/keyhandler.h>
4216+#include "sched_rt.h"
4217+#include "sched_rt_repq.h"
4218+
4219+
4220+
4221+//burn the extra budget on RdyQ
4222+static void
4223+repq_burn_rdyq(struct rt_vcpu *dvc, s_time_t now) {
4224+ s_time_t delta;
4225+ unsigned int consume;
4226+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
4227+ struct list_head * iter;
4228+
4229+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4230+
4231+ if (dvc->last_start_time == 0) {
4232+ dvc->last_start_time = now;
4233+ return;
4234+ }
4235+
4236+ delta = now - dvc->last_start_time;
4237+ BUG_ON(delta <= 0);
4238+
4239+ consume = ( delta/BUDGET(1) );
4240+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4241+
4242+ // burn budgets on RdyQ
4243+ list_for_each(iter, rdyq) {
4244+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4245+ if (iter_dvc->cur_budget > 0) {
4246+ iter_dvc->cur_budget -= consume;
4247+ if (iter_dvc->cur_budget < 0) {
4248+ iter_dvc->budget = 0;
4249+ }
4250+ return; // only burn one budget
4251+ }
4252+ }
4253+
4254+ return;
4255+}
4256+
4257+
4258+// most important function, called every budget time
4259+static struct task_slice
4260+periodic_schedule(s_time_t now) {
4261+ const int cpu = smp_processor_id();
4262+ struct list_head *runq = RUNQ(cpu);
4263+ struct rt_vcpu *scurr = RT_VCPU(current);
4264+ struct rt_vcpu *snext;
4265+ struct task_slice ret;
4266+
4267+ RT_VCPU_CHECK(current);
4268+
4269+ if ((scurr->vcpu->domain->domain_id != 0)) {
4270+ if (!is_idle_vcpu(scurr->vcpu)) {
4271+ repq_burn(scurr, now);
4272+ } else if (cpu == 1) { //scurr is the idle vcpu on cpu 1, need to deal with periodic server
4273+ repq_burn_rdyq(scurr, now);
4274+ }
4275+ }
4276+
4277+ if (vcpu_runnable(current)) {
4278+ if (!__vcpu_on_runq(scurr)) {
4279+ __runq_insert(cpu, scurr);
4280+ }
4281+ } else {
4282+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
4283+ if (!__vcpu_on_rdyq(scurr)) {
4284+ __rdyq_insert(cpu, scurr);
4285+ }
4286+ }
4287+
4288+ if ( (__rdyq_pick(cpu) == NULL) || (__runq_pick(cpu)->level < __rdyq_pick(cpu)->level) ) {
4289+ snext = __runq_pick(cpu);
4290+ } else {
4291+ snext = __runq_pick_idle(cpu); // pick the IDLE to mimic the as if budget idled away behavior
4292+ }
4293+
4294+ if (snext->vcpu->domain->domain_id != 0) {
4295+ snext->last_start_time = NOW();
4296+ }
4297+
4298+ BUG_ON(!__vcpu_on_runq(snext));
4299+ __runq_remove(snext);
4300+
4301+ ret.time = BUDGET(1);
4302+ ret.task = snext->vcpu;
4303+
4304+ RT_VCPU_CHECK(ret.task);
4305+
4306+ BUG_ON(!vcpu_runnable(snext->vcpu));
4307+
4308+ return ret;
4309+}
4310+
4311+const struct rt_scheduler sched_periodic_def = {
4312+ .name = "Pure Periodic Server Scheduler",
4313+ .opt_name = "pps",
4314+
4315+ .tick = repq_tick,
4316+ .vcpu_sleep = NULL,
4317+ .vcpu_wake = NULL,
4318+ .schedule = periodic_schedule
4319+};
4320diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_repq.h xen-4.0.1/xen/common/sched_rt_repq.h
4321--- xen/xen-4.0.1/xen/common/sched_rt_repq.h 1969-12-31 17:00:00.000000000 -0700
4322+++ xen-4.0.1/xen/common/sched_rt_repq.h 2011-05-02 21:06:21.000000000 -0600
4323@@ -0,0 +1,86 @@
4324+/******************************************************************************
4325+ * Real Time Xen scheduler Headfile, including the common data structures
4326+ *
4327+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4328+ * based on code by Jaewoo Lee (C) 2010 University of Pennsylvania
4329+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4330+ ******************************************************************************/
4331+
4332+
4333+/*********************************************
4334+ * Shared by the subschedulers
4335+*********************************************/
4336+
4337+//check the current repQ to see if a repl needs to happen
4338+//Even if the IDLE VCPU is running, just raise an interrupt to trigger the schedule function!!
4339+static int
4340+check_cpu_for_repl(int cpu) {
4341+ struct rt_pcpu * ppc = RT_PCPU(cpu);
4342+ int flag = 0; //used for interrupt
4343+
4344+ while((ppc->rep_size != 0) && ppc->repq[0].re_time < NOW()) {
4345+ ppc->repq[0].dvc->cur_budget += ppc->repq[0].re_amount;
4346+ if (ppc->repq[0].dvc->cur_budget > ppc->repq[0].dvc->budget) {
4347+ ppc->repq[0].dvc->cur_budget = ppc->repq[0].dvc->budget;
4348+ }
4349+
4350+ while (ppc->repq[0].dvc->next_time <= NOW()) {
4351+ ppc->repq[0].dvc->next_time += BUDGET(1) * ppc->repq[0].dvc->period;
4352+ }
4353+ rt_repq_insert(ppc->repq[0].dvc->vcpu->processor, ppc->repq[0].dvc, ppc->repq[0].dvc->budget);
4354+
4355+ if (ppc->repq[0].dvc->level < RT_CUR(cpu)->level) flag = 1; // need to raise an interrupt
4356+
4357+ // bug fix 0501
4358+ if (ppc->repq[0].dvc->level != RT_CUR(cpu)->level) { // do not change the current running one
4359+ ppc->repq[0].dvc->last_start_time = NOW();
4360+ }
4361+
4362+ rt_repq_remove(cpu);
4363+ }
4364+
4365+ return flag;
4366+}
4367+
4368+//ticked by pcpu tick in pcpu, used in the repq way
4369+static void
4370+repq_tick(void *_cpu) {
4371+ unsigned int cpu = (unsigned long) _cpu;
4372+ struct rt_pcpu *ppc = RT_PCPU(cpu);
4373+
4374+ BUG_ON(current->processor != cpu);
4375+
4376+ if (check_cpu_for_repl(cpu)) {
4377+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
4378+ }
4379+
4380+ set_timer(&ppc->ticker, NOW() + BUDGET(1));
4381+}
4382+
4383+static int
4384+repq_burn(struct rt_vcpu *dvc, s_time_t now) {
4385+ s_time_t delta;
4386+ unsigned int consume;
4387+
4388+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4389+
4390+ if (dvc->last_start_time == 0) {
4391+ dvc->last_start_time = now;
4392+ return 0;
4393+ }
4394+
4395+ delta = now - dvc->last_start_time;
4396+ BUG_ON(delta <= 0);
4397+
4398+ consume = ( delta/BUDGET(1) );
4399+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4400+
4401+ if (consume > dvc->cur_budget) {
4402+ dvc->cur_budget = 0;
4403+ } else {
4404+ dvc->cur_budget -= consume;
4405+ }
4406+
4407+ return consume;
4408+}
4409+
4410diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_ssps.c xen-4.0.1/xen/common/sched_rt_ssps.c
4411--- xen/xen-4.0.1/xen/common/sched_rt_ssps.c 1969-12-31 17:00:00.000000000 -0700
4412+++ xen-4.0.1/xen/common/sched_rt_ssps.c 2011-05-01 19:41:06.000000000 -0600
4413@@ -0,0 +1,197 @@
4414+/******************************************************************************
4415+ * Real Time Xen scheduler Framework
4416+ *
4417+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4418+ * based on code by Jaewoo Lee (C) U Penn
4419+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4420+ ******************************************************************************/
4421+
4422+#include <xen/config.h>
4423+#include <xen/init.h>
4424+#include <xen/lib.h>
4425+#include <xen/sched.h>
4426+#include <xen/domain.h>
4427+#include <xen/delay.h>
4428+#include <xen/event.h>
4429+#include <xen/time.h>
4430+#include <xen/perfc.h>
4431+#include <xen/sched-if.h>
4432+#include <xen/softirq.h>
4433+#include <asm/atomic.h>
4434+#include <xen/errno.h>
4435+#include <xen/keyhandler.h>
4436+#include "sched_rt.h"
4437+#include "sched_rt_repq.h"
4438+
4439+
4440+static int
4441+check_rdyq(int cpu) {
4442+ struct list_head * rdyq = RDYQ(cpu);
4443+ struct list_head * iter;
4444+
4445+ list_for_each(iter, rdyq) {
4446+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4447+ if (iter_dvc->cur_budget > 0) {
4448+ return 1;
4449+ }
4450+ }
4451+
4452+ return 0;
4453+}
4454+
4455+//burn the extra budget on RdyQ
4456+static void
4457+ssps_burn_rdyq(struct rt_vcpu *dvc, s_time_t now) {
4458+ s_time_t delta;
4459+ unsigned int consume;
4460+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
4461+ struct list_head * iter;
4462+
4463+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4464+
4465+ if (dvc->last_start_time == 0) {
4466+ dvc->last_start_time = now;
4467+ return;
4468+ }
4469+
4470+ delta = now - dvc->last_start_time;
4471+ BUG_ON(delta <= 0);
4472+
4473+ consume = ( delta/BUDGET(1) );
4474+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4475+
4476+ // burn budgets on RdyQ
4477+ list_for_each(iter, rdyq) {
4478+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4479+ if (iter_dvc->cur_budget > 0) {
4480+ //bug fix 0501
4481+
4482+ delta = now - iter_dvc->last_start_time;
4483+ // just get repled, skip this VCPU
4484+ if (delta < BUDGET(1)) {
4485+ continue;
4486+ }
4487+ if (consume > iter_dvc->cur_budget) {
4488+ iter_dvc->cur_budget = 0;
4489+ } else {
4490+ iter_dvc->cur_budget -= consume;
4491+ }
4492+ return; // only burn one budget
4493+ }
4494+ }
4495+
4496+ return;
4497+}
4498+
4499+static void
4500+ssps_burn_extra(int cpu, int consume) {
4501+ struct list_head * rdyq = RDYQ(cpu);
4502+ struct list_head * iter;
4503+
4504+ // burn budgets on RdyQ
4505+ list_for_each(iter, rdyq) {
4506+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4507+ if (iter_dvc->cur_budget > 0) {
4508+ if (consume > iter_dvc->cur_budget) {
4509+ iter_dvc->cur_budget = 0;
4510+ } else {
4511+ iter_dvc->cur_budget -= consume;
4512+ }
4513+ return; // only burn one budget
4514+ }
4515+ }
4516+
4517+ return;
4518+}
4519+
4520+//pick the first vcpu whose budget is >0 from the runq
4521+static inline struct rt_vcpu *
4522+__ssps_runq_pick(unsigned int cpu) {
4523+ struct list_head * runq = RUNQ(cpu);
4524+ struct list_head * iter;
4525+
4526+ list_for_each(iter, runq) {
4527+ struct rt_vcpu * iter_dvc = __runq_elem(iter);
4528+ return iter_dvc;
4529+ }
4530+
4531+ BUG_ON(1);
4532+ return NULL;
4533+}
4534+
4535+// most important function, called every budget time
4536+static struct task_slice
4537+ssps_schedule(s_time_t now) {
4538+ const int cpu = smp_processor_id();
4539+ struct list_head *runq = RUNQ(cpu);
4540+ struct rt_vcpu *scurr = RT_VCPU(current);
4541+ struct rt_vcpu *snext;
4542+ struct task_slice ret;
4543+ int consume;
4544+ int old_budget;
4545+
4546+ RT_VCPU_CHECK(current);
4547+
4548+ if ((scurr->vcpu->domain->domain_id != 0)) {
4549+ if (!is_idle_vcpu(scurr->vcpu)) {
4550+ //check how many budget should burn
4551+ old_budget = scurr->cur_budget;
4552+ if (old_budget > 0) {
4553+ consume = repq_burn(scurr, now);
4554+ if (consume != 0 && __rdyq_pick(cpu) != NULL && __rdyq_pick(cpu)->level < scurr->level) {
4555+ scurr->cur_budget = old_budget; //restore its original budget
4556+ ssps_burn_extra(cpu, consume); // burn the one on rdyq instead
4557+ }
4558+ } else {
4559+ ssps_burn_rdyq(scurr, now);
4560+ }
4561+ } else {
4562+ ssps_burn_rdyq(scurr, now); // idle VCPU, still need to burn the ones on rdyq
4563+ }
4564+ }
4565+
4566+ if (vcpu_runnable(current)) {
4567+ if (!__vcpu_on_runq(scurr)) {
4568+ __runq_insert(cpu, scurr);
4569+ }
4570+ } else {
4571+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
4572+ if (!__vcpu_on_rdyq(scurr)) {
4573+ __rdyq_insert(cpu, scurr);
4574+ }
4575+ }
4576+
4577+ snext = __runq_pick(cpu);
4578+ //slack stealing!!
4579+ if (is_idle_vcpu(snext->vcpu)) {
4580+ if (check_rdyq(snext->vcpu->processor)) {
4581+ snext = __ssps_runq_pick(cpu);
4582+ }
4583+ }
4584+
4585+ if (snext->vcpu->domain->domain_id != 0) {
4586+ snext->last_start_time = NOW();
4587+ }
4588+
4589+ BUG_ON(!__vcpu_on_runq(snext));
4590+ __runq_remove(snext);
4591+
4592+ ret.time = BUDGET(1);
4593+ ret.task = snext->vcpu;
4594+
4595+ RT_VCPU_CHECK(ret.task);
4596+
4597+ BUG_ON(!vcpu_runnable(snext->vcpu));
4598+
4599+ return ret;
4600+}
4601+
4602+
4603+const struct rt_scheduler sched_ssps_def = {
4604+ .name = "Slack Stealing Periodic Server Scheduler",
4605+ .opt_name = "ssps",
4606+ .tick = repq_tick,
4607+ .vcpu_sleep = NULL,
4608+ .vcpu_wake = NULL,
4609+ .schedule = ssps_schedule
4610+};
4611diff -ubrN xen/xen-4.0.1/xen/common/sched_rt_wcps.c xen-4.0.1/xen/common/sched_rt_wcps.c
4612--- xen/xen-4.0.1/xen/common/sched_rt_wcps.c 1969-12-31 17:00:00.000000000 -0700
4613+++ xen-4.0.1/xen/common/sched_rt_wcps.c 2011-05-01 13:24:27.000000000 -0600
4614@@ -0,0 +1,146 @@
4615+/******************************************************************************
4616+ * Real Time Xen scheduler Framework
4617+ *
4618+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4619+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4620+ ******************************************************************************/
4621+
4622+#include <xen/config.h>
4623+#include <xen/init.h>
4624+#include <xen/lib.h>
4625+#include <xen/sched.h>
4626+#include <xen/domain.h>
4627+#include <xen/delay.h>
4628+#include <xen/event.h>
4629+#include <xen/time.h>
4630+#include <xen/perfc.h>
4631+#include <xen/sched-if.h>
4632+#include <xen/softirq.h>
4633+#include <asm/atomic.h>
4634+#include <xen/errno.h>
4635+#include <xen/keyhandler.h>
4636+#include "sched_rt.h"
4637+#include "sched_rt_repq.h"
4638+
4639+//burn the extra budget on RdyQ
4640+static void
4641+wcps_burn_rdyq(struct rt_vcpu *dvc, s_time_t now) {
4642+ s_time_t delta;
4643+ unsigned int consume;
4644+ struct list_head * rdyq = RDYQ(dvc->vcpu->processor);
4645+ struct list_head * iter;
4646+
4647+ BUG_ON(dvc != RT_CUR(dvc->vcpu->processor));
4648+
4649+ if (dvc->last_start_time == 0) {
4650+ dvc->last_start_time = now;
4651+ return;
4652+ }
4653+
4654+ delta = now - dvc->last_start_time;
4655+ BUG_ON(delta <= 0);
4656+
4657+ consume = ( delta/BUDGET(1) );
4658+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
4659+
4660+ // burn budgets on RdyQ
4661+ list_for_each(iter, rdyq) {
4662+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4663+ if (iter_dvc->cur_budget > 0) {
4664+ if (consume > iter_dvc->cur_budget) {
4665+ iter_dvc->cur_budget = 0;
4666+ } else {
4667+ iter_dvc->cur_budget -= consume;
4668+ }
4669+ return; // only burn one budget
4670+ }
4671+ }
4672+
4673+ return;
4674+}
4675+
4676+
4677+static void
4678+wcps_burn_extra(int cpu, int consume) {
4679+ struct list_head * rdyq = RDYQ(cpu);
4680+ struct list_head * iter;
4681+
4682+ // burn budgets on RdyQ
4683+ list_for_each(iter, rdyq) {
4684+ struct rt_vcpu * iter_dvc = __rdyq_elem(iter);
4685+ if (iter_dvc->cur_budget > 0) {
4686+ if (consume > iter_dvc->cur_budget) {
4687+ iter_dvc->cur_budget = 0;
4688+ } else {
4689+ iter_dvc->cur_budget -= consume;
4690+ }
4691+ return; // only burn one budget
4692+ }
4693+ }
4694+
4695+ return;
4696+}
4697+
4698+
4699+// most important function, called every budget time
4700+static struct task_slice
4701+wcps_schedule(s_time_t now) {
4702+ const int cpu = smp_processor_id();
4703+ struct list_head *runq = RUNQ(cpu);
4704+ struct rt_vcpu *scurr = RT_VCPU(current);
4705+ struct rt_vcpu *snext;
4706+ struct task_slice ret;
4707+ int consume;
4708+
4709+ RT_VCPU_CHECK(current);
4710+
4711+ if ((scurr->vcpu->domain->domain_id != 0)) {
4712+ if (!is_idle_vcpu(scurr->vcpu)) {
4713+ consume = repq_burn(scurr, now);
4714+ if (consume != 0 && __rdyq_pick(cpu) != NULL && __rdyq_pick(cpu)->level < scurr->level) {
4715+ wcps_burn_extra(cpu, consume); // burn the extra budget on rdyq, mimic the idled away behavior
4716+ }
4717+ } else if (cpu == 1) {
4718+ wcps_burn_rdyq(scurr, now);
4719+ }
4720+ }
4721+
4722+ if (vcpu_runnable(current)) {
4723+ if (!__vcpu_on_runq(scurr)) {
4724+ __runq_insert(cpu, scurr);
4725+ }
4726+ } else {
4727+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
4728+ if (!__vcpu_on_rdyq(scurr)) {
4729+ __rdyq_insert(cpu, scurr);
4730+ }
4731+ }
4732+
4733+ snext = __runq_pick(cpu);
4734+
4735+ if (snext->vcpu->domain->domain_id != 0) {
4736+ snext->last_start_time = NOW();
4737+ }
4738+
4739+ BUG_ON(!__vcpu_on_runq(snext));
4740+ __runq_remove(snext);
4741+
4742+ ret.time = BUDGET(1);
4743+ ret.task = snext->vcpu;
4744+
4745+ RT_VCPU_CHECK(ret.task);
4746+
4747+ BUG_ON(!vcpu_runnable(snext->vcpu));
4748+
4749+ return ret;
4750+}
4751+
4752+const struct rt_scheduler sched_wcps_def = {
4753+ .name = "Work Conserving Periodic Server Scheduler",
4754+ .opt_name = "wcps",
4755+
4756+ .tick = repq_tick,
4757+ .vcpu_sleep = NULL,
4758+ .vcpu_wake = NULL,
4759+ .schedule = wcps_schedule,
4760+};
4761diff -ubrN xen/xen-4.0.1/xen/common/sched_sedf.c xen-4.0.1/xen/common/sched_sedf.c
4762--- xen/xen-4.0.1/xen/common/sched_sedf.c 2010-08-25 04:22:12.000000000 -0600
4763+++ xen-4.0.1/xen/common/sched_sedf.c 2011-04-09 23:29:38.000000000 -0600
4764@@ -1429,6 +1429,11 @@
4765 }
4766
4767 rc = sedf_adjust_weights(op);
4768+
4769+ if (p->domain_id == 0) {
4770+ return 1;
4771+ }
4772+
4773 if ( rc )
4774 return rc;
4775
4776@@ -1453,6 +1458,7 @@
4777 }
4778
4779 PRINT(2,"sedf_adjust_finished\n");
4780+
4781 return 0;
4782 }
4783
4784diff -ubrN xen/xen-4.0.1/xen/common/sched_ss.c xen-4.0.1/xen/common/sched_ss.c
4785--- xen/xen-4.0.1/xen/common/sched_ss.c 1969-12-31 17:00:00.000000000 -0700
4786+++ xen-4.0.1/xen/common/sched_ss.c 2011-01-21 08:38:10.000000000 -0700
4787@@ -0,0 +1,884 @@
4788+/******************************************************************************
4789+ * Sporadic Server scheduler for xen
4790+ *
4791+ * by Sisu Xi (C) 2010 Washington University in St. Louis
4792+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
4793+ ******************************************************************************/
4794+
4795+#include <xen/config.h>
4796+#include <xen/init.h>
4797+#include <xen/lib.h>
4798+#include <xen/sched.h>
4799+#include <xen/domain.h>
4800+#include <xen/delay.h>
4801+#include <xen/event.h>
4802+#include <xen/time.h>
4803+#include <xen/perfc.h>
4804+#include <xen/sched-if.h>
4805+#include <xen/softirq.h>
4806+#include <asm/atomic.h>
4807+#include <xen/errno.h>
4808+#include <xen/keyhandler.h>
4809+
4810+#define SS_DOM(_dom) ((struct ss_dom *) (_dom)->sched_priv)
4811+#define SS_PCPU(_c) ((struct ss_pcpu *)per_cpu(schedule_data, _c).sched_priv)
4812+#define SS_VCPU(_vcpu) ((struct ss_vcpu *) (_vcpu)->sched_priv)
4813+#define RUNQ(_cpu) (&(SS_PCPU(_cpu)->runq))
4814+#define SS_CUR(_cpu) SS_VCPU(per_cpu(schedule_data, _cpu).curr)
4815+#define BUDGET(_b) (MILLISECS(_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
4816+
4817+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
4818+
4819+#define SS_DOM_0_PERIOD 100
4820+#define SS_IDLE_PERIOD 200
4821+
4822+#define SS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
4823+#define SS_DOM_PERIOD 50
4824+
4825+//used for status
4826+#define IDLE 0
4827+#define ACTIVE 1
4828+
4829+//used for replenishment
4830+struct rep_elem {
4831+ s_time_t re_time;
4832+ uint16_t re_amount;
4833+ struct ss_vcpu *svc;
4834+};
4835+
4836+//physical cpu
4837+struct ss_pcpu {
4838+ struct list_head runq; // runQ on the pcpu, organized by linked list
4839+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
4840+ int rep_size; // current size
4841+ int rep_capacity; // upper limit
4842+ struct timer ticker; // for preemptive use, tick every budget
4843+};
4844+
4845+//virtual cpu
4846+struct ss_vcpu {
4847+ struct list_head runq_elem;
4848+ struct ss_dom *sdom;
4849+ struct vcpu *vcpu;
4850+
4851+ uint16_t budget;
4852+ uint16_t period;
4853+
4854+ uint16_t cur_budget;
4855+ s_time_t last_start_time; // used for burn_budget
4856+ uint16_t burn_total; // used for budget repl
4857+ int status;
4858+
4859+ s_time_t next_time; // used for repl
4860+};
4861+
4862+//domain
4863+struct ss_dom {
4864+ struct domain *dom;
4865+ uint16_t budget;
4866+ uint16_t period;
4867+};
4868+
4869+//global variable, records the number of cpus
4870+struct ss_private {
4871+ spinlock_t lock;
4872+ uint32_t ncpus;
4873+};
4874+static struct ss_private ss_priv;
4875+
4876+/*
4877+//used for record, overhead measurement
4878+#define RECORD 4000
4879+struct record_elem{
4880+ int curr;
4881+ int next;
4882+ s_time_t enter_base; // enter rep insert time
4883+ s_time_t leave_base; // leave rep insert time
4884+ s_time_t enter; // enter schedule time
4885+ s_time_t leave; // leave schedule time
4886+};
4887+*/
4888+struct timer ss_start_timer; // would start after 10s, used only once
4889+int ss_start_flag = 0; // start to record or not
4890+int ss_wake = 0;
4891+/*
4892+int idx = 0; //idx to record
4893+struct record_elem res[RECORD]; // domain_id, time in ms;
4894+//finish for the record
4895+*/
4896+static void ss_tick(void *_cpu);
4897+
4898+//dump the repq
4899+static void
4900+ss_dump_repq(int cpu) {
4901+ int loop = 0;
4902+ struct ss_pcpu *spc = SS_PCPU(cpu);
4903+
4904+ printk("\n# into %s on cpu %d, now is %lu, size: %d, the repQ is :\n", __func__, cpu, NOW(), spc->rep_size);
4905+ for (loop = 0; loop < spc->rep_size; loop++) {
4906+ printk("\t[%d. %d]: %d @ %lu\n",
4907+ spc->repq[loop].svc->vcpu->domain->domain_id,
4908+ spc->repq[loop].svc->vcpu->vcpu_id,
4909+ spc->repq[loop].re_amount,
4910+ spc->repq[loop].re_time);
4911+ }
4912+}
4913+
4914+//dump the virtual cpu
4915+static void
4916+ss_dump_vcpu(struct ss_vcpu *svc) {
4917+ printk("\t[%i, %i], (%i, %i), cpu: %i, cur_budget: %i, last_start_time: %lu, burn_total: %i, status %d, next_time: %lu\n",
4918+ svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id, svc->budget, svc->period, svc->vcpu->processor,
4919+ svc->cur_budget, svc->last_start_time, svc->burn_total, svc->status, svc->next_time);
4920+}
4921+
4922+//inlined code
4923+static inline struct ss_vcpu *
4924+__runq_elem(struct list_head *elem) {
4925+ return list_entry(elem, struct ss_vcpu, runq_elem);
4926+}
4927+
4928+//dump the physical cpu
4929+static void
4930+ss_dump_pcpu(int cpu) {
4931+ struct list_head *iter;
4932+ struct ss_pcpu *spc = SS_PCPU(cpu);
4933+ struct list_head *runq = &spc->runq;
4934+ struct ss_vcpu *svc = SS_CUR(cpu);
4935+ int loop = 0;
4936+
4937+ printk("\n# into %s, on cpu: %d, now is: %lu\n", __func__, cpu, NOW());
4938+
4939+ if (svc) {
4940+ printk("\trun: ");
4941+ ss_dump_vcpu(svc);
4942+ }
4943+
4944+ list_for_each(iter, runq) {
4945+ svc = __runq_elem(iter);
4946+ if (svc) {
4947+ printk("\t%3d: ", ++loop);
4948+ ss_dump_vcpu(svc);
4949+ }
4950+ }
4951+
4952+ ss_dump_repq(cpu);
4953+}
4954+/*
4955+//dump the record out.
4956+static void
4957+ss_dump_record(void) {
4958+ int i;
4959+
4960+ for (i = 1; i < RECORD; i++) {
4961+ printk("%-3d %-3d %13lu %13lu %13lu %13lu\n", res[i].curr, res[i].next, res[i].enter_base, res[i].leave_base, res[i].enter, res[i].leave);
4962+ }
4963+ ss_dump_pcpu(1);
4964+ idx = 0;
4965+ start_flag = 0;
4966+}
4967+
4968+*/
4969+// the current vcpu is on runQ?
4970+static inline int
4971+__vcpu_on_runq(struct ss_vcpu *svc) {
4972+ return !list_empty(&svc->runq_elem);
4973+}
4974+
4975+//pick the first vcpu whose budget is >0 from the runq
4976+static inline struct ss_vcpu *
4977+__runq_pick(unsigned int cpu) {
4978+ struct list_head * runq = RUNQ(cpu);
4979+ struct list_head * iter;
4980+
4981+ list_for_each(iter, runq) {
4982+ struct ss_vcpu * iter_svc = __runq_elem(iter);
4983+ if (iter_svc->cur_budget > 0) {
4984+ return iter_svc;
4985+ }
4986+ }
4987+
4988+ BUG_ON(1);
4989+ return NULL;
4990+}
4991+
4992+//insert into the runq, followed a FIFO way. sorted by period
4993+static inline void
4994+__runq_insert(unsigned int cpu, struct ss_vcpu *svc) {
4995+ struct list_head * runq = RUNQ(cpu);
4996+ struct list_head * iter;
4997+
4998+ BUG_ON(__vcpu_on_runq(svc));
4999+ BUG_ON(cpu != svc->vcpu->processor);
5000+
5001+ list_for_each(iter, runq) {
5002+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5003+ if (svc->vcpu->domain->domain_id <= iter_svc->vcpu->domain->domain_id) {
5004+ break;
5005+ }
5006+ }
5007+
5008+ list_add_tail(&svc->runq_elem, iter);
5009+}
5010+
5011+//remove it from runQ
5012+static inline void
5013+__runq_remove(struct ss_vcpu *svc) {
5014+ BUG_ON(!__vcpu_on_runq(svc));
5015+ list_del_init(&svc->runq_elem);
5016+}
5017+
5018+//used for the heap, repQ
5019+static inline int
5020+ss_rep_parent(int childIdx) {
5021+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
5022+}
5023+
5024+//insert into the repQ
5025+static inline void
5026+ss_repq_insert(unsigned int cpu, struct ss_vcpu *svc, int amount) {
5027+ struct ss_pcpu * spc = SS_PCPU(cpu);
5028+ int childIdx, parentIdx;
5029+
5030+ if (amount == 0) {
5031+ svc->next_time = 0;
5032+ return;
5033+ }
5034+
5035+ if (svc->next_time == 0) {
5036+ printk("\n# in %s, ERROR! svc is:", __func__);
5037+ ss_dump_vcpu(svc);
5038+ ss_dump_pcpu(cpu);
5039+ BUG_ON(1);
5040+ }
5041+
5042+ if (spc->rep_size == spc->rep_capacity) {
5043+ printk("\n# into %s, repQ full!!\n", __func__);
5044+ BUG_ON(1);
5045+ }
5046+
5047+ childIdx = spc->rep_size;
5048+ parentIdx = ss_rep_parent(childIdx);
5049+
5050+
5051+ while (childIdx > 0 && svc->next_time < spc->repq[parentIdx].re_time) {
5052+ spc->repq[childIdx] = spc->repq[parentIdx];
5053+ childIdx = parentIdx;
5054+ parentIdx = ss_rep_parent(childIdx);
5055+ }
5056+
5057+ spc->repq[childIdx].re_time = svc->next_time;
5058+ spc->repq[childIdx].re_amount = amount;
5059+ spc->repq[childIdx].svc = svc;
5060+ spc->rep_size++;
5061+/*
5062+ printk("\t add a repl. now: %lu, cpu: %d, re_time: %lu, amount: %d, for cpu [%d, %d]\n",
5063+ NOW(), cpu, svc->next_time, amount, svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id);
5064+ ss_dump_vcpu(svc);
5065+*/
5066+ svc->next_time = 0;
5067+}
5068+
5069+//remove from the repQ
5070+static inline void
5071+ss_repq_remove(unsigned int cpu) {
5072+ struct ss_pcpu * spc = SS_PCPU(cpu);
5073+ int childIdx = 1;
5074+ int rightChildIdx;
5075+ int rootIdx = 0;
5076+ struct rep_elem temp;
5077+
5078+ BUG_ON(spc->rep_size <= 0);
5079+
5080+ spc->repq[0] = spc->repq[spc->rep_size - 1];
5081+ spc->rep_size--;
5082+
5083+ temp = spc->repq[0];
5084+
5085+ while (childIdx < spc->rep_size) {
5086+ rightChildIdx = childIdx + 1;
5087+ if (rightChildIdx < spc->rep_size && spc->repq[rightChildIdx].re_time < spc->repq[childIdx].re_time) {
5088+ childIdx = rightChildIdx;
5089+ }
5090+ if (spc->repq[childIdx].re_time < temp.re_time) {
5091+ spc->repq[rootIdx] = spc->repq[childIdx];
5092+ rootIdx = childIdx;
5093+ childIdx = 2 * rootIdx + 1;
5094+ } else {
5095+ break;
5096+ }
5097+ }
5098+ spc->repq[rootIdx] = temp;
5099+}
5100+
5101+//svc should be snext. Doing this is because we can not get snext->period
5102+//scan the runQ to change status, deside next time or amount
5103+static void
5104+ss_scan_runq(unsigned int cpu, struct ss_vcpu *svc) {
5105+ struct list_head * runq = RUNQ(cpu);
5106+ struct ss_vcpu *cur = svc;
5107+ struct list_head * iter;
5108+ int re_amount;
5109+
5110+ list_for_each(iter, runq) {
5111+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5112+ if (is_idle_vcpu(iter_svc->vcpu)) {
5113+ return;
5114+ }
5115+
5116+ if (iter_svc->vcpu->domain->domain_id < cur->vcpu->domain->domain_id) {
5117+ if (iter_svc->status == ACTIVE) {
5118+ //change from ACTIVE to IDLE, decide the repl amount
5119+ BUG_ON(iter_svc->next_time == 0);
5120+ iter_svc->status = IDLE;
5121+ re_amount = iter_svc->burn_total;
5122+ iter_svc->burn_total = 0;
5123+ ss_repq_insert(cpu, iter_svc, re_amount);
5124+ }
5125+ } else {
5126+ if (iter_svc->status == IDLE) {
5127+ //mark it to be ACTIVE, decide the repl time
5128+ iter_svc->status = ACTIVE;
5129+ BUG_ON(iter_svc->next_time != 0);
5130+ iter_svc->next_time = NOW() + BUDGET(iter_svc->period);
5131+ }
5132+ }
5133+ }
5134+}
5135+
5136+//dump dump function
5137+static void
5138+ss_dump(void) {
5139+ printk("# into %s.\n", __func__);
5140+}
5141+
5142+//burn the scurr budget
5143+static void
5144+burn_budgets(struct ss_vcpu *svc, s_time_t now) {
5145+ s_time_t delta;
5146+ unsigned int consume;
5147+
5148+ BUG_ON(svc != SS_CUR(svc->vcpu->processor));
5149+
5150+ if (svc->last_start_time == 0) {
5151+ svc->last_start_time = now;
5152+ return;
5153+ }
5154+
5155+ delta = now - svc->last_start_time;
5156+ BUG_ON(delta <= 0);
5157+
5158+ consume = ( delta/BUDGET(1) );
5159+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
5160+ if (consume > svc->cur_budget) {
5161+ //printk("\n# into %s, this should not happen!\n", __func__);
5162+ consume = svc->cur_budget;
5163+ }
5164+
5165+ svc->cur_budget -= consume;
5166+ svc->burn_total += consume;
5167+}
5168+
5169+//init the physical cpu
5170+static int
5171+ss_pcpu_init(int cpu) {
5172+ struct ss_pcpu *spc;
5173+ unsigned long flags;
5174+
5175+ /* Allocate per-PCPU info */
5176+ spc = xmalloc(struct ss_pcpu);
5177+ if (spc == NULL)
5178+ return -1;
5179+ memset(spc, 0, sizeof (*spc));
5180+
5181+ spin_lock_irqsave(&ss_priv.lock, flags);
5182+
5183+ if (ss_priv.ncpus < cpu)
5184+ ss_priv.ncpus = cpu + 1;
5185+
5186+ init_timer(&spc->ticker, ss_tick, (void *) (unsigned long) cpu, cpu);
5187+ INIT_LIST_HEAD(&spc->runq);
5188+ per_cpu(schedule_data, cpu).sched_priv = spc;
5189+
5190+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
5191+
5192+ spc->rep_capacity = REPQ_CAPACITY;
5193+ spc->repq = xmalloc_array(struct rep_elem, spc->rep_capacity);
5194+ BUG_ON(spc->repq == NULL);
5195+ spc->rep_size = 0;
5196+
5197+ spin_unlock_irqrestore(&ss_priv.lock, flags);
5198+
5199+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
5200+
5201+ return 0;
5202+}
5203+
5204+//check the vcpu
5205+static inline void
5206+__ss_vcpu_check(struct vcpu *vc) {
5207+ struct ss_vcpu * const svc = SS_VCPU(vc);
5208+ struct ss_dom * const sdom = svc->sdom;
5209+
5210+ BUG_ON(svc->vcpu != vc);
5211+ BUG_ON(sdom != SS_DOM(vc->domain));
5212+ if (sdom) {
5213+ BUG_ON(is_idle_vcpu(vc));
5214+ BUG_ON(sdom->dom != vc->domain);
5215+ } else {
5216+ BUG_ON(!is_idle_vcpu(vc));
5217+ }
5218+}
5219+#define SS_VCPU_CHECK(_vc) (__ss_vcpu_check(_vc))
5220+
5221+//pick a cpu to run, used to migrate from different cpus
5222+static int
5223+ss_cpu_pick(struct vcpu *vc) {
5224+ cpumask_t cpus;
5225+ int cpu;
5226+
5227+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
5228+
5229+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
5230+ return cycle_cpu(vc->processor, cpus);
5231+ }
5232+
5233+ cpu = cpu_isset(vc->processor, cpus)
5234+ ? vc->processor
5235+ : cycle_cpu(vc->processor, cpus);
5236+
5237+ return cpu;
5238+}
5239+
5240+//check the current repQ to see if a repl needs to happen
5241+static int
5242+check_cpu_for_repl(int cpu) {
5243+ int ret = 0;
5244+ struct ss_pcpu * spc = SS_PCPU(cpu);
5245+
5246+ while((spc->rep_size != 0) && spc->repq[0].re_time < NOW()) {
5247+ spc->repq[0].svc->cur_budget += spc->repq[0].re_amount;
5248+ if (spc->repq[0].svc->cur_budget > spc->repq[0].svc->budget) {
5249+ printk("\n# into %s, this should not happen!\n", __func__);
5250+ spc->repq[0].svc->cur_budget = spc->repq[0].svc->budget;
5251+ }
5252+ ss_repq_remove(cpu);
5253+ ret = 1;
5254+ }
5255+
5256+ return ret;
5257+}
5258+
5259+//if a repl happens, do we need an interrupt? (higher priority than current running one)
5260+static void
5261+check_runq_for_interrupt(int cpu) {
5262+ struct list_head * runq = RUNQ(cpu);
5263+ struct list_head * iter;
5264+ struct ss_vcpu * cur = SS_CUR(cpu);
5265+
5266+ list_for_each(iter, runq) {
5267+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5268+ if (iter_svc->vcpu->domain->domain_id >= cur->vcpu->domain->domain_id) {
5269+ return;
5270+ } else if (iter_svc->cur_budget > 0) {
5271+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
5272+ }
5273+ }
5274+}
5275+
5276+//init the virtual cpu
5277+static int
5278+ss_vcpu_init(struct vcpu *vc) {
5279+ struct domain * const dom = vc->domain;
5280+ struct ss_dom *sdom = SS_DOM(dom);
5281+ struct ss_vcpu *svc;
5282+
5283+ /* Allocate per-VCPU info */
5284+ svc = xmalloc(struct ss_vcpu);
5285+ if (svc == NULL) {
5286+ return -1;
5287+ }
5288+ memset(svc, 0, sizeof (*svc));
5289+
5290+ INIT_LIST_HEAD(&svc->runq_elem);
5291+ svc->sdom = sdom;
5292+ svc->vcpu = vc;
5293+ svc->budget = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->budget;
5294+ svc->period = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->period;
5295+ svc->cur_budget = svc->budget;
5296+
5297+ svc->last_start_time = 0;
5298+ svc->burn_total = 0;
5299+ svc->next_time = 0;
5300+ svc->status = IDLE;
5301+ vc->sched_priv = svc;
5302+
5303+ /* Allocate per-PCPU info */
5304+ if (unlikely(!SS_PCPU(vc->processor))) {
5305+ if (ss_pcpu_init(vc->processor) != 0)
5306+ return -1;
5307+ }
5308+
5309+ SS_VCPU_CHECK(vc);
5310+
5311+ printk("\n# into %s, vcpu init: ", __func__);
5312+ ss_dump_vcpu(svc);
5313+
5314+ return 0;
5315+}
5316+
5317+//destory the vcpu
5318+static void
5319+ss_vcpu_destroy(struct vcpu *vc) {
5320+ struct ss_vcpu * const svc = SS_VCPU(vc);
5321+ struct ss_dom * const sdom = svc->sdom;
5322+
5323+ printk("\n# into %s, vcpu destroy: ", __func__);
5324+ ss_dump_vcpu(svc);
5325+
5326+ BUG_ON(sdom == NULL);
5327+ BUG_ON(!list_empty(&svc->runq_elem));
5328+
5329+ xfree(svc);
5330+}
5331+
5332+//sleep the vcpu
5333+static void
5334+ss_vcpu_sleep(struct vcpu *vc) {
5335+ struct ss_vcpu * const svc = SS_VCPU(vc);
5336+
5337+ if (vc->domain->domain_id != 0) {
5338+ printk("\n# into %s: now %lu, sleep vcpu: \n", __func__, NOW());
5339+ ss_dump_vcpu(svc);
5340+ }
5341+
5342+ BUG_ON(is_idle_vcpu(vc));
5343+
5344+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
5345+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
5346+ } else if (__vcpu_on_runq(svc)) {
5347+ //BUG_ON(svc->status == ACTIVE);
5348+ __runq_remove(svc);
5349+ }
5350+}
5351+
5352+//wake up the vcpu, insert it into runq, raise a softirq
5353+static void
5354+ss_vcpu_wake(struct vcpu *vc) {
5355+ struct ss_vcpu * const svc = SS_VCPU(vc);
5356+ const unsigned int cpu = vc->processor;
5357+
5358+ BUG_ON(is_idle_vcpu(vc));
5359+
5360+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
5361+ //printk("\n# why wake up running? migration?\n");
5362+ return;
5363+ }
5364+ if (unlikely(__vcpu_on_runq(svc))) {
5365+ //printk("\n# why wake up on runq ones? migration?\n");
5366+ return;
5367+ }
5368+
5369+ __runq_insert(cpu, svc);
5370+ if (svc->vcpu->domain->domain_id < SS_CUR(cpu)->vcpu->domain->domain_id) {
5371+ if (svc->vcpu->processor == 1 && ss_start_flag == 1) {
5372+ ss_wake++;
5373+ }
5374+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
5375+ }
5376+}
5377+
5378+//used for record data, for overhead measurement
5379+static void
5380+ss_ss_finish_timer(void * temp) {
5381+ ss_start_flag = 0;
5382+ printk("wake up %d times\n", ss_wake);
5383+ ss_wake = 0;
5384+}
5385+
5386+static void
5387+ss_ss_start_timer(void * temp) {
5388+ ss_start_flag = 1;
5389+ init_timer(&ss_start_timer, ss_ss_finish_timer, (void *) (unsigned int) 1, 1);
5390+ set_timer(&ss_start_timer, NOW() + MILLISECS(10000));
5391+}
5392+
5393+//adjust the domain's budget & period, also used to trigger the record
5394+static int
5395+ss_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
5396+ struct ss_dom * const sdom = SS_DOM(d);
5397+ unsigned long flags;
5398+ struct ss_vcpu *svc = SS_VCPU(d->vcpu[0]);
5399+
5400+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
5401+ op->u.ss.budget = sdom->budget;
5402+ op->u.ss.period = sdom->period;
5403+ //ss_dump_vcpu(svc);
5404+ } else {
5405+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
5406+
5407+ spin_lock_irqsave(&ss_priv.lock, flags);
5408+ if (op->u.ss.budget != 0) {
5409+ sdom->budget = op->u.ss.budget;
5410+ svc->budget = op->u.ss.budget;
5411+ }
5412+ if (op->u.ss.period != 0) {
5413+ sdom->period = op->u.ss.period;
5414+ svc->period = op->u.ss.period;
5415+ }
5416+ svc->cur_budget = svc->budget;
5417+ spin_unlock_irqrestore(&ss_priv.lock, flags);
5418+
5419+ if (svc->vcpu->domain->domain_id == 0) {
5420+ init_timer(&ss_start_timer, ss_ss_start_timer, (void *) (unsigned int) 1, 1);
5421+ set_timer(&ss_start_timer, NOW() + MILLISECS(5000));
5422+ return 1;
5423+ }
5424+
5425+ //ss_dump_vcpu(svc);
5426+ }
5427+
5428+ return 0;
5429+}
5430+
5431+//init a dom
5432+static int
5433+ss_dom_init(struct domain *dom) {
5434+ struct ss_dom *sdom;
5435+
5436+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
5437+
5438+ if (is_idle_domain(dom)) {
5439+ printk("\t# init an idle domain\n");
5440+ return 0;
5441+ }
5442+
5443+ sdom = xmalloc(struct ss_dom);
5444+ if (sdom == NULL)
5445+ return -ENOMEM;
5446+ memset(sdom, 0, sizeof (*sdom));
5447+
5448+ /* Initialize budget and period */
5449+ sdom->dom = dom;
5450+
5451+ switch(dom->domain_id) {
5452+ case 32767:
5453+ sdom->budget = SS_IDLE_PERIOD;
5454+ sdom->period = SS_IDLE_PERIOD;
5455+ break;
5456+ case 0:
5457+ sdom->budget = SS_DOM_0_PERIOD;
5458+ sdom->period = SS_DOM_0_PERIOD;
5459+ break;
5460+ default:
5461+ sdom->budget = SS_DOM_BUDGET;
5462+ sdom->period = SS_DOM_PERIOD;
5463+ break;
5464+ }
5465+
5466+ dom->sched_priv = sdom;
5467+
5468+ return 0;
5469+}
5470+
5471+//destory a domain
5472+static void
5473+ss_dom_destroy(struct domain *dom) {
5474+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
5475+ xfree(SS_DOM(dom));
5476+}
5477+
5478+//ticked by pcpu tick in pcpu.
5479+static void
5480+ss_tick(void *_cpu) {
5481+ unsigned int cpu = (unsigned long) _cpu;
5482+ struct ss_pcpu *spc = SS_PCPU(cpu);
5483+
5484+ BUG_ON(current->processor != cpu);
5485+
5486+ if (check_cpu_for_repl(cpu)) {
5487+ check_runq_for_interrupt(cpu);
5488+ }
5489+
5490+ if (ss_cpu_pick(current) != cpu) {
5491+ set_bit(_VPF_migrating, &current->pause_flags);
5492+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
5493+ }
5494+
5495+ set_timer(&spc->ticker, NOW() + BUDGET(1));
5496+}
5497+
5498+// most important function, called every budget time
5499+static struct task_slice
5500+ss_schedule(s_time_t now) {
5501+ const int cpu = smp_processor_id();
5502+ struct list_head *runq = RUNQ(cpu);
5503+ struct ss_vcpu *scurr = SS_VCPU(current);
5504+ struct ss_vcpu *snext;
5505+ struct task_slice ret;
5506+ int re_amount;
5507+
5508+ SS_VCPU_CHECK(current);
5509+/*
5510+// for record
5511+ if (smp_processor_id() == 1 && start_flag == 1) {
5512+ if(is_idle_vcpu(scurr->vcpu)) res[idx].curr = 10;
5513+ else res[idx].curr = scurr->vcpu->domain->domain_id;
5514+ res[idx].enter_base = NOW();
5515+ res[idx].leave_base = NOW();
5516+ res[idx].enter = NOW();
5517+ }
5518+*/
5519+ if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
5520+ //if (!is_idle_vcpu(scurr->vcpu)) {
5521+ burn_budgets(scurr, now);
5522+ }
5523+
5524+ if (vcpu_runnable(current)) {
5525+ __runq_insert(cpu, scurr);
5526+ } else {
5527+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
5528+ }
5529+
5530+ snext = __runq_pick(cpu);
5531+
5532+ __runq_remove(snext);
5533+
5534+//context switch do happen!, and snext is not an idle vcpu
5535+ if (cpu == 1 && snext != scurr) {
5536+ //if (snext != scurr) {
5537+ //for the scurr:
5538+ //if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
5539+ if (!is_idle_vcpu(scurr->vcpu)) {
5540+ BUG_ON(scurr->status != ACTIVE);
5541+ BUG_ON(scurr->next_time == 0);
5542+ scurr->status = IDLE;
5543+ re_amount = scurr->burn_total;
5544+ scurr->burn_total = 0;
5545+ //printk("\n# into %s, change status to IDLE, decide repl amount here! now is %lu, for vcpu[%d, %d], re_amount is: %d, re_time is %lu\n",
5546+ // __func__, NOW(), scurr->vcpu->domain->domain_id, scurr->vcpu->vcpu_id, re_amount, scurr->next_time);
5547+ ss_repq_insert(cpu, scurr, re_amount);
5548+ }
5549+
5550+ //for the snext:
5551+ //if (!is_idle_vcpu(snext->vcpu) && snext->vcpu->domain->domain_id != 0) {
5552+ if (!is_idle_vcpu(snext->vcpu)) {
5553+ if (snext->status == IDLE) {
5554+ BUG_ON(snext->next_time != 0);
5555+ snext->status = ACTIVE;
5556+ snext->next_time = NOW() + BUDGET(snext->period);
5557+ //printk("\n# into %s, change status to ACTIVE, decide repl time here! now is %lu, for vcpu [%d, %d], re_time is %lu\n",
5558+ // __func__, NOW(), snext->vcpu->domain->domain_id, snext->vcpu->vcpu_id, snext->next_time);
5559+ }
5560+ }
5561+
5562+ //scan the whole runq
5563+ ss_scan_runq(cpu, snext);
5564+ }
5565+
5566+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
5567+ snext->last_start_time = NOW();
5568+ }
5569+
5570+ ret.time = (is_idle_vcpu(snext->vcpu) ? -1 : BUDGET(1));
5571+ //ret.time = BUDGET(1);
5572+ ret.task = snext->vcpu;
5573+
5574+ SS_VCPU_CHECK(ret.task);
5575+
5576+ BUG_ON(!vcpu_runnable(snext->vcpu));
5577+ //printk("now is %lu\n", now);
5578+
5579+/*
5580+// for record
5581+
5582+ if (smp_processor_id() == 1 && start_flag == 1) {
5583+ if(is_idle_vcpu(snext->vcpu)) res[idx].next = 10;
5584+ else res[idx].next = snext->vcpu->domain->domain_id;
5585+ res[idx].leave = NOW();
5586+ if(idx++ >= RECORD) {
5587+ ss_dump_pcpu(1);
5588+ ss_dump_record();
5589+ }
5590+ }
5591+*/
5592+ return ret;
5593+}
5594+
5595+//init the global data
5596+static void
5597+ss_init(void) {
5598+ printk("\n# into %s\n", __func__);
5599+ spin_lock_init(&ss_priv.lock);
5600+ ss_priv.ncpus = 0;
5601+}
5602+
5603+/* Tickers cannot be kicked until SMP subsystem is alive. */
5604+static __init int
5605+ss_start_tickers(void) {
5606+ struct ss_pcpu *spc;
5607+ unsigned int cpu;
5608+
5609+ printk("\n# into %s, start all tickers right now\n", __func__);
5610+
5611+ if (ss_priv.ncpus == 0)
5612+ return 0;
5613+
5614+ for_each_online_cpu(cpu) {
5615+ spc = SS_PCPU(cpu);
5616+ set_timer(&spc->ticker, NOW() + BUDGET(1));
5617+ }
5618+
5619+ return 0;
5620+}
5621+__initcall(ss_start_tickers);
5622+
5623+static void ss_tick_suspend(void) {
5624+ struct ss_pcpu *spc;
5625+
5626+ printk("\n# into %s, why is this called?\n", __func__);
5627+
5628+ spc = SS_PCPU(smp_processor_id());
5629+
5630+ stop_timer(&spc->ticker);
5631+}
5632+
5633+static void ss_tick_resume(void) {
5634+ struct ss_pcpu *spc;
5635+ uint64_t now = NOW();
5636+
5637+ printk("\n# into %s, why is this called?\n", __func__);
5638+
5639+ spc = SS_PCPU(smp_processor_id());
5640+
5641+ set_timer(&spc->ticker, now + BUDGET(1));
5642+}
5643+
5644+const struct scheduler sched_ss_def = {
5645+ .name = "Sporadic Server Scheduler",
5646+ .opt_name = "ss",
5647+ .sched_id = XEN_SCHEDULER_SS,
5648+
5649+ .init_domain = ss_dom_init,
5650+ .destroy_domain = ss_dom_destroy,
5651+
5652+ .init_vcpu = ss_vcpu_init,
5653+ .destroy_vcpu = ss_vcpu_destroy,
5654+
5655+ .init = ss_init,
5656+
5657+ .pick_cpu = ss_cpu_pick,
5658+
5659+ .tick_suspend = ss_tick_suspend,
5660+ .tick_resume = ss_tick_resume,
5661+
5662+ .do_schedule = ss_schedule,
5663+
5664+ .sleep = ss_vcpu_sleep,
5665+ .wake = ss_vcpu_wake,
5666+
5667+ .adjust = ss_dom_cntl,
5668+
5669+ .dump_cpu_state = ss_dump_pcpu,
5670+ .dump_settings = ss_dump,
5671+};
5672diff -ubrN xen/xen-4.0.1/xen/common/sched_ss_rtas11.c xen-4.0.1/xen/common/sched_ss_rtas11.c
5673--- xen/xen-4.0.1/xen/common/sched_ss_rtas11.c 1969-12-31 17:00:00.000000000 -0700
5674+++ xen-4.0.1/xen/common/sched_ss_rtas11.c 2010-12-16 00:46:03.000000000 -0700
5675@@ -0,0 +1,893 @@
5676+/******************************************************************************
5677+ * Sporadic Server scheduler for xen
5678+ *
5679+ * by Sisu Xi (C) 2010 Washington University in St. Louis
5680+ * based on code by Mark Williamson (C) 2004 Intel Research Cambridge
5681+ ******************************************************************************/
5682+
5683+#include <xen/config.h>
5684+#include <xen/init.h>
5685+#include <xen/lib.h>
5686+#include <xen/sched.h>
5687+#include <xen/domain.h>
5688+#include <xen/delay.h>
5689+#include <xen/event.h>
5690+#include <xen/time.h>
5691+#include <xen/perfc.h>
5692+#include <xen/sched-if.h>
5693+#include <xen/softirq.h>
5694+#include <asm/atomic.h>
5695+#include <xen/errno.h>
5696+#include <xen/keyhandler.h>
5697+
5698+#define SS_DOM(_dom) ((struct ss_dom *) (_dom)->sched_priv)
5699+#define SS_PCPU(_c) ((struct ss_pcpu *)per_cpu(schedule_data, _c).sched_priv)
5700+#define SS_VCPU(_vcpu) ((struct ss_vcpu *) (_vcpu)->sched_priv)
5701+#define RUNQ(_cpu) (&(SS_PCPU(_cpu)->runq))
5702+#define SS_CUR(_cpu) SS_VCPU(per_cpu(schedule_data, _cpu).curr)
5703+#define BUDGET(_b) (MILLISECS(_b)) // time to run for 1 budget, default setting is 1ms = 1 budget
5704+
5705+#define REPQ_CAPACITY 500 // repQ is used for the replenishment
5706+
5707+#define SS_DOM_0_PERIOD 100
5708+#define SS_IDLE_PERIOD 200
5709+
5710+#define SS_DOM_BUDGET 25 // default budget, can bu changed via xm sched-ss -d target -b budget -p period
5711+#define SS_DOM_PERIOD 50
5712+
5713+//used for status
5714+#define IDLE 0
5715+#define ACTIVE 1
5716+
5717+//used for replenishment
5718+struct rep_elem {
5719+ s_time_t re_time;
5720+ uint16_t re_amount;
5721+ struct ss_vcpu *svc;
5722+};
5723+
5724+//physical cpu
5725+struct ss_pcpu {
5726+ struct list_head runq; // runQ on the pcpu, organized by linked list
5727+ struct rep_elem *repq; //repQ on the pcpu, organized by heap
5728+ int rep_size; // current size, for later dynamic reqQ use. currently set equals to capacity
5729+ int rep_capacity; // upper limit
5730+ struct timer ticker; // for preemptive use, tick every budget
5731+};
5732+
5733+//virtual cpu
5734+struct ss_vcpu {
5735+ struct list_head runq_elem;
5736+ struct ss_dom *sdom;
5737+ struct vcpu *vcpu;
5738+
5739+ uint16_t budget;
5740+ uint16_t period;
5741+
5742+ uint16_t cur_budget;
5743+ s_time_t last_start_time; // used for burn_budget
5744+ uint16_t burn_total; // used for budget repl
5745+ int status;
5746+
5747+ s_time_t next_time; // used for repl
5748+};
5749+
5750+//domain
5751+struct ss_dom {
5752+ struct domain *dom;
5753+ uint16_t budget;
5754+ uint16_t period;
5755+};
5756+
5757+//global variable, records the number of cpus
5758+struct ss_private {
5759+ spinlock_t lock; // used for init
5760+ uint32_t ncpus; //number of physical cpus
5761+};
5762+static struct ss_private ss_priv;
5763+
5764+//used for record, overhead measurement
5765+#define RECORD 4000
5766+struct record_elem{
5767+ int curr;
5768+ int next;
5769+ s_time_t enter_base; // enter rep insert time
5770+ s_time_t leave_base; // leave rep insert time
5771+ s_time_t enter; // enter schedule time
5772+ s_time_t leave; // leave schedule time
5773+};
5774+
5775+struct timer start_timer; // would start after 10s, used only once
5776+int start_flag = 0; // start to record or not
5777+int idx = 0; //idx to record
5778+struct record_elem res[RECORD]; // domain_id, time in ms;
5779+//finish for the record
5780+
5781+static void ss_tick(void *_cpu);
5782+
5783+//dump the repq
5784+static void
5785+ss_dump_repq(int cpu) {
5786+ int loop = 0;
5787+ struct ss_pcpu *spc = SS_PCPU(cpu);
5788+
5789+ printk("\n# into %s on cpu %d, now is %lu, size: %d, the repQ is :\n", __func__, cpu, NOW(), spc->rep_size);
5790+ for (loop = 0; loop < spc->rep_size; loop++) {
5791+ printk("\t[%d. %d]: %d @ %lu\n",
5792+ spc->repq[loop].svc->vcpu->domain->domain_id,
5793+ spc->repq[loop].svc->vcpu->vcpu_id,
5794+ spc->repq[loop].re_amount,
5795+ spc->repq[loop].re_time);
5796+ }
5797+}
5798+
5799+//dump the virtual cpu
5800+static void
5801+ss_dump_vcpu(struct ss_vcpu *svc) {
5802+ printk("\t[%i, %i], (%i, %i), cpu: %i, cur_budget: %i, last_start_time: %lu, burn_total: %i, status %d, next_time: %lu\n",
5803+ svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id, svc->budget, svc->period, svc->vcpu->processor,
5804+ svc->cur_budget, svc->last_start_time, svc->burn_total, svc->status, svc->next_time);
5805+}
5806+
5807+//inlined code
5808+static inline struct ss_vcpu *
5809+__runq_elem(struct list_head *elem) {
5810+ return list_entry(elem, struct ss_vcpu, runq_elem);
5811+}
5812+
5813+//dump the physical cpu
5814+static void
5815+ss_dump_pcpu(int cpu) {
5816+ struct list_head *iter;
5817+ struct ss_pcpu *spc = SS_PCPU(cpu);
5818+ struct list_head *runq = &spc->runq;
5819+ struct ss_vcpu *svc = SS_CUR(cpu);
5820+ int loop = 0;
5821+
5822+ printk("\n# into %s, on cpu: %d, now is: %lu\n", __func__, cpu, NOW());
5823+
5824+ if (svc) {
5825+ printk("\trun: ");
5826+ ss_dump_vcpu(svc);
5827+ }
5828+
5829+ list_for_each(iter, runq) {
5830+ svc = __runq_elem(iter);
5831+ if (svc) {
5832+ printk("\t%3d: ", ++loop);
5833+ ss_dump_vcpu(svc);
5834+ }
5835+ }
5836+
5837+ ss_dump_repq(cpu);
5838+}
5839+
5840+//dump the record out.
5841+static void
5842+ss_dump_record(void) {
5843+ int i;
5844+
5845+ for (i = 1; i < RECORD; i++) {
5846+ printk("%-3d %-3d %13lu %13lu %13lu %13lu\n", res[i].curr, res[i].next, res[i].enter_base, res[i].leave_base, res[i].enter, res[i].leave);
5847+ }
5848+ //ss_dump_pcpu(1);
5849+ idx = 0;
5850+ start_flag = 0;
5851+}
5852+
5853+// the current vcpu is on runQ?
5854+static inline int
5855+__vcpu_on_runq(struct ss_vcpu *svc) {
5856+ return !list_empty(&svc->runq_elem);
5857+}
5858+
5859+//pick the first vcpu whose budget is >0 from the runq
5860+static inline struct ss_vcpu *
5861+__runq_pick(unsigned int cpu) {
5862+ struct list_head * runq = RUNQ(cpu);
5863+ struct list_head * iter;
5864+
5865+ list_for_each(iter, runq) {
5866+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5867+ if (iter_svc->cur_budget > 0) {
5868+ return iter_svc;
5869+ }
5870+ }
5871+
5872+ BUG_ON(1);
5873+ return NULL;
5874+}
5875+
5876+//insert into the runq, followed a FIFO way. sorted by period
5877+static inline void
5878+__runq_insert(unsigned int cpu, struct ss_vcpu *svc) {
5879+ struct list_head * runq = RUNQ(cpu);
5880+ struct list_head * iter;
5881+
5882+ BUG_ON(__vcpu_on_runq(svc));
5883+ BUG_ON(cpu != svc->vcpu->processor);
5884+
5885+ list_for_each(iter, runq) {
5886+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5887+ if (svc->period <= iter_svc->period) {
5888+ break;
5889+ }
5890+ }
5891+
5892+ list_add_tail(&svc->runq_elem, iter);
5893+}
5894+
5895+//remove it from runQ
5896+static inline void
5897+__runq_remove(struct ss_vcpu *svc) {
5898+ BUG_ON(!__vcpu_on_runq(svc));
5899+ list_del_init(&svc->runq_elem);
5900+}
5901+
5902+//used for the heap, repQ
5903+static inline int
5904+ss_rep_parent(int childIdx) {
5905+ return (childIdx & 1)? ((childIdx - 1) >> 1) : ((childIdx - 2) >> 1);
5906+}
5907+
5908+//insert into the repQ
5909+static inline void
5910+ss_repq_insert(unsigned int cpu, struct ss_vcpu *svc, int amount) {
5911+ struct ss_pcpu * spc = SS_PCPU(cpu);
5912+ int childIdx, parentIdx;
5913+
5914+ if (amount == 0) {
5915+ svc->next_time = 0;
5916+ return;
5917+ }
5918+
5919+ if (svc->next_time == 0) {
5920+ printk("\n# in %s, ERROR! svc is:", __func__);
5921+ ss_dump_vcpu(svc);
5922+ ss_dump_pcpu(cpu);
5923+ BUG_ON(1);
5924+ }
5925+
5926+ if (spc->rep_size == spc->rep_capacity) {
5927+ printk("\n# into %s, repQ full!!\n", __func__);
5928+ BUG_ON(1);
5929+ }
5930+
5931+ childIdx = spc->rep_size;
5932+ parentIdx = ss_rep_parent(childIdx);
5933+
5934+
5935+ while (childIdx > 0 && svc->next_time < spc->repq[parentIdx].re_time) {
5936+ spc->repq[childIdx] = spc->repq[parentIdx];
5937+ childIdx = parentIdx;
5938+ parentIdx = ss_rep_parent(childIdx);
5939+ }
5940+
5941+ spc->repq[childIdx].re_time = svc->next_time;
5942+ spc->repq[childIdx].re_amount = amount;
5943+ spc->repq[childIdx].svc = svc;
5944+ spc->rep_size++;
5945+/*
5946+ printk("\t add a repl. now: %lu, cpu: %d, re_time: %lu, amount: %d, for cpu [%d, %d]\n",
5947+ NOW(), cpu, svc->next_time, amount, svc->vcpu->domain->domain_id, svc->vcpu->vcpu_id);
5948+ ss_dump_vcpu(svc);
5949+*/
5950+ svc->next_time = 0;
5951+}
5952+
5953+//remove from the repQ
5954+static inline void
5955+ss_repq_remove(unsigned int cpu) {
5956+ struct ss_pcpu * spc = SS_PCPU(cpu);
5957+ int childIdx = 1;
5958+ int rightChildIdx;
5959+ int rootIdx = 0;
5960+ struct rep_elem temp;
5961+
5962+ BUG_ON(spc->rep_size <= 0);
5963+
5964+ spc->repq[0] = spc->repq[spc->rep_size - 1];
5965+ spc->rep_size--;
5966+
5967+ temp = spc->repq[0];
5968+
5969+ while (childIdx < spc->rep_size) {
5970+ rightChildIdx = childIdx + 1;
5971+ if (rightChildIdx < spc->rep_size && spc->repq[rightChildIdx].re_time < spc->repq[childIdx].re_time) {
5972+ childIdx = rightChildIdx;
5973+ }
5974+ if (spc->repq[childIdx].re_time < temp.re_time) {
5975+ spc->repq[rootIdx] = spc->repq[childIdx];
5976+ rootIdx = childIdx;
5977+ childIdx = 2 * rootIdx + 1;
5978+ } else {
5979+ break;
5980+ }
5981+ }
5982+ spc->repq[rootIdx] = temp;
5983+}
5984+
5985+//svc should be snext. Doing this is because we can not get snext->period
5986+//scan the runQ to change status, deside next time or amount
5987+static void
5988+ss_scan_runq(unsigned int cpu, struct ss_vcpu *svc) {
5989+ struct list_head * runq = RUNQ(cpu);
5990+ struct ss_vcpu *cur = svc;
5991+ struct list_head * iter;
5992+ int re_amount;
5993+
5994+ list_for_each(iter, runq) {
5995+ struct ss_vcpu * iter_svc = __runq_elem(iter);
5996+ if (is_idle_vcpu(iter_svc->vcpu)) {
5997+ return;
5998+ }
5999+
6000+ //those who has higher priority but run out of budget
6001+ if (iter_svc->period < cur->period) {
6002+ if (iter_svc->status == ACTIVE) {
6003+ //change from ACTIVE to IDLE, decide the repl amount
6004+ BUG_ON(iter_svc->next_time == 0);
6005+ iter_svc->status = IDLE;
6006+ re_amount = iter_svc->burn_total;
6007+ iter_svc->burn_total = 0;
6008+ ss_repq_insert(cpu, iter_svc, re_amount);
6009+ }
6010+ }
6011+ //those who has lower priority, should all be set to IDLE. On runQ means it has work to do!!!
6012+ else {
6013+ /*
6014+ if (iter_svc->status == IDLE) {
6015+ //mark it to be ACTIVE, decide the repl time
6016+ iter_svc->status = ACTIVE;
6017+ BUG_ON(iter_svc->next_time != 0);
6018+ iter_svc->next_time = NOW() + BUDGET(iter_svc->period);
6019+ }
6020+ */
6021+ // modification made according to RTAS 10 paper
6022+ if (iter_svc->status == ACTIVE) {
6023+ //mark it to be IDLE, decide the repl amount
6024+ BUG_ON(iter_svc->next_time == 0);
6025+ iter_svc->status = IDLE;
6026+ re_amount = iter_svc->burn_total;
6027+ iter_svc->burn_total = 0;
6028+ ss_repq_insert(cpu, iter_svc, re_amount);
6029+ printk("# into %s, Mark lower running CPU to be IDLE!\n", __func__);
6030+ }
6031+ }
6032+ }
6033+}
6034+
6035+//dump dump function
6036+static void
6037+ss_dump(void) {
6038+ printk("# into %s. Did Nothing\n", __func__);
6039+}
6040+
6041+//burn the scurr budget
6042+static void
6043+burn_budgets(struct ss_vcpu *svc, s_time_t now) {
6044+ s_time_t delta;
6045+ unsigned int consume;
6046+
6047+ BUG_ON(svc != SS_CUR(svc->vcpu->processor));
6048+
6049+ if (svc->last_start_time == 0) {
6050+ svc->last_start_time = now;
6051+ return;
6052+ }
6053+
6054+ delta = now - svc->last_start_time;
6055+ BUG_ON(delta <= 0);
6056+
6057+ consume = ( delta/BUDGET(1) );
6058+ if ( delta%BUDGET(1) > BUDGET(1)/2 ) consume++;
6059+ if (consume > svc->cur_budget) {
6060+ printk("\n# into %s, consumed more than cur budget!\n", __func__);
6061+ consume = svc->cur_budget;
6062+ }
6063+
6064+ svc->cur_budget -= consume;
6065+ svc->burn_total += consume;
6066+}
6067+
6068+//init the physical cpu
6069+static int
6070+ss_pcpu_init(int cpu) {
6071+ struct ss_pcpu *spc;
6072+ unsigned long flags;
6073+
6074+ /* Allocate per-PCPU info */
6075+ spc = xmalloc(struct ss_pcpu);
6076+ if (spc == NULL)
6077+ return -1;
6078+ memset(spc, 0, sizeof (*spc));
6079+
6080+ spin_lock_irqsave(&ss_priv.lock, flags);
6081+
6082+ if (ss_priv.ncpus < cpu)
6083+ ss_priv.ncpus = cpu + 1;
6084+
6085+ init_timer(&spc->ticker, ss_tick, (void *) (unsigned long) cpu, cpu);
6086+ INIT_LIST_HEAD(&spc->runq);
6087+ per_cpu(schedule_data, cpu).sched_priv = spc;
6088+
6089+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
6090+
6091+ spc->rep_capacity = REPQ_CAPACITY;
6092+ spc->repq = xmalloc_array(struct rep_elem, spc->rep_capacity);
6093+ BUG_ON(spc->repq == NULL);
6094+ spc->rep_size = 0;
6095+
6096+ spin_unlock_irqrestore(&ss_priv.lock, flags);
6097+
6098+ printk("\n# finish %s, init cpu: %d\n", __func__, cpu);
6099+
6100+ return 0;
6101+}
6102+
6103+//check the vcpu
6104+static inline void
6105+__ss_vcpu_check(struct vcpu *vc) {
6106+ struct ss_vcpu * const svc = SS_VCPU(vc);
6107+ struct ss_dom * const sdom = svc->sdom;
6108+
6109+ BUG_ON(svc->vcpu != vc);
6110+ BUG_ON(sdom != SS_DOM(vc->domain));
6111+ if (sdom) {
6112+ BUG_ON(is_idle_vcpu(vc));
6113+ BUG_ON(sdom->dom != vc->domain);
6114+ } else {
6115+ BUG_ON(!is_idle_vcpu(vc));
6116+ }
6117+}
6118+#define SS_VCPU_CHECK(_vc) (__ss_vcpu_check(_vc))
6119+
6120+//pick a cpu to run, used to migrate from different cpus
6121+static int
6122+ss_cpu_pick(struct vcpu *vc) {
6123+ cpumask_t cpus;
6124+ int cpu;
6125+
6126+ cpus_and(cpus, cpu_online_map, vc->cpu_affinity);
6127+
6128+ if (vc->domain->domain_id == 0 && vc->processor != 0) {
6129+ return cycle_cpu(vc->processor, cpus);
6130+ }
6131+
6132+ cpu = cpu_isset(vc->processor, cpus)
6133+ ? vc->processor
6134+ : cycle_cpu(vc->processor, cpus);
6135+
6136+ return cpu;
6137+}
6138+
6139+//check the current repQ to see if a repl needs to happen
6140+static int
6141+check_cpu_for_repl(int cpu) {
6142+// int ret = 0;
6143+ struct ss_pcpu * spc = SS_PCPU(cpu);
6144+ int flag = 0; //used for interrupt
6145+ int priority = SS_CUR(cpu)->period; // current running vcpu's period
6146+
6147+ while((spc->rep_size != 0) && spc->repq[0].re_time < NOW()) {
6148+ spc->repq[0].svc->cur_budget += spc->repq[0].re_amount;
6149+ if (spc->repq[0].svc->cur_budget > spc->repq[0].svc->budget) {
6150+ //printk("\n# into %s, repl to more than init budget!\n", __func__);
6151+ spc->repq[0].svc->cur_budget = spc->repq[0].svc->budget;
6152+ }
6153+ if (flag == 0 && spc->repq[0].svc->period < priority) {
6154+ flag = 1; // need interrupt
6155+ }
6156+ ss_repq_remove(cpu);
6157+// ret = 1;
6158+ }
6159+
6160+ return flag;
6161+}
6162+
6163+/*
6164+//if a repl happens, do we need an interrupt? (higher priority than current running one)
6165+static void
6166+check_runq_for_interrupt(int cpu) {
6167+ struct list_head * runq = RUNQ(cpu);
6168+ struct list_head * iter;
6169+ struct ss_vcpu * cur = SS_CUR(cpu);
6170+
6171+ list_for_each(iter, runq) {
6172+ struct ss_vcpu * iter_svc = __runq_elem(iter);
6173+ if (iter_svc->period >= cur->period) {
6174+ return;
6175+ } else if (iter_svc->cur_budget > 0) {
6176+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6177+ }
6178+ }
6179+}
6180+*/
6181+
6182+//init the virtual cpu
6183+static int
6184+ss_vcpu_init(struct vcpu *vc) {
6185+ struct domain * const dom = vc->domain;
6186+ struct ss_dom *sdom = SS_DOM(dom);
6187+ struct ss_vcpu *svc;
6188+
6189+ /* Allocate per-VCPU info */
6190+ svc = xmalloc(struct ss_vcpu);
6191+ if (svc == NULL) {
6192+ return -1;
6193+ }
6194+ memset(svc, 0, sizeof (*svc));
6195+
6196+ INIT_LIST_HEAD(&svc->runq_elem);
6197+ svc->sdom = sdom;
6198+ svc->vcpu = vc;
6199+ svc->budget = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->budget;
6200+ svc->period = is_idle_vcpu(vc)? SS_IDLE_PERIOD: sdom->period;
6201+ svc->cur_budget = svc->budget;
6202+
6203+ svc->last_start_time = 0;
6204+ svc->burn_total = 0;
6205+ svc->next_time = 0;
6206+ svc->status = IDLE;
6207+ vc->sched_priv = svc;
6208+
6209+ /* Allocate per-PCPU info */
6210+ if (unlikely(!SS_PCPU(vc->processor))) {
6211+ if (ss_pcpu_init(vc->processor) != 0)
6212+ return -1;
6213+ }
6214+
6215+ SS_VCPU_CHECK(vc);
6216+
6217+ printk("\n# into %s, vcpu init: ", __func__);
6218+ ss_dump_vcpu(svc);
6219+
6220+ return 0;
6221+}
6222+
6223+//destory the vcpu
6224+static void
6225+ss_vcpu_destroy(struct vcpu *vc) {
6226+ struct ss_vcpu * const svc = SS_VCPU(vc);
6227+ struct ss_dom * const sdom = svc->sdom;
6228+
6229+ printk("\n# into %s, vcpu destroy: ", __func__);
6230+ ss_dump_vcpu(svc);
6231+
6232+ BUG_ON(sdom == NULL);
6233+ BUG_ON(!list_empty(&svc->runq_elem));
6234+
6235+ xfree(svc);
6236+}
6237+
6238+//sleep the vcpu
6239+static void
6240+ss_vcpu_sleep(struct vcpu *vc) {
6241+ struct ss_vcpu * const svc = SS_VCPU(vc);
6242+
6243+/*
6244+ if (vc->domain->domain_id != 0) {
6245+ printk("\n# into %s: now %lu, sleep vcpu: \n", __func__, NOW());
6246+ ss_dump_vcpu(svc);
6247+ }
6248+*/
6249+ BUG_ON(is_idle_vcpu(vc));
6250+
6251+ if (per_cpu(schedule_data, vc->processor).curr == vc) {
6252+ cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
6253+ } else if (__vcpu_on_runq(svc)) {
6254+ //BUG_ON(svc->status == ACTIVE);
6255+ __runq_remove(svc);
6256+ }
6257+}
6258+
6259+//wake up the vcpu, insert it into runq, raise a softirq
6260+static void
6261+ss_vcpu_wake(struct vcpu *vc) {
6262+ struct ss_vcpu * const svc = SS_VCPU(vc);
6263+ const unsigned int cpu = vc->processor;
6264+
6265+ BUG_ON(is_idle_vcpu(vc));
6266+
6267+ if (unlikely(per_cpu(schedule_data, cpu).curr == vc)) {
6268+ //printk("\n# why wake up running? migration?\n");
6269+ return;
6270+ }
6271+ if (unlikely(__vcpu_on_runq(svc))) {
6272+ //printk("\n# why wake up on runq ones? migration?\n");
6273+ return;
6274+ }
6275+
6276+/*
6277+ if (smp_processor_id() == 1) {
6278+ printk("%s, domain %d, now %lu\n", __func__, vc->domain->domain_id, NOW()/1000000);
6279+ }
6280+*/
6281+ __runq_insert(cpu, svc);
6282+ //if (svc->period < SS_CUR(cpu)->period)
6283+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6284+}
6285+
6286+//used for record data, for overhead measurement
6287+static void
6288+ss_start_timer(void * temp) {
6289+ start_flag = 1;
6290+}
6291+
6292+//adjust the domain's budget & period, also used to trigger the record
6293+static int
6294+ss_dom_cntl(struct domain *d, struct xen_domctl_scheduler_op *op) {
6295+ struct ss_dom * const sdom = SS_DOM(d);
6296+ unsigned long flags;
6297+ struct ss_vcpu *svc = SS_VCPU(d->vcpu[0]);
6298+
6299+ if (op->cmd == XEN_DOMCTL_SCHEDOP_getinfo) {
6300+ op->u.ss.budget = sdom->budget;
6301+ op->u.ss.period = sdom->period;
6302+ //ss_dump_vcpu(svc);
6303+ } else {
6304+ BUG_ON(op->cmd != XEN_DOMCTL_SCHEDOP_putinfo);
6305+
6306+ spin_lock_irqsave(&ss_priv.lock, flags);
6307+ if (op->u.ss.budget != 0) {
6308+ sdom->budget = op->u.ss.budget;
6309+ svc->budget = op->u.ss.budget;
6310+ }
6311+ if (op->u.ss.period != 0) {
6312+ sdom->period = op->u.ss.period;
6313+ svc->period = op->u.ss.period;
6314+ }
6315+ svc->cur_budget = svc->budget;
6316+ spin_unlock_irqrestore(&ss_priv.lock, flags);
6317+
6318+ if (svc->vcpu->domain->domain_id == 0) {
6319+ printk("into %s, start to record now!\n", __func__);
6320+ init_timer(&start_timer, ss_start_timer, (void *) (unsigned int) 1, 1);
6321+ set_timer(&start_timer, NOW() + MILLISECS(10000));
6322+ }
6323+
6324+ //ss_dump_vcpu(svc);
6325+ }
6326+
6327+ return 0;
6328+}
6329+
6330+//init a dom
6331+static int
6332+ss_dom_init(struct domain *dom) {
6333+ struct ss_dom *sdom;
6334+
6335+ printk("\n# into %s, domain id is: %d\n", __func__, dom->domain_id);
6336+
6337+ if (is_idle_domain(dom)) {
6338+ printk("\t# init an idle domain\n");
6339+ return 0;
6340+ }
6341+
6342+ sdom = xmalloc(struct ss_dom);
6343+ if (sdom == NULL)
6344+ return -ENOMEM;
6345+ memset(sdom, 0, sizeof (*sdom));
6346+
6347+ /* Initialize budget and period */
6348+ sdom->dom = dom;
6349+
6350+ switch(dom->domain_id) {
6351+ case 32767:
6352+ sdom->budget = SS_IDLE_PERIOD;
6353+ sdom->period = SS_IDLE_PERIOD;
6354+ break;
6355+ case 0:
6356+ sdom->budget = SS_DOM_0_PERIOD;
6357+ sdom->period = SS_DOM_0_PERIOD;
6358+ break;
6359+ default:
6360+ sdom->budget = SS_DOM_BUDGET;
6361+ sdom->period = SS_DOM_PERIOD;
6362+ break;
6363+ }
6364+
6365+ dom->sched_priv = sdom;
6366+
6367+ return 0;
6368+}
6369+
6370+//destory a domain
6371+static void
6372+ss_dom_destroy(struct domain *dom) {
6373+ printk("\n# into %s, destroy domain: %d\n", __func__, dom->domain_id);
6374+ xfree(SS_DOM(dom));
6375+}
6376+
6377+//ticked by pcpu tick in pcpu.
6378+static void
6379+ss_tick(void *_cpu) {
6380+ unsigned int cpu = (unsigned long) _cpu;
6381+ struct ss_pcpu *spc = SS_PCPU(cpu);
6382+
6383+ BUG_ON(current->processor != cpu);
6384+
6385+ if (check_cpu_for_repl(cpu)) {
6386+// check_runq_for_interrupt(cpu);
6387+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6388+ }
6389+
6390+ if (ss_cpu_pick(current) != cpu) {
6391+ set_bit(_VPF_migrating, &current->pause_flags);
6392+ cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
6393+ }
6394+
6395+ set_timer(&spc->ticker, NOW() + BUDGET(1));
6396+}
6397+
6398+// most important function, called every budget time
6399+static struct task_slice
6400+ss_schedule(s_time_t now) {
6401+ const int cpu = smp_processor_id();
6402+ struct list_head *runq = RUNQ(cpu);
6403+ struct ss_vcpu *scurr = SS_VCPU(current);
6404+ struct ss_vcpu *snext;
6405+ struct task_slice ret;
6406+ int re_amount;
6407+
6408+ SS_VCPU_CHECK(current);
6409+
6410+// for record
6411+ if (smp_processor_id() == 1 && start_flag == 1) {
6412+ if(is_idle_vcpu(scurr->vcpu)) res[idx].curr = 10;
6413+ else res[idx].curr = scurr->vcpu->domain->domain_id;
6414+ res[idx].enter_base = NOW();
6415+ res[idx].leave_base = NOW();
6416+ res[idx].enter = NOW();
6417+ }
6418+
6419+ if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
6420+ //if (!is_idle_vcpu(scurr->vcpu)) {
6421+ burn_budgets(scurr, now);
6422+ }
6423+
6424+ if (vcpu_runnable(current)) {
6425+ __runq_insert(cpu, scurr);
6426+ } else {
6427+ BUG_ON(is_idle_vcpu(current) || list_empty(runq));
6428+ }
6429+
6430+ snext = __runq_pick(cpu);
6431+
6432+ __runq_remove(snext);
6433+
6434+//context switch do happen!, and snext is not an idle vcpu
6435+ if (cpu == 1 && snext != scurr) {
6436+ //if (snext != scurr) {
6437+ //for the scurr:
6438+ //if (!is_idle_vcpu(scurr->vcpu) && scurr->vcpu->domain->domain_id != 0) {
6439+ if (!is_idle_vcpu(scurr->vcpu)) {
6440+ BUG_ON(scurr->status != ACTIVE);
6441+ BUG_ON(scurr->next_time == 0);
6442+ scurr->status = IDLE;
6443+ re_amount = scurr->burn_total;
6444+ scurr->burn_total = 0;
6445+ //printk("\n# into %s, change status to IDLE, decide repl amount here! now is %lu, for vcpu[%d, %d], re_amount is: %d, re_time is %lu\n",
6446+ // __func__, NOW(), scurr->vcpu->domain->domain_id, scurr->vcpu->vcpu_id, re_amount, scurr->next_time);
6447+ ss_repq_insert(cpu, scurr, re_amount);
6448+ }
6449+
6450+ //for the snext:
6451+ //if (!is_idle_vcpu(snext->vcpu) && snext->vcpu->domain->domain_id != 0) {
6452+ if (!is_idle_vcpu(snext->vcpu)) {
6453+ if (snext->status == IDLE) {
6454+ BUG_ON(snext->next_time != 0);
6455+ snext->status = ACTIVE;
6456+ snext->next_time = NOW() + BUDGET(snext->period);
6457+ //printk("\n# into %s, change status to ACTIVE, decide repl time here! now is %lu, for vcpu [%d, %d], re_time is %lu\n",
6458+ // __func__, NOW(), snext->vcpu->domain->domain_id, snext->vcpu->vcpu_id, snext->next_time);
6459+ }
6460+ }
6461+
6462+ //scan the whole runq
6463+ ss_scan_runq(cpu, snext);
6464+ }
6465+
6466+ if (cpu == 1 && snext->vcpu->domain->domain_id != 0) {
6467+ snext->last_start_time = NOW();
6468+ }
6469+
6470+ ret.time = (is_idle_vcpu(snext->vcpu) ? -1 : BUDGET(1));
6471+ //ret.time = BUDGET(1);
6472+ ret.task = snext->vcpu;
6473+
6474+ SS_VCPU_CHECK(ret.task);
6475+
6476+ BUG_ON(!vcpu_runnable(snext->vcpu));
6477+ //printk("now is %lu\n", now);
6478+
6479+// for record
6480+ if (smp_processor_id() == 1 && start_flag == 1) {
6481+ if(is_idle_vcpu(snext->vcpu)) res[idx].next = 10;
6482+ else res[idx].next = snext->vcpu->domain->domain_id;
6483+ res[idx].leave = NOW();
6484+ if(idx++ >= RECORD) {
6485+ ss_dump_record();
6486+ }
6487+ }
6488+
6489+ return ret;
6490+}
6491+
6492+//init the global data
6493+static void
6494+ss_init(void) {
6495+ printk("\n# into %s\n", __func__);
6496+ spin_lock_init(&ss_priv.lock);
6497+ ss_priv.ncpus = 0;
6498+}
6499+
6500+/* Tickers cannot be kicked until SMP subsystem is alive. */
6501+static __init int
6502+ss_start_tickers(void) {
6503+ struct ss_pcpu *spc;
6504+ unsigned int cpu;
6505+
6506+ printk("\n# into %s, start all tickers right now\n", __func__);
6507+
6508+ if (ss_priv.ncpus == 0)
6509+ return 0;
6510+
6511+ for_each_online_cpu(cpu) {
6512+ spc = SS_PCPU(cpu);
6513+ set_timer(&spc->ticker, NOW() + BUDGET(1));
6514+ }
6515+
6516+ return 0;
6517+}
6518+__initcall(ss_start_tickers);
6519+
6520+static void ss_tick_suspend(void) {
6521+ struct ss_pcpu *spc;
6522+
6523+ printk("\n# into %s, why is this called?\n", __func__);
6524+
6525+ spc = SS_PCPU(smp_processor_id());
6526+
6527+ stop_timer(&spc->ticker);
6528+}
6529+
6530+static void ss_tick_resume(void) {
6531+ struct ss_pcpu *spc;
6532+ uint64_t now = NOW();
6533+
6534+ printk("\n# into %s, why is this called?\n", __func__);
6535+
6536+ spc = SS_PCPU(smp_processor_id());
6537+
6538+ set_timer(&spc->ticker, now + BUDGET(1));
6539+}
6540+
6541+const struct scheduler sched_ss_def = {
6542+ .name = "Sporadic Server Scheduler",
6543+ .opt_name = "ss",
6544+ .sched_id = XEN_SCHEDULER_SS,
6545+
6546+ .init_domain = ss_dom_init,
6547+ .destroy_domain = ss_dom_destroy,
6548+
6549+ .init_vcpu = ss_vcpu_init,
6550+ .destroy_vcpu = ss_vcpu_destroy,
6551+
6552+ .init = ss_init,
6553+
6554+ .pick_cpu = ss_cpu_pick,
6555+
6556+ .tick_suspend = ss_tick_suspend,
6557+ .tick_resume = ss_tick_resume,
6558+
6559+ .do_schedule = ss_schedule,
6560+
6561+ .sleep = ss_vcpu_sleep,
6562+ .wake = ss_vcpu_wake,
6563+
6564+ .adjust = ss_dom_cntl,
6565+
6566+ .dump_cpu_state = ss_dump_pcpu,
6567+ .dump_settings = ss_dump,
6568+};
6569diff -ubrN xen/xen-4.0.1/xen/common/schedule.c xen-4.0.1/xen/common/schedule.c
6570--- xen/xen-4.0.1/xen/common/schedule.c 2010-08-25 04:22:12.000000000 -0600
6571+++ xen-4.0.1/xen/common/schedule.c 2011-04-24 15:43:52.000000000 -0600
6572@@ -34,8 +34,8 @@
6573 #include <public/sched.h>
6574 #include <xsm/xsm.h>
6575
6576-/* opt_sched: scheduler - default to credit */
6577-static char __initdata opt_sched[10] = "credit";
6578+/* opt_sched: scheduler - default to rt */
6579+static char __initdata opt_sched[10] = "rt";
6580 string_param("sched", opt_sched);
6581
6582 /* if sched_smt_power_savings is set,
6583@@ -56,12 +56,32 @@
6584
6585 extern const struct scheduler sched_sedf_def;
6586 extern const struct scheduler sched_credit_def;
6587+// added by Sisu Xi
6588+extern const struct scheduler sched_rt_def;
6589 static const struct scheduler *__initdata schedulers[] = {
6590 &sched_sedf_def,
6591 &sched_credit_def,
6592+ &sched_rt_def,
6593 NULL
6594 };
6595
6596+//for record
6597+#define RECORD 15000
6598+struct record_elem{
6599+ int processor; // 1: idle to busy, 2: busy to idle, 3: busy to busy(dif), 4: same
6600+ int curr;
6601+ int next;
6602+ s_time_t dur_sub;
6603+ s_time_t dur;
6604+};
6605+
6606+//int sched_idx;
6607+int sched_start_flag = 0; // to record data
6608+struct timer sched_start_timer;
6609+s_time_t temp_dur_sub;
6610+s_time_t temp_dur;
6611+//finish record
6612+
6613 static struct scheduler __read_mostly ops;
6614
6615 #define SCHED_OP(fn, ...) \
6616@@ -777,6 +797,37 @@
6617 return ops.sched_id;
6618 }
6619
6620+//for record
6621+static void
6622+record_finish_timer(void * temp) {
6623+// int i = 0;
6624+
6625+ sched_start_flag = 0;
6626+/*
6627+ for (i = 0; i < sched_idx; i++) {
6628+ printk("%d %5d %5d %7lu %7lu\n", sched_res[i].processor, sched_res[i].curr, sched_res[i].next, sched_res[i].dur_sub, sched_res[i].dur);
6629+ }
6630+
6631+ for (i = 0; i < RECORD; i++) {
6632+ sched_res[i].processor = 0;
6633+ sched_res[i].curr = 0;
6634+ sched_res[i].next = 0;
6635+ sched_res[i].dur_sub = 0;
6636+ sched_res[i].dur = 0;
6637+ }
6638+
6639+ sched_idx = 0;
6640+*/
6641+}
6642+
6643+static void
6644+record_start_timer(void * temp) {
6645+ sched_start_flag = 1;
6646+ init_timer(&sched_start_timer, record_finish_timer, (void *) (unsigned int) 1, 1);
6647+ set_timer(&sched_start_timer, NOW() + MILLISECS(10000));
6648+}
6649+//finish recording
6650+
6651 /* Adjust scheduling parameter for a given domain. */
6652 long sched_adjust(struct domain *d, struct xen_domctl_scheduler_op *op)
6653 {
6654@@ -810,9 +861,17 @@
6655 if ( d == current->domain )
6656 vcpu_schedule_lock_irq(current);
6657
6658- if ( (ret = SCHED_OP(adjust, d, op)) == 0 )
6659+ if ( (ret = SCHED_OP(adjust, d, op)) >= 0 )
6660 TRACE_1D(TRC_SCHED_ADJDOM, d->domain_id);
6661
6662+//trigger recording!!
6663+ if (ret == 1) {
6664+ printk("start!\n");
6665+ init_timer(&sched_start_timer, record_start_timer, (void *) (unsigned int) 1, 1);
6666+ set_timer(&sched_start_timer, NOW() + MILLISECS(5000));
6667+ ret = 0;
6668+ }
6669+
6670 if ( d == current->domain )
6671 vcpu_schedule_unlock_irq(current);
6672
6673@@ -860,6 +919,11 @@
6674 struct schedule_data *sd;
6675 struct task_slice next_slice;
6676
6677+//record
6678+ if (prev->processor == 1 && sched_start_flag == 1) {
6679+ temp_dur = now;
6680+ }
6681+
6682 ASSERT(!in_irq());
6683 ASSERT(this_cpu(mc_state).flags == 0);
6684
6685@@ -871,8 +935,16 @@
6686
6687 stop_timer(&sd->s_timer);
6688
6689+//record
6690+ if (prev->processor == 1 && sched_start_flag == 1) {
6691+ temp_dur_sub = NOW();
6692+ }
6693 /* get policy-specific decision on scheduling... */
6694 next_slice = ops.do_schedule(now);
6695+ if (prev->processor == 1 && sched_start_flag == 1) {
6696+ printk("%7lu ", NOW() - temp_dur_sub);
6697+ //sched_res[sched_idx].dur_sub = NOW() - temp_dur_sub;
6698+ }
6699
6700 next = next_slice.task;
6701
6702@@ -881,10 +953,19 @@
6703 if ( next_slice.time >= 0 ) /* -ve means no limit */
6704 set_timer(&sd->s_timer, now + next_slice.time);
6705
6706+ if (prev->processor == 1 && sched_start_flag == 1) {
6707+ printk("%7d %7d %13lu ", prev->domain->domain_id, next->domain->domain_id, NOW());
6708+ }
6709+
6710 if ( unlikely(prev == next) )
6711 {
6712 spin_unlock_irq(&sd->schedule_lock);
6713 trace_continue_running(next);
6714+ if (prev->processor == 1 && sched_start_flag == 1) {
6715+ printk("%13lu\n", NOW());
6716+ //sched_res[sched_idx].dur = NOW() - temp_dur;
6717+ //sched_idx++;
6718+ }
6719 return continue_running(prev);
6720 }
6721
6722@@ -931,7 +1012,11 @@
6723 update_vcpu_system_time(next);
6724 vcpu_periodic_timer_work(next);
6725
6726- context_switch(prev, next);
6727+ if (prev->processor == 1) {
6728+ context_switch(sched_start_flag, prev, next);
6729+ } else {
6730+ context_switch(0, prev, next);
6731+ }
6732 }
6733
6734 void context_saved(struct vcpu *prev)
6735diff -ubrN xen/xen-4.0.1/xen/drivers/char/console.c xen-4.0.1/xen/drivers/char/console.c
6736--- xen/xen-4.0.1/xen/drivers/char/console.c 2010-08-25 04:22:12.000000000 -0600
6737+++ xen-4.0.1/xen/drivers/char/console.c 2011-01-15 10:57:46.000000000 -0700
6738@@ -63,7 +63,9 @@
6739 static uint32_t __initdata opt_conring_size;
6740 size_param("conring_size", opt_conring_size);
6741
6742-#define _CONRING_SIZE 16384
6743+//#define _CONRING_SIZE 16384
6744+//Sisu xi
6745+#define _CONRING_SIZE 1638400
6746 #define CONRING_IDX_MASK(i) ((i)&(conring_size-1))
6747 static char __initdata _conring[_CONRING_SIZE];
6748 static char *__read_mostly conring = _conring;
6749diff -ubrN xen/xen-4.0.1/xen/include/public/domctl.h xen-4.0.1/xen/include/public/domctl.h
6750--- xen/xen-4.0.1/xen/include/public/domctl.h 2010-08-25 04:22:14.000000000 -0600
6751+++ xen-4.0.1/xen/include/public/domctl.h 2011-04-24 15:51:25.000000000 -0600
6752@@ -303,6 +303,9 @@
6753 /* Scheduler types. */
6754 #define XEN_SCHEDULER_SEDF 4
6755 #define XEN_SCHEDULER_CREDIT 5
6756+// added by Sisu Xi
6757+#define XEN_SCHEDULER_RT 7
6758+
6759 /* Set or get info? */
6760 #define XEN_DOMCTL_SCHEDOP_putinfo 0
6761 #define XEN_DOMCTL_SCHEDOP_getinfo 1
6762@@ -321,6 +324,12 @@
6763 uint16_t weight;
6764 uint16_t cap;
6765 } credit;
6766+ // added by Sisu Xi
6767+ struct xen_domctl_sched_rt {
6768+ uint16_t budget;
6769+ uint16_t period;
6770+ uint16_t level;
6771+ } rt;
6772 } u;
6773 };
6774 typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
6775diff -ubrN xen/xen-4.0.1/xen/include/xen/sched.h xen-4.0.1/xen/include/xen/sched.h
6776--- xen/xen-4.0.1/xen/include/xen/sched.h 2010-08-25 04:22:14.000000000 -0600
6777+++ xen-4.0.1/xen/include/xen/sched.h 2011-01-18 00:58:43.000000000 -0700
6778@@ -492,6 +492,7 @@
6779 * sync_vcpu_execstate() will switch and commit @prev's state.
6780 */
6781 void context_switch(
6782+ int flag,
6783 struct vcpu *prev,
6784 struct vcpu *next);
6785
diff --git a/recipes-extended/xen/xen-rt_4.0.1.bb b/recipes-extended/xen/xen-rt_4.0.1.bb
new file mode 100644
index 00000000..3422ab3c
--- /dev/null
+++ b/recipes-extended/xen/xen-rt_4.0.1.bb
@@ -0,0 +1,25 @@
1# Xen official download
2# Using libxl instead of xend. No longer require Python
3
4require xen.inc
5
6SRCREV = "3cf61880403b4e484539596a95937cc066243388"
7
8SRC_URI = "http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz \
9 git://xenbits.xensource.com/qemu-xen-4.1-testing.git \
10 file://ioemu-cross-gl-check.patch \
11 file://rt-xen_0.3_${PV}.patch"
12
13# file://allow_disable_xend.patch"
14
15SRC_URI[md5sum] = "d197afad975ab2396a67323d57388c27"
16SRC_URI[sha256sum] = "6e6d1d29400db93cb8095e034138aa8748b1bd4cffb4d3fd07af4ba15c918873"
17
18S = "${WORKDIR}/xen-${PV}"
19
20do_compile_prepend() {
21
22 export XEN_DISABLE_XEND=1
23
24}
25
diff --git a/recipes-extended/xen/xen.inc b/recipes-extended/xen/xen.inc
new file mode 100644
index 00000000..a2723b97
--- /dev/null
+++ b/recipes-extended/xen/xen.inc
@@ -0,0 +1,305 @@
1DESCRIPTION = "Xen is a virtual-machine monitor providing services that allow multiple computer operating systems to execute on the same computer hardware concurrently."
2HOMEPAGE = "http://xen.org"
3LICENSE = "GPLv2"
4SECTION = "console/tools"
5PR = "r0"
6
7# Disable xend and python support
8XEN_DISABLE_XEND=1
9
10DEPENDS = "util-linux util-linux-native file-native zlib ncurses openssl bison-native flex-native gettext dev86-native iasl-native pciutils virtual/libgl virtual/libsdl bridge-utils iproute2 procps"
11
12# RDEPENDS_xen = "libgcc pciutils bridge-utils iproute2 util-linux udev procps bash"
13RDEPENDS_xen-minimal = "libgcc xen-keymaps-base xen-xenstore xen-xenconsole xen-xenlight xen-hvmloader xen-qemu-dm"
14RDEPENDS_xen = "libgcc xen-keymaps-base xen-xenstore xen-xenconsole xen-xenlight xen-hvmloader xen-qemu-dm xen-keymaps"
15RDEPENDS_xen-networking = "bridge-utils"
16RDEPENDS_xen-domains = "bash procps coreutils"
17RDEPENDS_xen-commons = "bash procps coreutils"
18RDEPENDS_xen-watchdog = "bash procps coreutils"
19
20COMPATIBLE_HOST = '(x86_64.*|i.86.*).*-linux'
21
22ALLOW_EMPTY_${PN} = "1"
23
24PACKAGES = "\
25 ${PN}-boot ${PN}-watchdog ${PN}-examples ${PN}-debugging ${PN}-tools ${PN}-pm ${PN}-domains ${PN}-commons \
26 ${PN}-bios-ppc ${PN}-bios-sparc ${PN}-networking \
27 ${PN}-doc ${PN}-dbg ${PN}-staticdev ${PN}-minimal ${PN}-keymaps-base ${PN}-keymaps \
28 ${PN}-xenstore ${PN}-xenconsole ${PN}-xenlight ${PN}-hvmloader ${PN}-qemu-dm \
29 libxenlight libfsimage libflask libxenguest libblktap libblktapctl libvhd libxlutil libxenstore libxenctrl \
30 libxenlight-dev libfsimage-dev libflask-dev libxenguest-dev libblktap-dev libblktapctl-dev libvhd-dev libxlutil-dev libxenstore-dev libxenctrl-dev \
31 ${PN}-dev ${PN} \
32 "
33
34FILES_${PN} += "\
35 ${libdir}/xen \
36 ${libdir}/fs \
37 /usr/lib64 \
38 "
39
40FILES_${PN}-minimal = "\
41 ${sysconfdir}/init.d/xenminiinit \
42 "
43
44FILES_${PN}-qemu-dm = "\
45 ${libdir}/xen/bin/qemu-dm \
46 /var/lib/xen \
47 "
48
49FILES_${PN}-keymaps-base = "\
50 /usr/share/xen/qemu/keymaps/common \
51 /usr/share/xen/qemu/keymaps/modifiers \
52 /usr/share/xen/qemu/keymaps/en-us \
53 "
54
55FILES_${PN}-keymaps = "\
56 /usr/share/xen/qemu/keymaps \
57 "
58
59FILES_${PN}-xenlight = "\
60 ${sbindir}/xl \
61 ${sysconfdir}/xen/xl.conf \
62 ${sysconfdir}/bash_completion.d/xl.sh \
63 "
64
65FILES_${PN}-xenconsole = "\
66 ${sbindir}/xenconsoled \
67 ${libdir}/xen/bin/xc_restore \
68 ${libdir}/xen/bin/xc_save \
69 ${libdir}/xen/bin/xenconsole \
70 "
71
72FILES_${PN}-xenstore = "\
73 ${bindir}/xenstore \
74 ${bindir}/xenstore-* \
75 ${sbindir}/xenstored \
76 /var/run/xenstored \
77 "
78
79FILES_${PN}-hvmloader = "\
80 ${libdir}/xen/boot/hvmloader \
81 "
82
83FILES_libxenlight = "${libdir}/libxenlight.so.*"
84FILES_libxenlight-dev = "${libdir}/libxenlight.so {libdir}/libxenlight.a"
85FILES_libfsimage = "${libdir}/libfsimage.so.*"
86FILES_libfsimage-dev = "${libdir}/libfsimage.so {libdir}/libfsimage.a"
87FILES_libflask = "${libdir}/libflask.so.*"
88FILES_libflask-dev = "${libdir}/libflask.so ${libdir}/libflask.a"
89FILES_libxenguest = "${libdir}/libxenguest.so.*"
90FILES_libxenguest-dev = "${libdir}/libxenguest.so ${libdir}/libxenguest.a"
91FILES_libblktap = "${libdir}/libblktap.so.*"
92FILES_libblktap-dev = "${libdir}/libblktap.so ${libdir}/libblktap.a"
93FILES_libblktapctl = "${libdir}/libblktapctl.so.*"
94FILES_libblktapctl-dev = "${libdir}/libblktapctl.so ${libdir}/libblktapctl.a"
95FILES_libxlutil = "${libdir}/libxlutil.so.*"
96FILES_libxlutil-dev = "${libdir}/libxlutil.so ${libdir}/libxlutil.a"
97FILES_libvhd = "${libdir}/libvhd.so.*"
98FILES_libvhd-dev = "${libdir}/libvhd.so ${libdir}/libvhd.a"
99FILES_libxenstore = "${libdir}/libxenstore.so.*"
100FILES_libxenstore-dev = "${libdir}/libxenstore.so ${libdir}/libxenstore.a"
101FILES_libxenctrl = "${libdir}/libxenctrl.so.*"
102FILES_libxenctrl-dev = "${libdir}/libxenctrl.so ${libdir}/libxenctrl.a"
103
104FILES_${PN}-doc += "\
105 /usr/share/xen/man \
106 ${sysconfdir}/xen/README* \
107 "
108
109FILES_${PN}-dbg += "\
110 ${libdir}/xen/bin/.debug \
111 ${libdir}/fs/ufs/.debug \
112 ${libdir}/fs/zfs/.debug \
113 ${libdir}/fs/ext2fs-lib/.debug \
114 ${libdir}/fs/fat/.debug \
115 ${libdir}/fs/iso9660/.debug \
116 ${libdir}/fs/reiserfs/.debug \
117 "
118
119FILES_${PN}-boot = "/boot"
120
121FILES_${PN}-domains = "\
122 ${sysconfdir}/default/xendomains \
123 ${sysconfdir}/init.d/xendomains \
124 "
125
126FILES_${PN}-commons = "\
127 ${sysconfdir}/default/xencommons \
128 ${sysconfdir}/init.d/xencommons \
129 "
130
131FILES_${PN}-bios-sparc = "\
132 /usr/share/xen/qemu/openbios-sparc32 \
133 /usr/share/xen/qemu/openbios-sparc64 \
134 "
135
136FILES_${PN}-bios-ppc = "\
137 /usr/share/xen/qemu/openbios-ppc \
138 /usr/share/xen/qemu/ppc_rom.bin \
139 "
140
141FILES_${PN}-networking = "\
142 ${sysconfdir}/xen/scripts/network-nat \
143 ${sysconfdir}/xen/scripts/network-route \
144 ${sysconfdir}/xen/scripts/qemu-ifup \
145 ${sysconfdir}/xen/scripts/vif2 \
146 ${sysconfdir}/xen/scripts/vif-bridge \
147 ${sysconfdir}/xen/scripts/vif-route \
148 ${sysconfdir}/xen/scripts/vif-setup \
149 ${sysconfdir}/xen/scripts/vif-common \
150 ${sysconfdir}/xen/scripts/vif-nat \
151 ${sysconfdir}/xen/scripts/xen-network-common \
152 /usr/share/xen/qemu/pxe-e1000.bin \
153 /usr/share/xen/qemu/pxe-ne2k_pci.bin \
154 /usr/share/xen/qemu/pxe-pcnet.bin \
155 /usr/share/xen/qemu/pxe-rtl8139.bin \
156 "
157
158FILES_${PN}-pm = "\
159 ${sbindir}/xenpmd \
160 ${sbindir}/xenpm \
161 "
162
163FILES_${PN}-watchdog = "\
164 ${sysconfdir}/init.d/xen-watchdog \
165 ${sbindir}/xenwatchdogd \
166 "
167
168FILES_${PN}-examples = "\
169 ${sysconfdir}/xen/xmexample* \
170 "
171
172FILES_${PN}-debugging = "\
173 ${sbindir}/gdbsx \
174 ${sbindir}/kdd \
175 ${sbindir}/xen-hvmcrash \
176 ${sbindir}/gtraceview \
177 ${sbindir}/gtracestat \
178 "
179
180FILES_${PN}-tools = "\
181 ${bindir}/xen-detect \
182 ${bindir}/xentrace \
183 ${bindir}/xentrace_* \
184 ${bindir}/qemu-img-xen \
185 ${sbindir}/tap-ctl \
186 ${sbindir}/xentrace_* \
187 ${sbindir}/tapdisk \
188 ${sbindir}/tapdisk2 \
189 ${sbindir}/tapdisk-* \
190 ${sbindir}/flask-genenforce \
191 ${sbindir}/qcow-create \
192 ${sbindir}/qcow2raw \
193 ${sbindir}/xen-hptool \
194 ${sbindir}/blktapctrl \
195 ${sbindir}/xsview \
196 ${sbindir}/xen-hvmctx \
197 ${sbindir}/lock-util \
198 ${sbindir}/tapdisk-stream \
199 ${sbindir}/vhd-update \
200 ${sbindir}/xenpaging \
201 ${sbindir}/xenperf \
202 ${sbindir}/xenlockprof \
203 ${sbindir}/td-util \
204 ${sbindir}/flask-loadpolicy \
205 ${sbindir}/xentop \
206 ${sbindir}/img2qcow \
207 ${sbindir}/flask-setenforce \
208 ${sbindir}/xen-tmem-list-parse \
209 ${sbindir}/vhd-util \
210 ${sbindir}/xenbaked \
211 "
212
213# Don't run architecture tests on xen packages
214QAPATHTEST[arch]=""
215
216inherit update-rc.d
217
218INITSCRIPT_PACKAGES = "${PN}-commons ${PN}-watchdog ${PN}-domains"
219INITSCRIPT_NAME_${PN}-commons = "xencommons"
220INITSCRIPT_PARAMS_${PN}-commons = "defaults 62"
221INITSCRIPT_NAME_${PN}-watchdog = "xen-watchdog"
222INITSCRIPT_PARAMS_${PN}-watchdog = "defaults 66"
223INITSCRIPT_NAME_${PN}-domains = "xendomains"
224INITSCRIPT_PARAMS_${PN}-domains = "defaults 68"
225NITSCRIPT_NAME_${PN}-minimal = "xenminiinit"
226INITSCRIPT_PARAMS_${PN}-minimal = "defaults 69"
227
228do_compile() {
229
230 # Hack to get around missing/failed multilib support
231 export LIBLEAFDIR_x86_64=lib
232 test -d ${S}/tools/firmware/rombios/gnu || mkdir ${S}/tools/firmware/rombios/gnu
233 test -e ${S}/tools/firmware/rombios/32bit/gnu || ln -s ../gnu ${S}/tools/firmware/rombios/32bit/gnu
234 test -e ${S}/tools/firmware/hvmloader/gnu || ln -s ../rombios/gnu ${S}/tools/firmware/hvmloader/gnu
235 test -e ${S}/tools/firmware/hvmloader/acpi/gnu || ln -s ../../rombios/gnu ${S}/tools/firmware/hvmloader/acpi/gnu
236 test -d ${S}/tools/include || mkdir -p ${S}/tools/include
237 test -e ${S}/tools/include/gnu || ln -s ../firmware/rombios/gnu ${S}/tools/include/gnu
238
239 if ! test -f ${STAGING_DIR_TARGET}/usr/include/gnu/stubs-32.h ; then
240 cat ${STAGING_DIR_TARGET}/usr/include/gnu/stubs-64.h | grep -v stub_bdflush | grep -v stub_getmsg | grep -v stub_putmsg > ${S}/tools/firmware/rombios/gnu/stubs-32.h
241 echo \#define __stub___kernel_cosl >> ${S}/tools/firmware/rombios/gnu/stubs-32.h
242 echo \#define __stub___kernel_sinl >> ${S}/tools/firmware/rombios/gnu/stubs-32.h
243 echo \#define __stub___kernel_tanl >> ${S}/tools/firmware/rombios/gnu/stubs-32.h
244 fi
245 # End multilib hack
246
247 export CONFIG_QEMU=${WORKDIR}/git
248
249 export XEN_TARGET_ARCH=${TARGET_ARCH}
250 export XEN_OS=Linux
251 export XEN_DISABLE_XEND=${XEN_DISABLE_XEND}
252
253 export EXTRA_PREFIX=${STAGING_DIR_TARGET}
254 export CROSS_COMPILE=${TARGET_PREFIX}
255 export CROSS_BIN_PATH=${STAGING_DIR_NATIVE}/usr/bin
256 export CROSS_SYS_ROOT=${STAGING_DIR_TARGET}
257
258 # These are needed by sysconfig.py
259 export BUILD_SYS=${BUILD_SYS}
260 export HOST_SYS=${HOST_SYS}
261 export STAGING_INCDIR=${STAGING_INCDIR}
262 export STAGING_LIBDIR=${STAGING_LIBDIR}
263
264 export CFLAGS=
265 export LDFLAGS=
266
267 # These two checks are for binaries that are not installed yet
268 rm -f ${S}/tools/check/check_python_devel
269 rm -f ${S}/tools/check/check_xgettext
270
271 # These checks are for libraries utilizing ldconfig
272 rm -f ${S}/tools/check/check_zlib_lib
273 rm -f ${S}/tools/check/check_crypto_lib
274
275 #stubdom image builds are being a pain
276 oe_runmake dist-xen dist-tools dist-kernels dist-docs
277}
278
279do_install() {
280
281 for foo in `find ${S}/dist/install -type f` ; do
282 if file $foo | grep text 2>&1 ; then
283 echo Fixing paths in $foo
284 sed -e "s%${STAGING_DIR_NATIVE}%%g" -i $foo
285 sed -e "s%${STAGING_DIR_TARGET}%%g" -i $foo
286 fi
287 done
288
289 cp -av ${S}/dist/install/* ${D}/
290 install -d ${D}/etc/xen
291 install -d ${D}/etc/init.d
292
293 install -m 0755 ${WORKDIR}/xenminiinit.sh ${D}/etc/init.d/xenminiinit
294 install -m 0644 ${WORKDIR}/xend-config.sxp ${D}/etc/xen/xend-config.sxp
295 test -e ${D}/usr/lib64 || ln -s lib ${D}/usr/lib64
296
297}
298
299sysroot_stage_all_append() {
300 sysroot_stage_dir ${D}/boot ${SYSROOT_DESTDIR}/kernel
301
302 install -d ${DEPLOY_DIR_IMAGE}
303 install -m 0644 ${D}/boot/xen.gz ${DEPLOY_DIR_IMAGE}/xen-${MACHINE}.gz
304}
305
diff --git a/recipes-extended/xen/xen_4.1.2.bb b/recipes-extended/xen/xen_4.1.2.bb
new file mode 100644
index 00000000..5a87bc41
--- /dev/null
+++ b/recipes-extended/xen/xen_4.1.2.bb
@@ -0,0 +1,24 @@
1# Xen official download
2
3require xen.inc
4
5PR="r1"
6
7LIC_FILES_CHKSUM = "file://COPYING;md5=f46a39d9fa181e4933b1acdfdcd72017"
8
9SRCREV = "3cf61880403b4e484539596a95937cc066243388"
10
11SRC_URI = "http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz \
12 git://xenbits.xensource.com/qemu-xen-4.1-testing.git \
13 file://ioemu-cross-gl-check.patch \
14 file://allow_disable_xend.patch \
15 file://xend-config.sxp \
16 file://xenminiinit.sh"
17
18SRC_URI[md5sum] = "73561faf3c1b5e36ec5c089b5db848ad"
19SRC_URI[sha256sum] = "7d9c93057cf480d3f1efa792b19285a84fa3c06060ea5c5c453be00887389b0d"
20
21S = "${WORKDIR}/xen-${PV}"
22
23# Include python and xend support
24require xen-python.inc
diff --git a/recipes-extended/xen/xen_hg.bb b/recipes-extended/xen/xen_hg.bb
new file mode 100644
index 00000000..ef8e595e
--- /dev/null
+++ b/recipes-extended/xen/xen_hg.bb
@@ -0,0 +1,29 @@
1# A build of Xen Unstable from Mercurial
2
3# Build is not yet verified as functional
4# Setting BROKEN for now
5BROKEN=1
6
7inherit autotools
8
9require xen.inc
10
11DEPENDS += "yajl"
12
13LIC_FILES_CHKSUM = "file://COPYING;md5=e0f0f3ac55608719a82394cc353928df"
14
15SRCREV = "82db8de16530f016809264d3179823999d702849"
16
17SRC_URI = "hg://xenbits.xen.org;module=xen-unstable.hg;rev=d690c7e896a2 \
18 git://xenbits.xensource.com/qemu-xen-unstable.git \
19 file://ioemu-cross-gl-check.patch \
20 file://tools_qemu_xen_remove_CFLAGS.patch"
21
22SRC_URI[md5sum] = "2f3e36c96fe13cebc7475652c2803e14"
23SRC_URI[sha256sum] = "b63bc8d48aaf2688cff1417f99a140943e71de0777b28ed8cbba8aa018b4117c"
24
25S = "${WORKDIR}/xen-unstable.hg"
26
27#EXTRA_OECONF="--disable-pythontools"
28require xen-python.inc
29