def execute(wb): depth = wb.mems.payload.size // 4 # bytes to 32-bit instructions program = [w for w in PAYLOAD] program += [0] * (wb.mems.payload.size // 4 - len(program) ) # fill with NOOPs # Write some data to the column we are reading to check that scratchpad gets filled converter = DRAMAddressConverter.load() data = list(itertools.islice(word_gen(3), 128)) memwrite(wb, data, base=converter.encode_bus(bank=0, row=100, col=200)) print('\nTransferring the payload ...') memwrite(wb, program, base=wb.mems.payload.base) def ready(): status = wb.regs.payload_executor_status.read() return (status & 1) != 0 print('\nExecuting ...') assert ready() wb.regs.payload_executor_start.write(1) while not ready(): time.sleep(0.001) print('Finished') print('\nScratchpad contents:') scratchpad = memread(wb, n=512 // 4, base=wb.mems.scratchpad.base) memdump(scratchpad, base=0)
def runner(): if profile: cProfile.runctx(command, {}, ctx, fname) else: if is_write: memwrite(wb, datas, burst=burst) else: x = len(memread(wb, n, burst=burst))
def runner(): if profile: cProfile.runctx(command, {}, ctx, fname) else: if rw == 'memread': x = len(memread(wb, n, burst=burst)) print(x) else: memwrite(wb, datas, burst=burst)
def run(args, builder, build_kwargs, target_name): # Generate files in the build directory configure_generated_files(builder, args, target_name) # Build & run if not args.sim: # hardware builder.build(**build_kwargs, run=args.build) else: # simulation sim_kwargs = get_sim_kwargs(args) builder.build(**build_kwargs, run=args.build, **sim_kwargs) if args.docs: doc.generate_docs(builder.soc, base_dir="build/documentation", project_name="LiteX Row Hammer Tester", author="Antmicro") if args.load: prog = builder.soc.platform.create_programmer() prog.load_bitstream( os.path.join(builder.gateware_dir, builder.soc.build_name + ".bit")) if args.load_bios: assert args.rw_bios_mem, 'BIOS memory must be writible' from rowhammer_tester.scripts.utils import RemoteClient, memwrite wb = RemoteClient() wb.open() from litex.soc.integration.common import get_mem_data bios_bin = os.path.join(builder.software_dir, "bios", "bios.bin") rom_data = get_mem_data(bios_bin, "little") print( f"Loading BIOS from: {bios_bin} starting at 0x{wb.mems.rom.base:08x} ..." ) print('Stopping CPU') wb.regs.ctrl_reset.write(0b10) # cpu_rst memwrite(wb, rom_data, base=wb.mems.rom.base) wb.read(wb.mems.rom.base) print('Rebooting CPU') wb.regs.ctrl_reset.write(0) wb.close() if args.flash: prog = builder.soc.platform.create_programmer() prog.flash( 0, os.path.join(builder.gateware_dir, builder.soc.build_name + ".bin"))
def attack(self, row_tuple, read_count, progress_header=''): addresses = [ self.converter.encode_dma(bank=self.bank, col=self.column, row=r) for r in row_tuple ] row_strw = len(str(2**self.settings.geom.rowbits - 1)) # FIXME: ------------------ move to utils ---------------------------- # Flush error fifo self.wb.regs.reader_skip_fifo.write(1) time.sleep(0.1) # Enable error FIFO self.wb.regs.reader_skip_fifo.write(0) assert self.wb.regs.reader_ready.read() == 1 # Skip errors fifo self.wb.regs.reader_skip_fifo.write(1) # Do not increment memory address self.wb.regs.reader_mem_mask.write(0x00000000) self.wb.regs.reader_data_mask.write(len(row_tuple) - 1) # Attacked addresses memwrite(self.wb, addresses, base=self.wb.mems.pattern_addr.base) # how many print('read_count: ' + str(int(read_count))) self.wb.regs.reader_count.write(int(read_count)) self.wb.regs.reader_start.write(1) self.wb.regs.reader_start.write(0) # FIXME: --------------------------- move to utils ------------------ def progress(count): s = ' {}'.format(progress_header + ' ' if progress_header else '') s += 'Rows = {}, Count = {:5.2f}M / {:5.2f}M'.format(row_tuple, count / 1e6, read_count / 1e6, n=row_strw) print(s, end=' \r') while True: r_count = self.wb.regs.reader_done.read() progress(r_count) if self.wb.regs.reader_ready.read(): break else: time.sleep(10 / 1e3) progress(self.wb.regs.reader_done.read()) # also clears the value print()
def payload_executor_attack(self, read_count, row): # FIXME: read from dedicated status registers tras = 5 trp = 3 encoder = Encoder(bankbits=self.bankbits) payload = [ encoder(OpCode.NOOP, timeslice=30), ] # fill payload so that we have >= desired read_count count_max = 2**Decoder.LOOP_COUNT - 1 n_loops = ceil(read_count / (count_max + 1)) for _ in range(n_loops): payload.extend([ encoder(OpCode.ACT, timeslice=tras, address=encoder.address(bank=self.bank, row=row)), encoder(OpCode.PRE, timeslice=trp, address=encoder.address(col=1 << 10)), # all encoder(OpCode.LOOP, count=count_max, jump=2), ]) payload.append(encoder(OpCode.NOOP, timeslice=30)) toggle_count = (count_max + 1) * n_loops print(' Payload size = {:5.2f}KB / {:5.2f}KB'.format(4*len(payload)/2**10, self.wb.mems.payload.size/2**10)) print(' Payload row toggle count = {:5.2f}M'.format(toggle_count/1e6)) assert len(payload) < self.wb.mems.payload.size//4 payload += [0] * (self.wb.mems.payload.size//4 - len(payload)) # fill with NOOPs print('\nTransferring the payload ...') memwrite(self.wb, payload, base=self.wb.mems.payload.base) def ready(): status = self.wb.regs.payload_executor_status.read() return (status & 1) != 0 print('\nExecuting ...') assert ready() self.wb.regs.payload_executor_start.write(1) while not ready(): time.sleep(0.001)
def payload_executor_attack(self, read_count, row_tuple): tras = self.settings.timing.tRAS trp = self.settings.timing.tRP trefi = self.settings.timing.tREFI trfc = self.settings.timing.tRFC print(' tras: {} trp: {} trefi: {} trfc: {}'.format( tras, trp, trefi, trfc)) accum = 0 encoder = Encoder(bankbits=self.settings.geom.bankbits) payload = [ encoder(OpCode.NOOP, timeslice=30), ] # fill payload so that we have >= desired read_count count_max = 2**Decoder.LOOP_COUNT - 1 n_loops = ceil(read_count / (count_max + 1)) assert len(row_tuple) * 2 < 2**Decoder.LOOP_JUMP refreshes = 0 for outer_idx in range(n_loops): local_refreshes = 0 payload.append(encoder(OpCode.REF, timeslice=trfc)) accum = trfc for row in row_tuple: if accum + tras + trp > trefi and not self.no_refresh: payload.append(encoder(OpCode.REF, timeslice=trfc)) # Invariant: time between the beginning of two refreshes # is is less than tREFI. accum = trfc local_refreshes += 1 accum += tras + trp payload.extend([ encoder(OpCode.ACT, timeslice=tras, address=encoder.address(bank=self.bank, row=row)), encoder(OpCode.PRE, timeslice=trp, address=encoder.address(col=1 << 10)), # all ]) if outer_idx == 0: loop_count = ceil(read_count) % (count_max + 1) else: loop_count = count_max refreshes += local_refreshes * loop_count payload.append( encoder(OpCode.LOOP, count=loop_count, jump=2 * len(row_tuple))) # TODO: improve synchronization when connecting/disconnecting memory controller payload.append(encoder(OpCode.NOOP, timeslice=30)) toggle_count = (count_max + 1) * n_loops print(' Payload size = {:5.2f}KB / {:5.2f}KB'.format( 4 * len(payload) / 2**10, self.wb.mems.payload.size / 2**10)) print(' Payload per-row toggle count = {:5.2f}M x{} rows'.format( toggle_count / 1e6, len(row_tuple))) print(' Payload refreshes = {}'.format(refreshes)) assert len(payload) < self.wb.mems.payload.size // 4 payload += [0] * (self.wb.mems.payload.size // 4 - len(payload) ) # fill with NOOPs print('\nTransferring the payload ...') memwrite(self.wb, payload, base=self.wb.mems.payload.base) def ready(): status = self.wb.regs.payload_executor_status.read() return (status & 1) != 0 print('\nExecuting ...') assert ready() start = time.time() self.wb.regs.payload_executor_start.write(1) while not ready(): time.sleep(0.001) print('Time taken: {}\n'.format(time.time() - start))