diff --git a/configure.ac b/configure.ac index ae5f8aa4..2909d67b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. dnl -dnl Copyright (C) 2014-2017 Petr Tesarik +dnl Copyright (C) 2014-2020 Petr Tesarik dnl dnl This file is part of libkdumpfile. dnl @@ -19,7 +19,7 @@ dnl along with this program. If not, see . dnl Package release versioning m4_define([pkg_major_version], [0]) -m4_define([pkg_minor_version], [3]) +m4_define([pkg_minor_version], [4]) m4_define([pkg_micro_version], [0]) m4_define([pkg_version], [pkg_major_version.pkg_minor_version.pkg_micro_version]) @@ -108,8 +108,6 @@ AC_CONFIG_FILES([ src/addrxlat/Makefile src/kdumpfile/Makefile python/Makefile - python/addrxlat/Makefile - python/kdumpfile/Makefile tests/Makefile libaddrxlat.pc libkdumpfile.pc diff --git a/debian/control b/debian/control index fb4fd8e8..850509c3 100644 --- a/debian/control +++ b/debian/control @@ -17,5 +17,5 @@ Build-Depends: autoconf, Package: libkdumpfile Architecture: any -Depends: ${shlibs:Depends}, ${python3:Depends} +Depends: libsnappy-dev, ${shlibs:Depends}, ${python3:Depends} Description: Kernel coredump file access diff --git a/include/libkdumpfile/addrxlat.h.in b/include/libkdumpfile/addrxlat.h.in index aec85158..c39c48de 100644 --- a/include/libkdumpfile/addrxlat.h.in +++ b/include/libkdumpfile/addrxlat.h.in @@ -592,6 +592,12 @@ typedef struct _addrxlat_paging_form { /** Parameters of page table translation. */ typedef struct _addrxlat_param_pgt { addrxlat_fulladdr_t root; /**< Root page table address. */ + + /** Page table entry mask. + * Bits to be masked off the raw value. Zero means no masking. + */ + addrxlat_pte_t pte_mask; + addrxlat_paging_form_t pf; /**< Paging form. */ } addrxlat_param_pgt_t; diff --git a/include/libkdumpfile/kdumpfile.h.in b/include/libkdumpfile/kdumpfile.h.in index 01300dbe..25f61989 100644 --- a/include/libkdumpfile/kdumpfile.h.in +++ b/include/libkdumpfile/kdumpfile.h.in @@ -71,6 +71,17 @@ extern "C" { */ typedef uint_fast64_t kdump_num_t; +/** @name fprintf() macros for the libkdumpfile number type + * @{ + * + * POSIX @c PRI_xxx style macros for use with @ref kdump_num_t. + */ +#define KDUMP_PRIoNUM PRIoFAST64 /**< Octal @c kdump_num_t */ +#define KDUMP_PRIuNUM PRIuFAST64 /**< Decimal @c kdump_num_t */ +#define KDUMP_PRIxNUM PRIxFAST64 /**< Lowercase hex @c kdump_num_t */ +#define KDUMP_PRIXNUM PRIXFAST64 /**< Uppercase hex @c kdump_num_t */ +/* @} */ + /** Type of a physical or virtual address. * * This type is large enough to hold any possible address type on any @@ -97,6 +108,18 @@ typedef kdump_addr_t kdump_paddr_t; */ typedef kdump_addr_t kdump_vaddr_t; +/** @name fprintf() macros for the libkdumpfile address type + * @{ + * + * POSIX @c PRI_xxx style macros for use with @ref kdump_addr_t, + * @ref kdump_paddr_t and @ref kdump_vaddr_t. + */ +#define KDUMP_PRIoADDR ADDRXLAT_PRIoADDR /**< Octal address */ +#define KDUMP_PRIuADDR ADDRXLAT_PRIuADDR /**< Decimal address */ +#define KDUMP_PRIxADDR ADDRXLAT_PRIxADDR /**< Lowercase hex address */ +#define KDUMP_PRIXADDR ADDRXLAT_PRIXADDR /**< Uppercase hex address */ +/* @} */ + /** Representation of a dump file. * * The context contains all information needed to work with a dump file. @@ -138,6 +161,24 @@ typedef enum _kdump_byte_order { KDUMP_LITTLE_ENDIAN = ADDRXLAT_LITTLE_ENDIAN, } kdump_byte_order_t; +/** File mmap policy. + * + * Control if and how mmap(2) should be used to access data from the + * underlying core file. + * + * @sa KDUMP_ATTR_FILE_MMAP_POLICY + */ +typedef enum _kdump_mmap_policy { + KDUMP_MMAP_NEVER, /**< Never use mmap(2), always use read(2). */ + KDUMP_MMAP_ALWAYS, /**< Always use mmap(2), never use read(2). */ + KDUMP_MMAP_TRY, /**< Try mmap(2), fall back to read(2). */ + + /** Same as @c KDUMP_MMAP_TRY, but change to @c KDUMP_MMAP_NEVER + * or @c KDUMP_MMAP_ALWAYS based on the result of the next read. + */ + KDUMP_MMAP_TRY_ONCE, +} kdump_mmap_policy_t; + /** Type of a Xen dump. * @sa KDUMP_ATTR_XEN_TYPE */ @@ -406,6 +447,35 @@ kdump_status kdump_bmp_find_clear( */ typedef struct _kdump_blob kdump_blob_t; +/** Create a new blob object. + * @param data Raw data buffer (can be @c NULL). + * @param size Length of data at @c data. + * @returns New blob object, or @c NULL on allocation error. + * + * Create a new blob object from a dynamically allocated memory buffer. + * Keep in mind that the buffer will be eventually de-allocated with + * free(3) when the blob reference count drops to zero. + * + * If @c data is @c NULL, then the blob does not contain any data. + * + * The new object's reference count is initialized to 1 (the caller + * receives one reference), and the memory buffer is not pinned. + */ +kdump_blob_t *kdump_blob_new(void *data, size_t size); + +/** Create a new blob object from a copy of a buffer. + * @param data Raw data buffer (can be @c NULL). + * @param size Length of data at @c data. + * @returns New blob object, or @c NULL on allocation error. + * + * Create a new blob object by duplicating data from a buffer. The + * data is copied into a newly allocated buffer which is owned by + * the blob object itself. + * + * @sa kdump_blob_new + */ +kdump_blob_t *kdump_blob_new_dup(const void *data, size_t size); + /** Increment kdump blob reference counter. * @param blob Binary object. * @returns New reference count. @@ -923,24 +993,36 @@ void kdump_attr_iter_end(kdump_ctx_t *ctx, kdump_attr_iter_t *iter); /** Fill excluded pages with zeroes? */ #define KDUMP_ATTR_ZERO_EXCLUDED "file.zero_excluded" +/** Policy for using mmap vs. read. + * Default is @c KDUMP_MMAP_TRY. + * @sa kdump_mmap_policy_t + */ +#define KDUMP_ATTR_FILE_MMAP_POLICY "file.mmap_policy" + /** Get VMCOREINFO raw data. * @param ctx Dump file object. - * @param raw Filled with raw VMCOREINFO string on success. + * @param raw Filled with a copy of the raw VMCOREINFO string on success. * @returns Error status. * * The output string is always NUL-terminated, but if there was a NUL * byte inside VMCOREINFO, there is no way to know the full length. + * + * The output string is dynamically allocated and must be eventually + * deallocated by the caller using @c free(3). */ -kdump_status kdump_vmcoreinfo_raw(kdump_ctx_t *ctx, const char **raw); +kdump_status kdump_vmcoreinfo_raw(kdump_ctx_t *ctx, char **raw); /** Get a VMCOREINFO line. * @param ctx Dump file object. * @param[in] key Name of the VMCOREINFO variable (part before '='). * @param[out] val Filled with the part after (first) '='. * @returns Error status. + * + * The output string is dynamically allocated and must be eventually + * deallocated by the caller using @c free(3). */ kdump_status kdump_vmcoreinfo_line(kdump_ctx_t *ctx, const char *key, - const char **val); + char **val); /** Get VMCOREINFO symbol value. * @param ctx Dump file object. diff --git a/python/.gitignore b/python/.gitignore index d6d81e93..29fb1699 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -1,3 +1,9 @@ +# generated by Makefile +setup.cfg + +# distutils build +build + # Test results *.log *.trs diff --git a/python/Makefile.am b/python/Makefile.am index 38f5f2f9..6e6de87e 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -23,17 +23,42 @@ AM_CPPFLAGS = -I$(top_builddir)/include AM_CFLAGS = $(PYTHON_CFLAGS) AM_LDFLAGS = -module -avoid-version -pyexec_LTLIBRARIES = _addrxlat.la _kdumpfile.la +installed_list = installed.list -_addrxlat_la_SOURCES = addrxlat.c -_addrxlat_la_LDFLAGS = $(AM_LDFLAGS) -export-symbols $(srcdir)/addrxlat.sym -_addrxlat_la_LIBADD = $(PYTHON_LIBS) $(top_builddir)/src/addrxlat/libaddrxlat.la -EXTRA__addrxlat_la_DEPENDENCIES = addrxlat.sym +setup.cfg: Makefile + $(AM_V_GEN) + $(AM_V_at)echo "[kdumpfile]" > $@ + $(AM_V_at)echo "version=$(VERSION)" >> $@ + $(AM_V_at)echo "srcdir=$(srcdir)" >> $@ + $(AM_V_at)echo "top_builddir=$(top_builddir)" >> $@ + $(AM_V_at)echo >> $@ + $(AM_V_at)echo "[build_ext]" >> $@ + $(AM_V_at)echo "libtool=$(LIBTOOL)" >> $@ + $(AM_V_at)echo "pyexecdir=$(pyexecdir)" >> $@ + $(AM_V_at)echo >> $@ + $(AM_V_at)echo "[install_lib]" >> $@ + $(AM_V_at)echo "libtool_install=$(LIBTOOL) --mode=install $(INSTALL)" >> $@ -_kdumpfile_la_SOURCES = kdumpfile.c -_kdumpfile_la_LDFLAGS = $(AM_LDFLAGS) -export-symbols $(srcdir)/kdumpfile.sym -_kdumpfile_la_LIBADD = $(PYTHON_LIBS) $(top_builddir)/src/kdumpfile/libkdumpfile.la -EXTRA__kdumpfile_la_DEPENDENCIES = kdumpfile.sym +all-local: setup.cfg + $(PYTHON) $(srcdir)/setup.py build + +install-exec-local: setup.cfg + $(PYTHON) $(srcdir)/setup.py install \ + --root "$(DESTDIR)"/ \ + --install-purelib $(pythondir) \ + --install-platlib $(pyexecdir) \ + --record $(installed_list) + +uninstall-local: $(installed_list) + while read f ; do \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)/$$f" ; \ + done < $< + +mostlyclean-local: setup.cfg + $(PYTHON) $(srcdir)/setup.py clean --all + rm $< + +CLEANFILES = $(installed_list) check_LTLIBRARIES = _test_addrxlat.la @@ -45,13 +70,22 @@ _test_addrxlat_la_LDFLAGS = \ _test_addrxlat_la_LIBADD = $(PYTHON_LIBS) $(top_builddir)/src/addrxlat/libaddrxlat.la EXTRA__test_addrxlat_la_DEPENDENCIES = test_addrxlat.sym -dist_noinst_DATA = \ - addrxlat.sym \ - kdumpfile.sym \ - test_addrxlat.sym \ +dist_noinst_SCRIPTS = \ + setup.py \ + libtoolize.py \ + addrxlat/__init__.py \ + addrxlat/exceptions.py \ + kdumpfile/__init__.py \ + kdumpfile/exceptions.py \ + kdumpfile/views.py \ showxlat.py \ vtop.py +dist_noinst_DATA = \ + addrxlat.c \ + kdumpfile.c \ + test_addrxlat.sym + noinst_HEADERS = \ addrxlatmod.h @@ -68,5 +102,3 @@ LOG_COMPILER = $(PYTHON) AM_TESTS_ENVIRONMENT = \ eval " $$($(LIBTOOL) --config)"; \ PYTHONPATH="$$srcdir:$$objdir" - -SUBDIRS = addrxlat kdumpfile diff --git a/python/addrxlat.c b/python/addrxlat.c index 03767a5c..16ae2b63 100644 --- a/python/addrxlat.c +++ b/python/addrxlat.c @@ -521,6 +521,39 @@ set_addrspace(PyObject *self, PyObject *value, void *data) return 0; } +/** Getter for the addrxlat_pte_t type. + * @param self any object + * @param data offset of the addrxlat_pte_t member + * @returns PyLong object (or @c NULL on failure) + */ +static PyObject * +get_pte(PyObject *self, void *data) +{ + Py_ssize_t off = (intptr_t)data; + addrxlat_pte_t *pval = (addrxlat_pte_t*)((char*)self + off); + return PyLong_FromUnsignedLongLong(*pval); +} + +/** Setter for the addrxlat_pte_t type. + * @param self any object + * @param value new value (a @c PyLong or @c PyInt) + * @param data offset of the addrxlat_pte_t member + * @returns zero on success, -1 otherwise + */ +static int +set_pte(PyObject *self, PyObject *value, void *data) +{ + Py_ssize_t off = (intptr_t)data; + addrxlat_pte_t *pval = (addrxlat_pte_t*)((char*)self + off); + unsigned long long pte = Number_AsUnsignedLongLongMask(value); + + if (PyErr_Occurred()) + return -1; + + *pval = pte; + return 0; +} + /** An object with a C pointer. * This object is used to create a Python object from a C pointer to * the corresponding libaddrxlat object passed as a _C_POINTER argument. @@ -3110,10 +3143,15 @@ static fulladdr_loc pgtmeth_root_loc = { "root" }; +PyDoc_STRVAR(pgtmeth_pte_mask__doc__, +"page table entry mask"); + static PyGetSetDef pgtmeth_getset[] = { { "kind", meth_get_kind, 0, pgtmeth_kind__doc__ }, { "root", get_fulladdr, set_fulladdr, pgtmeth_root__doc__, &pgtmeth_root_loc }, + { "pte_mask", get_pte, set_pte, pgtmeth_pte_mask__doc__, + OFFSETOF_PTR(meth_object, meth.param.pgt.pte_mask) }, { "pte_format", pgtmeth_get_pte_format, pgtmeth_set_pte_format, pgtmeth_pte_format__doc__ }, { "fields", pgtmeth_get_fields, pgtmeth_set_fields, diff --git a/python/libtoolize.py b/python/libtoolize.py new file mode 100644 index 00000000..da1f76d1 --- /dev/null +++ b/python/libtoolize.py @@ -0,0 +1,132 @@ +"""libtool + +Build and install extensions using libtool. +""" + +import os +from distutils import log +from distutils.util import split_quoted +from distutils.dir_util import mkpath +from distutils.file_util import copy_file +from distutils.spawn import spawn +from distutils.errors import DistutilsFileError + +from distutils.command.build_ext import build_ext as _build_ext +class build_ext(_build_ext): + def initialize_options(self): + _build_ext.initialize_options(self) + self.libtool = None + self.pyexecdir = None + + def finalize_options(self): + _build_ext.finalize_options(self) + + if self.libtool is None: + self.libtool = 'libtool' + if self.pyexecdir is None: + import sysconfig + self.pyexecdir = sysconfig.get_path('platlib') + self.cmd_libtool = split_quoted(self.libtool) + + def libtoolize(self, key, mode, *args): + val = getattr(self.compiler, key) + val = val[:1] + list(args) + val[1:] + setattr(self.compiler, key, + self.cmd_libtool + [ '--mode='+mode ] + val) + + def build_extensions(self): + self.compiler.obj_extension = '.lo' + self.libtoolize('compiler', 'compile') + self.libtoolize('compiler_so', 'compile') + self.libtoolize('linker_exe', 'link') + self.libtoolize('linker_so', 'link', + '-module', '-avoid-version', + '-export-symbols-regex', 'init.*|PyInit_.*', + '-rpath', self.pyexecdir) + _build_ext.build_extensions(self) + +from distutils.command.install_lib import install_lib as _install_lib +class install_lib(_install_lib): + def initialize_options(self): + _install_lib.initialize_options(self) + self.libtool_install = None + + def finalize_options(self): + _install_lib.finalize_options(self) + + if self.libtool_install is None: + self.libtool_install = 'libtool --mode=install install' + self.cmd_libtool_install = split_quoted(self.libtool_install) + + def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1, + preserve_symlinks=0, level=1): + """Copy the build directory tree, respecting dry-run and force flags. + Special treatment of libtool files. + """ + if not self.dry_run and not os.path.isdir(infile): + raise DistutilsFileError( + "cannot copy tree '%s': not a directory" % infile) + try: + names = os.listdir(infile) + except OSError as e: + if self.dry_run: + names = [] + else: + raise DistutilsFileError( + "error listing files in '%s': %s" % (infile, e.strerror)) + + if not self.dry_run: + mkpath(outfile) + + outputs = [] + + for n in names: + src_name = os.path.join(infile, n) + dst_name = os.path.join(outfile, n) + + if n.startswith('.nfs'): + # skip NFS rename files + continue + if n in ('.libs', '_libs'): + # skip libtool directories + continue + + if preserve_symlinks and os.path.islink(src_name): + link_dest = os.readlink(src_name) + log.info("linking %s -> %s", dst_name, link_dest) + if not self.dry_run: + os.symlink(link_dest, dst_name) + outputs.append(dst_name) + + elif os.path.isdir(src_name): + outputs.extend( + self.copy_tree(src_name, dst_name, preserve_mode, + preserve_times, preserve_symlinks)) + + elif n.endswith('.la'): + spawn(self.cmd_libtool_install + [ src_name, dst_name ], + dry_run=self.dry_run) + + else: + copy_file(src_name, dst_name, preserve_mode, + preserve_times, not self.force, + dry_run=self.dry_run) + outputs.append(dst_name) + + return outputs + +def sysconfig_replace_ext(varname, newext): + """Replace the extension in a system config variable. + """ + from distutils.sysconfig import _config_vars + val = _config_vars.get(varname, '') + suffpos = val.rfind('.') + if suffpos >= 0: + val = val[:suffpos] + _config_vars[varname] = val + newext + +# change default shared object suffix to .la +from distutils.sysconfig import get_config_vars +get_config_vars() +sysconfig_replace_ext('EXT_SUFFIX', '.la') +sysconfig_replace_ext('SO', '.la') diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 00000000..982d79d6 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,49 @@ +from distutils.core import setup, Extension +import libtoolize +import os + +try: + from configparser import ConfigParser +except ImportError: + from ConfigParser import ConfigParser + +cfg = ConfigParser() +cfg.read('setup.cfg') +srcdir = cfg.get('kdumpfile', 'srcdir') +top_builddir = cfg.get('kdumpfile', 'top_builddir') +include_dir=os.path.join(top_builddir, 'include'), +addrxlat_la = os.path.join( + top_builddir, 'src', 'addrxlat', 'libaddrxlat.la') +kdumpfile_la = os.path.join( + top_builddir, 'src', 'kdumpfile', 'libkdumpfile.la') + +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) ", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+) ", + "Programming Language :: Python", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Software Development :: Debuggers "] + +setup(name='libkdumpfile', + version=cfg.get('kdumpfile', 'version'), + description='Python bindings for libkdumpfile', + author='Petr Tesarik', + author_email='ptesarik@suse.com', + url='https://github.com/ptesarik/libkdumpfile', + packages=['addrxlat', 'kdumpfile'], + package_dir={'': srcdir}, + ext_modules=[ + Extension('_addrxlat', [os.path.join(srcdir, 'addrxlat.c')], + include_dirs=[include_dir], + extra_objects=[addrxlat_la]), + Extension('_kdumpfile', [os.path.join(srcdir, 'kdumpfile.c')], + include_dirs=[include_dir], + extra_objects=[kdumpfile_la]), + ], + cmdclass={ + 'build_ext': libtoolize.build_ext, + 'install_lib': libtoolize.install_lib, + }, +) diff --git a/src/addrxlat/Makefile.am b/src/addrxlat/Makefile.am index 73a25cbf..dde5e7e8 100644 --- a/src/addrxlat/Makefile.am +++ b/src/addrxlat/Makefile.am @@ -35,7 +35,7 @@ libaddrxlat_la_SOURCES = \ s390x.c \ x86_64.c -libaddrxlat_la_LDFLAGS = -version-info 0:0:0 +libaddrxlat_la_LDFLAGS = -version-info 2:0:0 if HAVE_LD_VERSION_SCRIPT libaddrxlat_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libaddrxlat.map diff --git a/src/addrxlat/aarch64.c b/src/addrxlat/aarch64.c index 15802d9b..099a803f 100644 --- a/src/addrxlat/aarch64.c +++ b/src/addrxlat/aarch64.c @@ -112,19 +112,20 @@ pte_invalid(addrxlat_step_t *step) addrxlat_status pgt_aarch64(addrxlat_step_t *step) { + addrxlat_pte_t pte; addrxlat_status status; - status = read_pte64(step); + status = read_pte64(step, &pte); if (status != ADDRXLAT_OK) return status; - if (!PTE_VALID(step->raw.pte)) + if (!PTE_VALID(pte)) return pte_not_present(step); - step->base.addr = step->raw.pte & PA_MASK; + step->base.addr = pte & PA_MASK; step->base.as = step->meth->target_as; - if (PTE_TYPE(step->raw.pte) == PTE_TYPE_BLOCK) { + if (PTE_TYPE(pte) == PTE_TYPE_BLOCK) { addrxlat_addr_t mask = pf_table_mask( &step->meth->param.pgt.pf, step->remain); if (mask > PAGE_MASK_1G) diff --git a/src/addrxlat/addrxlat-priv.h b/src/addrxlat/addrxlat-priv.h index 98b4c125..333b1637 100644 --- a/src/addrxlat/addrxlat-priv.h +++ b/src/addrxlat/addrxlat-priv.h @@ -251,37 +251,43 @@ struct _addrxlat_sys { /** Read raw 32-bit PTE value. * @param step Current step state. + * @param pte Set to the (masked) PTE value on success. * @returns Error status. * * On successful return, @c step->raw.pte contains the raw * PTE value for the current translation step. */ static inline addrxlat_status -read_pte32(addrxlat_step_t *step) +read_pte32(addrxlat_step_t *step, addrxlat_pte_t *pte) { uint32_t pte32; addrxlat_status status; status = read32(step, &step->base, &pte32, "PTE"); - if (status == ADDRXLAT_OK) + if (status == ADDRXLAT_OK) { step->raw.pte = pte32; + *pte = pte32 & ~step->meth->param.pgt.pte_mask; + } return status; } /** Read raw 64-bit PTE value. * @param step Current step state. + * @param pte Set to the (masked) PTE value on success. * @returns Error status. * * On successful return, @c step->raw.pte contains the raw * PTE value for the current translation step. */ static inline addrxlat_status -read_pte64(addrxlat_step_t *step) +read_pte64(addrxlat_step_t *step, addrxlat_pte_t *pte) { uint64_t pte64; addrxlat_status status; status = read64(step, &step->base, &pte64, "PTE"); - if (status == ADDRXLAT_OK) + if (status == ADDRXLAT_OK) { step->raw.pte = pte64; + *pte = pte64 & ~step->meth->param.pgt.pte_mask; + } return status; } @@ -383,6 +389,7 @@ enum optidx { OPT_levels, /**< Number of page table levels. */ OPT_pagesize, /**< Page size (number). */ OPT_phys_base, /**< [x86-64] Linux physical base address. */ + OPT_pte_mask, /**< Page table entry mask. */ OPT_rootpgt, /**< Root page table address. */ OPT_xen_p2m_mfn, /**< Xen p2m root machine frame number. */ OPT_xen_xlat, /**< Use Xen m2p and p2m translation. */ @@ -416,6 +423,17 @@ INTERNAL_DECL(addrxlat_status, parse_opts, (struct parsed_opts *popt, addrxlat_ctx_t *ctx, const char *opts)); +/** Get a numeric option, with fallback to default value. + * @param opt Parsed options. + * @param idx Option index. + * @param def Default value if the option is not set. + */ +static inline long +opt_num_default(const struct parsed_opts *opts, enum optidx idx, long def) +{ + return opts->val[idx].set ? opts->val[idx].num : def; +} + /* Translation system */ /** Data used during translation system initialization. */ diff --git a/src/addrxlat/ia32.c b/src/addrxlat/ia32.c index ab83705c..b31adfa8 100644 --- a/src/addrxlat/ia32.c +++ b/src/addrxlat/ia32.c @@ -90,13 +90,14 @@ pgt_ia32(addrxlat_step_t *step) "pte", "pgd", }; + addrxlat_pte_t pte; addrxlat_status status; - status = read_pte32(step); + status = read_pte32(step, &pte); if (status != ADDRXLAT_OK) return status; - if (!(step->raw.pte & _PAGE_PRESENT)) + if (!(pte & _PAGE_PRESENT)) return !step->ctx->noerr.notpresent ? set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "%s not present: %s[%u] = 0x%" ADDRXLAT_PRIxPTE, @@ -106,12 +107,12 @@ pgt_ia32(addrxlat_step_t *step) step->raw.pte) : ADDRXLAT_ERR_NOTPRESENT; - step->base.addr = step->raw.pte; + step->base.addr = pte; step->base.as = step->meth->target_as; - if (step->remain == 2 && (step->raw.pte & _PAGE_PSE)) { + if (step->remain == 2 && (pte & _PAGE_PSE)) { step->base.addr &= ~PAGE_MASK_4M; - step->base.addr |= pgd_pse_high(step->raw.pte); + step->base.addr |= pgd_pse_high(pte); return pgt_huge_page(step); } @@ -139,13 +140,14 @@ pgt_ia32_pae(addrxlat_step_t *step) "pmd", "pgd", }; + addrxlat_pte_t pte; addrxlat_status status; - status = read_pte64(step); + status = read_pte64(step, &pte); if (status != ADDRXLAT_OK) return status; - if (!(step->raw.pte & _PAGE_PRESENT)) + if (!(pte & _PAGE_PRESENT)) return !step->ctx->noerr.notpresent ? set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "%s not present: %s[%u] = 0x%" ADDRXLAT_PRIxPTE, @@ -155,10 +157,10 @@ pgt_ia32_pae(addrxlat_step_t *step) step->raw.pte) : ADDRXLAT_ERR_NOTPRESENT; - step->base.addr = step->raw.pte & PHYSADDR_MASK_PAE; + step->base.addr = pte & PHYSADDR_MASK_PAE; step->base.as = step->meth->target_as; - if (step->remain == 2 && (step->raw.pte & _PAGE_PSE)) { + if (step->remain == 2 && (pte & _PAGE_PSE)) { step->base.addr &= ~PAGE_MASK_2M; return pgt_huge_page(step); } @@ -212,6 +214,8 @@ check_pae(struct os_init_data *ctl, const addrxlat_fulladdr_t *root, if (status != ADDRXLAT_OK) return set_error(ctl->ctx, status, "Cannot set up physical mappings"); + meth.param.pgt.pte_mask = + opt_num_default(&ctl->popt, OPT_pte_mask, 0); meth.param.pgt.pf = ia32_pf_pae; step.ctx = ctl->ctx; step.sys = ctl->sys; @@ -294,6 +298,8 @@ sys_ia32_nonpae(struct os_init_data *ctl) meth->param.pgt.root = ctl->popt.val[OPT_rootpgt].fulladdr; else meth->param.pgt.root.as = ADDRXLAT_NOADDR; + meth->param.pgt.pte_mask = + opt_num_default(&ctl->popt, OPT_pte_mask, 0); meth->param.pgt.pf = ia32_pf; return ADDRXLAT_OK; } @@ -319,6 +325,8 @@ sys_ia32_pae(struct os_init_data *ctl) meth->param.pgt.root = ctl->popt.val[OPT_rootpgt].fulladdr; else meth->param.pgt.root.as = ADDRXLAT_NOADDR; + meth->param.pgt.pte_mask = + opt_num_default(&ctl->popt, OPT_pte_mask, 0); meth->param.pgt.pf = ia32_pf_pae; return ADDRXLAT_OK; } diff --git a/src/addrxlat/opt.c b/src/addrxlat/opt.c index 89ab6f6f..f5b17740 100644 --- a/src/addrxlat/opt.c +++ b/src/addrxlat/opt.c @@ -217,6 +217,7 @@ static const struct { char name[9]; } opt8[] = { DEF(pagesize, number), + DEF(pte_mask, number), DEF(xen_xlat, bool), END }; diff --git a/src/addrxlat/ppc64.c b/src/addrxlat/ppc64.c index 381fcc4f..8408e073 100644 --- a/src/addrxlat/ppc64.c +++ b/src/addrxlat/ppc64.c @@ -113,22 +113,23 @@ hugepd_shift(addrxlat_pte_t hpde) /** Translate a Linux huge page using its directory entry. * @param step Current step state. + * @param pte Page table entry value (possibly masked). * @returns Error status. */ static addrxlat_status -huge_pd_linux(addrxlat_step_t *step) +huge_pd_linux(addrxlat_step_t *step, addrxlat_pte_t pte) { const addrxlat_paging_form_t *pf = &step->meth->param.pgt.pf; addrxlat_addr_t off; unsigned pdshift; unsigned short i; - pdshift = hugepd_shift(step->raw.pte); + pdshift = hugepd_shift(pte); if (!pdshift) return set_error(step->ctx, ADDRXLAT_ERR_INVALID, "Invalid hugepd shift"); - step->base.addr = (step->raw.pte & ~HUGEPD_SHIFT_MASK) | PD_HUGE; + step->base.addr = (pte & ~HUGEPD_SHIFT_MASK) | PD_HUGE; step->base.as = ADDRXLAT_KVADDR; /* Calculate the total byte offset below current table. */ @@ -151,7 +152,7 @@ huge_pd_linux(addrxlat_step_t *step) } /** Check whether a Linux page table entry is huge. - * @param pte Page table entry (value). + * @param pte Page table entry value (possibly masked). * @returns Non-zero if this is a huge page entry. */ static inline int @@ -161,7 +162,8 @@ is_hugepte_linux(addrxlat_pte_t pte) } /** Update current step state for Linux huge page. - * @param state Current step state. + * @param step Current step state. + * @param pte Page table entry value (possibly masked). * @param rpn_shift RPN shift. * @returns Always @c ADDRXLAT_OK. * @@ -170,11 +172,11 @@ is_hugepte_linux(addrxlat_pte_t pte) * offset and terminates. */ static addrxlat_status -huge_page_linux(addrxlat_step_t *step, unsigned rpn_shift) +huge_page_linux(addrxlat_step_t *step, addrxlat_pte_t pte, unsigned rpn_shift) { const addrxlat_paging_form_t *pf = &step->meth->param.pgt.pf; - step->base.addr = (step->raw.pte >> rpn_shift) << pf->fieldsz[0]; + step->base.addr = (pte >> rpn_shift) << pf->fieldsz[0]; step->base.as = step->meth->target_as; return pgt_huge_page(step); } @@ -194,13 +196,14 @@ pgt_ppc64_linux(addrxlat_step_t *step, unsigned rpn_shift) "pgd", }; const addrxlat_paging_form_t *pf = &step->meth->param.pgt.pf; + addrxlat_pte_t pte; addrxlat_status status; - status = read_pte64(step); + status = read_pte64(step, &pte); if (status != ADDRXLAT_OK) return status; - if (!step->raw.pte) + if (!pte) return !step->ctx->noerr.notpresent ? set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "%s[%u] is none", @@ -211,19 +214,18 @@ pgt_ppc64_linux(addrxlat_step_t *step, unsigned rpn_shift) if (step->remain > 1) { addrxlat_addr_t table_size; - if (is_hugepte_linux(step->raw.pte)) - return huge_page_linux(step, rpn_shift); + if (is_hugepte_linux(pte)) + return huge_page_linux(step, pte, rpn_shift); - if (is_hugepd_linux(step->raw.pte)) - return huge_pd_linux(step); + if (is_hugepd_linux(pte)) + return huge_pd_linux(step, pte); table_size = ((addrxlat_addr_t)1 << PTE_SHIFT << pf->fieldsz[step->remain - 1]); - step->base.addr = step->raw.pte & ~(table_size - 1); + step->base.addr = pte & ~(table_size - 1); step->base.as = ADDRXLAT_KVADDR; } else { - step->base.addr = - (step->raw.pte >> rpn_shift) << pf->fieldsz[0]; + step->base.addr = (pte >> rpn_shift) << pf->fieldsz[0]; step->base.as = step->meth->target_as; step->elemsz = 1; } @@ -359,10 +361,7 @@ map_linux_ppc64(struct os_init_data *ctl) addrxlat_meth_t *meth; addrxlat_status status; - pagesize = ctl->popt.val[OPT_pagesize].set - ? ctl->popt.val[OPT_pagesize].num - : _64K; /* default 64k */ - + pagesize = opt_num_default(&ctl->popt, OPT_pagesize, _64K); if (pagesize != _64K) return set_error(ctl->ctx, ADDRXLAT_ERR_NOTIMPL, "Unsupported page size: %ld", pagesize); @@ -378,6 +377,8 @@ map_linux_ppc64(struct os_init_data *ctl) meth = &ctl->sys->meth[ADDRXLAT_SYS_METH_UPGT]; meth->kind = ADDRXLAT_PGT; meth->target_as = ADDRXLAT_MACHPHYSADDR; + meth->param.pgt.pte_mask = + opt_num_default(&ctl->popt, OPT_pte_mask, 0); meth->param.pgt.root.as = ADDRXLAT_NOADDR; meth->param.pgt.pf = ppc64_pf_64k; diff --git a/src/addrxlat/s390x.c b/src/addrxlat/s390x.c index f5801eef..d8edcb85 100644 --- a/src/addrxlat/s390x.c +++ b/src/addrxlat/s390x.c @@ -81,13 +81,14 @@ pgt_s390x(addrxlat_step_t *step) "rg1", /* Invented; does not exist in the wild. */ }; const addrxlat_paging_form_t *pf = &step->meth->param.pgt.pf; + addrxlat_pte_t pte; addrxlat_status status; - status = read_pte64(step); + status = read_pte64(step, &pte); if (status != ADDRXLAT_OK) return status; - if (PTE_I(step->raw.pte)) + if (PTE_I(pte)) return !step->ctx->noerr.notpresent ? set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "%s not present: %s[%u] = 0x%" ADDRXLAT_PRIxPTE, @@ -97,21 +98,21 @@ pgt_s390x(addrxlat_step_t *step) step->raw.pte) : ADDRXLAT_ERR_NOTPRESENT; - if (step->remain >= 2 && PTE_TT(step->raw.pte) != step->remain - 2) + if (step->remain >= 2 && PTE_TT(pte) != step->remain - 2) return set_error(step->ctx, ADDRXLAT_ERR_INVALID, "Table type field %u in %s", - (unsigned) PTE_TT(step->raw.pte), + (unsigned) PTE_TT(pte), pgt_full_name[step->remain]); - step->base.addr = step->raw.pte; + step->base.addr = pte; step->base.as = step->meth->target_as; - if (step->remain == 3 && PTE_FC(step->raw.pte)) { + if (step->remain == 3 && PTE_FC(pte)) { step->base.addr &= ~RFAA_MASK; return pgt_huge_page(step); } - if (step->remain == 2 && PTE_FC(step->raw.pte)) { + if (step->remain == 2 && PTE_FC(pte)) { step->base.addr &= ~SFAA_MASK; return pgt_huge_page(step); } @@ -119,15 +120,14 @@ pgt_s390x(addrxlat_step_t *step) if (step->remain >= 3) { unsigned pgidx = step->idx[step->remain - 1] >> (pf->fieldsz[step->remain - 1] - pf->fieldsz[0]); - if (pgidx < PTE_TF(step->raw.pte) || - pgidx > PTE_TL(step->raw.pte)) + if (pgidx < PTE_TF(pte) || pgidx > PTE_TL(pte)) return !step->ctx->noerr.notpresent ? set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "%s index %u not within %u and %u", pgt_full_name[step->remain-1], (unsigned) step->idx[step->remain-1], - (unsigned) PTE_TF(step->raw.pte), - (unsigned) PTE_TL(step->raw.pte)) + (unsigned) PTE_TF(pte), + (unsigned) PTE_TL(pte)) : ADDRXLAT_ERR_NOTPRESENT; } @@ -238,6 +238,8 @@ init_paging_form(struct os_init_data *ctl) meth->kind = ADDRXLAT_PGT; meth->target_as = ADDRXLAT_MACHPHYSADDR; + meth->param.pgt.pte_mask = + opt_num_default(&ctl->popt, OPT_pte_mask, 0); meth->param.pgt.pf = pf; meth->param.pgt.pf.nfields = levels + 1; return ADDRXLAT_OK; diff --git a/src/addrxlat/step.c b/src/addrxlat/step.c index 81c2c3f2..bd56e9a2 100644 --- a/src/addrxlat/step.c +++ b/src/addrxlat/step.c @@ -139,22 +139,22 @@ first_step_pgt_generic(addrxlat_step_t *step, addrxlat_addr_t addr) /** Common next step helper for page frame number. * @param step Current step state. + * @param pte Page table entry value (possibly masked). * @returns Error status. * * This function contains the common processing for 32-bit and - * 64-bit PFNs after the PTE was read into @c step->raw.pte. + * 64-bit PFNs after the PTE was read. */ static addrxlat_status -next_step_pfn_common(addrxlat_step_t *step) +next_step_pfn_common(addrxlat_step_t *step, addrxlat_pte_t pte) { const addrxlat_meth_t *meth; - if (!step->raw.pte) + if (!pte) return set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "Level-%u PFN not present", step->remain); meth = step->meth; - step->base.addr = - step->raw.pte << meth->param.pgt.pf.fieldsz[0]; + step->base.addr = pte << meth->param.pgt.pf.fieldsz[0]; step->base.as = meth->target_as; if (step->remain == 1) step->elemsz = 1; @@ -170,10 +170,11 @@ next_step_pfn_common(addrxlat_step_t *step) static addrxlat_status next_step_pfn32(addrxlat_step_t *step) { - addrxlat_status status = read_pte32(step); + addrxlat_pte_t pte; + addrxlat_status status = read_pte32(step, &pte); if (status != ADDRXLAT_OK) return status; - return next_step_pfn_common(step); + return next_step_pfn_common(step, pte); } /** Next step function for a 64-bit page frame number. @@ -185,10 +186,11 @@ next_step_pfn32(addrxlat_step_t *step) static addrxlat_status next_step_pfn64(addrxlat_step_t *step) { - addrxlat_status status = read_pte64(step); + addrxlat_pte_t pte; + addrxlat_status status = read_pte64(step, &pte); if (status != ADDRXLAT_OK) return status; - return next_step_pfn_common(step); + return next_step_pfn_common(step, pte); } /** Check unsigned address overflow. diff --git a/src/addrxlat/x86_64.c b/src/addrxlat/x86_64.c index a0549941..95228e58 100644 --- a/src/addrxlat/x86_64.c +++ b/src/addrxlat/x86_64.c @@ -139,13 +139,14 @@ pgt_x86_64(addrxlat_step_t *step) "p4d", "pgd", }; + addrxlat_pte_t pte; addrxlat_status status; - status = read_pte64(step); + status = read_pte64(step, &pte); if (status != ADDRXLAT_OK) return status; - if (!(step->raw.pte & _PAGE_PRESENT)) + if (!(pte & _PAGE_PRESENT)) return !step->ctx->noerr.notpresent ? set_error(step->ctx, ADDRXLAT_ERR_NOTPRESENT, "%s not present: %s[%u] = 0x%" ADDRXLAT_PRIxPTE, @@ -155,15 +156,15 @@ pgt_x86_64(addrxlat_step_t *step) step->raw.pte) : ADDRXLAT_ERR_NOTPRESENT; - step->base.addr = step->raw.pte & PHYSADDR_MASK; + step->base.addr = pte & PHYSADDR_MASK; step->base.as = step->meth->target_as; - if (step->remain == 3 && (step->raw.pte & _PAGE_PSE)) { + if (step->remain == 3 && (pte & _PAGE_PSE)) { step->base.addr &= ~PAGE_MASK_1G; return pgt_huge_page(step); } - if (step->remain == 2 && (step->raw.pte & _PAGE_PSE)) { + if (step->remain == 2 && (pte & _PAGE_PSE)) { step->base.addr &= ~PAGE_MASK_2M; return pgt_huge_page(step); } @@ -655,6 +656,7 @@ set_xen_p2m(struct os_init_data *ctl) meth->target_as = ADDRXLAT_MACHPHYSADDR; meth->param.pgt.root.addr = p2m_maddr; meth->param.pgt.root.as = ADDRXLAT_MACHPHYSADDR; + meth->param.pgt.pte_mask = 0; meth->param.pgt.pf = xen_p2m_pf; range.endoff = paging_max_index(&xen_p2m_pf); @@ -961,6 +963,8 @@ sys_x86_64(struct os_init_data *ctl) meth->param.pgt.root = ctl->popt.val[OPT_rootpgt].fulladdr; else meth->param.pgt.root.as = ADDRXLAT_NOADDR; + meth->param.pgt.pte_mask = + opt_num_default(&ctl->popt, OPT_pte_mask, 0); meth->param.pgt.pf = x86_64_pf; if (ctl->popt.val[OPT_levels].set) { diff --git a/src/kdumpfile/Makefile.am b/src/kdumpfile/Makefile.am index 914fe598..3dc080c3 100644 --- a/src/kdumpfile/Makefile.am +++ b/src/kdumpfile/Makefile.am @@ -57,7 +57,7 @@ libkdumpfile_la_LIBADD = \ $(LZO_LIBS) \ $(SNAPPY_LIBS) -libkdumpfile_la_LDFLAGS = -version-info 7:0:0 +libkdumpfile_la_LDFLAGS = -version-info 9:0:0 if HAVE_LD_VERSION_SCRIPT libkdumpfile_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libkdumpfile.map diff --git a/src/kdumpfile/attr.c b/src/kdumpfile/attr.c index 75a973bf..531a8ed8 100644 --- a/src/kdumpfile/attr.c +++ b/src/kdumpfile/attr.c @@ -317,6 +317,66 @@ alloc_attr(struct attr_dict *dict, struct attr_data *parent, return d; } +/** Discard an attribute's value. + * @param attr The attribute whose value is being discarded. + * + * Call this function if the attribute data is no longer needed. + * If the value is dynamically allocated, free the associated memory. + * If the value is refcounted, drop the reference. + */ +static void +discard_value(struct attr_data *attr) +{ + if (!attr_isset(attr)) + return; + + switch (attr->template->type) { + case KDUMP_NIL: + case KDUMP_DIRECTORY: + case KDUMP_NUMBER: + case KDUMP_ADDRESS: + /* Value is embedded: Nothing to be done. */ + break; + + case KDUMP_STRING: + if (attr->flags.dynstr) { + attr->flags.dynstr = 0; + free((void*) attr_value(attr)->string); + } + break; + + case KDUMP_BITMAP: + internal_bmp_decref(attr_value(attr)->bitmap); + break; + + case KDUMP_BLOB: + internal_blob_decref(attr_value(attr)->blob); + break; + } +} + +/** Discard the new value of an attribute. + * @param attr Base attribute. + * @prarm flags New value flags. + * @param newval New value (which should be discarded). + * + * This helper is called when a new value cannot be set (the pre_set hook + * returns an error status). At that point the attribute should preserve its + * old value, but the new value should be discarded. + */ +static void +discard_new_value(const struct attr_data *attr, + struct attr_flags flags, kdump_attr_value_t *newval) +{ + struct attr_data tmp; + tmp.template = attr->template; + tmp.flags = flags; + tmp.flags.isset = 1; + tmp.flags.indirect = 0; + tmp.val = *newval; + discard_value(&tmp); +} + /** Clear (unset) a single attribute. * @param ctx Dump file object. * @param attr Attribute to be cleared. @@ -331,11 +391,8 @@ clear_single_attr(kdump_ctx_t *ctx, struct attr_data *attr) if (ops && ops->pre_clear) ops->pre_clear(ctx, attr); + discard_value(attr); attr->flags.isset = 0; - if (attr->flags.dynstr) { - attr->flags.dynstr = 0; - free((void*) attr_value(attr)->string); - } } /** Clear (unset) any attribute and its children recursively. @@ -402,8 +459,7 @@ dealloc_attr(struct attr_data *attr) } } - if (attr->flags.dynstr) - free((void*) attr_value(attr)->string); + discard_value(attr); if (attr->tflags.dyntmpl) free((void*) attr->template); @@ -768,6 +824,13 @@ attr_has_value(struct attr_data *attr, kdump_attr_value_t newval) * The idea is that you set @c flags.indirect, if @p pval should become * the new indirect value of @p attr. If you want to modify only the value * of @p attr, leave @c flags.indirect clear. + * + * The attribute object takes over ownership of the new value. If the + * attribute type is refcounted, then the reference is stolen from the + * caller. This is true even if the function fails and returns an error + * status. In other words, you must increase the reference count to the new + * value before calling this function if you use that object in the error + * path. */ kdump_status set_attr(kdump_ctx_t *ctx, struct attr_data *attr, @@ -780,8 +843,7 @@ set_attr(kdump_ctx_t *ctx, struct attr_data *attr, const struct attr_ops *ops = attr->template->ops; if (ops && ops->pre_set && (res = ops->pre_set(ctx, attr, pval)) != KDUMP_OK) { - if (flags.dynstr) - free((void*) pval->string); + discard_new_value(attr, flags, pval); return res; } } @@ -789,8 +851,7 @@ set_attr(kdump_ctx_t *ctx, struct attr_data *attr, instantiate_path(attr->parent); if (attr->template->type != KDUMP_DIRECTORY) { - if (attr->flags.dynstr) - free((void*) attr_value(attr)->string); + discard_value(attr); if (flags.indirect) attr->pval = pval; @@ -934,6 +995,7 @@ attr_add_override(struct attr_data *attr, struct attr_override *override) override->template.key = tmpl->key; override->template.parent = attr->template; override->template.type = tmpl->type; + override->template.override = 1; override->template.ops = &override->ops; attr->template = &override->template; @@ -955,7 +1017,7 @@ attr_remove_override(struct attr_data *attr, struct attr_override *override) break; } pprev = &((struct attr_template*)tmpl)->parent; - } while (tmpl->parent != tmpl); + } while (tmpl->override); } DEFINE_ALIAS(get_attr); diff --git a/src/kdumpfile/blob.c b/src/kdumpfile/blob.c index d8f7d41d..07fc7364 100644 --- a/src/kdumpfile/blob.c +++ b/src/kdumpfile/blob.c @@ -35,12 +35,6 @@ #include #include -/** Allocate a new bitmap object. - * @param ops Bitmap operations. - * @returns New bitmap, or @c NULL on allocation error. - * - * The new object's reference count is initialized to 1. - */ kdump_blob_t * kdump_blob_new(void *data, size_t size) { @@ -55,6 +49,26 @@ kdump_blob_new(void *data, size_t size) return blob; } +kdump_blob_t * +kdump_blob_new_dup(const void *data, size_t size) +{ + kdump_blob_t *ret; + void *newdata; + + if (data) { + newdata = malloc(size); + if (!newdata) + return NULL; + memcpy(newdata, data, size); + data = newdata; + } else + newdata = NULL; + ret = internal_blob_new(newdata, size); + if (!ret && newdata) + free(newdata); + return ret; +} + unsigned long kdump_blob_incref(kdump_blob_t *blob) { diff --git a/src/kdumpfile/cache.c b/src/kdumpfile/cache.c index 0dcd9572..4cf4663c 100644 --- a/src/kdumpfile/cache.c +++ b/src/kdumpfile/cache.c @@ -818,57 +818,30 @@ get_cache_size(kdump_ctx_t *ctx) : DEFAULT_CACHE_SIZE; } -/** Re-allocate a cache with default parameters. - * @param ctx Dump file object. - * @returns Error status. - * - * This function can be used as the @c realloc_caches method if - * the cache is organized as @c cache.size elements of @c arch.page_size - * bytes each. +/** Set up cache statistics attributes. + * @param cache Cache object. + * @param ctx Dump file object containing the attributes. + * @param hits Attribute for cache hits. + * @param misses Attribute for cache misses. + * @returns Error status. */ kdump_status -def_realloc_caches(kdump_ctx_t *ctx) +cache_set_attrs(struct cache *cache, kdump_ctx_t *ctx, + struct attr_data *hits, struct attr_data *misses) { - unsigned cache_size = get_cache_size(ctx); - struct cache *cache; + kdump_status status; - cache = cache_alloc(cache_size, get_page_size(ctx)); - if (!cache) - return set_error(ctx, KDUMP_ERR_SYSTEM, - "Cannot allocate cache (%u * %zu bytes)", - cache_size, get_page_size(ctx)); - - set_attr(ctx, gattr(ctx, GKI_cache_hits), - ATTR_PERSIST_INDIRECT, &cache->hits); - set_attr(ctx, gattr(ctx, GKI_cache_misses), - ATTR_PERSIST_INDIRECT, &cache->misses); + status = set_attr(ctx, hits, ATTR_PERSIST_INDIRECT, &cache->hits); + if (status != KDUMP_OK) + return set_error(ctx, status, + "Cannot set up cache '%s' attribute", + "hits"); - if (ctx->shared->cache) - cache_free(ctx->shared->cache); - ctx->shared->cache = cache; + status = set_attr(ctx, misses, ATTR_PERSIST_INDIRECT, &cache->misses); + if (status != KDUMP_OK) + return set_error(ctx, status, + "Cannot set up cache '%s' attribute", + "misses"); return KDUMP_OK; } - -static kdump_status -cache_size_pre_hook(kdump_ctx_t *ctx, struct attr_data *attr, - kdump_attr_value_t *val) -{ - if (val->number > UINT_MAX) - return set_error(ctx, KDUMP_ERR_INVALID, - "Cache size too big (max %u)", UINT_MAX); - return KDUMP_OK; -} - -static kdump_status -cache_size_post_hook(kdump_ctx_t *ctx, struct attr_data *attr) -{ - return ctx->shared->ops && ctx->shared->ops->realloc_caches - ? ctx->shared->ops->realloc_caches(ctx) - : KDUMP_OK; -} - -const struct attr_ops cache_size_ops = { - .pre_set = cache_size_pre_hook, - .post_set = cache_size_post_hook, -}; diff --git a/src/kdumpfile/context.c b/src/kdumpfile/context.c index b825c796..a3e9a819 100644 --- a/src/kdumpfile/context.c +++ b/src/kdumpfile/context.c @@ -148,7 +148,23 @@ shared_decref(struct kdump_shared *shared) kdump_ctx_t * kdump_new(void) { + /* Numeric attributes that to be initialized */ + static const struct { + enum global_keyidx key; + kdump_num_t val; + } numeric_attrs[] = { + { GKI_cache_hits, 0 }, + { GKI_cache_misses, 0 }, + { GKI_cache_size, DEFAULT_CACHE_SIZE }, + { GKI_file_mmap_policy, KDUMP_MMAP_TRY }, + { GKI_mmap_cache_hits, 0 }, + { GKI_mmap_cache_misses, 0 }, + { GKI_read_cache_hits, 0 }, + { GKI_read_cache_misses, 0 }, + }; + kdump_ctx_t *ctx; + int i; ctx = alloc_ctx(); if (!ctx) @@ -168,12 +184,9 @@ kdump_new(void) goto err_xlat; list_add(&ctx->xlat_list, &ctx->xlat->ctx); - set_attr_number(ctx, gattr(ctx, GKI_cache_size), - ATTR_PERSIST, DEFAULT_CACHE_SIZE); - set_attr_number(ctx, gattr(ctx, GKI_cache_hits), - ATTR_PERSIST, 0); - set_attr_number(ctx, gattr(ctx, GKI_cache_misses), - ATTR_PERSIST, 0); + for (i = 0; i < ARRAY_SIZE(numeric_attrs); ++i) + set_attr_number(ctx, gattr(ctx, numeric_attrs[i].key), + ATTR_PERSIST, numeric_attrs[i].val); return ctx; diff --git a/src/kdumpfile/diskdump.c b/src/kdumpfile/diskdump.c index 193d1bff..7ed40709 100644 --- a/src/kdumpfile/diskdump.c +++ b/src/kdumpfile/diskdump.c @@ -506,6 +506,7 @@ static kdump_status read_vmcoreinfo(kdump_ctx_t *ctx, off_t off, size_t size) { struct fcache_chunk fch; + kdump_attr_value_t val; kdump_status ret; ret = fcache_get_chunk(ctx->shared->fcache, &fch, size, off); @@ -514,9 +515,12 @@ read_vmcoreinfo(kdump_ctx_t *ctx, off_t off, size_t size) "Cannot read %zu VMCOREINFO bytes at %llu", size, (unsigned long long) off); - ret = set_attr_sized_string( - ctx, gattr(ctx, GKI_linux_vmcoreinfo_raw), - ATTR_DEFAULT, fch.data, size); + val.blob = internal_blob_new_dup(fch.data, size); + if (!val.blob) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", "VMCOREINFO blob"); + ret = set_attr(ctx, gattr(ctx, GKI_linux_vmcoreinfo_raw), + ATTR_DEFAULT, &val); if (ret != KDUMP_OK) ret = set_error(ctx, ret, "Cannot set VMCOREINFO"); @@ -881,11 +885,6 @@ open_common(kdump_ctx_t *ctx, void *hdr) set_addrspace_caps(ctx->xlat, ADDRXLAT_CAPS(ADDRXLAT_MACHPHYSADDR)); - if (uts_looks_sane(&dh32->utsname)) - set_uts(ctx, &dh32->utsname); - else if (uts_looks_sane(&dh64->utsname)) - set_uts(ctx, &dh64->utsname); - ret = try_header_32(&sd, dh32); if (ret == KDUMP_ERR_CORRUPT) { clear_error(ctx); @@ -909,6 +908,11 @@ open_common(kdump_ctx_t *ctx, void *hdr) shared_incref_locked(ctx->shared); set_file_pagemap(ctx, bmp); + if (uts_looks_sane(&dh32->utsname)) + set_uts(ctx, &dh32->utsname); + else if (uts_looks_sane(&dh64->utsname)) + set_uts(ctx, &dh64->utsname); + if (sd.note_sz) { ret = read_notes(ctx, sd.note_off, sd.note_sz); if (ret != KDUMP_OK) diff --git a/src/kdumpfile/fcache.c b/src/kdumpfile/fcache.c index 5ff2f329..7fd46ea5 100644 --- a/src/kdumpfile/fcache.c +++ b/src/kdumpfile/fcache.c @@ -68,6 +68,7 @@ fcache_new(int fd, unsigned n, unsigned order) fc->refcnt = 1; fc->fd = fd; + fc->mmap_policy.number = KDUMP_MMAP_TRY; fc->pgsz = sysconf(_SC_PAGESIZE); fc->mmapsz = fc->pgsz << order; @@ -104,42 +105,58 @@ fcache_free(struct fcache *fc) free(fc); } -/** Get file cache content. +/** Get file cache content using mmap(2). * @param fc File cache object. * @param fce File cache entry, updated on success. * @param pos File position. * @returns Error status. */ kdump_status -fcache_get(struct fcache *fc, struct fcache_entry *fce, off_t pos) +fcache_get_mmap(struct fcache *fc, struct fcache_entry *fce, off_t pos) { + struct cache_entry *ce; off_t blkpos; size_t off; - struct cache_entry *ce; blkpos = pos & ~(fc->pgsz - 1); - if (blkpos < fc->filesz) { - blkpos = pos & ~(fc->mmapsz - 1); - ce = cache_get_entry(fc->cache, blkpos); - if (!ce) - return KDUMP_ERR_BUSY; - - if (!cache_entry_valid(ce)) { - ce->data = mmap(NULL, fc->mmapsz, PROT_READ, - MAP_SHARED, fc->fd, blkpos); - cache_insert(fc->cache, ce); - } + if (blkpos >= fc->filesz) + return KDUMP_ERR_NODATA; - if (ce->data != MAP_FAILED) { - fce->ce = ce; - off = pos & (fc->mmapsz - 1); - fce->len = fc->mmapsz - off; - fce->data = ce->data + off; - fce->cache = fc->cache; - return KDUMP_OK; - } + blkpos = pos & ~(fc->mmapsz - 1); + ce = cache_get_entry(fc->cache, blkpos); + if (!ce) + return KDUMP_ERR_BUSY; + + if (!cache_entry_valid(ce)) { + ce->data = mmap(NULL, fc->mmapsz, PROT_READ, + MAP_SHARED, fc->fd, blkpos); + cache_insert(fc->cache, ce); } + if (ce->data == MAP_FAILED) + return KDUMP_ERR_SYSTEM; + + fce->ce = ce; + off = pos & (fc->mmapsz - 1); + fce->len = fc->mmapsz - off; + fce->data = ce->data + off; + fce->cache = fc->cache; + return KDUMP_OK; +} + +/** Get file cache content using read(2). + * @param fc File cache object. + * @param fce File cache entry, updated on success. + * @param pos File position. + * @returns Error status. + */ +kdump_status +fcache_get_read(struct fcache *fc, struct fcache_entry *fce, off_t pos) +{ + struct cache_entry *ce; + off_t blkpos; + size_t off; + blkpos = pos & ~(fc->pgsz - 1); ce = cache_get_entry(fc->fbcache, blkpos); if (!ce) @@ -164,6 +181,35 @@ fcache_get(struct fcache *fc, struct fcache_entry *fce, off_t pos) return KDUMP_OK; } +/** Get file cache content. + * @param fc File cache object. + * @param fce File cache entry, updated on success. + * @param pos File position. + * @returns Error status. + */ +kdump_status +fcache_get(struct fcache *fc, struct fcache_entry *fce, off_t pos) +{ + kdump_mmap_policy_t policy = fc->mmap_policy.number; + kdump_status status; + + if (policy != KDUMP_MMAP_NEVER) { + status = fcache_get_mmap(fc, fce, pos); + + if (policy == KDUMP_MMAP_TRY_ONCE) + fc->mmap_policy.number = + (status == KDUMP_OK + ? KDUMP_MMAP_ALWAYS + : KDUMP_MMAP_NEVER); + + if (status == KDUMP_OK || + policy == KDUMP_MMAP_ALWAYS) + return status; + } + + return fcache_get_read(fc, fce, pos); +} + /** Get file cache content with a fallback buffer. * @param fc File cache object. * @param fce File cache entry, updated on success. diff --git a/src/kdumpfile/global-attr.def b/src/kdumpfile/global-attr.def index 17d3d2ce..00ed4562 100644 --- a/src/kdumpfile/global-attr.def +++ b/src/kdumpfile/global-attr.def @@ -46,6 +46,17 @@ ATTR(cache, "misses", cache_misses, number, unsigned long) ATTR(file, "format", file_format, string, const char *) ATTR(file, "description", file_description, string, const char *) +/* file-level cache statistics */ +ATTR(file, "mmap_cache", dir_file_mmap_cache, directory, struct attr_data *) +ATTR(file_mmap_cache, "hits", mmap_cache_hits, number, unsigned long) +ATTR(file_mmap_cache, "misses", mmap_cache_misses, number, unsigned long) +ATTR(file, "read_cache", dir_file_read_cache, directory, struct attr_data *) +ATTR(file_read_cache, "hits", read_cache_hits, number, unsigned long) +ATTR(file_read_cache, "misses", read_cache_misses, number, unsigned long) + +/* mmap policy */ +ATTR(file, "mmap_policy", file_mmap_policy, number, kdump_mmap_policy_t) + /* Linux */ ATTR(root, "linux", dir_linux, directory, struct attr_data *) ATTR(linux, "version_code", linux_version_code, number, unsigned, @@ -66,7 +77,7 @@ ATTR(linux_uts, "domainname", linux_uts_domainname, string, const char *) ATTR(linux, "vmcoreinfo", dir_linux_vmcoreinfo, directory, struct attr_data *) ATTR(linux_vmcoreinfo, "lines", linux_vmcoreinfo_lines, directory, struct attr_data *) -ATTR(linux_vmcoreinfo, "raw", linux_vmcoreinfo_raw, string, const char *, +ATTR(linux_vmcoreinfo, "raw", linux_vmcoreinfo_raw, blob, kdump_blob_t *, .ops = &vmcoreinfo_raw_ops) ATTR(linux_vmcoreinfo, "LENGTH", linux_length, directory, struct attr_data *) ATTR(linux_vmcoreinfo, "NUMBER", linux_number, directory, struct attr_data *) @@ -92,7 +103,7 @@ ATTR(xen, "version_code", xen_version_code, number, unsigned, ATTR(xen, "vmcoreinfo", dir_xen_vmcoreinfo, directory, struct attr_data *) ATTR(xen_vmcoreinfo, "lines", xen_vmcoreinfo_lines, directory, struct attr_data *) -ATTR(xen_vmcoreinfo, "raw", xen_vmcoreinfo_raw, string, const char *, +ATTR(xen_vmcoreinfo, "raw", xen_vmcoreinfo_raw, blob, kdump_addr_t *, .ops = &vmcoreinfo_raw_ops) ATTR(xen_vmcoreinfo, "LENGTH", xen_length, directory, struct attr_data *) ATTR(xen_vmcoreinfo, "NUMBER", xen_number, directory, struct attr_data *) diff --git a/src/kdumpfile/kdumpfile-priv.h b/src/kdumpfile/kdumpfile-priv.h index b7ecbd4e..9ccd2646 100644 --- a/src/kdumpfile/kdumpfile-priv.h +++ b/src/kdumpfile/kdumpfile-priv.h @@ -209,6 +209,8 @@ struct format_ops { void (*cleanup)(struct kdump_shared *); }; +INTERNAL_DECL(kdump_status, def_realloc_caches, (kdump_ctx_t *ctx)); + struct arch_ops { /** Initialize any arch-specific data. */ kdump_status (*init)(kdump_ctx_t *); @@ -219,6 +221,15 @@ struct arch_ops { /** Process a Xen .xen_prstatus section. */ kdump_status (*process_xen_prstatus)(kdump_ctx_t *, const void *, size_t); + /** OS type post-hook. + * @param ctx Dump file object. + * @returns Status code. + * + * This hook is called after the OS type is changed to allow + * arch-specific initialization (e.g. read OS_INFO on s390x). + */ + kdump_status (*post_ostype)(kdump_ctx_t *ctx); + /** Address translation post-hook. * @param ctx Dump file object. * @returns Status code. @@ -272,6 +283,9 @@ struct _kdump_bmp { kdump_errmsg_t err; }; +DECLARE_ALIAS(bmp_incref); +DECLARE_ALIAS(bmp_decref); + INTERNAL_DECL(kdump_bmp_t *, kdump_bmp_new, (const struct kdump_bmp_ops *ops)); @@ -292,9 +306,10 @@ struct _kdump_blob { size_t size; /**< Size of binary data. */ }; -INTERNAL_DECL(kdump_blob_t *, kdump_blob_new, - (void *data, size_t size)); - +DECLARE_ALIAS(blob_new); +DECLARE_ALIAS(blob_new_dup); +DECLARE_ALIAS(blob_incref); +DECLARE_ALIAS(blob_decref); DECLARE_ALIAS(blob_pin); DECLARE_ALIAS(blob_unpin); @@ -418,6 +433,7 @@ struct attr_template { unsigned depth; }; kdump_attr_type_t type; + unsigned override:1; /**< Set iff this is a template override. */ const struct attr_ops *ops; }; @@ -1020,6 +1036,21 @@ attr_value(const struct attr_data *attr) return attr->flags.indirect ? attr->pval : &attr->val; } +/** Make sure that attribute value is embedded (not indirect). + * @param attr Attribute data. + * + * If the attribute is indirect, copy the value into the attribute + * data itself and clear the indirect flag. + */ +static inline void +attr_embed_value(struct attr_data *attr) +{ + if (attr->flags.indirect) { + attr->val = *attr->pval; + attr->flags.indirect = 0; + } +} + /** Revalidate attribute data. * @param ctx Dump file object. * @param attr Attribute data. @@ -1209,7 +1240,9 @@ INTERNAL_DECL(void, cache_put_entry, INTERNAL_DECL(void, cache_insert, (struct cache *, struct cache_entry *)); INTERNAL_DECL(void, cache_discard, (struct cache *, struct cache_entry *)); -INTERNAL_DECL(kdump_status, def_realloc_caches, (kdump_ctx_t *ctx)); +INTERNAL_DECL(kdump_status, cache_set_attrs, + (struct cache *cache, kdump_ctx_t *ctx, + struct attr_data *hits, struct attr_data *misses)); /** Check if a cache entry is valid. * @@ -1249,6 +1282,11 @@ struct fcache { /** Open file descriptor. */ int fd; + /** Policy for using mmap(2) vs. read(2). + * @sa kdump_mmap_policy_t + */ + kdump_attr_value_t mmap_policy; + /** Page size (in bytes). */ size_t pgsz; diff --git a/src/kdumpfile/libkdumpfile.map b/src/kdumpfile/libkdumpfile.map index 8c34766c..7a891c91 100644 --- a/src/kdumpfile/libkdumpfile.map +++ b/src/kdumpfile/libkdumpfile.map @@ -22,6 +22,8 @@ LIBKDUMPFILE_0 { kdump_bmp_find_set; kdump_bmp_find_clear; + kdump_blob_new; + kdump_blob_new_dup; kdump_blob_incref; kdump_blob_decref; kdump_blob_pin; diff --git a/src/kdumpfile/notes.c b/src/kdumpfile/notes.c index 6ee08d9d..7916f6dc 100644 --- a/src/kdumpfile/notes.c +++ b/src/kdumpfile/notes.c @@ -348,12 +348,17 @@ static kdump_status set_vmcoreinfo(kdump_ctx_t *ctx, enum global_keyidx key, void *data, size_t sz, const char *what) { + kdump_attr_value_t val; kdump_status res; - res = set_attr_sized_string(ctx, gattr(ctx, key), - ATTR_DEFAULT, data, sz); + val.blob = internal_blob_new_dup(data, sz); + if (!val.blob) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", what); + res = set_attr(ctx, gattr(ctx, key), ATTR_DEFAULT, &val); if (res != KDUMP_OK) return set_error(ctx, res, "Cannot set %s", what); + return KDUMP_OK; } diff --git a/src/kdumpfile/open.c b/src/kdumpfile/open.c index e29b60ef..b0c09b18 100644 --- a/src/kdumpfile/open.c +++ b/src/kdumpfile/open.c @@ -80,17 +80,42 @@ static const struct format_ops *formats[] = { static kdump_status file_fd_post_hook(kdump_ctx_t *ctx, struct attr_data *attr) { + /* Attributes that point into ctx->shared->fcache */ + static const enum global_keyidx fcache_attrs[] = { + GKI_file_mmap_policy, + GKI_mmap_cache_hits, + GKI_mmap_cache_misses, + GKI_read_cache_hits, + GKI_read_cache_misses, + }; + + struct attr_data *mmap_attr; kdump_status ret; int i; - if (ctx->shared->fcache) + if (ctx->shared->fcache) { + for (i = 0; i < ARRAY_SIZE(fcache_attrs); ++i) + attr_embed_value(gattr(ctx, fcache_attrs[i])); fcache_decref(ctx->shared->fcache); + } ctx->shared->fcache = fcache_new(get_file_fd(ctx), FCACHE_SIZE, FCACHE_ORDER); if (!ctx->shared->fcache) return set_error(ctx, KDUMP_ERR_SYSTEM, "Cannot allocate file cache"); + mmap_attr = gattr(ctx, GKI_file_mmap_policy); + ctx->shared->fcache->mmap_policy = *attr_value(mmap_attr); + set_attr(ctx, mmap_attr, ATTR_PERSIST_INDIRECT, + &ctx->shared->fcache->mmap_policy); + + cache_set_attrs(ctx->shared->fcache->cache, ctx, + gattr(ctx, GKI_mmap_cache_hits), + gattr(ctx, GKI_mmap_cache_misses)); + cache_set_attrs(ctx->shared->fcache->fbcache, ctx, + gattr(ctx, GKI_read_cache_hits), + gattr(ctx, GKI_read_cache_misses)); + ctx->xlat->dirty = true; for (i = 0; i < ARRAY_SIZE(formats); ++i) { @@ -261,6 +286,12 @@ ostype_post_hook(kdump_ctx_t *ctx, struct attr_data *attr) ctx->xlat->dirty = true; + if (ctx->shared->arch_ops && ctx->shared->arch_ops->post_ostype) { + status = ctx->shared->arch_ops->post_ostype(ctx); + if (status != KDUMP_OK) + return status; + } + switch (ctx->xlat->ostype) { case ADDRXLAT_OS_LINUX: status = update_linux_utsname(ctx); diff --git a/src/kdumpfile/s390x.c b/src/kdumpfile/s390x.c index 68a54429..b3381897 100644 --- a/src/kdumpfile/s390x.c +++ b/src/kdumpfile/s390x.c @@ -79,6 +79,7 @@ read_os_info_from_lowcore(kdump_ctx_t *ctx) uint64_t magic; uint32_t csum, csum_expect; void *vmcoreinfo; + kdump_attr_value_t val; kdump_status ret; sz = sizeof(addr); @@ -141,9 +142,14 @@ read_os_info_from_lowcore(kdump_ctx_t *ctx) (unsigned long) csum_expect); } - ret = set_attr_sized_string(ctx, gattr(ctx, GKI_linux_vmcoreinfo_raw), - ATTR_DEFAULT, vmcoreinfo, sz); - free(vmcoreinfo); + val.blob = internal_blob_new(vmcoreinfo, sz); + if (!val.blob) { + free(vmcoreinfo); + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", "VMCOREINFO blob"); + } + ret = set_attr(ctx, gattr(ctx, GKI_linux_vmcoreinfo_raw), + ATTR_DEFAULT, &val); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot set VMCOREINFO"); @@ -205,15 +211,26 @@ process_lowcore_info(kdump_ctx_t *ctx) return ret; } +static kdump_status +s390x_post_ostype(kdump_ctx_t *ctx) +{ + return ctx->xlat->ostype == ADDRXLAT_OS_LINUX + ? process_lowcore_info(ctx) + : KDUMP_OK; +} + static kdump_status s390x_init(kdump_ctx_t *ctx) { - process_lowcore_info(ctx); - clear_error(ctx); + if (ctx->xlat->ostype == ADDRXLAT_OS_LINUX) { + process_lowcore_info(ctx); + clear_error(ctx); + } return KDUMP_OK; } const struct arch_ops s390x_ops = { .init = s390x_init, + .post_ostype = s390x_post_ostype, }; diff --git a/src/kdumpfile/util.c b/src/kdumpfile/util.c index 701148fc..4fb2960e 100644 --- a/src/kdumpfile/util.c +++ b/src/kdumpfile/util.c @@ -537,6 +537,65 @@ const struct attr_ops xen_ver_ops = { .post_set = xen_ver_post_hook, }; +/** Re-allocate a cache with default parameters. + * @param ctx Dump file object. + * @returns Error status. + * + * This function can be used as the @c realloc_caches method if + * the cache is organized as @c cache.size elements of @c arch.page_size + * bytes each. + */ +kdump_status +def_realloc_caches(kdump_ctx_t *ctx) +{ + unsigned cache_size = get_cache_size(ctx); + struct cache *cache; + kdump_status status; + + cache = cache_alloc(cache_size, get_page_size(ctx)); + if (!cache) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate cache (%u * %zu bytes)", + cache_size, get_page_size(ctx)); + + status = cache_set_attrs(cache, ctx, + gattr(ctx, GKI_cache_hits), + gattr(ctx, GKI_cache_misses)); + if (status != KDUMP_OK) { + cache_free(cache); + return status; + } + + if (ctx->shared->cache) + cache_free(ctx->shared->cache); + ctx->shared->cache = cache; + + return KDUMP_OK; +} + +static kdump_status +cache_size_pre_hook(kdump_ctx_t *ctx, struct attr_data *attr, + kdump_attr_value_t *val) +{ + if (val->number > UINT_MAX) + return set_error(ctx, KDUMP_ERR_INVALID, + "Cache size too big (max %u)", UINT_MAX); + return KDUMP_OK; +} + +static kdump_status +cache_size_post_hook(kdump_ctx_t *ctx, struct attr_data *attr) +{ + return ctx->shared->ops && ctx->shared->ops->realloc_caches + ? ctx->shared->ops->realloc_caches(ctx) + : KDUMP_OK; +} + +const struct attr_ops cache_size_ops = { + .pre_set = cache_size_pre_hook, + .post_set = cache_size_post_hook, +}; + static kdump_status page_size_pre_hook(kdump_ctx_t *ctx, struct attr_data *attr, kdump_attr_value_t *newval) @@ -874,7 +933,6 @@ init_cpu_blob_attr(kdump_ctx_t *ctx, unsigned cpu, const void *data, size_t size, const struct attr_template *tmpl) { - void *buffer; struct attr_data *dir, *attr; kdump_attr_value_t val; kdump_status status; @@ -883,32 +941,22 @@ init_cpu_blob_attr(kdump_ctx_t *ctx, unsigned cpu, if (status != KDUMP_OK) return status; - buffer = malloc(size); - if (!buffer) - return set_error(ctx, KDUMP_ERR_SYSTEM, - "Buffer allocation failed"); - memcpy(buffer, data, size); - - val.blob = kdump_blob_new(buffer, size); - if (!val.blob) { - free(buffer); + val.blob = internal_blob_new_dup(data, size); + if (!val.blob) return set_error(ctx, KDUMP_ERR_SYSTEM, "Blob allocation failed"); - } attr = new_attr(ctx->dict, dir, tmpl); if (!attr) { - kdump_blob_decref(val.blob); + internal_blob_decref(val.blob); return set_error(ctx, status, "Attribute allocation failed"); } status = set_attr(ctx, attr, ATTR_DEFAULT, &val); - if (status != KDUMP_OK) { - kdump_blob_decref(val.blob); + if (status != KDUMP_OK) return set_error(ctx, status, "Cannot set attribute"); - } return status; } @@ -972,7 +1020,8 @@ get_attr_blob(kdump_ctx_t *ctx, struct attr_data *attr, raw = lookup_attr_child(attr->parent, tmpl); if (!raw) - return set_error(ctx, KDUMP_ERR_NODATA, "PRSTATUS not found"); + return set_error(ctx, KDUMP_ERR_NODATA, + "%s raw attribute not found", tmpl->key); *blob = raw->val.blob; return KDUMP_OK; diff --git a/src/kdumpfile/vmcoreinfo.c b/src/kdumpfile/vmcoreinfo.c index de708a09..a4116034 100644 --- a/src/kdumpfile/vmcoreinfo.c +++ b/src/kdumpfile/vmcoreinfo.c @@ -214,7 +214,8 @@ static const struct attr_ops vmcoreinfo_lines_ops = { static kdump_status vmcoreinfo_raw_post_hook(kdump_ctx_t *ctx, struct attr_data *rawattr) { - const char *p, *endp, *val; + kdump_blob_t *blob; + const char *p, *endp, *endl, *val; size_t len; struct attr_data *dir; kdump_status res; @@ -222,24 +223,27 @@ vmcoreinfo_raw_post_hook(kdump_ctx_t *ctx, struct attr_data *rawattr) dir = rawattr->parent; dealloc_vmcoreinfo(dir); - for (p = attr_value(rawattr)->string; *p; p = endp) { - endp = strchrnul(p, '\n'); - val = memchr(p, '=', endp - p); + blob = attr_value(rawattr)->blob; + p = internal_blob_pin(blob); + endp = p + blob->size; + while (p < endp) { + endl = memchr(p, '\n', endp - p) ?: endp; + val = memchr(p, '=', endl - p); if (val) { len = val - p; ++val; } else { - val = endp; + val = endl; len = val - p; } - res = add_parsed_row(ctx, dir, p, len, val, endp - val); + res = add_parsed_row(ctx, dir, p, len, val, endl - val); if (res != KDUMP_OK) break; - if (*endp) - ++endp; + p = endl + 1; } + internal_blob_unpin(blob); return res; } @@ -256,7 +260,7 @@ const struct attr_ops vmcoreinfo_raw_ops = { }; static kdump_status -get_raw_locked(kdump_ctx_t *ctx, const char **raw) +get_raw_locked(kdump_ctx_t *ctx, char **raw) { static const struct ostype_attr_map raw_map[] = { { ADDRXLAT_OS_LINUX, GKI_linux_vmcoreinfo_raw }, @@ -264,6 +268,7 @@ get_raw_locked(kdump_ctx_t *ctx, const char **raw) { ADDRXLAT_OS_UNKNOWN } }; struct attr_data *attr = ostype_attr(ctx, raw_map); + size_t len; kdump_status status; if (!attr) @@ -278,12 +283,19 @@ get_raw_locked(kdump_ctx_t *ctx, const char **raw) return set_error(ctx, status, "Value cannot be revalidated"); - *raw = attr_value(attr)->string; + len = attr_value(attr)->blob->size; + *raw = malloc(len + 1); + if (!*raw) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate raw attribute value"); + memcpy(*raw, attr_value(attr)->blob->data, len); + (*raw)[len] = 0; + return KDUMP_OK; } kdump_status -kdump_vmcoreinfo_raw(kdump_ctx_t *ctx, const char **raw) +kdump_vmcoreinfo_raw(kdump_ctx_t *ctx, char **raw) { kdump_status ret; @@ -327,13 +339,17 @@ get_line_locked(kdump_ctx_t *ctx, const char *key, return set_error(ctx, status, "Value cannot be revalidated"); - *val = attr_value(attr)->string; + *val = strdup(attr_value(attr)->string); + if (!*val) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate attribute value"); + return KDUMP_OK; } kdump_status kdump_vmcoreinfo_line(kdump_ctx_t *ctx, const char *key, - const char **val) + char **val) { kdump_status ret; diff --git a/src/kdumpfile/vtop.c b/src/kdumpfile/vtop.c index b792ad76..3b5dc0d7 100644 --- a/src/kdumpfile/vtop.c +++ b/src/kdumpfile/vtop.c @@ -232,7 +232,6 @@ get_linux_x86_64_levels(kdump_ctx_t *ctx, int *levels) { static const char l5_enabled[] = "pgtable_l5_enabled"; struct attr_data *attr; - int len; attr = lookup_dir_attr(ctx->dict, gattr(ctx, GKI_linux_number), l5_enabled, sizeof(l5_enabled) - 1); @@ -293,6 +292,38 @@ set_linux_levels_opt(kdump_ctx_t *ctx, struct opts *opts) return KDUMP_OK; } +/** Add a "pte_mask=" addrxlat option if applicable. + * @param ctx Dump file object. + * @param opts Options. + * @returns Error status. + * + * If VMCOREINFO specifies a SME bit, use it for pte_mask. + */ +static kdump_status +set_linux_pte_mask(kdump_ctx_t *ctx, struct opts *opts) +{ + static const char sme_mask[] = "sme_mask"; + struct attr_data *attr; + int len; + + attr = lookup_dir_attr(ctx->dict, gattr(ctx, GKI_linux_number), + sme_mask, sizeof(sme_mask) - 1); + if (attr && attr_isset(attr)) { + kdump_status status = attr_revalidate(ctx, attr); + if (status != KDUMP_OK) + return set_error(ctx, status, + "Cannot get %s from vmcoreinfo", + sme_mask); + len = asprintf(&opts->str[opts->n], "%s=0x%llx", "pte_mask", + (unsigned long long)attr_value(attr)->number); + if (len < 0) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot make %s option", "pte_mask"); + ++opts->n; + } + return KDUMP_OK; +} + static kdump_status set_linux_opts(kdump_ctx_t *ctx, struct opts *opts) { @@ -304,6 +335,10 @@ set_linux_opts(kdump_ctx_t *ctx, struct opts *opts) if (status != KDUMP_OK) return status; + status = set_linux_pte_mask(ctx, opts); + if (status != KDUMP_OK) + return status; + if (isset_phys_base(ctx)) { len = asprintf(&opts->str[opts->n], "phys_base=0x%"ADDRXLAT_PRIxADDR, diff --git a/tests/Makefile.am b/tests/Makefile.am index f0a13665..acde84ab 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -153,6 +153,7 @@ test_scripts = \ addrxlat-s390x-5l \ addrxlat-x86_64-4l \ addrxlat-x86_64-5l \ + addrxlat-x86_64-sme \ addrxlat-invalid-pfn32 \ addrxlat-invalid-pfn64 \ addrxlat-invalid-ia32 \ @@ -256,6 +257,7 @@ test_scripts = \ xlat-linux-x86_64-2.6.31-nover \ xlat-linux-x86_64-2.6.31-nover-reloc \ xlat-linux-x86_64-2.6.31-nover-xen \ + xlat-linux-x86_64-4.12-sme \ xlat-linux-x86_64-4.13-nover \ xlat-linux-x86_64-4.13-kaslr \ xlat-linux-x86_64-5l \ @@ -401,6 +403,9 @@ dist_check_DATA = \ xlat-linux-x86_64-2.6.31-reloc.data \ xlat-linux-x86_64-2.6.31-reloc.expect \ xlat-linux-x86_64-2.6.31-reloc.sym \ + xlat-linux-x86_64-4.12-sme.data \ + xlat-linux-x86_64-4.12-sme.expect \ + xlat-linux-x86_64-4.12-sme.sym \ xlat-linux-x86_64-4.13-nover.data \ xlat-linux-x86_64-4.13-nover.expect \ xlat-linux-x86_64-4.13-nover.sym \ diff --git a/tests/addrxlat-x86_64-sme b/tests/addrxlat-x86_64-sme new file mode 100755 index 00000000..6efab45e --- /dev/null +++ b/tests/addrxlat-x86_64-sme @@ -0,0 +1,33 @@ +#! /bin/sh + +# +# Check VTOP translation for X86-64 using 4-level paging with SME bit +# + +pf="x86_64:12,9,9,9,9 -k 0x800000000000" + +ptes="-e 0x0000:0x800000001067" # PGD[0] -> 1000 +ptes="$ptes -e 0x0008:0x800000005067" # PGD[1] -> 5000 +ptes="$ptes -e 0x0880:0x800000008067" # PGD[272] -> 8000 +ptes="$ptes -e 0x1000:0x800000002067" # PGD[0] -> PUD[0] -> 2000 +ptes="$ptes -e 0x1010:0x8003c00000e7" # PGD[0] -> PUD[2] -> 0x3c0000000 (1G) +ptes="$ptes -e 0x2000:0x800000003067" # PGD[0] -> PUD[0] -> PMD[0] -> 3000 +ptes="$ptes -e 0x2008:0x800000004067" # PGD[0] -> PUD[0] -> PMD[1] -> 4000 +ptes="$ptes -e 0x2010:0x800000e000e7" # PGD[0] -> PUD[0] -> PMD[2] -> e00000 (2M) +ptes="$ptes -e 0x3000:0x80000000a067" # PGD[0] -> PUD[0] -> PMD[0] -> PTE[0] -> a000 +ptes="$ptes -e 0x3008:0x80000000b067" # PGD[0] -> PUD[0] -> PMD[0] -> PTE[1] -> b000 +ptes="$ptes -e 0x4800:0x80000000c067" # PGD[0] -> PUD[0] -> PMD[1] -> PTE[256] -> c000 +ptes="$ptes -e 0x5010:0x800000006067" # PGD[1] -> PUD[2] -> 6000 +ptes="$ptes -e 0x6018:0x800000007067" # PGD[1] -> PUD[2] -> PMD[3] -> 7000 +ptes="$ptes -e 0x7020:0x80000000d067" # PGD[0] -> PUD[1] -> PMD[3] -> PTE[4] -> d000 +ptes="$ptes -e 0x8240:0x8012000000e7" # PGD[272] -> PUD[72] -> directmap (1G) + +list="0x123:0xa123" # PGD[0] -> PUD[0] -> PMD[0] -> PTE[0] +list="$list 0x1234:0xb234" # PGD[0] -> PUD[0] -> PMD[0] -> PTE[1] +list="$list 0x300567:0xc567" # PGD[0] -> PUD[0] -> PMD[1] -> PTE[256] +list="$list 0x808060489a:0xd89a" # PGD[1] -> PUD[2] -> PMD[3] -> PTE[4] +list="$list 0x523456:0xf23456" # PGD[0] -> PUD[0] -> PMD[1] (2M) +list="$list 0xa1234567:0x3e1234567" # PGD[0] -> PUD[2] (1G) +list="$list 0xffff88123456789a:0x123456789a" # PGD[272] -> PUD[72] (1G) + +. "$srcdir"/addrxlat-common diff --git a/tests/addrxlat.c b/tests/addrxlat.c index f2b5ae2b..fd946aa8 100644 --- a/tests/addrxlat.c +++ b/tests/addrxlat.c @@ -189,6 +189,20 @@ set_root(addrxlat_fulladdr_t *root, const char *spec) return TEST_OK; } +static int +set_pte_mask(addrxlat_pte_t *mask, const char *spec) +{ + char *endp; + + *mask = strtoull(spec, &endp, 0); + if (*endp) { + fprintf(stderr, "Invalid mask value: %s\n", spec); + return TEST_ERR; + } + + return TEST_OK; +} + static int set_linear(addrxlat_off_t *off, const char *spec) { @@ -289,6 +303,7 @@ static const struct option opts[] = { { "entry", required_argument, NULL, 'e' }, { "form", required_argument, NULL, 'f' }, { "root", required_argument, NULL, 'r' }, + { "mask", required_argument, NULL, 'k' }, { "linear", required_argument, NULL, 'l' }, { "memarr", required_argument, NULL, 'm' }, { "pgt", no_argument, NULL, 'p' }, @@ -309,6 +324,7 @@ usage(const char *name) " -m|--memarr params Use memory array translation\n" " -f|--form fmt:fields Set paging form\n" " -r|--root as:addr Set the root page table address\n" + " -k|--mask val PTE mask for page table translation\n" " -e|--entry addr:val Set table entry value\n", name); } @@ -336,6 +352,7 @@ main(int argc, char **argv) pgt.target_as = ADDRXLAT_MACHPHYSADDR; pgt.param.pgt.root.as = ADDRXLAT_NOADDR; pgt.param.pgt.root.addr = 0; + pgt.param.pgt.pte_mask = 0; linear.kind = ADDRXLAT_LINEAR; linear.target_as = ADDRXLAT_MACHPHYSADDR; @@ -349,7 +366,7 @@ main(int argc, char **argv) memarr.target_as = ADDRXLAT_MACHPHYSADDR; memarr.param.memarr.base.as = ADDRXLAT_NOADDR; - while ((opt = getopt_long(argc, argv, "he:f:l:m:pr:t:", + while ((opt = getopt_long(argc, argv, "he:f:k:l:m:pr:t:", opts, NULL)) != -1) { switch (opt) { case 'f': @@ -366,6 +383,12 @@ main(int argc, char **argv) return rc; break; + case 'k': + rc = set_pte_mask(&meth->param.pgt.pte_mask, optarg); + if (rc != TEST_OK) + return rc; + break; + case 'e': rc = add_entry(optarg); if (rc != TEST_OK) diff --git a/tests/sys-xlat.c b/tests/sys-xlat.c index c8298681..e413de8e 100644 --- a/tests/sys-xlat.c +++ b/tests/sys-xlat.c @@ -142,6 +142,7 @@ enum param_index { /* Page tables */ pgt_root, + pgt_pte_mask, pgt_pte_format, pgt_fields, @@ -169,6 +170,7 @@ static const kw_pair_t linear_param[] = { static const kw_pair_t pgt_param[] = { {"root", pgt_root }, + {"pte_mask", pgt_pte_mask }, {"pte_format", pgt_pte_format }, {"fields", pgt_fields }, {NULL} @@ -464,6 +466,14 @@ parse_meth_param(const char *spec, addrxlat_meth_t *meth) res = parse_fulladdr(p, &meth->param.pgt.root); break; + case pgt_pte_mask: + meth->param.pgt.pte_mask = strtoull(p, (char**)&endp, 0); + if (endp != p && !*endp) + res = TEST_OK; + else + fprintf(stderr, "Invalid number: %s", p); + break; + case pgt_pte_format: res = parse_pte_format(p, &meth->param.pgt.pf.pte_format); break; @@ -950,6 +960,8 @@ int main(int argc, char *argv[]) } data.sys = read_config(cfg); fclose(cfg); + if (!data.sys) + return TEST_ERR; for (i = optind; i < argc; ++i) { rc = translate(&data, argv[i]); diff --git a/tests/vmci-cleanup.c b/tests/vmci-cleanup.c index 73536017..ef8a2020 100644 --- a/tests/vmci-cleanup.c +++ b/tests/vmci-cleanup.c @@ -27,6 +27,7 @@ */ #include +#include #include #include @@ -39,17 +40,20 @@ static const char vmcore2[] = "DIR.SUB=test2\n"; static int -check(kdump_ctx_t *ctx) +set_vmcoreinfo_value(kdump_ctx_t *ctx, int cnt, const char *val) { - unsigned cnt; + kdump_blob_t *blob; kdump_attr_t attr; kdump_status status; - /* First value. */ - cnt = 1; - - attr.type = KDUMP_STRING; - attr.val.string = vmcore1; + blob = kdump_blob_new_dup(val, strlen(val)); + if (!blob) { + fprintf(stderr, "#%d: Cannot allocate VMCOREINFO blob.\n", + cnt); + return TEST_ERR; + } + attr.type = KDUMP_BLOB; + attr.val.blob = blob; status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); if (status != KDUMP_OK) { fprintf(stderr, "#%d: Cannot set vmcoreinfo: %s\n", @@ -57,6 +61,79 @@ check(kdump_ctx_t *ctx) return TEST_ERR; } + return TEST_OK; +} + +static int +check_vmcoreinfo_raw(kdump_ctx_t *ctx, int cnt, const char *expect) +{ + char *rawval; + kdump_status status; + + status = kdump_vmcoreinfo_raw(ctx, &rawval); + if (status != KDUMP_OK) { + fprintf(stderr, "#%d: kdump_vmcoreinfo_raw() failed: %s\n", + cnt, kdump_get_err(ctx)); + return TEST_ERR; + } + if (strcmp(rawval, expect)) { + fprintf(stderr, "#%d: Invalid raw value:\n%s\n", + cnt, rawval); + return TEST_FAIL; + } + printf("#%d: kdump_vmcoreinfo_raw() value match\n", cnt); + free(rawval); + + return TEST_OK; +} + +static int +check_vmcoreinfo_line(kdump_ctx_t *ctx, int cnt, const char *key, + const char *expect) +{ + char *lineval; + kdump_status status; + + status = kdump_vmcoreinfo_line(ctx, key, &lineval); + if (status != KDUMP_OK) { + fprintf(stderr, "#%d: kdump_vmcoreinfo_line() failed: %s\n", + cnt, kdump_get_err(ctx)); + return TEST_ERR; + } + if (strcmp(lineval, expect)) { + fprintf(stderr, "#%d: Invalid line value: %s\n", + cnt, lineval); + return TEST_FAIL; + } + printf("#%d: kdump_vmcoreinfo_line() value match\n", cnt); + free(lineval); +} + +static int +check(kdump_ctx_t *ctx) +{ + unsigned cnt; + kdump_attr_t attr; + kdump_status status; + int rc; + + status = kdump_set_string_attr(ctx, "addrxlat.ostype", "linux"); + if (status != KDUMP_OK) { + fprintf(stderr, "Cannot set ostype: %s\n", + kdump_get_err(ctx)); + return TEST_ERR; + } + + /* First value. */ + cnt = 1; + rc = set_vmcoreinfo_value(ctx, cnt, vmcore1); + if (rc != TEST_OK) + return rc; + + rc = check_vmcoreinfo_raw(ctx, cnt, vmcore1); + if (rc != TEST_OK) + return rc; + status = kdump_get_attr(ctx, "linux.vmcoreinfo.lines.DIR.SUB.VAL", &attr); if (status != KDUMP_OK) { @@ -71,17 +148,19 @@ check(kdump_ctx_t *ctx) } printf("#%d: DIR.SUB.VAL=%s\n", cnt, attr.val.string); + rc = check_vmcoreinfo_line(ctx, cnt, "DIR.SUB.VAL", attr.val.string); + if (rc != TEST_OK) + return rc; + /* (Conflicting) second value */ cnt = 2; + rc = set_vmcoreinfo_value(ctx, cnt, vmcore2); + if (rc != TEST_OK) + return rc; - attr.type = KDUMP_STRING; - attr.val.string = vmcore2; - status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); - if (status != KDUMP_OK) { - fprintf(stderr, "#%d: Cannot set vmcoreinfo: %s\n", - cnt, kdump_get_err(ctx)); - return TEST_ERR; - } + rc = check_vmcoreinfo_raw(ctx, cnt, vmcore2); + if (rc != TEST_OK) + return rc; status = kdump_get_attr(ctx, "linux.vmcoreinfo.lines.DIR.SUB", &attr); if (status != KDUMP_OK) { @@ -96,6 +175,10 @@ check(kdump_ctx_t *ctx) } printf("#%d: DIR.SUB=%s\n", cnt, attr.val.string); + rc = check_vmcoreinfo_line(ctx, cnt, "DIR.SUB", attr.val.string); + if (rc != TEST_OK) + return rc; + attr.type = KDUMP_NIL; status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); if (status != KDUMP_OK) { diff --git a/tests/vmci-lines-post.c b/tests/vmci-lines-post.c index dc6113f2..d5356015 100644 --- a/tests/vmci-lines-post.c +++ b/tests/vmci-lines-post.c @@ -79,6 +79,30 @@ static const char vmcore[] = "SIZE(" SIZE_NAME ")=" str(SIZE_VALUE) "\n" ""; +static int +set_vmcoreinfo_value(kdump_ctx_t *ctx, const char *val) +{ + kdump_blob_t *blob; + kdump_attr_t attr; + kdump_status status; + + blob = kdump_blob_new_dup(val, strlen(val)); + if (!blob) { + fprintf(stderr, "#%d: Cannot allocate VMCOREINFO blob.\n"); + return TEST_ERR; + } + attr.type = KDUMP_BLOB; + attr.val.blob = blob; + status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); + if (status != KDUMP_OK) { + fprintf(stderr, "Cannot set vmcoreinfo: %s\n", + kdump_get_err(ctx)); + return TEST_ERR; + } + + return TEST_OK; +} + static int check_string(kdump_ctx_t *ctx, const char *attrpath, const char *expect) { @@ -151,16 +175,10 @@ check(kdump_ctx_t *ctx) return TEST_ERR; } - attr.type = KDUMP_STRING; - attr.val.string = vmcore; - status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); - if (status != KDUMP_OK) { - fprintf(stderr, "Cannot set vmcoreinfo: %s\n", - kdump_get_err(ctx)); - return TEST_ERR; - } + rc = set_vmcoreinfo_value(ctx, vmcore); + if (rc != TEST_OK) + return rc; - rc = TEST_OK; attr.type = KDUMP_STRING; /* Check modifications */ diff --git a/tests/vmci-post.c b/tests/vmci-post.c index e9e7b37d..c8ef4fcf 100644 --- a/tests/vmci-post.c +++ b/tests/vmci-post.c @@ -72,6 +72,30 @@ static const char vmcore[] = "SIZE(" SIZE_NAME ")=" str(SIZE_VALUE) "\n" ""; +static int +set_vmcoreinfo_value(kdump_ctx_t *ctx, const char *val) +{ + kdump_blob_t *blob; + kdump_attr_t attr; + kdump_status status; + + blob = kdump_blob_new_dup(val, strlen(val)); + if (!blob) { + fprintf(stderr, "#%d: Cannot allocate VMCOREINFO blob.\n"); + return TEST_ERR; + } + attr.type = KDUMP_BLOB; + attr.val.blob = blob; + status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); + if (status != KDUMP_OK) { + fprintf(stderr, "Cannot set vmcoreinfo: %s\n", + kdump_get_err(ctx)); + return TEST_ERR; + } + + return TEST_OK; +} + static int check_string(kdump_ctx_t *ctx, const char *attrpath, const char *expect) { @@ -144,14 +168,9 @@ check(kdump_ctx_t *ctx) return TEST_ERR; } - attr.type = KDUMP_STRING; - attr.val.string = vmcore; - status = kdump_set_attr(ctx, "linux.vmcoreinfo.raw", &attr); - if (status != KDUMP_OK) { - fprintf(stderr, "Cannot set vmcoreinfo: %s\n", - kdump_get_err(ctx)); - return TEST_ERR; - } + rc = set_vmcoreinfo_value(ctx, vmcore); + if (rc != TEST_OK) + return rc; rc = TEST_OK; diff --git a/tests/xlat-linux-ia32-pae.expect b/tests/xlat-linux-ia32-pae.expect index 325f6f27..2569c602 100644 --- a/tests/xlat-linux-ia32-pae.expect +++ b/tests/xlat-linux-ia32-pae.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x926000 + pte_mask=0x0 pte_format=ia32_pae fields=12,9,9,2 diff --git a/tests/xlat-linux-ia32.expect b/tests/xlat-linux-ia32.expect index e9d12221..ac765ead 100644 --- a/tests/xlat-linux-ia32.expect +++ b/tests/xlat-linux-ia32.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x911000 + pte_mask=0x0 pte_format=ia32 fields=12,10,10 diff --git a/tests/xlat-linux-ppc64-64k.expect b/tests/xlat-linux-ppc64-64k.expect index 78da7782..a8aabbd5 100644 --- a/tests/xlat-linux-ppc64-64k.expect +++ b/tests/xlat-linux-ppc64-64k.expect @@ -1,12 +1,14 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=ppc64_linux_rpn30 fields=16,12,12,4 @userpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=ppc64_linux_rpn30 fields=16,12,12,4 diff --git a/tests/xlat-linux-s390x-2l.expect b/tests/xlat-linux-s390x-2l.expect index e37c6516..2d6f323a 100644 --- a/tests/xlat-linux-s390x-2l.expect +++ b/tests/xlat-linux-s390x-2l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11 diff --git a/tests/xlat-linux-s390x-3l.expect b/tests/xlat-linux-s390x-3l.expect index 9a1191d0..2c78be57 100644 --- a/tests/xlat-linux-s390x-3l.expect +++ b/tests/xlat-linux-s390x-3l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11,11 diff --git a/tests/xlat-linux-s390x-4l.expect b/tests/xlat-linux-s390x-4l.expect index a3cc3375..eab8c528 100644 --- a/tests/xlat-linux-s390x-4l.expect +++ b/tests/xlat-linux-s390x-4l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11,11,11 diff --git a/tests/xlat-linux-x86_64-2.6.11-nover.expect b/tests/xlat-linux-x86_64-2.6.11-nover.expect index 39f2153f..7b48edac 100644 --- a/tests/xlat-linux-x86_64-2.6.11-nover.expect +++ b/tests/xlat-linux-x86_64-2.6.11-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.11.expect b/tests/xlat-linux-x86_64-2.6.11.expect index f2bd6aa6..196facf9 100644 --- a/tests/xlat-linux-x86_64-2.6.11.expect +++ b/tests/xlat-linux-x86_64-2.6.11.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.27-cr3-xen.expect b/tests/xlat-linux-x86_64-2.6.27-cr3-xen.expect index f4261a2d..b7a8e123 100644 --- a/tests/xlat-linux-x86_64-2.6.27-cr3-xen.expect +++ b/tests/xlat-linux-x86_64-2.6.27-cr3-xen.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x401af000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.27-nover.expect b/tests/xlat-linux-x86_64-2.6.27-nover.expect index 6e173903..a089e852 100644 --- a/tests/xlat-linux-x86_64-2.6.27-nover.expect +++ b/tests/xlat-linux-x86_64-2.6.27-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.27.expect b/tests/xlat-linux-x86_64-2.6.27.expect index 176e8f80..c3fb99d5 100644 --- a/tests/xlat-linux-x86_64-2.6.27.expect +++ b/tests/xlat-linux-x86_64-2.6.27.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31-cr3.expect b/tests/xlat-linux-x86_64-2.6.31-cr3.expect index 429f701a..a176e61e 100644 --- a/tests/xlat-linux-x86_64-2.6.31-cr3.expect +++ b/tests/xlat-linux-x86_64-2.6.31-cr3.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x2e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31-kvaddr.expect b/tests/xlat-linux-x86_64-2.6.31-kvaddr.expect index a4818b7b..c31d4369 100644 --- a/tests/xlat-linux-x86_64-2.6.31-kvaddr.expect +++ b/tests/xlat-linux-x86_64-2.6.31-kvaddr.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31-nover-reloc.expect b/tests/xlat-linux-x86_64-2.6.31-nover-reloc.expect index b29de634..2768de96 100644 --- a/tests/xlat-linux-x86_64-2.6.31-nover-reloc.expect +++ b/tests/xlat-linux-x86_64-2.6.31-nover-reloc.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31-nover-xen.expect b/tests/xlat-linux-x86_64-2.6.31-nover-xen.expect index b1c2a64e..66d99ad4 100644 --- a/tests/xlat-linux-x86_64-2.6.31-nover-xen.expect +++ b/tests/xlat-linux-x86_64-2.6.31-nover-xen.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -26,6 +27,7 @@ @kphys_machphys: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x3abc000 + pte_mask=0x0 pte_format=pfn64 fields=12,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31-nover.expect b/tests/xlat-linux-x86_64-2.6.31-nover.expect index 7bc86674..2e8b921a 100644 --- a/tests/xlat-linux-x86_64-2.6.31-nover.expect +++ b/tests/xlat-linux-x86_64-2.6.31-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31-reloc.expect b/tests/xlat-linux-x86_64-2.6.31-reloc.expect index b29de634..2768de96 100644 --- a/tests/xlat-linux-x86_64-2.6.31-reloc.expect +++ b/tests/xlat-linux-x86_64-2.6.31-reloc.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-2.6.31.expect b/tests/xlat-linux-x86_64-2.6.31.expect index 0e85ccf5..0ac52f9a 100644 --- a/tests/xlat-linux-x86_64-2.6.31.expect +++ b/tests/xlat-linux-x86_64-2.6.31.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-4.12-sme b/tests/xlat-linux-x86_64-4.12-sme new file mode 100755 index 00000000..7bd42994 --- /dev/null +++ b/tests/xlat-linux-x86_64-4.12-sme @@ -0,0 +1,14 @@ +#! /bin/sh + +# +# Check Linux 4.12 X86_64 translation with SME active +# using page table content alone +# + +arch=x86_64 +ostype=1 +osver=0 +# Page encryption indicated by bit 47 => mask is 0x800000000000 +opts="phys_base=0x1691000000 pte_mask=140737488355328" + +. "$srcdir"/xlat-os-common diff --git a/tests/xlat-linux-x86_64-4.12-sme.data b/tests/xlat-linux-x86_64-4.12-sme.data new file mode 100644 index 00000000..3764deda --- /dev/null +++ b/tests/xlat-linux-x86_64-4.12-sme.data @@ -0,0 +1,69 @@ +# (based on an actual Linux 4.12 dump, simplified) +# kernel text at 0xffffffff92000000 +@0x16a400aff8 +00008016a400e067 +@0x16a400eff0 +00008016a400f063 +@0x16a400f000 +0000000000000000*144 +00008016a30001e1 00008016a32001e1 00008016a34001e1 00008016a36001e1 +00008016a38001e1 00008016a3a001e1 80008016a3c001e1 80008016a3e001e1 +80008016a40001e3 80008016a42001e3 80008016a44001e3 80008016a46001e3 +80008016a48001e3 80008016a4a001e3 80008016a4c001e3 80008016a4e001e3 +80008016a50001e3 00008030fdfe5063 0000000000000000 0000000000000000 +0000000000000000*348 +@0x30fdfe5000 +80008016a5200163*512+1000 + +# direct mapping at 0xffff96bbc0000000 +@0x16a400a880 +0000000000000000*29 +00008016a52a2067 +0000000000000000*50 +00008008ffc20067 +@0x16a52a2000 +0000000000000000*239 +00008016a52a3067 000080407fdfe067 0000000000000000 0000000000000000 +80008001000001e3*253+40000000 +00008016a52a6067 +0000000000000000*15 +@0x16a52a3000 +00008016a52a4067 +8000800000200000*511+200000 +@0x16a52a4000 +8000800000000163*512+1000 +@0x407fdfe000 +80008000400001e3*455+200000 +000080407fdfd067 +0000000000000000*11 +000080407fdfc067 +0000000000000000*4 +000080407fdfb067 +800080007b2001e3*7+200000 +0000000000000000*32 +@0x407fdfd000 +8000800078e00163*457+1000 +0000000000000000*55 +@0x407fdfc000 +0000000000000000*179 +800080007a6b3163*183+1000 +0000000000000000*150 +@0x407fdfb000 +0000000000000000*394 +800080007b18a163*118+1000 +@0x16a52a6000 +80008040400001e3*511+200000 +000080407fdf4067 +@0x407fdf4000 +800080407fe00163*384+1000 +0000000000000000*128 +@0x8ffc20000 +0000000000000000*45 +00008010ffc20067 +# (rest of this PDPT left out) +@0x10ffc20000 +00008018ffc20067 +# (rest of this page directory left out) +@0x18ffc20000 +80000000FED00173 +# (rest of this page table left out) diff --git a/tests/xlat-linux-x86_64-4.12-sme.expect b/tests/xlat-linux-x86_64-4.12-sme.expect new file mode 100644 index 00000000..001b8747 --- /dev/null +++ b/tests/xlat-linux-x86_64-4.12-sme.expect @@ -0,0 +1,52 @@ +@rootpgt: PGT + target_as=MACHPHYSADDR + root=KVADDR:0xffffffff9300a000 + pte_mask=0x800000000000 + pte_format=x86_64 + fields=12,9,9,9,9 + +@direct: LINEAR + target_as=KPHYSADDR + off=0x694440000000 + +@ktext: LINEAR + target_as=KPHYSADDR + off=0x1711000000 + +@rdirect: LINEAR + target_as=KVADDR + off=0xffff96bbc0000000 + +@machphys_kphys: LINEAR + target_as=KPHYSADDR + off=0x0 + +@kphys_machphys: LINEAR + target_as=MACHPHYSADDR + off=0x0 + +KV -> HW: +0-7fffffffffff: @rootpgt +800000000000-ffff7fffffffffff: NONE +ffff800000000000-ffffffffffffffff: @rootpgt + +KV -> PHYS: +0-7fffffffffff: @rootpgt +800000000000-ffff7fffffffffff: NONE +ffff800000000000-ffff96bbbfffffff: @rootpgt +ffff96bbc0000000-ffff96fc3ff7ffff: @direct +ffff96fc3ff80000-ffffffff91ffffff: @rootpgt +ffffffff92000000-ffffffff943fffff: @ktext +ffffffff94400000-ffffffffffffffff: @rootpgt + +KPHYS -> DIRECT: +0-407ff7ffff: @rdirect +407ff80000-ffffffffffffffff: NONE + +MACHPHYS -> KPHYS: +0-fffffffffffff: @machphys_kphys +10000000000000-ffffffffffffffff: NONE + +KPHYS -> MACHPHYS: +0-fffffffffffff: @kphys_machphys +10000000000000-ffffffffffffffff: NONE diff --git a/tests/xlat-linux-x86_64-4.12-sme.sym b/tests/xlat-linux-x86_64-4.12-sme.sym new file mode 100644 index 00000000..0c7ee72a --- /dev/null +++ b/tests/xlat-linux-x86_64-4.12-sme.sym @@ -0,0 +1,2 @@ +@VALUE(init_top_pgt) +ffffffff9300a000 diff --git a/tests/xlat-linux-x86_64-4.13-kaslr.expect b/tests/xlat-linux-x86_64-4.13-kaslr.expect index 14b9d9fd..67ea2eca 100644 --- a/tests/xlat-linux-x86_64-4.13-kaslr.expect +++ b/tests/xlat-linux-x86_64-4.13-kaslr.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff92c09000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-4.13-nover.expect b/tests/xlat-linux-x86_64-4.13-nover.expect index eeaa2f40..7568b285 100644 --- a/tests/xlat-linux-x86_64-4.13-nover.expect +++ b/tests/xlat-linux-x86_64-4.13-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81c09000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-5l.expect b/tests/xlat-linux-x86_64-5l.expect index 2e5d535a..3e302dc8 100644 --- a/tests/xlat-linux-x86_64-5l.expect +++ b/tests/xlat-linux-x86_64-5l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff8b40a000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-128M.expect b/tests/xlat-linux-x86_64-ktext-128M.expect index 6a7ae1ba..93395b80 100644 --- a/tests/xlat-linux-x86_64-ktext-128M.expect +++ b/tests/xlat-linux-x86_64-ktext-128M.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-130M-nonlinear.expect b/tests/xlat-linux-x86_64-ktext-130M-nonlinear.expect index d5cb9225..df81a7a2 100644 --- a/tests/xlat-linux-x86_64-ktext-130M-nonlinear.expect +++ b/tests/xlat-linux-x86_64-ktext-130M-nonlinear.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff99e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-130M.expect b/tests/xlat-linux-x86_64-ktext-130M.expect index 26e59e64..2868d3d0 100644 --- a/tests/xlat-linux-x86_64-ktext-130M.expect +++ b/tests/xlat-linux-x86_64-ktext-130M.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-1G.expect b/tests/xlat-linux-x86_64-ktext-1G.expect index cea06928..a81e06d6 100644 --- a/tests/xlat-linux-x86_64-ktext-1G.expect +++ b/tests/xlat-linux-x86_64-ktext-1G.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-40M.expect b/tests/xlat-linux-x86_64-ktext-40M.expect index e40c1c74..bb15ab20 100644 --- a/tests/xlat-linux-x86_64-ktext-40M.expect +++ b/tests/xlat-linux-x86_64-ktext-40M.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-512M.expect b/tests/xlat-linux-x86_64-ktext-512M.expect index 9f22953d..6accfacd 100644 --- a/tests/xlat-linux-x86_64-ktext-512M.expect +++ b/tests/xlat-linux-x86_64-ktext-512M.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-520M.expect b/tests/xlat-linux-x86_64-ktext-520M.expect index 6cdd438b..28d6eb6e 100644 --- a/tests/xlat-linux-x86_64-ktext-520M.expect +++ b/tests/xlat-linux-x86_64-ktext-520M.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-crosspage.expect b/tests/xlat-linux-x86_64-ktext-crosspage.expect index f9a5a43a..ec702722 100644 --- a/tests/xlat-linux-x86_64-ktext-crosspage.expect +++ b/tests/xlat-linux-x86_64-ktext-crosspage.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-ktext-pgt.expect b/tests/xlat-linux-x86_64-ktext-pgt.expect index 36d5cbee..7f0ef721 100644 --- a/tests/xlat-linux-x86_64-ktext-pgt.expect +++ b/tests/xlat-linux-x86_64-ktext-pgt.expect @@ -1,12 +1,14 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @ktext: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-old-nover.expect b/tests/xlat-linux-x86_64-old-nover.expect index 748bd4cf..0f4f58fc 100644 --- a/tests/xlat-linux-x86_64-old-nover.expect +++ b/tests/xlat-linux-x86_64-old-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=KVADDR:0xffffffff81e10000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-linux-x86_64-old.expect b/tests/xlat-linux-x86_64-old.expect index 579d807a..10ff4aa6 100644 --- a/tests/xlat-linux-x86_64-old.expect +++ b/tests/xlat-linux-x86_64-old.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-os-ia32-none.expect b/tests/xlat-os-ia32-none.expect index b04b5755..3cfc5a2c 100644 --- a/tests/xlat-os-ia32-none.expect +++ b/tests/xlat-os-ia32-none.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=ia32 fields=12,10,10 diff --git a/tests/xlat-os-ia32-pae-none.expect b/tests/xlat-os-ia32-pae-none.expect index 642a16d6..24bc768c 100644 --- a/tests/xlat-os-ia32-pae-none.expect +++ b/tests/xlat-os-ia32-pae-none.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=ia32_pae fields=12,9,9,2 diff --git a/tests/xlat-os-s390x-2l.expect b/tests/xlat-os-s390x-2l.expect index dfc64944..69b9d894 100644 --- a/tests/xlat-os-s390x-2l.expect +++ b/tests/xlat-os-s390x-2l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11 diff --git a/tests/xlat-os-s390x-3l.expect b/tests/xlat-os-s390x-3l.expect index 6442b30e..62aa36cc 100644 --- a/tests/xlat-os-s390x-3l.expect +++ b/tests/xlat-os-s390x-3l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11,11 diff --git a/tests/xlat-os-s390x-4l.expect b/tests/xlat-os-s390x-4l.expect index 221dff52..fa4cc52a 100644 --- a/tests/xlat-os-s390x-4l.expect +++ b/tests/xlat-os-s390x-4l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11,11,11 diff --git a/tests/xlat-os-s390x-5l.expect b/tests/xlat-os-s390x-5l.expect index 29262bdf..1abe1bd2 100644 --- a/tests/xlat-os-s390x-5l.expect +++ b/tests/xlat-os-s390x-5l.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x8b5000 + pte_mask=0x0 pte_format=s390x fields=12,8,11,11,11,11 diff --git a/tests/xlat-os-x86_64-none.expect b/tests/xlat-os-x86_64-none.expect index c7e09505..12409be6 100644 --- a/tests/xlat-os-x86_64-none.expect +++ b/tests/xlat-os-x86_64-none.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-os.c b/tests/xlat-os.c index c1583920..04da4901 100644 --- a/tests/xlat-os.c +++ b/tests/xlat-os.c @@ -259,6 +259,8 @@ print_pgt(const addrxlat_meth_t *meth) fputs(" root=", stdout); print_fulladdr(&meth->param.pgt.root); putchar('\n'); + printf(" pte_mask=0x%"ADDRXLAT_PRIxPTE"\n", + meth->param.pgt.pte_mask); fputs(" pte_format=", stdout); if (pf->pte_format < ARRAY_SIZE(pte_formats) && pte_formats[pf->pte_format]) diff --git a/tests/xlat-xen-ia32-pae.expect b/tests/xlat-xen-ia32-pae.expect index 9eaf3c3f..4663754c 100644 --- a/tests/xlat-xen-ia32-pae.expect +++ b/tests/xlat-xen-ia32-pae.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x100120 + pte_mask=0x0 pte_format=ia32_pae fields=12,9,9,2 diff --git a/tests/xlat-xen-ia32.expect b/tests/xlat-xen-ia32.expect index 303c0429..00a590e3 100644 --- a/tests/xlat-xen-ia32.expect +++ b/tests/xlat-xen-ia32.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0x1e3000 + pte_mask=0x0 pte_format=ia32 fields=12,10,10 diff --git a/tests/xlat-xen-x86_64-3.2-nover.expect b/tests/xlat-xen-x86_64-3.2-nover.expect index 9e0ea3b5..decf0619 100644 --- a/tests/xlat-xen-x86_64-3.2-nover.expect +++ b/tests/xlat-xen-x86_64-3.2-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-3.2.expect b/tests/xlat-xen-x86_64-3.2.expect index e27dd271..02b6ec24 100644 --- a/tests/xlat-xen-x86_64-3.2.expect +++ b/tests/xlat-xen-x86_64-3.2.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.0-nover.expect b/tests/xlat-xen-x86_64-4.0-nover.expect index 6963f12e..5235583e 100644 --- a/tests/xlat-xen-x86_64-4.0-nover.expect +++ b/tests/xlat-xen-x86_64-4.0-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.0.expect b/tests/xlat-xen-x86_64-4.0.expect index 6d53eaad..0c0d8739 100644 --- a/tests/xlat-xen-x86_64-4.0.expect +++ b/tests/xlat-xen-x86_64-4.0.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.0dev-nover.expect b/tests/xlat-xen-x86_64-4.0dev-nover.expect index 28cf7075..eaf31b33 100644 --- a/tests/xlat-xen-x86_64-4.0dev-nover.expect +++ b/tests/xlat-xen-x86_64-4.0dev-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.3-nover.expect b/tests/xlat-xen-x86_64-4.3-nover.expect index db3e743f..3bd32b47 100644 --- a/tests/xlat-xen-x86_64-4.3-nover.expect +++ b/tests/xlat-xen-x86_64-4.3-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.3.expect b/tests/xlat-xen-x86_64-4.3.expect index f90f4bed..dcd18e77 100644 --- a/tests/xlat-xen-x86_64-4.3.expect +++ b/tests/xlat-xen-x86_64-4.3.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.4-nover.expect b/tests/xlat-xen-x86_64-4.4-nover.expect index 7905e606..fc609ddb 100644 --- a/tests/xlat-xen-x86_64-4.4-nover.expect +++ b/tests/xlat-xen-x86_64-4.4-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.4.expect b/tests/xlat-xen-x86_64-4.4.expect index a5ddf619..93be6cc4 100644 --- a/tests/xlat-xen-x86_64-4.4.expect +++ b/tests/xlat-xen-x86_64-4.4.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 @@ -11,6 +12,7 @@ @ktext: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-4.6-bigmem.expect b/tests/xlat-xen-x86_64-4.6-bigmem.expect index 7d51a3d9..2265a4aa 100644 --- a/tests/xlat-xen-x86_64-4.6-bigmem.expect +++ b/tests/xlat-xen-x86_64-4.6-bigmem.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-old-nover.expect b/tests/xlat-xen-x86_64-old-nover.expect index 2d39ac5b..dae53fff 100644 --- a/tests/xlat-xen-x86_64-old-nover.expect +++ b/tests/xlat-xen-x86_64-old-nover.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=MACHPHYSADDR:0xffc94000 + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9 diff --git a/tests/xlat-xen-x86_64-old.expect b/tests/xlat-xen-x86_64-old.expect index c77c3de9..4f99aaf2 100644 --- a/tests/xlat-xen-x86_64-old.expect +++ b/tests/xlat-xen-x86_64-old.expect @@ -1,6 +1,7 @@ @rootpgt: PGT target_as=MACHPHYSADDR root=NOADDR + pte_mask=0x0 pte_format=x86_64 fields=12,9,9,9,9