direct-io.hg

view xen/common/dom0_ops.c @ 440:91f49ffad7d5

bitkeeper revision 1.222 (3eba9f498RAq8VzoEW7GBoEnFA1WGw)

dom0_ops.c:
Fix domain creation to avoid conflicts in domain-id space.
author kaf24@scramble.cl.cam.ac.uk
date Thu May 08 18:17:45 2003 +0000 (2003-05-08)
parents f852e2cc6f5c
children 553dadf99bbc
line source
1 /******************************************************************************
2 * dom0_ops.c
3 *
4 * Process command requests from domain-0 guest OS.
5 *
6 * Copyright (c) 2002, K A Fraser
7 */
9 #include <xeno/config.h>
10 #include <xeno/types.h>
11 #include <xeno/lib.h>
12 #include <xeno/mm.h>
13 #include <xeno/dom0_ops.h>
14 #include <xeno/sched.h>
15 #include <xeno/event.h>
16 #include <asm/domain_page.h>
18 extern unsigned int alloc_new_dom_mem(struct task_struct *, unsigned int);
20 /* Basically used to protect the domain-id space. */
21 static spinlock_t create_dom_lock = SPIN_LOCK_UNLOCKED;
23 static unsigned int get_domnr(void)
24 {
25 static unsigned int domnr = 0;
26 struct task_struct *p;
27 int tries = 0;
29 for ( tries = 0; tries < 1024; tries++ )
30 {
31 domnr = (domnr+1) & ((1<<20)-1);
32 if ( (p = find_domain_by_id(domnr)) == NULL )
33 return domnr;
34 free_task_struct(p);
35 }
37 return 0;
38 }
40 static void build_page_list(struct task_struct *p)
41 {
42 unsigned long *list;
43 unsigned long curr;
44 struct list_head *list_ent;
46 curr = list_entry(p->pg_head.next, struct pfn_info, list) - frame_table;
47 list = (unsigned long *)map_domain_mem(curr << PAGE_SHIFT);
49 list_for_each(list_ent, &p->pg_head)
50 {
51 *list++ = list_entry(list_ent, struct pfn_info, list) - frame_table;
53 if( ((unsigned long)list & ~PAGE_MASK) == 0 )
54 {
55 struct list_head *ent = frame_table[curr].list.next;
56 curr = list_entry(ent, struct pfn_info, list) - frame_table;
57 unmap_domain_mem(list-1);
58 list = (unsigned long *)map_domain_mem(curr << PAGE_SHIFT);
59 }
60 }
62 unmap_domain_mem(list);
63 }
65 long do_dom0_op(dom0_op_t *u_dom0_op)
66 {
67 long ret = 0;
68 dom0_op_t op;
70 if ( current->domain != 0 )
71 return -EPERM;
73 if ( copy_from_user(&op, u_dom0_op, sizeof(op)) )
74 return -EFAULT;
76 switch ( op.cmd )
77 {
79 case DOM0_BUILDDOMAIN:
80 {
81 struct task_struct * p = find_domain_by_id(op.u.meminfo.domain);
82 if ( (ret = final_setup_guestos(p, &op.u.meminfo)) != 0 )
83 break;
84 ret = p->domain;
85 free_task_struct(p);
86 }
87 break;
89 case DOM0_STARTDOMAIN:
90 {
91 struct task_struct * p = find_domain_by_id(op.u.meminfo.domain);
92 ret = -EINVAL;
93 if ( (p == NULL) || !(p->flags & PF_CONSTRUCTED) )
94 break;
95 wake_up(p);
96 reschedule(p);
97 ret = p->domain;
98 free_task_struct(p);
99 }
100 break;
102 case DOM0_STOPDOMAIN:
103 {
104 ret = stop_other_domain (op.u.meminfo.domain);
105 }
106 break;
108 case DOM0_CREATEDOMAIN:
109 {
110 struct task_struct *p;
111 static unsigned int pro = 0;
112 unsigned int dom;
113 ret = -ENOMEM;
115 spin_lock_irq(&create_dom_lock);
117 if ( (dom = get_domnr()) == 0 )
118 goto exit_create;
120 pro = (pro+1) % smp_num_cpus;
121 p = do_newdomain(dom, pro);
122 if ( p == NULL )
123 goto exit_create;
125 if (op.u.newdomain.name[0]) {
126 strncpy (p -> name, op.u.newdomain.name, MAX_DOMAIN_NAME);
127 p -> name[MAX_DOMAIN_NAME - 1] = 0;
128 }
130 ret = alloc_new_dom_mem(p, op.u.newdomain.memory_kb);
131 if ( ret != 0 )
132 {
133 __kill_domain(p);
134 goto exit_create;
135 }
137 build_page_list(p);
139 ret = p->domain;
141 op.u.newdomain.domain = ret;
142 op.u.newdomain.pg_head =
143 list_entry(p->pg_head.next, struct pfn_info, list) -
144 frame_table;
145 copy_to_user(u_dom0_op, &op, sizeof(op));
147 exit_create:
148 spin_unlock_irq(&create_dom_lock);
149 }
150 break;
152 case DOM0_DESTROYDOMAIN:
153 {
154 unsigned int dom = op.u.killdomain.domain;
155 int force = op.u.killdomain.force;
156 if ( dom == IDLE_DOMAIN_ID )
157 {
158 ret = -EPERM;
159 }
160 else
161 {
162 ret = kill_other_domain(dom, force);
163 }
164 }
165 break;
167 case DOM0_BVTCTL:
168 {
169 unsigned long ctx_allow = op.u.bvtctl.ctx_allow;
170 ret = sched_bvtctl(ctx_allow);
172 }
173 break;
175 case DOM0_ADJUSTDOM:
176 {
177 unsigned int dom = op.u.adjustdom.domain;
178 unsigned long mcu_adv = op.u.adjustdom.mcu_adv;
179 unsigned long warp = op.u.adjustdom.warp;
180 unsigned long warpl = op.u.adjustdom.warpl;
181 unsigned long warpu = op.u.adjustdom.warpu;
184 if ( dom == IDLE_DOMAIN_ID )
185 {
186 ret = -EPERM;
187 }
188 else
189 {
190 ret = sched_adjdom(dom, mcu_adv, warp, warpl, warpu);
191 }
192 }
193 break;
195 case DOM0_GETMEMLIST:
196 {
197 int i;
198 unsigned long pfn = op.u.getmemlist.start_pfn;
199 unsigned long *buffer = op.u.getmemlist.buffer;
200 struct list_head *list_ent;
202 for ( i = 0; i < op.u.getmemlist.num_pfns; i++ )
203 {
204 /* XXX We trust DOM0 to give us a safe buffer. XXX */
205 *buffer++ = pfn;
206 list_ent = frame_table[pfn].list.next;
207 pfn = list_entry(list_ent, struct pfn_info, list) - frame_table;
208 }
209 }
210 break;
212 case DOM0_GETDOMAININFO:
213 {
214 struct task_struct *p;
215 u_long flags;
217 p = idle0_task.next_task;
218 read_lock_irqsave (&tasklist_lock, flags);
219 do {
220 if ((!is_idle_task (p)) && (p -> domain >= op.u.getdominfo.domain)) {
221 break;
222 }
223 } while ((p = p -> next_task) != &idle0_task);
225 if (p == &idle0_task) {
226 ret = -ESRCH;
227 } else {
228 op.u.getdominfo.domain = p -> domain;
229 strcpy (op.u.getdominfo.name, p -> name);
230 op.u.getdominfo.processor = p -> processor;
231 op.u.getdominfo.has_cpu = p -> has_cpu;
232 op.u.getdominfo.state = p -> state;
233 op.u.getdominfo.hyp_events = p -> hyp_events;
234 op.u.getdominfo.mcu_advance = p -> mcu_advance;
235 op.u.getdominfo.pg_head = list_entry(p->pg_head.next,
236 struct pfn_info, list) - frame_table;
237 op.u.getdominfo.tot_pages = p -> tot_pages;
238 }
239 read_unlock_irqrestore (&tasklist_lock, flags);
240 copy_to_user(u_dom0_op, &op, sizeof(op));
241 break;
242 }
244 default:
245 ret = -ENOSYS;
247 }
249 return ret;
250 }