source: trunk/packages/xen-3.1/xen-3.1/xen/arch/ia64/xen/dom0_ops.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 11.9 KB
Line 
1/******************************************************************************
2 * Arch-specific dom0_ops.c
3 *
4 * Process command requests from domain-0 guest OS.
5 *
6 * Copyright (c) 2002, K A Fraser
7 */
8
9#include <xen/config.h>
10#include <xen/types.h>
11#include <xen/lib.h>
12#include <xen/mm.h>
13#include <public/domctl.h>
14#include <public/sysctl.h>
15#include <xen/sched.h>
16#include <xen/event.h>
17#include <asm/pdb.h>
18#include <xen/trace.h>
19#include <xen/console.h>
20#include <xen/guest_access.h>
21#include <asm/vmx.h>
22#include <asm/dom_fw.h>
23#include <xen/iocap.h>
24#include <xen/errno.h>
25#include <xen/nodemask.h>
26
27#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
28
29extern unsigned long total_pages;
30
31long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
32{
33    long ret = 0;
34
35    if ( !IS_PRIV(current->domain) )
36        return -EPERM;
37
38    switch ( op->cmd )
39    {
40    case XEN_DOMCTL_getmemlist:
41    {
42        unsigned long i;
43        struct domain *d = get_domain_by_id(op->domain);
44        unsigned long start_page = op->u.getmemlist.start_pfn;
45        unsigned long nr_pages = op->u.getmemlist.max_pfns;
46        uint64_t mfn;
47
48        if ( d == NULL ) {
49            ret = -EINVAL;
50            break;
51        }
52        for (i = 0 ; i < nr_pages ; i++) {
53            pte_t *pte;
54
55            pte = (pte_t *)lookup_noalloc_domain_pte(d,
56                                               (start_page + i) << PAGE_SHIFT);
57            if (pte && pte_present(*pte))
58                mfn = start_page + i;
59            else
60                mfn = INVALID_MFN;
61
62            if ( copy_to_guest_offset(op->u.getmemlist.buffer, i, &mfn, 1) ) {
63                    ret = -EFAULT;
64                    break;
65            }
66        }
67
68        op->u.getmemlist.num_pfns = i;
69        if (copy_to_guest(u_domctl, op, 1))
70            ret = -EFAULT;
71
72        put_domain(d);
73    }
74    break;
75
76    case XEN_DOMCTL_arch_setup:
77    {
78        xen_domctl_arch_setup_t *ds = &op->u.arch_setup;
79        struct domain *d = get_domain_by_id(op->domain);
80
81        if ( d == NULL) {
82            ret = -EINVAL;
83            break;
84        }
85
86        if (ds->flags & XEN_DOMAINSETUP_query) {
87            /* Set flags.  */
88            if (d->arch.is_vti)
89                ds->flags |= XEN_DOMAINSETUP_hvm_guest;
90            /* Set params.  */
91            ds->bp = 0;         /* unknown.  */
92            ds->maxmem = 0; /* unknown.  */
93            ds->xsi_va = d->arch.shared_info_va;
94            ds->hypercall_imm = d->arch.breakimm;
95            /* Copy back.  */
96            if ( copy_to_guest(u_domctl, op, 1) )
97                ret = -EFAULT;
98        }
99        else {
100            if (ds->flags & XEN_DOMAINSETUP_hvm_guest) {
101                if (!vmx_enabled) {
102                    printk("No VMX hardware feature for vmx domain.\n");
103                    ret = -EINVAL;
104                    break;
105                }
106                d->arch.is_vti = 1;
107                vmx_setup_platform(d);
108            }
109            else {
110                dom_fw_setup(d, ds->bp, ds->maxmem);
111                if (ds->xsi_va)
112                    d->arch.shared_info_va = ds->xsi_va;
113                if (ds->hypercall_imm) {
114                    struct vcpu *v;
115                    d->arch.breakimm = ds->hypercall_imm;
116                    for_each_vcpu (d, v)
117                        v->arch.breakimm = d->arch.breakimm;
118                }
119                {
120                    /*
121                     * XXX IA64_SHARED_INFO_PADDR
122                     * assign these pages into guest psudo physical address
123                     * space for dom0 to map this page by gmfn.
124                     * this is necessary for domain build, save, restore and
125                     * dump-core.
126                     */
127                    unsigned long i;
128                    for (i = 0; i < XSI_SIZE; i += PAGE_SIZE)
129                        assign_domain_page(d, IA64_SHARED_INFO_PADDR + i,
130                                           virt_to_maddr(d->shared_info + i));
131                }
132            }
133        }
134
135        put_domain(d);
136    }
137    break;
138
139    case XEN_DOMCTL_shadow_op:
140    {
141        struct domain *d; 
142        ret = -ESRCH;
143        d = get_domain_by_id(op->domain);
144        if ( d != NULL )
145        {
146            ret = shadow_mode_control(d, &op->u.shadow_op);
147            put_domain(d);
148            copy_to_guest(u_domctl, op, 1);
149        } 
150    }
151    break;
152
153    case XEN_DOMCTL_ioport_permission:
154    {
155        struct domain *d;
156        unsigned int fp = op->u.ioport_permission.first_port;
157        unsigned int np = op->u.ioport_permission.nr_ports;
158        unsigned int lp = fp + np - 1;
159
160        ret = -ESRCH;
161        d = get_domain_by_id(op->domain);
162        if (unlikely(d == NULL))
163            break;
164
165        if (np == 0)
166            ret = 0;
167        else {
168            if (op->u.ioport_permission.allow_access)
169                ret = ioports_permit_access(d, fp, lp);
170            else
171                ret = ioports_deny_access(d, fp, lp);
172        }
173
174        put_domain(d);
175    }
176    break;
177
178    case XEN_DOMCTL_sendtrigger:
179    {
180        struct domain *d;
181        struct vcpu *v;
182
183        ret = -ESRCH;
184        d = get_domain_by_id(op->domain);
185        if ( d == NULL )
186            break;
187
188        ret = -EINVAL;
189        if ( op->u.sendtrigger.vcpu >= MAX_VIRT_CPUS )
190            goto sendtrigger_out;
191
192        ret = -ESRCH;
193        if ( (v = d->vcpu[op->u.sendtrigger.vcpu]) == NULL )
194            goto sendtrigger_out;
195
196        ret = 0;
197        switch (op->u.sendtrigger.trigger)
198        {
199        case XEN_DOMCTL_SENDTRIGGER_INIT:
200        {
201            if (VMX_DOMAIN(v))
202                vmx_pend_pal_init(d);
203            else
204                ret = -ENOSYS;
205        }
206        break;
207
208        default:
209            ret = -ENOSYS;
210        }
211
212    sendtrigger_out:
213        put_domain(d);
214    }
215    break;
216
217    default:
218        printk("arch_do_domctl: unrecognized domctl: %d!!!\n",op->cmd);
219        ret = -ENOSYS;
220
221    }
222
223    return ret;
224}
225
226/*
227 * Temporarily disable the NUMA PHYSINFO code until the rest of the
228 * changes are upstream.
229 */
230#undef IA64_NUMA_PHYSINFO
231
232long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
233{
234    long ret = 0;
235
236    switch ( op->cmd )
237    {
238    case XEN_SYSCTL_physinfo:
239    {
240#ifdef IA64_NUMA_PHYSINFO
241        int i;
242        node_data_t *chunks;
243        u64 *map, cpu_to_node_map[MAX_NUMNODES];
244#endif
245
246        xen_sysctl_physinfo_t *pi = &op->u.physinfo;
247
248        pi->threads_per_core =
249            cpus_weight(cpu_sibling_map[0]);
250        pi->cores_per_socket =
251            cpus_weight(cpu_core_map[0]) / pi->threads_per_core;
252        pi->sockets_per_node = 
253            num_online_cpus() / cpus_weight(cpu_core_map[0]);
254#ifndef IA64_NUMA_PHYSINFO
255        pi->nr_nodes         = 1; 
256#endif
257        pi->total_pages      = total_pages; 
258        pi->free_pages       = avail_domheap_pages();
259        pi->scrub_pages      = avail_scrub_pages();
260        pi->cpu_khz          = local_cpu_data->proc_freq / 1000;
261        memset(pi->hw_cap, 0, sizeof(pi->hw_cap));
262        //memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
263        ret = 0;
264
265#ifdef IA64_NUMA_PHYSINFO
266        /* fetch memory_chunk pointer from guest */
267        get_xen_guest_handle(chunks, pi->memory_chunks);
268
269        printk("chunks=%p, num_node_memblks=%u\n", chunks, num_node_memblks);
270        /* if it is set, fill out memory chunk array */
271        if (chunks != NULL) {
272            if (num_node_memblks == 0) {
273                /* Non-NUMA machine.  Put pseudo-values.  */
274                node_data_t data;
275                data.node_start_pfn = 0;
276                data.node_spanned_pages = total_pages;
277                data.node_id = 0;
278                /* copy memory chunk structs to guest */
279                if (copy_to_guest_offset(pi->memory_chunks, 0, &data, 1)) {
280                    ret = -EFAULT;
281                    break;
282                }
283            } else {
284                for (i = 0; i < num_node_memblks && i < PUBLIC_MAXCHUNKS; i++) {
285                    node_data_t data;
286                    data.node_start_pfn = node_memblk[i].start_paddr >>
287                                          PAGE_SHIFT;
288                    data.node_spanned_pages = node_memblk[i].size >> PAGE_SHIFT;
289                    data.node_id = node_memblk[i].nid;
290                    /* copy memory chunk structs to guest */
291                    if (copy_to_guest_offset(pi->memory_chunks, i, &data, 1)) {
292                        ret = -EFAULT;
293                        break;
294                    }
295                }
296            }
297        }
298        /* set number of notes */
299        pi->nr_nodes = num_online_nodes();
300
301        /* fetch cpu_to_node pointer from guest */
302        get_xen_guest_handle(map, pi->cpu_to_node);
303
304        /* if set, fill out cpu_to_node array */
305        if (map != NULL) {
306            /* copy cpu to node mapping to domU */
307            memset(cpu_to_node_map, 0, sizeof(cpu_to_node_map));
308            for (i = 0; i < num_online_cpus(); i++) {
309                cpu_to_node_map[i] = cpu_to_node(i);
310                if (copy_to_guest_offset(pi->cpu_to_node, i,
311                                         &(cpu_to_node_map[i]), 1)) {
312                    ret = -EFAULT;
313                    break;
314                }
315            }
316        }
317#endif
318
319        if ( copy_to_guest(u_sysctl, op, 1) )
320            ret = -EFAULT;
321    }
322    break;
323
324    default:
325        printk("arch_do_sysctl: unrecognized sysctl: %d!!!\n",op->cmd);
326        ret = -ENOSYS;
327
328    }
329
330    return ret;
331}
332
333static unsigned long
334dom0vp_ioremap(struct domain *d, unsigned long mpaddr, unsigned long size)
335{
336    unsigned long end;
337
338    /* Linux may use a 0 size!  */
339    if (size == 0)
340        size = PAGE_SIZE;
341
342    if (size == 0)
343        printk(XENLOG_WARNING "ioremap(): Trying to map %lx, size 0\n", mpaddr);
344
345    end = PAGE_ALIGN(mpaddr + size);
346
347    if (!iomem_access_permitted(d, mpaddr >> PAGE_SHIFT,
348                                (end >> PAGE_SHIFT) - 1))
349        return -EPERM;
350
351    return assign_domain_mmio_page(d, mpaddr, mpaddr, size,
352                                   ASSIGN_writable | ASSIGN_nocache);
353}
354
355unsigned long
356do_dom0vp_op(unsigned long cmd,
357             unsigned long arg0, unsigned long arg1, unsigned long arg2,
358             unsigned long arg3)
359{
360    unsigned long ret = 0;
361    struct domain *d = current->domain;
362
363    switch (cmd) {
364    case IA64_DOM0VP_ioremap:
365        ret = dom0vp_ioremap(d, arg0, arg1);
366        break;
367    case IA64_DOM0VP_phystomach:
368        ret = ____lookup_domain_mpa(d, arg0 << PAGE_SHIFT);
369        if (ret == INVALID_MFN) {
370            dprintk(XENLOG_INFO, "%s: INVALID_MFN ret: 0x%lx\n",
371                     __func__, ret);
372        } else {
373            ret = (ret & _PFN_MASK) >> PAGE_SHIFT;//XXX pte_pfn()
374        }
375        perfc_incr(dom0vp_phystomach);
376        break;
377    case IA64_DOM0VP_machtophys:
378        if (!mfn_valid(arg0)) {
379            ret = INVALID_M2P_ENTRY;
380            break;
381        }
382        ret = get_gpfn_from_mfn(arg0);
383        perfc_incr(dom0vp_machtophys);
384        break;
385    case IA64_DOM0VP_zap_physmap:
386        ret = dom0vp_zap_physmap(d, arg0, (unsigned int)arg1);
387        break;
388    case IA64_DOM0VP_add_physmap:
389        ret = dom0vp_add_physmap(d, arg0, arg1, (unsigned int)arg2,
390                                 (domid_t)arg3);
391        break;
392    case IA64_DOM0VP_add_physmap_with_gmfn:
393        ret = dom0vp_add_physmap_with_gmfn(d, arg0, arg1, (unsigned int)arg2,
394                                           (domid_t)arg3);
395        break;
396    case IA64_DOM0VP_expose_p2m:
397        ret = dom0vp_expose_p2m(d, arg0, arg1, arg2, arg3);
398        break;
399    case IA64_DOM0VP_perfmon: {
400        XEN_GUEST_HANDLE(void) hnd;
401        set_xen_guest_handle(hnd, (void*)arg1);
402        ret = do_perfmon_op(arg0, hnd, arg2);
403        break;
404    }
405    default:
406        ret = -1;
407                printk("unknown dom0_vp_op 0x%lx\n", cmd);
408        break;
409    }
410
411    return ret;
412}
413
414/*
415 * Local variables:
416 * mode: C
417 * c-set-style: "BSD"
418 * c-basic-offset: 4
419 * tab-width: 4
420 * indent-tabs-mode: nil
421 * End:
422 */
Note: See TracBrowser for help on using the repository browser.