Changeset 313 for trunk/kernel/mm
- Timestamp:
- Aug 2, 2017, 3:24:57 PM (7 years ago)
- Location:
- trunk/kernel/mm
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/mapper.c
r296 r313 299 299 } // end mapper_release_page() 300 300 301 //////////////////////////////////////////////// 302 error_t mapper_move_buffer( mapper_t * mapper, 303 bool_t to_buffer, 304 bool_t is_user, 305 uint32_t file_offset, 306 void * buffer, 307 uint32_t size ) 301 /////////////////////////////////////////////////// 302 error_t mapper_move_user( mapper_t * mapper, 303 bool_t to_buffer, 304 uint32_t file_offset, 305 void * buffer, 306 uint32_t size ) 308 307 { 309 308 uint32_t page_offset; // first byte to move to/from a mapper page … … 335 334 else page_offset = 0; 336 335 337 // compute page_count336 // compute number of bytes in page 338 337 if ( first == last ) page_count = size; 339 338 else if ( index == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset; … … 359 358 360 359 // move fragment 361 if( to_buffer ) 362 { 363 if( is_user ) hal_copy_to_uspace( buf_ptr , map_ptr , page_count ); 364 else memcpy( buf_ptr , map_ptr , page_count ); 360 if( to_buffer ) 361 { 362 hal_copy_to_uspace( buf_ptr , map_ptr , page_count ); 365 363 } 366 364 else 367 365 { 368 366 page_do_dirty( page ); 369 if( is_user ) hal_copy_from_uspace( map_ptr , buf_ptr , page_count ); 370 else memcpy( map_ptr , buf_ptr , page_count ); 367 hal_copy_from_uspace( map_ptr , buf_ptr , page_count ); 371 368 } 372 369 … … 379 376 return 0; 380 377 381 } // end mapper_move_buffer() 382 378 } // end mapper_move_user() 379 380 //////////////////////////////////////////////// 381 error_t mapper_move_kernel( mapper_t * mapper, 382 bool_t to_buffer, 383 uint32_t file_offset, 384 xptr_t buffer_xp, 385 uint32_t size ) 386 { 387 uint32_t page_offset; // first byte to move to/from a mapper page 388 uint32_t page_count; // number of bytes to move to/from a mapper page 389 uint32_t index; // current mapper page index 390 uint32_t done; // number of moved bytes 391 page_t * page; // current mapper page descriptor 392 393 uint8_t * src_ptr; // source buffer local pointer 394 cxy_t src_cxy; // source cluster 395 uint8_t * dst_ptr; // destination buffer local pointer 396 cxy_t dst_cxy; // destination cluster 397 398 mapper_dmsg("\n[INFO] %s : enters / to_buf = %d / buffer = %l / size = %x / cycle %d\n", 399 __FUNCTION__ , to_buffer , buffer_xp , size , hal_time_stamp() ); 400 401 // compute offsets of first and last bytes in file 402 uint32_t min_byte = file_offset; 403 uint32_t max_byte = file_offset + size -1; 404 405 // compute indexes for first and last pages in mapper 406 uint32_t first = min_byte >> CONFIG_PPM_PAGE_SHIFT; 407 uint32_t last = max_byte >> CONFIG_PPM_PAGE_SHIFT; 408 409 // get buffer cluster and local pointer 410 cxy_t buffer_cxy = GET_CXY( buffer_xp ); 411 uint8_t * buffer_ptr = (uint8_t *)GET_PTR( buffer_xp ); 412 413 // compute source and destination clusters 414 if( to_buffer ) 415 { 416 dst_cxy = buffer_cxy; 417 src_cxy = local_cxy; 418 } 419 else 420 { 421 src_cxy = buffer_cxy; 422 dst_cxy = local_cxy; 423 } 424 425 done = 0; 426 427 // loop on pages in mapper 428 for( index = first ; index <= last ; index++ ) 429 { 430 // compute page_offset 431 if( index == first ) page_offset = min_byte & CONFIG_PPM_PAGE_MASK; 432 else page_offset = 0; 433 434 // compute number of bytes to move in page 435 if ( first == last ) page_count = size; 436 else if ( index == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset; 437 else if ( index == last ) page_count = (max_byte & CONFIG_PPM_PAGE_MASK) + 1; 438 else page_count = CONFIG_PPM_PAGE_SIZE; 439 440 mapper_dmsg("\n[INFO] %s : page_index = %d / offset = %d / count = %d\n", 441 __FUNCTION__ , index , page_offset , page_count ); 442 443 // get page descriptor 444 page = mapper_get_page( mapper , index ); 445 446 if ( page == NULL ) return EINVAL; 447 448 // compute source and destination pointers 449 if( to_buffer ) 450 { 451 dst_ptr = buf_ptr + done; 452 src_ptr = (uint8_t *)ppm_page2vaddr( page ) + page_offset; 453 } 454 else 455 { 456 src_ptr = buf_ptr + done; 457 dst_ptr = (uint8_t *)ppm_page2vaddr( page ) + page_offset; 458 459 page_do_dirty( page ); 460 } 461 462 mapper_dmsg("\n[INFO] %s : index = %d / buf_ptr = %x / map_ptr = %x\n", 463 __FUNCTION__ , index , buf_ptr , map_ptr ); 464 465 // move fragment 466 hal_remote_memcpy( XPTR( dst_cxy , dst_ptr ), XPTR( src_cxy , src_ptr ), page_count ); 467 468 done += page_count; 469 } 470 471 mapper_dmsg("\n[INFO] %s : exit for buffer %l / size = %x / cycle %d\n", 472 __FUNCTION__ , buffer_xp , size , hal_time_stamp() ); 473 474 return 0; 475 476 } // end mapper_move_kernel_buffer() 477 -
trunk/kernel/mm/mapper.h
r265 r313 57 57 * - the mapper_move_user() function is used to move data to or from an user buffer. 58 58 * This user space buffer can be physically distributed in several clusters. 59 * - the mapper_move_kernel() function is used to move data to or from a remote kernel 60 * buffer, that can be physically located in any cluster. 59 61 * - In the present implementation the cache size for a given file increases on demand, 60 62 * and the allocated memory is only released when the mapper/inode is destroyed. … … 117 119 118 120 /******************************************************************************************* 119 * This function move data between a mapper and a n user or kernelbuffer.121 * This function move data between a mapper and a - possibly distributed - user buffer. 120 122 * It must be called by a thread running in the cluster containing the mapper. 121 * - A kernel buffer must be entirely contained in the same cluster as the mapper. 122 * - An user buffer can be physically distributed in several clusters. 123 * In both cases, the data transfer is split in "fragments": one fragment contains 123 * It is called by the vfs_user_move() function to implement sys_read() and sys_write(). 124 * If required, the data transfer is split in "fragments", where one fragment contains 124 125 * contiguous bytes in the same mapper page. 125 * - It uses "hal_uspace" accesses to move a fragment to/from the user buffer. 126 * - It uses a simple memcpy" access to move a fragment to/from a kernel buffer. 126 * It uses "hal_uspace" accesses to move a fragment to/from the user buffer. 127 127 * In case of write, the dirty bit is set for all pages written in the mapper. 128 128 * The offset in the file descriptor is not modified by this function. … … 132 132 * @ is_user : user space buffer if true / kernel local buffer if false. 133 133 * @ file_offset : first byte to move in file. 134 * @ buffer : pointer on buffer (local kernel buffer or user spaceaddress in user space.134 * @ buffer : user space pointer on user buffer. 135 135 * @ size : number of bytes to move. 136 136 * returns O if success / returns EINVAL if error. 137 137 ******************************************************************************************/ 138 error_t mapper_move_buffer( mapper_t * mapper, 138 error_t mapper_move_user( mapper_t * mapper, 139 bool_t to_buffer, 140 bool_t is_user, 141 uint32_t file_offset, 142 void * buffer, 143 uint32_t size ); 144 145 /******************************************************************************************* 146 * This function move data between a mapper and a remote kernel buffer. 147 * It must be called by a thread running in the cluster containing the mapper. 148 * If required, the data transfer is split in "fragments", where one fragment contains 149 * contiguous bytes in the same mapper page. 150 * It uses a "remote_memcpy" to move a fragment to/from the kernel buffer. 151 * In case of write, the dirty bit is set for all pages written in the mapper. 152 * The offset in the file descriptor is not modified by this function. 153 ******************************************************************************************* 154 * @ mapper : local pointer on mapper. 155 * @ to_buffer : mapper -> buffer if true / buffer -> mapper if false. 156 * @ file_offset : first byte to move in file. 157 * @ buffer_xp : extended pointer on kernel buffer. 158 * @ size : number of bytes to move. 159 * returns O if success / returns EINVAL if error. 160 ******************************************************************************************/ 161 error_t mapper_move_kernel( mapper_t * mapper, 139 162 bool_t to_buffer, 140 bool_t is_user,141 163 uint32_t file_offset, 142 void * buffer,164 xptr_t buffer_xp, 143 165 uint32_t size ); 166 144 167 145 168 /******************************************************************************************* -
trunk/kernel/mm/ppm.c
r177 r313 61 61 } 62 62 63 //////////////////////////////////////////64 inline ppn_t ppm_page2ppn( page_t * page )65 {66 ppm_t * ppm = &LOCAL_CLUSTER->ppm;67 return (ppn_t)( page - ppm->pages_tbl );68 }69 70 /////////////////////////////////////////71 inline page_t * ppm_ppn2page( ppn_t ppn )72 {73 ppm_t * ppm = &LOCAL_CLUSTER->ppm;74 return &ppm->pages_tbl[ppn];75 }76 77 ///////////////////////////////////////78 inline void * ppm_ppn2vaddr( ppn_t ppn )79 {80 ppm_t * ppm = &LOCAL_CLUSTER->ppm;81 return ppm->vaddr_base + (ppn << CONFIG_PPM_PAGE_SHIFT);82 }83 84 //////////////////////////////////////////85 inline ppn_t ppm_vaddr2ppn( void * vaddr )86 {87 ppm_t * ppm = &LOCAL_CLUSTER->ppm;88 return ( (ppm->vaddr_base - vaddr) >> CONFIG_PPM_PAGE_SHIFT );89 }90 91 92 63 /////////////////////////////////////////// 93 64 void ppm_free_pages_nolock( page_t * page ) -
trunk/kernel/mm/ppm.h
r160 r313 123 123 124 124 /***************************************************************************************** 125 * Get the PPN from the page descriptor pointer.126 *****************************************************************************************127 * @ page : pointer to page descriptor128 * @ returns physical page number129 ****************************************************************************************/130 inline ppn_t ppm_page2ppn( page_t * page );131 132 /*****************************************************************************************133 * Get the page descriptor pointer from the PPN.134 *****************************************************************************************135 * @ ppn : physical page number136 * @ returns pointer on page descriptor137 ****************************************************************************************/138 inline page_t * ppm_ppn2page( ppn_t ppn );139 140 /*****************************************************************************************141 * Get the page virtual address from the PPN.142 *****************************************************************************************143 * @ ppn : physical page number144 * @ returns page virtual address.145 ****************************************************************************************/146 inline void* ppm_ppn2vaddr( ppn_t ppn );147 148 /*****************************************************************************************149 * Get the PPN from the page virtual address.150 *****************************************************************************************151 * @ vaddr : page virtual address152 * @ returns physical page number.153 ****************************************************************************************/154 inline ppn_t ppm_vaddr2ppn( void * base );155 156 /*****************************************************************************************157 125 * This function prints the PPM allocator status. 158 126 ***************************************************************************************** -
trunk/kernel/mm/vmm.c
r286 r313 741 741 } 742 742 743 //////////////////////////////////////// 744 error_t vmm_get_one_ppn( vseg_t * vseg, 745 vpn_t vpn, 746 ppn_t * ppn ) 747 { 748 error_t error; 749 cxy_t page_cxy; // physical page cluster 750 page_t * page_ptr; // local pointer on physical page descriptor 751 752 uint32_t type = vseg->type; 753 xptr_t mapper_xp = vseg->mapper_xp; 754 755 // get mapper cluster and local pointer 756 cxy_t mapper_cxy = GET_CXY( mapper_xp ); 757 mapper_t * mapper_ptr = (mapper_t *)GET_PTR( mapper_xp ); 758 759 // FILE type : simply get the physical page from the file mapper 760 if( type == VSEG_TYPE_FILE ) 761 { 762 // compute index in file mapper 763 uint32_t index = vpn - vseg->vpn_base; 764 765 // get page descriptor from mapper 766 if( mapper_cxy == local_cxy ) // mapper is local 767 { 768 page_ptr = mapper_get_page( mapper_ptr , index ); 769 } 770 else // mapper is remote 771 { 772 rpc_mapper_get_page_client( mapper_cxy , mapper_ptr , index , &page_ptr ); 773 } 774 775 if ( page_ptr == NULL ) return EINVAL; 776 777 page_cxy = mapper_cxy; 778 } 779 780 // all other types : allocate a physical page from target cluster, 781 else 782 { 783 // get target cluster for physical page 784 if( flags & VSEG_DISTRIB ) // depends on VPN LSB 785 { 786 uint32_t x_width = LOCAL_CLUSTER->x_width; 787 uint32_t y_width = LOCAL_CLUSTER->y_width; 788 page_cxy = vpn & ((1<<(x_width + y_width)) - 1); 789 } 790 else // defined in vseg descriptor 791 { 792 page_cxy = vseg->cxy; 793 } 794 795 // allocate a physical page in target cluster 796 kmem_req_t req; 797 if( page_cxy == local_cxy ) // target cluster is the local cluster 798 { 799 req.type = KMEM_PAGE; 800 req.size = 0; 801 req.flags = AF_NONE; 802 page_ptr = (page_t *)kmem_alloc( &req ); 803 } 804 else // target cluster is not the local cluster 805 { 806 rpc_pmem_get_pages_client( page_cxy , 0 , &page_ptr ); 807 } 808 809 if( page_ptr == NULL ) return ENOMEM; 810 811 // initialise page from .elf file mapper for DATA and CODE types 812 if( (type == VSEG_TYPE_CODE) || (type == VSEG_TYPE_DATA) ) 813 { 814 // compute missing page index in vseg 815 vpn_t page_index = vpn - vseg->vpn_base; 816 817 // compute missing page offset in .elf file 818 intptr_t page_offset = vseg->file_offset + (page_index << PPM_PAGE_SHIFT); 819 820 // compute both local and extended pointer on page first byte 821 // WARNING : the pages_offset must have the same value in all clusters !!! 822 // to use this ppm_page2vaddr() function for a remote cluster 823 uint8_t * base_ptr = (uint8_t *)ppm_page2vaddr( page_ptr ); 824 xptr_t base_xp = XPTR( page_cxy , base_ptr ); 825 826 // file_size can be smaller than vseg_size for BSS 827 file_size = vseg->file_size; 828 829 if( file_size < page_offset ) // page fully in BSS 830 { 831 if( page_cxy == local_cxy ) 832 { 833 memset( base_ptr , 0 , PPM_PAGE_SIZE ); 834 } 835 else 836 { 837 hal_remote_memset( base_xp , 0 , PPM_PAGE_SIZE ); 838 } 839 } 840 else if( file size >= (page_offset + PPM_PAGE_SIZE) ) // page fully in mapper 841 842 if( mapper_cxy == local_cxy ) 843 { 844 error = mapper_move_kernel( mapper_ptr, 845 true, // to_buffer 846 page_offset, 847 base_xp, 848 PPM_PAGE_SIZE ); 849 } 850 else 851 { 852 rpc_mapper_move_buffer_client( mapper_cxy, 853 mapper_ptr, 854 true, // to buffer 855 false, // kernel buffer 856 page_offset, 857 (uint64_t)base_xp, 858 PPM_PAGE_SIZE, 859 &error ); 860 } 861 if( error ) return EINVAL; 862 } 863 else // in mapper : from page_offset -> (file_size - page_offset) 864 // in BSS : from file_size -> (page_offset + page_size) 865 { 866 // initialize mapper part 867 if( mapper_cxy == local_cxy ) // mapper is local 868 { 869 error = mapper_move_kernel( mapper_ptr, 870 true, // to_buffer 871 page_offset, 872 base_xp, 873 file_size - page_offset ); 874 } 875 else // mapper is remote 876 { 877 rpc_mapper_move_buffer_client( mapper_cxy, 878 mapper_ptr, 879 true, 880 false, // kernel buffer 881 page_offset, 882 (uint64_t)base_xp, 883 file_size - page_offset, 884 &error ); 885 } 886 if( error ) return EINVAL; 887 888 // initialize BSS part 889 if( page_cxy == local_cxy ) 890 { 891 memset( base_ptr + file_size - page_offset , 0 , 892 page_offset + PPM_PAGE_SIZE - file_size ); 893 } 894 else 895 { 896 hal_remote_memset( base_xp + file_size - page_offset , 0 , 897 page_offset + PPM_PAGE_SIZE - file_size ); 898 } 899 } 900 } // end initialisation for CODE or DATA types 901 } 902 903 // return ppn 904 *ppn = hal_page2ppn( XPTR( page_cxy , page_ptr ) ); 905 return 0; 906 907 } // end vmm_get_one_ppn() 908 743 909 ///////////////////////////////////////// 744 910 error_t vmm_get_pte( process_t * process, … … 748 914 { 749 915 vseg_t * vseg; // pointer on vseg containing VPN 750 ppn_t ppn; // PPN from GPT entry916 ppn_t ppn; // physical page number 751 917 uint32_t attr; // attributes from GPT entry 752 918 error_t error; … … 762 928 hal_gpt_get_pte( &vmm->gpt , vpn , &attr , &ppn ); 763 929 764 // if PTE unmapped => allocate one small physical page to map it 930 // if PTE is unmapped 931 // 1) get VSEG containing the missing VPN 932 // 2) get & initialize physical page (depending on vseg type), 933 // 3) register the PTE in reference GPT 765 934 if( (attr & GPT_MAPPED) == 0 ) 766 935 { 767 // get vseg pointer936 // 1. get vseg pointer 768 937 vseg = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT ); 769 938 … … 775 944 } 776 945 777 // select the target cluster for physical mapping 778 uint32_t target_cxy; 779 if( vseg->flags & VSEG_DISTRIB ) // depends on VPN LSB 780 { 781 uint32_t x_width = LOCAL_CLUSTER->x_width; 782 uint32_t y_width = LOCAL_CLUSTER->y_width; 783 target_cxy = vpn & ((1<<(x_width + y_width)) - 1); 784 } 785 else // defined in vseg descriptor 786 { 787 target_cxy = vseg->cxy; 788 } 789 790 // allocate memory for page fault 791 kmem_req_t req; 792 page_t * page; 793 if( target_cxy == local_cxy ) // target cluster is the local cluster 794 { 795 req.type = KMEM_PAGE; 796 req.size = 0; 797 req.flags = AF_NONE; 798 page = (page_t *)kmem_alloc( &req ); 799 800 error = ( page == NULL ) ? 1 : 0; 801 ppn = ppm_page2ppn( page ); 802 } 803 else // target cluster is not the local cluster 804 { 805 rpc_pmem_get_pages_client( target_cxy , 0 , &error , &ppn ); 806 } 946 // 2. get physical page number, depending on vseg type 947 error = vmm_get_one_ppn( vseg , vpn , &ppn ); 807 948 808 949 if( error ) … … 810 951 printk("\n[ERROR] in %s : cannot allocate memory / process = %x / vpn = %x\n", 811 952 __FUNCTION__ , process->pid , vpn ); 812 return ENOMEM;953 return error; 813 954 } 814 955 815 // define GPT attributes from vseg flags956 // 3. define attributes from vseg flags and register in GPT 816 957 attr = GPT_MAPPED | GPT_SMALL; 817 958 if( vseg->flags & VSEG_USER ) attr |= GPT_USER; … … 820 961 if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE; 821 962 822 // set the missing PTE in local VMM823 963 error = hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr ); 964 824 965 if( error ) 825 966 { … … 828 969 return ENOMEM; 829 970 } 830 } 971 } // end new PTE 831 972 832 973 *ret_ppn = ppn; 833 974 *ret_attr = attr; 834 975 return 0; 835 } 976 977 } // end vmm_get_pte() 836 978 837 979 /////////////////////////////////////////////////// … … 851 993 process_t * ref_ptr = (process_t *)GET_PTR( process->ref_xp ); 852 994 853 // get missing PTE attributes and PPN 995 // get missing PTE attributes and PPN from reference cluster 854 996 if( local_cxy != ref_cxy ) // local cluster is not the reference cluster 855 997 { … … 879 1021 880 1022 return 0; 881 } 1023 1024 } // end vmm_handle_page_fault() 1025 882 1026 883 1027 /////////////////////////////////////////// … … 919 1063 920 1064 return error; 1065 921 1066 } 922 923 1067 /* 924 1068 -
trunk/kernel/mm/vmm.h
r68 r313 272 272 intptr_t vaddr ); 273 273 274 274 275 /********************************************************************************************* 275 276 * This function is called by the generic exception handler when a page fault … … 291 292 /********************************************************************************************* 292 293 * This function returns in the "attr" and "ppn" arguments the PTE associated to a given 293 * VPN for a given process. This function must be called on the reference cluster.294 * To get the PTE from another cluster, use the RPC_VMM_GET_PTE.294 * VPN for a given process. This function must be called by a thread running in the 295 * reference cluster. To get the PTE from another cluster, use the RPC_VMM_GET_PTE. 295 296 * The vseg containing the searched VPN should be registered in the reference VMM. 296 297 * If the PTE in the reference page table is unmapped, this function allocates the missing 297 * physical page from the target cluster defined by the vseg type, and update the reference298 * page table. It can call a RPC_PMEM_GET_PAGES to get the missing physical page,299 * i f the target cluster is not the reference cluster.298 * physical page from the target cluster defined by the vseg type, initilize it, 299 * and update the reference page table. It calls the RPC_PMEM_GET_PAGES to get and 300 * initialize the missing physical page, if the target cluster is not the reference cluster. 300 301 ********************************************************************************************* 301 302 * @ process : [in] pointer on process descriptor. … … 309 310 uint32_t * attr, 310 311 ppn_t * ppn ); 312 313 /********************************************************************************************* 314 * This function is called by the vmm_get_pte() function. 315 * Depending on the vseg type, defined by the <vseg> argument, it returns the PPN 316 * (Physical Page Number) associated to a missing page defined by the <vpn> argument. 317 * - For the VSEG_TYPE_FILE, it returns the physical page from the file mapper. 318 * For all other types, it allocates a new physical page from the cluster defined 319 * by the <vseg->cxy> field, or by the <vpn> MSB bits for a distributed vseg. 320 * - For the VSEG_TYPE_CODE and VSEG_TYPE_DATA types, the allocated page is initialized 321 * from the .elf file mapper. For others vseg types it is not initialised. 322 ********************************************************************************************* 323 * @ vseg : local pointer on vseg containing the mising page. 324 * @ vpn : Virtual Page Number identifying the missing page. 325 * @ ppn : [out] returned Physical Page Number. 326 ********************************************************************************************/ 327 error_t vmm_get_one_ppn( vseg_t * vseg, 328 vpn_t vpn, 329 ppn_t * ppn ); 311 330 312 331 /********************************************************************************************* -
trunk/kernel/mm/vseg.h
r101 r313 81 81 vpn_t vpn_size; /*! number of pages occupied */ 82 82 uint32_t flags; /*! vseg attributes */ 83 xptr_t mapper; /*! extended pointer on associated mapper*/84 fdid_t fdid; /*! associated fdid for a VSEG_TYPE_FILE*/85 uint32_t offset; /*! offset in file for a VSEG_TYPE_FILE*/86 cxy_t cxy; /*! target cluster for physical mapping */83 xptr_t file_mapper; /*! xptr on remote mapper (for types CODE / DATA / FILE) */ 84 intptr_t file_offset; /*! offset in file (for types CODE / DATA / FILE) */ 85 intptr_t file_size; /*! max segment size in mapper (for type DATA) */ 86 cxy_t cxy; /*! cluster for physical mapping (for non distributed) */ 87 87 } 88 88 vseg_t;
Note: See TracChangeset
for help on using the changeset viewer.