-
Notifications
You must be signed in to change notification settings - Fork 23
Adding Architectures
This is a step-by-step guide to add support for a new target architecture. If you add an architecture, you do not have to implement everything described here, but the library may offer less features and/or worse performance for your architecture.
This step is a pre-requisite for everything else.
First, choose a name for the translation format(s). Use a generic name based on the name of the ISA rather than a specific implementation. Add suffixes to distinguish between multiple translation variants if necessary.
Second, write a test case for the target address translation. Of course, the
test will fail at this point, but you can use it to track your progress. More
importantly, you can use this test case to make sure that already implemented
features do not break as you write more code. Name your test case like
tests/addrxlat-newarch-variant
. Start with this dummy template:
#! /bin/sh
pf="newarch:12,9,9"
list="0:0" # dummy
. "$srcdir"/addrxlat-common
Don't forget to make the script executable and add it to the test_scripts
variable in test/Makefile.am
. If you run the test suite now, the new test
should fail like this:
Checking 0... Unknown PTE format: newarch:12,9,9
ERROR
Cannot translate 0
Note: You can run a single test case from the test suite with a command like
srcdir=. ./addrxlat-newarch-variant
from the tests
directory. However, if
you take this shortcut, remember to rebuild the library and tests/addrxlat
after every change, e.g. with (cd .. && make) && make addrxlat
.
Next, add an identifier for your architecture's translation format to the
addrxlat_pte_format_t
enum in include/libkdumpfile/addrxlat.h.in
. Add a
string representation of the translation format to the pte_format_names
array in src/addrxlat/step.c
. The output of your test case should change to:
Checking 0... Address translation failed: Unknown PTE format
FAILED
You can start implementing actual address translation now. If your architecture offers various formats of a page table entry, you may want to start with the simplest variant and gradually expand your code.
Always start by adding a test case. Change the dummy page table and list of
addresses in tests/addrxlat-newarch-variant
to add the expected page
translation result, e.g.:
ptes="-e 0x000:0x1000" # PGD[0] -> 1000
ptes="$ptes -e 0x1000:0xa000" # PGD[0] -> PTE[0] -> a000
list="0x123:0xa123" # PGT[0] -> PTE[0]
Next, create a new file src/addrxlat/newarch.c
. Assuming your target
architecture does nothing fancy, you can modify this very minimal stub:
#include "addrxlat-priv.h"
/** Page mask. */
#define PAGE_MASK ADDR_MASK(12)
/** New architecture page table step function.
* @param step Current step state.
* @returns Error status.
*/
addrxlat_status
pgt_newarch(addrxlat_step_t *step)
{
addrxlat_pte_t pte;
addrxlat_status status;
status = read_pte32(step, &pte);
if (status != ADDRXLAT_OK)
return status;
step->base.as = step->meth->target_as;
step->base.addr = pte & ~PAGE_MASK;
if (step->remain == 1)
step->elemsz = 1;
return ADDRXLAT_OK;
}
Note that these are just the bare bones of a step functions. The function does not even check a present (or valid) bit, required by all architectures known to me.
Add the above file to libaddrxlat_la_SOURCES
in src/addrxlat/Makefile.am
.
Add the declaration of your page table step function to
src/addrxlat/addrxlat-priv.h
(sorted alphabetically):
INTERNAL_DECL(addrxlat_next_step_fn, pgt_newarch, );
To use the generic page table translation helpers, let the library know the
size of a single page table entry by extending pteval_shift()
in
src/addrxlat/addrxlat-priv.h
. Make it return 2 for 32-bit entries and 3 for
64-bit entries.
Next, extend the switches in first_step_pgt()
and next_step_pgt()
. The
latter should obviously call pgt_newarch(step)
, but the former may be less
clear:
- Call
first_step_pgt_generic(step, addr)
if your architecture uses all bits of the translation input address, or if unused bits are ignored. - Call
first_step_uaddr(step, addr)
if unused bits must be zero. - Call
first_step_saddr(step, addr)
if unused bits must be a copy of the highest used bit (the sign bit). - Write a new helper if none of the above applies.
When you're done with this part, make a commit. These commits are titled like Add newarch page table translation.