1 /** 2 * Functions for generating pseudo-random CPER ARM processor sections. 3 * 4 * Author: Lawrence.Tang@arm.com 5 **/ 6 7 #include <stdlib.h> 8 #include <string.h> 9 #include "../../edk/BaseTypes.h" 10 #include "../gen-utils.h" 11 #include "gen-section.h" 12 #define ARM_ERROR_INFO_SIZE 32 13 14 void *generate_arm_error_info(); 15 size_t generate_arm_context_info(void **location); 16 17 //Generates a single pseudo-random ARM processor section, saving the resulting address to the given 18 //location. Returns the size of the newly created section. 19 size_t generate_section_arm(void **location) 20 { 21 //Set up for generation of error/context structures. 22 UINT16 error_structure_num = rand() % 4 + 1; //Must be at least 1. 23 UINT16 context_structure_num = rand() % 3 + 1; 24 void *error_structures[error_structure_num]; 25 void *context_structures[context_structure_num]; 26 size_t context_structure_lengths[context_structure_num]; 27 28 //Generate the structures. 29 for (int i = 0; i < error_structure_num; i++) { 30 error_structures[i] = generate_arm_error_info(); 31 } 32 for (int i = 0; i < context_structure_num; i++) { 33 context_structure_lengths[i] = 34 generate_arm_context_info(context_structures + i); 35 } 36 37 //Determine a random amount of vendor specific info. 38 int vendor_info_len = rand() % 16; 39 40 //Create the section as a whole. 41 size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE); 42 for (int i = 0; i < context_structure_num; i++) { 43 total_len += context_structure_lengths[i]; 44 } 45 total_len += vendor_info_len; 46 UINT8 *section = generate_random_bytes(total_len); 47 48 //Set header information. 49 UINT16 *info_nums = (UINT16 *)(section + 4); 50 *info_nums = error_structure_num; 51 *(info_nums + 1) = context_structure_num; 52 UINT32 *section_length = (UINT32 *)(section + 8); 53 *section_length = total_len; 54 55 //Error affinity. 56 *(section + 12) = rand() % 4; 57 58 //Reserved zero bytes. 59 UINT64 *validation = (UINT64 *)section; 60 *validation &= 0x7; 61 UINT32 *running_state = (UINT32 *)(section + 32); 62 *running_state &= 0x1; 63 memset(section + 13, 0, 3); 64 65 //Copy in the sections/context structures, free resources. 66 UINT8 *cur_pos = section + 40; 67 for (int i = 0; i < error_structure_num; i++) { 68 memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE); 69 free(error_structures[i]); 70 cur_pos += ARM_ERROR_INFO_SIZE; 71 } 72 for (int i = 0; i < context_structure_num; i++) { 73 memcpy(cur_pos, context_structures[i], 74 context_structure_lengths[i]); 75 free(context_structures[i]); 76 cur_pos += context_structure_lengths[i]; 77 } 78 79 //Set return values and exit. 80 *location = section; 81 return total_len; 82 } 83 84 //Generates a single pseudo-random ARM error info structure. Must be later freed. 85 void *generate_arm_error_info() 86 { 87 UINT8 *error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE); 88 89 //Version (zero for revision of table referenced), length. 90 *error_info = 0; 91 *(error_info + 1) = ARM_ERROR_INFO_SIZE; 92 93 //Type of error. 94 UINT8 error_type = rand() % 4; 95 *(error_info + 4) = error_type; 96 97 //Reserved bits for error information. 98 UINT16 *validation = (UINT16 *)(error_info + 2); 99 *validation &= 0x1F; 100 101 //Make sure reserved bits are zero according with the type. 102 UINT64 *error_subinfo = (UINT64 *)(error_info + 8); 103 switch (error_type) { 104 //Cache/TLB 105 case 0: 106 case 1: 107 *error_subinfo &= 0xFFFFFFF; 108 break; 109 110 //Bus 111 case 2: 112 *error_subinfo &= 0xFFFFFFFFFFF; 113 break; 114 115 //Microarch/other. 116 default: 117 break; 118 } 119 120 return error_info; 121 } 122 123 //Generates a single pseudo-random ARM context info structure. Must be later freed. 124 size_t generate_arm_context_info(void **location) 125 { 126 //Initial length is 8 bytes. Add extra based on type. 127 UINT16 reg_type = rand() % 9; 128 UINT32 reg_size = 0; 129 130 //Set register size. 131 switch (reg_type) { 132 //AARCH32 GPR, AARCH32 EL2 133 case 0: 134 case 2: 135 reg_size = 64; 136 break; 137 138 //AARCH32 EL1 139 case 1: 140 reg_size = 96; 141 break; 142 143 //AARCH32 EL3 144 case 3: 145 reg_size = 8; 146 break; 147 148 //AARCH64 GPR 149 case 4: 150 reg_size = 256; 151 break; 152 153 //AARCH64 EL1 154 case 5: 155 reg_size = 136; 156 break; 157 158 //AARCH64 EL2 159 case 6: 160 reg_size = 120; 161 break; 162 163 //AARCH64 EL3 164 case 7: 165 reg_size = 80; 166 break; 167 168 //Misc. single register. 169 case 8: 170 reg_size = 10; 171 break; 172 } 173 174 //Create context structure randomly. 175 int total_size = 8 + reg_size; 176 UINT16 *context_info = (UINT16 *)generate_random_bytes(total_size); 177 178 //Set header information. 179 *(context_info + 1) = reg_type; 180 *((UINT32 *)(context_info + 2)) = reg_size; 181 182 //Set return values and exit. 183 *location = context_info; 184 return total_size; 185 } 186