<p>For branches, some are like <code>jc .somewhere</code> where the CPU only really needs to guess if the branch will be taken or not taken to be able to speculate down the guessed path. However, some branches are like <code>jmp [table+eax*8]</code> where there can be over 4 billion possible directions, and for those cases the CPU needs to guess the target address to be able to speculate down the guessed path. Because there's very different types of branches, the CPU uses very different types of predictors.</p>

<p>For Spectre, there's a "meta pattern" - the attacker uses speculative execution to trick CPU into leaving information in something, then extracts that information from the something. There are multiple possibilities for "something" (data caches, instruction caches, TLBs, branch target buffer, branch direction buffer, return stack, write-combining buffers, ...) and therefore there's are many possible variations of spectre (and not just the "well known first two variations" that were made public in early 2018).</p>

<p>For spectre v1 (where "something" is a data cache) the attacker needs some way to trick the CPU into putting data into the data cache (e.g. a load and then a second load that depends on the value from the first load, which can be executed speculatively) and some way to extract the information (flush everything in the cache, then use the amount of time that a load takes to determine how the state of the data cache changed).</p>

<p>For spectre v2 (where "something" is the branch direction buffer that's used for instructions like <code>jc .somewhere</code>) the attacker needs some way to trick the CPU into putting data into the branch direction buffer (e.g. a load and then a branch that depends on the load, which can be executed speculatively) and some way to extract the information (set the branch direction buffer to a known state beforehand, then use the amount of time that a branch takes to determine how the state of the branch direction buffer changed).</p>

<p>For all of the many possible variations of spectre, the only important thing (for defense) is what the "something" can be (and how to prevent information from getting into the "something", or flush/overwrite/destroy information that got into the "something"). Everything else (specific details of one of the many possible implementations of code to attack any one of the many possible spectre variations) is unimportant.</p>

<p><strong>Vague History Of Spectre</strong></p>

<p>The original Spectre (v1, using cache timing) was found in 2017 and publicly announced in January 2018. It was like a dam bursting, and a few other variants (e.g. v2, using branch prediction) quickly followed. These early variations grabbed a lot of publicity. In the ~6 months or so after that multiple other variants were found, but didn't get as much publicity and a lot of people weren't (and still aren't) aware of them. By the "latter half" of 2018 people (e.g. me) started losing track of which variants were proven (via. "proof of concept" implementations) and which were still unproven, and some researchers started trying to enumerate the possibilities and establish naming conventions for them. The best example of this that I've seen so far is "A Systematic Evaluation of Transient Execution Attacks and Defenses" (see <a href="https://arxiv.org/pdf/1811.05441.pdf" rel="nofollow noreferrer">https://arxiv.org/pdf/1811.05441.pdf</a> ).</p>

<p>However, the "hole in the dam wall" isn't something that can be plugged easily, and (for random guesses) I think it's going to take several years before we can assume all possibilities have been explored (and I think the need for mitigation will never go away).</p>
The inner workings of Spectre (v2)
<p>I have done some reading about Spectre v2 and obviously you get the non technical explanations. Peter Cordes has a more in-depth <a href="https://security.stackexchange.com/questions/177100/why-are-amd-processors-not-less-vulnerable-to-meltdown-and-spectre/177101#177101">explanation</a> but it doesn't fully address a few details. Note: I have never performed a Spectre v2 attack so I do not have hands on experience. I have only read up about about the theory.</p>

<p>My understanding of Spectre v2 is that you make an indirect branch mispredict for instance <code>if (input &lt; data.size)</code>. If the Indirect Target Array (which I'm not too sure of the details of -- i.e. why it is separate from the BTB structure) -- which is rechecked at decode for RIPs of indirect branches -- does not contain a prediction then it will insert the new jump RIP (branch execution will eventually insert the target RIP of the branch), but for now it does not know the target RIP of the jump so any form of static prediction will not work. My understanding is it is always going to predict not taken for new indirect branches and when Port 6 eventually works out the jump target RIP and prediction it will roll back using the BOB and update the ITA with the correct jump address and then update the local and global branch history registers and the saturating counters accordingly. </p>

<p>The hacker needs to train the saturating counters to always predict taken which, I imagine, they do by running the <code>if(input &lt; data.size)</code> multiple times in a loop where <code>input</code> is set to something that is indeed less than <code>data.size</code> (catching errors accordingly) and on the final iteration of the loop, make <code>input</code> more than <code>data.size</code> (1000 for instance); the indirect branch will be predicted taken and it will jump to the body of the if statement where the cache load takes place.</p>

<p>The if statement contains <code>secret = data[1000]</code> (A particular memory address (data[1000]) that contains secret data is targeted for loading from memory to cache) then this will be allocated to the load buffer speculatively. The preceding indirect branch is still in the branch execution unit and waiting to complete.</p>

<p>I believe the premise is that the load needs to be executed (assigned a line fill buffer) before the load buffers are flushed on the misprediction. If it has been assigned a line fill buffer already then nothing can be done. It makes sense that there isn't a mechanism to cancel a line fill buffer allocation because the line fill buffer would have to pend before storing to the cache after returning it to the load buffer. This could cause line fill buffers to become saturated because instead of deallocating when required (keeping it in there for speed of other loads to the same address but deallocating when the there are no other available line buffers). It would not be able to deallocate until it receives some signal that a flush is <em>not</em> going to occur, meaning it has to halt for the previous branch to execute instead of immediately making the line fill buffer available for the stores of the other logical core. This signalling mechanism could be difficult to implement and perhaps it didn't cross their minds (pre-Spectre thinking) and it would also introduce delay in the event that branch execution takes enough time for hanging line fill buffers to cause a performance impact i.e. if <code>data.size</code> is purposefully flushed from the cache (<code>CLFLUSH</code>) before the final iteration of the loop meaning branch execution could take up to 100 cycles.</p>

<p>I hope my thinking is correct but I'm not 100% sure. If anyone has anything to add or correct then please do.</p>