blob: f4edc70be0ba7df763f9b6b794c093636f9ecd18 [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.
Ed Tanousfedd4572024-07-12 13:56:00 -07003 *
Lawrence Tang67cbed62022-07-18 16:44:51 +01004 * 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
John Chungf8fc7052024-05-03 20:05:29 +080014void *generate_arm_error_info();
15size_t generate_arm_context_info(void **location);
Lawrence Tang67cbed62022-07-18 16:44:51 +010016
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.
John Chungf8fc7052024-05-03 20:05:29 +080019size_t generate_section_arm(void **location)
Lawrence Tang67cbed62022-07-18 16:44:51 +010020{
John Chungf8fc7052024-05-03 20:05:29 +080021 //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];
Lawrence Tang67cbed62022-07-18 16:44:51 +010027
John Chungf8fc7052024-05-03 20:05:29 +080028 //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 }
Lawrence Tang67cbed62022-07-18 16:44:51 +010036
John Chungf8fc7052024-05-03 20:05:29 +080037 //Determine a random amount of vendor specific info.
38 int vendor_info_len = rand() % 16;
Lawrence Tang67cbed62022-07-18 16:44:51 +010039
John Chungf8fc7052024-05-03 20:05:29 +080040 //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);
Lawrence Tang67cbed62022-07-18 16:44:51 +010047
John Chungf8fc7052024-05-03 20:05:29 +080048 //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;
Lawrence Tang67cbed62022-07-18 16:44:51 +010054
John Chungf8fc7052024-05-03 20:05:29 +080055 //Error affinity.
56 *(section + 12) = rand() % 4;
Lawrence Tang67cbed62022-07-18 16:44:51 +010057
John Chungf8fc7052024-05-03 20:05:29 +080058 //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);
Lawrence Tang67cbed62022-07-18 16:44:51 +010064
John Chungf8fc7052024-05-03 20:05:29 +080065 //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;
Lawrence Tang67cbed62022-07-18 16:44:51 +010082}
83
84//Generates a single pseudo-random ARM error info structure. Must be later freed.
John Chungf8fc7052024-05-03 20:05:29 +080085void *generate_arm_error_info()
Lawrence Tang67cbed62022-07-18 16:44:51 +010086{
John Chungf8fc7052024-05-03 20:05:29 +080087 UINT8 *error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE);
Lawrence Tang67cbed62022-07-18 16:44:51 +010088
John Chungf8fc7052024-05-03 20:05:29 +080089 //Version (zero for revision of table referenced), length.
90 *error_info = 0;
91 *(error_info + 1) = ARM_ERROR_INFO_SIZE;
Lawrence Tang67cbed62022-07-18 16:44:51 +010092
John Chungf8fc7052024-05-03 20:05:29 +080093 //Type of error.
94 UINT8 error_type = rand() % 4;
95 *(error_info + 4) = error_type;
Lawrence Tang67cbed62022-07-18 16:44:51 +010096
John Chungf8fc7052024-05-03 20:05:29 +080097 //Reserved bits for error information.
98 UINT16 *validation = (UINT16 *)(error_info + 2);
99 *validation &= 0x1F;
Lawrence Tang01e3a442022-07-20 15:14:50 +0100100
John Chungf8fc7052024-05-03 20:05:29 +0800101 //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;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100109
John Chungf8fc7052024-05-03 20:05:29 +0800110 //Bus
111 case 2:
112 *error_subinfo &= 0xFFFFFFFFFFF;
113 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100114
John Chungf8fc7052024-05-03 20:05:29 +0800115 //Microarch/other.
116 default:
117 break;
118 }
Lawrence Tang67cbed62022-07-18 16:44:51 +0100119
John Chungf8fc7052024-05-03 20:05:29 +0800120 return error_info;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100121}
122
123//Generates a single pseudo-random ARM context info structure. Must be later freed.
John Chungf8fc7052024-05-03 20:05:29 +0800124size_t generate_arm_context_info(void **location)
Lawrence Tang67cbed62022-07-18 16:44:51 +0100125{
John Chungf8fc7052024-05-03 20:05:29 +0800126 //Initial length is 8 bytes. Add extra based on type.
127 UINT16 reg_type = rand() % 9;
128 UINT32 reg_size = 0;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100129
John Chungf8fc7052024-05-03 20:05:29 +0800130 //Set register size.
131 switch (reg_type) {
132 //AARCH32 GPR, AARCH32 EL2
133 case 0:
134 case 2:
135 reg_size = 64;
136 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100137
John Chungf8fc7052024-05-03 20:05:29 +0800138 //AARCH32 EL1
139 case 1:
140 reg_size = 96;
141 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100142
John Chungf8fc7052024-05-03 20:05:29 +0800143 //AARCH32 EL3
144 case 3:
145 reg_size = 8;
146 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100147
John Chungf8fc7052024-05-03 20:05:29 +0800148 //AARCH64 GPR
149 case 4:
150 reg_size = 256;
151 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100152
John Chungf8fc7052024-05-03 20:05:29 +0800153 //AARCH64 EL1
154 case 5:
155 reg_size = 136;
156 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100157
John Chungf8fc7052024-05-03 20:05:29 +0800158 //AARCH64 EL2
159 case 6:
160 reg_size = 120;
161 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100162
John Chungf8fc7052024-05-03 20:05:29 +0800163 //AARCH64 EL3
164 case 7:
165 reg_size = 80;
166 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100167
John Chungf8fc7052024-05-03 20:05:29 +0800168 //Misc. single register.
169 case 8:
170 reg_size = 10;
171 break;
172 }
Lawrence Tang67cbed62022-07-18 16:44:51 +0100173
John Chungf8fc7052024-05-03 20:05:29 +0800174 //Create context structure randomly.
175 int total_size = 8 + reg_size;
176 UINT16 *context_info = (UINT16 *)generate_random_bytes(total_size);
Lawrence Tang67cbed62022-07-18 16:44:51 +0100177
John Chungf8fc7052024-05-03 20:05:29 +0800178 //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}