#ifndef __RAD_MACROS_LOADED #define __RAD_MACROS_LOADED 1 /************************************************************************* * * * © Copyright 2004 Hewlett-Packard Development Company, L.P. * * * * Confidential computer software. Valid license from HP and/or * * its subsidiaries required for possession, use, or copying. * * * * Consistent with FAR 12.211 and 12.212, Commercial Computer Software, * * Computer Software Documentation, and Technical Data for Commercial * * Items are licensed to the U.S. Government under vendor's standard * * commercial license. * * * * Neither HP nor any of its subsidiaries shall be liable for technical * * or editorial errors or omissions contained herein. The information * * in this document is provided "as is" without warranty of any kind and * * is subject to change without notice. The warranties for HP products * * are set forth in the express limited warranty statements accompanying * * such products. Nothing herein should be construed as constituting an * * additional warranty. * * * *************************************************************************/ /* * Version X-15 *++ * FACILITY: * * VMS Executive (LIB_H) * * ABSTRACT: * * This header file provides the Resource Affinity Domain (RAD) macros for C. * * AUTHOR: * * Karen Noel * * CREATION DATE: 09-Dec-1999 * * MODIFICATION HISTORY: * * X-15 GHJ Gregory H. Jordan 14-Oct-2008 * Change the parameter passed to both incr_zeroed_count * and decr_zeroed_count to be PFN_T. * * Add code in decr_zero_count for the future possibility * of setting a bit requesting zeroing assistance - * the page_zeroing routine in SYS_SCHED for more info. * * X-14 GHJ Gregory H. Jordan 12-Sep-2008 * Add support for per RAD page zeroing. Two new macros * have been added for incrementing and decrementing the * zero page counts - as there is now a system wide count * and a RAD specific count. * * X-13 GHJ Gregory H. Jordan 17-Apr-2008 * Change $rad_to_cpu_mask to return a quadword mask. * * X-12 KLN3448 Karen L. Noel 5-Mar-2004 * Use 64-bit PFN data cells for 50-bit PA project. * * X-11 KLN3418 Karen L. Noel 14-Jan-2004 * Include mmgdef.h since MMG$ symbols are referenced here. * * X-10 KLN3415 Karen L. Noel 13-Jan-2004 * Add $GET_PAGE_COLOR macro. * * X-9 CMOS Christian Moser 30-OCT-2001 * For Marvel we cannot simply shift the PFN to find the Rad id * and for a given RAD there might not be a single PFN range. * Change relevant macros to call a platform specific routines, * if necessary. * * X-8 CMOS Christian Moser 5-OCT-2001 * define exe$gl_radid and typecast rad parameter when doing * a comparison. * * X-7 CMOS Christian Moser 1-OCT-2001 * Update $GET_CURRENT_RAD macro to use EXE$GL_RADID. * * X-5,6 WBF Burns Fisher 06-Mar-2000 * Fix build break and use new mask in RIH instead of calculation * * X-4 WBF Burns Fisher 01-Mar-2000 * Add $rad_to_cpu_mask * * X-3 KLN2134 Karen L. Noel 10-Feb-2000 * Add $pfn_to_rad and $cpu_to_rad. * * X-2 KLN2125 Karen L. Noel 13-Jan-2000 * Add $get_current_rad macro *-- */ #ifdef __INITIAL_POINTER_SIZE /* Defined whenever ptr size pragmas supported */ #pragma __required_pointer_size __save /* Save the previously-defined required ptr size */ #pragma __required_pointer_size __short /* And set ptr size default to 32-bit pointers */ #endif /*** MODULE RAD_MACROS ***/ /* Include any header files we need to make these macros work. */ #include #include #include #include #include /** * $cpu_to_rad - Convert CPU ID to RAD. * * This macro returns the RAD corresponding to the specified CPU. * * Input: CPU - CPU ID * Output: RAD - Resource Affinity Domain * *-- */ #define $cpu_to_rad(cpu,rad)\ { \ rad = 0; \ if (exe$gpq_rad_info_header) \ { \ if ( exe$gpq_rad_info_header->rih$l_cpu_shift_value == -1 ) \ rad = exe$gpq_rad_info_header->rih$l_cpu_to_rad ( (cpu) ); \ else \ rad = ((cpu) >> exe$gpq_rad_info_header->rih$l_cpu_shift_value); \ } \ } /** * $pfn_to_rad - Convert PFN to RAD. * * This macro returns the RAD corresponding to the specified PFN. * * Input: PFN - Page Frame Number * Output: RAD - Resource Affinity Domain * *-- */ #define $pfn_to_rad(pfn,rad)\ { \ extern const uint64 mmg$gq_vpn_to_va; \ rad = 0; \ if (exe$gpq_rad_info_header) { \ if ( exe$gpq_rad_info_header->rih$l_pfn_shift_value == -1 ) \ rad = exe$gpq_rad_info_header->rih$l_pa_to_rad ( (uint64)(pfn) << mmg$gq_vpn_to_va ); \ else \ rad = ((uint64)(pfn) >> exe$gpq_rad_info_header->rih$l_pfn_shift_value); \ } \ } /** * $get_current_rad - Get the current CPU's RAD. * * Macro to retrieve the current Rad id. In a non-NUMA environment, * the global cell EXE$GL_RADID is initialized to 0, which is always * true. In a NUMA environment, the cell is initialized to -1, and * only if replication is enabled, the cell will hold the true value * which is fetched from per-RAD local memory. If we get a -1 back, * we need to do it the hard way, by converting the CPU id into a * Rad id. * **/ #define $get_current_rad(rad) \ { \ extern int exe$gl_radid; \ rad = exe$gl_radid; \ if ( (int)rad < 0 ) \ { \ rad = 0; \ if (exe$gpq_rad_info_header) \ { \ rad = __PAL_MFPR_WHAMI(); \ if ( exe$gpq_rad_info_header->rih$l_cpu_shift_value == -1 ) \ rad = exe$gpq_rad_info_header->rih$l_cpu_to_rad ( (rad) ); \ else \ rad = ((rad) >> exe$gpq_rad_info_header->rih$l_cpu_shift_value); \ } \ } \ } /** * $get_next_color - Get the next "random" color. * * This macro works with either type of page coloring, VPN based or RAD based. * It will skip those page colors that are not present in the system. * * Output: color - the next random color to use * **/ #define $get_next_color(color) \ { \ extern uint32 mmg$gl_next_color_index; \ extern uint32 mmg$gl_present_color_mask; \ extern uint32 mmg$gl_color_count; \ \ if (mmg$gl_present_color_mask == 0) \ color = 0; \ else \ { \ color = -1; \ while ((int)color == -1) \ { \ color = mmg$gl_next_color_index; \ if (((1 << color) & mmg$gl_present_color_mask) == 0) \ { \ color = -1; \ mmg$gl_next_color_index++; \ if (mmg$gl_next_color_index >= mmg$gl_color_count) \ mmg$gl_next_color_index = 0; \ } \ } \ mmg$gl_next_color_index++; \ if (mmg$gl_next_color_index >= mmg$gl_color_count) \ mmg$gl_next_color_index = 0; \ } \ } /** * $get_base_rad - Get the base operating system RAD. * * This macro will return 0 if there is no RAD info header. * * Output: rad - Resource Affinity Domain for the base operating system * *-- */ #define $get_base_rad(rad) \ { \ extern RIH_PQ const exe$gpq_rad_info_header; \ \ if (exe$gpq_rad_info_header == 0) \ rad=0; \ else \ rad = exe$gpq_rad_info_header->rih$l_base_rad; \ } /** * $rad_to_pfn_range - Convert the RAD to a range of PFNs within the RAD * * Input: rad - Resource Affinity Domain * range_index - request range index * * Output: low_pfn - the lowest PFN within the specified RAD * high_pfn - the highest PFN within the specified RAD * * Some RADs may contain multiple PFN ranges. Additional PFN ranges can be obtained * by calling by incrementing the range index for the same rad. Should the range_index * exceed the number of PFN ranges, then both low_pfn and high_pfn will be returned as * zero. **/ #pragma inline ($rad_to_pfn_range) static void $rad_to_pfn_range(int rad,uint64 range_index,PFN_T *low_pfn, PFN_T *high_pfn) { extern RIH_PQ const exe$gpq_rad_info_header; extern const uint64 mmg$gq_min_node_pfn, mmg$gq_max_node_pfn; *low_pfn = 0; *high_pfn = 0; // // For non-rad systems, return the nodes min and max pfn values. As there is only // a single range of pfns, return with the low and high pfn set to zero if the // range index is anything other than 0. // if (exe$gpq_rad_info_header == 0) { if (range_index != 0) return; *low_pfn = mmg$gq_min_node_pfn; *high_pfn = mmg$gq_max_node_pfn; return; } if (exe$gpq_rad_info_header->rih$l_pfn_shift_value == -1) { extern const uint64 mmg$gq_vpn_to_va; uint64 low_pa, high_pa; #pragma __required_pointer_size long /* And set ptr size default to 32-bit pointers */ uint64 *pa_range; #pragma __required_pointer_size __short /* And set ptr size default to 32-bit pointers */ #if __ia64 // // On Integrity, it is possible to have systems with more than 1 disjoing pfn range. // The rad_to_pa_range call will return an array of quadwords. The first contains // a count of the pa ranges and following are pairs of quadwords with the low and // high PA address for the ranges. // exe$gpq_rad_info_header->rih$l_rad_to_pa_range( rad, &pa_range ); if (range_index >= pa_range[0]) return; pa_range = &pa_range[(range_index*2)+1]; *low_pfn = pa_range[0] >> mmg$gq_vpn_to_va; *high_pfn = pa_range[1] >> mmg$gq_vpn_to_va; #endif #if ALPHA if (range_index != 0) return; // never more than 1 range of pfns on Alpha exe$gpq_rad_info_header->rih$l_rad_to_pa_range( rad, &low_pa, &high_pa ); *low_pfn = low_pa >> mmg$gq_vpn_to_va; *high_pfn = high_pa >> mmg$gq_vpn_to_va; #endif } else { if (range_index != 0) return; *low_pfn = rad << exe$gpq_rad_info_header->rih$l_pfn_shift_value; *high_pfn = (rad+1) << exe$gpq_rad_info_header->rih$l_pfn_shift_value; *high_pfn--; } } /** * Macro to get a mask of CPUs from a RAD number. RAD Support has an assumption * of a max CPU id of 63. * * Use: * $rad_to_cpu_mask rad,cpu_mask * * WHERE: * rad - Specified RAD * cpu_mask- Returned mask of CPUs */ #define $rad_to_cpu_mask(rad,cpu_mask) \ { \ extern uint64 smp$gl_cpuconf; \ if (exe$gpq_rad_info_header != 0) \ if (rad <= RIH$C_MAX_RAD_COUNT) \ cpu_mask = exe$gpq_rad_info_header->rih$r_cpu_array[rad].rih$q_cpu_mask_array[0]; \ else \ cpu_mask = 0; \ else \ if (rad==0) \ cpu_mask = smp$gl_cpuconf; \ else \ cpu_mask == 0; \ } /** * Function to convert vpn and rad to page color * * Use: * color = $get_page_color (flags, vpn, rad); * * WHERE: * flags - MMG$M_COLOR_MUST or MMG$M_COLOR_RANDOM * vpn - virtual page number * rad - specified RAD */ static uint32 $get_page_color (uint32 flags, uint64 vpn, uint32 rad) { extern RIH_PQ const exe$gpq_rad_info_header; extern uint32 mmg$gl_color_mask; extern uint32 mmg$gl_color_count; uint32 color=0; RIH_PQ rih; // Get rad info header rih = exe$gpq_rad_info_header; // Return a random color if ((flags & MMG$M_COLOR_RANDOM) || (rih && ((int)rad == MMG$K_NO_RAD))) { $get_next_color(color); color = color & ~mmg$gl_color_mask; return (color); } // Return a rad based color if (rih) { if ((int)rad == MMG$K_BASE_RAD) color = rih->rih$l_base_rad; else color = rad; color = color & ~mmg$gl_color_mask; return (color); } // Return a VPN based color if (mmg$gl_color_count && ((int)vpn != MMG$K_NO_VPN)) color = vpn; color = color & ~mmg$gl_color_mask; return (color); } /* DECR_ZEROED_LIST_COUNT This macro will decrement the appropriate zeroed list count. This maintains the count for the overall system and for the appropriate RAD. */ #pragma inline (decr_zeroed_list_count) static void decr_zeroed_list_count( PFN_T pfn ) { extern RAD_PQ exe$gq_rad_data_array[]; extern volatile uint64 mmg$gq_zeroed_list_count; int rad; uint32 rad_bit; RAD_PQ rad_data; int high_limit; extern RIH_PQ const exe$gpq_rad_info_header; extern int mmg$gl_zero_list_hi_lim; $pfn_to_rad( pfn, rad ); rad_data = exe$gq_rad_data_array[rad]; rad_data->rad$l_zeroed_list_count--; mmg$gq_zeroed_list_count--; #ifdef MMG$ZERO_ASSIST if (exe$gpq_rad_info_header) { if (rad_data->rad$l_zero_list_hi_lim != 0) high_limit = rad_data->rad$l_zero_list_hi_lim; else high_limit = mmg$gl_zero_list_hi_lim; rad_bit = 1<rad$l_zeroed_list_count < (high_limit / 2 )) if ((exe$gpq_rad_info_header->rih$l_page_zero_assist && rad_bit) == 0) exe$gpq_rad_info_header->rih$l_page_zero_assist |= rad_bit; } #endif } #pragma inline (incr_zeroed_list_count) static void incr_zeroed_list_count( PFN_T pfn ) { extern RAD_PQ exe$gq_rad_data_array[]; extern volatile uint64 mmg$gq_zeroed_list_count; extern RIH_PQ const exe$gpq_rad_info_header; int rad; RAD_PQ rad_data; $pfn_to_rad( pfn, rad ); rad_data = exe$gq_rad_data_array[rad]; if (rad_data != 0) rad_data->rad$l_zeroed_list_count++; mmg$gq_zeroed_list_count++; } #ifdef __INITIAL_POINTER_SIZE /* Defined whenever ptr size pragmas supported */ #pragma __required_pointer_size __restore /* Restore the previously-defined required ptr size */ #endif #endif /* __RAD_MACROS_LOADED */