Currently the ppc_hash{32,64}_pte_update_flags() helper functions update a
PTE's referenced and changed bits as necessary to reflect the access. It
is somewhat long winded, though. This patch open codes them in their
(single) callers, in a simpler way.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
BEHAVIOUR CHANGE
Currently, for 64-bit hash mmu, the execute protection bit placed into the
qemu tlb is based only on the N (No execute) bit from the PTE. However,
No Execute can also be set at the segment level. We do check this on
execute faults, but this still means we could incorrectly allow execution
of code from a No Execute segment, if a prior read or write fault caused
the page to be loaded into the qemu tlb with PROT_EXEC set.
To correct this, we (re-)check the segment level no execute permission when
generating the protection bits for the qemu tlb.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Currently checking of PTE permission bits is split messily amongst
ppc_hash{32,64}_pp_check(), ppc_hash{32,64}_check_prot() and their callers.
This patch cleans this up to have the new function
ppc_hash{32,64}_pte_prot() compute the page permissions from the SLBE (for
64-bit) or segment register (32-bit) and the pte. A greatly simplified
version of the actual permissions check is then open coded in the callers.
The 32-bit version of ppc_hash32_pte_prot() is implemented in terms of
ppc_hash32_pp_prot(), a renamed and slightly cleaned up version of the old
ppc_hash32_pp_check(), which is also used for checking BAT permissions on
the 601.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
BEHAVIOUR CHANGE
Currently if ppc_hash{32,64}_translate() finds a PTE matching the given
virtual address, it will always update the PTE's R & C (Referenced and
Changed) bits. This happens even if the PTE's permissions mean we are
about to deny the translation.
This is clearly a bug, although we get away with it because:
a) It will only incorrectly set, never reset the bits, which should not
cause guest correctness problems.
b) Linux guests never use the R & C bits anyway.
This patch fixes the behaviour, only updating R & C when access is granted
by the PTE.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
With previous cleanups made, the 32-bit and 64-bit pte_check*() functions
are pretty trivial and only have one call site. This patch therefore
clarifies the overall code flow by folding those functions into their
call site.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
This patch makes a general cleanup of the address mangling logic in
ppc_hash64_htab_lookup(). In particular it now avoids repeatedly switching
on the segment size. The lack of SLB and multiple segment sizes on 32-bit
means an analogous cleanup is not needed there.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
find_pte{32,64}() are poorly named, since they both find a PTE and do
permissions checking of it. This patch makes them only locate a matching
PTE, moving the permission checking and other logic to the caller. We
rename the resulting search functions ppc_hash{32,64}_htab_lookup().
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
find_pte{32,64}() are not particularly well named. They only "find" a PTE
within a given PTE group, and they also do permissions checking and other
things.
This patch makes it somewhat close to matching the name, by folding the
search of both primary and secondary hash bucket into it, along with the
various address bit shuffling to determine the right hash buckets.
In the 32-bit case we also remove the code for splitting large pages into
4k pieces for the qemu tlb, since no 32-bit hash MMUs support multiple page
sizes.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
find_pte{32,64{() do several things. First they search through a PTEG
ooking for a PTE matching our virtual address. Then they do permissions
checking and other processing on that PTE.
This patch separates the search by VA out from the rest. The search is
combined with the pte{32,64}_match() functions into new
ppc_has{32,64}_pteg_search() functions.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
BEHAVIOUR CHANGE
The ppc hash mmu hashes each virtual address to a primary and secondary
possible hash bucket (aka PTE group or PTEG) each with 8 PTEs. Then we
need a linear search through the PTEs to find the correct one for the
virtual address we're translating.
It is a programming error for the guest to insert multiple PTEs mapping the
same virtual address into a PTEG - in this case the ppc architecture says
the MMU can either act as if just one was present, or give a machine check.
Currently our code takes the first matching PTE in a PTEG if it finds a
successful translation. But if a matching PTE is found, but permission
bits don't allow the access, we keep looking through the PTEG, checking
that any other matching PTEs contain an identical translation.
That behaviour is perhaps not exactly wrong, but it's certainly not useful.
This patch changes it to always just find the first matching PTE in a PTEG.
In addition, if we get a permissions problem on the primary PTEG, we then
search the secondary PTEG. This is incorrect - a permission denying PTE
in the primary PTEG should not be overwritten by an access granting PTE in
the secondary (although again, it would be a programming error for the
guest to set up such a situation anyway). So additionally we update the
code to only search the secondary PTEG if no matching PTE is found in the
primary at all.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
On the ppc hash mmus, no-execute can be set at the segment level (on more
recent 64-bit hash mmus it can also be set at the page level). This patch
separates out this check to make it clearer what is going on, and avoiding
excessive indentation of the remaining translation code.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
After previous work, ppc_hash{32,64}_get_physical_address() are almost
trivial wrappers around get_segment{32,64}() which does nearly all the work of
translating an address according to the hash mmu model. Therefore combine the
two functions into one, under the better name of
ppc_hash{32,64}_translate().
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
The eaddr field of mmu_ctx_hash{32,64} is effectively just used to pass the
effective address from get_segment{32,64}() to find_pte{32,64}(). Just
pass it as a normal parameter instead.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
The nx field in mmu_ctx_hash64 is used in two different functions. But its
used for slightly different things in each place, and the value is never
propagated between them. In other words, it might as well be two local
variables. This patch makes it so.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
In ppc env->access_type is updated by e.g. integer load/stores with
ACCESS_INT floating point load/stores with ACCESS_FLOAT and so forth. In
hash mmu fault paths it can also b set to ACCESS_CODE for instruction
fetch accesses.
But the only place which uses anything more of the access_type than
whether it is instruction fetch or data access is the direct store segment
handling. Instruction versus data access can be more simply determined
from the rw value passed down from the top.
This changes the code to use rw in preference to checking access_type.
For the 32-bit case there is a small amount of code (for direct store
segments) that still needs the full access type. Instead of passing it
all the way down the stack, we retrieve it from the env structure, which
is where it came anyway, before this patch.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
On real hardware the ppc hash page table is stored in memory; accordingly
our mmu emulation code can read a hash page table in guest memory. But,
when paravirtualized under PAPR, the real hash page table is in host
memory, accessible to the guest only via hypercalls. We model this by
also allowing the MMU emulation code to access a specially allocated hash
page table outside the guest's memory image. At present these two options
are implemented with some ugly conditionals at each access point in the mmu
emulation code. In the implementation of the PAPR hypercalls, we assume
the external hash table.
This patch cleans things up by adding helpers to load and store from the
hash table for both 32-bit and 64-bit hash mmus. The 64-bit versions
handle both the in-guest-memory and outside guest memory cases. The 32-bit
versions only handle the in-guest-memory case since no 32-bit systems can
have an external hash table at present.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Currently cpu.h contains a number of definitions relating to the 64-bit
hash MMU. Some are used in the MMU emulation code, but some are only used
in the spapr MMU management hcall implementations.
This patch moves these definitions (except for a few that are needed
more widely) into mmu-hash64.h header, shared between the MMU emulation
code and the spapr hcall code. The MMU emulation code is also updated to
actually use a number of those definitions in place of hard coded
constants.
Similarly, we add new analogous definitions to mmu-hash32.h and use those
in place of many hard-coded constants in mmu-hash32.c
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[agraf: fix 32-bit hosts]
Signed-off-by: Alexander Graf <agraf@suse.de>
mmu_ctx_t is currently defined in cpu.h. However it is used for temporary
information relating to mmu translation, and is only used in mmu_helper.c
and (now) mmu-hash{32,64}.c. Furthermore it contains information which
should be specific to particular MMU types. Therefore, move its definition
to mmu_helper.c. mmu-hash{32,64}.c are converted to use new data types
private to the relevant MMUs (identical to mmu_ctx_t for now, but that will
change in future patches).
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
The get_pteg_offset() helper function is currently shared between 32-bit
and 64-bit hash mmus, taking a parameter for the hash pte size. In the
64-bit paths, it's only called in one place, and it's a trivial
calculation. This patch, therefore, open codes it for 64-bit. The
remaining version, which is used in two places is made 32-bit only and
moved to mmu-hash32.c.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
The newly separated paths for hash mmus rely on several helper functions
which are still shared with 32-bit hash mmus: pp_check(), check_prot() and
pte_update_flags(). While these don't have ugly ifdefs on the mmu type,
they're not very well thought out, so sharing them impedes cleaning up the
hash mmu paths. For now, put near-duplicate versions into mmu-hash64.c and
mmu-hash32.c, leaving the old version in mmu_helper.c for 6xx software
loaded tlb implementations. The hash 32 and software loaded
implementations are simplfied slightly, using the fact that no 32-bit CPUs
implement the 3rd page protection bit.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
cpu_get_phys_page_debug() is a trivial wrapper around
get_physical_address(). But even the signature of
get_physical_address() has some things we'd like to clean up on a
per-mmu basis, so this patch moves the test on mmu model out to
cpu_get_phys_page_debug(), moving the version for 64-bit hash MMUs out
to mmu-hash64.c and the version for 32-bit hash MMUs to mmu-hash32.c
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
cpu_ppc_handle_mmu_fault() calls get_physical_address() (whose behaviour
depends on MMU type) then, if that fails, issues an appropriate exception
- which again has a number of dependencies on MMU type.
This patch starts converting cpu_ppc_handle_mmu_fault() to have a
single switch on MMU type, calling MMU specific fault handler
functions which deal with both translation and exception delivery
appropriately for the MMU type. We convert 32-bit and 64-bit hash
MMUs to this new model, but the existing code is left in place for
other MMU types for now.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Depending on the MSR state, for 64-bit hash MMUs, get_physical_address
can either call check_physical (which has further tests for mmu type)
or get_segment64. Similarly for 32-bit hash MMUs we can either call
check_physucal or get_bat() and get_segment32().
This patch splits off the whole get_physical_addresss() path for hash
MMUs into 32-bit and 64-bit versions, handling real mode correctly for
such MMUs without going to check_physical and rechecking the mmu type.
Correspondingly, the hash MMU specific paths in check_physical() are
removed.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
The poorly named get_segment() function handles most of the address
translation logic for hash-based MMUs. It has many ugly conditionals on
whether the MMU is 32-bit or 64-bit.
This patch splits the function into 32 and 64-bit versions, using the
switch on mmu_type that's already in the caller
(get_physical_address()) to select the right one. Most of the
original function remains in mmu_helper.c to support the 6xx software
loaded TLB implementations (cleaning those up is a project for another
day).
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
32-bit and 64-bit hash MMU implementations currently share a find_pte
function. This results in a whole bunch of ugly conditionals in the shared
function, and not all that much actually shared code.
This patch separates out the 32-bit and 64-bit versions, putting then
in mmu-hash64.c and mmu-has32.c, and removes the conditionals from
both versions.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Currently support for both 32-bit and 64-bit hash MMUs share an
implementation of pte_check. But there are enough differences that this
means the shared function has several very ugly conditionals on "is_64b".
This patch cleans things up by separating out the 64-bit version
(putting it into mmu-hash64.c) and the 32-bit hash version (putting it
in mmu-hash32.c). Another copy remains in mmu_helper.c, which is used
for the 6xx software loaded TLB paths.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
As a first step to disentangling the handling for 64-bit hash MMUs from
the rest, we move the code handling the Segment Lookaside Buffer (SLB)
(which only exists on 64-bit hash MMUs) into a new mmu-hash64.c file.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>