ia64/xen-unstable

view xen/common/acm_ops.c @ 12390:e28beea6d228

[IA64] Fix time services of EFI emulation

This patch serializes the execution of following efi.runtimes.
- GetTime
- SetTime
- GetWakeTime
- SetWakeTime

Linux/ia64 uses similar spinlocks in the EFI RTC driver.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Fri Nov 10 12:03:19 2006 -0700 (2006-11-10)
parents 86d26e6ec89b
children 56cd6d669151
line source
1 /******************************************************************************
2 * acm_ops.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * Process acm command requests from guest OS.
15 *
16 */
18 #include <xen/config.h>
19 #include <xen/types.h>
20 #include <xen/lib.h>
21 #include <xen/mm.h>
22 #include <public/acm.h>
23 #include <public/acm_ops.h>
24 #include <xen/sched.h>
25 #include <xen/event.h>
26 #include <xen/trace.h>
27 #include <xen/console.h>
28 #include <xen/guest_access.h>
29 #include <acm/acm_hooks.h>
31 #ifndef ACM_SECURITY
34 long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
35 {
36 return -ENOSYS;
37 }
40 #else
43 int acm_authorize_acm_ops(struct domain *d)
44 {
45 /* currently, policy management functions are restricted to privileged domains */
46 if (!IS_PRIV(d))
47 return -EPERM;
48 return 0;
49 }
52 long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
53 {
54 long rc = -EFAULT;
56 if (acm_authorize_acm_ops(current->domain))
57 return -EPERM;
59 switch ( cmd )
60 {
62 case ACMOP_setpolicy: {
63 struct acm_setpolicy setpolicy;
64 if (copy_from_guest(&setpolicy, arg, 1) != 0)
65 return -EFAULT;
66 if (setpolicy.interface_version != ACM_INTERFACE_VERSION)
67 return -EACCES;
69 rc = acm_set_policy(setpolicy.pushcache,
70 setpolicy.pushcache_size);
71 break;
72 }
74 case ACMOP_getpolicy: {
75 struct acm_getpolicy getpolicy;
76 if (copy_from_guest(&getpolicy, arg, 1) != 0)
77 return -EFAULT;
78 if (getpolicy.interface_version != ACM_INTERFACE_VERSION)
79 return -EACCES;
81 rc = acm_get_policy(getpolicy.pullcache,
82 getpolicy.pullcache_size);
83 break;
84 }
86 case ACMOP_dumpstats: {
87 struct acm_dumpstats dumpstats;
88 if (copy_from_guest(&dumpstats, arg, 1) != 0)
89 return -EFAULT;
90 if (dumpstats.interface_version != ACM_INTERFACE_VERSION)
91 return -EACCES;
93 rc = acm_dump_statistics(dumpstats.pullcache,
94 dumpstats.pullcache_size);
95 break;
96 }
98 case ACMOP_getssid: {
99 struct acm_getssid getssid;
100 ssidref_t ssidref;
102 if (copy_from_guest(&getssid, arg, 1) != 0)
103 return -EFAULT;
104 if (getssid.interface_version != ACM_INTERFACE_VERSION)
105 return -EACCES;
107 if (getssid.get_ssid_by == ACM_GETBY_ssidref)
108 ssidref = getssid.id.ssidref;
109 else if (getssid.get_ssid_by == ACM_GETBY_domainid)
110 {
111 struct domain *subj = find_domain_by_id(getssid.id.domainid);
112 if (!subj)
113 {
114 rc = -ESRCH; /* domain not found */
115 break;
116 }
117 if (subj->ssid == NULL)
118 {
119 put_domain(subj);
120 rc = -ESRCH;
121 break;
122 }
123 ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
124 put_domain(subj);
125 }
126 else
127 {
128 rc = -ESRCH;
129 break;
130 }
131 rc = acm_get_ssid(ssidref, getssid.ssidbuf, getssid.ssidbuf_size);
132 break;
133 }
135 case ACMOP_getdecision: {
136 struct acm_getdecision getdecision;
137 ssidref_t ssidref1, ssidref2;
139 if (copy_from_guest(&getdecision, arg, 1) != 0)
140 return -EFAULT;
141 if (getdecision.interface_version != ACM_INTERFACE_VERSION)
142 return -EACCES;
144 if (getdecision.get_decision_by1 == ACM_GETBY_ssidref)
145 ssidref1 = getdecision.id1.ssidref;
146 else if (getdecision.get_decision_by1 == ACM_GETBY_domainid)
147 {
148 struct domain *subj = find_domain_by_id(getdecision.id1.domainid);
149 if (!subj)
150 {
151 rc = -ESRCH; /* domain not found */
152 break;
153 }
154 if (subj->ssid == NULL)
155 {
156 put_domain(subj);
157 rc = -ESRCH;
158 break;
159 }
160 ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
161 put_domain(subj);
162 }
163 else
164 {
165 rc = -ESRCH;
166 break;
167 }
168 if (getdecision.get_decision_by2 == ACM_GETBY_ssidref)
169 ssidref2 = getdecision.id2.ssidref;
170 else if (getdecision.get_decision_by2 == ACM_GETBY_domainid)
171 {
172 struct domain *subj = find_domain_by_id(getdecision.id2.domainid);
173 if (!subj)
174 {
175 rc = -ESRCH; /* domain not found */
176 break;;
177 }
178 if (subj->ssid == NULL)
179 {
180 put_domain(subj);
181 rc = -ESRCH;
182 break;
183 }
184 ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
185 put_domain(subj);
186 }
187 else
188 {
189 rc = -ESRCH;
190 break;
191 }
192 rc = acm_get_decision(ssidref1, ssidref2, getdecision.hook);
194 if (rc == ACM_ACCESS_PERMITTED)
195 {
196 getdecision.acm_decision = ACM_ACCESS_PERMITTED;
197 rc = 0;
198 }
199 else if (rc == ACM_ACCESS_DENIED)
200 {
201 getdecision.acm_decision = ACM_ACCESS_DENIED;
202 rc = 0;
203 }
204 else
205 rc = -ESRCH;
207 if ( (rc == 0) && (copy_to_guest(arg, &getdecision, 1) != 0) )
208 rc = -EFAULT;
209 break;
210 }
212 default:
213 rc = -ENOSYS;
214 break;
215 }
217 return rc;
218 }
220 #endif
222 /*
223 * Local variables:
224 * mode: C
225 * c-set-style: "BSD"
226 * c-basic-offset: 4
227 * tab-width: 4
228 * indent-tabs-mode: nil
229 * End:
230 */