Changeset 313 for trunk/kernel/mm/vmm.c
- Timestamp:
- Aug 2, 2017, 3:24:57 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note: See TracChangeset
for help on using the changeset viewer.