ia64/xen-unstable
changeset 1322:1983d16b31c5
bitkeeper revision 1.843.1.2 (408e8143LyGsYifYGyfzELLCq3v-RQ)
WIP
WIP
author | iap10@labyrinth.cl.cam.ac.uk |
---|---|
date | Tue Apr 27 15:50:27 2004 +0000 (2004-04-27) |
parents | 29c2aca35d1d |
children | d41f26deb150 |
files | tools/xc/lib/xc_linux_save.c tools/xc/lib/xc_private.c tools/xc/lib/xc_private.h xenolinux-2.4.25-sparse/arch/xen/drivers/dom0/core.c xenolinux-2.4.25-sparse/arch/xen/mm/ioremap.c xenolinux-2.4.25-sparse/include/asm-xen/proc_cmd.h |
line diff
1.1 --- a/tools/xc/lib/xc_linux_save.c Tue Apr 27 15:34:25 2004 +0000 1.2 +++ b/tools/xc/lib/xc_linux_save.c Tue Apr 27 15:50:27 2004 +0000 1.3 @@ -84,6 +84,9 @@ int xc_linux_save(int xc_handle, 1.4 unsigned long mfn; 1.5 unsigned int prev_pc, this_pc; 1.6 1.7 + /* state of the new MFN mapper */ 1.8 + mfn_mapper_t *mapper_handle1, *mapper_handle2; 1.9 + 1.10 /* Remember if we stopped the guest, so we can restart it on exit. */ 1.11 int we_stopped_it = 0; 1.12 1.13 @@ -102,18 +105,23 @@ int xc_linux_save(int xc_handle, 1.14 /* A temporary mapping, and a copy, of one frame of guest memory. */ 1.15 unsigned long *ppage, page[1024]; 1.16 1.17 - /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */ 1.18 - unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024]; 1.19 - /* A temporary mapping of one frame in the above list. */ 1.20 - unsigned long *pfn_to_mfn_frame; 1.21 + /* A copy of the pfn-to-mfn table frame list. */ 1.22 + unsigned long *pfn_to_mfn_frame_list; 1.23 + /* A live mapping of the pfn-to-mfn table frame list. */ 1.24 + unsigned long *live_pfn_to_mfn_frame_list; 1.25 1.26 - /* A table mapping each PFN to its current MFN. */ 1.27 + /* A table translating each PFN to its current MFN. */ 1.28 unsigned long *pfn_to_mfn_table = NULL; 1.29 - /* A table mapping each current MFN to its canonical PFN. */ 1.30 + /* Live mapping of the table mapping each PFN to its current MFN. */ 1.31 + unsigned long *live_pfn_to_mfn_table = NULL; 1.32 + /* A table translating each current MFN to its canonical PFN. */ 1.33 unsigned long *mfn_to_pfn_table = NULL; 1.34 1.35 + /* Live mapping of shared info structure */ 1.36 + unsigned long *live_shinfo; 1.37 + 1.38 /* A temporary mapping, and a copy, of the guest's suspend record. */ 1.39 - suspend_record_t *p_srec, srec; 1.40 + suspend_record_t *srec; 1.41 1.42 /* The name and descriptor of the file that we are writing to. */ 1.43 int fd; 1.44 @@ -178,8 +186,10 @@ int xc_linux_save(int xc_handle, 1.45 goto out; 1.46 } 1.47 1.48 - if ( (pm_handle = init_pfn_mapper()) < 0 ) 1.49 - goto out; 1.50 + 1.51 + /* Map the suspend-record MFN to pin it */ 1.52 + srec = mfn_mapper_map_single(xc_handle, PROT_READ, 1.53 + ctxt.cpu_ctxt.esi, sizeof(*srec)); 1.54 1.55 /* Is the suspend-record MFN actually valid for this domain? */ 1.56 if ( !check_pfn_ownership(xc_handle, ctxt.cpu_ctxt.esi, domid) ) 1.57 @@ -188,33 +198,65 @@ int xc_linux_save(int xc_handle, 1.58 goto out; 1.59 } 1.60 1.61 - /* If the suspend-record MFN is okay then grab a copy of it to @srec. */ 1.62 - p_srec = map_pfn_readonly(pm_handle, ctxt.cpu_ctxt.esi); 1.63 - memcpy(&srec, p_srec, sizeof(srec)); 1.64 - unmap_pfn(pm_handle, p_srec); 1.65 - 1.66 - if ( srec.nr_pfns > 1024*1024 ) 1.67 + /* cheesy sanity check */ 1.68 + if ( srec->nr_pfns > 1024*1024 ) 1.69 { 1.70 ERROR("Invalid state record -- pfn count out of range"); 1.71 goto out; 1.72 } 1.73 1.74 - if ( !check_pfn_ownership(xc_handle, srec.pfn_to_mfn_frame_list, domid) ) 1.75 + 1.76 + /* the pfn_to_mfn_frame_list fits in a single page */ 1.77 + live_pfn_to_mfn_frame_list = 1.78 + mfn_mapper_map_single(xc_handle, PROT_WRITE, 1.79 + srec->pfn_to_mfn_frame_list, 1.80 + PAGE_SIZE); 1.81 + 1.82 + if ( !check_pfn_ownership(xc_handle, 1.83 + srec->pfn_to_mfn_frame_list, domid) ) 1.84 { 1.85 - ERROR("Invalid pfn-to-mfn frame list pointer"); 1.86 - goto out; 1.87 + ERROR("Invalid pfn-to-mfn frame list pointer"); 1.88 + goto out; 1.89 } 1.90 1.91 - /* Grab a copy of the pfn-to-mfn table frame list. */ 1.92 - p_pfn_to_mfn_frame_list = map_pfn_readonly( 1.93 - pm_handle, srec.pfn_to_mfn_frame_list); 1.94 - memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE); 1.95 - unmap_pfn(pm_handle, p_pfn_to_mfn_frame_list); 1.96 + memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE ); 1.97 + 1.98 + if ( (mapper_handle1 = mfn_mapper_init(xc_handle, 1024*1024, PROT_READ )) 1.99 + == NULL ) 1.100 + goto out; 1.101 + 1.102 + for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ ) 1.103 + { 1.104 + /* Grab a copy of the pfn-to-mfn table frame list. 1.105 + This has the effect of preventing the page from being freed and 1.106 + given to another domain. (though the domain is stopped anyway...) */ 1.107 + mfn_mapper_queue_entry( mapper_handle1, i<<PAGE_SHIFT, 1.108 + pfn_to_mfn_frame_list[i], 1.109 + PAGE_SIZE ); 1.110 + } 1.111 + 1.112 + mfn_mapper_flush_queue(mapper_handle1); 1.113 + 1.114 + /* Now they're pined, check they're the right dom. We assume 1.115 + they're not going to change, otherwise the suspend is going to fail, 1.116 + with only itself to blame. */ 1.117 + 1.118 + for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ ) 1.119 + { 1.120 + if ( !check_pfn_ownership(xc_handle, 1.121 + pfn_to_mfn_frame_list[i], domid) ) 1.122 + { 1.123 + ERROR("Invalid pfn-to-mfn frame list pointer"); 1.124 + goto out; 1.125 + } 1.126 + } 1.127 + 1.128 + live_pfn_to_mfn_table = mfn_mapper_base( mapper_handle1 ); 1.129 1.130 /* We want zeroed memory so use calloc rather than malloc. */ 1.131 mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024); 1.132 - pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns); 1.133 - pfn_type = calloc(1, 4 * srec.nr_pfns); 1.134 + pfn_to_mfn_table = calloc(1, 4 * srec->nr_pfns); 1.135 + pfn_type = calloc(1, 4 * srec->nr_pfns); 1.136 1.137 if ( (mfn_to_pfn_table == NULL) || 1.138 (pfn_to_mfn_table == NULL) || 1.139 @@ -230,24 +272,10 @@ int xc_linux_save(int xc_handle, 1.140 * loop we have each MFN mapped at most once. Note that there may be MFNs 1.141 * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP. 1.142 */ 1.143 - pfn_to_mfn_frame = NULL; 1.144 - for ( i = 0; i < srec.nr_pfns; i++ ) 1.145 + 1.146 + for ( i = 0; i < srec->nr_pfns; i++ ) 1.147 { 1.148 - /* Each frameful of table frames must be checked & mapped on demand. */ 1.149 - if ( (i & 1023) == 0 ) 1.150 - { 1.151 - mfn = pfn_to_mfn_frame_list[i/1024]; 1.152 - if ( !check_pfn_ownership(xc_handle, mfn, domid) ) 1.153 - { 1.154 - ERROR("Invalid frame number if pfn-to-mfn frame list"); 1.155 - goto out; 1.156 - } 1.157 - if ( pfn_to_mfn_frame != NULL ) 1.158 - unmap_pfn(pm_handle, pfn_to_mfn_frame); 1.159 - pfn_to_mfn_frame = map_pfn_readonly(pm_handle, mfn); 1.160 - } 1.161 - 1.162 - mfn = pfn_to_mfn_frame[i & 1023]; 1.163 + mfn = live_pfn_to_mfn_table[i]; 1.164 1.165 if ( !check_pfn_ownership(xc_handle, mfn, domid) ) 1.166 { 1.167 @@ -256,14 +284,14 @@ int xc_linux_save(int xc_handle, 1.168 } 1.169 1.170 /* Did we map this MFN already? That would be invalid! */ 1.171 - if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 1.172 + if ( mfn_to_pfn_table[mfn] ) 1.173 { 1.174 ERROR("A machine frame appears twice in pseudophys space"); 1.175 goto out; 1.176 } 1.177 1.178 - pfn_to_mfn_table[i] = mfn; 1.179 mfn_to_pfn_table[mfn] = i; 1.180 + pfn_to_mfn_table[i] = live_pfn_to_mfn_table[i]; 1.181 1.182 /* Query page type by MFN, but store it by PFN. */ 1.183 if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == 1.184 @@ -307,63 +335,110 @@ int xc_linux_save(int xc_handle, 1.185 } 1.186 1.187 /* Start writing out the saved-domain record. */ 1.188 - ppage = map_pfn_readonly(pm_handle, shared_info_frame); 1.189 + live_shinfo = mfn_mapper_map_single(xc_handle, PROT_READ, 1.190 + shared_info_frame, PAGE_SIZE); 1.191 + 1.192 + /* Belts and braces safety check on the shared info record */ 1.193 + if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) ) 1.194 + { 1.195 + ERROR("Invalid shared_info_frame"); 1.196 + goto out; 1.197 + } 1.198 + 1.199 if ( !checked_write(gfd, "LinuxGuestRecord", 16) || 1.200 !checked_write(gfd, name, sizeof(name)) || 1.201 !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || 1.202 !checked_write(gfd, &ctxt, sizeof(ctxt)) || 1.203 - !checked_write(gfd, ppage, PAGE_SIZE) || 1.204 + !checked_write(gfd, live_shinfo, PAGE_SIZE) || 1.205 !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) || 1.206 !checked_write(gfd, pfn_type, 4 * srec.nr_pfns) ) 1.207 { 1.208 ERROR("Error when writing to state file"); 1.209 goto out; 1.210 } 1.211 - unmap_pfn(pm_handle, ppage); 1.212 + munmap(live_shinfo, PAGE_SIZE); 1.213 1.214 verbose_printf("Saving memory pages: 0%%"); 1.215 1.216 + if ( (mapper_handle2 = mfn_mapper_init(xc_handle, 1.217 + BATCH_SIZE*4096, PROT_READ )) 1.218 + == NULL ) 1.219 + goto out; 1.220 + 1.221 + region_base = mfn_mapper_base( mapper_handle2 ); 1.222 + 1.223 /* Now write out each data page, canonicalising page tables as we go... */ 1.224 prev_pc = 0; 1.225 - for ( i = 0; i < srec.nr_pfns; i++ ) 1.226 + for ( n = 0; n < srec.nr_pfns; ) 1.227 { 1.228 - this_pc = (i * 100) / srec.nr_pfns; 1.229 + this_pc = (n * 100) / srec.nr_pfns; 1.230 if ( (this_pc - prev_pc) >= 5 ) 1.231 { 1.232 verbose_printf("\b\b\b\b%3d%%", this_pc); 1.233 prev_pc = this_pc; 1.234 } 1.235 1.236 - mfn = pfn_to_mfn_table[i]; 1.237 + 1.238 + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) 1.239 + { 1.240 + /* queue up mappings for all of the pages in this batch */ 1.241 + 1.242 + mfn_mapper_queue_entry( mapper_handle2, j<<PAGE_SHIFT, 1.243 + pfn_to_mfn_frame_list[i], 1.244 + PAGE_SIZE ); 1.245 + } 1.246 + mfn_mapper_flush_queue(mapper_handle2); 1.247 + 1.248 + typer_handle = get_type_init( xc_handle, BATCH_SIZE ) 1.249 1.250 - ppage = map_pfn_readonly(pm_handle, mfn); 1.251 - memcpy(page, ppage, PAGE_SIZE); 1.252 - unmap_pfn(pm_handle, ppage); 1.253 + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) 1.254 + { 1.255 + /* queue up ownership and type checks for all pages in batch */ 1.256 + 1.257 + get_type_queue_entry( typer_handle, domain, 1.258 + pfn_to_mfn_frame_list[i] ); 1.259 + } 1.260 + 1.261 + 1.262 + region_type = get_type; 1.263 + 1.264 + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) 1.265 + { 1.266 + /* write out pages in batch */ 1.267 + 1.268 + mfn = pfn_to_mfn_table[i]; 1.269 1.270 - if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) ) 1.271 - { 1.272 - for ( j = 0; 1.273 - j < ((pfn_type[i] == L2TAB) ? 1.274 - (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 1.275 - j++ ) 1.276 - { 1.277 - if ( !(page[j] & _PAGE_PRESENT) ) continue; 1.278 - mfn = page[j] >> PAGE_SHIFT; 1.279 - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 1.280 - { 1.281 - ERROR("Frame number in pagetable page is invalid"); 1.282 - goto out; 1.283 - } 1.284 - page[j] &= PAGE_SIZE - 1; 1.285 - page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT; 1.286 - } 1.287 - } 1.288 + ppage = map_pfn_readonly(pm_handle, mfn); 1.289 + memcpy(page, ppage, PAGE_SIZE); 1.290 + unmap_pfn(pm_handle, ppage); 1.291 1.292 - if ( !checked_write(gfd, page, PAGE_SIZE) ) 1.293 - { 1.294 - ERROR("Error when writing to state file"); 1.295 - goto out; 1.296 - } 1.297 + if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) ) 1.298 + { 1.299 + for ( j = 0; 1.300 + j < ((pfn_type[i] == L2TAB) ? 1.301 + (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 1.302 + j++ ) 1.303 + { 1.304 + if ( !(page[j] & _PAGE_PRESENT) ) continue; 1.305 + mfn = page[j] >> PAGE_SHIFT; 1.306 + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) 1.307 + { 1.308 + ERROR("Frame number in pagetable page is invalid"); 1.309 + goto out; 1.310 + } 1.311 + page[j] &= PAGE_SIZE - 1; 1.312 + page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT; 1.313 + } 1.314 + } 1.315 + 1.316 + if ( !checked_write(gfd, page, PAGE_SIZE) ) 1.317 + { 1.318 + ERROR("Error when writing to state file"); 1.319 + goto out; 1.320 + } 1.321 + } 1.322 + 1.323 + n+=j; /* i is the master loop counter */ 1.324 } 1.325 1.326 verbose_printf("\b\b\b\b100%%\nMemory saved.\n"); 1.327 @@ -371,7 +446,7 @@ int xc_linux_save(int xc_handle, 1.328 /* Success! */ 1.329 rc = 0; 1.330 1.331 - out: 1.332 +out: 1.333 /* Restart the domain if we had to stop it to save its state. */ 1.334 if ( we_stopped_it ) 1.335 { 1.336 @@ -397,4 +472,6 @@ int xc_linux_save(int xc_handle, 1.337 unlink(state_file); 1.338 1.339 return !!rc; 1.340 + 1.341 + 1.342 }
2.1 --- a/tools/xc/lib/xc_private.c Tue Apr 27 15:34:25 2004 +0000 2.2 +++ b/tools/xc/lib/xc_private.c Tue Apr 27 15:50:27 2004 +0000 2.3 @@ -39,6 +39,112 @@ void unmap_pfn(int pm_handle, void *vadd 2.4 (void)munmap(vaddr, PAGE_SIZE); 2.5 } 2.6 2.7 +/*******************/ 2.8 + 2.9 +void * mfn_mapper_map_single(int xc_handle, int prot, 2.10 + unsigned long mfn, int size) 2.11 +{ 2.12 + privcmd_mmap_t ioctlx; 2.13 + privcmd_mmap_entry_t entry; 2.14 + void *addr; 2.15 + addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 ); 2.16 + if (addr) 2.17 + { 2.18 + ioctlx.num=1; 2.19 + ioctlx.entry=&entry; 2.20 + entry.va=(unsigned long) addr; 2.21 + entry.mfn=mfn; 2.22 + entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT; 2.23 + if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 ) 2.24 + return 0; 2.25 + } 2.26 + return addr; 2.27 +} 2.28 + 2.29 +mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot) 2.30 +{ 2.31 + mfn_mapper_t * t; 2.32 + t = calloc( 1, sizeof(mfn_mapper_t)+ 2.33 + mfn_mapper_queue_size*sizeof(privcmd_mmap_entry_t) ); 2.34 + if (!t) return NULL; 2.35 + t->xc_handle = xc_handle; 2.36 + t->size = size; 2.37 + t->prot = prot; 2.38 + t->max_queue_size = mfn_mapper_queue_size; 2.39 + t->addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 ); 2.40 + if (!t->addr) 2.41 + { 2.42 + free(t); 2.43 + return NULL; 2.44 + } 2.45 + t->ioctl.num = 0; 2.46 + t->ioctl.entry = (privcmd_mmap_entry_t *) &t[1]; 2.47 + return t; 2.48 +} 2.49 + 2.50 +void * mfn_mapper_base(mfn_mapper_t *t) 2.51 +{ 2.52 + return t->addr; 2.53 +} 2.54 + 2.55 +void mfn_mapper_close(mfn_mapper_t *t) 2.56 +{ 2.57 + if(t->addr) munmap( t->addr, t->size ); 2.58 + free(t); 2.59 +} 2.60 + 2.61 +int mfn_mapper_flush_queue(mfn_mapper_t *t) 2.62 +{ 2.63 + int rc; 2.64 + 2.65 + rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl ); 2.66 + if (rc<0) return rc; 2.67 + t->ioctl.num = 0; 2.68 + return 0; 2.69 +} 2.70 + 2.71 +void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 2.72 + unsigned long mfn, int size) 2.73 +{ 2.74 + privcmd_mmap_entry_t *entry, *prev; 2.75 + int pages; 2.76 + 2.77 + offset &= PAGE_MASK; 2.78 + pages =(size+PAGE_SIZE-1)>>PAGE_SHIFT; 2.79 + entry = &t->ioctl.entry[t->ioctl.num]; 2.80 + 2.81 + if ( t->ioctl.num > 0 ) 2.82 + { 2.83 + prev = &t->ioctl.entry[t->ioctl.num-1]; 2.84 + 2.85 + if ( (prev->va+(prev->npages*PAGE_SIZE)) == (t->addr+offset) && 2.86 + (prev->mfn+prev->npages) == mfn ) 2.87 + { 2.88 + prev->npages += pages; 2.89 +printf("merge\n"); 2.90 + return t->addr+offset; 2.91 + } 2.92 + } 2.93 + 2.94 + entry->va = t->addr+offset; 2.95 + entry->mfn = mfn; 2.96 + entry->npages = pages; 2.97 + t->ioctl.num++; 2.98 + 2.99 + if(t->ioctl.num == t->max_queue_size) 2.100 + { 2.101 + if ( mfn_mapper_flush_queue(t) ) 2.102 + return 0; 2.103 + } 2.104 + 2.105 + return t->addr+offset; 2.106 +} 2.107 + 2.108 + 2.109 + 2.110 + 2.111 +/*******************/ 2.112 + 2.113 #define FIRST_MMU_UPDATE 2 2.114 2.115 static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
3.1 --- a/tools/xc/lib/xc_private.h Tue Apr 27 15:34:25 2004 +0000 3.2 +++ b/tools/xc/lib/xc_private.h Tue Apr 27 15:50:27 2004 +0000 3.3 @@ -171,4 +171,49 @@ int add_mmu_update(int xc_handle, mmu_t 3.4 unsigned long ptr, unsigned long val); 3.5 int finish_mmu_updates(int xc_handle, mmu_t *mmu); 3.6 3.7 + 3.8 +/* 3.9 + * ioctl-based mfn mapping interface 3.10 + */ 3.11 + 3.12 +/* 3.13 +typedef struct privcmd_mmap_entry { 3.14 + unsigned long va; 3.15 + unsigned long mfn; 3.16 + unsigned long npages; 3.17 +} privcmd_mmap_entry_t; 3.18 + 3.19 +typedef struct privcmd_mmap { 3.20 + int num; 3.21 + privcmd_mmap_entry_t *entry; 3.22 +} privcmd_mmap_t; 3.23 +*/ 3.24 + 3.25 +#define mfn_mapper_queue_size 128 3.26 + 3.27 +typedef struct mfn_mapper { 3.28 + int xc_handle; 3.29 + int size; 3.30 + int prot; 3.31 + int max_queue_size; 3.32 + void * addr; 3.33 + privcmd_mmap_t ioctl; 3.34 + 3.35 +} mfn_mapper_t; 3.36 + 3.37 +void * mfn_mapper_map_single(int xc_handle, int prot, 3.38 + unsigned long mfn, int size); 3.39 + 3.40 +mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot); 3.41 + 3.42 +void * mfn_mapper_base(mfn_mapper_t *t); 3.43 + 3.44 +void mfn_mapper_close(mfn_mapper_t *t); 3.45 + 3.46 +int mfn_mapper_flush_queue(mfn_mapper_t *t); 3.47 + 3.48 +void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 3.49 + unsigned long mfn, int size ); 3.50 + 3.51 + 3.52 #endif /* __XC_PRIVATE_H__ */
4.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/dom0/core.c Tue Apr 27 15:34:25 2004 +0000 4.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/dom0/core.c Tue Apr 27 15:50:27 2004 +0000 4.3 @@ -62,16 +62,70 @@ static int privcmd_ioctl(struct inode *i 4.4 } 4.5 break; 4.6 4.7 + case IOCTL_PRIVCMD_MMAP: 4.8 + { 4.9 +#define PRIVCMD_MMAP_SZ 32 4.10 + privcmd_mmap_t mmapcmd; 4.11 + privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p; 4.12 + int i; 4.13 + 4.14 + if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) ) 4.15 + return -EFAULT; 4.16 + 4.17 + p = mmapcmd.entry; 4.18 + 4.19 + for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ) 4.20 + { 4.21 + int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)? 4.22 + PRIVCMD_MMAP_SZ:(mmapcmd.num-i); 4.23 + if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) ) 4.24 + return -EFAULT; 4.25 + 4.26 + for (j=0;j<n;j++) 4.27 + { 4.28 + struct vm_area_struct *vma = 4.29 + find_vma( current->mm, msg[j].va ); 4.30 + 4.31 + if (!vma) 4.32 + return -EINVAL; 4.33 + 4.34 + if (msg[j].va > PAGE_OFFSET) 4.35 + return -EINVAL; 4.36 + 4.37 + if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end) 4.38 + return -EINVAL; 4.39 + 4.40 + if (direct_remap_area_pages(vma->vm_mm, 4.41 + msg[j].va&PAGE_MASK, 4.42 + msg[j].mfn<<PAGE_SHIFT, 4.43 + msg[j].npages<<PAGE_SHIFT, 4.44 + vma->vm_page_prot)) 4.45 + return -EINVAL; 4.46 + } 4.47 + } 4.48 + ret = 0; 4.49 + } 4.50 + break; 4.51 + 4.52 default: 4.53 ret = -EINVAL; 4.54 break; 4.55 - } 4.56 + } 4.57 return ret; 4.58 } 4.59 4.60 +static int privcmd_mmap(struct file * file, struct vm_area_struct * vma) 4.61 +{ 4.62 +printk(KERN_ALERT"privcmd_mmap\n"); 4.63 + /* DONTCOPY is essential for Xen as copy_page_range is broken. */ 4.64 + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY; 4.65 + 4.66 + return 0; 4.67 +} 4.68 4.69 static struct file_operations privcmd_file_ops = { 4.70 - ioctl : privcmd_ioctl 4.71 + ioctl : privcmd_ioctl, 4.72 + mmap: privcmd_mmap 4.73 }; 4.74 4.75
5.1 --- a/xenolinux-2.4.25-sparse/arch/xen/mm/ioremap.c Tue Apr 27 15:34:25 2004 +0000 5.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/mm/ioremap.c Tue Apr 27 15:50:27 2004 +0000 5.3 @@ -42,10 +42,12 @@ static inline void direct_remap_area_pte 5.4 if (address >= end) 5.5 BUG(); 5.6 do { 5.7 +#if 0 /* thanks to new ioctl mmaping interface this is no longer a bug */ 5.8 if (!pte_none(*pte)) { 5.9 printk("direct_remap_area_pte: page already exists\n"); 5.10 BUG(); 5.11 } 5.12 +#endif 5.13 set_pte(pte, pte_mkio(direct_mk_pte_phys(machine_addr, prot))); 5.14 address += PAGE_SIZE; 5.15 machine_addr += PAGE_SIZE; 5.16 @@ -91,6 +93,9 @@ int direct_remap_area_pages(struct mm_st 5.17 pgd_t * dir; 5.18 unsigned long end = address + size; 5.19 5.20 +printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n", 5.21 + address, machine_addr, size); 5.22 + 5.23 machine_addr -= address; 5.24 dir = pgd_offset(mm, address); 5.25 flush_cache_all();
6.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/proc_cmd.h Tue Apr 27 15:34:25 2004 +0000 6.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/proc_cmd.h Tue Apr 27 15:50:27 2004 +0000 6.3 @@ -13,6 +13,17 @@ typedef struct privcmd_hypercall 6.4 unsigned long arg[5]; 6.5 } privcmd_hypercall_t; 6.6 6.7 +typedef struct privcmd_mmap_entry { 6.8 + unsigned long va; 6.9 + unsigned long mfn; 6.10 + unsigned long npages; 6.11 +} privcmd_mmap_entry_t; 6.12 + 6.13 +typedef struct privcmd_mmap { 6.14 + int num; 6.15 + privcmd_mmap_entry_t *entry; 6.16 +} privcmd_mmap_t; 6.17 + 6.18 typedef struct privcmd_blkmsg 6.19 { 6.20 unsigned long op; 6.21 @@ -24,5 +35,7 @@ typedef struct privcmd_blkmsg 6.22 _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t)) 6.23 #define IOCTL_PRIVCMD_BLKMSG \ 6.24 _IOC(_IOC_NONE, 'P', 1, sizeof(privcmd_blkmsg_t)) 6.25 +#define IOCTL_PRIVCMD_MMAP \ 6.26 + _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t)) 6.27 6.28 #endif /* __PROC_CMD_H__ */