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 <libcper/BaseTypes.h>
10 #include <libcper/generator/gen-utils.h>
11 #include <libcper/generator/sections/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.
generate_section_arm(void ** location)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.
generate_arm_error_info()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.
generate_arm_context_info(void ** location)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