Checkpoint: finish debug of tests, working on hitting sbbusyerror case

This commit is contained in:
Ryan Macdonald 2018-04-05 16:31:09 -07:00
parent c5a8e1cf4c
commit 3bdb8b29a8
3 changed files with 206 additions and 124 deletions

View File

@ -57,7 +57,7 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a,
static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a); static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a);
static int riscv013_dmi_write_u64_bits(struct target *target); static int riscv013_dmi_write_u64_bits(struct target *target);
static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf); static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf);
static int riscv013_test_sba_config_reg(struct target *target, uint32_t address); static int riscv013_test_sba_config_reg(struct target *target, target_addr_t illegal_address);
uint32_t read_memory_sba_simple(struct target *target, uint32_t addr, uint32_t sbcs); uint32_t read_memory_sba_simple(struct target *target, uint32_t addr, uint32_t sbcs);
void write_memory_sba_simple(struct target *target, uint32_t addr, uint32_t data, uint32_t sbcs); void write_memory_sba_simple(struct target *target, uint32_t addr, uint32_t data, uint32_t sbcs);
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number); static int register_read_direct(struct target *target, uint64_t *value, uint32_t number);
@ -2815,49 +2815,87 @@ void riscv013_fill_dmi_nop_u64(struct target *target, char *buf)
buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0); buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0);
} }
static int riscv013_test_sba_config_reg(struct target *target, uint32_t address) static int get_max_sbaccess(struct target *target)
{
uint32_t sbcs;
dmi_read(target,&sbcs,DMI_SBCS);
uint32_t sbaccess128 = get_field(sbcs, DMI_SBCS_SBACCESS128);
uint32_t sbaccess64 = get_field(sbcs, DMI_SBCS_SBACCESS64);
uint32_t sbaccess32 = get_field(sbcs, DMI_SBCS_SBACCESS32);
uint32_t sbaccess16 = get_field(sbcs, DMI_SBCS_SBACCESS16);
uint32_t sbaccess8 = get_field(sbcs, DMI_SBCS_SBACCESS8);
if(sbaccess128){
return 4;
}else if(sbaccess64){
return 3;
}else if(sbaccess32){
return 2;
}else if(sbaccess16){
return 1;
}else if(sbaccess8){
return 0;
} else {
return ERROR_FAIL;
}
}
static int riscv013_test_sba_config_reg(struct target *target, target_addr_t illegal_address)
{ {
LOG_INFO("Testing System Bus Access as defined by RISC-V Debug Spec v0.13"); LOG_INFO("Testing System Bus Access as defined by RISC-V Debug Spec v0.13");
if(!riscv_rtos_enabled(target)) {
LOG_ERROR("Please run with -rtos riscv to run SBA test.");
}
uint32_t rd_val; uint32_t rd_val;
uint32_t sbcs_orig; uint32_t sbcs_orig;
dmi_read(target, &sbcs_orig, DMI_SBCS); dmi_read(target, &sbcs_orig, DMI_SBCS)
uint32_t sbcs = sbcs_orig; uint32_t sbcs = sbcs_orig;
bool test_passed;
int max_sbaccess = get_max_sbaccess(target);
if(max_sbaccess == ERROR_FAIL) {
LOG_ERROR("System Bus Access not supported in this config.");
return ERROR_FAIL;
}
if(get_field(sbcs, DMI_SBCS_SBVERSION) != 1) {
LOG_ERROR("System Bus Access unsupported SBVERSION");
return ERROR_FAIL;
}
// Test 1: Simple write/read test, no address autoincrement // Test 1: Simple write/read test, no address autoincrement
test_passed = true;
sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 0); sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 0);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
for(int sbaccess = 0; sbaccess < 0x5; sbaccess++) { for(int sbaccess = 0; sbaccess <= max_sbaccess; sbaccess++){
sbcs = set_field(sbcs_orig,DMI_SBCS_SBACCESS,sbaccess); sbcs = set_field(sbcs, DMI_SBCS_SBACCESS, sbaccess);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
for(int i = 0; i < 100; i++){ for(int i = 0; i < 100; i++){
uint32_t addr = 0x80000000 + (i << sbaccess); uint32_t addr = 0x80000000 + (i << sbaccess);
write_memory_sba_simple(target,addr,i,sbcs_orig); write_memory_sba_simple(target, addr, i, sbcs);
} }
for(uint32_t i = 0; i < 100; i++){ for(uint32_t i = 0; i < 100; i++){
uint32_t addr = 0x80000000 + (i << sbaccess); uint32_t addr = 0x80000000 + (i << sbaccess);
uint32_t val = read_memory_sba_simple(target,addr,sbcs_orig); uint32_t val = read_memory_sba_simple(target, addr, sbcs);
if(i != val) { if(i != val) {
LOG_ERROR("System Bus Access Test: Error reading non-autoincremented address %x, expected val = %d, read val = %d",addr,i,val); LOG_ERROR("System Bus Access Test 1: Error reading non-autoincremented address %x, expected val = %d, read val = %d", addr, i, val);
test_passed = false;
} }
} }
} }
LOG_INFO("System Bus Access Test: Read/write test, no addr autoincrement PASSED"); if(test_passed) LOG_INFO("System Bus Access Test 1: Read/write test, no addr autoincrement PASSED");
// Test 2: Simple write/read test, with address autoincrement // Test 2: Simple write/read test, with address autoincrement
test_passed = true;
sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 1); sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 1);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
for(int sbaccess = 0; sbaccess < 0x5; sbaccess++){ for(int sbaccess = 0; sbaccess <= max_sbaccess; sbaccess++){
sbcs = set_field(sbcs_orig,DMI_SBCS_SBACCESS,sbaccess); sbcs = set_field(sbcs, DMI_SBCS_SBACCESS, sbaccess);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
dmi_write(target, DMI_SBADDRESS0, 0x80000000); dmi_write(target, DMI_SBADDRESS0, 0x80000000);
@ -2866,86 +2904,129 @@ static int riscv013_test_sba_config_reg(struct target *target, uint32_t address)
dmi_write(target, DMI_SBDATA0, i); dmi_write(target, DMI_SBDATA0, i);
} }
sbcs = set_field(sbcs_orig,DMI_SBCS_SBREADONDATA,1); read_sbcs_nonbusy(target, &sbcs);
dmi_write(target, DMI_SBADDRESS0, 0x80000000); dmi_write(target, DMI_SBADDRESS0, 0x80000000);
uint32_t val;
sbcs = set_field(sbcs, DMI_SBCS_SBREADONDATA, 1);
dmi_write(target, DMI_SBCS, sbcs);
dmi_read(target, &val, DMI_SBDATA0); // Dummy read to trigger first system bus read
for(uint32_t i = 0; i < 100; i++){ for(uint32_t i = 0; i < 100; i++){
read_sbcs_nonbusy(target, &sbcs); read_sbcs_nonbusy(target, &sbcs);
uint32_t val;
dmi_read(target, &val, DMI_SBDATA0); dmi_read(target, &val, DMI_SBDATA0);
read_sbcs_nonbusy(target, &sbcs);
if(i != val) { if(i != val) {
LOG_ERROR("System Bus Access Test: Error reading autoincremented address, expected val = %d, read val = %d",i,val); LOG_ERROR("System Bus Access Test 2: Error reading autoincremented address, expected val = %d, read val = %d",i,val);
test_passed = false;
} }
} }
} }
LOG_INFO("System Bus Access Test: Read/write test, with addr autoincrement PASSED"); if(test_passed) LOG_INFO("System Bus Access Test 2: Read/write test, addr autoincrement PASSED");
// Test 3: Read from illegal address // Test 3: Read from illegal address
read_memory_sba_simple(target,address,sbcs_orig); read_memory_sba_simple(target, illegal_address, sbcs_orig);
dmi_read(target, &rd_val, DMI_SBCS); dmi_read(target, &rd_val, DMI_SBCS);
if(get_field(rd_val,DMI_SBCS_SBERROR) == 0x2) { if(get_field(rd_val, DMI_SBCS_SBERROR) == 2) {
LOG_INFO("System Bus Access Test: Illegal address read test PASSED"); LOG_INFO("System Bus Access Test 3: Illegal address read test PASSED");
sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1); sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
} else { } else {
LOG_ERROR("System Bus Access Test: Illegal address read test FAILED"); LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED");
} }
// Test 4: Write to illegal address // Test 4: Write to illegal address
write_memory_sba_simple(target,address,0xdeadbeef,sbcs_orig); write_memory_sba_simple(target, illegal_address, 0xdeadbeef, sbcs_orig);
dmi_read(target, &rd_val, DMI_SBCS); dmi_read(target, &rd_val, DMI_SBCS);
if(get_field(rd_val,DMI_SBCS_SBERROR) == 0x2) { if(get_field(rd_val, DMI_SBCS_SBERROR) == 2) {
LOG_INFO("System Bus Access Test: Illegal address write test PASSED"); LOG_INFO("System Bus Access Test 4: Illegal address write test PASSED");
sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1); sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1);
dmi_write(target, DMI_SBCS,sbcs); dmi_write(target, DMI_SBCS,sbcs);
} else { } else {
LOG_ERROR("System Bus Access Test: Illegal address write test FAILED"); LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED");
} }
// Test 5: Write to unsupported sbaccess size // Test 5: Write to unsupported sbaccess size
uint32_t sbaccess128 = get_field(sbcs_orig, DMI_SBCS_SBACCESS128); uint32_t sbaccess128 = get_field(sbcs_orig, DMI_SBCS_SBACCESS128);
if(sbaccess128) { if(sbaccess128) {
LOG_INFO("System Bus Access Test: SBCS Alignment error test PASSED, all alignments supported"); LOG_INFO("System Bus Access Test 5: SBCS Alignment error test PASSED, all alignments supported");
} else { } else {
sbcs = set_field(sbcs_orig,DMI_SBCS_SBACCESS,0x4); sbcs = set_field(sbcs_orig, DMI_SBCS_SBACCESS, 4);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
write_memory_sba_simple(target, 0x80000000, 0xdeadbeef, sbcs_orig); write_memory_sba_simple(target, 0x80000000, 0xdeadbeef, sbcs_orig);
dmi_read(target, &rd_val, DMI_SBCS); dmi_read(target, &rd_val, DMI_SBCS);
if(get_field(rd_val,DMI_SBCS_SBERROR) == 0x3) { if(get_field(rd_val, DMI_SBCS_SBERROR) == 3) {
LOG_INFO("System Bus Access Test: SBCS Alignment error test PASSED"); LOG_INFO("System Bus Access Test 5: SBCS Alignment error test PASSED");
sbcs = set_field(sbcs_orig,DMI_SBCS_SBERROR,0x1); sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
} else { } else {
LOG_ERROR("System Bus Access Test: SBCS Alignment error test FAILED"); LOG_ERROR("System Bus Access Test 5: SBCS Alignment error test FAILED");
} }
} }
// Test 5: Set sbbusyerror // Test 6: Set sbbusyerror
sbcs = set_field(sbcs_orig, DMI_SBCS_SBREADONADDR, 1);
dmi_write(target, DMI_SBCS, sbcs);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBDATA0, 0xdeadbeef);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000); dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_write(target, DMI_SBADDRESS0, 0x80000000); dmi_write(target, DMI_SBADDRESS0, 0x80000000);
dmi_read(target, &rd_val, DMI_SBCS); dmi_read(target, &rd_val, DMI_SBCS);
if(get_field(rd_val,DMI_SBCS_SBBUSYERROR)) { if(get_field(rd_val,DMI_SBCS_SBBUSYERROR)) {
LOG_INFO("System Bus Access Test: SBCS sbbusy test PASSED"); sbcs = set_field(sbcs_orig, DMI_SBCS_SBBUSYERROR, 1);
sbcs = set_field(sbcs_orig,DMI_SBCS_SBBUSYERROR,0x1);
dmi_write(target, DMI_SBCS, sbcs); dmi_write(target, DMI_SBCS, sbcs);
dmi_read(target, &rd_val, DMI_SBCS);
if(get_field(rd_val, DMI_SBCS_SBBUSYERROR) == 0) LOG_INFO("System Bus Access Test 6: SBCS sbbusyerror test PASSED");
else LOG_ERROR("System Bus Access Test 6: SBCS sbbusyerror test FAILED, unable to clear to 0");
} else { } else {
LOG_ERROR("System Bus Access Test: SBCS sbbusy test FAILED"); LOG_ERROR("System Bus Access Test 6: SBCS sbbusyerror test FAILED, unable to set");
} }
return 0; return ERROR_OK;
} }
void write_memory_sba_simple(struct target *target, uint32_t addr, uint32_t data, uint32_t sbcs) void write_memory_sba_simple(struct target *target, uint32_t addr, uint32_t data, uint32_t sbcs)
{ {
uint32_t rd_sbcs; uint32_t rd_sbcs;
read_sbcs_nonbusy(target, &rd_sbcs); read_sbcs_nonbusy(target, &rd_sbcs);
uint32_t sbcs_no_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 0); uint32_t sbcs_no_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 0);
@ -2958,6 +3039,7 @@ uint32_t read_memory_sba_simple(struct target *target, uint32_t addr, uint32_t s
{ {
uint32_t rd_val; uint32_t rd_val;
uint32_t rd_sbcs; uint32_t rd_sbcs;
read_sbcs_nonbusy(target, &rd_sbcs); read_sbcs_nonbusy(target, &rd_sbcs);
uint32_t sbcs_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 1); uint32_t sbcs_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 1);

View File

@ -1438,11 +1438,11 @@ COMMAND_HANDLER(riscv_test_sba_config_reg)
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r); RISCV_INFO(r);
uint32_t address; uint32_t illegal_address;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], illegal_address);
if (r->test_sba_config_reg) { if (r->test_sba_config_reg) {
return r->test_sba_config_reg(target,address); return r->test_sba_config_reg(target, illegal_address);
} else { } else {
LOG_ERROR("test_sba_config_reg is not implemented for this target."); LOG_ERROR("test_sba_config_reg is not implemented for this target.");
return ERROR_FAIL; return ERROR_FAIL;
@ -1520,8 +1520,8 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.name = "test_sba_config_reg", .name = "test_sba_config_reg",
.handler = riscv_test_sba_config_reg, .handler = riscv_test_sba_config_reg,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "riscv test_sba_config_reg address", .usage = "riscv test_sba_config_reg illegal_address",
.help = "Perform a series of tests on the SBCS register. Pass in a non-readable/writable address" .help = "Perform a series of tests on the SBCS register. Input arg is a non-readable/writable address."
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -117,7 +117,7 @@ typedef struct {
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address); int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value); int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
int (*test_sba_config_reg)(struct target *target, uint32_t address); int (*test_sba_config_reg)(struct target *target, target_addr_t illegal_address);
} riscv_info_t; } riscv_info_t;