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