mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.1720 (42b7bb86ag6KD5OEx2v6YdSnS1BhGQ)
Merge freefall.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk into freefall.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
This commit is contained in:
commit
22e32f8c3c
107 files changed
+7147
-606
No files matched your search
@@ -21,6 +21,7 @@
|
||||
420b949cy9ZGzED74Fz_DaWlK7tT4g docs/misc/crashdb.txt
|
||||
4251a1f82AexscYEiF4Iku8Gc_kWfQ docs/misc/grant-tables.txt
|
||||
424d462b5GuApQ_NyMsRFt9LbrsWow docs/misc/sedf_scheduler_mini-HOWTO.txt
|
||||
42b7434c-M2l4Og0klGf6xSAARqa2w docs/misc/shype4xen_readme.txt
|
||||
40d6ccbfKKBq8jE0ula4eHEzBiQuDA docs/misc/xen_config.html
|
||||
410a4c2bAO_m_l4RsiiPHnZ4ixHWbQ docs/misc/xend.tex
|
||||
3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/src/interface.tex
|
||||
@@ -777,6 +778,16 @@
|
||||
40c9c469kT0H9COWzA4XzPBjWK0WsA tools/misc/netfix
|
||||
4022a73cEKvrYe_DVZW2JlAxobg9wg tools/misc/nsplitd/Makefile
|
||||
4022a73cKms4Oq030x2JBzUB426lAQ tools/misc/nsplitd/nsplitd.c
|
||||
42b74436oXEaaUH_dPcGFviMiwNgCQ tools/misc/policyprocessor/SecurityLabel.java
|
||||
42b74436fIW8ZI3pUpu13-Ox6G2cOA tools/misc/policyprocessor/SecurityPolicySpec.xsd
|
||||
42b74436T4CN4HMWsuaHD2zS8jY1BA tools/misc/policyprocessor/SsidsEntry.java
|
||||
42b74436Dk3WKJl6-SyP3LEBo3DXkQ tools/misc/policyprocessor/XmlToBin.java
|
||||
42b74436ABj4SOVBWqY_IEIboFUkeA tools/misc/policyprocessor/XmlToBinInterface.java
|
||||
42b7443684kBOrEBKFod4fGvnJ-rdA tools/misc/policyprocessor/myHandler.java
|
||||
42b74436JjvZmOp2DfMb-TnpGZXQ8w tools/misc/policyprocessor/readme.install
|
||||
42b74436-0Ig0yb-w1BYyCAFVTwqUg tools/misc/policyprocessor/readme.xen
|
||||
42b74436WAJ6lmTO3foadk2527PFBQ tools/misc/policyprocessor/xen_sample_def.xml
|
||||
42b744365VrTALmqRroQOBZ9EopUsw tools/misc/policyprocessor/xen_sample_policy.xml
|
||||
42308df9dv_ZuP49nNPIROEMQ3F_LA tools/misc/xc_shadow.c
|
||||
3f5ef5a2ir1kVAthS14Dc5QIRCEFWg tools/misc/xen-clone
|
||||
3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
|
||||
@@ -785,6 +796,8 @@
|
||||
41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c
|
||||
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
|
||||
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
|
||||
42b742f6JFcp6LFpYu-B4AEsfQwSFw tools/policy/Makefile
|
||||
42b742f66XOdRMrwaHvbCdSSQyCrFw tools/policy/policy_tool.c
|
||||
4270cc81g3nSNYCZ1ryCMDEbLtMtbQ tools/pygrub/Makefile
|
||||
4270deeccyRsJn6jLnRh9odRtMW9SA tools/pygrub/README
|
||||
4270cc81EIl7NyaS3Av6IPRk2c2a6Q tools/pygrub/setup.py
|
||||
@@ -1101,6 +1114,12 @@
|
||||
3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
|
||||
3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
|
||||
3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
|
||||
42b742f6XHTfIEm_hUPtzjKr37LVhw xen/acm/Makefile
|
||||
42b742f6tHzn0fZWH3TjPva8gbqpow xen/acm/acm_chinesewall_hooks.c
|
||||
42b742f6bM8kZwuIUbepHZ8SQQkjJA xen/acm/acm_core.c
|
||||
42b742f6cwfrPubqH47gQpke8xkYSA xen/acm/acm_null_hooks.c
|
||||
42b742f69qSxm5MM-wtPaWtCqyI3KA xen/acm/acm_policy.c
|
||||
42b742f6VbmdlwekQRMhXugjcu9QXg xen/acm/acm_simple_type_enforcement_hooks.c
|
||||
421098b25A0RvuYN3rP28ga3_FN3_Q xen/arch/ia64/Makefile
|
||||
421098b2okIeYXS9w9avmSozls61xA xen/arch/ia64/Rules.mk
|
||||
421098b21p12UcKjHBrLh_LjlvNEwA xen/arch/ia64/acpi.c
|
||||
@@ -1146,6 +1165,7 @@
|
||||
425ae516juUB257qrwUdsL9AsswrqQ xen/arch/ia64/patch/linux-2.6.11/time.c
|
||||
425ae5167zQn7zYcgKtDUDX2v-e8mw xen/arch/ia64/patch/linux-2.6.11/tlb.c
|
||||
425ae5162bIl2Dgd19x-FceB4L9oGw xen/arch/ia64/patch/linux-2.6.11/types.h
|
||||
42ae01f01KDfSgVQnscwJ0psRmEaCw xen/arch/ia64/patch/linux-2.6.11/uaccess.h
|
||||
425ae516cFUNY2jHD46bujcF5NJheA xen/arch/ia64/patch/linux-2.6.11/unaligned.c
|
||||
421098b39QFMC-1t1r38CA7NxAYBPA xen/arch/ia64/patch/linux-2.6.7/bootmem.h
|
||||
421098b3SIA1vZX9fFUjo1T3o_jMCQ xen/arch/ia64/patch/linux-2.6.7/current.h
|
||||
@@ -1323,6 +1343,7 @@
|
||||
41a61536SZbR6cj1ukWTb0DYU-vz9w xen/common/multicall.c
|
||||
3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c
|
||||
3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
|
||||
42b742f6mgq9puEr7lUrLST0VEpsig xen/common/policy_ops.c
|
||||
40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c
|
||||
41ebbfe9oF1BF3cH5v7yE3eOL9uPbA xen/common/sched_sedf.c
|
||||
3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
|
||||
@@ -1338,6 +1359,9 @@
|
||||
4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c
|
||||
4298e018XQtZkCdufpyFimOGZqqsFA xen/drivers/char/ns16550.c
|
||||
3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c
|
||||
42b742f6OteAMPWnoqxqfRX3yxD0yw xen/include/acm/acm_core.h
|
||||
42b742f6XfIijctEwA0YWL2BoWtDNg xen/include/acm/acm_endian.h
|
||||
42b742f6jXvp1vdbU2v2WJjTPku65A xen/include/acm/acm_hooks.h
|
||||
40715b2cFpte_UNWnBZW0Du7z9AhTQ xen/include/acpi/acconfig.h
|
||||
40715b2ctNvVZ058w8eM8DR9hOat_A xen/include/acpi/acexcep.h
|
||||
40715b2com8I01qcHcAw47e93XsCqQ xen/include/acpi/acglobal.h
|
||||
@@ -1364,6 +1388,7 @@
|
||||
421098b6ZcIrn_gdqjUtdJyCE0YkZQ xen/include/asm-ia64/debugger.h
|
||||
421098b6z0zSuW1rcSJK1gR8RUi-fw xen/include/asm-ia64/dom_fw.h
|
||||
421098b6Nn0I7hGB8Mkd1Cis0KMkhA xen/include/asm-ia64/domain.h
|
||||
42b1d2d0rkNCmG2nFOnL-OfhJG9mDw xen/include/asm-ia64/event.h
|
||||
4241e880hAyo_dk0PPDYj3LsMIvf-Q xen/include/asm-ia64/flushtlb.h
|
||||
421098b6X3Fs2yht42TE2ufgKqt2Fw xen/include/asm-ia64/ia64_int.h
|
||||
421098b7psFAn8kbeR-vcRCdc860Vw xen/include/asm-ia64/init.h
|
||||
@@ -1388,7 +1413,6 @@
|
||||
428b9f38is0zTsIm96_BKo4MLw0SzQ xen/include/asm-ia64/vmx_pal_vsa.h
|
||||
428b9f38iDqbugHUheJrcTCD7zlb4g xen/include/asm-ia64/vmx_phy_mode.h
|
||||
428b9f38grd_B0AGB1yp0Gi2befHaQ xen/include/asm-ia64/vmx_platform.h
|
||||
428b9f38lm0ntDBusHggeQXkx1-1HQ xen/include/asm-ia64/vmx_ptrace.h
|
||||
428b9f38XgwHchZEpOzRtWfz0agFNQ xen/include/asm-ia64/vmx_vcpu.h
|
||||
428b9f38tDTTJbkoONcAB9ODP8CiVg xen/include/asm-ia64/vmx_vpd.h
|
||||
428b9f38_o0U5uJqmxZf_bqi6_PqVw xen/include/asm-ia64/vtm.h
|
||||
@@ -1412,6 +1436,7 @@
|
||||
40715b2dTokMLYGSuD58BnxOqyWVew xen/include/asm-x86/div64.h
|
||||
4204e7acwzqgXyTAPKa1nM-L7Ec0Qw xen/include/asm-x86/domain.h
|
||||
41d3eaaeIBzW621S1oa0c2yk7X43qQ xen/include/asm-x86/e820.h
|
||||
42b1d2caFkOByU5n4LuMnT05f3kJFg xen/include/asm-x86/event.h
|
||||
3ddb79c3NU8Zy40OTrq3D-i30Y3t4A xen/include/asm-x86/fixmap.h
|
||||
3e2d29944GI24gf7vOP_7x8EyuqxeA xen/include/asm-x86/flushtlb.h
|
||||
4294b5eep4lWuDtYUR74gYwt-_FnHA xen/include/asm-x86/genapic.h
|
||||
@@ -1487,6 +1512,8 @@
|
||||
404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86/x86_64/uaccess.h
|
||||
422f27c8RHFkePhD34VIEpMMqofZcA xen/include/asm-x86/x86_emulate.h
|
||||
400304fcmRQmDdFYEzDh0wcBba9alg xen/include/public/COPYING
|
||||
42b742f6duiOTlZvysQkRYZHYBXqvg xen/include/public/acm.h
|
||||
42b742f7TIMsQgUaNDJXp3QlBve2SQ xen/include/public/acm_dom0_setup.h
|
||||
421098b7OKb9YH_EUA_UpCxBjaqtgA xen/include/public/arch-ia64.h
|
||||
404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/public/arch-x86_32.h
|
||||
404f1bc7IwU-qnH8mJeVu0YsNGMrcw xen/include/public/arch-x86_64.h
|
||||
@@ -1500,8 +1527,10 @@
|
||||
41d40e9b8zCk5VDqhVbuQyhc7G3lqA xen/include/public/io/ring.h
|
||||
41ee5e8c6mLxIx82KPsbpt_uts_vSA xen/include/public/io/usbif.h
|
||||
4051db79512nOCGweabrFWO2M2h5ng xen/include/public/physdev.h
|
||||
42b742f7Lzy8SKKG25L_-fgk5FHA2Q xen/include/public/policy_ops.h
|
||||
40589968wmhPmV5-ENbBYmMjnedgKw xen/include/public/sched_ctl.h
|
||||
404f3d2eR2Owk-ZcGOx9ULGHg3nrww xen/include/public/trace.h
|
||||
42b5a5f2QC1IxeuwCwwsOEhvcJ2BJg xen/include/public/version.h
|
||||
4266bd01Ul-pC01ZVvBkhBnv5eqzvw xen/include/public/vmx_assist.h
|
||||
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/public/xen.h
|
||||
3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h
|
||||
|
||||
@@ -39,6 +39,7 @@ iap10@labyrinth.cl.cam.ac.uk
|
||||
iap10@nidd.cl.cam.ac.uk
|
||||
iap10@pb001.cl.cam.ac.uk
|
||||
iap10@pb007.cl.cam.ac.uk
|
||||
iap10@spot.cl.cam.ac.uk
|
||||
iap10@striker.cl.cam.ac.uk
|
||||
iap10@tetris.cl.cam.ac.uk
|
||||
jrb44@plym.cl.cam.ac.uk
|
||||
|
||||
@@ -31,3 +31,6 @@ endif
|
||||
|
||||
LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i))
|
||||
CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
|
||||
|
||||
# Choose the best mirror to download linux kernel
|
||||
KERNEL_REPO = http://www.kernel.org
|
||||
@@ -27,7 +27,7 @@ vpath linux-%.tar.bz2 $(LINUX_SRC_PATH)
|
||||
linux-%.tar.bz2: override _LINUX_VDIR = $(word 1,$(subst ., ,$*)).$(word 2,$(subst ., ,$*))
|
||||
linux-%.tar.bz2:
|
||||
@echo "Cannot find $@ in path $(LINUX_SRC_PATH)"
|
||||
wget http://www.kernel.org/pub/linux/kernel/v$(_LINUX_VDIR)/$@ -O./$@
|
||||
wget $(KERNEL_REPO)/pub/linux/kernel/v$(_LINUX_VDIR)/$@ -O./$@
|
||||
|
||||
# Expand NetBSD release to NetBSD version
|
||||
NETBSD_RELEASE ?= 2.0
|
||||
@@ -57,6 +57,7 @@ $(patsubst %,pristine-%/.valid-pristine,$(ALLSPARSETREES)) : pristine-%/.valid-p
|
||||
mkdir -p tmp-pristine-$*
|
||||
touch tmp-pristine-$*/.bk_skip
|
||||
tar -C tmp-pristine-$* -jxf $<
|
||||
-@rm tmp-pristine-$*/pax_global_header
|
||||
mv tmp-pristine-$*/* $(@D)
|
||||
@rm -rf tmp-pristine-$*
|
||||
touch $@ # update timestamp to avoid rebuild
|
||||
|
||||
@@ -0,0 +1,580 @@
|
||||
Copyright: IBM Corporation (C)
|
||||
20 June 2005
|
||||
Author: Reiner Sailer
|
||||
|
||||
This document is a very short introduction into the sHype access control
|
||||
security architecture implementation and how it is perceived by users. It
|
||||
is a very preliminary draft for the courageous ones to get "their feet wet"
|
||||
and to be able to give feedback (via the xen-devel/xense-devel mailing lists).
|
||||
|
||||
Install:
|
||||
|
||||
cd into xeno-unstable.bk
|
||||
(use --dry-run option if you want to test the patch only)
|
||||
patch -p1 -g0 < *tools.diff
|
||||
patch -p1 -g0 < *xen.diff
|
||||
|
||||
(no rejects, probably some line offsets)
|
||||
|
||||
make uninstall; make mrproper; make; ./install.sh should install the default
|
||||
sHype into Xen (rebuild your initrd images if necessary). Reboot.
|
||||
|
||||
Debug output: there are two triggers for debug output:
|
||||
a) General sHype debug:
|
||||
xeno-unstable.bk/xen/include/public/acm.h
|
||||
undefine ACM_DEBUG to switch this debug off
|
||||
|
||||
b) sHype enforcement hook trace: This prints a small trace for each enforcement
|
||||
hook that is executed. The trigger is in
|
||||
xeno-unstable.bk/xen/include/acm/acm_hooks.h
|
||||
undefine ACM_TRACE_MODE to switch this debug off
|
||||
|
||||
1. The default NULL policy
|
||||
***************************
|
||||
When you apply the patches and startup xen, you should at first not notice any
|
||||
difference because the default policy is the "NULL" policy, which as the name
|
||||
implies does not enforce anything.
|
||||
|
||||
However, when you try
|
||||
|
||||
[root@laptop policy]# xm list
|
||||
Name Id Mem(MB) CPU State Time(s) Console SSID-REF
|
||||
Domain-0 0 620 0 r---- 25.6 default
|
||||
|
||||
You might detect a new parameter "SSID-REF" displayed for domains. This
|
||||
parameter describes the subject security identifier reference of the domain. It
|
||||
is shown as "default" since there is no policy to be enforced.
|
||||
|
||||
To display the currently enforced policy, use the policy tool under xeno-
|
||||
unstable.bk/tools/policy: policy_tool getpolicy. You should see output like the
|
||||
one below.
|
||||
|
||||
[root@laptop policy]#./policy_tool getpolicy
|
||||
|
||||
Policy dump:
|
||||
============
|
||||
Magic = 1debc.
|
||||
PolVer = aaaa0000.
|
||||
Len = 14.
|
||||
Primary = NULL policy (c=0, off=14).
|
||||
Secondary = NULL policy (c=0, off=14).
|
||||
No primary policy (NULL).
|
||||
No secondary policy (NULL).
|
||||
|
||||
Policy dump End.
|
||||
|
||||
Since this is a dump of a binary policy, it's not pretty. The important parts
|
||||
are the "Primary" and "Secondary" policy fields set to "NULL policy". sHype
|
||||
currently allows to set two independent policies; thus the two SSID-REF parts
|
||||
shown in 'xm list'. Right here: primary policy only means this policy is
|
||||
checked first, the secondary policy is checked if the primary results in
|
||||
"permitted access". The result of the combined policy is "permitted" if both
|
||||
policies return permitted (NULL policy always returns permitted). The result is
|
||||
"denied" if at least one of the policies returns "denied". Look into xeno-
|
||||
unstable.bk/xen/include/acm/acm_hooks.h for the general hook structure
|
||||
integrating the policy decisions (if you like, you won't need it for the rest
|
||||
of the Readme file).
|
||||
|
||||
2. Setting Chinese Wall and Simple Type Enforcement policies:
|
||||
*************************************************************
|
||||
|
||||
We'll get fast to the point. However, in order to understand what we are doing,
|
||||
we must at least understand the purpose of the policies that we are going to
|
||||
enforce. The two policies presented here are just examples and the
|
||||
implementation encourages adding new policies easily.
|
||||
|
||||
2.1. Chinese Wall policy: "decides whether a domain can be started based on
|
||||
this domain's ssidref and the ssidrefs of the currently running domains".
|
||||
Generally, the Chinese wall policy allows specifying certain types (or classes
|
||||
or categories, whatever the preferred word) that conflict; we usually assign a
|
||||
type to a workload and the set of types of those workloads running in a domain
|
||||
make up the type set for this domain. Each domain is assigned a set of types
|
||||
through its SSID-REF (we register Chinese Wall as primary policy, so the
|
||||
ssidref used for determining the Chinese Wall types is the one annotated with
|
||||
"p:" in xm list) since each SSID-REF points at a set of types. We'll see how
|
||||
SSIDREFs are represented in Xen later when we will look at the policy. (A good
|
||||
read for Chinese Wall is: Brewer/Nash The Chinese Wall Security Policy 1989.)
|
||||
|
||||
So let's assume the Chinese Wall policy we are running distinguishes 10 types:
|
||||
t0 ... t9. Let us assume further that each SSID-REF points to a set that
|
||||
includes exactly one type (attached to domains that run workloads of a single
|
||||
type). SSID-REF 0 points to {t0}, ssidref 1 points to {t1} ... 9 points to
|
||||
{t9}. [This is actually the example policy we are going to push into xen later]
|
||||
|
||||
Now the Chinese Wall policy allows you to define "Conflict type sets" and it
|
||||
guarantees that of any conflict set at most one type is "running" at any time.
|
||||
As an example, we have defined 2 conflict set: {t2, t3} and {t0, t5, t6}.
|
||||
Specifying these conflict sets, sHype ensures that at most one type of each set
|
||||
is running (either t2 or t3 but not both; either t0 or t5 or t6 but not
|
||||
multiple of them).
|
||||
|
||||
The effect is that administrators can define which workload types cannot run
|
||||
simultaneously on a single Xen system. This is useful to limit the covert
|
||||
timing channels between such payloads or to ensure that payloads don't
|
||||
interfere with each other through existing resource dependencies.
|
||||
|
||||
2.2. Simple Type Enforcement (ste) policy: "decides whether two domains can
|
||||
share data, e.g., setup event channels or grant tables to each other, based on
|
||||
the two domains' ssidref. This, as the name says, is a simple policy. Think of
|
||||
each type as of a single color. Each domain has one or more colors, i.e., the
|
||||
domains ssid for the ste policy points to a set that has set one or multiple
|
||||
types. Let us assume in our example policy we differentiate 5 colors (types)
|
||||
and define 5 different ssids referenced by ssidref=0..4. Each ssid shall have
|
||||
exactly one type set, i.e., describes a uni-color. Only ssid(0) has all types
|
||||
set, i.e., has all defined colors.
|
||||
|
||||
Sharing is enforced by the ste policy by requiring that two domains that want
|
||||
to establish an event channel or grant pages to each other must have a common
|
||||
color. Currently all domains communicate through DOM0 by default; i.e., Domain0
|
||||
will necessarily have all colors to be able to create domains (thus, we will
|
||||
assign ssidref(0) to Domain0 in our example below.
|
||||
|
||||
More complex mandatory access control policies governing sharing will follow;
|
||||
such policies are more sophisticated than the "color" scheme above by allowing
|
||||
more flexible (and complex :_) access control decisions than "share a color" or
|
||||
"don't share a color" and will be able to express finer-grained policies.
|
||||
|
||||
|
||||
2.3 Binary Policy:
|
||||
In the future, we will have a policy tool that takes as input a more humane
|
||||
policy description, using types such as development, home-banking, donated-
|
||||
Grid, CorpA-Payload ... and translates the respective policy into what we see
|
||||
today as the binary policy using 1s and 0s and sets of them. For now, we must
|
||||
live with the binary policy when working with sHype.
|
||||
|
||||
|
||||
2.4 Exemplary use of a real sHype policy on Xen. To activate a real policy,
|
||||
edit the file (yes, this will soon be a compile option):
|
||||
xeno-unstable.bk/xen/include/public/acm.h
|
||||
Change: #define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY
|
||||
To : #define ACM_USE_SECURITY_POLICY ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
|
||||
cd xeno-unstable.bk
|
||||
make mrproper
|
||||
make uninstall (manually remove /etc/xen.old if necessary)
|
||||
make
|
||||
./install.sh (recreate your kernel initrd's if necessary)
|
||||
Reboot into new xen.gz
|
||||
|
||||
After booting, check out 'xm dmesg'; should show somewhere in the middle:
|
||||
|
||||
(XEN) acm_init: Enforcing Primary CHINESE WALL policy, Secondary SIMPLE TYPE
|
||||
ENFORCEMENT policy.
|
||||
|
||||
Even though you can activate those policies in any combination and also
|
||||
independently, the policy tool currently only supports setting the policy for
|
||||
the above combination.
|
||||
|
||||
Now look at the minimal startup policy with:
|
||||
xeno-unstable.bk/tools/policytool getpolicy
|
||||
|
||||
You should see something like:
|
||||
|
||||
[root@laptop policy]# ./policy_tool getpolicy
|
||||
|
||||
Policy dump:
|
||||
============
|
||||
Magic = 1debc.
|
||||
PolVer = aaaa0000.
|
||||
Len = 36.
|
||||
Primary = CHINESE WALL policy (c=1, off=14).
|
||||
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=2c).
|
||||
|
||||
|
||||
Chinese Wall policy:
|
||||
====================
|
||||
Max Types = 1.
|
||||
Max Ssidrefs = 1.
|
||||
Max ConfSets = 1.
|
||||
Ssidrefs Off = 10.
|
||||
Conflicts Off = 12.
|
||||
Runing T. Off = 14.
|
||||
C. Agg. Off = 16.
|
||||
|
||||
SSID To CHWALL-Type matrix:
|
||||
|
||||
ssidref 0: 00
|
||||
|
||||
Confict Sets:
|
||||
|
||||
c-set 0: 00
|
||||
|
||||
Running
|
||||
Types: 00
|
||||
|
||||
Conflict
|
||||
Aggregate Set: 00
|
||||
|
||||
|
||||
Simple Type Enforcement policy:
|
||||
===============================
|
||||
Max Types = 1.
|
||||
Max Ssidrefs = 1.
|
||||
Ssidrefs Off = 8.
|
||||
|
||||
SSID To STE-Type matrix:
|
||||
|
||||
ssidref 0: 01
|
||||
|
||||
|
||||
Policy dump End.
|
||||
|
||||
This is a minimal policy (of little use), except it will disable starting any
|
||||
domain that does not have ssidref set to 0x0. The Chinese Wall policy has
|
||||
nothing to enforce and the ste policy only knows one type, which is set for the
|
||||
only defined ssidref.
|
||||
|
||||
The item that defines the ssidref in a domain configuration is:
|
||||
|
||||
ssidref = 0x12345678
|
||||
|
||||
Where ssidref is interpreted as a 32bit number, where the lower 16bits become
|
||||
the ssidref for the primary policy and the higher 16bits become the ssidref for
|
||||
the secondary policy. sHype currently supports two policies but this is an
|
||||
implementation decision and can be extended if necessary.
|
||||
|
||||
This reference defines the security information of a domain. The meaning of the
|
||||
SSID-REF depends on the policy, so we explain it when we explain the real
|
||||
policies.
|
||||
|
||||
|
||||
Setting a new Security Policy:
|
||||
******************************
|
||||
The policy tool with all its current limitations has one usable example policy
|
||||
compiled-in. Please try at this time to use the setpolicy command:
|
||||
xeno-unstable.bk/tools/policy/policy_tool setpolicy
|
||||
|
||||
You should see a dump of the policy you are setting. It should say at the very
|
||||
end:
|
||||
|
||||
Policy successfully set.
|
||||
|
||||
Now try to dump the currently enforced policy, which is the policy we have just
|
||||
set and the dynamic security state information of this policy
|
||||
(<<< ... some additional explanations)
|
||||
|
||||
[root@laptop policy]# ./policy_tool getpolicy
|
||||
|
||||
Policy dump:
|
||||
============
|
||||
Magic = 1debc.
|
||||
PolVer = aaaa0000.
|
||||
Len = 112.
|
||||
Primary = CHINESE WALL policy (c=1, off=14).
|
||||
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8).
|
||||
|
||||
|
||||
Chinese Wall policy:
|
||||
====================
|
||||
Max Types = a.
|
||||
Max Ssidrefs = 5.
|
||||
Max ConfSets = 2.
|
||||
Ssidrefs Off = 10.
|
||||
Conflicts Off = 74.
|
||||
Runing T. Off = 9c.
|
||||
C. Agg. Off = b0.
|
||||
|
||||
SSID To CHWALL-Type matrix:
|
||||
|
||||
ssidref 0: 01 00 00 00 00 00 00 00 00 00 <<< type0 is set for ssidref0
|
||||
ssidref 1: 00 01 00 00 00 00 00 00 00 00
|
||||
ssidref 2: 00 00 01 00 00 00 00 00 00 00
|
||||
ssidref 3: 00 00 00 01 00 00 00 00 00 00
|
||||
ssidref 4: 00 00 00 00 01 00 00 00 00 00 <<< type4 is set for ssidref4
|
||||
<<< types 5-9 are unused
|
||||
Confict Sets:
|
||||
|
||||
c-set 0: 00 00 01 01 00 00 00 00 00 00 <<< type2 and type3 never run together
|
||||
c-set 1: 01 00 00 00 00 01 01 00 00 00 <<< only one of types 0, 5 or 6
|
||||
<<< can run simultaneously
|
||||
Running
|
||||
Types: 01 00 00 00 00 00 00 00 00 00 <<< ref-count for types of running domains
|
||||
|
||||
Conflict
|
||||
Aggregate Set: 00 00 00 00 00 01 01 00 00 00 <<< aggregated set of types that
|
||||
<<< cannot run because they
|
||||
<<< are in conflict set 1 and
|
||||
<<< (domain 0 is running w t0)
|
||||
|
||||
|
||||
Simple Type Enforcement policy:
|
||||
===============================
|
||||
Max Types = 5.
|
||||
Max Ssidrefs = 5.
|
||||
Ssidrefs Off = 8.
|
||||
|
||||
SSID To STE-Type matrix:
|
||||
|
||||
ssidref 0: 01 01 01 01 01 <<< ssidref0 points to a set that
|
||||
<<< has all types set (colors)
|
||||
ssidref 1: 00 01 00 00 00 <<< ssidref1 has color1 set
|
||||
ssidref 2: 00 00 01 00 00 <<< ...
|
||||
ssidref 3: 00 00 00 01 00
|
||||
ssidref 4: 00 00 00 00 01
|
||||
|
||||
|
||||
Policy dump End.
|
||||
|
||||
|
||||
This is a small example policy with which we will demonstrate the enforcement.
|
||||
|
||||
Starting Domains with policy enforcement
|
||||
========================================
|
||||
Now let us play with this policy.
|
||||
|
||||
Define 3 or 4 domain configurations. I use the following config using a ramdisk
|
||||
only and about 8MBytes of memory for each DomU (test purposes):
|
||||
|
||||
#-------configuration xmsec1-------------------------
|
||||
kernel = "/boot/vmlinuz-2.6.11-xenU"
|
||||
ramdisk="/boot/U1_ramdisk.img"
|
||||
#security reference identifier
|
||||
ssidref= 0x00010001
|
||||
memory = 10
|
||||
name = "xmsec1"
|
||||
cpu = -1 # leave to Xen to pick
|
||||
# Number of network interfaces. Default is 1.
|
||||
nics=1
|
||||
dhcp="dhcp"
|
||||
#-----------------------------------------------------
|
||||
|
||||
xmsec2 and xmsec3 look the same except for the name and the ssidref line. Use
|
||||
your domain config file and add "ssidref = 0x00010001" to the first (xmsec1),
|
||||
"ssidref= 0x00020002" to the second (call it xmsec2), and "ssidref=0x00030003"
|
||||
to the third (we will call this one xmsec3).
|
||||
|
||||
First start xmsec1: xm create -c xmsec1 (succeeds)
|
||||
|
||||
Then
|
||||
[root@laptop policy]# xm list
|
||||
Name Id Mem(MB) CPU State Time(s) Console SSID-REF
|
||||
Domain-0 0 620 0 r---- 42.3 s:00/p:00
|
||||
xmnosec 1 9 0 -b--- 0.3 9601 s:00/p:05
|
||||
xmsec1 2 9 0 -b--- 0.2 9602 s:01/p:01
|
||||
|
||||
Shows a new domain xmsec1 running with primary (here: chinese wall) ssidref 1
|
||||
and secondary (here: simple type enforcement) ssidref 1. The ssidrefs are
|
||||
independent and can differ for a domain.
|
||||
|
||||
[root@laptop policy]# ./policy_tool getpolicy
|
||||
|
||||
Policy dump:
|
||||
============
|
||||
Magic = 1debc.
|
||||
PolVer = aaaa0000.
|
||||
Len = 112.
|
||||
Primary = CHINESE WALL policy (c=1, off=14).
|
||||
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8).
|
||||
|
||||
|
||||
Chinese Wall policy:
|
||||
====================
|
||||
Max Types = a.
|
||||
Max Ssidrefs = 5.
|
||||
Max ConfSets = 2.
|
||||
Ssidrefs Off = 10.
|
||||
Conflicts Off = 74.
|
||||
Runing T. Off = 9c.
|
||||
C. Agg. Off = b0.
|
||||
|
||||
SSID To CHWALL-Type matrix:
|
||||
|
||||
ssidref 0: 01 00 00 00 00 00 00 00 00 00
|
||||
ssidref 1: 00 01 00 00 00 00 00 00 00 00
|
||||
ssidref 2: 00 00 01 00 00 00 00 00 00 00
|
||||
ssidref 3: 00 00 00 01 00 00 00 00 00 00
|
||||
ssidref 4: 00 00 00 00 01 00 00 00 00 00
|
||||
|
||||
Confict Sets:
|
||||
|
||||
c-set 0: 00 00 01 01 00 00 00 00 00 00
|
||||
c-set 1: 01 00 00 00 00 01 01 00 00 00 <<< t1 is not part of any c-set
|
||||
|
||||
Running
|
||||
Types: 01 01 00 00 00 00 00 00 00 00 <<< xmsec1 has ssidref 1->type1
|
||||
^^ <<< ref-count at position 1 incr
|
||||
Conflict
|
||||
Aggregate Set: 00 00 00 00 00 01 01 00 00 00 <<< domain 1 was allowed to
|
||||
<<< start since type 1 was not
|
||||
<<< in conflict with running
|
||||
<<< types
|
||||
|
||||
Simple Type Enforcement policy:
|
||||
===============================
|
||||
Max Types = 5.
|
||||
Max Ssidrefs = 5.
|
||||
Ssidrefs Off = 8.
|
||||
|
||||
SSID To STE-Type matrix:
|
||||
|
||||
ssidref 0: 01 01 01 01 01 <<< the ste policy does not maintain; we
|
||||
ssidref 1: 00 01 00 00 00 <-- <<< see that domain xmsec1 has ste
|
||||
ssidref 2: 00 00 01 00 00 <<< ssidref1->type1 and has this type in
|
||||
ssidref 3: 00 00 00 01 00 <<< common with dom0
|
||||
ssidref 4: 00 00 00 00 01
|
||||
|
||||
|
||||
Policy dump End.
|
||||
|
||||
Look at sHype output in xen dmesg:
|
||||
|
||||
[root@laptop xen]# xm dmesg
|
||||
.
|
||||
.
|
||||
[somewhere near the very end]
|
||||
(XEN) chwall_init_domain_ssid: determined chwall_ssidref to 1.
|
||||
(XEN) ste_init_domain_ssid.
|
||||
(XEN) ste_init_domain_ssid: determined ste_ssidref to 1.
|
||||
(XEN) acm_init_domain_ssid: Instantiated individual ssid for domain 0x01.
|
||||
(XEN) chwall_post_domain_create.
|
||||
(XEN) ste_pre_eventchannel_interdomain.
|
||||
(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01.
|
||||
(XEN) shype_authorize_domops.
|
||||
(XEN) ste_pre_eventchannel_interdomain.
|
||||
(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01.
|
||||
(XEN) ste_pre_eventchannel_interdomain.
|
||||
(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01.
|
||||
|
||||
|
||||
You can see that the chinese wall policy does not complain and that the ste
|
||||
policy makes three access control decisions for three event-channels setup
|
||||
between domain 0 and the new domain 1. Each time, the two domains share the
|
||||
type1 and setting up the eventchannel is permitted.
|
||||
|
||||
|
||||
Starting up a second domain xmsec2:
|
||||
|
||||
[root@laptop xen]# xm create -c xmsec2
|
||||
Using config file "xmsec2".
|
||||
Started domain xmsec2, console on port 9602
|
||||
************ REMOTE CONSOLE: CTRL-] TO QUIT ********
|
||||
Linux version 2.6.11-xenU (root@laptop.home.org) (gcc version 3.4.2 20041017
|
||||
(Red Hat 3.4.2-6.fc3)) #1 Wed Mar 30 13:14:31 EST 2005
|
||||
.
|
||||
.
|
||||
.
|
||||
[root@laptop policy]# xm list
|
||||
Name Id Mem(MB) CPU State Time(s) Console SSID-REF
|
||||
Domain-0 0 620 0 r---- 71.7 s:00/p:00
|
||||
xmsec1 1 9 0 -b--- 0.3 9601 s:01/p:01
|
||||
xmsec2 2 7 0 -b--- 0.3 9602 s:02/p:02 << our domain runs both policies with ssidref 2
|
||||
|
||||
|
||||
[root@laptop policy]# ./policy_tool getpolicy
|
||||
|
||||
Policy dump:
|
||||
============
|
||||
Magic = 1debc.
|
||||
PolVer = aaaa0000.
|
||||
Len = 112.
|
||||
Primary = CHINESE WALL policy (c=1, off=14).
|
||||
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8).
|
||||
|
||||
|
||||
Chinese Wall policy:
|
||||
====================
|
||||
Max Types = a.
|
||||
Max Ssidrefs = 5.
|
||||
Max ConfSets = 2.
|
||||
Ssidrefs Off = 10.
|
||||
Conflicts Off = 74.
|
||||
Runing T. Off = 9c.
|
||||
C. Agg. Off = b0.
|
||||
|
||||
SSID To CHWALL-Type matrix:
|
||||
|
||||
ssidref 0: 01 00 00 00 00 00 00 00 00 00
|
||||
ssidref 1: 00 01 00 00 00 00 00 00 00 00
|
||||
ssidref 2: 00 00 01 00 00 00 00 00 00 00 <<< our domain has type 2 set
|
||||
ssidref 3: 00 00 00 01 00 00 00 00 00 00
|
||||
ssidref 4: 00 00 00 00 01 00 00 00 00 00
|
||||
|
||||
Confict Sets:
|
||||
|
||||
c-set 0: 00 00 01 01 00 00 00 00 00 00 <<< t2 is in c-set0 with type 3
|
||||
c-set 1: 01 00 00 00 00 01 01 00 00 00
|
||||
|
||||
Running
|
||||
Types: 01 01 01 00 00 00 00 00 00 00 <<< t2 is running since the
|
||||
^^ <<< current aggregate conflict
|
||||
<<< set (see above) does not
|
||||
<<< include type 2
|
||||
Conflict
|
||||
Aggregate Set: 00 00 00 01 00 01 01 00 00 00 <<< type 3 is added to the
|
||||
<<< conflict aggregate
|
||||
|
||||
|
||||
Simple Type Enforcement policy:
|
||||
===============================
|
||||
Max Types = 5.
|
||||
Max Ssidrefs = 5.
|
||||
Ssidrefs Off = 8.
|
||||
|
||||
SSID To STE-Type matrix:
|
||||
|
||||
ssidref 0: 01 01 01 01 01
|
||||
ssidref 1: 00 01 00 00 00
|
||||
ssidref 2: 00 00 01 00 00
|
||||
ssidref 3: 00 00 00 01 00
|
||||
ssidref 4: 00 00 00 00 01
|
||||
|
||||
|
||||
Policy dump End.
|
||||
|
||||
|
||||
The sHype xen dmesg output looks similar to the one above when starting the
|
||||
first domain.
|
||||
|
||||
Now we start xmsec3 and it has ssidref3. Thus, it tries to run as type3 which
|
||||
conflicts with running type2 (from xmsec2). As expected, creating this domain
|
||||
fails for security policy enforcement reasons.
|
||||
|
||||
[root@laptop xen]# xm create -c xmsec3
|
||||
Using config file "xmsec3".
|
||||
Error: Error creating domain: (22, 'Invalid argument')
|
||||
[root@laptop xen]#
|
||||
|
||||
[root@laptop xen]# xm dmesg
|
||||
.
|
||||
.
|
||||
[somewhere near the very end]
|
||||
(XEN) chwall_pre_domain_create.
|
||||
(XEN) chwall_pre_domain_create: CHINESE WALL CONFLICT in type 03.
|
||||
|
||||
xmsec3 ssidref3 points to type3, which is in the current conflict aggregate
|
||||
set. This domain cannot start until domain xmsec2 is destroyed, at which time
|
||||
the aggregate conflict set is reduced and type3 is excluded from it. Then,
|
||||
xmsec3 can start. Of course, afterwards, xmsec2 cannot be restarted. Try it.
|
||||
|
||||
3. Policy tool
|
||||
**************
|
||||
toos/policy/policy_tool.c
|
||||
|
||||
a) ./policy_tool getpolicy
|
||||
prints the currently enforced policy
|
||||
(see for example section 1.)
|
||||
|
||||
b) ./policy_tool setpolicy
|
||||
sets a predefined and hardcoded security
|
||||
policy (the one described in section 2.)
|
||||
|
||||
c) ./policy_tool dumpstats
|
||||
prints some status information about the caching
|
||||
of access control decisions (number of cache hits
|
||||
and number of policy evaluations for grant_table
|
||||
and event channels).
|
||||
|
||||
d) ./policy_tool loadpolicy <binary_policy_file>
|
||||
sets the policy defined in the <binary_policy_file>
|
||||
please use the policy_processor that is posted to this
|
||||
mailing list to create such a binary policy from an XML
|
||||
policy description
|
||||
|
||||
4. Policy interface:
|
||||
********************
|
||||
The Policy interface is working in "network-byte-order" (big endian). The reason for this
|
||||
is that policy files/management should be portable and independent of the platforms.
|
||||
|
||||
Our policy interface enables managers to create a single binary policy file in a trusted
|
||||
environment and distributed it to multiple systems for enforcement.
|
||||
|
||||
====================end-of file=======================================
|
||||
@@ -623,7 +623,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
/* Only copy the packet if it fits in the current MTU. */
|
||||
if (skb->len <= (dev->mtu + ETH_HLEN)) {
|
||||
if ((skb->tail > skb->end) && net_ratelimit())
|
||||
printk(KERN_INFO "Received packet needs %d bytes more "
|
||||
printk(KERN_INFO "Received packet needs %zd bytes more "
|
||||
"headroom.\n", skb->tail - skb->end);
|
||||
|
||||
if ((nskb = alloc_xen_skb(skb->len + 2)) != NULL) {
|
||||
@@ -967,9 +967,9 @@ static int create_netdev(int handle, struct net_device **val)
|
||||
|
||||
/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
|
||||
for (i = 0; i <= NETIF_TX_RING_SIZE; i++)
|
||||
np->tx_skbs[i] = (void *)(i+1);
|
||||
np->tx_skbs[i] = (void *)((unsigned long) i+1);
|
||||
for (i = 0; i <= NETIF_RX_RING_SIZE; i++)
|
||||
np->rx_skbs[i] = (void *)(i+1);
|
||||
np->rx_skbs[i] = (void *)((unsigned long) i+1);
|
||||
|
||||
dev->open = network_open;
|
||||
dev->hard_start_xmit = network_start_xmit;
|
||||
@@ -1343,7 +1343,7 @@ static int xennet_proc_read(
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL);
|
||||
struct net_private *np = netdev_priv(dev);
|
||||
int len = 0, which_target = (int)data & 3;
|
||||
int len = 0, which_target = (unsigned long) data & 3;
|
||||
|
||||
switch (which_target)
|
||||
{
|
||||
@@ -1368,7 +1368,7 @@ static int xennet_proc_write(
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL);
|
||||
struct net_private *np = netdev_priv(dev);
|
||||
int which_target = (int)data & 3;
|
||||
int which_target = (unsigned long) data & 3;
|
||||
char string[64];
|
||||
long target;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ SUBDIRS += xcs
|
||||
SUBDIRS += xcutils
|
||||
SUBDIRS += pygrub
|
||||
SUBDIRS += firmware
|
||||
SUBDIRS += policy
|
||||
|
||||
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ int xc_waitdomain_core(int domain,
|
||||
|
||||
typedef struct {
|
||||
u32 domid;
|
||||
u32 ssidref;
|
||||
unsigned int dying:1, crashed:1, shutdown:1,
|
||||
paused:1, blocked:1, running:1;
|
||||
unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
|
||||
@@ -124,6 +125,7 @@ typedef struct {
|
||||
|
||||
typedef dom0_getdomaininfo_t xc_domaininfo_t;
|
||||
int xc_domain_create(int xc_handle,
|
||||
u32 ssidref,
|
||||
u32 *pdomid);
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "xc_private.h"
|
||||
|
||||
int xc_domain_create(int xc_handle,
|
||||
u32 ssidref,
|
||||
u32 *pdomid)
|
||||
{
|
||||
int err;
|
||||
@@ -16,6 +17,7 @@ int xc_domain_create(int xc_handle,
|
||||
|
||||
op.cmd = DOM0_CREATEDOMAIN;
|
||||
op.u.createdomain.domain = (domid_t)*pdomid;
|
||||
op.u.createdomain.ssidref = ssidref;
|
||||
if ( (err = do_dom0_op(xc_handle, &op)) != 0 )
|
||||
return err;
|
||||
|
||||
@@ -101,6 +103,7 @@ int xc_domain_getinfo(int xc_handle,
|
||||
info->crashed = 1;
|
||||
}
|
||||
|
||||
info->ssidref = op.u.getdomaininfo.ssidref;
|
||||
info->nr_pages = op.u.getdomaininfo.tot_pages;
|
||||
info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT);
|
||||
info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* (C) Copyright IBM Corp. 2005
|
||||
*
|
||||
* $Id: SecurityLabel.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $
|
||||
*
|
||||
* Author: Ray Valdez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* SecurityLabel Class.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* Keeps track of types.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
import java.util.*;
|
||||
public class SecurityLabel
|
||||
{
|
||||
Vector ids;
|
||||
Vector vlans;
|
||||
Vector slots;
|
||||
Vector steTypes;
|
||||
int steSsidPosition;
|
||||
Vector chwIDs;
|
||||
Vector chwTypes;
|
||||
int chwSsidPosition;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Author: Ray Valdez, rvaldez@us.ibm.com -->
|
||||
<!-- xml schema definition for xen xml policies -->
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://www.ibm.com"
|
||||
xmlns="http://www.ibm.com"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<xsd:element name="TE" type="xsd:string" />
|
||||
<xsd:element name="ChWall" type="xsd:string" />
|
||||
|
||||
<xsd:element name="Definition">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
|
||||
<!-- simple type enforcement -->
|
||||
<xsd:element name="Types" minOccurs ="0" maxOccurs="1">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="TE" minOccurs ="1" maxOccurs ="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<!-- chinese wall -->
|
||||
<!-- type definition -->
|
||||
<xsd:element name="ChWallTypes" minOccurs ="0" maxOccurs="1">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="ChWall" minOccurs ="1" maxOccurs ="unbounded"/>
|
||||
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<!-- conflict set -->
|
||||
<xsd:element name="ConflictSet" minOccurs ="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="ChWall" minOccurs ="2" maxOccurs ="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="Policy">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
|
||||
<xsd:element name="PolicyHeader">
|
||||
<xsd:complexType>
|
||||
<xsd:all>
|
||||
<xsd:element name = "Name" type="xsd:string"/>
|
||||
<xsd:element name = "DateTime" type="xsd:dateTime"/>
|
||||
<xsd:element name = "Tag" minOccurs ="1" maxOccurs ="1" type="xsd:string"/>
|
||||
<xsd:element name = "TypeDefinition">
|
||||
<xsd:complexType>
|
||||
<xsd:all>
|
||||
<xsd:element name = "url" type="xsd:string"/>
|
||||
<xsd:element name = "hash" minOccurs ="0" maxOccurs ="1" type="xsd:string"/>
|
||||
</xsd:all>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:all>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="VM" minOccurs ="1" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="id" type="xsd:integer"/>
|
||||
<xsd:element ref="TE" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element ref="ChWall" minOccurs ="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="Vlan" minOccurs ="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="vid" type="xsd:integer"/>
|
||||
<xsd:element ref="TE" minOccurs="1" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="Slot" minOccurs ="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="bus" type="xsd:integer"/>
|
||||
<xsd:element name="slot" type="xsd:integer"/>
|
||||
<xsd:element ref="TE" minOccurs="1" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<!-- root element -->
|
||||
<xsd:element name="SecurityPolicySpec">
|
||||
<xsd:complexType>
|
||||
<xsd:choice>
|
||||
<xsd:element ref="Definition" minOccurs ="1" maxOccurs="unbounded"/>
|
||||
<xsd:element ref="Policy" minOccurs ="1" maxOccurs="unbounded"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* (C) Copyright IBM Corp. 2005
|
||||
*
|
||||
* $Id: SsidsEntry.java,v 1.2 2005/06/17 20:02:40 rvaldez Exp $
|
||||
*
|
||||
* Author: Ray Valdez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* SsidsEntry Class.
|
||||
* <p>
|
||||
*
|
||||
* Holds ssid information.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SsidsEntry
|
||||
{
|
||||
int id; /* used for partition and vlan */
|
||||
int bus; /* used for slots */
|
||||
int slot;
|
||||
int ste = 0xffffffff;
|
||||
int chw = 0xffffffff;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* (C) Copyright IBM Corp. 2005
|
||||
*
|
||||
* $Id: XmlToBinInterface.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $
|
||||
*
|
||||
* Author: Ray Valdez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* XmlToBinInterface Class.
|
||||
* <p>
|
||||
*
|
||||
* Defines constants used by XmToBin.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* policy binary structures
|
||||
*
|
||||
* typedef struct {
|
||||
* u32 magic;
|
||||
*
|
||||
* u32 policyversion;
|
||||
* u32 len;
|
||||
*
|
||||
* u16 primary_policy_code;
|
||||
* u16 primary_buffer_offset;
|
||||
* u16 secondary_policy_code;
|
||||
* u16 secondary_buffer_offset;
|
||||
* u16 resource_offset;
|
||||
*
|
||||
* } acm_policy_buffer_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 policy_code;
|
||||
* u16 ste_max_types;
|
||||
* u16 ste_max_ssidrefs;
|
||||
* u16 ste_ssid_offset;
|
||||
* } acm_ste_policy_buffer_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* uint16 policy_code;
|
||||
* uint16 chwall_max_types;
|
||||
* uint16 chwall_max_ssidrefs;
|
||||
* uint16 chwall_max_conflictsets;
|
||||
* uint16 chwall_ssid_offset;
|
||||
* uint16 chwall_conflict_sets_offset;
|
||||
* uint16 chwall_running_types_offset;
|
||||
* uint16 chwall_conflict_aggregate_offset;
|
||||
* } acm_chwall_policy_buffer_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 partition_max;
|
||||
* u16 partition_offset;
|
||||
* u16 vlan_max;
|
||||
* u16 vlan_offset;
|
||||
* u16 slot_max;
|
||||
* u16 slot_offset;
|
||||
* } acm_resource_buffer_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 id;
|
||||
* u16 ssid_ste;
|
||||
* u16 ssid_chwall;
|
||||
* } acm_partition_entry_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 vlan;
|
||||
* u16 ssid_ste;
|
||||
* } acm_vlan_entry_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 bus;
|
||||
* u16 slot;
|
||||
* u16 ssid_ste;
|
||||
* } acm_slot_entry_t;
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface XmlToBinInterface
|
||||
{
|
||||
/* policy code (uint16) */
|
||||
final int policyCodeSize = 2;
|
||||
|
||||
/* max_types (uint16) */
|
||||
final int maxTypesSize = 2;
|
||||
|
||||
/* max_ssidrefs (uint16) */
|
||||
final int maxSsidrefSize = 2;
|
||||
|
||||
/* ssid_offset (uint32) */
|
||||
final int ssidOffsetSize = 2;
|
||||
|
||||
final short markSymbol = 0x0001;
|
||||
|
||||
final int u32Size = 4;
|
||||
final int u16Size = 2;
|
||||
|
||||
/* num of bytes for acm_ste_policy_buffer_t */
|
||||
final short steHeaderSize = (4 * u16Size);
|
||||
/* byte for acm_chinese_wall_policy_buffer_t */
|
||||
final short chwHeaderSize = (8 * u16Size);
|
||||
|
||||
final short primaryPolicyCodeSize = u16Size;
|
||||
final short primaryBufferOffsetSize = u16Size ;
|
||||
|
||||
final int secondaryPolicyCodeSz = u16Size;
|
||||
final int secondaryBufferOffsetSz = u16Size;
|
||||
final short resourceOffsetSz = u16Size;
|
||||
|
||||
final short partitionBufferSz = (2 * u16Size);
|
||||
final short partitionEntrySz = (3 * u16Size);
|
||||
|
||||
final short slotBufferSz = (2 * u16Size);
|
||||
final short slotEntrySz = (3 * u16Size);
|
||||
|
||||
final short vlanBufferSz = (2 * u16Size);
|
||||
final short vlanEntrySz = (2 * u16Size);
|
||||
|
||||
final short binaryBufferHeaderSz = (3 * u32Size + 4* u16Size);
|
||||
|
||||
/* copied directlty from policy_ops.h */
|
||||
final int POLICY_INTERFACE_VERSION = 0xAAAA0000;
|
||||
|
||||
/* copied directly from acm.h */
|
||||
final int ACM_MAGIC = 0x0001debc;
|
||||
final short ACM_NULL_POLICY = 0;
|
||||
final short ACM_CHINESE_WALL_POLICY = 1;
|
||||
final short ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2;
|
||||
final short ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY = 3;
|
||||
final short ACM_EMPTY_POLICY = 4;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* (C) Copyright IBM Corp. 2005
|
||||
*
|
||||
* $Id: myHandler.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $
|
||||
*
|
||||
* Author: Ray Valdez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* myHandler Class.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* A dummy class used for detecting XML validating/parsing errors.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
import org.xml.sax.helpers.*;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
class myHandler extends DefaultHandler
|
||||
{
|
||||
public boolean isValid = true;
|
||||
|
||||
/* Notification of a recoverable error. */
|
||||
public void error(SAXParseException se)
|
||||
{
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
/* Notification of a non-recoverable error. */
|
||||
public void fatalError(SAXParseException se)
|
||||
{
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
/* Notification of a warning. */
|
||||
public void warning(SAXParseException se)
|
||||
{
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# Author: Ray Valdez, rvaldez@us.ibm.com
|
||||
# Version: 1.0
|
||||
#
|
||||
# install readme
|
||||
#
|
||||
PREREQUISITES:
|
||||
|
||||
Prior to installation of the policy processor tool (XmlToBin) you must have...
|
||||
|
||||
1. Java version 1.4.2
|
||||
2. xmlParserAPIs.jar and xercesImpl.jar
|
||||
|
||||
The above can be obtained from the Sun Developer Network web site at
|
||||
http://java.sun.com/j2se/1.4.2/download.html.
|
||||
|
||||
XmlParserAPIs and xercesImpl jars can be obtained from
|
||||
http://www.apache.org/dist/xml/xerces-j (Xerces-J-bin.2.6.2.tar.gz,
|
||||
for example).
|
||||
|
||||
The tool has been tested with J2SE v1.4.2_08 JRE on Linux (32-bit
|
||||
INTEL).
|
||||
|
||||
INSTALLATION
|
||||
|
||||
1. Set PATH to include $HOME_JAVA/bin and $HOME_JAVA/jre/bin
|
||||
where $HOME_JAVA is your java installation directory
|
||||
|
||||
2. Compile XmlToBin:
|
||||
javac XmlToBin.java
|
||||
|
||||
USAGE
|
||||
|
||||
See readme.xen
|
||||
@@ -0,0 +1,65 @@
|
||||
# Author: Ray Valdez, rvaldez@us.ibm.com
|
||||
# Version: 1.0
|
||||
#
|
||||
# This readme describes the policy processor tool for sHype.
|
||||
#
|
||||
|
||||
Java program:
|
||||
|
||||
java XmlToBin -i [file.xml] -o <file.bin> -xssid <SsidFile> -xssidconf <SsidConf>
|
||||
|
||||
Command line options:
|
||||
|
||||
-i inputFile: name of policyfile (.xml)
|
||||
-o outputFile: name of binary policy file (Big Endian)
|
||||
-xssid SsidFile: xen ssids to named types text file
|
||||
-xssidconf SsidConf: xen conflict ssids to types text file
|
||||
-debug turn on debug messages
|
||||
-help help. This printout
|
||||
|
||||
Where:
|
||||
|
||||
file.xml is the (input) xml policy file to be parsed and validated.
|
||||
The syntax for file.xml is defined in the SecurityPolicySpec.xsd file.
|
||||
file.bin is the (output) binary policy file generated by XmlToBin.
|
||||
This binary policy can be activated in sHype. The binary policy file
|
||||
is laid out in network byte order (i.e., big endian). The SsidFile
|
||||
file contains the mapping of type enforcement (TE) ssids to the "named
|
||||
types". Similarly, the SsidConf file contains the mapping of Chinese
|
||||
Wall (ChWall) ssids to conflict named types. The ssidFile and SsidConf
|
||||
files are used by Xen.
|
||||
|
||||
Xml Schema and policy:
|
||||
|
||||
The SecurityPolicySpec.xsd defines the syntax of a policy file. It
|
||||
declares the tags that are used by XmlToBin to generate the binary
|
||||
policy file. The tags that XmlToBin keys on are TE, ChWall, id, vid,
|
||||
etc. The xml files that describe a policy are simple. Semantic
|
||||
checking of a policy is performed mostly by XmlToBin. A type, for
|
||||
example, is a string. No fixed values are defined for types in Xml.
|
||||
|
||||
A policy consists of two Xml files: definition and policy. The
|
||||
definition Xml declares the types that are permitted in the policy
|
||||
Xml. The policy Xml contains the assignment of labels to
|
||||
subject/object (e.g., vm). This Xml file contains an explicit
|
||||
reference to the definition Xml (e.g., <url>xen_sample_def.xml</url>).
|
||||
The policy Xml is the one provided as a command line argument.
|
||||
|
||||
|
||||
Files:
|
||||
|
||||
*.java - policy processor source
|
||||
xen_sample_policy.xml - sample xml policy file
|
||||
xen_sample_def.xml - sample user defined types
|
||||
SecurityPolicySpec.xsd - schema definition file
|
||||
|
||||
|
||||
To generate the sample binary policy:
|
||||
|
||||
export CLASSPATH=$XERCES_HOME/xercesImpl.jar:$XERCES_HOME/xmlParserAPIs.jar:.
|
||||
|
||||
java XmlToBin -i xen_sample_policy.xml -o xen_sample_policy.bin
|
||||
|
||||
where $XERCES_HOME is the installation directory of the Apache Xerces-J
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Author: Ray Valdez, rvaldez@us.ibm.com -->
|
||||
<!-- example policy type definition -->
|
||||
<SecurityPolicySpec
|
||||
xmlns="http://www.ibm.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd">
|
||||
|
||||
<Definition>
|
||||
<!-- an example of a simple type enforcement type definition -->
|
||||
<Types>
|
||||
<TE>LOCAL-management</TE>
|
||||
<TE>R-Company-development</TE>
|
||||
<TE>S-Company-order</TE>
|
||||
<TE>T-Company-advertising</TE>
|
||||
<TE>U-Company-computing</TE>
|
||||
<!-- TE nondevelopment -->
|
||||
</Types>
|
||||
|
||||
<!-- an example of a chinese wall type definition along with conflict sets-->
|
||||
<ChWallTypes>
|
||||
<ChWall>Q-Company</ChWall>
|
||||
<ChWall>R-Company</ChWall>
|
||||
<ChWall>S-Company</ChWall>
|
||||
<ChWall>T-Company</ChWall>
|
||||
<ChWall>U-Company</ChWall>
|
||||
<ChWall>V-Company</ChWall>
|
||||
<ChWall>W-Company</ChWall>
|
||||
<ChWall>X-Company</ChWall>
|
||||
<ChWall>Y-Company</ChWall>
|
||||
<ChWall>Z-Company</ChWall>
|
||||
</ChWallTypes>
|
||||
|
||||
<ConflictSet>
|
||||
<ChWall>T-Company</ChWall>
|
||||
<ChWall>S-Company</ChWall>
|
||||
</ConflictSet>
|
||||
|
||||
<ConflictSet>
|
||||
<ChWall>Q-Company</ChWall>
|
||||
<ChWall>V-Company</ChWall>
|
||||
<ChWall>W-Company</ChWall>
|
||||
</ConflictSet>
|
||||
|
||||
</Definition>
|
||||
</SecurityPolicySpec>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Author: Ray Valdez, rvaldez@us.ibm.com -->
|
||||
<!-- example xen policy file -->
|
||||
|
||||
<SecurityPolicySpec
|
||||
xmlns="http://www.ibm.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd">
|
||||
<Policy>
|
||||
<PolicyHeader>
|
||||
<Name>xen sample policy</Name>
|
||||
<DateTime>2005-05-20T16:56:00</DateTime>
|
||||
<Tag>foobar</Tag>
|
||||
<TypeDefinition>
|
||||
<url>xen_sample_def.xml</url>
|
||||
<hash>abcdef123456abcdef</hash>
|
||||
</TypeDefinition>
|
||||
</PolicyHeader>
|
||||
|
||||
<VM>
|
||||
<id> 0 </id>
|
||||
<TE>LOCAL-management</TE>
|
||||
<TE>R-Company-development</TE>
|
||||
<TE>S-Company-order</TE>
|
||||
<TE>T-Company-advertising</TE>
|
||||
<TE>U-Company-computing</TE>
|
||||
<ChWall>Q-Company</ChWall>
|
||||
</VM>
|
||||
|
||||
<VM>
|
||||
<id> 1 </id>
|
||||
<TE>R-Company-development</TE>
|
||||
<ChWall>R-Company</ChWall>
|
||||
</VM>
|
||||
|
||||
<VM>
|
||||
<id> 2 </id>
|
||||
<TE>S-Company-order</TE>
|
||||
<ChWall>S-Company</ChWall>
|
||||
|
||||
</VM>
|
||||
|
||||
<VM>
|
||||
<id> 3 </id>
|
||||
<TE>T-Company-advertising</TE>
|
||||
<ChWall>T-Company</ChWall>
|
||||
</VM>
|
||||
|
||||
|
||||
<VM>
|
||||
<id> 4 </id>
|
||||
<TE>U-Company-computing</TE>
|
||||
<ChWall>U-Company</ChWall>
|
||||
</VM>
|
||||
|
||||
|
||||
</Policy>
|
||||
</SecurityPolicySpec>
|
||||
@@ -0,0 +1,36 @@
|
||||
XEN_ROOT = ../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
SRCS = policy_tool.c
|
||||
CFLAGS += -static
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -O3
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -I.
|
||||
|
||||
all: build
|
||||
build: mk-symlinks
|
||||
$(MAKE) policy_tool
|
||||
|
||||
default: all
|
||||
|
||||
install: all
|
||||
|
||||
policy_tool : policy_tool.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf policy_tool xen
|
||||
|
||||
|
||||
LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
|
||||
mk-symlinks:
|
||||
[ -e xen/linux ] || mkdir -p xen/linux
|
||||
[ -e xen/io ] || mkdir -p xen/io
|
||||
( cd xen >/dev/null ; \
|
||||
ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . )
|
||||
( cd xen/io >/dev/null ; \
|
||||
ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . )
|
||||
( cd xen/linux >/dev/null ; \
|
||||
ln -sf ../../$(LINUX_ROOT)/include/asm-xen/linux-public/*.h . )
|
||||
@@ -0,0 +1,557 @@
|
||||
/****************************************************************
|
||||
* policy_tool.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype policy management tool. This code runs in a domain and
|
||||
* manages the Xen security policy by interacting with the
|
||||
* Xen access control module via a /proc/xen/policycmd proc-ioctl,
|
||||
* which is translated into a policy_op hypercall into Xen.
|
||||
*
|
||||
* todo: implement setpolicy to dynamically set a policy cache.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
#include <xen/acm.h>
|
||||
|
||||
#include <xen/policy_ops.h>
|
||||
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
#define ERROR(_m, _a...) \
|
||||
fprintf(stderr, "ERROR: " _m "\n" , ## _a )
|
||||
|
||||
#define PERROR(_m, _a...) \
|
||||
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
|
||||
errno, strerror(errno))
|
||||
|
||||
static inline int do_policycmd(int xc_handle,
|
||||
unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
return ioctl(xc_handle, cmd, data);
|
||||
}
|
||||
|
||||
static inline int do_xen_hypercall(int xc_handle,
|
||||
privcmd_hypercall_t *hypercall)
|
||||
{
|
||||
return do_policycmd(xc_handle,
|
||||
IOCTL_PRIVCMD_HYPERCALL,
|
||||
(unsigned long)hypercall);
|
||||
}
|
||||
|
||||
static inline int do_policy_op(int xc_handle, policy_op_t *op)
|
||||
{
|
||||
int ret = -1;
|
||||
privcmd_hypercall_t hypercall;
|
||||
|
||||
op->interface_version = POLICY_INTERFACE_VERSION;
|
||||
|
||||
hypercall.op = __HYPERVISOR_policy_op;
|
||||
hypercall.arg[0] = (unsigned long)op;
|
||||
|
||||
if ( mlock(op, sizeof(*op)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock memory for Xen policy hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
|
||||
{
|
||||
if ( errno == EACCES )
|
||||
fprintf(stderr, "POLICY operation failed -- need to"
|
||||
" rebuild the user-space tool set?\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
out2: (void)munlock(op, sizeof(*op));
|
||||
out1: return ret;
|
||||
}
|
||||
|
||||
/*************************** DUMPS *******************************/
|
||||
|
||||
void acm_dump_chinesewall_buffer(void *buf, int buflen) {
|
||||
|
||||
struct acm_chwall_policy_buffer *cwbuf = (struct acm_chwall_policy_buffer *)buf;
|
||||
domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
|
||||
int i,j;
|
||||
|
||||
|
||||
if (htons(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) {
|
||||
printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
|
||||
return;
|
||||
}
|
||||
printf("\n\nChinese Wall policy:\n");
|
||||
printf("====================\n");
|
||||
printf("Max Types = %x.\n", ntohs(cwbuf->chwall_max_types));
|
||||
printf("Max Ssidrefs = %x.\n", ntohs(cwbuf->chwall_max_ssidrefs));
|
||||
printf("Max ConfSets = %x.\n", ntohs(cwbuf->chwall_max_conflictsets));
|
||||
printf("Ssidrefs Off = %x.\n", ntohs(cwbuf->chwall_ssid_offset));
|
||||
printf("Conflicts Off = %x.\n", ntohs(cwbuf->chwall_conflict_sets_offset));
|
||||
printf("Runing T. Off = %x.\n", ntohs(cwbuf->chwall_running_types_offset));
|
||||
printf("C. Agg. Off = %x.\n", ntohs(cwbuf->chwall_conflict_aggregate_offset));
|
||||
printf("\nSSID To CHWALL-Type matrix:\n");
|
||||
|
||||
ssids = (domaintype_t *)(buf + ntohs(cwbuf->chwall_ssid_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_ssidrefs); i++) {
|
||||
printf("\n ssidref%2x: ", i);
|
||||
for(j=0; j< ntohs(cwbuf->chwall_max_types); j++)
|
||||
printf("%02x ", ntohs(ssids[i*ntohs(cwbuf->chwall_max_types) + j]));
|
||||
}
|
||||
printf("\n\nConfict Sets:\n");
|
||||
conflicts = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_sets_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_conflictsets); i++) {
|
||||
printf("\n c-set%2x: ", i);
|
||||
for(j=0; j< ntohs(cwbuf->chwall_max_types); j++)
|
||||
printf("%02x ", ntohs(conflicts[i*ntohs(cwbuf->chwall_max_types) +j]));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("\nRunning\nTypes: ");
|
||||
if (ntohs(cwbuf->chwall_running_types_offset)) {
|
||||
running_types = (domaintype_t *)(buf + ntohs(cwbuf->chwall_running_types_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) {
|
||||
printf("%02x ", ntohs(running_types[i]));
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Not Reported!\n");
|
||||
}
|
||||
printf("\nConflict\nAggregate Set: ");
|
||||
if (ntohs(cwbuf->chwall_conflict_aggregate_offset)) {
|
||||
conflict_aggregate = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_aggregate_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) {
|
||||
printf("%02x ", ntohs(conflict_aggregate[i]));
|
||||
}
|
||||
printf("\n\n");
|
||||
} else {
|
||||
printf("Not Reported!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void acm_dump_ste_buffer(void *buf, int buflen) {
|
||||
|
||||
struct acm_ste_policy_buffer *stebuf = (struct acm_ste_policy_buffer *)buf;
|
||||
domaintype_t *ssids;
|
||||
int i,j;
|
||||
|
||||
|
||||
if (ntohs(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
|
||||
printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
|
||||
return;
|
||||
}
|
||||
printf("\nSimple Type Enforcement policy:\n");
|
||||
printf("===============================\n");
|
||||
printf("Max Types = %x.\n", ntohs(stebuf->ste_max_types));
|
||||
printf("Max Ssidrefs = %x.\n", ntohs(stebuf->ste_max_ssidrefs));
|
||||
printf("Ssidrefs Off = %x.\n", ntohs(stebuf->ste_ssid_offset));
|
||||
printf("\nSSID To STE-Type matrix:\n");
|
||||
|
||||
ssids = (domaintype_t *)(buf + ntohs(stebuf->ste_ssid_offset));
|
||||
for(i=0; i< ntohs(stebuf->ste_max_ssidrefs); i++) {
|
||||
printf("\n ssidref%2x: ", i);
|
||||
for(j=0; j< ntohs(stebuf->ste_max_types); j++)
|
||||
printf("%02x ", ntohs(ssids[i*ntohs(stebuf->ste_max_types) +j]));
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
void acm_dump_policy_buffer(void *buf, int buflen) {
|
||||
struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
|
||||
|
||||
printf("\nPolicy dump:\n");
|
||||
printf("============\n");
|
||||
printf("Magic = %x.\n", ntohl(pol->magic));
|
||||
printf("PolVer = %x.\n", ntohl(pol->policyversion));
|
||||
printf("Len = %x.\n", ntohl(pol->len));
|
||||
printf("Primary = %s (c=%x, off=%x).\n",
|
||||
ACM_POLICY_NAME(ntohs(pol->primary_policy_code)),
|
||||
ntohs(pol->primary_policy_code), ntohs(pol->primary_buffer_offset));
|
||||
printf("Secondary = %s (c=%x, off=%x).\n",
|
||||
ACM_POLICY_NAME(ntohs(pol->secondary_policy_code)),
|
||||
ntohs(pol->secondary_policy_code), ntohs(pol->secondary_buffer_offset));
|
||||
switch (ntohs(pol->primary_policy_code)) {
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
acm_dump_chinesewall_buffer(buf+ntohs(pol->primary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->primary_buffer_offset));
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
acm_dump_ste_buffer(buf+ntohs(pol->primary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->primary_buffer_offset));
|
||||
break;
|
||||
case ACM_NULL_POLICY:
|
||||
printf("Primary policy is NULL Policy (n/a).\n");
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN POLICY!\n");
|
||||
}
|
||||
switch (ntohs(pol->secondary_policy_code)) {
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
acm_dump_chinesewall_buffer(buf+ntohs(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->secondary_buffer_offset));
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
acm_dump_ste_buffer(buf+ntohs(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->secondary_buffer_offset));
|
||||
break;
|
||||
case ACM_NULL_POLICY:
|
||||
printf("Secondary policy is NULL Policy (n/a).\n");
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN POLICY!\n");
|
||||
}
|
||||
printf("\nPolicy dump End.\n\n");
|
||||
}
|
||||
|
||||
/*************************** set policy ****************************/
|
||||
|
||||
int acm_domain_set_chwallpolicy(void *bufstart, int buflen) {
|
||||
#define CWALL_MAX_SSIDREFS 5
|
||||
#define CWALL_MAX_TYPES 10
|
||||
#define CWALL_MAX_CONFLICTSETS 2
|
||||
|
||||
struct acm_chwall_policy_buffer *chwall_bin_pol = (struct acm_chwall_policy_buffer *)bufstart;
|
||||
domaintype_t *ssidrefs, *conflicts;
|
||||
int ret = 0;
|
||||
int i,j;
|
||||
|
||||
chwall_bin_pol->chwall_max_types = htons(CWALL_MAX_TYPES);
|
||||
chwall_bin_pol->chwall_max_ssidrefs = htons(CWALL_MAX_SSIDREFS);
|
||||
chwall_bin_pol->policy_code = htons(ACM_CHINESE_WALL_POLICY);
|
||||
chwall_bin_pol->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
|
||||
chwall_bin_pol->chwall_max_conflictsets = htons(CWALL_MAX_CONFLICTSETS);
|
||||
chwall_bin_pol->chwall_conflict_sets_offset =
|
||||
htons(
|
||||
ntohs(chwall_bin_pol->chwall_ssid_offset) +
|
||||
sizeof(domaintype_t)*CWALL_MAX_SSIDREFS*CWALL_MAX_TYPES);
|
||||
chwall_bin_pol->chwall_running_types_offset = 0; /* not set */
|
||||
chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */
|
||||
ret += sizeof(struct acm_chwall_policy_buffer);
|
||||
/* now push example ssids into the buffer (max_ssidrefs x max_types entries) */
|
||||
/* check buffer size */
|
||||
if ((buflen - ret) < (CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
ssidrefs = (domaintype_t *)(bufstart+ntohs(chwall_bin_pol->chwall_ssid_offset));
|
||||
for(i=0; i< CWALL_MAX_SSIDREFS; i++) {
|
||||
for (j=0; j< CWALL_MAX_TYPES; j++)
|
||||
ssidrefs[i*CWALL_MAX_TYPES + j] = htons(0);
|
||||
/* here, set type i for ssidref i; generally, a ssidref can have multiple chwall types */
|
||||
if (i < CWALL_MAX_SSIDREFS)
|
||||
ssidrefs[i*CWALL_MAX_TYPES + i] = htons(1);
|
||||
}
|
||||
ret += CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t);
|
||||
if ((buflen - ret) < (CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
/* now the chinese wall policy conflict sets*/
|
||||
conflicts = (domaintype_t *)(bufstart +
|
||||
ntohs(chwall_bin_pol->chwall_conflict_sets_offset));
|
||||
memset((void *)conflicts, 0, CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t));
|
||||
/* just 1 conflict set [0]={2,3}, [1]={0,5,6} */
|
||||
if (CWALL_MAX_TYPES > 3) {
|
||||
conflicts[2] = htons(1); conflicts[3] = htons(1); /* {2,3} */
|
||||
conflicts[CWALL_MAX_TYPES] = htons(1); conflicts[CWALL_MAX_TYPES+5] = htons(1);
|
||||
conflicts[CWALL_MAX_TYPES+6] = htons(1);/* {0,5,6} */
|
||||
}
|
||||
ret += sizeof(domaintype_t)*CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int acm_domain_set_stepolicy(void *bufstart, int buflen) {
|
||||
#define STE_MAX_SSIDREFS 5
|
||||
#define STE_MAX_TYPES 5
|
||||
|
||||
struct acm_ste_policy_buffer *ste_bin_pol = (struct acm_ste_policy_buffer *)bufstart;
|
||||
domaintype_t *ssidrefs;
|
||||
int i,j, ret = 0;
|
||||
|
||||
ste_bin_pol->ste_max_types = htons(STE_MAX_TYPES);
|
||||
ste_bin_pol->ste_max_ssidrefs = htons(STE_MAX_SSIDREFS);
|
||||
ste_bin_pol->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
ste_bin_pol->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
|
||||
ret += sizeof(struct acm_ste_policy_buffer);
|
||||
/* check buffer size */
|
||||
if ((buflen - ret) < (STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
ssidrefs = (domaintype_t *)(bufstart+ntohs(ste_bin_pol->ste_ssid_offset));
|
||||
for(i=0; i< STE_MAX_SSIDREFS; i++) {
|
||||
for (j=0; j< STE_MAX_TYPES; j++)
|
||||
ssidrefs[i*STE_MAX_TYPES + j] = htons(0);
|
||||
/* set type i in ssidref 0 and ssidref i */
|
||||
ssidrefs[i] = htons(1); /* ssidref 0 has all types set */
|
||||
if (i < STE_MAX_SSIDREFS)
|
||||
ssidrefs[i*STE_MAX_TYPES + i] = htons(1);
|
||||
}
|
||||
ret += STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_PUSH_BUFFER 16384
|
||||
u8 push_buffer[MAX_PUSH_BUFFER];
|
||||
|
||||
int acm_domain_setpolicy(int xc_handle)
|
||||
{
|
||||
int ret;
|
||||
struct acm_policy_buffer *bin_pol;
|
||||
policy_op_t op;
|
||||
|
||||
/* future: read policy from file and set it */
|
||||
bin_pol = (struct acm_policy_buffer *)push_buffer;
|
||||
bin_pol->magic = htonl(ACM_MAGIC);
|
||||
bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION);
|
||||
bin_pol->primary_policy_code = htons(ACM_CHINESE_WALL_POLICY);
|
||||
bin_pol->secondary_policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
|
||||
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
|
||||
bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
ret = acm_domain_set_chwallpolicy(push_buffer + ntohs(bin_pol->primary_buffer_offset),
|
||||
MAX_PUSH_BUFFER - ntohs(bin_pol->primary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printf("ERROR creating chwallpolicy buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
ret = acm_domain_set_stepolicy(push_buffer + ntohs(bin_pol->secondary_buffer_offset),
|
||||
MAX_PUSH_BUFFER - ntohs(bin_pol->secondary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printf("ERROR creating chwallpolicy buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
|
||||
/* dump it and then push it down into xen/acm */
|
||||
acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len));
|
||||
op.cmd = POLICY_SETPOLICY;
|
||||
op.u.setpolicy.pushcache = (void *)push_buffer;
|
||||
op.u.setpolicy.pushcache_size = ntohl(bin_pol->len);
|
||||
op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY;
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
|
||||
if (ret)
|
||||
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
||||
else
|
||||
printf("Successfully changed policy.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************* get policy ******************************/
|
||||
|
||||
#define PULL_CACHE_SIZE 8192
|
||||
u8 pull_buffer[PULL_CACHE_SIZE];
|
||||
int acm_domain_getpolicy(int xc_handle)
|
||||
{
|
||||
policy_op_t op;
|
||||
int ret;
|
||||
|
||||
memset(pull_buffer, 0x00, sizeof(pull_buffer));
|
||||
op.cmd = POLICY_GETPOLICY;
|
||||
op.u.getpolicy.pullcache = (void *)pull_buffer;
|
||||
op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
/* dump policy */
|
||||
acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************ load binary policy ******************************/
|
||||
|
||||
int acm_domain_loadpolicy(int xc_handle,
|
||||
const char *filename)
|
||||
{
|
||||
struct stat mystat;
|
||||
int ret, fd;
|
||||
off_t len;
|
||||
u8 *buffer;
|
||||
|
||||
if ((ret = stat(filename, &mystat))) {
|
||||
printf("File %s not found.\n",filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = mystat.st_size;
|
||||
if ((buffer = malloc(len)) == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if ((fd = open(filename, O_RDONLY)) <= 0) {
|
||||
ret = -ENOENT;
|
||||
printf("File %s not found.\n",filename);
|
||||
goto free_out;
|
||||
}
|
||||
if (len == read(fd, buffer, len)) {
|
||||
policy_op_t op;
|
||||
/* dump it and then push it down into xen/acm */
|
||||
acm_dump_policy_buffer(buffer, len);
|
||||
op.cmd = POLICY_SETPOLICY;
|
||||
op.u.setpolicy.pushcache = (void *)buffer;
|
||||
op.u.setpolicy.pushcache_size = len;
|
||||
op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY;
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
|
||||
if (ret)
|
||||
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
||||
else
|
||||
printf("Successfully changed policy.\n");
|
||||
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
close(fd);
|
||||
free_out:
|
||||
free(buffer);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************ dump hook statistics ******************************/
|
||||
void
|
||||
dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
|
||||
{
|
||||
printf("STE-Policy Security Hook Statistics:\n");
|
||||
printf("ste: event_channel eval_count = %d\n", ntohl(ste_stats->ec_eval_count));
|
||||
printf("ste: event_channel denied_count = %d\n", ntohl(ste_stats->ec_denied_count));
|
||||
printf("ste: event_channel cache_hit_count = %d\n", ntohl(ste_stats->ec_cachehit_count));
|
||||
printf("ste:\n");
|
||||
printf("ste: grant_table eval_count = %d\n", ntohl(ste_stats->gt_eval_count));
|
||||
printf("ste: grant_table denied_count = %d\n", ntohl(ste_stats->gt_denied_count));
|
||||
printf("ste: grant_table cache_hit_count = %d\n", ntohl(ste_stats->gt_cachehit_count));
|
||||
}
|
||||
|
||||
#define PULL_STATS_SIZE 8192
|
||||
int acm_domain_dumpstats(int xc_handle)
|
||||
{
|
||||
u8 stats_buffer[PULL_STATS_SIZE];
|
||||
policy_op_t op;
|
||||
int ret;
|
||||
struct acm_stats_buffer *stats;
|
||||
|
||||
memset(stats_buffer, 0x00, sizeof(stats_buffer));
|
||||
op.cmd = POLICY_DUMPSTATS;
|
||||
op.u.dumpstats.pullcache = (void *)stats_buffer;
|
||||
op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
|
||||
return ret;
|
||||
}
|
||||
stats = (struct acm_stats_buffer *)stats_buffer;
|
||||
|
||||
printf("\nPolicy dump:\n");
|
||||
printf("============\n");
|
||||
printf("Magic = %x.\n", ntohl(stats->magic));
|
||||
printf("PolVer = %x.\n", ntohl(stats->policyversion));
|
||||
printf("Len = %x.\n", ntohl(stats->len));
|
||||
|
||||
switch(ntohs(stats->primary_policy_code)) {
|
||||
case ACM_NULL_POLICY:
|
||||
printf("NULL Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
printf("Chinese Wall Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->primary_stats_offset)));
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN PRIMARY POLICY ERROR!\n");
|
||||
}
|
||||
switch(ntohs(stats->secondary_policy_code)) {
|
||||
case ACM_NULL_POLICY:
|
||||
printf("NULL Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
printf("Chinese Wall Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->secondary_stats_offset)));
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN SECONDARY POLICY ERROR!\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************** main **************************************/
|
||||
|
||||
void
|
||||
usage(char *progname){
|
||||
printf("Use: %s \n"
|
||||
"\t setpolicy\n"
|
||||
"\t getpolicy\n"
|
||||
"\t dumpstats\n"
|
||||
"\t loadpolicy <binary policy file>\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
|
||||
int policycmd_fd;
|
||||
|
||||
if (argc < 2)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((policycmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0) {
|
||||
printf("ERROR: Could not open xen policycmd device!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "setpolicy")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
acm_domain_setpolicy(policycmd_fd);
|
||||
|
||||
} else if (!strcmp(argv[1], "getpolicy")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
acm_domain_getpolicy(policycmd_fd);
|
||||
|
||||
} else if (!strcmp(argv[1], "loadpolicy")) {
|
||||
if (argc != 3)
|
||||
usage(argv[0]);
|
||||
acm_domain_loadpolicy(policycmd_fd, argv[2]);
|
||||
|
||||
} else if (!strcmp(argv[1], "dumpstats")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
acm_domain_dumpstats(policycmd_fd);
|
||||
|
||||
} else
|
||||
usage(argv[0]);
|
||||
|
||||
close(policycmd_fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -78,13 +78,14 @@ static PyObject *pyxc_domain_create(PyObject *self,
|
||||
|
||||
u32 dom = 0;
|
||||
int ret;
|
||||
u32 ssidref = 0xFFFFFFFF;
|
||||
|
||||
static char *kwd_list[] = { "dom", NULL };
|
||||
static char *kwd_list[] = { "dom", "ssidref", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &dom))
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, &dom, &ssidref))
|
||||
return NULL;
|
||||
|
||||
if ( (ret = xc_domain_create(xc->xc_handle, &dom)) < 0 )
|
||||
if ( (ret = xc_domain_create(xc->xc_handle, ssidref, &dom)) < 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
return PyInt_FromLong(dom);
|
||||
@@ -230,7 +231,7 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
|
||||
}
|
||||
|
||||
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
|
||||
",s:l,s:L,s:l,s:i}",
|
||||
",s:l,s:L,s:l,s:i,s:i}",
|
||||
"dom", info[i].domid,
|
||||
"vcpus", info[i].vcpus,
|
||||
"dying", info[i].dying,
|
||||
@@ -242,6 +243,7 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
|
||||
"mem_kb", info[i].nr_pages*4,
|
||||
"cpu_time", info[i].cpu_time,
|
||||
"maxmem_kb", info[i].max_memkb,
|
||||
"ssidref", info[i].ssidref,
|
||||
"shutdown_reason", info[i].shutdown_reason);
|
||||
PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
|
||||
PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
Python interface to the Xen Store Daemon.
|
||||
Copyright (C) 2005 Mike Wray Hewlett-Packard
|
||||
*/
|
||||
* Python interface to the Xen Store Daemon.
|
||||
* Copyright (C) 2005 Mike Wray Hewlett-Packard
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
@@ -196,6 +196,7 @@ static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
#define xspy_rm_doc "\n" \
|
||||
"Remove a path.\n" \
|
||||
" path [string] : path to remove\n" \
|
||||
"\n" \
|
||||
"Returns: [int] 0 on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
"\n"
|
||||
@@ -339,13 +340,14 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
|
||||
return val;
|
||||
}
|
||||
|
||||
#define xspy_watch_doc "\n" \
|
||||
"Watch a path, get notifications when it changes.\n" \
|
||||
" path [string] : xenstore path.\n" \
|
||||
" token [string] : returned in watch notification\n" \
|
||||
"\n" \
|
||||
"Returns: [int] 0 on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
#define xspy_watch_doc "\n" \
|
||||
"Watch a path, get notifications when it changes.\n" \
|
||||
" path [string] : xenstore path.\n" \
|
||||
" priority [int] : watch priority (default 0).\n" \
|
||||
" token [string] : returned in watch notification.\n" \
|
||||
"\n" \
|
||||
"Returns: [int] 0 on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
"\n"
|
||||
|
||||
static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
@@ -371,12 +373,14 @@ static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
return val;
|
||||
}
|
||||
|
||||
#define xspy_read_watch_doc "\n" \
|
||||
"Read a watch notification.\n" \
|
||||
" path [string]: xenstore path.\n" \
|
||||
"\n" \
|
||||
"Returns: [tuple] (path, token).\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
#define xspy_read_watch_doc "\n" \
|
||||
"Read a watch notification.\n" \
|
||||
"The notification must be acknowledged by passing\n" \
|
||||
"the token to acknowledge_watch().\n" \
|
||||
" path [string]: xenstore path.\n" \
|
||||
"\n" \
|
||||
"Returns: [tuple] (path, token).\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
"\n"
|
||||
|
||||
static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
|
||||
@@ -408,7 +412,7 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
|
||||
|
||||
#define xspy_acknowledge_watch_doc "\n" \
|
||||
"Acknowledge a watch notification that has been read.\n" \
|
||||
" token [string] : returned in watch notification\n" \
|
||||
" token [string] : from the watch notification\n" \
|
||||
"\n" \
|
||||
"Returns: [int] 0 on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
@@ -499,7 +503,7 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
|
||||
#define xspy_transaction_end_doc "\n" \
|
||||
"End the current transaction.\n" \
|
||||
"Attempts to commit the transaction unless abort is true.\n" \
|
||||
" abort [int]: Abort flag..\n" \
|
||||
" abort [int]: abort flag (default 0).\n" \
|
||||
"\n" \
|
||||
"Returns: [int] 0 on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
@@ -556,10 +560,7 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&dom, &page, &port, &path))
|
||||
goto exit;
|
||||
printf("%s> dom=%u page=0x%08lx port=%u path=%s\n", __FUNCTION__, dom,
|
||||
page, port, path);
|
||||
xsval = xs_introduce_domain(xh, dom, page, port, path);
|
||||
printf("%s> xsval=%d\n", __FUNCTION__, xsval);
|
||||
val = pyvalue_int(xsval);
|
||||
exit:
|
||||
return val;
|
||||
@@ -590,9 +591,7 @@ static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&dom))
|
||||
goto exit;
|
||||
printf("%s> dom=%u\n", __FUNCTION__, dom);
|
||||
xsval = xs_release_domain(xh, dom);
|
||||
printf("%s> xsval=%d\n", __FUNCTION__, xsval);
|
||||
val = pyvalue_int(xsval);
|
||||
exit:
|
||||
return val;
|
||||
@@ -651,6 +650,28 @@ static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
return val;
|
||||
}
|
||||
|
||||
#define xspy_fileno_doc "\n" \
|
||||
"Get the file descriptor of the xenstore socket.\n" \
|
||||
"Allows an xs object to be passed to select().\n" \
|
||||
"\n" \
|
||||
"Returns: [int] file descriptor.\n" \
|
||||
"\n"
|
||||
|
||||
static PyObject *xspy_fileno(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { NULL };
|
||||
static char *arg_spec = "";
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
|
||||
goto exit;
|
||||
val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
|
||||
exit:
|
||||
return val;
|
||||
}
|
||||
|
||||
#define XSPY_METH(_name) { \
|
||||
.ml_name = #_name, \
|
||||
.ml_meth = (PyCFunction) xspy_ ## _name, \
|
||||
@@ -675,17 +696,14 @@ static PyMethodDef xshandle_methods[] = {
|
||||
XSPY_METH(release_domain),
|
||||
XSPY_METH(close),
|
||||
XSPY_METH(shutdown),
|
||||
XSPY_METH(fileno),
|
||||
{ /* Terminator. */ },
|
||||
};
|
||||
|
||||
static PyObject *xshandle_getattr(PyObject *self, char *name)
|
||||
{
|
||||
PyObject *val = NULL;
|
||||
if (strcmp(name, "fileno") == 0) {
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
|
||||
} else
|
||||
val = Py_FindMethod(xshandle_methods, self, name);
|
||||
val = Py_FindMethod(xshandle_methods, self, name);
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -754,7 +772,7 @@ static PyMethodDef xs_methods[] = {
|
||||
"Raises RuntimeError on error.\n"
|
||||
"\n"
|
||||
},
|
||||
{ NULL, NULL, 0, NULL }
|
||||
{ /* Terminator. */ }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC initxs (void)
|
||||
|
||||
@@ -202,7 +202,9 @@ class XendDomainInfo:
|
||||
"""
|
||||
db = parentdb.addChild(uuid)
|
||||
vm = cls(db)
|
||||
id = xc.domain_create()
|
||||
ssidref = int(sxp.child_value(config, 'ssidref'))
|
||||
log.debug('restoring with ssidref='+str(ssidref))
|
||||
id = xc.domain_create(ssidref = ssidref)
|
||||
vm.setdom(id)
|
||||
try:
|
||||
vm.restore = True
|
||||
@@ -241,6 +243,7 @@ class XendDomainInfo:
|
||||
self.start_time = None
|
||||
self.name = None
|
||||
self.memory = None
|
||||
self.ssidref = None
|
||||
self.image = None
|
||||
|
||||
self.channel = None
|
||||
@@ -316,6 +319,7 @@ class XendDomainInfo:
|
||||
"""
|
||||
self.info = info
|
||||
self.memory = self.info['mem_kb'] / 1024
|
||||
self.ssidref = self.info['ssidref']
|
||||
|
||||
def state_set(self, state):
|
||||
self.state_updated.acquire()
|
||||
@@ -336,6 +340,7 @@ class XendDomainInfo:
|
||||
s += " id=" + str(self.id)
|
||||
s += " name=" + self.name
|
||||
s += " memory=" + str(self.memory)
|
||||
s += " ssidref=" + str(self.ssidref)
|
||||
console = self.getConsole()
|
||||
if console:
|
||||
s += " console=" + str(console.console_port)
|
||||
@@ -398,7 +403,8 @@ class XendDomainInfo:
|
||||
sxpr = ['domain',
|
||||
['id', self.id],
|
||||
['name', self.name],
|
||||
['memory', self.memory] ]
|
||||
['memory', self.memory],
|
||||
['ssidref', self.ssidref] ]
|
||||
if self.uuid:
|
||||
sxpr.append(['uuid', self.uuid])
|
||||
if self.info:
|
||||
@@ -511,7 +517,7 @@ class XendDomainInfo:
|
||||
self.configure_restart()
|
||||
self.construct_image()
|
||||
self.configure()
|
||||
self.exportToDB()
|
||||
self.exportToDB(save=True)
|
||||
except Exception, ex:
|
||||
# Catch errors, cleanup and re-raise.
|
||||
print 'Domain construction error:', ex
|
||||
@@ -523,7 +529,7 @@ class XendDomainInfo:
|
||||
def register_domain(self):
|
||||
xd = get_component('xen.xend.XendDomain')
|
||||
xd._add_domain(self)
|
||||
self.exportToDB()
|
||||
self.exportToDB(save=True)
|
||||
|
||||
def configure_cpus(self, config):
|
||||
try:
|
||||
@@ -533,6 +539,7 @@ class XendDomainInfo:
|
||||
self.memory = int(sxp.child_value(config, 'memory'))
|
||||
if self.memory is None:
|
||||
raise VmError('missing memory size')
|
||||
self.ssidref = int(sxp.child_value(config, 'ssidref'))
|
||||
cpu = sxp.child_value(config, 'cpu')
|
||||
if self.recreate and self.id and cpu is not None and int(cpu) >= 0:
|
||||
xc.domain_pincpu(self.id, 0, 1<<int(cpu))
|
||||
@@ -644,7 +651,7 @@ class XendDomainInfo:
|
||||
def show(self):
|
||||
"""Print virtual machine info.
|
||||
"""
|
||||
print "[VM dom=%d name=%s memory=%d" % (self.id, self.name, self.memory)
|
||||
print "[VM dom=%d name=%s memory=%d ssidref=%d" % (self.id, self.name, self.memory, self.ssidref)
|
||||
print "image:"
|
||||
sxp.show(self.image)
|
||||
print "]"
|
||||
@@ -660,7 +667,7 @@ class XendDomainInfo:
|
||||
cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
|
||||
except:
|
||||
raise VmError('invalid cpu')
|
||||
id = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
|
||||
id = self.image.initDomain(self.id, self.memory, self.ssidref, cpu, self.cpu_weight)
|
||||
log.debug('init_domain> Created domain=%d name=%s memory=%d',
|
||||
id, self.name, self.memory)
|
||||
self.setdom(id)
|
||||
@@ -1011,6 +1018,7 @@ addImageHandlerClass(VmxImageHandler)
|
||||
# Ignore the fields we already handle.
|
||||
add_config_handler('name', vm_field_ignore)
|
||||
add_config_handler('memory', vm_field_ignore)
|
||||
add_config_handler('ssidref', vm_field_ignore)
|
||||
add_config_handler('cpu', vm_field_ignore)
|
||||
add_config_handler('cpu_weight', vm_field_ignore)
|
||||
add_config_handler('console', vm_field_ignore)
|
||||
|
||||
@@ -111,7 +111,7 @@ class ImageHandler:
|
||||
except OSError, ex:
|
||||
log.warning("error removing bootloader file '%s': %s", f, ex)
|
||||
|
||||
def initDomain(self, dom, memory, cpu, cpu_weight):
|
||||
def initDomain(self, dom, memory, ssidref, cpu, cpu_weight):
|
||||
"""Initial domain create.
|
||||
|
||||
@return domain id
|
||||
@@ -119,14 +119,14 @@ class ImageHandler:
|
||||
|
||||
mem_kb = self.getDomainMemory(memory)
|
||||
if not self.vm.restore:
|
||||
dom = xc.domain_create(dom = dom or 0)
|
||||
dom = xc.domain_create(dom = dom or 0, ssidref = ssidref)
|
||||
# if bootloader, unlink here. But should go after buildDomain() ?
|
||||
if self.vm.bootloader:
|
||||
self.unlink(self.kernel)
|
||||
self.unlink(self.ramdisk)
|
||||
if dom <= 0:
|
||||
raise VmError('Creating domain failed: name=%s' % self.vm.name)
|
||||
log.debug("initDomain: cpu=%d mem_kb=%d dom=%d", cpu, mem_kb, dom)
|
||||
log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, mem_kb, ssidref, dom)
|
||||
# xc.domain_setuuid(dom, uuid)
|
||||
xc.domain_setcpuweight(dom, cpu_weight)
|
||||
xc.domain_setmaxmem(dom, mem_kb)
|
||||
|
||||
@@ -142,6 +142,7 @@ class SrvDomainDir(SrvDir):
|
||||
% (url, d.name, d.name))
|
||||
req.write('id=%s' % d.id)
|
||||
req.write('memory=%d'% d.memory)
|
||||
req.write('ssidref=%d'% d.ssidref)
|
||||
req.write('</li>')
|
||||
req.write('</ul>')
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ class BlkifBackend:
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
def getEvtchn(self):
|
||||
return self.evtchn
|
||||
|
||||
def closeEvtchn(self):
|
||||
if self.evtchn:
|
||||
channel.eventChannelClose(self.evtchn)
|
||||
@@ -198,7 +201,7 @@ class BlkDev(Dev):
|
||||
backend = self.getBackend()
|
||||
if backend and backend.evtchn:
|
||||
db = self.db.addChild("evtchn")
|
||||
backend.evtchn.exportToDB(db, save=save)
|
||||
backend.evtchn.saveToDB(db, save=save)
|
||||
|
||||
def init(self, recreate=False, reboot=False):
|
||||
self.frontendDomain = self.getDomain()
|
||||
|
||||
@@ -95,7 +95,7 @@ class NetDev(Dev):
|
||||
Dev.exportToDB(self, save=save)
|
||||
if self.evtchn:
|
||||
db = self.db.addChild("evtchn")
|
||||
self.evtchn.exportToDB(db, save=save)
|
||||
self.evtchn.saveToDB(db, save=save)
|
||||
|
||||
def init(self, recreate=False, reboot=False):
|
||||
self.destroyed = False
|
||||
|
||||
@@ -64,7 +64,7 @@ class Watcher:
|
||||
|
||||
def fileno(self):
|
||||
if self.xs:
|
||||
return self.xs.fileno
|
||||
return self.xs.fileno()
|
||||
else:
|
||||
return -1
|
||||
|
||||
|
||||
@@ -120,6 +120,10 @@ gopts.var('memory', val='MEMORY',
|
||||
fn=set_int, default=128,
|
||||
use="Domain memory in MB.")
|
||||
|
||||
gopts.var('ssidref', val='SSIDREF',
|
||||
fn=set_u32, default=0xffffffff,
|
||||
use="Security Identifier.")
|
||||
|
||||
gopts.var('maxmem', val='MEMORY',
|
||||
fn=set_int, default=None,
|
||||
use="Maximum domain memory in MB.")
|
||||
@@ -405,7 +409,8 @@ def make_config(opts, vals):
|
||||
|
||||
config = ['vm',
|
||||
['name', vals.name ],
|
||||
['memory', vals.memory ]]
|
||||
['memory', vals.memory ],
|
||||
['ssidref', vals.ssidref ]]
|
||||
if vals.maxmem:
|
||||
config.append(['maxmem', vals.maxmem])
|
||||
if vals.cpu is not None:
|
||||
|
||||
@@ -383,7 +383,7 @@ class ProgList(Prog):
|
||||
self.brief_list(doms)
|
||||
|
||||
def brief_list(self, doms):
|
||||
print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console'
|
||||
print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console SSID-REF'
|
||||
for dom in doms:
|
||||
info = server.xend_domain(dom)
|
||||
d = {}
|
||||
@@ -399,8 +399,12 @@ class ProgList(Prog):
|
||||
d['port'] = sxp.child_value(console, 'console_port')
|
||||
else:
|
||||
d['port'] = ''
|
||||
print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s"
|
||||
% d)
|
||||
if ((int(sxp.child_value(info, 'ssidref', '-1'))) != -1):
|
||||
d['ssidref1'] = int(sxp.child_value(info, 'ssidref', '-1')) & 0xffff
|
||||
d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '-1')) >> 16) & 0xffff
|
||||
print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
|
||||
else:
|
||||
print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s default" % d)
|
||||
|
||||
def show_vcpus(self, doms):
|
||||
print 'Name Id VCPU CPU CPUMAP'
|
||||
|
||||
@@ -451,6 +451,13 @@ def set_bool(opt, k, v):
|
||||
else:
|
||||
opt.opts.err('Invalid value:' +v)
|
||||
|
||||
def set_u32(opt, k, v):
|
||||
"""Set an option to an u32 value."""
|
||||
try:
|
||||
v = u32(v)
|
||||
except:
|
||||
opt.opts.err('Invalid value: ' + str(v))
|
||||
opt.set(v)
|
||||
|
||||
def set_value(opt, k, v):
|
||||
"""Set an option to a value."""
|
||||
|
||||
+3
-1
@@ -46,6 +46,7 @@ clean: delete-unfresh-files
|
||||
$(MAKE) -C tools clean
|
||||
$(MAKE) -C common clean
|
||||
$(MAKE) -C drivers clean
|
||||
$(MAKE) -C acm clean
|
||||
$(MAKE) -C arch/$(TARGET_ARCH) clean
|
||||
rm -f include/asm *.o $(TARGET)* *~ core
|
||||
rm -f include/asm-*/asm-offsets.h
|
||||
@@ -58,6 +59,7 @@ $(TARGET): delete-unfresh-files
|
||||
$(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h
|
||||
$(MAKE) -C common
|
||||
$(MAKE) -C drivers
|
||||
$(MAKE) -C acm
|
||||
$(MAKE) -C arch/$(TARGET_ARCH)
|
||||
|
||||
# drivers/char/console.o may contain static banner/compile info. Blow it away.
|
||||
@@ -109,7 +111,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
|
||||
|
||||
.PHONY: default debug install dist clean delete-unfresh-files TAGS tags
|
||||
|
||||
SUBDIRS = arch/$(TARGET_ARCH) common drivers
|
||||
SUBDIRS = acm arch/$(TARGET_ARCH) common drivers
|
||||
define all_sources
|
||||
( find include/asm-$(TARGET_ARCH) -name SCCS -prune -o -name '*.h' -print; \
|
||||
find include -type d -name SCCS -prune -o \( -name "asm-*" -o \
|
||||
|
||||
@@ -35,6 +35,7 @@ OBJS += $(patsubst %.c,%.o,$(C_SRCS))
|
||||
ALL_OBJS := $(BASEDIR)/common/common.o
|
||||
ALL_OBJS += $(BASEDIR)/drivers/char/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/acm/acm.o
|
||||
ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
include $(BASEDIR)/Rules.mk
|
||||
OBJS = acm_core.o
|
||||
OBJS += acm_policy.o
|
||||
OBJS += acm_simple_type_enforcement_hooks.o
|
||||
OBJS += acm_chinesewall_hooks.o
|
||||
OBJS += acm_null_hooks.o
|
||||
|
||||
default: acm.o
|
||||
|
||||
acm.o: $(OBJS)
|
||||
$(LD) $(LDFLAGS) -r -o acm.o $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ core
|
||||
@@ -0,0 +1,503 @@
|
||||
/****************************************************************
|
||||
* acm_chinesewall_hooks.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* Contributions:
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype Chinese Wall Policy for Xen
|
||||
* This code implements the hooks that are called
|
||||
* throughout Xen operations and decides authorization
|
||||
* based on domain types and Chinese Wall conflict type
|
||||
* sets. The CHWALL policy decides if a new domain can be started
|
||||
* based on the types of running domains and the type of the
|
||||
* new domain to be started. If the new domain's type is in
|
||||
* conflict with types of running domains, then this new domain
|
||||
* is not allowed to be created. A domain can have multiple types,
|
||||
* in which case all types of a new domain must be conflict-free
|
||||
* with all types of already running domains.
|
||||
*
|
||||
*/
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/acm.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <acm/acm_core.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <acm/acm_endian.h>
|
||||
|
||||
/* local cache structures for chinese wall policy */
|
||||
struct chwall_binary_policy chwall_bin_pol;
|
||||
|
||||
/*
|
||||
* Initializing chinese wall policy (will be filled by policy partition
|
||||
* using setpolicy command)
|
||||
*/
|
||||
int acm_init_chwall_policy(void)
|
||||
{
|
||||
/* minimal startup policy; policy write-locked already */
|
||||
chwall_bin_pol.max_types = 1;
|
||||
chwall_bin_pol.max_ssidrefs = 1;
|
||||
chwall_bin_pol.max_conflictsets = 1;
|
||||
chwall_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types);
|
||||
chwall_bin_pol.conflict_sets = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types);
|
||||
chwall_bin_pol.running_types = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types);
|
||||
chwall_bin_pol.conflict_aggregate_set = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types);
|
||||
|
||||
if ((chwall_bin_pol.conflict_sets == NULL) || (chwall_bin_pol.running_types == NULL) ||
|
||||
(chwall_bin_pol.ssidrefs == NULL) || (chwall_bin_pol.conflict_aggregate_set == NULL))
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
|
||||
/* initialize state */
|
||||
memset((void *)chwall_bin_pol.ssidrefs, 0, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types*sizeof(domaintype_t));
|
||||
memset((void *)chwall_bin_pol.conflict_sets, 0, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types*sizeof(domaintype_t));
|
||||
memset((void *)chwall_bin_pol.running_types, 0, chwall_bin_pol.max_types*sizeof(domaintype_t));
|
||||
memset((void *)chwall_bin_pol.conflict_aggregate_set, 0, chwall_bin_pol.max_types*sizeof(domaintype_t));
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
|
||||
{
|
||||
struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
|
||||
traceprintk("%s.\n", __func__);
|
||||
if (chwall_ssidp == NULL)
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
/*
|
||||
* depending on wheter chwall is primary or secondary, get the respective
|
||||
* part of the global ssidref (same way we'll get the partial ssid pointer)
|
||||
*/
|
||||
chwall_ssidp->chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
|
||||
if (chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs) {
|
||||
printkd("%s: ERROR chwall_ssidref(%x) > max(%x).\n",
|
||||
__func__, chwall_ssidp->chwall_ssidref, chwall_bin_pol.max_ssidrefs-1);
|
||||
xfree(chwall_ssidp);
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
}
|
||||
(*chwall_ssid) = chwall_ssidp;
|
||||
printkd("%s: determined chwall_ssidref to %x.\n",
|
||||
__func__, chwall_ssidp->chwall_ssidref);
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
chwall_free_domain_ssid(void *chwall_ssid)
|
||||
{
|
||||
traceprintk("%s.\n", __func__);
|
||||
if (chwall_ssid != NULL)
|
||||
xfree(chwall_ssid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* dump chinese wall cache; policy read-locked already */
|
||||
static int
|
||||
chwall_dump_policy(u8 *buf, u16 buf_size) {
|
||||
struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
|
||||
int ret = 0;
|
||||
|
||||
chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types);
|
||||
chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs);
|
||||
chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY);
|
||||
chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
|
||||
chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets);
|
||||
chwall_buf->chwall_conflict_sets_offset =
|
||||
htons(
|
||||
ntohs(chwall_buf->chwall_ssid_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
|
||||
chwall_bin_pol.max_types);
|
||||
|
||||
chwall_buf->chwall_running_types_offset =
|
||||
htons(
|
||||
ntohs(chwall_buf->chwall_conflict_sets_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
|
||||
chwall_bin_pol.max_types);
|
||||
|
||||
chwall_buf->chwall_conflict_aggregate_offset =
|
||||
htons(
|
||||
ntohs(chwall_buf->chwall_running_types_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_types);
|
||||
|
||||
ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_types;
|
||||
|
||||
/* now copy buffers over */
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)),
|
||||
chwall_bin_pol.ssidrefs,
|
||||
chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
|
||||
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)),
|
||||
chwall_bin_pol.conflict_sets,
|
||||
chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
|
||||
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)),
|
||||
chwall_bin_pol.running_types,
|
||||
chwall_bin_pol.max_types);
|
||||
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_aggregate_offset)),
|
||||
chwall_bin_pol.conflict_aggregate_set,
|
||||
chwall_bin_pol.max_types);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* adapt security state (running_types and conflict_aggregate_set) to all running
|
||||
* domains; chwall_init_state is called when a policy is changed to bring the security
|
||||
* information into a consistent state and to detect violations (return != 0).
|
||||
* from a security point of view, we simulate that all running domains are re-started
|
||||
*/
|
||||
static int
|
||||
chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf, domaintype_t *ssidrefs, domaintype_t *conflict_sets,
|
||||
domaintype_t *running_types, domaintype_t *conflict_aggregate_set)
|
||||
{
|
||||
int violation = 0, i, j;
|
||||
struct chwall_ssid *chwall_ssid;
|
||||
ssidref_t chwall_ssidref;
|
||||
struct domain **pd;
|
||||
|
||||
write_lock(&domlist_lock);
|
||||
/* go through all domains and adjust policy as if this domain was started now */
|
||||
pd = &domain_list;
|
||||
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
|
||||
chwall_ssid = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)(*pd)->ssid);
|
||||
chwall_ssidref = chwall_ssid->chwall_ssidref;
|
||||
traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
|
||||
__func__, (*pd)->domain_id, chwall_ssidref);
|
||||
/* a) adjust types ref-count for running domains */
|
||||
for (i=0; i< chwall_buf->chwall_max_types; i++)
|
||||
running_types[i] +=
|
||||
ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i];
|
||||
|
||||
/* b) check for conflict */
|
||||
for (i=0; i< chwall_buf->chwall_max_types; i++)
|
||||
if (conflict_aggregate_set[i] &&
|
||||
ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i]) {
|
||||
printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
|
||||
violation = 1;
|
||||
goto out;
|
||||
}
|
||||
/* set violation and break out of the loop */
|
||||
/* c) adapt conflict aggregate set for this domain (notice conflicts) */
|
||||
for (i=0; i<chwall_buf->chwall_max_conflictsets; i++) {
|
||||
int common = 0;
|
||||
/* check if conflict_set_i and ssidref have common types */
|
||||
for (j=0; j<chwall_buf->chwall_max_types; j++)
|
||||
if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
|
||||
ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j]) {
|
||||
common = 1;
|
||||
break;
|
||||
}
|
||||
if (common == 0)
|
||||
continue; /* try next conflict set */
|
||||
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
|
||||
for (j=0; j<chwall_buf->chwall_max_types; j++)
|
||||
if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
|
||||
!ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j])
|
||||
conflict_aggregate_set[j]++;
|
||||
}
|
||||
}
|
||||
out:
|
||||
write_unlock(&domlist_lock);
|
||||
return violation;
|
||||
/* returning "violation != 0" means that the currently running set of domains would
|
||||
* not be possible if the new policy had been enforced before starting them; for chinese
|
||||
* wall, this means that the new policy includes at least one conflict set of which
|
||||
* more than one type is currently running */
|
||||
}
|
||||
|
||||
static int
|
||||
chwall_set_policy(u8 *buf, u16 buf_size)
|
||||
{
|
||||
/* policy write-locked already */
|
||||
struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
|
||||
void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, *conflict_aggregate_set = NULL;
|
||||
|
||||
/* rewrite the policy due to endianess */
|
||||
chwall_buf->policy_code = ntohs(chwall_buf->policy_code);
|
||||
chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types);
|
||||
chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs);
|
||||
chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets);
|
||||
chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset);
|
||||
chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset);
|
||||
chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset);
|
||||
chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset);
|
||||
|
||||
/* 1. allocate new buffers */
|
||||
ssids = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types*chwall_buf->chwall_max_ssidrefs);
|
||||
conflict_sets = xmalloc_array(domaintype_t, chwall_buf->chwall_max_conflictsets*chwall_buf->chwall_max_types);
|
||||
running_types = xmalloc_array(domaintype_t,chwall_buf->chwall_max_types);
|
||||
conflict_aggregate_set = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
|
||||
|
||||
if ((ssids == NULL)||(conflict_sets == NULL)||(running_types == NULL)||(conflict_aggregate_set == NULL))
|
||||
goto error_free;
|
||||
|
||||
/* 2. set new policy */
|
||||
if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
|
||||
chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs > buf_size)
|
||||
goto error_free;
|
||||
arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
|
||||
sizeof(domaintype_t),
|
||||
chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
|
||||
|
||||
if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
|
||||
chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets > buf_size)
|
||||
goto error_free;
|
||||
|
||||
arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
|
||||
sizeof(domaintype_t),
|
||||
chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets);
|
||||
|
||||
/* we also use new state buffers since max_types can change */
|
||||
memset(running_types, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
|
||||
memset(conflict_aggregate_set, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
|
||||
|
||||
/* 3. now re-calculate the state for the new policy based on running domains;
|
||||
* this can fail if new policy is conflicting with running domains */
|
||||
if (chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set)) {
|
||||
printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
|
||||
goto error_free; /* new policy conflicts with running domains */
|
||||
}
|
||||
/* 4. free old policy buffers, replace with new ones */
|
||||
chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
|
||||
chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
|
||||
chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
|
||||
if (chwall_bin_pol.ssidrefs != NULL)
|
||||
xfree(chwall_bin_pol.ssidrefs);
|
||||
if (chwall_bin_pol.conflict_aggregate_set != NULL)
|
||||
xfree(chwall_bin_pol.conflict_aggregate_set);
|
||||
if (chwall_bin_pol.running_types != NULL)
|
||||
xfree(chwall_bin_pol.running_types);
|
||||
if (chwall_bin_pol.conflict_sets != NULL)
|
||||
xfree(chwall_bin_pol.conflict_sets);
|
||||
chwall_bin_pol.ssidrefs = ssids;
|
||||
chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
|
||||
chwall_bin_pol.running_types = running_types;
|
||||
chwall_bin_pol.conflict_sets = conflict_sets;
|
||||
return ACM_OK;
|
||||
|
||||
error_free:
|
||||
printk("%s: ERROR setting policy.\n", __func__);
|
||||
if (ssids != NULL) xfree(ssids);
|
||||
if (conflict_sets != NULL) xfree(conflict_sets);
|
||||
if (running_types != NULL) xfree(running_types);
|
||||
if (conflict_aggregate_set != NULL) xfree(conflict_aggregate_set);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
chwall_dump_stats(u8 *buf, u16 len)
|
||||
{
|
||||
/* no stats for Chinese Wall Policy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************
|
||||
* Authorization functions
|
||||
***************************/
|
||||
|
||||
|
||||
/* -------- DOMAIN OPERATION HOOKS -----------*/
|
||||
|
||||
static int
|
||||
chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
|
||||
{
|
||||
ssidref_t chwall_ssidref;
|
||||
int i,j;
|
||||
traceprintk("%s.\n", __func__);
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
|
||||
if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) {
|
||||
printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", __func__);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_DENIED; /* catching and indicating config error */
|
||||
}
|
||||
if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) {
|
||||
printk("%s: ERROR chwall_ssidref > max(%x).\n",
|
||||
__func__, chwall_bin_pol.max_ssidrefs-1);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
/* A: chinese wall check for conflicts */
|
||||
for (i=0; i< chwall_bin_pol.max_types; i++)
|
||||
if (chwall_bin_pol.conflict_aggregate_set[i] &&
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]) {
|
||||
printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* B: chinese wall conflict set adjustment (so that other
|
||||
* other domains simultaneously created are evaluated against this new set)*/
|
||||
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
|
||||
int common = 0;
|
||||
/* check if conflict_set_i and ssidref have common types */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
|
||||
common = 1;
|
||||
break;
|
||||
}
|
||||
if (common == 0)
|
||||
continue; /* try next conflict set */
|
||||
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
|
||||
chwall_bin_pol.conflict_aggregate_set[j]++;
|
||||
}
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
static void
|
||||
chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
|
||||
{
|
||||
int i,j;
|
||||
ssidref_t chwall_ssidref;
|
||||
traceprintk("%s.\n", __func__);
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
|
||||
/* adjust types ref-count for running domains */
|
||||
for (i=0; i< chwall_bin_pol.max_types; i++)
|
||||
chwall_bin_pol.running_types[i] +=
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
|
||||
if (domid) {
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return;
|
||||
}
|
||||
/* Xen does not call pre-create hook for DOM0;
|
||||
* to consider type conflicts of any domain with DOM0, we need
|
||||
* to adjust the conflict_aggregate for DOM0 here the same way it
|
||||
* is done for non-DOM0 domains in the pre-hook */
|
||||
printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
|
||||
__func__, ssidref, chwall_ssidref);
|
||||
|
||||
/* chinese wall conflict set adjustment (so that other
|
||||
* other domains simultaneously created are evaluated against this new set)*/
|
||||
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
|
||||
int common = 0;
|
||||
/* check if conflict_set_i and ssidref have common types */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
|
||||
common = 1;
|
||||
break;
|
||||
}
|
||||
if (common == 0)
|
||||
continue; /* try next conflict set */
|
||||
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
|
||||
chwall_bin_pol.conflict_aggregate_set[j]++;
|
||||
}
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref)
|
||||
{
|
||||
int i, j;
|
||||
ssidref_t chwall_ssidref;
|
||||
traceprintk("%s.\n", __func__);
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
|
||||
/* roll-back: re-adjust conflicting types aggregate */
|
||||
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
|
||||
int common = 0;
|
||||
/* check if conflict_set_i and ssidref have common types */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
|
||||
common = 1;
|
||||
break;
|
||||
}
|
||||
if (common == 0)
|
||||
continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
|
||||
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
|
||||
chwall_bin_pol.conflict_aggregate_set[j]--;
|
||||
}
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
chwall_post_domain_destroy(void *object_ssid, domid_t id)
|
||||
{
|
||||
int i,j;
|
||||
struct chwall_ssid *chwall_ssidp =
|
||||
GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)object_ssid);
|
||||
ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
|
||||
|
||||
traceprintk("%s.\n", __func__);
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
/* adjust running types set */
|
||||
for (i=0; i< chwall_bin_pol.max_types; i++)
|
||||
chwall_bin_pol.running_types[i] -=
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
|
||||
|
||||
/* roll-back: re-adjust conflicting types aggregate */
|
||||
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
|
||||
int common = 0;
|
||||
/* check if conflict_set_i and ssidref have common types */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
|
||||
common = 1;
|
||||
break;
|
||||
}
|
||||
if (common == 0)
|
||||
continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
|
||||
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
|
||||
for (j=0; j<chwall_bin_pol.max_types; j++)
|
||||
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
|
||||
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
|
||||
chwall_bin_pol.conflict_aggregate_set[j]--;
|
||||
}
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return;
|
||||
}
|
||||
|
||||
struct acm_operations acm_chinesewall_ops = {
|
||||
/* policy management services */
|
||||
.init_domain_ssid = chwall_init_domain_ssid,
|
||||
.free_domain_ssid = chwall_free_domain_ssid,
|
||||
.dump_binary_policy = chwall_dump_policy,
|
||||
.set_binary_policy = chwall_set_policy,
|
||||
.dump_statistics = chwall_dump_stats,
|
||||
/* domain management control hooks */
|
||||
.pre_domain_create = chwall_pre_domain_create,
|
||||
.post_domain_create = chwall_post_domain_create,
|
||||
.fail_domain_create = chwall_fail_domain_create,
|
||||
.post_domain_destroy = chwall_post_domain_destroy,
|
||||
/* event channel control hooks */
|
||||
.pre_eventchannel_unbound = NULL,
|
||||
.fail_eventchannel_unbound = NULL,
|
||||
.pre_eventchannel_interdomain = NULL,
|
||||
.fail_eventchannel_interdomain = NULL,
|
||||
/* grant table control hooks */
|
||||
.pre_grant_map_ref = NULL,
|
||||
.fail_grant_map_ref = NULL,
|
||||
.pre_grant_setup = NULL,
|
||||
.fail_grant_setup = NULL,
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
/****************************************************************
|
||||
* acm_core.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype access control module (ACM)
|
||||
* This file handles initialization of the ACM
|
||||
* as well as initializing/freeing security
|
||||
* identifiers for domains (it calls on active
|
||||
* policy hook functions).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/sched.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <acm/acm_endian.h>
|
||||
|
||||
/* debug:
|
||||
* include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
|
||||
* define/undefine this constant to receive / suppress any
|
||||
* security hook debug output of sHype
|
||||
*
|
||||
* include/public/acm.h defines a constant ACM_DEBUG
|
||||
* define/undefine this constant to receive non-hook-related
|
||||
* debug output.
|
||||
*/
|
||||
|
||||
/* function prototypes */
|
||||
void acm_init_chwall_policy(void);
|
||||
void acm_init_ste_policy(void);
|
||||
|
||||
extern struct acm_operations acm_chinesewall_ops,
|
||||
acm_simple_type_enforcement_ops, acm_null_ops;
|
||||
|
||||
/* global ops structs called by the hooks */
|
||||
struct acm_operations *acm_primary_ops = NULL;
|
||||
/* called in hook if-and-only-if primary succeeds */
|
||||
struct acm_operations *acm_secondary_ops = NULL;
|
||||
|
||||
/* acm global binary policy (points to 'local' primary and secondary policies */
|
||||
struct acm_binary_policy acm_bin_pol;
|
||||
/* acm binary policy lock */
|
||||
rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
|
||||
|
||||
/* until we have endian support in Xen, we discover it at runtime */
|
||||
u8 little_endian = 1;
|
||||
void acm_set_endian(void)
|
||||
{
|
||||
u32 test = 1;
|
||||
if (*((u8 *)&test) == 1) {
|
||||
printk("ACM module running in LITTLE ENDIAN.\n");
|
||||
little_endian = 1;
|
||||
} else {
|
||||
printk("ACM module running in BIG ENDIAN.\n");
|
||||
little_endian = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize global security policy for Xen; policy write-locked already */
|
||||
static void
|
||||
acm_init_binary_policy(void *primary, void *secondary)
|
||||
{
|
||||
acm_bin_pol.primary_policy_code = 0;
|
||||
acm_bin_pol.secondary_policy_code = 0;
|
||||
acm_bin_pol.primary_binary_policy = primary;
|
||||
acm_bin_pol.secondary_binary_policy = secondary;
|
||||
}
|
||||
|
||||
int
|
||||
acm_init(void)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
acm_set_endian();
|
||||
write_lock(&acm_bin_pol_rwlock);
|
||||
|
||||
if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) {
|
||||
acm_init_binary_policy(NULL, NULL);
|
||||
acm_init_chwall_policy();
|
||||
acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
|
||||
acm_primary_ops = &acm_chinesewall_ops;
|
||||
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
|
||||
acm_secondary_ops = &acm_null_ops;
|
||||
ret = ACM_OK;
|
||||
} else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
|
||||
acm_init_binary_policy(NULL, NULL);
|
||||
acm_init_ste_policy();
|
||||
acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
|
||||
acm_primary_ops = &acm_simple_type_enforcement_ops;
|
||||
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
|
||||
acm_secondary_ops = &acm_null_ops;
|
||||
ret = ACM_OK;
|
||||
} else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
|
||||
acm_init_binary_policy(NULL, NULL);
|
||||
acm_init_chwall_policy();
|
||||
acm_init_ste_policy();
|
||||
acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
|
||||
acm_primary_ops = &acm_chinesewall_ops;
|
||||
acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
|
||||
acm_secondary_ops = &acm_simple_type_enforcement_ops;
|
||||
ret = ACM_OK;
|
||||
} else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) {
|
||||
acm_init_binary_policy(NULL, NULL);
|
||||
acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
|
||||
acm_primary_ops = &acm_null_ops;
|
||||
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
|
||||
acm_secondary_ops = &acm_null_ops;
|
||||
ret = ACM_OK;
|
||||
}
|
||||
write_unlock(&acm_bin_pol_rwlock);
|
||||
|
||||
if (ret != ACM_OK)
|
||||
return -EINVAL;
|
||||
printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__,
|
||||
ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
|
||||
{
|
||||
struct acm_ssid_domain *ssid;
|
||||
struct domain *subj = find_domain_by_id(id);
|
||||
int ret1, ret2;
|
||||
|
||||
if (subj == NULL) {
|
||||
printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
|
||||
return ACM_NULL_POINTER_ERROR;
|
||||
}
|
||||
if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
|
||||
ssid->datatype = DOMAIN;
|
||||
ssid->subject = subj;
|
||||
ssid->domainid = subj->domain_id;
|
||||
ssid->primary_ssid = NULL;
|
||||
ssid->secondary_ssid = NULL;
|
||||
|
||||
if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
|
||||
ssid->ssidref = ssidref;
|
||||
else
|
||||
ssid->ssidref = ACM_DEFAULT_SSID;
|
||||
|
||||
subj->ssid = ssid;
|
||||
/* now fill in primary and secondary parts; we only get here through hooks */
|
||||
if (acm_primary_ops->init_domain_ssid != NULL)
|
||||
ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
|
||||
else
|
||||
ret1 = ACM_OK;
|
||||
|
||||
if (acm_secondary_ops->init_domain_ssid != NULL)
|
||||
ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
|
||||
else
|
||||
ret2 = ACM_OK;
|
||||
|
||||
if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) {
|
||||
printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
|
||||
__func__, subj->domain_id);
|
||||
acm_free_domain_ssid(ssid);
|
||||
put_domain(subj);
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
}
|
||||
printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref);
|
||||
put_domain(subj);
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
acm_free_domain_ssid(struct acm_ssid_domain *ssid)
|
||||
{
|
||||
domid_t id;
|
||||
|
||||
/* domain is already gone, just ssid is left */
|
||||
if (ssid == NULL) {
|
||||
printk("%s: ACM_NULL_POINTER ERROR.\n", __func__);
|
||||
return ACM_NULL_POINTER_ERROR;
|
||||
}
|
||||
id = ssid->domainid;
|
||||
ssid->subject = NULL;
|
||||
|
||||
if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
|
||||
acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
|
||||
ssid->primary_ssid = NULL;
|
||||
if (acm_secondary_ops->free_domain_ssid != NULL)
|
||||
acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
|
||||
ssid->secondary_ssid = NULL;
|
||||
xfree(ssid);
|
||||
printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id);
|
||||
return ACM_OK;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/****************************************************************
|
||||
* acm_null_hooks.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
static int
|
||||
null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
|
||||
{
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
null_free_domain_ssid(void *chwall_ssid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
null_dump_binary_policy(u8 *buf, u16 buf_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
null_set_binary_policy(u8 *buf, u16 buf_size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
null_dump_stats(u8 *buf, u16 buf_size)
|
||||
{
|
||||
/* no stats for NULL policy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* now define the hook structure similarly to LSM */
|
||||
struct acm_operations acm_null_ops = {
|
||||
.init_domain_ssid = null_init_domain_ssid,
|
||||
.free_domain_ssid = null_free_domain_ssid,
|
||||
.dump_binary_policy = null_dump_binary_policy,
|
||||
.set_binary_policy = null_set_binary_policy,
|
||||
.dump_statistics = null_dump_stats,
|
||||
/* domain management control hooks */
|
||||
.pre_domain_create = NULL,
|
||||
.post_domain_create = NULL,
|
||||
.fail_domain_create = NULL,
|
||||
.post_domain_destroy = NULL,
|
||||
/* event channel control hooks */
|
||||
.pre_eventchannel_unbound = NULL,
|
||||
.fail_eventchannel_unbound = NULL,
|
||||
.pre_eventchannel_interdomain = NULL,
|
||||
.fail_eventchannel_interdomain = NULL,
|
||||
/* grant table control hooks */
|
||||
.pre_grant_map_ref = NULL,
|
||||
.fail_grant_map_ref = NULL,
|
||||
.pre_grant_setup = NULL,
|
||||
.fail_grant_setup = NULL
|
||||
|
||||
};
|
||||
@@ -0,0 +1,197 @@
|
||||
/****************************************************************
|
||||
* acm_policy.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* Contributions:
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
* support for network-byte-order binary policies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype access control policy management for Xen.
|
||||
* This interface allows policy tools in authorized
|
||||
* domains to interact with the Xen access control module
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/policy_ops.h>
|
||||
#include <acm/acm_core.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <acm/acm_endian.h>
|
||||
|
||||
int
|
||||
acm_set_policy(void *buf, u16 buf_size, u16 policy)
|
||||
{
|
||||
u8 *policy_buffer = NULL;
|
||||
struct acm_policy_buffer *pol;
|
||||
|
||||
if (policy != ACM_USE_SECURITY_POLICY) {
|
||||
printk("%s: Loading incompatible policy (running: %s).\n", __func__,
|
||||
ACM_POLICY_NAME(ACM_USE_SECURITY_POLICY));
|
||||
return -EFAULT;
|
||||
}
|
||||
/* now check correct buffer sizes for policy combinations */
|
||||
if (policy == ACM_NULL_POLICY) {
|
||||
printkd("%s: NULL Policy, no policy needed.\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (buf_size < sizeof(struct acm_policy_buffer))
|
||||
return -EFAULT;
|
||||
/* 1. copy buffer from domain */
|
||||
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
|
||||
goto error_free;
|
||||
if (copy_from_user(policy_buffer, buf, buf_size)) {
|
||||
printk("%s: Error copying!\n",__func__);
|
||||
goto error_free;
|
||||
}
|
||||
/* 2. some sanity checking */
|
||||
pol = (struct acm_policy_buffer *)policy_buffer;
|
||||
|
||||
if ((ntohl(pol->magic) != ACM_MAGIC) ||
|
||||
(ntohs(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
|
||||
(ntohs(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) {
|
||||
printkd("%s: Wrong policy magics!\n", __func__);
|
||||
goto error_free;
|
||||
}
|
||||
if (buf_size != ntohl(pol->len)) {
|
||||
printk("%s: ERROR in buf size.\n", __func__);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
/* get bin_policy lock and rewrite policy (release old one) */
|
||||
write_lock(&acm_bin_pol_rwlock);
|
||||
|
||||
/* 3. now get/set primary policy data */
|
||||
if (acm_primary_ops->set_binary_policy(buf + ntohs(pol->primary_buffer_offset),
|
||||
ntohs(pol->secondary_buffer_offset) -
|
||||
ntohs(pol->primary_buffer_offset))) {
|
||||
goto error_lock_free;
|
||||
}
|
||||
/* 4. now get/set secondary policy data */
|
||||
if (acm_secondary_ops->set_binary_policy(buf + ntohs(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) -
|
||||
ntohs(pol->secondary_buffer_offset))) {
|
||||
goto error_lock_free;
|
||||
}
|
||||
write_unlock(&acm_bin_pol_rwlock);
|
||||
out:
|
||||
printk("%s: Done .\n", __func__);
|
||||
if (policy_buffer != NULL)
|
||||
xfree(policy_buffer);
|
||||
return ACM_OK;
|
||||
|
||||
error_lock_free:
|
||||
write_unlock(&acm_bin_pol_rwlock);
|
||||
error_free:
|
||||
printk("%s: Error setting policy.\n", __func__);
|
||||
if (policy_buffer != NULL)
|
||||
xfree(policy_buffer);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int
|
||||
acm_get_policy(void *buf, u16 buf_size)
|
||||
{
|
||||
u8 *policy_buffer;
|
||||
int ret;
|
||||
struct acm_policy_buffer *bin_pol;
|
||||
|
||||
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
/* future: read policy from file and set it */
|
||||
bin_pol = (struct acm_policy_buffer *)policy_buffer;
|
||||
bin_pol->magic = htonl(ACM_MAGIC);
|
||||
bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION);
|
||||
bin_pol->primary_policy_code = htons(acm_bin_pol.primary_policy_code);
|
||||
bin_pol->secondary_policy_code = htons(acm_bin_pol.secondary_policy_code);
|
||||
|
||||
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
|
||||
bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
|
||||
ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohs(bin_pol->primary_buffer_offset),
|
||||
buf_size - ntohs(bin_pol->primary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
|
||||
ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohs(bin_pol->secondary_buffer_offset),
|
||||
buf_size - ntohs(bin_pol->secondary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len)))
|
||||
return -EFAULT;
|
||||
xfree(policy_buffer);
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
int
|
||||
acm_dump_statistics(void *buf, u16 buf_size)
|
||||
{
|
||||
/* send stats to user space */
|
||||
u8 *stats_buffer;
|
||||
int len1, len2;
|
||||
struct acm_stats_buffer acm_stats;
|
||||
|
||||
if ((stats_buffer = xmalloc_array(u8, buf_size)) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
|
||||
len1 = acm_primary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer),
|
||||
buf_size - sizeof(struct acm_stats_buffer));
|
||||
if (len1 < 0)
|
||||
goto error_lock_free;
|
||||
|
||||
len2 = acm_secondary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer) + len1,
|
||||
buf_size - sizeof(struct acm_stats_buffer) - len1);
|
||||
if (len2 < 0)
|
||||
goto error_lock_free;
|
||||
|
||||
acm_stats.magic = htonl(ACM_MAGIC);
|
||||
acm_stats.policyversion = htonl(POLICY_INTERFACE_VERSION);
|
||||
acm_stats.primary_policy_code = htons(acm_bin_pol.primary_policy_code);
|
||||
acm_stats.secondary_policy_code = htons(acm_bin_pol.secondary_policy_code);
|
||||
acm_stats.primary_stats_offset = htons(sizeof(struct acm_stats_buffer));
|
||||
acm_stats.secondary_stats_offset = htons(sizeof(struct acm_stats_buffer) + len1);
|
||||
acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2);
|
||||
memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
|
||||
|
||||
if (copy_to_user(buf, stats_buffer, sizeof(struct acm_stats_buffer) + len1 + len2))
|
||||
goto error_lock_free;
|
||||
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
xfree(stats_buffer);
|
||||
return ACM_OK;
|
||||
|
||||
error_lock_free:
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
xfree(stats_buffer);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*eof*/
|
||||
@@ -0,0 +1,638 @@
|
||||
/****************************************************************
|
||||
* acm_simple_type_enforcement_hooks.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
* support for network order binary policies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype Simple Type Enforcement for Xen
|
||||
* STE allows to control which domains can setup sharing
|
||||
* (eventchannels right now) with which other domains. Hooks
|
||||
* are defined and called throughout Xen when domains bind to
|
||||
* shared resources (setup eventchannels) and a domain is allowed
|
||||
* to setup sharing with another domain if and only if both domains
|
||||
* share at least on common type.
|
||||
*
|
||||
*/
|
||||
#include <xen/lib.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/current.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <acm/acm_endian.h>
|
||||
|
||||
/* local cache structures for chinese wall policy */
|
||||
struct ste_binary_policy ste_bin_pol;
|
||||
|
||||
static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) {
|
||||
int i;
|
||||
for(i=0; i< ste_bin_pol.max_types; i++)
|
||||
if ( ste_bin_pol.ssidrefs[ref1*ste_bin_pol.max_types + i] &&
|
||||
ste_bin_pol.ssidrefs[ref2*ste_bin_pol.max_types + i]) {
|
||||
printkd("%s: common type #%02x.\n", __func__, i);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper function: return = (subj and obj share a common type) */
|
||||
static int share_common_type(struct domain *subj, struct domain *obj)
|
||||
{
|
||||
ssidref_t ref_s, ref_o;
|
||||
int ret;
|
||||
|
||||
if ((subj == NULL) || (obj == NULL) || (subj->ssid == NULL) || (obj->ssid == NULL))
|
||||
return 0;
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
/* lookup the policy-local ssids */
|
||||
ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
|
||||
ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
|
||||
/* check whether subj and obj share a common ste type */
|
||||
ret = have_common_type(ref_s, ref_o);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializing chinese wall policy (will be filled by policy partition
|
||||
* using setpolicy command)
|
||||
*/
|
||||
int acm_init_ste_policy(void)
|
||||
{
|
||||
/* minimal startup policy; policy write-locked already */
|
||||
ste_bin_pol.max_types = 1;
|
||||
ste_bin_pol.max_ssidrefs = 1;
|
||||
ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 1);
|
||||
|
||||
if (ste_bin_pol.ssidrefs == NULL)
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
|
||||
/* initialize state */
|
||||
ste_bin_pol.ssidrefs[0] = 1;
|
||||
|
||||
/* init stats */
|
||||
atomic_set(&(ste_bin_pol.ec_eval_count), 0);
|
||||
atomic_set(&(ste_bin_pol.ec_denied_count), 0);
|
||||
atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
|
||||
atomic_set(&(ste_bin_pol.gt_eval_count), 0);
|
||||
atomic_set(&(ste_bin_pol.gt_denied_count), 0);
|
||||
atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ste initialization function hooks */
|
||||
static int
|
||||
ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
|
||||
{
|
||||
int i;
|
||||
struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
|
||||
traceprintk("%s.\n", __func__);
|
||||
|
||||
if (ste_ssidp == NULL)
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
|
||||
/* get policy-local ssid reference */
|
||||
ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
|
||||
if (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) {
|
||||
printkd("%s: ERROR ste_ssidref (%x) > max(%x).\n",
|
||||
__func__, ste_ssidp->ste_ssidref, ste_bin_pol.max_ssidrefs-1);
|
||||
xfree(ste_ssidp);
|
||||
return ACM_INIT_SSID_ERROR;
|
||||
}
|
||||
/* clean ste cache */
|
||||
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
|
||||
ste_ssidp->ste_cache[i].valid = FREE;
|
||||
|
||||
(*ste_ssid) = ste_ssidp;
|
||||
printkd("%s: determined ste_ssidref to %x.\n",
|
||||
__func__, ste_ssidp->ste_ssidref);
|
||||
return ACM_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ste_free_domain_ssid(void *ste_ssid)
|
||||
{
|
||||
traceprintk("%s.\n", __func__);
|
||||
if (ste_ssid != NULL)
|
||||
xfree(ste_ssid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* dump type enforcement cache; policy read-locked already */
|
||||
static int
|
||||
ste_dump_policy(u8 *buf, u16 buf_size) {
|
||||
struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
|
||||
int ret = 0;
|
||||
|
||||
ste_buf->ste_max_types = htons(ste_bin_pol.max_types);
|
||||
ste_buf->ste_max_ssidrefs = htons(ste_bin_pol.max_ssidrefs);
|
||||
ste_buf->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
ste_buf->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
|
||||
ret = ntohs(ste_buf->ste_ssid_offset) +
|
||||
sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
|
||||
|
||||
/* now copy buffer over */
|
||||
arrcpy(buf + ntohs(ste_buf->ste_ssid_offset),
|
||||
ste_bin_pol.ssidrefs,
|
||||
sizeof(domaintype_t),
|
||||
ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ste_init_state is called when a policy is changed to detect violations (return != 0).
|
||||
* from a security point of view, we simulate that all running domains are re-started and
|
||||
* all sharing decisions are replayed to detect violations or current sharing behavior
|
||||
* (right now: event_channels, future: also grant_tables)
|
||||
*/
|
||||
static int
|
||||
ste_init_state(struct acm_ste_policy_buffer *ste_buf, domaintype_t *ssidrefs)
|
||||
{
|
||||
int violation = 1;
|
||||
struct ste_ssid *ste_ssid, *ste_rssid;
|
||||
ssidref_t ste_ssidref, ste_rssidref;
|
||||
struct domain **pd, *rdom;
|
||||
domid_t rdomid;
|
||||
grant_entry_t sha_copy;
|
||||
int port, i;
|
||||
|
||||
read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */
|
||||
/* go through all domains and adjust policy as if this domain was started now */
|
||||
pd = &domain_list;
|
||||
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(*pd)->ssid);
|
||||
ste_ssidref = ste_ssid->ste_ssidref;
|
||||
traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
|
||||
__func__, (*pd)->domain_id, ste_ssidref);
|
||||
/* a) check for event channel conflicts */
|
||||
for (port=0; port < NR_EVTCHN_BUCKETS; port++) {
|
||||
spin_lock(&(*pd)->evtchn_lock);
|
||||
if ((*pd)->evtchn[port] == NULL) {
|
||||
spin_unlock(&(*pd)->evtchn_lock);
|
||||
continue;
|
||||
}
|
||||
if ((*pd)->evtchn[port]->state == ECS_INTERDOMAIN) {
|
||||
rdom = (*pd)->evtchn[port]->u.interdomain.remote_dom;
|
||||
rdomid = rdom->domain_id;
|
||||
/* rdom now has remote domain */
|
||||
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(rdom->ssid));
|
||||
ste_rssidref = ste_rssid->ste_ssidref;
|
||||
} else if ((*pd)->evtchn[port]->state == ECS_UNBOUND) {
|
||||
rdomid = (*pd)->evtchn[port]->u.unbound.remote_domid;
|
||||
if ((rdom = find_domain_by_id(rdomid)) == NULL) {
|
||||
printk("%s: Error finding domain to id %x!\n", __func__, rdomid);
|
||||
goto out;
|
||||
}
|
||||
/* rdom now has remote domain */
|
||||
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(rdom->ssid));
|
||||
ste_rssidref = ste_rssid->ste_ssidref;
|
||||
put_domain(rdom);
|
||||
} else {
|
||||
spin_unlock(&(*pd)->evtchn_lock);
|
||||
continue; /* port unused */
|
||||
}
|
||||
spin_unlock(&(*pd)->evtchn_lock);
|
||||
|
||||
/* rdom now has remote domain */
|
||||
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(rdom->ssid));
|
||||
ste_rssidref = ste_rssid->ste_ssidref;
|
||||
traceprintk("%s: eventch: domain %x (ssidref %x) --> domain %x (rssidref %x) used (port %x).\n",
|
||||
__func__, (*pd)->domain_id, ste_ssidref, rdom->domain_id, ste_rssidref, port);
|
||||
/* check whether on subj->ssid, obj->ssid share a common type*/
|
||||
if (!have_common_type(ste_ssidref, ste_rssidref)) {
|
||||
printkd("%s: Policy violation in event channel domain %x -> domain %x.\n",
|
||||
__func__, (*pd)->domain_id, rdomid);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* b) check for grant table conflicts on shared pages */
|
||||
if ((*pd)->grant_table->shared == NULL) {
|
||||
printkd("%s: Grant ... sharing for domain %x not setup!\n", __func__, (*pd)->domain_id);
|
||||
continue;
|
||||
}
|
||||
for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) {
|
||||
sha_copy = (*pd)->grant_table->shared[i];
|
||||
if ( sha_copy.flags ) {
|
||||
printkd("%s: grant dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n",
|
||||
__func__, (*pd)->domain_id, i, sha_copy.flags, sha_copy.domid,
|
||||
(unsigned long)sha_copy.frame);
|
||||
rdomid = sha_copy.domid;
|
||||
if ((rdom = find_domain_by_id(rdomid)) == NULL) {
|
||||
printkd("%s: domain not found ERROR!\n", __func__);
|
||||
goto out;
|
||||
};
|
||||
/* rdom now has remote domain */
|
||||
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(rdom->ssid));
|
||||
ste_rssidref = ste_rssid->ste_ssidref;
|
||||
put_domain(rdom);
|
||||
if (!have_common_type(ste_ssidref, ste_rssidref)) {
|
||||
printkd("%s: Policy violation in grant table sharing domain %x -> domain %x.\n",
|
||||
__func__, (*pd)->domain_id, rdomid);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
violation = 0;
|
||||
out:
|
||||
read_unlock(&domlist_lock);
|
||||
return violation;
|
||||
/* returning "violation != 0" means that existing sharing between domains would not
|
||||
* have been allowed if the new policy had been enforced before the sharing; for ste,
|
||||
* this means that there are at least 2 domains that have established sharing through
|
||||
* event-channels or grant-tables but these two domains don't have no longer a common
|
||||
* type in their typesets referenced by their ssidrefs */
|
||||
}
|
||||
|
||||
/* set new policy; policy write-locked already */
|
||||
static int
|
||||
ste_set_policy(u8 *buf, u16 buf_size)
|
||||
{
|
||||
struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
|
||||
void *ssidrefsbuf;
|
||||
struct ste_ssid *ste_ssid;
|
||||
struct domain **pd;
|
||||
int i;
|
||||
|
||||
/* Convert endianess of policy */
|
||||
ste_buf->policy_code = ntohs(ste_buf->policy_code);
|
||||
ste_buf->ste_max_types = ntohs(ste_buf->ste_max_types);
|
||||
ste_buf->ste_max_ssidrefs = ntohs(ste_buf->ste_max_ssidrefs);
|
||||
ste_buf->ste_ssid_offset = ntohs(ste_buf->ste_ssid_offset);
|
||||
|
||||
/* 1. create and copy-in new ssidrefs buffer */
|
||||
ssidrefsbuf = xmalloc_array(u8, sizeof(domaintype_t)*ste_buf->ste_max_types*ste_buf->ste_max_ssidrefs);
|
||||
if (ssidrefsbuf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size)
|
||||
goto error_free;
|
||||
|
||||
arrcpy(ssidrefsbuf,
|
||||
buf + ste_buf->ste_ssid_offset,
|
||||
sizeof(domaintype_t),
|
||||
ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
|
||||
|
||||
/* 2. now re-calculate sharing decisions based on running domains;
|
||||
* this can fail if new policy is conflicting with sharing of running domains
|
||||
* now: reject violating new policy; future: adjust sharing through revoking sharing */
|
||||
if (ste_init_state(ste_buf, (domaintype_t *)ssidrefsbuf)) {
|
||||
printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
|
||||
goto error_free; /* new policy conflicts with sharing of running domains */
|
||||
}
|
||||
/* 3. replace old policy (activate new policy) */
|
||||
ste_bin_pol.max_types = ste_buf->ste_max_types;
|
||||
ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
|
||||
if (ste_bin_pol.ssidrefs)
|
||||
xfree(ste_bin_pol.ssidrefs);
|
||||
ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
|
||||
|
||||
/* clear all ste caches */
|
||||
read_lock(&domlist_lock);
|
||||
pd = &domain_list;
|
||||
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(*pd)->ssid);
|
||||
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
|
||||
ste_ssid->ste_cache[i].valid = FREE;
|
||||
}
|
||||
read_unlock(&domlist_lock);
|
||||
return ACM_OK;
|
||||
|
||||
error_free:
|
||||
printk("%s: ERROR setting policy.\n", __func__);
|
||||
if (ssidrefsbuf != NULL) xfree(ssidrefsbuf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
ste_dump_stats(u8 *buf, u16 buf_len)
|
||||
{
|
||||
struct acm_ste_stats_buffer stats;
|
||||
|
||||
#ifdef ACM_DEBUG
|
||||
int i;
|
||||
struct ste_ssid *ste_ssid;
|
||||
struct domain **pd;
|
||||
|
||||
printk("ste: Decision caches:\n");
|
||||
/* go through all domains and adjust policy as if this domain was started now */
|
||||
read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */
|
||||
pd = &domain_list;
|
||||
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
|
||||
printk("ste: Cache Domain %02x.\n", (*pd)->domain_id);
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(*pd)->ssid);
|
||||
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
|
||||
printk("\t\tcache[%02x] = %s, domid=%x.\n", i,
|
||||
(ste_ssid->ste_cache[i].valid == VALID) ?
|
||||
"VALID" : "FREE",
|
||||
(ste_ssid->ste_cache[i].valid == VALID) ?
|
||||
ste_ssid->ste_cache[i].id : 0xffffffff);
|
||||
}
|
||||
read_unlock(&domlist_lock);
|
||||
/* init stats */
|
||||
printk("STE-Policy Security Hook Statistics:\n");
|
||||
printk("ste: event_channel eval_count = %x\n", atomic_read(&(ste_bin_pol.ec_eval_count)));
|
||||
printk("ste: event_channel denied_count = %x\n", atomic_read(&(ste_bin_pol.ec_denied_count)));
|
||||
printk("ste: event_channel cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.ec_cachehit_count)));
|
||||
printk("ste:\n");
|
||||
printk("ste: grant_table eval_count = %x\n", atomic_read(&(ste_bin_pol.gt_eval_count)));
|
||||
printk("ste: grant_table denied_count = %x\n", atomic_read(&(ste_bin_pol.gt_denied_count)));
|
||||
printk("ste: grant_table cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.gt_cachehit_count)));
|
||||
#endif
|
||||
|
||||
if (buf_len < sizeof(struct acm_ste_stats_buffer))
|
||||
return -ENOMEM;
|
||||
|
||||
/* now send the hook counts to user space */
|
||||
stats.ec_eval_count = htonl(atomic_read(&ste_bin_pol.ec_eval_count));
|
||||
stats.gt_eval_count = htonl(atomic_read(&ste_bin_pol.gt_eval_count));
|
||||
stats.ec_denied_count = htonl(atomic_read(&ste_bin_pol.ec_denied_count));
|
||||
stats.gt_denied_count = htonl(atomic_read(&ste_bin_pol.gt_denied_count));
|
||||
stats.ec_cachehit_count = htonl(atomic_read(&ste_bin_pol.ec_cachehit_count));
|
||||
stats.gt_cachehit_count = htonl(atomic_read(&ste_bin_pol.gt_cachehit_count));
|
||||
memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
|
||||
return sizeof(struct acm_ste_stats_buffer);
|
||||
}
|
||||
|
||||
|
||||
/* we need to go through this before calling the hooks,
|
||||
* returns 1 == cache hit */
|
||||
static int inline
|
||||
check_cache(struct domain *dom, domid_t rdom) {
|
||||
struct ste_ssid *ste_ssid;
|
||||
int i;
|
||||
|
||||
printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(dom)->ssid);
|
||||
|
||||
for(i=0; i< ACM_TE_CACHE_SIZE; i++) {
|
||||
if ((ste_ssid->ste_cache[i].valid == VALID) &&
|
||||
(ste_ssid->ste_cache[i].id == rdom)) {
|
||||
printkd("cache hit (entry %x, id= %x!\n", i, ste_ssid->ste_cache[i].id);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* we only get here if there is NO entry yet; no duplication check! */
|
||||
static void inline
|
||||
cache_result(struct domain *subj, struct domain *obj) {
|
||||
struct ste_ssid *ste_ssid;
|
||||
int i;
|
||||
printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id);
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(subj)->ssid);
|
||||
for(i=0; i< ACM_TE_CACHE_SIZE; i++)
|
||||
if (ste_ssid->ste_cache[i].valid == FREE)
|
||||
break;
|
||||
if (i< ACM_TE_CACHE_SIZE) {
|
||||
ste_ssid->ste_cache[i].valid = VALID;
|
||||
ste_ssid->ste_cache[i].id = obj->domain_id;
|
||||
} else
|
||||
printk ("Cache of dom %x is full!\n", subj->domain_id);
|
||||
}
|
||||
|
||||
/* deletes entries for domain 'id' from all caches (re-use) */
|
||||
static void inline
|
||||
clean_id_from_cache(domid_t id)
|
||||
{
|
||||
struct ste_ssid *ste_ssid;
|
||||
int i;
|
||||
struct domain **pd;
|
||||
|
||||
printkd("deleting cache for dom %x.\n", id);
|
||||
|
||||
read_lock(&domlist_lock); /* look through caches of all domains */
|
||||
pd = &domain_list;
|
||||
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(*pd)->ssid);
|
||||
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
|
||||
if ((ste_ssid->ste_cache[i].valid == VALID) &&
|
||||
(ste_ssid->ste_cache[i].id = id))
|
||||
ste_ssid->ste_cache[i].valid = FREE;
|
||||
}
|
||||
read_unlock(&domlist_lock);
|
||||
}
|
||||
|
||||
/***************************
|
||||
* Authorization functions
|
||||
**************************/
|
||||
|
||||
static int
|
||||
ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
|
||||
{
|
||||
/* check for ssidref in range for policy */
|
||||
ssidref_t ste_ssidref;
|
||||
traceprintk("%s.\n", __func__);
|
||||
|
||||
read_lock(&acm_bin_pol_rwlock);
|
||||
ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
|
||||
if (ste_ssidref == ACM_DEFAULT_LOCAL_SSID) {
|
||||
printk("%s: ERROR STE SSID is NOT SET but policy enforced.\n", __func__);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_DENIED; /* catching and indicating config error */
|
||||
}
|
||||
if (ste_ssidref >= ste_bin_pol.max_ssidrefs) {
|
||||
printk("%s: ERROR ste_ssidref > max(%x).\n",
|
||||
__func__, ste_bin_pol.max_ssidrefs-1);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
static void
|
||||
ste_post_domain_destroy(void *subject_ssid, domid_t id)
|
||||
{
|
||||
/* clean all cache entries for destroyed domain (might be re-used) */
|
||||
clean_id_from_cache(id);
|
||||
}
|
||||
|
||||
/* -------- EVENTCHANNEL OPERATIONS -----------*/
|
||||
static int
|
||||
ste_pre_eventchannel_unbound(domid_t id) {
|
||||
struct domain *subj, *obj;
|
||||
int ret;
|
||||
traceprintk("%s: dom%x-->dom%x.\n",
|
||||
__func__, current->domain->domain_id, id);
|
||||
|
||||
if (check_cache(current->domain, id)) {
|
||||
atomic_inc(&ste_bin_pol.ec_cachehit_count);
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
atomic_inc(&ste_bin_pol.ec_eval_count);
|
||||
subj = current->domain;
|
||||
obj = find_domain_by_id(id);
|
||||
|
||||
if (share_common_type(subj, obj)) {
|
||||
cache_result(subj, obj);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
} else {
|
||||
atomic_inc(&ste_bin_pol.ec_denied_count);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
|
||||
{
|
||||
struct domain *subj, *obj;
|
||||
int ret;
|
||||
traceprintk("%s: dom%x-->dom%x.\n", __func__,
|
||||
(id1 == DOMID_SELF) ? current->domain->domain_id : id1,
|
||||
(id2 == DOMID_SELF) ? current->domain->domain_id : id2);
|
||||
|
||||
/* following is a bit longer but ensures that we
|
||||
* "put" only domains that we where "find"-ing
|
||||
*/
|
||||
if (id1 == DOMID_SELF) id1 = current->domain->domain_id;
|
||||
if (id2 == DOMID_SELF) id2 = current->domain->domain_id;
|
||||
|
||||
subj = find_domain_by_id(id1);
|
||||
obj = find_domain_by_id(id2);
|
||||
if ((subj == NULL) || (obj == NULL)) {
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
goto out;
|
||||
}
|
||||
/* cache check late, but evtchn is not on performance critical path */
|
||||
if (check_cache(subj, obj->domain_id)) {
|
||||
atomic_inc(&ste_bin_pol.ec_cachehit_count);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
goto out;
|
||||
}
|
||||
atomic_inc(&ste_bin_pol.ec_eval_count);
|
||||
|
||||
if (share_common_type(subj, obj)) {
|
||||
cache_result(subj, obj);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
} else {
|
||||
atomic_inc(&ste_bin_pol.ec_denied_count);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
out:
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
if (subj != NULL)
|
||||
put_domain(subj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------- SHARED MEMORY OPERATIONS -----------*/
|
||||
|
||||
static int
|
||||
ste_pre_grant_map_ref (domid_t id) {
|
||||
struct domain *obj, *subj;
|
||||
int ret;
|
||||
traceprintk("%s: dom%x-->dom%x.\n", __func__,
|
||||
current->domain->domain_id, id);
|
||||
|
||||
if (check_cache(current->domain, id)) {
|
||||
atomic_inc(&ste_bin_pol.gt_cachehit_count);
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
atomic_inc(&ste_bin_pol.gt_eval_count);
|
||||
subj = current->domain;
|
||||
obj = find_domain_by_id(id);
|
||||
|
||||
if (share_common_type(subj, obj)) {
|
||||
cache_result(subj, obj);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
} else {
|
||||
atomic_inc(&ste_bin_pol.gt_denied_count);
|
||||
printkd("%s: ACCESS DENIED!\n", __func__);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* since setting up grant tables involves some implicit information
|
||||
flow from the creating domain to the domain that is setup, we
|
||||
check types in addition to the general authorization */
|
||||
static int
|
||||
ste_pre_grant_setup (domid_t id) {
|
||||
struct domain *obj, *subj;
|
||||
int ret;
|
||||
traceprintk("%s: dom%x-->dom%x.\n", __func__,
|
||||
current->domain->domain_id, id);
|
||||
|
||||
if (check_cache(current->domain, id)) {
|
||||
atomic_inc(&ste_bin_pol.gt_cachehit_count);
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
atomic_inc(&ste_bin_pol.gt_eval_count);
|
||||
/* a) check authorization (eventually use specific capabilities) */
|
||||
if (!IS_PRIV(current->domain)) {
|
||||
printk("%s: Grant table management authorization denied ERROR!\n", __func__);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
/* b) check types */
|
||||
subj = current->domain;
|
||||
obj = find_domain_by_id(id);
|
||||
|
||||
if (share_common_type(subj, obj)) {
|
||||
cache_result(subj, obj);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
} else {
|
||||
atomic_inc(&ste_bin_pol.gt_denied_count);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* now define the hook structure similarly to LSM */
|
||||
struct acm_operations acm_simple_type_enforcement_ops = {
|
||||
/* policy management services */
|
||||
.init_domain_ssid = ste_init_domain_ssid,
|
||||
.free_domain_ssid = ste_free_domain_ssid,
|
||||
.dump_binary_policy = ste_dump_policy,
|
||||
.set_binary_policy = ste_set_policy,
|
||||
.dump_statistics = ste_dump_stats,
|
||||
/* domain management control hooks */
|
||||
.pre_domain_create = ste_pre_domain_create,
|
||||
.post_domain_create = NULL,
|
||||
.fail_domain_create = NULL,
|
||||
.post_domain_destroy = ste_post_domain_destroy,
|
||||
/* event channel control hooks */
|
||||
.pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
|
||||
.fail_eventchannel_unbound = NULL,
|
||||
.pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
|
||||
.fail_eventchannel_interdomain = NULL,
|
||||
/* grant table control hooks */
|
||||
.pre_grant_map_ref = ste_pre_grant_map_ref,
|
||||
.fail_grant_map_ref = NULL,
|
||||
.pre_grant_setup = ste_pre_grant_setup,
|
||||
.fail_grant_setup = NULL,
|
||||
};
|
||||
@@ -15,7 +15,7 @@ OBJS = xensetup.o setup.o time.o irq.o ia64_ksyms.o process.o smp.o \
|
||||
ifeq ($(CONFIG_VTI),y)
|
||||
OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o \
|
||||
vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \
|
||||
vtlb.o mmio.o vlsapic.o
|
||||
vtlb.o mmio.o vlsapic.o vmx_hypercall.o mm.o
|
||||
endif
|
||||
# perfmon.o
|
||||
# unwind.o needed for kernel unwinding (rare)
|
||||
|
||||
@@ -75,6 +75,9 @@ void foo(void)
|
||||
DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0));
|
||||
DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm));
|
||||
DEFINE(IA64_VCPU_IVA_OFFSET, offsetof (struct vcpu, arch.iva));
|
||||
DEFINE(IA64_VCPU_IRR0_OFFSET, offsetof (struct vcpu, arch.irr[0]));
|
||||
DEFINE(IA64_VCPU_IRR3_OFFSET, offsetof (struct vcpu, arch.irr[3]));
|
||||
DEFINE(IA64_VCPU_INSVC3_OFFSET, offsetof (struct vcpu, arch.insvc[3]));
|
||||
|
||||
BLANK();
|
||||
|
||||
|
||||
+43
-15
@@ -18,14 +18,6 @@
|
||||
#include <xen/console.h>
|
||||
#include <public/sched_ctl.h>
|
||||
|
||||
#define TRC_DOM0OP_ENTER_BASE 0x00020000
|
||||
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
|
||||
|
||||
static int msr_cpu_mask;
|
||||
static unsigned long msr_addr;
|
||||
static unsigned long msr_lo;
|
||||
static unsigned long msr_hi;
|
||||
|
||||
long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
{
|
||||
long ret = 0;
|
||||
@@ -35,6 +27,49 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
|
||||
switch ( op->cmd )
|
||||
{
|
||||
/*
|
||||
* NOTE: DOM0_GETMEMLIST has somewhat different semantics on IA64 -
|
||||
* it actually allocates and maps pages.
|
||||
*/
|
||||
case DOM0_GETMEMLIST:
|
||||
{
|
||||
unsigned long i;
|
||||
struct domain *d = find_domain_by_id(op->u.getmemlist.domain);
|
||||
unsigned long start_page = op->u.getmemlist.max_pfns >> 32;
|
||||
unsigned long nr_pages = op->u.getmemlist.max_pfns & 0xffffffff;
|
||||
unsigned long pfn;
|
||||
unsigned long *buffer = op->u.getmemlist.buffer;
|
||||
struct page *page;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( d != NULL )
|
||||
{
|
||||
ret = 0;
|
||||
|
||||
for ( i = start_page; i < (start_page + nr_pages); i++ )
|
||||
{
|
||||
page = map_new_domain_page(d, i << PAGE_SHIFT);
|
||||
if ( page == NULL )
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
pfn = page_to_pfn(page);
|
||||
if ( put_user(pfn, buffer) )
|
||||
{
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
|
||||
op->u.getmemlist.num_pfns = i - start_page;
|
||||
copy_to_user(u_dom0_op, op, sizeof(*op));
|
||||
|
||||
put_domain(d);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
@@ -43,10 +78,3 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void arch_getdomaininfo_ctxt(struct domain *d, struct vcpu_guest_context *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
dummy();
|
||||
}
|
||||
+96
-130
@@ -76,7 +76,7 @@ extern unsigned long dom_fw_setup(struct domain *, char *, int);
|
||||
/* this belongs in include/asm, but there doesn't seem to be a suitable place */
|
||||
void free_perdomain_pt(struct domain *d)
|
||||
{
|
||||
dummy();
|
||||
printf("free_perdomain_pt: not implemented\n");
|
||||
//free_page((unsigned long)d->mm.perdomain_pt);
|
||||
}
|
||||
|
||||
@@ -166,27 +166,49 @@ void arch_free_vcpu_struct(struct vcpu *v)
|
||||
free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
|
||||
}
|
||||
|
||||
static void init_switch_stack(struct vcpu *v)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
|
||||
struct switch_stack *sw = (struct switch_stack *) regs - 1;
|
||||
extern void ia64_ret_from_clone;
|
||||
|
||||
memset(sw, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs));
|
||||
sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET;
|
||||
sw->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
sw->ar_fpsr = FPSR_DEFAULT;
|
||||
v->arch._thread.ksp = (unsigned long) sw - 16;
|
||||
// stay on kernel stack because may get interrupts!
|
||||
// ia64_ret_from_clone (which b0 gets in new_thread) switches
|
||||
// to user stack
|
||||
v->arch._thread.on_ustack = 0;
|
||||
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VTI
|
||||
void arch_do_createdomain(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
struct thread_info *ti = alloc_thread_info(v);
|
||||
|
||||
/* If domain is VMX domain, shared info area is created
|
||||
* by domain and then domain notifies HV by specific hypercall.
|
||||
* If domain is xenolinux, shared info area is created by
|
||||
* HV.
|
||||
* Since we have no idea about whether domain is VMX now,
|
||||
* (dom0 when parse and domN when build), postpone possible
|
||||
* allocation.
|
||||
*/
|
||||
/* Clear thread_info to clear some important fields, like preempt_count */
|
||||
memset(ti, 0, sizeof(struct thread_info));
|
||||
init_switch_stack(v);
|
||||
|
||||
/* Shared info area is required to be allocated at domain
|
||||
* creation, since control panel will write some I/O info
|
||||
* between front end and back end to that area. However for
|
||||
* vmx domain, our design is to let domain itself to allcoate
|
||||
* shared info area, to keep machine page contiguous. So this
|
||||
* page will be released later when domainN issues request
|
||||
* after up.
|
||||
*/
|
||||
d->shared_info = (void *)alloc_xenheap_page();
|
||||
|
||||
/* FIXME: Because full virtual cpu info is placed in this area,
|
||||
* it's unlikely to put it into one shareinfo page. Later
|
||||
* need split vcpu context from vcpu_info and conforms to
|
||||
* normal xen convention.
|
||||
*/
|
||||
d->shared_info = NULL;
|
||||
v->vcpu_info = (void *)alloc_xenheap_page();
|
||||
if (!v->vcpu_info) {
|
||||
printk("ERROR/HALTING: CAN'T ALLOC PAGE\n");
|
||||
@@ -194,9 +216,6 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
}
|
||||
memset(v->vcpu_info, 0, PAGE_SIZE);
|
||||
|
||||
/* Clear thread_info to clear some important fields, like preempt_count */
|
||||
memset(ti, 0, sizeof(struct thread_info));
|
||||
|
||||
/* Allocate per-domain vTLB and vhpt */
|
||||
v->arch.vtlb = init_domain_tlb(v);
|
||||
|
||||
@@ -211,38 +230,25 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
d->xen_vastart = 0xf000000000000000;
|
||||
d->xen_vaend = 0xf300000000000000;
|
||||
d->arch.breakimm = 0x1000;
|
||||
|
||||
// stay on kernel stack because may get interrupts!
|
||||
// ia64_ret_from_clone (which b0 gets in new_thread) switches
|
||||
// to user stack
|
||||
v->arch._thread.on_ustack = 0;
|
||||
}
|
||||
#else // CONFIG_VTI
|
||||
void arch_do_createdomain(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
struct thread_info *ti = alloc_thread_info(v);
|
||||
|
||||
/* Clear thread_info to clear some important fields, like preempt_count */
|
||||
memset(ti, 0, sizeof(struct thread_info));
|
||||
init_switch_stack(v);
|
||||
|
||||
d->shared_info = (void *)alloc_xenheap_page();
|
||||
v->vcpu_info = (void *)alloc_xenheap_page();
|
||||
if (!v->vcpu_info) {
|
||||
if (!d->shared_info) {
|
||||
printk("ERROR/HALTING: CAN'T ALLOC PAGE\n");
|
||||
while (1);
|
||||
}
|
||||
memset(v->vcpu_info, 0, PAGE_SIZE);
|
||||
/* pin mapping */
|
||||
// FIXME: Does this belong here? Or do only at domain switch time?
|
||||
#if 0
|
||||
// this is now done in ia64_new_rr7
|
||||
{
|
||||
/* WARNING: following must be inlined to avoid nested fault */
|
||||
unsigned long psr = ia64_clear_ic();
|
||||
ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR,
|
||||
pte_val(pfn_pte(ia64_tpa(d->shared_info) >> PAGE_SHIFT, PAGE_KERNEL)),
|
||||
PAGE_SHIFT);
|
||||
ia64_set_psr(psr);
|
||||
ia64_srlz_i();
|
||||
}
|
||||
#endif
|
||||
memset(d->shared_info, 0, PAGE_SIZE);
|
||||
v->vcpu_info = &(d->shared_info->vcpu_data[0]);
|
||||
|
||||
d->max_pages = (128*1024*1024)/PAGE_SIZE; // 128MB default // FIXME
|
||||
if ((d->arch.metaphysical_rr0 = allocate_metaphysical_rr0()) == -1UL)
|
||||
BUG();
|
||||
@@ -258,33 +264,63 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
d->shared_info_va = 0xf100000000000000;
|
||||
d->arch.breakimm = 0x1000;
|
||||
v->arch.breakimm = d->arch.breakimm;
|
||||
// stay on kernel stack because may get interrupts!
|
||||
// ia64_ret_from_clone (which b0 gets in new_thread) switches
|
||||
// to user stack
|
||||
v->arch._thread.on_ustack = 0;
|
||||
|
||||
d->arch.mm = xmalloc(struct mm_struct);
|
||||
if (unlikely(!d->arch.mm)) {
|
||||
printk("Can't allocate mm_struct for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
|
||||
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
|
||||
if (unlikely(!d->arch.mm->pgd)) {
|
||||
printk("Can't allocate pgd for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_VTI
|
||||
|
||||
void arch_do_boot_vcpu(struct vcpu *v)
|
||||
void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
{
|
||||
return;
|
||||
struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
|
||||
|
||||
printf("arch_getdomaininfo_ctxt\n");
|
||||
c->regs = *regs;
|
||||
c->vcpu = v->vcpu_info->arch;
|
||||
c->shared = v->domain->shared_info->arch;
|
||||
}
|
||||
|
||||
int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
{
|
||||
dummy();
|
||||
return 1;
|
||||
struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
|
||||
|
||||
printf("arch_set_info_guest\n");
|
||||
*regs = c->regs;
|
||||
regs->cr_ipsr = IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IC|IA64_PSR_I|IA64_PSR_DFH|IA64_PSR_BN|IA64_PSR_SP|IA64_PSR_DI;
|
||||
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
|
||||
regs->ar_rsc |= (2 << 2); /* force PL2/3 */
|
||||
|
||||
v->vcpu_info->arch = c->vcpu;
|
||||
init_all_rr(v);
|
||||
|
||||
// this should be in userspace
|
||||
regs->r28 = dom_fw_setup(v->domain,"nomca nosmp xencons=ttyS console=ttyS0",256L); //FIXME
|
||||
v->vcpu_info->arch.banknum = 1;
|
||||
v->vcpu_info->arch.metaphysical_mode = 1;
|
||||
|
||||
v->domain->shared_info->arch = c->shared;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_final_setup_guest(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
void arch_do_boot_vcpu(struct vcpu *v)
|
||||
{
|
||||
dummy();
|
||||
return 1;
|
||||
printf("arch_do_boot_vcpu: not implemented\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void domain_relinquish_resources(struct domain *d)
|
||||
{
|
||||
dummy();
|
||||
/* FIXME */
|
||||
printf("domain_relinquish_resources: not implemented\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VTI
|
||||
@@ -294,10 +330,8 @@ void new_thread(struct vcpu *v,
|
||||
unsigned long start_info)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
struct switch_stack *sw;
|
||||
struct xen_regs *regs;
|
||||
struct ia64_boot_param *bp;
|
||||
extern char ia64_ret_from_clone;
|
||||
extern char saved_command_line[];
|
||||
//char *dom0_cmdline = "BOOT_IMAGE=scsi0:\EFI\redhat\xenlinux nomca root=/dev/sdb1 ro";
|
||||
|
||||
@@ -305,11 +339,8 @@ void new_thread(struct vcpu *v,
|
||||
#ifdef CONFIG_DOMAIN0_CONTIGUOUS
|
||||
if (d == dom0) start_pc += dom0_start;
|
||||
#endif
|
||||
regs = (struct xen_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
|
||||
sw = (struct switch_stack *) regs - 1;
|
||||
/* Sanity Clear */
|
||||
memset(sw, 0, sizeof(struct xen_regs) + sizeof(struct switch_stack));
|
||||
|
||||
regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
|
||||
if (VMX_DOMAIN(v)) {
|
||||
/* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
|
||||
regs->cr_ipsr = 0x501008826008; /* Need to be expanded as macro */
|
||||
@@ -320,33 +351,23 @@ void new_thread(struct vcpu *v,
|
||||
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2
|
||||
}
|
||||
regs->cr_iip = start_pc;
|
||||
regs->ar_rsc = 0x0;
|
||||
regs->cr_ifs = 0x0;
|
||||
regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT;
|
||||
sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET;
|
||||
printf("new_thread: v=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n",
|
||||
v,regs,sw,sw->ar_bspstore,IA64_STK_OFFSET,®s->r8);
|
||||
printf("iip:0x%lx,ipsr:0x%lx\n", regs->cr_iip, regs->cr_ipsr);
|
||||
|
||||
sw->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
v->arch._thread.ksp = (unsigned long) sw - 16;
|
||||
printk("new_thread, about to call init_all_rr\n");
|
||||
regs->cr_ifs = 0; /* why? - matthewc */
|
||||
regs->ar_fpsr = FPSR_DEFAULT;
|
||||
if (VMX_DOMAIN(v)) {
|
||||
vmx_init_all_rr(v);
|
||||
} else
|
||||
init_all_rr(v);
|
||||
// set up boot parameters (and fake firmware)
|
||||
printk("new_thread, about to call dom_fw_setup\n");
|
||||
VMX_VPD(v,vgr[12]) = dom_fw_setup(d,saved_command_line,256L); //FIXME
|
||||
printk("new_thread, done with dom_fw_setup\n");
|
||||
|
||||
if (VMX_DOMAIN(v)) {
|
||||
VMX_VPD(v,vgr[12]) = dom_fw_setup(d,saved_command_line,256L);
|
||||
/* Virtual processor context setup */
|
||||
VMX_VPD(v, vpsr) = IA64_PSR_BN;
|
||||
VPD_CR(v, dcr) = 0;
|
||||
} else {
|
||||
// don't forget to set this!
|
||||
regs->r28 = dom_fw_setup(d,saved_command_line,256L);
|
||||
v->vcpu_info->arch.banknum = 1;
|
||||
v->vcpu_info->arch.metaphysical_mode = 1;
|
||||
d->shared_info->arch.flags = (d == dom0) ? (SIF_INITDOMAIN|SIF_PRIVILEGED|SIF_BLK_BE_DOMAIN|SIF_NET_BE_DOMAIN|SIF_USB_BE_DOMAIN) : 0;
|
||||
}
|
||||
}
|
||||
#else // CONFIG_VTI
|
||||
@@ -359,54 +380,27 @@ void new_thread(struct vcpu *v,
|
||||
unsigned long start_info)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
struct switch_stack *sw;
|
||||
struct pt_regs *regs;
|
||||
unsigned long new_rbs;
|
||||
struct ia64_boot_param *bp;
|
||||
extern char ia64_ret_from_clone;
|
||||
extern char saved_command_line[];
|
||||
|
||||
#ifdef CONFIG_DOMAIN0_CONTIGUOUS
|
||||
if (d == dom0) start_pc += dom0_start;
|
||||
#endif
|
||||
|
||||
regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
|
||||
sw = (struct switch_stack *) regs - 1;
|
||||
memset(sw,0,sizeof(struct switch_stack)+sizeof(struct pt_regs));
|
||||
new_rbs = (unsigned long) v + IA64_RBS_OFFSET;
|
||||
regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
|
||||
| IA64_PSR_BITS_TO_SET | IA64_PSR_BN
|
||||
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS);
|
||||
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2
|
||||
regs->cr_iip = start_pc;
|
||||
regs->ar_rsc = 0; /* lazy mode */
|
||||
regs->ar_rnat = 0;
|
||||
regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT;
|
||||
regs->loadrs = 0;
|
||||
//regs->r8 = current->mm->dumpable; /* set "don't zap registers" flag */
|
||||
//regs->r8 = 0x01234567890abcdef; // FIXME: temp marker
|
||||
//regs->r12 = ((unsigned long) regs - 16); /* 16 byte scratch */
|
||||
regs->cr_ifs = 1UL << 63;
|
||||
regs->pr = 0;
|
||||
sw->pr = 0;
|
||||
regs->ar_pfs = 0;
|
||||
sw->caller_unat = 0;
|
||||
sw->ar_pfs = 0;
|
||||
sw->ar_bspstore = new_rbs;
|
||||
//regs->r13 = (unsigned long) v;
|
||||
printf("new_thread: v=%p, start_pc=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n",
|
||||
v,start_pc,regs,sw,new_rbs,IA64_STK_OFFSET,®s->r8);
|
||||
sw->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
v->arch._thread.ksp = (unsigned long) sw - 16;
|
||||
//v->thread_info->flags = 0;
|
||||
printk("new_thread, about to call init_all_rr\n");
|
||||
regs->ar_fpsr = FPSR_DEFAULT;
|
||||
init_all_rr(v);
|
||||
// set up boot parameters (and fake firmware)
|
||||
printk("new_thread, about to call dom_fw_setup\n");
|
||||
regs->r28 = dom_fw_setup(d,saved_command_line,256L); //FIXME
|
||||
printk("new_thread, done with dom_fw_setup\n");
|
||||
// don't forget to set this!
|
||||
v->vcpu_info->arch.banknum = 1;
|
||||
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
|
||||
v->vcpu_info->arch.metaphysical_mode = 1;
|
||||
d->shared_info->arch.flags = (d == dom0) ? (SIF_INITDOMAIN|SIF_PRIVILEGED|SIF_BLK_BE_DOMAIN|SIF_NET_BE_DOMAIN|SIF_USB_BE_DOMAIN) : 0;
|
||||
}
|
||||
#endif // CONFIG_VTI
|
||||
|
||||
@@ -1037,21 +1031,6 @@ int construct_dom0(struct domain *d,
|
||||
strcpy(d->name,"Domain0");
|
||||
#endif
|
||||
|
||||
// prepare domain0 pagetable (maps METAphysical to physical)
|
||||
// following is roughly mm_init() in linux/kernel/fork.c
|
||||
d->arch.mm = xmalloc(struct mm_struct);
|
||||
if (unlikely(!d->arch.mm)) {
|
||||
printk("Can't allocate mm_struct for domain0\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
|
||||
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
|
||||
if (unlikely(!d->arch.mm->pgd)) {
|
||||
printk("Can't allocate pgd for domain0\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/* Mask all upcalls... */
|
||||
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||||
d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
|
||||
@@ -1146,19 +1125,6 @@ int construct_domU(struct domain *d,
|
||||
printk("parsedomainelfimage returns %d\n",rc);
|
||||
if ( rc != 0 ) return rc;
|
||||
|
||||
d->arch.mm = xmalloc(struct mm_struct);
|
||||
if (unlikely(!d->arch.mm)) {
|
||||
printk("Can't allocate mm_struct for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
|
||||
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
|
||||
if (unlikely(!d->arch.mm->pgd)) {
|
||||
printk("Can't allocate pgd for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/* Mask all upcalls... */
|
||||
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||||
d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
|
||||
@@ -1231,10 +1197,10 @@ void machine_halt(void)
|
||||
while(1);
|
||||
}
|
||||
|
||||
void dummy(void)
|
||||
void dummy_called(char *function)
|
||||
{
|
||||
if (platform_is_hp_ski()) asm("break 0;;");
|
||||
printf("dummy called: spinning....\n");
|
||||
printf("dummy called in %s: spinning....\n", function);
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@ extern unsigned long translate_domain_mpaddr(unsigned long);
|
||||
extern struct ia64_sal_retval pal_emulator_static(UINT64);
|
||||
extern struct ia64_sal_retval sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
|
||||
|
||||
void fooefi(void) {}
|
||||
|
||||
int
|
||||
ia64_hypercall (struct pt_regs *regs)
|
||||
{
|
||||
@@ -122,6 +120,31 @@ ia64_hypercall (struct pt_regs *regs)
|
||||
case 0xfffb: // test dummy hypercall
|
||||
regs->r8 = domU_staging_read_8(vcpu_get_gr(v,32));
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_dom0_op:
|
||||
regs->r8 = do_dom0_op(regs->r14);
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_dom_mem_op:
|
||||
#ifdef CONFIG_VTI
|
||||
regs->r8 = do_dom_mem_op(regs->r14, regs->r15, regs->r16, regs->r17, regs->r18);
|
||||
#else
|
||||
/* we don't handle reservations; just return success */
|
||||
regs->r8 = regs->r16;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_event_channel_op:
|
||||
regs->r8 = do_event_channel_op(regs->r14);
|
||||
break;
|
||||
|
||||
case __HYPERVISOR_console_io:
|
||||
regs->r8 = do_console_io(regs->r14, regs->r15, regs->r16);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unknown hypercall %x\n", regs->r2);
|
||||
regs->r8 = (unsigned long)-1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
+35
-19
@@ -41,40 +41,46 @@
|
||||
// r19 == vpsr.ic (low 32 bits) | vpsr.i (high 32 bits)
|
||||
// r31 == pr
|
||||
GLOBAL_ENTRY(fast_hyperprivop)
|
||||
#if 1
|
||||
// HYPERPRIVOP_SSM_I?
|
||||
// assumes domain interrupts pending, so just do it
|
||||
cmp.eq p7,p6=XEN_HYPER_SSM_I,r17
|
||||
(p7) br.sptk.many hyper_ssm_i;;
|
||||
#endif
|
||||
#if 1
|
||||
// if domain interrupts pending, give up for now and do it the slow way
|
||||
|
||||
// FIXME. This algorithm gives up (goes to the slow path) if there
|
||||
// are ANY interrupts pending, even if they are currently
|
||||
// undeliverable. This should be improved later...
|
||||
adds r20=XSI_PEND_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
ld8 r20=[r20] ;;
|
||||
cmp.ne p7,p0=r0,r20
|
||||
(p7) br.sptk.many dispatch_break_fault ;;
|
||||
ld4 r20=[r20] ;;
|
||||
cmp.eq p7,p0=r0,r20
|
||||
(p7) br.cond.sptk.many 1f
|
||||
mov r20=IA64_KR(CURRENT);;
|
||||
adds r21=IA64_VCPU_IRR0_OFFSET,r20;
|
||||
adds r22=IA64_VCPU_IRR0_OFFSET+8,r20;;
|
||||
ld8 r23=[r21],16; ld8 r24=[r22],16;;
|
||||
ld8 r21=[r21]; ld8 r22=[r22];;
|
||||
or r23=r23,r24; or r21=r21,r22;;
|
||||
or r20=r23,r21;;
|
||||
1: // when we get to here r20=~=interrupts pending
|
||||
|
||||
// HYPERPRIVOP_RFI?
|
||||
cmp.eq p7,p6=XEN_HYPER_RFI,r17
|
||||
(p7) br.sptk.many hyper_rfi;;
|
||||
|
||||
cmp.ne p7,p0=r20,r0
|
||||
(p7) br.spnt.many dispatch_break_fault ;;
|
||||
|
||||
// hard to test, because only called from rbs_switch
|
||||
// HYPERPRIVOP_COVER?
|
||||
cmp.eq p7,p6=XEN_HYPER_COVER,r17
|
||||
(p7) br.sptk.many hyper_cover;;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// HYPERPRIVOP_SSM_DT?
|
||||
cmp.eq p7,p6=XEN_HYPER_SSM_DT,r17
|
||||
(p7) br.sptk.many hyper_ssm_dt;;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// HYPERPRIVOP_RSM_DT?
|
||||
cmp.eq p7,p6=XEN_HYPER_RSM_DT,r17
|
||||
(p7) br.sptk.many hyper_rsm_dt;;
|
||||
#endif
|
||||
|
||||
// if not one of the above, give up for now and do it the slow way
|
||||
br.sptk.many dispatch_break_fault ;;
|
||||
@@ -336,12 +342,16 @@ GLOBAL_ENTRY(fast_break_reflect)
|
||||
|
||||
// ensure that, if giving up, registers at entry to fast_hyperprivop unchanged
|
||||
ENTRY(hyper_rfi)
|
||||
#ifdef FAST_HYPERPRIVOP_CNT
|
||||
movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
|
||||
ld8 r21=[r20];;
|
||||
adds r21=1,r21;;
|
||||
st8 [r20]=r21;;
|
||||
#endif
|
||||
// if no interrupts pending, proceed
|
||||
cmp.eq p7,p0=r20,r0
|
||||
(p7) br.sptk.many 1f
|
||||
// interrupts pending, if rfi'ing to interrupts on, go slow way
|
||||
adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
ld8 r21=[r20];; // r21 = vcr.ipsr
|
||||
extr.u r22=r21,IA64_PSR_I_BIT,1 ;;
|
||||
cmp.ne p7,p0=r22,r0 ;;
|
||||
(p7) br.spnt.many dispatch_break_fault ;;
|
||||
1:
|
||||
adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
ld8 r21=[r20];; // r21 = vcr.ipsr
|
||||
extr.u r22=r21,IA64_PSR_BE_BIT,1 ;;
|
||||
@@ -375,7 +385,13 @@ ENTRY(hyper_rfi)
|
||||
(p7) br.sptk.many dispatch_break_fault ;;
|
||||
|
||||
// OK now, let's do an rfi.
|
||||
// r18=&vpsr.i|vpsr.ic, r21==vpsr, r20==&vcr.iip, r22=vcr.iip
|
||||
#ifdef FAST_HYPERPRIVOP_CNT
|
||||
movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
|
||||
ld8 r23=[r20];;
|
||||
adds r23=1,r23;;
|
||||
st8 [r20]=r23;;
|
||||
#endif
|
||||
// r18=&vpsr.i|vpsr.ic, r21==vpsr, r22=vcr.iip
|
||||
mov cr.iip=r22;;
|
||||
adds r20=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
st4 [r20]=r0 ;;
|
||||
|
||||
+40
-9
@@ -348,12 +348,23 @@ ENTRY(alt_itlb_miss)
|
||||
// ;;
|
||||
//#endif
|
||||
#endif
|
||||
#ifdef XEN
|
||||
mov r31=pr
|
||||
mov r16=cr.ifa // get address that caused the TLB miss
|
||||
;;
|
||||
late_alt_itlb_miss:
|
||||
movl r17=PAGE_KERNEL
|
||||
mov r21=cr.ipsr
|
||||
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
|
||||
;;
|
||||
#else
|
||||
mov r16=cr.ifa // get address that caused the TLB miss
|
||||
movl r17=PAGE_KERNEL
|
||||
mov r21=cr.ipsr
|
||||
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
|
||||
mov r31=pr
|
||||
;;
|
||||
#endif
|
||||
#ifdef CONFIG_DISABLE_VHPT
|
||||
shr.u r22=r16,61 // get the region number into r21
|
||||
;;
|
||||
@@ -367,9 +378,15 @@ ENTRY(alt_itlb_miss)
|
||||
#endif
|
||||
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
|
||||
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
|
||||
#ifdef XEN
|
||||
shr.u r18=r16,55 // move address bit 59 to bit 4
|
||||
;;
|
||||
and r18=0x10,r18 // bit 4=address-bit(59)
|
||||
#else
|
||||
shr.u r18=r16,57 // move address bit 61 to bit 4
|
||||
;;
|
||||
andcm r18=0x10,r18 // bit 4=~address-bit(61)
|
||||
#endif
|
||||
cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
|
||||
or r19=r17,r19 // insert PTE control bits into r19
|
||||
;;
|
||||
@@ -393,13 +410,18 @@ ENTRY(alt_dtlb_miss)
|
||||
// ;;
|
||||
//#endif
|
||||
#endif
|
||||
#ifdef XEN
|
||||
mov r31=pr
|
||||
mov r16=cr.ifa // get address that caused the TLB miss
|
||||
;;
|
||||
late_alt_dtlb_miss:
|
||||
movl r17=PAGE_KERNEL
|
||||
mov r20=cr.isr
|
||||
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
|
||||
mov r21=cr.ipsr
|
||||
mov r31=pr
|
||||
;;
|
||||
#else
|
||||
#endif
|
||||
#ifdef CONFIG_DISABLE_VHPT
|
||||
shr.u r22=r16,61 // get the region number into r21
|
||||
;;
|
||||
@@ -414,24 +436,33 @@ ENTRY(alt_dtlb_miss)
|
||||
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
|
||||
and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
|
||||
tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
|
||||
#ifdef XEN
|
||||
shr.u r18=r16,55 // move address bit 59 to bit 4
|
||||
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
|
||||
tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
|
||||
;;
|
||||
and r18=0x10,r18 // bit 4=address-bit(59)
|
||||
#else
|
||||
shr.u r18=r16,57 // move address bit 61 to bit 4
|
||||
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
|
||||
tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
|
||||
;;
|
||||
andcm r18=0x10,r18 // bit 4=~address-bit(61)
|
||||
#endif
|
||||
cmp.ne p8,p0=r0,r23
|
||||
(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
|
||||
(p8) br.cond.spnt page_fault
|
||||
#ifdef XEN
|
||||
;;
|
||||
// FIXME: inadequate test, this is where we test for Xen address
|
||||
// note that 0xf000 (cached) and 0xd000 (uncached) addresses
|
||||
// should be OK. (Though no I/O is done in Xen, EFI needs uncached
|
||||
// addresses and some domain EFI calls are passed through)
|
||||
tbit.nz p0,p8=r16,60
|
||||
(p8) br.cond.spnt page_fault
|
||||
//(p8) br.cond.spnt 0
|
||||
;;
|
||||
// Test for Xen address, if not handle via page_fault
|
||||
// note that 0xf000 (cached) and 0xe800 (uncached) addresses
|
||||
// should be OK.
|
||||
extr.u r22=r16,59,5;;
|
||||
cmp.eq p8,p0=0x1e,r22
|
||||
(p8) br.cond.spnt 1f;;
|
||||
cmp.ne p8,p0=0x1d,r22
|
||||
(p8) br.cond.sptk page_fault ;;
|
||||
1:
|
||||
#endif
|
||||
|
||||
dep r21=-1,r21,IA64_PSR_ED_BIT,1
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#define SLOW_DOWN_IO do { } while (0)
|
||||
|
||||
+#ifdef XEN
|
||||
+#define __IA64_UNCACHED_OFFSET 0xd000000000000000UL /* region 6 */
|
||||
+#define __IA64_UNCACHED_OFFSET 0xe800000000000000UL
|
||||
+#else
|
||||
#define __IA64_UNCACHED_OFFSET 0xc000000000000000UL /* region 6 */
|
||||
+#endif
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* (because the memory stack pointer MUST ALWAYS be aligned this way)
|
||||
*
|
||||
*/
|
||||
+#ifdef CONFIG_VTI
|
||||
+#include "vmx_ptrace.h"
|
||||
+#else //CONFIG_VTI
|
||||
+#ifdef XEN
|
||||
+#include <public/arch-ia64.h>
|
||||
+#else
|
||||
struct pt_regs {
|
||||
/* The following registers are saved by SAVE_MIN: */
|
||||
unsigned long b6; /* scratch */
|
||||
@@ -14,7 +14,7 @@
|
||||
struct ia64_fpreg f10; /* scratch */
|
||||
struct ia64_fpreg f11; /* scratch */
|
||||
};
|
||||
+#endif // CONFIG_VTI
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* This structure contains the addition registers that need to
|
||||
@@ -0,0 +1,22 @@
|
||||
--- ../../linux-2.6.11/include/asm-ia64/uaccess.h 2005-06-06 10:36:23.000000000 -0600
|
||||
+++ include/asm-ia64/uaccess.h 2005-06-10 18:08:06.000000000 -0600
|
||||
@@ -60,6 +60,11 @@
|
||||
* address TASK_SIZE is never valid. We also need to make sure that the address doesn't
|
||||
* point inside the virtually mapped linear page table.
|
||||
*/
|
||||
+#ifdef XEN
|
||||
+/* VT-i reserves bit 60 for the VMM; guest addresses have bit 60 = bit 59 */
|
||||
+#define IS_VMM_ADDRESS(addr) ((((addr) >> 60) ^ ((addr) >> 59)) & 1)
|
||||
+#define __access_ok(addr, size, segment) (!IS_VMM_ADDRESS((unsigned long)(addr)))
|
||||
+#else
|
||||
#define __access_ok(addr, size, segment) \
|
||||
({ \
|
||||
__chk_user_ptr(addr); \
|
||||
@@ -67,6 +72,7 @@
|
||||
&& ((segment).seg == KERNEL_DS.seg \
|
||||
|| likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))); \
|
||||
})
|
||||
+#endif
|
||||
#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs())
|
||||
|
||||
static inline int
|
||||
+52
-1
@@ -748,10 +748,22 @@ priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr)
|
||||
#define HYPERPRIVOP_ITC_D 0x5
|
||||
#define HYPERPRIVOP_ITC_I 0x6
|
||||
#define HYPERPRIVOP_SSM_I 0x7
|
||||
#define HYPERPRIVOP_MAX 0x7
|
||||
#define HYPERPRIVOP_GET_IVR 0x8
|
||||
#define HYPERPRIVOP_GET_TPR 0x9
|
||||
#define HYPERPRIVOP_SET_TPR 0xa
|
||||
#define HYPERPRIVOP_EOI 0xb
|
||||
#define HYPERPRIVOP_SET_ITM 0xc
|
||||
#define HYPERPRIVOP_THASH 0xd
|
||||
#define HYPERPRIVOP_PTC_GA 0xe
|
||||
#define HYPERPRIVOP_ITR_D 0xf
|
||||
#define HYPERPRIVOP_GET_RR 0x10
|
||||
#define HYPERPRIVOP_SET_RR 0x11
|
||||
#define HYPERPRIVOP_MAX 0x11
|
||||
|
||||
char *hyperpriv_str[HYPERPRIVOP_MAX+1] = {
|
||||
0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i", "ssm.i",
|
||||
"=ivr", "=tpr", "tpr=", "eoi", "itm=", "thash", "ptc.ga", "itr.d",
|
||||
"=rr", "rr=",
|
||||
0
|
||||
};
|
||||
|
||||
@@ -766,6 +778,7 @@ ia64_hyperprivop(unsigned long iim, REGS *regs)
|
||||
struct vcpu *v = (struct domain *) current;
|
||||
INST64 inst;
|
||||
UINT64 val;
|
||||
UINT64 itir, ifa;
|
||||
|
||||
// FIXME: Handle faults appropriately for these
|
||||
if (!iim || iim > HYPERPRIVOP_MAX) {
|
||||
@@ -797,6 +810,44 @@ ia64_hyperprivop(unsigned long iim, REGS *regs)
|
||||
case HYPERPRIVOP_SSM_I:
|
||||
(void)vcpu_set_psr_i(v);
|
||||
return 1;
|
||||
case HYPERPRIVOP_GET_IVR:
|
||||
(void)vcpu_get_ivr(v,&val);
|
||||
regs->r8 = val;
|
||||
return 1;
|
||||
case HYPERPRIVOP_GET_TPR:
|
||||
(void)vcpu_get_tpr(v,&val);
|
||||
regs->r8 = val;
|
||||
return 1;
|
||||
case HYPERPRIVOP_SET_TPR:
|
||||
(void)vcpu_set_tpr(v,regs->r8);
|
||||
return 1;
|
||||
case HYPERPRIVOP_EOI:
|
||||
(void)vcpu_set_eoi(v,0L);
|
||||
return 1;
|
||||
case HYPERPRIVOP_SET_ITM:
|
||||
(void)vcpu_set_itm(v,regs->r8);
|
||||
return 1;
|
||||
case HYPERPRIVOP_THASH:
|
||||
(void)vcpu_thash(v,regs->r8,&val);
|
||||
regs->r8 = val;
|
||||
return 1;
|
||||
case HYPERPRIVOP_PTC_GA:
|
||||
// FIXME: this doesn't seem to work yet, turned off
|
||||
//(void)vcpu_ptc_ga(v,regs->r8,regs->r9);
|
||||
//return 1;
|
||||
break;
|
||||
case HYPERPRIVOP_ITR_D:
|
||||
(void)vcpu_get_itir(v,&itir);
|
||||
(void)vcpu_get_ifa(v,&ifa);
|
||||
(void)vcpu_itr_d(v,regs->r8,regs->r9,itir,ifa);
|
||||
return 1;
|
||||
case HYPERPRIVOP_GET_RR:
|
||||
(void)vcpu_get_rr(v,regs->r8,&val);
|
||||
regs->r8 = val;
|
||||
return 1;
|
||||
case HYPERPRIVOP_SET_RR:
|
||||
(void)vcpu_set_rr(v,regs->r8,regs->r9);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+18
-32
@@ -313,45 +313,31 @@ void xen_handle_domain_access(unsigned long address, unsigned long isr, struct p
|
||||
}
|
||||
if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip);
|
||||
|
||||
if (trp = match_tr(current,address)) {
|
||||
// FIXME address had better be pre-validated on insert
|
||||
pteval = translate_domain_pte(trp->page_flags,address,trp->itir);
|
||||
vcpu_itc_no_srlz(current,6,address,pteval,-1UL,(trp->itir>>2)&0x3f);
|
||||
return;
|
||||
}
|
||||
// if we are fortunate enough to have it in the 1-entry TLB...
|
||||
if (pteval = match_dtlb(ed,address,&ps,NULL)) {
|
||||
vcpu_itc_no_srlz(ed,6,address,pteval,-1UL,ps);
|
||||
return;
|
||||
}
|
||||
// look in the TRs
|
||||
fault = vcpu_tpa(ed,address,&mpaddr);
|
||||
if (fault != IA64_NO_FAULT) {
|
||||
static int uacnt = 0;
|
||||
// can't translate it, just fail (poor man's exception)
|
||||
// which results in retrying execution
|
||||
//printk("*** xen_handle_domain_access: poor man's exception cnt=%i iip=%p, addr=%p...\n",uacnt++,iip,address);
|
||||
if (ia64_done_with_exception(regs)) {
|
||||
if (ia64_done_with_exception(regs)) {
|
||||
//if (!(uacnt++ & 0x3ff)) printk("*** xen_handle_domain_access: successfully handled cnt=%d iip=%p, addr=%p...\n",uacnt,iip,address);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// should never happen. If it does, region 0 addr may
|
||||
// indicate a bad xen pointer
|
||||
printk("*** xen_handle_domain_access: exception table"
|
||||
" lookup failed, iip=%p, addr=%p, spinning...\n",
|
||||
iip,address);
|
||||
panic_domain(regs,"*** xen_handle_domain_access: exception table"
|
||||
" lookup failed, iip=%p, addr=%p, spinning...\n",
|
||||
iip,address);
|
||||
}
|
||||
}
|
||||
if (d == dom0) {
|
||||
if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
|
||||
printk("xen_handle_domain_access: vcpu_tpa returned out-of-bounds dom0 mpaddr %p! continuing...\n",mpaddr);
|
||||
tdpfoo();
|
||||
}
|
||||
else {
|
||||
// should never happen. If it does, region 0 addr may
|
||||
// indicate a bad xen pointer
|
||||
printk("*** xen_handle_domain_access: exception table"
|
||||
" lookup failed, iip=%p, addr=%p, spinning...\n",
|
||||
iip,address);
|
||||
panic_domain(regs,"*** xen_handle_domain_access: exception table"
|
||||
" lookup failed, iip=%p, addr=%p, spinning...\n",
|
||||
iip,address);
|
||||
}
|
||||
//printk("*** xen_handle_domain_access: tpa resolved miss @%p...\n",address);
|
||||
pteval = lookup_domain_mpa(d,mpaddr);
|
||||
// would be nice to have a counter here
|
||||
//printf("Handling privop data TLB miss\n");
|
||||
// FIXME, must be inlined or potential for nested fault here!
|
||||
vcpu_itc_no_srlz(ed,2,address,pteval,-1UL,PAGE_SHIFT);
|
||||
}
|
||||
|
||||
void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs, unsigned long itir)
|
||||
@@ -441,7 +427,7 @@ panic_domain(0,"ia64_do_page_fault: @%p???, iip=%p, b0=%p, itc=%p (spinning...)\
|
||||
if (pteval & _PAGE_P)
|
||||
{
|
||||
pteval = translate_domain_pte(pteval,address,itir);
|
||||
vcpu_itc_no_srlz(current,is_data?2:1,address,pteval,-1UL,(itir>>2)&0x3f);
|
||||
vcpu_itc_no_srlz(current,is_data?6:1,address,pteval,-1UL,(itir>>2)&0x3f);
|
||||
return;
|
||||
}
|
||||
else vector = is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
|
||||
@@ -768,7 +754,7 @@ if (!running_on_sim) { printf("SSC_OPEN, not implemented on hardware. (ignoring
|
||||
vcpu_set_gr(current,8,-1L);
|
||||
break;
|
||||
default:
|
||||
printf("ia64_handle_break: bad ssc code %lx, iip=%p\n",ssc,regs->cr_iip);
|
||||
printf("ia64_handle_break: bad ssc code %lx, iip=%p, b0=%p\n",ssc,regs->cr_iip,regs->b0);
|
||||
break;
|
||||
}
|
||||
vcpu_increment_iip(current);
|
||||
|
||||
@@ -274,6 +274,7 @@ int set_one_rr(unsigned long rr, unsigned long val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VTI
|
||||
memrrv.rrval = rrv.rrval;
|
||||
if (rreg == 7) {
|
||||
newrrv.rid = newrid;
|
||||
@@ -290,6 +291,15 @@ int set_one_rr(unsigned long rr, unsigned long val)
|
||||
if (rreg == 0) v->arch.metaphysical_saved_rr0 = newrrv.rrval;
|
||||
set_rr(rr,newrrv.rrval);
|
||||
}
|
||||
#else
|
||||
memrrv.rrval = rrv.rrval;
|
||||
newrrv.rid = newrid;
|
||||
newrrv.ve = 1; // VHPT now enabled for region 7!!
|
||||
newrrv.ps = PAGE_SHIFT;
|
||||
if (rreg == 0) v->arch.metaphysical_saved_rr0 = newrrv.rrval;
|
||||
if (rreg == 7) ia64_new_rr7(vmMangleRID(newrrv.rrval),v->vcpu_info);
|
||||
else set_rr(rr,newrrv.rrval);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ softlink include/asm-ia64/string.h include/asm-ia64/string.h
|
||||
softlink include/asm-ia64/thread_info.h include/asm-ia64/thread_info.h
|
||||
softlink include/asm-ia64/timex.h include/asm-ia64/timex.h
|
||||
softlink include/asm-ia64/topology.h include/asm-ia64/topology.h
|
||||
softlink include/asm-ia64/uaccess.h include/asm-ia64/uaccess.h
|
||||
cp_patch include/asm-ia64/uaccess.h include/asm-ia64/uaccess.h uaccess.h
|
||||
softlink include/asm-ia64/unaligned.h include/asm-ia64/unaligned.h
|
||||
softlink include/asm-ia64/unistd.h include/asm-ia64/unistd.h
|
||||
softlink include/asm-ia64/unwind.h include/asm-ia64/unwind.h
|
||||
|
||||
+14
-8
@@ -43,8 +43,9 @@ typedef union {
|
||||
|
||||
#ifdef PRIVOP_ADDR_COUNT
|
||||
struct privop_addr_count privop_addr_counter[PRIVOP_COUNT_NINSTS] = {
|
||||
{ "rsm", { 0 }, { 0 }, 0 },
|
||||
{ "ssm", { 0 }, { 0 }, 0 }
|
||||
{ "=ifa", { 0 }, { 0 }, 0 },
|
||||
{ "thash", { 0 }, { 0 }, 0 },
|
||||
0
|
||||
};
|
||||
extern void privop_count_addr(unsigned long addr, int inst);
|
||||
#define PRIVOP_COUNT_ADDR(regs,inst) privop_count_addr(regs->cr_iip,inst)
|
||||
@@ -135,7 +136,7 @@ IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
|
||||
struct ia64_psr psr, imm, *ipsr;
|
||||
REGS *regs = vcpu_regs(vcpu);
|
||||
|
||||
PRIVOP_COUNT_ADDR(regs,_RSM);
|
||||
//PRIVOP_COUNT_ADDR(regs,_RSM);
|
||||
// TODO: All of these bits need to be virtualized
|
||||
// TODO: Only allowed for current vcpu
|
||||
__asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
|
||||
@@ -183,7 +184,7 @@ IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
|
||||
REGS *regs = vcpu_regs(vcpu);
|
||||
UINT64 mask, enabling_interrupts = 0;
|
||||
|
||||
PRIVOP_COUNT_ADDR(regs,_SSM);
|
||||
//PRIVOP_COUNT_ADDR(regs,_SSM);
|
||||
// TODO: All of these bits need to be virtualized
|
||||
__asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
|
||||
imm = *(struct ia64_psr *)&imm24;
|
||||
@@ -369,6 +370,8 @@ IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval)
|
||||
IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval)
|
||||
{
|
||||
UINT64 val = PSCB(vcpu,ifa);
|
||||
REGS *regs = vcpu_regs(vcpu);
|
||||
PRIVOP_COUNT_ADDR(regs,_GET_IFA);
|
||||
*pval = val;
|
||||
return (IA64_NO_FAULT);
|
||||
}
|
||||
@@ -422,6 +425,8 @@ IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval)
|
||||
{
|
||||
//return vcpu_thash(vcpu,PSCB(vcpu,ifa),pval);
|
||||
UINT64 val = PSCB(vcpu,iha);
|
||||
REGS *regs = vcpu_regs(vcpu);
|
||||
PRIVOP_COUNT_ADDR(regs,_THASH);
|
||||
*pval = val;
|
||||
return (IA64_NO_FAULT);
|
||||
}
|
||||
@@ -539,7 +544,7 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
|
||||
} else
|
||||
#endif // CONFIG_VTI
|
||||
{
|
||||
if (!test_bit(vector,PSCB(vcpu,delivery_mask))) return;
|
||||
/* if (!test_bit(vector,PSCB(vcpu,delivery_mask))) return; */
|
||||
if (test_bit(vector,PSCBX(vcpu,irr))) {
|
||||
//printf("vcpu_pend_interrupt: overrun\n");
|
||||
}
|
||||
@@ -569,10 +574,10 @@ UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
|
||||
UINT64 *p, *q, *r, bits, bitnum, mask, i, vector;
|
||||
|
||||
p = &PSCBX(vcpu,irr[3]);
|
||||
q = &PSCB(vcpu,delivery_mask[3]);
|
||||
/* q = &PSCB(vcpu,delivery_mask[3]); */
|
||||
r = &PSCBX(vcpu,insvc[3]);
|
||||
for (i = 3; ; p--, q--, r--, i--) {
|
||||
bits = *p & *q;
|
||||
bits = *p /* & *q */;
|
||||
if (bits) break; // got a potential interrupt
|
||||
if (*r) {
|
||||
// nothing in this word which is pending+inservice
|
||||
@@ -1589,7 +1594,8 @@ void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64
|
||||
// addresses never get flushed. More work needed if this
|
||||
// ever happens.
|
||||
//printf("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
|
||||
vhpt_insert(vaddr,pte,logps<<2);
|
||||
if (logps > PAGE_SHIFT) vhpt_multiple_insert(vaddr,pte,logps);
|
||||
else vhpt_insert(vaddr,pte,logps<<2);
|
||||
}
|
||||
// even if domain pagesize is larger than PAGE_SIZE, just put
|
||||
// PAGE_SIZE mapping in the vhpt for now, else purging is complicated
|
||||
|
||||
@@ -87,6 +87,37 @@ void vhpt_map(void)
|
||||
ia64_srlz_i();
|
||||
}
|
||||
|
||||
void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long logps)
|
||||
{
|
||||
unsigned long mask = (1L << logps) - 1;
|
||||
int i;
|
||||
|
||||
if (logps-PAGE_SHIFT > 10) {
|
||||
// if this happens, we may want to revisit this algorithm
|
||||
printf("vhpt_multiple_insert:logps-PAGE_SHIFT>10,spinning..\n");
|
||||
while(1);
|
||||
}
|
||||
if (logps-PAGE_SHIFT > 2) {
|
||||
// FIXME: Should add counter here to see how often this
|
||||
// happens (e.g. for 16MB pages!) and determine if it
|
||||
// is a performance problem. On a quick look, it takes
|
||||
// about 39000 instrs for a 16MB page and it seems to occur
|
||||
// only a few times/second, so OK for now.
|
||||
// An alternate solution would be to just insert the one
|
||||
// 16KB in the vhpt (but with the full mapping)?
|
||||
//printf("vhpt_multiple_insert: logps-PAGE_SHIFT==%d,"
|
||||
//"va=%p, pa=%p, pa-masked=%p\n",
|
||||
//logps-PAGE_SHIFT,vaddr,pte&_PFN_MASK,
|
||||
//(pte&_PFN_MASK)&~mask);
|
||||
}
|
||||
vaddr &= ~mask;
|
||||
pte = ((pte & _PFN_MASK) & ~mask) | (pte & ~_PFN_MASK);
|
||||
for (i = 1L << (logps-PAGE_SHIFT); i > 0; i--) {
|
||||
vhpt_insert(vaddr,pte,logps<<2);
|
||||
vaddr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void vhpt_init(void)
|
||||
{
|
||||
unsigned long vhpt_total_size, vhpt_alignment, vhpt_imva;
|
||||
|
||||
+34
-42
@@ -454,12 +454,13 @@ IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
|
||||
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
|
||||
data.itir=itir;
|
||||
data.vadr=PAGEALIGN(ifa,data.ps);
|
||||
data.section=THASH_TLB_TC;
|
||||
data.tc = 1;
|
||||
data.cl=ISIDE_TLB;
|
||||
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
|
||||
data.rid = vrr.rid;
|
||||
|
||||
sections.v = THASH_SECTION_TR;
|
||||
sections.tr = 1;
|
||||
sections.tc = 0;
|
||||
|
||||
ovl = thash_find_overlap(hcb, &data, sections);
|
||||
while (ovl) {
|
||||
@@ -467,9 +468,7 @@ IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
|
||||
panic("Tlb conflict!!");
|
||||
return;
|
||||
}
|
||||
sections.v = THASH_SECTION_TC;
|
||||
thash_purge_entries(hcb, &data, sections);
|
||||
thash_insert(hcb, &data, ifa);
|
||||
thash_purge_and_insert(hcb, &data);
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
@@ -488,11 +487,12 @@ IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
|
||||
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
|
||||
data.itir=itir;
|
||||
data.vadr=PAGEALIGN(ifa,data.ps);
|
||||
data.section=THASH_TLB_TC;
|
||||
data.tc = 1;
|
||||
data.cl=DSIDE_TLB;
|
||||
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
|
||||
data.rid = vrr.rid;
|
||||
sections.v = THASH_SECTION_TR;
|
||||
sections.tr = 1;
|
||||
sections.tc = 0;
|
||||
|
||||
ovl = thash_find_overlap(hcb, &data, sections);
|
||||
if (ovl) {
|
||||
@@ -500,42 +500,27 @@ IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
|
||||
panic("Tlb conflict!!");
|
||||
return;
|
||||
}
|
||||
sections.v = THASH_SECTION_TC;
|
||||
thash_purge_entries(hcb, &data, sections);
|
||||
thash_insert(hcb, &data, ifa);
|
||||
thash_purge_and_insert(hcb, &data);
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
IA64FAULT insert_foreignmap(VCPU *vcpu, UINT64 pte, UINT64 ps, UINT64 va)
|
||||
/*
|
||||
* Return TRUE/FALSE for success of lock operation
|
||||
*/
|
||||
int vmx_lock_guest_dtc (VCPU *vcpu, UINT64 va, int lock)
|
||||
{
|
||||
|
||||
thash_data_t data, *ovl;
|
||||
thash_cb_t *hcb;
|
||||
search_section_t sections;
|
||||
rr_t vrr;
|
||||
rr_t vrr;
|
||||
u64 preferred_size;
|
||||
|
||||
hcb = vmx_vcpu_get_vtlb(vcpu);
|
||||
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
|
||||
data.itir=0;
|
||||
data.ps = ps;
|
||||
data.vadr=PAGEALIGN(va,ps);
|
||||
data.section=THASH_TLB_FM;
|
||||
data.cl=DSIDE_TLB;
|
||||
vmx_vcpu_get_rr(vcpu, va, &vrr);
|
||||
data.rid = vrr.rid;
|
||||
sections.v = THASH_SECTION_TR|THASH_SECTION_TC|THASH_SECTION_FM;
|
||||
|
||||
ovl = thash_find_overlap(hcb, &data, sections);
|
||||
if (ovl) {
|
||||
// generate MCA.
|
||||
panic("Foreignmap Tlb conflict!!");
|
||||
return;
|
||||
}
|
||||
thash_insert(hcb, &data, va);
|
||||
return IA64_NO_FAULT;
|
||||
hcb = vmx_vcpu_get_vtlb(vcpu);
|
||||
va = PAGEALIGN(va,vrr.ps);
|
||||
preferred_size = PSIZE(vrr.ps);
|
||||
return thash_lock_tc(hcb, va, preferred_size, vrr.rid, DSIDE_TLB, lock);
|
||||
}
|
||||
|
||||
|
||||
IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64 idx)
|
||||
{
|
||||
|
||||
@@ -548,11 +533,12 @@ IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
|
||||
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
|
||||
data.itir=itir;
|
||||
data.vadr=PAGEALIGN(ifa,data.ps);
|
||||
data.section=THASH_TLB_TR;
|
||||
data.tc = 0;
|
||||
data.cl=ISIDE_TLB;
|
||||
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
|
||||
data.rid = vrr.rid;
|
||||
sections.v = THASH_SECTION_TR;
|
||||
sections.tr = 1;
|
||||
sections.tc = 0;
|
||||
|
||||
ovl = thash_find_overlap(hcb, &data, sections);
|
||||
if (ovl) {
|
||||
@@ -560,7 +546,8 @@ IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
|
||||
panic("Tlb conflict!!");
|
||||
return;
|
||||
}
|
||||
sections.v=THASH_SECTION_TC;
|
||||
sections.tr = 0;
|
||||
sections.tc = 1;
|
||||
thash_purge_entries(hcb, &data, sections);
|
||||
thash_tr_insert(hcb, &data, ifa, idx);
|
||||
return IA64_NO_FAULT;
|
||||
@@ -579,11 +566,12 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
|
||||
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
|
||||
data.itir=itir;
|
||||
data.vadr=PAGEALIGN(ifa,data.ps);
|
||||
data.section=THASH_TLB_TR;
|
||||
data.tc = 0;
|
||||
data.cl=DSIDE_TLB;
|
||||
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
|
||||
data.rid = vrr.rid;
|
||||
sections.v = THASH_SECTION_TR;
|
||||
sections.tr = 1;
|
||||
sections.tc = 0;
|
||||
|
||||
ovl = thash_find_overlap(hcb, &data, sections);
|
||||
while (ovl) {
|
||||
@@ -591,7 +579,8 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
|
||||
panic("Tlb conflict!!");
|
||||
return;
|
||||
}
|
||||
sections.v=THASH_SECTION_TC;
|
||||
sections.tr = 0;
|
||||
sections.tc = 1;
|
||||
thash_purge_entries(hcb, &data, sections);
|
||||
thash_tr_insert(hcb, &data, ifa, idx);
|
||||
return IA64_NO_FAULT;
|
||||
@@ -607,7 +596,8 @@ IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 ps)
|
||||
|
||||
hcb = vmx_vcpu_get_vtlb(vcpu);
|
||||
rr=vmx_vcpu_rr(vcpu,vadr);
|
||||
sections.v = THASH_SECTION_TR | THASH_SECTION_TC;
|
||||
sections.tr = 1;
|
||||
sections.tc = 1;
|
||||
thash_purge_entries_ex(hcb,rr.rid,vadr,ps,sections,DSIDE_TLB);
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
@@ -619,7 +609,8 @@ IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 ps)
|
||||
search_section_t sections;
|
||||
hcb = vmx_vcpu_get_vtlb(vcpu);
|
||||
rr=vmx_vcpu_rr(vcpu,vadr);
|
||||
sections.v = THASH_SECTION_TR | THASH_SECTION_TC;
|
||||
sections.tr = 1;
|
||||
sections.tc = 1;
|
||||
thash_purge_entries_ex(hcb,rr.rid,vadr,ps,sections,ISIDE_TLB);
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
@@ -632,7 +623,8 @@ IA64FAULT vmx_vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 ps)
|
||||
thash_data_t data, *ovl;
|
||||
hcb = vmx_vcpu_get_vtlb(vcpu);
|
||||
vrr=vmx_vcpu_rr(vcpu,vadr);
|
||||
sections.v = THASH_SECTION_TC;
|
||||
sections.tr = 0;
|
||||
sections.tc = 1;
|
||||
vadr = PAGEALIGN(vadr, ps);
|
||||
|
||||
thash_purge_entries_ex(hcb,vrr.rid,vadr,ps,sections,DSIDE_TLB);
|
||||
|
||||
+76
-8
@@ -180,7 +180,7 @@ ENTRY(vmx_dtlb_miss)
|
||||
mov r29=cr.ipsr;
|
||||
;;
|
||||
tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
|
||||
(p6)br.sptk vmx_fault_1
|
||||
(p6)br.sptk vmx_fault_2
|
||||
mov r16 = cr.ifa
|
||||
;;
|
||||
thash r17 = r16
|
||||
@@ -249,9 +249,9 @@ ENTRY(vmx_alt_itlb_miss)
|
||||
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
|
||||
;;
|
||||
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
|
||||
shr.u r18=r16,57 // move address bit 61 to bit 4
|
||||
shr.u r18=r16,55 // move address bit 59 to bit 4
|
||||
;;
|
||||
andcm r18=0x10,r18 // bit 4=~address-bit(61)
|
||||
and r18=0x10,r18 // bit 4=address-bit(61)
|
||||
or r19=r17,r19 // insert PTE control bits into r19
|
||||
;;
|
||||
or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
|
||||
@@ -280,11 +280,11 @@ ENTRY(vmx_alt_dtlb_miss)
|
||||
;;
|
||||
and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
|
||||
tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
|
||||
shr.u r18=r16,57 // move address bit 61 to bit 4
|
||||
shr.u r18=r16,55 // move address bit 59 to bit 4
|
||||
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
|
||||
tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
|
||||
;;
|
||||
andcm r18=0x10,r18 // bit 4=~address-bit(61)
|
||||
and r18=0x10,r18 // bit 4=address-bit(61)
|
||||
(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
|
||||
dep r24=-1,r24,IA64_PSR_ED_BIT,1
|
||||
or r19=r19,r17 // insert PTE control bits into r19
|
||||
@@ -346,7 +346,12 @@ END(vmx_daccess_bit)
|
||||
ENTRY(vmx_break_fault)
|
||||
mov r31=pr
|
||||
mov r19=11
|
||||
br.sptk.many vmx_dispatch_break_fault
|
||||
mov r30=cr.iim
|
||||
mov r29=0x1100
|
||||
;;
|
||||
cmp4.eq p6,p7=r29,r30
|
||||
(p6) br.dptk.few vmx_hypercall_dispatch
|
||||
(p7) br.sptk.many vmx_dispatch_break_fault
|
||||
END(vmx_break_fault)
|
||||
|
||||
.org vmx_ia64_ivt+0x3000
|
||||
@@ -929,10 +934,9 @@ END(vmx_dispatch_tlb_miss)
|
||||
|
||||
|
||||
ENTRY(vmx_dispatch_break_fault)
|
||||
cmp.ne pEml,pNonEml=r0,r0 /* force pNonEml =1, don't save r4 ~ r7 */
|
||||
;;
|
||||
VMX_SAVE_MIN_WITH_COVER_R19
|
||||
;;
|
||||
;;
|
||||
alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!)
|
||||
mov out0=cr.ifa
|
||||
adds out1=16,sp
|
||||
@@ -951,9 +955,37 @@ ENTRY(vmx_dispatch_break_fault)
|
||||
;;
|
||||
mov rp=r14
|
||||
br.call.sptk.many b6=vmx_ia64_handle_break
|
||||
;;
|
||||
END(vmx_dispatch_break_fault)
|
||||
|
||||
|
||||
ENTRY(vmx_hypercall_dispatch)
|
||||
VMX_SAVE_MIN_WITH_COVER
|
||||
ssm psr.ic
|
||||
;;
|
||||
srlz.i // guarantee that interruption collection is on
|
||||
;;
|
||||
ssm psr.i // restore psr.i
|
||||
adds r3=16,r2 // set up second base pointer
|
||||
;;
|
||||
VMX_SAVE_REST
|
||||
;;
|
||||
movl r14=ia64_leave_hypervisor
|
||||
movl r2=hyper_call_table
|
||||
;;
|
||||
mov rp=r14
|
||||
shladd r2=r15,3,r2
|
||||
;;
|
||||
ld8 r2=[r2]
|
||||
;;
|
||||
mov b6=r2
|
||||
;;
|
||||
br.call.sptk.many b6=b6
|
||||
;;
|
||||
END(vmx_hypercall_dispatch)
|
||||
|
||||
|
||||
|
||||
ENTRY(vmx_dispatch_interrupt)
|
||||
cmp.ne pEml,pNonEml=r0,r0 /* force pNonEml =1, don't save r4 ~ r7 */
|
||||
;;
|
||||
@@ -976,3 +1008,39 @@ ENTRY(vmx_dispatch_interrupt)
|
||||
mov rp=r14
|
||||
br.call.sptk.many b6=vmx_ia64_handle_irq
|
||||
END(vmx_dispatch_interrupt)
|
||||
|
||||
|
||||
|
||||
.rodata
|
||||
.align 8
|
||||
.globl hyper_call_table
|
||||
hyper_call_table:
|
||||
data8 hyper_not_support //hyper_set_trap_table /* 0 */
|
||||
data8 hyper_mmu_update
|
||||
data8 hyper_not_support //hyper_set_gdt
|
||||
data8 hyper_not_support //hyper_stack_switch
|
||||
data8 hyper_not_support //hyper_set_callbacks
|
||||
data8 hyper_not_support //hyper_fpu_taskswitch /* 5 */
|
||||
data8 hyper_sched_op
|
||||
data8 hyper_dom0_op
|
||||
data8 hyper_not_support //hyper_set_debugreg
|
||||
data8 hyper_not_support //hyper_get_debugreg
|
||||
data8 hyper_not_support //hyper_update_descriptor /* 10 */
|
||||
data8 hyper_not_support //hyper_set_fast_trap
|
||||
data8 hyper_dom_mem_op
|
||||
data8 hyper_not_support //hyper_multicall
|
||||
data8 hyper_not_support //hyper_update_va_mapping
|
||||
data8 hyper_not_support //hyper_set_timer_op /* 15 */
|
||||
data8 hyper_event_channel_op
|
||||
data8 hyper_xen_version
|
||||
data8 hyper_not_support //hyper_console_io
|
||||
data8 hyper_not_support //hyper_physdev_op
|
||||
data8 hyper_not_support //hyper_grant_table_op /* 20 */
|
||||
data8 hyper_not_support //hyper_vm_assist
|
||||
data8 hyper_not_support //hyper_update_va_mapping_otherdomain
|
||||
data8 hyper_not_support //hyper_switch_vm86
|
||||
data8 hyper_not_support //hyper_boot_vcpu
|
||||
data8 hyper_not_support //hyper_ni_hypercall /* 25 */
|
||||
data8 hyper_not_support //hyper_mmuext_op
|
||||
data8 hyper_lock_page
|
||||
data8 hyper_set_shared_page
|
||||
@@ -282,11 +282,9 @@
|
||||
;; \
|
||||
.mem.offset 0,0; st8.spill [r4]=r20,16; \
|
||||
.mem.offset 8,0; st8.spill [r5]=r21,16; \
|
||||
mov r18=b6; \
|
||||
;; \
|
||||
.mem.offset 0,0; st8.spill [r4]=r22,16; \
|
||||
.mem.offset 8,0; st8.spill [r5]=r23,16; \
|
||||
mov r19=b7; \
|
||||
;; \
|
||||
.mem.offset 0,0; st8.spill [r4]=r24,16; \
|
||||
.mem.offset 8,0; st8.spill [r5]=r25,16; \
|
||||
@@ -296,9 +294,11 @@
|
||||
;; \
|
||||
.mem.offset 0,0; st8.spill [r4]=r28,16; \
|
||||
.mem.offset 8,0; st8.spill [r5]=r29,16; \
|
||||
mov r26=b6; \
|
||||
;; \
|
||||
.mem.offset 0,0; st8.spill [r4]=r30,16; \
|
||||
.mem.offset 8,0; st8.spill [r5]=r31,16; \
|
||||
mov r27=b7; \
|
||||
;; \
|
||||
mov r30=ar.unat; \
|
||||
;; \
|
||||
@@ -317,8 +317,8 @@
|
||||
adds r2=PT(B6)-PT(F10),r2; \
|
||||
adds r3=PT(B7)-PT(F11),r3; \
|
||||
;; \
|
||||
st8 [r2]=r18,16; /* b6 */ \
|
||||
st8 [r3]=r19,16; /* b7 */ \
|
||||
st8 [r2]=r26,16; /* b6 */ \
|
||||
st8 [r3]=r27,16; /* b7 */ \
|
||||
;; \
|
||||
st8 [r2]=r9; /* ar.csd */ \
|
||||
st8 [r3]=r10; /* ar.ssd */ \
|
||||
|
||||
@@ -116,7 +116,6 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is
|
||||
case FW_HYPERCALL_EFI_GET_TIME:
|
||||
{
|
||||
unsigned long *tv, *tc;
|
||||
fooefi();
|
||||
vmx_vcpu_get_gr(v, 32, &tv);
|
||||
vmx_vcpu_get_gr(v, 33, &tc);
|
||||
printf("efi_get_time(%p,%p) called...",tv,tc);
|
||||
|
||||
+82
-14
@@ -252,7 +252,7 @@ static thash_data_t *_vtlb_next_overlap_in_chain(thash_cb_t *hcb)
|
||||
|
||||
/* Find overlap TLB entry */
|
||||
for (cch=priv->cur_cch; cch; cch = cch->next) {
|
||||
if ( ((1UL<<cch->section) & priv->s_sect.v) &&
|
||||
if ( ( cch->tc ? priv->s_sect.tc : priv->s_sect.tr ) &&
|
||||
__is_tlb_overlap(hcb, cch, priv->rid, priv->cl,
|
||||
priv->_curva, priv->_eva) ) {
|
||||
return cch;
|
||||
@@ -322,7 +322,7 @@ int __tlb_to_vhpt(thash_cb_t *hcb,
|
||||
|
||||
void thash_tr_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va, int idx)
|
||||
{
|
||||
if ( hcb->ht != THASH_TLB || entry->section != THASH_TLB_TR ) {
|
||||
if ( hcb->ht != THASH_TLB || entry->tc ) {
|
||||
panic("wrong parameter\n");
|
||||
}
|
||||
entry->vadr = PAGEALIGN(entry->vadr,entry->ps);
|
||||
@@ -356,7 +356,7 @@ thash_data_t *__alloc_chain(thash_cb_t *hcb,thash_data_t *entry)
|
||||
* 3: The caller need to make sure the new entry will not overlap
|
||||
* with any existed entry.
|
||||
*/
|
||||
static void vtlb_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
|
||||
void vtlb_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
|
||||
{
|
||||
thash_data_t *hash_table, *cch;
|
||||
rr_t vrr;
|
||||
@@ -411,7 +411,7 @@ void thash_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
|
||||
rr_t vrr;
|
||||
|
||||
vrr = (hcb->get_rr_fn)(hcb->vcpu,entry->vadr);
|
||||
if ( entry->ps != vrr.ps && entry->section==THASH_TLB_TC) {
|
||||
if ( entry->ps != vrr.ps && entry->tc ) {
|
||||
panic("Not support for multiple page size now\n");
|
||||
}
|
||||
entry->vadr = PAGEALIGN(entry->vadr,entry->ps);
|
||||
@@ -450,7 +450,7 @@ static void rem_vtlb(thash_cb_t *hcb, thash_data_t *entry)
|
||||
thash_internal_t *priv = &hcb->priv;
|
||||
int idx;
|
||||
|
||||
if ( entry->section == THASH_TLB_TR ) {
|
||||
if ( !entry->tc ) {
|
||||
return rem_tr(hcb, entry->cl, entry->tr_idx);
|
||||
}
|
||||
rem_thash(hcb, entry);
|
||||
@@ -525,19 +525,19 @@ thash_data_t *thash_find_overlap(thash_cb_t *hcb,
|
||||
thash_data_t *in, search_section_t s_sect)
|
||||
{
|
||||
return (hcb->find_overlap)(hcb, in->vadr,
|
||||
in->ps, in->rid, in->cl, s_sect);
|
||||
PSIZE(in->ps), in->rid, in->cl, s_sect);
|
||||
}
|
||||
|
||||
static thash_data_t *vtlb_find_overlap(thash_cb_t *hcb,
|
||||
u64 va, u64 ps, int rid, char cl, search_section_t s_sect)
|
||||
u64 va, u64 size, int rid, char cl, search_section_t s_sect)
|
||||
{
|
||||
thash_data_t *hash_table;
|
||||
thash_internal_t *priv = &hcb->priv;
|
||||
u64 tag;
|
||||
rr_t vrr;
|
||||
|
||||
priv->_curva = PAGEALIGN(va,ps);
|
||||
priv->_eva = priv->_curva + PSIZE(ps);
|
||||
priv->_curva = va & ~(size-1);
|
||||
priv->_eva = priv->_curva + size;
|
||||
priv->rid = rid;
|
||||
vrr = (hcb->get_rr_fn)(hcb->vcpu,va);
|
||||
priv->ps = vrr.ps;
|
||||
@@ -553,15 +553,15 @@ static thash_data_t *vtlb_find_overlap(thash_cb_t *hcb,
|
||||
}
|
||||
|
||||
static thash_data_t *vhpt_find_overlap(thash_cb_t *hcb,
|
||||
u64 va, u64 ps, int rid, char cl, search_section_t s_sect)
|
||||
u64 va, u64 size, int rid, char cl, search_section_t s_sect)
|
||||
{
|
||||
thash_data_t *hash_table;
|
||||
thash_internal_t *priv = &hcb->priv;
|
||||
u64 tag;
|
||||
rr_t vrr;
|
||||
|
||||
priv->_curva = PAGEALIGN(va,ps);
|
||||
priv->_eva = priv->_curva + PSIZE(ps);
|
||||
priv->_curva = va & ~(size-1);
|
||||
priv->_eva = priv->_curva + size;
|
||||
priv->rid = rid;
|
||||
vrr = (hcb->get_rr_fn)(hcb->vcpu,va);
|
||||
priv->ps = vrr.ps;
|
||||
@@ -691,13 +691,46 @@ void thash_purge_entries_ex(thash_cb_t *hcb,
|
||||
{
|
||||
thash_data_t *ovl;
|
||||
|
||||
ovl = (hcb->find_overlap)(hcb, va, ps, rid, cl, p_sect);
|
||||
ovl = (hcb->find_overlap)(hcb, va, PSIZE(ps), rid, cl, p_sect);
|
||||
while ( ovl != NULL ) {
|
||||
(hcb->rem_hash)(hcb, ovl);
|
||||
ovl = (hcb->next_overlap)(hcb);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Purge overlap TCs and then insert the new entry to emulate itc ops.
|
||||
* Notes: Only TC entry can purge and insert.
|
||||
*/
|
||||
void thash_purge_and_insert(thash_cb_t *hcb, thash_data_t *in)
|
||||
{
|
||||
thash_data_t *ovl;
|
||||
search_section_t sections;
|
||||
|
||||
#ifdef XEN_DEBUGGER
|
||||
vrr = (hcb->get_rr_fn)(hcb->vcpu,in->vadr);
|
||||
if ( in->ps != vrr.ps || hcb->ht != THASH_TLB || !in->tc ) {
|
||||
panic ("Oops, wrong call for purge_and_insert\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
in->vadr = PAGEALIGN(in->vadr,in->ps);
|
||||
in->ppn = PAGEALIGN(in->ppn, in->ps-12);
|
||||
sections.tr = 0;
|
||||
sections.tc = 1;
|
||||
ovl = (hcb->find_overlap)(hcb, in->vadr, PSIZE(in->ps),
|
||||
in->rid, in->cl, sections);
|
||||
if(ovl)
|
||||
(hcb->rem_hash)(hcb, ovl);
|
||||
#ifdef XEN_DEBUGGER
|
||||
ovl = (hcb->next_overlap)(hcb);
|
||||
if ( ovl ) {
|
||||
panic ("Oops, 2+ overlaps for purge_and_insert\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
(hcb->ins_hash)(hcb, in, in->vadr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Purge all TCs or VHPT entries including those in Hash table.
|
||||
@@ -766,6 +799,42 @@ thash_data_t *vtlb_lookup_ex(thash_cb_t *hcb,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock/Unlock TC if found.
|
||||
* NOTES: Only the page in prefered size can be handled.
|
||||
* return:
|
||||
* 1: failure
|
||||
* 0: success
|
||||
*/
|
||||
int thash_lock_tc(thash_cb_t *hcb, u64 va, u64 size, int rid, char cl, int lock)
|
||||
{
|
||||
thash_data_t *ovl;
|
||||
search_section_t sections;
|
||||
|
||||
sections.tr = 1;
|
||||
sections.tc = 1;
|
||||
ovl = (hcb->find_overlap)(hcb, va, size, rid, cl, sections);
|
||||
if ( ovl ) {
|
||||
if ( !ovl->tc ) {
|
||||
// panic("Oops, TR for lock\n");
|
||||
return 0;
|
||||
}
|
||||
else if ( lock ) {
|
||||
if ( ovl->locked ) {
|
||||
DPRINTK("Oops, already locked entry\n");
|
||||
}
|
||||
ovl->locked = 1;
|
||||
}
|
||||
else if ( !lock ) {
|
||||
if ( !ovl->locked ) {
|
||||
DPRINTK("Oops, already unlocked entry\n");
|
||||
}
|
||||
ovl->locked = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notifier when TLB is deleted from hash table and its collision chain.
|
||||
@@ -824,7 +893,6 @@ void thash_init(thash_cb_t *hcb, u64 sz)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef VTLB_DEBUG
|
||||
static u64 cch_length_statistics[MAX_CCH_LENGTH+1];
|
||||
u64 sanity_check=0;
|
||||
|
||||
@@ -52,7 +52,7 @@ paging_init (void)
|
||||
panic("Not enough memory to bootstrap Xen.\n");
|
||||
|
||||
printk("machine to physical table: 0x%lx\n", (u64)mpt_table);
|
||||
memset(mpt_table, 0x55, mpt_table_size);
|
||||
memset(mpt_table, INVALID_M2P_ENTRY, mpt_table_size);
|
||||
|
||||
/* Any more setup here? On VMX enabled platform,
|
||||
* there's no need to keep guest linear pg table,
|
||||
|
||||
@@ -63,13 +63,7 @@ void sync_lazy_execstate_mask(cpumask_t mask) {}
|
||||
void sync_lazy_execstate_all(void) {}
|
||||
|
||||
int grant_table_create(struct domain *d) { return 0; }
|
||||
void grant_table_destroy(struct domain *d)
|
||||
{
|
||||
printf("grant_table_destroy: domain_destruct not tested!!!\n");
|
||||
printf("grant_table_destroy: ensure atomic_* calls work in domain_destruct!!\n");
|
||||
dummy();
|
||||
return;
|
||||
}
|
||||
void grant_table_destroy(struct domain *d) { return; }
|
||||
|
||||
struct pt_regs *guest_cpu_user_regs(void) { return ia64_task_regs(current); }
|
||||
|
||||
|
||||
+18
-11
@@ -193,23 +193,30 @@ static void __init init_amd(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
display_cacheinfo(c);
|
||||
detect_ht(c);
|
||||
|
||||
#ifdef CONFIG_X86_HT
|
||||
/* AMD dual core looks like HT but isn't really. Hide it from the
|
||||
scheduler. This works around problems with the domain scheduler.
|
||||
Also probably gives slightly better scheduling and disables
|
||||
SMT nice which is harmful on dual core.
|
||||
TBD tune the domain scheduler for dual core. */
|
||||
if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
||||
smp_num_siblings = 1;
|
||||
#endif
|
||||
|
||||
if (cpuid_eax(0x80000000) >= 0x80000008) {
|
||||
c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
|
||||
if (c->x86_num_cores & (c->x86_num_cores - 1))
|
||||
c->x86_num_cores = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_HT
|
||||
/*
|
||||
* On a AMD dual core setup the lower bits of the APIC id
|
||||
* distingush the cores. Assumes number of cores is a power
|
||||
* of two.
|
||||
*/
|
||||
if (c->x86_num_cores > 1) {
|
||||
int cpu = smp_processor_id();
|
||||
unsigned bits = 0;
|
||||
while ((1 << bits) < c->x86_num_cores)
|
||||
bits++;
|
||||
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
|
||||
phys_proc_id[cpu] >>= bits;
|
||||
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
|
||||
cpu, c->x86_num_cores, cpu_core_id[cpu]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
|
||||
|
||||
+27
-22
@@ -186,7 +186,7 @@ static inline int flag_is_changeable_p(unsigned long flag)
|
||||
|
||||
|
||||
/* Probe for the CPUID instruction */
|
||||
int __init have_cpuid_p(void)
|
||||
static int __init have_cpuid_p(void)
|
||||
{
|
||||
return flag_is_changeable_p(X86_EFLAGS_ID);
|
||||
}
|
||||
@@ -194,7 +194,7 @@ int __init have_cpuid_p(void)
|
||||
/* Do minimum CPU detection early.
|
||||
Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
|
||||
The others are not touched to avoid unwanted side effects. */
|
||||
void __init early_cpu_detect(void)
|
||||
static void __init early_cpu_detect(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
|
||||
@@ -228,6 +228,10 @@ void __init early_cpu_detect(void)
|
||||
}
|
||||
|
||||
early_intel_workaround(c);
|
||||
|
||||
#ifdef CONFIG_X86_HT
|
||||
phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init generic_identify(struct cpuinfo_x86 * c)
|
||||
@@ -416,25 +420,15 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
|
||||
mcheck_init(c);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
|
||||
*/
|
||||
|
||||
void __init dodgy_tsc(void)
|
||||
{
|
||||
if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
|
||||
( boot_cpu_data.x86_vendor == X86_VENDOR_NSC ))
|
||||
cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_HT
|
||||
void __init detect_ht(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
int index_lsb, index_msb, tmp;
|
||||
int index_msb, tmp;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_HT))
|
||||
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
||||
return;
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
@@ -443,7 +437,6 @@ void __init detect_ht(struct cpuinfo_x86 *c)
|
||||
if (smp_num_siblings == 1) {
|
||||
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
|
||||
} else if (smp_num_siblings > 1 ) {
|
||||
index_lsb = 0;
|
||||
index_msb = 31;
|
||||
|
||||
if (smp_num_siblings > NR_CPUS) {
|
||||
@@ -452,21 +445,34 @@ void __init detect_ht(struct cpuinfo_x86 *c)
|
||||
return;
|
||||
}
|
||||
tmp = smp_num_siblings;
|
||||
while ((tmp & 1) == 0) {
|
||||
tmp >>=1 ;
|
||||
index_lsb++;
|
||||
}
|
||||
tmp = smp_num_siblings;
|
||||
while ((tmp & 0x80000000 ) == 0) {
|
||||
tmp <<=1 ;
|
||||
index_msb--;
|
||||
}
|
||||
if (index_lsb != index_msb )
|
||||
if (smp_num_siblings & (smp_num_siblings - 1))
|
||||
index_msb++;
|
||||
phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
|
||||
|
||||
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
||||
phys_proc_id[cpu]);
|
||||
|
||||
smp_num_siblings = smp_num_siblings / c->x86_num_cores;
|
||||
|
||||
tmp = smp_num_siblings;
|
||||
index_msb = 31;
|
||||
while ((tmp & 0x80000000) == 0) {
|
||||
tmp <<=1 ;
|
||||
index_msb--;
|
||||
}
|
||||
|
||||
if (smp_num_siblings & (smp_num_siblings - 1))
|
||||
index_msb++;
|
||||
|
||||
cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
|
||||
|
||||
if (c->x86_num_cores > 1)
|
||||
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
||||
cpu_core_id[cpu]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -511,7 +517,6 @@ extern int amd_init_cpu(void);
|
||||
extern int centaur_init_cpu(void);
|
||||
extern int transmeta_init_cpu(void);
|
||||
extern int rise_init_cpu(void);
|
||||
void early_cpu_detect(void);
|
||||
|
||||
void __init early_cpu_init(void)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,6 @@ extern int get_model_name(struct cpuinfo_x86 *c);
|
||||
extern void display_cacheinfo(struct cpuinfo_x86 *c);
|
||||
|
||||
extern void generic_identify(struct cpuinfo_x86 * c);
|
||||
extern int have_cpuid_p(void);
|
||||
|
||||
extern void early_intel_workaround(struct cpuinfo_x86 *c);
|
||||
|
||||
@@ -74,6 +74,27 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* find out the number of processor cores on the die
|
||||
*/
|
||||
static int __init num_cpu_cores(struct cpuinfo_x86 *c)
|
||||
{
|
||||
unsigned int eax;
|
||||
|
||||
if (c->cpuid_level < 4)
|
||||
return 1;
|
||||
|
||||
__asm__("cpuid"
|
||||
: "=a" (eax)
|
||||
: "0" (4), "c" (0)
|
||||
: "bx", "dx");
|
||||
|
||||
if (eax & 0x1f)
|
||||
return ((eax >> 26) + 1);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void __init init_intel(struct cpuinfo_x86 *c)
|
||||
{
|
||||
unsigned int l2 = 0;
|
||||
@@ -136,6 +157,8 @@ static void __init init_intel(struct cpuinfo_x86 *c)
|
||||
if ( p )
|
||||
strcpy(c->x86_model_id, p);
|
||||
|
||||
c->x86_num_cores = num_cpu_cores(c);
|
||||
|
||||
detect_ht(c);
|
||||
|
||||
/* Work around errata */
|
||||
|
||||
@@ -179,8 +179,8 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
{
|
||||
dom0_physinfo_t *pi = &op->u.physinfo;
|
||||
|
||||
pi->ht_per_core = ht_per_core;
|
||||
pi->cores = num_online_cpus() / ht_per_core;
|
||||
pi->ht_per_core = smp_num_siblings;
|
||||
pi->cores = boot_cpu_data.x86_num_cores;
|
||||
pi->total_pages = max_page;
|
||||
pi->free_pages = avail_domheap_pages();
|
||||
pi->cpu_khz = cpu_khz;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <asm/desc.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/e820.h>
|
||||
#include <public/acm_dom0_setup.h>
|
||||
|
||||
extern void dmi_scan_machine(void);
|
||||
extern void generic_apic_probe(void);
|
||||
@@ -66,7 +67,6 @@ boolean_param("noapic", skip_ioapic_setup);
|
||||
|
||||
int early_boot = 1;
|
||||
|
||||
int ht_per_core = 1;
|
||||
cpumask_t cpu_present_map;
|
||||
|
||||
/* Limits of Xen heap, used to initialise the allocator. */
|
||||
@@ -394,12 +394,17 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
|
||||
shadow_mode_init();
|
||||
|
||||
/* initialize access control security module */
|
||||
acm_init();
|
||||
|
||||
/* Create initial domain 0. */
|
||||
dom0 = do_createdomain(0, 0);
|
||||
if ( dom0 == NULL )
|
||||
panic("Error creating domain 0\n");
|
||||
|
||||
set_bit(_DOMF_privileged, &dom0->domain_flags);
|
||||
/* post-create hooks sets security label */
|
||||
acm_post_domain0_create(dom0->domain_id);
|
||||
|
||||
/* Grab the DOM0 command line. */
|
||||
cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
|
||||
|
||||
+29
-3
@@ -62,6 +62,8 @@ static int __initdata smp_b_stepping;
|
||||
int smp_num_siblings = 1;
|
||||
int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
|
||||
EXPORT_SYMBOL(phys_proc_id);
|
||||
int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
|
||||
EXPORT_SYMBOL(cpu_core_id);
|
||||
|
||||
/* bitmap of online cpus */
|
||||
cpumask_t cpu_online_map;
|
||||
@@ -923,6 +925,8 @@ static int boot_cpu_logical_apicid;
|
||||
void *xquad_portio;
|
||||
|
||||
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
|
||||
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
|
||||
EXPORT_SYMBOL(cpu_core_map);
|
||||
|
||||
static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
{
|
||||
@@ -947,6 +951,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
cpus_clear(cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
|
||||
cpus_clear(cpu_core_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
|
||||
/*
|
||||
* If we couldn't find an SMP configuration at boot time,
|
||||
* get out of here now!
|
||||
@@ -959,6 +966,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
printk(KERN_NOTICE "Local APIC not detected."
|
||||
" Using dummy APIC emulation.\n");
|
||||
map_cpu_to_logical_apicid();
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1079,10 +1088,13 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
* construct cpu_sibling_map[], so that we can tell sibling CPUs
|
||||
* efficiently.
|
||||
*/
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++)
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++) {
|
||||
cpus_clear(cpu_sibling_map[cpu]);
|
||||
cpus_clear(cpu_core_map[cpu]);
|
||||
}
|
||||
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++) {
|
||||
struct cpuinfo_x86 *c = cpu_data + cpu;
|
||||
int siblings = 0;
|
||||
int i;
|
||||
if (!cpu_isset(cpu, cpu_callout_map))
|
||||
@@ -1092,7 +1104,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
if (!cpu_isset(i, cpu_callout_map))
|
||||
continue;
|
||||
if (phys_proc_id[cpu] == phys_proc_id[i]) {
|
||||
if (cpu_core_id[cpu] == cpu_core_id[i]) {
|
||||
siblings++;
|
||||
cpu_set(i, cpu_sibling_map[cpu]);
|
||||
}
|
||||
@@ -1102,8 +1114,22 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
}
|
||||
|
||||
if (siblings != smp_num_siblings)
|
||||
if (siblings != smp_num_siblings) {
|
||||
printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
|
||||
smp_num_siblings = siblings;
|
||||
}
|
||||
|
||||
if (c->x86_num_cores > 1) {
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
if (!cpu_isset(i, cpu_callout_map))
|
||||
continue;
|
||||
if (phys_proc_id[cpu] == phys_proc_id[i]) {
|
||||
cpu_set(i, cpu_core_map[cpu]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cpu_core_map[cpu] = cpu_sibling_map[cpu];
|
||||
}
|
||||
}
|
||||
|
||||
if (nmi_watchdog == NMI_LOCAL_APIC)
|
||||
|
||||
@@ -751,6 +751,7 @@ ENTRY(hypercall_table)
|
||||
.long do_boot_vcpu
|
||||
.long do_ni_hypercall /* 25 */
|
||||
.long do_mmuext_op
|
||||
.long do_policy_op /* 27 */
|
||||
.rept NR_hypercalls-((.-hypercall_table)/4)
|
||||
.long do_ni_hypercall
|
||||
.endr
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
|
||||
include $(BASEDIR)/Rules.mk
|
||||
|
||||
ifeq ($(TARGET_ARCH),ia64)
|
||||
OBJS := $(subst dom_mem_ops.o,,$(OBJS))
|
||||
ifeq ($(TARGET_ARCH),ia64)
|
||||
#OBJS := $(subst dom_mem_ops.o,,$(OBJS))
|
||||
OBJS := $(subst grant_table.o,,$(OBJS))
|
||||
endif
|
||||
|
||||
|
||||
+16
-3
@@ -19,6 +19,7 @@
|
||||
#include <asm/current.h>
|
||||
#include <public/dom0_ops.h>
|
||||
#include <public/sched_ctl.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op);
|
||||
extern void arch_getdomaininfo_ctxt(
|
||||
@@ -91,6 +92,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
{
|
||||
long ret = 0;
|
||||
dom0_op_t curop, *op = &curop;
|
||||
void *ssid = NULL; /* save security ptr between pre and post/fail hooks */
|
||||
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EPERM;
|
||||
@@ -101,6 +103,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
if ( op->interface_version != DOM0_INTERFACE_VERSION )
|
||||
return -EACCES;
|
||||
|
||||
if ( acm_pre_dom0_op(op, &ssid) )
|
||||
return -EACCES;
|
||||
|
||||
switch ( op->cmd )
|
||||
{
|
||||
|
||||
@@ -184,8 +189,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
* domains will all share the second HT of each CPU. Since dom0 is on
|
||||
* CPU 0, we favour high numbered CPUs in the event of a tie.
|
||||
*/
|
||||
pro = ht_per_core - 1;
|
||||
for ( i = pro; i < num_online_cpus(); i += ht_per_core )
|
||||
pro = smp_num_siblings - 1;
|
||||
for ( i = pro; i < num_online_cpus(); i += smp_num_siblings )
|
||||
if ( cnt[i] <= cnt[pro] )
|
||||
pro = i;
|
||||
|
||||
@@ -357,6 +362,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
|
||||
d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
|
||||
|
||||
if (d->ssid != NULL)
|
||||
op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
|
||||
else
|
||||
op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID;
|
||||
|
||||
op->u.getdomaininfo.tot_pages = d->tot_pages;
|
||||
op->u.getdomaininfo.max_pages = d->max_pages;
|
||||
op->u.getdomaininfo.shared_info_frame =
|
||||
@@ -493,7 +503,10 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
|
||||
ret = arch_do_dom0_op(op,u_dom0_op);
|
||||
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
acm_post_dom0_op(op, ssid);
|
||||
else
|
||||
acm_fail_dom0_op(op, ssid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <public/xen.h>
|
||||
#include <public/event_channel.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
#define bucket_from_port(d,p) \
|
||||
((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])
|
||||
@@ -587,6 +588,9 @@ long do_event_channel_op(evtchn_op_t *uop)
|
||||
if ( copy_from_user(&op, uop, sizeof(op)) != 0 )
|
||||
return -EFAULT;
|
||||
|
||||
if (acm_pre_event_channel(&op))
|
||||
return -EACCES;
|
||||
|
||||
switch ( op.cmd )
|
||||
{
|
||||
case EVTCHNOP_alloc_unbound:
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/shadow.h>
|
||||
#include <xen/mm.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
#define PIN_FAIL(_lbl, _rc, _f, _a...) \
|
||||
do { \
|
||||
@@ -357,6 +358,11 @@ __gnttab_map_grant_ref(
|
||||
return GNTST_bad_gntref;
|
||||
}
|
||||
|
||||
if (acm_pre_grant_map_ref(dom)) {
|
||||
(void)__put_user(GNTST_permission_denied, &uop->handle);
|
||||
return GNTST_permission_denied;
|
||||
}
|
||||
|
||||
if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
|
||||
unlikely(ld == rd) )
|
||||
{
|
||||
|
||||
+33
-8
@@ -1,10 +1,7 @@
|
||||
/******************************************************************************
|
||||
* kernel.c
|
||||
*
|
||||
* This file should contain architecture-independent bootstrap and low-level
|
||||
* help routines. It's a bit x86/PC specific right now!
|
||||
*
|
||||
* Copyright (c) 2002-2003 K A Fraser
|
||||
* Copyright (c) 2002-2005 K A Fraser
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
@@ -14,6 +11,7 @@
|
||||
#include <xen/compile.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/current.h>
|
||||
#include <public/version.h>
|
||||
|
||||
void cmdline_parse(char *cmdline)
|
||||
{
|
||||
@@ -83,11 +81,38 @@ void cmdline_parse(char *cmdline)
|
||||
* Simple hypercalls.
|
||||
*/
|
||||
|
||||
long do_xen_version(int cmd)
|
||||
long do_xen_version(int cmd, void *arg)
|
||||
{
|
||||
if ( cmd != 0 )
|
||||
return -ENOSYS;
|
||||
return (XEN_VERSION<<16) | (XEN_SUBVERSION);
|
||||
switch ( cmd )
|
||||
{
|
||||
case XENVER_version:
|
||||
{
|
||||
return (XEN_VERSION<<16) | (XEN_SUBVERSION);
|
||||
}
|
||||
|
||||
case XENVER_extraversion:
|
||||
{
|
||||
char extraversion[16];
|
||||
safe_strcpy(extraversion, XEN_EXTRAVERSION);
|
||||
if ( copy_to_user(arg, extraversion, sizeof(extraversion)) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case XENVER_compile_info:
|
||||
{
|
||||
struct xen_compile_info info;
|
||||
safe_strcpy(info.compiler, XEN_COMPILER);
|
||||
safe_strcpy(info.compile_by, XEN_COMPILE_BY);
|
||||
safe_strcpy(info.compile_domain, XEN_COMPILE_DOMAIN);
|
||||
safe_strcpy(info.compile_date, XEN_COMPILE_DATE);
|
||||
if ( copy_to_user(arg, &info, sizeof(info)) )
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
long do_vm_assist(unsigned int cmd, unsigned int type)
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/******************************************************************************
|
||||
*policy_ops.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* Process policy command requests from guest OS.
|
||||
*
|
||||
*/
|
||||
#include <xen/config.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/mm.h>
|
||||
#include <public/policy_ops.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/console.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <public/sched_ctl.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
/* function prototypes defined in acm/acm_policy.c */
|
||||
int acm_set_policy(void *buf, u16 buf_size, u16 policy);
|
||||
int acm_get_policy(void *buf, u16 buf_size);
|
||||
int acm_dump_statistics(void *buf, u16 buf_size);
|
||||
|
||||
typedef enum policyoperation {
|
||||
POLICY, /* access to policy interface (early drop) */
|
||||
GETPOLICY, /* dump policy cache */
|
||||
SETPOLICY, /* set policy cache (controls security) */
|
||||
DUMPSTATS /* dump policy statistics */
|
||||
} policyoperation_t;
|
||||
|
||||
int
|
||||
acm_authorize_policyops(struct domain *d, policyoperation_t pops)
|
||||
{
|
||||
/* currently, all policy management functions are restricted to privileged domains,
|
||||
* soon we will introduce finer-grained privileges for policy operations
|
||||
*/
|
||||
if (!IS_PRIV(d)) {
|
||||
printk("%s: Policy management authorization denied ERROR!\n", __func__);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
long do_policy_op(policy_op_t *u_policy_op)
|
||||
{
|
||||
long ret = 0;
|
||||
policy_op_t curop, *op = &curop;
|
||||
|
||||
/* check here policy decision for policy commands */
|
||||
/* for now allow DOM0 only, later indepedently */
|
||||
if (acm_authorize_policyops(current->domain, POLICY))
|
||||
return -EACCES;
|
||||
|
||||
if ( copy_from_user(op, u_policy_op, sizeof(*op)) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( op->interface_version != POLICY_INTERFACE_VERSION )
|
||||
return -EACCES;
|
||||
|
||||
switch ( op->cmd )
|
||||
{
|
||||
case POLICY_SETPOLICY:
|
||||
{
|
||||
if (acm_authorize_policyops(current->domain, SETPOLICY))
|
||||
return -EACCES;
|
||||
printkd("%s: setting policy.\n", __func__);
|
||||
ret = acm_set_policy(op->u.setpolicy.pushcache, op->u.setpolicy.pushcache_size, op->u.setpolicy.policy_type);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLICY_GETPOLICY:
|
||||
{
|
||||
if (acm_authorize_policyops(current->domain, GETPOLICY))
|
||||
return -EACCES;
|
||||
printkd("%s: getting policy.\n", __func__);
|
||||
ret = acm_get_policy(op->u.getpolicy.pullcache, op->u.getpolicy.pullcache_size);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLICY_DUMPSTATS:
|
||||
{
|
||||
if (acm_authorize_policyops(current->domain, DUMPSTATS))
|
||||
return -EACCES;
|
||||
printkd("%s: dumping statistics.\n", __func__);
|
||||
ret = acm_dump_statistics(op->u.dumpstats.pullcache, op->u.dumpstats.pullcache_size);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ESRCH;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/****************************************************************
|
||||
* acm_core.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype header file describing core data types and constants
|
||||
* for the access control module and relevant policies
|
||||
*
|
||||
*/
|
||||
#ifndef _ACM_CORE_H
|
||||
#define _ACM_CORE_H
|
||||
|
||||
#include <xen/spinlock.h>
|
||||
#include <public/acm.h>
|
||||
#include <public/policy_ops.h>
|
||||
|
||||
/* Xen-internal representation of the binary policy */
|
||||
struct acm_binary_policy {
|
||||
u16 primary_policy_code;
|
||||
u16 secondary_policy_code;
|
||||
void *primary_binary_policy;
|
||||
void *secondary_binary_policy;
|
||||
|
||||
};
|
||||
|
||||
struct chwall_binary_policy {
|
||||
u16 max_types;
|
||||
u16 max_ssidrefs;
|
||||
u16 max_conflictsets;
|
||||
domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */
|
||||
domaintype_t *conflict_aggregate_set; /* [max_types] */
|
||||
domaintype_t *running_types; /* [max_types] */
|
||||
domaintype_t *conflict_sets; /* [max_conflictsets][max_types]*/
|
||||
};
|
||||
|
||||
struct ste_binary_policy {
|
||||
u16 max_types;
|
||||
u16 max_ssidrefs;
|
||||
domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */
|
||||
atomic_t ec_eval_count, gt_eval_count;
|
||||
atomic_t ec_denied_count, gt_denied_count;
|
||||
atomic_t ec_cachehit_count, gt_cachehit_count;
|
||||
};
|
||||
|
||||
/* global acm policy */
|
||||
extern struct acm_binary_policy acm_bin_pol;
|
||||
extern struct chwall_binary_policy chwall_bin_pol;
|
||||
extern struct ste_binary_policy ste_bin_pol;
|
||||
/* use the lock when reading / changing binary policy ! */
|
||||
extern rwlock_t acm_bin_pol_rwlock;
|
||||
|
||||
/* subject and object type definitions */
|
||||
enum acm_datatype { DOMAIN };
|
||||
|
||||
/* defines number of access decisions to other domains can be cached
|
||||
* one entry per domain, TE does not distinguish evtchn or grant_table */
|
||||
#define ACM_TE_CACHE_SIZE 8
|
||||
enum acm_ste_flag { VALID, FREE };
|
||||
|
||||
/* cache line:
|
||||
* if cache_line.valid==VALID, then
|
||||
* STE decision is cached as "permitted"
|
||||
* on domain cache_line.id
|
||||
*/
|
||||
struct acm_ste_cache_line {
|
||||
enum acm_ste_flag valid;
|
||||
domid_t id;
|
||||
};
|
||||
|
||||
/* general definition of a subject security id */
|
||||
struct acm_ssid_domain {
|
||||
enum acm_datatype datatype; /* type of subject (e.g., partition) */
|
||||
ssidref_t ssidref; /* combined security reference */
|
||||
void *primary_ssid; /* primary policy ssid part (e.g. chinese wall) */
|
||||
void *secondary_ssid; /* secondary policy ssid part (e.g. type enforcement) */
|
||||
struct domain *subject; /* backpointer to subject structure */
|
||||
domid_t domainid; /* replicate id */
|
||||
};
|
||||
|
||||
/* chinese wall ssid type */
|
||||
struct chwall_ssid {
|
||||
ssidref_t chwall_ssidref;
|
||||
};
|
||||
|
||||
/* simple type enforcement ssid type */
|
||||
struct ste_ssid {
|
||||
ssidref_t ste_ssidref;
|
||||
struct acm_ste_cache_line ste_cache[ACM_TE_CACHE_SIZE]; /* decision cache */
|
||||
};
|
||||
|
||||
/* macros to access ssidref for primary / secondary policy
|
||||
* primary ssidref = lower 16 bit
|
||||
* secondary ssidref = higher 16 bit
|
||||
*/
|
||||
#define GET_SSIDREF(POLICY, ssidref) \
|
||||
((POLICY) == acm_bin_pol.primary_policy_code) ? \
|
||||
((ssidref) & 0xffff) : ((ssidref) >> 16)
|
||||
|
||||
/* macros to access ssid pointer for primary / secondary policy */
|
||||
#define GET_SSIDP(POLICY, ssid) \
|
||||
((POLICY) == acm_bin_pol.primary_policy_code) ? \
|
||||
((ssid)->primary_ssid) : ((ssid)->secondary_ssid)
|
||||
|
||||
/* protos */
|
||||
int acm_init_domain_ssid(domid_t id, ssidref_t ssidref);
|
||||
int acm_free_domain_ssid(struct acm_ssid_domain *ssid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/****************************************************************
|
||||
* acm_endian.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
*
|
||||
* Contributions:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype header file defining endian-dependent functions for the
|
||||
* big-endian policy interface
|
||||
*
|
||||
*/
|
||||
#ifndef _ACM_ENDIAN_H
|
||||
#define _ACM_ENDIAN_H
|
||||
|
||||
/* don't use these functions in performance critical sections! */
|
||||
|
||||
/* set during initialization by testing */
|
||||
extern u8 little_endian;
|
||||
|
||||
static inline u32 ntohl(u32 x)
|
||||
{
|
||||
if (little_endian)
|
||||
return
|
||||
( (((x) >> 24) & 0xff )|
|
||||
(((x) >> 8) & 0xff00 )|
|
||||
(((x) << 8) & 0xff0000 )|
|
||||
(((x) << 24) & 0xff000000) );
|
||||
else
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline u16 ntohs(u16 x)
|
||||
{
|
||||
if (little_endian)
|
||||
return
|
||||
( (((x) >> 8) & 0xff )|
|
||||
(((x) << 8) & 0xff00 ) );
|
||||
else
|
||||
return x;
|
||||
}
|
||||
|
||||
#define htonl(x) ntohl(x)
|
||||
#define htons(x) ntohs(x)
|
||||
|
||||
static inline void arrcpy16(u16 *dest, const u16 *src, size_t n)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while (i < n) {
|
||||
dest[i] = htons(src[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void arrcpy32(u32 *dest, const u32 *src, size_t n)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while (i < n) {
|
||||
dest[i] = htonl(src[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void arrcpy(void *dest, const void *src, unsigned int elsize, size_t n)
|
||||
{
|
||||
switch (elsize) {
|
||||
case sizeof(u16):
|
||||
arrcpy16((u16 *)dest, (u16 *)src, n);
|
||||
break;
|
||||
|
||||
case sizeof(u32):
|
||||
arrcpy32((u32 *)dest, (u32 *)src, n);
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy(dest, src, elsize*n);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,337 @@
|
||||
/****************************************************************
|
||||
* acm_hooks.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* acm header file implementing the global (policy-independent)
|
||||
* sHype hooks that are called throughout Xen.
|
||||
*
|
||||
*/
|
||||
#ifndef _ACM_HOOKS_H
|
||||
#define _ACM_HOOKS_H
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/acm.h>
|
||||
#include <acm/acm_core.h>
|
||||
#include <public/dom0_ops.h>
|
||||
#include <public/event_channel.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
/* if ACM_TRACE_MODE defined, all hooks should
|
||||
* print a short trace message */
|
||||
/* #define ACM_TRACE_MODE */
|
||||
|
||||
#ifdef ACM_TRACE_MODE
|
||||
# define traceprintk(fmt, args...) printk(fmt,## args)
|
||||
#else
|
||||
# define traceprintk(fmt, args...)
|
||||
#endif
|
||||
|
||||
/* global variables */
|
||||
extern struct acm_operations *acm_primary_ops;
|
||||
extern struct acm_operations *acm_secondary_ops;
|
||||
|
||||
/**********************************************************************************************
|
||||
* HOOK structure and meaning (justifies a few words about our model):
|
||||
*
|
||||
* General idea: every policy-controlled system operation is reflected in a
|
||||
* transaction in the system's security state
|
||||
*
|
||||
* Keeping the security state consistent requires "atomic" transactions.
|
||||
* The name of the hooks to place around policy-controlled transactions
|
||||
* reflects this. If authorizations do not involve security state changes,
|
||||
* then and only then POST and FAIL hooks remain empty since we don't care
|
||||
* about the eventual outcome of the operation from a security viewpoint.
|
||||
*
|
||||
* PURPOSE of hook types:
|
||||
* ======================
|
||||
* PRE-Hooks
|
||||
* a) general authorization to guard a controlled system operation
|
||||
* b) prepare security state change (means: fail hook must be able to "undo" this)
|
||||
*
|
||||
* POST-Hooks
|
||||
* a) commit prepared state change
|
||||
*
|
||||
* FAIL-Hooks
|
||||
* a) roll-back prepared security state change from PRE-Hook
|
||||
*
|
||||
*
|
||||
* PLACEMENT of hook types:
|
||||
* ========================
|
||||
* PRE-Hooks must be called:
|
||||
* a) before a guarded/controlled system operation is started
|
||||
* (return is ACM_ACCESS_PERMITTED or ACM_ACCESS_DENIED or error)
|
||||
* --> operation must be aborted if return is != ACM_ACCESS_PERMITTED
|
||||
*
|
||||
* POST-Hooks must be called:
|
||||
* a) after successful transaction (no return value; commit shall never fail)
|
||||
*
|
||||
* FAIL-Hooks must be called:
|
||||
* a) if system transaction (operation) fails somewhen after calling the PRE-hook
|
||||
* (obviously the POST-Hook is not called in this case)
|
||||
* b) if another (secondary) policy denies access in its PRE-Hook
|
||||
* (policy layering is useful but requires additional handling)
|
||||
*
|
||||
*
|
||||
*
|
||||
* Hook model from a security transaction viewpoint:
|
||||
*
|
||||
* start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success
|
||||
* (pre-hook) \ (post-hook)
|
||||
* \
|
||||
* fail
|
||||
* \
|
||||
* \
|
||||
* roll-back
|
||||
* (fail-hook)
|
||||
* \
|
||||
* sys-ops error
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
struct acm_operations {
|
||||
/* policy management functions (must always be defined!) */
|
||||
int (*init_domain_ssid) (void **ssid, ssidref_t ssidref);
|
||||
void (*free_domain_ssid) (void *ssid);
|
||||
int (*dump_binary_policy) (u8 *buffer, u16 buf_size);
|
||||
int (*set_binary_policy) (u8 *buffer, u16 buf_size);
|
||||
int (*dump_statistics) (u8 *buffer, u16 buf_size);
|
||||
/* domain management control hooks (can be NULL) */
|
||||
int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref);
|
||||
void (*post_domain_create) (domid_t domid, ssidref_t ssidref);
|
||||
void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref);
|
||||
void (*post_domain_destroy) (void *object_ssid, domid_t id);
|
||||
/* event channel control hooks (can be NULL) */
|
||||
int (*pre_eventchannel_unbound) (domid_t id);
|
||||
void (*fail_eventchannel_unbound) (domid_t id);
|
||||
int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2);
|
||||
int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2);
|
||||
/* grant table control hooks (can be NULL) */
|
||||
int (*pre_grant_map_ref) (domid_t id);
|
||||
void (*fail_grant_map_ref) (domid_t id);
|
||||
int (*pre_grant_setup) (domid_t id);
|
||||
void (*fail_grant_setup) (domid_t id);
|
||||
};
|
||||
|
||||
static inline int acm_pre_domain_create (void *subject_ssid, ssidref_t ssidref)
|
||||
{
|
||||
if ((acm_primary_ops->pre_domain_create != NULL) &&
|
||||
acm_primary_ops->pre_domain_create (subject_ssid, ssidref))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_domain_create != NULL) &&
|
||||
acm_secondary_ops->pre_domain_create (subject_ssid, ssidref)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_domain_create != NULL)
|
||||
acm_primary_ops->fail_domain_create (subject_ssid, ssidref);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
static inline void acm_post_domain_create (domid_t domid, ssidref_t ssidref)
|
||||
{
|
||||
if (acm_primary_ops->post_domain_create != NULL)
|
||||
acm_primary_ops->post_domain_create (domid, ssidref);
|
||||
if (acm_secondary_ops->post_domain_create != NULL)
|
||||
acm_secondary_ops->post_domain_create (domid, ssidref);
|
||||
}
|
||||
|
||||
static inline void acm_fail_domain_create (void *subject_ssid, ssidref_t ssidref)
|
||||
{
|
||||
if (acm_primary_ops->fail_domain_create != NULL)
|
||||
acm_primary_ops->fail_domain_create (subject_ssid, ssidref);
|
||||
if (acm_secondary_ops->fail_domain_create != NULL)
|
||||
acm_secondary_ops->fail_domain_create (subject_ssid, ssidref);
|
||||
}
|
||||
|
||||
static inline void acm_post_domain_destroy (void *object_ssid, domid_t id)
|
||||
{
|
||||
if (acm_primary_ops->post_domain_destroy != NULL)
|
||||
acm_primary_ops->post_domain_destroy (object_ssid, id);
|
||||
if (acm_secondary_ops->post_domain_destroy != NULL)
|
||||
acm_secondary_ops->post_domain_destroy (object_ssid, id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* event channel ops */
|
||||
|
||||
static inline int acm_pre_eventchannel_unbound (domid_t id)
|
||||
{
|
||||
if ((acm_primary_ops->pre_eventchannel_unbound != NULL) &&
|
||||
acm_primary_ops->pre_eventchannel_unbound (id))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) &&
|
||||
acm_secondary_ops->pre_eventchannel_unbound (id)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_eventchannel_unbound != NULL)
|
||||
acm_primary_ops->fail_eventchannel_unbound (id);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
static inline int acm_pre_eventchannel_interdomain (domid_t id1, domid_t id2)
|
||||
{
|
||||
if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
|
||||
acm_primary_ops->pre_eventchannel_interdomain (id1, id2))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
|
||||
acm_secondary_ops->pre_eventchannel_interdomain (id1, id2)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
|
||||
acm_primary_ops->fail_eventchannel_interdomain (id1, id2);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
/************ Xen inline hooks ***************/
|
||||
|
||||
/* small macro to make the hooks more readable
|
||||
* (eliminates hooks if NULL policy is active)
|
||||
*/
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
|
||||
{ return 0; }
|
||||
#else
|
||||
static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
|
||||
{
|
||||
int ret = -EACCES;
|
||||
struct domain *d;
|
||||
|
||||
switch(op->cmd) {
|
||||
case DOM0_CREATEDOMAIN:
|
||||
ret = acm_pre_domain_create(current->domain->ssid, op->u.createdomain.ssidref);
|
||||
break;
|
||||
case DOM0_DESTROYDOMAIN:
|
||||
d = find_domain_by_id(op->u.destroydomain.domain);
|
||||
if (d != NULL) {
|
||||
*ssid = d->ssid; /* save for post destroy when d is gone */
|
||||
/* no policy-specific hook */
|
||||
put_domain(d);
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = 0; /* ok */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
|
||||
{ return; }
|
||||
#else
|
||||
static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
|
||||
{
|
||||
switch(op->cmd) {
|
||||
case DOM0_CREATEDOMAIN:
|
||||
/* initialialize shared sHype security labels for new domain */
|
||||
acm_init_domain_ssid(op->u.createdomain.domain, op->u.createdomain.ssidref);
|
||||
acm_post_domain_create(op->u.createdomain.domain, op->u.createdomain.ssidref);
|
||||
break;
|
||||
case DOM0_DESTROYDOMAIN:
|
||||
acm_post_domain_destroy(ssid, op->u.destroydomain.domain);
|
||||
/* free security ssid for the destroyed domain (also if running null policy */
|
||||
acm_free_domain_ssid((struct acm_ssid_domain *)ssid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICy == ACM_NULL_POLICY)
|
||||
static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid)
|
||||
{ return; }
|
||||
#else
|
||||
static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid)
|
||||
{
|
||||
switch(op->cmd) {
|
||||
case DOM0_CREATEDOMAIN:
|
||||
acm_fail_domain_create(current->domain->ssid, op->u.createdomain.ssidref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
static inline int acm_pre_event_channel(evtchn_op_t *op)
|
||||
{ return 0; }
|
||||
#else
|
||||
static inline int acm_pre_event_channel(evtchn_op_t *op)
|
||||
{
|
||||
int ret = -EACCES;
|
||||
|
||||
switch(op->cmd) {
|
||||
case EVTCHNOP_alloc_unbound:
|
||||
ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom);
|
||||
break;
|
||||
case EVTCHNOP_bind_interdomain:
|
||||
ret = acm_pre_eventchannel_interdomain(op->u.bind_interdomain.dom1, op->u.bind_interdomain.dom2);
|
||||
break;
|
||||
default:
|
||||
ret = 0; /* ok */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
static inline int acm_pre_grant_map_ref(domid_t id)
|
||||
{ return 0; }
|
||||
#else
|
||||
static inline int acm_pre_grant_map_ref (domid_t id)
|
||||
{
|
||||
if ((acm_primary_ops->pre_grant_map_ref != NULL) &&
|
||||
acm_primary_ops->pre_grant_map_ref (id))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_grant_map_ref != NULL) &&
|
||||
acm_secondary_ops->pre_grant_map_ref (id)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_grant_map_ref != NULL)
|
||||
acm_primary_ops->fail_grant_map_ref (id);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
static inline int acm_pre_grant_setup(domid_t id)
|
||||
{ return 0; }
|
||||
#else
|
||||
static inline int acm_pre_grant_setup (domid_t id)
|
||||
{
|
||||
if ((acm_primary_ops->pre_grant_setup != NULL) &&
|
||||
acm_primary_ops->pre_grant_setup (id))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_grant_setup != NULL) &&
|
||||
acm_secondary_ops->pre_grant_setup (id)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_grant_setup != NULL)
|
||||
acm_primary_ops->fail_grant_setup (id);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -177,8 +177,7 @@ void sort_main_extable(void);
|
||||
// see include/asm-x86/atomic.h (different from standard linux)
|
||||
#define _atomic_set(v,i) (((v).counter) = (i))
|
||||
#define _atomic_read(v) ((v).counter)
|
||||
// FIXME following needs work
|
||||
#define atomic_compareandswap(old, new, v) old
|
||||
#define atomic_compareandswap(old, new, v) ((atomic_t){ cmpxchg(v, _atomic_read(old), _atomic_read(new)) })
|
||||
|
||||
// see include/asm-ia64/mm.h, handle remaining pfn_info uses until gone
|
||||
#define pfn_info page
|
||||
@@ -227,6 +226,8 @@ struct screen_info { };
|
||||
|
||||
#define FORCE_CRASH() asm("break 0;;");
|
||||
|
||||
#define dummy() dummy_called(__FUNCTION__)
|
||||
|
||||
// these declarations got moved at some point, find a better place for them
|
||||
extern int ht_per_core;
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
#define __ASM_DOMAIN_H__
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
#include <asm/tlb.h>
|
||||
#ifdef CONFIG_VTI
|
||||
#include <asm/vmx_vpd.h>
|
||||
#include <asm/vmmu.h>
|
||||
#include <asm/regionreg.h>
|
||||
#include <public/arch-ia64.h>
|
||||
#endif // CONFIG_VTI
|
||||
#include <xen/list.h>
|
||||
|
||||
extern void arch_do_createdomain(struct vcpu *);
|
||||
|
||||
extern int arch_final_setup_guestos(
|
||||
struct vcpu *, struct vcpu_guest_context *);
|
||||
|
||||
extern void domain_relinquish_resources(struct domain *);
|
||||
|
||||
#ifdef CONFIG_VTI
|
||||
@@ -36,7 +35,15 @@ struct arch_domain {
|
||||
int imp_va_msb;
|
||||
ia64_rr emul_phy_rr0;
|
||||
ia64_rr emul_phy_rr4;
|
||||
u64 *pmt; /* physical to machine table */
|
||||
unsigned long *pmt; /* physical to machine table */
|
||||
/*
|
||||
* max_pfn is the maximum page frame in guest physical space, including
|
||||
* inter-middle I/O ranges and memory holes. This is different with
|
||||
* max_pages in domain struct, which indicates maximum memory size
|
||||
*/
|
||||
unsigned long max_pfn;
|
||||
unsigned int section_nr;
|
||||
mm_section_t *sections; /* Describe memory hole except for Dom0 */
|
||||
#endif //CONFIG_VTI
|
||||
u64 xen_vastart;
|
||||
u64 xen_vaend;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/******************************************************************************
|
||||
* event.h
|
||||
*
|
||||
* A nice interface for passing asynchronous events to guest OSes.
|
||||
* (architecture-dependent part)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_EVENT_H__
|
||||
#define __ASM_EVENT_H__
|
||||
|
||||
static inline void evtchn_notify(struct vcpu *v)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
+87
-53
@@ -27,43 +27,12 @@ typedef unsigned long page_flags_t;
|
||||
|
||||
/*
|
||||
* Per-page-frame information.
|
||||
*
|
||||
* Every architecture must ensure the following:
|
||||
* 1. 'struct pfn_info' contains a 'struct list_head list'.
|
||||
* 2. Provide a PFN_ORDER() macro for accessing the order of a free page.
|
||||
*/
|
||||
|
||||
//FIXME: This can go away when common/dom0_ops.c is fully arch-independent
|
||||
#if 0
|
||||
struct pfn_info
|
||||
{
|
||||
/* Each frame can be threaded onto a doubly-linked list. */
|
||||
struct list_head list;
|
||||
/* Context-dependent fields follow... */
|
||||
union {
|
||||
|
||||
/* Page is in use by a domain. */
|
||||
struct {
|
||||
/* Owner of this page. */
|
||||
struct domain *domain;
|
||||
/* Reference count and various PGC_xxx flags and fields. */
|
||||
u32 count_info;
|
||||
/* Type reference count and various PGT_xxx flags and fields. */
|
||||
u32 type_info;
|
||||
} inuse;
|
||||
|
||||
/* Page is on a free list. */
|
||||
struct {
|
||||
/* Mask of possibly-tainted TLBs. */
|
||||
unsigned long cpu_mask;
|
||||
/* Must be at same offset as 'u.inuse.count_flags'. */
|
||||
u32 __unavailable;
|
||||
/* Order-size of the free chunk this page is the head of. */
|
||||
u8 order;
|
||||
} free;
|
||||
|
||||
} u;
|
||||
|
||||
/* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
|
||||
u32 tlbflush_timestamp;
|
||||
};
|
||||
#endif
|
||||
#define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
|
||||
|
||||
struct page
|
||||
{
|
||||
@@ -82,7 +51,7 @@ struct page
|
||||
/* Page is in use by a domain. */
|
||||
struct {
|
||||
/* Owner of this page. */
|
||||
u64 _domain;
|
||||
u32 _domain;
|
||||
/* Type reference count and various PGT_xxx flags and fields. */
|
||||
u32 type_info;
|
||||
} inuse;
|
||||
@@ -104,37 +73,49 @@ struct page
|
||||
|
||||
#define set_page_count(p,v) atomic_set(&(p)->_count, v - 1)
|
||||
|
||||
//FIXME: These can go away when common/dom0_ops.c is fully arch-independent
|
||||
/* The following page types are MUTUALLY EXCLUSIVE. */
|
||||
/* Still small set of flags defined by far on IA-64 */
|
||||
/* The following page types are MUTUALLY EXCLUSIVE. */
|
||||
#define PGT_none (0<<29) /* no special uses of this page */
|
||||
#define PGT_l1_page_table (1<<29) /* using this page as an L1 page table? */
|
||||
#define PGT_l2_page_table (2<<29) /* using this page as an L2 page table? */
|
||||
#define PGT_l3_page_table (3<<29) /* using this page as an L3 page table? */
|
||||
#define PGT_l4_page_table (4<<29) /* using this page as an L4 page table? */
|
||||
#define PGT_gdt_page (5<<29) /* using this page in a GDT? */
|
||||
#define PGT_ldt_page (6<<29) /* using this page in an LDT? */
|
||||
#define PGT_writeable_page (7<<29) /* has writable mappings of this page? */
|
||||
#define PGT_type_mask (7<<29) /* Bits 29-31. */
|
||||
#define PGT_writeable_page (5<<29) /* has writable mappings of this page? */
|
||||
#define PGT_type_mask (5<<29) /* Bits 29-31. */
|
||||
|
||||
/* Has this page been validated for use as its current type? */
|
||||
#define _PGT_validated 28
|
||||
#define PGT_validated (1<<_PGT_validated)
|
||||
/* 28-bit count of uses of this frame as its current type. */
|
||||
#define PGT_count_mask ((1<<28)-1)
|
||||
/* Owning guest has pinned this page to its current type? */
|
||||
#define _PGT_pinned 27
|
||||
#define PGT_pinned (1U<<_PGT_pinned)
|
||||
|
||||
/* 27-bit count of uses of this frame as its current type. */
|
||||
#define PGT_count_mask ((1U<<27)-1)
|
||||
|
||||
/* Cleared when the owning guest 'frees' this page. */
|
||||
#define _PGC_allocated 31
|
||||
#define PGC_allocated (1U<<_PGC_allocated)
|
||||
#define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
|
||||
/* Set when the page is used as a page table */
|
||||
#define _PGC_page_table 30
|
||||
#define PGC_page_table (1U<<_PGC_page_table)
|
||||
/* 30-bit count of references to this frame. */
|
||||
#define PGC_count_mask ((1U<<30)-1)
|
||||
|
||||
#define IS_XEN_HEAP_FRAME(_pfn) ((page_to_phys(_pfn) < xenheap_phys_end) \
|
||||
&& (page_to_phys(_pfn) >= xen_pstart))
|
||||
|
||||
#define pickle_domptr(_d) ((u64)(_d))
|
||||
#define unpickle_domptr(_d) ((struct domain*)(_d))
|
||||
static inline struct domain *unpickle_domptr(u32 _d)
|
||||
{ return (_d == 0) ? NULL : __va(_d); }
|
||||
static inline u32 pickle_domptr(struct domain *_d)
|
||||
{ return (_d == NULL) ? 0 : (u32)__pa(_d); }
|
||||
|
||||
#define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
|
||||
#define page_set_owner(_p, _d) ((_p)->u.inuse._domain = pickle_domptr(_d))
|
||||
|
||||
/* Dummy now */
|
||||
#define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) do { } while (0)
|
||||
|
||||
extern struct pfn_info *frame_table;
|
||||
extern unsigned long frame_table_size;
|
||||
extern struct list_head free_list;
|
||||
@@ -151,16 +132,46 @@ void add_to_domain_alloc_list(unsigned long ps, unsigned long pe);
|
||||
|
||||
static inline void put_page(struct pfn_info *page)
|
||||
{
|
||||
dummy();
|
||||
u32 nx, x, y = page->count_info;
|
||||
|
||||
do {
|
||||
x = y;
|
||||
nx = x - 1;
|
||||
}
|
||||
while (unlikely((y = cmpxchg(&page->count_info, x, nx)) != x));
|
||||
|
||||
if (unlikely((nx & PGC_count_mask) == 0))
|
||||
free_domheap_page(page);
|
||||
}
|
||||
|
||||
|
||||
/* count_info and ownership are checked atomically. */
|
||||
static inline int get_page(struct pfn_info *page,
|
||||
struct domain *domain)
|
||||
{
|
||||
dummy();
|
||||
u64 x, nx, y = *((u64*)&page->count_info);
|
||||
u32 _domain = pickle_domptr(domain);
|
||||
|
||||
do {
|
||||
x = y;
|
||||
nx = x + 1;
|
||||
if (unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
|
||||
unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
|
||||
unlikely((x >> 32) != _domain)) { /* Wrong owner? */
|
||||
DPRINTK("Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%08x\n",
|
||||
page_to_pfn(page), domain, unpickle_domptr(d),
|
||||
x, page->u.inuse.typeinfo);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while(unlikely(y = cmpxchg(&page->count_info, x, nx)) != x);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* No type info now */
|
||||
#define put_page_and_type(page) put_page((page))
|
||||
#define get_page_and_type(page, domain, type) get_page((page))
|
||||
|
||||
#define set_machinetophys(_mfn, _pfn) do { } while(0);
|
||||
|
||||
#ifdef MEMORY_GUARD
|
||||
@@ -364,17 +375,40 @@ extern unsigned long *mpt_table;
|
||||
#undef machine_to_phys_mapping
|
||||
#define machine_to_phys_mapping mpt_table
|
||||
|
||||
#define INVALID_M2P_ENTRY (~0U)
|
||||
#define VALID_M2P(_e) (!((_e) & (1U<<63)))
|
||||
#define IS_INVALID_M2P_ENTRY(_e) (!VALID_M2P(_e))
|
||||
/* If pmt table is provided by control pannel later, we need __get_user
|
||||
* here. However if it's allocated by HV, we should access it directly
|
||||
*/
|
||||
#define phys_to_machine_mapping(d, gpfn) \
|
||||
((d) == dom0 ? gpfn : (d)->arch.pmt[(gpfn)])
|
||||
#define phys_to_machine_mapping(d, gpfn) \
|
||||
((d) == dom0 ? gpfn : \
|
||||
(gpfn <= d->arch.max_pfn ? (d)->arch.pmt[(gpfn)] : \
|
||||
INVALID_MFN))
|
||||
|
||||
#define __mfn_to_gpfn(_d, mfn) \
|
||||
machine_to_phys_mapping[(mfn)]
|
||||
|
||||
#define __gpfn_to_mfn(_d, gpfn) \
|
||||
phys_to_machine_mapping((_d), (gpfn))
|
||||
|
||||
#define __gpfn_invalid(_d, gpfn) \
|
||||
(__gpfn_to_mfn((_d), (gpfn)) & GPFN_INV_MASK)
|
||||
|
||||
#define __gpfn_valid(_d, gpfn) !__gpfn_invalid(_d, gpfn)
|
||||
|
||||
/* Return I/O type if trye */
|
||||
#define __gpfn_is_io(_d, gpfn) \
|
||||
(__gpfn_valid(_d, gpfn) ? \
|
||||
(__gpfn_to_mfn((_d), (gpfn)) & GPFN_IO_MASK) : 0)
|
||||
|
||||
#define __gpfn_is_mem(_d, gpfn) \
|
||||
(__gpfn_valid(_d, gpfn) ? \
|
||||
((__gpfn_to_mfn((_d), (gpfn)) & GPFN_IO_MASK) == GPFN_MEM) : 0)
|
||||
|
||||
|
||||
#define __gpa_to_mpa(_d, gpa) \
|
||||
((__gpfn_to_mfn((_d),(gpa)>>PAGE_SHIFT)<<PAGE_SHIFT)|((gpa)&~PAGE_MASK))
|
||||
#endif // CONFIG_VTI
|
||||
|
||||
#endif /* __ASM_IA64_MM_H__ */
|
||||
@@ -39,11 +39,11 @@ typedef struct {
|
||||
typedef union {
|
||||
unsigned long value;
|
||||
struct {
|
||||
uint64_t ve : 1;
|
||||
uint64_t rv1 : 1;
|
||||
uint64_t ps : 6;
|
||||
uint64_t rid : 24;
|
||||
uint64_t rv2 : 32;
|
||||
unsigned long ve : 1;
|
||||
unsigned long rv1 : 1;
|
||||
unsigned long ps : 6;
|
||||
unsigned long rid : 24;
|
||||
unsigned long rv2 : 32;
|
||||
};
|
||||
} rr_t;
|
||||
#endif // CONFIG_VTI
|
||||
|
||||
@@ -23,8 +23,8 @@ typedef struct pt_regs REGS;
|
||||
|
||||
#define PRIVOP_ADDR_COUNT
|
||||
#ifdef PRIVOP_ADDR_COUNT
|
||||
#define _RSM 0
|
||||
#define _SSM 1
|
||||
#define _GET_IFA 0
|
||||
#define _THASH 1
|
||||
#define PRIVOP_COUNT_NINSTS 2
|
||||
#define PRIVOP_COUNT_NADDRS 30
|
||||
|
||||
|
||||
@@ -139,13 +139,21 @@ CC_##Name:; \
|
||||
mov r31 = pr; \
|
||||
mov r16 = cr.ifa; \
|
||||
movl r30 = int_counts; \
|
||||
;; \
|
||||
extr.u r17=r16,59,5 \
|
||||
;; \
|
||||
cmp.eq p6,p0=0x1e,r17; \
|
||||
(p6) br.cond.spnt .Alt_##Name \
|
||||
;; \
|
||||
cmp.eq p6,p0=0x1d,r17; \
|
||||
(p6) br.cond.spnt .Alt_##Name \
|
||||
;; \
|
||||
thash r28 = r16; \
|
||||
adds r30 = CAUSE_VHPT_CC_HANDLED << 3, r30; \
|
||||
;; \
|
||||
ttag r19 = r16; \
|
||||
ld8 r27 = [r30]; \
|
||||
adds r17 = VLE_CCHAIN_OFFSET, r28; \
|
||||
ld8 r27 = [r30]; \
|
||||
adds r17 = VLE_CCHAIN_OFFSET, r28; \
|
||||
;; \
|
||||
ld8 r17 = [r17]; \
|
||||
;; \
|
||||
@@ -192,6 +200,11 @@ CC_##Name:; \
|
||||
rfi; \
|
||||
;; \
|
||||
\
|
||||
.Alt_##Name:; \
|
||||
mov pr = r31, 0x1ffff; \
|
||||
;; \
|
||||
br.cond.sptk late_alt_##Name \
|
||||
;; \
|
||||
.Out_##Name:; \
|
||||
mov pr = r31, 0x1ffff; \
|
||||
;; \
|
||||
|
||||
+15
-16
@@ -28,13 +28,13 @@
|
||||
#include "public/xen.h"
|
||||
#include "asm/tlb.h"
|
||||
|
||||
#define THASH_TLB_TR 0
|
||||
#define THASH_TLB_TC 1
|
||||
#define THASH_TLB_FM 2 // foreign map
|
||||
//#define THASH_TLB_TR 0
|
||||
//#define THASH_TLB_TC 1
|
||||
|
||||
#define THASH_SECTION_TR (1<<0)
|
||||
#define THASH_SECTION_TC (1<<1)
|
||||
#define THASH_SECTION_FM (1<<2)
|
||||
|
||||
// bit definition of TR, TC search cmobination
|
||||
//#define THASH_SECTION_TR (1<<0)
|
||||
//#define THASH_SECTION_TC (1<<1)
|
||||
|
||||
/*
|
||||
* Next bit definition must be same with THASH_TLB_XX
|
||||
@@ -43,8 +43,7 @@ typedef union search_section {
|
||||
struct {
|
||||
u32 tr : 1;
|
||||
u32 tc : 1;
|
||||
u32 fm : 1;
|
||||
u32 rsv: 29;
|
||||
u32 rsv: 30;
|
||||
};
|
||||
u32 v;
|
||||
} search_section_t;
|
||||
@@ -80,12 +79,10 @@ typedef struct thash_data {
|
||||
u64 ig1 : 11; //53-63
|
||||
};
|
||||
struct {
|
||||
u64 __rv1 : 12;
|
||||
// sizeof(domid_t) must be less than 38!!! Refer to its definition
|
||||
u64 fm_dom : 38; // 12-49 foreign map domain ID
|
||||
u64 __rv2 : 3; // 50-52
|
||||
u64 __rv1 : 53; // 0-52
|
||||
// next extension to ig1, only for TLB instance
|
||||
u64 section : 2; // 53-54 TR, TC or FM (thash_TLB_XX)
|
||||
u64 tc : 1; // 53 TR or TC
|
||||
u64 locked : 1; // 54 entry locked or not
|
||||
CACHE_LINE_TYPE cl : 1; // I side or D side cache line
|
||||
u64 nomap : 1; // entry cann't be inserted into machine TLB.
|
||||
u64 __ig1 : 5; // 56-61
|
||||
@@ -227,8 +224,8 @@ typedef struct thash_cb {
|
||||
INVALID_ENTRY(hcb, hash) = 1; \
|
||||
hash->next = NULL; }
|
||||
|
||||
#define PURGABLE_ENTRY(hcb,en) \
|
||||
((hcb)->ht == THASH_VHPT || (en)->section == THASH_TLB_TC)
|
||||
#define PURGABLE_ENTRY(hcb,en) \
|
||||
((hcb)->ht == THASH_VHPT || ( (en)->tc && !(en->locked)) )
|
||||
|
||||
|
||||
/*
|
||||
@@ -306,7 +303,7 @@ extern void thash_purge_entries_ex(thash_cb_t *hcb,
|
||||
u64 rid, u64 va, u64 sz,
|
||||
search_section_t p_sect,
|
||||
CACHE_LINE_TYPE cl);
|
||||
extern thash_cb_t *init_domain_tlb(struct vcpu *d);
|
||||
extern void thash_purge_and_insert(thash_cb_t *hcb, thash_data_t *in);
|
||||
|
||||
/*
|
||||
* Purge all TCs or VHPT entries including those in Hash table.
|
||||
@@ -323,6 +320,7 @@ extern thash_data_t *vtlb_lookup(thash_cb_t *hcb,
|
||||
thash_data_t *in);
|
||||
extern thash_data_t *vtlb_lookup_ex(thash_cb_t *hcb,
|
||||
u64 rid, u64 va,CACHE_LINE_TYPE cl);
|
||||
extern int thash_lock_tc(thash_cb_t *hcb, u64 va, u64 size, int rid, char cl, int lock);
|
||||
|
||||
|
||||
#define ITIR_RV_MASK (((1UL<<32)-1)<<32 | 0x3)
|
||||
@@ -332,6 +330,7 @@ extern u64 machine_thash(PTA pta, u64 va, u64 rid, u64 ps);
|
||||
extern void purge_machine_tc_by_domid(domid_t domid);
|
||||
extern void machine_tlb_insert(struct vcpu *d, thash_data_t *tlb);
|
||||
extern rr_t vmmu_get_rr(struct vcpu *vcpu, u64 va);
|
||||
extern thash_cb_t *init_domain_tlb(struct vcpu *d);
|
||||
|
||||
#define VTLB_DEBUG
|
||||
#ifdef VTLB_DEBUG
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
struct mmio_list;
|
||||
typedef struct virutal_platform_def {
|
||||
//unsigned long *real_mode_data; /* E820, etc. */
|
||||
//unsigned long shared_page_va;
|
||||
unsigned long shared_page_va;
|
||||
//struct vmx_virpit_t vmx_pit;
|
||||
//struct vmx_handler_t vmx_handler;
|
||||
//struct mi_per_cpu_info mpci; /* MMIO */
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 1998-2003 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
* Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2003 Intel Co
|
||||
* Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
* Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Arun Sharma <arun.sharma@intel.com>
|
||||
*
|
||||
* 12/07/98 S. Eranian added pt_regs & switch_stack
|
||||
* 12/21/98 D. Mosberger updated to match latest code
|
||||
* 6/17/99 D. Mosberger added second unat member to "struct switch_stack"
|
||||
* 4/28/05 Anthony Xu ported to Xen
|
||||
*
|
||||
*/
|
||||
|
||||
struct pt_regs {
|
||||
/* The following registers are saved by SAVE_MIN: */
|
||||
unsigned long b6; /* scratch */
|
||||
unsigned long b7; /* scratch */
|
||||
|
||||
unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
|
||||
unsigned long ar_ssd; /* reserved for future use (scratch) */
|
||||
|
||||
unsigned long r8; /* scratch (return value register 0) */
|
||||
unsigned long r9; /* scratch (return value register 1) */
|
||||
unsigned long r10; /* scratch (return value register 2) */
|
||||
unsigned long r11; /* scratch (return value register 3) */
|
||||
|
||||
unsigned long cr_ipsr; /* interrupted task's psr */
|
||||
unsigned long cr_iip; /* interrupted task's instruction pointer */
|
||||
unsigned long cr_ifs; /* interrupted task's function state */
|
||||
|
||||
unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
|
||||
unsigned long ar_pfs; /* prev function state */
|
||||
unsigned long ar_rsc; /* RSE configuration */
|
||||
/* The following two are valid only if cr_ipsr.cpl > 0: */
|
||||
unsigned long ar_rnat; /* RSE NaT */
|
||||
unsigned long ar_bspstore; /* RSE bspstore */
|
||||
|
||||
unsigned long pr; /* 64 predicate registers (1 bit each) */
|
||||
unsigned long b0; /* return pointer (bp) */
|
||||
unsigned long loadrs; /* size of dirty partition << 16 */
|
||||
|
||||
unsigned long r1; /* the gp pointer */
|
||||
unsigned long r12; /* interrupted task's memory stack pointer */
|
||||
unsigned long r13; /* thread pointer */
|
||||
|
||||
unsigned long ar_fpsr; /* floating point status (preserved) */
|
||||
unsigned long r15; /* scratch */
|
||||
|
||||
/* The remaining registers are NOT saved for system calls. */
|
||||
|
||||
unsigned long r14; /* scratch */
|
||||
unsigned long r2; /* scratch */
|
||||
unsigned long r3; /* scratch */
|
||||
unsigned long r4; /* preserved */
|
||||
unsigned long r5; /* preserved */
|
||||
unsigned long r6; /* preserved */
|
||||
unsigned long r7; /* preserved */
|
||||
unsigned long cr_iipa; /* for emulation */
|
||||
unsigned long cr_isr; /* for emulation */
|
||||
unsigned long eml_unat; /* used for emulating instruction */
|
||||
unsigned long rfi_pfs; /* used for elulating rfi */
|
||||
|
||||
/* The following registers are saved by SAVE_REST: */
|
||||
unsigned long r16; /* scratch */
|
||||
unsigned long r17; /* scratch */
|
||||
unsigned long r18; /* scratch */
|
||||
unsigned long r19; /* scratch */
|
||||
unsigned long r20; /* scratch */
|
||||
unsigned long r21; /* scratch */
|
||||
unsigned long r22; /* scratch */
|
||||
unsigned long r23; /* scratch */
|
||||
unsigned long r24; /* scratch */
|
||||
unsigned long r25; /* scratch */
|
||||
unsigned long r26; /* scratch */
|
||||
unsigned long r27; /* scratch */
|
||||
unsigned long r28; /* scratch */
|
||||
unsigned long r29; /* scratch */
|
||||
unsigned long r30; /* scratch */
|
||||
unsigned long r31; /* scratch */
|
||||
|
||||
unsigned long ar_ccv; /* compare/exchange value (scratch) */
|
||||
|
||||
/*
|
||||
* Floating point registers that the kernel considers scratch:
|
||||
*/
|
||||
struct ia64_fpreg f6; /* scratch */
|
||||
struct ia64_fpreg f7; /* scratch */
|
||||
struct ia64_fpreg f8; /* scratch */
|
||||
struct ia64_fpreg f9; /* scratch */
|
||||
struct ia64_fpreg f10; /* scratch */
|
||||
struct ia64_fpreg f11; /* scratch */
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <asm/vtm.h>
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <public/arch-ia64.h>
|
||||
|
||||
#define VPD_SHIFT 17 /* 128K requirement */
|
||||
#define VPD_SIZE (1 << VPD_SHIFT)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/******************************************************************************
|
||||
* event.h
|
||||
*
|
||||
* A nice interface for passing asynchronous events to guest OSes.
|
||||
* (architecture-dependent part)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_EVENT_H__
|
||||
#define __ASM_EVENT_H__
|
||||
|
||||
static inline void evtchn_notify(struct vcpu *v)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -181,6 +181,7 @@ extern struct cpuinfo_x86 cpu_data[];
|
||||
#endif
|
||||
|
||||
extern int phys_proc_id[NR_CPUS];
|
||||
extern int cpu_core_id[NR_CPUS];
|
||||
|
||||
extern void identify_cpu(struct cpuinfo_x86 *);
|
||||
extern void print_cpu_info(struct cpuinfo_x86 *);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/cpumask.h>
|
||||
#include <asm/current.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
@@ -34,6 +35,7 @@ extern void smp_alloc_memory(void);
|
||||
extern int pic_mode;
|
||||
extern int smp_num_siblings;
|
||||
extern cpumask_t cpu_sibling_map[];
|
||||
extern cpumask_t cpu_core_map[];
|
||||
|
||||
extern void smp_flush_tlb(void);
|
||||
extern void smp_invalidate_rcv(void); /* Process an NMI */
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/****************************************************************
|
||||
* acm.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
* added network byte order support for binary policies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype general access control module header file.
|
||||
* here are all definitions that are shared between
|
||||
* xen-core, guest-kernels, and applications.
|
||||
*
|
||||
* todo: move from static policy choice to compile option.
|
||||
*/
|
||||
|
||||
#ifndef _XEN_PUBLIC_SHYPE_H
|
||||
#define _XEN_PUBLIC_SHYPE_H
|
||||
|
||||
#include "xen.h"
|
||||
#include "sched_ctl.h"
|
||||
|
||||
/* if ACM_DEBUG defined, all hooks should
|
||||
* print a short trace message (comment it out
|
||||
* when not in testing mode )
|
||||
*/
|
||||
/* #define ACM_DEBUG */
|
||||
|
||||
#ifdef ACM_DEBUG
|
||||
# define printkd(fmt, args...) printk(fmt,## args)
|
||||
#else
|
||||
# define printkd(fmt, args...)
|
||||
#endif
|
||||
|
||||
/* default ssid reference value if not supplied */
|
||||
#define ACM_DEFAULT_SSID 0xffffffff
|
||||
#define ACM_DEFAULT_LOCAL_SSID 0xffff
|
||||
|
||||
/* Internal ACM ERROR types */
|
||||
#define ACM_OK 0
|
||||
#define ACM_UNDEF -1
|
||||
#define ACM_INIT_SSID_ERROR -2
|
||||
#define ACM_INIT_SOID_ERROR -3
|
||||
#define ACM_ERROR -4
|
||||
|
||||
/* External ACCESS DECISIONS */
|
||||
#define ACM_ACCESS_PERMITTED 0
|
||||
#define ACM_ACCESS_DENIED -111
|
||||
#define ACM_NULL_POINTER_ERROR -200
|
||||
|
||||
#define ACM_MAX_POLICY 3
|
||||
|
||||
#define ACM_NULL_POLICY 0
|
||||
#define ACM_CHINESE_WALL_POLICY 1
|
||||
#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
|
||||
#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3
|
||||
|
||||
/* policy: */
|
||||
#define ACM_POLICY_NAME(X) \
|
||||
(X == ACM_NULL_POLICY) ? "NULL policy" : \
|
||||
(X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \
|
||||
(X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT policy" : \
|
||||
(X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
|
||||
"UNDEFINED policy"
|
||||
|
||||
#ifndef ACM_USE_SECURITY_POLICY
|
||||
#define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY
|
||||
#endif
|
||||
|
||||
/* defines a ssid reference used by xen */
|
||||
typedef u32 ssidref_t;
|
||||
|
||||
/* -------security policy relevant type definitions-------- */
|
||||
|
||||
/* type identifier; compares to "equal" or "not equal" */
|
||||
typedef u16 domaintype_t;
|
||||
|
||||
/* CHINESE WALL POLICY DATA STRUCTURES
|
||||
*
|
||||
* current accumulated conflict type set:
|
||||
* When a domain is started and has a type that is in
|
||||
* a conflict set, the conflicting types are incremented in
|
||||
* the aggregate set. When a domain is destroyed, the
|
||||
* conflicting types to its type are decremented.
|
||||
* If a domain has multiple types, this procedure works over
|
||||
* all those types.
|
||||
*
|
||||
* conflict_aggregate_set[i] holds the number of
|
||||
* running domains that have a conflict with type i.
|
||||
*
|
||||
* running_types[i] holds the number of running domains
|
||||
* that include type i in their ssidref-referenced type set
|
||||
*
|
||||
* conflict_sets[i][j] is "0" if type j has no conflict
|
||||
* with type i and is "1" otherwise.
|
||||
*/
|
||||
/* high-16 = version, low-16 = check magic */
|
||||
#define ACM_MAGIC 0x0001debc
|
||||
|
||||
/* each offset in bytes from start of the struct they
|
||||
* the are part of */
|
||||
/* each buffer consists of all policy information for
|
||||
* the respective policy given in the policy code
|
||||
*/
|
||||
struct acm_policy_buffer {
|
||||
u32 magic;
|
||||
u32 policyversion;
|
||||
u32 len;
|
||||
u16 primary_policy_code;
|
||||
u16 primary_buffer_offset;
|
||||
u16 secondary_policy_code;
|
||||
u16 secondary_buffer_offset;
|
||||
};
|
||||
|
||||
struct acm_chwall_policy_buffer {
|
||||
u16 policy_code;
|
||||
u16 chwall_max_types;
|
||||
u16 chwall_max_ssidrefs;
|
||||
u16 chwall_max_conflictsets;
|
||||
u16 chwall_ssid_offset;
|
||||
u16 chwall_conflict_sets_offset;
|
||||
u16 chwall_running_types_offset;
|
||||
u16 chwall_conflict_aggregate_offset;
|
||||
};
|
||||
|
||||
struct acm_ste_policy_buffer {
|
||||
u16 policy_code;
|
||||
u16 ste_max_types;
|
||||
u16 ste_max_ssidrefs;
|
||||
u16 ste_ssid_offset;
|
||||
};
|
||||
|
||||
struct acm_stats_buffer {
|
||||
u32 magic;
|
||||
u32 policyversion;
|
||||
u32 len;
|
||||
u16 primary_policy_code;
|
||||
u16 primary_stats_offset;
|
||||
u16 secondary_policy_code;
|
||||
u16 secondary_stats_offset;
|
||||
};
|
||||
|
||||
struct acm_ste_stats_buffer {
|
||||
u32 ec_eval_count;
|
||||
u32 gt_eval_count;
|
||||
u32 ec_denied_count;
|
||||
u32 gt_denied_count;
|
||||
u32 ec_cachehit_count;
|
||||
u32 gt_cachehit_count;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
/****************************************************************
|
||||
* acm_dom0_setup.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* Includes necessary definitions to bring-up dom0
|
||||
*/
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
extern int acm_init(void);
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
|
||||
static inline void acm_post_domain0_create(domid_t domid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* predefined ssidref for DOM0 used by xen when creating DOM0 */
|
||||
#define ACM_DOM0_SSIDREF 0
|
||||
|
||||
static inline void acm_post_domain0_create(domid_t domid)
|
||||
{
|
||||
/* initialialize shared sHype security labels for new domain */
|
||||
acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF);
|
||||
acm_post_domain_create(domid, ACM_DOM0_SSIDREF);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,11 +14,41 @@
|
||||
#define _MEMORY_PADDING(_X)
|
||||
#define MEMORY_PADDING
|
||||
|
||||
/* Maximum number of virtual CPUs in multi-processor guests. */
|
||||
/* WARNING: before changing this, check that shared_info fits on a page */
|
||||
#define MAX_VIRT_CPUS 1
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* NB. Both the following are 64 bits each. */
|
||||
typedef unsigned long memory_t; /* Full-sized pointer/address/memory-size. */
|
||||
|
||||
#define MAX_NR_SECTION 32 // at most 32 memory holes
|
||||
typedef struct {
|
||||
unsigned long start; /* start of memory hole */
|
||||
unsigned long end; /* end of memory hole */
|
||||
} mm_section_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned long mfn : 56;
|
||||
unsigned long type: 8;
|
||||
} pmt_entry_t;
|
||||
|
||||
#define GPFN_MEM (0UL << 56) /* Guest pfn is normal mem */
|
||||
#define GPFN_FRAME_BUFFER (1UL << 56) /* VGA framebuffer */
|
||||
#define GPFN_LOW_MMIO (2UL << 56) /* Low MMIO range */
|
||||
#define GPFN_PIB (3UL << 56) /* PIB base */
|
||||
#define GPFN_IOSAPIC (4UL << 56) /* IOSAPIC base */
|
||||
#define GPFN_LEGACY_IO (5UL << 56) /* Legacy I/O base */
|
||||
#define GPFN_GFW (6UL << 56) /* Guest Firmware */
|
||||
#define GPFN_HIGH_MMIO (7UL << 56) /* High MMIO range */
|
||||
|
||||
#define GPFN_IO_MASK (7UL << 56) /* Guest pfn is I/O type */
|
||||
#define GPFN_INV_MASK (31UL << 59) /* Guest pfn is invalid */
|
||||
|
||||
#define INVALID_MFN (~0UL)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
} PACKED cpu_user_regs;
|
||||
@@ -28,11 +58,99 @@ typedef struct
|
||||
* structure size will still be 8 bytes, so no other alignments will change.
|
||||
*/
|
||||
typedef struct {
|
||||
u32 tsc_bits; /* 0: 32 bits read from the CPU's TSC. */
|
||||
u32 tsc_bitshift; /* 4: 'tsc_bits' uses N:N+31 of TSC. */
|
||||
unsigned int tsc_bits; /* 0: 32 bits read from the CPU's TSC. */
|
||||
unsigned int tsc_bitshift; /* 4: 'tsc_bits' uses N:N+31 of TSC. */
|
||||
} PACKED tsc_timestamp_t; /* 8 bytes */
|
||||
|
||||
#include <asm/tlb.h> /* TR_ENTRY */
|
||||
struct pt_fpreg {
|
||||
union {
|
||||
unsigned long bits[2];
|
||||
long double __dummy; /* force 16-byte alignment */
|
||||
} u;
|
||||
};
|
||||
|
||||
struct pt_regs {
|
||||
/* The following registers are saved by SAVE_MIN: */
|
||||
unsigned long b6; /* scratch */
|
||||
unsigned long b7; /* scratch */
|
||||
|
||||
unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
|
||||
unsigned long ar_ssd; /* reserved for future use (scratch) */
|
||||
|
||||
unsigned long r8; /* scratch (return value register 0) */
|
||||
unsigned long r9; /* scratch (return value register 1) */
|
||||
unsigned long r10; /* scratch (return value register 2) */
|
||||
unsigned long r11; /* scratch (return value register 3) */
|
||||
|
||||
unsigned long cr_ipsr; /* interrupted task's psr */
|
||||
unsigned long cr_iip; /* interrupted task's instruction pointer */
|
||||
unsigned long cr_ifs; /* interrupted task's function state */
|
||||
|
||||
unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
|
||||
unsigned long ar_pfs; /* prev function state */
|
||||
unsigned long ar_rsc; /* RSE configuration */
|
||||
/* The following two are valid only if cr_ipsr.cpl > 0: */
|
||||
unsigned long ar_rnat; /* RSE NaT */
|
||||
unsigned long ar_bspstore; /* RSE bspstore */
|
||||
|
||||
unsigned long pr; /* 64 predicate registers (1 bit each) */
|
||||
unsigned long b0; /* return pointer (bp) */
|
||||
unsigned long loadrs; /* size of dirty partition << 16 */
|
||||
|
||||
unsigned long r1; /* the gp pointer */
|
||||
unsigned long r12; /* interrupted task's memory stack pointer */
|
||||
unsigned long r13; /* thread pointer */
|
||||
|
||||
unsigned long ar_fpsr; /* floating point status (preserved) */
|
||||
unsigned long r15; /* scratch */
|
||||
|
||||
/* The remaining registers are NOT saved for system calls. */
|
||||
|
||||
unsigned long r14; /* scratch */
|
||||
unsigned long r2; /* scratch */
|
||||
unsigned long r3; /* scratch */
|
||||
|
||||
#ifdef CONFIG_VTI
|
||||
unsigned long r4; /* preserved */
|
||||
unsigned long r5; /* preserved */
|
||||
unsigned long r6; /* preserved */
|
||||
unsigned long r7; /* preserved */
|
||||
unsigned long cr_iipa; /* for emulation */
|
||||
unsigned long cr_isr; /* for emulation */
|
||||
unsigned long eml_unat; /* used for emulating instruction */
|
||||
unsigned long rfi_pfs; /* used for elulating rfi */
|
||||
#endif
|
||||
|
||||
/* The following registers are saved by SAVE_REST: */
|
||||
unsigned long r16; /* scratch */
|
||||
unsigned long r17; /* scratch */
|
||||
unsigned long r18; /* scratch */
|
||||
unsigned long r19; /* scratch */
|
||||
unsigned long r20; /* scratch */
|
||||
unsigned long r21; /* scratch */
|
||||
unsigned long r22; /* scratch */
|
||||
unsigned long r23; /* scratch */
|
||||
unsigned long r24; /* scratch */
|
||||
unsigned long r25; /* scratch */
|
||||
unsigned long r26; /* scratch */
|
||||
unsigned long r27; /* scratch */
|
||||
unsigned long r28; /* scratch */
|
||||
unsigned long r29; /* scratch */
|
||||
unsigned long r30; /* scratch */
|
||||
unsigned long r31; /* scratch */
|
||||
|
||||
unsigned long ar_ccv; /* compare/exchange value (scratch) */
|
||||
|
||||
/*
|
||||
* Floating point registers that the kernel considers scratch:
|
||||
*/
|
||||
struct pt_fpreg f6; /* scratch */
|
||||
struct pt_fpreg f7; /* scratch */
|
||||
struct pt_fpreg f8; /* scratch */
|
||||
struct pt_fpreg f9; /* scratch */
|
||||
struct pt_fpreg f10; /* scratch */
|
||||
struct pt_fpreg f11; /* scratch */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned long ipsr;
|
||||
@@ -64,18 +182,20 @@ typedef struct {
|
||||
unsigned long krs[8]; // kernel registers
|
||||
unsigned long pkrs[8]; // protection key registers
|
||||
unsigned long tmp[8]; // temp registers (e.g. for hyperprivops)
|
||||
//} PACKED arch_shared_info_t;
|
||||
//} PACKED arch_vcpu_info_t;
|
||||
} arch_vcpu_info_t; // DON'T PACK
|
||||
|
||||
typedef struct {
|
||||
int evtchn_vector;
|
||||
int domain_controller_evtchn;
|
||||
unsigned int flags;
|
||||
//} PACKED arch_shared_info_t;
|
||||
} arch_shared_info_t; // DON'T PACK
|
||||
|
||||
/*
|
||||
* The following is all CPU context. Note that the i387_ctxt block is filled
|
||||
* in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
|
||||
*/
|
||||
typedef struct vcpu_guest_context {
|
||||
//unsigned long flags;
|
||||
struct pt_regs regs;
|
||||
arch_vcpu_info_t vcpu;
|
||||
arch_shared_info_t shared;
|
||||
} PACKED vcpu_guest_context_t;
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
|
||||
#endif
|
||||
|
||||
/* Maximum number of virtual CPUs in multi-processor guests. */
|
||||
#define MAX_VIRT_CPUS 32
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* NB. Both the following are 32 bits each. */
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
#define HYPERVISOR_VIRT_END (0xFFFF880000000000UL)
|
||||
#endif
|
||||
|
||||
/* Maximum number of virtual CPUs in multi-processor guests. */
|
||||
#define MAX_VIRT_CPUS 32
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* The machine->physical mapping table starts at this address, read-only. */
|
||||
|
||||
@@ -43,6 +43,8 @@ typedef struct sched_adjdom_cmd dom0_adjustdom_t;
|
||||
|
||||
#define DOM0_CREATEDOMAIN 8
|
||||
typedef struct {
|
||||
/* IN parameters */
|
||||
u32 ssidref;
|
||||
/* IN/OUT parameters. */
|
||||
/* Identifier for new domain (auto-allocate if zero is specified). */
|
||||
domid_t domain;
|
||||
@@ -88,6 +90,7 @@ typedef struct {
|
||||
u32 n_vcpu;
|
||||
s32 vcpu_to_cpu[MAX_VIRT_CPUS]; /* current mapping */
|
||||
cpumap_t cpumap[MAX_VIRT_CPUS]; /* allowable mapping */
|
||||
u32 ssidref;
|
||||
} dom0_getdomaininfo_t;
|
||||
|
||||
#define DOM0_SETDOMAININFO 13
|
||||
|
||||
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff.
Show more