167cbed6bSLawrence Tang /**
2efe17e2cSLawrence Tang * Functions for generating pseudo-random CPER ARM processor sections.
367cbed6bSLawrence Tang *
467cbed6bSLawrence Tang * Author: Lawrence.Tang@arm.com
567cbed6bSLawrence Tang **/
667cbed6bSLawrence Tang
767cbed6bSLawrence Tang #include <stdlib.h>
867cbed6bSLawrence Tang #include <string.h>
967cbed6bSLawrence Tang #include "../../edk/BaseTypes.h"
1067cbed6bSLawrence Tang #include "../gen-utils.h"
118f977457SLawrence Tang #include "gen-section.h"
1267cbed6bSLawrence Tang #define ARM_ERROR_INFO_SIZE 32
1367cbed6bSLawrence Tang
1467cbed6bSLawrence Tang void *generate_arm_error_info();
1567cbed6bSLawrence Tang size_t generate_arm_context_info(void **location);
1667cbed6bSLawrence Tang
17efe17e2cSLawrence Tang //Generates a single pseudo-random ARM processor section, saving the resulting address to the given
1867cbed6bSLawrence Tang //location. Returns the size of the newly created section.
generate_section_arm(void ** location)1967cbed6bSLawrence Tang size_t generate_section_arm(void **location)
2067cbed6bSLawrence Tang {
2167cbed6bSLawrence Tang //Set up for generation of error/context structures.
2267cbed6bSLawrence Tang UINT16 error_structure_num = rand() % 4 + 1; //Must be at least 1.
23*f8fc7052SJohn Chung UINT16 context_structure_num = rand() % 3 + 1;
2467cbed6bSLawrence Tang void *error_structures[error_structure_num];
2567cbed6bSLawrence Tang void *context_structures[context_structure_num];
2667cbed6bSLawrence Tang size_t context_structure_lengths[context_structure_num];
2767cbed6bSLawrence Tang
2867cbed6bSLawrence Tang //Generate the structures.
29*f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) {
3067cbed6bSLawrence Tang error_structures[i] = generate_arm_error_info();
31*f8fc7052SJohn Chung }
32*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) {
33*f8fc7052SJohn Chung context_structure_lengths[i] =
34*f8fc7052SJohn Chung generate_arm_context_info(context_structures + i);
35*f8fc7052SJohn Chung }
3667cbed6bSLawrence Tang
3767cbed6bSLawrence Tang //Determine a random amount of vendor specific info.
3867cbed6bSLawrence Tang int vendor_info_len = rand() % 16;
3967cbed6bSLawrence Tang
4067cbed6bSLawrence Tang //Create the section as a whole.
4167cbed6bSLawrence Tang size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE);
42*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) {
4367cbed6bSLawrence Tang total_len += context_structure_lengths[i];
44*f8fc7052SJohn Chung }
4567cbed6bSLawrence Tang total_len += vendor_info_len;
4667cbed6bSLawrence Tang UINT8 *section = generate_random_bytes(total_len);
4767cbed6bSLawrence Tang
4867cbed6bSLawrence Tang //Set header information.
4967cbed6bSLawrence Tang UINT16 *info_nums = (UINT16 *)(section + 4);
5067cbed6bSLawrence Tang *info_nums = error_structure_num;
5167cbed6bSLawrence Tang *(info_nums + 1) = context_structure_num;
5267cbed6bSLawrence Tang UINT32 *section_length = (UINT32 *)(section + 8);
5367cbed6bSLawrence Tang *section_length = total_len;
5467cbed6bSLawrence Tang
5567cbed6bSLawrence Tang //Error affinity.
5667cbed6bSLawrence Tang *(section + 12) = rand() % 4;
5767cbed6bSLawrence Tang
5867cbed6bSLawrence Tang //Reserved zero bytes.
5901e3a44dSLawrence Tang UINT64 *validation = (UINT64 *)section;
60*f8fc7052SJohn Chung *validation &= 0x7;
6101e3a44dSLawrence Tang UINT32 *running_state = (UINT32 *)(section + 32);
62*f8fc7052SJohn Chung *running_state &= 0x1;
6367cbed6bSLawrence Tang memset(section + 13, 0, 3);
6467cbed6bSLawrence Tang
6567cbed6bSLawrence Tang //Copy in the sections/context structures, free resources.
6667cbed6bSLawrence Tang UINT8 *cur_pos = section + 40;
67*f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) {
6867cbed6bSLawrence Tang memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE);
6967cbed6bSLawrence Tang free(error_structures[i]);
7067cbed6bSLawrence Tang cur_pos += ARM_ERROR_INFO_SIZE;
7167cbed6bSLawrence Tang }
72*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) {
73*f8fc7052SJohn Chung memcpy(cur_pos, context_structures[i],
74*f8fc7052SJohn Chung context_structure_lengths[i]);
7567cbed6bSLawrence Tang free(context_structures[i]);
7667cbed6bSLawrence Tang cur_pos += context_structure_lengths[i];
7767cbed6bSLawrence Tang }
7867cbed6bSLawrence Tang
7967cbed6bSLawrence Tang //Set return values and exit.
8067cbed6bSLawrence Tang *location = section;
8167cbed6bSLawrence Tang return total_len;
8267cbed6bSLawrence Tang }
8367cbed6bSLawrence Tang
8467cbed6bSLawrence Tang //Generates a single pseudo-random ARM error info structure. Must be later freed.
generate_arm_error_info()8567cbed6bSLawrence Tang void *generate_arm_error_info()
8667cbed6bSLawrence Tang {
8767cbed6bSLawrence Tang UINT8 *error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE);
8867cbed6bSLawrence Tang
8967cbed6bSLawrence Tang //Version (zero for revision of table referenced), length.
9067cbed6bSLawrence Tang *error_info = 0;
9167cbed6bSLawrence Tang *(error_info + 1) = ARM_ERROR_INFO_SIZE;
9267cbed6bSLawrence Tang
9367cbed6bSLawrence Tang //Type of error.
9467cbed6bSLawrence Tang UINT8 error_type = rand() % 4;
9567cbed6bSLawrence Tang *(error_info + 4) = error_type;
9667cbed6bSLawrence Tang
9701e3a44dSLawrence Tang //Reserved bits for error information.
9801e3a44dSLawrence Tang UINT16 *validation = (UINT16 *)(error_info + 2);
9901e3a44dSLawrence Tang *validation &= 0x1F;
10001e3a44dSLawrence Tang
10167cbed6bSLawrence Tang //Make sure reserved bits are zero according with the type.
10267cbed6bSLawrence Tang UINT64 *error_subinfo = (UINT64 *)(error_info + 8);
103*f8fc7052SJohn Chung switch (error_type) {
10467cbed6bSLawrence Tang //Cache/TLB
10567cbed6bSLawrence Tang case 0:
10667cbed6bSLawrence Tang case 1:
10767cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFF;
10867cbed6bSLawrence Tang break;
10967cbed6bSLawrence Tang
11067cbed6bSLawrence Tang //Bus
11167cbed6bSLawrence Tang case 2:
11267cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFFFFFF;
11367cbed6bSLawrence Tang break;
11467cbed6bSLawrence Tang
11567cbed6bSLawrence Tang //Microarch/other.
11667cbed6bSLawrence Tang default:
11767cbed6bSLawrence Tang break;
11867cbed6bSLawrence Tang }
11967cbed6bSLawrence Tang
12067cbed6bSLawrence Tang return error_info;
12167cbed6bSLawrence Tang }
12267cbed6bSLawrence Tang
12367cbed6bSLawrence Tang //Generates a single pseudo-random ARM context info structure. Must be later freed.
generate_arm_context_info(void ** location)12467cbed6bSLawrence Tang size_t generate_arm_context_info(void **location)
12567cbed6bSLawrence Tang {
12667cbed6bSLawrence Tang //Initial length is 8 bytes. Add extra based on type.
12767cbed6bSLawrence Tang UINT16 reg_type = rand() % 9;
12867cbed6bSLawrence Tang UINT32 reg_size = 0;
12967cbed6bSLawrence Tang
13067cbed6bSLawrence Tang //Set register size.
131*f8fc7052SJohn Chung switch (reg_type) {
13267cbed6bSLawrence Tang //AARCH32 GPR, AARCH32 EL2
13367cbed6bSLawrence Tang case 0:
13467cbed6bSLawrence Tang case 2:
13567cbed6bSLawrence Tang reg_size = 64;
13667cbed6bSLawrence Tang break;
13767cbed6bSLawrence Tang
13867cbed6bSLawrence Tang //AARCH32 EL1
13967cbed6bSLawrence Tang case 1:
14067cbed6bSLawrence Tang reg_size = 96;
14167cbed6bSLawrence Tang break;
14267cbed6bSLawrence Tang
14367cbed6bSLawrence Tang //AARCH32 EL3
14467cbed6bSLawrence Tang case 3:
14567cbed6bSLawrence Tang reg_size = 8;
14667cbed6bSLawrence Tang break;
14767cbed6bSLawrence Tang
14867cbed6bSLawrence Tang //AARCH64 GPR
14967cbed6bSLawrence Tang case 4:
15067cbed6bSLawrence Tang reg_size = 256;
15167cbed6bSLawrence Tang break;
15267cbed6bSLawrence Tang
15367cbed6bSLawrence Tang //AARCH64 EL1
15467cbed6bSLawrence Tang case 5:
15567cbed6bSLawrence Tang reg_size = 136;
15667cbed6bSLawrence Tang break;
15767cbed6bSLawrence Tang
15867cbed6bSLawrence Tang //AARCH64 EL2
15967cbed6bSLawrence Tang case 6:
16067cbed6bSLawrence Tang reg_size = 120;
16167cbed6bSLawrence Tang break;
16267cbed6bSLawrence Tang
16367cbed6bSLawrence Tang //AARCH64 EL3
16467cbed6bSLawrence Tang case 7:
16567cbed6bSLawrence Tang reg_size = 80;
16667cbed6bSLawrence Tang break;
16767cbed6bSLawrence Tang
16867cbed6bSLawrence Tang //Misc. single register.
16967cbed6bSLawrence Tang case 8:
17067cbed6bSLawrence Tang reg_size = 10;
17167cbed6bSLawrence Tang break;
17267cbed6bSLawrence Tang }
17367cbed6bSLawrence Tang
17467cbed6bSLawrence Tang //Create context structure randomly.
17567cbed6bSLawrence Tang int total_size = 8 + reg_size;
17667cbed6bSLawrence Tang UINT16 *context_info = (UINT16 *)generate_random_bytes(total_size);
17767cbed6bSLawrence Tang
17867cbed6bSLawrence Tang //Set header information.
17967cbed6bSLawrence Tang *(context_info + 1) = reg_type;
18067cbed6bSLawrence Tang *((UINT32 *)(context_info + 2)) = reg_size;
18167cbed6bSLawrence Tang
18267cbed6bSLawrence Tang //Set return values and exit.
18367cbed6bSLawrence Tang *location = context_info;
18467cbed6bSLawrence Tang return total_size;
18567cbed6bSLawrence Tang }
186