The page table walker might need to write back page table entries to set
their accessed bits. It was already checking whether the access was 32
or 64 bit when the PTE was retrieved from the incoming packet, but was
not checking the size when it was written back out, causing an assert to
fail when working with 32 bit legacy PTEs.
Change-Id: I7d02241cad20681e6cac0111edf2454335c466fa
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55808
Reviewed-by: Matthew Poremba <matthew.poremba@amd.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This pin should be connected to the master I8259 output which is used to
bypass the IOAPIC when it is disabled and the local APIC is in virtual
wire mode. This is how the system is supposed to start, and can later be
switched into symmetric multiprocessing mode later on by an SMP aware OS
(most of them). Only the BSP should have it's LINT0 pin connected to the
I8259, since I8259 type interrupts are only usable by a single CPU at a
time.
Change-Id: I0e3e3338f14d384c26da660cf54779579eb0d641
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55696
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
In a real system, once a CPU receives an interrupt of type ExtInt, it
will send an INTA message out to the I8259 sytle interrupt controllers
to read the vector for that interrupt. In ye-olden-times, that would
literally mean the I8259 would be in charge of the bus and would write
the eight bit vector for the CPU to read. In more modern systems, the
vector is transported on the system interconnect using a special
message.
To better approximate a real system, and to make the interrupt
controllers more modular and agnostic (so the IO APIC doesn't have a
I8259 pointer within it, for instance), this change adds a new special
address which the I8259 can respond to on reads which will act as if it
received an INTA message, and the read data will be the interrupt
vector.
Only the master controller, or a single device, will respond to this
address, and because of its value and the fact that it's beyond the end
of the 16 bit IO port address space's effective range but still within
it, that address won't be generated by any other activity other than
possibly a bogus address.
Also by putting the special address in the IO port address space, that
will make it easier to ensure that it's within the range of addresses
which are routed towards the I8259 which operates off the IO port bus.
This address is not yet actually used by the IO APIC or local APIC but
will be shortly.
Change-Id: Ib73ab4ee08531028d3540570594c552f39053a40
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55694
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
The PC value is put in t7, but for that to be consistent with the way
microcode usually sees and interacts with the PC, it needs to have the
CS base value subtracted from it first. Otherwise the base could be
added into new PC values twice.
Change-Id: I8a8c5bc1befd9a89e6735981fd2fc69a702fdc68
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55690
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
This is a far call direct, which has a far pointer (a 16 bit segment
selector and a 16 or 32 bit offset) as an immediate value. The gem5
decoder was expecting no immediate, and so was not gathering one. The
actual microcode for the instruction was taking the junk immediate and
trying to use it which did not work.
This change makes a small update to the table which says how big the
immediate values are for various instructions, changing the entry for
one byte opcode 0x9a from 0 (no immediate) to PO (pointer sized). The
immediate size will be automatically selected by the decoder based on
the PO rule, and the currently active operand size.
Change-Id: Ic290e7bb01dc6165c4eabed214887e4b5adb42da
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55626
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
For all instructions which affect the RIP, they are supposed to
truncate/zero extend the RIP based on the width of the instruction. We
should do that after the target is calculated by adding the two operands
together, but before adding in the segment base address.
Change-Id: I105e58de6a07c7aa3155a9a188d8877c2955651f
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55592
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
The stack segment is the default for instructions that use rSP or rBP in
their address calculations at all, except if they're used as a base.
Even though the wording in the AMD manual is a bit misleading, the
presence of a displacement does not make the default DS.
Also, allow segment override prefixes even if the default is SS. If an
instruction *must* use SS (like push or pop) it will have explicitly
specified that in the microcode.
Change-Id: I73c6e367440a664c5c7c483337c16d4ab14f0e34
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55589
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
There are instructions in 64 bit mode which have been turned into the
REX and VEX prefixes, and which should no longer behave as instructions.
When not in 64 bit mode however, those instructions still need to behave
properly.
We were handling that for the REX prefixes by explicitly checking if the
prefix we found was one of those, and then whether we were in 64 bit
mode or not. We were not handling the VEX prefixes at all, so those were
always acting as prefixes, even when not in 64 bit mode.
This change replaces the REX check and possible VEX check by having two
prefix tables, one for 64 bit mode, and one for otherwise. The REX and
VEX prefixes are simply left out of the non 64b it mode table, making an
explicit check for them unnecessary.
Change-Id: Ia2fc17074015e074d1f156177bd499d67da5411d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55587
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
The stack size is something that applies to addresses when performing
accesses as part of some instructions. This was handled inconsistently
or incompletely or simply incorrectly in a few ways.
First, when pushing or popping from the stack, the *address size* should
be set to the stack size. The data size is generally the operand size.
When the stack pointer is incremented/decremented, it should be changed
by the data size. When a stack pointer is manipulated, the data size
for those calculations should be the stack size. Importantly that does
not change the value of the increment/decrement, which is the operand
size still. This usage has been fixed throughout.
The TLB generally needs to know what the address size was in order to
figure out what segment offset was used so that it can do limit checks.
There is some inherent inaccuracy in doing things in reverse like this,
but that's how it works currently. To find that size, the TLB tried to
start from first principles to figure out what the default address size
was, and then whether there was an override was passed in through the
request flags.
This is *very* inaccurate for a few reasons. First, the override doesn't
always apply. Second, the address size used by a particular instruction
doesn't have to be based on any particular size, whether that is the
default or alternate address size, the stack size, etc.
Instead, the instructions now pass the actual size being used in as a 2
bit value (0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes, 3 -> 8 bytes),
avoiding most of the inaccuracy and approximation.
Because the CPU won't embed any size information into fetches, we'll
just assume those have no wrap around within the address size.
Finally, there were microops that had been added which overrode the
address size to be the stack size internally, and try to help the TLB
figure out what to do to figure out the address size. Because both of
those things are now handled in a different way, those microops are no
longer needed or used and have been deleted.
Change-Id: I2b1bdf1acf1540bf643fac6d49fe1a5a576ba5c1
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55443
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
When instructions perform accesses, they embed the segment being used
into the request flags. When the CPU creates a request instead, for
instance when fetching an instruction, it doesn't know to do that.
This change adds a check in the TLB when makes sure CS is used when
checking a fetch, even if the flags didn't say to.
Change-Id: Ie9da3afc0b10eeb96247353150c64f1829cea41b
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55247
Reviewed-by: Matthew Poremba <matthew.poremba@amd.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
When dealing with segmentation in x86, it is *usually* illegal to
attempt to access a segment which has a null selector when in protected
mode and not in 64 bit mode. While this is *almost* true, it is not
actually technically true.
What actually *is* true is that if you *set up* a segment using a null
selector in those circumstances, that segment becomes unusable, and then
tryint to use it causes a fault.
When in real mode, it is perfectly legal to use a null selector to
access memory, since that is just a selector with numerical value 0.
When you then transition into protected mode, the selector would still
be 0 (a null selector), but the segment itself would still be set up
properly and usuable using the base value, limit, and other attributes
it carried over from real mode.
Rather than check if a segment has a null selector while handling
segmentation, it's more correct for us to keep track of whether the
segment is currently usable and check that in the TLB.
Change-Id: Ic2c09e1cfa05afcb03900213b72733545c8f0f4c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55245
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu>
These were loading the immediate into a temporary microcode register
which would then be used to calculate the address to actually send to
the memory system. Unfortunately this was using a data size equal to the
address size, which would mean that the immediate would be merged into
that temporary, leaving previously set bits intact. The data size
*should* have been set to 8, and was already in other similar
instructions. That forces the limm microop to overwrite the temporary
entirely.
Change-Id: I87c82b4677db768ccb6401a3dbda61317c014152
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55286
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu>
The near call instruction first attempts to store the return address on
the stack (the part of the instruction that could fail), and then if
that succeeds it decrements the stack pointer to point at the newly
stored data.
Unfortunately, the microcode was not using the same offset between
those two steps. Specifically it was using the effective operand size
when storing the return address, but then incorrectly using the
effective stack size when adjusting the stack pointer.
This change updates the microcode to use the effective operand size in
both places.
Change-Id: Ic4211a96900fee5d10c2fa0e038070383fefaac3
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55250
Maintainer: Bobby Bruce <bbruce@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>
The KvmVM will declare itself to the System object, instead of the other
way around. This way the System object can just keep an opaque KvmVM
pointer which does not depend on the KvmVM code even being compiled into
gem5. If there is a KvmVM object, that can more safely assume there is a
corresponding System object to attach itself to.
Also move use of the KvmVM pointer out of constructors, since the VM may
not have registered itself with the System object yet. Those uses can
happen in the init() method instead.
Change-Id: Ia0842612b101315bc1af0232d7f5ae2b55a15922
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/56187
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
These registers used to be accessed with a two dimensional index, with
one dimension specifying the register, and the second index specifying
the element within that register. This change linearizes that index down
to one dimension, where the elements of each register are laid out one
after the other in sequence.
Change-Id: I41110f57b505679a327108369db61c826d24922e
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49148
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
These are mapped to instruction definitions like MOV_R_R, even though
one or more of the Rs might have come from a fixed value. Because
MOV_R_R (for instance) is only defined once, using a fixed text constant
there won't work because that can only have one value.
Instead, use a variable which will have the value of that constant so
that the same disassembly code will work no matter what fixed value was
used.
Change-Id: Ie45181c6becce80ad44fa30fc3323757ef713d7c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55444
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com>
Maintainer: Matt Sinclair <mattdsinclair@gmail.com>
Reviewed-by: Gabe Black <gabe.black@gmail.com>