ia64/xen-unstable

annotate xen/arch/ia64/xen/dom0_ops.c @ 10663:49cea8b66d4a

[IA64] Bug fix: DOM0_GETMEMLIST: do not return -EINVAL in case of success!

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Thu Jul 06 08:18:50 2006 -0600 (2006-07-06)
parents 2b815d9acdea
children 306d7857928c
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>
djm@6458 13 #include <public/dom0_ops.h>
djm@6458 14 #include <xen/sched.h>
djm@6458 15 #include <xen/event.h>
djm@6458 16 #include <asm/pdb.h>
djm@6458 17 #include <xen/trace.h>
djm@6458 18 #include <xen/console.h>
kaf24@9133 19 #include <xen/guest_access.h>
djm@6458 20 #include <public/sched_ctl.h>
awilliam@9005 21 #include <asm/vmx.h>
awilliam@10570 22 #include <asm/dom_fw.h>
awilliam@10570 23
awilliam@10570 24 void build_physmap_table(struct domain *d);
awilliam@10570 25
awilliam@9773 26 extern unsigned long total_pages;
kaf24@9873 27 long arch_do_dom0_op(dom0_op_t *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
djm@6458 28 {
djm@6458 29 long ret = 0;
djm@6458 30
djm@6458 31 if ( !IS_PRIV(current->domain) )
djm@6458 32 return -EPERM;
djm@6458 33
djm@6458 34 switch ( op->cmd )
djm@6458 35 {
djm@6458 36 case DOM0_GETPAGEFRAMEINFO:
djm@6458 37 {
kaf24@8726 38 struct page_info *page;
kfraser@10660 39 unsigned long mfn = op->u.getpageframeinfo.gmfn;
djm@6458 40 domid_t dom = op->u.getpageframeinfo.domain;
djm@6458 41 struct domain *d;
djm@6458 42
djm@6458 43 ret = -EINVAL;
djm@6458 44
kaf24@8750 45 if ( unlikely(!mfn_valid(mfn)) ||
djm@6458 46 unlikely((d = find_domain_by_id(dom)) == NULL) )
djm@6458 47 break;
djm@6458 48
awilliam@9689 49 page = mfn_to_page(mfn);
djm@6458 50
djm@6458 51 if ( likely(get_page(page, d)) )
djm@6458 52 {
djm@6458 53 ret = 0;
djm@6458 54
djm@6458 55 op->u.getpageframeinfo.type = NOTAB;
djm@6458 56
djm@6458 57 if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
djm@6458 58 {
djm@6458 59 switch ( page->u.inuse.type_info & PGT_type_mask )
djm@6458 60 {
kaf24@8750 61 default:
kaf24@8750 62 panic("No such page type\n");
djm@6458 63 break;
djm@6458 64 }
djm@6458 65 }
djm@6458 66
djm@6458 67 put_page(page);
djm@6458 68 }
djm@6458 69
djm@6458 70 put_domain(d);
djm@6458 71
kaf24@9133 72 copy_to_guest(u_dom0_op, op, 1);
djm@6458 73 }
djm@6458 74 break;
djm@6458 75
djm@6458 76 case DOM0_GETPAGEFRAMEINFO2:
djm@6458 77 {
djm@6458 78 #define GPF2_BATCH 128
djm@6458 79 int n,j;
djm@6458 80 int num = op->u.getpageframeinfo2.num;
djm@6458 81 domid_t dom = op->u.getpageframeinfo2.domain;
djm@6458 82 struct domain *d;
djm@6458 83 unsigned long *l_arr;
djm@6458 84 ret = -ESRCH;
djm@6458 85
djm@6458 86 if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
djm@6458 87 break;
djm@6458 88
djm@6458 89 if ( unlikely(num > 1024) )
djm@6458 90 {
djm@6458 91 ret = -E2BIG;
djm@6458 92 break;
djm@6458 93 }
djm@6458 94
djm@6458 95 l_arr = (unsigned long *)alloc_xenheap_page();
djm@6458 96
djm@6458 97 ret = 0;
djm@6458 98 for( n = 0; n < num; )
djm@6458 99 {
djm@6458 100 int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
djm@6458 101
kaf24@9133 102 if ( copy_from_guest_offset(l_arr, op->u.getpageframeinfo2.array,
kaf24@9133 103 n, k) )
djm@6458 104 {
djm@6458 105 ret = -EINVAL;
djm@6458 106 break;
djm@6458 107 }
djm@6458 108
djm@6458 109 for( j = 0; j < k; j++ )
djm@6458 110 {
kaf24@8726 111 struct page_info *page;
djm@6458 112 unsigned long mfn = l_arr[j];
djm@6458 113
djm@6458 114 if ( unlikely(mfn >= max_page) )
djm@6458 115 goto e2_err;
djm@6458 116
awilliam@9689 117 page = mfn_to_page(mfn);
djm@6458 118
djm@6458 119 if ( likely(get_page(page, d)) )
djm@6458 120 {
djm@6458 121 unsigned long type = 0;
djm@6458 122
djm@6458 123 switch( page->u.inuse.type_info & PGT_type_mask )
djm@6458 124 {
kaf24@8750 125 default:
kaf24@8750 126 panic("No such page type\n");
kaf24@8750 127 break;
djm@6458 128 }
djm@6458 129
djm@6458 130 if ( page->u.inuse.type_info & PGT_pinned )
djm@6458 131 type |= LPINTAB;
djm@6458 132 l_arr[j] |= type;
djm@6458 133 put_page(page);
djm@6458 134 }
djm@6458 135 else
djm@6458 136 {
djm@6458 137 e2_err:
djm@6458 138 l_arr[j] |= XTAB;
djm@6458 139 }
djm@6458 140
djm@6458 141 }
djm@6458 142
kaf24@9133 143 if ( copy_to_guest_offset(op->u.getpageframeinfo2.array,
kaf24@9133 144 n, l_arr, k) )
djm@6458 145 {
djm@6458 146 ret = -EINVAL;
djm@6458 147 break;
djm@6458 148 }
djm@6458 149
djm@6458 150 n += j;
djm@6458 151 }
djm@6458 152
awilliam@9005 153 free_xenheap_page((void *) l_arr);
djm@6458 154
djm@6458 155 put_domain(d);
djm@6458 156 }
djm@6458 157 break;
awilliam@10009 158
djm@6458 159 case DOM0_GETMEMLIST:
djm@6458 160 {
awilliam@10570 161 unsigned long i;
djm@6458 162 struct domain *d = find_domain_by_id(op->u.getmemlist.domain);
djm@6458 163 unsigned long start_page = op->u.getmemlist.max_pfns >> 32;
djm@6458 164 unsigned long nr_pages = op->u.getmemlist.max_pfns & 0xffffffff;
kaf24@8750 165 unsigned long mfn;
djm@6458 166
awilliam@10663 167 if ( d == NULL ) {
awilliam@10663 168 ret = -EINVAL;
awilliam@10570 169 break;
awilliam@10663 170 }
awilliam@10570 171 for (i = 0 ; i < nr_pages ; i++) {
awilliam@10570 172 pte_t *pte;
djm@6799 173
awilliam@10570 174 pte = (pte_t *)lookup_noalloc_domain_pte(d,
awilliam@10570 175 (start_page + i) << PAGE_SHIFT);
awilliam@10570 176 if (pte && pte_present(*pte))
awilliam@10570 177 mfn = pte_pfn(*pte);
awilliam@10570 178 else
awilliam@10570 179 mfn = INVALID_MFN;
djm@7333 180
awilliam@10570 181 if ( copy_to_guest_offset(op->u.getmemlist.buffer, i, &mfn, 1) ) {
awilliam@10570 182 ret = -EFAULT;
awilliam@10570 183 break;
awilliam@10570 184 }
awilliam@10570 185 }
djm@6458 186
awilliam@10570 187 op->u.getmemlist.num_pfns = i;
awilliam@10570 188 if (copy_to_guest(u_dom0_op, op, 1))
awilliam@10570 189 ret = -EFAULT;
awilliam@10570 190
awilliam@10570 191 put_domain(d);
djm@6458 192 }
djm@6458 193 break;
djm@7924 194
djm@7924 195 case DOM0_PHYSINFO:
djm@7924 196 {
djm@7924 197 dom0_physinfo_t *pi = &op->u.physinfo;
djm@7924 198
awilliam@9494 199 pi->threads_per_core =
awilliam@9494 200 cpus_weight(cpu_sibling_map[0]);
awilliam@9494 201 pi->cores_per_socket =
awilliam@9494 202 cpus_weight(cpu_core_map[0]) / pi->threads_per_core;
djm@7924 203 pi->sockets_per_node =
awilliam@9494 204 num_online_cpus() / cpus_weight(cpu_core_map[0]);
djm@7924 205 pi->nr_nodes = 1;
awilliam@9773 206 pi->total_pages = total_pages;
djm@7924 207 pi->free_pages = avail_domheap_pages();
awilliam@9494 208 pi->cpu_khz = local_cpu_data->proc_freq / 1000;
djm@7924 209 memset(pi->hw_cap, 0, sizeof(pi->hw_cap));
djm@7924 210 //memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
djm@7924 211 ret = 0;
kaf24@9133 212 if ( copy_to_guest(u_dom0_op, op, 1) )
kaf24@8750 213 ret = -EFAULT;
djm@7924 214 }
djm@7924 215 break;
djm@7924 216
awilliam@10570 217 case DOM0_DOMAIN_SETUP:
awilliam@10570 218 {
awilliam@10570 219 dom0_domain_setup_t *ds = &op->u.domain_setup;
awilliam@10570 220 struct domain *d = find_domain_by_id(ds->domain);
awilliam@10570 221
awilliam@10570 222 if ( d == NULL) {
awilliam@10570 223 ret = -EINVAL;
awilliam@10570 224 break;
awilliam@10570 225 }
awilliam@10570 226
awilliam@10570 227 if (ds->flags & XEN_DOMAINSETUP_hvm_guest) {
awilliam@10570 228 if (!vmx_enabled) {
awilliam@10570 229 printk("No VMX hardware feature for vmx domain.\n");
awilliam@10570 230 ret = -EINVAL;
awilliam@10570 231 break;
awilliam@10570 232 }
awilliam@10570 233 d->arch.is_vti = 1;
awilliam@10570 234 vmx_setup_platform(d);
awilliam@10570 235 }
awilliam@10570 236 else {
awilliam@10570 237 build_physmap_table(d);
awilliam@10570 238 dom_fw_setup(d, ds->bp, ds->maxmem);
awilliam@10570 239 }
awilliam@10570 240 put_domain(d);
awilliam@10570 241 }
awilliam@10570 242 break;
awilliam@10570 243
djm@6458 244 default:
kaf24@8750 245 printf("arch_do_dom0_op: unrecognized dom0 op: %d!!!\n",op->cmd);
djm@6458 246 ret = -ENOSYS;
djm@6458 247
djm@6458 248 }
djm@6458 249
djm@6458 250 return ret;
djm@6458 251 }
kaf24@8750 252
awilliam@9759 253 #ifdef CONFIG_XEN_IA64_DOM0_VP
awilliam@9759 254 unsigned long
awilliam@9759 255 do_dom0vp_op(unsigned long cmd,
awilliam@9759 256 unsigned long arg0, unsigned long arg1, unsigned long arg2,
awilliam@9759 257 unsigned long arg3)
awilliam@9759 258 {
awilliam@9759 259 unsigned long ret = 0;
awilliam@9759 260 struct domain *d = current->domain;
awilliam@9759 261
awilliam@9759 262 switch (cmd) {
awilliam@9759 263 case IA64_DOM0VP_ioremap:
awilliam@9759 264 ret = assign_domain_mmio_page(d, arg0, arg1);
awilliam@9759 265 break;
awilliam@9759 266 case IA64_DOM0VP_phystomach:
awilliam@9759 267 ret = ____lookup_domain_mpa(d, arg0 << PAGE_SHIFT);
awilliam@9759 268 if (ret == INVALID_MFN) {
awilliam@9759 269 DPRINTK("%s:%d INVALID_MFN ret: 0x%lx\n", __func__, __LINE__, ret);
awilliam@9759 270 } else {
awilliam@9759 271 ret = (ret & _PFN_MASK) >> PAGE_SHIFT;//XXX pte_pfn()
awilliam@9759 272 }
awilliam@9759 273 break;
awilliam@9759 274 case IA64_DOM0VP_machtophys:
awilliam@10451 275 if (!mfn_valid(arg0)) {
awilliam@9759 276 ret = INVALID_M2P_ENTRY;
awilliam@9759 277 break;
awilliam@9759 278 }
awilliam@9759 279 ret = get_gpfn_from_mfn(arg0);
awilliam@9759 280 break;
awilliam@9759 281 case IA64_DOM0VP_zap_physmap:
awilliam@9759 282 ret = dom0vp_zap_physmap(d, arg0, (unsigned int)arg1);
awilliam@9759 283 break;
awilliam@9759 284 case IA64_DOM0VP_add_physmap:
awilliam@9759 285 ret = dom0vp_add_physmap(d, arg0, arg1, (unsigned int)arg2,
awilliam@9759 286 (domid_t)arg3);
awilliam@9759 287 break;
awilliam@9759 288 default:
awilliam@9759 289 ret = -1;
awilliam@9759 290 printf("unknown dom0_vp_op 0x%lx\n", cmd);
awilliam@9759 291 break;
awilliam@9759 292 }
awilliam@9759 293
awilliam@9759 294 return ret;
awilliam@9759 295 }
awilliam@9759 296 #endif
awilliam@9759 297
kaf24@8750 298 /*
kaf24@8750 299 * Local variables:
kaf24@8750 300 * mode: C
kaf24@8750 301 * c-set-style: "BSD"
kaf24@8750 302 * c-basic-offset: 4
kaf24@8750 303 * tab-width: 4
kaf24@8750 304 * indent-tabs-mode: nil
kaf24@8750 305 * End:
kaf24@8750 306 */