mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
merge with xen-unstable.hg
This commit is contained in:
commit
b4fa7c40e9
327 files changed
+7773
-4486
No files matched your search
@@ -14,3 +14,4 @@ fb875591fd72e15c31879c0e9034d99b80225595 RELEASE-2.0.4
|
||||
3d330e41f41ce1bc118c02346e18949ad5d67f6b split-1.1
|
||||
c8fdb0caa77b429cf47f9707926e83947778cb48 RELEASE-3.0.0
|
||||
af0573e9e5258db0a9d28aa954dd302ddd2c2d23 3.0.2-rc
|
||||
d0d3fef37685be264a7f52201f8ef44c030daad3 3.0.2-branched
|
||||
@@ -24,6 +24,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||
|
||||
DISTDIR ?= $(XEN_ROOT)/dist
|
||||
DESTDIR ?= /
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_DIR = $(INSTALL) -d -m0755
|
||||
|
||||
@@ -14,6 +14,7 @@ export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE
|
||||
endif
|
||||
|
||||
# Default target must appear before any include lines
|
||||
.PHONY: all
|
||||
all: dist
|
||||
|
||||
XEN_ROOT=$(CURDIR)
|
||||
@@ -24,12 +25,11 @@ ifeq ($(XEN_TARGET_X86_PAE),y)
|
||||
export pae=y
|
||||
endif
|
||||
|
||||
.PHONY: all dist install xen kernels tools dev-docs docs world clean
|
||||
.PHONY: mkpatches mrproper kbuild kdelete kclean
|
||||
|
||||
# build and install everything into the standard system directories
|
||||
.PHONY: install
|
||||
install: install-xen install-kernels install-tools install-docs
|
||||
|
||||
.PHONY: build
|
||||
build: kernels
|
||||
$(MAKE) -C xen build
|
||||
$(MAKE) -C tools build
|
||||
@@ -38,10 +38,12 @@ build: kernels
|
||||
# The test target is for unit tests that can run without an installation. Of
|
||||
# course, many tests require a machine running Xen itself, and these are
|
||||
# handled elsewhere.
|
||||
.PHONY: test
|
||||
test:
|
||||
$(MAKE) -C tools/python test
|
||||
|
||||
# build and install everything into local dist directory
|
||||
.PHONY: dist
|
||||
dist: DESTDIR=$(DISTDIR)/install
|
||||
dist: dist-xen dist-kernels dist-tools dist-docs
|
||||
$(INSTALL_DIR) $(DISTDIR)/check
|
||||
@@ -54,79 +56,83 @@ dist-%: install-%
|
||||
@: # do nothing
|
||||
|
||||
# Legacy dist targets
|
||||
.PHONY: xen tools kernels docs
|
||||
xen: dist-xen
|
||||
tools: dist-tools
|
||||
kernels: dist-kernels
|
||||
docs: dist-docs
|
||||
|
||||
.PHONY: prep-kernels
|
||||
prep-kernels:
|
||||
for i in $(XKERNELS) ; do $(MAKE) $$i-prep || exit 1; done
|
||||
|
||||
.PHONY: install-xen
|
||||
install-xen:
|
||||
$(MAKE) -C xen install
|
||||
|
||||
.PHONY: install-tools
|
||||
install-tools:
|
||||
$(MAKE) -C tools install
|
||||
|
||||
.PHONY: install-kernels
|
||||
install-kernels:
|
||||
for i in $(XKERNELS) ; do $(MAKE) $$i-install || exit 1; done
|
||||
|
||||
.PHONY: install-docs
|
||||
install-docs:
|
||||
sh ./docs/check_pkgs && $(MAKE) -C docs install || true
|
||||
|
||||
.PHONY: dev-docs
|
||||
dev-docs:
|
||||
$(MAKE) -C docs dev-docs
|
||||
|
||||
# Build all the various kernels and modules
|
||||
.PHONY: kbuild
|
||||
kbuild: kernels
|
||||
|
||||
# Delete the kernel build trees entirely
|
||||
.PHONY: kdelete
|
||||
kdelete:
|
||||
for i in $(XKERNELS) ; do $(MAKE) $$i-delete ; done
|
||||
|
||||
# Clean the kernel build trees
|
||||
.PHONY: kclean
|
||||
kclean:
|
||||
for i in $(XKERNELS) ; do $(MAKE) $$i-clean ; done
|
||||
|
||||
# Make patches from kernel sparse trees
|
||||
.PHONY: mkpatches
|
||||
mkpatches:
|
||||
for i in $(ALLSPARSETREES) ; do $(MAKE) $$i-xen.patch; done
|
||||
|
||||
# build xen, the tools, and a domain 0 plus unprivileged linux-xen images,
|
||||
# and place them in the install directory. 'make install' should then
|
||||
# copy them to the normal system directories
|
||||
.PHONY: world
|
||||
world:
|
||||
$(MAKE) clean
|
||||
$(MAKE) kdelete
|
||||
$(MAKE) dist
|
||||
|
||||
# clean doesn't do a kclean
|
||||
.PHONY: clean
|
||||
clean::
|
||||
$(MAKE) -C xen clean
|
||||
$(MAKE) -C tools clean
|
||||
$(MAKE) -C docs clean
|
||||
|
||||
# clean, but blow away kernel build tree plus tarballs
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
rm -rf dist patches/tmp
|
||||
for i in $(ALLKERNELS) ; do $(MAKE) $$i-delete ; done
|
||||
for i in $(ALLSPARSETREES) ; do $(MAKE) $$i-mrproper ; done
|
||||
|
||||
# Linux name for GNU distclean
|
||||
.PHONY: mrproper
|
||||
mrproper: distclean
|
||||
|
||||
install-logging: LOGGING=logging-0.4.9.2
|
||||
install-logging:
|
||||
[ -f $(LOGGING).tar.gz ] || wget http://www.red-dove.com/$(LOGGING).tar.gz
|
||||
tar -zxf $(LOGGING).tar.gz
|
||||
cd $(LOGGING) && python setup.py install
|
||||
|
||||
# handy target to upgrade iptables (use rpm or apt-get in preference)
|
||||
install-iptables:
|
||||
wget http://www.netfilter.org/files/iptables-1.2.11.tar.bz2
|
||||
tar -jxf iptables-1.2.11.tar.bz2
|
||||
$(MAKE) -C iptables-1.2.11 PREFIX= KERNEL_DIR=../linux-$(LINUX_VER)-xen0 install
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Installation targets:'
|
||||
@echo ' install - build and install everything'
|
||||
@@ -147,25 +153,28 @@ help:
|
||||
@echo ' dev-docs - build developer-only documentation'
|
||||
@echo ''
|
||||
@echo 'Cleaning targets:'
|
||||
@echo ' clean - clean the Xen, tools and docs (but not'
|
||||
@echo ' guest kernel) trees'
|
||||
@echo ' distclean - clean plus delete kernel tarballs and kernel'
|
||||
@echo ' build trees'
|
||||
@echo ' clean - clean the Xen, tools and docs (but not guest kernel trees)'
|
||||
@echo ' distclean - clean plus delete kernel build trees and'
|
||||
@echo ' local downloaded files'
|
||||
@echo ' kdelete - delete guest kernel build trees'
|
||||
@echo ' kclean - clean guest kernel build trees'
|
||||
@echo ''
|
||||
@echo 'Dependency installation targets:'
|
||||
@echo ' install-logging - install the Python Logging package'
|
||||
@echo ' install-iptables - install iptables tools'
|
||||
@echo ''
|
||||
@echo 'Miscellaneous targets:'
|
||||
@echo ' prep-kernels - prepares kernel directories, does not build'
|
||||
@echo ' mkpatches - make patches against vanilla kernels from'
|
||||
@echo ' sparse trees'
|
||||
@echo ' uninstall - attempt to remove installed Xen tools (use'
|
||||
@echo ' with extreme care!)'
|
||||
@echo ' uninstall - attempt to remove installed Xen tools'
|
||||
@echo ' (use with extreme care!)'
|
||||
@echo
|
||||
@echo 'Environment:'
|
||||
@echo ' XEN_PYTHON_NATIVE_INSTALL=y'
|
||||
@echo ' - native python install or dist'
|
||||
@echo ' install into prefix/lib/python<VERSION>'
|
||||
@echo ' instead of <PREFIX>/lib/python'
|
||||
@echo ' true if set to non-empty value, false otherwise'
|
||||
|
||||
# Use this target with extreme care!
|
||||
.PHONY: uninstall
|
||||
uninstall: D=$(DESTDIR)
|
||||
uninstall:
|
||||
[ -d $(D)/etc/xen ] && mv -f $(D)/etc/xen $(D)/etc/xen.old-`date +%s` || true
|
||||
@@ -199,5 +208,6 @@ uninstall:
|
||||
rm -rf $(D)/usr/share/man/man8/xen*
|
||||
|
||||
# Legacy targets for compatibility
|
||||
.PHONY: linux26
|
||||
linux26:
|
||||
$(MAKE) 'KERNELS=linux-2.6*' kernels
|
||||
@@ -1,158 +1,176 @@
|
||||
################################
|
||||
__ __ _____ ___
|
||||
\ \/ /___ _ __ |___ / / _ \
|
||||
\ // _ \ '_ \ |_ \| | | |
|
||||
/ \ __/ | | | ___) | |_| |
|
||||
/_/\_\___|_| |_| |____(_)___/
|
||||
|
||||
################################
|
||||
|
||||
http://www.xensource.com/xen/about.html
|
||||
|
||||
What is Xen?
|
||||
============
|
||||
|
||||
Xen is a Virtual Machine Monitor (VMM) originally developed by the
|
||||
Systems Research Group of the University of Cambridge Computer
|
||||
Laboratory, as part of the UK-EPSRC funded XenoServers project. Xen
|
||||
is freely-distributable Open Source software, released under the GNU
|
||||
GPL. Since its initial public release, Xen has grown a large
|
||||
development community, spearheaded by XenSource Inc, a company created
|
||||
by the original Xen development team to build enterprise products
|
||||
around Xen.
|
||||
|
||||
The 3.0 release offers excellent performance, hardware support and
|
||||
enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and
|
||||
live relocation of VMs. This install tree contains source for a Linux
|
||||
2.6 guest; ports to Linux 2.4, NetBSD, FreeBSD and Solaris will follow
|
||||
later (and are already available for previous Xen releases).
|
||||
|
||||
This file contains some quick-start instructions to install Xen on
|
||||
your system. For full documentation, see the Xen User Manual. If this
|
||||
is a pre-built release then you can find the manual at:
|
||||
dist/install/usr/share/doc/xen/pdf/user.pdf
|
||||
If you have a source release, then 'make -C docs' will build the
|
||||
manual at docs/pdf/user.pdf.
|
||||
|
||||
Quick-Start Guide - Pre-Built Binary Release
|
||||
============================================
|
||||
|
||||
[NB. Unless noted otherwise, all the following steps should be
|
||||
performed with root privileges.]
|
||||
|
||||
1. Install the binary distribution onto your filesystem:
|
||||
|
||||
# sh ./install.sh
|
||||
|
||||
Among other things, this will install Xen and Xen-ready Linux
|
||||
kernel files in /boot, kernel modules and Python packages in /lib,
|
||||
and various control tools in standard 'bin' directories.
|
||||
|
||||
2. Configure your bootloader to boot Xen and an initial Linux virtual
|
||||
machine. Note that Xen currently only works with GRUB and pxelinux
|
||||
derived boot loaders: less common alternatives such as LILO are
|
||||
*not* supported. You can most likely find your GRUB menu file at
|
||||
/boot/grub/menu.lst: edit this file to include an entry like the
|
||||
following:
|
||||
|
||||
title Xen 3.0 / XenLinux 2.6
|
||||
kernel /boot/xen-3.0.gz console=vga
|
||||
module /boot/vmlinuz-2.6-xen root=<root-dev> ro console=tty0
|
||||
module /boot/initrd-2.6-xen.img
|
||||
|
||||
NB: Not all kernel configs need an initial ram disk (initrd), but
|
||||
if you do specify one you'll need to use the 'module' grub directive
|
||||
rather than 'initrd'.
|
||||
|
||||
The linux command line takes all the usual options, such as
|
||||
root=<root-dev> to specify your usual root partition (e.g.,
|
||||
/dev/hda1).
|
||||
|
||||
The Xen command line takes a number of optional arguments described
|
||||
in the manual. The most common is 'dom0_mem=xxxM' which sets the
|
||||
amount of memory to allocate for use by your initial virtual
|
||||
machine (known as domain 0). Note that Xen itself reserves about
|
||||
32MB memory for internal use, which is not available for allocation
|
||||
to virtual machines.
|
||||
|
||||
3. Reboot your system and select the "Xen 3.0 / XenLinux 2.6" menu
|
||||
option. After booting Xen, Linux will start and your initialisation
|
||||
scripts should execute in the usual way.
|
||||
|
||||
Quick-Start Guide - Source Release
|
||||
==================================
|
||||
|
||||
First, there are a number of prerequisites for building a Xen source
|
||||
release. Make sure you have all the following installed, either by
|
||||
visiting the project webpage or installing a pre-built package
|
||||
provided by your Linux distributor:
|
||||
* GCC (preferably v3.2.x or v3.3.x; older versions are unsupported)
|
||||
* GNU Make
|
||||
* GNU Binutils
|
||||
* Development install of zlib (e.g., zlib-dev)
|
||||
* Development install of Python v2.3 or later (e.g., python-dev)
|
||||
* bridge-utils package (/sbin/brctl)
|
||||
* iproute package (/sbin/ip)
|
||||
* hotplug or udev
|
||||
|
||||
[NB. Unless noted otherwise, all the following steps should be
|
||||
performed with root privileges.]
|
||||
|
||||
1. Download and untar the source tarball file. This will be a
|
||||
file named xen-unstable-src.tgz, or xen-$version-src.tgz.
|
||||
You can also pull the current version from the SCMS
|
||||
that is being used (Bitkeeper, scheduled to change shortly).
|
||||
|
||||
# tar xzf xen-unstable-src.tgz
|
||||
|
||||
Assuming you are using the unstable tree, this will
|
||||
untar into xen-unstable. The rest of the instructions
|
||||
use the unstable tree as an example, substitute the
|
||||
version for unstable.
|
||||
|
||||
2. cd to xen-unstable (or whatever you sensibly rename it to).
|
||||
The Linux, netbsd and freebsd kernel source trees are in
|
||||
the $os-$version-xen-sparse directories.
|
||||
|
||||
On Linux:
|
||||
|
||||
3. For the very first build, or if you want to destroy existing
|
||||
.configs and build trees, perform the following steps:
|
||||
|
||||
# make KERNELS=linux-2.6-xen world
|
||||
# make install
|
||||
|
||||
It will create and install into the dist/ directory which is the
|
||||
default install location. It will build the xen binary (xen.gz),
|
||||
and a linux kernel and modules that can be used in both dom0 and an
|
||||
unprivileged guest kernel (vmlinuz-2.6.x-xen), the tools and the
|
||||
documentation.
|
||||
|
||||
If you don't specify KERNELS= on the make command line it will
|
||||
default to building two kernels, vmlinuz-2.6.x-xen0 and
|
||||
vmlinuz-2.6.x-xenU. These are smaller builds with just selected
|
||||
modules, intended primarilly for developers that don't like to wait
|
||||
for a -xen kernel to build. The -xenU kernel is particularly small
|
||||
as it does not contain any physical device drivers, and hence is
|
||||
only useful for guest domains.
|
||||
|
||||
If you want to build an x86_32 PAE capable xen and kernel to work
|
||||
on machines with >= 4GB of memory, use XEN_TARGET_X86_PAE=y on the
|
||||
make command line.
|
||||
|
||||
4. To rebuild an existing tree without modifying the config:
|
||||
# make dist
|
||||
|
||||
This will build and install xen, kernels, tools, and
|
||||
docs into the local dist/ directory.
|
||||
|
||||
5. To rebuild a kernel with a modified config:
|
||||
|
||||
# make linux-2.6-xen-config CONFIGMODE=menuconfig (or xconfig)
|
||||
# make linux-2.6-xen-build
|
||||
# make linux-2.6-xen-install
|
||||
|
||||
Depending on your config, you may need to use 'mkinitrd' to create
|
||||
an initial ram disk, just like a native system e.g.
|
||||
# depmod 2.6.12.6-xen
|
||||
# mkinitrd -v -f --with=aacraid --with=sd_mod --with=scsi_mod initrd-2.6.12.6-xen.img 2.6.12.6-xen
|
||||
################################
|
||||
__ __ _____ ___
|
||||
\ \/ /___ _ __ |___ / / _ \
|
||||
\ // _ \ '_ \ |_ \| | | |
|
||||
/ \ __/ | | | ___) | |_| |
|
||||
/_/\_\___|_| |_| |____(_)___/
|
||||
|
||||
################################
|
||||
|
||||
http://www.xensource.com/xen/about.html
|
||||
|
||||
What is Xen?
|
||||
============
|
||||
|
||||
Xen is a Virtual Machine Monitor (VMM) originally developed by the
|
||||
Systems Research Group of the University of Cambridge Computer
|
||||
Laboratory, as part of the UK-EPSRC funded XenoServers project. Xen
|
||||
is freely-distributable Open Source software, released under the GNU
|
||||
GPL. Since its initial public release, Xen has grown a large
|
||||
development community, spearheaded by XenSource Inc, a company created
|
||||
by the original Xen development team to build enterprise products
|
||||
around Xen.
|
||||
|
||||
The 3.0 release offers excellent performance, hardware support and
|
||||
enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and
|
||||
live relocation of VMs. This install tree contains source for a Linux
|
||||
2.6 guest; ports to Linux 2.4, NetBSD, FreeBSD and Solaris will follow
|
||||
later (and are already available for previous Xen releases).
|
||||
|
||||
This file contains some quick-start instructions to install Xen on
|
||||
your system. For full documentation, see the Xen User Manual. If this
|
||||
is a pre-built release then you can find the manual at:
|
||||
dist/install/usr/share/doc/xen/pdf/user.pdf
|
||||
If you have a source release, then 'make -C docs' will build the
|
||||
manual at docs/pdf/user.pdf.
|
||||
|
||||
Quick-Start Guide - Pre-Built Binary Release
|
||||
============================================
|
||||
|
||||
[NB. Unless noted otherwise, all the following steps should be
|
||||
performed with root privileges.]
|
||||
|
||||
1. Install the binary distribution onto your filesystem:
|
||||
|
||||
# sh ./install.sh
|
||||
|
||||
Among other things, this will install Xen and Xen-ready Linux
|
||||
kernel files in /boot, kernel modules and Python packages in /lib,
|
||||
and various control tools in standard 'bin' directories.
|
||||
|
||||
2. Configure your bootloader to boot Xen and an initial Linux virtual
|
||||
machine. Note that Xen currently only works with GRUB and pxelinux
|
||||
derived boot loaders: less common alternatives such as LILO are
|
||||
*not* supported. You can most likely find your GRUB menu file at
|
||||
/boot/grub/menu.lst: edit this file to include an entry like the
|
||||
following:
|
||||
|
||||
title Xen 3.0 / XenLinux 2.6
|
||||
kernel /boot/xen-3.0.gz console=vga
|
||||
module /boot/vmlinuz-2.6-xen root=<root-dev> ro console=tty0
|
||||
module /boot/initrd-2.6-xen.img
|
||||
|
||||
NB: Not all kernel configs need an initial ram disk (initrd), but
|
||||
if you do specify one you'll need to use the 'module' grub directive
|
||||
rather than 'initrd'.
|
||||
|
||||
The linux command line takes all the usual options, such as
|
||||
root=<root-dev> to specify your usual root partition (e.g.,
|
||||
/dev/hda1).
|
||||
|
||||
The Xen command line takes a number of optional arguments described
|
||||
in the manual. The most common is 'dom0_mem=xxxM' which sets the
|
||||
amount of memory to allocate for use by your initial virtual
|
||||
machine (known as domain 0). Note that Xen itself reserves about
|
||||
32MB memory for internal use, which is not available for allocation
|
||||
to virtual machines.
|
||||
|
||||
3. Reboot your system and select the "Xen 3.0 / XenLinux 2.6" menu
|
||||
option. After booting Xen, Linux will start and your initialisation
|
||||
scripts should execute in the usual way.
|
||||
|
||||
Quick-Start Guide - Source Release
|
||||
==================================
|
||||
|
||||
First, there are a number of prerequisites for building a Xen source
|
||||
release. Make sure you have all the following installed, either by
|
||||
visiting the project webpage or installing a pre-built package
|
||||
provided by your Linux distributor:
|
||||
* GCC (preferably v3.2.x or v3.3.x; older versions are unsupported)
|
||||
* GNU Make
|
||||
* GNU Binutils
|
||||
* Development install of zlib (e.g., zlib-dev)
|
||||
* Development install of Python v2.3 or later (e.g., python-dev)
|
||||
* bridge-utils package (/sbin/brctl)
|
||||
* iproute package (/sbin/ip)
|
||||
* hotplug or udev
|
||||
|
||||
[NB. Unless noted otherwise, all the following steps should be
|
||||
performed with root privileges.]
|
||||
|
||||
1. Download and untar the source tarball file. This will be a
|
||||
file named xen-unstable-src.tgz, or xen-$version-src.tgz.
|
||||
You can also pull the current version from the SCMS
|
||||
that is being used (Bitkeeper, scheduled to change shortly).
|
||||
|
||||
# tar xzf xen-unstable-src.tgz
|
||||
|
||||
Assuming you are using the unstable tree, this will
|
||||
untar into xen-unstable. The rest of the instructions
|
||||
use the unstable tree as an example, substitute the
|
||||
version for unstable.
|
||||
|
||||
2. cd to xen-unstable (or whatever you sensibly rename it to).
|
||||
The Linux, netbsd and freebsd kernel source trees are in
|
||||
the $os-$version-xen-sparse directories.
|
||||
|
||||
On Linux:
|
||||
|
||||
3. For the very first build, or if you want to destroy existing
|
||||
.configs and build trees, perform the following steps:
|
||||
|
||||
# make world
|
||||
# make install
|
||||
|
||||
This will create and install onto the local machine. It will build
|
||||
the xen binary (xen.gz), and a linux kernel and modules that can be
|
||||
used in both dom0 and an unprivileged guest kernel (vmlinuz-2.6.x-xen),
|
||||
the tools and the documentation.
|
||||
|
||||
You can override the destination for make install by setting DESTDIR
|
||||
to some value.
|
||||
|
||||
The make command line defaults to building the kernel vmlinuz-2.6.x-xen.
|
||||
You can override this default by specifying KERNELS=kernelname. For
|
||||
example, you can make two kernels - linux-2.6-xen0
|
||||
and linux-2.6-xenU - which are smaller builds containing only selected
|
||||
modules, intended primarily for developers that don't like to wait
|
||||
for a full -xen kernel to build. The -xenU kernel is particularly small,
|
||||
as it does not contain any physical device drivers, and hence is
|
||||
only useful for guest domains.
|
||||
|
||||
To make these two kernels, simply specify
|
||||
|
||||
KERNELS="linux-2.6-xen0 linux-2.6-xenU"
|
||||
|
||||
in the make command line.
|
||||
|
||||
If you want to build an x86_32 PAE capable xen and kernel to work
|
||||
on machines with >= 4GB of memory, use XEN_TARGET_X86_PAE=y on the
|
||||
make command line.
|
||||
|
||||
4. To rebuild an existing tree without modifying the config:
|
||||
# make dist
|
||||
|
||||
This will build and install xen, kernels, tools, and
|
||||
docs into the local dist/ directory.
|
||||
|
||||
You can override the destination for make install by setting DISTDIR
|
||||
to some value.
|
||||
|
||||
make install and make dist differ in that make install does the
|
||||
right things for your local machine (installing the appropriate
|
||||
version of hotplug or udev scripts, for example), but make dist
|
||||
includes all versions of those scripts, so that you can copy the dist
|
||||
directory to another machine and install from that distribution.
|
||||
|
||||
5. To rebuild a kernel with a modified config:
|
||||
|
||||
# make linux-2.6-xen-config CONFIGMODE=menuconfig (or xconfig)
|
||||
# make linux-2.6-xen-build
|
||||
# make linux-2.6-xen-install
|
||||
|
||||
Depending on your config, you may need to use 'mkinitrd' to create
|
||||
an initial ram disk, just like a native system e.g.
|
||||
# depmod 2.6.16-xen
|
||||
# mkinitrd -v -f --with=aacraid --with=sd_mod --with=scsi_mod initrd-2.6.16-xen.img 2.6.16-xen
|
||||
+5
-35
@@ -6,8 +6,6 @@ export DESTDIR
|
||||
ALLKERNELS = $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.*))
|
||||
ALLSPARSETREES = $(patsubst %-xen-sparse,%,$(wildcard *-xen-sparse))
|
||||
|
||||
.PHONY: mkpatches mrproper
|
||||
|
||||
# Setup pristine search path
|
||||
PRISTINE_SRC_PATH ?= .:..
|
||||
vpath pristine-% $(PRISTINE_SRC_PATH)
|
||||
@@ -40,29 +38,6 @@ patch-%.bz2:
|
||||
@echo "Cannot find $(@F) in path $(LINUX_SRC_PATH)"
|
||||
wget $(KERNEL_REPO)/pub/linux/kernel/v$(_LINUX_VDIR)/$(_LINUX_XDIR)/$(@F) -O./$@
|
||||
|
||||
# Expand NetBSD release to NetBSD version
|
||||
NETBSD_RELEASE ?= 2.0
|
||||
NETBSD_VER ?= $(patsubst netbsd-%-xen-sparse,%,$(wildcard netbsd-$(NETBSD_RELEASE)*-xen-sparse))
|
||||
NETBSD_CVSSNAP ?= 20050309
|
||||
|
||||
# Setup NetBSD search path
|
||||
NETBSD_SRC_PATH ?= .:..
|
||||
vpath netbsd-%.tar.bz2 $(NETBSD_SRC_PATH)
|
||||
|
||||
# download a pristine NetBSD tarball if there isn't one in NETBSD_SRC_PATH
|
||||
netbsd-%-xen-kernel-$(NETBSD_CVSSNAP).tar.bz2:
|
||||
@echo "Cannot find $@ in path $(NETBSD_SRC_PATH)"
|
||||
wget http://www.cl.cam.ac.uk/Research/SRG/netos/xen/downloads/$@ -O./$@
|
||||
|
||||
netbsd-%.tar.bz2: netbsd-%-xen-kernel-$(NETBSD_CVSSNAP).tar.bz2
|
||||
ln -fs $< $@
|
||||
|
||||
ifeq ($(OS),linux)
|
||||
OS_VER = $(LINUX_VER)
|
||||
else
|
||||
OS_VER = $(NETBSD_VER)
|
||||
endif
|
||||
|
||||
pristine-%: pristine-%/.valid-pristine
|
||||
@true
|
||||
|
||||
@@ -84,6 +59,7 @@ ifneq ($(PATCHDIRS),)
|
||||
$(patsubst patches/%,patches/%/.makedep,$(PATCHDIRS)): patches/%/.makedep:
|
||||
@echo 'ref-$*/.valid-ref: $$(wildcard patches/$*/*.patch)' >$@
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
rm -f patches/*/.makedep
|
||||
|
||||
@@ -124,27 +100,21 @@ linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref
|
||||
rm -rf tmp-$@
|
||||
cp -al $(<D) tmp-$@
|
||||
( cd linux-2.6-xen-sparse && ./mkbuildtree ../tmp-$@ )
|
||||
diff -Nurp $(<D) tmp-$@ > $@ || true
|
||||
diff -Nurp $(patsubst ref%,pristine%,$(<D)) tmp-$@ > $@ || true
|
||||
rm -rf tmp-$@
|
||||
|
||||
%-xen.patch: ref-%/.valid-ref
|
||||
rm -rf tmp-$@
|
||||
cp -al $(<D) tmp-$@
|
||||
( cd $*-xen-sparse && ./mkbuildtree ../tmp-$@ )
|
||||
diff -Nurp $(<D) tmp-$@ > $@ || true
|
||||
diff -Nurp $(patsubst ref%,pristine%,$(<D)) tmp-$@ > $@ || true
|
||||
rm -rf tmp-$@
|
||||
|
||||
%-mrproper: %-mrproper-extra
|
||||
%-mrproper:
|
||||
rm -rf pristine-$(*)* ref-$(*)* $*.tar.bz2
|
||||
rm -rf $*-xen.patch
|
||||
|
||||
netbsd-%-mrproper-extra:
|
||||
rm -rf netbsd-$*-tools netbsd-$*-tools.tar.bz2
|
||||
rm -f netbsd-$*-xen-kernel-$(NETBSD_CVSSNAP).tar.bz2
|
||||
|
||||
%-mrproper-extra:
|
||||
@: # do nothing
|
||||
|
||||
.PHONY: config-update-pae
|
||||
config-update-pae:
|
||||
ifeq ($(XEN_TARGET_X86_PAE),y)
|
||||
sed -e 's!^CONFIG_HIGHMEM4G=y$$!\# CONFIG_HIGHMEM4G is not set!;s!^\# CONFIG_HIGHMEM64G is not set$$!CONFIG_HIGHMEM64G=y!' $(CONFIG_FILE) > $(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE)
|
||||
|
||||
@@ -95,6 +95,7 @@ CONFIG_ARCH_XEN=y
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
CONFIG_XEN_BLKDEV_GRANT=y
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16-rc3-xen0
|
||||
# Thu Feb 16 22:52:42 2006
|
||||
# Linux kernel version: 2.6.16-xen0
|
||||
# Sat Apr 8 11:34:07 2006
|
||||
#
|
||||
CONFIG_X86_32=y
|
||||
CONFIG_SEMAPHORE_SLEEPERS=y
|
||||
@@ -208,7 +208,6 @@ CONFIG_ACPI_BLACKLIST_YEAR=0
|
||||
CONFIG_ACPI_EC=y
|
||||
CONFIG_ACPI_POWER=y
|
||||
CONFIG_ACPI_SYSTEM=y
|
||||
# CONFIG_X86_PM_TIMER is not set
|
||||
# CONFIG_ACPI_CONTAINER is not set
|
||||
|
||||
#
|
||||
@@ -392,7 +391,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
# CONFIG_PNP is not set
|
||||
CONFIG_PNP=y
|
||||
CONFIG_PNP_DEBUG=y
|
||||
|
||||
#
|
||||
# Protocols
|
||||
#
|
||||
CONFIG_PNPACPI=y
|
||||
|
||||
#
|
||||
# Block devices
|
||||
@@ -440,6 +445,7 @@ CONFIG_BLK_DEV_IDECD=y
|
||||
#
|
||||
CONFIG_IDE_GENERIC=y
|
||||
# CONFIG_BLK_DEV_CMD640 is not set
|
||||
# CONFIG_BLK_DEV_IDEPNP is not set
|
||||
CONFIG_BLK_DEV_IDEPCI=y
|
||||
# CONFIG_IDEPCI_SHARE_IRQ is not set
|
||||
# CONFIG_BLK_DEV_OFFBOARD is not set
|
||||
@@ -623,6 +629,7 @@ CONFIG_NETDEVICES=y
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
CONFIG_TUN=y
|
||||
# CONFIG_NET_SB1000 is not set
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
@@ -1064,11 +1071,7 @@ CONFIG_USB_MON=y
|
||||
# CONFIG_INFINIBAND is not set
|
||||
|
||||
#
|
||||
# SN Devices
|
||||
#
|
||||
|
||||
#
|
||||
# EDAC - error detection and reporting (RAS)
|
||||
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_EDAC is not set
|
||||
|
||||
@@ -1231,6 +1234,7 @@ CONFIG_NLS_ISO8859_1=y
|
||||
#
|
||||
# Instrumentation Support
|
||||
#
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_KPROBES is not set
|
||||
|
||||
#
|
||||
@@ -1305,13 +1309,14 @@ CONFIG_CRYPTO_CRC32C=m
|
||||
#
|
||||
# CONFIG_CRYPTO_DEV_PADLOCK is not set
|
||||
CONFIG_XEN=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030101
|
||||
|
||||
#
|
||||
# XEN
|
||||
#
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
|
||||
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
|
||||
@@ -1331,6 +1336,7 @@ CONFIG_XEN_DISABLE_SERIAL=y
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_HAVE_ARCH_ALLOC_SKB=y
|
||||
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
@@ -1343,4 +1349,6 @@ CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_GENERIC_IRQ_PROBE=y
|
||||
CONFIG_X86_BIOS_REBOOT=y
|
||||
CONFIG_X86_NO_TSS=y
|
||||
CONFIG_X86_NO_IDT=y
|
||||
CONFIG_KTIME_SCALAR=y
|
||||
@@ -327,7 +327,13 @@ CONFIG_STANDALONE=y
|
||||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
# CONFIG_PNP is not set
|
||||
CONFIG_PNP=y
|
||||
CONFIG_PNP_DEBUG=y
|
||||
|
||||
#
|
||||
# Protocols
|
||||
#
|
||||
CONFIG_PNPACPI=y
|
||||
|
||||
#
|
||||
# Block devices
|
||||
@@ -375,6 +381,7 @@ CONFIG_BLK_DEV_IDECD=y
|
||||
#
|
||||
CONFIG_IDE_GENERIC=y
|
||||
# CONFIG_BLK_DEV_CMD640 is not set
|
||||
# CONFIG_BLK_DEV_IDEPNP is not set
|
||||
CONFIG_BLK_DEV_IDEPCI=y
|
||||
# CONFIG_IDEPCI_SHARE_IRQ is not set
|
||||
# CONFIG_BLK_DEV_OFFBOARD is not set
|
||||
@@ -559,6 +566,7 @@ CONFIG_NETDEVICES=y
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
CONFIG_TUN=y
|
||||
# CONFIG_NET_SB1000 is not set
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
@@ -1183,6 +1191,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
@@ -1237,6 +1246,7 @@ CONFIG_NO_IDLE_HZ=y
|
||||
#
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
|
||||
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
|
||||
|
||||
@@ -92,6 +92,7 @@ CONFIG_ARCH_XEN=y
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
CONFIG_XEN_BLKDEV_GRANT=y
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
|
||||
@@ -779,6 +779,7 @@ CONFIG_NLS_ISO8859_1=y
|
||||
#
|
||||
# Instrumentation Support
|
||||
#
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_KPROBES is not set
|
||||
|
||||
#
|
||||
@@ -858,13 +859,9 @@ CONFIG_NO_IDLE_HZ=y
|
||||
#
|
||||
# CONFIG_XEN_PRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_UNPRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND is not set
|
||||
# CONFIG_XEN_BLKDEV_BACKEND is not set
|
||||
# CONFIG_XEN_NETDEV_BACKEND is not set
|
||||
# CONFIG_XEN_TPMDEV_BACKEND is not set
|
||||
# CONFIG_XEN_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
# CONFIG_XEN_BLKDEV_TAP is not set
|
||||
# CONFIG_XEN_TPMDEV_FRONTEND is not set
|
||||
CONFIG_XEN_SCRUB_PAGES=y
|
||||
CONFIG_XEN_DISABLE_SERIAL=y
|
||||
|
||||
@@ -1080,6 +1080,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
@@ -1134,13 +1135,9 @@ CONFIG_NO_IDLE_HZ=y
|
||||
#
|
||||
# CONFIG_XEN_PRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_UNPRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND is not set
|
||||
# CONFIG_XEN_BLKDEV_BACKEND is not set
|
||||
# CONFIG_XEN_NETDEV_BACKEND is not set
|
||||
# CONFIG_XEN_TPMDEV_BACKEND is not set
|
||||
# CONFIG_XEN_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
# CONFIG_XEN_BLKDEV_TAP is not set
|
||||
# CONFIG_XEN_TPMDEV_FRONTEND is not set
|
||||
CONFIG_XEN_SCRUB_PAGES=y
|
||||
CONFIG_XEN_DISABLE_SERIAL=y
|
||||
|
||||
@@ -95,6 +95,7 @@ CONFIG_ARCH_XEN=y
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
CONFIG_XEN_BLKDEV_GRANT=y
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
|
||||
@@ -292,11 +292,11 @@ CONFIG_NET=y
|
||||
# Networking options
|
||||
#
|
||||
# CONFIG_NETDEBUG is not set
|
||||
CONFIG_PACKET=m
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_PACKET_MMAP=y
|
||||
CONFIG_UNIX=m
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM=y
|
||||
CONFIG_XFRM_USER=m
|
||||
CONFIG_XFRM_USER=y
|
||||
CONFIG_NET_KEY=m
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
@@ -912,12 +912,12 @@ CONFIG_PARPORT_1284=y
|
||||
# Plug and Play support
|
||||
#
|
||||
CONFIG_PNP=y
|
||||
# CONFIG_PNP_DEBUG is not set
|
||||
CONFIG_PNP_DEBUG=y
|
||||
|
||||
#
|
||||
# Protocols
|
||||
#
|
||||
# CONFIG_PNPACPI is not set
|
||||
CONFIG_PNPACPI=y
|
||||
|
||||
#
|
||||
# Block devices
|
||||
@@ -2892,6 +2892,7 @@ CONFIG_NLS_UTF8=m
|
||||
#
|
||||
# Instrumentation Support
|
||||
#
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_KPROBES is not set
|
||||
|
||||
#
|
||||
@@ -2978,6 +2979,7 @@ CONFIG_NO_IDLE_HZ=y
|
||||
#
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
|
||||
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
|
||||
|
||||
@@ -776,7 +776,13 @@ CONFIG_PARPORT_1284=y
|
||||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
# CONFIG_PNP is not set
|
||||
CONFIG_PNP=y
|
||||
CONFIG_PNP_DEBUG=y
|
||||
|
||||
#
|
||||
# Protocols
|
||||
#
|
||||
CONFIG_PNPACPI=y
|
||||
|
||||
#
|
||||
# Block devices
|
||||
@@ -857,6 +863,7 @@ CONFIG_BLK_DEV_IDESCSI=m
|
||||
CONFIG_IDE_GENERIC=y
|
||||
CONFIG_BLK_DEV_CMD640=y
|
||||
CONFIG_BLK_DEV_CMD640_ENHANCED=y
|
||||
CONFIG_BLK_DEV_IDEPNP=y
|
||||
CONFIG_BLK_DEV_IDEPCI=y
|
||||
CONFIG_IDEPCI_SHARE_IRQ=y
|
||||
# CONFIG_BLK_DEV_OFFBOARD is not set
|
||||
@@ -1088,6 +1095,7 @@ CONFIG_DUMMY=m
|
||||
CONFIG_BONDING=m
|
||||
CONFIG_EQUALIZER=m
|
||||
CONFIG_TUN=m
|
||||
CONFIG_NET_SB1000=m
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
@@ -2587,6 +2595,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
# CONFIG_FRAME_POINTER is not set
|
||||
@@ -2647,6 +2656,7 @@ CONFIG_NO_IDLE_HZ=y
|
||||
#
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
|
||||
CONFIG_XEN_PCIDEV_BACKEND_PASS=y
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
|
||||
OS = linux
|
||||
|
||||
LINUX_SERIES = 2.6
|
||||
LINUX_VER = 2.6.16
|
||||
LINUX_SRCS = linux-2.6.16.tar.bz2
|
||||
|
||||
EXTRAVERSION ?= xen
|
||||
|
||||
LINUX_DIR = $(OS)-$(LINUX_VER)-$(EXTRAVERSION)
|
||||
LINUX_DIR = linux-$(LINUX_VER)-$(EXTRAVERSION)
|
||||
|
||||
include buildconfigs/Rules.mk
|
||||
|
||||
.PHONY: build clean delete
|
||||
|
||||
# The real action starts here!
|
||||
.PHONY: build
|
||||
build: $(LINUX_DIR)/include/linux/autoconf.h
|
||||
if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
|
||||
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
|
||||
@@ -22,7 +18,7 @@ build: $(LINUX_DIR)/include/linux/autoconf.h
|
||||
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) vmlinuz
|
||||
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) install
|
||||
|
||||
$(LINUX_DIR)/include/linux/autoconf.h: ref-$(OS)-$(LINUX_VER)/.valid-ref
|
||||
$(LINUX_DIR)/include/linux/autoconf.h: ref-linux-$(LINUX_VER)/.valid-ref
|
||||
rm -rf $(LINUX_DIR)
|
||||
cp -al $(<D) $(LINUX_DIR)
|
||||
# Apply arch-xen patches
|
||||
@@ -42,14 +38,18 @@ $(LINUX_DIR)/include/linux/autoconf.h: ref-$(OS)-$(LINUX_VER)/.valid-ref
|
||||
rm -f Makefile ; mv Mk.tmp Makefile )
|
||||
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) oldconfig
|
||||
|
||||
.PHONY: prep
|
||||
prep: $(LINUX_DIR)/include/linux/autoconf.h
|
||||
|
||||
.PHONY: config
|
||||
config: CONFIGMODE = menuconfig
|
||||
config: $(LINUX_DIR)/include/linux/autoconf.h
|
||||
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
|
||||
|
||||
.PHONY: delete
|
||||
delete:
|
||||
rm -rf tmp-$(OS)-$(LINUX_VER) $(LINUX_DIR)
|
||||
rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR)
|
||||
+11
-2
@@ -26,22 +26,28 @@ DOC_HTML := $(patsubst src/%.tex,html/%/index.html,$(DOC_TEX))
|
||||
|
||||
GFX = $(patsubst %.fig, %.eps, $(wildcard figs/*.fig))
|
||||
|
||||
.PHONY: all build dev-docs python-dev-docs ps pdf html clean install
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
.PHONY: build
|
||||
build: ps pdf html man-pages
|
||||
rm -f *.aux *.dvi *.bbl *.blg *.glo *.idx *.ilg *.log *.ind *.toc
|
||||
|
||||
.PHONY: dev-docs
|
||||
dev-docs: python-dev-docs
|
||||
|
||||
.PHONY: ps
|
||||
ps: $(DOC_PS)
|
||||
|
||||
.PHONY: pdf
|
||||
pdf: $(DOC_PDF)
|
||||
|
||||
.PHONY: html
|
||||
html:
|
||||
@if which $(LATEX2HTML) 1>/dev/null 2>/dev/null; then \
|
||||
$(MAKE) $(DOC_HTML); fi
|
||||
|
||||
.PHONY: python-dev-docs
|
||||
python-dev-docs:
|
||||
@mkdir -v -p api/tools/python
|
||||
@if which $(DOXYGEN) 1>/dev/null 2>/dev/null; then \
|
||||
@@ -50,6 +56,7 @@ python-dev-docs:
|
||||
$(MAKE) -C api/tools/python/latex ; else \
|
||||
echo "Doxygen not installed; skipping python-dev-docs."; fi
|
||||
|
||||
.PHONY: man-pages
|
||||
man-pages:
|
||||
@if which $(POD2MAN) 1>/dev/null 2>/dev/null; then \
|
||||
$(MAKE) $(DOC_MAN1) $(DOC_MAN5); fi
|
||||
@@ -64,6 +71,7 @@ man5/%.5: man/%.pod.5 Makefile
|
||||
$(POD2MAN) --release=$(VERSION) --name=`echo $@ | sed 's/^man5.//'| \
|
||||
sed 's/.5//'` -s 5 -c "Xen" $< $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf .word_count *.aux *.dvi *.bbl *.blg *.glo *.idx *~
|
||||
rm -rf *.ilg *.log *.ind *.toc *.bak core
|
||||
@@ -72,6 +80,7 @@ clean:
|
||||
rm -rf man5
|
||||
rm -rf man1
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
rm -rf $(DESTDIR)$(pkgdocdir)
|
||||
$(INSTALL_DIR) $(DESTDIR)$(pkgdocdir)
|
||||
|
||||
+3
-3
@@ -360,7 +360,7 @@ your Linux Kernel sources.
|
||||
Moves a domain out of the paused state. This will allow a previously
|
||||
paused domain to now be eligible for scheduling by the Xen hypervisor.
|
||||
|
||||
=item B<set-vcpus> I<domain-id> I<vcpu-count>
|
||||
=item B<vcpu-set> I<domain-id> I<vcpu-count>
|
||||
|
||||
Enables the I<vcpu-count> virtual CPUs for the domain in question.
|
||||
Like mem-set, this command can only allocate up to the maximum virtual
|
||||
@@ -370,8 +370,8 @@ If the I<vcpu-count> is smaller than the current number of active
|
||||
VCPUs, the highest number VCPUs will be hotplug removed. This may be
|
||||
important for pinning purposes.
|
||||
|
||||
Attempting to set-vcpus to a number larger than the initially
|
||||
configured VCPU count is an error. Trying to set-vcpus to < 1 will be
|
||||
Attempting to set the VCPUs to a number larger than the initially
|
||||
configured VCPU count is an error. Trying to set VCPUs to < 1 will be
|
||||
quietly ignored.
|
||||
|
||||
=item B<vcpu-list> I<[domain-id]>
|
||||
|
||||
+27
-1
@@ -2052,7 +2052,7 @@ dev86 & The dev86 package provides an assembler and linker for real mode 80x86 i
|
||||
|
||||
If the dev86 package is not available on the x86\_64 distribution, you can install the i386 version of it. The dev86 rpm package for various distributions can be found at {\scriptsize {\tt http://www.rpmfind.net/linux/rpm2html/search.php?query=dev86\&submit=Search}} \\
|
||||
|
||||
LibVNCServer & The unmodified guest's VGA display, keyboard, and mouse are virtualized using the vncserver library provided by this package. You can get the sources of libvncserver from {\small {\tt http://sourceforge.net/projects/libvncserver}}. Build and install the sources on the build system to get the libvncserver library. The 0.8pre version of libvncserver is currently working well with Xen.\\
|
||||
LibVNCServer & The unmodified guest's VGA display, keyboard, and mouse can be virtualized by the vncserver library. You can get the sources of libvncserver from {\small {\tt http://sourceforge.net/projects/libvncserver}}. Build and install the sources on the build system to get the libvncserver library. There is a significant performance degradation in 0.8 version. The current sources in the CVS tree have fixed this degradation. So it is highly recommended to download the latest CVS sources and install them.\\
|
||||
|
||||
SDL-devel, SDL & Simple DirectMedia Layer (SDL) is another way of virtualizing the unmodified guest console. It provides an X window for the guest console.
|
||||
|
||||
@@ -2077,6 +2077,8 @@ acpi & Enable VMX guest ACPI, default=0 (disabled)\\
|
||||
|
||||
apic & Enable VMX guest APIC, default=0 (disabled)\\
|
||||
|
||||
pae & Enable VMX guest PAE, default=0 (disabled)\\
|
||||
|
||||
vif & Optionally defines MAC address and/or bridge for the network interfaces. Random MACs are assigned if not given. {\small {\tt type=ioemu}} means ioemu is used to virtualize the VMX NIC. If no type is specified, vbd is used, as with paravirtualized guests.\\
|
||||
|
||||
disk & Defines the disk devices you want the domain to have access to, and what you want them accessible as. If using a physical device as the VMX guest's disk, each disk entry is of the form
|
||||
@@ -2229,6 +2231,30 @@ Simply follow the usual method of creating the guest, using the -f parameter and
|
||||
|
||||
In the default configuration, VNC is on and SDL is off. Therefore VNC windows will open when VMX guests are created. If you want to use SDL to create VMX guests, set {\small {\tt sdl=1}} in your VMX configuration file. You can also turn off VNC by setting {\small {\tt vnc=0}}.
|
||||
|
||||
\subsection{Use mouse in VNC window}
|
||||
The default PS/2 mouse will not work properly in VMX by a VNC window. Summagraphics mouse emulation does work in this environment. A Summagraphics mouse can be enabled by reconfiguring 2 services:
|
||||
|
||||
{\small {\tt 1. General Purpose Mouse (GPM). The GPM daemon is configured in different ways in different Linux distributions. On a Redhat distribution, this is accomplished by changing the file `/etc/sysconfig/mouse' to have the following:\\
|
||||
MOUSETYPE="summa"\\
|
||||
XMOUSETYPE="SUMMA"\\
|
||||
DEVICE=/dev/ttyS0\\
|
||||
\\
|
||||
2. X11. For all Linux distributions, change the Mouse0 stanza in `/etc/X11/xorg.conf' to:\\
|
||||
Section "InputDevice"\\
|
||||
Identifier "Mouse0"\\
|
||||
Driver "summa"\\
|
||||
Option "Device" "/dev/ttyS0"\\
|
||||
Option "InputFashion" "Tablet"\\
|
||||
Option "Mode" "Absolute"\\
|
||||
Option "Name" "EasyPen"\\
|
||||
Option "Compatible" "True"\\
|
||||
Option "Protocol" "Auto"\\
|
||||
Option "SendCoreEvents" "on"\\
|
||||
Option "Vendor" "GENIUS"\\
|
||||
EndSection}}
|
||||
|
||||
If the Summagraphics mouse isn't the default mouse, you can manually kill 'gpm' and restart it with the command "gpm -m /dev/ttyS0 -t summa". Note that Summagraphics mouse makes no sense in an SDL window and is therefore not available in this environment.
|
||||
|
||||
\subsection{Destroy VMX guests}
|
||||
VMX guests can be destroyed in the same way as can paravirtualized guests. We recommend that you type the command
|
||||
|
||||
|
||||
@@ -37,8 +37,10 @@ OBJS += $(patsubst %.c,%.o,$(wildcard console/*.c))
|
||||
HDRS := $(wildcard include/*.h)
|
||||
HDRS += $(wildcard include/xen/*.h)
|
||||
|
||||
.PHONY: default
|
||||
default: $(TARGET)
|
||||
|
||||
.PHONY: links
|
||||
links:
|
||||
[ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
|
||||
|
||||
@@ -46,6 +48,7 @@ $(TARGET): links $(OBJS)
|
||||
$(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf
|
||||
gzip -f -9 -c $@.elf >$@.gz
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
find . -type f -name '*.o' | xargs rm -f
|
||||
rm -f *.o *~ core $(TARGET).elf $(TARGET).raw $(TARGET) $(TARGET).gz
|
||||
|
||||
+25
-28
@@ -4,6 +4,7 @@
|
||||
#include <hypervisor.h>
|
||||
#include <mm.h>
|
||||
#include <lib.h>
|
||||
#include <sched.h>
|
||||
|
||||
/*
|
||||
* These are assembler stubs in entry.S.
|
||||
@@ -31,6 +32,8 @@ void machine_check(void);
|
||||
|
||||
void dump_regs(struct pt_regs *regs)
|
||||
{
|
||||
printk("Thread: %s\n", current->name);
|
||||
#ifdef __i386__
|
||||
printk("EIP: %x, EFLAGS %x.\n", regs->eip, regs->eflags);
|
||||
printk("EBX: %08x ECX: %08x EDX: %08x\n",
|
||||
regs->ebx, regs->ecx, regs->edx);
|
||||
@@ -40,9 +43,22 @@ void dump_regs(struct pt_regs *regs)
|
||||
regs->xds, regs->xes, regs->orig_eax, regs->eip);
|
||||
printk("CS: %04x EFLAGS: %08x esp: %08x ss: %04x\n",
|
||||
regs->xcs, regs->eflags, regs->esp, regs->xss);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
|
||||
printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n",
|
||||
regs->ss, regs->rsp, regs->eflags);
|
||||
printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
|
||||
regs->rax, regs->rbx, regs->rcx);
|
||||
printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
|
||||
regs->rdx, regs->rsi, regs->rdi);
|
||||
printk("RBP: %016lx R08: %016lx R09: %016lx\n",
|
||||
regs->rbp, regs->r8, regs->r9);
|
||||
printk("R10: %016lx R11: %016lx R12: %016lx\n",
|
||||
regs->r10, regs->r11, regs->r12);
|
||||
printk("R13: %016lx R14: %016lx R15: %016lx\n",
|
||||
regs->r13, regs->r14, regs->r15);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void do_trap(int trapnr, char *str, struct pt_regs * regs, unsigned long error_code)
|
||||
{
|
||||
@@ -110,36 +126,17 @@ void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
printk("Page fault at linear address %p, regs %p, code %lx\n", addr, regs,
|
||||
error_code);
|
||||
dump_regs(regs);
|
||||
#ifdef __x86_64__
|
||||
/* FIXME: _PAGE_PSE */
|
||||
{
|
||||
unsigned long *tab = (unsigned long *)start_info.pt_base;
|
||||
unsigned long page;
|
||||
|
||||
printk("Pagetable walk from %p:\n", tab);
|
||||
|
||||
page = tab[l4_table_offset(addr)];
|
||||
tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
|
||||
printk(" L4 = %p (%p)\n", page, tab);
|
||||
|
||||
page = tab[l3_table_offset(addr)];
|
||||
tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
|
||||
printk(" L3 = %p (%p)\n", page, tab);
|
||||
|
||||
page = tab[l2_table_offset(addr)];
|
||||
tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
|
||||
printk(" L2 = %p (%p)\n", page, tab);
|
||||
|
||||
page = tab[l1_table_offset(addr)];
|
||||
printk(" L1 = %p\n", page);
|
||||
}
|
||||
#endif
|
||||
page_walk(addr);
|
||||
do_exit();
|
||||
}
|
||||
|
||||
void do_general_protection(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
printk("GPF %p, error_code=%lx\n", regs, error_code);
|
||||
#ifdef __i386__
|
||||
printk("GPF eip: %p, error_code=%lx\n", regs->eip, error_code);
|
||||
#else
|
||||
printk("GPF rip: %p, error_code=%lx\n", regs->rip, error_code);
|
||||
#endif
|
||||
dump_regs(regs);
|
||||
do_exit();
|
||||
}
|
||||
|
||||
@@ -1116,9 +1116,7 @@ source "fs/Kconfig"
|
||||
menu "Instrumentation Support"
|
||||
depends on EXPERIMENTAL
|
||||
|
||||
if !X86_XEN
|
||||
source "arch/i386/oprofile/Kconfig"
|
||||
endif
|
||||
|
||||
config KPROBES
|
||||
bool "Kprobes (EXPERIMENTAL)"
|
||||
|
||||
@@ -45,6 +45,11 @@ CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-op
|
||||
|
||||
CFLAGS += $(cflags-y)
|
||||
|
||||
cppflags-$(CONFIG_XEN) += \
|
||||
-D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION)
|
||||
|
||||
CPPFLAGS += $(cppflags-y)
|
||||
|
||||
# Default subarch .c files
|
||||
mcore-y := mach-default
|
||||
|
||||
@@ -107,7 +112,7 @@ boot := arch/i386/boot
|
||||
zdisk bzdisk fdimage fdimage144 fdimage288 install
|
||||
|
||||
ifdef CONFIG_XEN
|
||||
CPPFLAGS := -D__KERNEL__ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(LINUXINCLUDE)
|
||||
CPPFLAGS := -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
|
||||
head-y := arch/i386/kernel/head-xen.o arch/i386/kernel/init_task-xen.o
|
||||
boot := arch/i386/boot-xen
|
||||
.PHONY: vmlinuz
|
||||
@@ -157,3 +162,4 @@ define archhelp
|
||||
endef
|
||||
|
||||
CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
|
||||
CLEAN_FILES += vmlinuz vmlinux-stripped
|
||||
@@ -65,7 +65,6 @@ ES = 0x20
|
||||
ORIG_EAX = 0x24
|
||||
EIP = 0x28
|
||||
CS = 0x2C
|
||||
EVENT_MASK = 0x2E
|
||||
EFLAGS = 0x30
|
||||
OLDESP = 0x34
|
||||
OLDSS = 0x38
|
||||
@@ -290,14 +289,14 @@ restore_all:
|
||||
restore_nocheck:
|
||||
#else
|
||||
restore_nocheck:
|
||||
testl $(VM_MASK|NMI_MASK), EFLAGS(%esp)
|
||||
movl EFLAGS(%esp), %eax
|
||||
testl $(VM_MASK|NMI_MASK), %eax
|
||||
jnz hypervisor_iret
|
||||
movb EVENT_MASK(%esp), %al
|
||||
notb %al # %al == ~saved_mask
|
||||
shr $9, %eax # EAX[0] == IRET_EFLAGS.IF
|
||||
GET_VCPU_INFO
|
||||
andb evtchn_upcall_mask(%esi),%al
|
||||
andb $1,%al # %al == mask & ~saved_mask
|
||||
jnz restore_all_enable_events # != 0 => reenable event delivery
|
||||
andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask
|
||||
jnz restore_all_enable_events # != 0 => enable event delivery
|
||||
#endif
|
||||
RESTORE_REGS
|
||||
addl $4, %esp
|
||||
@@ -462,7 +461,7 @@ vector=0
|
||||
ENTRY(irq_entries_start)
|
||||
.rept NR_IRQS
|
||||
ALIGN
|
||||
1: pushl 0x80000000+$vector
|
||||
1: pushl $~(vector)
|
||||
jmp common_interrupt
|
||||
.data
|
||||
.long 1b
|
||||
@@ -479,7 +478,7 @@ common_interrupt:
|
||||
|
||||
#define BUILD_INTERRUPT(name, nr) \
|
||||
ENTRY(name) \
|
||||
pushl 0x80000000+$nr; \
|
||||
pushl $~(nr); \
|
||||
SAVE_ALL \
|
||||
movl %esp,%eax; \
|
||||
call smp_/**/name; \
|
||||
@@ -555,14 +554,9 @@ scrit: /**** START OF CRITICAL REGION ****/
|
||||
RESTORE_REGS
|
||||
addl $4, %esp
|
||||
1: iret
|
||||
.section .fixup,"ax"
|
||||
2: pushl $0
|
||||
pushl $do_iret_error
|
||||
jmp error_code
|
||||
.previous
|
||||
.section __ex_table,"a"
|
||||
.align 4
|
||||
.long 1b,2b
|
||||
.long 1b,iret_exc
|
||||
.previous
|
||||
14: __DISABLE_INTERRUPTS
|
||||
jmp 11b
|
||||
@@ -614,30 +608,51 @@ critical_fixup_table:
|
||||
.byte 0x00,0x00 # jmp 11b
|
||||
|
||||
# Hypervisor uses this for application faults while it executes.
|
||||
# We get here for two reasons:
|
||||
# 1. Fault while reloading DS, ES, FS or GS
|
||||
# 2. Fault while executing IRET
|
||||
# Category 1 we fix up by reattempting the load, and zeroing the segment
|
||||
# register if the load fails.
|
||||
# Category 2 we fix up by jumping to do_iret_error. We cannot use the
|
||||
# normal Linux return path in this case because if we use the IRET hypercall
|
||||
# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
|
||||
# We distinguish between categories by maintaining a status value in EAX.
|
||||
ENTRY(failsafe_callback)
|
||||
1: popl %ds
|
||||
2: popl %es
|
||||
3: popl %fs
|
||||
4: popl %gs
|
||||
subl $4,%esp
|
||||
pushl %eax
|
||||
movl $1,%eax
|
||||
1: mov 4(%esp),%ds
|
||||
2: mov 8(%esp),%es
|
||||
3: mov 12(%esp),%fs
|
||||
4: mov 16(%esp),%gs
|
||||
testl %eax,%eax
|
||||
popl %eax
|
||||
jz 5f
|
||||
addl $16,%esp # EAX != 0 => Category 2 (Bad IRET)
|
||||
jmp iret_exc
|
||||
5: addl $16,%esp # EAX == 0 => Category 1 (Bad segment)
|
||||
pushl $0
|
||||
SAVE_ALL
|
||||
jmp ret_from_exception
|
||||
.section .fixup,"ax"; \
|
||||
6: movl $0,(%esp); \
|
||||
jmp 1b; \
|
||||
7: movl $0,(%esp); \
|
||||
jmp 2b; \
|
||||
8: movl $0,(%esp); \
|
||||
jmp 3b; \
|
||||
9: movl $0,(%esp); \
|
||||
jmp 4b; \
|
||||
.previous; \
|
||||
.section __ex_table,"a";\
|
||||
.align 4; \
|
||||
.long 1b,6b; \
|
||||
.long 2b,7b; \
|
||||
.long 3b,8b; \
|
||||
.long 4b,9b; \
|
||||
jmp ret_from_exception
|
||||
.section .fixup,"ax"; \
|
||||
6: xorl %eax,%eax; \
|
||||
movl %eax,4(%esp); \
|
||||
jmp 1b; \
|
||||
7: xorl %eax,%eax; \
|
||||
movl %eax,8(%esp); \
|
||||
jmp 2b; \
|
||||
8: xorl %eax,%eax; \
|
||||
movl %eax,12(%esp); \
|
||||
jmp 3b; \
|
||||
9: xorl %eax,%eax; \
|
||||
movl %eax,16(%esp); \
|
||||
jmp 4b; \
|
||||
.previous; \
|
||||
.section __ex_table,"a"; \
|
||||
.align 4; \
|
||||
.long 1b,6b; \
|
||||
.long 2b,7b; \
|
||||
.long 3b,8b; \
|
||||
.long 4b,9b; \
|
||||
.previous
|
||||
#endif
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ static union irq_ctx *softirq_ctx[NR_CPUS];
|
||||
fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
/* high bit used in ret_from_ code */
|
||||
int irq = regs->orig_eax & __IRQ_MASK(BITS_PER_LONG - 1);
|
||||
int irq = ~regs->orig_eax;
|
||||
#ifdef CONFIG_4KSTACKS
|
||||
union irq_ctx *curctx, *irqctx;
|
||||
u32 *isp;
|
||||
|
||||
@@ -69,7 +69,7 @@ dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
|
||||
} else {
|
||||
for (i = 0; i < nents; i++ ) {
|
||||
sg[i].dma_address =
|
||||
page_to_phys(sg[i].page) + sg[i].offset;
|
||||
page_to_bus(sg[i].page) + sg[i].offset;
|
||||
sg[i].dma_length = sg[i].length;
|
||||
BUG_ON(!sg[i].page);
|
||||
IOMMU_BUG_ON(address_needs_mapping(
|
||||
@@ -105,7 +105,7 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset,
|
||||
dma_addr = swiotlb_map_page(
|
||||
dev, page, offset, size, direction);
|
||||
} else {
|
||||
dma_addr = page_to_phys(page) + offset;
|
||||
dma_addr = page_to_bus(page) + offset;
|
||||
IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr));
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ void xen_idle(void)
|
||||
smp_mb__after_clear_bit();
|
||||
stop_hz_timer();
|
||||
/* Blocking includes an implicit local_irq_enable(). */
|
||||
HYPERVISOR_sched_op(SCHEDOP_block, 0);
|
||||
HYPERVISOR_block();
|
||||
start_hz_timer();
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
|
||||
#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI)
|
||||
|
||||
static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
|
||||
{
|
||||
|
||||
@@ -1317,6 +1317,11 @@ void __init setup_bootmem_allocator(void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_KEXEC
|
||||
if (crashk_res.start != crashk_res.end)
|
||||
reserve_bootmem(crashk_res.start,
|
||||
crashk_res.end - crashk_res.start + 1);
|
||||
#endif
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap))
|
||||
phys_to_machine_mapping =
|
||||
@@ -1436,11 +1441,6 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_KEXEC
|
||||
if (crashk_res.start != crashk_res.end)
|
||||
reserve_bootmem(crashk_res.start,
|
||||
crashk_res.end - crashk_res.start + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1633,9 +1633,9 @@ void __init setup_arch(char **cmdline_p)
|
||||
physdev_op_t op;
|
||||
unsigned long max_low_pfn;
|
||||
|
||||
/* Force a quick death if the kernel panics. */
|
||||
/* Force a quick death if the kernel panics (not domain 0). */
|
||||
extern int panic_timeout;
|
||||
if (panic_timeout == 0)
|
||||
if (!panic_timeout && !(xen_start_info->flags & SIF_INITDOMAIN))
|
||||
panic_timeout = 1;
|
||||
|
||||
/* Register a call for panic conditions. */
|
||||
@@ -1848,10 +1848,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
get_smp_config();
|
||||
#endif
|
||||
|
||||
/* XXX Disable irqdebug until we have a way to avoid interrupt
|
||||
* conflicts. */
|
||||
noirqdebug_setup("");
|
||||
|
||||
register_memory();
|
||||
|
||||
if (xen_start_info->flags & SIF_INITDOMAIN) {
|
||||
@@ -1877,7 +1873,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
static int
|
||||
xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash);
|
||||
HYPERVISOR_shutdown(SHUTDOWN_crash);
|
||||
/* we're never actually going to get here... */
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ EXPORT_SYMBOL(swiotlb);
|
||||
|
||||
#define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
|
||||
|
||||
#define SG_ENT_PHYS_ADDRESS(sg) (page_to_phys((sg)->page) + (sg)->offset)
|
||||
#define SG_ENT_PHYS_ADDRESS(sg) (page_to_bus((sg)->page) + (sg)->offset)
|
||||
|
||||
/*
|
||||
* Maximum allowable number of contiguous slabs to map,
|
||||
@@ -607,7 +607,7 @@ swiotlb_map_page(struct device *hwdev, struct page *page,
|
||||
dma_addr_t dev_addr;
|
||||
char *map;
|
||||
|
||||
dev_addr = page_to_phys(page) + offset;
|
||||
dev_addr = page_to_bus(page) + offset;
|
||||
if (address_needs_mapping(hwdev, dev_addr)) {
|
||||
buffer.page = page;
|
||||
buffer.offset = offset;
|
||||
|
||||
@@ -177,6 +177,32 @@ int touch_pte_range(struct mm_struct *mm,
|
||||
|
||||
EXPORT_SYMBOL(touch_pte_range);
|
||||
|
||||
void *vm_map_xen_pages (unsigned long maddr, int vm_size, pgprot_t prot)
|
||||
{
|
||||
int error;
|
||||
|
||||
struct vm_struct *vma;
|
||||
vma = get_vm_area (vm_size, VM_IOREMAP);
|
||||
|
||||
if (vma == NULL) {
|
||||
printk ("ioremap.c,vm_map_xen_pages(): "
|
||||
"Failed to get VMA area\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = direct_kernel_remap_pfn_range((unsigned long) vma->addr,
|
||||
maddr >> PAGE_SHIFT, vm_size,
|
||||
prot, DOMID_SELF );
|
||||
if (error == 0) {
|
||||
return vma->addr;
|
||||
} else {
|
||||
printk ("ioremap.c,vm_map_xen_pages(): "
|
||||
"Failed to map xen shared pages into kernel space\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(vm_map_xen_pages);
|
||||
|
||||
/*
|
||||
* Does @address reside within a non-highmem page that is local to this virtual
|
||||
* machine (i.e., not an I/O page, nor a memory page belonging to another VM).
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
obj-$(CONFIG_OPROFILE) += oprofile.o
|
||||
|
||||
DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
|
||||
oprof.o cpu_buffer.o buffer_sync.o \
|
||||
event_buffer.o oprofile_files.o \
|
||||
oprofilefs.o oprofile_stats.o \
|
||||
timer_int.o )
|
||||
|
||||
ifdef CONFIG_XEN
|
||||
oprofile-y := $(DRIVER_OBJS) xenoprof.o
|
||||
else
|
||||
oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
|
||||
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \
|
||||
op_model_ppro.o op_model_p4.o
|
||||
oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o
|
||||
endif
|
||||
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* @file xenoprof.c
|
||||
*
|
||||
* @remark Copyright 2002 OProfile authors
|
||||
* @remark Read the file COPYING
|
||||
*
|
||||
* @author John Levon <levon@movementarian.org>
|
||||
*
|
||||
* Modified by Aravind Menon and Jose Renato Santos for Xen
|
||||
* These modifications are:
|
||||
* Copyright (C) 2005 Hewlett-Packard Co.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/oprofile.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include "op_counter.h"
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/xenoprof.h>
|
||||
|
||||
static int xenoprof_start(void);
|
||||
static void xenoprof_stop(void);
|
||||
|
||||
void * vm_map_xen_pages(unsigned long maddr, int vm_size, pgprot_t prot);
|
||||
|
||||
static int xenoprof_enabled = 0;
|
||||
static int num_events = 0;
|
||||
static int is_primary = 0;
|
||||
|
||||
/* sample buffers shared with Xen */
|
||||
xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
|
||||
/* Shared buffer area */
|
||||
char * shared_buffer;
|
||||
/* Number of buffers in shared area (one per VCPU) */
|
||||
int nbuf;
|
||||
/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
|
||||
int ovf_irq[NR_CPUS];
|
||||
/* cpu model type string - copied from Xen memory space on XENOPROF_init command */
|
||||
char cpu_type[XENOPROF_CPU_TYPE_SIZE];
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
|
||||
{
|
||||
if (xenoprof_enabled == 1)
|
||||
xenoprof_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int xenoprof_resume(struct sys_device * dev)
|
||||
{
|
||||
if (xenoprof_enabled == 1)
|
||||
xenoprof_start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct sysdev_class oprofile_sysclass = {
|
||||
set_kset_name("oprofile"),
|
||||
.resume = xenoprof_resume,
|
||||
.suspend = xenoprof_suspend
|
||||
};
|
||||
|
||||
|
||||
static struct sys_device device_oprofile = {
|
||||
.id = 0,
|
||||
.cls = &oprofile_sysclass,
|
||||
};
|
||||
|
||||
|
||||
static int __init init_driverfs(void)
|
||||
{
|
||||
int error;
|
||||
if (!(error = sysdev_class_register(&oprofile_sysclass)))
|
||||
error = sysdev_register(&device_oprofile);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void __exit exit_driverfs(void)
|
||||
{
|
||||
sysdev_unregister(&device_oprofile);
|
||||
sysdev_class_unregister(&oprofile_sysclass);
|
||||
}
|
||||
|
||||
#else
|
||||
#define init_driverfs() do { } while (0)
|
||||
#define exit_driverfs() do { } while (0)
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
unsigned long long oprofile_samples = 0;
|
||||
|
||||
static irqreturn_t
|
||||
xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
|
||||
{
|
||||
int head, tail, size;
|
||||
xenoprof_buf_t * buf;
|
||||
int cpu;
|
||||
|
||||
cpu = smp_processor_id();
|
||||
buf = xenoprof_buf[cpu];
|
||||
|
||||
head = buf->event_head;
|
||||
tail = buf->event_tail;
|
||||
size = buf->event_size;
|
||||
|
||||
if (tail > head) {
|
||||
while (tail < size) {
|
||||
oprofile_add_pc(buf->event_log[tail].eip,
|
||||
buf->event_log[tail].mode,
|
||||
buf->event_log[tail].event);
|
||||
oprofile_samples++;
|
||||
tail++;
|
||||
}
|
||||
tail = 0;
|
||||
}
|
||||
while (tail < head) {
|
||||
oprofile_add_pc(buf->event_log[tail].eip,
|
||||
buf->event_log[tail].mode,
|
||||
buf->event_log[tail].event);
|
||||
oprofile_samples++;
|
||||
tail++;
|
||||
}
|
||||
|
||||
buf->event_tail = tail;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static void unbind_virq_cpu(void * info)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
if (ovf_irq[cpu] >= 0) {
|
||||
unbind_from_irqhandler(ovf_irq[cpu], NULL);
|
||||
ovf_irq[cpu] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void unbind_virq(void)
|
||||
{
|
||||
on_each_cpu(unbind_virq_cpu, NULL, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
int bind_virq_error;
|
||||
|
||||
static void bind_virq_cpu(void * info)
|
||||
{
|
||||
int result;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
|
||||
cpu,
|
||||
xenoprof_ovf_interrupt,
|
||||
SA_INTERRUPT,
|
||||
"xenoprof",
|
||||
NULL);
|
||||
|
||||
if (result<0) {
|
||||
bind_virq_error = result;
|
||||
printk("xenoprof.c: binding VIRQ_XENOPROF to IRQ failed on CPU "
|
||||
"%d\n", cpu);
|
||||
} else {
|
||||
ovf_irq[cpu] = result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int bind_virq(void)
|
||||
{
|
||||
bind_virq_error = 0;
|
||||
on_each_cpu(bind_virq_cpu, NULL, 0, 1);
|
||||
if (bind_virq_error) {
|
||||
unbind_virq();
|
||||
return bind_virq_error;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int xenoprof_setup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bind_virq();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (is_primary) {
|
||||
ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events,
|
||||
(unsigned long)&counter_config,
|
||||
(unsigned long)num_events);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
xenoprof_enabled = 1;
|
||||
return 0;
|
||||
err:
|
||||
unbind_virq();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void xenoprof_shutdown(void)
|
||||
{
|
||||
xenoprof_enabled = 0;
|
||||
|
||||
HYPERVISOR_xenoprof_op(XENOPROF_disable_virq,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
|
||||
if (is_primary) {
|
||||
HYPERVISOR_xenoprof_op(XENOPROF_release_counters,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
}
|
||||
|
||||
unbind_virq();
|
||||
}
|
||||
|
||||
|
||||
static int xenoprof_start(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (is_primary)
|
||||
ret = HYPERVISOR_xenoprof_op(XENOPROF_start,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void xenoprof_stop(void)
|
||||
{
|
||||
if (is_primary)
|
||||
HYPERVISOR_xenoprof_op(XENOPROF_stop,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
}
|
||||
|
||||
|
||||
static int xenoprof_set_active(int * active_domains,
|
||||
unsigned int adomains)
|
||||
{
|
||||
int ret = 0;
|
||||
if (is_primary)
|
||||
ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active,
|
||||
(unsigned long)active_domains,
|
||||
(unsigned long)adomains);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct op_counter_config counter_config[OP_MAX_COUNTER];
|
||||
|
||||
static int xenoprof_create_files(struct super_block * sb, struct dentry * root)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_events; ++i) {
|
||||
struct dentry * dir;
|
||||
char buf[2];
|
||||
|
||||
snprintf(buf, 2, "%d", i);
|
||||
dir = oprofilefs_mkdir(sb, root, buf);
|
||||
oprofilefs_create_ulong(sb, dir, "enabled",
|
||||
&counter_config[i].enabled);
|
||||
oprofilefs_create_ulong(sb, dir, "event",
|
||||
&counter_config[i].event);
|
||||
oprofilefs_create_ulong(sb, dir, "count",
|
||||
&counter_config[i].count);
|
||||
oprofilefs_create_ulong(sb, dir, "unit_mask",
|
||||
&counter_config[i].unit_mask);
|
||||
oprofilefs_create_ulong(sb, dir, "kernel",
|
||||
&counter_config[i].kernel);
|
||||
oprofilefs_create_ulong(sb, dir, "user",
|
||||
&counter_config[i].user);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct oprofile_operations xenoprof_ops = {
|
||||
.create_files = xenoprof_create_files,
|
||||
.set_active = xenoprof_set_active,
|
||||
.setup = xenoprof_setup,
|
||||
.shutdown = xenoprof_shutdown,
|
||||
.start = xenoprof_start,
|
||||
.stop = xenoprof_stop
|
||||
};
|
||||
|
||||
|
||||
/* in order to get driverfs right */
|
||||
static int using_xenoprof;
|
||||
|
||||
int __init oprofile_arch_init(struct oprofile_operations * ops)
|
||||
{
|
||||
xenoprof_init_result_t result;
|
||||
xenoprof_buf_t * buf;
|
||||
int max_samples = 16;
|
||||
int vm_size;
|
||||
int npages;
|
||||
int i;
|
||||
|
||||
int ret = HYPERVISOR_xenoprof_op(XENOPROF_init,
|
||||
(unsigned long)max_samples,
|
||||
(unsigned long)&result);
|
||||
|
||||
if (!ret) {
|
||||
pgprot_t prot = __pgprot(_KERNPG_TABLE);
|
||||
|
||||
num_events = result.num_events;
|
||||
is_primary = result.is_primary;
|
||||
nbuf = result.nbuf;
|
||||
|
||||
npages = (result.bufsize * nbuf - 1) / PAGE_SIZE + 1;
|
||||
vm_size = npages * PAGE_SIZE;
|
||||
|
||||
shared_buffer = (char *) vm_map_xen_pages(result.buf_maddr,
|
||||
vm_size, prot);
|
||||
if (!shared_buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i=0; i< nbuf; i++) {
|
||||
buf = (xenoprof_buf_t*)
|
||||
&shared_buffer[i * result.bufsize];
|
||||
BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
|
||||
xenoprof_buf[buf->vcpu_id] = buf;
|
||||
}
|
||||
|
||||
/* cpu_type is detected by Xen */
|
||||
cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
|
||||
strncpy(cpu_type, result.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
|
||||
xenoprof_ops.cpu_type = cpu_type;
|
||||
|
||||
init_driverfs();
|
||||
using_xenoprof = 1;
|
||||
*ops = xenoprof_ops;
|
||||
|
||||
for (i=0; i<NR_CPUS; i++)
|
||||
ovf_irq[i] = -1;
|
||||
}
|
||||
out:
|
||||
printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
|
||||
"is_primary %d\n", ret, num_events, is_primary);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void __exit oprofile_arch_exit(void)
|
||||
{
|
||||
if (using_xenoprof)
|
||||
exit_driverfs();
|
||||
|
||||
if (shared_buffer) {
|
||||
vunmap(shared_buffer);
|
||||
shared_buffer = NULL;
|
||||
}
|
||||
if (is_primary)
|
||||
HYPERVISOR_xenoprof_op(XENOPROF_shutdown,
|
||||
(unsigned long)NULL,
|
||||
(unsigned long)NULL);
|
||||
}
|
||||
@@ -79,11 +79,16 @@ config XEN_BLKDEV_FRONTEND
|
||||
bool
|
||||
default y
|
||||
|
||||
config XEN_BLKDEV_BACKEND
|
||||
config XEN_BACKEND
|
||||
depends on XEN
|
||||
bool
|
||||
default y
|
||||
|
||||
config XEN_BLKDEV_BACKEND
|
||||
depends on XEN && XEN_BACKEND
|
||||
bool
|
||||
default y
|
||||
|
||||
config XEN_SYSFS
|
||||
bool "Export Xen attributes in sysfs"
|
||||
depends on XEN && SYSFS
|
||||
@@ -91,6 +96,11 @@ config XEN_SYSFS
|
||||
help
|
||||
Xen hypervisor attributes will show up under /sys/hypervisor/.
|
||||
|
||||
config XEN_INTERFACE_VERSION
|
||||
hex
|
||||
depends on XEN
|
||||
default 0x00030101
|
||||
|
||||
config SCHED_NO_NO_OMIT_FRAME_POINTER
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -42,6 +42,12 @@ ifeq ($(call cc-version),0304)
|
||||
endif
|
||||
|
||||
CFLAGS += $(cflags-y)
|
||||
|
||||
cppflags-$(CONFIG_XEN) += \
|
||||
-D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION)
|
||||
|
||||
CPPFLAGS += $(cppflags-y)
|
||||
|
||||
head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
|
||||
|
||||
libs-y += arch/ia64/lib/
|
||||
|
||||
@@ -10,7 +10,7 @@ $(obj)/vmlinux.lds.S:
|
||||
@ln -fsn $(srctree)/arch/$(XENARCH)/kernel/vmlinux.lds.S $@
|
||||
|
||||
|
||||
obj-y := gnttab.o
|
||||
obj-y := gnttab.o features.o
|
||||
obj-$(CONFIG_PROC_FS) += xen_proc.o
|
||||
|
||||
ifeq ($(ARCH),ia64)
|
||||
|
||||
@@ -31,6 +31,10 @@ cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
|
||||
cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
|
||||
CFLAGS += $(cflags-y)
|
||||
|
||||
cppflags-$(CONFIG_XEN) += \
|
||||
-D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION)
|
||||
CPPFLAGS += $(cppflags-y)
|
||||
|
||||
CFLAGS += -m64
|
||||
CFLAGS += -mno-red-zone
|
||||
CFLAGS += -mcmodel=kernel
|
||||
@@ -71,7 +75,7 @@ boot := arch/x86_64/boot
|
||||
fdimage fdimage144 fdimage288 archclean
|
||||
|
||||
ifdef CONFIG_XEN
|
||||
CPPFLAGS := -D__KERNEL__ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(LINUXINCLUDE)
|
||||
CPPFLAGS := -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
|
||||
head-y := arch/x86_64/kernel/head-xen.o arch/x86_64/kernel/head64-xen.o arch/x86_64/kernel/init_task.o
|
||||
LDFLAGS_vmlinux := -e _start
|
||||
boot := arch/i386/boot-xen
|
||||
|
||||
@@ -520,13 +520,13 @@ retint_check:
|
||||
CFI_REMEMBER_STATE
|
||||
jnz retint_careful
|
||||
retint_restore_args:
|
||||
movb EVENT_MASK-REST_SKIP(%rsp), %al
|
||||
notb %al # %al == ~saved_mask
|
||||
XEN_GET_VCPU_INFO(%rsi)
|
||||
andb evtchn_upcall_mask(%rsi),%al
|
||||
andb $1,%al # %al == mask & ~saved_mask
|
||||
jnz restore_all_enable_events # != 0 => reenable event delivery
|
||||
XEN_PUT_VCPU_INFO(%rsi)
|
||||
movl EFLAGS-REST_SKIP(%rsp), %eax
|
||||
shr $9, %eax # EAX[0] == IRET_EFLAGS.IF
|
||||
XEN_GET_VCPU_INFO(%rsi)
|
||||
andb evtchn_upcall_mask(%rsi),%al
|
||||
andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask
|
||||
jnz restore_all_enable_events # != 0 => enable event delivery
|
||||
XEN_PUT_VCPU_INFO(%rsi)
|
||||
|
||||
RESTORE_ARGS 0,8,0
|
||||
HYPERVISOR_IRET 0
|
||||
@@ -584,7 +584,7 @@ retint_kernel:
|
||||
*/
|
||||
.macro apicinterrupt num,func
|
||||
INTR_FRAME
|
||||
pushq 0x8000000000000000+$\num
|
||||
pushq $~(\num)
|
||||
CFI_ADJUST_CFA_OFFSET 8
|
||||
interrupt \func
|
||||
jmp error_entry
|
||||
@@ -803,12 +803,11 @@ ENTRY(hypervisor_callback)
|
||||
# So, on entry to the handler we detect whether we interrupted an
|
||||
# existing activation in its critical region -- if so, we pop the current
|
||||
# activation and restart the handler using the previous one.
|
||||
ENTRY(do_hypervisor_callback) # do_hyperviosr_callback(struct *pt_regs)
|
||||
ENTRY(do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs)
|
||||
# Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
|
||||
# see the correct pointer to the pt_regs
|
||||
movq %rdi, %rsp # we don't return, adjust the stack frame
|
||||
11: movb $0, EVENT_MASK(%rdi)
|
||||
movq %gs:pda_irqstackptr,%rax
|
||||
11: movq %gs:pda_irqstackptr,%rax
|
||||
incl %gs:pda_irqcount
|
||||
cmovzq %rax,%rsp
|
||||
pushq %rdi
|
||||
@@ -853,15 +852,44 @@ ecrit: /**** END OF CRITICAL REGION ****/
|
||||
# When the kernel is interrupted in the critical section, the kernel
|
||||
# will do IRET in that case, and everything will be restored at that point,
|
||||
# i.e. it just resumes from the next instruction interrupted with the same context.
|
||||
|
||||
|
||||
# Hypervisor uses this for application faults while it executes.
|
||||
# Unlike i386 there is no need to reload the saved segment selectors:
|
||||
# Xen already reloaded all valid ones and zeroed the others.
|
||||
# We get here for two reasons:
|
||||
# 1. Fault while reloading DS, ES, FS or GS
|
||||
# 2. Fault while executing IRET
|
||||
# Category 1 we do not need to fix up as Xen has already reloaded all segment
|
||||
# registers that could be reloaded and zeroed the others.
|
||||
# Category 2 we fix up by killing the current process. We cannot use the
|
||||
# normal Linux return path in this case because if we use the IRET hypercall
|
||||
# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
|
||||
# We distinguish between categories by comparing each saved segment register
|
||||
# with its current contents: any discrepancy means we in category 1.
|
||||
ENTRY(failsafe_callback)
|
||||
addq $0x30,%rsp /* skip %rcx,%r11,%ds,%es,%fs,%gs */
|
||||
movw %ds,%cx
|
||||
cmpw %cx,0x10(%rsp)
|
||||
jne 1f
|
||||
movw %es,%cx
|
||||
cmpw %cx,0x18(%rsp)
|
||||
jne 1f
|
||||
movw %fs,%cx
|
||||
cmpw %cx,0x20(%rsp)
|
||||
jne 1f
|
||||
movw %gs,%cx
|
||||
cmpw %cx,0x28(%rsp)
|
||||
jne 1f
|
||||
/* All segments match their saved values => Category 2 (Bad IRET). */
|
||||
movq (%rsp),%rcx
|
||||
movq 8(%rsp),%r11
|
||||
addq $0x30,%rsp
|
||||
movq $-9999,%rdi /* better code? */
|
||||
jmp do_exit
|
||||
1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
|
||||
movq (%rsp),%rcx
|
||||
movq 8(%rsp),%r11
|
||||
addq $0x30,%rsp
|
||||
pushq $0
|
||||
SAVE_ALL
|
||||
jmp error_exit
|
||||
|
||||
jmp error_exit
|
||||
#if 0
|
||||
.section __ex_table,"a"
|
||||
.align 8
|
||||
|
||||
@@ -97,7 +97,7 @@ skip:
|
||||
asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
/* high bit used in ret_from_ code */
|
||||
int irq = regs->orig_rax & __IRQ_MASK(BITS_PER_LONG - 1);
|
||||
unsigned irq = ~regs->orig_rax;
|
||||
|
||||
exit_idle();
|
||||
irq_enter();
|
||||
|
||||
@@ -131,7 +131,7 @@ void xen_idle(void)
|
||||
smp_mb__after_clear_bit();
|
||||
stop_hz_timer();
|
||||
/* Blocking includes an implicit local_irq_enable(). */
|
||||
HYPERVISOR_sched_op(SCHEDOP_block, 0);
|
||||
HYPERVISOR_block();
|
||||
start_hz_timer();
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
}
|
||||
|
||||
@@ -999,7 +999,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
static int
|
||||
xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash);
|
||||
HYPERVISOR_shutdown(SHUTDOWN_crash);
|
||||
/* we're never actually going to get here... */
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copied from arch/xen/i386/kernel/entry.S
|
||||
*/
|
||||
/* Offsets into shared_info_t. */
|
||||
#define evtchn_upcall_pending 0
|
||||
#define evtchn_upcall_pending /* 0 */
|
||||
#define evtchn_upcall_mask 1
|
||||
|
||||
#define sizeof_vcpu_shift 6
|
||||
@@ -35,7 +35,6 @@
|
||||
XEN_PUT_VCPU_INFO(reg)
|
||||
#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
|
||||
|
||||
EVENT_MASK = (CS+4)
|
||||
VGCF_IN_SYSCALL = (1<<8)
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# oprofile for x86-64.
|
||||
# Just reuse the one from i386.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_OPROFILE) += oprofile.o
|
||||
|
||||
DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
|
||||
oprof.o cpu_buffer.o buffer_sync.o \
|
||||
event_buffer.o oprofile_files.o \
|
||||
oprofilefs.o oprofile_stats.o \
|
||||
timer_int.o )
|
||||
|
||||
ifdef CONFIG_XEN
|
||||
OPROFILE-y := xenoprof.o
|
||||
else
|
||||
OPROFILE-y := init.o backtrace.o
|
||||
OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o op_model_p4.o \
|
||||
op_model_ppro.o
|
||||
OPROFILE-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o
|
||||
endif
|
||||
oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
|
||||
@@ -10,12 +10,11 @@ config XEN
|
||||
help
|
||||
This is the Linux Xen port.
|
||||
|
||||
config NO_IDLE_HZ
|
||||
bool
|
||||
depends on XEN
|
||||
default y
|
||||
|
||||
if XEN
|
||||
config XEN_INTERFACE_VERSION
|
||||
hex
|
||||
default 0x00030101
|
||||
|
||||
menu "XEN"
|
||||
|
||||
config XEN_PRIVILEGED_GUEST
|
||||
@@ -29,9 +28,16 @@ config XEN_UNPRIVILEGED_GUEST
|
||||
bool
|
||||
default !XEN_PRIVILEGED_GUEST
|
||||
|
||||
config XEN_BACKEND
|
||||
tristate "Backend driver support"
|
||||
default y
|
||||
help
|
||||
Support for backend device drivers that provide I/O services
|
||||
to other virtual machines.
|
||||
|
||||
config XEN_PCIDEV_BACKEND
|
||||
tristate "PCI device backend driver"
|
||||
depends PCI
|
||||
depends on PCI && XEN_BACKEND
|
||||
default XEN_PRIVILEGED_GUEST
|
||||
help
|
||||
The PCI device backend driver allows the kernel to export arbitrary
|
||||
@@ -71,6 +77,7 @@ config XEN_PCIDEV_BE_DEBUG
|
||||
|
||||
config XEN_BLKDEV_BACKEND
|
||||
tristate "Block-device backend driver"
|
||||
depends on XEN_BACKEND
|
||||
default y
|
||||
help
|
||||
The block-device backend driver allows the kernel to export its
|
||||
@@ -92,6 +99,7 @@ config XEN_BLKDEV_TAP_BE
|
||||
|
||||
config XEN_NETDEV_BACKEND
|
||||
tristate "Network-device backend driver"
|
||||
depends on XEN_BACKEND
|
||||
default y
|
||||
help
|
||||
The network-device backend driver allows the kernel to export its
|
||||
@@ -121,6 +129,7 @@ config XEN_NETDEV_LOOPBACK
|
||||
|
||||
config XEN_TPMDEV_BACKEND
|
||||
tristate "TPM-device backend driver"
|
||||
depends on XEN_BACKEND
|
||||
default n
|
||||
help
|
||||
The TPM-device backend driver
|
||||
@@ -156,6 +165,7 @@ config XEN_NETDEV_FRONTEND
|
||||
|
||||
config XEN_BLKDEV_TAP
|
||||
tristate "Block device tap driver"
|
||||
depends on XEN_BACKEND
|
||||
default n
|
||||
help
|
||||
This driver allows a VM to interact on block device channels
|
||||
@@ -191,7 +201,6 @@ config XEN_DISABLE_SERIAL
|
||||
|
||||
config XEN_SYSFS
|
||||
tristate "Export Xen attributes in sysfs"
|
||||
depends on XEN
|
||||
depends on SYSFS
|
||||
default y
|
||||
help
|
||||
@@ -207,4 +216,8 @@ config HAVE_ARCH_DEV_ALLOC_SKB
|
||||
bool
|
||||
default y
|
||||
|
||||
config NO_IDLE_HZ
|
||||
bool
|
||||
default y
|
||||
|
||||
endif
|
||||
@@ -215,52 +215,26 @@ static void print_stats(blkif_t *blkif)
|
||||
|
||||
int blkif_schedule(void *arg)
|
||||
{
|
||||
blkif_t *blkif = arg;
|
||||
blkif_t *blkif = arg;
|
||||
|
||||
blkif_get(blkif);
|
||||
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: started\n", current->comm);
|
||||
for (;;) {
|
||||
if (kthread_should_stop()) {
|
||||
/* asked to quit? */
|
||||
if (!atomic_read(&blkif->io_pending))
|
||||
break;
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: I/O pending, "
|
||||
"delaying exit\n", current->comm);
|
||||
}
|
||||
|
||||
if (!atomic_read(&blkif->io_pending)) {
|
||||
/* Wait for work to do. */
|
||||
wait_event_interruptible(
|
||||
blkif->wq,
|
||||
(atomic_read(&blkif->io_pending) ||
|
||||
kthread_should_stop()));
|
||||
} else if (list_empty(&pending_free)) {
|
||||
/* Wait for pending_req becoming available. */
|
||||
wait_event_interruptible(
|
||||
pending_free_wq,
|
||||
!list_empty(&pending_free));
|
||||
}
|
||||
while (!kthread_should_stop()) {
|
||||
wait_event_interruptible(
|
||||
blkif->wq,
|
||||
blkif->waiting_reqs || kthread_should_stop());
|
||||
wait_event_interruptible(
|
||||
pending_free_wq,
|
||||
!list_empty(&pending_free) || kthread_should_stop());
|
||||
|
||||
if (blkif->status != CONNECTED) {
|
||||
/* make sure we are connected */
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: not connected "
|
||||
"(%d pending)\n",
|
||||
current->comm,
|
||||
atomic_read(&blkif->io_pending));
|
||||
wait_event_interruptible(
|
||||
blkif->wq,
|
||||
(blkif->status == CONNECTED ||
|
||||
kthread_should_stop()));
|
||||
continue;
|
||||
}
|
||||
blkif->waiting_reqs = 0;
|
||||
smp_mb(); /* clear flag *before* checking for work */
|
||||
|
||||
/* Schedule I/O */
|
||||
atomic_set(&blkif->io_pending, 0);
|
||||
if (do_block_io_op(blkif))
|
||||
atomic_inc(&blkif->io_pending);
|
||||
blkif->waiting_reqs = 1;
|
||||
unplug_queue(blkif);
|
||||
|
||||
if (log_stats && time_after(jiffies, blkif->st_print))
|
||||
@@ -271,8 +245,10 @@ int blkif_schedule(void *arg)
|
||||
print_stats(blkif);
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: exiting\n", current->comm);
|
||||
|
||||
blkif->xenblkd = NULL;
|
||||
blkif_put(blkif);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -311,12 +287,15 @@ static int end_block_io_op(struct bio *bio, unsigned int done, int error)
|
||||
* NOTIFICATION FROM GUEST OS.
|
||||
*/
|
||||
|
||||
static void blkif_notify_work(blkif_t *blkif)
|
||||
{
|
||||
blkif->waiting_reqs = 1;
|
||||
wake_up(&blkif->wq);
|
||||
}
|
||||
|
||||
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
blkif_t *blkif = dev_id;
|
||||
|
||||
atomic_inc(&blkif->io_pending);
|
||||
wake_up(&blkif->wq);
|
||||
blkif_notify_work(dev_id);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -536,10 +515,8 @@ static void make_response(blkif_t *blkif, unsigned long id,
|
||||
}
|
||||
spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
|
||||
|
||||
if (more_to_do) {
|
||||
atomic_inc(&blkif->io_pending);
|
||||
wake_up(&blkif->wq);
|
||||
}
|
||||
if (more_to_do)
|
||||
blkif_notify_work(blkif);
|
||||
if (notify)
|
||||
notify_remote_via_irq(blkif->irq);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ typedef struct blkif_st {
|
||||
/* Back pointer to the backend_info. */
|
||||
struct backend_info *be;
|
||||
/* Private fields. */
|
||||
enum { DISCONNECTED, CONNECTED } status;
|
||||
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
|
||||
/* Is this a blktap frontend */
|
||||
unsigned int is_blktap;
|
||||
@@ -82,7 +81,7 @@ typedef struct blkif_st {
|
||||
|
||||
wait_queue_head_t wq;
|
||||
struct task_struct *xenblkd;
|
||||
atomic_t io_pending;
|
||||
unsigned int waiting_reqs;
|
||||
request_queue_t *plug;
|
||||
|
||||
/* statistics */
|
||||
@@ -133,8 +132,6 @@ void blkif_xenbus_init(void);
|
||||
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
|
||||
int blkif_schedule(void *arg);
|
||||
|
||||
void update_blkif_status(blkif_t *blkif);
|
||||
|
||||
#endif /* __BLKIF__BACKEND__COMMON_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -45,7 +45,6 @@ blkif_t *alloc_blkif(domid_t domid)
|
||||
|
||||
memset(blkif, 0, sizeof(*blkif));
|
||||
blkif->domid = domid;
|
||||
blkif->status = DISCONNECTED;
|
||||
spin_lock_init(&blkif->blk_ring_lock);
|
||||
atomic_set(&blkif->refcnt, 1);
|
||||
init_waitqueue_head(&blkif->wq);
|
||||
@@ -138,9 +137,6 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
|
||||
blkif->irq = bind_evtchn_to_irqhandler(
|
||||
blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
|
||||
|
||||
/* We're potentially connected now */
|
||||
update_blkif_status(blkif);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kthread.h>
|
||||
@@ -25,36 +24,52 @@
|
||||
#include "common.h"
|
||||
|
||||
#undef DPRINTK
|
||||
#define DPRINTK(fmt, args...) \
|
||||
pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
|
||||
|
||||
#define DPRINTK(fmt, args...) \
|
||||
pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \
|
||||
__FUNCTION__, __LINE__, ##args)
|
||||
|
||||
struct backend_info
|
||||
{
|
||||
struct xenbus_device *dev;
|
||||
blkif_t *blkif;
|
||||
struct xenbus_watch backend_watch;
|
||||
|
||||
unsigned major;
|
||||
unsigned minor;
|
||||
char *mode;
|
||||
};
|
||||
|
||||
|
||||
static void maybe_connect(struct backend_info *);
|
||||
static void connect(struct backend_info *);
|
||||
static int connect_ring(struct backend_info *);
|
||||
static void backend_changed(struct xenbus_watch *, const char **,
|
||||
unsigned int);
|
||||
|
||||
|
||||
void update_blkif_status(blkif_t *blkif)
|
||||
static void update_blkif_status(blkif_t *blkif)
|
||||
{
|
||||
if(blkif->irq && blkif->vbd.bdev) {
|
||||
blkif->status = CONNECTED;
|
||||
(void)blkif_be_int(0, blkif, NULL);
|
||||
int err;
|
||||
|
||||
/* Not ready to connect? */
|
||||
if (!blkif->irq || !blkif->vbd.bdev)
|
||||
return;
|
||||
|
||||
/* Already connected? */
|
||||
if (blkif->be->dev->state == XenbusStateConnected)
|
||||
return;
|
||||
|
||||
/* Attempt to connect: exit if we fail to. */
|
||||
connect(blkif->be);
|
||||
if (blkif->be->dev->state != XenbusStateConnected)
|
||||
return;
|
||||
|
||||
blkif->xenblkd = kthread_run(blkif_schedule, blkif,
|
||||
"xvd %d %02x:%02x",
|
||||
blkif->domid,
|
||||
blkif->be->major, blkif->be->minor);
|
||||
if (IS_ERR(blkif->xenblkd)) {
|
||||
err = PTR_ERR(blkif->xenblkd);
|
||||
blkif->xenblkd = NULL;
|
||||
xenbus_dev_error(blkif->be->dev, err, "start xenblkd");
|
||||
}
|
||||
maybe_connect(blkif->be);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +106,6 @@ static int blkback_remove(struct xenbus_device *dev)
|
||||
be->backend_watch.node = NULL;
|
||||
}
|
||||
if (be->blkif) {
|
||||
be->blkif->status = DISCONNECTED;
|
||||
if (be->blkif->xenblkd)
|
||||
kthread_stop(be->blkif->xenblkd);
|
||||
blkif_put(be->blkif);
|
||||
@@ -142,7 +156,7 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
|
||||
err = xenbus_switch_state(dev, XenbusStateInitWait);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
@@ -185,8 +199,8 @@ static void backend_changed(struct xenbus_watch *watch,
|
||||
return;
|
||||
}
|
||||
|
||||
if (be->major && be->minor &&
|
||||
(be->major != major || be->minor != minor)) {
|
||||
if ((be->major || be->minor) &&
|
||||
((be->major != major) || (be->minor != minor))) {
|
||||
printk(KERN_WARNING
|
||||
"blkback: changing physical device (from %x:%x to "
|
||||
"%x:%x) not supported.\n", be->major, be->minor,
|
||||
@@ -220,17 +234,6 @@ static void backend_changed(struct xenbus_watch *watch,
|
||||
return;
|
||||
}
|
||||
|
||||
be->blkif->xenblkd = kthread_run(blkif_schedule, be->blkif,
|
||||
"xvd %d %02x:%02x",
|
||||
be->blkif->domid,
|
||||
be->major, be->minor);
|
||||
if (IS_ERR(be->blkif->xenblkd)) {
|
||||
err = PTR_ERR(be->blkif->xenblkd);
|
||||
be->blkif->xenblkd = NULL;
|
||||
xenbus_dev_error(dev, err, "start xenblkd");
|
||||
return;
|
||||
}
|
||||
|
||||
device_create_file(&dev->dev, &dev_attr_physical_device);
|
||||
device_create_file(&dev->dev, &dev_attr_mode);
|
||||
|
||||
@@ -253,19 +256,24 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
|
||||
switch (frontend_state) {
|
||||
case XenbusStateInitialising:
|
||||
case XenbusStateConnected:
|
||||
break;
|
||||
|
||||
case XenbusStateInitialised:
|
||||
case XenbusStateConnected:
|
||||
/* Ensure we connect even when two watches fire in
|
||||
close successsion and we miss the intermediate value
|
||||
of frontend_state. */
|
||||
if (dev->state == XenbusStateConnected)
|
||||
break;
|
||||
|
||||
err = connect_ring(be);
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
update_blkif_status(be->blkif);
|
||||
if (err)
|
||||
break;
|
||||
update_blkif_status(be->blkif);
|
||||
break;
|
||||
|
||||
case XenbusStateClosing:
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
|
||||
xenbus_switch_state(dev, XenbusStateClosing);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
@@ -285,14 +293,6 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
/* ** Connection ** */
|
||||
|
||||
|
||||
static void maybe_connect(struct backend_info *be)
|
||||
{
|
||||
if ((be->major != 0 || be->minor != 0) &&
|
||||
be->blkif->status == CONNECTED)
|
||||
connect(be);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write the physical details regarding the block device to the store, and
|
||||
* switch to Connected state.
|
||||
@@ -338,15 +338,17 @@ again:
|
||||
goto abort;
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
|
||||
if (err)
|
||||
goto abort;
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err == -EAGAIN)
|
||||
goto again;
|
||||
if (err)
|
||||
xenbus_dev_fatal(dev, err, "ending transaction");
|
||||
|
||||
err = xenbus_switch_state(dev, XenbusStateConnected);
|
||||
if (err)
|
||||
xenbus_dev_fatal(dev, err, "switching to Connected state",
|
||||
dev->nodename);
|
||||
|
||||
return;
|
||||
abort:
|
||||
xenbus_transaction_end(xbt, 1);
|
||||
|
||||
@@ -176,10 +176,6 @@ again:
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(dev, xbt, XenbusStateInitialised);
|
||||
if (err)
|
||||
goto abort_transaction;
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err) {
|
||||
if (err == -EAGAIN)
|
||||
@@ -188,6 +184,8 @@ again:
|
||||
goto destroy_blkring;
|
||||
}
|
||||
|
||||
xenbus_switch_state(dev, XenbusStateInitialised);
|
||||
|
||||
return 0;
|
||||
|
||||
abort_transaction:
|
||||
@@ -324,7 +322,7 @@ static void connect(struct blkfront_info *info)
|
||||
return;
|
||||
}
|
||||
|
||||
(void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
|
||||
(void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
|
||||
|
||||
/* Kick pending requests. */
|
||||
spin_lock_irq(&blkif_io_lock);
|
||||
@@ -349,7 +347,7 @@ static void blkfront_closing(struct xenbus_device *dev)
|
||||
|
||||
xlvbd_del(info);
|
||||
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
}
|
||||
|
||||
|
||||
@@ -755,7 +753,7 @@ static void blkif_recover(struct blkfront_info *info)
|
||||
|
||||
kfree(copy);
|
||||
|
||||
(void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected);
|
||||
(void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
|
||||
|
||||
/* Now safe for us to use the shared ring */
|
||||
spin_lock_irq(&blkif_io_lock);
|
||||
|
||||
@@ -170,9 +170,9 @@ static inline void exit_idle(void) {}
|
||||
#include <asm/idle.h>
|
||||
#define IRQ_REG orig_rax
|
||||
#endif
|
||||
#define do_IRQ(irq, regs) do { \
|
||||
(regs)->IRQ_REG = (irq) | (1UL << (BITS_PER_LONG - 1)); \
|
||||
do_IRQ((regs)); \
|
||||
#define do_IRQ(irq, regs) do { \
|
||||
(regs)->IRQ_REG = ~(irq); \
|
||||
do_IRQ((regs)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -395,6 +395,9 @@ gnttab_resume(void)
|
||||
setup.frame_list = frames;
|
||||
|
||||
rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
|
||||
if (rc == -ENOSYS)
|
||||
return -ENOSYS;
|
||||
|
||||
BUG_ON(rc || setup.status);
|
||||
|
||||
#ifndef __ia64__
|
||||
@@ -436,7 +439,8 @@ gnttab_init(void)
|
||||
if (xen_init() < 0)
|
||||
return -ENODEV;
|
||||
|
||||
BUG_ON(gnttab_resume());
|
||||
if (gnttab_resume() < 0)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
|
||||
gnttab_list[i] = i + 1;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <xen/xenbus.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <xen/gnttab.h>
|
||||
#include <xen/xencons.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
@@ -41,7 +42,7 @@ void machine_emergency_restart(void)
|
||||
{
|
||||
/* We really want to get pending console data out before we die. */
|
||||
xencons_force_flush();
|
||||
HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_reboot);
|
||||
HYPERVISOR_shutdown(SHUTDOWN_reboot);
|
||||
}
|
||||
|
||||
void machine_restart(char * __unused)
|
||||
@@ -58,7 +59,11 @@ void machine_power_off(void)
|
||||
{
|
||||
/* We really want to get pending console data out before we die. */
|
||||
xencons_force_flush();
|
||||
HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_poweroff);
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (pm_power_off)
|
||||
pm_power_off();
|
||||
#endif
|
||||
HYPERVISOR_shutdown(SHUTDOWN_poweroff);
|
||||
}
|
||||
|
||||
int reboot_thru_bios = 0; /* for dmi_scan.c */
|
||||
@@ -76,31 +81,41 @@ static int shutting_down = SHUTDOWN_INVALID;
|
||||
static void __shutdown_handler(void *unused);
|
||||
static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
|
||||
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
#define cpu_down(x) (-EOPNOTSUPP)
|
||||
#define cpu_up(x) (-EOPNOTSUPP)
|
||||
#ifdef CONFIG_SMP
|
||||
int smp_suspend(void);
|
||||
void smp_resume(void);
|
||||
#else
|
||||
#define smp_suspend() (0)
|
||||
#define smp_resume() ((void)0)
|
||||
#endif
|
||||
|
||||
/* Ensure we run on the idle task page tables so that we will
|
||||
switch page tables before running user space. This is needed
|
||||
on architectures with separate kernel and user page tables
|
||||
because the user page table pointer is not saved/restored. */
|
||||
static void switch_idle_mm(void)
|
||||
{
|
||||
struct mm_struct *mm = current->active_mm;
|
||||
|
||||
if (mm == &init_mm)
|
||||
return;
|
||||
|
||||
atomic_inc(&init_mm.mm_count);
|
||||
switch_mm(mm, &init_mm, current);
|
||||
current->active_mm = &init_mm;
|
||||
mmdrop(mm);
|
||||
}
|
||||
|
||||
static int __do_suspend(void *ignore)
|
||||
{
|
||||
int i, j, k, fpp;
|
||||
int i, j, k, fpp, err;
|
||||
|
||||
extern unsigned long max_pfn;
|
||||
extern unsigned long *pfn_to_mfn_frame_list_list;
|
||||
extern unsigned long *pfn_to_mfn_frame_list[];
|
||||
|
||||
extern int gnttab_suspend(void);
|
||||
extern int gnttab_resume(void);
|
||||
extern void time_resume(void);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cpumask_t prev_online_cpus;
|
||||
int vcpu_prepare(int vcpu);
|
||||
#endif
|
||||
|
||||
int err = 0;
|
||||
|
||||
BUG_ON(smp_processor_id() != 0);
|
||||
BUG_ON(in_interrupt());
|
||||
|
||||
@@ -110,50 +125,21 @@ static int __do_suspend(void *ignore)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
|
||||
if (num_online_cpus() > 1) {
|
||||
printk(KERN_WARNING "Can't suspend SMP guests "
|
||||
"without CONFIG_HOTPLUG_CPU\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
err = smp_suspend();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
xenbus_suspend();
|
||||
|
||||
lock_cpu_hotplug();
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* Take all other CPUs offline. We hold the hotplug mutex to
|
||||
* avoid other processes bringing up CPUs under our feet.
|
||||
*/
|
||||
cpus_clear(prev_online_cpus);
|
||||
while (num_online_cpus() > 1) {
|
||||
for_each_online_cpu(i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
unlock_cpu_hotplug();
|
||||
err = cpu_down(i);
|
||||
lock_cpu_hotplug();
|
||||
if (err != 0) {
|
||||
printk(KERN_CRIT "Failed to take all CPUs "
|
||||
"down: %d.\n", err);
|
||||
goto out_reenable_cpus;
|
||||
}
|
||||
cpu_set(i, prev_online_cpus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
preempt_disable();
|
||||
|
||||
#ifdef __i386__
|
||||
kmem_cache_shrink(pgd_cache);
|
||||
mm_pin_all();
|
||||
#endif
|
||||
mm_pin_all();
|
||||
|
||||
__cli();
|
||||
preempt_enable();
|
||||
unlock_cpu_hotplug();
|
||||
|
||||
gnttab_suspend();
|
||||
|
||||
@@ -199,34 +185,15 @@ static int __do_suspend(void *ignore)
|
||||
|
||||
time_resume();
|
||||
|
||||
switch_idle_mm();
|
||||
|
||||
__sti();
|
||||
|
||||
xencons_resume();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
for_each_cpu(i)
|
||||
vcpu_prepare(i);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Only resume xenbus /after/ we've prepared our VCPUs; otherwise
|
||||
* the VCPU hotplug callback can race with our vcpu_prepare
|
||||
*/
|
||||
xenbus_resume();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
out_reenable_cpus:
|
||||
for_each_cpu_mask(i, prev_online_cpus) {
|
||||
j = cpu_up(i);
|
||||
if ((j != 0) && !cpu_online(i)) {
|
||||
printk(KERN_CRIT "Failed to bring cpu "
|
||||
"%d back up (%d).\n",
|
||||
i, j);
|
||||
err = j;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
smp_resume();
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -334,7 +301,6 @@ static void shutdown_handler(struct xenbus_watch *watch,
|
||||
kfree(str);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
|
||||
unsigned int len)
|
||||
{
|
||||
@@ -360,45 +326,35 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
|
||||
if (err == -EAGAIN)
|
||||
goto again;
|
||||
|
||||
if (sysrq_key != '\0') {
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
if (sysrq_key != '\0')
|
||||
handle_sysrq(sysrq_key, NULL, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct xenbus_watch shutdown_watch = {
|
||||
.node = "control/shutdown",
|
||||
.callback = shutdown_handler
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static struct xenbus_watch sysrq_watch = {
|
||||
.node ="control/sysrq",
|
||||
.callback = sysrq_handler
|
||||
};
|
||||
#endif
|
||||
|
||||
static int setup_shutdown_watcher(struct notifier_block *notifier,
|
||||
unsigned long event,
|
||||
void *data)
|
||||
{
|
||||
int err1 = 0;
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
int err2 = 0;
|
||||
#endif
|
||||
int err;
|
||||
|
||||
err1 = register_xenbus_watch(&shutdown_watch);
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
err2 = register_xenbus_watch(&sysrq_watch);
|
||||
#endif
|
||||
|
||||
if (err1)
|
||||
err = register_xenbus_watch(&shutdown_watch);
|
||||
if (err)
|
||||
printk(KERN_ERR "Failed to set shutdown watcher\n");
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
if (err2)
|
||||
err = register_xenbus_watch(&sysrq_watch);
|
||||
if (err)
|
||||
printk(KERN_ERR "Failed to set sysrq watcher\n");
|
||||
#endif
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,15 @@ EXPORT_SYMBOL(x86_cpu_to_apicid);
|
||||
unsigned int maxcpus = NR_CPUS;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set of CPUs that remote admin software will allow us to bring online.
|
||||
* Notified to us via xenbus.
|
||||
*/
|
||||
static cpumask_t xenbus_allowed_cpumask;
|
||||
|
||||
/* Set of CPUs that local admin will allow us to bring online. */
|
||||
static cpumask_t local_allowed_cpumask = CPU_MASK_ALL;
|
||||
|
||||
void __init prefill_possible_map(void)
|
||||
{
|
||||
int i, rc;
|
||||
@@ -146,7 +155,7 @@ static void cpu_bringup(void)
|
||||
cpu_idle();
|
||||
}
|
||||
|
||||
void vcpu_prepare(int vcpu)
|
||||
static void vcpu_prepare(int vcpu)
|
||||
{
|
||||
vcpu_guest_context_t ctxt;
|
||||
struct task_struct *idle = idle_task(vcpu);
|
||||
@@ -278,6 +287,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
vcpu_prepare(cpu);
|
||||
}
|
||||
|
||||
xenbus_allowed_cpumask = cpu_present_map;
|
||||
|
||||
/* Currently, Xen gives no dynamic NUMA/HT info. */
|
||||
for (cpu = 1; cpu < NR_CPUS; cpu++) {
|
||||
cpu_sibling_map[cpu] = cpumask_of_cpu(cpu);
|
||||
@@ -301,6 +312,15 @@ void __devinit smp_prepare_boot_cpu(void)
|
||||
cpu_online_map = cpumask_of_cpu(0);
|
||||
}
|
||||
|
||||
static int local_cpu_hotplug_request(void)
|
||||
{
|
||||
/*
|
||||
* We assume a CPU hotplug request comes from local admin if it is made
|
||||
* via a userspace process (i.e., one with a real mm_struct).
|
||||
*/
|
||||
return (current->mm != NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
|
||||
/*
|
||||
@@ -331,8 +351,10 @@ static void vcpu_hotplug(unsigned int cpu)
|
||||
}
|
||||
|
||||
if (strcmp(state, "online") == 0) {
|
||||
cpu_set(cpu, xenbus_allowed_cpumask);
|
||||
(void)cpu_up(cpu);
|
||||
} else if (strcmp(state, "offline") == 0) {
|
||||
cpu_clear(cpu, xenbus_allowed_cpumask);
|
||||
(void)cpu_down(cpu);
|
||||
} else {
|
||||
printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
|
||||
@@ -353,6 +375,22 @@ static void handle_vcpu_hotplug_event(
|
||||
}
|
||||
}
|
||||
|
||||
static int smpboot_cpu_notify(struct notifier_block *notifier,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
int cpu = (long)hcpu;
|
||||
|
||||
/*
|
||||
* We do this in a callback notifier rather than __cpu_disable()
|
||||
* because local_cpu_hotplug_request() does not work in the latter
|
||||
* as it's always executed from within a stopmachine kthread.
|
||||
*/
|
||||
if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
|
||||
cpu_clear(cpu, local_allowed_cpumask);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int setup_cpu_watcher(struct notifier_block *notifier,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
@@ -360,7 +398,8 @@ static int setup_cpu_watcher(struct notifier_block *notifier,
|
||||
|
||||
static struct xenbus_watch cpu_watch = {
|
||||
.node = "cpu",
|
||||
.callback = handle_vcpu_hotplug_event };
|
||||
.callback = handle_vcpu_hotplug_event,
|
||||
.flags = XBWF_new_thread };
|
||||
(void)register_xenbus_watch(&cpu_watch);
|
||||
|
||||
if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
|
||||
@@ -375,14 +414,62 @@ static int setup_cpu_watcher(struct notifier_block *notifier,
|
||||
|
||||
static int __init setup_vcpu_hotplug_event(void)
|
||||
{
|
||||
static struct notifier_block hotplug_cpu = {
|
||||
.notifier_call = smpboot_cpu_notify };
|
||||
static struct notifier_block xsn_cpu = {
|
||||
.notifier_call = setup_cpu_watcher };
|
||||
|
||||
register_cpu_notifier(&hotplug_cpu);
|
||||
register_xenstore_notifier(&xsn_cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(setup_vcpu_hotplug_event);
|
||||
|
||||
int smp_suspend(void)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
lock_cpu_hotplug();
|
||||
|
||||
/*
|
||||
* Take all other CPUs offline. We hold the hotplug mutex to
|
||||
* avoid other processes bringing up CPUs under our feet.
|
||||
*/
|
||||
while (num_online_cpus() > 1) {
|
||||
unlock_cpu_hotplug();
|
||||
for_each_online_cpu(i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
err = cpu_down(i);
|
||||
if (err) {
|
||||
printk(KERN_CRIT "Failed to take all CPUs "
|
||||
"down: %d.\n", err);
|
||||
for_each_cpu(i)
|
||||
vcpu_hotplug(i);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
lock_cpu_hotplug();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void smp_resume(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_cpu(i)
|
||||
vcpu_prepare(i);
|
||||
|
||||
unlock_cpu_hotplug();
|
||||
|
||||
for_each_cpu(i)
|
||||
vcpu_hotplug(i);
|
||||
}
|
||||
|
||||
int __cpu_disable(void)
|
||||
{
|
||||
cpumask_t map = cpu_online_map;
|
||||
@@ -415,6 +502,20 @@ void __cpu_die(unsigned int cpu)
|
||||
|
||||
#else /* !CONFIG_HOTPLUG_CPU */
|
||||
|
||||
int smp_suspend(void)
|
||||
{
|
||||
if (num_online_cpus() > 1) {
|
||||
printk(KERN_WARNING "Can't suspend SMP guests "
|
||||
"without CONFIG_HOTPLUG_CPU\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void smp_resume(void)
|
||||
{
|
||||
}
|
||||
|
||||
int __cpu_disable(void)
|
||||
{
|
||||
return -ENOSYS;
|
||||
@@ -429,6 +530,20 @@ void __cpu_die(unsigned int cpu)
|
||||
|
||||
int __devinit __cpu_up(unsigned int cpu)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (local_cpu_hotplug_request()) {
|
||||
cpu_set(cpu, local_allowed_cpumask);
|
||||
if (!cpu_isset(cpu, xenbus_allowed_cpumask)) {
|
||||
printk("%s: attempt to bring up CPU %u disallowed by "
|
||||
"remote admin.\n", __FUNCTION__, cpu);
|
||||
return -EBUSY;
|
||||
}
|
||||
} else if (!cpu_isset(cpu, local_allowed_cpumask) ||
|
||||
!cpu_isset(cpu, xenbus_allowed_cpumask)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP_ALTERNATIVES
|
||||
if (num_online_cpus() == 1)
|
||||
prepare_for_smp();
|
||||
@@ -436,7 +551,9 @@ int __devinit __cpu_up(unsigned int cpu)
|
||||
|
||||
xen_smp_intr_init(cpu);
|
||||
cpu_set(cpu, cpu_online_map);
|
||||
if (HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL) != 0)
|
||||
|
||||
rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
|
||||
if (rc != 0)
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -97,7 +97,6 @@ typedef struct netif_st {
|
||||
#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
|
||||
#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
|
||||
|
||||
void netif_creditlimit(netif_t *netif);
|
||||
void netif_disconnect(netif_t *netif);
|
||||
|
||||
netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
static void __netif_up(netif_t *netif)
|
||||
@@ -71,6 +72,12 @@ static int net_close(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ethtool_ops network_ethtool_ops =
|
||||
{
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.set_tx_csum = ethtool_op_set_tx_csum,
|
||||
};
|
||||
|
||||
netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
|
||||
{
|
||||
int err = 0, i;
|
||||
@@ -101,7 +108,9 @@ netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
|
||||
dev->get_stats = netif_be_get_stats;
|
||||
dev->open = net_open;
|
||||
dev->stop = net_close;
|
||||
dev->features = NETIF_F_NO_CSUM;
|
||||
dev->features = NETIF_F_IP_CSUM;
|
||||
|
||||
SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
|
||||
|
||||
/* Disable queuing. */
|
||||
dev->tx_queue_len = 0;
|
||||
@@ -293,25 +302,6 @@ void free_netif(netif_t *netif)
|
||||
schedule_work(&netif->free_work);
|
||||
}
|
||||
|
||||
void netif_creditlimit(netif_t *netif)
|
||||
{
|
||||
#if 0
|
||||
/* Set the credit limit (reset remaining credit to new limit). */
|
||||
netif->credit_bytes = creditlimit->credit_bytes;
|
||||
netif->remaining_credit = creditlimit->credit_bytes;
|
||||
netif->credit_usec = creditlimit->period_usec;
|
||||
|
||||
if (netif->status == CONNECTED) {
|
||||
/*
|
||||
* Schedule work so that any packets waiting under previous
|
||||
* credit limit are dealt with (acts as a replenishment point).
|
||||
*/
|
||||
netif->credit_timeout.expires = jiffies;
|
||||
netif_schedule_work(netif);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void netif_disconnect(netif_t *netif)
|
||||
{
|
||||
switch (netif->status) {
|
||||
|
||||
@@ -100,10 +100,10 @@ static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Defer checksum calculation. */
|
||||
skb->proto_csum_blank = 1;
|
||||
/* Must be a local packet: assert its integrity. */
|
||||
skb->proto_csum_valid = 1;
|
||||
skb->proto_data_valid = 1;
|
||||
}
|
||||
|
||||
skb->ip_summed = skb->proto_csum_valid ?
|
||||
skb->ip_summed = skb->proto_data_valid ?
|
||||
CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
|
||||
|
||||
skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
|
||||
@@ -121,6 +121,12 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
|
||||
return &np->stats;
|
||||
}
|
||||
|
||||
static struct ethtool_ops network_ethtool_ops =
|
||||
{
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.set_tx_csum = ethtool_op_set_tx_csum,
|
||||
};
|
||||
|
||||
static void loopback_construct(struct net_device *dev, struct net_device *lo)
|
||||
{
|
||||
struct net_private *np = netdev_priv(dev);
|
||||
@@ -134,7 +140,11 @@ static void loopback_construct(struct net_device *dev, struct net_device *lo)
|
||||
|
||||
dev->tx_queue_len = 0;
|
||||
|
||||
dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
|
||||
dev->features = (NETIF_F_HIGHDMA |
|
||||
NETIF_F_LLTX |
|
||||
NETIF_F_IP_CSUM);
|
||||
|
||||
SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
|
||||
|
||||
/*
|
||||
* We do not set a jumbo MTU on the interface. Otherwise the network
|
||||
@@ -147,12 +157,6 @@ static void loopback_construct(struct net_device *dev, struct net_device *lo)
|
||||
/*dev->mtu = 16*1024;*/
|
||||
}
|
||||
|
||||
static struct ethtool_ops network_ethtool_ops =
|
||||
{
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.set_tx_csum = ethtool_op_set_tx_csum,
|
||||
};
|
||||
|
||||
static int __init make_loopback(int i)
|
||||
{
|
||||
struct net_device *dev1, *dev2;
|
||||
@@ -172,11 +176,6 @@ static int __init make_loopback(int i)
|
||||
loopback_construct(dev1, dev2);
|
||||
loopback_construct(dev2, dev1);
|
||||
|
||||
dev1->features |= NETIF_F_NO_CSUM;
|
||||
dev2->features |= NETIF_F_IP_CSUM;
|
||||
|
||||
SET_ETHTOOL_OPS(dev2, &network_ethtool_ops);
|
||||
|
||||
/*
|
||||
* Initialise a dummy MAC address for the 'dummy backend' interface. We
|
||||
* choose the numerically largest non-broadcast address to prevent the
|
||||
|
||||
@@ -171,7 +171,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
skb->len + hlen);
|
||||
BUG_ON(ret);
|
||||
nskb->dev = skb->dev;
|
||||
nskb->proto_csum_valid = skb->proto_csum_valid;
|
||||
nskb->proto_data_valid = skb->proto_data_valid;
|
||||
dev_kfree_skb(skb);
|
||||
skb = nskb;
|
||||
}
|
||||
@@ -213,7 +213,7 @@ static void net_rx_action(unsigned long unused)
|
||||
{
|
||||
netif_t *netif = NULL;
|
||||
s8 status;
|
||||
u16 size, id, irq;
|
||||
u16 size, id, irq, flags;
|
||||
multicall_entry_t *mcl;
|
||||
mmu_update_t *mmu;
|
||||
gnttab_transfer_t *gop;
|
||||
@@ -301,9 +301,6 @@ static void net_rx_action(unsigned long unused)
|
||||
netif = netdev_priv(skb->dev);
|
||||
size = skb->tail - skb->data;
|
||||
|
||||
/* Rederive the machine addresses. */
|
||||
new_mfn = mcl->args[1] >> PAGE_SHIFT;
|
||||
old_mfn = gop->mfn;
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
@@ -328,10 +325,14 @@ static void net_rx_action(unsigned long unused)
|
||||
}
|
||||
irq = netif->irq;
|
||||
id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id;
|
||||
flags = 0;
|
||||
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
|
||||
flags |= NETRXF_csum_blank | NETRXF_data_validated;
|
||||
else if (skb->proto_data_valid) /* remote but checksummed? */
|
||||
flags |= NETRXF_data_validated;
|
||||
if (make_rx_response(netif, id, status,
|
||||
(unsigned long)skb->data & ~PAGE_MASK,
|
||||
size, skb->proto_csum_valid ?
|
||||
NETRXF_data_validated : 0) &&
|
||||
size, flags) &&
|
||||
(rx_notify[irq] == 0)) {
|
||||
rx_notify[irq] = 1;
|
||||
notify_list[notify_nr++] = irq;
|
||||
@@ -655,11 +656,16 @@ static void net_tx_action(unsigned long unused)
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
|
||||
/*
|
||||
* No checking needed on localhost, but remember the field is
|
||||
* blank.
|
||||
*/
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->proto_csum_valid = 1;
|
||||
* Old frontends do not assert data_validated but we
|
||||
* can infer it from csum_blank so test both flags.
|
||||
*/
|
||||
if (txreq.flags & (NETTXF_data_validated|NETTXF_csum_blank)) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->proto_data_valid = 1;
|
||||
} else {
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
skb->proto_data_valid = 0;
|
||||
}
|
||||
skb->proto_csum_blank = !!(txreq.flags & NETTXF_csum_blank);
|
||||
|
||||
netif->stats.rx_bytes += txreq.size;
|
||||
|
||||
@@ -92,7 +92,7 @@ static int netback_probe(struct xenbus_device *dev,
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
|
||||
err = xenbus_switch_state(dev, XenbusStateInitWait);
|
||||
if (err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
break;
|
||||
|
||||
case XenbusStateClosing:
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
|
||||
xenbus_switch_state(dev, XenbusStateClosing);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
@@ -233,9 +233,44 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
|
||||
static void maybe_connect(struct backend_info *be)
|
||||
{
|
||||
if (be->netif != NULL && be->frontend_state == XenbusStateConnected) {
|
||||
if (be->netif && (be->frontend_state == XenbusStateConnected))
|
||||
connect(be);
|
||||
}
|
||||
}
|
||||
|
||||
static void xen_net_read_rate(struct xenbus_device *dev,
|
||||
unsigned long *bytes, unsigned long *usec)
|
||||
{
|
||||
char *s, *e;
|
||||
unsigned long b, u;
|
||||
char *ratestr;
|
||||
|
||||
/* Default to unlimited bandwidth. */
|
||||
*bytes = ~0UL;
|
||||
*usec = 0;
|
||||
|
||||
ratestr = xenbus_read(XBT_NULL, dev->nodename, "rate", NULL);
|
||||
if (IS_ERR(ratestr))
|
||||
return;
|
||||
|
||||
s = ratestr;
|
||||
b = simple_strtoul(s, &e, 10);
|
||||
if ((s == e) || (*e != ','))
|
||||
goto fail;
|
||||
|
||||
s = e + 1;
|
||||
u = simple_strtoul(s, &e, 10);
|
||||
if ((s == e) || (*e != '\0'))
|
||||
goto fail;
|
||||
|
||||
*bytes = b;
|
||||
*usec = u;
|
||||
|
||||
kfree(ratestr);
|
||||
return;
|
||||
|
||||
fail:
|
||||
WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n");
|
||||
kfree(ratestr);
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +289,11 @@ static void connect(struct backend_info *be)
|
||||
return;
|
||||
}
|
||||
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateConnected);
|
||||
xen_net_read_rate(dev, &be->netif->credit_bytes,
|
||||
&be->netif->credit_usec);
|
||||
be->netif->remaining_credit = be->netif->credit_bytes;
|
||||
|
||||
xenbus_switch_state(dev, XenbusStateConnected);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -300,13 +300,6 @@ again:
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename,
|
||||
"state", "%d", XenbusStateConnected);
|
||||
if (err) {
|
||||
message = "writing frontend XenbusStateConnected";
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err) {
|
||||
if (err == -EAGAIN)
|
||||
@@ -315,6 +308,8 @@ again:
|
||||
goto destroy_ring;
|
||||
}
|
||||
|
||||
xenbus_switch_state(dev, XenbusStateConnected);
|
||||
|
||||
return 0;
|
||||
|
||||
abort_transaction:
|
||||
@@ -696,7 +691,12 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
tx->gref = np->grant_tx_ref[id] = ref;
|
||||
tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
|
||||
tx->size = skb->len;
|
||||
tx->flags = (skb->ip_summed == CHECKSUM_HW) ? NETTXF_csum_blank : 0;
|
||||
|
||||
tx->flags = 0;
|
||||
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
|
||||
tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
|
||||
if (skb->proto_data_valid) /* remote but checksummed? */
|
||||
tx->flags |= NETTXF_data_validated;
|
||||
|
||||
np->tx.req_prod_pvt = i + 1;
|
||||
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
|
||||
@@ -811,8 +811,18 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
skb->len = rx->status;
|
||||
skb->tail = skb->data + skb->len;
|
||||
|
||||
if (rx->flags & NETRXF_data_validated)
|
||||
/*
|
||||
* Old backends do not assert data_validated but we
|
||||
* can infer it from csum_blank so test both flags.
|
||||
*/
|
||||
if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank)) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->proto_data_valid = 1;
|
||||
} else {
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
skb->proto_data_valid = 0;
|
||||
}
|
||||
skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank);
|
||||
|
||||
np->stats.rx_packets++;
|
||||
np->stats.rx_bytes += rx->status;
|
||||
@@ -978,8 +988,8 @@ static void network_connect(struct net_device *dev)
|
||||
* the RX ring because some of our pages are currently flipped out
|
||||
* so we can't just free the RX skbs.
|
||||
* NB2. Freelist index entries are always going to be less than
|
||||
* __PAGE_OFFSET, whereas pointers to skbs will always be equal or
|
||||
* greater than __PAGE_OFFSET: we use this property to distinguish
|
||||
* PAGE_OFFSET, whereas pointers to skbs will always be equal or
|
||||
* greater than PAGE_OFFSET: we use this property to distinguish
|
||||
* them.
|
||||
*/
|
||||
|
||||
@@ -990,7 +1000,7 @@ static void network_connect(struct net_device *dev)
|
||||
* interface has been down.
|
||||
*/
|
||||
for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) {
|
||||
if ((unsigned long)np->tx_skbs[i] < __PAGE_OFFSET)
|
||||
if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
|
||||
continue;
|
||||
|
||||
skb = np->tx_skbs[i];
|
||||
@@ -1006,8 +1016,11 @@ static void network_connect(struct net_device *dev)
|
||||
tx->gref = np->grant_tx_ref[i];
|
||||
tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
|
||||
tx->size = skb->len;
|
||||
tx->flags = (skb->ip_summed == CHECKSUM_HW) ?
|
||||
NETTXF_csum_blank : 0;
|
||||
tx->flags = 0;
|
||||
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
|
||||
tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
|
||||
if (skb->proto_data_valid) /* remote but checksummed? */
|
||||
tx->flags |= NETTXF_data_validated;
|
||||
|
||||
np->stats.tx_bytes += skb->len;
|
||||
np->stats.tx_packets++;
|
||||
@@ -1018,7 +1031,7 @@ static void network_connect(struct net_device *dev)
|
||||
|
||||
/* Rebuild the RX buffer freelist and the RX ring itself. */
|
||||
for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) {
|
||||
if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET)
|
||||
if ((unsigned long)np->rx_skbs[i] < PAGE_OFFSET)
|
||||
continue;
|
||||
gnttab_grant_foreign_transfer_ref(
|
||||
np->grant_rx_ref[i], np->xbdev->otherend_id,
|
||||
@@ -1216,7 +1229,7 @@ static void netfront_closing(struct xenbus_device *dev)
|
||||
|
||||
close_netdev(info);
|
||||
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ static inline int valid_request(int offset, int size)
|
||||
}
|
||||
|
||||
static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
|
||||
u32 offset)
|
||||
int offset)
|
||||
{
|
||||
if (offset >= 0) {
|
||||
new_val_mask <<= (offset * 8);
|
||||
@@ -180,7 +180,8 @@ int pciback_config_read(struct pci_dev *dev, int offset, int size,
|
||||
|
||||
if ((req_start >= field_start && req_start < field_end)
|
||||
|| (req_end > field_start && req_end <= field_end)) {
|
||||
err = conf_space_read(dev, cfg_entry, offset, &tmp_val);
|
||||
err = conf_space_read(dev, cfg_entry, field_start,
|
||||
&tmp_val);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -228,14 +229,16 @@ int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
|
||||
|| (req_end > field_start && req_end <= field_end)) {
|
||||
tmp_val = 0;
|
||||
|
||||
err = pciback_config_read(dev, offset, size, &tmp_val);
|
||||
err = pciback_config_read(dev, field_start,
|
||||
field->size, &tmp_val);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
tmp_val = merge_value(tmp_val, value, get_mask(size),
|
||||
field_start - req_start);
|
||||
req_start - field_start);
|
||||
|
||||
err = conf_space_write(dev, cfg_entry, offset, tmp_val);
|
||||
err = conf_space_write(dev, cfg_entry, field_start,
|
||||
tmp_val);
|
||||
handled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
|
||||
{
|
||||
struct pciback_device *pdev;
|
||||
|
||||
pdev = kmalloc(sizeof(struct pciback_device), GFP_KERNEL);
|
||||
pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL);
|
||||
if (pdev == NULL)
|
||||
goto out;
|
||||
dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
|
||||
@@ -137,7 +137,7 @@ static int pciback_attach(struct pciback_device *pdev)
|
||||
|
||||
dev_dbg(&pdev->xdev->dev, "Connecting...\n");
|
||||
|
||||
err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected);
|
||||
err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
|
||||
if (err)
|
||||
xenbus_dev_fatal(pdev->xdev, err,
|
||||
"Error switching to connected state!");
|
||||
@@ -165,7 +165,7 @@ static void pciback_frontend_changed(struct xenbus_device *xdev,
|
||||
break;
|
||||
|
||||
case XenbusStateClosing:
|
||||
xenbus_switch_state(xdev, XBT_NULL, XenbusStateClosing);
|
||||
xenbus_switch_state(xdev, XenbusStateClosing);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
@@ -341,7 +341,7 @@ static int pciback_setup_backend(struct pciback_device *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateInitialised);
|
||||
err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
|
||||
if (err)
|
||||
xenbus_dev_fatal(pdev->xdev, err,
|
||||
"Error switching to initialised state!");
|
||||
@@ -386,7 +386,7 @@ static int pciback_xenbus_probe(struct xenbus_device *dev,
|
||||
}
|
||||
|
||||
/* wait for xend to configure us */
|
||||
err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
|
||||
err = xenbus_switch_state(dev, XenbusStateInitWait);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -96,10 +96,6 @@ static int pcifront_publish_info(struct pcifront_device *pdev)
|
||||
if (!err)
|
||||
err = xenbus_printf(trans, pdev->xdev->nodename,
|
||||
"magic", XEN_PCI_MAGIC);
|
||||
if (!err)
|
||||
err =
|
||||
xenbus_switch_state(pdev->xdev, trans,
|
||||
XenbusStateInitialised);
|
||||
|
||||
if (err) {
|
||||
xenbus_transaction_end(trans, 1);
|
||||
@@ -118,6 +114,8 @@ static int pcifront_publish_info(struct pcifront_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
|
||||
|
||||
dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
|
||||
|
||||
out:
|
||||
@@ -186,7 +184,7 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected);
|
||||
err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -205,8 +203,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
|
||||
prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
|
||||
|
||||
if (prev_state < XenbusStateClosing)
|
||||
err = xenbus_switch_state(pdev->xdev, XBT_NULL,
|
||||
XenbusStateClosing);
|
||||
err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
|
||||
|
||||
if (!err && prev_state == XenbusStateConnected)
|
||||
pcifront_disconnect(pdev);
|
||||
|
||||
@@ -277,6 +277,7 @@ static int __init privcmd_init(void)
|
||||
set_bit(__HYPERVISOR_mmu_update, hypercall_permission_map);
|
||||
set_bit(__HYPERVISOR_mmuext_op, hypercall_permission_map);
|
||||
set_bit(__HYPERVISOR_xen_version, hypercall_permission_map);
|
||||
set_bit(__HYPERVISOR_sched_op, hypercall_permission_map);
|
||||
|
||||
privcmd_intf = create_xen_proc_entry("privcmd", 0400);
|
||||
if (privcmd_intf != NULL)
|
||||
|
||||
@@ -55,6 +55,7 @@ static int tpmback_remove(struct xenbus_device *dev)
|
||||
be->backend_watch.node = NULL;
|
||||
}
|
||||
if (be->tpmif) {
|
||||
vtpm_release_packets(be->tpmif, 0);
|
||||
tpmif_put(be->tpmif);
|
||||
be->tpmif = NULL;
|
||||
}
|
||||
@@ -87,7 +88,7 @@ static int tpmback_probe(struct xenbus_device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
|
||||
err = xenbus_switch_state(dev, XenbusStateInitWait);
|
||||
if (err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -175,7 +176,7 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
break;
|
||||
|
||||
case XenbusStateClosing:
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
|
||||
xenbus_switch_state(dev, XenbusStateClosing);
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
@@ -247,18 +248,15 @@ again:
|
||||
goto abort;
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(dev, xbt, XenbusStateConnected);
|
||||
if (err)
|
||||
goto abort;
|
||||
|
||||
be->tpmif->status = CONNECTED;
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err == -EAGAIN)
|
||||
goto again;
|
||||
if (err) {
|
||||
if (err)
|
||||
xenbus_dev_fatal(be->dev, err, "end of transaction");
|
||||
}
|
||||
|
||||
err = xenbus_switch_state(dev, XenbusStateConnected);
|
||||
if (!err)
|
||||
be->tpmif->status = CONNECTED;
|
||||
return;
|
||||
abort:
|
||||
xenbus_transaction_end(xbt, 1);
|
||||
|
||||
@@ -65,14 +65,18 @@ static irqreturn_t tpmif_int(int irq,
|
||||
void *tpm_priv,
|
||||
struct pt_regs *ptregs);
|
||||
static void tpmif_rx_action(unsigned long unused);
|
||||
static void tpmif_connect(struct tpm_private *tp, domid_t domid);
|
||||
static int tpmif_connect(struct xenbus_device *dev,
|
||||
struct tpm_private *tp,
|
||||
domid_t domid);
|
||||
static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
|
||||
static int tpm_allocate_buffers(struct tpm_private *tp);
|
||||
static int tpmif_allocate_tx_buffers(struct tpm_private *tp);
|
||||
static void tpmif_free_tx_buffers(struct tpm_private *tp);
|
||||
static void tpmif_set_connected_state(struct tpm_private *tp,
|
||||
u8 newstate);
|
||||
static int tpm_xmit(struct tpm_private *tp,
|
||||
const u8 * buf, size_t count, int userbuffer,
|
||||
void *remember);
|
||||
static void destroy_tpmring(struct tpm_private *tp);
|
||||
|
||||
#define DPRINTK(fmt, args...) \
|
||||
pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
|
||||
@@ -81,6 +85,8 @@ static int tpm_xmit(struct tpm_private *tp,
|
||||
#define WPRINTK(fmt, args...) \
|
||||
printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args)
|
||||
|
||||
#define GRANT_INVALID_REF 0
|
||||
|
||||
|
||||
static inline int
|
||||
tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len,
|
||||
@@ -119,6 +125,14 @@ static inline struct tx_buffer *tx_buffer_alloc(void)
|
||||
}
|
||||
|
||||
|
||||
static inline void tx_buffer_free(struct tx_buffer *txb)
|
||||
{
|
||||
if (txb) {
|
||||
free_page((long)txb->data);
|
||||
kfree(txb);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Utility function for the tpm_private structure
|
||||
**************************************************************/
|
||||
@@ -128,23 +142,29 @@ static inline void tpm_private_init(struct tpm_private *tp)
|
||||
init_waitqueue_head(&tp->wait_q);
|
||||
}
|
||||
|
||||
static inline void tpm_private_free(void)
|
||||
{
|
||||
tpmif_free_tx_buffers(my_priv);
|
||||
kfree(my_priv);
|
||||
my_priv = NULL;
|
||||
}
|
||||
|
||||
static struct tpm_private *tpm_private_get(void)
|
||||
{
|
||||
int err;
|
||||
if (!my_priv) {
|
||||
my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL);
|
||||
if (my_priv) {
|
||||
tpm_private_init(my_priv);
|
||||
err = tpmif_allocate_tx_buffers(my_priv);
|
||||
if (err < 0) {
|
||||
tpm_private_free();
|
||||
}
|
||||
}
|
||||
}
|
||||
return my_priv;
|
||||
}
|
||||
|
||||
static inline void tpm_private_free(void)
|
||||
{
|
||||
kfree(my_priv);
|
||||
my_priv = NULL;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
|
||||
The interface to let the tpm plugin register its callback
|
||||
@@ -233,6 +253,8 @@ static int setup_tpmring(struct xenbus_device *dev,
|
||||
tpmif_tx_interface_t *sring;
|
||||
int err;
|
||||
|
||||
tp->ring_ref = GRANT_INVALID_REF;
|
||||
|
||||
sring = (void *)__get_free_page(GFP_KERNEL);
|
||||
if (!sring) {
|
||||
xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
|
||||
@@ -240,8 +262,6 @@ static int setup_tpmring(struct xenbus_device *dev,
|
||||
}
|
||||
tp->tx = sring;
|
||||
|
||||
tpm_allocate_buffers(tp);
|
||||
|
||||
err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx));
|
||||
if (err < 0) {
|
||||
free_page((unsigned long)sring);
|
||||
@@ -251,14 +271,13 @@ static int setup_tpmring(struct xenbus_device *dev,
|
||||
}
|
||||
tp->ring_ref = err;
|
||||
|
||||
err = xenbus_alloc_evtchn(dev, &tp->evtchn);
|
||||
err = tpmif_connect(dev, tp, dev->otherend_id);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
tpmif_connect(tp, dev->otherend_id);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
destroy_tpmring(tp);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -266,14 +285,17 @@ fail:
|
||||
static void destroy_tpmring(struct tpm_private *tp)
|
||||
{
|
||||
tpmif_set_connected_state(tp, 0);
|
||||
if (tp->tx != NULL) {
|
||||
|
||||
if (tp->ring_ref != GRANT_INVALID_REF) {
|
||||
gnttab_end_foreign_access(tp->ring_ref, 0,
|
||||
(unsigned long)tp->tx);
|
||||
tp->ring_ref = GRANT_INVALID_REF;
|
||||
tp->tx = NULL;
|
||||
}
|
||||
|
||||
if (tp->irq)
|
||||
unbind_from_irqhandler(tp->irq, NULL);
|
||||
unbind_from_irqhandler(tp->irq, tp);
|
||||
|
||||
tp->evtchn = tp->irq = 0;
|
||||
}
|
||||
|
||||
@@ -377,6 +399,9 @@ static int tpmfront_probe(struct xenbus_device *dev,
|
||||
int handle;
|
||||
struct tpm_private *tp = tpm_private_get();
|
||||
|
||||
if (!tp)
|
||||
return -ENOMEM;
|
||||
|
||||
err = xenbus_scanf(XBT_NULL, dev->nodename,
|
||||
"handle", "%i", &handle);
|
||||
if (XENBUS_EXIST_ERR(err))
|
||||
@@ -402,15 +427,14 @@ static int tpmfront_probe(struct xenbus_device *dev,
|
||||
|
||||
static int tpmfront_remove(struct xenbus_device *dev)
|
||||
{
|
||||
struct tpm_private *tp = dev->data;
|
||||
struct tpm_private *tp = (struct tpm_private *)dev->data;
|
||||
destroy_tpmring(tp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tpmfront_suspend(struct xenbus_device *dev)
|
||||
static int tpmfront_suspend(struct xenbus_device *dev)
|
||||
{
|
||||
struct tpm_private *tp = dev->data;
|
||||
struct tpm_private *tp = (struct tpm_private *)dev->data;
|
||||
u32 ctr;
|
||||
|
||||
/* lock, so no app can send */
|
||||
@@ -437,29 +461,35 @@ tpmfront_suspend(struct xenbus_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tpmfront_resume(struct xenbus_device *dev)
|
||||
static int tpmfront_resume(struct xenbus_device *dev)
|
||||
{
|
||||
struct tpm_private *tp = dev->data;
|
||||
struct tpm_private *tp = (struct tpm_private *)dev->data;
|
||||
destroy_tpmring(tp);
|
||||
return talk_to_backend(dev, tp);
|
||||
}
|
||||
|
||||
static void
|
||||
tpmif_connect(struct tpm_private *tp, domid_t domid)
|
||||
static int tpmif_connect(struct xenbus_device *dev,
|
||||
struct tpm_private *tp,
|
||||
domid_t domid)
|
||||
{
|
||||
int err;
|
||||
|
||||
tp->backend_id = domid;
|
||||
|
||||
err = xenbus_alloc_evtchn(dev, &tp->evtchn);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = bind_evtchn_to_irqhandler(tp->evtchn,
|
||||
tpmif_int, SA_SAMPLE_RANDOM, "tpmif",
|
||||
tp);
|
||||
if (err <= 0) {
|
||||
WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
|
||||
tp->irq = err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xenbus_device_id tpmfront_ids[] = {
|
||||
@@ -488,19 +518,30 @@ static void __exit exit_tpm_xenbus(void)
|
||||
xenbus_unregister_driver(&tpmfront);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
tpm_allocate_buffers(struct tpm_private *tp)
|
||||
static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < TPMIF_TX_RING_SIZE; i++)
|
||||
for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
|
||||
tp->tx_buffers[i] = tx_buffer_alloc();
|
||||
return 1;
|
||||
if (!tp->tx_buffers[i]) {
|
||||
tpmif_free_tx_buffers(tp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tpmif_rx_action(unsigned long priv)
|
||||
static void tpmif_free_tx_buffers(struct tpm_private *tp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
|
||||
tx_buffer_free(tp->tx_buffers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void tpmif_rx_action(unsigned long priv)
|
||||
{
|
||||
struct tpm_private *tp = (struct tpm_private *)priv;
|
||||
|
||||
@@ -545,8 +586,7 @@ exit:
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t
|
||||
tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
|
||||
static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
|
||||
{
|
||||
struct tpm_private *tp = tpm_priv;
|
||||
unsigned long flags;
|
||||
@@ -560,10 +600,9 @@ tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
tpm_xmit(struct tpm_private *tp,
|
||||
const u8 * buf, size_t count, int isuserbuffer,
|
||||
void *remember)
|
||||
static int tpm_xmit(struct tpm_private *tp,
|
||||
const u8 * buf, size_t count, int isuserbuffer,
|
||||
void *remember)
|
||||
{
|
||||
tpmif_tx_request_t *tx;
|
||||
TPMIF_RING_IDX i;
|
||||
@@ -693,8 +732,7 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected)
|
||||
* =================================================================
|
||||
*/
|
||||
|
||||
static int __init
|
||||
tpmif_init(void)
|
||||
static int __init tpmif_init(void)
|
||||
{
|
||||
IPRINTK("Initialising the vTPM driver.\n");
|
||||
if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE,
|
||||
@@ -709,8 +747,7 @@ tpmif_init(void)
|
||||
|
||||
module_init(tpmif_init);
|
||||
|
||||
static void __exit
|
||||
tpmif_exit(void)
|
||||
static void __exit tpmif_exit(void)
|
||||
{
|
||||
exit_tpm_xenbus();
|
||||
gnttab_free_grant_references(gref_head);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
obj-y += xenbus.o
|
||||
obj-$(CONFIG_XEN_BACKEND) += xenbus_be.o
|
||||
|
||||
xenbus_be-objs =
|
||||
xenbus_be-objs += xenbus_backend_client.o
|
||||
|
||||
xenbus-objs =
|
||||
xenbus-objs += xenbus_client.o
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/******************************************************************************
|
||||
* Backend-client-facing interface for the Xenbus driver. In other words, the
|
||||
* interface between the Xenbus and the device-specific code in the backend
|
||||
* driver.
|
||||
*
|
||||
* Copyright (C) 2005-2006 XenSource Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation; or, when distributed
|
||||
* separately from the Linux kernel or incorporated into other
|
||||
* software packages, subject to the following license:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this source file (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <xen/gnttab.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/driver_util.h>
|
||||
|
||||
/* Based on Rusty Russell's skeleton driver's map_page */
|
||||
int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
|
||||
{
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = gnt_ref,
|
||||
.dom = dev->otherend_id,
|
||||
};
|
||||
struct vm_struct *area;
|
||||
|
||||
*vaddr = NULL;
|
||||
|
||||
area = alloc_vm_area(PAGE_SIZE);
|
||||
if (!area)
|
||||
return -ENOMEM;
|
||||
|
||||
op.host_addr = (unsigned long)area->addr;
|
||||
|
||||
lock_vm_area(area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
unlock_vm_area(area);
|
||||
|
||||
if (op.status != GNTST_okay) {
|
||||
free_vm_area(area);
|
||||
xenbus_dev_fatal(dev, op.status,
|
||||
"mapping in shared page %d from domain %d",
|
||||
gnt_ref, dev->otherend_id);
|
||||
return op.status;
|
||||
}
|
||||
|
||||
/* Stuff the handle in an unused field */
|
||||
area->phys_addr = (unsigned long)op.handle;
|
||||
|
||||
*vaddr = area->addr;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
|
||||
|
||||
|
||||
int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
|
||||
grant_handle_t *handle, void *vaddr)
|
||||
{
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = gnt_ref,
|
||||
.dom = dev->otherend_id,
|
||||
};
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
|
||||
if (op.status != GNTST_okay) {
|
||||
xenbus_dev_fatal(dev, op.status,
|
||||
"mapping in shared page %d from domain %d",
|
||||
gnt_ref, dev->otherend_id);
|
||||
} else
|
||||
*handle = op.handle;
|
||||
|
||||
return op.status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_map_ring);
|
||||
|
||||
|
||||
/* Based on Rusty Russell's skeleton driver's unmap_page */
|
||||
int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
struct gnttab_unmap_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
};
|
||||
|
||||
/* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
|
||||
* method so that we don't have to muck with vmalloc internals here.
|
||||
* We could force the user to hang on to their struct vm_struct from
|
||||
* xenbus_map_ring_valloc, but these 6 lines considerably simplify
|
||||
* this API.
|
||||
*/
|
||||
read_lock(&vmlist_lock);
|
||||
for (area = vmlist; area != NULL; area = area->next) {
|
||||
if (area->addr == vaddr)
|
||||
break;
|
||||
}
|
||||
read_unlock(&vmlist_lock);
|
||||
|
||||
if (!area) {
|
||||
xenbus_dev_error(dev, -ENOENT,
|
||||
"can't find mapped virtual address %p", vaddr);
|
||||
return GNTST_bad_virt_addr;
|
||||
}
|
||||
|
||||
op.handle = (grant_handle_t)area->phys_addr;
|
||||
|
||||
lock_vm_area(area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
unlock_vm_area(area);
|
||||
|
||||
if (op.status == GNTST_okay)
|
||||
free_vm_area(area);
|
||||
else
|
||||
xenbus_dev_error(dev, op.status,
|
||||
"unmapping page at handle %d error %d",
|
||||
(int16_t)area->phys_addr, op.status);
|
||||
|
||||
return op.status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
|
||||
|
||||
|
||||
int xenbus_unmap_ring(struct xenbus_device *dev,
|
||||
grant_handle_t handle, void *vaddr)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
.handle = handle,
|
||||
};
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
|
||||
if (op.status != GNTST_okay)
|
||||
xenbus_dev_error(dev, op.status,
|
||||
"unmapping page at handle %d error %d",
|
||||
handle, op.status);
|
||||
|
||||
return op.status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
@@ -84,9 +84,7 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
|
||||
EXPORT_SYMBOL_GPL(xenbus_watch_path2);
|
||||
|
||||
|
||||
int xenbus_switch_state(struct xenbus_device *dev,
|
||||
xenbus_transaction_t xbt,
|
||||
XenbusState state)
|
||||
int xenbus_switch_state(struct xenbus_device *dev, XenbusState state)
|
||||
{
|
||||
/* We check whether the state is currently set to the given value, and
|
||||
if not, then the state is set. We don't want to unconditionally
|
||||
@@ -94,6 +92,12 @@ int xenbus_switch_state(struct xenbus_device *dev,
|
||||
unnecessarily. Furthermore, if the node has gone, we don't write
|
||||
to it, as the device will be tearing down, and we don't want to
|
||||
resurrect that directory.
|
||||
|
||||
Note that, because of this cached value of our state, this function
|
||||
will not work inside a Xenstore transaction (something it was
|
||||
trying to in the past) because dev->state would not get reset if
|
||||
the transaction was aborted.
|
||||
|
||||
*/
|
||||
|
||||
int current_state;
|
||||
@@ -102,12 +106,12 @@ int xenbus_switch_state(struct xenbus_device *dev,
|
||||
if (state == dev->state)
|
||||
return 0;
|
||||
|
||||
err = xenbus_scanf(xbt, dev->nodename, "state", "%d",
|
||||
¤t_state);
|
||||
err = xenbus_scanf(XBT_NULL, dev->nodename, "state", "%d",
|
||||
¤t_state);
|
||||
if (err != 1)
|
||||
return 0;
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
|
||||
err = xenbus_printf(XBT_NULL, dev->nodename, "state", "%d", state);
|
||||
if (err) {
|
||||
if (state != XenbusStateClosing) /* Avoid looping */
|
||||
xenbus_dev_fatal(dev, err, "writing new state");
|
||||
@@ -193,7 +197,7 @@ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
|
||||
_dev_error(dev, err, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing);
|
||||
xenbus_switch_state(dev, XenbusStateClosing);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
|
||||
|
||||
@@ -257,134 +261,6 @@ int xenbus_free_evtchn(struct xenbus_device *dev, int port)
|
||||
}
|
||||
|
||||
|
||||
/* Based on Rusty Russell's skeleton driver's map_page */
|
||||
int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
|
||||
{
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = gnt_ref,
|
||||
.dom = dev->otherend_id,
|
||||
};
|
||||
struct vm_struct *area;
|
||||
|
||||
*vaddr = NULL;
|
||||
|
||||
area = alloc_vm_area(PAGE_SIZE);
|
||||
if (!area)
|
||||
return -ENOMEM;
|
||||
|
||||
op.host_addr = (unsigned long)area->addr;
|
||||
|
||||
lock_vm_area(area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
unlock_vm_area(area);
|
||||
|
||||
if (op.status != GNTST_okay) {
|
||||
free_vm_area(area);
|
||||
xenbus_dev_fatal(dev, op.status,
|
||||
"mapping in shared page %d from domain %d",
|
||||
gnt_ref, dev->otherend_id);
|
||||
return op.status;
|
||||
}
|
||||
|
||||
/* Stuff the handle in an unused field */
|
||||
area->phys_addr = (unsigned long)op.handle;
|
||||
|
||||
*vaddr = area->addr;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
|
||||
|
||||
|
||||
int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
|
||||
grant_handle_t *handle, void *vaddr)
|
||||
{
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = gnt_ref,
|
||||
.dom = dev->otherend_id,
|
||||
};
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
|
||||
if (op.status != GNTST_okay) {
|
||||
xenbus_dev_fatal(dev, op.status,
|
||||
"mapping in shared page %d from domain %d",
|
||||
gnt_ref, dev->otherend_id);
|
||||
} else
|
||||
*handle = op.handle;
|
||||
|
||||
return op.status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_map_ring);
|
||||
|
||||
|
||||
/* Based on Rusty Russell's skeleton driver's unmap_page */
|
||||
int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
struct gnttab_unmap_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
};
|
||||
|
||||
/* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
|
||||
* method so that we don't have to muck with vmalloc internals here.
|
||||
* We could force the user to hang on to their struct vm_struct from
|
||||
* xenbus_map_ring_valloc, but these 6 lines considerably simplify
|
||||
* this API.
|
||||
*/
|
||||
read_lock(&vmlist_lock);
|
||||
for (area = vmlist; area != NULL; area = area->next) {
|
||||
if (area->addr == vaddr)
|
||||
break;
|
||||
}
|
||||
read_unlock(&vmlist_lock);
|
||||
|
||||
if (!area) {
|
||||
xenbus_dev_error(dev, -ENOENT,
|
||||
"can't find mapped virtual address %p", vaddr);
|
||||
return GNTST_bad_virt_addr;
|
||||
}
|
||||
|
||||
op.handle = (grant_handle_t)area->phys_addr;
|
||||
|
||||
lock_vm_area(area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
unlock_vm_area(area);
|
||||
|
||||
if (op.status == GNTST_okay)
|
||||
free_vm_area(area);
|
||||
else
|
||||
xenbus_dev_error(dev, op.status,
|
||||
"unmapping page at handle %d error %d",
|
||||
(int16_t)area->phys_addr, op.status);
|
||||
|
||||
return op.status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
|
||||
|
||||
|
||||
int xenbus_unmap_ring(struct xenbus_device *dev,
|
||||
grant_handle_t handle, void *vaddr)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
.handle = handle,
|
||||
};
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
|
||||
if (op.status != GNTST_okay)
|
||||
xenbus_dev_error(dev, op.status,
|
||||
"unmapping page at handle %d error %d",
|
||||
handle, op.status);
|
||||
|
||||
return op.status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
|
||||
|
||||
|
||||
XenbusState xenbus_read_driver_state(const char *path)
|
||||
{
|
||||
XenbusState result;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2005 Rusty Russell, IBM Corporation
|
||||
* Copyright (C) 2005 Mike Wray, Hewlett-Packard
|
||||
* Copyright (C) 2005 XenSource Ltd
|
||||
* Copyright (C) 2005, 2006 XenSource Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/xen_proc.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/features.h>
|
||||
|
||||
#include "xenbus_comms.h"
|
||||
|
||||
@@ -364,7 +365,7 @@ static int xenbus_dev_probe(struct device *_dev)
|
||||
return 0;
|
||||
fail:
|
||||
xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -381,7 +382,7 @@ static int xenbus_dev_remove(struct device *_dev)
|
||||
if (drv->remove)
|
||||
drv->remove(dev);
|
||||
|
||||
xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed);
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -882,7 +883,7 @@ static int all_devices_ready_(struct device *dev, void *data)
|
||||
int *result = data;
|
||||
|
||||
if (xendev->state != XenbusStateConnected) {
|
||||
result = 0;
|
||||
*result = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -901,8 +902,6 @@ static int all_devices_ready(void)
|
||||
|
||||
void xenbus_probe(void *unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON((xenstored_ready <= 0));
|
||||
|
||||
/* Enumerate devices in xenstore. */
|
||||
@@ -915,28 +914,6 @@ void xenbus_probe(void *unused)
|
||||
|
||||
/* Notify others that xenstore is up */
|
||||
notifier_call_chain(&xenstore_chain, 0, NULL);
|
||||
|
||||
/* On a 10 second timeout, waiting for all devices currently
|
||||
configured. We need to do this to guarantee that the filesystems
|
||||
and / or network devices needed for boot are available, before we
|
||||
can allow the boot to proceed.
|
||||
|
||||
A possible improvement here would be to have the tools add a
|
||||
per-device flag to the store entry, indicating whether it is needed
|
||||
at boot time. This would allow people who knew what they were
|
||||
doing to accelerate their boot slightly, but of course needs tools
|
||||
or manual intervention to set up those flags correctly.
|
||||
*/
|
||||
for (i = 0; i < 10 * HZ; i++) {
|
||||
if (all_devices_ready())
|
||||
return;
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
|
||||
printk(KERN_WARNING
|
||||
"XENBUS: Timeout connecting to devices!\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -983,6 +960,7 @@ static int xsd_port_read(char *page, char **start, off_t off,
|
||||
static int __init xenbus_probe_init(void)
|
||||
{
|
||||
int err = 0, dom0;
|
||||
unsigned long page = 0;
|
||||
|
||||
DPRINTK("");
|
||||
|
||||
@@ -991,11 +969,9 @@ static int __init xenbus_probe_init(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Register ourselves with the kernel bus & device subsystems */
|
||||
/* Register ourselves with the kernel bus subsystem */
|
||||
bus_register(&xenbus_frontend.bus);
|
||||
bus_register(&xenbus_backend.bus);
|
||||
device_register(&xenbus_frontend.dev);
|
||||
device_register(&xenbus_backend.dev);
|
||||
|
||||
/*
|
||||
* Domain0 doesn't have a store_evtchn or store_mfn yet.
|
||||
@@ -1003,11 +979,7 @@ static int __init xenbus_probe_init(void)
|
||||
dom0 = (xen_start_info->store_evtchn == 0);
|
||||
|
||||
if (dom0) {
|
||||
|
||||
unsigned long page;
|
||||
evtchn_op_t op = { 0 };
|
||||
int ret;
|
||||
|
||||
|
||||
/* Allocate page. */
|
||||
page = get_zeroed_page(GFP_KERNEL);
|
||||
@@ -1023,8 +995,10 @@ static int __init xenbus_probe_init(void)
|
||||
op.u.alloc_unbound.dom = DOMID_SELF;
|
||||
op.u.alloc_unbound.remote_dom = 0;
|
||||
|
||||
ret = HYPERVISOR_event_channel_op(&op);
|
||||
BUG_ON(ret);
|
||||
err = HYPERVISOR_event_channel_op(&op);
|
||||
if (err == -ENOSYS)
|
||||
goto err;
|
||||
BUG_ON(err);
|
||||
xen_start_info->store_evtchn = op.u.alloc_unbound.port;
|
||||
|
||||
/* And finally publish the above info in /proc/xen */
|
||||
@@ -1047,17 +1021,65 @@ static int __init xenbus_probe_init(void)
|
||||
if (err) {
|
||||
printk(KERN_WARNING
|
||||
"XENBUS: Error initializing xenstore comms: %i\n", err);
|
||||
return err;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Register ourselves with the kernel device subsystem */
|
||||
device_register(&xenbus_frontend.dev);
|
||||
device_register(&xenbus_backend.dev);
|
||||
|
||||
if (!dom0)
|
||||
xenbus_probe(NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (page)
|
||||
free_page(page);
|
||||
|
||||
/*
|
||||
* Do not unregister the xenbus front/backend buses here. The
|
||||
* buses must exist because front/backend drivers will use
|
||||
* them when they are registered.
|
||||
*/
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
postcore_initcall(xenbus_probe_init);
|
||||
|
||||
|
||||
/*
|
||||
* On a 10 second timeout, wait for all devices currently configured. We need
|
||||
* to do this to guarantee that the filesystems and / or network devices
|
||||
* needed for boot are available, before we can allow the boot to proceed.
|
||||
*
|
||||
* This needs to be on a late_initcall, to happen after the frontend device
|
||||
* drivers have been initialised, but before the root fs is mounted.
|
||||
*
|
||||
* A possible improvement here would be to have the tools add a per-device
|
||||
* flag to the store entry, indicating whether it is needed at boot time.
|
||||
* This would allow people who knew what they were doing to accelerate their
|
||||
* boot slightly, but of course needs tools or manual intervention to set up
|
||||
* those flags correctly.
|
||||
*/
|
||||
static int __init wait_for_devices(void)
|
||||
{
|
||||
unsigned long timeout = jiffies + 10*HZ;
|
||||
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (all_devices_ready())
|
||||
return 0;
|
||||
schedule_timeout_interruptible(HZ/10);
|
||||
}
|
||||
|
||||
printk(KERN_WARNING "XENBUS: Timeout connecting to devices!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(wait_for_devices);
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
|
||||
@@ -685,6 +685,24 @@ void xs_resume(void)
|
||||
up_write(&xs_state.suspend_mutex);
|
||||
}
|
||||
|
||||
static int xenwatch_handle_callback(void *data)
|
||||
{
|
||||
struct xs_stored_msg *msg = data;
|
||||
|
||||
msg->u.watch.handle->callback(msg->u.watch.handle,
|
||||
(const char **)msg->u.watch.vec,
|
||||
msg->u.watch.vec_size);
|
||||
|
||||
kfree(msg->u.watch.vec);
|
||||
kfree(msg);
|
||||
|
||||
/* Kill this kthread if we were spawned just for this callback. */
|
||||
if (current->pid != xenwatch_pid)
|
||||
do_exit(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xenwatch_thread(void *unused)
|
||||
{
|
||||
struct list_head *ent;
|
||||
@@ -707,12 +725,11 @@ static int xenwatch_thread(void *unused)
|
||||
|
||||
if (ent != &watch_events) {
|
||||
msg = list_entry(ent, struct xs_stored_msg, list);
|
||||
msg->u.watch.handle->callback(
|
||||
msg->u.watch.handle,
|
||||
(const char **)msg->u.watch.vec,
|
||||
msg->u.watch.vec_size);
|
||||
kfree(msg->u.watch.vec);
|
||||
kfree(msg);
|
||||
if (msg->u.watch.handle->flags & XBWF_new_thread)
|
||||
kthread_run(xenwatch_handle_callback,
|
||||
msg, "xenwatch_cb");
|
||||
else
|
||||
xenwatch_handle_callback(msg);
|
||||
}
|
||||
|
||||
mutex_unlock(&xenwatch_mutex);
|
||||
|
||||
@@ -33,10 +33,9 @@
|
||||
#ifndef __HYPERCALL_H__
|
||||
#define __HYPERCALL_H__
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/interface/nmi.h>
|
||||
#include <linux/errno.h>
|
||||
#ifndef __HYPERVISOR_H__
|
||||
# error "please don't include this file directly"
|
||||
#endif
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
@@ -167,35 +166,17 @@ HYPERVISOR_fpu_taskswitch(
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_sched_op(
|
||||
HYPERVISOR_sched_op_compat(
|
||||
int cmd, unsigned long arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
return _hypercall2(int, sched_op_compat, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_sched_op_new(
|
||||
HYPERVISOR_sched_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op_new, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_poll(
|
||||
evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
|
||||
{
|
||||
struct sched_poll sched_poll = {
|
||||
.ports = ports,
|
||||
.nr_ports = nr_ports,
|
||||
.timeout = jiffies_to_st(timeout)
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline long
|
||||
@@ -327,8 +308,18 @@ static inline int
|
||||
HYPERVISOR_suspend(
|
||||
unsigned long srec)
|
||||
{
|
||||
return _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
struct sched_shutdown sched_shutdown = {
|
||||
.reason = SHUTDOWN_suspend
|
||||
};
|
||||
|
||||
int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
&sched_shutdown, srec);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -338,6 +329,21 @@ HYPERVISOR_nmi_op(
|
||||
return _hypercall2(int, nmi_op, op, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_callback_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, callback_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_xenoprof_op(
|
||||
int op, unsigned long arg1, unsigned long arg2)
|
||||
{
|
||||
return _hypercall3(int, xenoprof_op, op, arg1, arg2);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __HYPERCALL_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -37,8 +37,11 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/errno.h>
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/dom0_ops.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/interface/nmi.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/page.h>
|
||||
#if defined(__i386__)
|
||||
@@ -115,6 +118,64 @@ u64 jiffies_to_st(unsigned long jiffies);
|
||||
|
||||
#define xen_init() (0)
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_yield(
|
||||
void)
|
||||
{
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_block(
|
||||
void)
|
||||
{
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_shutdown(
|
||||
unsigned int reason)
|
||||
{
|
||||
struct sched_shutdown sched_shutdown = {
|
||||
.reason = reason
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_poll(
|
||||
evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
|
||||
{
|
||||
struct sched_poll sched_poll = {
|
||||
.ports = ports,
|
||||
.nr_ports = nr_ports,
|
||||
.timeout = jiffies_to_st(timeout)
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void
|
||||
MULTI_update_va_mapping(
|
||||
multicall_entry_t *mcl, unsigned long va,
|
||||
|
||||
@@ -102,6 +102,7 @@ static inline void * phys_to_virt(unsigned long address)
|
||||
*/
|
||||
#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
|
||||
#define page_to_phys(page) (phys_to_machine(page_to_pseudophys(page)))
|
||||
#define page_to_bus(page) (phys_to_machine(page_to_pseudophys(page)))
|
||||
|
||||
#define bio_to_pseudophys(bio) (page_to_pseudophys(bio_page((bio))) + \
|
||||
(unsigned long) bio_offset((bio)))
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* use of all of the static functions.
|
||||
**/
|
||||
|
||||
#include <xen/interface/callback.h>
|
||||
|
||||
static char * __init machine_specific_memory_setup(void)
|
||||
{
|
||||
unsigned long max_pfn = xen_start_info->nr_pages;
|
||||
@@ -23,6 +25,14 @@ extern void nmi(void);
|
||||
static void __init machine_specific_arch_setup(void)
|
||||
{
|
||||
struct xen_platform_parameters pp;
|
||||
struct callback_register event = {
|
||||
.type = CALLBACKTYPE_event,
|
||||
.address = { __KERNEL_CS, (unsigned long)hypervisor_callback },
|
||||
};
|
||||
struct callback_register failsafe = {
|
||||
.type = CALLBACKTYPE_failsafe,
|
||||
.address = { __KERNEL_CS, (unsigned long)failsafe_callback },
|
||||
};
|
||||
struct xennmi_callback cb;
|
||||
|
||||
if (xen_feature(XENFEAT_auto_translated_physmap) &&
|
||||
@@ -32,9 +42,8 @@ static void __init machine_specific_arch_setup(void)
|
||||
memset(empty_zero_page, 0, sizeof(empty_zero_page));
|
||||
}
|
||||
|
||||
HYPERVISOR_set_callbacks(
|
||||
__KERNEL_CS, (unsigned long)hypervisor_callback,
|
||||
__KERNEL_CS, (unsigned long)failsafe_callback);
|
||||
HYPERVISOR_callback_op(CALLBACKOP_register, &event);
|
||||
HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
|
||||
|
||||
cb.handler_address = (unsigned long)&nmi;
|
||||
HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
|
||||
|
||||
@@ -33,11 +33,9 @@
|
||||
#ifndef __HYPERCALL_H__
|
||||
#define __HYPERCALL_H__
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/interface/dom0_ops.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/hypervisor.h> // for jiffies_to_st()
|
||||
#ifndef __HYPERVISOR_H__
|
||||
# error "please don't include this file directly"
|
||||
#endif
|
||||
|
||||
/* FIXME: temp place to hold these page related macros */
|
||||
#include <asm/page.h>
|
||||
@@ -165,35 +163,17 @@
|
||||
})
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_sched_op(
|
||||
HYPERVISOR_sched_op_compat(
|
||||
int cmd, unsigned long arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
return _hypercall2(int, sched_op_compat, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_sched_op_new(
|
||||
HYPERVISOR_sched_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op_new, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_poll(
|
||||
evtchn_port_t *ports, unsigned int nr_ports, unsigned long timeout)
|
||||
{
|
||||
struct sched_poll sched_poll = {
|
||||
.ports = ports,
|
||||
.nr_ports = nr_ports,
|
||||
.timeout = jiffies_to_st(timeout)
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline long
|
||||
@@ -273,8 +253,18 @@ static inline int
|
||||
HYPERVISOR_suspend(
|
||||
unsigned long srec)
|
||||
{
|
||||
return _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
struct sched_shutdown sched_shutdown = {
|
||||
.reason = SHUTDOWN_suspend
|
||||
};
|
||||
|
||||
int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
&sched_shutdown, srec);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
|
||||
|
||||
@@ -37,8 +37,10 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/errno.h>
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/dom0_ops.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/xen/privop.h> // for running_on_xen
|
||||
@@ -55,6 +57,64 @@ int xen_init(void);
|
||||
|
||||
#include <asm/hypercall.h>
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_yield(
|
||||
void)
|
||||
{
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_block(
|
||||
void)
|
||||
{
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_shutdown(
|
||||
unsigned int reason)
|
||||
{
|
||||
struct sched_shutdown sched_shutdown = {
|
||||
.reason = reason
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_poll(
|
||||
evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
|
||||
{
|
||||
struct sched_poll sched_poll = {
|
||||
.ports = ports,
|
||||
.nr_ports = nr_ports,
|
||||
.timeout = jiffies_to_st(timeout)
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// for drivers/xen/privcmd/privcmd.c
|
||||
#define direct_remap_pfn_range(a,b,c,d,e,f) remap_pfn_range(a,b,c,d,e)
|
||||
#define pfn_to_mfn(x) (x)
|
||||
|
||||
@@ -37,10 +37,9 @@
|
||||
#ifndef __HYPERCALL_H__
|
||||
#define __HYPERCALL_H__
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/interface/nmi.h>
|
||||
#include <linux/errno.h>
|
||||
#ifndef __HYPERVISOR_H__
|
||||
# error "please don't include this file directly"
|
||||
#endif
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
@@ -172,35 +171,17 @@ HYPERVISOR_fpu_taskswitch(
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_sched_op(
|
||||
HYPERVISOR_sched_op_compat(
|
||||
int cmd, unsigned long arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
return _hypercall2(int, sched_op_compat, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_sched_op_new(
|
||||
HYPERVISOR_sched_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op_new, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_poll(
|
||||
evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
|
||||
{
|
||||
struct sched_poll sched_poll = {
|
||||
.ports = ports,
|
||||
.nr_ports = nr_ports,
|
||||
.timeout = jiffies_to_st(timeout)
|
||||
};
|
||||
|
||||
int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0);
|
||||
|
||||
return rc;
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline long
|
||||
@@ -328,8 +309,18 @@ static inline int
|
||||
HYPERVISOR_suspend(
|
||||
unsigned long srec)
|
||||
{
|
||||
return _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
struct sched_shutdown sched_shutdown = {
|
||||
.reason = SHUTDOWN_suspend
|
||||
};
|
||||
|
||||
int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
&sched_shutdown, srec);
|
||||
|
||||
if (rc == -ENOSYS)
|
||||
rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -339,6 +330,20 @@ HYPERVISOR_nmi_op(
|
||||
return _hypercall2(int, nmi_op, op, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_callback_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, callback_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_xenoprof_op(
|
||||
int op, unsigned long arg1, unsigned long arg2)
|
||||
{
|
||||
return _hypercall3(int, xenoprof_op, op, arg1, arg2);
|
||||
}
|
||||
|
||||
#endif /* __HYPERCALL_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -130,6 +130,7 @@ static inline void * phys_to_virt(unsigned long address)
|
||||
*/
|
||||
#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
|
||||
#define page_to_phys(page) (phys_to_machine(page_to_pseudophys(page)))
|
||||
#define page_to_bus(page) (phys_to_machine(page_to_pseudophys(page)))
|
||||
|
||||
#define bio_to_pseudophys(bio) (page_to_pseudophys(bio_page((bio))) + \
|
||||
(unsigned long) bio_offset((bio)))
|
||||
|
||||
@@ -6,20 +6,33 @@
|
||||
* use of all of the static functions.
|
||||
**/
|
||||
|
||||
#include <xen/interface/callback.h>
|
||||
|
||||
extern void hypervisor_callback(void);
|
||||
extern void failsafe_callback(void);
|
||||
extern void nmi(void);
|
||||
|
||||
static void __init machine_specific_arch_setup(void)
|
||||
{
|
||||
struct callback_register event = {
|
||||
.type = CALLBACKTYPE_event,
|
||||
.address = (unsigned long) hypervisor_callback,
|
||||
};
|
||||
struct callback_register failsafe = {
|
||||
.type = CALLBACKTYPE_failsafe,
|
||||
.address = (unsigned long)failsafe_callback,
|
||||
};
|
||||
struct callback_register syscall = {
|
||||
.type = CALLBACKTYPE_syscall,
|
||||
.address = (unsigned long)system_call,
|
||||
};
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
struct xennmi_callback cb;
|
||||
#endif
|
||||
|
||||
HYPERVISOR_set_callbacks(
|
||||
(unsigned long) hypervisor_callback,
|
||||
(unsigned long) failsafe_callback,
|
||||
(unsigned long) system_call);
|
||||
HYPERVISOR_callback_op(CALLBACKOP_register, &event);
|
||||
HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
|
||||
HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
cb.handler_address = (unsigned long)&nmi;
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
#ifndef __irq_h
|
||||
#define __irq_h
|
||||
|
||||
/*
|
||||
* Please do not include this file in generic code. There is currently
|
||||
* no requirement for any architecture to implement anything held
|
||||
* within this file.
|
||||
*
|
||||
* Thanks. --rmk
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#if !defined(CONFIG_S390)
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
/*
|
||||
* IRQ line status.
|
||||
*/
|
||||
#define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */
|
||||
#define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */
|
||||
#define IRQ_PENDING 4 /* IRQ pending - replay on enable */
|
||||
#define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */
|
||||
#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */
|
||||
#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
|
||||
#define IRQ_LEVEL 64 /* IRQ level triggered */
|
||||
#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */
|
||||
#if defined(ARCH_HAS_IRQ_PER_CPU)
|
||||
# define IRQ_PER_CPU 256 /* IRQ is per CPU */
|
||||
# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
|
||||
#else
|
||||
# define CHECK_IRQ_PER_CPU(var) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interrupt controller descriptor. This is all we need
|
||||
* to describe about the low-level hardware.
|
||||
*/
|
||||
struct hw_interrupt_type {
|
||||
const char * typename;
|
||||
unsigned int (*startup)(unsigned int irq);
|
||||
void (*shutdown)(unsigned int irq);
|
||||
void (*enable)(unsigned int irq);
|
||||
void (*disable)(unsigned int irq);
|
||||
void (*ack)(unsigned int irq);
|
||||
void (*end)(unsigned int irq);
|
||||
void (*set_affinity)(unsigned int irq, cpumask_t dest);
|
||||
/* Currently used only by UML, might disappear one day.*/
|
||||
#ifdef CONFIG_IRQ_RELEASE_METHOD
|
||||
void (*release)(unsigned int irq, void *dev_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct hw_interrupt_type hw_irq_controller;
|
||||
|
||||
/*
|
||||
* This is the "IRQ descriptor", which contains various information
|
||||
* about the irq, including what kind of hardware handling it has,
|
||||
* whether it is disabled etc etc.
|
||||
*
|
||||
* Pad this out to 32 bytes for cache and indexing reasons.
|
||||
*/
|
||||
typedef struct irq_desc {
|
||||
hw_irq_controller *handler;
|
||||
void *handler_data;
|
||||
struct irqaction *action; /* IRQ action list */
|
||||
unsigned int status; /* IRQ status */
|
||||
unsigned int depth; /* nested irq disables */
|
||||
unsigned int irq_count; /* For detecting broken interrupts */
|
||||
unsigned int irqs_unhandled;
|
||||
spinlock_t lock;
|
||||
#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
|
||||
unsigned int move_irq; /* Flag need to re-target intr dest*/
|
||||
#endif
|
||||
} ____cacheline_aligned irq_desc_t;
|
||||
|
||||
extern irq_desc_t irq_desc [NR_IRQS];
|
||||
|
||||
/* Return a pointer to the irq descriptor for IRQ. */
|
||||
static inline irq_desc_t *
|
||||
irq_descp (int irq)
|
||||
{
|
||||
return irq_desc + irq;
|
||||
}
|
||||
|
||||
#include <asm/hw_irq.h> /* the arch dependent stuff */
|
||||
|
||||
extern int setup_irq(unsigned int irq, struct irqaction * new);
|
||||
#ifdef CONFIG_XEN
|
||||
extern int teardown_irq(unsigned int irq, struct irqaction * old);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_GENERIC_HARDIRQS
|
||||
extern cpumask_t irq_affinity[NR_IRQS];
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static inline void set_native_irq_info(int irq, cpumask_t mask)
|
||||
{
|
||||
irq_affinity[irq] = mask;
|
||||
}
|
||||
#else
|
||||
static inline void set_native_irq_info(int irq, cpumask_t mask)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
|
||||
extern cpumask_t pending_irq_cpumask[NR_IRQS];
|
||||
|
||||
static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
desc->move_irq = 1;
|
||||
pending_irq_cpumask[irq] = mask;
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
move_native_irq(int irq)
|
||||
{
|
||||
cpumask_t tmp;
|
||||
irq_desc_t *desc = irq_descp(irq);
|
||||
|
||||
if (likely (!desc->move_irq))
|
||||
return;
|
||||
|
||||
desc->move_irq = 0;
|
||||
|
||||
if (likely(cpus_empty(pending_irq_cpumask[irq])))
|
||||
return;
|
||||
|
||||
if (!desc->handler->set_affinity)
|
||||
return;
|
||||
|
||||
/* note - we hold the desc->lock */
|
||||
cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
|
||||
|
||||
/*
|
||||
* If there was a valid mask to work with, please
|
||||
* do the disable, re-program, enable sequence.
|
||||
* This is *not* particularly important for level triggered
|
||||
* but in a edge trigger case, we might be setting rte
|
||||
* when an active trigger is comming in. This could
|
||||
* cause some ioapics to mal-function.
|
||||
* Being paranoid i guess!
|
||||
*/
|
||||
if (unlikely(!cpus_empty(tmp))) {
|
||||
desc->handler->disable(irq);
|
||||
desc->handler->set_affinity(irq,tmp);
|
||||
desc->handler->enable(irq);
|
||||
}
|
||||
cpus_clear(pending_irq_cpumask[irq]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
/*
|
||||
* Wonder why these are dummies?
|
||||
* For e.g the set_ioapic_affinity_vector() calls the set_ioapic_affinity_irq()
|
||||
* counter part after translating the vector to irq info. We need to perform
|
||||
* this operation on the real irq, when we dont use vector, i.e when
|
||||
* pci_use_vector() is false.
|
||||
*/
|
||||
static inline void move_irq(int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void set_irq_info(int irq, cpumask_t mask)
|
||||
{
|
||||
}
|
||||
|
||||
#else // CONFIG_PCI_MSI
|
||||
|
||||
static inline void move_irq(int irq)
|
||||
{
|
||||
move_native_irq(irq);
|
||||
}
|
||||
|
||||
static inline void set_irq_info(int irq, cpumask_t mask)
|
||||
{
|
||||
set_native_irq_info(irq, mask);
|
||||
}
|
||||
#endif // CONFIG_PCI_MSI
|
||||
|
||||
#else // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE
|
||||
|
||||
#define move_irq(x)
|
||||
#define move_native_irq(x)
|
||||
#define set_pending_irq(x,y)
|
||||
static inline void set_irq_info(int irq, cpumask_t mask)
|
||||
{
|
||||
set_native_irq_info(irq, mask);
|
||||
}
|
||||
|
||||
#endif // CONFIG_GENERIC_PENDING_IRQ
|
||||
|
||||
#else // CONFIG_SMP
|
||||
|
||||
#define move_irq(x)
|
||||
#define move_native_irq(x)
|
||||
|
||||
#endif // CONFIG_SMP
|
||||
|
||||
extern int no_irq_affinity;
|
||||
extern int noirqdebug_setup(char *str);
|
||||
|
||||
extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
|
||||
struct irqaction *action);
|
||||
extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
|
||||
extern void note_interrupt(unsigned int irq, irq_desc_t *desc,
|
||||
int action_ret, struct pt_regs *regs);
|
||||
extern int can_request_irq(unsigned int irq, unsigned long irqflags);
|
||||
|
||||
extern void init_irq_proc(void);
|
||||
|
||||
#ifdef CONFIG_AUTO_IRQ_AFFINITY
|
||||
extern int select_smp_affinity(unsigned int irq);
|
||||
#else
|
||||
static inline int
|
||||
select_smp_affinity(unsigned int irq)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
extern hw_irq_controller no_irq_type; /* needed in every arch ? */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __irq_h */
|
||||
@@ -189,7 +189,7 @@ enum {
|
||||
* @local_df: allow local fragmentation
|
||||
* @cloned: Head may be cloned (check refcnt to be sure)
|
||||
* @nohdr: Payload reference only, must not modify header
|
||||
* @proto_csum_valid: Protocol csum validated since arriving at localhost
|
||||
* @proto_data_valid: Protocol data validated since arriving at localhost
|
||||
* @proto_csum_blank: Protocol csum must be added before leaving localhost
|
||||
* @pkt_type: Packet class
|
||||
* @fclone: skbuff clone status
|
||||
@@ -271,7 +271,7 @@ struct sk_buff {
|
||||
ipvs_property:1;
|
||||
#else
|
||||
ipvs_property:1,
|
||||
proto_csum_valid:1,
|
||||
proto_data_valid:1,
|
||||
proto_csum_blank:1;
|
||||
#endif
|
||||
__be16 protocol;
|
||||
|
||||
@@ -110,6 +110,9 @@ void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
|
||||
#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
|
||||
#endif
|
||||
|
||||
int gnttab_suspend(void);
|
||||
int gnttab_resume(void);
|
||||
|
||||
#endif /* __ASM_GNTTAB_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -55,8 +55,17 @@ struct xenbus_watch
|
||||
/* Callback (executed in a process context with no locks held). */
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char **vec, unsigned int len);
|
||||
|
||||
/* See XBWF_ definitions below. */
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Execute callback in its own kthread. Useful if the callback is long
|
||||
* running or heavily serialised, to avoid taking out the main xenwatch thread
|
||||
* for a long period of time (or even unwittingly causing a deadlock).
|
||||
*/
|
||||
#define XBWF_new_thread 1
|
||||
|
||||
/* A xenbus device. */
|
||||
struct xenbus_device {
|
||||
@@ -195,14 +204,10 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
|
||||
|
||||
/**
|
||||
* Advertise in the store a change of the given driver to the given new_state.
|
||||
* Perform the change inside the given transaction xbt. xbt may be NULL, in
|
||||
* which case this is performed inside its own transaction. Return 0 on
|
||||
* success, or -errno on error. On error, the device will switch to
|
||||
* XenbusStateClosing, and the error will be saved in the store.
|
||||
* Return 0 on success, or -errno on error. On error, the device will switch
|
||||
* to XenbusStateClosing, and the error will be saved in the store.
|
||||
*/
|
||||
int xenbus_switch_state(struct xenbus_device *dev,
|
||||
xenbus_transaction_t xbt,
|
||||
XenbusState new_state);
|
||||
int xenbus_switch_state(struct xenbus_device *dev, XenbusState new_state);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
/*
|
||||
* linux/kernel/irq/manage.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
|
||||
*
|
||||
* This file contains driver APIs to the irq subsystem.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
|
||||
|
||||
#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
|
||||
cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
|
||||
* @irq: interrupt number to wait for
|
||||
*
|
||||
* This function waits for any pending IRQ handlers for this interrupt
|
||||
* to complete before returning. If you use this function while
|
||||
* holding a resource the IRQ handler may need you will deadlock.
|
||||
*
|
||||
* This function may be called - with care - from IRQ context.
|
||||
*/
|
||||
void synchronize_irq(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return;
|
||||
|
||||
while (desc->status & IRQ_INPROGRESS)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(synchronize_irq);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* disable_irq_nosync - disable an irq without waiting
|
||||
* @irq: Interrupt to disable
|
||||
*
|
||||
* Disable the selected interrupt line. Disables and Enables are
|
||||
* nested.
|
||||
* Unlike disable_irq(), this function does not ensure existing
|
||||
* instances of the IRQ handler have completed before returning.
|
||||
*
|
||||
* This function may be called from IRQ context.
|
||||
*/
|
||||
void disable_irq_nosync(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
if (!desc->depth++) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->handler->disable(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(disable_irq_nosync);
|
||||
|
||||
/**
|
||||
* disable_irq - disable an irq and wait for completion
|
||||
* @irq: Interrupt to disable
|
||||
*
|
||||
* Disable the selected interrupt line. Enables and Disables are
|
||||
* nested.
|
||||
* This function waits for any pending IRQ handlers for this interrupt
|
||||
* to complete before returning. If you use this function while
|
||||
* holding a resource the IRQ handler may need you will deadlock.
|
||||
*
|
||||
* This function may be called - with care - from IRQ context.
|
||||
*/
|
||||
void disable_irq(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return;
|
||||
|
||||
disable_irq_nosync(irq);
|
||||
if (desc->action)
|
||||
synchronize_irq(irq);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(disable_irq);
|
||||
|
||||
/**
|
||||
* enable_irq - enable handling of an irq
|
||||
* @irq: Interrupt to enable
|
||||
*
|
||||
* Undoes the effect of one call to disable_irq(). If this
|
||||
* matches the last disable, processing of interrupts on this
|
||||
* IRQ line is re-enabled.
|
||||
*
|
||||
* This function may be called from IRQ context.
|
||||
*/
|
||||
void enable_irq(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
switch (desc->depth) {
|
||||
case 0:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case 1: {
|
||||
unsigned int status = desc->status & ~IRQ_DISABLED;
|
||||
|
||||
desc->status = status;
|
||||
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
|
||||
desc->status = status | IRQ_REPLAY;
|
||||
hw_resend_irq(desc->handler,irq);
|
||||
}
|
||||
desc->handler->enable(irq);
|
||||
/* fall-through */
|
||||
}
|
||||
default:
|
||||
desc->depth--;
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(enable_irq);
|
||||
|
||||
/*
|
||||
* Internal function that tells the architecture code whether a
|
||||
* particular irq has been exclusively allocated or is available
|
||||
* for driver use.
|
||||
*/
|
||||
int can_request_irq(unsigned int irq, unsigned long irqflags)
|
||||
{
|
||||
struct irqaction *action;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return 0;
|
||||
|
||||
action = irq_desc[irq].action;
|
||||
if (action)
|
||||
if (irqflags & action->flags & SA_SHIRQ)
|
||||
action = NULL;
|
||||
|
||||
return !action;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_irq - register an irqaction structure
|
||||
* @irq: Interrupt to register
|
||||
* @irqaction: The irqaction structure to be registered
|
||||
*
|
||||
* Normally called by request_irq, this function can be used
|
||||
* directly to allocate special interrupts that are part of the
|
||||
* architecture.
|
||||
*/
|
||||
int setup_irq(unsigned int irq, struct irqaction * new)
|
||||
{
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
struct irqaction *old, **p;
|
||||
unsigned long flags;
|
||||
int shared = 0;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->handler == &no_irq_type)
|
||||
return -ENOSYS;
|
||||
/*
|
||||
* Some drivers like serial.c use request_irq() heavily,
|
||||
* so we have to be careful not to interfere with a
|
||||
* running system.
|
||||
*/
|
||||
if (new->flags & SA_SAMPLE_RANDOM) {
|
||||
/*
|
||||
* This function might sleep, we want to call it first,
|
||||
* outside of the atomic block.
|
||||
* Yes, this might clear the entropy pool if the wrong
|
||||
* driver is attempted to be loaded, without actually
|
||||
* installing a new handler, but is this really a problem,
|
||||
* only the sysadmin is able to do this.
|
||||
*/
|
||||
rand_initialize_irq(irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following block of code has to be executed atomically
|
||||
*/
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
p = &desc->action;
|
||||
if ((old = *p) != NULL) {
|
||||
/* Can't share interrupts unless both agree to */
|
||||
if (!(old->flags & new->flags & SA_SHIRQ)) {
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* add new interrupt at end of irq queue */
|
||||
do {
|
||||
p = &old->next;
|
||||
old = *p;
|
||||
} while (old);
|
||||
shared = 1;
|
||||
}
|
||||
|
||||
*p = new;
|
||||
|
||||
if (!shared) {
|
||||
desc->depth = 0;
|
||||
desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT |
|
||||
IRQ_WAITING | IRQ_INPROGRESS);
|
||||
if (desc->handler->startup)
|
||||
desc->handler->startup(irq);
|
||||
else
|
||||
desc->handler->enable(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
|
||||
new->irq = irq;
|
||||
register_irq_proc(irq);
|
||||
new->dir = NULL;
|
||||
register_handler_proc(irq, new);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* teardown_irq - unregister an irqaction
|
||||
* @irq: Interrupt line being freed
|
||||
* @old: Pointer to the irqaction that is to be unregistered
|
||||
*
|
||||
* This function is called by free_irq and does the actual
|
||||
* business of unregistering the handler. It exists as a
|
||||
* seperate function to enable handlers to be unregistered
|
||||
* for irqactions that have been allocated statically at
|
||||
* boot time.
|
||||
*
|
||||
* This function must not be called from interrupt context.
|
||||
*/
|
||||
#ifndef CONFIG_XEN
|
||||
static
|
||||
#endif
|
||||
int teardown_irq(unsigned int irq, struct irqaction * old)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
struct irqaction **p;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return -ENOENT;
|
||||
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
p = &desc->action;
|
||||
for (;;) {
|
||||
struct irqaction * action = *p;
|
||||
|
||||
if (action) {
|
||||
struct irqaction **pp = p;
|
||||
|
||||
p = &action->next;
|
||||
if (action != old)
|
||||
continue;
|
||||
|
||||
/* Found it - now remove it from the list of entries */
|
||||
*pp = action->next;
|
||||
|
||||
/* Currently used only by UML, might disappear one day.*/
|
||||
#ifdef CONFIG_IRQ_RELEASE_METHOD
|
||||
if (desc->handler->release)
|
||||
desc->handler->release(irq, dev_id);
|
||||
#endif
|
||||
|
||||
if (!desc->action) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
if (desc->handler->shutdown)
|
||||
desc->handler->shutdown(irq);
|
||||
else
|
||||
desc->handler->disable(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
unregister_handler_proc(irq, action);
|
||||
|
||||
/* Make sure it's not being used on another CPU */
|
||||
synchronize_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_ERR "Trying to teardown free IRQ%d\n",irq);
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* free_irq - free an interrupt
|
||||
* @irq: Interrupt line to free
|
||||
* @dev_id: Device identity to free
|
||||
*
|
||||
* Remove an interrupt handler. The handler is removed and if the
|
||||
* interrupt line is no longer in use by any driver it is disabled.
|
||||
* On a shared IRQ the caller must ensure the interrupt is disabled
|
||||
* on the card it drives before calling this function. The function
|
||||
* does not return until any executing interrupts for this IRQ
|
||||
* have completed.
|
||||
*
|
||||
* This function must not be called from interrupt context.
|
||||
*/
|
||||
void free_irq(unsigned int irq, void *dev_id)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
struct irqaction *action;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return;
|
||||
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
for (action = desc->action; action != NULL; action = action->next) {
|
||||
if (action->dev_id != dev_id)
|
||||
continue;
|
||||
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
|
||||
if (teardown_irq(irq, action) == 0)
|
||||
kfree(action);
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(free_irq);
|
||||
|
||||
/**
|
||||
* request_irq - allocate an interrupt line
|
||||
* @irq: Interrupt line to allocate
|
||||
* @handler: Function to be called when the IRQ occurs
|
||||
* @irqflags: Interrupt type flags
|
||||
* @devname: An ascii name for the claiming device
|
||||
* @dev_id: A cookie passed back to the handler function
|
||||
*
|
||||
* This call allocates interrupt resources and enables the
|
||||
* interrupt line and IRQ handling. From the point this
|
||||
* call is made your handler function may be invoked. Since
|
||||
* your handler function must clear any interrupt the board
|
||||
* raises, you must take care both to initialise your hardware
|
||||
* and to set up the interrupt handler in the right order.
|
||||
*
|
||||
* Dev_id must be globally unique. Normally the address of the
|
||||
* device data structure is used as the cookie. Since the handler
|
||||
* receives this value it makes sense to use it.
|
||||
*
|
||||
* If your interrupt is shared you must pass a non NULL dev_id
|
||||
* as this is required when freeing the interrupt.
|
||||
*
|
||||
* Flags:
|
||||
*
|
||||
* SA_SHIRQ Interrupt is shared
|
||||
* SA_INTERRUPT Disable local interrupts while processing
|
||||
* SA_SAMPLE_RANDOM The interrupt can be used for entropy
|
||||
*
|
||||
*/
|
||||
int request_irq(unsigned int irq,
|
||||
irqreturn_t (*handler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags, const char * devname, void *dev_id)
|
||||
{
|
||||
struct irqaction * action;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Sanity-check: shared interrupts must pass in a real dev-ID,
|
||||
* otherwise we'll have trouble later trying to figure out
|
||||
* which interrupt is which (messes up the interrupt freeing
|
||||
* logic etc).
|
||||
*/
|
||||
if ((irqflags & SA_SHIRQ) && !dev_id)
|
||||
return -EINVAL;
|
||||
if (irq >= NR_IRQS)
|
||||
return -EINVAL;
|
||||
if (!handler)
|
||||
return -EINVAL;
|
||||
|
||||
action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
|
||||
if (!action)
|
||||
return -ENOMEM;
|
||||
|
||||
action->handler = handler;
|
||||
action->flags = irqflags;
|
||||
cpus_clear(action->mask);
|
||||
action->name = devname;
|
||||
action->next = NULL;
|
||||
action->dev_id = dev_id;
|
||||
|
||||
select_smp_affinity(irq);
|
||||
|
||||
retval = setup_irq(irq, action);
|
||||
if (retval)
|
||||
kfree(action);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(request_irq);
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
|
||||
config PRINTK_TIME
|
||||
bool "Show timing information on printks"
|
||||
help
|
||||
Selecting this option causes timing information to be
|
||||
included in printk output. This allows you to measure
|
||||
the interval between kernel operations, including bootup
|
||||
operations. This is useful for identifying long delays
|
||||
in kernel startup.
|
||||
|
||||
|
||||
config MAGIC_SYSRQ
|
||||
bool "Magic SysRq key"
|
||||
depends on !UML
|
||||
help
|
||||
If you say Y here, you will have some control over the system even
|
||||
if the system crashes for example during kernel debugging (e.g., you
|
||||
will be able to flush the buffer cache to disk, reboot the system
|
||||
immediately or dump some status information). This is accomplished
|
||||
by pressing various keys while holding SysRq (Alt+PrintScreen). It
|
||||
also works on a serial console (on PC hardware at least), if you
|
||||
send a BREAK and then within 5 seconds a command keypress. The
|
||||
keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
|
||||
unless you really know what this hack does.
|
||||
|
||||
config DEBUG_KERNEL
|
||||
bool "Kernel debugging"
|
||||
help
|
||||
Say Y here if you are developing drivers or trying to debug and
|
||||
identify kernel problems.
|
||||
|
||||
config LOG_BUF_SHIFT
|
||||
int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
|
||||
range 12 21
|
||||
default 17 if S390
|
||||
default 16 if X86_NUMAQ || IA64
|
||||
default 15 if SMP
|
||||
default 14
|
||||
help
|
||||
Select kernel log buffer size as a power of 2.
|
||||
Defaults and Examples:
|
||||
17 => 128 KB for S/390
|
||||
16 => 64 KB for x86 NUMAQ or IA-64
|
||||
15 => 32 KB for SMP
|
||||
14 => 16 KB for uniprocessor
|
||||
13 => 8 KB
|
||||
12 => 4 KB
|
||||
|
||||
config DETECT_SOFTLOCKUP
|
||||
bool "Detect Soft Lockups"
|
||||
depends on DEBUG_KERNEL
|
||||
default y
|
||||
help
|
||||
Say Y here to enable the kernel to detect "soft lockups",
|
||||
which are bugs that cause the kernel to loop in kernel
|
||||
mode for more than 10 seconds, without giving other tasks a
|
||||
chance to run.
|
||||
|
||||
When a soft-lockup is detected, the kernel will print the
|
||||
current stack trace (which you should report), but the
|
||||
system will stay locked up. This feature has negligible
|
||||
overhead.
|
||||
|
||||
(Note that "hard lockups" are separate type of bugs that
|
||||
can be detected via the NMI-watchdog, on platforms that
|
||||
support it.)
|
||||
|
||||
config SCHEDSTATS
|
||||
bool "Collect scheduler statistics"
|
||||
depends on DEBUG_KERNEL && PROC_FS
|
||||
help
|
||||
If you say Y here, additional code will be inserted into the
|
||||
scheduler and related routines to collect statistics about
|
||||
scheduler behavior and provide them in /proc/schedstat. These
|
||||
stats may be useful for both tuning and debugging the scheduler
|
||||
If you aren't debugging the scheduler or trying to tune a specific
|
||||
application, you can say N to avoid the very slight overhead
|
||||
this adds.
|
||||
|
||||
config DEBUG_SLAB
|
||||
bool "Debug memory allocations"
|
||||
depends on DEBUG_KERNEL && SLAB
|
||||
help
|
||||
Say Y here to have the kernel do limited verification on memory
|
||||
allocation as well as poisoning memory on free to catch use of freed
|
||||
memory. This can make kmalloc/kfree-intensive workloads much slower.
|
||||
|
||||
config DEBUG_PREEMPT
|
||||
bool "Debug preemptible kernel"
|
||||
depends on DEBUG_KERNEL && PREEMPT
|
||||
default y
|
||||
help
|
||||
If you say Y here then the kernel will use a debug variant of the
|
||||
commonly used smp_processor_id() function and will print warnings
|
||||
if kernel code uses it in a preemption-unsafe way. Also, the kernel
|
||||
will detect preemption count underflows.
|
||||
|
||||
config DEBUG_MUTEXES
|
||||
bool "Mutex debugging, deadlock detection"
|
||||
default y
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
This allows mutex semantics violations and mutex related deadlocks
|
||||
(lockups) to be detected and reported automatically.
|
||||
|
||||
config DEBUG_SPINLOCK
|
||||
bool "Spinlock debugging"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
Say Y here and build SMP to catch missing spinlock initialization
|
||||
and certain other kinds of spinlock errors commonly made. This is
|
||||
best used in conjunction with the NMI watchdog so that spinlock
|
||||
deadlocks are also debuggable.
|
||||
|
||||
config DEBUG_SPINLOCK_SLEEP
|
||||
bool "Sleep-inside-spinlock checking"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
If you say Y here, various routines which may sleep will become very
|
||||
noisy if they are called with a spinlock held.
|
||||
|
||||
config DEBUG_KOBJECT
|
||||
bool "kobject debugging"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
If you say Y here, some extra kobject debugging messages will be sent
|
||||
to the syslog.
|
||||
|
||||
config DEBUG_HIGHMEM
|
||||
bool "Highmem debugging"
|
||||
depends on DEBUG_KERNEL && HIGHMEM
|
||||
help
|
||||
This options enables addition error checking for high memory systems.
|
||||
Disable for production systems.
|
||||
|
||||
config DEBUG_BUGVERBOSE
|
||||
bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
|
||||
depends on BUG
|
||||
depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV
|
||||
default !EMBEDDED
|
||||
help
|
||||
Say Y here to make BUG() panics output the file name and line number
|
||||
of the BUG call as well as the EIP and oops trace. This aids
|
||||
debugging but costs about 70-100K of memory.
|
||||
|
||||
config DEBUG_INFO
|
||||
bool "Compile the kernel with debug info"
|
||||
depends on DEBUG_KERNEL && !X86_64_XEN
|
||||
help
|
||||
If you say Y here the resulting kernel image will include
|
||||
debugging info resulting in a larger kernel image.
|
||||
Say Y here only if you plan to debug the kernel.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config DEBUG_IOREMAP
|
||||
bool "Enable ioremap() debugging"
|
||||
depends on DEBUG_KERNEL && PARISC
|
||||
help
|
||||
Enabling this option will cause the kernel to distinguish between
|
||||
ioremapped and physical addresses. It will print a backtrace (at
|
||||
most one every 10 seconds), hopefully allowing you to see which
|
||||
drivers need work. Fixing all these problems is a prerequisite
|
||||
for turning on USE_HPPA_IOREMAP. The warnings are harmless;
|
||||
the kernel has enough information to fix the broken drivers
|
||||
automatically, but we'd like to make it more efficient by not
|
||||
having to do that.
|
||||
|
||||
config DEBUG_FS
|
||||
bool "Debug Filesystem"
|
||||
depends on DEBUG_KERNEL && SYSFS
|
||||
help
|
||||
debugfs is a virtual file system that kernel developers use to put
|
||||
debugging files into. Enable this option to be able to read and
|
||||
write to these files.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config DEBUG_VM
|
||||
bool "Debug VM"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
Enable this to turn on extended checks in the virtual-memory system
|
||||
that may impact performance.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config FRAME_POINTER
|
||||
bool "Compile the kernel with frame pointers"
|
||||
depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
|
||||
default y if DEBUG_INFO && UML
|
||||
help
|
||||
If you say Y here the resulting kernel image will be slightly larger
|
||||
and slower, but it might give very useful debugging information on
|
||||
some architectures or if you use external debuggers.
|
||||
If you don't debug the kernel, you can say N.
|
||||
|
||||
config FORCED_INLINING
|
||||
bool "Force gcc to inline functions marked 'inline'"
|
||||
depends on DEBUG_KERNEL
|
||||
default y
|
||||
help
|
||||
This option determines if the kernel forces gcc to inline the functions
|
||||
developers have marked 'inline'. Doing so takes away freedom from gcc to
|
||||
do what it thinks is best, which is desirable for the gcc 3.x series of
|
||||
compilers. The gcc 4.x series have a rewritten inlining algorithm and
|
||||
disabling this option will generate a smaller kernel there. Hopefully
|
||||
this algorithm is so good that allowing gcc4 to make the decision can
|
||||
become the default in the future, until then this option is there to
|
||||
test gcc for this.
|
||||
|
||||
config RCU_TORTURE_TEST
|
||||
tristate "torture tests for RCU"
|
||||
depends on DEBUG_KERNEL
|
||||
default n
|
||||
help
|
||||
This option provides a kernel module that runs torture tests
|
||||
on the RCU infrastructure. The kernel module may be built
|
||||
after the fact on the running kernel to be tested, if desired.
|
||||
|
||||
Say Y here if you want RCU torture tests to start automatically
|
||||
at boot time (you probably don't).
|
||||
Say M if you want the RCU torture tests to build as a module.
|
||||
Say N if you are unsure.
|
||||
@@ -1649,12 +1649,12 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||
#ifdef CONFIG_XEN
|
||||
switch (skb->ip_summed) {
|
||||
case CHECKSUM_UNNECESSARY:
|
||||
skb->proto_csum_valid = 1;
|
||||
skb->proto_data_valid = 1;
|
||||
break;
|
||||
case CHECKSUM_HW:
|
||||
/* XXX Implement me. */
|
||||
default:
|
||||
skb->proto_csum_valid = 0;
|
||||
skb->proto_data_valid = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -428,7 +428,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
|
||||
n->cloned = 1;
|
||||
n->nohdr = 0;
|
||||
#ifdef CONFIG_XEN
|
||||
C(proto_csum_valid);
|
||||
C(proto_data_valid);
|
||||
C(proto_csum_blank);
|
||||
#endif
|
||||
C(pkt_type);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
Subject: Increase x86 interrupt vector range
|
||||
|
||||
Remove the limit of 256 interrupt vectors by changing the value
|
||||
stored in orig_{e,r}ax to be the negated interrupt vector.
|
||||
The orig_{e,r}ax needs to be < 0 to allow the signal code to
|
||||
distinguish between return from interrupt and return from syscall.
|
||||
With this change applied, NR_IRQS can be > 256.
|
||||
|
||||
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
|
||||
---
|
||||
arch/i386/kernel/entry.S | 4 ++--
|
||||
arch/i386/kernel/irq.c | 4 ++--
|
||||
arch/x86_64/kernel/entry.S | 2 +-
|
||||
arch/x86_64/kernel/irq.c | 4 ++--
|
||||
arch/x86_64/kernel/smp.c | 4 ++--
|
||||
include/asm-x86_64/hw_irq.h | 2 +-
|
||||
6 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff -r 7d239c83edea arch/i386/kernel/entry.S
|
||||
--- a/arch/i386/kernel/entry.S Mon Mar 20 06:00:20 2006 +0000
|
||||
+++ b/arch/i386/kernel/entry.S Fri Mar 31 17:01:35 2006 +0100
|
||||
@@ -406,7 +406,7 @@ ENTRY(irq_entries_start)
|
||||
ENTRY(irq_entries_start)
|
||||
.rept NR_IRQS
|
||||
ALIGN
|
||||
-1: pushl $vector-256
|
||||
+1: pushl $~(vector)
|
||||
jmp common_interrupt
|
||||
.data
|
||||
.long 1b
|
||||
@@ -423,7 +423,7 @@ common_interrupt:
|
||||
|
||||
#define BUILD_INTERRUPT(name, nr) \
|
||||
ENTRY(name) \
|
||||
- pushl $nr-256; \
|
||||
+ pushl $~(nr); \
|
||||
SAVE_ALL \
|
||||
movl %esp,%eax; \
|
||||
call smp_/**/name; \
|
||||
diff -r 7d239c83edea arch/i386/kernel/irq.c
|
||||
--- a/arch/i386/kernel/irq.c Mon Mar 20 06:00:20 2006 +0000
|
||||
+++ b/arch/i386/kernel/irq.c Fri Mar 31 17:01:35 2006 +0100
|
||||
@@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPU
|
||||
*/
|
||||
fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
- /* high bits used in ret_from_ code */
|
||||
- int irq = regs->orig_eax & 0xff;
|
||||
+ /* high bit used in ret_from_ code */
|
||||
+ int irq = ~regs->orig_eax;
|
||||
#ifdef CONFIG_4KSTACKS
|
||||
union irq_ctx *curctx, *irqctx;
|
||||
u32 *isp;
|
||||
diff -r 7d239c83edea arch/x86_64/kernel/entry.S
|
||||
--- a/arch/x86_64/kernel/entry.S Mon Mar 20 06:00:20 2006 +0000
|
||||
+++ b/arch/x86_64/kernel/entry.S Fri Mar 31 17:01:35 2006 +0100
|
||||
@@ -609,7 +609,7 @@ retint_kernel:
|
||||
*/
|
||||
.macro apicinterrupt num,func
|
||||
INTR_FRAME
|
||||
- pushq $\num-256
|
||||
+ pushq $~(\num)
|
||||
CFI_ADJUST_CFA_OFFSET 8
|
||||
interrupt \func
|
||||
jmp ret_from_intr
|
||||
diff -r 7d239c83edea arch/x86_64/kernel/irq.c
|
||||
--- a/arch/x86_64/kernel/irq.c Mon Mar 20 06:00:20 2006 +0000
|
||||
+++ b/arch/x86_64/kernel/irq.c Fri Mar 31 17:01:35 2006 +0100
|
||||
@@ -96,8 +96,8 @@ skip:
|
||||
*/
|
||||
asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
- /* high bits used in ret_from_ code */
|
||||
- unsigned irq = regs->orig_rax & 0xff;
|
||||
+ /* high bit used in ret_from_ code */
|
||||
+ unsigned irq = ~regs->orig_rax;
|
||||
|
||||
exit_idle();
|
||||
irq_enter();
|
||||
diff -r 7d239c83edea arch/x86_64/kernel/smp.c
|
||||
--- a/arch/x86_64/kernel/smp.c Mon Mar 20 06:00:20 2006 +0000
|
||||
+++ b/arch/x86_64/kernel/smp.c Fri Mar 31 17:01:35 2006 +0100
|
||||
@@ -135,10 +135,10 @@ asmlinkage void smp_invalidate_interrupt
|
||||
|
||||
cpu = smp_processor_id();
|
||||
/*
|
||||
- * orig_rax contains the interrupt vector - 256.
|
||||
+ * orig_rax contains the negated interrupt vector.
|
||||
* Use that to determine where the sender put the data.
|
||||
*/
|
||||
- sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
|
||||
+ sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START;
|
||||
f = &per_cpu(flush_state, sender);
|
||||
|
||||
if (!cpu_isset(cpu, f->flush_cpumask))
|
||||
diff -r 7d239c83edea include/asm-x86_64/hw_irq.h
|
||||
--- a/include/asm-x86_64/hw_irq.h Mon Mar 20 06:00:20 2006 +0000
|
||||
+++ b/include/asm-x86_64/hw_irq.h Fri Mar 31 17:01:35 2006 +0100
|
||||
@@ -127,7 +127,7 @@ __asm__( \
|
||||
__asm__( \
|
||||
"\n.p2align\n" \
|
||||
"IRQ" #nr "_interrupt:\n\t" \
|
||||
- "push $" #nr "-256 ; " \
|
||||
+ "push $~(" #nr ") ; " \
|
||||
"jmp common_interrupt");
|
||||
|
||||
#if defined(CONFIG_X86_IO_APIC)
|
||||
@@ -0,0 +1,384 @@
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/buffer_sync.c ./drivers/oprofile/buffer_sync.c
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/buffer_sync.c 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/buffer_sync.c 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -6,6 +6,10 @@
|
||||
*
|
||||
* @author John Levon <levon@movementarian.org>
|
||||
*
|
||||
+ * Modified by Aravind Menon for Xen
|
||||
+ * These modifications are:
|
||||
+ * Copyright (C) 2005 Hewlett-Packard Co.
|
||||
+ *
|
||||
* This is the core of the buffer management. Each
|
||||
* CPU buffer is processed and entered into the
|
||||
* global event buffer. Such processing is necessary
|
||||
@@ -275,15 +279,24 @@ static void add_cpu_switch(int i)
|
||||
last_cookie = INVALID_COOKIE;
|
||||
}
|
||||
|
||||
-static void add_kernel_ctx_switch(unsigned int in_kernel)
|
||||
+static void add_cpu_mode_switch(unsigned int cpu_mode)
|
||||
{
|
||||
add_event_entry(ESCAPE_CODE);
|
||||
- if (in_kernel)
|
||||
- add_event_entry(KERNEL_ENTER_SWITCH_CODE);
|
||||
- else
|
||||
- add_event_entry(KERNEL_EXIT_SWITCH_CODE);
|
||||
+ switch (cpu_mode) {
|
||||
+ case CPU_MODE_USER:
|
||||
+ add_event_entry(USER_ENTER_SWITCH_CODE);
|
||||
+ break;
|
||||
+ case CPU_MODE_KERNEL:
|
||||
+ add_event_entry(KERNEL_ENTER_SWITCH_CODE);
|
||||
+ break;
|
||||
+ case CPU_MODE_XEN:
|
||||
+ add_event_entry(XEN_ENTER_SWITCH_CODE);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
-
|
||||
+
|
||||
static void
|
||||
add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
|
||||
{
|
||||
@@ -348,9 +361,9 @@ static int add_us_sample(struct mm_struc
|
||||
* for later lookup from userspace.
|
||||
*/
|
||||
static int
|
||||
-add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
|
||||
+add_sample(struct mm_struct * mm, struct op_sample * s, int cpu_mode)
|
||||
{
|
||||
- if (in_kernel) {
|
||||
+ if (cpu_mode >= CPU_MODE_KERNEL) {
|
||||
add_sample_entry(s->eip, s->event);
|
||||
return 1;
|
||||
} else if (mm) {
|
||||
@@ -496,7 +509,7 @@ void sync_buffer(int cpu)
|
||||
struct mm_struct *mm = NULL;
|
||||
struct task_struct * new;
|
||||
unsigned long cookie = 0;
|
||||
- int in_kernel = 1;
|
||||
+ int cpu_mode = 1;
|
||||
unsigned int i;
|
||||
sync_buffer_state state = sb_buffer_start;
|
||||
unsigned long available;
|
||||
@@ -513,12 +526,12 @@ void sync_buffer(int cpu)
|
||||
struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
|
||||
|
||||
if (is_code(s->eip)) {
|
||||
- if (s->event <= CPU_IS_KERNEL) {
|
||||
+ if (s->event <= CPU_MODE_XEN) {
|
||||
/* kernel/userspace switch */
|
||||
- in_kernel = s->event;
|
||||
+ cpu_mode = s->event;
|
||||
if (state == sb_buffer_start)
|
||||
state = sb_sample_start;
|
||||
- add_kernel_ctx_switch(s->event);
|
||||
+ add_cpu_mode_switch(s->event);
|
||||
} else if (s->event == CPU_TRACE_BEGIN) {
|
||||
state = sb_bt_start;
|
||||
add_trace_begin();
|
||||
@@ -536,7 +549,7 @@ void sync_buffer(int cpu)
|
||||
}
|
||||
} else {
|
||||
if (state >= sb_bt_start &&
|
||||
- !add_sample(mm, s, in_kernel)) {
|
||||
+ !add_sample(mm, s, cpu_mode)) {
|
||||
if (state == sb_bt_start) {
|
||||
state = sb_bt_ignore;
|
||||
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.c 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/cpu_buffer.c 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -6,6 +6,10 @@
|
||||
*
|
||||
* @author John Levon <levon@movementarian.org>
|
||||
*
|
||||
+ * Modified by Aravind Menon for Xen
|
||||
+ * These modifications are:
|
||||
+ * Copyright (C) 2005 Hewlett-Packard Co.
|
||||
+ *
|
||||
* Each CPU has a local buffer that stores PC value/event
|
||||
* pairs. We also log context switches when we notice them.
|
||||
* Eventually each CPU's buffer is processed into the global
|
||||
@@ -58,7 +62,7 @@ int alloc_cpu_buffers(void)
|
||||
goto fail;
|
||||
|
||||
b->last_task = NULL;
|
||||
- b->last_is_kernel = -1;
|
||||
+ b->last_cpu_mode = -1;
|
||||
b->tracing = 0;
|
||||
b->buffer_size = buffer_size;
|
||||
b->tail_pos = 0;
|
||||
@@ -114,7 +118,7 @@ void cpu_buffer_reset(struct oprofile_cp
|
||||
* collected will populate the buffer with proper
|
||||
* values to initialize the buffer
|
||||
*/
|
||||
- cpu_buf->last_is_kernel = -1;
|
||||
+ cpu_buf->last_cpu_mode = -1;
|
||||
cpu_buf->last_task = NULL;
|
||||
}
|
||||
|
||||
@@ -164,13 +168,13 @@ add_code(struct oprofile_cpu_buffer * bu
|
||||
* because of the head/tail separation of the writer and reader
|
||||
* of the CPU buffer.
|
||||
*
|
||||
- * is_kernel is needed because on some architectures you cannot
|
||||
+ * cpu_mode is needed because on some architectures you cannot
|
||||
* tell if you are in kernel or user space simply by looking at
|
||||
- * pc. We tag this in the buffer by generating kernel enter/exit
|
||||
- * events whenever is_kernel changes
|
||||
+ * pc. We tag this in the buffer by generating kernel/user (and xen)
|
||||
+ * enter events whenever cpu_mode changes
|
||||
*/
|
||||
static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
|
||||
- int is_kernel, unsigned long event)
|
||||
+ int cpu_mode, unsigned long event)
|
||||
{
|
||||
struct task_struct * task;
|
||||
|
||||
@@ -181,16 +185,16 @@ static int log_sample(struct oprofile_cp
|
||||
return 0;
|
||||
}
|
||||
|
||||
- is_kernel = !!is_kernel;
|
||||
+ WARN_ON(cpu_mode > CPU_MODE_XEN);
|
||||
|
||||
task = current;
|
||||
|
||||
/* notice a switch from user->kernel or vice versa */
|
||||
- if (cpu_buf->last_is_kernel != is_kernel) {
|
||||
- cpu_buf->last_is_kernel = is_kernel;
|
||||
- add_code(cpu_buf, is_kernel);
|
||||
+ if (cpu_buf->last_cpu_mode != cpu_mode) {
|
||||
+ cpu_buf->last_cpu_mode = cpu_mode;
|
||||
+ add_code(cpu_buf, cpu_mode);
|
||||
}
|
||||
-
|
||||
+
|
||||
/* notice a task switch */
|
||||
if (cpu_buf->last_task != task) {
|
||||
cpu_buf->last_task = task;
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.h ./drivers/oprofile/cpu_buffer.h
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.h 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/cpu_buffer.h 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer {
|
||||
volatile unsigned long tail_pos;
|
||||
unsigned long buffer_size;
|
||||
struct task_struct * last_task;
|
||||
- int last_is_kernel;
|
||||
+ int last_cpu_mode;
|
||||
int tracing;
|
||||
struct op_sample * buffer;
|
||||
unsigned long sample_received;
|
||||
@@ -51,7 +51,9 @@ extern struct oprofile_cpu_buffer cpu_bu
|
||||
void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
|
||||
|
||||
/* transient events for the CPU buffer -> event buffer */
|
||||
-#define CPU_IS_KERNEL 1
|
||||
-#define CPU_TRACE_BEGIN 2
|
||||
+#define CPU_MODE_USER 0
|
||||
+#define CPU_MODE_KERNEL 1
|
||||
+#define CPU_MODE_XEN 2
|
||||
+#define CPU_TRACE_BEGIN 3
|
||||
|
||||
#endif /* OPROFILE_CPU_BUFFER_H */
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/event_buffer.h ./drivers/oprofile/event_buffer.h
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/event_buffer.h 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/event_buffer.h 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -29,11 +29,12 @@ void wake_up_buffer_waiter(void);
|
||||
#define CPU_SWITCH_CODE 2
|
||||
#define COOKIE_SWITCH_CODE 3
|
||||
#define KERNEL_ENTER_SWITCH_CODE 4
|
||||
-#define KERNEL_EXIT_SWITCH_CODE 5
|
||||
+#define USER_ENTER_SWITCH_CODE 5
|
||||
#define MODULE_LOADED_CODE 6
|
||||
#define CTX_TGID_CODE 7
|
||||
#define TRACE_BEGIN_CODE 8
|
||||
#define TRACE_END_CODE 9
|
||||
+#define XEN_ENTER_SWITCH_CODE 10
|
||||
|
||||
#define INVALID_COOKIE ~0UL
|
||||
#define NO_COOKIE 0UL
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/oprof.c ./drivers/oprofile/oprof.c
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/oprof.c 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/oprof.c 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -5,6 +5,10 @@
|
||||
* @remark Read the file COPYING
|
||||
*
|
||||
* @author John Levon <levon@movementarian.org>
|
||||
+ *
|
||||
+ * Modified by Aravind Menon for Xen
|
||||
+ * These modifications are:
|
||||
+ * Copyright (C) 2005 Hewlett-Packard Co.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -19,7 +23,7 @@
|
||||
#include "cpu_buffer.h"
|
||||
#include "buffer_sync.h"
|
||||
#include "oprofile_stats.h"
|
||||
-
|
||||
+
|
||||
struct oprofile_operations oprofile_ops;
|
||||
|
||||
unsigned long oprofile_started;
|
||||
@@ -33,6 +37,17 @@ static DECLARE_MUTEX(start_sem);
|
||||
*/
|
||||
static int timer = 0;
|
||||
|
||||
+extern unsigned int adomains;
|
||||
+extern int active_domains[MAX_OPROF_DOMAINS];
|
||||
+
|
||||
+int oprofile_set_active(void)
|
||||
+{
|
||||
+ if (oprofile_ops.set_active)
|
||||
+ return oprofile_ops.set_active(active_domains, adomains);
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
int oprofile_setup(void)
|
||||
{
|
||||
int err;
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/oprof.h ./drivers/oprofile/oprof.h
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/oprof.h 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/oprof.h 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -35,5 +35,7 @@ void oprofile_create_files(struct super_
|
||||
void oprofile_timer_init(struct oprofile_operations * ops);
|
||||
|
||||
int oprofile_set_backtrace(unsigned long depth);
|
||||
+
|
||||
+int oprofile_set_active(void);
|
||||
|
||||
#endif /* OPROF_H */
|
||||
diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/oprofile_files.c ./drivers/oprofile/oprofile_files.c
|
||||
--- ../pristine-linux-2.6.16/drivers/oprofile/oprofile_files.c 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./drivers/oprofile/oprofile_files.c 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -5,15 +5,21 @@
|
||||
* @remark Read the file COPYING
|
||||
*
|
||||
* @author John Levon <levon@movementarian.org>
|
||||
+ *
|
||||
+ * Modified by Aravind Menon for Xen
|
||||
+ * These modifications are:
|
||||
+ * Copyright (C) 2005 Hewlett-Packard Co.
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/oprofile.h>
|
||||
+#include <asm/uaccess.h>
|
||||
+#include <linux/ctype.h>
|
||||
|
||||
#include "event_buffer.h"
|
||||
#include "oprofile_stats.h"
|
||||
#include "oprof.h"
|
||||
-
|
||||
+
|
||||
unsigned long fs_buffer_size = 131072;
|
||||
unsigned long fs_cpu_buffer_size = 8192;
|
||||
unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
|
||||
@@ -117,11 +123,79 @@ static ssize_t dump_write(struct file *
|
||||
static struct file_operations dump_fops = {
|
||||
.write = dump_write,
|
||||
};
|
||||
-
|
||||
+
|
||||
+#define TMPBUFSIZE 512
|
||||
+
|
||||
+unsigned int adomains = 0;
|
||||
+long active_domains[MAX_OPROF_DOMAINS];
|
||||
+
|
||||
+static ssize_t adomain_write(struct file * file, char const __user * buf,
|
||||
+ size_t count, loff_t * offset)
|
||||
+{
|
||||
+ char tmpbuf[TMPBUFSIZE];
|
||||
+ char * startp = tmpbuf;
|
||||
+ char * endp = tmpbuf;
|
||||
+ int i;
|
||||
+ unsigned long val;
|
||||
+
|
||||
+ if (*offset)
|
||||
+ return -EINVAL;
|
||||
+ if (!count)
|
||||
+ return 0;
|
||||
+ if (count > TMPBUFSIZE - 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ memset(tmpbuf, 0x0, TMPBUFSIZE);
|
||||
+
|
||||
+ if (copy_from_user(tmpbuf, buf, count))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ for (i = 0; i < MAX_OPROF_DOMAINS; i++)
|
||||
+ active_domains[i] = -1;
|
||||
+ adomains = 0;
|
||||
+
|
||||
+ while (1) {
|
||||
+ val = simple_strtol(startp, &endp, 0);
|
||||
+ if (endp == startp)
|
||||
+ break;
|
||||
+ while (ispunct(*endp))
|
||||
+ endp++;
|
||||
+ active_domains[adomains++] = val;
|
||||
+ if (adomains >= MAX_OPROF_DOMAINS)
|
||||
+ break;
|
||||
+ startp = endp;
|
||||
+ }
|
||||
+ if (oprofile_set_active())
|
||||
+ return -EINVAL;
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t adomain_read(struct file * file, char __user * buf,
|
||||
+ size_t count, loff_t * offset)
|
||||
+{
|
||||
+ char tmpbuf[TMPBUFSIZE];
|
||||
+ size_t len = 0;
|
||||
+ int i;
|
||||
+ /* This is all screwed up if we run out of space */
|
||||
+ for (i = 0; i < adomains; i++)
|
||||
+ len += snprintf(tmpbuf + len, TMPBUFSIZE - len,
|
||||
+ "%u ", (unsigned int)active_domains[i]);
|
||||
+ len += snprintf(tmpbuf + len, TMPBUFSIZE - len, "\n");
|
||||
+ return simple_read_from_buffer((void __user *)buf, count,
|
||||
+ offset, tmpbuf, len);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static struct file_operations active_domain_ops = {
|
||||
+ .read = adomain_read,
|
||||
+ .write = adomain_write,
|
||||
+};
|
||||
+
|
||||
void oprofile_create_files(struct super_block * sb, struct dentry * root)
|
||||
{
|
||||
oprofilefs_create_file(sb, root, "enable", &enable_fops);
|
||||
oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
|
||||
+ oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
|
||||
oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
|
||||
oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
|
||||
oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed);
|
||||
diff -pruN ../pristine-linux-2.6.16/include/linux/oprofile.h ./include/linux/oprofile.h
|
||||
--- ../pristine-linux-2.6.16/include/linux/oprofile.h 2006-03-20 05:53:29.000000000 +0000
|
||||
+++ ./include/linux/oprofile.h 2006-04-03 15:53:05.000000000 +0100
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/atomic.h>
|
||||
+
|
||||
+#include <xen/interface/xenoprof.h>
|
||||
|
||||
struct super_block;
|
||||
struct dentry;
|
||||
@@ -27,6 +29,8 @@ struct oprofile_operations {
|
||||
/* create any necessary configuration files in the oprofile fs.
|
||||
* Optional. */
|
||||
int (*create_files)(struct super_block * sb, struct dentry * root);
|
||||
+ /* setup active domains with Xen */
|
||||
+ int (*set_active)(int *active_domains, unsigned int adomains);
|
||||
/* Do any necessary interrupt setup. Optional. */
|
||||
int (*setup)(void);
|
||||
/* Do any necessary interrupt shutdown. Optional. */
|
||||
+6
-2
@@ -24,14 +24,14 @@ SUBDIRS += python
|
||||
SUBDIRS += pygrub
|
||||
endif
|
||||
|
||||
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
|
||||
|
||||
.PHONY: all
|
||||
all: check
|
||||
@set -e; for subdir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$subdir $@; \
|
||||
done
|
||||
$(MAKE) ioemu
|
||||
|
||||
.PHONY: install
|
||||
install: check
|
||||
@set -e; for subdir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$subdir $@; \
|
||||
@@ -39,18 +39,22 @@ install: check
|
||||
$(MAKE) ioemuinstall
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/var/xen/dump
|
||||
|
||||
.PHONY: clean
|
||||
clean: check_clean
|
||||
@set -e; for subdir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$subdir $@; \
|
||||
done
|
||||
$(MAKE) ioemuclean
|
||||
|
||||
.PHONY: check
|
||||
check:
|
||||
$(MAKE) -C check
|
||||
|
||||
.PHONY: check_clean
|
||||
check_clean:
|
||||
$(MAKE) -C check clean
|
||||
|
||||
.PHONY: ioemu ioemuinstall ioemuclean
|
||||
ifndef XEN_NO_IOEMU
|
||||
ioemu ioemuinstall ioemuclean:
|
||||
[ -f ioemu/config-host.h ] || \
|
||||
|
||||
@@ -12,6 +12,8 @@ XEN_LIBXENSTAT = $(XEN_ROOT)/tools/xenstat/libxenstat/src
|
||||
|
||||
X11_LDPATH = -L/usr/X11R6/$(LIBDIR)
|
||||
|
||||
CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030101
|
||||
|
||||
%.opic: %.c
|
||||
$(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $<
|
||||
|
||||
@@ -21,6 +23,7 @@ X11_LDPATH = -L/usr/X11R6/$(LIBDIR)
|
||||
%.o: %.cc
|
||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
.PHONY: mk-symlinks
|
||||
mk-symlinks: LINUX_ROOT=$(XEN_ROOT)/linux-2.6-xen-sparse
|
||||
mk-symlinks:
|
||||
mkdir -p xen
|
||||
|
||||
@@ -39,11 +39,13 @@ IBINS :=
|
||||
|
||||
LIB = libblktap.so libblktap.so.$(MAJOR) libblktap.so.$(MAJOR).$(MINOR)
|
||||
|
||||
.PHONY: all
|
||||
all: mk-symlinks libblktap.so #blkdump
|
||||
@set -e; for subdir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$subdir $@; \
|
||||
done
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/include
|
||||
@@ -54,12 +56,14 @@ install: all
|
||||
$(MAKE) -C $$subdir $@; \
|
||||
done
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS blkdump
|
||||
@set -e; for subdir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$subdir $@; \
|
||||
done
|
||||
|
||||
.PHONY: rpm
|
||||
rpm: all
|
||||
rm -rf staging
|
||||
mkdir staging
|
||||
@@ -82,6 +86,7 @@ blkdump: libblktap.so
|
||||
|
||||
.PHONY: TAGS clean install mk-symlinks rpm
|
||||
|
||||
.PHONY: TAGS
|
||||
TAGS:
|
||||
etags -t $(SRCS) *.h
|
||||
|
||||
|
||||
@@ -43,11 +43,14 @@ DEPS = .*.d
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
IBINS = parallax $(VDI_TOOLS)
|
||||
|
||||
.PHONY: all
|
||||
all: $(VDI_TOOLS) parallax blockstored
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
$(INSTALL_PROG) $(IBINS) $(DESTDIR)$(PARALLAX_INSTALL_DIR)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o *~ $(DEPS) xen TAGS $(VDI_TOOLS) parallax vdi_unittest
|
||||
|
||||
@@ -57,5 +60,4 @@ parallax: $(PLX_SRCS)
|
||||
${VDI_TOOLS}: %: %.c $(VDI_SRCS)
|
||||
$(CC) $(CFLAGS) -o $@ $@.c $(LDFLAGS) $(VDI_SRCS)
|
||||
|
||||
.PHONY: TAGS clean install rpm
|
||||
-include $(DEPS)
|
||||
@@ -21,12 +21,16 @@ DEPS = .*.d
|
||||
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
.PHONY: all
|
||||
all: $(IBIN)
|
||||
|
||||
LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INSTALL_DIR)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.o*~ $(DEPS) xen TAGS $(IBIN)
|
||||
|
||||
@@ -34,6 +38,4 @@ ublkback:
|
||||
$(CC) $(CFLAGS) -o ublkback -L$(XEN_LIBXC) -L. -L.. \
|
||||
-lblktap -laio ublkback.c ublkbacklib.c -pg
|
||||
|
||||
.PHONY: clean install
|
||||
|
||||
-include $(DEPS)
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
# Check this machine is OK for building on.
|
||||
.PHONY: build
|
||||
build:
|
||||
./chk build
|
||||
|
||||
@@ -9,8 +11,10 @@ build:
|
||||
# DO NOT use this check from 'make install' in the parent
|
||||
# directory, as that target can be used to make an installable
|
||||
# copy rather than actually installing.
|
||||
.PHONY: install
|
||||
install:
|
||||
./chk install
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
./chk clean
|
||||
./chk clean
|
||||
@@ -16,8 +16,10 @@ CFLAGS += -I $(XEN_XENSTORE)
|
||||
|
||||
BIN = xenconsoled xenconsole
|
||||
|
||||
.PHONY: all
|
||||
all: $(BIN)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) *.a *.so *.o *.rpm $(BIN)
|
||||
$(RM) client/*.o daemon/*.o
|
||||
@@ -30,6 +32,7 @@ xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
|
||||
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
|
||||
-lxenctrl -lxenstore
|
||||
|
||||
.PHONY: install
|
||||
install: $(BIN)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/$(DAEMON_INSTALL_DIR)
|
||||
$(INSTALL_PROG) xenconsoled $(DESTDIR)/$(DAEMON_INSTALL_DIR)
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <errno.h>
|
||||
#include <pty.h>
|
||||
|
||||
#include "xenctrl.h"
|
||||
#include "xs.h"
|
||||
|
||||
#define ESCAPE_CHARACTER 0x1d
|
||||
@@ -92,7 +91,7 @@ static void restore_term(int fd, struct termios *old)
|
||||
tcsetattr(fd, TCSAFLUSH, old);
|
||||
}
|
||||
|
||||
static int console_loop(int xc_handle, domid_t domid, int fd)
|
||||
static int console_loop(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -161,7 +160,6 @@ int main(int argc, char **argv)
|
||||
{
|
||||
struct termios attr;
|
||||
int domid;
|
||||
int xc_handle;
|
||||
char *sopt = "h";
|
||||
int ch;
|
||||
int opt_ind=0;
|
||||
@@ -206,11 +204,6 @@ int main(int argc, char **argv)
|
||||
err(errno, "Could not contact XenStore");
|
||||
}
|
||||
|
||||
xc_handle = xc_interface_open();
|
||||
if (xc_handle == -1) {
|
||||
err(errno, "xc_interface_open()");
|
||||
}
|
||||
|
||||
signal(SIGTERM, sighandler);
|
||||
|
||||
path = xs_get_domain_path(xs, domid);
|
||||
@@ -260,7 +253,7 @@ int main(int argc, char **argv)
|
||||
free(path);
|
||||
|
||||
init_term(STDIN_FILENO, &attr);
|
||||
console_loop(xc_handle, domid, spty);
|
||||
console_loop(spty);
|
||||
restore_term(STDIN_FILENO, &attr);
|
||||
|
||||
return 0;
|
||||
|
||||
+25
-13
@@ -434,26 +434,37 @@ void enum_domains(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int ring_free_bytes(struct domain *dom)
|
||||
{
|
||||
struct xencons_interface *intf = dom->interface;
|
||||
XENCONS_RING_IDX cons, prod, space;
|
||||
|
||||
cons = intf->in_cons;
|
||||
prod = intf->in_prod;
|
||||
mb();
|
||||
|
||||
space = prod - cons;
|
||||
if (space > sizeof(intf->in))
|
||||
return 0; /* ring is screwed: ignore it */
|
||||
|
||||
return (sizeof(intf->in) - space);
|
||||
}
|
||||
|
||||
static void handle_tty_read(struct domain *dom)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
char msg[80];
|
||||
int i;
|
||||
struct xencons_interface *intf = dom->interface;
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
|
||||
cons = intf->in_cons;
|
||||
prod = intf->in_prod;
|
||||
mb();
|
||||
|
||||
if (sizeof(intf->in) > (prod - cons))
|
||||
len = sizeof(intf->in) - (prod - cons);
|
||||
if (len > sizeof(msg))
|
||||
len = sizeof(msg);
|
||||
XENCONS_RING_IDX prod;
|
||||
|
||||
len = ring_free_bytes(dom);
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (len > sizeof(msg))
|
||||
len = sizeof(msg);
|
||||
|
||||
len = read(dom->tty_fd, msg, len);
|
||||
if (len < 1) {
|
||||
close(dom->tty_fd);
|
||||
@@ -465,6 +476,7 @@ static void handle_tty_read(struct domain *dom)
|
||||
shutdown_domain(dom);
|
||||
}
|
||||
} else if (domain_is_valid(dom->domid)) {
|
||||
prod = intf->in_prod;
|
||||
for (i = 0; i < len; i++) {
|
||||
intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
|
||||
msg[i];
|
||||
@@ -514,7 +526,7 @@ static void handle_ring_read(struct domain *dom)
|
||||
(void)write_sync(dom->evtchn_fd, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static void handle_xs(int fd)
|
||||
static void handle_xs(void)
|
||||
{
|
||||
char **vec;
|
||||
int domid;
|
||||
@@ -560,7 +572,7 @@ void handle_io(void)
|
||||
}
|
||||
|
||||
if (d->tty_fd != -1) {
|
||||
if (!d->is_dead)
|
||||
if (!d->is_dead && ring_free_bytes(d))
|
||||
FD_SET(d->tty_fd, &readfds);
|
||||
|
||||
if (!buffer_empty(&d->buffer))
|
||||
@@ -572,7 +584,7 @@ void handle_io(void)
|
||||
ret = select(max_fd + 1, &readfds, &writefds, 0, NULL);
|
||||
|
||||
if (FD_ISSET(xs_fileno(xs), &readfds))
|
||||
handle_xs(xs_fileno(xs));
|
||||
handle_xs();
|
||||
|
||||
for (d = dom_head; d; d = n) {
|
||||
n = d->next;
|
||||
|
||||
@@ -3,10 +3,12 @@ include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
LDFLAGS=-static
|
||||
|
||||
.PHONY: all
|
||||
all: console-dom0 console-domU procpipe
|
||||
|
||||
console-dom0: console-dom0.o
|
||||
console-domU: console-domU.o
|
||||
procpipe: procpipe.o
|
||||
|
||||
.PHONY: clean
|
||||
clean:; $(RM) *.o console-domU console-dom0 procpipe
|
||||
@@ -1,16 +1,17 @@
|
||||
|
||||
DomU GDB server for 32-bit (PAE and non-PAE) systems
|
||||
DomU & HVM GDB server for 32-bit (PAE and non-PAE) and x86_64 systems
|
||||
----------------------------------------------------
|
||||
|
||||
Lines marked below with [*] are optional, if you want full
|
||||
source-level debugging of your kernel image.
|
||||
|
||||
To build the GDB server:
|
||||
0. Build rest of the Xen first from the base directory
|
||||
1. Run ./gdbbuild from within this directory.
|
||||
2. Copy ./gdb-6.2.1-linux-i386-xen/gdb/gdbserver/gdbserver-xen
|
||||
to your test machine.
|
||||
|
||||
To build a debuggable guest kernel image:
|
||||
To build a debuggable guest domU kernel image:
|
||||
1. cd linux-2.6.xx-xenU
|
||||
2. make menuconfig
|
||||
3. From within the configurator, enable the following options:
|
||||
@@ -28,7 +29,7 @@ To debug a running guest:
|
||||
# bt
|
||||
# disass
|
||||
|
||||
To debug a crashed guest:
|
||||
To debug a crashed domU guest:
|
||||
1. Add '(enable-dump yes)' to /etc/xen/xend-config.sxp before
|
||||
starting xend.
|
||||
2. When the domain crashes, a core file is written to
|
||||
|
||||
@@ -286,6 +286,21 @@ handle_v_requests (char *own_buf, char *status, unsigned char *signal)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
handle_breakpoint_requests (char *own_buf, char *status, unsigned char *signal)
|
||||
{
|
||||
/* Currently we only support software breakpoints */
|
||||
switch (own_buf[1]) {
|
||||
case '0': /* software breakpoint, int3 based */
|
||||
own_buf[0] = '\0';
|
||||
break;
|
||||
case '1': /* hardware breakpoint */
|
||||
default:
|
||||
write_enn (own_buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
myresume (int step, int sig)
|
||||
{
|
||||
@@ -322,6 +337,18 @@ gdbserver_usage (void)
|
||||
"HOST:PORT to listen for a TCP connection.\n");
|
||||
}
|
||||
|
||||
extern control_c_pressed_flag;
|
||||
#include <signal.h>
|
||||
|
||||
void ctrl_c_handler(int signo)
|
||||
{
|
||||
printf("Ctrl-C pressed: Quit from the attached gdb first\n");
|
||||
control_c_pressed_flag = 1;
|
||||
}
|
||||
|
||||
struct sigaction ctrl_c_sigaction = { .sa_handler = ctrl_c_handler };
|
||||
struct sigaction old_sigaction;
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -396,9 +423,11 @@ main (int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
remote_open (argv[1]);
|
||||
sigaction(SIGINT, &ctrl_c_sigaction, &old_sigaction);
|
||||
|
||||
restart:
|
||||
setjmp (toplevel);
|
||||
@@ -587,6 +616,9 @@ main (int argc, char *argv[])
|
||||
/* Extended (long) request. */
|
||||
handle_v_requests (own_buf, &status, &signal);
|
||||
break;
|
||||
case 'Z':
|
||||
handle_breakpoint_requests (own_buf, &status, &signal);
|
||||
break;
|
||||
default:
|
||||
/* It is a request we don't understand. Respond with an
|
||||
empty packet so that gdb knows that we don't support this
|
||||
@@ -643,5 +675,6 @@ main (int argc, char *argv[])
|
||||
"GDBserver will reopen the connection.\n");
|
||||
remote_close ();
|
||||
}
|
||||
sigaction(SIGINT, &old_sigaction, NULL);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 327 files, more files were not shown because too many files have changed in this diff.
Show more