def main(): valid_keys = set( [ "payload_generator", "payload_generator_config", "inversion_divisor", "inversion_mask", "row_pattern" ]) parser = argparse.ArgumentParser() parser.add_argument("config_file", type=open) args = parser.parse_args() config_string = "" config_lines = args.config_file.readlines() for line in config_lines: index = line.find('#') if index >= 0: line = line[0:index] line += '\n' config_string += line config = json.loads(config_string) assert validate_keys(config, valid_keys) args.config_file.close() pg = PayloadGenerator.get_by_name(config["payload_generator"]) pg.initialize(config) wb = RemoteClient() wb.open() settings = get_litedram_settings() inversion_divisor = 0 inversion_mask = 0 inversion_divisor = config.get("inversion_divisor", 0) inversion_mask = int(config.get("inversion_mask", "0"), 0) row_pattern = config.get("row_pattern", 0) setup_inverters(wb, inversion_divisor, inversion_mask) while not pg.done(): offset, size = pg.get_memset_range(wb, settings) hw_memset(wb, offset, size, [row_pattern]) converter = DRAMAddressConverter.load() bank = 0 sys_clk_freq = float(get_generated_defs()['SYS_CLK_FREQ']) payload = pg.get_payload( settings=settings, bank=bank, payload_mem_size=wb.mems.payload.size, sys_clk_freq=sys_clk_freq) execute_payload(wb, payload) offset, size = pg.get_memtest_range(wb, settings) errors = hw_memtest(wb, offset, size, [row_pattern]) row_errors = decode_errors(wb, settings, converter, bank, errors) pg.process_errors(settings, row_errors) pg.summarize() wb.close()
parser.add_argument('--dbg', action='store_true') parser.add_argument('--test-modules', action='store_true') parser.add_argument('--test-memory', action='store_true') args = parser.parse_args() if args.srv: litex_server() wb = RemoteClient() wb.open() mem_base = wb.mems.main_ram.base mem_range = wb.mems.main_ram.size # bytes # we are limited to multiples of DMA data width settings = get_litedram_settings() dma_data_width = settings.phy.dfi_databits * settings.phy.nphases nbytes = dma_data_width // 8 if args.test_modules: hw_memset(wb, 0x0, mem_range, [0xffffffff], args.dbg) # --------------------------- Introduce error ------------------------ rng = random.Random(datetime.now()) offsets = [] for i, n in enumerate(range(0, 5000)): print('Generated {:d} offsets'.format(i), end='\r') offset = rng.randrange(0x0, mem_range - 4) offset &= ~0b11 # must be 32-bit aligned if offset // nbytes not in offsets: offsets.append(offset // nbytes)
def main(row_hammer_cls): parser = argparse.ArgumentParser() parser.add_argument('--nrows', type=int, default=0, help='Number of rows to consider') parser.add_argument('--bank', type=int, default=0, help='Bank number') parser.add_argument('--column', type=int, default=512, help='Column to read from') parser.add_argument('--start-row', type=int, default=0, help='Starting row (range = (start, start+nrows))') parser.add_argument( '--read_count', type=float, default=10e6, help='How many reads to perform for single address pair') parser.add_argument('--hammer-only', nargs=2, type=int, help='Run only the row hammer attack') parser.add_argument('--no-refresh', action='store_true', help='Disable refresh commands during the attacks') parser.add_argument( '--pattern', default='01_per_row', choices=['all_0', 'all_1', '01_in_row', '01_per_row', 'rand_per_row'], help='Pattern written to DRAM before running attacks') parser.add_argument( '--row-pairs', choices=['sequential', 'const', 'random'], default='sequential', help='How the rows for subsequent attacks are selected') parser.add_argument('--const-rows-pair', type=int, nargs='+', required=False, help='When using --row-pairs constant') parser.add_argument('--plot', action='store_true', help='Plot errors distribution' ) # requiers matplotlib and pyqt5 packages parser.add_argument( '--payload-executor', action='store_true', help='Do the attack using Payload Executor (1st row only)') parser.add_argument('-v', '--verbose', action='store_true', help='Be more verbose') parser.add_argument("--srv", action="store_true", help='Start LiteX server') parser.add_argument("--experiment-no", type=int, default=0, help='Run preconfigured experiment #no') args = parser.parse_args() if args.experiment_no == 1: args.nrows = 512 args.read_count = 15e6 args.pattern = '01_in_row' args.row_pairs = 'const' args.const_rows_pair = 88, 99 args.no_refresh = True if args.srv: litex_server() wb = RemoteClient() wb.open() row_hammer = row_hammer_cls( wb, nrows=args.nrows, settings=get_litedram_settings(), column=args.column, bank=args.bank, rows_start=args.start_row, verbose=args.verbose, plot=args.plot, no_refresh=args.no_refresh, payload_executor=args.payload_executor, ) if args.hammer_only: row_hammer.attack(*args.hammer_only, read_count=args.read_count) else: rng = random.Random(42) def rand_row(): return rng.randint(args.start_row, args.start_row + args.nrows) assert not (args.row_pairs == 'const' and not args.const_rows_pair), 'Specify --const-rows-pair' row_pairs = { 'sequential': [(0 + args.start_row, i + args.start_row) for i in range(args.nrows)], 'const': [tuple(args.const_rows_pair)], 'random': [(rand_row(), rand_row()) for i in range(args.nrows)], }[args.row_pairs] pattern = { 'all_0': lambda rows: patterns_const(rows, 0x00000000), 'all_ones': lambda rows: patterns_const(rows, 0xffffffff), '01_in_row': lambda rows: patterns_const(rows, 0xaaaaaaaa), '01_per_row': patterns_alternating_per_row, 'rand_per_row': patterns_random_per_row, }[args.pattern] row_hammer.run(row_pairs=row_pairs, read_count=args.read_count, pattern_generator=pattern) wb.close()