From 3bdb8b29a85be3b5b717dfa576a9249c7ab3b47e Mon Sep 17 00:00:00 2001 From: Ryan Macdonald Date: Thu, 5 Apr 2018 16:31:09 -0700 Subject: [PATCH] Checkpoint: finish debug of tests, working on hitting sbbusyerror case --- src/target/riscv/riscv-013.c | 318 ++++++++++++++++++++++------------- src/target/riscv/riscv.c | 10 +- src/target/riscv/riscv.h | 2 +- 3 files changed, 206 insertions(+), 124 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index a701e2c9e..57578bf1d 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -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 int riscv013_dmi_write_u64_bits(struct target *target); 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); 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); @@ -1491,7 +1491,7 @@ static int init_target(struct command_context *cmd_ctx, generic_info->fill_dmi_read_u64 = &riscv013_fill_dmi_read_u64; generic_info->fill_dmi_nop_u64 = &riscv013_fill_dmi_nop_u64; generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits; - generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg; + generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg; generic_info->authdata_read = &riscv013_authdata_read; generic_info->authdata_write = &riscv013_authdata_write; generic_info->dmi_read = &dmi_read; @@ -2815,160 +2815,242 @@ void riscv013_fill_dmi_nop_u64(struct target *target, char *buf) 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) { - LOG_INFO("Testing System Bus Access as defined by RISC-V Debug Spec v0.13"); + uint32_t sbcs; + dmi_read(target,&sbcs,DMI_SBCS); - if(!riscv_rtos_enabled(target)) { - LOG_ERROR("Please run with -rtos riscv to run SBA test."); - } + 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); - uint32_t rd_val; - uint32_t sbcs_orig; - dmi_read(target, &sbcs_orig, DMI_SBCS); + 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; + } +} - uint32_t sbcs = sbcs_orig; +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"); - // Test 1: Simple write/read test, no address autoincrement - sbcs = set_field(sbcs_orig,DMI_SBCS_SBAUTOINCREMENT,0); - dmi_write(target,DMI_SBCS,sbcs); + uint32_t rd_val; + uint32_t sbcs_orig; + dmi_read(target, &sbcs_orig, DMI_SBCS) - for(int sbaccess = 0; sbaccess < 0x5; sbaccess++) { - sbcs = set_field(sbcs_orig,DMI_SBCS_SBACCESS,sbaccess); - dmi_write(target,DMI_SBCS,sbcs); + uint32_t sbcs = sbcs_orig; + bool test_passed; - for(int i = 0; i < 100; i++){ - uint32_t addr = 0x80000000 + (i << sbaccess); - write_memory_sba_simple(target,addr,i,sbcs_orig); - } + int max_sbaccess = get_max_sbaccess(target); - for(uint32_t i = 0; i < 100; i++){ - uint32_t addr = 0x80000000 + (i << sbaccess); - uint32_t val = read_memory_sba_simple(target,addr,sbcs_orig); - 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_INFO("System Bus Access Test: Read/write test, no addr autoincrement PASSED"); + if(max_sbaccess == ERROR_FAIL) { + LOG_ERROR("System Bus Access not supported in this config."); + return ERROR_FAIL; + } - // Test 2: Simple write/read test, with address autoincrement - sbcs = set_field(sbcs_orig,DMI_SBCS_SBAUTOINCREMENT,1); - dmi_write(target,DMI_SBCS,sbcs); + if(get_field(sbcs, DMI_SBCS_SBVERSION) != 1) { + LOG_ERROR("System Bus Access unsupported SBVERSION"); + return ERROR_FAIL; + } - for(int sbaccess = 0; sbaccess < 0x5; sbaccess++){ - sbcs = set_field(sbcs_orig,DMI_SBCS_SBACCESS,sbaccess); - dmi_write(target,DMI_SBCS,sbcs); + // Test 1: Simple write/read test, no address autoincrement + test_passed = true; + sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 0); + dmi_write(target, DMI_SBCS, sbcs); - dmi_write(target,DMI_SBADDRESS0,0x80000000); - for(int i = 0; i < 100; i++){ - read_sbcs_nonbusy(target,&sbcs); - dmi_write(target,DMI_SBDATA0,i); - } + for(int sbaccess = 0; sbaccess <= max_sbaccess; sbaccess++){ + sbcs = set_field(sbcs, DMI_SBCS_SBACCESS, sbaccess); + dmi_write(target, DMI_SBCS, sbcs); - sbcs = set_field(sbcs_orig,DMI_SBCS_SBREADONDATA,1); + for(int i = 0; i < 100; i++){ + uint32_t addr = 0x80000000 + (i << sbaccess); + write_memory_sba_simple(target, addr, i, sbcs); + } - dmi_write(target,DMI_SBADDRESS0,0x80000000); - for(uint32_t i = 0; i < 100; i++){ - read_sbcs_nonbusy(target,&sbcs); - uint32_t val; - dmi_read(target,&val,DMI_SBDATA0); - if(i != val) { - LOG_ERROR("System Bus Access Test: Error reading autoincremented address, expected val = %d, read val = %d",i,val); - } - } - } - LOG_INFO("System Bus Access Test: Read/write test, with addr autoincrement PASSED"); + for(uint32_t i = 0; i < 100; i++){ + uint32_t addr = 0x80000000 + (i << sbaccess); + uint32_t val = read_memory_sba_simple(target, addr, sbcs); + if(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; + } + } + } + if(test_passed) LOG_INFO("System Bus Access Test 1: Read/write test, no addr autoincrement PASSED"); - // Test 3: Read from illegal address - read_memory_sba_simple(target,address,sbcs_orig); + // Test 2: Simple write/read test, with address autoincrement + test_passed = true; + sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 1); + dmi_write(target, DMI_SBCS, sbcs); - dmi_read(target,&rd_val,DMI_SBCS); - if(get_field(rd_val,DMI_SBCS_SBERROR) == 0x2) { - LOG_INFO("System Bus Access Test: Illegal address read test PASSED"); - sbcs = set_field(sbcs_orig,DMI_SBCS_SBERROR,1); - dmi_write(target,DMI_SBCS,sbcs); - } else { - LOG_ERROR("System Bus Access Test: Illegal address read test FAILED"); - } + for(int sbaccess = 0; sbaccess <= max_sbaccess; sbaccess++){ + sbcs = set_field(sbcs, DMI_SBCS_SBACCESS, sbaccess); + dmi_write(target, DMI_SBCS, sbcs); - // Test 4: Write to illegal address - write_memory_sba_simple(target,address,0xdeadbeef,sbcs_orig); + dmi_write(target, DMI_SBADDRESS0, 0x80000000); + for(int i = 0; i < 100; i++){ + read_sbcs_nonbusy(target, &sbcs); + dmi_write(target, DMI_SBDATA0, i); + } - dmi_read(target,&rd_val,DMI_SBCS); - if(get_field(rd_val,DMI_SBCS_SBERROR) == 0x2) { - LOG_INFO("System Bus Access Test: Illegal address write test PASSED"); - sbcs = set_field(sbcs_orig,DMI_SBCS_SBERROR,1); - dmi_write(target,DMI_SBCS,sbcs); - } else { - LOG_ERROR("System Bus Access Test: Illegal address write test FAILED"); - } + read_sbcs_nonbusy(target, &sbcs); - // Test 5: Write to unsupported sbaccess size - uint32_t sbaccess128 = get_field(sbcs_orig,DMI_SBCS_SBACCESS128); + dmi_write(target, DMI_SBADDRESS0, 0x80000000); - if(sbaccess128) { - LOG_INFO("System Bus Access Test: SBCS Alignment error test PASSED, all alignments supported"); - } else { - sbcs = set_field(sbcs_orig,DMI_SBCS_SBACCESS,0x4); - dmi_write(target, DMI_SBCS, sbcs); + 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++){ + read_sbcs_nonbusy(target, &sbcs); + dmi_read(target, &val, DMI_SBDATA0); + read_sbcs_nonbusy(target, &sbcs); + if(i != val) { + LOG_ERROR("System Bus Access Test 2: Error reading autoincremented address, expected val = %d, read val = %d",i,val); + test_passed = false; + } + } + } + if(test_passed) LOG_INFO("System Bus Access Test 2: Read/write test, addr autoincrement PASSED"); - write_memory_sba_simple(target, 0x80000000, 0xdeadbeef, sbcs_orig); + // Test 3: Read from illegal address + 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) == 2) { + LOG_INFO("System Bus Access Test 3: Illegal address read test PASSED"); + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1); + dmi_write(target, DMI_SBCS, sbcs); + } else { + LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED"); + } - if(get_field(rd_val,DMI_SBCS_SBERROR) == 0x3) { - LOG_INFO("System Bus Access Test: SBCS Alignment error test PASSED"); - sbcs = set_field(sbcs_orig,DMI_SBCS_SBERROR,0x1); - dmi_write(target,DMI_SBCS,sbcs); - } else { - LOG_ERROR("System Bus Access Test: SBCS Alignment error test FAILED"); - } - } - - // Test 5: Set sbbusyerror - dmi_write(target,DMI_SBADDRESS0,0x80000000); - dmi_write(target,DMI_SBADDRESS0,0x80000000); + // Test 4: Write to illegal address + write_memory_sba_simple(target, illegal_address, 0xdeadbeef, sbcs_orig); - dmi_read(target,&rd_val,DMI_SBCS); - 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,0x1); - dmi_write(target,DMI_SBCS,sbcs); - } else { - LOG_ERROR("System Bus Access Test: SBCS sbbusy test FAILED"); - } + dmi_read(target, &rd_val, DMI_SBCS); + if(get_field(rd_val, DMI_SBCS_SBERROR) == 2) { + LOG_INFO("System Bus Access Test 4: Illegal address write test PASSED"); + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1); + dmi_write(target, DMI_SBCS,sbcs); + } else { + LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED"); + } - return 0; + // Test 5: Write to unsupported sbaccess size + uint32_t sbaccess128 = get_field(sbcs_orig, DMI_SBCS_SBACCESS128); + + if(sbaccess128) { + LOG_INFO("System Bus Access Test 5: SBCS Alignment error test PASSED, all alignments supported"); + } else { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBACCESS, 4); + dmi_write(target, DMI_SBCS, sbcs); + + write_memory_sba_simple(target, 0x80000000, 0xdeadbeef, sbcs_orig); + + dmi_read(target, &rd_val, DMI_SBCS); + + if(get_field(rd_val, DMI_SBCS_SBERROR) == 3) { + LOG_INFO("System Bus Access Test 5: SBCS Alignment error test PASSED"); + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 1); + dmi_write(target, DMI_SBCS, sbcs); + } else { + LOG_ERROR("System Bus Access Test 5: SBCS Alignment error test FAILED"); + } + } + + // 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_read(target, &rd_val, DMI_SBCS); + if(get_field(rd_val,DMI_SBCS_SBBUSYERROR)) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBBUSYERROR, 1); + 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 { + LOG_ERROR("System Bus Access Test 6: SBCS sbbusyerror test FAILED, unable to set"); + } + + return ERROR_OK; } void write_memory_sba_simple(struct target *target, uint32_t addr, uint32_t data, uint32_t sbcs) { - uint32_t rd_sbcs; - read_sbcs_nonbusy(target,&rd_sbcs); + uint32_t rd_sbcs; - uint32_t sbcs_no_readonaddr = set_field(sbcs,DMI_SBCS_SBREADONADDR,0); - dmi_write(target,DMI_SBCS,sbcs_no_readonaddr); - dmi_write(target,DMI_SBADDRESS0,addr); - dmi_write(target,DMI_SBDATA0,data); + read_sbcs_nonbusy(target, &rd_sbcs); + + uint32_t sbcs_no_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 0); + dmi_write(target, DMI_SBCS, sbcs_no_readonaddr); + dmi_write(target, DMI_SBADDRESS0, addr); + dmi_write(target, DMI_SBDATA0, data); } uint32_t read_memory_sba_simple(struct target *target, uint32_t addr, uint32_t sbcs) { - uint32_t rd_val; - uint32_t rd_sbcs; - read_sbcs_nonbusy(target,&rd_sbcs); + uint32_t rd_val; + uint32_t rd_sbcs; - uint32_t sbcs_readonaddr = set_field(sbcs,DMI_SBCS_SBREADONADDR,1); - dmi_write(target,DMI_SBCS,sbcs_readonaddr); - dmi_write(target,DMI_SBADDRESS0,addr); + read_sbcs_nonbusy(target, &rd_sbcs); - read_sbcs_nonbusy(target,&rd_sbcs); + uint32_t sbcs_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 1); + dmi_write(target, DMI_SBCS,sbcs_readonaddr); + dmi_write(target, DMI_SBADDRESS0,addr); - dmi_read(target,&rd_val,DMI_SBDATA0); + read_sbcs_nonbusy(target, &rd_sbcs); - return rd_val; + dmi_read(target, &rd_val, DMI_SBDATA0); + + return rd_val; } int riscv013_dmi_write_u64_bits(struct target *target) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 4577ef553..a94640eee 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1438,11 +1438,11 @@ COMMAND_HANDLER(riscv_test_sba_config_reg) struct target *target = get_current_target(CMD_CTX); RISCV_INFO(r); - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + uint32_t illegal_address; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], illegal_address); if (r->test_sba_config_reg) { - return r->test_sba_config_reg(target,address); + return r->test_sba_config_reg(target, illegal_address); } else { LOG_ERROR("test_sba_config_reg is not implemented for this target."); return ERROR_FAIL; @@ -1520,8 +1520,8 @@ static const struct command_registration riscv_exec_command_handlers[] = { .name = "test_sba_config_reg", .handler = riscv_test_sba_config_reg, .mode = COMMAND_ANY, - .usage = "riscv test_sba_config_reg address", - .help = "Perform a series of tests on the SBCS register. Pass in a non-readable/writable address" + .usage = "riscv test_sba_config_reg illegal_address", + .help = "Perform a series of tests on the SBCS register. Input arg is a non-readable/writable address." }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index a564fb1f7..18f47b7a8 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -117,7 +117,7 @@ typedef struct { 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 (*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;