My Macs:
(2015) 2 DIMMs:
each 4 GB, DDR3, 1067 MHz, Manuf = 0x859B.
(2017) 2 DIMMs:
each 8 GB, DDR3, 1600 MHz, Manuf = 0x80AD.
Assuming 8 chips/DIMM I get 4 Gb / chip. Assuming 4 banks per chip I get 1Gb/bank. √G = 32K. 32Kb/row. A 4KB page (memory map unit) is 32Kb.Oops, I get that a page is a chip row. Worse a page is normally distributed as ¼ of each of 4 rows on different chips.
On the subject of memory chips, I think that several registers per bank might be strategic. On chip cache. Several rows open per bank. Managed by memory controller. Possible controller strategy: leave recently accessed rows open but lazily close less used rows in order normally avoid closing a row in order to open a new row.
See this. pretty good description of SDRAM logic.
Another scheme is to implement 2n decaying counters, perhaps analog, for some n that you can afford. For each line refresh of line x originated by a suspect source, increment counter x mod 2n. If the counter gets too big, zero it and refresh both of the neighbor lines.
The row-hammer fix proposal is to add a few (8?) bit counter to each row and to each regen register. The counter is incremented on each write signal. When the counter wraps a signal is sent to the controller that presumably refreshes either neighbor. Whenever a row is refreshed its counter is reset. The counter measures potential damage to its two neighbors, malicious or otherwise.
When the controller opens long row j, it sets C[j] to 0 and increments both C[j–1] and C[j+1]. If either of these overflow it refreshes the corresponding long row. This additional logic should not be in the critical path. It fixes innocent and malicious cases.