ia64/xen-unstable

annotate xen/arch/ia64/xen/dom0_ops.c @ 13608:30af6cfdb05c

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